Project

General

Profile

Download (8.27 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
package eu.etaxonomy.cdm.model.term;
10

    
11
import java.util.HashSet;
12
import java.util.List;
13
import java.util.Set;
14
import java.util.SortedSet;
15
import java.util.TreeSet;
16
import java.util.UUID;
17

    
18
import javax.persistence.Entity;
19
import javax.persistence.FetchType;
20
import javax.persistence.OneToMany;
21
import javax.xml.bind.annotation.XmlAccessType;
22
import javax.xml.bind.annotation.XmlAccessorType;
23
import javax.xml.bind.annotation.XmlElement;
24
import javax.xml.bind.annotation.XmlElementWrapper;
25
import javax.xml.bind.annotation.XmlIDREF;
26
import javax.xml.bind.annotation.XmlRootElement;
27
import javax.xml.bind.annotation.XmlSchemaType;
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.annotations.Type;
34
import org.hibernate.envers.Audited;
35
import org.hibernate.search.annotations.Analyze;
36
import org.hibernate.search.annotations.Field;
37
import org.hibernate.search.annotations.FieldBridge;
38
import org.hibernate.search.annotations.IndexedEmbedded;
39

    
40
import eu.etaxonomy.cdm.common.CdmUtils;
41
import eu.etaxonomy.cdm.common.URI;
42
import eu.etaxonomy.cdm.compare.term.TermLanguageComparator;
43
import eu.etaxonomy.cdm.hibernate.search.UriBridge;
44
import eu.etaxonomy.cdm.model.common.ExternallyManaged;
45
import eu.etaxonomy.cdm.model.common.Language;
46

    
47
/**
48
 * A single enumeration must only contain DefinedTerm instances of one kind
49
 * (this means a subclass of DefinedTerm).
50
 * @author m.doering
51
 * @since 08-Nov-2007 13:06:23
52
 */
53
@XmlAccessorType(XmlAccessType.FIELD)
54
@XmlType(name = "TermVocabulary", propOrder = {
55
    "termSourceUri",
56
    "terms",
57
    "externallyManaged"
58
})
59
@XmlRootElement(name = "TermVocabulary")
60
@Entity
61
//@Indexed disabled to reduce clutter in indexes, since this type is not used by any search
62
//@Indexed(index = "eu.etaxonomy.cdm.model.term.TermVocabulary")
63
@Audited
64
public class TermVocabulary<T extends DefinedTermBase>
65
        extends TermCollection<T,TermNode> {
66

    
67
    private static final long serialVersionUID = 1925052321596648672L;
68
	private static final Logger logger = Logger.getLogger(TermVocabulary.class);
69

    
70
	//The vocabulary source (e.g. ontology) defining the terms to be loaded when a database
71
	//is created for the first time.
72
	// Software can go and grap these terms incl. labels and description.
73
	// UUID needed? Further vocs can be setup through our own ontology.
74
	@XmlElement(name = "TermSourceURI")
75
	@Field(analyze = Analyze.NO)
76
    @FieldBridge(impl = UriBridge.class)
77
	@Type(type="uriUserType")
78
	private URI termSourceUri;
79

    
80
	@XmlElementWrapper(name = "Terms")
81
	@XmlElement(name = "Term")
82
    @XmlIDREF
83
    @XmlSchemaType(name = "IDREF")
84
    @OneToMany(mappedBy="vocabulary", fetch=FetchType.LAZY, targetEntity = DefinedTermBase.class)
85
	@Type(type="DefinedTermBase")
86
	@Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE})
87
	@IndexedEmbedded(depth = 2)
88
	protected Set<T> terms = newTermSet();
89

    
90
    private ExternallyManaged externallyManaged;
91

    
92
// ********************************* FACTORY METHODS *****************************************/
93

    
94

    
95
	public static TermVocabulary NewInstance(TermType type){
96
		return new TermVocabulary(type);
97
	}
98

    
99
	public static <T extends DefinedTermBase<T>> TermVocabulary<T> NewInstance(TermType type, Class<T> clazz){
100
		return new TermVocabulary<T>(type);
101
	}
102

    
103
	/**
104
	 * @deprecated use {@link #NewInstance(TermType, Class, String, String, String, URI)} instead
105
	 */
106
	@Deprecated
107
	public static TermVocabulary NewInstance(TermType type, String description, String label, String abbrev, URI termSourceUri){
108
		return new TermVocabulary(type, description, label, abbrev, termSourceUri);
109
	}
110

    
111
    public static <T extends DefinedTermBase<T>> TermVocabulary<T> NewInstance(TermType type, Class<T> clazz, String description, String label, String abbrev, URI termSourceUri){
112
        return new TermVocabulary<T>(type, description, label, abbrev, termSourceUri);
113
    }
114

    
115
// ************************* CONSTRUCTOR *************************************************
116

    
117
	//for hibernate use only
118
	@Deprecated
119
	protected TermVocabulary() {
120
		super(TermType.Unknown);
121
	}
