162c8b91e22fcdb138d79928cd145a952a2ae98e
[cdmlib.git] / cdmlib-model / src / main / java / eu / etaxonomy / cdm / model / occurrence / DerivedUnit.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.occurrence;
11
12 import java.util.HashSet;
13 import java.util.Set;
14
15 import javax.persistence.Entity;
16 import javax.persistence.FetchType;
17 import javax.persistence.ManyToOne;
18 import javax.persistence.OneToMany;
19 import javax.persistence.Transient;
20 import javax.validation.constraints.Size;
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.envers.Audited;
34 import org.hibernate.search.annotations.Analyze;
35 import org.hibernate.search.annotations.Field;
36 import org.hibernate.search.annotations.Indexed;
37 import org.hibernate.search.annotations.IndexedEmbedded;
38 import org.hibernate.validator.constraints.Length;
39
40 import eu.etaxonomy.cdm.model.molecular.DnaSample;
41 import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignation;
42 import eu.etaxonomy.cdm.model.name.TaxonNameBase;
43 import eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy;
44
45 /**
46 * A derived unit is regarded as derived from a field unit,
47 * so locality and gathering related information is captured as a separate FieldUnit object
48 * related to a specimen via a derivation event
49 *
50 * http://www.bgbm.org/biodivinf/docs/CollectionModel/ReprintTNR.pdf
51 * http://www.bgbm.org/biodivinf/docs/CollectionModel/
52 * <BR>
53 * Type figures are derived units with at least a figure object in media
54 *
55 * @author m.doering
56 * @created 08-Nov-2007 13:06:52
57 *
58 */
59 @XmlAccessorType(XmlAccessType.FIELD)
60 @XmlType(name = "DerivedUnit", propOrder = {
61 "collection",
62 "catalogNumber",
63 "storedUnder",
64 "derivedFrom",
65 "accessionNumber",
66 "collectorsNumber",
67 "barcode",
68 "preservation",
69 "exsiccatum",
70 "specimenTypeDesignations"
71 })
72 @XmlRootElement(name = "DerivedUnit")
73 @Entity
74 @Audited
75 // even if hibernate complains "Abstract classes can never insert index documents. Remove @Indexed."
76 // this is needed, otherwise the fields of the also abstract super class are missed during indexing
77 @Indexed(index = "eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase")
78 public class DerivedUnit extends SpecimenOrObservationBase<IIdentifiableEntityCacheStrategy> implements Cloneable{
79 private static final long serialVersionUID = -3525746216270843517L;
80
81 private static final Logger logger = Logger.getLogger(DnaSample.class);
82
83 @XmlElement(name = "Collection")
84 @XmlIDREF
85 @XmlSchemaType(name = "IDREF")
86 @ManyToOne(fetch = FetchType.LAZY)
87 @Cascade(CascadeType.SAVE_UPDATE)
88 @IndexedEmbedded
89 private Collection collection;
90
91 @XmlElement(name = "CatalogNumber")
92 @Field(analyze = Analyze.NO)
93 //TODO Val #3379
94 // @NullOrNotEmpty
95 @Length(max = 255)
96 private String catalogNumber;
97
98 @XmlElement(name = "AccessionNumber")
99 @Field(analyze = Analyze.NO)
100 //TODO Val #3379
101 // @NullOrNotEmpty
102 @Length(max = 255)
103 private String accessionNumber;
104
105 @XmlElement(name = "CollectorsNumber")
106 @Field(analyze = Analyze.NO)
107 //TODO Val #3379
108 // @NullOrNotEmpty
109 @Length(max = 255)
110 private String collectorsNumber;
111
112 @XmlElement(name = "Barcode")
113 @Field(analyze = Analyze.NO)
114 //TODO Val #3379
115 // @NullOrNotEmpty
116 @Length(max = 255)
117 private String barcode;
118
119 @XmlElement(name = "StoredUnder")
120 @XmlIDREF
121 @XmlSchemaType(name = "IDREF")
122 @ManyToOne(fetch = FetchType.LAZY)
123 @Cascade(CascadeType.SAVE_UPDATE)
124 @IndexedEmbedded
125 private TaxonNameBase storedUnder;
126
127 @XmlElement(name = "DerivedFrom")
128 @XmlIDREF
129 @XmlSchemaType(name = "IDREF")
130 @ManyToOne(fetch = FetchType.LAZY)
131 @Cascade(CascadeType.SAVE_UPDATE)
132 @IndexedEmbedded(depth = 4)
133 private DerivationEvent derivedFrom;
134
135 @XmlElementWrapper(name = "SpecimenTypeDesignations")
136 @XmlElement(name = "SpecimenTypeDesignation")
137 @OneToMany(fetch = FetchType.LAZY, mappedBy = "typeSpecimen")
138 @Cascade({ CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.DELETE })
139 private final Set<SpecimenTypeDesignation> specimenTypeDesignations = new HashSet<SpecimenTypeDesignation>();
140
141
142 //*** attributes valid only for preserved specimen (PreservedSpecimen, Fossil, DnaSample)
143
144 @XmlElement(name = "Preservation")
145 @XmlIDREF
146 @XmlSchemaType(name = "IDREF")
147 @ManyToOne(fetch = FetchType.LAZY)
148 private PreservationMethod preservation;
149
150
151 @XmlElement(name = "Exsiccatum")
152 //TODO Val #3379
153 // @NullOrNotEmpty
154 @Field
155 @Size(max = 255)
156 private String exsiccatum;
157
158 // ******************** FACTORY METHOD **********************************/
159
160
161 public static DerivedUnit NewInstance(SpecimenOrObservationType type) {
162 return new DerivedUnit(type);
163 }
164
165 /**
166 * Factory method
167 * @return
168 */
169 public static DerivedUnit NewPreservedSpecimenInstance(){
170 DerivedUnit result = new DerivedUnit(SpecimenOrObservationType.PreservedSpecimen);
171 return result;
172 }
173
174 //************************** CONSTRUCTOR *********************************/
175
176 //Constructor: For hibernate use only
177 protected DerivedUnit() {super();}
178
179
180 /**
181 * Constructor
182 * @param recordBasis
183 */
184 protected DerivedUnit(SpecimenOrObservationType recordBasis) {
185 super(recordBasis);
186 }
187
188
189 /**
190 * Create new unit derived from an existing field unit
191 * @param fieldUnit existing field unit from where this unit is derived
192 */
193 protected DerivedUnit(SpecimenOrObservationType recordBasis, FieldUnit fieldUnit) {
194 super(recordBasis);
195 DerivationEvent derivedFrom = new DerivationEvent();
196 // TODO: should be done in a more controlled way. Probably by making derivation event implement a general relationship interface (for bidirectional add/remove etc)
197 fieldUnit.addDerivationEvent(derivedFrom);
198 derivedFrom.getOriginals().add(fieldUnit);
199 derivedFrom.getDerivatives().add(this);
200 this.setDerivedFrom(derivedFrom);
201 }
202
203 /**
204 * create new unit derived from an existing gathering event,
205 * thereby creating a new empty field unit
206 * @param gatheringEvent the gathering event this unit was collected at
207 */
208 protected DerivedUnit(SpecimenOrObservationType recordBasis, GatheringEvent gatheringEvent) {
209 this(recordBasis, new FieldUnit());
210 FieldUnit field = (FieldUnit)this.getOriginalUnit();
211 field.setGatheringEvent(gatheringEvent);
212 }
213
214 // ******************** GETTER / SETTER *************************************/
215
216 public DerivationEvent getDerivedFrom() {
217 return derivedFrom;
218 }
219
220 public void setDerivedFrom(DerivationEvent derivedFrom){
221 if (getDerivedFrom() != null){
222 getDerivedFrom().getDerivatives().remove(derivedFrom);
223 }
224 this.derivedFrom = derivedFrom;
225 if (derivedFrom != null){
226 derivedFrom.addDerivative(this);
227 }
228 }
229
230 @Transient
231 public Set<SpecimenOrObservationBase> getOriginals(){
232 if(getDerivedFrom() != null){
233 return getDerivedFrom().getOriginals();
234 }
235 return null;
236 }
237
238 public Collection getCollection(){
239 return this.collection;
240 }
241
242 public void setCollection(Collection collection){
243 this.collection = collection;
244 }
245
246
247 public String getCatalogNumber() {
248 return catalogNumber;
249 }
250
251 public void setCatalogNumber(String catalogNumber) {
252 this.catalogNumber = catalogNumber;
253 }
254
255 public void setBarcode(String barcode) {
256 this.barcode = barcode;
257 }
258 public String getBarcode() {
259 return barcode;
260 }
261
262 public void setStoredUnder(TaxonNameBase storedUnder) {
263 this.storedUnder = storedUnder;
264 }
265
266 public String getAccessionNumber() {
267 return accessionNumber;
268 }
269
270
271 public void setAccessionNumber(String accessionNumber) {
272 this.accessionNumber = accessionNumber;
273 }
274
275 /**
276 * Will be removed in future versions as semantics is not clear.
277 * For accessing the collecting number use
278 * {@link FieldUnit#getFieldNumber()} instead.
279 * @return
280 */
281 @Deprecated
282 public String getCollectorsNumber() {
283 return collectorsNumber;
284 }
285
286 /**
287 * Will be removed in future versions as semantics is not clear.
288 * For editing the collecting number use
289 * {@link FieldUnit#getFieldNumber()} instead.
290 * @return
291 */
292 @Deprecated
293 public void setCollectorsNumber(String collectorsNumber) {
294 this.collectorsNumber = collectorsNumber;
295 }
296
297 public TaxonNameBase getStoredUnder() {
298 return storedUnder;
299 }
300
301 public void addSpecimenTypeDesignation(SpecimenTypeDesignation specimenTypeDesignation){
302 if (specimenTypeDesignation.getTypeSpecimen() == this){
303 return ;
304 }else if (specimenTypeDesignation.getTypeSpecimen() != null){
305 specimenTypeDesignation.getTypeSpecimen().removeSpecimenTypeDesignation(specimenTypeDesignation);
306
307 }
308 specimenTypeDesignations.add(specimenTypeDesignation);
309 specimenTypeDesignation.setTypeSpecimen(this);
310 }
311
312 public void removeSpecimenTypeDesignation(SpecimenTypeDesignation specimenTypeDesignation){
313 if (specimenTypeDesignation == null){
314 return;
315 }
316 if (specimenTypeDesignations.contains(specimenTypeDesignation)){
317 specimenTypeDesignations.remove(specimenTypeDesignation);
318 specimenTypeDesignation.setTypeSpecimen(null);
319 }
320 }
321
322 // ******* GETTER / SETTER for preserved specimen only ******************/
323
324 public Set<SpecimenTypeDesignation> getSpecimenTypeDesignations(){
325 return specimenTypeDesignations;
326 }
327
328 public PreservationMethod getPreservation(){
329 return this.preservation;
330 }
331
332 public void setPreservation(PreservationMethod preservation){
333 this.preservation = preservation;
334 }
335
336
337 public void setExsiccatum(String exsiccatum) {
338 this.exsiccatum = exsiccatum;
339 }
340
341 public String getExsiccatum() {
342 return exsiccatum;
343 }
344
345 //*********** CLONE **********************************/
346
347 /**
348 * Clones <i>this</i> derivedUnit. This is a shortcut that enables to
349 * create a new instance that differs only slightly from <i>this</i> specimen
350 * by modifying only some of the attributes.<BR>
351 * This method overrides the clone method from {@link SpecimenOrObservationBase SpecimenOrObservationBase}.
352 *
353 * @see SpecimenOrObservationBase#clone()
354 * @see eu.etaxonomy.cdm.model.media.IdentifiableMediaEntity#clone()
355 * @see java.lang.Object#clone()
356 */
357 @Override
358 public Object clone() {
359 try{
360 DerivedUnit result = (DerivedUnit)super.clone();
361 //collection
362 result.setCollection(this.collection);
363 //derivedFrom
364 result.setDerivedFrom(this.derivedFrom);
365 //storedUnder
366 result.setStoredUnder(this.storedUnder);
367 //preservation
368 result.setPreservation(this.preservation);
369 //no changes to: accessionNumber, catalogNumber, collectorsNumber
370 return result;
371 } catch (CloneNotSupportedException e) {
372 logger.warn("Object does not implement cloneable");
373 e.printStackTrace();
374 return null;
375 }
376 }
377
378
379 }