NomenclaturalCode -> enum
[cdmlib.git] / cdmlib-model / src / main / java / eu / etaxonomy / cdm / model / common / DefinedTermBase.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 import org.apache.log4j.Logger;
13 import org.hibernate.annotations.Cascade;
14 import org.hibernate.annotations.CascadeType;
15 import org.hibernate.collection.AbstractPersistentCollection;
16 import org.hibernate.search.annotations.Indexed;
17
18 import au.com.bytecode.opencsv.CSVWriter;
19 import eu.etaxonomy.cdm.model.common.init.ITermInitializer;
20 import eu.etaxonomy.cdm.model.media.Media;
21 import eu.etaxonomy.cdm.model.name.NomenclaturalCode;
22
23 import java.lang.reflect.Field;
24 import java.util.*;
25
26 import javax.persistence.*;
27 import javax.xml.bind.annotation.XmlAccessType;
28 import javax.xml.bind.annotation.XmlAccessorType;
29 import javax.xml.bind.annotation.XmlElement;
30 import javax.xml.bind.annotation.XmlElementWrapper;
31 import javax.xml.bind.annotation.XmlIDREF;
32 import javax.xml.bind.annotation.XmlRootElement;
33 import javax.xml.bind.annotation.XmlSchemaType;
34 import javax.xml.bind.annotation.XmlTransient;
35 import javax.xml.bind.annotation.XmlType;
36
37
38 /**
39 * walkaround for enumerations, base type according to TDWG. For linear ordering
40 * use partOf relation and BreadthFirst. Default iterator order should therefore
41 * be BreadthFirst (not DepthFirst)
42 * @author m.doering
43 * @version 1.0
44 * @created 08-Nov-2007 13:06:19
45 */
46 @XmlAccessorType(XmlAccessType.FIELD)
47 @XmlType(name = "DefinedTermBase", propOrder = {
48 "kindOf",
49 "generalizationOf",
50 "partOf",
51 "includes",
52 "media",
53 "vocabulary"
54 })
55 @XmlRootElement(name = "DefinedTermBase")
56 @Entity
57 //@Audited
58 @Inheritance(strategy=InheritanceType.SINGLE_TABLE)
59 @Indexed
60 public abstract class DefinedTermBase<T extends DefinedTermBase> extends TermBase implements ILoadableTerm<T>, IDefinedTerm<T> {
61 private static final long serialVersionUID = 2931811562248571531L;
62 private static final Logger logger = Logger.getLogger(DefinedTermBase.class);
63
64 @XmlElement(name = "KindOf")
65 @XmlIDREF
66 @XmlSchemaType(name = "IDREF")
67 private T kindOf;
68 /**
69 * FIXME - Hibernate retuns this as a collection of CGLibProxy$$DefinedTermBase objects
70 * which can't be cast to instances of T - can we explicitly initialize these terms using
71 * Hibernate.initialize(), does this imply a distinct load, and find methods in the dao?
72 */
73 @XmlElement(name = "GeneralizationOf")
74 @XmlIDREF
75 @XmlSchemaType(name = "IDREF")
76 private Set<T> generalizationOf = new HashSet<T>();
77
78 @XmlElement(name = "PartOf")
79 @XmlIDREF
80 @XmlSchemaType(name = "IDREF")
81 private T partOf;
82
83 /**
84 * FIXME - Hibernate retuns this as a collection of CGLibProxy$$DefinedTermBase objects
85 * which can't be cast to instances of T - can we explicitly initialize these terms using
86 * Hibernate.initialize(), does this imply a distinct load, and find methods in the dao?
87 */
88 @XmlElementWrapper(name = "Includes")
89 @XmlElement(name = "Include")
90 private Set<T> includes = new HashSet<T>();
91
92 @XmlElementWrapper(name = "Media")
93 @XmlElement(name = "Medium")
94 @XmlIDREF
95 @XmlSchemaType(name = "IDREF")
96 private Set<Media> media = new HashSet<Media>();
97
98 @XmlElement(name = "TermVocabulary")
99 @XmlIDREF
100 @XmlSchemaType(name = "IDREF")
101 protected TermVocabulary<T> vocabulary;
102
103 // ************** Constructor ******************************************/
104
105 public DefinedTermBase() {
106 super();
107 }
108 public DefinedTermBase(String term, String label, String labelAbbrev) {
109 super(term, label, labelAbbrev);
110 }
111
112 protected abstract void setDefaultTerms(TermVocabulary<T> termVocabulary);
113
114 /* (non-Javadoc)
115 * @see eu.etaxonomy.cdm.model.common.ILoadableTerm#readCsvLine(java.util.List)
116 */
117 /* (non-Javadoc)
118 * @see eu.etaxonomy.cdm.model.common.IDefinedTerm#readCsvLine(java.lang.Class, java.util.List, java.util.Map)
119 */
120 public T readCsvLine(Class<T> termClass, List<String> csvLine, Map<UUID,DefinedTermBase> terms) {
121 try {
122 T newInstance = termClass.newInstance();
123 return readCsvLine(newInstance, csvLine, Language.ENGLISH());
124 } catch (Exception e) {
125 logger.error(e);
126 for(StackTraceElement ste : e.getStackTrace()) {
127 logger.error(ste);
128 }
129 }
130
131 return null;
132 }
133
134 protected static <TERM extends DefinedTermBase> TERM readCsvLine(TERM newInstance, List<String> csvLine, Language lang) {
135 newInstance.setUuid(UUID.fromString(csvLine.get(0)));
136 newInstance.setUri(csvLine.get(1));
137 String label = csvLine.get(2).trim();
138 String text = csvLine.get(3);
139 String abbreviatedLabel = csvLine.get(4);
140 newInstance.addRepresentation(Representation.NewInstance(text, label, abbreviatedLabel, lang) );
141 return newInstance;
142 }
143
144 /* (non-Javadoc)
145 * @see eu.etaxonomy.cdm.model.common.ILoadableTerm#writeCsvLine(au.com.bytecode.opencsv.CSVWriter)
146 */
147 public void writeCsvLine(CSVWriter writer, T term) {
148 String [] line = new String[4];
149 line[0] = term.getUuid().toString();
150 line[1] = term.getUri();
151 line[2] = term.getLabel();
152 line[3] = term.getDescription();
153 writer.writeNext(line);
154 }
155
156 /* (non-Javadoc)
157 * @see eu.etaxonomy.cdm.model.common.IDefinedTerm#getByUuid(java.util.UUID)
158 */
159 @Transient
160 public T getByUuid(UUID uuid){
161 return this.vocabulary.findTermByUuid(uuid);
162 }
163
164
165 /* (non-Javadoc)
166 * @see eu.etaxonomy.cdm.model.common.IDefinedTerm#getKindOf()
167 */
168 @ManyToOne(fetch = FetchType.LAZY, targetEntity = DefinedTermBase.class)
169 @Cascade({CascadeType.SAVE_UPDATE})
170 public T getKindOf(){
171 return this.kindOf;
172 }
173
174 /* (non-Javadoc)
175 * @see eu.etaxonomy.cdm.model.common.IDefinedTerm#setKindOf(T)
176 */
177 public void setKindOf(T kindOf){
178 this.kindOf = kindOf;
179 }
180
181 /* (non-Javadoc)
182 * @see eu.etaxonomy.cdm.model.common.IDefinedTerm#getGeneralizationOf()
183 */
184 @OneToMany(fetch=FetchType.LAZY, mappedBy = "kindOf", targetEntity = DefinedTermBase.class)
185 @Cascade({CascadeType.SAVE_UPDATE})
186 public Set<T> getGeneralizationOf(){
187 return this.generalizationOf;
188 }
189
190 /* (non-Javadoc)
191 * @see eu.etaxonomy.cdm.model.common.IDefinedTerm#setGeneralizationOf(java.util.Set)
192 */
193 public void setGeneralizationOf(Set<T> generalizationOf) {
194 this.generalizationOf = generalizationOf;
195 }
196
197 /* (non-Javadoc)
198 * @see eu.etaxonomy.cdm.model.common.IDefinedTerm#addGeneralizationOf(T)
199 */
200 public void addGeneralizationOf(T generalization) {
201 generalization.setKindOf(this);
202 this.generalizationOf.add(generalization);
203 }
204
205 /* (non-Javadoc)
206 * @see eu.etaxonomy.cdm.model.common.IDefinedTerm#removeGeneralization(T)
207 */
208 public void removeGeneralization(T generalization) {
209 if(generalizationOf.contains(generalization)){
210 generalization.setKindOf(null);
211 this.generalizationOf.remove(generalization);
212 }
213 }
214
215
216 /* (non-Javadoc)
217 * @see eu.etaxonomy.cdm.model.common.IDefinedTerm#getPartOf()
218 */
219 @ManyToOne(fetch = FetchType.LAZY, targetEntity = DefinedTermBase.class)
220 @Cascade({CascadeType.SAVE_UPDATE})
221 public T getPartOf(){
222 return this.partOf;
223 }
224 /* (non-Javadoc)
225 * @see eu.etaxonomy.cdm.model.common.IDefinedTerm#setPartOf(T)
226 */
227 public void setPartOf(T partOf){
228 this.partOf = partOf;
229 }
230
231
232 /* (non-Javadoc)
233 * @see eu.etaxonomy.cdm.model.common.IDefinedTerm#getIncludes()
234 */
235 @OneToMany(fetch=FetchType.LAZY, mappedBy = "partOf", targetEntity = DefinedTermBase.class)
236 @Cascade({CascadeType.SAVE_UPDATE})
237 public Set<T> getIncludes(){
238 return this.includes;
239 }
240 /* (non-Javadoc)
241 * @see eu.etaxonomy.cdm.model.common.IDefinedTerm#setIncludes(java.util.Set)
242 */
243 public void setIncludes(Set<T> includes) {
244 this.includes = includes;
245 }
246 /* (non-Javadoc)
247 * @see eu.etaxonomy.cdm.model.common.IDefinedTerm#addIncludes(T)
248 */
249 public void addIncludes(T includes) {
250 includes.setPartOf(this);
251 this.includes.add(includes);
252 }
253 /* (non-Javadoc)
254 * @see eu.etaxonomy.cdm.model.common.IDefinedTerm#removeIncludes(T)
255 */
256 public void removeIncludes(T includes) {
257 if(this.includes.contains(includes)) {
258 includes.setPartOf(null);
259 this.includes.remove(includes);
260 }
261 }
262
263
264 /* (non-Javadoc)
265 * @see eu.etaxonomy.cdm.model.common.IDefinedTerm#getMedia()
266 */
267 @ManyToMany(fetch = FetchType.LAZY)
268 @Cascade({CascadeType.SAVE_UPDATE})
269 public Set<Media> getMedia(){
270 return this.media;
271 }
272 /* (non-Javadoc)
273 * @see eu.etaxonomy.cdm.model.common.IDefinedTerm#setMedia(java.util.Set)
274 */
275 public void setMedia(Set<Media> media) {
276 this.media = media;
277 }
278 /* (non-Javadoc)
279 * @see eu.etaxonomy.cdm.model.common.IDefinedTerm#addMedia(eu.etaxonomy.cdm.model.media.Media)
280 */
281 public void addMedia(Media media) {
282 this.media.add(media);
283 }
284 /* (non-Javadoc)
285 * @see eu.etaxonomy.cdm.model.common.IDefinedTerm#removeMedia(eu.etaxonomy.cdm.model.media.Media)
286 */
287 public void removeMedia(Media media) {
288 this.media.remove(media);
289 }
290
291 /* (non-Javadoc)
292 * @see eu.etaxonomy.cdm.model.common.IDefTerm#getVocabulary()
293 */
294 /* (non-Javadoc)
295 * @see eu.etaxonomy.cdm.model.common.IDefinedTerm#getVocabulary()
296 */
297 @XmlTransient
298 @ManyToOne(fetch=FetchType.LAZY)
299 @Cascade( { CascadeType.SAVE_UPDATE })
300 public TermVocabulary<T> getVocabulary() {
301 return this.vocabulary;
302 }
303 /* (non-Javadoc)
304 * @see eu.etaxonomy.cdm.model.common.IDefTerm#setVocabulary(eu.etaxonomy.cdm.model.common.TermVocabulary)
305 */
306 /* (non-Javadoc)
307 * @see eu.etaxonomy.cdm.model.common.IDefinedTerm#setVocabulary(eu.etaxonomy.cdm.model.common.TermVocabulary)
308 */
309 public void setVocabulary(TermVocabulary<T> newVocabulary) {
310 this.vocabulary = newVocabulary;
311 }
312 }