Only documentation
[cdmlib.git] / cdmlib-model / src / main / java / eu / etaxonomy / cdm / model / description / FeatureNode.java
1 /**
2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
5 *
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
8 */
9
10 package eu.etaxonomy.cdm.model.description;
11
12 import java.util.ArrayList;
13 import java.util.List;
14
15 import javax.persistence.Entity;
16 import javax.persistence.JoinColumn;
17 import javax.persistence.ManyToOne;
18 import javax.persistence.OneToMany;
19 import javax.persistence.Transient;
20 import javax.swing.tree.TreeNode;
21 import javax.xml.bind.annotation.XmlAccessType;
22 import javax.xml.bind.annotation.XmlAccessorType;
23 import javax.xml.bind.annotation.XmlElement;
24 import javax.xml.bind.annotation.XmlElementWrapper;
25 import javax.xml.bind.annotation.XmlIDREF;
26 import javax.xml.bind.annotation.XmlRootElement;
27 import javax.xml.bind.annotation.XmlSchemaType;
28 import javax.xml.bind.annotation.XmlType;
29
30 import org.apache.log4j.Logger;
31 import org.hibernate.annotations.Cascade;
32 import org.hibernate.annotations.CascadeType;
33
34 import eu.etaxonomy.cdm.model.common.VersionableEntity;
35 import eu.etaxonomy.cdm.model.taxon.Taxon;
36
37 /**
38 * The class for tree nodes within a {@link FeatureTree feature tree} structure.
39 * Feature nodes are the elementary components of such a tree since they might
40 * be related to other nodes as a parent or as a child. A feature node belongs
41 * at most to one feature tree. It cannot have more than one parent node but
42 * may have several child nodes. Parent/child relations are bidirectional:
43 * a node N1 is the parent of a node N2 if and only if the node N2 is a child of
44 * the node N1.
45 *
46 * @author m.doering
47 * @version 1.0
48 * @created 08-Nov-2007 13:06:16
49 */
50 @XmlAccessorType(XmlAccessType.FIELD)
51 @XmlType(name = "FeatureNode", propOrder = {
52 "feature",
53 // "type",
54 "parent",
55 "children"
56 })
57 @XmlRootElement(name = "FeatureNode")
58 @Entity
59 public class FeatureNode extends VersionableEntity {
60 static Logger logger = Logger.getLogger(FeatureNode.class);
61
62 @XmlElement(name = "Feature")
63 @XmlIDREF
64 @XmlSchemaType(name = "IDREF")
65 private Feature feature;
66
67 // @XmlElement(name = "FeatureType")
68 // @XmlIDREF
69 // @XmlSchemaType(name = "IDREF")
70 // private Feature type;
71
72 @XmlElement(name = "Parent")
73 @XmlIDREF
74 @XmlSchemaType(name = "IDREF")
75 private FeatureNode parent;
76
77 @XmlElementWrapper(name = "Children")
78 @XmlElement(name = "Child")
79 @XmlIDREF
80 @XmlSchemaType(name = "IDREF")
81 private List<FeatureNode> children = new ArrayList<FeatureNode>();
82
83 /**
84 * Class constructor: creates a new empty feature node instance.
85 */
86 protected FeatureNode() {
87 super();
88 }
89
90 /**
91 * Creates a new empty feature node instance.
92 *
93 * @see #NewInstance(Feature)
94 */
95 public static FeatureNode NewInstance(){
96 return new FeatureNode();
97 }
98
99 /**
100 * Creates a new feature node instance only with the given {@link Feature feature}
101 * (without parent and children).
102 *
103 * @param feature the feature assigned to the new feature node
104 * @see #NewInstance()
105 */
106 public static FeatureNode NewInstance(Feature feature){
107 FeatureNode result = new FeatureNode();
108 result.setFeature(feature);
109 return result;
110 }
111
112
113
114
115 //** ********************** FEATURE ******************************/
116 // /**
117 // * Does the same as getFeature
118 // */
119 // @Transient
120 // @Deprecated
121 // protected Feature getType() {
122 // return feature;
123 // }
124 // /**
125 // * Does the same as setFeature
126 // */
127 // protected void setType(Feature feature) {
128 // this.feature = feature;
129 // }
130
131 /**
132 * Returns the {@link Feature feature} <i>this</i> feature node is based on.
133 */
134 @ManyToOne
135 public Feature getFeature() {
136 return feature;
137 }
138 /**
139 * @see #getFeature()
140 */
141 public void setFeature(Feature feature) {
142 this.feature = feature;
143 }
144
145
146 //** ********************** PARENT ******************************/
147
148
149 /**
150 * Returns the feature node <i>this</i> feature node is a child of.
151 *
152 * @see #getChildren()
153 */
154 @ManyToOne
155 @JoinColumn(name="parent_fk")
156 @Cascade({CascadeType.SAVE_UPDATE})
157 public FeatureNode getParent() {
158 return parent;
159 }
160 /**
161 * Assigns the given feature node as the parent of <i>this</i> feature node.
162 * Due to bidirectionality this method must also add <i>this</i> feature node
163 * to the list of children of the given parent.
164 *
165 * @param parent the feature node to be set as parent
166 * @see #getParent()
167 */
168 protected void setParent(FeatureNode parent) {
169 this.parent = parent;
170 }
171
172 //** ********************** CHILDREN ******************************/
173
174 /**
175 * Returns the (ordered) list of feature nodes which are children nodes of
176 * <i>this</i> feature node.
177 */
178 @OneToMany(mappedBy="parent")
179 @Cascade({CascadeType.SAVE_UPDATE})
180 public List<FeatureNode> getChildren() {
181 return children;
182 }
183 /**
184 * Assigns the given feature node list as the list of children of
185 * <i>this</i> feature node. Due to bidirectionality this method must also
186 * add <i>this</i> feature node to the list of children of the given parent.
187 *
188 * @param children the feature node list to be set as child list
189 * @see #getChildren()
190 * @see #addChild(FeatureNode)
191 * @see #addChild(FeatureNode, int)
192 */
193 public void setChildren(List<FeatureNode> children) {
194 this.children = children;
195 }
196 /**
197 * Adds the given feature node at the end of the list of children of
198 * <i>this</i> feature node. Due to bidirectionality this method must also
199 * assign <i>this</i> feature node as the parent of the given child.
200 *
201 * @param child the feature node to be added
202 * @see #getChildren()
203 * @see #setChildren(List)
204 * @see #addChild(FeatureNode, int)
205 * @see #removeChild(FeatureNode)
206 * @see #removeChild(int)
207 */
208 public void addChild(FeatureNode child){
209 addChild(child, children.size());
210 }
211 /**
212 * Inserts the given feature node in the list of children of <i>this</i> feature node
213 * at the given (index + 1) position. If the given index is out of bounds
214 * an exception will arise.<BR>
215 * Due to bidirectionality this method must also assign <i>this</i> feature node
216 * as the parent of the given child.
217 *
218 * @param child the feature node to be added
219 * @param index the integer indicating the position at which the child
220 * should be added
221 * @see #getChildren()
222 * @see #setChildren(List)
223 * @see #addChild(FeatureNode)
224 * @see #removeChild(FeatureNode)
225 * @see #removeChild(int)
226 */
227 public void addChild(FeatureNode child, int index){
228 if (index < 0 || index > children.size() + 1){
229 throw new IndexOutOfBoundsException("Wrong index");
230 }
231 if (child.getParent() != null){
232 child.getParent().removeChild(child);
233 }
234 child.setParent(this);
235 children.add(index, child);
236 }
237 /**
238 * Removes the given feature node from the list of {@link #getChildren() children}
239 * of <i>this</i> feature node.
240 *
241 * @param child the feature node which should be removed
242 * @see #getChildren()
243 * @see #addChild(FeatureNode, int)
244 * @see #addChild(FeatureNode)
245 * @see #removeChild(int)
246 */
247 public void removeChild(FeatureNode child){
248 int index = children.indexOf(child);
249 if (index >= 0){
250 removeChild(index);
251 }
252 }
253 /**
254 * Removes the feature node placed at the given (index + 1) position from
255 * the list of {@link #getChildren() children} of <i>this</i> feature node.
256 * If the given index is out of bounds no child will be removed.
257 *
258 * @param index the integer indicating the position of the feature node to
259 * be removed
260 * @see #getChildren()
261 * @see #addChild(FeatureNode, int)
262 * @see #addChild(FeatureNode)
263 * @see #removeChild(FeatureNode)
264 */
265 public void removeChild(int index){
266 FeatureNode child = children.get(index);
267 if (child != null){
268 children.remove(index);
269 child.setParent(child);
270 }
271 }
272
273
274 /**
275 * Returns the feature node placed at the given (childIndex + 1) position
276 * within the list of {@link #getChildren() children} of <i>this</i> feature node.
277 * If the given index is out of bounds no child will be returned.
278 *
279 * @param childIndex the integer indicating the position of the feature node
280 * @see #getChildren()
281 * @see #addChild(FeatureNode, int)
282 * @see #removeChild(int)
283 */
284 @Transient
285 public FeatureNode getChildAt(int childIndex) {
286 return children.get(childIndex);
287 }
288
289 /**
290 * Returns the number of children nodes of <i>this</i> feature node.
291 *
292 * @see #getChildren()
293 */
294 @Transient
295 public int getChildCount() {
296 return children.size();
297 }
298
299 /**
300 * Returns the integer indicating the position of the given feature node
301 * within the list of {@link #getChildren() children} of <i>this</i> feature node.
302 * If the list does not contain this node then -1 will be returned.
303 *
304 * @param node the feature node the position of which is being searched
305 * @see #addChild(FeatureNode, int)
306 * @see #removeChild(int)
307 */
308 @Transient
309 // public int getIndex(TreeNode node) {
310 public int getIndex(FeatureNode node) {
311 if (! children.contains(node)){
312 return -1;
313 }else{
314 return children.indexOf(node);
315 }
316 }
317
318 /**
319 * Returns the boolean value indicating if <i>this</i> feature node has
320 * children (false) or not (true). A node without children is at the
321 * bottommost level of a tree and is called a leaf.
322 *
323 * @see #getChildren()
324 * @see #getChildCount()
325 */
326 @Transient
327 public boolean isLeaf() {
328 return children.size() < 1;
329 }
330
331
332
333 }