PageRenderTime 67ms CodeModel.GetById 19ms app.highlight 43ms RepoModel.GetById 1ms app.codeStats 0ms

/alaspatial/src/main/java/org/ala/spatial/analysis/index/ValueCorrection.java

http://alageospatialportal.googlecode.com/
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}