Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Genesys PGR
Geo Tools
Commits
b805dde3
Commit
b805dde3
authored
Jan 21, 2016
by
Matija Obreza
Browse files
Country of Origin validator
parent
aec11cd9
Changes
4
Hide whitespace changes
Inline
Side-by-side
src/main/java/org/genesys/geotools/CountryCLI.java
0 → 100644
View file @
b805dde3
package
org.genesys.geotools
;
import
java.io.BufferedReader
;
import
java.io.IOException
;
import
java.io.InputStreamReader
;
import
java.io.OutputStreamWriter
;
import
java.util.Arrays
;
import
java.util.regex.Matcher
;
import
java.util.regex.Pattern
;
import
com.opencsv.CSVReader
;
import
com.opencsv.CSVWriter
;
public
class
CountryCLI
{
// 2000 meters
private
static
final
int
ALLOWED_DISTANCE_MARGIN
=
2000
;
public
static
void
main
(
String
arg
[])
throws
Exception
{
if
(
arg
.
length
==
0
)
{
CountryOfOriginServiceImpl
countryOfOriginService
=
new
CountryOfOriginServiceImpl
();
countryOfOriginService
.
afterPropertiesSet
();
BufferedReader
br
=
new
BufferedReader
(
new
InputStreamReader
(
System
.
in
));
Pattern
pattern
=
Pattern
.
compile
(
"^(\\w{3})[\\s,]+(\\-?\\d*\\.?\\d*)[\\s,]+(\\-?\\d*\\.?\\d*)$"
);
System
.
err
.
println
(
"Expects input rows in format: Latitude\tLongitude"
);
System
.
err
.
println
(
"Enter 'q' to quit."
);
System
.
out
.
println
(
"OrigCty\tLatitude\tLongitude\tResult"
);
String
input
=
null
;
do
{
input
=
br
.
readLine
();
if
(
input
==
null
||
"q"
.
equals
(
input
))
break
;
Matcher
matcher
=
pattern
.
matcher
(
input
);
if
(
matcher
.
find
())
{
String
origCty
=
matcher
.
group
(
1
).
trim
();
float
latitude
=
Float
.
parseFloat
(
matcher
.
group
(
2
).
replace
(
","
,
"."
));
float
longitude
=
Float
.
parseFloat
(
matcher
.
group
(
3
).
replace
(
","
,
"."
));
System
.
out
.
println
(
latitude
+
", "
+
longitude
+
", "
+
countryOfOriginService
.
getCountries
(
longitude
,
latitude
,
origCty
,
ALLOWED_DISTANCE_MARGIN
));
}
else
{
System
.
err
.
println
(
"Invalid format: "
+
input
);
}
}
while
(
input
!=
null
&&
!
"q"
.
equals
(
input
));
}
else
{
doCSV
(
arg
);
}
}
private
static
void
doCSV
(
String
[]
arg
)
throws
IOException
{
int
columnOrigCty
=
5
;
int
columnLatitude
=
4
;
int
columnLongitude
=
3
;
CSVWriter
writer
=
new
CSVWriter
(
new
OutputStreamWriter
(
System
.
out
),
','
,
'"'
,
'\\'
,
"\n"
);
CSVReader
reader
=
new
CSVReader
(
new
InputStreamReader
(
System
.
in
),
','
,
'"'
,
'\\'
,
0
,
false
);
CountryOfOriginServiceImpl
countryOfOriginService
=
new
CountryOfOriginServiceImpl
();
countryOfOriginService
.
afterPropertiesSet
();
String
[]
nextLine
;
int
lineCount
=
0
;
while
((
nextLine
=
reader
.
readNext
())
!=
null
)
{
lineCount
++;
if
(
lineCount
%
1000
==
0
)
{
System
.
err
.
println
(
"FYI, "
+
lineCount
+
" entries have been processed."
);
}
String
[]
writeLine
=
Arrays
.
copyOf
(
nextLine
,
nextLine
.
length
+
1
);
try
{
String
origCty
=
nextLine
[
columnOrigCty
].
trim
();
float
longitude
=
Float
.
parseFloat
(
nextLine
[
columnLongitude
].
trim
());
float
latitude
=
Float
.
parseFloat
(
nextLine
[
columnLatitude
].
trim
());
try
{
String
geoCountry
=
countryOfOriginService
.
getCountries
(
longitude
,
latitude
,
origCty
,
ALLOWED_DISTANCE_MARGIN
);
writeLine
[
writeLine
.
length
-
1
]
=
geoCountry
;
// TODO Use origCty?
}
catch
(
Exception
e
)
{
writeLine
[
writeLine
.
length
-
1
]
=
e
.
getMessage
();
}
}
catch
(
Throwable
e
)
{
writeLine
[
writeLine
.
length
-
1
]
=
"ERROR: "
+
e
.
getMessage
();
}
writer
.
writeNext
(
writeLine
);
}
writer
.
close
();
reader
.
close
();
}
}
src/main/java/org/genesys/geotools/CountryOfOriginService.java
0 → 100644
View file @
b805dde3
package
org.genesys.geotools
;
public
interface
CountryOfOriginService
{
String
getCountries
(
float
longitude
,
float
latitude
,
String
origCty
,
int
allowedDistanceMargin
)
throws
Exception
;
}
src/main/java/org/genesys/geotools/CountryOfOriginServiceImpl.java
0 → 100644
View file @
b805dde3
package
org.genesys.geotools
;
import
java.io.IOException
;
import
java.net.MalformedURLException
;
import
java.util.concurrent.ExecutionException
;
import
java.util.concurrent.TimeUnit
;
import
org.geotools.data.DataStore
;
import
org.geotools.data.FeatureSource
;
import
org.geotools.factory.CommonFactoryFinder
;
import
org.geotools.feature.FeatureCollection
;
import
org.geotools.feature.FeatureIterator
;
import
org.geotools.geometry.jts.JTSFactoryFinder
;
import
org.geotools.geometry.jts.ReferencedEnvelope
;
import
org.geotools.referencing.crs.DefaultGeographicCRS
;
import
org.opengis.feature.simple.SimpleFeature
;
import
org.opengis.feature.simple.SimpleFeatureType
;
import
org.opengis.filter.Filter
;
import
org.opengis.filter.FilterFactory2
;
import
com.google.common.cache.CacheBuilder
;
import
com.google.common.cache.CacheLoader
;
import
com.google.common.cache.LoadingCache
;
import
com.vividsolutions.jts.geom.Coordinate
;
import
com.vividsolutions.jts.geom.GeometryFactory
;
import
com.vividsolutions.jts.geom.Point
;
/**
* Polygons used here are derived from OSM data, © OpenStreetMap contributors
*/
public
class
CountryOfOriginServiceImpl
implements
CountryOfOriginService
{
private
static
final
FilterFactory2
ff
=
CommonFactoryFinder
.
getFilterFactory2
();
private
static
final
GeometryFactory
geometryFactory
=
JTSFactoryFinder
.
getGeometryFactory
();
private
FeatureSource
<
SimpleFeatureType
,
SimpleFeature
>
sourceAdmin0
;
private
FeatureSource
<
SimpleFeatureType
,
SimpleFeature
>
sourceAdmin0X
;
private
LoadingCache
<
LonLatCacheKey
,
String
>
countryCache
;
static
{
try
{
// Initialize stuff
}
catch
(
Throwable
e
)
{
// big problem
throw
new
RuntimeException
(
e
);
}
}
public
void
afterPropertiesSet
()
throws
MalformedURLException
,
IOException
{
// http://www.gadm.org/version2
// Use "six dissolved layers"
DataStore
dataStoreAdm0
=
ShapefileUtils
.
openShapeFile
(
"TM_WORLD_BORDERS-0.3.shp"
);
DataStore
dataStoreAdm0X
=
ShapefileUtils
.
openShapeFile
(
"gadm28_adm0.shp"
);
sourceAdmin0
=
dataStoreAdm0
.
getFeatureSource
(
dataStoreAdm0
.
getTypeNames
()[
0
]);
sourceAdmin0X
=
dataStoreAdm0X
.
getFeatureSource
(
dataStoreAdm0X
.
getTypeNames
()[
0
]);
countryCache
=
CacheBuilder
.
newBuilder
().
maximumSize
(
1000
).
expireAfterWrite
(
20
,
TimeUnit
.
SECONDS
)
.
build
(
new
CacheLoader
<
LonLatCacheKey
,
String
>()
{
public
String
load
(
LonLatCacheKey
key
)
throws
Exception
{
// System.err.println("Loading");
return
_getCountry
(
key
.
getLongitude
(),
key
.
getLatitude
(),
key
.
getOrigCty
(),
key
.
getAllowedDistanceMargin
());
}
});
}
/*
* (non-Javadoc)
*
* @see org.genesys.geotools.LandOrSeaService#isOnLand(float, float, int)
*/
@Override
public
String
getCountries
(
float
longitude
,
float
latitude
,
String
origCty
,
int
allowedDistanceMargin
)
throws
Exception
{
try
{
return
countryCache
.
get
(
new
LonLatCacheKey
(
longitude
,
latitude
,
origCty
,
allowedDistanceMargin
));
}
catch
(
ExecutionException
e
)
{
throw
new
Exception
(
e
.
getCause
());
}
}
private
String
_getCountry
(
float
longitude
,
float
latitude
,
String
origCtyISO
,
int
allowedDistanceMargin
)
throws
Exception
{
// System.err.println(longitude + ", " + latitude + " " + origCtyISO);
Point
point
=
geometryFactory
.
createPoint
(
new
Coordinate
(
longitude
,
latitude
));
String
geometryPropertyName
=
sourceAdmin0
.
getSchema
().
getGeometryDescriptor
().
getLocalName
();
// CoordinateReferenceSystem targetCRS =
// sourceAdmin0.getSchema().getGeometryDescriptor()
// .getCoordinateReferenceSystem();
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
))
);
StringBuffer
sb
=
new
StringBuffer
();
// System.err.println(1);
FeatureCollection
<
SimpleFeatureType
,
SimpleFeature
>
matchingFeatures
=
sourceAdmin0
.
getFeatures
(
filterExact
);
try
(
FeatureIterator
<
SimpleFeature
>
features
=
matchingFeatures
.
features
())
{
if
(
features
.
hasNext
())
{
// System.err.println(3);
SimpleFeature
feature
=
features
.
next
();
// System.out.print(feature.getID());
// System.out.print(": ");
// System.out.println(feature.getDefaultGeometryProperty().getValue());
if
(
sb
.
length
()
>
0
)
sb
.
append
(
", "
);
sb
.
append
(
feature
.
getAttribute
(
"ISO3"
));
}
}
if
(
sb
.
length
()
==
0
||
!
sb
.
toString
().
contains
(
origCtyISO
))
{
// if (sb.length() > 0) sb.append(", ");
// sb.append("???");
// Filter filterBuffered = 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);
try
(
FeatureIterator
<
SimpleFeature
>
features
=
matchingFeatures2
.
features
())
{
if
(
features
.
hasNext
())
{
// System.err.println(7);
SimpleFeature
feature
=
features
.
next
();
// System.out.print(feature.getID());
// System.out.print(": ");
//
// System.out.println(feature.getDefaultGeometryProperty().getValue());
Object
isoAttr
=
feature
.
getAttribute
(
"ISO"
);
String
countryIsoCode
=
isoAttr
==
null
?
""
:
isoAttr
.
toString
();
if
(!
sb
.
toString
().
contains
(
countryIsoCode
))
{
if
(
sb
.
length
()
>
0
)
sb
.
append
(
", "
);
sb
.
append
(
countryIsoCode
);
}
}
}
}
// System.err.println(sb);
return
sb
.
toString
();
}
}
src/main/java/org/genesys/geotools/LonLatCacheKey.java
View file @
b805dde3
...
...
@@ -7,6 +7,7 @@ public class LonLatCacheKey implements Serializable {
private
static
final
long
serialVersionUID
=
-
3626533849742141104L
;
private
float
longitude
;
private
float
latitude
;
private
String
origCty
;
private
int
allowedDistanceMargin
;
public
LonLatCacheKey
(
float
longitude
,
float
latitude
,
int
allowedDistanceMargin
)
{
...
...
@@ -15,6 +16,14 @@ public class LonLatCacheKey implements Serializable {
this
.
allowedDistanceMargin
=
allowedDistanceMargin
;
}
public
LonLatCacheKey
(
float
longitude
,
float
latitude
,
String
origCty
,
int
allowedDistanceMargin
)
{
this
.
longitude
=
longitude
;
this
.
latitude
=
latitude
;
this
.
origCty
=
origCty
;
this
.
allowedDistanceMargin
=
allowedDistanceMargin
;
}
@Override
public
int
hashCode
()
{
final
int
prime
=
31
;
...
...
@@ -22,6 +31,7 @@ public class LonLatCacheKey implements Serializable {
result
=
prime
*
result
+
allowedDistanceMargin
;
result
=
prime
*
result
+
Float
.
floatToIntBits
(
latitude
);
result
=
prime
*
result
+
Float
.
floatToIntBits
(
longitude
);
result
=
prime
*
result
+
((
origCty
==
null
)
?
0
:
origCty
.
hashCode
());
return
result
;
}
...
...
@@ -40,6 +50,10 @@ public class LonLatCacheKey implements Serializable {
return
false
;
if
(
Float
.
floatToIntBits
(
longitude
)
!=
Float
.
floatToIntBits
(
other
.
longitude
))
return
false
;
if
(
origCty
==
null
)
{
if
(
other
.
origCty
!=
null
)
return
false
;
}
else
if
(!
origCty
.
equals
(
other
.
origCty
))
return
false
;
return
true
;
}
...
...
@@ -55,4 +69,8 @@ public class LonLatCacheKey implements Serializable {
public
int
getAllowedDistanceMargin
()
{
return
allowedDistanceMargin
;
}
public
String
getOrigCty
()
{
return
origCty
;
}
}
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment