001/* 002 * (C) Copyright 2006-2007 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Jean-Marc Orliaguet, Chalmers 018 * 019 * $Id$ 020 */ 021 022package org.nuxeo.theme.nodes; 023 024import java.util.ArrayList; 025import java.util.List; 026 027public abstract class AbstractNode implements Node { 028 029 private Node parentNode; 030 031 private List<Node> childrenNodes = new ArrayList<Node>(); 032 033 public void clearParent() { 034 parentNode = null; 035 } 036 037 public void setParent(Node parent) throws NodeException { 038 if (equals(parent)) { 039 throw new NodeException(String.format("A node cannot be made a parent of itself: %s.", this)); 040 } 041 if (parent != null && parent.isChildOf(this)) { 042 throw new NodeException(String.format("Cycle detected while trying to make %s a parent of %s.", parent, 043 this)); 044 } 045 if (parentNode != null) { 046 List<Node> siblings = parentNode.getChildren(); 047 siblings.remove(this); 048 parentNode.setChildren(siblings); 049 } 050 parentNode = parent; 051 } 052 053 public Node getParent() { 054 return parentNode; 055 } 056 057 public Node addChild(Node node) throws NodeException { 058 if (equals(node)) { 059 throw new NodeException(String.format("A node cannot be made a child of itself: %s.", this)); 060 } 061 if (isChildOf(node)) { 062 throw new NodeException(String.format("Cycle detected while trying to add child %s to %s.", node, this)); 063 } 064 childrenNodes.add(node); 065 node.setParent(this); 066 return node; 067 } 068 069 public void removeChild(Node node) throws NodeException { 070 if (!childrenNodes.contains(node)) { 071 throw new NodeException(String.format("Trying to remove unexisting child %s of %s", node, this)); 072 } 073 childrenNodes.remove(node); 074 node.setParent(null); 075 } 076 077 public List<Node> getChildren() { 078 return childrenNodes; 079 } 080 081 public void setChildren(List<Node> children) throws NodeException { 082 for (Node child : children) { 083 if (equals(child)) { 084 throw new NodeException(String.format("Node %s cannot be made a child of itself", child)); 085 } 086 if (isChildOf(child)) { 087 throw new NodeException(String.format("Cycle detected while trying to set children of %s.", this)); 088 } 089 } 090 childrenNodes = children; 091 } 092 093 public abstract NodeTypeFamily getNodeTypeFamily(); 094 095 public boolean isLeaf() { 096 return getNodeTypeFamily() == NodeTypeFamily.LEAF; 097 } 098 099 public Integer getOrder() { 100 Integer order = null; 101 if (parentNode != null) { 102 order = parentNode.getChildren().indexOf(this); 103 } 104 return order; 105 } 106 107 public void setOrder(Integer order) throws NodeException { 108 if (order == null) { 109 throw new NodeException(String.format("Cannot set node order to null on %s", this)); 110 } 111 if (parentNode == null) { 112 throw new NodeException(String.format("Cannot set order on node %s unless it has a parent", this)); 113 } 114 List<Node> siblings = parentNode.getChildren(); 115 siblings.remove(this); 116 if (order < 0 || (order > 0 && order > siblings.size())) { 117 throw new NodeException(String.format("Incorrect node order value (%s) for %s", order, this)); 118 } 119 siblings.add(order, this); 120 parentNode.setChildren(siblings); 121 } 122 123 public void moveTo(Node container, Integer order) throws NodeException { 124 setParent(container); 125 setOrder(order); 126 } 127 128 public void insertAfter(Node node) throws NodeException { 129 node.getParent().addChild(this); 130 moveTo(node.getParent(), node.getOrder() + 1); 131 } 132 133 public boolean hasSiblings() { 134 if (parentNode == null) { 135 return false; 136 } 137 return parentNode.getChildren().size() > 1; 138 } 139 140 public Node getNextNode() { 141 int order = getOrder(); 142 List<Node> siblings = parentNode.getChildren(); 143 if (order + 1 >= siblings.size()) { 144 return null; 145 } 146 return siblings.get(order + 1); 147 } 148 149 public Node getPreviousNode() { 150 int order = getOrder(); 151 if (order == 0) { 152 return null; 153 } 154 List<Node> siblings = parentNode.getChildren(); 155 return siblings.get(order - 1); 156 } 157 158 public boolean hasChildren() { 159 return !childrenNodes.isEmpty(); 160 } 161 162 public boolean isChildOf(Node node) { 163 boolean res = false; 164 Node parent = parentNode; 165 while (parent != null) { 166 if (parent == node) { 167 res = true; 168 break; 169 } 170 parent = parent.getParent(); 171 } 172 return res; 173 } 174 175 public void removeDescendants() throws NodeException { 176 for (Node child : childrenNodes) { 177 child.removeDescendants(); 178 child.clearParent(); 179 } 180 childrenNodes.clear(); 181 } 182 183 public List<Node> getDescendants() { 184 List<Node> descendants = new ArrayList<Node>(); 185 collectDescendants(descendants); 186 return descendants; 187 } 188 189 public void collectDescendants(List<Node> nodes) { 190 for (Node child : childrenNodes) { 191 nodes.add(child); 192 child.collectDescendants(nodes); 193 } 194 } 195 196}