Project

General

Profile

Revision 0774bb03

ID0774bb031c0cf7ae74949cc283d80c3d49ea5565
Parent 3048fbc9
Child ab5b84ab

Added by Andreas Müller 12 months ago

ref #6794 remove FeatureTree class

View differences:

cdmlib-model/src/main/java/eu/etaxonomy/cdm/model/term/FeatureTree.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.term;
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.Column;
19
import javax.persistence.Entity;
20
import javax.persistence.FetchType;
21
import javax.persistence.OneToMany;
22
import javax.persistence.OneToOne;
23
import javax.persistence.Transient;
24
import javax.validation.constraints.NotNull;
25
import javax.xml.bind.annotation.XmlAccessType;
26
import javax.xml.bind.annotation.XmlAccessorType;
27
import javax.xml.bind.annotation.XmlAttribute;
28
import javax.xml.bind.annotation.XmlElement;
29
import javax.xml.bind.annotation.XmlElementWrapper;
30
import javax.xml.bind.annotation.XmlRootElement;
31
import javax.xml.bind.annotation.XmlType;
32

  
33
import org.apache.log4j.Logger;
34
import org.hibernate.annotations.Cascade;
35
import org.hibernate.annotations.CascadeType;
36
import org.hibernate.annotations.Type;
37
import org.hibernate.envers.Audited;
38

  
39
import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
40
import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
41
import eu.etaxonomy.cdm.model.description.Feature;
42
import eu.etaxonomy.cdm.model.description.MediaKey;
43
import eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy;
44

  
45
/**
46
 * The class to arrange {@link Feature features} (characters) in a tree structure.
47
 * Feature trees are essential as interactive multiple-access keys for
48
 * determination process and for systematical output arrangement of
49
 * {@link DescriptionElementBase description elements} according to different goals
50
 * but may also be used to define flat feature subsets for filtering purposes.<BR>
51
 * A feature tree is build on {@link TermTreeNode feature nodes}.
52
 * <P>
53
 * This class corresponds partially to ConceptTreeDefType according to the SDD
54
 * schema.
55
 * <P>
56
 * Note: The tree structure of features used for purposes described above has
57
 * nothing in common with the possible hierarchical structure of features
58
 * depending on their grade of precision.
59
 *
60
 * @see		MediaKey
61
 *
62
 * @author  m.doering
63
 * @since 08-Nov-2007 13:06:16
64
 */
65
@XmlAccessorType(XmlAccessType.FIELD)
66
@XmlType(name = "FeatureTree", propOrder = {
67
    "root",
68
    "termType",
69
    "allowDuplicates",
70
    "representations"
71

  
72
})
73
@XmlRootElement(name = "FeatureTree")
74
@Entity
75
//@Indexed disabled to reduce clutter in indexes, since this type is not used by any search
76
//@Indexed(index = "eu.etaxonomy.cdm.model.term.FeatureTree")
77
@Audited
78
public class FeatureTree <T extends DefinedTermBase>
79
            extends IdentifiableEntity<IIdentifiableEntityCacheStrategy>
80
            implements IHasTermType, Cloneable{
81

  
82
	private static final long serialVersionUID = -6713834139003172735L;
83
	private static final Logger logger = Logger.getLogger(FeatureTree.class);
84

  
85
	@XmlElement(name = "Root")
86
	@OneToOne(fetch = FetchType.LAZY, targetEntity=TermTreeNode.class)
87
	@Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE})
88
	private TermTreeNode<T> root;
89

  
90
    /**
91
     * The {@link TermType type} of this term collection. All nodes in the graph must refer to a term of the same type.
92
     */
93
    @XmlAttribute(name ="TermType")
94
    @Column(name="termType")
95
    @NotNull
96
    @Type(type = "eu.etaxonomy.cdm.hibernate.EnumUserType",
97
        parameters = {@org.hibernate.annotations.Parameter(name  = "enumClass", value = "eu.etaxonomy.cdm.model.term.TermType")}
98
    )
99
    @Audited
100
    private TermType termType;
101

  
102
    // TODO needed? FeatureTree was a TermBase until v3.3 but was removed from
103
	//it as TermBase got the termType which does not apply to FeatureTree.
104
	//We need to check how far representations and uri is still required
105
	//or can be deleted. Current implementations seem all to use the title cache
106
	//instead of representation. This may not be correct.
107
	@XmlElementWrapper(name = "Representations")
108
    @XmlElement(name = "Representation")
109
    @OneToMany(fetch=FetchType.EAGER, orphanRemoval=true)
110
    @Cascade( { CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.DELETE})
111
    // @IndexedEmbedded no need for embedding since we are using the DefinedTermBaseClassBridge
112
    private Set<Representation> representations = new HashSet<>();
113
    //make them private for now as we may delete representations in future
114
	//otherwise if we decide to use representations we can make the getters public
115
	private Set<Representation> getRepresentations() {return representations;}
116
    private void setRepresentations(Set<Representation> representations) {this.representations = representations;}
117

  
118
    //#7372 indicates if this tree/graph allows duplicated terms/features
119
    private boolean allowDuplicates = false;
120

  
121
//******************** FACTORY METHODS ******************************************/
122

  
123
    /**
124
     * Creates a new term collection instance for the given term type
125
     * with an empty {@link #getRoot() root node}.
126
     * @param termType the {@link TermType term type}, must not be null
127
     */
128
    public static <T extends DefinedTermBase<T>> FeatureTree<T> NewInstance(@NotNull TermType termType){
129
        return new FeatureTree<>(termType);
130
    }
131

  
132
    /**
133
	 * Creates a new feature tree instance with an empty {@link #getRoot() root node}.
134
	 *
135
	 * @see #NewInstance(UUID)
136
	 * @see #NewInstance(List)
137
	 */
