2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
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.
10 package eu
.etaxonomy
.taxeditor
.model
;
12 import java
.util
.ArrayList
;
13 import java
.util
.List
;
15 import eu
.etaxonomy
.cdm
.hibernate
.HibernateProxyHelper
;
16 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionBase
;
17 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionElementBase
;
18 import eu
.etaxonomy
.cdm
.model
.description
.Feature
;
19 import eu
.etaxonomy
.cdm
.model
.description
.FeatureNode
;
20 import eu
.etaxonomy
.cdm
.model
.description
.FeatureTree
;
21 import eu
.etaxonomy
.cdm
.model
.description
.TaxonDescription
;
24 * This class is a simple container to allow generation of a datastructure that
25 * describes a feature tree according to a specific description element, i.e a tree
26 * structure that halds only the {@link FeatureNode}s that are relevant for a specific
27 * {@link TaxonDescription} as well as the {@link DescriptionElementBase} at the leaf level.
29 * This kind of datastructure is needed by interface elements such as viewers and greatly simplify
30 * the handling of {@link FeatureTree}s in conjunction with {@link TaxonDescription}s.
33 * @created Sep 20, 2010
36 public class FeatureNodeContainer
{
40 private FeatureNodeContainer parent
;
44 private FeatureNode featureNode
;
45 private List
<FeatureNodeContainer
> children
= new ArrayList
<FeatureNodeContainer
>();
46 private List
<DescriptionElementBase
> descriptionElements
= new ArrayList
<DescriptionElementBase
>();
48 private FeatureNodeContainerTree containerTree
;
54 protected FeatureNodeContainer(FeatureNodeContainerTree containerTree
) {
55 this.containerTree
= containerTree
;
56 this.containerTree
.addContainer(this);
61 * Recursively traverse a branch of a feature tree and check if there are
67 protected void findLeaves(FeatureNode featureNode
) {
68 if(featureNode
.isLeaf()){
69 buildLeaf(featureNode
);
71 for(FeatureNode childNode
: featureNode
.getChildNodes()){
72 findLeaves(childNode
);
83 private void buildLeaf(FeatureNode featureNode
){
84 if(featureNode
.getFeature() == null){
85 throw new IllegalArgumentException("The given feature node does not have a feature.");
88 Feature feature
= (Feature
) HibernateProxyHelper
.deproxy(featureNode
.getFeature());
90 // get feature node container for the given feature
91 FeatureNodeContainer container
= containerTree
.getFeatureNodeContainer(feature
);
93 // get description elements for the given feature
94 List
<DescriptionElementBase
> elements
= containerTree
.getDescriptionsElementsForFeature(feature
);
95 // no description elements, so we should also remove the feature node container
96 if(elements
.isEmpty()){
97 if(container
!= null){
101 // there are description elements
103 if(container
== null){
104 container
= new FeatureNodeContainer(containerTree
);
105 container
.setFeatureNode(featureNode
);
106 // build the branch up to root level
107 container
.buildBranch();
109 // add description elements to the feature node container
110 container
.setDescriptionElements(elements
);
117 private void remove() {
118 if(getParent() != null){
119 if(getParent().getChildren().size() == 1){
120 getParent().remove();
122 getParent().removeChild(this);
128 * @param featureNodeContainer
130 private void removeChild(FeatureNodeContainer featureNodeContainer
) {
131 children
.remove(featureNodeContainer
);
138 * @param featureNodeMap
141 private void buildBranch(){
142 if(getParent() == null){
143 FeatureNode parentFeatureNode
= getFeatureNode().getParent();
145 if(parentFeatureNode
.isRoot()){
146 containerTree
.getRoot().addChild(this);
148 FeatureNodeContainer parentContainer
= containerTree
.getFeatureNodeContainer(parentFeatureNode
);
149 if(parentContainer
== null){
150 parentContainer
= new FeatureNodeContainer(containerTree
);
151 parentContainer
.setFeatureNode(parentFeatureNode
);
154 parentContainer
.addChild(this);
156 parentContainer
.buildBranch();
163 * <p>Getter for the field <code>children</code>.</p>
165 * @return a {@link java.util.List} object.
167 public List
<FeatureNodeContainer
> getChildren() {
172 * Sets the list of children of this containers children
174 * @param children a {@link java.util.List} object.
175 * @throws java.lang.IllegalStateException when <code>this</code> container contains a description element.
177 public void setChildren(List
<FeatureNodeContainer
> children
) {
178 if(descriptionElements
.isEmpty()){
179 this.children
= children
;
181 throw new IllegalStateException("Container may not have a description element set when setting children.");
186 * Adds a child container to the list of this containers children
188 * @param container a {@link eu.etaxonomy.taxeditor.model.FeatureNodeContainer} object.
189 * @throws java.lang.IllegalStateException when <code>this</code> container contains a description element.
191 public void addChild(FeatureNodeContainer container
){
192 if(descriptionElements
.isEmpty()){
193 children
.add(container
);
194 container
.setParent(this);
196 throw new IllegalStateException("Container may not have a description element set when adding children.");
200 public void addDescriptionElement(DescriptionElementBase descriptionElement
){
201 descriptionElements
.add(descriptionElement
);
204 public void removeDescriptionElement(DescriptionElementBase descriptionElement
){
205 descriptionElements
.remove(descriptionElement
);
209 * If {@link #isLeaf()} is true, i.e. this container should have elements, returns the list of description elements.
211 * @return a {@link java.util.List} object.
213 public List
<DescriptionElementBase
> getDescriptionElements() {
214 return descriptionElements
;
218 * Cumulates description elements for <code>this</code> container as well as child feature nodes recursively,
219 * thus returning a list of description elements for the branch of the feature tree starting with <code>this</code>
222 * @return a {@link java.util.List} object.
224 public List
<DescriptionElementBase
> getDescriptionElementsForEntireBranch(){
225 return getDescriptionElementsRecursively(new ArrayList
<DescriptionElementBase
>());
228 private List
<DescriptionElementBase
> getDescriptionElementsRecursively(List
<DescriptionElementBase
> descriptionElements
){
230 descriptionElements
.addAll(getDescriptionElements());
232 for(FeatureNodeContainer container
: getChildren()){
233 container
.getDescriptionElementsRecursively(descriptionElements
);
236 return descriptionElements
;
239 protected List
<FeatureNodeContainer
> getLeafs(){
240 List
<FeatureNodeContainer
> leafs
= new ArrayList
<FeatureNodeContainer
>();
245 for(FeatureNodeContainer container
: getChildren()){
246 leafs
.addAll(container
.getLeafs());
253 * Set the description element
255 * @throws java.lang.IllegalStateException when <code>this</code> container contains child container.
256 * @param descriptionElements a {@link java.util.List} object.
258 public void setDescriptionElements(List
<DescriptionElementBase
> descriptionElements
) {
259 if(children
.isEmpty()){
260 this.descriptionElements
= descriptionElements
;
262 throw new IllegalStateException("Container may not contain child container when adding description elements.");
267 * If the container is a leaf, it will hold a description element and no child containers
271 public boolean isLeaf(){
272 return ! descriptionElements
.isEmpty() && children
.isEmpty();
276 * <p>Setter for the field <code>featureNode</code>.</p>
278 * @param featureNode a {@link eu.etaxonomy.cdm.model.description.FeatureNode} object.
280 public void setFeatureNode(FeatureNode featureNode
) {
281 this.featureNode
= featureNode
;
285 * <p>Getter for the field <code>featureNode</code>.</p>
287 * @return a {@link eu.etaxonomy.cdm.model.description.FeatureNode} object.
289 public FeatureNode
getFeatureNode() {
296 * @return a {@link eu.etaxonomy.cdm.model.description.Feature} object.
298 public Feature
getFeature(){
299 if(featureNode
!= null){
300 return featureNode
.getFeature();
306 * <p>Getter for the field <code>description</code>.</p>
308 * @return a {@link eu.etaxonomy.cdm.model.description.DescriptionBase} object.
310 public DescriptionBase
getDescription(){
311 return containerTree
.getDescription();
314 public FeatureNodeContainerTree
getContainerTree(){
315 return containerTree
;
322 public void clear() {
324 descriptionElements
.clear();
331 public boolean isEmpty() {
332 return children
.isEmpty() && descriptionElements
.isEmpty();
338 public FeatureNodeContainer
getParent() {
344 * @param parent the parent to set
346 public void setParent(FeatureNodeContainer parent
) {
347 this.parent
= parent
;