// License: GPL. For details, see LICENSE file. package org.openstreetmap.josm.plugins.graphview.core.util; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.openstreetmap.josm.Main; public final class ValueStringParser { /** prevents instantiation */ private ValueStringParser() { } /** pattern that splits into a part before and after a decimal point */ private static final Pattern DEC_POINT_PATTERN = Pattern.compile("^(\\-?\\d+)\\.(\\d+)$"); public static Float parseOsmDecimal(String value, boolean allowNegative) { /* positive integer */ try { int weight = Integer.parseInt(value); if (weight >= 0 || allowNegative) { return (float) weight; } } catch (NumberFormatException nfe) { Main.trace(nfe); } /* positive number with decimal point */ Matcher matcher = DEC_POINT_PATTERN.matcher(value); if (matcher.matches()) { String stringBeforePoint = matcher.group(1); String stringAfterPoint = matcher.group(2); if (stringBeforePoint.length() > 0 || stringAfterPoint.length() > 0) { try { float beforePoint = Integer.parseInt(stringBeforePoint); float afterPoint = Integer.parseInt(stringAfterPoint); double result = Math.signum(beforePoint) * (Math.abs(beforePoint) + Math.pow(10, -stringAfterPoint.length()) * afterPoint); if (result >= 0 || allowNegative) { return (float) result; } } catch (NumberFormatException nfe) { Main.trace(nfe); } } } return null; } private static final Pattern KMH_PATTERN = Pattern.compile("^(\\d+)\\s*km/h$"); private static final Pattern MPH_PATTERN = Pattern.compile("^(\\d+)\\s*mph$"); private static final float KM_PER_MILE = 1.609344f; /** * parses a speed value given e.g. for the "maxspeed" key. * * @return speed in km/h; null if value had syntax errors */ public static Float parseSpeed(String value) { /* try numeric speed (implied km/h) */ Float speed = parseOsmDecimal(value, false); if (speed != null) { return speed; } /* try km/h speed */ Matcher kmhMatcher = KMH_PATTERN.matcher(value); if (kmhMatcher.matches()) { String kmhString = kmhMatcher.group(1); try { return (float) Integer.parseInt(kmhString); } catch (NumberFormatException nfe) { Main.trace(nfe); } } /* try mph speed */ Matcher mphMatcher = MPH_PATTERN.matcher(value); if (mphMatcher.matches()) { String mphString = mphMatcher.group(1); try { int mph = Integer.parseInt(mphString); return KM_PER_MILE * mph; } catch (NumberFormatException nfe) { Main.trace(nfe); } } /* all possibilities failed */ return null; } private static final Pattern M_PATTERN = Pattern.compile("^([\\d\\.]+)\\s*m$"); private static final Pattern KM_PATTERN = Pattern.compile("^([\\d\\.]+)\\s*km$"); private static final Pattern MI_PATTERN = Pattern.compile("^([\\d\\.]+)\\s*mi$"); private static final Pattern FEET_INCHES_PATTERN = Pattern.compile("^([\\d]+)'\\s*([\\d]+)\""); private static final double M_PER_MI = 1609.344; private static final double M_PER_INCH = 0.0254f; /** * parses a measure value given e.g. for the "width" or "length" key. * * @return measure in m; null if value had syntax errors */ public static Float parseMeasure(String value) { /* try numeric measure (implied m) */ Float measure = parseOsmDecimal(value, false); if (measure != null) { return measure; } /* try m measure */ Matcher mMatcher = M_PATTERN.matcher(value); if (mMatcher.matches()) { String mString = mMatcher.group(1); return parseOsmDecimal(mString, false); } /* try km measure */ Matcher kmMatcher = KM_PATTERN.matcher(value); if (kmMatcher.matches()) { String kmString = kmMatcher.group(1); float km = parseOsmDecimal(kmString, false); return 1000 * km; } /* try mi measure */ Matcher miMatcher = MI_PATTERN.matcher(value); if (miMatcher.matches()) { String miString = miMatcher.group(1); float mi = parseOsmDecimal(miString, false); return (float) (M_PER_MI * mi); } /* try feet/inches measure */ Matcher feetInchesMatcher = FEET_INCHES_PATTERN.matcher(value); if (feetInchesMatcher.matches()) { String feetString = feetInchesMatcher.group(1); String inchesString = feetInchesMatcher.group(2); try { int feet = Integer.parseInt(feetString); int inches = Integer.parseInt(inchesString); if (feet >= 0 && inches >= 0 && inches < 12) { return (float) (M_PER_INCH * (12 * feet + inches)); } } catch (NumberFormatException nfe) { Main.trace(nfe); } } /* all possibilities failed */ return null; } private static final Pattern T_PATTERN = Pattern.compile("^([\\d\\.]+)\\s*t$"); /** * parses a weight value given e.g. for the "maxweight" or "maxaxleload" key. * * @return weight in t; null if value had syntax errors */ public static Float parseWeight(String value) { /* try numeric weight (implied t) */ Float weight = parseOsmDecimal(value, false); if (weight != null) { return weight; } /* try t weight */ Matcher tMatcher = T_PATTERN.matcher(value); if (tMatcher.matches()) { String tString = tMatcher.group(1); return parseOsmDecimal(tString, false); } /* all possibilities failed */ return null; } private static final Pattern INCLINE_PATTERN = Pattern.compile("^(\\-?\\d+(?:\\.\\d+)?)\\s*%$"); /** * parses an incline value as given for the "incline" key. * * @return incline in percents; null if value had syntax errors */ public static Float parseIncline(String value) { Matcher inclineMatcher = INCLINE_PATTERN.matcher(value); if (inclineMatcher.matches()) { String inclineString = inclineMatcher.group(1); return parseOsmDecimal(inclineString, true); } return null; } }