Project

General

Profile

Download (11.4 KB) Statistics
| Branch: | Tag: | Revision:
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.HashMap;
13
import java.util.HashSet;
14
import java.util.Map;
15
import java.util.Set;
16

    
17
import javax.persistence.Entity;
18
import javax.persistence.FetchType;
19
import javax.persistence.Inheritance;
20
import javax.persistence.InheritanceType;
21
import javax.persistence.ManyToMany;
22
import javax.persistence.ManyToOne;
23
import javax.persistence.OneToMany;
24
import javax.persistence.Transient;
25
import javax.validation.constraints.Min;
26
import javax.validation.constraints.NotNull;
27
import javax.xml.bind.annotation.XmlAccessType;
28
import javax.xml.bind.annotation.XmlAccessorType;
29
import javax.xml.bind.annotation.XmlElement;
30
import javax.xml.bind.annotation.XmlElementWrapper;
31
import javax.xml.bind.annotation.XmlIDREF;
32
import javax.xml.bind.annotation.XmlRootElement;
33
import javax.xml.bind.annotation.XmlSchemaType;
34
import javax.xml.bind.annotation.XmlType;
35
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
36

    
37
import org.apache.log4j.Logger;
38
import org.hibernate.annotations.Cascade;
39
import org.hibernate.annotations.CascadeType;
40
import org.hibernate.annotations.Index;
41
import org.hibernate.annotations.Table;
42
import org.hibernate.envers.Audited;
43
import org.hibernate.search.annotations.Field;
44
import org.hibernate.search.annotations.IndexedEmbedded;
45

    
46
import eu.etaxonomy.cdm.jaxb.MultilanguageTextAdapter;
47
import eu.etaxonomy.cdm.model.common.Language;
48
import eu.etaxonomy.cdm.model.common.LanguageString;
49
import eu.etaxonomy.cdm.model.description.DescriptionBase;
50
import eu.etaxonomy.cdm.model.description.Sex;
51
import eu.etaxonomy.cdm.model.description.SpecimenDescription;
52
import eu.etaxonomy.cdm.model.description.Stage;
53
import eu.etaxonomy.cdm.model.description.TaxonDescription;
54
import eu.etaxonomy.cdm.model.description.TaxonNameDescription;
55
import eu.etaxonomy.cdm.model.media.IdentifiableMediaEntity;
56
import eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy;
57

    
58
/**
59
 * type figures are observations with at least a figure object in media
60
 * @author m.doering
61
 * @version 1.0
62
 * @created 08-Nov-2007 13:06:41
63
 */
64
@XmlAccessorType(XmlAccessType.FIELD)
65
@XmlType(name = "SpecimenOrObservationBase", propOrder = {
66
	"sex",
67
    "individualCount",
68
    "lifeStage",
69
    "description",
70
    "descriptions",
71
    "determinations",
72
    "derivationEvents"
73
})
74
@XmlRootElement(name = "SpecimenOrObservationBase")
75
@Entity
76
@Audited
77
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
78
@Table(appliesTo="SpecimenOrObservationBase", indexes = { @Index(name = "specimenOrObservationBaseTitleCacheIndex", columnNames = { "titleCache" }) })
79
public abstract class SpecimenOrObservationBase<S extends IIdentifiableEntityCacheStrategy> extends IdentifiableMediaEntity<S> {
80
	
81
	private static final Logger logger = Logger.getLogger(SpecimenOrObservationBase.class);
82
	
83
	@XmlElementWrapper(name = "Descriptions")
84
	@XmlElement(name = "Description")
85
	@ManyToMany(fetch = FetchType.LAZY,mappedBy="describedSpecimenOrObservations",targetEntity=DescriptionBase.class)
86
	@Cascade(CascadeType.SAVE_UPDATE)
87
	@NotNull
88
	private Set<DescriptionBase> descriptions = new HashSet<DescriptionBase>();
89
	
90
	@XmlElementWrapper(name = "Determinations")
91
	@XmlElement(name = "Determination")
92
	@OneToMany(mappedBy="identifiedUnit")
93
	@Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.DELETE, CascadeType.DELETE_ORPHAN})
94
	@IndexedEmbedded(depth = 2)
95
	@NotNull
96
	private Set<DeterminationEvent> determinations = new HashSet<DeterminationEvent>();
97
	
98
	@XmlElement(name = "Sex")
99
	@XmlIDREF
100
	@XmlSchemaType(name = "IDREF")
101
	@ManyToOne(fetch = FetchType.LAZY)
102
	private Sex sex;
103
	
104
	@XmlElement(name = "LifeStage")
105
	@XmlIDREF
106
	@XmlSchemaType(name = "IDREF")
107
	@ManyToOne(fetch = FetchType.LAZY)
