]> gitweb.fperrin.net Git - GpsPrune.git/blobdiff - tim/prune/load/FieldGuesser.java
Moved source into separate src directory due to popular request
[GpsPrune.git] / tim / prune / load / FieldGuesser.java
diff --git a/tim/prune/load/FieldGuesser.java b/tim/prune/load/FieldGuesser.java
deleted file mode 100644 (file)
index 970926b..0000000
+++ /dev/null
@@ -1,370 +0,0 @@
-package tim.prune.load;
-
-import tim.prune.I18nManager;
-import tim.prune.data.Field;
-import tim.prune.data.Latitude;
-import tim.prune.data.Longitude;
-import tim.prune.data.TimestampUtc;
-
-/**
- * Class to try to match data with field names,
- * using a variety of guessing techniques
- */
-public abstract class FieldGuesser
-{
-       /**
-        * Try to guess whether the given line is a header line or data
-        * @param inValues array of values from first non-blank line of file
-        * @return true if it looks like a header row, false if it looks like data
-        */
-       private static boolean isHeaderRow(String[] inValues)
-       {
-               // Loop over values seeing if any are mostly numeric
-               if (inValues != null)
-               {
-                       for (String value : inValues)
-                       {
-                               if (fieldLooksNumeric(value)) {return false;}
-                       }
-               }
-               // No (mostly) numeric values found so presume header
-               return true;
-       }
-
-
-       /**
-        * See if a field looks numeric or not by comparing the number of numeric vs non-numeric characters
-        * @param inValue field value to check
-        * @return true if there are more numeric characters than not
-        */
-       private static boolean fieldLooksNumeric(String inValue)
-       {
-               if (inValue == null) {
-                       return false;
-               }
-               final int numChars = inValue.length();
-               if (numChars < 3) {return false;} // Don't care about one or two character values
-               // Loop through characters seeing which ones are numeric and which not
-               int numNums = 0;
-               for (int i=0; i<numChars; i++)
-               {
-                       char currChar = inValue.charAt(i);
-                       if (currChar >= '0' && currChar <= '9') {numNums++;}
-               }
-               // Return true if more than half the characters are numeric
-               return numNums > (numChars/2);
-       }
-
-       /**
-        * Try to guess the fields for the given values from the file
-        * @param inValues array of values from first non-blank line of file
-        * @return array of fields which hopefully match
-        */
-       public static Field[] guessFields(String[] inValues)
-       {
-               // Guess whether it's a header line or not
-               boolean isHeader = isHeaderRow(inValues);
-               // make array of Fields
-               int numFields = inValues.length;
-               Field[] fields = new Field[numFields];
-               // Loop over fields to try to guess the main ones
-               for (int f=0; f<numFields; f++)
-               {
-                       if (inValues[f] != null) {
-                               String value = inValues[f].trim();
-                               // check for latitude
-                               if (!checkArrayHasField(fields, Field.LATITUDE) && fieldLooksLikeLatitude(value, isHeader))
-                               {
-                                       fields[f] = Field.LATITUDE;
-                                       continue;
-                               }
-                               // check for longitude
-                               if (!checkArrayHasField(fields, Field.LONGITUDE) && fieldLooksLikeLongitude(value, isHeader))
-                               {
-                                       fields[f] = Field.LONGITUDE;
-                                       continue;
-                               }
-                               // check for altitude
-                               if (!checkArrayHasField(fields, Field.ALTITUDE) && fieldLooksLikeAltitude(value, isHeader))
-                               {
-                                       fields[f] = Field.ALTITUDE;
-                                       continue;
-                               }
-                               // check for waypoint name
-                               if (!checkArrayHasField(fields, Field.WAYPT_NAME) && fieldLooksLikeName(value, isHeader))
-                               {
-                                       fields[f] = Field.WAYPT_NAME;
-                                       continue;
-                               }
-                               // check for timestamp
-                               if (!checkArrayHasField(fields, Field.TIMESTAMP) && fieldLooksLikeTimestamp(value, isHeader))
-                               {
-                                       fields[f] = Field.TIMESTAMP;
-                                       continue;
-                               }
-                               // check for tracksegment
-                               if (!checkArrayHasField(fields, Field.NEW_SEGMENT) && fieldLooksLikeSegment(value, isHeader))
-                               {
-                                       fields[f] = Field.NEW_SEGMENT;
-                                       continue;
-                               }
-                               // check for waypoint type
-                               if (!checkArrayHasField(fields, Field.WAYPT_TYPE) && fieldLooksLikeWaypointType(value, isHeader))
-                               {
-                                       fields[f] = Field.WAYPT_TYPE;
-                                       continue;
-                               }
-                       }
-               }
-               // Fill in the rest of the fields using just custom fields
-               // Could try to guess other fields (waypoint type, segment) or unguessed altitude, name, but keep simple for now
-               String customPrefix = I18nManager.getText("fieldname.prefix") + " ";
-               int customFieldNum = 0;
-               for (int f=0; f<numFields; f++) {
-                       if (fields[f] == null)
-                       {
-                               // Make sure lat and long are filled in if not already
-                               if (!checkArrayHasField(fields, Field.LATITUDE)) {
-                                       fields[f] = Field.LATITUDE;
-                               }
-                               else if (!checkArrayHasField(fields, Field.LONGITUDE)) {
-                                       fields[f] = Field.LONGITUDE;
-                               }
-                               else
-                               {
-                                       // Can we use the field name given?
-                                       Field customField = null;
-                                       if (isHeader && inValues[f] != null && inValues[f].length() > 0) {
-                                               customField = new Field(inValues[f]);
-                                       }
-                                       // Find an unused field number
-                                       while (customField == null || checkArrayHasField(fields, customField))
-                                       {
-                                               customFieldNum++;
-                                               customField = new Field(customPrefix + (customFieldNum));
-                                       }
-                                       fields[f] = customField;
-                               }
-                       }
-               }
-
-               // Do a final check to make sure lat and long are in there
-               if (!checkArrayHasField(fields, Field.LATITUDE)) {
-                       fields[0] = Field.LATITUDE;
-               }
-               else if (!checkArrayHasField(fields, Field.LONGITUDE)) {
-                       fields[1] = Field.LONGITUDE;
-               }
-               // Longitude _could_ have overwritten latitude in position 1
-               if (!checkArrayHasField(fields, Field.LATITUDE)) {
-                       fields[0] = Field.LATITUDE;
-               }
-               return fields;
-       }
-
-
-       /**
-        * Check whether the given field array has the specified field
-        * @param inFields
-        * @param inCheckField
-        * @return true if Field is contained within the array
-        */
-       private static boolean checkArrayHasField(Field[] inFields, Field inCheckField)
-       {
-               for (int f=0; f<inFields.length; f++)
-               {
-                       if (inFields[f] != null && inFields[f].equals(inCheckField)) {
-                               return true;
-                       }
-               }
-               // not found
-               return false;
-       }
-
-
-       /**
-        * Check whether the given String looks like a Latitude value
-        * @param inValue value from file
-        * @param inIsHeader true if this is a header line, false for data
-        * @return true if it could be latitude
-        */
-       private static boolean fieldLooksLikeLatitude(String inValue, boolean inIsHeader)
-       {
-               if (inValue == null || inValue.equals("")) {return false;}
-               if (inIsHeader)
-               {
-                       // This is a header line so look for english or local text
-                       String upperValue = inValue.toUpperCase();
-                       return (upperValue.equals("LATITUDE")
-                               || upperValue.equals(I18nManager.getText("fieldname.latitude").toUpperCase()));
-               }
-               else
-               {
-                       // Note this will also catch longitudes too
-                       Latitude lat = new Latitude(inValue);
-                       return lat.isValid();
-               }
-       }
-
-       /**
-        * Check whether the given String looks like a Longitude value
-        * @param inValue value from file
-        * @param inIsHeader true if this is a header line, false for data
-        * @return true if it could be longitude
-        */
-       private static boolean fieldLooksLikeLongitude(String inValue, boolean inIsHeader)
-       {
-               if (inValue == null || inValue.equals("")) {return false;}
-               if (inIsHeader)
-               {
-                       // This is a header line so look for english or local text
-                       String upperValue = inValue.toUpperCase();
-                       return (upperValue.equals("LONGITUDE")
-                               || upperValue.equals(I18nManager.getText("fieldname.longitude").toUpperCase()));
-               }
-               else
-               {
-                       // Note this will also catch latitudes too
-                       Longitude lon = new Longitude(inValue);
-                       return lon.isValid();
-               }
-       }
-
-       /**
-        * Check whether the given String looks like an Altitude value
-        * @param inValue value from file
-        * @param inIsHeader true if this is a header line, false for data
-        * @return true if it could be altitude
-        */
-       private static boolean fieldLooksLikeAltitude(String inValue, boolean inIsHeader)
-       {
-               if (inValue == null || inValue.equals("")) {return false;}
-               if (inIsHeader)
-               {
-                       // This is a header line so look for english or local text
-                       String upperValue = inValue.toUpperCase();
-                       return (upperValue.equals("ALTITUDE")
-                               || upperValue.equals("ALT")
-                               || upperValue.equals("HMSL") // height above mean sea level
-                               || upperValue.equals(I18nManager.getText("fieldname.altitude").toUpperCase()));
-               }
-               else
-               {
-                       // Look for a number less than 100000
-                       try
-                       {
-                               int intValue = Integer.parseInt(inValue);
-                               return (intValue > 0 && intValue < 100000);
-                       }
-                       catch (NumberFormatException nfe) {}
-                       return false;
-               }
-       }
-
-
-       /**
-        * Check whether the given String looks like a waypoint name
-        * @param inValue value from file
-        * @param inIsHeader true if this is a header line, false for data
-        * @return true if it could be a name
-        */
-       private static boolean fieldLooksLikeName(String inValue, boolean inIsHeader)
-       {
-               if (inValue == null || inValue.equals("")) {return false;}
-               if (inIsHeader)
-               {
-                       // This is a header line so look for english or local text
-                       String upperValue = inValue.toUpperCase();
-                       return (upperValue.equals("NAME")
-                               || upperValue.equals("LABEL")
-                               || upperValue.equals(I18nManager.getText("fieldname.waypointname").toUpperCase()));
-               }
-               else
-               {
-                       // Look for at least two letters in it
-                       int numLetters = 0;
-                       for (int i=0; i<inValue.length(); i++)
-                       {
-                               char currChar = inValue.charAt(i);
-                               if (Character.isLetter(currChar)) {
-                                       numLetters++;
-                               }
-                               // Not interested if it contains ":" or "."
-                               if (currChar == ':' || currChar == '.') {return false;}
-                       }
-                       return numLetters >= 2;
-               }
-       }
-
-       /**
-        * Check whether the given String looks like a timestamp
-        * @param inValue value from file
-        * @param inIsHeader true if this is a header line, false for data
-        * @return true if it could be a timestamp
-        */
-       private static boolean fieldLooksLikeTimestamp(String inValue, boolean inIsHeader)
-       {
-               if (inValue == null || inValue.equals("")) {return false;}
-               if (inIsHeader)
-               {
-                       String upperValue = inValue.toUpperCase();
-                       // This is a header line so look for english or local text
-                       return (upperValue.equals("TIMESTAMP")
-                               || upperValue.equals("TIME")
-                               || upperValue.equals(I18nManager.getText("fieldname.timestamp").toUpperCase()));
-               }
-               else
-               {
-                       // must be at least 7 characters long
-                       if (inValue.length() < 7) {return false;}
-                       TimestampUtc stamp = new TimestampUtc(inValue);
-                       return stamp.isValid();
-               }
-       }
-
-       /**
-        * Check whether the given String looks like a track segment field
-        * @param inValue value from file
-        * @param inIsHeader true if this is a header line, false for data
-        * @return true if it could be a track segment
-        */
-       private static boolean fieldLooksLikeSegment(String inValue, boolean inIsHeader)
-       {
-               if (inValue == null || inValue.equals("")) {return false;}
-               if (inIsHeader)
-               {
-                       String upperValue = inValue.toUpperCase();
-                       // This is a header line so look for english or local text
-                       return upperValue.equals("SEGMENT")
-                               || upperValue.equals(I18nManager.getText("fieldname.newsegment").toUpperCase());
-               }
-               else
-               {
-                       // can't reliably identify it just using the value
-                       return false;
-               }
-       }
-
-       /**
-        * Check whether the given String looks like a waypoint type
-        * @param inValue value from file
-        * @param inIsHeader true if this is a header line, false for data
-        * @return true if it could be a waypoint type
-        */
-       private static boolean fieldLooksLikeWaypointType(String inValue, boolean inIsHeader)
-       {
-               if (inValue == null || inValue.equals("")) {return false;}
-               if (inIsHeader)
-               {
-                       String upperValue = inValue.toUpperCase();
-                       // This is a header line so look for english or local text
-                       return (upperValue.equals("TYPE")
-                               || upperValue.equals(I18nManager.getText("fieldname.waypointtype").toUpperCase()));
-               }
-               else
-               {
-                       // can't reliably identify it just using the value
-                       return false;
-               }
-       }
-}