Project

General

Profile

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

    
16
import javax.persistence.Column;
17
import javax.persistence.Entity;
18
import javax.persistence.FetchType;
19
import javax.persistence.ManyToMany;
20
import javax.persistence.ManyToOne;
21
import javax.persistence.OneToOne;
22
import javax.persistence.Transient;
23
import javax.validation.Valid;
24
import javax.validation.constraints.NotNull;
25
import javax.xml.bind.annotation.XmlAccessType;
26
import javax.xml.bind.annotation.XmlAccessorType;
27
import javax.xml.bind.annotation.XmlElement;
28
import javax.xml.bind.annotation.XmlElementWrapper;
29
import javax.xml.bind.annotation.XmlIDREF;
30
import javax.xml.bind.annotation.XmlRootElement;
31
import javax.xml.bind.annotation.XmlSchemaType;
32
import javax.xml.bind.annotation.XmlType;
33

    
34
import org.apache.commons.lang.StringUtils;
35
import org.apache.log4j.Logger;
36
import org.hibernate.annotations.Cascade;
37
import org.hibernate.annotations.CascadeType;
38
import org.hibernate.envers.Audited;
39
import org.hibernate.search.annotations.Analyze;
40
import org.hibernate.search.annotations.Field;
41
import org.hibernate.search.annotations.IndexedEmbedded;
42
import org.hibernate.search.annotations.NumericField;
43
import org.joda.time.Partial;
44

    
45
import eu.etaxonomy.cdm.model.agent.AgentBase;
46
import eu.etaxonomy.cdm.model.common.EventBase;
47
import eu.etaxonomy.cdm.model.common.Language;
48
import eu.etaxonomy.cdm.model.common.LanguageString;
49
import eu.etaxonomy.cdm.model.common.TimePeriod;
50
import eu.etaxonomy.cdm.model.location.NamedArea;
51
import eu.etaxonomy.cdm.model.location.Point;
52

    
53
/**
54
 * The event when gathering a specimen or recording a field unit only
55
 * @author m.doering
56
 *
57
 */