108
	private Stage lifeStage;
109
	
110
	@XmlElement(name = "IndividualCount")
111
	@Field(index=org.hibernate.search.annotations.Index.UN_TOKENIZED)
112
	@Min(0)
113
	private Integer individualCount;
114
	
115
	// the verbatim description of this occurrence. Free text usable when no atomised data is available.
116
	// in conjunction with titleCache which serves as the "citation" string for this object
117
	@XmlElement(name = "Description")
118
	@XmlJavaTypeAdapter(MultilanguageTextAdapter.class)
119
	@OneToMany(fetch = FetchType.LAZY)
120
	@Cascade({CascadeType.SAVE_UPDATE, CascadeType.DELETE, CascadeType.DELETE_ORPHAN})
121
	@IndexedEmbedded
122
	@NotNull
123
	protected Map<Language,LanguageString> description = new HashMap<Language,LanguageString>();
124
	
125
	// events that created derivedUnits from this unit
126
	@XmlElementWrapper(name = "DerivationEvents")
127
	@XmlElement(name = "DerivationEvent")
128
    @XmlIDREF
129
    @XmlSchemaType(name = "IDREF")
130
    @ManyToMany(fetch=FetchType.LAZY)
131
    @Cascade({CascadeType.SAVE_UPDATE, CascadeType.DELETE, CascadeType.DELETE_ORPHAN})
132
    @NotNull
133
	protected Set<DerivationEvent> derivationEvents = new HashSet<DerivationEvent>();
134

    
135
	/**
136
	 * Constructor
137
	 */
138
	protected SpecimenOrObservationBase(){
139
		super();
140
	}
141
	
142
	/**
143
	 * The descriptions this specimen or observation is part of.<BR>
144
	 * A specimen can not only have it's own {@link SpecimenDescription specimen description }
145
	 * but can also be part of a {@link TaxonDescription taxon description} or a 
146
	 * {@link TaxonNameDescription taxon name description}.<BR>
147
	 * @see #getSpecimenDescriptions()
148
	 * @return
149
	 */
150
	public Set<DescriptionBase> getDescriptions() {
151
		if(descriptions == null) {
152
			this.descriptions = new HashSet<DescriptionBase>();
153
		}
154
		return this.descriptions;
155
	}
156
	
157
	/**
158
	 * Returns the {@link SpecimenDescription specimen descriptions} this specimen is part of.
159
	 * @see #getDescriptions()
160
	 * @return
161
	 */
162
	public Set<SpecimenDescription> getSpecimenDescriptions() {
163
		return getSpecimenDescriptions(true);
164
	}
165
	
166
	/**
167
	 * Returns the {@link SpecimenDescription specimen descriptions} this specimen is part of.
168
	 * @see #getDescriptions()
169
	 * @return
170
	 */
171
	public Set<SpecimenDescription> getSpecimenDescriptions(boolean includeImageGallery) {
172
		Set<SpecimenDescription> specimenDescriptions = new HashSet<SpecimenDescription>();
173
		for (DescriptionBase descriptionBase : getDescriptions()){
174
			if (descriptionBase.isInstanceOf(SpecimenDescription.class)){
175
				if (includeImageGallery || descriptionBase.isImageGallery() == false){
176
					specimenDescriptions.add(descriptionBase.deproxy(descriptionBase, SpecimenDescription.class));
177
				}
178
				
179
			}
180
		}
181
		return specimenDescriptions;
182
	}
183

    
184
	/**
185
	 * Adds a new description to this specimen or observation
186
	 * @param description
187
	 */
188
	public void addDescription(DescriptionBase description) {
189
		this.descriptions.add(description);
190
		if (! description.getDescribedSpecimenOrObservations().contains(this)){
191
			description.addDescribedSpecimenOrObservation(this);
192
		}
193
//		Method method = ReflectionUtils.findMethod(SpecimenDescription.class, "addDescribedSpecimenOrObservation", new Class[] {SpecimenOrObservationBase.class});
194
//		ReflectionUtils.makeAccessible(method);
195
//		ReflectionUtils.invokeMethod(method, description, new Object[] {this});
196
	}
197
	
198
	/**
199
	 * Removes a specimen from a description (removes a description from this specimen)
200
	 * @param description
201
	 */
202
	public void removeDescription(DescriptionBase description) {
203
		this.descriptions.remove(description);
204
		if (description.getDescribedSpecimenOrObservations().contains(this)){
205
			description.removeDescribedSpecimenOrObservation(this);
206
		}
207
//		Method method = ReflectionUtils.findMethod(SpecimenDescription.class, "removeDescribedSpecimenOrObservations", new Class[] {SpecimenOrObservationBase.class});
208
//		ReflectionUtils.makeAccessible(method);
209
//		ReflectionUtils.invokeMethod(method, description, new Object[] {this});
210
	}
