Project

General

Profile

Download (16.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.description;
11

    
12
import java.math.BigDecimal;
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.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.Indexed;
36
import org.hibernate.validator.constraints.NotEmpty;
37

    
38
import eu.etaxonomy.cdm.model.common.DefinedTerm;
39
import eu.etaxonomy.cdm.validation.Level2;
40

    
41
/**
42
 * This class represents information pieces expressed in numerical data
43
 * (in opposition to {@link CategoricalData categorical data} on one side and to literal data on
44
 * the other side). Only {@link TaxonDescription taxon descriptions} and
45
 * {@link SpecimenDescription specimen descriptions} may contain quantitative data.<BR>
46
 * The "length of leaves" {@link Feature feature} for instance can be measured in inches.
47
 * If the length of leaves of a particular tree is described as
48
 * "typically between 3 and 5 inches" and "at the utmost 8 inches" then three
49
 * {@link StatisticalMeasurementValue statistical measurement value} instances
50
 * must be assigned to an instance of the present class
51
 * (with the {@link MeasurementUnit measurement unit} set to "inch"):<ul>
52
 * <li> the first one with the value "3" and the {@link StatisticalMeasure statistical measure}
53
 * "typical lower boundary",
54
 * <li> the second one with the value "5" and the statistical measure
55
 * "typical upper boundary"
56
 * <li> the third one with the value "8" and the statistical measure "maximum"
57
 * </ul> 
58
 * <P>
59
 * This class corresponds partially to CodedDescriptionType according to
60
 * the SDD schema.
61
 * 
62
 * @author m.doering
63
 * @version 1.0
64
 * @created 08-Nov-2007 13:06:46
65
 */
66
@XmlAccessorType(XmlAccessType.FIELD)
67
@XmlType(name = "QuantitativeData", propOrder = {
68
    "unit",
69
    "statisticalValues",
70
    "unknownData"
71
})
72
@XmlRootElement(name = "QuantitativeData")
73
@Entity
74
@Indexed(index = "eu.etaxonomy.cdm.model.description.DescriptionElementBase")
75
@Audited
76
public class QuantitativeData extends DescriptionElementBase implements Cloneable {
77
	private static final long serialVersionUID = -2755806455420051488L;
78

    
79
	private static final Logger logger = Logger.getLogger(QuantitativeData.class);
80
	
81
	@XmlElement(name = "MeasurementUnit")
82
	@XmlIDREF
83
	@XmlSchemaType(name = "IDREF")
84
	@ManyToOne(fetch = FetchType.LAZY)
85
	private MeasurementUnit unit;
86
	
87
	@XmlElementWrapper(name = "StatisticalValues")
88
	@XmlElement(name = "StatisticalValue")
89
	@OneToMany(fetch = FetchType.LAZY, orphanRemoval=true)
90
	@Cascade({ CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.DELETE})
91
	@NotEmpty(groups = Level2.class)
92
	private Set<StatisticalMeasurementValue> statisticalValues = new HashSet<StatisticalMeasurementValue>();
93

    
94
//see #4471
95
//	@Column(precision = 20, scale = 10)
96
//	private BigDecimal minimum;
97
//
98
//	@Column(precision = 20, scale = 10)
99
//	private BigDecimal maximum;
100
//	
101
//	@Column(precision = 20, scale = 10)
102
//	private BigDecimal average;
103
//	
104
//	@Column(precision = 16, scale = 8)
105
//	private BigDecimal variance;
106
//	
107
//	@Column(precision = 16, scale = 8)
108
//	private BigDecimal standardDeviation;
109
//	
110
//	@Column(precision = 20, scale = 10)
111
//	private BigDecimal singleValue; 
112
//	
113
//	private Integer sampleSize;
114
	
115
	@XmlElement(name = "UnknownData")
116
	private Boolean unknownData = false;
117
	
118
	
119
// ******************************** FACTORY METHOD *******************************/
120
	
121
	/** 
122
	 * Creates a new empty quantitative data instance.
123
	 */
124
	public static QuantitativeData NewInstance(){
125
		return new QuantitativeData();
126
	}
127

    
128
// ******************************** FACTORY METHOD *******************************/
129
	
130
	/** 
131
	 * Creates a new empty quantitative data instance.
132
	 */
133
	public static QuantitativeData NewInstance(Feature feature){
134
		return new QuantitativeData(feature);
135
	}
136

    
137
	
138
// ******************************** CONSTRUCTOR *******************************/
139

    
140
	/** 
141
	 * Class constructor: creates a new empty quantitative data instance.
142
	 */
143
	protected QuantitativeData(){
144
		super(null);
145
	}
146

    
147
	/** 
148
	 * Class constructor: creates a new empty quantitative data instance.
149
	 */
150
	protected QuantitativeData(Feature feature){
151
		super(feature);
152
	}
153

    
154
	
155
// ******************************** GETTER /SETTER *******************************/
156
	
157
	
158
	/** 
159
	 * Returns the set of {@link StatisticalMeasurementValue statistical measurement values} describing
160
	 * the {@link Feature feature} corresponding to <i>this</i> quantitative data.
161
	 */
162
	public Set<StatisticalMeasurementValue> getStatisticalValues() {
163
		return statisticalValues;
164
	}
165

    
166
	protected void setStatisticalValues(Set<StatisticalMeasurementValue> statisticalValues) {
167
		this.statisticalValues = statisticalValues;
168
	}
169
	/**
170
	 * Adds a {@link StatisticalMeasurementValue statistical measurement value} to the set of
171
	 * {@link #getStatisticalValues() statistical measurement values} describing
172
	 * the {@link Feature feature} corresponding to <i>this</i> quantitative data.
173
	 * 
174
	 * @param statisticalValue	the statistical measurement value to be added to
175
	 * 							<i>this</i> quantitative data
176
	 * @see    	   				#getStatisticalValues()
177
	 */
178
	public void addStatisticalValue(StatisticalMeasurementValue statisticalValue) {
179
		this.statisticalValues.add(statisticalValue);
180
	}
181
	/** 
182
	 * Removes one element from the set of {@link #getStatisticalValues() statistical measurement values}
183
	 * describing the {@link Feature feature} corresponding to <i>this</i> quantitative data.
184
	 *
185
	 * @param  statisticalValue	the statistical measurement value which should be removed
186
	 * @see     				#getStatisticalValues()
187
	 * @see     				#addStatisticalValue(StatisticalMeasurementValue)
188
	 */
189
	public void removeStatisticalValue(StatisticalMeasurementValue statisticalValue) {
190
		this.statisticalValues.remove(statisticalValue);
191
	}
192

    
193
	
194
	/** 
195
	 * Returns the {@link MeasurementUnit measurement unit} used in <i>this</i>
196
	 * quantitative data.
197
	 */
198
	public MeasurementUnit getUnit(){
199
		return this.unit;
200
	}
201
	/**
202
	 * @see	#getUnit() 
203
	 */
204
	public void setUnit(MeasurementUnit unit){
205
		this.unit = unit;
206
	}
207

    
208
// ******************************** TRANSIENT METHODS *******************************/
209
	
210
	
211
	/** 
212
	 * Returns the numerical value of the one {@link StatisticalMeasurementValue statistical measurement value}
213
	 * with the corresponding {@link StatisticalMeasure statistical measure} "minimum" and
214
	 * belonging to <i>this</i> quantitative data. Returns <code>null</code> if no such
215
	 * statistical measurement value instance exists. 
216
	 */
217
	@Transient
218
	public Float getMin(){
219
		return getSpecificStatisticalValue(StatisticalMeasure.MIN());
220
	}
221

    
222
	/** 
223
	 * Returns the numerical value of the one {@link StatisticalMeasurementValue statistical measurement value}
224
	 * with the corresponding {@link StatisticalMeasure statistical measure} "maximum" and
225
	 * belonging to <i>this</i> quantitative data. Returns <code>null</code> if no such
226
	 * statistical measurement value instance exists. 
227
	 */
228
	@Transient
229
	public Float getMax(){
230
		return getSpecificStatisticalValue(StatisticalMeasure.MAX());
231
	}
232

    
233
	/** 
234
	 * Returns the numerical value of the one {@link StatisticalMeasurementValue statistical measurement value}
235
	 * with the corresponding {@link StatisticalMeasure statistical measure}
236
	 * "typical lower boundary" and belonging to <i>this</i> quantitative data.
237
	 * Returns <code>null</code> if no such statistical measurement value instance exists. 
238
	 */
239
	@Transient
240
	public Float getTypicalLowerBoundary(){
241
		return getSpecificStatisticalValue(StatisticalMeasure.TYPICAL_LOWER_BOUNDARY());
242
	}
243
	
244
	/** 
245
	 * Returns the numerical value of the one {@link StatisticalMeasurementValue statistical measurement value}
246
	 * with the corresponding {@link StatisticalMeasure statistical measure}
247
	 * "average" and belonging to <i>this</i> quantitative data.
248
	 * Returns <code>null</code> if no such statistical measurement value instance exists. 
249
	 */
250
	@Transient
251
	public Float getAverage(){
252
		return getSpecificStatisticalValue(StatisticalMeasure.AVERAGE());
253
	}
254

    
255
	/** 
256
	 * Returns the numerical value of the one {@link StatisticalMeasurementValue statistical measurement value}
257
	 * with the corresponding {@link StatisticalMeasure statistical measure}
258
	 * "standard deviation" and belonging to <i>this</i> quantitative data.
259
	 * Returns <code>null</code> if no such statistical measurement value instance exists. 
260
	 */
261
	@Transient
262
	public Float getStandardDeviation(){
263
		return getSpecificStatisticalValue(StatisticalMeasure.STANDARD_DEVIATION());
264
	}
265

    
266
	/** 
267
	 * Returns the numerical value of the one {@link StatisticalMeasurementValue statistical measurement value}
268
	 * with the corresponding {@link StatisticalMeasure statistical measure}
269
	 * "sample size" and belonging to <i>this</i> quantitative data.
270
	 * Returns <code>null</code> if no such statistical measurement value instance exists. 
271
	 */
272
	@Transient
273
	public Float getSampleSize(){
274
		return getSpecificStatisticalValue(StatisticalMeasure.SAMPLE_SIZE());
275
	}
276
	
277
	/** 
278
	 * Returns the numerical value of the one {@link StatisticalMeasurementValue statistical measurement value}
279
	 * with the corresponding {@link StatisticalMeasure statistical measure}
280
	 * "typical upper boundary" and belonging to <i>this</i> quantitative data.
281
	 * Returns <code>null</code> if no such statistical measurement value instance exists. 
282
	 */
283
	@Transient
284
	public Float getTypicalUpperBoundary(){
285
		return getSpecificStatisticalValue(StatisticalMeasure.TYPICAL_UPPER_BOUNDARY());
286
	}
287

    
288
	/**
289
	 * Returns the statistical value of type <code>type</code>.
290
	 * If no such value exists <code>null</code> is returned. If multiple such
291
	 * values exist an arbitrary one is returned.
292
	 * @param type
293
	 * @return the value
294
	 */
295
	public Float getSpecificStatisticalValue(StatisticalMeasure type){
296
		Float result = null;
297
		for (StatisticalMeasurementValue value : statisticalValues){
298
			if (type.equals(value.getType())){
299
				result = value.getValue();
300
				break;
301
			}
302
		}
303
		return result;
304
	}
305

    
306
	
307
	/**
308
	 * Sets the statistical value for the minimum.
309
	 * If such value exists the old value is replaced by the new value. 
310
	 * The new value is returned.
311
	 * @param type
312
	 * @param value
313
	 * @return the newValue
314
	 */
315
	@Transient
316
	public StatisticalMeasurementValue setMinimum(Float value, Set<DefinedTerm> modifiers){
317
		return setSpecificStatisticalValue(value, modifiers, StatisticalMeasure.MIN());
318
	}
319

    
320
	
321
	/**
322
	 * Sets the statistical value for the maximum.
323
	 * If such value exists the old value is replaced by the new value. 
324
	 * The new value is returned.
325
	 * @param type
326
	 * @param value
327
	 * @return the newValue
328
	 */
329
	@Transient
330
	public StatisticalMeasurementValue setMaximum(Float value, Set<DefinedTerm> modifiers){
331
		return setSpecificStatisticalValue(value, modifiers, StatisticalMeasure.MAX());
332
	}
333
	
334
	
335
	/**
336
	 * Sets the statistical value for the average.
337
	 * If such value exists the old value is replaced by the new value. 
338
	 * The new value is returned.
339
	 * @param type
340
	 * @param value
341
	 * @return the newValue
342
	 */
343
	@Transient
344
	public StatisticalMeasurementValue setAverage(Float value, Set<DefinedTerm> modifiers){
345
		return setSpecificStatisticalValue(value, modifiers, StatisticalMeasure.AVERAGE());
346
	}
347

    
348
	
349
	/**
350
	 * Sets the statistical value for the standard deviation.
351
	 * If such value exists the old value is replaced by the new value. 
352
	 * The new value is returned.
353
	 * @param type
354
	 * @param value
355
	 * @return the newValue
356
	 */
357
	@Transient
358
	public StatisticalMeasurementValue setStandardDeviation(Float value, Set<DefinedTerm> modifiers){
359
		return setSpecificStatisticalValue(value, modifiers, StatisticalMeasure.STANDARD_DEVIATION());
360
	}
361

    
362
	/**
363
	 * Sets the statistical value for the sample size.
364
	 * If such value exists the old value is replaced by the new value. 
365
	 * The new value is returned.
366
	 * @param type
367
	 * @param value
368
	 * @return the newValue
369
	 */
370
	@Transient
371
	public StatisticalMeasurementValue setSampleSize(Float value, Set<DefinedTerm> modifiers){
372
		return setSpecificStatisticalValue(value, modifiers, StatisticalMeasure.SAMPLE_SIZE());
373
	}
374

    
375
	
376
	/**
377
	 * Sets the statistical value for the typical lower boundary.
378
	 * If such value exists the old value is replaced by the new value. 
379
	 * The new value is returned.
380
	 * @param type
381
	 * @param value
382
	 * @return the newValue
383
	 */
384
	@Transient
385
	public StatisticalMeasurementValue setTypicalLowerBoundary(Float value, Set<DefinedTerm> modifiers){
386
		return setSpecificStatisticalValue(value, modifiers, StatisticalMeasure.TYPICAL_LOWER_BOUNDARY());
387
	}
388

    
389
	
390
	/**
391
	 * Sets the statistical value for the typical upper boundary.
392
	 * If such value exists the old value is replaced by the new value. 
393
	 * The new value is returned.
394
	 * @param type
395
	 * @param value
396
	 * @return the newValue
397
	 */
398
	@Transient
399
	public StatisticalMeasurementValue setTypicalUpperBoundary(Float value, Set<DefinedTerm> modifiers){
400
		return setSpecificStatisticalValue(value, modifiers, StatisticalMeasure.TYPICAL_UPPER_BOUNDARY());
401
	}
402
	
403
	/**
404
	 * Sets the statistical value of type <code>type</code>.
405
	 * If such value exists the old value is replaced by the new value. 
406
	 * The new value is returned.
407
	 * @param type
408
	 * @param value
409
	 * @return the newValue
410
	 */
411
	public StatisticalMeasurementValue setSpecificStatisticalValue(Float value, Set<DefinedTerm> modifiers, StatisticalMeasure type){
412
		StatisticalMeasurementValue result = null;
413
		if (value != null){
414
			StatisticalMeasurementValue newValue = StatisticalMeasurementValue.NewInstance();
415
			newValue.setValue(value);
416
			if (modifiers != null){
417
				newValue.getModifiers().addAll(modifiers);
418
			}
419
			newValue.setType(type);
420
			result = newValue;
421
		}
422
		for (StatisticalMeasurementValue existingValue : statisticalValues){
423
			if (type.equals(existingValue.getType())){
424
				result = existingValue;
425
				statisticalValues.remove(existingValue);
426
				break;
427
			}
428
		}
429
		if (result != null){
430
			statisticalValues.add(result);
431
		}
432
		return result;
433
	}
434

    
435
	public Boolean getUnknownData() {
436
		return unknownData;
437
	}
438

    
439
	public void setUnknownData(Boolean unknownData) {
440
		this.unknownData = unknownData;
441
	}
442
	
443
//	
444
//	public BigDecimal getMinimum() {
445
//		return minimum;
446
//	}
447
//
448
//	public void setMinimum(BigDecimal minimum) {
449
//		this.minimum = minimum;
450
//	}
451
//
452
//	public BigDecimal getMaximum() {
453
//		return maximum;
454
//	}
455
//
456
//	public void setMaximum(BigDecimal maximum) {
457
//		this.maximum = maximum;
458
//	}
459
//
460
//	public BigDecimal getVariance() {
461
//		return variance;
462
//	}
463
//
464
//	public void setVariance(BigDecimal variance) {
465
//		this.variance = variance;
466
//	}
467
//
468
//	public BigDecimal getSingleValue() {
469
//		return singleValue;
470
//	}
471
//
472
//	public void setSingleValue(BigDecimal singleValue) {
473
//		this.singleValue = singleValue;
474
//	}
475

    
476
//
477
//	public void setAverage(BigDecimal average) {
478
//		this.average = average;
479
//	}
480
//
481
//	public void setStandardDeviation(BigDecimal standardDeviation) {
482
//		this.standardDeviation = standardDeviation;
483
//	}
484
//
485
//	public void setSampleSize(Integer sampleSize) {
486
//		this.sampleSize = sampleSize;
487
//	}
488
	
489

    
490
//*********************************** CLONE *****************************************/
491

    
492
	/** 
493
	 * Clones <i>this</i> quantitative data. This is a shortcut that enables to create
494
	 * a new instance that differs only slightly from <i>this</i> quantitative data by
495
	 * modifying only some of the attributes.
496
	 * 
497
	 * @see eu.etaxonomy.cdm.model.description.DescriptionElementBase#clone()
498
	 * @see java.lang.Object#clone()
499
	 */
500
	@Override
501
	public Object clone() {
502

    
503
		try {
504
			QuantitativeData result = (QuantitativeData)super.clone();
505
			
506
			//states
507
			result.statisticalValues = new HashSet<StatisticalMeasurementValue>();
508
			for (StatisticalMeasurementValue data : getStatisticalValues()){
509
				//TODO do we need to clone here?
510
				StatisticalMeasurementValue newData = (StatisticalMeasurementValue)data.clone();
511
				result.statisticalValues.add(newData);
512
			}
513
			
514
			return result;
515
			//no changes to: unit
516
		} catch (CloneNotSupportedException e) {
517
			logger.warn("Object does not implement cloneable");
518
			e.printStackTrace();
519
			return null;
520
		}
521
	}	
522

    
523
}
(23-23/36)