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 @Cascade(CascadeType
.SAVE_UPDATE
)
149 private PreservationMethod preservation
;
152 @XmlElement(name
= "Exsiccatum")
157 private String exsiccatum
;
159 // ******************** FACTORY METHOD **********************************/
162 public static DerivedUnit
NewInstance(SpecimenOrObservationType type
) {
163 return new DerivedUnit(type
);
170 public static DerivedUnit
NewPreservedSpecimenInstance(){
171 DerivedUnit result
= new DerivedUnit(SpecimenOrObservationType
.PreservedSpecimen
);
175 //************************** CONSTRUCTOR *********************************/
177 //Constructor: For hibernate use only
178 protected DerivedUnit() {super();}
185 protected DerivedUnit(SpecimenOrObservationType recordBasis
) {
191 * Create new unit derived from an existing field unit
192 * @param fieldUnit existing field unit from where this unit is derived
194 protected DerivedUnit(SpecimenOrObservationType recordBasis
, FieldUnit fieldUnit
) {
196 DerivationEvent derivedFrom
= new DerivationEvent();
197 // TODO: should be done in a more controlled way. Probably by making derivation event implement a general relationship interface (for bidirectional add/remove etc)
198 fieldUnit
.addDerivationEvent(derivedFrom
);
199 derivedFrom
.getOriginals().add(fieldUnit
);
200 derivedFrom
.getDerivatives().add(this);
201 this.setDerivedFrom(derivedFrom
);
205 * create new unit derived from an existing gathering event,
206 * thereby creating a new empty field unit
207 * @param gatheringEvent the gathering event this unit was collected at
209 protected DerivedUnit(SpecimenOrObservationType recordBasis
, GatheringEvent gatheringEvent
) {
210 this(recordBasis
, new FieldUnit());
211 FieldUnit field
= (FieldUnit
)this.getOriginalUnit();
212 field
.setGatheringEvent(gatheringEvent
);
215 // ******************** GETTER / SETTER *************************************/
217 public DerivationEvent
getDerivedFrom() {
221 public void setDerivedFrom(DerivationEvent derivedFrom
){
222 if (getDerivedFrom() != null){
223 getDerivedFrom().getDerivatives().remove(derivedFrom
);
225 this.derivedFrom
= derivedFrom
;
226 if (derivedFrom
!= null){
227 derivedFrom
.addDerivative(this);
232 public Set
<SpecimenOrObservationBase
> getOriginals(){
233 if(getDerivedFrom() != null){
234 return getDerivedFrom().getOriginals();
239 public Collection
getCollection(){
240 return this.collection
;
243 public void setCollection(Collection collection
){
244 this.collection
= collection
;
248 public String
getCatalogNumber() {
249 return catalogNumber
;
252 public void setCatalogNumber(String catalogNumber
) {
253 this.catalogNumber
= catalogNumber
;
256 public void setBarcode(String barcode
) {
257 this.barcode
= barcode
;
259 public String
getBarcode() {
263 public void setStoredUnder(TaxonNameBase storedUnder
) {
264 this.storedUnder
= storedUnder
;
267 public String
getAccessionNumber() {
268 return accessionNumber
;
272 public void setAccessionNumber(String accessionNumber
) {
273 this.accessionNumber
= accessionNumber
;
277 * Will be removed in future versions as semantics is not clear.
278 * For accessing the collecting number use
279 * {@link FieldUnit#getFieldNumber()} instead.
283 public String
getCollectorsNumber() {
284 return collectorsNumber
;
288 * Will be removed in future versions as semantics is not clear.
289 * For editing the collecting number use
290 * {@link FieldUnit#getFieldNumber()} instead.
294 public void setCollectorsNumber(String collectorsNumber
) {
295 this.collectorsNumber
= collectorsNumber
;
298 public TaxonNameBase
getStoredUnder() {
302 public void addSpecimenTypeDesignation(SpecimenTypeDesignation specimenTypeDesignation
){
303 if (specimenTypeDesignation
.getTypeSpecimen() == this){
305 }else if (specimenTypeDesignation
.getTypeSpecimen() != null){
306 specimenTypeDesignation
.getTypeSpecimen().removeSpecimenTypeDesignation(specimenTypeDesignation
);
309 specimenTypeDesignations
.add(specimenTypeDesignation
);
310 specimenTypeDesignation
.setTypeSpecimen(this);
313 public void removeSpecimenTypeDesignation(SpecimenTypeDesignation specimenTypeDesignation
){
314 if (specimenTypeDesignation
== null){
317 if (specimenTypeDesignations
.contains(specimenTypeDesignation
)){
318 specimenTypeDesignations
.remove(specimenTypeDesignation
);
319 specimenTypeDesignation
.setTypeSpecimen(null);
323 // ******* GETTER / SETTER for preserved specimen only ******************/
325 public Set
<SpecimenTypeDesignation
> getSpecimenTypeDesignations(){
326 return specimenTypeDesignations
;
329 public PreservationMethod
getPreservation(){
330 return this.preservation
;
333 public void setPreservation(PreservationMethod preservation
){
334 this.preservation
= preservation
;
338 public void setExsiccatum(String exsiccatum
) {
339 this.exsiccatum
= exsiccatum
;
342 public String
getExsiccatum() {
346 //*********** CLONE **********************************/
349 * Clones <i>this</i> derivedUnit. This is a shortcut that enables to
350 * create a new instance that differs only slightly from <i>this</i> specimen
351 * by modifying only some of the attributes.<BR>
352 * This method overrides the clone method from {@link SpecimenOrObservationBase SpecimenOrObservationBase}.
354 * @see SpecimenOrObservationBase#clone()
355 * @see eu.etaxonomy.cdm.model.media.IdentifiableMediaEntity#clone()
356 * @see java.lang.Object#clone()
359 public Object
clone() {
361 DerivedUnit result
= (DerivedUnit
)super.clone();
363 result
.setCollection(this.collection
);
365 result
.setDerivedFrom(this.derivedFrom
);
367 result
.setStoredUnder(this.storedUnder
);
369 result
.setPreservation(this.preservation
);
370 //no changes to: accessionNumber, catalogNumber, collectorsNumber
372 } catch (CloneNotSupportedException e
) {
373 logger
.warn("Object does not implement cloneable");