/*
*
* Copyright 2009-2013 The MITRE Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* **************************************************************************
* NOTICE
* This software was produced for the U. S. Government under Contract No.
* W15P7T-12-C-F600, and is subject to the Rights in Noncommercial Computer
* Software and Noncommercial Computer Software Documentation Clause
* 252.227-7014 (JUN 1995)
*
* (c) 2012 The MITRE Corporation. All Rights Reserved.
* **************************************************************************
*/
package org.opensextant.regex.geo;
import java.util.HashMap;
import java.util.Map;
/**
* Ordinate represents all the various fields a WGS84 cartesian coordinate could
* have. degree/minute/second, as well as fractional minutes and fractional
* seconds. * Patterns may have symbols which further indicate if a pattern is a
* literal decimal number (e.g., 33-44, 33.44, 33.444, 33-4444) of if the
* numbers are in minutes/seconds units (33:44). *
*
* @author ubaldino
*/
public final class OrdinateParser {
/**
* Log object private static final Logger LOGGER =
* LoggerFactory.getLogger(Ordinate.class); the two type of Ordinates
*/
public enum ORDINATETYPE {
DD, DMS
}
/** The two axes. */
public enum AXIS {
LATITUDE, LONGITUDE
}
public static final int LAT_MAX = 90;
public static final int LON_MAX = 180;
/**
* Public static final String[] COORDINATE_SYMBOLS = {"��", "��", "'", "\"",
* ":", "lat", "lon", "geo", "coord", "deg"};
*/
public static final String WEST = "W";
public static final String SOUTH = "S";
public static final String NORTH = "N";
public static final String EAST = "E";
public static final String NEGATIVE = "-";
public static final String POSITIVE = "+";
/** Public static final int NO_HEMISPHERE_VALUE = -0x10;. */
public static final int POS_HEMI = 1;
public static final int NEG_HEMI = -1;
public static final int NO_HEMI = 0;
public static final Map<String, Integer> HEMI_MAP = new HashMap<String, Integer>();
static {
HEMI_MAP.put(WEST, NEG_HEMI);
HEMI_MAP.put(SOUTH, NEG_HEMI);
HEMI_MAP.put(EAST, POS_HEMI);
HEMI_MAP.put(NORTH, POS_HEMI);
HEMI_MAP.put(NEGATIVE, NEG_HEMI);
HEMI_MAP.put(POSITIVE, POS_HEMI);
}
private OrdinateParser() {
}
public static Ordinate parse(Map<String, String> elements, AXIS ax, OrdinateParser.ORDINATETYPE type) {
Ordinate ord = new Ordinate();
ord.setType(type);
ord.setAxis(ax);
if (ax == AXIS.LATITUDE) {
parseLatitude(ord, elements);
parseLatitudeHemisphere(ord, elements);
} else {
parseLongitude(ord, elements);
parseLongitudeHemisphere(ord, elements);
}
if (ord.isValid()) {
return ord;
} else {
return null;
}
}
private static boolean parseLatitude(Ordinate ord, Map<String, String> elements) {
// DEGREES
Double degrees = null;
Integer deg = getIntValue(elements.get("degLat"));
Integer deg2 = getIntValue(elements.get("dmsDegLat"));
Float deg3 = getDecimalValue(elements.get("decDegLat"));
if (deg != null) {
degrees = 1.0 * deg;
} else if (deg2 != null) {
degrees = 1.0 * deg2;
} else if (deg3 != null) {
degrees = 1.0 * deg3;
} else {
return false;
}
// MINUTES
Double minutes = null;
Integer min = getIntValue(elements.get("minLat"));
Integer min2 = getIntValue(elements.get("dmsMinLat"));
Float min3 = getDecimalValue(elements.get("decMinLat"));
Float min3dash = getDecimalValue(elements.get("decMinLat3"));
if (min != null) {
minutes = 1.0 * min;
} else if (min2 != null) {
minutes = 1.0 * min2;
} else if (min3 != null) {
minutes = 1.0 * min3;
} else if (min3dash != null) {
minutes = 1.0 * min3dash;
}
Float minFract = getFractionValue(elements.get("fractMinLat"));
Float minFract2 = getFractionValue(elements.get("fractMinLat3")); // variation
// 2, is a 3-digit orlongerfraction
if (minFract != null) {
minutes += minFract.floatValue();
} else if (minFract2 != null) {
minutes += minFract2.floatValue();
}
// SECONDS
Double seconds = null;
Integer sec = getIntValue(elements.get("secLat"));
Integer sec2 = getIntValue(elements.get("dmsSecLat"));
if (sec != null) {
seconds = 1.0 * sec;
} else if (sec2 != null) {
seconds = 1.0 * sec2;
}
Float fsec = getFractionValue(elements.get("fractSecLat"));
Float fsec2 = getFractionValue(elements.get("fractSecLatOpt"));
if (fsec != null) {
seconds += fsec.floatValue();
} else if (fsec2 != null) {
seconds += fsec2.floatValue();
}
if (degrees != null) {
ord.setDegrees(degrees);
if (minutes != null) {
ord.setMinutes(minutes);
if (seconds != null) {
ord.setSeconds(seconds);
}
}
}
return true;
}
/**
* This is a copy of the logic for digest_latitude_match; All I replace is
* "Lat" with "Lon".
*
* @return
*/
private static boolean parseLongitude(Ordinate ord, Map<String, String> elements) {
// DEGREES
Double degrees = null;
Integer deg = getIntValue(elements.get("degLon"));
Integer deg2 = getIntValue(elements.get("dmsDegLon"));
Float deg3 = getDecimalValue(elements.get("decDegLon"));
if (deg != null) {
degrees = 1.0 * deg;
} else if (deg2 != null) {
degrees = 1.0 * deg2;
} else if (deg3 != null) {
degrees = 1.0 * deg3;
} else {
return false;
}
// MINUTES
Double minutes = null;
Integer min = getIntValue(elements.get("minLon"));
Integer min2 = getIntValue(elements.get("dmsMinLon"));
Float min3 = getDecimalValue(elements.get("decMinLon"));
Float min3dash = getDecimalValue(elements.get("decMinLon3"));
if (min != null) {
minutes = 1.0 * min;
} else if (min2 != null) {
minutes = 1.0 * min2;
} else if (min3 != null) {
minutes = 1.0 * min3;
} else if (min3dash != null) {
minutes = 1.0 * min3dash;
}
Float minFract = getFractionValue(elements.get("fractMinLon"));
Float minFract2 = getFractionValue(elements.get("fractMinLon3")); // variation
// 2, is
// a
// 3-digit
// or
// longer
// fraction
if (minFract != null) {
minutes += minFract.floatValue();
} else if (minFract2 != null) {
minutes += minFract2.floatValue();
}
// SECONDS
Double seconds = null;
Integer sec = getIntValue(elements.get("secLon"));
Integer sec2 = getIntValue(elements.get("dmsSecLon"));
if (sec != null) {
seconds = 1.0 * sec;
} else if (sec2 != null) {
seconds = 1.0 * sec2;
}
Float fsec = getFractionValue(elements.get("fractSecLon"));
Float fsec2 = getFractionValue(elements.get("fractSecLonOpt"));
if (fsec != null) {
seconds += fsec.floatValue();
} else if (fsec2 != null) {
seconds += fsec2.floatValue();
}
if (degrees != null) {
ord.setDegrees(degrees);
if (minutes != null) {
ord.setMinutes(minutes);
if (seconds != null) {
ord.setSeconds(seconds);
}
}
}
return true;
}
private static void parseLatitudeHemisphere(Ordinate ord, java.util.Map<String, String> elements) {
String hemiLat = elements.get("hemiLat");
String hemiSignLat = elements.get("hemiLatSign");
String hemiLatPre = elements.get("hemiLatPre");
// default to psoitive
int z = POS_HEMI;
if (hemiLatPre != null) {
z = getHemisphereSign(hemiLatPre);
} else if (hemiLat != null) {
z = getHemisphereSign(hemiLat);
} else if (hemiSignLat != null) {
z = getHemisphereSign(hemiSignLat);
}
ord.setHemi(z);
return;
}
private static void parseLongitudeHemisphere(Ordinate ord, java.util.Map<String, String> elements) {
String hemiLon = elements.get("hemiLon");
String hemiSignLon = elements.get("hemiLonSign");
String hemiLonPre = elements.get("hemiLonPre");
int z = POS_HEMI;
if (hemiLonPre != null) {
z = getHemisphereSign(hemiLonPre);
} else if (hemiLon != null) {
z = getHemisphereSign(hemiLon);
} else if (hemiSignLon != null) {
z = getHemisphereSign(hemiSignLon);
}
ord.setHemi(z);
return;
}
private static Integer getIntValue(String val) {
if (val != null) {
return Integer.valueOf(val);
}
return null;
}
/**
* Convert numbers like "8.888" or "8-888" to decimal numbers.
*/
private static Float getDecimalValue(String val) {
if (val == null) {
return null;
}
if (val.contains("-")) {
// Log this situation
Float.valueOf(val.replaceFirst("-", "."));
}
return Float.valueOf(val);
}
private static Float getFractionValue(String val) {
if (val == null) {
return null;
}
if (val.startsWith("-")) {
// Log this situation
Float.valueOf(val.replaceFirst("-", "."));
} else if (!val.startsWith(".")) {
// already has a decimal point?
Float.valueOf("." + val);
}
return Float.parseFloat(val);
}
public static int getHemisphereSign(String val) {
if (val == null) {
return NO_HEMI;
}
Integer s = HEMI_MAP.get(val.trim().toUpperCase());
if (s != null) {
return s.intValue();
}
return NO_HEMI;
}
}