1 package jalview.datamodel.features;
3 import java.util.ArrayList;
4 import java.util.Collections;
5 import java.util.HashMap;
8 import java.util.TreeMap;
11 * A singleton class to hold the set of attributes known for each feature type
13 public class FeatureAttributes
15 private static FeatureAttributes instance = new FeatureAttributes();
17 private Map<String, Map<String, AttributeData>> attributes;
19 private class AttributeData
22 * description(s) for this attribute, if known
23 * (different feature source might have differing descriptions)
25 List<String> description;
28 * minimum value (of any numeric values recorded)
33 * maximum value (of any numeric values recorded)
38 * flag is set true if any numeric value is detected for this attribute
40 boolean hasValue = false;
43 * Note one instance of this attribute, recording unique, non-null names,
44 * and the min/max of any numerical values
49 void addInstance(String desc, String value)
57 float f = Float.valueOf(value);
58 min = Float.min(min, f);
59 max = Float.max(max, f);
61 } catch (NumberFormatException e)
63 // ok, wasn't a number, ignore for min-max purposes
69 * Answers the description of the attribute, if recorded and unique, or null if either no, or more than description is recorded
72 public String getDescription()
74 if (description != null && description.size() == 1)
76 return description.get(0);
82 * Adds the given description to the list of known descriptions (without
87 public void addDescription(String desc)
91 if (description == null)
93 description = new ArrayList<>();
95 if (!description.contains(desc))
97 description.add(desc);
104 * Answers the singleton instance of this class
108 public static FeatureAttributes getInstance()
113 private FeatureAttributes()
115 attributes = new HashMap<>();
119 * Answers the attributes known for the given feature type, in alphabetical
120 * order (not case sensitive), or an empty set if no attributes are known
125 public List<String> getAttributes(String featureType)
127 if (!attributes.containsKey(featureType))
129 return Collections.<String> emptyList();
132 return new ArrayList<>(attributes.get(featureType).keySet());
136 * Answers true if at least one attribute is known for the given feature type,
142 public boolean hasAttributes(String featureType)
144 if (attributes.containsKey(featureType))
146 if (!attributes.get(featureType).isEmpty())
155 * Records the given attribute name and description for the given feature
156 * type, and updates the min-max for any numeric value
163 public void addAttribute(String featureType, String attName,
164 String description, String value)
166 if (featureType == null || attName == null)
171 Map<String, AttributeData> atts = attributes.get(featureType);
174 atts = new TreeMap<String, AttributeData>(
175 String.CASE_INSENSITIVE_ORDER);
176 attributes.put(featureType, atts);
178 AttributeData attData = atts.get(attName);
181 attData = new AttributeData();
182 atts.put(attName, attData);
184 attData.addInstance(description, value);
188 * Answers the description of the given attribute for the given feature type,
189 * if known and unique, else null
195 public String getDescription(String featureType, String attName)
198 Map<String, AttributeData> atts = attributes.get(featureType);
201 AttributeData attData = atts.get(attName);
204 desc = attData.getDescription();
211 * Answers the [min, max] value range of the given attribute for the given
212 * feature type, if known, else null. Attributes which only have text values
213 * would normally return null, however text values which happen to be numeric
214 * could result in a 'min-max' range.
220 public float[] getMinMax(String featureType, String attName)
222 Map<String, AttributeData> atts = attributes.get(featureType);
225 AttributeData attData = atts.get(attName);
226 if (attData != null && attData.hasValue)
228 return new float[] { attData.min, attData.max };
235 * Records the given attribute description for the given feature type
241 public void addDescription(String featureType, String attName,
244 if (featureType == null || attName == null)
249 Map<String, AttributeData> atts = attributes.get(featureType);
252 atts = new TreeMap<String, AttributeData>(
253 String.CASE_INSENSITIVE_ORDER);
254 attributes.put(featureType, atts);
256 AttributeData attData = atts.get(attName);
259 attData = new AttributeData();
260 atts.put(attName, attData);
262 attData.addDescription(description);