Support for GMLLiterals and tests.
Project: http://git-wip-us.apache.org/repos/asf/incubator-rya/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-rya/commit/1490b5db Tree: http://git-wip-us.apache.org/repos/asf/incubator-rya/tree/1490b5db Diff: http://git-wip-us.apache.org/repos/asf/incubator-rya/diff/1490b5db Branch: refs/heads/develop Commit: 1490b5dbff8c2fadaf31ead16d0c3d7dfec5ea5a Parents: 4da17f8 Author: David W. Lotts <david.lo...@parsons.com> Authored: Wed Jul 13 03:49:30 2016 -0400 Committer: Aaron Mihalik <miha...@alum.mit.edu> Committed: Tue Aug 23 11:02:28 2016 -0400 ---------------------------------------------------------------------- extras/indexing/pom.xml | 27 ++ .../rya/indexing/accumulo/geo/GeoConstants.java | 29 +- .../accumulo/geo/GeoMesaGeoIndexer.java | 5 +- .../indexing/accumulo/geo/GeoParseUtils.java | 93 +++++- .../indexing/accumulo/geo/GeoIndexerSfTest.java | 311 +++++++++++++++---- .../indexing/accumulo/geo/GeoIndexerTest.java | 6 +- 6 files changed, 388 insertions(+), 83 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/1490b5db/extras/indexing/pom.xml ---------------------------------------------------------------------- diff --git a/extras/indexing/pom.xml b/extras/indexing/pom.xml index bfa02f8..d2d7e10 100644 --- a/extras/indexing/pom.xml +++ b/extras/indexing/pom.xml @@ -23,6 +23,18 @@ <artifactId>rya.indexing</artifactId> <name>Apache Rya Secondary Indexing</name> + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <geotools.version>14.3</geotools.version> + </properties> + <repositories> + <repository> + <id>osgeo</id> + <name>Open Source Geospatial Foundation Repository</name> + <url>http://download.osgeo.org/webdav/geotools/</url> + </repository> + </repositories> + <dependencies> <dependency> @@ -107,6 +119,21 @@ <version>${project.version}</version> <type>test-jar</type> </dependency> + <dependency> + <groupId>org.geotools.xsd</groupId> + <artifactId>gt-xsd-gml3</artifactId> + <version>${geotools.version}</version> + </dependency> + <dependency> + <groupId>org.geotools</groupId> + <artifactId>gt-api</artifactId> + <version>${geotools.version}</version> + </dependency> + <dependency> + <groupId>com.vividsolutions</groupId> + <artifactId>jts</artifactId> + <version>1.13</version> + </dependency> </dependencies> <build> <pluginManagement> http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/1490b5db/extras/indexing/src/main/java/mvm/rya/indexing/accumulo/geo/GeoConstants.java ---------------------------------------------------------------------- diff --git a/extras/indexing/src/main/java/mvm/rya/indexing/accumulo/geo/GeoConstants.java b/extras/indexing/src/main/java/mvm/rya/indexing/accumulo/geo/GeoConstants.java index 6cb01e1..8f563e0 100644 --- a/extras/indexing/src/main/java/mvm/rya/indexing/accumulo/geo/GeoConstants.java +++ b/extras/indexing/src/main/java/mvm/rya/indexing/accumulo/geo/GeoConstants.java @@ -19,8 +19,6 @@ package mvm.rya.indexing.accumulo.geo; * under the License. */ - - import org.openrdf.model.URI; import org.openrdf.model.impl.URIImpl; @@ -28,18 +26,21 @@ import org.openrdf.model.impl.URIImpl; * A set of URIs used in GeoSPARQL */ public class GeoConstants { - public static final String NS_GEO = "http://www.opengis.net/ont/geosparql#"; - public static final String NS_GEOF = "http://www.opengis.net/def/function/geosparql/"; + public static final String NS_GEO = "http://www.opengis.net/ont/geosparql#"; + public static final String NS_GEOF = "http://www.opengis.net/def/function/geosparql/"; + + public static final URI XMLSCHEMA_OGC_WKT = new URIImpl(NS_GEO + "wktLiteral"); + public static final URI GEO_AS_WKT = new URIImpl(NS_GEO + "asWKT"); - public static final URI XMLSCHEMA_OGC_WKT = new URIImpl(NS_GEO + "wktLiteral"); - public static final URI GEO_AS_WKT = new URIImpl(NS_GEO + "asWKT"); + public static final URI XMLSCHEMA_OGC_GML = new URIImpl(NS_GEO + "gmlLiteral"); + public static final URI GEO_AS_GML = new URIImpl(NS_GEO + "asGML"); - public static final URI GEO_SF_EQUALS = new URIImpl(NS_GEOF + "sfEquals"); - public static final URI GEO_SF_DISJOINT = new URIImpl(NS_GEOF + "sfDisjoint"); - public static final URI GEO_SF_INTERSECTS = new URIImpl(NS_GEOF + "sfIntersects"); - public static final URI GEO_SF_TOUCHES = new URIImpl(NS_GEOF + "sfTouches"); - public static final URI GEO_SF_CROSSES = new URIImpl(NS_GEOF + "sfCrosses"); - public static final URI GEO_SF_WITHIN = new URIImpl(NS_GEOF + "sfWithin"); - public static final URI GEO_SF_CONTAINS = new URIImpl(NS_GEOF + "sfContains"); - public static final URI GEO_SF_OVERLAPS = new URIImpl(NS_GEOF + "sfOverlaps"); + public static final URI GEO_SF_EQUALS = new URIImpl(NS_GEOF + "sfEquals"); + public static final URI GEO_SF_DISJOINT = new URIImpl(NS_GEOF + "sfDisjoint"); + public static final URI GEO_SF_INTERSECTS = new URIImpl(NS_GEOF + "sfIntersects"); + public static final URI GEO_SF_TOUCHES = new URIImpl(NS_GEOF + "sfTouches"); + public static final URI GEO_SF_CROSSES = new URIImpl(NS_GEOF + "sfCrosses"); + public static final URI GEO_SF_WITHIN = new URIImpl(NS_GEOF + "sfWithin"); + public static final URI GEO_SF_CONTAINS = new URIImpl(NS_GEOF + "sfContains"); + public static final URI GEO_SF_OVERLAPS = new URIImpl(NS_GEOF + "sfOverlaps"); } http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/1490b5db/extras/indexing/src/main/java/mvm/rya/indexing/accumulo/geo/GeoMesaGeoIndexer.java ---------------------------------------------------------------------- diff --git a/extras/indexing/src/main/java/mvm/rya/indexing/accumulo/geo/GeoMesaGeoIndexer.java b/extras/indexing/src/main/java/mvm/rya/indexing/accumulo/geo/GeoMesaGeoIndexer.java index 0c8c898..7bfe6b7 100644 --- a/extras/indexing/src/main/java/mvm/rya/indexing/accumulo/geo/GeoMesaGeoIndexer.java +++ b/extras/indexing/src/main/java/mvm/rya/indexing/accumulo/geo/GeoMesaGeoIndexer.java @@ -234,10 +234,7 @@ public class GeoMesaGeoIndexer extends AbstractAccumuloIndexer implements GeoInd public void storeStatements(final Collection<RyaStatement> ryaStatements) throws IOException { // create a feature collection final DefaultFeatureCollection featureCollection = new DefaultFeatureCollection(); - - for (final RyaStatement ryaStatement : ryaStatements) { - final Statement statement = RyaToRdfConversions.convertStatement(ryaStatement); // if the predicate list is empty, accept all predicates. // Otherwise, make sure the predicate is on the "valid" list @@ -279,7 +276,7 @@ public class GeoMesaGeoIndexer extends AbstractAccumuloIndexer implements GeoInd final SimpleFeature newFeature = SimpleFeatureBuilder.build(featureType, noValues, statementId); // write the statement data to the fields - final Geometry geom = (new WKTReader()).read(GeoParseUtils.getWellKnownText(statement)); + final Geometry geom = GeoParseUtils.getGeometry(statement); if(geom == null || geom.isEmpty() || !geom.isValid()) { throw new ParseException("Could not create geometry for statement " + statement); } http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/1490b5db/extras/indexing/src/main/java/mvm/rya/indexing/accumulo/geo/GeoParseUtils.java ---------------------------------------------------------------------- diff --git a/extras/indexing/src/main/java/mvm/rya/indexing/accumulo/geo/GeoParseUtils.java b/extras/indexing/src/main/java/mvm/rya/indexing/accumulo/geo/GeoParseUtils.java index e5c3adf..119f351 100644 --- a/extras/indexing/src/main/java/mvm/rya/indexing/accumulo/geo/GeoParseUtils.java +++ b/extras/indexing/src/main/java/mvm/rya/indexing/accumulo/geo/GeoParseUtils.java @@ -1,5 +1,14 @@ package mvm.rya.indexing.accumulo.geo; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.StringReader; +import java.nio.charset.StandardCharsets; + +import javax.xml.parsers.ParserConfigurationException; + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -21,26 +30,94 @@ package mvm.rya.indexing.accumulo.geo; import org.apache.log4j.Logger; +import org.geotools.data.collection.ListFeatureCollection; +import org.geotools.gml3.GMLConfiguration; +import org.geotools.xml.Parser; import org.openrdf.model.Literal; import org.openrdf.model.Statement; +import org.xml.sax.SAXException; +import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.io.ParseException; +import com.vividsolutions.jts.io.WKTReader; + +import mvm.rya.api.domain.RyaStatement; public class GeoParseUtils { static final Logger logger = Logger.getLogger(GeoParseUtils.class); - + /** + * @deprecated Not needed since geo literals may be WKT or GML. + * + * This method warns on a condition that must already be tested. Replaced by + * {@link #getLiteral(Statement)} and {@link #getGeometry(Statement} + * and getLiteral(statement).toString() + * and getLiteral(statement).getDatatype() + */ + @Deprecated public static String getWellKnownText(Statement statement) throws ParseException { - org.openrdf.model.Value v = statement.getObject(); - if (!(v instanceof Literal)) { - throw new ParseException("Statement does not contain Literal: " + statement.toString()); - } - - Literal lit = (Literal) v; + Literal lit = getLiteral(statement); if (!GeoConstants.XMLSCHEMA_OGC_WKT.equals(lit.getDatatype())) { logger.warn("Literal is not of type " + GeoConstants.XMLSCHEMA_OGC_WKT + ": " + statement.toString()); } - return lit.getLabel().toString(); } + public static Literal getLiteral(Statement statement) throws ParseException { + org.openrdf.model.Value v = statement.getObject(); + if (!(v instanceof Literal)) { + throw new ParseException("Statement does not contain Literal: " + statement.toString()); + } + Literal lit = (Literal) v; + return lit; + } + + /** + * Parse GML/wkt literal to Geometry + * + * @param statement + * @return + * @throws ParseException + * @throws ParserConfigurationException + * @throws SAXException + * @throws IOException + */ + public static Geometry getGeometry(Statement statement) throws ParseException { + // handle GML or WKT + Literal lit = getLiteral(statement); + if (GeoConstants.XMLSCHEMA_OGC_WKT.equals(lit.getDatatype())) { + final String wkt = lit.getLabel().toString(); + return (new WKTReader()).read(wkt); + } else if (GeoConstants.XMLSCHEMA_OGC_GML.equals(lit.getDatatype())) { + String gml = lit.getLabel().toString(); + try { + return getGeometryGml(gml); + } catch (IOException | SAXException | ParserConfigurationException e) { + throw new ParseException(e); + } + } else { + throw new ParseException("Literal is unknown geo type, expecting WKT or GML: " + statement.toString()); + } + } + /** + * Convert GML/XML string into a geometry that can be indexed. + * @param gmlString + * @return + * @throws IOException + * @throws SAXException + * @throws ParserConfigurationException + */ + public static Geometry getGeometryGml(String gmlString) throws IOException, SAXException, ParserConfigurationException { + Reader reader = new StringReader(gmlString); + GMLConfiguration gmlConfiguration = new GMLConfiguration(); + Parser gmlParser = new Parser(gmlConfiguration); + // gmlParser.setStrict(false); // attempt at allowing deprecated elements, but no. + // gmlParser.setValidating(false); + final Geometry geometry = (Geometry) gmlParser.parse(reader); + // This sometimes gets populated with the SRS/CRS: geometry.getUserData() + // Always returns 0 : geometry.getSRID() + //TODO geometry.setUserData(some default CRS); OR geometry.setSRID(some default CRS) + + return geometry; + } + } http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/1490b5db/extras/indexing/src/test/java/mvm/rya/indexing/accumulo/geo/GeoIndexerSfTest.java ---------------------------------------------------------------------- diff --git a/extras/indexing/src/test/java/mvm/rya/indexing/accumulo/geo/GeoIndexerSfTest.java b/extras/indexing/src/test/java/mvm/rya/indexing/accumulo/geo/GeoIndexerSfTest.java index 81be7d4..0f7d018 100644 --- a/extras/indexing/src/test/java/mvm/rya/indexing/accumulo/geo/GeoIndexerSfTest.java +++ b/extras/indexing/src/test/java/mvm/rya/indexing/accumulo/geo/GeoIndexerSfTest.java @@ -19,34 +19,31 @@ package mvm.rya.indexing.accumulo.geo; * under the License. */ +import static org.junit.Assert.*; - -import info.aduna.iteration.CloseableIteration; - +import java.util.Arrays; +import java.util.Collection; import java.util.HashSet; import java.util.Map; import java.util.Set; -import mvm.rya.accumulo.AccumuloRdfConfiguration; -import mvm.rya.api.RdfCloudTripleStoreConfiguration; -import mvm.rya.api.domain.RyaStatement; -import mvm.rya.api.resolver.RdfToRyaConversions; -import mvm.rya.api.resolver.RyaToRdfConversions; -import mvm.rya.indexing.StatementConstraints; -import mvm.rya.indexing.accumulo.ConfigUtils; -import mvm.rya.indexing.accumulo.geo.GeoConstants; -import mvm.rya.indexing.accumulo.geo.GeoMesaGeoIndexer; - import org.apache.accumulo.core.client.admin.TableOperations; +import org.apache.hadoop.conf.Configuration; +import org.geotools.geometry.jts.Geometries; import org.junit.Assert; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; import org.openrdf.model.Resource; import org.openrdf.model.Statement; import org.openrdf.model.URI; import org.openrdf.model.Value; import org.openrdf.model.ValueFactory; import org.openrdf.model.impl.StatementImpl; +import org.openrdf.model.impl.URIImpl; import org.openrdf.model.impl.ValueFactoryImpl; import com.google.common.collect.Maps; @@ -60,10 +57,21 @@ import com.vividsolutions.jts.geom.Point; import com.vividsolutions.jts.geom.Polygon; import com.vividsolutions.jts.geom.PrecisionModel; import com.vividsolutions.jts.geom.impl.PackedCoordinateSequence; +import com.vividsolutions.jts.io.ParseException; +import com.vividsolutions.jts.io.gml2.GMLWriter; + +import info.aduna.iteration.CloseableIteration; +import mvm.rya.api.domain.RyaStatement; +import mvm.rya.api.resolver.RdfToRyaConversions; +import mvm.rya.api.resolver.RyaToRdfConversions; +import mvm.rya.indexing.StatementConstraints; +import mvm.rya.indexing.accumulo.ConfigUtils; /** - * Tests all of the "simple functions" of the geoindexer. + * Tests all of the "simple functions" of the geoindexer specific to GML. + * Parameterized so that each test is run for WKT and for GML. */ +@RunWith(value = Parameterized.class) public class GeoIndexerSfTest { private static AccumuloRdfConfiguration conf; private static GeometryFactory gf = new GeometryFactory(new PrecisionModel(), 4326); @@ -74,28 +82,28 @@ public class GeoIndexerSfTest { // Here is the landscape: /** * <pre> - * +---+---+---+---+---+---+---+ - * | F | | - * + A + + C + - * | | | - * +---+---+ E +---+---+ - * | | / | - * + B + /+---+---+ - * | | / | | - * +---+---+/--+---+---+ - * / | D | - * / +---+---+ + * 2---+---+---+---+---+---+ + * | F |G | + * 1 A o(-1,1) o C | + * | | | + * 0---+---+ +---+---+(3,0) + * | | E | + * -1 B + .---+---+ + * | | /| | | + * -2---+---+-/-+---+ + + * ^ / | D | + * -3 -2 -1 0---1---2 3 4 * </pre> **/ + private static final Polygon A = poly(bbox(-3, -2, 1, 2)); + private static final Polygon B = poly(bbox(-3, -2, -1, 0)); + private static final Polygon C = poly(bbox(1, 0, 3, 2)); + private static final Polygon D = poly(bbox(0, -3, 2, -1)); - private static final Polygon A = poly(bbox(0, 1, 4, 5)); - private static final Polygon B = poly(bbox(0, 1, 2, 3)); - private static final Polygon C = poly(bbox(4, 3, 6, 5)); - private static final Polygon D = poly(bbox(3, 0, 5, 2)); + private static final Point F = point(-1, 1); + private static final Point G = point(1, 1); - private static final Point F = point(2, 4); - - private static final LineString E = line(2, 0, 3, 3); + private static final LineString E = line(-1, -3, 0, -1); private static final Map<Geometry, String> names = Maps.newHashMap(); static { @@ -105,8 +113,36 @@ public class GeoIndexerSfTest { names.put(D, "D"); names.put(E, "E"); names.put(F, "F"); + names.put(G, "G"); } + /** + * JUnit 4 parameterized iterates thru this list and calls the constructor with each. + * For each test, Call the constructor three times, for WKT and for GML encoding 1, and GML encoding 2 + * @return + */ + final static URI useJtsLibEncoding = new URIImpl("uri:useLib") ; + final static URI useRoughEncoding = new URIImpl("uri:useRough") ; + + @Parameters + public static Collection<URI[]> constructorData() { + URI[][] data = new URI[][] { { GeoConstants.XMLSCHEMA_OGC_WKT,useJtsLibEncoding }, { GeoConstants.XMLSCHEMA_OGC_GML,useJtsLibEncoding } , { GeoConstants.XMLSCHEMA_OGC_GML,useRoughEncoding } }; + return Arrays.asList(data); + } + + private URI schemaToTest; + private URI encodeMethod; + /** + * Constructor required by JUnit parameterized runner. See data() for constructor values. + */ + public GeoIndexerSfTest(URI schemaToTest, URI encodeMethod) { + this.schemaToTest=schemaToTest; + this.encodeMethod = encodeMethod; + } + /** + * Run before each test method. + * @throws Exception + */ @Before public void before() throws Exception { conf = new AccumuloRdfConfiguration(); @@ -131,36 +167,152 @@ public class GeoIndexerSfTest { g = new GeoMesaGeoIndexer(); g.setConf(conf); - g.storeStatement(statement(A)); - g.storeStatement(statement(B)); - g.storeStatement(statement(C)); - g.storeStatement(statement(D)); - g.storeStatement(statement(F)); - g.storeStatement(statement(E)); + // Convert the statements as schema WKT or GML, then GML has two methods to encode. + g.storeStatement(RyaStatement(A,schemaToTest, encodeMethod)); + g.storeStatement(RyaStatement(B,schemaToTest, encodeMethod)); + g.storeStatement(RyaStatement(C,schemaToTest, encodeMethod)); + g.storeStatement(RyaStatement(D,schemaToTest, encodeMethod)); + g.storeStatement(RyaStatement(F,schemaToTest, encodeMethod)); + g.storeStatement(RyaStatement(E,schemaToTest, encodeMethod)); + g.storeStatement(RyaStatement(G,schemaToTest, encodeMethod)); } - private static RyaStatement statement(Geometry geo) { + private static RyaStatement RyaStatement(Geometry geo, URI schema, URI encodingMethod) { + return RdfToRyaConversions.convertStatement(genericStatement(geo,schema,encodingMethod)); + } + private static Statement genericStatement(Geometry geo, URI schema, URI encodingMethod) { + if (schema.equals(GeoConstants.XMLSCHEMA_OGC_WKT)) { + return genericStatementWkt(geo); + } else if (schema.equals(GeoConstants.XMLSCHEMA_OGC_GML)) { + return genericStatementGml(geo, encodingMethod); + } + throw new Error("schema unsupported: "+schema); + } + private static Statement genericStatementWkt(Geometry geo) { ValueFactory vf = new ValueFactoryImpl(); Resource subject = vf.createURI("uri:" + names.get(geo)); URI predicate = GeoConstants.GEO_AS_WKT; Value object = vf.createLiteral(geo.toString(), GeoConstants.XMLSCHEMA_OGC_WKT); - return RdfToRyaConversions.convertStatement(new StatementImpl(subject, predicate, object)); + return new StatementImpl(subject, predicate, object); + } + + private static Statement genericStatementGml(Geometry geo, URI encodingMethod) { + ValueFactory vf = new ValueFactoryImpl(); + Resource subject = vf.createURI("uri:" + names.get(geo)); + URI predicate = GeoConstants.GEO_AS_GML; + + final String gml ; + if (encodingMethod==useJtsLibEncoding) + gml = geoToGmlUseJtsLib(geo); + else if (encodingMethod==useRoughEncoding) + gml = geoToGmlRough(geo); + else + throw new Error("invalid encoding method: "+encodingMethod); + // System.out.println("===created GML===="); + // System.out.println(gml); + // System.out.println("========== GML===="); + + Value object = vf.createLiteral(gml, GeoConstants.XMLSCHEMA_OGC_GML); + return new StatementImpl(subject, predicate, object); + } + /** + * JTS library conversion from geometry to GML. + * @param geo base Geometry gets delegated + * @return String gml encoding of the geomoetry + */ + private static String geoToGmlUseJtsLib(Geometry geo) { + int srid = geo.getSRID(); + GMLWriter gmlWriter = new GMLWriter(); + gmlWriter.setNamespace(false); + gmlWriter.setPrefix(null); + + if (srid != -1 || srid != 0) { + gmlWriter.setSrsName("EPSG:" + geo.getSRID()); + } + String gml = gmlWriter.write(geo); + // Hack to replace a gml 2.0 deprecated element in the Polygon. + // It should tolerate this as it does other depreciated elements like <gml:coordinates>. + return gml.replace("outerBoundaryIs", "exterior"); } + /** + * Rough conversion from geometry to GML using a template. + * @param geo base Geometry gets delegated + * @return String gml encoding of the gemoetry + */ + private static String geoToGmlRough(Geometry geo) { + final Geometries theType = org.geotools.geometry.jts.Geometries.get(geo); + switch (theType) { + case POINT: + return geoToGml((Point)geo); + case LINESTRING: + return geoToGml((LineString)geo); + case POLYGON: + return geoToGml((Polygon)geo); + case MULTIPOINT: + case MULTILINESTRING: + case MULTIPOLYGON: + default: + throw new Error("No code to convert to GML for this type: "+theType); + } + } + private static Point point(double x, double y) { return gf.createPoint(new Coordinate(x, y)); } + private static String geoToGml(Point point) { + //CRS:84 long X,lat Y + //ESPG:4326 lat Y,long X + return "<Point"// + + " srsName='CRS:84'"// TODO: point.getSRID() + + "><pos>"+point.getX()+" "+point.getY()+"</pos> "// assumes Y=lat X=long + + " </Point>"; + } + private static LineString line(double x1, double y1, double x2, double y2) { return new LineString(new PackedCoordinateSequence.Double(new double[] { x1, y1, x2, y2 }, 2), gf); } + /** + * convert a lineString geometry to GML + * @param line + * @return String that is XML that is a GMLLiteral of line + */ + private static String geoToGml(LineString line) { + StringBuilder coordString = new StringBuilder() ; + for (Coordinate coor : line.getCoordinates()) { + coordString.append(" ").append(coor.x).append(" ").append(coor.y); //ESPG:4326 lat/long + } + return " <gml:LineString srsName=\"http://www.opengis.net/def/crs/EPSG/0/4326\" xmlns:gml='http://www.opengis.net/gml'>\n" + + "<gml:posList srsDimension=\"2\">"// + + coordString // + + "</gml:posList></gml:LineString >"; + } private static Polygon poly(double[] arr) { LinearRing r1 = gf.createLinearRing(new PackedCoordinateSequence.Double(arr, 2)); Polygon p1 = gf.createPolygon(r1, new LinearRing[] {}); return p1; } + /** + * convert a Polygon geometry to GML + * @param geometry + * @return String that is XML that is a GMLLiteral of line + */ + private static String geoToGml(Polygon poly) { + StringBuilder coordString = new StringBuilder() ; + for (Coordinate coor : poly.getCoordinates()) { + coordString.append(" ").append(coor.x).append(" ").append(coor.y); //ESPG:4326 lat/long + //with commas: coordString.append(" ").append(coor.x).append(",").append(coor.y); + } + return "<gml:Polygon srsName=\"EPSG:4326\" xmlns:gml='http://www.opengis.net/gml'>\r\n"// + + "<gml:exterior><gml:LinearRing>\r\n"// + + "<gml:posList srsDimension='2'>\r\n" + + coordString + + "</gml:posList>\r\n"// + + "</gml:LinearRing></gml:exterior>\r\n</gml:Polygon>\r\n"; + } private static double[] bbox(double x1, double y1, double x2, double y2) { return new double[] { x1, y1, x1, y2, x2, y2, x2, y1, x1, y1 }; @@ -169,7 +321,7 @@ public class GeoIndexerSfTest { public void compare(CloseableIteration<Statement, ?> actual, Geometry... expected) throws Exception { Set<Statement> expectedSet = Sets.newHashSet(); for (Geometry geo : expected) { - expectedSet.add(RyaToRdfConversions.convertStatement(statement(geo))); + expectedSet.add(RyaToRdfConversions.convertStatement(RyaStatement(geo,this.schemaToTest, encodeMethod))); } Assert.assertEquals(expectedSet, getSet(actual)); @@ -186,90 +338,136 @@ public class GeoIndexerSfTest { private static Geometry[] EMPTY_RESULTS = {}; @Test + public void testParsePoly() throws Exception { + assertParseable(D); + } + + @Test + public void testParseLine() throws Exception { + assertParseable(E); + } + + @Test + public void testParsePoint() throws Exception { + assertParseable(F); + } + + /** + * Convert Geometry to Wkt|GML (schemaToTest), parse to Geometry, and compare to original. + * @throws ParseException + */ + public void assertParseable(Geometry originalGeom) throws ParseException { + Geometry parsedGeom = GeoParseUtils.getGeometry(genericStatement(originalGeom,schemaToTest, encodeMethod)); + assertTrue("Parsed should equal original: "+originalGeom+" parsed: "+parsedGeom, originalGeom.equalsNorm(parsedGeom)); + // assertEquals( originalGeom, parsedGeom ); //also passes + // assertTrue( originalGeom.equalsExact(parsedGeom) ); //also passes + } + + @Test public void testEquals() throws Exception { // point compare(g.queryEquals(F, EMPTY_CONSTRAINTS), F); - compare(g.queryEquals(point(2, 2), EMPTY_CONSTRAINTS), EMPTY_RESULTS); + compare(g.queryEquals(point(-1, -1), EMPTY_CONSTRAINTS), EMPTY_RESULTS); // line compare(g.queryEquals(E, EMPTY_CONSTRAINTS), E); - compare(g.queryEquals(line(2, 2, 3, 3), EMPTY_CONSTRAINTS), EMPTY_RESULTS); + compare(g.queryEquals(line(-1, -1, 0, 0), EMPTY_CONSTRAINTS), EMPTY_RESULTS); // poly compare(g.queryEquals(A, EMPTY_CONSTRAINTS), A); - compare(g.queryEquals(poly(bbox(1, 1, 4, 5)), EMPTY_CONSTRAINTS), EMPTY_RESULTS); + compare(g.queryEquals(poly(bbox(-2, -2, 1, 2)), EMPTY_CONSTRAINTS), EMPTY_RESULTS); } @Test public void testDisjoint() throws Exception { // point - compare(g.queryDisjoint(F, EMPTY_CONSTRAINTS), B, C, D, E); + compare(g.queryDisjoint(F, EMPTY_CONSTRAINTS), B, C, D, E, G); // line - compare(g.queryDisjoint(E, EMPTY_CONSTRAINTS), B, C, D, F); + compare(g.queryDisjoint(E, EMPTY_CONSTRAINTS), B, C, F, G); // poly compare(g.queryDisjoint(A, EMPTY_CONSTRAINTS), EMPTY_RESULTS); - compare(g.queryDisjoint(B, EMPTY_CONSTRAINTS), C, D, F, E); + compare(g.queryDisjoint(B, EMPTY_CONSTRAINTS), C, D, F, E, G); } @Test + @Ignore public void testIntersectsPoint() throws Exception { // This seems like a bug + // scala.MatchError: POINT (2 4) (of class com.vividsolutions.jts.geom.Point) + // at org.locationtech.geomesa.filter.FilterHelper$.updateToIDLSafeFilter(FilterHelper.scala:53) // compare(g.queryIntersects(F, EMPTY_CONSTRAINTS), A, F); - // compare(g.queryIntersects(F, EMPTY_CONSTRAINTS), EMPTY_RESULTS); + // compare(g.queryIntersects(F, EMPTY_CONSTRAINTS), EMPTY_RESULTS); } + @Ignore @Test public void testIntersectsLine() throws Exception { // This seems like a bug - // compare(g.queryIntersects(E, EMPTY_CONSTRAINTS), A, E); - // compare(g.queryIntersects(E, EMPTY_CONSTRAINTS), EMPTY_RESULTS); + // fails with: + // scala.MatchError: LINESTRING (2 0, 3 3) (of class com.vividsolutions.jts.geom.LineString) + // at org.locationtech.geomesa.filter.FilterHelper$.updateToIDLSafeFilter(FilterHelper.scala:53) + //compare(g.queryIntersects(E, EMPTY_CONSTRAINTS), A, E, D); + //compare(g.queryIntersects(E, EMPTY_CONSTRAINTS), EMPTY_RESULTS); } @Test public void testIntersectsPoly() throws Exception { - compare(g.queryIntersects(A, EMPTY_CONSTRAINTS), A, B, C, D, F, E); + compare(g.queryIntersects(A, EMPTY_CONSTRAINTS), A, B, C, D, F, E, G); } @Test public void testTouchesPoint() throws Exception { compare(g.queryTouches(F, EMPTY_CONSTRAINTS), EMPTY_RESULTS); + compare(g.queryTouches(G, EMPTY_CONSTRAINTS), A, C); } @Test public void testTouchesLine() throws Exception { - compare(g.queryTouches(E, EMPTY_CONSTRAINTS), EMPTY_RESULTS); + compare(g.queryTouches(E, EMPTY_CONSTRAINTS), D); } @Test public void testTouchesPoly() throws Exception { - compare(g.queryTouches(A, EMPTY_CONSTRAINTS), C); + compare(g.queryTouches(A, EMPTY_CONSTRAINTS), C,G); } @Test public void testCrossesPoint() throws Exception { compare(g.queryCrosses(F, EMPTY_CONSTRAINTS), EMPTY_RESULTS); + compare(g.queryCrosses(G, EMPTY_CONSTRAINTS), EMPTY_RESULTS); + // bug? java.lang.IllegalStateException: getX called on empty Point + // compare(g.queryCrosses(point(2, 0), EMPTY_CONSTRAINTS), E); } + @Ignore @Test public void testCrossesLine() throws Exception { + // fails with: + // java.lang.IllegalStateException: getX called on empty Point + // at com.vividsolutions.jts.geom.Point.getX(Point.java:124) + // at org.locationtech.geomesa.utils.geohash.GeohashUtils$.considerCandidate$1(GeohashUtils.scala:1023) + // compare(g.queryCrosses(E, EMPTY_CONSTRAINTS), A); } @Test public void testCrossesPoly() throws Exception { compare(g.queryCrosses(A, EMPTY_CONSTRAINTS), E); + compare(g.queryCrosses(poly(bbox(-0.9, -2.9, -0.1, -1.1)), EMPTY_CONSTRAINTS), E); } @Test public void testWithin() throws Exception { // point - // compare(g.queryWithin(F, EMPTY_CONSTRAINTS), F); + // geomesa bug? scala.MatchError: POINT (2 4) (of class com.vividsolutions.jts.geom.Point) + // compare(g.queryWithin(F, EMPTY_CONSTRAINTS), F); // line - // compare(g.queryWithin(E, EMPTY_CONSTRAINTS), E); + // geomesa bug? scala.MatchError: LINESTRING (2 0, 3 2) (of class com.vividsolutions.jts.geom.LineString) + // compare(g.queryWithin(E, EMPTY_CONSTRAINTS), E); // poly compare(g.queryWithin(A, EMPTY_CONSTRAINTS), A, B, F); @@ -280,6 +478,7 @@ public class GeoIndexerSfTest { compare(g.queryContains(F, EMPTY_CONSTRAINTS), A, F); } + @Ignore @Test public void testContainsLine() throws Exception { // compare(g.queryContains(E, EMPTY_CONSTRAINTS), E); @@ -291,6 +490,7 @@ public class GeoIndexerSfTest { compare(g.queryContains(B, EMPTY_CONSTRAINTS), A, B); } + @Ignore @Test public void testOverlapsPoint() throws Exception { // compare(g.queryOverlaps(F, EMPTY_CONSTRAINTS), F); @@ -298,6 +498,7 @@ public class GeoIndexerSfTest { // compare(g.queryOverlaps(F, EMPTY_CONSTRAINTS), EMPTY_RESULTS); } + @Ignore @Test public void testOverlapsLine() throws Exception { // compare(g.queryOverlaps(E, EMPTY_CONSTRAINTS), A, E); http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/1490b5db/extras/indexing/src/test/java/mvm/rya/indexing/accumulo/geo/GeoIndexerTest.java ---------------------------------------------------------------------- diff --git a/extras/indexing/src/test/java/mvm/rya/indexing/accumulo/geo/GeoIndexerTest.java b/extras/indexing/src/test/java/mvm/rya/indexing/accumulo/geo/GeoIndexerTest.java index 94c265b..1e95db7 100644 --- a/extras/indexing/src/test/java/mvm/rya/indexing/accumulo/geo/GeoIndexerTest.java +++ b/extras/indexing/src/test/java/mvm/rya/indexing/accumulo/geo/GeoIndexerTest.java @@ -19,8 +19,6 @@ package mvm.rya.indexing.accumulo.geo; * under the License. */ - - import static mvm.rya.api.resolver.RdfToRyaConversions.convertStatement; import java.util.Collections; @@ -54,6 +52,10 @@ import mvm.rya.api.RdfCloudTripleStoreConfiguration; import mvm.rya.indexing.StatementConstraints; import mvm.rya.indexing.accumulo.ConfigUtils; +/** + * Tests higher level functioning of the geoindexer parse WKT, predicate list, + * prime and anti meridian, delete, search, context, search with Statement Constraints. + */ public class GeoIndexerTest { private static final StatementConstraints EMPTY_CONSTRAINTS = new StatementConstraints();