122

    
123
	protected TermVocabulary(TermType type) {
124
		super(type);
125
	}
126

    
127
	protected TermVocabulary(TermType type, String term, String label, String labelAbbrev, URI termSourceUri) {
128
		super(type, term, label, labelAbbrev);
129
		setTermSourceUri(termSourceUri);
130
	}
131

    
132

    
133
	protected Set<T> newTermSet(){
134
	    return new HashSet<>();
135
	}
136

    
137
// ******************* METHODS *************************************************/
138

    
139
	public T findTermByUuid(UUID uuid){
140
		for(T t : terms) {
141
			if(t.getUuid().equals(uuid)) {
142
				return t;
143
			}
144
		}
145
		return null;
146
	}
147

    
148

    
149
	public Set<T> getTerms() {
150
		return terms;
151
	}
152

    
153
	public void addTerm(T term) {
154
	    checkTermType(term);
155
		term.setVocabulary(this);
156
		this.terms.add(term);
157
	}
158
	public void removeTerm(T term) {
159
		this.terms.remove(term);
160
		term.setVocabulary(null);
161
	}
162

    
163
	public URI getTermSourceUri() {
164
		return termSourceUri;
165
	}
166
	public void setTermSourceUri(URI vocabularyUri) {
167
		this.termSourceUri = vocabularyUri;
168
	}
169

    
170
	@Deprecated //deprecated for now as only needed for property path handling; but may become generally public in future
171
    public Set<TermNode> getTermRelations() {
172
        return super.termRelations();
173
    }
174

    
175
    /**
176
     * Returns the first term found having the defined idInVocabulary.
177
     * If number of terms with given idInVoc > 1 the result is not deterministic.
178
     * @param idInVoc
179
     * @return the term with the given idInVoc
180
     */
181
    public T getTermByIdInvocabulary(String idInVoc) {
182
        for (T term : getTerms() ){
183
            if (CdmUtils.nullSafeEqual(idInVoc, term.getIdInVocabulary())){
184
                return term;
185
            }
186
        }
187
        return null;
188
    }
189

    
190
	public int size(){
191
		return terms.size();
192
	}
193

    
194
	/**
195
	 * Returns all terms of this vocabulary sorted by their representation defined by the given language.
196
	 * If such an representation does not exist, the representation of the default language is testing instead for ordering.
197
	 */
198
	public SortedSet<T> getTermsOrderedByLabels(Language language){
199
		TermLanguageComparator<T> comp = new TermLanguageComparator<>(Language.DEFAULT(), language);
200

    
201
		SortedSet<T> result = new TreeSet<>(comp);
202
		result.addAll(getTerms());
203
		return result;
204
	}
205

    
206
	public TermVocabulary<T> readCsvLine(List<String> csvLine) {
207
		return readCsvLine(csvLine, Language.CSV_LANGUAGE());
208
	}
209

    
210
	public TermVocabulary<T> readCsvLine(List<String> csvLine, Language lang) {
211
		this.setUuid(UUID.fromString(csvLine.get(0)));
212
        String uriStr = CdmUtils.Ne(csvLine.get(1));
213
        this.setUri(uriStr == null? null: URI.create(uriStr));
214
		String label = csvLine.get(2).trim();
215
		String description = csvLine.get(3);
216

    
217
		//see  https://dev.e-taxonomy.eu/redmine/issues/3550
218
		this.addRepresentation(Representation.NewInstance(description, label, null, lang) );
219

    
220
		TermType termType = TermType.getByKey(csvLine.get(4));
221
		if (termType == null){
222
			throw new IllegalArgumentException("TermType can not be mapped: " + csvLine.get(4));
223
		}
224
		this.setTermType(termType);
225

    
226
		return this;
227
	}
228

    
229
	/**
230
     * Throws {@link IllegalArgumentException} if the given
231
     * term has not the same term type as this term or if term type is null.
232
     * @param term
233
     */
234
    private void checkTermType(IHasTermType term) {
235
        IHasTermType.checkTermTypes(term, this);
236
    }
237

    
238
//*********************** CLONE ********************************************************/
239

    
240
	/**
241
	 * Clones <i>this</i> TermVocabulary. This is a shortcut that enables to create
242
	 * a new instance that differs only slightly from <i>this</i> TermVocabulary.
243
	 * The terms of the original vocabulary are cloned
244
	 *
245
	 * @see eu.etaxonomy.cdm.model.term.TermBase#clone()
246
	 * @see java.lang.Object#clone()
247
	 */
248
	@Override
249
	public TermVocabulary<T> clone() {
250
		TermVocabulary<T> result;
251
		try {
252
			result = (TermVocabulary<T>) super.clone();
253

    
254
		}catch (CloneNotSupportedException e) {
255
			logger.warn("Object does not implement cloneable");
256
			e.printStackTrace();
257
			return null;
258
		}
259
		result.terms = new HashSet<T>();
260
		for (T term: this.terms){
261
			result.addTerm((T)term.clone());
262
		}
263

    
264
		return result;
265
	}
266
}
(28-28/30)