JAL-2808 don't capture or report min-max for mixed text/numeric attribute
[jalview.git] / src / jalview / datamodel / features / FeatureAttributes.java
index 7221d62..10249f3 100644 (file)
@@ -14,6 +14,11 @@ import java.util.TreeMap;
  */
 public class FeatureAttributes
 {
+  public enum Datatype
+  {
+    Character, Number, Mixed
+  }
+
   private static FeatureAttributes instance = new FeatureAttributes();
 
   /*
@@ -79,9 +84,11 @@ public class FeatureAttributes
      */
     boolean hasValue = false;
 
+    Datatype type;
+
     /**
-     * Note one instance of this attribute, recording unique, non-null names,
-     * and the min/max of any numerical values
+     * Note one instance of this attribute, recording unique, non-null
+     * descriptions, and the min/max of any numerical values
      * 
      * @param desc
      * @param value
@@ -92,15 +99,35 @@ public class FeatureAttributes
 
       if (value != null)
       {
-        try
-        {
-          float f = Float.valueOf(value);
-          min = Float.min(min, f);
-          max = Float.max(max, f);
-          hasValue = true;
-        } catch (NumberFormatException e)
+        value = value.trim();
+
+        /*
+         * Parse numeric value unless we have previously
+         * seen text data for this attribute type
+         */
+        if (type == null || type == Datatype.Number)
         {
-          // ok, wasn't a number, ignore for min-max purposes
+          try
+          {
+            float f = Float.valueOf(value);
+            min = hasValue ? Float.min(min, f) : f;
+            max = hasValue ? Float.max(max, f) : f;
+            hasValue = true;
+            type = (type == null || type == Datatype.Number)
+                    ? Datatype.Number
+                    : Datatype.Mixed;
+          } catch (NumberFormatException e)
+          {
+            /*
+             * non-numeric data: treat attribute as Character (or Mixed)
+             */
+            type = (type == null || type == Datatype.Character)
+                    ? Datatype.Character
+                    : Datatype.Mixed;
+            min = 0f;
+            max = 0f;
+            hasValue = false;
+          }
         }
       }
     }
@@ -118,6 +145,11 @@ public class FeatureAttributes
       return null;
     }
 
+    public Datatype getType()
+    {
+      return type;
+    }
+
     /**
      * Adds the given description to the list of known descriptions (without
      * duplication)
@@ -267,9 +299,8 @@ public class FeatureAttributes
 
   /**
    * Answers the [min, max] value range of the given attribute for the given
-   * feature type, if known, else null. Attributes which only have text values
-   * would normally return null, however text values which happen to be numeric
-   * could result in a 'min-max' range.
+   * feature type, if known, else null. Attributes with a mixture of text and
+   * numeric values are considered text (do not return a min-max range).
    * 
    * @param featureType
    * @param attName
@@ -318,4 +349,26 @@ public class FeatureAttributes
     }
     attData.addDescription(description);
   }
+
+  /**
+   * Answers the datatype of the feature, which is one of Character, Number or
+   * Mixed (or null if not known), as discovered from values recorded.
+   * 
+   * @param featureType
+   * @param attName
+   * @return
+   */
+  public Datatype getDatatype(String featureType, String... attName)
+  {
+    Map<String[], AttributeData> atts = attributes.get(featureType);
+    if (atts != null)
+    {
+      AttributeData attData = atts.get(attName);
+      if (attData != null)
+      {
+        return attData.getType();
+      }
+    }
+    return null;
+  }
 }