211
	
212
	public Set<DerivationEvent> getDerivationEvents() {
213
		if(derivationEvents == null) {
214
			this.derivationEvents = new HashSet<DerivationEvent>();
215
		}
216
		return this.derivationEvents;
217
	}
218
	
219
	public void addDerivationEvent(DerivationEvent derivationEvent) {
220
		if (! this.derivationEvents.contains(derivationEvent)){
221
			this.derivationEvents.add(derivationEvent);
222
			derivationEvent.addOriginal(this);
223
		}
224
	}
225
	
226
	public void removeDerivationEvent(DerivationEvent derivationEvent) {
227
		this.derivationEvents.remove(derivationEvent);
228
	}
229
	
230
	public Set<DeterminationEvent> getDeterminations() {
231
		if(determinations == null) {
232
			this.determinations = new HashSet<DeterminationEvent>();
233
		}
234
		return this.determinations;
235
	}
236

    
237
	public void addDetermination(DeterminationEvent determination) {
238
		// FIXME bidirectional integrity. Use protected Determination setter
239
		this.determinations.add(determination);
240
	}
241
	
242
	public void removeDetermination(DeterminationEvent determination) {
243
		// FIXME bidirectional integrity. Use protected Determination setter
244
		this.determinations.remove(determination);
245
	}
246
	
247
	public Sex getSex() {
248
		return sex;
249
	}
250

    
251
	public void setSex(Sex sex) {
252
		this.sex = sex;
253
	}
254

    
255
	public Stage getLifeStage() {
256
		return lifeStage;
257
	}
258

    
259
	public void setLifeStage(Stage lifeStage) {
260
		this.lifeStage = lifeStage;
261
	}
262
	
263
	@Override
264
	public String generateTitle(){
265
		return getCacheStrategy().getTitleCache(this);
266
	}
267
	
268
	public Integer getIndividualCount() {
269
		return individualCount;
270
	}
271

    
272
	public void setIndividualCount(Integer individualCount) {
273
		this.individualCount = individualCount;
274
	}
275

    
276
	public Map<Language,LanguageString> getDefinition(){
277
		return this.description;
278
	}
279
	
280
	public void addDefinition(LanguageString description){
281
		this.description.put(description.getLanguage(),description);
282
	}
283
	
284
	public void addDefinition(String text, Language language){
285
		this.description.put(language, LanguageString.NewInstance(text, language));
286
	}
287
	public void removeDefinition(Language lang){
288
		this.description.remove(lang);
289
	}
290
	
291
	/**
292
	 * for derived units get the single next higher parental/original unit.
293
	 * If multiple original units exist throw error
294
	 * @return
295
	 */
296
	@Transient
297
	public SpecimenOrObservationBase getOriginalUnit(){
298
		logger.warn("GetOriginalUnit not yet implemented");
299
		return null;
300
	}
301

    
302
	@Transient
303
	public abstract GatheringEvent getGatheringEvent();
304
	
305
	
306
//******************** CLONE **********************************************/
307
	
308
	/* (non-Javadoc)
309
	 * @see eu.etaxonomy.cdm.model.media.IdentifiableMediaEntity#clone()
310
	 * @see eu.etaxonomy.cdm.model.common.IdentifiableEntity#clone()
311
	 * @see java.lang.Object#clone()
312
	 */
313
	@Override
314
	public Object clone() throws CloneNotSupportedException {
315
		SpecimenOrObservationBase result = null;
316
		result = (SpecimenOrObservationBase)super.clone();
317
		
318
		//defininion (description, languageString)
319
		result.description = new HashMap<Language,LanguageString>();
320
		for(LanguageString languageString : this.description.values()) {
321
			LanguageString newLanguageString = (LanguageString)languageString.clone();
322
			result.addDefinition(newLanguageString);
323
		} 
324

    
325
		//sex
326
		result.setSex(this.sex);
327
		//life stage
328
		result.setLifeStage(this.lifeStage);
329
		
330
		//Descriptions
331
		for(DescriptionBase description : this.descriptions) {
332
			result.addDescription((SpecimenDescription)description);
333
		}
334
		
335
		//DeterminationEvent FIXME should clone() the determination
336
		// as the relationship is OneToMany
337
		for(DeterminationEvent determination : this.determinations) {
338
			result.addDetermination(determination);
339
		}
340
		
341
		//DerivationEvent
342
		for(DerivationEvent derivationEvent : this.derivationEvents) {
343
			result.addDerivationEvent(derivationEvent);
344
		}
345
		
346
		//no changes to: individualCount
347
		return result;
348
	}
349
}
(15-15/17)