free text search: better querying for 'isNotNull' and code harmonization
[cdmlib.git] / cdmlib-model / src / main / java / eu / etaxonomy / cdm / model / description / QuantitativeData.java
index 126b5639ae99419864ce8d496a9c2dc4585d4be2..208ac3c5fbf52a9fa5228c8d423a9ad4b001ffd7 100644 (file)
@@ -16,6 +16,7 @@ import javax.persistence.Entity;
 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;
@@ -30,6 +31,9 @@ import org.hibernate.annotations.Cascade;
 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
@@ -65,7 +69,7 @@ import org.hibernate.search.annotations.Indexed;
 @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);
@@ -80,21 +84,47 @@ public class QuantitativeData extends DescriptionElementBase {
        @XmlElement(name = "StatisticalValue")
        @OneToMany(fetch = FetchType.LAZY)
        @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
@@ -104,6 +134,9 @@ public class QuantitativeData extends DescriptionElementBase {
                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
@@ -113,8 +146,7 @@ public class QuantitativeData extends DescriptionElementBase {
         *                                                      <i>this</i> quantitative data
         * @see                                         #getStatisticalValues()
         */
-       public void addStatisticalValue(
-                       StatisticalMeasurementValue statisticalValue) {
+       public void addStatisticalValue(StatisticalMeasurementValue statisticalValue) {
                this.statisticalValues.add(statisticalValue);
        }
        /** 
@@ -125,8 +157,7 @@ public class QuantitativeData extends DescriptionElementBase {
         * @see                                 #getStatisticalValues()
         * @see                                 #addStatisticalValue(StatisticalMeasurementValue)
         */
-       public void removeStatisticalValue(
-                       StatisticalMeasurementValue statisticalValue) {
+       public void removeStatisticalValue(StatisticalMeasurementValue statisticalValue) {
                this.statisticalValues.remove(statisticalValue);
        }
 
@@ -145,44 +176,265 @@ public class QuantitativeData extends DescriptionElementBase {
                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