Commit 0e4e2b7d authored by Matija Obreza's avatar Matija Obreza
Browse files

Javadoc

parent 861f39a2
......@@ -27,11 +27,16 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This is the default entry point for the -jar execution
* This is the default entry point for the -jar execution.
*/
public class CLI {
/** The LOG. */
private final static Logger LOG = LoggerFactory.getLogger(CLI.class);
/**
* Prints the help.
*/
private static void printHelp() {
System.out.println("Usage: java -jar geo-tools.jar country|landorsea [options] <inputFile> <outputFile>");
System.out.println("\nOptions:");
......@@ -43,6 +48,11 @@ public class CLI {
System.out.println("\nThe program writes log messages to STDERR.");
}
/**
* The main method.
*
* @param args the arguments
*/
public static void main(String[] args) {
String sourceName = null;
String outputName = null;
......@@ -138,6 +148,12 @@ public class CLI {
}
}
/**
* Get the next LOG level.
*
* @param level the level
* @return the level
*/
private static Level nextLevel(Level level) {
if (level.equals(Level.FATAL)) {
return Level.ERROR;
......
......@@ -21,7 +21,17 @@ import java.io.InputStreamReader;
import com.opencsv.CSVReader;
/**
* Generate a KML/KMZ file from CSV data.
*/
public class CSV2KML {
/**
* The main method.
*
* @param args the arguments
* @throws IOException Signals that an I/O exception has occurred.
*/
public static void main(String[] args) throws IOException {
int columnGenesysId = 0;
int columnAcceNumb = 1;
......
......@@ -19,11 +19,14 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* GeoTool interface for CLI programs.
*/
public interface GeoTool {
/**
* Execute the tool
*
* Execute the tool.
*
* @param inputStream CSV input stream
* @param outputStream output stream for resulting CSV
* @param separatorChar separator char (,)
......
......@@ -39,15 +39,33 @@ import org.slf4j.LoggerFactory;
import com.opencsv.CSVReader;
import com.opencsv.CSVWriter;
/**
* The Class LandOrSeaCLI.
*/
public class LandOrSeaCLI implements GeoTool {
/** The Constant LOG. */
private final static Logger LOG = LoggerFactory.getLogger(LandOrSeaCLI.class);
/** The Constant ALLOWED_DISTANCE_MARGIN. */
// 2000 meters
private static final int ALLOWED_DISTANCE_MARGIN = 2000;
/** The Constant HEADER_LATITUDE. */
private static final String HEADER_LATITUDE = "DECLATITUDE";
/** The Constant HEADER_LONGITUDE. */
private static final String HEADER_LONGITUDE = "DECLONGITUDE";
/** The Constant HEADER_LANDORSEA_CHECK. */
private static final String HEADER_LANDORSEA_CHECK = "LANDorSEA_check";
/**
* The main method.
*
* @param arg the arguments
* @throws Exception the exception
*/
public static void main(String arg[]) throws Exception {
if (arg.length == 0) {
......@@ -84,6 +102,9 @@ public class LandOrSeaCLI implements GeoTool {
}
}
/* (non-Javadoc)
* @see org.genesys.geotools.cli.GeoTool#execute(java.io.InputStream, java.io.OutputStream, char, char, char)
*/
public void execute(InputStream input, OutputStream output, char separatorChar, char quoteChar, char escapeChar) throws IOException {
try (CSVReader reader = new CSVReader(new BufferedReader(new InputStreamReader(input), 10000), separatorChar, quoteChar, escapeChar, 0, false)) {
......
......@@ -16,8 +16,21 @@
package org.genesys.geotools.service;
/**
* The Interface CountryOfOriginService.
*/
public interface CountryOfOriginService {
/**
* Gets the countries.
*
* @param longitude the longitude
* @param latitude the latitude
* @param origCty the orig cty
* @param allowedDistanceMargin the allowed distance margin
* @return the countries
* @throws Exception the exception
*/
String getCountries(float longitude, float latitude, String origCty, int allowedDistanceMargin) throws Exception;
}
......@@ -27,14 +27,16 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Helper for CSV header management
* Helper for CSV header management.
*/
public abstract class HeaderUtils {
/** The Constant LOG. */
private final static Logger LOG = LoggerFactory.getLogger(HeaderUtils.class);
/**
* Check for invalid headers and throw IOException if one is found
*
* Check for invalid headers and throw IOException if one is found.
*
* @param headers input headers
* @param notAllowedHeaders array of unacceptable headers
* @throws IOException when one unacceptable header is found
......@@ -49,10 +51,10 @@ public abstract class HeaderUtils {
}
/**
* Check for required headers and throw IOException if one is missing
*
* Check for required headers and throw IOException if one is missing.
*
* @param headers input headers
* @param notAllowedHeaders array of unacceptable headers
* @param requiredHeaders the array of required headers
* @throws IOException when one unacceptable header is found
*/
public static void throwIfHeaderNotFound(final String[] headers, final String[] requiredHeaders) throws IOException {
......@@ -65,10 +67,10 @@ public abstract class HeaderUtils {
}
/**
* Map CSV headers to their positions
*
* Map CSV headers to their positions.
*
* @param headers CSV header list
* @return a new List<Integer> with header indexes
* @return a new List with header indexes
*/
public static List<Integer> mapHeaderPositions(final String[] headers) {
List<Integer> outputMapping = new ArrayList<>();
......@@ -82,7 +84,8 @@ public abstract class HeaderUtils {
/**
* We are mostly interested in only a few supported headers. Get their indexes.
*
*
* @param headers the headers
* @param supportedHeaders Array of supported headers
* @return Map of positions of supported headers
*/
......@@ -104,8 +107,8 @@ public abstract class HeaderUtils {
}
/**
* Copy data from input CSV line to output CSV line with appropriate destination mapping
*
* Copy data from input CSV line to output CSV line with appropriate destination mapping.
*
* @param nextLine source line
* @param outputHeaders output headers
* @param outputMapping mapping of output columns
......
......@@ -16,8 +16,20 @@
package org.genesys.geotools.service;
/**
* The Interface LandOrSeaService.
*/
public interface LandOrSeaService {
/**
* Checks if is on land.
*
* @param longitude the longitude
* @param latitude the latitude
* @param allowedDistanceFromLand the allowed distance from land
* @return the boolean
* @throws Exception the exception
*/
public Boolean isOnLand(float longitude, float latitude, int allowedDistanceFromLand) throws Exception;
}
......@@ -18,20 +18,47 @@ package org.genesys.geotools.service;
import java.io.Serializable;
/**
* LonLatCacheKey is used as caching key.
*/
public class LonLatCacheKey implements Serializable {
/** The Constant serialVersionUID. */
private static final long serialVersionUID = -3626533849742141104L;
/** The longitude. */
private float longitude;
/** The latitude. */
private float latitude;
/** The orig cty. */
private String origCty;
/** The allowed distance margin. */
private int allowedDistanceMargin;
/**
* Instantiates a new lon lat cache key.
*
* @param longitude the longitude
* @param latitude the latitude
* @param allowedDistanceMargin the allowed distance margin
*/
public LonLatCacheKey(float longitude, float latitude, int allowedDistanceMargin) {
this.longitude = longitude;
this.latitude = latitude;
this.allowedDistanceMargin = allowedDistanceMargin;
}
/**
* Instantiates a new lon lat cache key.
*
* @param longitude the longitude
* @param latitude the latitude
* @param origCty the orig cty
* @param allowedDistanceMargin the allowed distance margin
*/
public LonLatCacheKey(float longitude, float latitude, String origCty, int allowedDistanceMargin) {
this.longitude = longitude;
this.latitude = latitude;
......@@ -39,6 +66,9 @@ public class LonLatCacheKey implements Serializable {
this.allowedDistanceMargin = allowedDistanceMargin;
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
......@@ -50,6 +80,9 @@ public class LonLatCacheKey implements Serializable {
return result;
}
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
......@@ -73,18 +106,38 @@ public class LonLatCacheKey implements Serializable {
return true;
}
/**
* Gets the longitude.
*
* @return the longitude
*/
public float getLongitude() {
return longitude;
}
/**
* Gets the latitude.
*
* @return the latitude
*/
public float getLatitude() {
return latitude;
}
/**
* Gets the allowed distance margin.
*
* @return the allowed distance margin
*/
public int getAllowedDistanceMargin() {
return allowedDistanceMargin;
}
/**
* Gets the orig cty.
*
* @return the orig cty
*/
public String getOrigCty() {
return origCty;
}
......
......@@ -37,10 +37,25 @@ import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.Polygon;
/**
* The Class ShapefileUtils.
*/
public class ShapefileUtils {
/** The Constant RING_POINTS. */
private static final int RING_POINTS = 12;
/** The Constant geometryFactory. */
private static final GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory(null);
/**
* Open shape file.
*
* @param shapeFilePath the shape file path
* @return the data store
* @throws MalformedURLException the malformed url exception
* @throws IOException Signals that an I/O exception has occurred.
*/
public static DataStore openShapeFile(String shapeFilePath) throws MalformedURLException, IOException {
File file = new File("data", shapeFilePath);
......@@ -55,14 +70,14 @@ public class ShapefileUtils {
/**
* Uses ideas from
* https://geoaware.wordpress.com/2013/10/16/geodetic-buffers-with-geotools/
*
* @param longitude
* @param latitude
* @param distanceMeters
* @return
* @throws MismatchedDimensionException
* @throws TransformException
* @throws FactoryException
*
* @param longitude the longitude
* @param latitude the latitude
* @param distanceMeters the distance meters
* @return the point buffer
* @throws MismatchedDimensionException the mismatched dimension exception
* @throws TransformException the transform exception
* @throws FactoryException the factory exception
*/
public static Geometry getPointBuffer(double longitude, double latitude, double distanceMeters)
throws MismatchedDimensionException, TransformException, FactoryException {
......
......@@ -37,6 +37,8 @@ import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.filter.Filter;
import org.opengis.filter.FilterFactory2;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
......@@ -47,16 +49,29 @@ import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.Point;
/**
* Polygons used here are derived from OSM data, © OpenStreetMap contributors
* Polygons used here are derived from OSM data, © OpenStreetMap contributors.
*/
public class CountryOfOriginServiceImpl implements CountryOfOriginService {
/** LOG */
private final static Logger LOG = LoggerFactory.getLogger(CountryOfOriginServiceImpl.class);
/** The Constant ff. */
private static final FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2();
/** The Constant geometryFactory. */
private static final GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory();
/** The source admin0. */
private FeatureSource<SimpleFeatureType, SimpleFeature> sourceAdmin0;
/** The source admin0 x. */
private FeatureSource<SimpleFeatureType, SimpleFeature> sourceAdmin0X;
/** The country cache. */
private LoadingCache<LonLatCacheKey, String> countryCache;
/** The debug. */
private boolean debug = false;
static {
......@@ -69,6 +84,12 @@ public class CountryOfOriginServiceImpl implements CountryOfOriginService {
}
}
/**
* After properties set.
*
* @throws MalformedURLException the malformed url exception
* @throws IOException Signals that an I/O exception has occurred.
*/
public void afterPropertiesSet() throws MalformedURLException, IOException {
// http://www.gadm.org/version2
// Use "six dissolved layers"
......@@ -78,15 +99,13 @@ public class CountryOfOriginServiceImpl implements CountryOfOriginService {
sourceAdmin0 = dataStoreAdm0.getFeatureSource(dataStoreAdm0.getTypeNames()[0]);
sourceAdmin0X = dataStoreAdm0X.getFeatureSource(dataStoreAdm0X.getTypeNames()[0]);
countryCache = CacheBuilder.newBuilder().maximumSize(5000).recordStats().expireAfterWrite(20, TimeUnit.SECONDS)
.build(new CacheLoader<LonLatCacheKey, String>() {
@Override
public String load(LonLatCacheKey key) throws Exception {
// System.err.println("Loading");
return _getCountry(key.getLongitude(), key.getLatitude(), key.getOrigCty(),
key.getAllowedDistanceMargin());
}
});
countryCache = CacheBuilder.newBuilder().maximumSize(5000).recordStats().expireAfterWrite(20, TimeUnit.SECONDS).build(new CacheLoader<LonLatCacheKey, String>() {
@Override
public String load(LonLatCacheKey key) throws Exception {
// LOG.debug("Loading");
return _getCountry(key.getLongitude(), key.getLatitude(), key.getOrigCty(), key.getAllowedDistanceMargin());
}
});
}
/*
......@@ -95,16 +114,15 @@ public class CountryOfOriginServiceImpl implements CountryOfOriginService {
* @see org.genesys.geotools.LandOrSeaService#isOnLand(float, float, int)
*/
@Override
public String getCountries(float longitude, float latitude, String origCty, int allowedDistanceMargin)
throws Exception {
public String getCountries(float longitude, float latitude, String origCty, int allowedDistanceMargin) throws Exception {
// 1 geographical mile is 1855.3248 metres for WGS84
// 1855.3248m * 60 = 111319.488m
// 111319.488m for 1 degree, can trim by 1000 for 100m precision at
// equator
// longitude = (long) (longitude * 1000) / 1000f;
// latitude = (long) (latitude * 1000) / 1000f;
// longitude = (long) (longitude * 1000) / 1000f;
// latitude = (long) (latitude * 1000) / 1000f;
try {
return countryCache.get(new LonLatCacheKey(longitude, latitude, origCty, allowedDistanceMargin));
......@@ -113,10 +131,19 @@ public class CountryOfOriginServiceImpl implements CountryOfOriginService {
}
}
private String _getCountry(float longitude, float latitude, String origCtyISO, int allowedDistanceMargin)
throws Exception {
/**
* _get country.
*
* @param longitude the longitude
* @param latitude the latitude
* @param origCtyISO the orig cty iso
* @param allowedDistanceMargin the allowed distance margin
* @return the string
* @throws Exception the exception
*/
private String _getCountry(float longitude, float latitude, String origCtyISO, int allowedDistanceMargin) throws Exception {
// System.err.println(longitude + ", " + latitude + " " + origCtyISO);
// LOG.debug(longitude + ", " + latitude + " " + origCtyISO);
StopWatch stopWatch = new StopWatch();
Point point = geometryFactory.createPoint(new Coordinate(longitude, latitude));
......@@ -125,23 +152,21 @@ public class CountryOfOriginServiceImpl implements CountryOfOriginService {
// sourceAdmin0.getSchema().getGeometryDescriptor()
// .getCoordinateReferenceSystem();
ReferencedEnvelope bbox = new ReferencedEnvelope(longitude - 30, longitude + 30, latitude - 30, latitude + 30,
DefaultGeographicCRS.WGS84);
ReferencedEnvelope bbox = new ReferencedEnvelope(longitude - 30, longitude + 30, latitude - 30, latitude + 30, DefaultGeographicCRS.WGS84);
Filter filterExact =
// ff.and(
// ff.equal(ff.property("ISO3"), ff.literal(origCtyISO), false),
ff.and(ff.bbox(ff.property(geometryPropertyName), bbox),
ff.contains(ff.property(geometryPropertyName), ff.literal(point)));
// ff.and(
// ff.equal(ff.property("ISO3"), ff.literal(origCtyISO), false),
ff.and(ff.bbox(ff.property(geometryPropertyName), bbox), ff.contains(ff.property(geometryPropertyName), ff.literal(point)));
StringBuffer sb = new StringBuffer();
stopWatch.start();
// System.err.println(1);
// LOG.debug(1);
FeatureCollection<SimpleFeatureType, SimpleFeature> matchingFeatures = sourceAdmin0.getFeatures(filterExact);
try (FeatureIterator<SimpleFeature> features = matchingFeatures.features()) {
if (features.hasNext()) {
// System.err.println(3);
// LOG.debug(3);
SimpleFeature feature = features.next();
// System.out.print(feature.getID());
// System.out.print(": ");
......@@ -155,9 +180,9 @@ public class CountryOfOriginServiceImpl implements CountryOfOriginService {
stopWatch.split();
long processingTime = stopWatch.getSplitTime();
if (debug) {
System.err.println("Processing time split: " + processingTime);
LOG.debug("Processing time split: " + processingTime);
}
if (sb.length() == 0 || !sb.toString().contains(origCtyISO)) {
// if (sb.length() > 0) sb.append(", ");
// sb.append("???");
......@@ -165,19 +190,18 @@ public class CountryOfOriginServiceImpl implements CountryOfOriginService {
// ff.intersects(ff.property(geometryPropertyName),
// ff.literal(ShapefileUtils.getPointBuffer(point,
// allowedDistanceMargin)));
// System.err.println(4);
FeatureCollection<SimpleFeatureType, SimpleFeature> matchingFeatures2 = sourceAdmin0X
.getFeatures(filterExact);
// System.err.println(4.1);
// LOG.debug(4);
FeatureCollection<SimpleFeatureType, SimpleFeature> matchingFeatures2 = sourceAdmin0X.getFeatures(filterExact);
// LOG.debug(4.1);
try (FeatureIterator<SimpleFeature> features = matchingFeatures2.features()) {
if (features.hasNext()) {
// System.err.println(7);
// LOG.debug(7);
SimpleFeature feature = features.next();
// System.out.print(feature.getID());
// System.out.print(": ");
//
// System.out.println(feature.getDefaultGeometryProperty().getValue());
// System.out.println(feature.getDefaultGeometryProperty().getValue());
Object isoAttr = feature.getAttribute("ISO");
String countryIsoCode = isoAttr == null ? "" : isoAttr.toString();
......@@ -191,18 +215,21 @@ public class CountryOfOriginServiceImpl implements CountryOfOriginService {
}
stopWatch.stop();
processingTime = stopWatch.getTime();
if (debug || processingTime > 3000) {
System.err
.println("Total processing time: " + processingTime + " for\t" + origCtyISO + "\t" + longitude + "\t" + latitude);
if (LOG.isInfoEnabled() || processingTime > 3000) {
LOG.info("Total processing time: {} for\t{}\t\t", processingTime, origCtyISO, longitude, latitude);
}
// System.err.println(sb);
// LOG.debug(sb);
return sb.toString();
}
/**
* Prints the cache.
*/
public void printCache() {
CacheStats stats = countryCache.stats();
System.err.println("Hit count=" + stats.hitCount() + " rate=" + stats.hitRate() + " Miss count="
+ stats.missCount() + " rate=" + stats.missRate());
if (LOG.isInfoEnabled()) {
LOG.info("Hit count=" + stats.hitCount() + " rate=" + stats.hitRate() + " Miss count=" + stats.missCount() + " rate=" + stats.missRate());
}