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
.cdm
.model
.description
;
12 import java
.util
.ArrayList
;
13 import java
.util
.HashSet
;
14 import java
.util
.List
;
16 import java
.util
.UUID
;
18 import javax
.persistence
.Entity
;
19 import javax
.persistence
.FetchType
;
20 import javax
.persistence
.OneToMany
;
21 import javax
.persistence
.OneToOne
;
22 import javax
.persistence
.Transient
;
23 import javax
.xml
.bind
.annotation
.XmlAccessType
;
24 import javax
.xml
.bind
.annotation
.XmlAccessorType
;
25 import javax
.xml
.bind
.annotation
.XmlElement
;
26 import javax
.xml
.bind
.annotation
.XmlElementWrapper
;
27 import javax
.xml
.bind
.annotation
.XmlRootElement
;
28 import javax
.xml
.bind
.annotation
.XmlType
;
30 import org
.apache
.log4j
.Logger
;
31 import org
.hibernate
.annotations
.Cascade
;
32 import org
.hibernate
.annotations
.CascadeType
;
33 import org
.hibernate
.envers
.Audited
;
35 import eu
.etaxonomy
.cdm
.model
.common
.IdentifiableEntity
;
36 import eu
.etaxonomy
.cdm
.model
.common
.Representation
;
37 import eu
.etaxonomy
.cdm
.strategy
.cache
.common
.IIdentifiableEntityCacheStrategy
;
40 * The class to arrange {@link Feature features} (characters) in a tree structure.
41 * Feature trees are essential as interactive multiple-access keys for
42 * determination process and for systematical output arrangement of
43 * {@link DescriptionElementBase description elements} according to different goals but may also be used
44 * to define flat feature subsets for filtering purposes.<BR>
45 * A feature tree is build on {@link FeatureNode feature nodes}.
47 * This class corresponds partially to ConceptTreeDefType according to the SDD
50 * Note: The tree structure of features used for purposes described above has
51 * nothing in common with the possible hierarchical structure of features
52 * depending on their grade of precision.
57 * @created 08-Nov-2007 13:06:16
59 @XmlAccessorType(XmlAccessType
.FIELD
)
60 @XmlType(name
= "FeatureTree", propOrder
= {
64 @XmlRootElement(name
= "FeatureTree")
66 //@Indexed disabled to reduce clutter in indexes, since this type is not used by any search
67 //@Indexed(index = "eu.etaxonomy.cdm.model.description.FeatureTree")
69 public class FeatureTree
extends IdentifiableEntity
<IIdentifiableEntityCacheStrategy
> implements Cloneable
{
70 private static final long serialVersionUID
= -6713834139003172735L;
71 private static final Logger logger
= Logger
.getLogger(FeatureTree
.class);
73 @XmlElement(name
= "Root")
74 @OneToOne(fetch
= FetchType
.LAZY
)
75 @Cascade({CascadeType
.SAVE_UPDATE
, CascadeType
.MERGE
})
76 private FeatureNode root
;
79 // TODO needed? FeatureTree was a TermBase until v3.3 but was removed from
80 //it as TermBase got the termType which does not apply to FeatureTree.
81 //We need to check how far representations and uri is still required
82 //or can be deleted. Current implementations seem all to use the title cache
83 //instead of representation. This may not be correct.
84 @XmlElementWrapper(name
= "Representations")
85 @XmlElement(name
= "Representation")
86 @OneToMany(fetch
=FetchType
.EAGER
, orphanRemoval
=true)
87 @Cascade( { CascadeType
.SAVE_UPDATE
, CascadeType
.MERGE
, CascadeType
.DELETE
})
88 // @IndexedEmbedded no need for embedding since we are using the DefinedTermBaseClassBridge
89 private Set
<Representation
> representations
= new HashSet
<Representation
>();
90 //make them private for now as we may delete representations in future
91 //otherwise if we decide to use representations we can make the getters public
92 private Set
<Representation
> getRepresentations() {return representations
;}
93 private void setRepresentations(Set
<Representation
> representations
) {this.representations
= representations
;}
96 //******************** FACTORY METHODS ******************************************/
100 * Creates a new feature tree instance with an empty {@link #getRoot() root node}.
102 * @see #NewInstance(UUID)
103 * @see #NewInstance(List)
105 public static FeatureTree
NewInstance(){
106 return new FeatureTree();
110 * Creates a new feature tree instance with an empty {@link #getRoot() root node}
111 * and assigns to the new feature tree the given
112 * UUID (universally unique identifier).
114 * @param uuid the universally unique identifier
115 * @see #NewInstance()
116 * @see #NewInstance(List)
118 public static FeatureTree
NewInstance(UUID uuid
){
119 FeatureTree result
= new FeatureTree();
120 result
.setUuid(uuid
);
125 * Creates a new feature tree instance with a {@link #getRoot() root node}
126 * the children of which are the feature nodes build on the base of the
127 * given list of {@link Feature features}. This corresponds to a flat feature tree.
128 * For each feature within the list a new {@link FeatureNode feature node} without
129 * children nodes will be created.
131 * @param featureList the feature list
132 * @see #NewInstance()
133 * @see #NewInstance(UUID)
135 public static FeatureTree
NewInstance(List
<Feature
> featureList
){
136 FeatureTree result
= new FeatureTree();
137 FeatureNode root
= result
.getRoot();
139 for (Feature feature
: featureList
){
140 FeatureNode child
= FeatureNode
.NewInstance(feature
);
141 root
.addChild(child
);
148 // ******************** CONSTRUCTOR *************************************/
151 * Class constructor: creates a new feature tree instance with an empty
152 * {@link #getRoot() root node}.
154 protected FeatureTree() {
156 root
= FeatureNode
.NewInstance();
157 root
.setFeatureTree(this);
160 // ****************** GETTER / SETTER **********************************/
164 // @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
165 // public Set<FeatureNode> getNodes() {
168 // public void setNodes(Set<FeatureNode> nodes) {
169 // this.nodes = nodes;
173 * Returns the topmost {@link FeatureNode feature node} (root node) of <i>this</i>
174 * feature tree. The root node does not have any parent. Since feature nodes
175 * recursively point to their child nodes the complete feature tree is
176 * defined by its root node.
178 public FeatureNode
getRoot() {
184 public void setRoot(FeatureNode root
) {
189 * Returns the (ordered) list of {@link FeatureNode feature nodes} which are immediate
190 * children of the root node of <i>this</i> feature tree.
193 public List
<FeatureNode
> getRootChildren(){
194 List
<FeatureNode
> result
= new ArrayList
<FeatureNode
>();
195 result
.addAll(root
.getChildNodes());
200 * Computes a set of distinct features that are present in this feature tree
205 public Set
<Feature
> getDistinctFeatures(){
206 Set
<Feature
> features
= new HashSet
<Feature
>();
208 return root
.getDistinctFeaturesRecursive(features
);
211 //*********************** CLONE ********************************************************/
214 * Clones <i>this</i> FeatureTree. This is a shortcut that enables to create
215 * a new instance that differs only slightly from <i>this</i> FeatureTree by
216 * modifying only some of the attributes.
217 * FeatureNodes always belong only to one tree, so all FeatureNodes are cloned to build
218 * the new FeatureTree
221 * @see eu.etaxonomy.cdm.model.common.TermBase#clone()
222 * @see java.lang.Object#clone()
226 public Object
clone() {
229 result
= (FeatureTree
)super.clone();
230 }catch (CloneNotSupportedException e
) {
231 logger
.warn("Object does not implement cloneable");
235 FeatureNode rootClone
= this.getRoot().cloneDescendants();
236 result
.root
= rootClone
;