Project

General

Profile

Download (12.2 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
package eu.etaxonomy.cdm.model.occurrence;
10

    
11
import java.util.Calendar;
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.ManyToMany;
19
import javax.persistence.ManyToOne;
20
import javax.persistence.OneToOne;
21
import javax.persistence.Transient;
22
import javax.validation.Valid;
23
import javax.validation.constraints.NotNull;
24
import javax.xml.bind.annotation.XmlAccessType;
25
import javax.xml.bind.annotation.XmlAccessorType;
26
import javax.xml.bind.annotation.XmlElement;
27
import javax.xml.bind.annotation.XmlElementWrapper;
28
import javax.xml.bind.annotation.XmlIDREF;
29
import javax.xml.bind.annotation.XmlRootElement;
30
import javax.xml.bind.annotation.XmlSchemaType;
31
import javax.xml.bind.annotation.XmlType;
32

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

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

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

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

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

    
94

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

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

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

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

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

    
134

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

    
148
	// 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
149
	@XmlElement(name = "DistanceToGround")
150
	@Field(analyze = Analyze.NO)
151
	@NumericField
152
	private Double distanceToGround;
153

    
154
	// 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
155
	@XmlElement(name = "distanceToGroundMax")
156
	@Field(analyze = Analyze.NO)
157
	@NumericField
158
	private Double distanceToGroundMax;
159

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

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

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

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

    
198
//*********************** FACTORY ****************************************/
199

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

    
207
//**************************** CONSTRUCTOR ************************************/
208

    
209
    //for hibernate use only, *packet* private required by bytebuddy
210
	GatheringEvent() {
211
		super();
212
	}
213

    
214
//********************* GETTER /SETTER *************************************/
215

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

    
223
	public NamedArea getCountry() {
224
		return country;
225
	}
226
	public void setCountry(NamedArea country) {
227
		this.country = country;
228
	}
229

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

    
240
	/**
241
	 * Further collecting areas. Should not include #getCountry()
242
	 * @param area
243
	 */
244
	public void addCollectingArea(NamedArea area){
245
		if (this.collectingAreas == null) {
246
            this.collectingAreas = getNewNamedAreaSet();
247
        }
248
		this.collectingAreas.add(area);
249
	}
250

    
251
	public void removeCollectingArea(NamedArea area){
252
		//TODO to be implemented?
253
		logger.warn("not yet fully implemented?");
254
		this.collectingAreas.remove(area);
255
	}
256

    
257
	public LanguageString getLocality(){
258
		return this.locality;
259
	}
260

    
261
	public void setLocality(LanguageString locality){
262
		this.locality = locality;
263
	}
264
	public void putLocality(Language language, String locality){
265
		this.setLocality(LanguageString.NewInstance(locality, language));
266
	}
267

    
268
/* ***** EventBase managed attributes  */
269

    
270
	@Transient
271
	public Partial getGatheringDate(){
272
	    if(this.getTimeperiod()!=null){
273
	        return this.getTimeperiod().getStart();
274
	    }
275
	    return null;
276
	}
277

    
278
	public void setGatheringDate(Partial gatheringDate){
279
		this.setTimeperiod(TimePeriod.NewInstance(gatheringDate));
280
	}
281
	public void setGatheringDate(Calendar gatheringDate){
282
		this.setTimeperiod(TimePeriod.NewInstance(gatheringDate));
283
	}
284

    
285
	@Transient
286
	public AgentBase getCollector(){
287
		return this.getActor();
288
	}
289
	public void setCollector(AgentBase collector){
290
		this.setActor(collector);
291
	}
292

    
293
// ****************** GETTER / SETTER ************************/
294

    
295
	public String getCollectingMethod() {
296
		return collectingMethod;
297
	}
298
	public void setCollectingMethod(String collectingMethod) {
299
		this.collectingMethod = isBlank(collectingMethod)? null : collectingMethod;
300
	}
301

    
302
	public Integer getAbsoluteElevation() {
303
		return absoluteElevation;
304
	}
305
	public void setAbsoluteElevation(Integer absoluteElevation) {
306
		this.absoluteElevation = absoluteElevation;
307
	}
308

    
309
	public Integer getAbsoluteElevationMax() {
310
		return absoluteElevationMax;
311
	}
312
	public void setAbsoluteElevationMax(Integer absoluteElevationMax) {
313
		this.absoluteElevationMax = absoluteElevationMax;
314
	}
315

    
316
	public String getAbsoluteElevationText() {
317
		return absoluteElevationText;
318
	}
319
	public void setAbsoluteElevationText(String absoluteElevationText) {
320
		this.absoluteElevationText = absoluteElevationText;
321
	}
322

    
323
	public Double getDistanceToGround() {
324
		return distanceToGround;
325
	}
326
	public void setDistanceToGround(Double distanceToGround) {
327
		this.distanceToGround = distanceToGround;
328
	}
329

    
330
	public Double getDistanceToWaterSurface() {
331
		return distanceToWaterSurface;
332
	}
333
	public void setDistanceToWaterSurface(Double distanceToWaterSurface) {
334
		this.distanceToWaterSurface = distanceToWaterSurface;
335
	}
336

    
337
	public Double getDistanceToGroundMax() {
338
		return distanceToGroundMax;
339
	}
340
	public void setDistanceToGroundMax(Double distanceToGroundMax) {
341
		this.distanceToGroundMax = distanceToGroundMax;
342
	}
343

    
344
	public Double getDistanceToWaterSurfaceMax() {
345
		return distanceToWaterSurfaceMax;
346
	}
347
	public void setDistanceToWaterSurfaceMax(Double distanceToWaterSurfaceMax) {
348
		this.distanceToWaterSurfaceMax = distanceToWaterSurfaceMax;
349
	}
350

    
351
	public String getDistanceToGroundText() {
352
		return distanceToGroundText;
353
	}
354
	public void setDistanceToGroundText(String distanceToGroundText) {
355
		this.distanceToGroundText = distanceToGroundText;
356
	}
357

    
358
	public String getDistanceToWaterSurfaceText() {
359
		return distanceToWaterSurfaceText;
360
	}
361
	public void setDistanceToWaterSurfaceText(String distanceToWaterSurfaceText) {
362
		this.distanceToWaterSurfaceText = distanceToWaterSurfaceText;
363
	}
364

    
365
//*********** CLONE **********************************/
366

    
367
	/**
368
	 * Clones <i>this</i> gathering event. This is a shortcut that enables to
369
	 * create a new instance that differs only slightly from <i>this</i> gathering event
370
	 * by modifying only some of the attributes.<BR>
371
	 * This method overrides the clone method from {@link DerivedUnit DerivedUnit}.
372
	 *
373
	 * @see DerivedUnit#clone()
374
	 * @see eu.etaxonomy.cdm.model.media.IdentifiableMediaEntity#clone()
375
	 * @see java.lang.Object#clone()
376
	 */
377
	@Override
378
	public GatheringEvent clone(){
379
		try{
380
			GatheringEvent result = (GatheringEvent)super.clone();
381
			//locality
382
			LanguageString langString = LanguageString.NewInstance(this.locality.getText(), this.locality.getLanguage());
383
			result.setLocality(langString);
384
			//exact location
385
			result.setExactLocation(this.exactLocation==null?null:this.exactLocation.clone());
386
			//namedAreas
387
			result.collectingAreas = new HashSet<>();
388
			for(NamedArea collectingArea : this.collectingAreas) {
389
				result.addCollectingArea(collectingArea);
390
			}
391

    
392
			//no changes to: distanceToWaterSurface, distanceToGround, collectingMethod, absoluteElevationError, absoluteElevation
393
			return result;
394
		} catch (CloneNotSupportedException e) {
395
			logger.warn("Object does not implement cloneable");
396
			e.printStackTrace();
397
			return null;
398
		}
399
	}
400

    
401
	private static Set<NamedArea> getNewNamedAreaSet(){
402
		return new HashSet<NamedArea>();
403
	}
404

    
405

    
406

    
407
}
(7-7/15)