138
	public static FeatureTree<Feature> NewInstance(){
139
		return new FeatureTree<>(TermType.Feature);
140
	}
141

  
142
	/**
143
	 * Creates a new feature tree instance with an empty {@link #getRoot() root node}
144
	 * and assigns to the new feature tree the given
145
	 * UUID (universally unique identifier).
146
	 *
147
	 * @param	uuid	the universally unique identifier
148
	 * @see 			#NewInstance()
149
	 * @see 			#NewInstance(List)
150
	 */
151
	public static <T extends DefinedTermBase<T>> FeatureTree<T> NewInstance(UUID uuid){
152
		FeatureTree<T> result =  new FeatureTree<>(TermType.Feature);
153
		result.setUuid(uuid);
154
		return result;
155
	}
156

  
157
	/**
158
	 * Creates a new feature tree instance with a {@link #getRoot() root node}
159
	 * the children of which are the feature nodes build on the base of the
160
	 * given list of {@link Feature features}. This corresponds to a flat feature tree.
161
	 * For each feature within the list a new {@link TermTreeNode feature node} without
162
	 * children nodes will be created.
163
	 *
164
	 * @param	featureList	the feature list
165
	 * @see 				#NewInstance()
166
	 * @see 				#NewInstance(UUID)
167
	 */
168
	public static FeatureTree<Feature> NewInstance(List<Feature> featureList){
169
		FeatureTree<Feature> result =  new FeatureTree<>(TermType.Feature);
170
		TermTreeNode<Feature> root = result.getRoot();
171

  
172
		for (Feature feature : featureList){
173
			root.addChild(feature);
174
		}
175

  
176
		return result;
177
	}
178

  
179

  
180
// ******************** CONSTRUCTOR *************************************/
181

  
182
    //for JAXB only, TODO needed?
183
    @Deprecated
184
    protected FeatureTree(){}
185

  
186
	/**
187
	 * Class constructor: creates a new feature tree instance with an empty
188
	 * {@link #getRoot() root node}.
189
	 */
190
	protected FeatureTree(TermType termType) {
191
        this.termType = termType;
192
        checkTermType(this);  //check not null
193
		root = new TermTreeNode<>(termType);
194
		root.setFeatureTree(this);
195
	}
196

  
197
// ****************** GETTER / SETTER **********************************/
198

  
199
	@Override
200
    public TermType getTermType() {
201
        return termType;
202
    }
203
    /**
204
	 * Returns the topmost {@link TermTreeNode feature node} (root node) of <i>this</i>
205
	 * feature tree. The root node does not have any parent. Since feature nodes
206
	 * recursively point to their child nodes the complete feature tree is
207
	 * defined by its root node.
208
	 */
209
	public TermTreeNode<T> getRoot() {
210
		return root;
211
	}
212

  
213
    /**
214
     * @deprecated this method is only for internal use when deleting a {@link FeatureTree}
215
     * from a database. It should never be called for other reasons.
216
     */
217
    @Deprecated
218
    public void removeRootNode() {
219
        this.root = null;
220
    }
221

  
222
	/**
223
	 * Returns the (ordered) list of {@link TermTreeNode feature nodes} which are immediate
224
	 * children of the root node of <i>this</i> feature tree.
225
	 */
226
	@Transient
227
	public List<TermTreeNode<T>> getRootChildren(){
228
		List<TermTreeNode<T>> result = new ArrayList<>();
229
		result.addAll(root.getChildNodes());
230
		return result;
231
	}
232

  
233
    public boolean isAllowDuplicates() {
234
        return allowDuplicates;
235
    }
236
    public void setAllowDuplicates(boolean allowDuplicates) {
237
        this.allowDuplicates = allowDuplicates;
238
    }
239

  
240
    /**
241
     * Throws {@link IllegalArgumentException} if the given
242
     * term has not the same term type as this term or if term type is null.
243
     * @param term
244
     */
245
    private void checkTermType(IHasTermType term) {
246
        IHasTermType.checkTermTypes(term, this);
247
    }
248

  
249
//******************** METHODS ***********************************************/
250

  
251
	/**
252
	 * Computes a set of distinct terms that are present in this feature tree
253
	 *
254
	 * @return
255
	 */
256
	@Transient
257
	public Set<T> getDistinctFeatures(){
258
	    Set<T> features = new HashSet<>();
259
	    return root.getDistinctFeaturesRecursive(features);
260
	}
261

  
262
//*********************** CLONE ********************************************************/
263

  
264
	/**
265
	 * Clones <i>this</i> {@link FeatureTree}. This is a shortcut that enables to create
266
	 * a new instance that differs only slightly from <i>this</i> tree by
267
	 * modifying only some of the attributes.
268
	 * {@link TermTreeNode tree nodes} always belong only to one tree, so all
269
	 * {@link TermTreeNode tree nodes} are cloned to build
270
	 * the new {@link FeatureTree}
271
	 *
272
	 *
273
	 * @see eu.etaxonomy.cdm.model.term.TermBase#clone()
274
	 * @see java.lang.Object#clone()
275
	 */
276
	@Override
277
	public Object clone() {
278
		FeatureTree<T> result;
279
		try {
280
			result = (FeatureTree<T>)super.clone();
281
		}catch (CloneNotSupportedException e) {
282
			logger.warn("Object does not implement cloneable");
283
			e.printStackTrace();
284
			return null;
285
		}
286
		TermTreeNode<T> rootClone = this.getRoot().cloneDescendants();
287
		result.root = rootClone;
288

  
289
		return result;
290

  
291
	}
292

  
293

  
294
}

Also available in: Unified diff

Add picture from clipboard (Maximum size: 40 MB)