JAL-3253 FileFormats static removal
[jalview.git] / src / jalview / datamodel / features / FeatureAttributes.java
index 7221d62..81c670b 100644 (file)
@@ -1,5 +1,7 @@
 package jalview.datamodel.features;
 
+import jalview.bin.Instance;
+
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
@@ -14,7 +16,23 @@ import java.util.TreeMap;
  */
 public class FeatureAttributes
 {
-  private static FeatureAttributes instance = new FeatureAttributes();
+  public enum Datatype
+  {
+    Character, Number, Mixed
+  }
+
+  public static FeatureAttributes getInstance()
+  {
+    Instance i = Instance.getInstance();
+    return (i.featureAttributes == null
+            ? i.featureAttributes = new FeatureAttributes()
+            : i.featureAttributes);
+  }
+
+  private FeatureAttributes()
+  {
+    attributes = new HashMap<>();
+  }
 
   /*
    * map, by feature type, of a map, by attribute name, of
@@ -79,9 +97,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 +112,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 ? Math.min(min, f) : f;
+            max = hasValue ? Math.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 +158,11 @@ public class FeatureAttributes
       return null;
     }
 
+    public Datatype getType()
+    {
+      return type;
+    }
+
     /**
      * Adds the given description to the list of known descriptions (without
      * duplication)
@@ -141,21 +186,6 @@ public class FeatureAttributes
   }
 
   /**
-   * Answers the singleton instance of this class
-   * 
-   * @return
-   */
-  public static FeatureAttributes getInstance()
-  {
-    return instance;
-  }
-
-  private FeatureAttributes()
-  {
-    attributes = new HashMap<>();
-  }
-
-  /**
    * Answers the attribute names known for the given feature type, in
    * alphabetical order (not case sensitive), or an empty set if no attributes
    * are known. An attribute name is typically 'simple' e.g. "AC", but may be
@@ -267,9 +297,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 +347,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;
+  }
 }