Project

General

Profile

Download (7.55 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
import org.hibernate.search.annotations.Indexed;
35

    
36
import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
37
import eu.etaxonomy.cdm.model.common.Representation;
38
import eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy;
39

    
40
/**
41
 * The class to arrange {@link Feature features} (characters) in a tree structure.
42
 * Feature trees are essential as interactive multiple-access keys for
43
 * determination process and for systematical output arrangement of
44
 * {@link DescriptionElementBase description elements} according to different goals but may also be used
45
 * to define flat feature subsets for filtering purposes.<BR>
46
 * A feature tree is build on {@link FeatureNode feature nodes}.
47
 * <P>
48
 * This class corresponds partially to ConceptTreeDefType according to the SDD
49
 * schema.
50
 * <P>
51
 * Note: The tree structure of features used for purposes described above has
52
 * nothing in common with the possible hierarchical structure of features
53
 * depending on their grade of precision.
54
 *
55
 * @see		MediaKey
56
 *
57
 * @author  m.doering
58
 * @created 08-Nov-2007 13:06:16
59
 */
60
@XmlAccessorType(XmlAccessType.FIELD)
61
@XmlType(name = "FeatureTree", propOrder = {
62
    "root",
63
    "representations"
64
})
65
@XmlRootElement(name = "FeatureTree")
66
@Entity
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
    private Set<Representation> getRepresentations() {return representations;}
91
    private void setRepresentations(Set<Representation> representations) {this.representations = representations;}
92

    
93

    
94
//******************** FACTORY METHODS ******************************************/
95

    
96

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

    
107
	/**
108
	 * Creates a new feature tree instance with an empty {@link #getRoot() root node}
109
	 * and assigns to the new feature tree the given
110
	 * UUID (universally unique identifier).
111
	 *
112
	 * @param	uuid	the universally unique identifier
113
	 * @see 			#NewInstance()
114
	 * @see 			#NewInstance(List)
115
	 */
116
	public static FeatureTree NewInstance(UUID uuid){
117
		FeatureTree result =  new FeatureTree();
118
		result.setUuid(uuid);
119
		return result;
120
	}
121

    
122
	/**
123
	 * Creates a new feature tree instance with a {@link #getRoot() root node}
124
	 * the children of which are the feature nodes build on the base of the
125
	 * given list of {@link Feature features}. This corresponds to a flat feature tree.
126
	 * For each feature within the list a new {@link FeatureNode feature node} without
127
	 * children nodes will be created.
128
	 *
129
	 * @param	featureList	the feature list
130
	 * @see 				#NewInstance()
131
	 * @see 				#NewInstance(UUID)
132
	 */
133
	public static FeatureTree NewInstance(List<Feature> featureList){
134
		FeatureTree result =  new FeatureTree();
135
		FeatureNode root = result.getRoot();
136

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

    
142
		return result;
143
	}
144

    
145

    
146
// ******************** CONSTRUCTOR *************************************/
147

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

    
158
// ****************** GETTER / SETTER **********************************/
159

    
160

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

    
170
	/**
171
	 * Returns the topmost {@link FeatureNode feature node} (root node) of <i>this</i>
172
	 * feature tree. The root node does not have any parent. Since feature nodes
173
	 * recursively point to their child nodes the complete feature tree is
174
	 * defined by its root node.
175
	 */
176
	public FeatureNode getRoot() {
177
		return root;
178
	}
179
	/**
180
	 * @see	#getRoot()
181
	 */
182
	public void setRoot(FeatureNode root) {
183
		this.root = root;
184
	}
185

    
186
	/**
187
	 * Returns the (ordered) list of {@link FeatureNode feature nodes} which are immediate
188
	 * children of the root node of <i>this</i> feature tree.
189
	 */
190
	@Transient
191
	public List<FeatureNode> getRootChildren(){
192
		List<FeatureNode> result = new ArrayList<FeatureNode>();
193
		result.addAll(root.getChildNodes());
194
		return result;
195
	}
196

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

    
206
		return root.getDistinctFeaturesRecursive(features);
207
	}
208

    
209
//*********************** CLONE ********************************************************/
210

    
211
	/**
212
	 * Clones <i>this</i> FeatureTree. This is a shortcut that enables to create
213
	 * a new instance that differs only slightly from <i>this</i> FeatureTree by
214
	 * modifying only some of the attributes.
215
	 * FeatureNodes always belong only to one tree, so all FeatureNodes are cloned to build
216
	 * the new FeatureTree
217
	 *
218
	 *
219
	 * @see eu.etaxonomy.cdm.model.common.TermBase#clone()
220
	 * @see java.lang.Object#clone()
221
	 */
222
	@Override
223

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

    
236
		return result;
237

    
238
	}
239

    
240

    
241
}
(10-10/36)