Project

General

Profile

Download (13.5 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.HashSet;
13
import java.util.Set;
14

    
15
import javax.persistence.Column;
16
import javax.persistence.Entity;
17
import javax.persistence.FetchType;
18
import javax.persistence.Lob;
19
import javax.persistence.ManyToOne;
20
import javax.persistence.OneToMany;
21
import javax.persistence.Transient;
22
import javax.xml.bind.annotation.XmlAccessType;
23
import javax.xml.bind.annotation.XmlAccessorType;
24
import javax.xml.bind.annotation.XmlElement;
25
import javax.xml.bind.annotation.XmlElementWrapper;
26
import javax.xml.bind.annotation.XmlIDREF;
27
import javax.xml.bind.annotation.XmlRootElement;
28
import javax.xml.bind.annotation.XmlSchemaType;
29
import javax.xml.bind.annotation.XmlType;
30

    
31
import org.apache.log4j.Logger;
32
import org.hibernate.annotations.Cascade;
33
import org.hibernate.annotations.CascadeType;
34
import org.hibernate.envers.Audited;
35
import org.hibernate.search.annotations.Analyze;
36
import org.hibernate.search.annotations.Field;
37
import org.hibernate.search.annotations.Indexed;
38
import org.hibernate.search.annotations.IndexedEmbedded;
39

    
40
import eu.etaxonomy.cdm.model.molecular.DnaSample;
41
import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignation;
42
import eu.etaxonomy.cdm.model.name.TaxonName;
43
import eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy;
44
import eu.etaxonomy.cdm.strategy.cache.common.IdentifiableEntityDefaultCacheStrategy;
45

    
46
/**
47
 * A derived unit is regarded as derived from a field unit,
48
 * so locality and gathering related information is captured as a separate FieldUnit object
49
 * related to a specimen via a derivation event
50
 *
51
 * http://www.bgbm.org/biodivinf/docs/CollectionModel/ReprintTNR.pdf
52
 * http://www.bgbm.org/biodivinf/docs/CollectionModel/
53
 * <BR>
54
 * Type figures are derived units with at least a figure object in media
55
 *
56
 * @author m.doering
57
 * @since 08-Nov-2007 13:06:52
58
 *
59
 */
60
@XmlAccessorType(XmlAccessType.FIELD)
61
@XmlType(name = "DerivedUnit", propOrder = {
62
    "collection",
63
    "catalogNumber",
64
    "storedUnder",
65
    "derivedFrom",
66
    "accessionNumber",
67
    "collectorsNumber",
68
    "barcode",
69
	"preservation",
70
	"exsiccatum",
71
	"originalLabelInfo",
72
    "specimenTypeDesignations"
73
})
74
@XmlRootElement(name = "DerivedUnit")
75
@Entity
76
@Audited
77
// even if hibernate complains "Abstract classes can never insert index documents. Remove @Indexed."
78
// this is needed, otherwise the fields of the also abstract super class are missed during indexing
79
@Indexed(index = "eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase")
80
public class DerivedUnit extends SpecimenOrObservationBase<IIdentifiableEntityCacheStrategy<? extends DerivedUnit>> implements Cloneable{
81
	private static final long serialVersionUID = -3525746216270843517L;
82

    
83
	private static final Logger logger = Logger.getLogger(DnaSample.class);
84

    
85
	@XmlElement(name = "Collection")
86
	@XmlIDREF
87
	@XmlSchemaType(name = "IDREF")
88
	@ManyToOne(fetch = FetchType.LAZY)
89
	@Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
90
	@IndexedEmbedded
91
	private Collection collection;
92

    
93
	@XmlElement(name = "CatalogNumber")
94
	@Field(analyze = Analyze.NO)
95
    //TODO Val #3379
96
//	@NullOrNotEmpty
97
	@Column(length=255)
98
	private String catalogNumber;
99

    
100
	@XmlElement(name = "AccessionNumber")
101
	@Field(analyze = Analyze.NO)
102
    //TODO Val #3379
103
//	@NullOrNotEmpty
104
	@Column(length=255)
105
	private String accessionNumber;
106

    
107
	@XmlElement(name = "CollectorsNumber")
108
	@Field(analyze = Analyze.NO)
109
    //TODO Val #3379
110
//	@NullOrNotEmpty
111
	@Column(length=255)
112
	private String collectorsNumber;
113

    
114
	@XmlElement(name = "Barcode")
115
	@Field(analyze = Analyze.NO)
116
    //TODO Val #3379
117
//	@NullOrNotEmpty
118
	@Column(length=255)
119
	private String barcode;
120

    
121
	@XmlElement(name = "StoredUnder")
122
	@XmlIDREF
123
	@XmlSchemaType(name = "IDREF")
124
	@ManyToOne(fetch = FetchType.LAZY)
125
	@Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
126
	@IndexedEmbedded(includeEmbeddedObjectId=true)
127
	private TaxonName storedUnder;
128

    
129
	@XmlElement(name = "DerivedFrom")
130
	@XmlIDREF
131
	@XmlSchemaType(name = "IDREF")
132
	@ManyToOne(fetch = FetchType.LAZY)
133
	@Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
134
	@IndexedEmbedded(depth = 4)
135
	private DerivationEvent derivedFrom;
136

    
137
	@XmlElement(name = "OriginalLabelInfo")
138
	@Lob
139
    private String originalLabelInfo;
140

    
141
	@XmlElementWrapper(name = "SpecimenTypeDesignations")
142
	@XmlElement(name = "SpecimenTypeDesignation")
143
	@OneToMany(fetch = FetchType.LAZY, mappedBy = "typeSpecimen")
144
	@Cascade({ CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.DELETE })
145
	private final Set<SpecimenTypeDesignation> specimenTypeDesignations = new HashSet<SpecimenTypeDesignation>();
146

    
147

    
148
//*** attributes valid only for preserved specimen (PreservedSpecimen, Fossil, DnaSample)
149

    
150
	@XmlElement(name = "Preservation")
151
	@XmlIDREF
152
	@XmlSchemaType(name = "IDREF")
153
	@ManyToOne(fetch = FetchType.LAZY)
154
    @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
155
	private PreservationMethod preservation;
156

    
157

    
158
	@XmlElement(name = "Exsiccatum")
159
    //TODO Val #3379
160
//	@NullOrNotEmpty
161
	@Field
162
    @Column(length=255)
163
    private String exsiccatum;
164

    
165
// ******************** FACTORY METHOD **********************************/
166

    
167

    
168
	public static DerivedUnit NewInstance(SpecimenOrObservationType type) {
169
		if (type.isMedia()){
170
			return MediaSpecimen.NewInstance(type);
171
		}else if (type.equals(SpecimenOrObservationType.DnaSample) || type.isKindOf(SpecimenOrObservationType.DnaSample)){
172
			return DnaSample.NewInstance();
173
		}else{
174
			return new DerivedUnit(type);
175
		}
176
	}
177

    
178
	/**
179
	 * Factory method
180
	 * @return
181
	 */
182
	public static DerivedUnit NewPreservedSpecimenInstance(){
183
		DerivedUnit result = new DerivedUnit(SpecimenOrObservationType.PreservedSpecimen);
184
		return result;
185
	}
186

    
187
//************************** CONSTRUCTOR *********************************/
188

    
189
	//Constructor: For hibernate use only
190
	protected DerivedUnit() {
191
	    super();
192
        initDefaultCacheStrategy();
193
	}
194

    
195

    
196
    /**
197
	 * Constructor
198
	 * @param recordBasis
199
	 */
200
	protected DerivedUnit(SpecimenOrObservationType recordBasis) {
201
		super(recordBasis);
202
        initDefaultCacheStrategy();
203
	}
204

    
205

    
206
	/**
207
	 * Create new unit derived from an existing field unit
208
	 * @param fieldUnit existing field unit from where this unit is derived
209
	 */
210
	protected DerivedUnit(SpecimenOrObservationType recordBasis, FieldUnit fieldUnit) {
211
		this(recordBasis);
212
		DerivationEvent derivedFrom = new DerivationEvent();
213
		// TODO: should be done in a more controlled way. Probably by making derivation event implement a general relationship interface (for bidirectional add/remove etc)
214
		fieldUnit.addDerivationEvent(derivedFrom);
215
		derivedFrom.getOriginals().add(fieldUnit);
216
		derivedFrom.getDerivatives().add(this);
217
		this.setDerivedFrom(derivedFrom);
218
	}
219

    
220
	/**
221
	 * create new unit derived from an existing gathering event,
222
	 * thereby creating a new empty field unit
223
	 * @param gatheringEvent the gathering event this unit was collected at
224
	 */
225
	protected DerivedUnit(SpecimenOrObservationType recordBasis, GatheringEvent gatheringEvent) {
226
		this(recordBasis, new FieldUnit());
227
		FieldUnit field = (FieldUnit)this.getOriginalUnit();
228
		field.setGatheringEvent(gatheringEvent);
229
	}
230

    
231
    private static final String facadeStrategyClassName = "eu.etaxonomy.cdm.api.facade.DerivedUnitFacadeCacheStrategy";
232
    /**
233
     * Sets the default cache strategy
234
     */
235
	@Override
236
    protected void initDefaultCacheStrategy() {
237
        try {
238
            String facadeClassName = facadeStrategyClassName;
239
            Class<?> facadeClass = Class.forName(facadeClassName);
240
            try {
241
                this.cacheStrategy = (IIdentifiableEntityCacheStrategy)facadeClass.newInstance();
242
            } catch (InstantiationException e) {
243
                e.printStackTrace();
244
            } catch (IllegalAccessException e) {
245
                e.printStackTrace();
246
            }
247
        } catch (ClassNotFoundException e) {
248
            this.cacheStrategy = new IdentifiableEntityDefaultCacheStrategy<>();
249
        }
250
    }
251
//
252
//    private static Class<?> facadeCacheStrategyClass;
253
//
254
//
255
//    @Override
256
//    protected void setFacadeCacheStrategyClass(Class<?> facadeCacheStrategyClass){
257
//        this.facadeCacheStrategyClass = facadeCacheStrategyClass;
258
//    }
259
//
260
//
261
//    @Override
262
//    protected Class<?> getFacadeCacheStrategyClass(){
263
//	    return facadeCacheStrategyClass;
264
//	}
265

    
266

    
267

    
268
// ******************** GETTER / SETTER *************************************/
269

    
270

    
271
	public DerivationEvent getDerivedFrom() {
272
		return derivedFrom;
273
	}
274

    
275
	public void setDerivedFrom(DerivationEvent derivedFrom){
276
		if (getDerivedFrom() != null){
277
			getDerivedFrom().getDerivatives().remove(derivedFrom);
278
		}
279
		this.derivedFrom = derivedFrom;
280
		if (derivedFrom != null){
281
			derivedFrom.addDerivative(this);
282
		}
283
	}
284

    
285
	@Transient
286
	public Set<SpecimenOrObservationBase> getOriginals(){
287
		if(getDerivedFrom() != null){
288
			return getDerivedFrom().getOriginals();
289
		}
290
		return null;
291
	}
292

    
293
	public Collection getCollection(){
294
		return this.collection;
295
	}
296

    
297
	public void setCollection(Collection collection){
298
		this.collection = collection;
299
	}
300

    
301
	public String getCatalogNumber() {
302
		return catalogNumber;
303
	}
304

    
305
	public void setCatalogNumber(String catalogNumber) {
306
		this.catalogNumber = isBlank(catalogNumber)?null:catalogNumber;
307
	}
308

    
309
	public void setBarcode(String barcode) {
310
		this.barcode = isBlank(barcode)? null : barcode;
311
	}
312
	public String getBarcode() {
313
		return barcode;
314
	}
315

    
316
	public void setStoredUnder(TaxonName storedUnder) {
317
		this.storedUnder = storedUnder;
318
	}
319

    
320
	public String getAccessionNumber() {
321
		return accessionNumber;
322
	}
323
	public void setAccessionNumber(String accessionNumber) {
324
		this.accessionNumber = isBlank(accessionNumber)? null : accessionNumber;
325
	}
326

    
327
	/**
328
	 * Original label information may present the exact original text
329
	 * or any other text which fully or partly represents the text available
330
	 * on the specimens label. This information may differ from the information
331
	 * available in the derived unit itself.
332
	 * @return the original label information
333
	 */
334
	//#4218
335
	public String getOriginalLabelInfo() {
336
		return originalLabelInfo;
337
	}
338

    
339
	public void setOriginalLabelInfo(String originalLabelInfo) {
340
		this.originalLabelInfo = originalLabelInfo;
341
	}
342

    
343
	/**
344
	 * Will be removed in future versions as semantics is not clear.
345
	 * For accessing the collecting number use
346
	 * {@link FieldUnit#getFieldNumber()} instead.
347
	 * @return
348
	 */
349
	@Deprecated
350
	public String getCollectorsNumber() {
351
		return collectorsNumber;
352
	}
353

    
354
	/**
355
	 * Will be removed in future versions as semantics is not clear.
356
	 * For editing the collecting number use
357
	 * {@link FieldUnit#getFieldNumber()} instead.
358
	 * @return
359
	 */
360
	@Deprecated
361
	public void setCollectorsNumber(String collectorsNumber) {
362
		this.collectorsNumber = isBlank(collectorsNumber)? null : collectorsNumber;
363
	}
364

    
365
	public TaxonName getStoredUnder() {
366
		return storedUnder;
367
	}
368

    
369
	public void addSpecimenTypeDesignation(SpecimenTypeDesignation specimenTypeDesignation){
370
		if (specimenTypeDesignation.getTypeSpecimen() == this){
371
			return ;
372
		}else if (specimenTypeDesignation.getTypeSpecimen() != null){
373
			specimenTypeDesignation.getTypeSpecimen().removeSpecimenTypeDesignation(specimenTypeDesignation);
374

    
375
		}
376
		specimenTypeDesignations.add(specimenTypeDesignation);
377
		specimenTypeDesignation.setTypeSpecimen(this);
378
	}
379

    
380
	public void removeSpecimenTypeDesignation(SpecimenTypeDesignation specimenTypeDesignation){
381
		if (specimenTypeDesignation == null){
382
			return;
383
		}
384
		if (specimenTypeDesignations.contains(specimenTypeDesignation)){
385
			specimenTypeDesignations.remove(specimenTypeDesignation);
386
			specimenTypeDesignation.setTypeSpecimen(null);
387
		}
388
	}
389

    
390
    public String getMostSignificantIdentifier() {
391
        if (isNotBlank(getAccessionNumber())) {
392
            return getAccessionNumber();
393
        }
394
        else if(isNotBlank(getBarcode())){
395
            return getBarcode();
396
        }
397
        else if(isNotBlank(getCatalogNumber())){
398
            return getCatalogNumber();
399
        }
400
        return null;
401
    }
402

    
403
// ******* GETTER / SETTER for preserved specimen only ******************/
404

    
405
	public Set<SpecimenTypeDesignation> getSpecimenTypeDesignations(){
406
		return specimenTypeDesignations;
407
	}
408

    
409
	public PreservationMethod getPreservation(){
410
		return this.preservation;
411
	}
412

    
413
	public void setPreservation(PreservationMethod preservation){
414
		this.preservation = preservation;
415
	}
416

    
417

    
418
	public void setExsiccatum(String exsiccatum) {
419
		this.exsiccatum = isBlank(exsiccatum)? null : exsiccatum;
420
	}
421

    
422
	public String getExsiccatum() {
423
		return exsiccatum;
424
	}
425

    
426
//*********** CLONE **********************************/
427

    
428
	/**
429
	 * Clones <i>this</i> derivedUnit. This is a shortcut that enables to
430
	 * create a new instance that differs only slightly from <i>this</i> specimen
431
	 * by modifying only some of the attributes.<BR>
432
	 * This method overrides the clone method from {@link SpecimenOrObservationBase SpecimenOrObservationBase}.
433
	 *
434
	 * @see SpecimenOrObservationBase#clone()
435
	 * @see eu.etaxonomy.cdm.model.media.IdentifiableMediaEntity#clone()
436
	 * @see java.lang.Object#clone()
437
	 */
438
	@Override
439
	public Object clone() {
440
		try{
441
			DerivedUnit result = (DerivedUnit)super.clone();
442
			//collection
443
			result.setCollection(this.collection);
444
			//derivedFrom
445
			result.setDerivedFrom(this.derivedFrom);
446
			//storedUnder
447
			result.setStoredUnder(this.storedUnder);
448
			//preservation
449
			result.setPreservation(this.preservation);
450
			//no changes to: accessionNumber, catalogNumber, collectorsNumber
451
			return result;
452
		} catch (CloneNotSupportedException e) {
453
			logger.warn("Object does not implement cloneable");
454
			e.printStackTrace();
455
			return null;
456
		}
457
	}
458

    
459

    
460

    
461
}
(4-4/14)