Project

General

Profile

Download (9.49 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.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.Entity;
19
import javax.persistence.FetchType;
20
import javax.persistence.OneToOne;
21
import javax.persistence.Transient;
22
import javax.validation.constraints.NotNull;
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.XmlRootElement;
27
import javax.xml.bind.annotation.XmlType;
28

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

    
34
import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
35
import eu.etaxonomy.cdm.model.description.Feature;
36

    
37
/**
38
 * The class to arrange {@link DefinedTermBase terms} in a tree structure.
39
 * A term tree is build on {@link TermNode term nodes}.
40
 *
41
 * Special term trees:
42
 *
43
 * <B>Feature</B> trees are essential as interactive multiple-access keys for
44
 * determination process and for systematic output arrangement of
45
 * {@link DescriptionElementBase description elements} according to different goals
46
 * but may also be used to define flat feature subsets for filtering purposes.<BR>
47
 * <P>
48
 * If used as feature tree this class corresponds partially to ConceptTreeDefType
49
 * according to the SDD schema.
50
 * <P>
51
 * Note: The tree structure of terms used for purposes described above has
52
 * nothing in common with the possible hierarchical structure of terms
53
 * depending on their grade of precision.
54
 *
55
 * @author  m.doering
56
 * @since 08-Nov-2007 13:06:16
57
 */
58
@XmlAccessorType(XmlAccessType.FIELD)
59
@XmlType(name = "TermTree", propOrder = {
60
    "root",
61
})
62
@XmlRootElement(name = "TermTree")
63
@Entity
64
//@Indexed disabled to reduce clutter in indexes, since this type is not used by any search
65
//@Indexed(index = "eu.etaxonomy.cdm.model.term.TermTree")
66
@Audited
67
public class TermTree <T extends DefinedTermBase>
68
            extends TermGraphBase<T, TermNode>
69
            implements ITermTree<T, TermNode> {
70

    
71
	private static final long serialVersionUID = -6713834139003172735L;
72
	private static final Logger logger = LogManager.getLogger(TermTree.class);
73

    
74

    
75
    // TODO representations needed? TermTree was a TermBase until v3.3 but was removed from
76
    //it as TermBase got the termType which does not apply to TermTree.
77
    //We need to check how far representations and uri is still required
78
    //or can be deleted. Current implementations seem all to use the title cache
79
    //instead of representation. This may not be correct.
80
	// Note: since model 5.8 representations are back as FeatureTree became TermTree and
81
	//inherits from TermBase. Need to check if they are correctly handled. Anyway,
82
	//translations should be synchronized all over the system (there is a ticket for this)
83

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

    
89

    
90
//******************** FACTORY METHODS ******************************************/
91

    
92
    /**
93
     * Creates a new term collection instance for the given term type
94
     * with an empty {@link #getRoot() root node}.
95
     * @param termType the {@link TermType term type}, must not be null
96
     */
97
    public static <T extends DefinedTermBase<T>> TermTree<T> NewInstance(@NotNull TermType termType){
98
        return new TermTree<>(termType);
99
    }
100

    
101
    /**
102
     * Creates a new term collection instance for the given term type
103
     * with an empty {@link #getRoot() root node}.
104
     * @param termType the {@link TermType term type}, must not be null
105
     */
106
    public static <T extends DefinedTermBase> TermTree<T> NewInstance(@NotNull TermType termType, @SuppressWarnings("unused") Class<T> clazz){
107
        return new TermTree<>(termType);
108
    }
109

    
110
    /**
111
	 * Creates a new feature tree instance with an empty {@link #getRoot() root node}.
112
	 *
113
	 * @see #NewInstance(UUID)
114
	 * @see #NewInstance(List)
115
	 * @deprecated since 5.9. Use {@link #NewFeatureInstance()} instead
116
	 */
117
	@Deprecated
118
    public static TermTree<Feature> NewInstance(){
119
		return NewFeatureInstance();
120
	}
121

    
122
    public static TermTree<Feature> NewFeatureInstance(){
123
        return new TermTree<>(TermType.Feature);
124
    }
125

    
126

    
127
	/**
128
	 * @deprecated since 5.9, use {@link #NewFeatureInstance(UUID)} instead
129
	 */
130
	@Deprecated
131
    public static TermTree<? extends Feature> NewInstance(UUID uuid){
132
		return NewFeatureInstance(uuid);
133
	}
134
	/**
135
     * Creates a new feature tree instance with an empty {@link #getRoot() root node}
136
     * and assigns to the new feature tree the given
137
     * UUID (universally unique identifier).
138
     *
139
     * @param   uuid    the universally unique identifier
140
     * @see             #NewInstance()
141
     * @see             #NewInstance(List)
142
     */
143
    public static <T extends DefinedTermBase<T>> TermTree<T> NewFeatureInstance(UUID uuid){
144
        TermTree<T> result =  new TermTree<>(TermType.Feature);
145
        result.setUuid(uuid);
146
        return result;
147
    }
148

    
149

    
150
    /**
151
     * @deprecated sinde 5.9 use {@link #NewFeatureInstance(List)} instead
152
     */
153
    @Deprecated
154
    public static TermTree<Feature> NewInstance(List<Feature> featureList){
155
        return NewFeatureInstance(featureList);
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 TermNode 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 TermTree<Feature> NewFeatureInstance(List<Feature> featureList){
169
		TermTree<Feature> result =  new TermTree<>(TermType.Feature);
170
		TermNode<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 TermTree(){}
185

    
186
	/**
187
	 * Class constructor: creates a new feature tree instance with an empty
188
	 * {@link #getRoot() root node}.
189
	 */
190
	protected TermTree(TermType termType) {
191
        super(termType);
192
		root = new TermNode<>(termType);
193
		root.setGraph(this);
194
	}
195

    
196
// ****************** GETTER / SETTER **********************************/
197

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

    
208
    /**
209
     * @deprecated this method is only for internal use when deleting a {@link TermTree}
210
     * from a database. It should never be called for other reasons.
211
     */
212
    @Deprecated
213
    public void removeRootNode() {
214
        this.root = null;
215
    }
216

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

    
230

    
231

    
232
//******************** METHODS ***********************************************/
233

    
234
	/**
235
	 * Computes a set of distinct terms that are present in this term tree
236
	 */
237
    @Override
238
    @Transient
239
	public Set<T> getDistinctTerms(){
240
	    Set<T> terms = new HashSet<>();
241
	    return root.getDistinctTermsRecursive(terms);
242
	}
243

    
244
    @Override
245
    public List<T> asTermList() {
246
        List<T> result = new ArrayList<>();
247
        for (TermNode<T> node : getRootChildren()){
248
            result.add(node.getTerm());
249
            for (TermNode<T> child : node.getChildNodes()){
250
                result.addAll(child.asTermListRecursive());
251
            }
252
        }
253
        return result;
254
    }
255

    
256

    
257
    public Set<T> independentTerms() {
258
        Set<T> terms = root.getIndependentTermsRecursive();
259
        return terms;
260
    }
261

    
262
    public void removeNullValueFromChildren(){
263
       root.removeNullValueFromChildren();
264

    
265

    
266
    }
267

    
268
//*********************** CLONE ********************************************************/
269

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

    
294
}
(26-26/30)