package org.openstreetmap.josm.plugins.graphview.core.util;
import java.awt.Color;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
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 final Float parseOsmDecimal(String value, boolean allowNegative) {
/* positive integer */
try {
int weight = Integer.parseInt(value);
if (weight >= 0 || allowNegative) {
return (float)weight;
}
} catch (NumberFormatException 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 {
boolean negative = stringBeforePoint.startsWith("-");
float beforePoint = Integer.parseInt(stringBeforePoint);
float afterPoint = Integer.parseInt(stringAfterPoint);
double result = Math.abs(beforePoint)
+ Math.pow(10, -stringAfterPoint.length()) * afterPoint;
if (negative) { result = - result; }
if (result >= 0 || allowNegative) {
return (float)result;
}
} catch (NumberFormatException 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 final 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) {}
}
/* 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) {}
}
/* 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 final 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) {}
}
/* 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 final Float parseIncline(String value) {
Matcher inclineMatcher = INCLINE_PATTERN.matcher(value);
if (inclineMatcher.matches()) {
String inclineString = inclineMatcher.group(1);
return parseOsmDecimal(inclineString, true);
}
return null;
}
/**
* parses an angular value as given for the "direction" key.
*
* @return angle in degrees measured from north, range [0, 360[;
* null if value had syntax errors
*/
public static final Float parseAngle(String value) {
/* try numeric angle */
Float measure = parseOsmDecimal(value, false);
if (measure != null) {
return measure % 360;
}
/* try cardinal directions (represented by letters) */
if ("N" .equals(value)) { return 0.0f; }
if ("NNE".equals(value)) { return 22.5f; }
if ("NE" .equals(value)) { return 45.0f; }
if ("ENE".equals(value)) { return 67.5f; }
if ("E" .equals(value)) { return 90.0f; }
if ("ESE".equals(value)) { return 112.5f; }
if ("SE" .equals(value)) { return 135.0f; }
if ("SSE".equals(value)) { return 157.5f; }
if ("S" .equals(value)) { return 180.0f; }
if ("SSW".equals(value)) { return 202.5f; }
if ("SW" .equals(value)) { return 225.0f; }
if ("WSW".equals(value)) { return 247.5f; }
if ("W" .equals(value)) { return 270.0f; }
if ("WNW".equals(value)) { return 292.5f; }
if ("NW" .equals(value)) { return 315.0f; }
if ("NNW".equals(value)) { return 337.5f; }
return null;
}
/**
* parses an hexadecimal color value
*
* @return color; null if value had syntax errors
*/
public static final Color parseColor(String value) {
try {
return Color.decode(value);
} catch (NumberFormatException e) {
return null;
}
}
}