2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
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.
10 package eu
.etaxonomy
.cdm
.model
.occurrence
;
12 import java
.util
.HashSet
;
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
;
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
;
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
;
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
50 * http://www.bgbm.org/biodivinf/docs/CollectionModel/ReprintTNR.pdf
51 * http://www.bgbm.org/biodivinf/docs/CollectionModel/
53 * Type figures are derived units with at least a figure object in media
56 * @created 08-Nov-2007 13:06:52
59 @XmlAccessorType(XmlAccessType
.FIELD
)
60 @XmlType(name
= "DerivedUnit", propOrder
= {
70 "specimenTypeDesignations"
72 @XmlRootElement(name
= "DerivedUnit")
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;
81 private static final Logger logger
= Logger
.getLogger(DnaSample
.class);
83 @XmlElement(name
= "Collection")
85 @XmlSchemaType(name
= "IDREF")
86 @ManyToOne(fetch
= FetchType
.LAZY
)
87 @Cascade(CascadeType
.SAVE_UPDATE
)
89 private Collection collection
;
91 @XmlElement(name
= "CatalogNumber")
92 @Field(analyze
= Analyze
.NO
)
96 private String catalogNumber
;
98 @XmlElement(name
= "AccessionNumber")
99 @Field(analyze
= Analyze
.NO
)
103 private String accessionNumber
;
105 @XmlElement(name
= "CollectorsNumber")
106 @Field(analyze
= Analyze
.NO
)
110 private String collectorsNumber
;
112 @XmlElement(name
= "Barcode")
113 @Field(analyze
= Analyze
.NO
)
117 private String barcode
;
119 @XmlElement(name
= "StoredUnder")
121 @XmlSchemaType(name
= "IDREF")
122 @ManyToOne(fetch
= FetchType
.LAZY
)
123 @Cascade(CascadeType
.SAVE_UPDATE
)
125 private TaxonNameBase storedUnder
;
127 @XmlElement(name
= "DerivedFrom")
129 @XmlSchemaType(name
= "IDREF")
130 @ManyToOne(fetch
= FetchType
.LAZY
)
131 @Cascade(CascadeType
.SAVE_UPDATE
)
132 @IndexedEmbedded(depth
= 4)
133 private DerivationEvent derivedFrom
;
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
>();
142 //*** attributes valid only for preserved specimen (PreservedSpecimen, Fossil, DnaSample)
144 @XmlElement(name
= "Preservation")
146 @XmlSchemaType(name
= "IDREF")
147 @ManyToOne(fetch
= FetchType
.LAZY
)
148 private PreservationMethod preservation
;
151 @XmlElement(name
= "Exsiccatum")
156 private String exsiccatum
;
158 // ******************** FACTORY METHOD **********************************/
161 public static DerivedUnit
NewInstance(SpecimenOrObservationType type
) {
162 return new DerivedUnit(type
);
169 public static DerivedUnit
NewPreservedSpecimenInstance(){
170 DerivedUnit result
= new DerivedUnit(SpecimenOrObservationType
.PreservedSpecimen
);
174 //************************** CONSTRUCTOR *********************************/
176 //Constructor: For hibernate use only
177 protected DerivedUnit() {super();}
184 protected DerivedUnit(SpecimenOrObservationType recordBasis
) {
190 * Create new unit derived from an existing field unit
191 * @param fieldUnit existing field unit from where this unit is derived
193 protected DerivedUnit(SpecimenOrObservationType recordBasis
, FieldUnit fieldUnit
) {
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
);
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
208 protected DerivedUnit(SpecimenOrObservationType recordBasis
, GatheringEvent gatheringEvent
) {
209 this(recordBasis
, new FieldUnit());
210 FieldUnit field
= (FieldUnit
)this.getOriginalUnit();
211 field
.setGatheringEvent(gatheringEvent
);
214 // ******************** GETTER / SETTER *************************************/
216 public DerivationEvent
getDerivedFrom() {
220 public void setDerivedFrom(DerivationEvent derivedFrom
){
221 if (getDerivedFrom() != null){
222 getDerivedFrom().getDerivatives().remove(derivedFrom
);
224 this.derivedFrom
= derivedFrom
;
225 if (derivedFrom
!= null){
226 derivedFrom
.addDerivative(this);
231 public Set
<SpecimenOrObservationBase
> getOriginals(){
232 if(getDerivedFrom() != null){
233 return getDerivedFrom().getOriginals();
238 public Collection
getCollection(){
239 return this.collection
;
242 public void setCollection(Collection collection
){
243 this.collection
= collection
;
247 public String
getCatalogNumber() {
248 return catalogNumber
;
251 public void setCatalogNumber(String catalogNumber
) {
252 this.catalogNumber
= catalogNumber
;
255 public void setBarcode(String barcode
) {
256 this.barcode
= barcode
;
258 public String
getBarcode() {
262 public void setStoredUnder(TaxonNameBase storedUnder
) {
263 this.storedUnder
= storedUnder
;
266 public String
getAccessionNumber() {
267 return accessionNumber
;
271 public void setAccessionNumber(String accessionNumber
) {
272 this.accessionNumber
= accessionNumber
;
276 * Will be removed in future versions as semantics is not clear.
277 * For accessing the collecting number use
278 * {@link FieldUnit#getFieldNumber()} instead.
282 public String
getCollectorsNumber() {
283 return collectorsNumber
;
287 * Will be removed in future versions as semantics is not clear.
288 * For editing the collecting number use
289 * {@link FieldUnit#getFieldNumber()} instead.
293 public void setCollectorsNumber(String collectorsNumber
) {
294 this.collectorsNumber
= collectorsNumber
;
297 public TaxonNameBase
getStoredUnder() {
301 public void addSpecimenTypeDesignation(SpecimenTypeDesignation specimenTypeDesignation
){
302 if (specimenTypeDesignation
.getTypeSpecimen() == this){
304 }else if (specimenTypeDesignation
.getTypeSpecimen() != null){
305 specimenTypeDesignation
.getTypeSpecimen().removeSpecimenTypeDesignation(specimenTypeDesignation
);
308 specimenTypeDesignations
.add(specimenTypeDesignation
);
309 specimenTypeDesignation
.setTypeSpecimen(this);
312 public void removeSpecimenTypeDesignation(SpecimenTypeDesignation specimenTypeDesignation
){
313 if (specimenTypeDesignation
== null){
316 if (specimenTypeDesignations
.contains(specimenTypeDesignation
)){
317 specimenTypeDesignations
.remove(specimenTypeDesignation
);
318 specimenTypeDesignation
.setTypeSpecimen(null);
322 // ******* GETTER / SETTER for preserved specimen only ******************/
324 public Set
<SpecimenTypeDesignation
> getSpecimenTypeDesignations(){
325 return specimenTypeDesignations
;
328 public PreservationMethod
getPreservation(){
329 return this.preservation
;
332 public void setPreservation(PreservationMethod preservation
){
333 this.preservation
= preservation
;
337 public void setExsiccatum(String exsiccatum
) {
338 this.exsiccatum
= exsiccatum
;
341 public String
getExsiccatum() {
345 //*********** CLONE **********************************/
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}.
353 * @see SpecimenOrObservationBase#clone()
354 * @see eu.etaxonomy.cdm.model.media.IdentifiableMediaEntity#clone()
355 * @see java.lang.Object#clone()
358 public Object
clone() {
360 DerivedUnit result
= (DerivedUnit
)super.clone();
362 result
.setCollection(this.collection
);
364 result
.setDerivedFrom(this.derivedFrom
);
366 result
.setStoredUnder(this.storedUnder
);
368 result
.setPreservation(this.preservation
);
369 //no changes to: accessionNumber, catalogNumber, collectorsNumber
371 } catch (CloneNotSupportedException e
) {
372 logger
.warn("Object does not implement cloneable");