implement RankClass, remove iso639_2, add max values to distance attributes, change...
[cdmlib.git] / cdmlib-model / src / main / java / eu / etaxonomy / cdm / model / common / TermVocabulary.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.common;
11
12
13 import java.net.URI;
14 import java.util.HashSet;
15 import java.util.Iterator;
16 import java.util.List;
17 import java.util.Set;
18 import java.util.SortedSet;
19 import java.util.TreeSet;
20 import java.util.UUID;
21
22 import javax.persistence.Entity;
23 import javax.persistence.FetchType;
24 import javax.persistence.Inheritance;
25 import javax.persistence.InheritanceType;
26 import javax.persistence.OneToMany;
27 import javax.persistence.Transient;
28 import javax.xml.bind.annotation.XmlAccessType;
29 import javax.xml.bind.annotation.XmlAccessorType;
30 import javax.xml.bind.annotation.XmlElement;
31 import javax.xml.bind.annotation.XmlElementWrapper;
32 import javax.xml.bind.annotation.XmlIDREF;
33 import javax.xml.bind.annotation.XmlRootElement;
34 import javax.xml.bind.annotation.XmlSchemaType;
35 import javax.xml.bind.annotation.XmlType;
36
37 import org.apache.log4j.Logger;
38 import org.hibernate.annotations.Cascade;
39 import org.hibernate.annotations.CascadeType;
40 import org.hibernate.annotations.Type;
41 import org.hibernate.envers.Audited;
42 import org.hibernate.search.annotations.Analyze;
43 import org.hibernate.search.annotations.Field;
44 import org.hibernate.search.annotations.Indexed;
45 import org.hibernate.search.annotations.IndexedEmbedded;
46
47
48 /**
49 * A single enumeration must only contain DefinedTerm instances of one kind
50 * (this means a subclass of DefinedTerm).
51 * @author m.doering
52 * @version 1.0
53 * @created 08-Nov-2007 13:06:23
54 */
55 @XmlAccessorType(XmlAccessType.FIELD)
56 @XmlType(name = "TermVocabulary", propOrder = {
57 "termSourceUri",
58 "terms"
59 })
60 @XmlRootElement(name = "TermVocabulary")
61 @Entity
62 @Indexed(index = "eu.etaxonomy.cdm.model.common.TermVocabulary")
63 @Audited
64 @Inheritance(strategy=InheritanceType.SINGLE_TABLE)
65 public class TermVocabulary<T extends DefinedTermBase> extends TermBase implements Iterable<T> {
66 private static final long serialVersionUID = 1925052321596648672L;
67 private static final Logger logger = Logger.getLogger(TermVocabulary.class);
68
69 //The vocabulary source (e.g. ontology) defining the terms to be loaded when a database is created for the first time.
70 // Software can go and grap these terms incl labels and description.
71 // UUID needed? Further vocs can be setup through our own ontology.
72 @XmlElement(name = "TermSourceURI")
73 @Type(type="uriUserType")
74 @Field(analyze = Analyze.NO)
75 private URI termSourceUri;
76
77
78 //TODO Changed
79 @XmlElementWrapper(name = "Terms")
80 @XmlElement(name = "Term")
81 @XmlIDREF
82 @XmlSchemaType(name = "IDREF")
83 @OneToMany(mappedBy="vocabulary", fetch=FetchType.LAZY, targetEntity = DefinedTermBase.class)
84 @Type(type="DefinedTermBase")
85 @Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE})
86 @IndexedEmbedded(depth = 2)
87 protected Set<T> terms = getNewTermSet();
88
89 // ********************************* FACTORY METHODS *****************************************/
90
91 public static TermVocabulary NewInstance(TermType type, String description, String label, String abbrev, URI termSourceUri){
92 return new TermVocabulary(type, description, label, abbrev, termSourceUri);
93 }
94
95 // ************************* CONSTRUCTOR *************************************************
96
97 protected TermVocabulary() {
98 }
99
100 protected TermVocabulary(TermType type, String term, String label, String labelAbbrev, URI termSourceUri) {
101 super(type, term, label, labelAbbrev);
102 setTermSourceUri(termSourceUri);
103 }
104
105
106 // ******************* METHODS *************************************************/
107
108 public T findTermByUuid(UUID uuid){
109 for(T t : terms) {
110 if(t.getUuid().equals(uuid)) {
111 return t;
112 }
113 }
114 return null;
115 }
116
117 @Transient
118 Set<T> getNewTermSet() {
119 return new HashSet<T>();
120 }
121
122 public Set<T> getTerms() {
123 return terms;
124 }
125
126 public void addTerm(T term) {
127 term.setVocabulary(this);
128 this.terms.add(term);
129 }
130 public void removeTerm(T term) {
131 this.terms.remove(term);
132 term.setVocabulary(null);
133 }
134
135 public URI getTermSourceUri() {
136 return termSourceUri;
137 }
138 public void setTermSourceUri(URI vocabularyUri) {
139 this.termSourceUri = vocabularyUri;
140 }
141
142
143 @Override
144 public Iterator<T> iterator() {
145 return terms.iterator(); // OLD: new TermIterator<T>(this.terms);
146 }
147
148 public int size(){
149 return terms.size();
150 }
151
152
153 /**
154 * Returns all terms of this vocabulary sorted by their representation defined by the given language.
155 * If such an representation does not exist, the representation of the default language is testing instead for ordering.
156 * @param language
157 * @return
158 */
159 public SortedSet<T> getTermsOrderedByLabels(Language language){
160 TermLanguageComparator<T> comp = new TermLanguageComparator<T>();
161 comp.setCompareLanguage(language);
162
163 SortedSet<T> result = new TreeSet<T>(comp);
164 result.addAll(getTerms());
165 return result;
166 }
167
168
169 /* (non-Javadoc)
170 * @see eu.etaxonomy.cdm.model.common.ILoadableTerm#readCsvLine(java.util.List)
171 */
172 public TermVocabulary<T> readCsvLine(List<String> csvLine) {
173 return readCsvLine(csvLine, Language.CSV_LANGUAGE());
174 }
175
176 public TermVocabulary<T> readCsvLine(List<String> csvLine, Language lang) {
177 this.setUuid(UUID.fromString(csvLine.get(0)));
178 this.setUri(URI.create(csvLine.get(1)));
179 String description = csvLine.get(3);
180 String label = csvLine.get(2).trim();
181 //see http://dev.e-taxonomy.eu/trac/ticket/3550
182 // this.addRepresentation(Representation.NewInstance(description, label, null, lang) );
183 //preliminary until above is solved
184 this.setTitleCache(label, true);
185
186 this.setTermType(TermType.byKey(csvLine.get(4)));
187
188 return this;
189 }
190
191 //*********************** CLONE ********************************************************/
192
193 /**
194 * Clones <i>this</i> TermVocabulary. This is a shortcut that enables to create
195 * a new instance that differs only slightly from <i>this</i> TermVocabulary.
196 * The terms of the original vocabulary are cloned
197 *
198 * @see eu.etaxonomy.cdm.model.common.TermBase#clone()
199 * @see java.lang.Object#clone()
200 */
201 @Override
202 public Object clone() {
203 TermVocabulary<T> result;
204 try {
205 result = (TermVocabulary<T>) super.clone();
206
207 }catch (CloneNotSupportedException e) {
208 logger.warn("Object does not implement cloneable");
209 e.printStackTrace();
210 return null;
211 }
212 result.terms = new HashSet<T>();
213 for (T term: this.terms){
214 result.addTerm((T)term.clone());
215 }
216
217 return result;
218 }
219
220 }