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
.lang
.reflect
.Method
;
13 import java
.util
.HashMap
;
14 import java
.util
.HashSet
;
18 import javax
.persistence
.Entity
;
19 import javax
.persistence
.FetchType
;
20 import javax
.persistence
.Inheritance
;
21 import javax
.persistence
.InheritanceType
;
22 import javax
.persistence
.ManyToMany
;
23 import javax
.persistence
.ManyToOne
;
24 import javax
.persistence
.OneToMany
;
25 import javax
.persistence
.Transient
;
26 import javax
.xml
.bind
.annotation
.XmlAccessType
;
27 import javax
.xml
.bind
.annotation
.XmlAccessorType
;
28 import javax
.xml
.bind
.annotation
.XmlElement
;
29 import javax
.xml
.bind
.annotation
.XmlElementWrapper
;
30 import javax
.xml
.bind
.annotation
.XmlIDREF
;
31 import javax
.xml
.bind
.annotation
.XmlRootElement
;
32 import javax
.xml
.bind
.annotation
.XmlSchemaType
;
33 import javax
.xml
.bind
.annotation
.XmlType
;
34 import javax
.xml
.bind
.annotation
.adapters
.XmlJavaTypeAdapter
;
36 import org
.apache
.log4j
.Logger
;
37 import org
.hibernate
.annotations
.Cascade
;
38 import org
.hibernate
.annotations
.CascadeType
;
39 import org
.hibernate
.annotations
.Index
;
40 import org
.hibernate
.annotations
.Table
;
41 import org
.hibernate
.envers
.Audited
;
42 import org
.springframework
.util
.ReflectionUtils
;
44 import eu
.etaxonomy
.cdm
.jaxb
.MultilanguageTextAdapter
;
45 import eu
.etaxonomy
.cdm
.model
.common
.Language
;
46 import eu
.etaxonomy
.cdm
.model
.common
.LanguageString
;
47 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionBase
;
48 import eu
.etaxonomy
.cdm
.model
.description
.Sex
;
49 import eu
.etaxonomy
.cdm
.model
.description
.SpecimenDescription
;
50 import eu
.etaxonomy
.cdm
.model
.description
.Stage
;
51 import eu
.etaxonomy
.cdm
.model
.media
.IdentifiableMediaEntity
;
52 import eu
.etaxonomy
.cdm
.strategy
.cache
.common
.IIdentifiableEntityCacheStrategy
;
55 * type figures are observations with at least a figure object in media
58 * @created 08-Nov-2007 13:06:41
60 @XmlAccessorType(XmlAccessType
.FIELD
)
61 @XmlType(name
= "SpecimenOrObservationBase", propOrder
= {
70 @XmlRootElement(name
= "SpecimenOrObservationBase")
73 @Inheritance(strategy
=InheritanceType
.SINGLE_TABLE
)
74 @Table(appliesTo
="SpecimenOrObservationBase", indexes
= { @Index(name
= "specimenOrObservationBaseTitleCacheIndex", columnNames
= { "titleCache" }) })
75 public abstract class SpecimenOrObservationBase
<S
extends IIdentifiableEntityCacheStrategy
> extends IdentifiableMediaEntity
<S
> {
77 private static final Logger logger
= Logger
.getLogger(SpecimenOrObservationBase
.class);
79 @XmlElementWrapper(name
= "Descriptions")
80 @XmlElement(name
= "Description")
81 @ManyToMany(fetch
= FetchType
.LAZY
,mappedBy
="describedSpecimenOrObservations",targetEntity
=DescriptionBase
.class)
82 private Set
<SpecimenDescription
> descriptions
= new HashSet
<SpecimenDescription
>();
84 @XmlElementWrapper(name
= "Determinations")
85 @XmlElement(name
= "Determination")
86 @OneToMany(mappedBy
="identifiedUnit")
87 @Cascade({CascadeType
.SAVE_UPDATE
, CascadeType
.MERGE
})
88 private Set
<DeterminationEvent
> determinations
= new HashSet
<DeterminationEvent
>();
90 @XmlElement(name
= "Sex")
92 @XmlSchemaType(name
= "IDREF")
93 @ManyToOne(fetch
= FetchType
.LAZY
)
96 @XmlElement(name
= "LifeStage")
98 @XmlSchemaType(name
= "IDREF")
99 @ManyToOne(fetch
= FetchType
.LAZY
)
100 private Stage lifeStage
;
102 @XmlElement(name
= "IndividualCount")
103 private Integer individualCount
;
105 // the verbatim description of this occurrence. Free text usable when no atomised data is available.
106 // in conjunction with titleCache which serves as the "citation" string for this object
107 @XmlElement(name
= "Description")
108 @XmlJavaTypeAdapter(MultilanguageTextAdapter
.class)
109 @OneToMany(fetch
= FetchType
.LAZY
)
110 protected Map
<Language
,LanguageString
> description
= new HashMap
<Language
,LanguageString
>();
112 // events that created derivedUnits from this unit
113 @XmlElementWrapper(name
= "DerivationEvents")
114 @XmlElement(name
= "DerivationEvent")
116 @XmlSchemaType(name
= "IDREF")
117 @ManyToMany(fetch
=FetchType
.LAZY
)
118 protected Set
<DerivationEvent
> derivationEvents
= new HashSet
<DerivationEvent
>();
123 protected SpecimenOrObservationBase(){
127 public Set
<SpecimenDescription
> getDescriptions() {
128 return this.descriptions
;
131 public void addDescription(SpecimenDescription description
) {
132 this.descriptions
.add(description
);
133 Method method
= ReflectionUtils
.findMethod(SpecimenDescription
.class, "addDescribedSpecimenOrObservations", new Class
[] {SpecimenOrObservationBase
.class});
134 ReflectionUtils
.makeAccessible(method
);
135 ReflectionUtils
.invokeMethod(method
, description
, new Object
[] {this});
138 public void removeDescription(SpecimenDescription description
) {
139 this.descriptions
.remove(description
);
140 Method method
= ReflectionUtils
.findMethod(SpecimenDescription
.class, "removeDescribedSpecimenOrObservations", new Class
[] {SpecimenOrObservationBase
.class});
141 ReflectionUtils
.makeAccessible(method
);
142 ReflectionUtils
.invokeMethod(method
, description
, new Object
[] {this});
145 public Set
<DerivationEvent
> getDerivationEvents() {
146 return this.derivationEvents
;
149 public void addDerivationEvent(DerivationEvent derivationEvent
) {
150 if (! this.derivationEvents
.contains(derivationEvent
)){
151 this.derivationEvents
.add(derivationEvent
);
152 derivationEvent
.addOriginal(this);
156 public void removeDerivationEvent(DerivationEvent derivationEvent
) {
157 this.derivationEvents
.remove(derivationEvent
);
160 public Set
<DeterminationEvent
> getDeterminations() {
161 return this.determinations
;
164 public void addDetermination(DeterminationEvent determination
) {
165 // FIXME bidirectional integrity. Use protected Determination setter
166 this.determinations
.add(determination
);
169 public void removeDetermination(DeterminationEvent determination
) {
170 // FIXME bidirectional integrity. Use protected Determination setter
171 this.determinations
.remove(determination
);
174 public Sex
getSex() {
178 public void setSex(Sex sex
) {
182 public Stage
getLifeStage() {
186 public void setLifeStage(Stage lifeStage
) {
187 this.lifeStage
= lifeStage
;
191 public String
generateTitle(){
195 public Integer
getIndividualCount() {
196 return individualCount
;
199 public void setIndividualCount(Integer individualCount
) {
200 this.individualCount
= individualCount
;
203 public Map
<Language
,LanguageString
> getDefinition(){
204 return this.description
;
207 public void addDefinition(LanguageString description
){
208 this.description
.put(description
.getLanguage(),description
);
211 public void addDefinition(String text
, Language language
){
212 this.description
.put(language
, LanguageString
.NewInstance(text
, language
));
214 public void removeDefinition(Language lang
){
215 this.description
.remove(lang
);
219 * for derived units get the single next higher parental/original unit.
220 * If multiple original units exist throw error
224 public SpecimenOrObservationBase
getOriginalUnit(){
229 public abstract GatheringEvent
getGatheringEvent();
232 //******************** CLONE **********************************************/
235 * @see eu.etaxonomy.cdm.model.media.IdentifiableMediaEntity#clone()
236 * @see eu.etaxonomy.cdm.model.common.IdentifiableEntity#clone()
237 * @see java.lang.Object#clone()
240 public Object
clone() throws CloneNotSupportedException
{
241 SpecimenOrObservationBase result
= null;
242 result
= (SpecimenOrObservationBase
)super.clone();
244 //defininion (description, languageString)
245 result
.description
= new HashMap
<Language
,LanguageString
>();
246 for(LanguageString languageString
: this.description
.values()) {
247 LanguageString newLanguageString
= (LanguageString
)languageString
.clone();
248 result
.addDefinition(newLanguageString
);
252 result
.setSex(this.sex
);
254 result
.setLifeStage(this.lifeStage
);
257 for(DescriptionBase description
: this.descriptions
) {
258 result
.addDescription((SpecimenDescription
)description
);
261 //DeterminationEvent FIXME should clone() the determination
262 // as the relationship is OneToMany
263 for(DeterminationEvent determination
: this.determinations
) {
264 result
.addDetermination(determination
);
268 for(DerivationEvent derivationEvent
: this.derivationEvents
) {
269 result
.addDerivationEvent(derivationEvent
);
272 //no changes to: individualCount