X-Git-Url: http://gitweb.fperrin.net/?p=GpsPrune.git;a=blobdiff_plain;f=src%2Ftim%2Fprune%2Fload%2FFieldGuesser.java;fp=src%2Ftim%2Fprune%2Fload%2FFieldGuesser.java;h=970926ba14bcdf9d22ece3cbc6bac2d45846efdc;hp=0000000000000000000000000000000000000000;hb=ce6f2161b8596f7018d6a76bff79bc9e571f35fd;hpb=2d8cb72e84d5cc1089ce77baf1e34ea3ea2f8465 diff --git a/src/tim/prune/load/FieldGuesser.java b/src/tim/prune/load/FieldGuesser.java new file mode 100644 index 0000000..970926b --- /dev/null +++ b/src/tim/prune/load/FieldGuesser.java @@ -0,0 +1,370 @@ +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= '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 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 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= 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; + } + } +}