Commit 185ef9cf authored by Matija Obreza's avatar Matija Obreza

Support for LATITUDE, LONGITUDE conversion to DECLATITUDE, DECLONGITUDE

parent 7f64baf4
......@@ -31,7 +31,9 @@ import org.genesys2.anno.gui.ColumnDefs;
import org.genesys2.anno.gui.IDataSourceSheet;
import org.genesys2.anno.model.Column;
import org.genesys2.anno.model.ColumnDef;
import org.genesys2.anno.predefined.DataConversionException;
import org.genesys2.anno.predefined.GenesysJSON;
import org.genesys2.anno.predefined.GenesysJSON.ConvertingJsonField;
import org.genesys2.anno.predefined.GenesysJSON.JsonField;
import com.fasterxml.jackson.core.JsonGenerationException;
......@@ -237,8 +239,7 @@ public class RowConverter {
int dotPost = fieldName.lastIndexOf('.');
if (dotPost > -1)
fieldName = fieldName.substring(dotPost + 1);
// System.err.println(">> " + jsonField.getFieldName() + " field=" +
// fieldName);
_log.trace(">> " + jsonField.getFieldName() + " field=" + fieldName);
JsonNode valueNode = containerNode.get(fieldName);
if (valueNode == null) {
......@@ -256,16 +257,16 @@ public class RowConverter {
} else if (rdfValues instanceof ArrayList<?>) {
ArrayNode arrayNode = (ArrayNode) valueNode;
for (String rdfValue : (ArrayList<String>) rdfValues) {
arrayNode.add(coerce(jsonField.getType(), rdfValue));
arrayNode.add(coerce(jsonField, rdfValue));
}
} else {
if (jsonField.hasAllowMultiple()) {
ArrayNode arrayNode = (ArrayNode) valueNode;
arrayNode.add(coerce(jsonField.getType(), rdfValues));
arrayNode.add(coerce(jsonField, rdfValues));
} else {
// System.err.println("Putting field=" + fieldName + " type=" +
// rdfValues.getClass());
containerNode.set(fieldName, coerce(jsonField.getType(), rdfValues));
containerNode.set(fieldName, coerce(jsonField, rdfValues));
}
}
}
......@@ -313,23 +314,43 @@ public class RowConverter {
return node != null && !node.isNull() && !node.isMissingNode() && !node.isArray() && node.isValueNode();
}
static JsonNode coerce(Class<?> clazz, Object rdfValues) {
static JsonNode coerce(JsonField jsonField, Object rdfValues) throws GenesysJSONException {
if (rdfValues == null) {
return null;
}
if (clazz == String.class) {
if (jsonField instanceof ConvertingJsonField<?>) {
try {
return coerce(jsonField.getType(), ((ConvertingJsonField<?>) jsonField).convert(rdfValues));
} catch (DataConversionException e) {
throw new GenesysJSONException(e.getMessage());
}
}
return coerce(jsonField.getType(), rdfValues);
}
static JsonNode coerce(Class<?> targetType, Object rdfValues) {
if (rdfValues == null) {
return null;
}
if (targetType == String.class) {
return new TextNode(rdfValues.toString());
}
if (clazz == double.class || clazz == float.class) {
if (targetType == double.class || targetType == float.class) {
if (rdfValues instanceof Number) {
return new DoubleNode(((Number) rdfValues).doubleValue());
}
return new DoubleNode(Double.parseDouble(rdfValues.toString()));
}
if (clazz == int.class || clazz == long.class) {
if (targetType == int.class || targetType == long.class) {
if (rdfValues instanceof Number) {
return new LongNode(((Number) rdfValues).longValue());
}
return new LongNode(Long.parseLong(rdfValues.toString()));
}
if (clazz == boolean.class) {
if (targetType == boolean.class) {
return BooleanNode.valueOf(toBoolean(rdfValues.toString()));
}
throw new RuntimeException("Unsupported JSON type " + clazz);
throw new RuntimeException("Unsupported JSON type " + targetType);
}
private static boolean toBoolean(String rdfValue) {
......
/*
* Copyright 2016 Global Crop Diversity Trust
*
* 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.
*/
package org.genesys2.anno.predefined;
public class DataConversionException extends Exception {
private static final long serialVersionUID = 1L;
public DataConversionException() {
}
public DataConversionException(String message) {
super(message);
}
}
......@@ -23,6 +23,8 @@ import java.util.List;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Predicate;
import org.genesys2.anno.util.CoordinateConversionException;
import org.genesys2.anno.util.GeoUtils;
public class GenesysJSON {
public static class JsonField {
......@@ -72,7 +74,17 @@ public class GenesysJSON {
return required;
}
}
/**
* For when you need to convert stuff
*/
public static abstract class ConvertingJsonField<T> extends JsonField {
public ConvertingJsonField(String fieldName, String rdfTerm) {
super(fieldName, rdfTerm);
}
public abstract T convert(Object rdfValues) throws DataConversionException;
}
private final List<JsonField> jsonFields;
private Collection<JsonField> requiredFields;
......@@ -136,6 +148,24 @@ public class GenesysJSON {
columnDef = new JsonField(Api1Constants.Accession.COLL + "." + Api1Constants.Collecting.COLLSRC, RdfMCPD.COLLSRC).setType(int.class);
columns.add(columnDef);
columnDef = new ConvertingJsonField<Double>(Api1Constants.Accession.GEO + "." + Api1Constants.Geo.LATITUDE, RdfMCPD.LATITUDE) {
@Override
public Double convert(Object value) throws CoordinateConversionException {
return GeoUtils.toDecimalLatitude((String) value);
}
}
.setType(double.class);
columns.add(columnDef);
columnDef = new ConvertingJsonField<Double>(Api1Constants.Accession.GEO + "." + Api1Constants.Geo.LONGITUDE, RdfMCPD.LONGITUDE){
@Override
public Double convert(Object value) throws CoordinateConversionException {
return GeoUtils.toDecimalLongitude((String) value);
}
}
.setType(double.class);
columns.add(columnDef);
columnDef = new JsonField(Api1Constants.Accession.GEO + "." + Api1Constants.Geo.LATITUDE, RdfMCPD.DECLATITUDE).setType(double.class);
columns.add(columnDef);
......
......@@ -86,6 +86,12 @@ public class MCPD {
columnDef = new ColumnDef("COLLSITE", "Location of collecting site", ColumnDataType.TEXT, false, RdfMCPD.COLLSITE);
columns.add(columnDef);
columnDef = new ColumnDef("LATITUDE", "Latitude of collecting site (DDMMSSN|S)", ColumnDataType.DOUBLE, false, RdfMCPD.LATITUDE);
columns.add(columnDef);
columnDef = new ColumnDef("LONGITUDE", "Longitude of collecting site (DDDMMSSE|W)", ColumnDataType.DOUBLE, false, RdfMCPD.LONGITUDE);
columns.add(columnDef);
columnDef = new ColumnDef("DECLATITUDE", "Latitude of collecting site (decimal)", ColumnDataType.DOUBLE, false, RdfMCPD.DECLATITUDE);
columns.add(columnDef);
......
......@@ -42,6 +42,8 @@ public class RdfMCPD {
public static final String GEOREFMETH = "http://purl.org/germplasm/germplasmTerm#georeferencingMethod";
// -- end made up
public static final String COLLSITE = "http://rs.tdwg.org/dwc/terms/verbatimLocality";
public static final String LATITUDE = "http://rs.tdwg.org/dwc/terms/verbatimLatitude";
public static final String LONGITUDE = "http://rs.tdwg.org/dwc/terms/verbatimLongitude";
public static final String DECLATITUDE = "http://rs.tdwg.org/dwc/terms/decimalLatitude";
public static final String DECLONGITUDE = "http://rs.tdwg.org/dwc/terms/decimalLongitude";
public static final String COORDUNCERT = "http://rs.tdwg.org/dwc/terms/coordinateUncertaintyInMeters";
......
/*
* Copyright 2016 Global Crop Diversity Trust
*
* 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.
*/
package org.genesys2.anno.util;
import org.genesys2.anno.predefined.DataConversionException;
public class CoordinateConversionException extends DataConversionException {
private static final long serialVersionUID = 1L;
public CoordinateConversionException(String message) {
super(message);
}
}
/*
* Copyright 2016 Global Crop Diversity Trust
*
* 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.
*/
package org.genesys2.anno.util;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
public class GeoUtils {
private static final Logger _log = Logger.getLogger(GeoUtils.class);
private static final Pattern LATITUDE = Pattern.compile("([\\d\\-]{2})([\\d\\-]{2})([\\d\\-]{2})(N|S)");
private static final Pattern LONGITUDE = Pattern.compile("([\\d\\-]{3})([\\d\\-]{2})([\\d\\-]{2})(E|W)");
/**
* Convert DDMMSS[NS] to decimal latitude
*
* @param str
* String in format DDMMSS[NS]
* @return latitude in decimal format, <code>null</code> if format not valid
* @throws CoordinateConversionException
* when latitude not in DDDMMSS[NS] format
*/
public static Double toDecimalLatitude(String str) throws CoordinateConversionException {
if (StringUtils.isBlank(str)) {
return null;
}
if (str.matches("^-+$")) {
return null;
}
Matcher m = LATITUDE.matcher(str.replace('-', '0'));
if (m.matches()) {
_log.trace("Latitude " + str + " matches format DDMMSS[EW]");
String deg = m.group(1);
String min = m.group(2);
String sec = m.group(3);
String compass = m.group(4);
double latitude = Double.parseDouble(deg);
latitude += Double.parseDouble(min) / 60.0;
latitude += Double.parseDouble(sec) / 60.0 / 60.0;
latitude *= compass.equals("N") ? 1.0 : -1.0;
latitude = Math.round(latitude * 100000.0) / 100000.0;
return latitude;
} else {
_log.error("Latitude " + str + " does not match format DDMMSS[EW]");
throw new CoordinateConversionException("Latitude " + str + " does not match format DDMMSS[EW]");
}
}
/**
* Convert DDDMMSS[EW] to decimal longitude
*
* @param str
* String in format DDDMMSS[EW]
* @return longitude in decimal format, <code>null</code> if format not
* valid
* @throws CoordinateConversionException
* when longitude not in DDDMMSS[EW] format
*/
public static Double toDecimalLongitude(String str) throws CoordinateConversionException {
if (StringUtils.isBlank(str)) {
return null;
}
if (str.matches("^-+$")) {
return null;
}
Matcher m = LONGITUDE.matcher(str.replace('-', '0'));
if (m.matches()) {
_log.trace("Longitude " + str + " matches format DDDMMSS[EW]");
String deg = m.group(1);
String min = m.group(2);
String sec = m.group(3);
String compass = m.group(4);
double longitude = Double.parseDouble(deg);
longitude += Double.parseDouble(min) / 60.0;
longitude += Double.parseDouble(sec) / 60.0 / 60.0;
longitude *= compass.equals("E") ? 1.0 : -1.0;
longitude = Math.round(longitude * 100000.0) / 100000.0;
return longitude;
} else {
_log.error("Longitude " + str + " does not match format DDDMMSS[EW]");
throw new CoordinateConversionException("Longitude " + str + " does not match format DDDMMSS[EW]");
}
}
}
/*
* Copyright 2016 Global Crop Diversity Trust
*
* 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.
*/
package org.genesys2.anno.util;
import static org.junit.Assert.*;
import org.junit.Test;
public class GeoUtilsTest {
@Test
public void testLatitude() throws CoordinateConversionException {
assertTrue(GeoUtils.toDecimalLatitude(null) == null);
assertTrue(GeoUtils.toDecimalLatitude("") == null);
assertTrue(GeoUtils.toDecimalLatitude("------") == null);
assertTrue(GeoUtils.toDecimalLatitude("000000N") == 0.0);
assertTrue(GeoUtils.toDecimalLatitude("000000S") == -0.0);
assertTrue(GeoUtils.toDecimalLatitude("100000N") == 10.0);
assertTrue(GeoUtils.toDecimalLatitude("100---N") == 10.0);
assertTrue(GeoUtils.toDecimalLatitude("100000S") == -10.0);
assertTrue(GeoUtils.toDecimalLatitude("000001N") == 0.00028);
assertTrue(GeoUtils.toDecimalLatitude("001000N") == 0.16667);
assertTrue(GeoUtils.toDecimalLatitude("000010N") == 0.00278);
assertTrue(GeoUtils.toDecimalLatitude("000010S") == -0.00278);
}
@Test
public void testLongitude() throws CoordinateConversionException {
assertTrue(GeoUtils.toDecimalLongitude(null) == null);
assertTrue(GeoUtils.toDecimalLongitude("") == null);
assertTrue(GeoUtils.toDecimalLongitude("-------") == null);
assertTrue(GeoUtils.toDecimalLongitude("0000000E") == 0.0);
assertTrue(GeoUtils.toDecimalLongitude("0000000W") == -0.0);
assertTrue(GeoUtils.toDecimalLongitude("1000000E") == 100.0);
assertTrue(GeoUtils.toDecimalLongitude("100----E") == 100.0);
assertTrue(GeoUtils.toDecimalLongitude("1000000W") == -100.0);
assertTrue(GeoUtils.toDecimalLongitude("0100000E") == 10.0);
assertTrue(GeoUtils.toDecimalLongitude("0001000E") == 0.16667);
assertTrue(GeoUtils.toDecimalLongitude("0000010E") == 0.00278);
assertTrue(GeoUtils.toDecimalLongitude("0000010W") == -0.00278);
}
@Test(expected = CoordinateConversionException.class)
public void testLatitudeEx1() throws CoordinateConversionException {
GeoUtils.toDecimalLatitude("000000");
}
@Test(expected = CoordinateConversionException.class)
public void testLatitudeEx2() throws CoordinateConversionException {
GeoUtils.toDecimalLatitude("000000A");
}
@Test(expected = CoordinateConversionException.class)
public void testLatitudeEx3() throws CoordinateConversionException {
GeoUtils.toDecimalLatitude("00000N");
}
@Test(expected = CoordinateConversionException.class)
public void testLongitudeEx1() throws CoordinateConversionException {
GeoUtils.toDecimalLatitude("0000000");
}
@Test(expected = CoordinateConversionException.class)
public void testLongitudeEx2() throws CoordinateConversionException {
GeoUtils.toDecimalLatitude("0000000A");
}
@Test(expected = CoordinateConversionException.class)
public void testLongitudeEx3() throws CoordinateConversionException {
GeoUtils.toDecimalLatitude("000000E");
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment