import javax.persistence.FetchType;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
+import javax.persistence.Transient;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import org.hibernate.annotations.CascadeType;
import org.hibernate.envers.Audited;
import org.hibernate.search.annotations.Indexed;
+import org.hibernate.validator.constraints.NotEmpty;
+
+import eu.etaxonomy.cdm.validation.Level2;
/**
* This class represents information pieces expressed in numerical data
@Entity
@Indexed(index = "eu.etaxonomy.cdm.model.description.DescriptionElementBase")
@Audited
-public class QuantitativeData extends DescriptionElementBase {
+public class QuantitativeData extends DescriptionElementBase implements Cloneable {
private static final long serialVersionUID = -2755806455420051488L;
@SuppressWarnings("unused")
private static final Logger logger = Logger.getLogger(QuantitativeData.class);
@XmlElementWrapper(name = "StatisticalValues")
@XmlElement(name = "StatisticalValue")
@OneToMany(fetch = FetchType.LAZY)
- @Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE})
+ @Cascade({ CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.DELETE,CascadeType.DELETE_ORPHAN })
+ @NotEmpty(groups = Level2.class)
private Set<StatisticalMeasurementValue> statisticalValues = new HashSet<StatisticalMeasurementValue>();
+
+// ******************************** FACTORY METHOD *******************************/
+
+ /**
+ * Creates a new empty quantitative data instance.
+ */
+ public static QuantitativeData NewInstance(){
+ return new QuantitativeData();
+ }
+
+// ******************************** FACTORY METHOD *******************************/
+
+ /**
+ * Creates a new empty quantitative data instance.
+ */
+ public static QuantitativeData NewInstance(Feature feature){
+ return new QuantitativeData(feature);
+ }
+
+// ******************************** CONSTRUCTOR *******************************/
+
/**
* Class constructor: creates a new empty quantitative data instance.
*/
protected QuantitativeData(){
super(null);
}
-
+
/**
- * Creates a new empty quantitative data instance.
+ * Class constructor: creates a new empty quantitative data instance.
*/
- public static QuantitativeData NewInstance(){
- return new QuantitativeData();
+ protected QuantitativeData(Feature feature){
+ super(feature);
}
+
+
+// ******************************** GETTER /SETTER *******************************/
+
/**
* Returns the set of {@link StatisticalMeasurementValue statistical measurement values} describing
return statisticalValues;
}
+ protected void setStatisticalValues(Set<StatisticalMeasurementValue> statisticalValues) {
+ this.statisticalValues = statisticalValues;
+ }
/**
* Adds a {@link StatisticalMeasurementValue statistical measurement value} to the set of
* {@link #getStatisticalValues() statistical measurement values} describing
* <i>this</i> quantitative data
* @see #getStatisticalValues()
*/
- public void addStatisticalValue(
- StatisticalMeasurementValue statisticalValue) {
+ public void addStatisticalValue(StatisticalMeasurementValue statisticalValue) {
this.statisticalValues.add(statisticalValue);
}
/**
* @see #getStatisticalValues()
* @see #addStatisticalValue(StatisticalMeasurementValue)
*/
- public void removeStatisticalValue(
- StatisticalMeasurementValue statisticalValue) {
+ public void removeStatisticalValue(StatisticalMeasurementValue statisticalValue) {
this.statisticalValues.remove(statisticalValue);
}
this.unit = unit;
}
+// ******************************** TRANSIENT METHODS *******************************/
+
+
/**
* Returns the numerical value of the one {@link StatisticalMeasurementValue statistical measurement value}
* with the corresponding {@link StatisticalMeasure statistical measure} "minimum" and
- * belonging to <i>this</i> quantitative data. Returns "0" if no such
+ * belonging to <i>this</i> quantitative data. Returns <code>null</code> if no such
* statistical measurement value instance exists.
*/
- public float getMin(){
- return 0;
+ @Transient
+ public Float getMin(){
+ return getSpecificStatisticalValue(StatisticalMeasure.MIN());
}
/**
* Returns the numerical value of the one {@link StatisticalMeasurementValue statistical measurement value}
* with the corresponding {@link StatisticalMeasure statistical measure} "maximum" and
- * belonging to <i>this</i> quantitative data. Returns "0" if no such
+ * belonging to <i>this</i> quantitative data. Returns <code>null</code> if no such
* statistical measurement value instance exists.
*/
- public float getMax(){
- return 0;
+ @Transient
+ public Float getMax(){
+ return getSpecificStatisticalValue(StatisticalMeasure.MAX());
}
/**
* Returns the numerical value of the one {@link StatisticalMeasurementValue statistical measurement value}
* with the corresponding {@link StatisticalMeasure statistical measure}
* "typical lower boundary" and belonging to <i>this</i> quantitative data.
- * Returns "0" if no such statistical measurement value instance exists.
+ * Returns <code>null</code> if no such statistical measurement value instance exists.
+ */
+ @Transient
+ public Float getTypicalLowerBoundary(){
+ return getSpecificStatisticalValue(StatisticalMeasure.TYPICAL_LOWER_BOUNDARY());
+ }
+
+ /**
+ * Returns the numerical value of the one {@link StatisticalMeasurementValue statistical measurement value}
+ * with the corresponding {@link StatisticalMeasure statistical measure}
+ * "average" and belonging to <i>this</i> quantitative data.
+ * Returns <code>null</code> if no such statistical measurement value instance exists.
+ */
+ @Transient
+ public Float getAverage(){
+ return getSpecificStatisticalValue(StatisticalMeasure.AVERAGE());
+ }
+
+ /**
+ * Returns the numerical value of the one {@link StatisticalMeasurementValue statistical measurement value}
+ * with the corresponding {@link StatisticalMeasure statistical measure}
+ * "standard deviation" and belonging to <i>this</i> quantitative data.
+ * Returns <code>null</code> if no such statistical measurement value instance exists.
*/
- public float getTypicalLowerBoundary(){
- return 0;
+ @Transient
+ public Float getStandardDeviation(){
+ return getSpecificStatisticalValue(StatisticalMeasure.STANDARD_DEVIATION());
}
+ /**
+ * Returns the numerical value of the one {@link StatisticalMeasurementValue statistical measurement value}
+ * with the corresponding {@link StatisticalMeasure statistical measure}
+ * "sample size" and belonging to <i>this</i> quantitative data.
+ * Returns <code>null</code> if no such statistical measurement value instance exists.
+ */
+ @Transient
+ public Float getSampleSize(){
+ return getSpecificStatisticalValue(StatisticalMeasure.SAMPLE_SIZE());
+ }
+
/**
* Returns the numerical value of the one {@link StatisticalMeasurementValue statistical measurement value}
* with the corresponding {@link StatisticalMeasure statistical measure}
* "typical upper boundary" and belonging to <i>this</i> quantitative data.
- * Returns "0" if no such statistical measurement value instance exists.
+ * Returns <code>null</code> if no such statistical measurement value instance exists.
+ */
+ @Transient
+ public Float getTypicalUpperBoundary(){
+ return getSpecificStatisticalValue(StatisticalMeasure.TYPICAL_UPPER_BOUNDARY());
+ }
+
+ /**
+ * Returns the statistical value of type <code>type</code>.
+ * If no such value exists <code>null</code> is returned. If multiple such
+ * values exist an arbitrary one is returned.
+ * @param type
+ * @return the value
+ */
+ public Float getSpecificStatisticalValue(StatisticalMeasure type){
+ Float result = null;
+ for (StatisticalMeasurementValue value : statisticalValues){
+ if (type.equals(value.getType())){
+ result = value.getValue();
+ break;
+ }
+ }
+ return result;
+ }
+
+
+ /**
+ * Sets the statistical value for the minimum.
+ * If such value exists the old value is replaced by the new value.
+ * The new value is returned.
+ * @param type
+ * @param value
+ * @return the newValue
+ */
+ @Transient
+ public StatisticalMeasurementValue setMinimum(Float value, Set<Modifier> modifiers){
+ return setSpecificStatisticalValue(value, modifiers, StatisticalMeasure.MIN());
+ }
+
+
+ /**
+ * Sets the statistical value for the maximum.
+ * If such value exists the old value is replaced by the new value.
+ * The new value is returned.
+ * @param type
+ * @param value
+ * @return the newValue
+ */
+ @Transient
+ public StatisticalMeasurementValue setMaximum(Float value, Set<Modifier> modifiers){
+ return setSpecificStatisticalValue(value, modifiers, StatisticalMeasure.MAX());
+ }
+
+
+ /**
+ * Sets the statistical value for the average.
+ * If such value exists the old value is replaced by the new value.
+ * The new value is returned.
+ * @param type
+ * @param value
+ * @return the newValue
+ */
+ @Transient
+ public StatisticalMeasurementValue setAverage(Float value, Set<Modifier> modifiers){
+ return setSpecificStatisticalValue(value, modifiers, StatisticalMeasure.AVERAGE());
+ }
+
+
+ /**
+ * Sets the statistical value for the standard deviation.
+ * If such value exists the old value is replaced by the new value.
+ * The new value is returned.
+ * @param type
+ * @param value
+ * @return the newValue
+ */
+ @Transient
+ public StatisticalMeasurementValue setStandardDeviation(Float value, Set<Modifier> modifiers){
+ return setSpecificStatisticalValue(value, modifiers, StatisticalMeasure.STANDARD_DEVIATION());
+ }
+
+ /**
+ * Sets the statistical value for the sample size.
+ * If such value exists the old value is replaced by the new value.
+ * The new value is returned.
+ * @param type
+ * @param value
+ * @return the newValue
+ */
+ @Transient
+ public StatisticalMeasurementValue setSampleSize(Float value, Set<Modifier> modifiers){
+ return setSpecificStatisticalValue(value, modifiers, StatisticalMeasure.SAMPLE_SIZE());
+ }
+
+
+ /**
+ * Sets the statistical value for the typical lower boundary.
+ * If such value exists the old value is replaced by the new value.
+ * The new value is returned.
+ * @param type
+ * @param value
+ * @return the newValue
+ */
+ @Transient
+ public StatisticalMeasurementValue setTypicalLowerBoundary(Float value, Set<Modifier> modifiers){
+ return setSpecificStatisticalValue(value, modifiers, StatisticalMeasure.TYPICAL_LOWER_BOUNDARY());
+ }
+
+
+ /**
+ * Sets the statistical value for the typical upper boundary.
+ * If such value exists the old value is replaced by the new value.
+ * The new value is returned.
+ * @param type
+ * @param value
+ * @return the newValue
+ */
+ @Transient
+ public StatisticalMeasurementValue setTypicalUpperBoundary(Float value, Set<Modifier> modifiers){
+ return setSpecificStatisticalValue(value, modifiers, StatisticalMeasure.TYPICAL_UPPER_BOUNDARY());
+ }
+
+ /**
+ * Sets the statistical value of type <code>type</code>.
+ * If such value exists the old value is replaced by the new value.
+ * The new value is returned.
+ * @param type
+ * @param value
+ * @return the newValue
*/
- public float getTypicalUpperBoundary(){
- return 0;
+ public StatisticalMeasurementValue setSpecificStatisticalValue(Float value, Set<Modifier> modifiers, StatisticalMeasure type){
+ StatisticalMeasurementValue result = null;
+ if (value != null){
+ StatisticalMeasurementValue newValue = StatisticalMeasurementValue.NewInstance();
+ newValue.setValue(value);
+ if (modifiers != null){
+ newValue.getModifiers().addAll(modifiers);
+ }
+ newValue.setType(type);
+ result = newValue;
+ }
+ for (StatisticalMeasurementValue existingValue : statisticalValues){
+ if (type.equals(existingValue.getType())){
+ result = existingValue;
+ statisticalValues.remove(existingValue);
+ break;
+ }
+ }
+ if (result != null){
+ statisticalValues.add(result);
+ }
+ return result;
}
+
+
+//*********************************** CLONE *****************************************/
+
+ /**
+ * Clones <i>this</i> quantitative data. This is a shortcut that enables to create
+ * a new instance that differs only slightly from <i>this</i> quantitative data by
+ * modifying only some of the attributes.
+ *
+ * @see eu.etaxonomy.cdm.model.description.DescriptionElementBase#clone()
+ * @see java.lang.Object#clone()
+ */
+ @Override
+ public Object clone() {
+
+ try {
+ QuantitativeData result = (QuantitativeData)super.clone();
+
+ //states
+ result.statisticalValues = new HashSet<StatisticalMeasurementValue>();
+ for (StatisticalMeasurementValue data : getStatisticalValues()){
+ //TODO do we need to clone here?
+ StatisticalMeasurementValue newData = (StatisticalMeasurementValue)data.clone();
+ result.statisticalValues.add(newData);
+ }
+
+ return result;
+ //no changes to: unit
+ } catch (CloneNotSupportedException e) {
+ logger.warn("Object does not implement cloneable");
+ e.printStackTrace();
+ return null;
+ }
+ }
}
\ No newline at end of file