58
@XmlAccessorType(XmlAccessType.FIELD)
59
@XmlType(name = "GatheringEvent", propOrder = {
60
    "locality",
61
    "exactLocation",
62
    "country",
63
    "collectingAreas",
64
    "collectingMethod",
65
    "absoluteElevation",
66
    "absoluteElevationMax",
67
    "absoluteElevationText",
68
    "distanceToGround",
69
    "distanceToGroundMax",
70
    "distanceToGroundText",
71
    "distanceToWaterSurface",
72
    "distanceToWaterSurfaceMax",
73
    "distanceToWaterSurfaceText"
74
})
75
@XmlRootElement(name = "GatheringEvent")
76
@Entity
77
@Audited
78
//@Indexed disabled to reduce clutter in indexes, since this type is not used by any search
79
//@Indexed
80
public class GatheringEvent extends EventBase implements Cloneable{
81
	private static final long serialVersionUID = 7980806082366532180L;
82
	private static final Logger logger = Logger.getLogger(GatheringEvent.class);
83

    
84
	@XmlElement(name = "Locality")
85
	@OneToOne(fetch = FetchType.LAZY, orphanRemoval=true)
86
	@Cascade({CascadeType.ALL})
87
	@IndexedEmbedded
88
	private LanguageString locality;
89

    
90
	@XmlElement(name = "ExactLocation")
91
	@IndexedEmbedded
92
	@Valid
93
	private Point exactLocation;
94

    
95

    
96
	@XmlElement(name = "Country")
97
	@XmlIDREF
98
	@XmlSchemaType(name = "IDREF")
99
	@ManyToOne(fetch = FetchType.LAZY)
100
	@IndexedEmbedded
101
	private NamedArea country;
102

    
103
    @XmlElementWrapper(name = "CollectingAreas")
104
	@XmlElement(name = "CollectingArea")
105
	@XmlIDREF
106
	@XmlSchemaType(name = "IDREF")
107
	@ManyToMany(fetch = FetchType.LAZY)
108
	@NotNull
109
	// further collecting areas. Should not include country
110
	private Set<NamedArea> collectingAreas = new HashSet<NamedArea>();
111

    
112
	@XmlElement(name = "CollectingMethod")
113
	@Field
114
    //TODO Val #3379
115
//	@NullOrNotEmpty
116
	@Column(length=255)
117
	private String collectingMethod;
118

    
119
	/**
120
	 * meter above/below sea level of the surface
121
	* if absoluteElevationMax is defined this is the minimum value
122
	* of the range
123
	 */
124
	@XmlElement(name = "AbsoluteElevation")
125
	@Field
126
	@NumericField
127
	private Integer absoluteElevation;
128

    
129
	// meter above/below sea level of the surface, maximum value
130
	@XmlElement(name = "AbsoluteElevationMax")
131
	@Field
132
	@NumericField
133
	private Integer absoluteElevationMax;
134

    
135

    
136
	/**
137
	 * Maximum value of meter above/below sea level of the surface as text.
138
	 * If min/max value exists together with absoluteElevationText
139
	 * the later will be preferred for formatting where as the former
140
	 * will be used for computations. If the absoluteElevation
141
	 * does not require any additional information such as
142
	 * "ca." it is suggested to use min/max value instead.
143
	 */
144
	@XmlElement(name = "AbsoluteElevationText")
145
	@Field
146
    @Column(length=30)
147
	private String absoluteElevationText;
148

    
149
	// distance in meter from the ground surface when collecting. E.g. 10m below the ground or 10m above the ground/bottom of a lake or 20m up in the canope
150
	@XmlElement(name = "DistanceToGround")
151
	@Field(analyze = Analyze.NO)
152
	@NumericField
153
	private Double distanceToGround;
154

    
155
	// distance in meter from the ground surface when collecting. E.g. 10m below the ground or 10m above the ground/bottom of a lake or 20m up in the canope
156
	@XmlElement(name = "distanceToGroundMax")
157
	@Field(analyze = Analyze.NO)
158
	@NumericField
159
	private Double distanceToGroundMax;
160

    
161

    
162
	/**
163
	 * Distance to ground (e.g. when sample is taken from a tree) as text.
164
	 * If min/max value exists together with distanceToGroundText
165
	 * the later will be preferred for formatting whereas the former
166
	 * will be used for computations. If the distanceToGround
167
	 * does not require any additional information such as
168
	 * "ca." it is suggested to use min/max value instead.
169
	 */
170
	@XmlElement(name = "distanceToGroundText")
171
	@Field
172
    @Column(length=30)
173
	private String distanceToGroundText;
174

    
175
	// distance in meters to lake or sea surface. Similar to distanceToGround use negative integers for distance *below* the surface, ie under water
176
	@XmlElement(name = "DistanceToWaterSurface")
177
	@Field(analyze = Analyze.NO)
178
	@NumericField
179
	private Double distanceToWaterSurface;
180

    
181
	// distance in meters to lake or sea surface. Similar to distanceToGround use negative integers for distance *below* the surface, ie under water
182
	@XmlElement(name = "DistanceToWaterSurface")
183
	@Field(analyze = Analyze.NO)
184
	@NumericField
185
	private Double distanceToWaterSurfaceMax;
186

    
187
	/**
188
	 * Distance to water surface (e.g. when sample is taken within water) as text.
189
	 * If min/max value exists together with distanceToWaterSurfaceText
190
	 * the later will be preferred for formatting whereas the former
191
	 * will be used for computations. If the distanceToWaterSurface
192
	 * does not require any additional information such as
193
	 * "ca." it is suggested to use min/max value instead.
194
	 */
195
	@XmlElement(name = "distanceToGroundText")
196
	@Field
197
    @Column(length=30)
198
	private String distanceToWaterSurfaceText;
199

    
200

    
201
	/**
202
	 * Factory method
203
	 * @return
204
	 */
205
	public static GatheringEvent NewInstance(){
206
		return new GatheringEvent();
207
	}
208

    
209
	/**
210
	 * Constructor
211
	 */
212
	protected GatheringEvent() {
213
		super();
214
	}
215

    
216
	public Point getExactLocation(){
217
		return this.exactLocation;
218
	}
219
	public void setExactLocation(Point exactLocation){
220
		this.exactLocation = exactLocation;
221
	}
222

    
223

    
224

    
225
	public NamedArea getCountry() {
226
		return country;
227
	}
228

    
229
	public void setCountry(NamedArea country) {
230
		this.country = country;
231
	}
232

    
233
	/**
234
	 * Further collecting areas. Should not include #getCountry()
235
	 * @return
236
	 */
237
	public Set<NamedArea> getCollectingAreas(){
238
		if(collectingAreas == null) {
239
			this.collectingAreas = new HashSet<NamedArea>();
240
		}
241
		return this.collectingAreas;
242
	}
243

    
244

    
245
	 /**
246
	  * Further collecting areas. Should not include #getCountry()
247
	  * @param area
248
	 */
249
	public void addCollectingArea(NamedArea area){
250
		if (this.collectingAreas == null) {
251
            this.collectingAreas = getNewNamedAreaSet();
252
        }
253
		this.collectingAreas.add(area);
254
	}
255

    
256
	public void removeCollectingArea(NamedArea area){
257
		//TODO to be implemented?
258
		logger.warn("not yet fully implemented?");
259
		this.collectingAreas.remove(area);
260
	}
261

    
262
	public LanguageString getLocality(){
263
		return this.locality;
264
	}
265

    
266
	public void setLocality(LanguageString locality){
267
		this.locality = locality;
268
	}
269
	public void putLocality(Language language, String locality){
270
		this.setLocality(LanguageString.NewInstance(locality, language));
271
	}
272

    
273

    
274
	/**
275
	 * EventBase managed attributes
276
	 * @return
277
	 */
278

    
279
	@Transient
280
	public Partial getGatheringDate(){
281
	    if(this.getTimeperiod()!=null){
282
	        return this.getTimeperiod().getStart();
283
	    }
284
	    return null;
285
	}
286

    
287
	public void setGatheringDate(Partial gatheringDate){
288
		this.setTimeperiod(TimePeriod.NewInstance(gatheringDate));
289
	}
290

    
291
	public void setGatheringDate(Calendar gatheringDate){
292
		this.setTimeperiod(TimePeriod.NewInstance(gatheringDate));
293
	}
294

    
295
	@Transient
296
	public AgentBase getCollector(){
297
		return this.getActor();
298
	}
299

    
300
	public void setCollector(AgentBase collector){
301
		this.setActor(collector);
302
	}
303

    
304
	public String getCollectingMethod() {
305
		return collectingMethod;
306
	}
307

    
308
	public void setCollectingMethod(String collectingMethod) {
309
		this.collectingMethod = StringUtils.isBlank(collectingMethod)? null : collectingMethod;
310
	}
311

    
312
	public Integer getAbsoluteElevation() {
313
		return absoluteElevation;
314
	}
315

    
316
	public void setAbsoluteElevation(Integer absoluteElevation) {
317
		this.absoluteElevation = absoluteElevation;
318
	}
319

    
320

    
321
	public Integer getAbsoluteElevationMax() {
322
		return absoluteElevationMax;
323
	}
324

    
325
	public void setAbsoluteElevationMax(Integer absoluteElevationMax) {
326
		this.absoluteElevationMax = absoluteElevationMax;
327
	}
328

    
329

    
330
	public String getAbsoluteElevationText() {
331
		return absoluteElevationText;
332
	}
333

    
334
	public void setAbsoluteElevationText(String absoluteElevationText) {
335
		this.absoluteElevationText = absoluteElevationText;
336
	}
337

    
338
	public Double getDistanceToGround() {
339
		return distanceToGround;
340
	}
341

    
342
	public void setDistanceToGround(Double distanceToGround) {
343
		this.distanceToGround = distanceToGround;
344
	}
345

    
346
	public Double getDistanceToWaterSurface() {
347
		return distanceToWaterSurface;
348
	}
349

    
350
	public void setDistanceToWaterSurface(Double distanceToWaterSurface) {
351
		this.distanceToWaterSurface = distanceToWaterSurface;
352
	}
353

    
354

    
355
	public Double getDistanceToGroundMax() {
356
		return distanceToGroundMax;
357
	}
358

    
359
	public void setDistanceToGroundMax(Double distanceToGroundMax) {
360
		this.distanceToGroundMax = distanceToGroundMax;
361
	}
362

    
363
	public Double getDistanceToWaterSurfaceMax() {
364
		return distanceToWaterSurfaceMax;
365
	}
366

    
367
	public void setDistanceToWaterSurfaceMax(Double distanceToWaterSurfaceMax) {
368
		this.distanceToWaterSurfaceMax = distanceToWaterSurfaceMax;
369
	}
370

    
371
	public String getDistanceToGroundText() {
372
		return distanceToGroundText;
373
	}
374

    
375
	public void setDistanceToGroundText(String distanceToGroundText) {
376
		this.distanceToGroundText = distanceToGroundText;
377
	}
378

    
379
	public String getDistanceToWaterSurfaceText() {
380
		return distanceToWaterSurfaceText;
381
	}
382

    
383
	public void setDistanceToWaterSurfaceText(String distanceToWaterSurfaceText) {
384
		this.distanceToWaterSurfaceText = distanceToWaterSurfaceText;
385
	}
386

    
387
//*********** CLONE **********************************/
388

    
389
	/**
390
	 * Clones <i>this</i> gathering event. This is a shortcut that enables to
391
	 * create a new instance that differs only slightly from <i>this</i> gathering event
392
	 * by modifying only some of the attributes.<BR>
393
	 * This method overrides the clone method from {@link DerivedUnit DerivedUnit}.
394
	 *
395
	 * @see DerivedUnit#clone()
396
	 * @see eu.etaxonomy.cdm.model.media.IdentifiableMediaEntity#clone()
397
	 * @see java.lang.Object#clone()
398
	 */
399
	@Override
400
	public GatheringEvent clone(){
401
		try{
402
			GatheringEvent result = (GatheringEvent)super.clone();
403
			//locality
404
			LanguageString langString = LanguageString.NewInstance(this.locality.getText(), this.locality.getLanguage());
405
			result.setLocality(langString);
406
			//exact location
407
			result.setExactLocation(this.exactLocation.clone());
408
			//namedAreas
409
			result.collectingAreas = new HashSet<NamedArea>();
410
			for(NamedArea collectingArea : this.collectingAreas) {
411
				result.addCollectingArea(collectingArea);
412
			}
413

    
414
			//no changes to: distanceToWaterSurface, distanceToGround, collectingMethod, absoluteElevationError, absoluteElevation
415
			return result;
416
		} catch (CloneNotSupportedException e) {
417
			logger.warn("Object does not implement cloneable");
418
			e.printStackTrace();
419
			return null;
420
		}
421
	}
422

    
423
	private static Set<NamedArea> getNewNamedAreaSet(){
424
		return new HashSet<NamedArea>();
425
	}
426

    
427

    
428

    
429
}
(7-7/14)