package com.esri.geoevent.solutions.processor.unitconversion;
import java.io.IOException;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.esri.ges.core.component.ComponentException;
import com.esri.ges.core.geoevent.GeoEvent;
import com.esri.ges.manager.geoeventdefinition.GeoEventDefinitionManager;
import com.esri.ges.messaging.Messaging;
import com.esri.ges.processor.GeoEventProcessorBase;
import com.esri.ges.processor.GeoEventProcessorDefinition;
public class UnitConversionProcessor extends GeoEventProcessorBase {
HashMap<String, Double> convertDistance = new HashMap<String, Double>();
HashMap<String, Double> convertTime = new HashMap<String, Double>();
HashMap<String, String> timeUnits = new HashMap<String, String>();
HashMap<String, String> distanceUnits = new HashMap<String, String>();
HashMap<String, String> freqUnits = new HashMap<String, String>();
HashMap<String, Double> convertMetric = new HashMap<String, Double>();
Messaging messaging;
GeoEventDefinitionManager manager;
private String inputv;
private String inputa;
private String inputf;
private String vtag;
private String ftag;
private String atag;
private String vout;
private String vin;
private String aout;
private String ain;
private String fout;
private String fin;
private String altOut;
private String dOut;
private String tOut;
private String freqOut;
private String altIn;
private String dIn;
private String tIn;
private String freqIn;
private static final Log LOG = LogFactory
.getLog(UnitConversionProcessor.class);
//public TagManager tm;
public UnitConversionProcessor(GeoEventProcessorDefinition definition,
GeoEventDefinitionManager m, Messaging msg)
throws ComponentException {
super(definition);
manager = m;
messaging = msg;
//tm = t;
geoEventMutator = true;
convertDistance.put("km-km", 1.0);
convertDistance.put("km-hm", 10.0);
convertDistance.put("km-nm", 0.539957);
convertDistance.put("km-ft", 3280.84);
convertDistance.put("km-mi", 0.621371);
convertDistance.put("km-m", 1000.0);
convertDistance.put("hm-km", 0.1);
convertDistance.put("hm-hm", 1.0);
convertDistance.put("hm-nm", 0.0539957);
convertDistance.put("hm-ft", 328.084);
convertDistance.put("hm-mi", 0.0621371);
convertDistance.put("hm-m", 100.0);
convertDistance.put("nm-km", 1.852);
convertDistance.put("nm-hm", 18.52);
convertDistance.put("nm-nm", 1.0);
convertDistance.put("nm-ft", 6076.12);
convertDistance.put("nm-mi", 1.15078);
convertDistance.put("nm-m", 1852.0);
convertDistance.put("ft-km", 0.0003048);
convertDistance.put("ft-hm", 0.003048);
convertDistance.put("ft-nm", 0.000164579);
convertDistance.put("ft-ft", 1.0);
convertDistance.put("ft-mi", 0.000189394);
convertDistance.put("ft-m", 0.3048);
convertDistance.put("mi-km", 1.0);
convertDistance.put("mi-hm", 10.0);
convertDistance.put("mi-nm", 0.539957);
convertDistance.put("mi-ft", 5280.0);
convertDistance.put("mi-mi", 1.0);
convertDistance.put("mi-m", 1609.34);
convertDistance.put("m-km", 0.001);
convertDistance.put("m-hm", 0.01);
convertDistance.put("m-nm", 0.000539957);
convertDistance.put("m-ft", 3.28084);
convertDistance.put("m-mi", 0.000621371);
convertDistance.put("m-m", 1.0);
convertTime.put("sec-sec", 1.0);
convertTime.put("sec-min", 0.0166667);
convertTime.put("sec-hr", 0.000277778);
convertTime.put("min-sec", 60.0);
convertTime.put("min-min", 1.0);
convertTime.put("min-hr", 0.0166667);
convertTime.put("hr-sec", 3600.0);
convertTime.put("hr-min", 60.0);
convertTime.put("hr-hr", 1.0);
convertMetric.put("giga", 1000000000.0);
convertMetric.put("mega", 1000000.0);
convertMetric.put("kilo", 1000.0);
convertMetric.put("none", 1.0);
convertMetric.put("hecto", 100.0);
timeUnits.put("Second", "sec");
timeUnits.put("Minute", "min");
timeUnits.put("Hour", "hr");
distanceUnits.put("Meters", "m");
distanceUnits.put("Kilometers", "km");
distanceUnits.put("Hectometers", "hm");
distanceUnits.put("Miles", "mi");
distanceUnits.put("Nautical Miles", "nm");
distanceUnits.put("Feet", "ft");
freqUnits.put("GHz", "giga");
freqUnits.put("MHz", "mega");
freqUnits.put("KHz", "kilo");
freqUnits.put("Hz", "none");
}
/*public void setTagManager(TagManager t)
{
tm = t;
}*/
private Object ConvertBack(Object o, Double val)
{
Object out = null;
if(o instanceof String)
{
out = val.toString();
}
else if(o instanceof Integer)
{
out = (Integer)val.intValue();
}
else if(o instanceof Double)
{
out = val;
}
return out;
}
@Override
public void afterPropertiesSet()
{
inputv = properties.get("input-v").getValueAsString();
inputa = properties.get("input-a").getValueAsString();
inputf = properties.get("input-f").getValueAsString();
vtag = null;
ftag = null;
atag = null;
if (inputv.equals("Field")) {
vtag = properties.get("velocity-manual").getValueAsString();
}
if (inputa.equals("Field")) {
atag = properties.get("alt-manual").getValueAsString();
}
if (inputf.equals("Field")) {
ftag = properties.get("freq-manual").getValueAsString();
}
vout = properties.get("vout").getValueAsString();
vin = properties.get("vin").getValueAsString();
aout = properties.get("altout").getValueAsString();
ain = properties.get("altin").getValueAsString();
fout = properties.get("freqout").getValueAsString();
fin = properties.get("freqin").getValueAsString();
}
@Override
public GeoEvent process(GeoEvent evt) throws Exception {
try {
// Integer validation;
String tag;
Double v = null;
if (!StringIsNullOrEmpty(vtag)) {
tag = vtag.toString();
Boolean isEmpty = false;
if (evt.getGeoEventDefinition().getFieldDefinition(tag) != null) {
Object velocity = evt.getField(tag);
if (velocity instanceof String) {
if(StringIsNullOrEmpty((String)velocity))
{
isEmpty=true;
}
}
if (velocity == null || isEmpty) {
evt.setField(tag, null);
} else {
parseVelocityOut(vout);
parseVelocityIn(vin);
try {
v = calculateVelocity(velocity);
Object v_out = ConvertBack(velocity, v);
evt.setField(tag, v_out);
} catch (Exception e) {
LOG.error("Unable to parse", e);
evt.setField(tag, null);
}
}
}
// vFld = new DefaultFieldDefinition(vFldName,
// FieldType.Double);
}
Double a = null;
if (!StringIsNullOrEmpty(atag)) {
tag = atag.toString();
Boolean isEmpty = false;
if (evt.getGeoEventDefinition().getFieldDefinition(tag) != null) {
Object alt = evt.getField(tag);
if (alt instanceof String) {
if(StringIsNullOrEmpty((String)alt))
{
isEmpty=true;
}
}
if (alt == null || isEmpty) {
evt.setField(tag, null);
} else {
parseAltOut(aout);
parseAltIn(ain);
try {
a = calculateAltitude(alt);
Object a_out = ConvertBack(alt, a);
evt.setField(tag, a_out);
} catch (Exception e) {
LOG.error("Unable to parse", e);
evt.setField(tag, null);
}
}
}
// aFld = new DefaultFieldDefinition(aFldName,
// FieldType.Double);
}
Double freq = null;
if (!StringIsNullOrEmpty(ftag)) {
tag = ftag.toString();
Boolean isEmpty = false;
if (evt.getGeoEventDefinition().getFieldDefinition(tag) != null) {
Object objFreq = evt.getField(tag);
if (objFreq instanceof String) {
if(StringIsNullOrEmpty((String)objFreq))
{
isEmpty=true;
}
}
if (objFreq == null || isEmpty) {
evt.setField(tag, null);
} else {
parseFreqOut(fout);
parseFreqIn(fin);
try {
freq = calculateFrequency(objFreq);
Object f_out = ConvertBack(objFreq, freq);
evt.setField(tag, f_out);
} catch (Exception e) {
LOG.error("Unable to parse", e);
evt.setField(tag, null);
}
}
}
// fFld = new DefaultFieldDefinition(fFldName,
// FieldType.Double);
}
// GeoEventDefinition geoDef = evt.getGeoEventDefinition();
/*
* String name = geoDef.getName() + "_converted"; GeoEventDefinition
* edOut; if(manager.searchGeoEventDefinition(name, getId())==null)
* { //FieldDefinition[] fDefs = { vFld, aFld, fFld };
* //List<FieldDefinition> fds = Arrays.asList(fDefs);
* List<FieldDefinition> fldDefs = geoDef.getFieldDefinitions();
* List<FieldDefinition> newFldDefs = geoDef.getFieldDefinitions();
* List <String> reduce = new ArrayList<String>();
* for(FieldDefinition f: fldDefs) { String fname = f.getName();
* if(fname.equals(vFldName)) { newFldDefs.add(vFld);
* //reduce.add(fname); } else if (fname.equals(aFldName)) {
* newFldDefs.add(aFld); //reduce.add(fname); } else
* if(fname.equals(fFldName)) { newFldDefs.add(fFld);
* //reduce.add(fname); } else { newFldDefs.add(f); }
*
* } edOut = new DefaultGeoEventDefinition(); edOut.setName(name);
* edOut.setOwner(getId()); edOut.setFieldDefinitions(newFldDefs);
* manager.addGeoEventDefinition(edOut); } else {
* edOut=manager.getGeoEventDefinition(name); }
*
* List<Object> vals = new ArrayList<Object>(); for(FieldDefinition
* fdef: edOut.getFieldDefinitions()) { String fname =
* fdef.getName(); if(fname.equals(vFldName)) { vals.add(v); } else
* if (fname.equals(aFldName)) { vals.add(a); } else
* if(fname.equals(fFldName)) { vals.add(freq); } else {
* vals.add(evt.getField(fname)); } } Object[] newVals =
* vals.toArray(); GeoEventCreator geoEventCreator =
* messaging.createGeoEventCreator(); GeoEvent geOut =
* geoEventCreator.create(edOut.getGuid(), newVals);
*
* for (Map.Entry<GeoEventPropertyName, Object> property : evt
* .getProperties()) { if (!geOut.hasProperty(property.getKey())) {
* geOut.setProperty(property.getKey(), property.getValue()); } }
*/
// return geOut;
return evt;
} catch (Exception e) {
LOG.debug(e.getMessage());
LOG.debug(e.getStackTrace());
throw (e);
}
}
private void parseVelocityIn(String v) {
if (v.equals("Knots")) {
dIn = "nm";
tIn = "hr";
} else {
String[] vel = v.split("/");
String d = vel[0];
String t = vel[1];
dIn = distanceUnits.get(d);
tIn = timeUnits.get(t);
}
}
private void parseAltIn(String a) {
altIn = distanceUnits.get(a);
}
private void parseFreqIn(String f) {
freqIn = freqUnits.get(f);
}
private void parseVelocityOut(String v) {
if (v.equals("Knots")) {
dOut = "nm";
tOut = "hr";
} else {
String[] vel = v.split("/");
String d = vel[0];
String t = vel[1];
dOut = distanceUnits.get(d);
tOut = timeUnits.get(t);
}
}
private void parseAltOut(String a) {
altOut = distanceUnits.get(a);
}
private void parseFreqOut(String f) {
freqOut = freqUnits.get(f);
}
private Double calculateVelocity(Object v) throws Exception {
try {
// String[] vArr = v.split(" ");
int i = -1;
String str_v = null;
Boolean isString = false;
if (v instanceof String) {
str_v = (String) v;
i = str_v.indexOf(" ");
isString = true;
}
Double cv = 0.0;
if (i > -1) {
int l = str_v.length();
Double ov = Double.valueOf(str_v.substring(0, i));
String unit = str_v.substring(i + 1, l);
Double dist = calculateDist(ov, unit);
Double time = calculateTime(unit);
cv = dist / time;
} else {
Double ov = null;
if (isString) {
ov = Double.valueOf(str_v);
} else if (v instanceof Integer) {
ov = ((Integer) v).doubleValue();
} else if (v instanceof Double) {
ov = (Double) v;
} else {
throw (new IOException());
}
Double dist = calculateDist(ov, null);
Double time = calculateTime(null);
cv = dist / time;
}
return cv;
} catch (Exception e) {
LOG.error("error calculating velocity value " + v.toString());
LOG.debug(e.getMessage());
LOG.debug(e.getStackTrace());
throw (e);
}
}
private Double calculateDist(Double d, String unit) throws Exception {
try {
String dKey;
if (StringIsNullOrEmpty(unit)) {
dKey = dIn + "-" + dOut;
} else {
String distUnit = findDistance(unit);
dKey = distUnit + "-" + dOut;
}
double factor = convertDistance.get(dKey);
return d * factor;
} catch (IOException e) {
LOG.error("ioerror calculating velocity value " + unit);
LOG.debug(e.getMessage());
LOG.debug(e.getStackTrace());
throw (e);
} catch (Exception e) {
LOG.error("error calculating distance value " + unit);
LOG.debug(e.getMessage());
LOG.debug(e.getStackTrace());
throw (e);
}
}
private Double calculateTime(String unit) throws Exception {
try {
String tKey;
if (StringIsNullOrEmpty(unit)) {
tKey = tIn + "-" + tOut;
} else {
String tUnit = findTime(unit);
tKey = tUnit + "-" + tOut;
}
return convertTime.get(tKey);
} catch (IOException e) {
LOG.error("ioerror calculating time value "+ unit.toString());
LOG.debug(e.getMessage());
LOG.debug(e.getStackTrace());
throw (e);
} catch (Exception e) {
LOG.error("error calculating time value " + unit.toString());
LOG.debug(e.getMessage());
LOG.debug(e.getStackTrace());
throw (e);
}
}
private Double calculateAltitude(Object a) throws Exception {
try {
int i = -1;
String str_a = null;
Boolean isString = false;
if (a instanceof String) {
str_a = (String) a;
i = str_a.indexOf(" ");
isString = true;
}
Double ca = 0.0;
if (i > -1) {
Double oa = Double.valueOf(str_a.substring(0, i));
int l = str_a.length();
String unit = str_a.substring(i + 1, l);
try {
String altKey;
if (StringIsNullOrEmpty(unit)) {
altKey = altIn + "-" + altOut;
} else {
String dUnit = findDistance(unit);
altKey = dUnit + "-" + altOut;
}
Double factor = convertDistance.get(altKey);
ca = oa * factor;
} catch (IOException e) {
LOG.error("ioerror calculating altitude value " + a.toString());
LOG.debug(e.getMessage());
LOG.debug(e.getStackTrace());
}
} else {
Double oa = null;
if (isString) {
oa = Double.valueOf(str_a);
} else if (a instanceof Integer) {
oa = ((Integer) a).doubleValue();
} else if (a instanceof Double) {
oa = (Double) a;
} else {
throw (new IOException());
}
String altKey = altIn + "-" + altOut;
Double factor = convertDistance.get(altKey);
ca = oa * factor;
}
return ca;
} catch (Exception e) {
LOG.error("error calculating altitude value " + a.toString());
LOG.debug(e.getMessage());
LOG.debug(e.getStackTrace());
throw (e);
}
}
private Double calculateFrequency(Object f) throws Exception {
try {
int i = -1;
String str_f = null;
Boolean isString = false;
if (f instanceof String) {
str_f = (String) f;
i = str_f.indexOf(" ");
isString = true;
}
Double cf = 0.0;
if (i > -1) {
Double of = Double.valueOf(str_f.substring(0, i));
int l = str_f.length();
String unit = str_f.substring(i + 1, l);
String dUnit;
try {
Double from;
if (StringIsNullOrEmpty(unit)) {
from = convertMetric.get(freqIn);
} else {
dUnit = findFrequencyModifier(unit);
from = convertMetric.get(dUnit);
}
Double to = convertMetric.get(freqOut);
Double factor = from / to;
cf = of * factor;
} catch (IOException e) {
LOG.error("ioerror calculating frequency value " + f.toString());
LOG.debug(e.getMessage());
LOG.debug(e.getStackTrace());
throw (e);
}
} else {
Double of = null;
if (isString) {
of = Double.valueOf(str_f);
} else {
if (f instanceof Integer) {
of = ((Integer) f).doubleValue();
} else if (f instanceof Double) {
of = (Double) f;
} else {
throw (new IOException());
}
}
Double from = convertMetric.get(freqIn);
Double to = convertMetric.get(freqOut);
Double factor = from / to;
cf = of * factor;
}
return cf;
} catch (Exception e) {
LOG.error("ioerror calculating frequency value " + f.toString());
LOG.debug(e.getMessage());
LOG.debug(e.getStackTrace());
throw (e);
}
}
private String findTime(String s) throws Exception {
try {
if (s.toLowerCase().equals("kp") || s.toLowerCase().equals("mi")
|| s.toLowerCase().equals("nm")) {
return "hr";
}
String time = "none";
String regex1 = "(pm)|(((m)|(M))((inutes?)|(INUTES?)))|(/m)|(\\\\m)|(MIN)|(min)|(Min)";
Pattern p1 = java.util.regex.Pattern.compile(regex1);
Matcher m1 = p1.matcher(s);
String regex2 = "(PH)|(ph)|(((h)|H))((ours?)|(OURS?))|(/h)|(\\\\h)";
Pattern p2 = java.util.regex.Pattern.compile(regex2);
Matcher m2 = p2.matcher(s);
String regex3 = "(PS)|(ps)|(((s)|S))((econds?)|(ECONDS?))|(/s)|(\\\\s)|(MIS)|(mis)";
Pattern p3 = java.util.regex.Pattern.compile(regex3);
Matcher m3 = p3.matcher(s);
String regex4 = "(k|K)(nots|NOTS)|(k|K)(t|T)";
Pattern p4 = java.util.regex.Pattern.compile(regex4);
Matcher m4 = p4.matcher(s);
if (m1.find()) {
time = "min";
} else if (m2.find()) {
time = "hr";
} else if (m3.find()) {
time = "sec";
} else if (m4.find()) {
time = "hr";
} else {
throw (new IOException("cannot handle time unit " + s));
}
return time;
} catch (Exception e) {
LOG.error("Error parsing time unit " + s);
LOG.debug(e.getMessage());
LOG.debug(e.getStackTrace());
throw (e);
}
}
private String findDistance(String s) throws Exception {
try {
String d = null;
String regex1 = "((M)|(m))((iles?)|(ILES?))|(((m)|(M))((p)|(P))((h)|(H)))|((M|m)/(H|h))|(mi)|(MI)";
Pattern p1 = java.util.regex.Pattern.compile(regex1);
Matcher m1 = p1.matcher(s);
String regex2 = "(NM)|(nmi)|((n)|(N))((autical)|(AUTICAL))";
Pattern p2 = java.util.regex.Pattern.compile(regex2);
Matcher m2 = p2.matcher(s);
String regex3 = "(((f)|(F))((o{2})|(O{2})|(e{2})|(E{2}))((t)|(T)))|(f|F)";
Pattern p3 = java.util.regex.Pattern.compile(regex3);
Matcher m3 = p3.matcher(s);
String regex4 = "(mps)|((m/))|(m|M(eter?|ETER?))";
Pattern p4 = java.util.regex.Pattern.compile(regex4);
Matcher m4 = p4.matcher(s);
String regex5 = "(knots)|(kt)";
Pattern p5 = java.util.regex.Pattern.compile(regex5,
Pattern.CASE_INSENSITIVE);
Matcher m5 = p5.matcher(s);
String regex6 = "k|km";
Pattern p6 = java.util.regex.Pattern.compile(regex6,
Pattern.CASE_INSENSITIVE);
Matcher m6 = p6.matcher(s);
String regex7 = "hm";
Pattern p7 = java.util.regex.Pattern.compile(regex7,
Pattern.CASE_INSENSITIVE);
Matcher m7 = p7.matcher(s);
String regex8 = "min";
Pattern p8 = java.util.regex.Pattern.compile(regex8,
Pattern.CASE_INSENSITIVE);
Matcher m8 = p8.matcher(s);
if (m1.find()) {
if (m6.find()) {
d = "km";
} else if (m7.find()) {
d = "hm";
} else if (m8.find()) {
d = null;
} else {
d = "mi";
}
}
if (d == null) {
if (m2.find()) {
d = "nm";
} else if (m3.find()) {
d = "ft";
} else if (m5.find()) {
d = "nm";
} else if (m6.find()) {
d = "km";
} else if (m4.find()) {
String mod = findMetricModifierDistance(s);
if (mod.equals("kilo")) {
d = "km";
} else if (mod.equals("hecto")) {
d = "hm";
} else {
d = "m";
}
} else {
throw (new IOException("Cannot handle distance unit " + s));
}
}
return d;
} catch (Exception e) {
LOG.error("Error parsing distance unit " + s);
LOG.debug(e.getMessage());
LOG.debug(e.getStackTrace());
throw (e);
}
}
private String findMetricModifierDistance(String s) throws Exception {
try {
String modifier = "none";
String regex1 = "k(ilo)|k";
Pattern p1 = Pattern.compile(regex1, Pattern.CASE_INSENSITIVE);
Matcher m1 = p1.matcher(s);
String regex2 = "h(ecto)|h";
Pattern p2 = Pattern.compile(regex2, Pattern.CASE_INSENSITIVE);
Matcher m2 = p2.matcher(s);
if (m1.find()) {
modifier = "kilo";
} else if (m2.find()) {
modifier = "hecto";
} else {
modifier = "none";
}
return modifier;
} catch (Exception e) {
LOG.error("Error parsing metric modifier " + s);
LOG.debug(e.getMessage());
LOG.debug(e.getStackTrace());
throw (e);
}
}
private String findFrequencyModifier(String s) throws Exception {
try {
String modifier = "none";
String regex1 = "(k([a-ln-z]{3}[^(meter)]))|(k )|(khz)|(k$)";
Pattern p1 = java.util.regex.Pattern.compile(regex1,
Pattern.CASE_INSENSITIVE);
Matcher m1 = p1.matcher(s);
String regex2 = "(M(hz))|(M(Hz))|(M(HZ))|((megahertz)|(MEGAHERTZ))";
Pattern p2 = java.util.regex.Pattern.compile(regex2);
Matcher m2 = p2.matcher(s);
String regex3 = "(g(hz))|(giga(hertz))";
Pattern p3 = java.util.regex.Pattern.compile(regex3,
Pattern.CASE_INSENSITIVE);
Matcher m3 = p3.matcher(s);
String regex4 = "([^a-zA-Z](hz))|([^a-zA-Z](HZ))|(([^(MEGA)|(GIGA)|(KILO)])HERTZ)|(([^(mega)|(giga)|(kilo)])hertz)";
Pattern p4 = java.util.regex.Pattern.compile(regex4);
Matcher m4 = p4.matcher(s);
if (m1.find()) {
modifier = "kilo";
} else if (m2.find()) {
modifier = "mega";
} else if (m3.find()) {
modifier = "giga";
// } //else if (m4.find()) {
// modifier = "none";
} else {
modifier = "none";
}
return modifier;
} catch (Exception e) {
LOG.error("Error parsing frequency unit " + s);
LOG.debug(e.getMessage());
LOG.debug(e.getStackTrace());
throw (e);
}
}
private Boolean StringIsNullOrEmpty(String s) {
if (s != null) {
if (s.equals("")) {
return true;
} else
return false;
} else
return true;
}
}