Project

General

Profile

Download (7.74 KB) Statistics
| Branch: | Tag: | Revision:
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.HashSet;
14
import java.util.List;
15
import java.util.Set;
16
import java.util.UUID;
17

    
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;
29

    
30
import org.apache.log4j.Logger;
31
import org.hibernate.annotations.Cascade;
32
import org.hibernate.annotations.CascadeType;
33
import org.hibernate.envers.Audited;
34

    
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;
38

    
39
/**
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}.
46
 * <P>
47
 * This class corresponds partially to ConceptTreeDefType according to the SDD
48
 * schema.
49
 * <P>
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.
53
 *
54
 * @see		MediaKey
55
 *
56
 * @author  m.doering
57
 * @created 08-Nov-2007 13:06:16
58
 */
59
@XmlAccessorType(XmlAccessType.FIELD)
60
@XmlType(name = "FeatureTree", propOrder = {
61
    "root",
62
    "representations"
63
})
64
@XmlRootElement(name = "FeatureTree")
65
@Entity
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")
68
@Audited
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);
72

    
73
	@XmlElement(name = "Root")
74
	@OneToOne(fetch = FetchType.LAZY)
75
	@Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE})
76
	private FeatureNode root;
77

    
78

    
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;}
94

    
95

    
96
//******************** FACTORY METHODS ******************************************/
97

    
98

    
99
    /**
100
	 * Creates a new feature tree instance with an empty {@link #getRoot() root node}.
101
	 *
102
	 * @see #NewInstance(UUID)
103
	 * @see #NewInstance(List)
104
	 */
105
	public static FeatureTree NewInstance(){
106
		return new FeatureTree();
107
	}
108

    
109
	/**
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).
113
	 *
114
	 * @param	uuid	the universally unique identifier
115
	 * @see 			#NewInstance()
116
	 * @see 			#NewInstance(List)
117
	 */
118
	public static FeatureTree NewInstance(UUID uuid){
119
		FeatureTree result =  new FeatureTree();
120
		result.setUuid(uuid);
121
		return result;
122
	}
123

    
124
	/**
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.
130
	 *
131
	 * @param	featureList	the feature list
132
	 * @see 				#NewInstance()
133
	 * @see 				#NewInstance(UUID)
134
	 */
135
	public static FeatureTree NewInstance(List<Feature> featureList){
136
		FeatureTree result =  new FeatureTree();
137
		FeatureNode root = result.getRoot();
138

    
139
		for (Feature feature : featureList){
140
			FeatureNode child = FeatureNode.NewInstance(feature);
141
			root.addChild(child);
142
		}
143

    
144
		return result;
145
	}
146

    
147

    
148
// ******************** CONSTRUCTOR *************************************/
149

    
150
	/**
151
	 * Class constructor: creates a new feature tree instance with an empty
152
	 * {@link #getRoot() root node}.
153
	 */
154
	protected FeatureTree() {
155
		super();
156
		root = FeatureNode.NewInstance();
157
		root.setFeatureTree(this);
158
	}
159

    
160
// ****************** GETTER / SETTER **********************************/
161

    
162

    
163
//	@OneToMany
164
//	@Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
165
//	public Set<FeatureNode> getNodes() {
166
//		return nodes;
167
//	}
168
//	public void setNodes(Set<FeatureNode> nodes) {
169
//		this.nodes = nodes;
170
//	}
171

    
172
	/**
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.
177
	 */
178
	public FeatureNode getRoot() {
179
		return root;
180
	}
181
	/**
182
	 * @see	#getRoot()
183
	 */
184
	public void setRoot(FeatureNode root) {
185
		this.root = root;
186
	}
187

    
188
	/**
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.
191
	 */
192
	@Transient
193
	public List<FeatureNode> getRootChildren(){
194
		List<FeatureNode> result = new ArrayList<FeatureNode>();
195
		result.addAll(root.getChildNodes());
196
		return result;
197
	}
198

    
199
	/**
200
	 * Computes a set of distinct features that are present in this feature tree
201
	 *
202
	 * @return
203
	 */
204
	@Transient
205
	public Set<Feature> getDistinctFeatures(){
206
		Set<Feature> features = new HashSet<Feature>();
207

    
208
		return root.getDistinctFeaturesRecursive(features);
209
	}
210

    
211
//*********************** CLONE ********************************************************/
212

    
213
	/**
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
219
	 *
220
	 *
221
	 * @see eu.etaxonomy.cdm.model.common.TermBase#clone()
222
	 * @see java.lang.Object#clone()
223
	 */
224
	@Override
225

    
226
	public Object clone() {
227
		FeatureTree result;
228
		try {
229
			result = (FeatureTree)super.clone();
230
		}catch (CloneNotSupportedException e) {
231
			logger.warn("Object does not implement cloneable");
232
			e.printStackTrace();
233
			return null;
234
		}
235
		FeatureNode rootClone = this.getRoot().cloneDescendants();
236
		result.root = rootClone;
237

    
238
		return result;
239

    
240
	}
241

    
242

    
243
}
(10-10/36)