/alaspatial/src/main/java/org/ala/spatial/analysis/index/ValueCorrection.java
Java | 295 lines | 172 code | 35 blank | 88 comment | 54 complexity | f812e6e940ceadef26dc882937d69160 MD5 | raw file
1/* 2 * To change this template, choose Tools | Templates 3 * and open the template in the editor. 4 */ 5package org.ala.spatial.analysis.index; 6 7import java.io.BufferedReader; 8import java.io.FileReader; 9 10/** 11 * Some value correction while parsing strings. 12 * 13 * Permitted units: 14 * mm, cm, km 15 * 16 * Permitted types (in m): 17 * depth, >= 0 18 * altitude, <= 10,000,000 19 * year, > 1600 and <= current 20 * distance, >= 0 and <= 20,000,000 21 * 22 * If invalid value, default to Double.NaN, Float.NaN, Integer.MIN_VALUE. 23 * 24 * @author Adam 25 */ 26public class ValueCorrection { 27 28 final static String[] unitsList = {"mm", "cm", "m", "km"}; 29 final static double[] unitsListScale = {0.001, 0.01, 1, 1000}; 30 final static String[] typesList = {"depth", "altitude", "year", "distance"}; 31 final static double[] typesListMin = {0, Double.NEGATIVE_INFINITY, 1000, 0}; 32 final static double[] typesListMax = {Double.POSITIVE_INFINITY, 10000000, java.util.Calendar.getInstance().get(java.util.Calendar.YEAR), Double.POSITIVE_INFINITY}; 33 34 static public int correctToInt(String targetUnits, String validationType, String stringValue) { 35 int i = scaleInt(targetUnits, stringValue); 36 i = correct(i, validationType); 37 return i; 38 } 39 40 static public double correctToDouble(String targetUnits, String validationType, String stringValue) { 41 double d = scaleDouble(targetUnits, stringValue); 42 d = correct(d, validationType); 43 return d; 44 } 45 46 /** 47 * Attempt to read an Integer to the target units. 48 * 49 * test for < # 50 * test for < # units 51 * test for # - # 52 * test for # units - # 53 * test for # units - # units 54 * test for # - # units 55 * 56 * @param targetUnits 57 * @param validationType 58 * @param stringValue 59 * @return 60 */ 61 static int scaleInt(String targetUnits, String stringValue) { 62 int vi = Integer.MIN_VALUE; 63 64 //test zero length 65 if (stringValue.length() == 0) { 66 return vi; 67 } 68 69 //attempt parse 70 try { 71 return Integer.parseInt(stringValue); 72 } catch (Exception e) { 73 } 74 75 stringValue = clean(stringValue); 76 77 //test for 'units' at end 78 int unitsPos = getUnitsPos(stringValue); 79 double multiplier = getUnitsMultiplier(unitsPos, targetUnits); 80 81 //fix stringValue for unitsPos >= 0 82 if (unitsPos >= 0) { 83 stringValue = stringValue.substring(0, stringValue.length() - unitsList[unitsPos].length()); 84 } 85 86 if (stringValue.length() > 0 && stringValue.charAt(0) == '<') { 87 //test for < # 88 //test for < # units 89 stringValue = stringValue.substring(1); 90 } else { 91 int dashPos = stringValue.indexOf('-', 1); 92 if (dashPos > 0) { 93 //test for # - # 94 //test for # units - # 95 //test for # units - # units 96 //test for # - # units 97 stringValue = stringValue.substring(dashPos + 1); 98 } 99 } 100 101 //parse remaining stringValue as int and apply multiplier 102 try { 103 vi = (int) (Integer.parseInt(stringValue) * multiplier); 104 } catch (Exception e) { 105 } 106 107 //failed 2nd parse as int, try as double and apply multiplier 108 if (vi == Integer.MIN_VALUE) { 109 try { 110 vi = (int) (Double.parseDouble(stringValue) * multiplier); 111 } catch (Exception e) { 112 } 113 } 114 115 return vi; 116 } 117 118 /** 119 * Attempt to read an Integer to the target units. 120 * 121 * test for < # 122 * test for < # units 123 * test for # - # 124 * test for # units - # 125 * test for # units - # units 126 * test for # - # units 127 * 128 * @param targetUnits 129 * @param validationType 130 * @param stringValue 131 * @return 132 */ 133 static double scaleDouble(String targetUnits, String stringValue) { 134 double vd = Double.NaN; 135 136 //test zero length 137 if (stringValue.length() == 0) { 138 return vd; 139 } 140 141 //attempt parse 142 try { 143 return Double.parseDouble(stringValue); 144 } catch (Exception e) { 145 } 146 147 stringValue = clean(stringValue); 148 149 //test for 'units' at end 150 int unitsPos = getUnitsPos(stringValue); 151 double multiplier = getUnitsMultiplier(unitsPos, targetUnits); 152 153 //fix stringValue for unitsPos >= 0 154 if (unitsPos >= 0) { 155 stringValue = stringValue.substring(0, stringValue.length() - unitsList[unitsPos].length()); 156 } 157 158 if (stringValue.length() > 0 && stringValue.charAt(0) == '<') { 159 //test for < # 160 //test for < # units 161 stringValue = stringValue.substring(1); 162 } else { 163 int dashPos = stringValue.indexOf('-', 1); 164 if (dashPos > 0) { 165 //test for # - # 166 //test for # units - # 167 //test for # units - # units 168 //test for # - # units 169 stringValue = stringValue.substring(dashPos + 1); 170 } 171 } 172 173 //parse remaining stringValue as double and apply multiplier 174 try { 175 vd = Double.parseDouble(stringValue) * multiplier; 176 } catch (Exception e) { 177 } 178 179 return vd; 180 } 181 182 private static String clean(String value) { 183 //remove spaces 184 value = value.replace(" ", ""); 185 186 //remove trailing non-unit or number characters 187 int i; 188 boolean remove = true; 189 while (remove && value.length() > 0) { 190 char end = value.charAt(value.length() - 1); 191 if (end <= '9' && end >= '0') { 192 break; 193 } else { 194// remove = true; 195// for(i=0;i<unitsList.length;i++) { 196// if(end == unitsList[i].charAt(unitsList[i].length()-1)) { 197// remove = false; 198// break; 199// } 200// } 201// if(remove) { 202// value = value.substring(0, value.length() - 1); 203// } 204 205 //only permit removal of '.' 206 if (end == '.') { 207 value = value.substring(0, value.length() - 1); 208 remove = true; 209 } else { 210 remove = false; 211 } 212 } 213 } 214 215 return value.trim().toLowerCase(); 216 } 217 218 private static int getUnitsPos(String stringValue) { 219 int pos = -1; 220 if (stringValue.length() > 0) { 221 for (int i = 0; i < unitsList.length; i++) { 222 if (stringValue.endsWith(unitsList[i])) { 223 char c = stringValue.charAt(stringValue.length() - unitsList[i].length() - 1); 224 if (c <= '9' && c >= '0') { 225 pos = i; 226 break; 227 } 228 } 229 } 230 } 231 return pos; 232 } 233 234 private static double getUnitsMultiplier(int unitsPos, String targetUnits) { 235 if (unitsPos < 0 || targetUnits == null) { 236 return 1; 237 } 238 double multiplier = 1; 239 for (int i = 0; i < unitsList.length; i++) { 240 if (targetUnits.equals(unitsList[i])) { 241 multiplier = unitsListScale[unitsPos] / unitsListScale[i]; 242 } 243 } 244 return multiplier; 245 } 246 247 public static void main(String[] args) { 248 String filename = "d:\\list.csv"; 249 250 try { 251 BufferedReader r = new BufferedReader(new FileReader(filename)); 252 String s; 253 System.out.println("original value,corrected double,corrected int"); 254 while ((s = r.readLine()) != null) { 255 double d = correctToDouble("m", "distance", s); 256 int i = correctToInt("m", "distance", s); 257 258 System.out.println(s + "," + ((Double.isNaN(d)) ? "" : d) + "," + ((i == Integer.MIN_VALUE) ? "" : i)); 259 } 260 r.close(); 261 } catch (Exception e) { 262 e.printStackTrace(); 263 } 264 } 265 266 private static int correct(int v, String validationType) { 267 if (validationType != null && v != Integer.MIN_VALUE) { 268 for (int i = 0; i < typesList.length; i++) { 269 if (typesList[i].equals(validationType)) { 270 //test 271 if (v < typesListMin[i] || v > typesListMax[i]) { 272 v = Integer.MIN_VALUE; 273 } 274 break; 275 } 276 } 277 } 278 return v; 279 } 280 281 private static double correct(double v, String validationType) { 282 if (validationType != null && !Double.isNaN(v)) { 283 for (int i = 0; i < typesList.length; i++) { 284 if (typesList[i].equals(validationType)) { 285 //test 286 if (v < typesListMin[i] || v > typesListMax[i]) { 287 v = Double.NaN; 288 } 289 break; 290 } 291 } 292 } 293 return v; 294 } 295}