/** * Class to store nutrition information on food. * On initialization of the program, the class searches for a file * "fields.txt" (or otherwise specified in loadFD()) and defines the * list of fields that FoodData objects contain. Some fields are * Strings and other doubles. Fields can be empty (because no info * was provided). * To get a value of a field, first you need to see if it has a value (and * you are getting the right type. The has___Value(int field) methods are * for this purpose. Then call get___Value(int field) to retrieve the * value. If you don't know the index of the field, you can lookup an * index given the name of the field by getFieldIndex. * The compareTo is currently a comparision on the "Shrt_Desc" field. * See the main here for an example of how to use the nutrition database. * @author Gary Yngve * @version 2/6/06 */ import java.io.*; import java.util.*; import java.net.*; public class FoodData implements Comparable { private static final FieldsDefinition fd = new FieldsDefinition(loadFD()); public static InputStream openFile(String filename) throws IOException { URL url = FoodData.class.getClassLoader().getResource(filename); if (url == null) throw new IOException("File not found: " + filename); return url.openStream(); } private static Scanner loadFD() { try { return new Scanner(openFile("fields.txt")); } catch (Exception e) { throw new RuntimeException("checked->unchecked: " + e.toString()); } } public static final int compareToField = getFieldIndex("Shrt_Desc"); private double[] doubleFields; private String[] stringFields; /** * Constructs a FoodData object given a line of text * @param text line of text containing the fields of data */ public FoodData(String text) { doubleFields = new double[fd.numDoubleFields()]; stringFields = new String[fd.numStringFields()]; fd.parseLine(text,doubleFields,stringFields); } /** * Creates a dummy FoodData with only a String filled in at idx. * Everything is empty. Useful to have to compare against something * else if the compareTo is just on a single field. * @param s String of data to put in * @param idx index to put the data */ public FoodData(String s, int idx) { doubleFields = new double[fd.numDoubleFields()]; stringFields = new String[fd.numStringFields()]; for(int i = 0; i < doubleFields.length; i++) { doubleFields[i] = -1; } stringFields[fd.getStringIndex(idx)] = s; } /** * Creates a dummy FoodData with only a double filled in at idx. * Everything is empty. Useful to have to compare against something * else if the compareTo is just on a single field. * @param s String of data to put in * @param idx index to put the data */ public FoodData(double d, int idx) { doubleFields = new double[fd.numDoubleFields()]; stringFields = new String[fd.numStringFields()]; for(int i = 0; i < doubleFields.length; i++) { doubleFields[i] = -1; } doubleFields[fd.getDoubleIndex(idx)] = d; } /** * returns if the field is empty * @return true if the field is empty */ public boolean isEmpty(int field) { return !hasDoubleValue(field) && !hasStringValue(field); } /** * returns if the field has a double value present * @return true if the field has a double, false if empty or String */ public boolean hasDoubleValue(int field) { int idx = fd.getDoubleIndex(field); return idx >= 0 && doubleFields[idx] >= 0; } /** * returns the double value in the field * @return the value stored in the field (type double) * @throws NoSuchElementException if OOB, empty, or wrong type */ public double getDoubleValue(int field) { if (!hasDoubleValue(field)) throw new NoSuchElementException(); return doubleFields[fd.getDoubleIndex(field)]; } /** * returns if the field has a String value present * @return true if the field has a String, false if empty or double */ public boolean hasStringValue(int field) { int idx = fd.getStringIndex(field); return idx >= 0 && stringFields[idx] != null; } /** * returns the String value in the field * @return the value stored in the field (type String) * @throws NoSuchElementException if OOB, empty, or wrong type */ public String getStringValue(int field) { if (!hasStringValue(field)) throw new NoSuchElementException(); return stringFields[fd.getStringIndex(field)]; } /** * returns the name of the field * @param index of the field * @return String that's the name of the field */ public static String getFieldName(int field) { return fd.fieldName(field); } /** * returns the name of the field * @param index of the field * @return String that's the name of the field */ public static int getFieldIndex(String name) { return fd.fieldNum(name); } /** * returns the description of the field * @param index of the field * @return String that describes the field */ public static String getFieldDescription(int field) { return fd.fieldDesc(field); } public static String getFieldString(int field) { return fd.fieldString(field); } public static boolean isString(int field) { return fd.isString(field); } /** * returns the number of fields in a FoodData object * @return number of fields in a FoodData object */ public static int numFields() { return fd.numDoubleFields()+fd.numStringFields(); } public int compareTo(Object other) { return getStringValue(compareToField).compareTo( ((FoodData)other).getStringValue(compareToField)); } public String toString() { String s = ""; for(int i = 0; i < numFields(); i++) { s += getFieldName(i) + ": "; if (hasStringValue(i)) s += getStringValue(i); else if (hasDoubleValue(i)) s += getDoubleValue(i); else s += ""; s += "\n"; } return s; } }