Delete Warning, no substantial changes
[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 org.apache.log4j.Logger;
14 import org.hibernate.annotations.Cascade;
15 import org.hibernate.annotations.CascadeType;
16 import org.hibernate.annotations.Type;
17
18 import eu.etaxonomy.cdm.model.common.init.DefaultVocabularyStore;
19 import eu.etaxonomy.cdm.model.common.init.IVocabularyStore;
20
21 import java.util.*;
22
23 import javax.persistence.*;
24 import javax.xml.bind.annotation.XmlAccessType;
25 import javax.xml.bind.annotation.XmlAccessorType;
26 import javax.xml.bind.annotation.XmlElement;
27 import javax.xml.bind.annotation.XmlElementWrapper;
28 import javax.xml.bind.annotation.XmlIDREF;
29 import javax.xml.bind.annotation.XmlRootElement;
30 import javax.xml.bind.annotation.XmlSchemaType;
31 import javax.xml.bind.annotation.XmlType;
32
33
34 /**
35 * A single enumeration must only contain DefinedTerm instances of one kind
36 * (this means a subclass of DefinedTerm).
37 * @author m.doering
38 * @version 1.0
39 * @created 08-Nov-2007 13:06:23
40 */
41 @XmlAccessorType(XmlAccessType.FIELD)
42 @XmlType(name = "TermVocabulary", propOrder = {
43 "termSourceUri",
44 "termClass",
45 "terms"
46 })
47 @XmlRootElement(name = "TermVocabulary")
48 @Entity
49 @Inheritance(strategy=InheritanceType.SINGLE_TABLE)
50 public class TermVocabulary<T extends DefinedTermBase> extends TermBase implements Iterable<T> {
51 private static final long serialVersionUID = 1925052321596648672L;
52 @SuppressWarnings("unused")
53 private static final Logger logger = Logger.getLogger(TermVocabulary.class);
54
55 static protected IVocabularyStore vocabularyStore = new DefaultVocabularyStore();
56
57 public static void setVocabularyStore(IVocabularyStore vocabularyStore){
58 DefinedTermBase.vocabularyStore = vocabularyStore;
59 }
60
61 private static final UUID uuidLanguage = UUID.fromString("17ba1c02-256d-47cf-bed0-2964ec1108ba");
62 private static final UUID uuidRank = UUID.fromString("b17451eb-4278-4179-af68-44f27aa3d151");
63 private static final UUID uuidContinent = UUID.fromString("ed4e5948-172a-424c-83d6-6fc7c7da70ed");
64 private static final UUID uuidTdwg = UUID.fromString("1fb40504-d1d7-44b0-9731-374fbe6cac77");
65
66
67 public static TermVocabulary findByUuid(UUID uuid){
68 TermVocabulary<?> voc = vocabularyStore.getVocabularyByUuid(uuid);
69 return voc;
70 }
71 public static final TermVocabulary getUUID(UUID uuid){
72 return findByUuid(uuid);
73 }
74 public static final TermVocabulary LANGUAGE(){
75 return getUUID(uuidLanguage);
76 }
77 public static final TermVocabulary TDWG(){
78 return getUUID(uuidTdwg);
79 }
80
81 //The vocabulary source (e.g. ontology) defining the terms to be loaded when a database is created for the first time.
82 // Software can go and grap these terms incl labels and description.
83 // UUID needed? Further vocs can be setup through our own ontology.
84 @XmlElement(name = "TermSourceURI")
85 private String termSourceUri;
86
87 @XmlElement(name = "TermClass")
88 protected Class termClass;
89
90 //TODO Changed
91 @XmlElementWrapper(name = "Terms")
92 @XmlElement(name = "Term")
93 @XmlIDREF
94 @XmlSchemaType(name = "IDREF")
95 public Set<T> terms = getNewTermSet();
96
97 //to be overriden by subclasses, e.g. OrderedTermVocabulary
98 @Transient
99 protected Set<T> getNewTermSet(){
100 return new HashSet<T>();
101 }
102
103 public TermVocabulary() {
104 super();
105 }
106 public TermVocabulary(String term, String label, String labelAbbrev, String termSourceUri) {
107 super(term, label, labelAbbrev);
108 setTermSourceUri(termSourceUri);
109 }
110
111 @Transient
112 public Set<T> getTerms() {
113 //Set<T> result = getNewTermSet();
114 //result.addAll(terms);
115 //return result;
116 return terms;
117 }
118 protected void setTerms(Set<T> terms) {
119 this.terms = terms;
120 }
121
122 @OneToMany(mappedBy="persistentVocabulary", fetch=FetchType.LAZY, targetEntity = DefinedTermBase.class)
123 @Type(type="DefinedTermBase")
124 @Cascade({CascadeType.SAVE_UPDATE})
125 public Set<T> getPersistentTerms() {
126 return terms;
127 }
128 protected void setPersistentTerms(Set<T> terms) {
129 this.terms = terms;
130 }
131 public void addTerm(T term) throws WrongTermTypeException {
132 if (terms.size()<1){
133 // no term yet in the list. First term defines the vocabulary kind
134 termClass=term.getClass();
135 }else if (term.getClass()!=termClass){
136 // check if new term in this vocabulary matches the previous ones
137 throw new WrongTermTypeException(term.getClass().getCanonicalName());
138 }
139 term.setVocabulary(this);
140 }
141 public void removeTerm(T term) {
142 term.setVocabulary(null);
143 }
144
145 public String getTermSourceUri() {
146 return termSourceUri;
147 }
148 public void setTermSourceUri(String vocabularyUri) {
149 this.termSourceUri = vocabularyUri;
150 }
151
152
153 public Class getTermClass() {
154 return termClass;
155 }
156 private void setTermClass(Class termClass) {
157 this.termClass = termClass;
158 }
159
160
161 // // inner iterator class for the iterable interface
162 // private class TermIterator<T> implements Iterator<T> {
163 // // FIXME: using a list here is probably not safe. Sth passed by value, an array, would be better
164 // // but arrays cause generics problems: http://forum.java.sun.com/thread.jspa?threadID=651276&messageID=3832182
165 // // hack for now ;(
166 // private Set<T> array;
167 // private int i= 0;
168 // // ctor
169 // public TermIterator(Set<T> array) {
170 // // check for null being passed in etc.
171 // this.array= array;
172 // }
173 // // interface implementation
174 // public boolean hasNext() { return i < array.size(); }
175 // public T next() { return array.get(i++); }
176 // public void remove() { throw new UnsupportedOperationException(); }
177 // }
178
179 public Iterator<T> iterator() {
180 return terms.iterator(); // OLD: new TermIterator<T>(this.terms);
181 }
182
183 public int size(){
184 return terms.size();
185 }
186
187
188 /**
189 * Returns all terms of this vocabulary sorted by their representation defined by the given language.
190 * If such an representation does not exist, the representation of the default language is testing instead for ordering.
191 * @param language
192 * @return
193 */
194 @Transient
195 public SortedSet<T> getTermsOrderedByLabels(Language language){
196 TermLanguageComparator<T> comp = new TermLanguageComparator<T>();
197 comp.setCompareLanguage(language);
198
199 SortedSet<T> result = new TreeSet<T>(comp);
200 result.addAll(getTerms());
201 return result;
202 }
203
204
205 /* (non-Javadoc)
206 * @see eu.etaxonomy.cdm.model.common.ILoadableTerm#readCsvLine(java.util.List)
207 */
208 public TermVocabulary readCsvLine(List<String> csvLine) {
209 return readCsvLine(csvLine, Language.ENGLISH());
210 }
211 public TermVocabulary readCsvLine(List<String> csvLine, Language lang) {
212 this.setUuid(UUID.fromString(csvLine.get(0)));
213 this.setUri(csvLine.get(1));
214 //this.addRepresentation(Representation.NewInstance(csvLine.get(3), csvLine.get(2).trim(), lang) );
215 return this;
216 }
217
218 }