Cloneable and other changes to occurrence classes
[cdmlib.git] / cdmlib-model / src / main / java / eu / etaxonomy / cdm / model / occurrence / SpecimenOrObservationBase.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 eu.etaxonomy.cdm.model.common.Language;
13 import eu.etaxonomy.cdm.model.common.LanguageString;
14 import eu.etaxonomy.cdm.model.common.MultilanguageText;
15 import eu.etaxonomy.cdm.model.description.DescriptionBase;
16 import eu.etaxonomy.cdm.model.description.Sex;
17 import eu.etaxonomy.cdm.model.description.SpecimenDescription;
18 import eu.etaxonomy.cdm.model.description.Stage;
19 import eu.etaxonomy.cdm.model.media.IdentifyableMediaEntity;
20 import eu.etaxonomy.cdm.model.media.Media;
21
22 import org.apache.log4j.Logger;
23 import org.hibernate.annotations.Cascade;
24 import org.hibernate.annotations.CascadeType;
25 import org.hibernate.annotations.Index;
26 import org.hibernate.annotations.Table;
27
28 import java.util.*;
29
30 import javax.persistence.*;
31 import javax.xml.bind.annotation.XmlAccessType;
32 import javax.xml.bind.annotation.XmlAccessorType;
33 import javax.xml.bind.annotation.XmlElement;
34 import javax.xml.bind.annotation.XmlElementWrapper;
35 import javax.xml.bind.annotation.XmlIDREF;
36 import javax.xml.bind.annotation.XmlRootElement;
37 import javax.xml.bind.annotation.XmlSchemaType;
38 import javax.xml.bind.annotation.XmlType;
39
40 /**
41 * type figures are observations with at least a figure object in media
42 * @author m.doering
43 * @version 1.0
44 * @created 08-Nov-2007 13:06:41
45 */
46 @XmlAccessorType(XmlAccessType.FIELD)
47 @XmlType(name = "SpecimenOrObservationBase", propOrder = {
48 "sex",
49 "individualCount",
50 "lifeStage",
51 "description",
52 "descriptions",
53 "determinations",
54 "derivationEvents"
55 })
56 @XmlRootElement(name = "SpecimenOrObservationBase")
57 @Entity
58 @Inheritance(strategy=InheritanceType.SINGLE_TABLE)
59 @Table(appliesTo="SpecimenOrObservationBase", indexes = { @Index(name = "specimenOrObservationBaseTitleCacheIndex", columnNames = { "persistentTitleCache" }) })
60 public abstract class SpecimenOrObservationBase extends IdentifyableMediaEntity {
61
62 private static final Logger logger = Logger.getLogger(SpecimenOrObservationBase.class);
63
64 @XmlElementWrapper(name = "Descriptions")
65 @XmlElement(name = "Description")
66 private Set<SpecimenDescription> descriptions = getNewDescriptionSet();
67
68 @XmlElementWrapper(name = "Determinations")
69 @XmlElement(name = "Determination")
70 private Set<DeterminationEvent> determinations = getNewDeterminationEventSet();
71
72 @XmlElement(name = "Sex")
73 @XmlIDREF
74 @XmlSchemaType(name = "IDREF")
75 private Sex sex;
76
77 @XmlElement(name = "LifeStage")
78 @XmlIDREF
79 @XmlSchemaType(name = "IDREF")
80 private Stage lifeStage;
81
82 @XmlElement(name = "IndividualCount")
83 private Integer individualCount;
84
85 // the verbatim description of this occurrence. Free text usable when no atomised data is available.
86 // in conjunction with titleCache which serves as the "citation" string for this object
87 @XmlElement(name = "Description")
88 private MultilanguageText description;
89
90 // events that created derivedUnits from this unit
91 @XmlElementWrapper(name = "DerivationEvents")
92 @XmlElement(name = "DerivationEvent")
93 @XmlIDREF
94 @XmlSchemaType(name = "IDREF")
95 private Set<DerivationEvent> derivationEvents = getNewDerivationEventSet();
96
97 /**
98 * Constructor
99 */
100 protected SpecimenOrObservationBase(){
101 super();
102 }
103
104 // @ManyToMany //FIXME
105 // @Cascade( { CascadeType.SAVE_UPDATE })
106 @Transient
107 public Set<SpecimenDescription> getDescriptions() {
108 return this.descriptions;
109 }
110 protected void setDescriptions(Set<SpecimenDescription> descriptions) {
111 this.descriptions = descriptions;
112 }
113 public void addDescription(SpecimenDescription description) {
114 if (this.descriptions == null){
115 this.descriptions = getNewDescriptionSet();
116 }
117 this.descriptions.add(description);
118 }
119 public void removeDescription(SpecimenDescription description) {
120 this.descriptions.remove(description);
121 }
122
123 @ManyToMany
124 @Cascade( { CascadeType.SAVE_UPDATE })
125 public Set<DerivationEvent> getDerivationEvents() {
126 return this.derivationEvents;
127 }
128 protected void setDerivationEvents(Set<DerivationEvent> derivationEvents) {
129 this.derivationEvents = derivationEvents;
130 }
131 public void addDerivationEvent(DerivationEvent derivationEvent) {
132 if (! this.derivationEvents.contains(derivationEvent)){
133 this.derivationEvents.add(derivationEvent);
134 derivationEvent.addOriginal(this);
135 }
136 }
137 public void removeDerivationEvent(DerivationEvent derivationEvent) {
138 this.derivationEvents.remove(derivationEvent);
139 }
140
141
142
143 @OneToMany(mappedBy="identifiedUnit")
144 @Cascade({CascadeType.SAVE_UPDATE})
145 public Set<DeterminationEvent> getDeterminations() {
146 return this.determinations;
147 }
148 protected void setDeterminations(Set<DeterminationEvent> determinations) {
149 this.determinations = determinations;
150 }
151 public void addDetermination(DeterminationEvent determination) {
152 // FIXME bidirectional integrity. Use protected Determination setter
153 this.determinations.add(determination);
154 }
155 public void removeDetermination(DeterminationEvent determination) {
156 // FIXME bidirectional integrity. Use protected Determination setter
157 this.determinations.remove(determination);
158 }
159
160
161 @ManyToOne
162 public Sex getSex() {
163 return sex;
164 }
165
166 public void setSex(Sex sex) {
167 this.sex = sex;
168 }
169
170 @ManyToOne
171 public Stage getLifeStage() {
172 return lifeStage;
173 }
174
175 public void setLifeStage(Stage lifeStage) {
176 this.lifeStage = lifeStage;
177 }
178
179
180 @Override
181 public String generateTitle(){
182 return "";
183 }
184
185
186 public Integer getIndividualCount() {
187 return individualCount;
188 }
189
190 public void setIndividualCount(Integer individualCount) {
191 this.individualCount = individualCount;
192 }
193
194
195 public MultilanguageText getDefinition(){
196 return this.description;
197 }
198 private void setDefinition(MultilanguageText description){
199 this.description = description;
200 }
201 public void addDefinition(LanguageString description){
202 initDescription();
203 this.description.add(description);
204 }
205 public void addDefinition(String text, Language language){
206 initDescription();
207 this.description.put(language, LanguageString.NewInstance(text, language));
208 }
209 public void removeDefinition(Language lang){
210 this.description.remove(lang);
211 }
212
213
214 /**
215 * for derived units get the single next higher parental/original unit.
216 * If multiple original units exist throw error
217 * @return
218 */
219 @Transient
220 public SpecimenOrObservationBase getOriginalUnit(){
221 return null;
222 }
223
224 @Transient
225 public abstract GatheringEvent getGatheringEvent();
226
227
228 //******************** CLONE **********************************************/
229
230 /* (non-Javadoc)
231 * @see eu.etaxonomy.cdm.model.media.IdentifyableMediaEntity#clone()
232 * @see eu.etaxonomy.cdm.model.common.IdentifiableEntity#clone()
233 * @see java.lang.Object#clone()
234 */
235 @Override
236 public Object clone() throws CloneNotSupportedException{
237 SpecimenOrObservationBase result = null;
238 result = (SpecimenOrObservationBase)super.clone();
239
240 //defininion (description, languageString)
241 if (this.getDefinition() != null){
242 result.setDefinition(this.getDefinition().clone());
243 }
244 //sex
245 result.setSex(this.sex);
246 //life stage
247 result.setLifeStage(this.lifeStage);
248
249 //Descriptions
250 Set<SpecimenDescription> descriptions = getNewDescriptionSet();
251 descriptions.addAll(this.descriptions);
252 result.setDescriptions(descriptions);
253
254 //DeterminationEvent
255 Set<DeterminationEvent> determinationEvents = getNewDeterminationEventSet();
256 determinationEvents.addAll(this.determinations);
257 result.setDeterminations(determinationEvents);
258
259 //DerivationEvent
260 Set<DerivationEvent> derivationEvent = getNewDerivationEventSet();
261 derivationEvent.addAll(this.getDerivationEvents());
262 result.setDerivationEvents(derivationEvent);
263
264 //no changes to: individualCount
265 return result;
266 }
267
268 @Transient
269 private Set<SpecimenDescription> getNewDescriptionSet(){
270 return new HashSet<SpecimenDescription>();
271 }
272
273 @Transient
274 private Set<DeterminationEvent> getNewDeterminationEventSet(){
275 return new HashSet<DeterminationEvent>();
276 }
277
278
279 @Transient
280 private Set<DerivationEvent> getNewDerivationEventSet(){
281 return new HashSet<DerivationEvent>();
282 }
283
284 /**
285 * Initializes the description multilanguage text if it is not yet initialized (== null).
286 */
287 @Transient
288 private void initDescription(){
289 if (this.description == null){
290 this.description = new MultilanguageText();
291 }
292 }
293 }