blob: ff723f8eb28dc23a035fe473f2761d32f7fb51d6 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.rya.indexing.mongo;
import static org.apache.rya.api.resolver.RdfToRyaConversions.convertStatement;
import static org.apache.rya.indexing.GeoIndexingTestUtils.getSet;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.Collections;
import java.util.Set;
import org.apache.rya.indexing.GeoConstants;
import org.apache.rya.indexing.StatementConstraints;
import org.apache.rya.indexing.accumulo.ConfigUtils;
import org.apache.rya.indexing.accumulo.geo.OptionalConfigUtils;
import org.apache.rya.indexing.mongodb.geo.MongoGeoIndexer;
import org.apache.rya.mongodb.MongoDBRdfConfiguration;
import org.apache.rya.mongodb.MongoITBase;
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Resource;
import org.eclipse.rdf4j.model.Statement;
import org.eclipse.rdf4j.model.Value;
import org.eclipse.rdf4j.model.ValueFactory;
import org.eclipse.rdf4j.model.impl.SimpleValueFactory;
import org.junit.Test;
import com.google.common.collect.Sets;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LinearRing;
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;
public class MongoGeoIndexerIT extends MongoITBase {
private static final StatementConstraints EMPTY_CONSTRAINTS = new StatementConstraints();
GeometryFactory gf = new GeometryFactory(new PrecisionModel(), 4326);
@Override
public void updateConfiguration(final MongoDBRdfConfiguration conf) {
conf.set(ConfigUtils.GEO_PREDICATES_LIST, "http://www.opengis.net/ont/geosparql#asWKT");
conf.set(OptionalConfigUtils.USE_GEO, "true");
}
@Test
public void testRestrictPredicatesSearch() throws Exception {
try (final MongoGeoIndexer f = new MongoGeoIndexer()) {
conf.setStrings(ConfigUtils.GEO_PREDICATES_LIST, "pred:1,pred:2");
f.setConf(conf);
f.init();
final ValueFactory vf = SimpleValueFactory.getInstance();
final Point point = gf.createPoint(new Coordinate(10, 10));
final Value pointValue = vf.createLiteral("Point(10 10)", GeoConstants.XMLSCHEMA_OGC_WKT);
final IRI invalidPredicate = GeoConstants.GEO_AS_WKT;
// These should not be stored because they are not in the predicate list
f.storeStatement(convertStatement(vf.createStatement(vf.createIRI("foo:subj1"), invalidPredicate, pointValue)));
f.storeStatement(convertStatement(vf.createStatement(vf.createIRI("foo:subj2"), invalidPredicate, pointValue)));
final IRI pred1 = vf.createIRI("pred:1");
final IRI pred2 = vf.createIRI("pred:2");
// These should be stored because they are in the predicate list
final Statement s3 = vf.createStatement(vf.createIRI("foo:subj3"), pred1, pointValue);
final Statement s4 = vf.createStatement(vf.createIRI("foo:subj4"), pred2, pointValue);
f.storeStatement(convertStatement(s3));
f.storeStatement(convertStatement(s4));
// This should not be stored because the object is not valid wkt
f.storeStatement(convertStatement(vf.createStatement(vf.createIRI("foo:subj5"), pred1, vf.createLiteral("soint(10 10)"))));
// This should not be stored because the object is not a literal
f.storeStatement(convertStatement(vf.createStatement(vf.createIRI("foo:subj6"), pred1, vf.createIRI("p:Point(10 10)"))));
f.flush();
final Set<Statement> actual = getSet(f.queryEquals(point, EMPTY_CONSTRAINTS));
assertEquals(2, actual.size());
assertTrue(actual.contains(s3));
assertTrue(actual.contains(s4));
}
}
@Test
public void testPrimeMeridianSearch() throws Exception {
try (final MongoGeoIndexer f = new MongoGeoIndexer()) {
f.setConf(conf);
f.init();
final ValueFactory vf = SimpleValueFactory.getInstance();
final Resource subject = vf.createIRI("foo:subj");
final IRI predicate = GeoConstants.GEO_AS_WKT;
final Value object = vf.createLiteral("Point(0 0)", GeoConstants.XMLSCHEMA_OGC_WKT);
final Resource context = vf.createIRI("foo:context");
final Statement statement = vf.createStatement(subject, predicate, object, context);
f.storeStatement(convertStatement(statement));
f.flush();
final double[] ONE = { 1, 1, -1, 1, -1, -1, 1, -1, 1, 1 };
final double[] TWO = { 2, 2, -2, 2, -2, -2, 2, -2, 2, 2 };
final double[] THREE = { 3, 3, -3, 3, -3, -3, 3, -3, 3, 3 };
final LinearRing r1 = gf.createLinearRing(new PackedCoordinateSequence.Double(ONE, 2));
final LinearRing r2 = gf.createLinearRing(new PackedCoordinateSequence.Double(TWO, 2));
final LinearRing r3 = gf.createLinearRing(new PackedCoordinateSequence.Double(THREE, 2));
final Polygon p1 = gf.createPolygon(r1, new LinearRing[] {});
final Polygon p2 = gf.createPolygon(r2, new LinearRing[] {});
final Polygon p3 = gf.createPolygon(r3, new LinearRing[] {});
assertEquals(Sets.newHashSet(statement), getSet(f.queryWithin(p1, EMPTY_CONSTRAINTS)));
assertEquals(Sets.newHashSet(statement), getSet(f.queryWithin(p2, EMPTY_CONSTRAINTS)));
assertEquals(Sets.newHashSet(statement), getSet(f.queryWithin(p3, EMPTY_CONSTRAINTS)));
// Test a ring with a hole in it
final Polygon p3m2 = gf.createPolygon(r3, new LinearRing[] { r2 });
assertEquals(Sets.newHashSet(), getSet(f.queryWithin(p3m2, EMPTY_CONSTRAINTS)));
// test a ring outside the point
final double[] OUT = { 3, 3, 1, 3, 1, 1, 3, 1, 3, 3 };
final LinearRing rOut = gf.createLinearRing(new PackedCoordinateSequence.Double(OUT, 2));
final Polygon pOut = gf.createPolygon(rOut, new LinearRing[] {});
assertEquals(Sets.newHashSet(), getSet(f.queryWithin(pOut, EMPTY_CONSTRAINTS)));
}
}
@Test
public void testDcSearch() throws Exception {
// test a ring around dc
try (final MongoGeoIndexer f = new MongoGeoIndexer()) {
f.setConf(conf);
f.init();
final ValueFactory vf = SimpleValueFactory.getInstance();
final Resource subject = vf.createIRI("foo:subj");
final IRI predicate = GeoConstants.GEO_AS_WKT;
final Value object = vf.createLiteral("Point(-77.03524 38.889468)", GeoConstants.XMLSCHEMA_OGC_WKT);
final Resource context = vf.createIRI("foo:context");
final Statement statement = vf.createStatement(subject, predicate, object, context);
f.storeStatement(convertStatement(statement));
f.flush();
final double[] IN = { -78, 39, -77, 39, -77, 38, -78, 38, -78, 39 };
final LinearRing r1 = gf.createLinearRing(new PackedCoordinateSequence.Double(IN, 2));
final Polygon p1 = gf.createPolygon(r1, new LinearRing[] {});
assertEquals(Sets.newHashSet(statement), getSet(f.queryWithin(p1, EMPTY_CONSTRAINTS)));
// test a ring outside the point
final double[] OUT = { -77, 39, -76, 39, -76, 38, -77, 38, -77, 39 };
final LinearRing rOut = gf.createLinearRing(new PackedCoordinateSequence.Double(OUT, 2));
final Polygon pOut = gf.createPolygon(rOut, new LinearRing[] {});
assertEquals(Sets.newHashSet(), getSet(f.queryWithin(pOut, EMPTY_CONSTRAINTS)));
}
}
@Test
public void testDeleteSearch() throws Exception {
// test a ring around dc
try (final MongoGeoIndexer f = new MongoGeoIndexer()) {
f.setConf(conf);
f.init();
final ValueFactory vf = SimpleValueFactory.getInstance();
final Resource subject = vf.createIRI("foo:subj");
final IRI predicate = GeoConstants.GEO_AS_WKT;
final Value object = vf.createLiteral("Point(-77.03524 38.889468)", GeoConstants.XMLSCHEMA_OGC_WKT);
final Resource context = vf.createIRI("foo:context");
final Statement statement = vf.createStatement(subject, predicate, object, context);
f.storeStatement(convertStatement(statement));
f.flush();
f.deleteStatement(convertStatement(statement));
// test a ring that the point would be inside of if not deleted
final double[] in = { -78, 39, -77, 39, -77, 38, -78, 38, -78, 39 };
final LinearRing r1 = gf.createLinearRing(new PackedCoordinateSequence.Double(in, 2));
final Polygon p1 = gf.createPolygon(r1, new LinearRing[] {});
assertEquals(Sets.newHashSet(), getSet(f.queryWithin(p1, EMPTY_CONSTRAINTS)));
// test a ring that the point would be outside of if not deleted
final double[] out = { -77, 39, -76, 39, -76, 38, -77, 38, -77, 39 };
final LinearRing rOut = gf.createLinearRing(new PackedCoordinateSequence.Double(out, 2));
final Polygon pOut = gf.createPolygon(rOut, new LinearRing[] {});
assertEquals(Sets.newHashSet(), getSet(f.queryWithin(pOut, EMPTY_CONSTRAINTS)));
// test a ring for the whole world and make sure the point is gone
// Geomesa is a little sensitive around lon 180, so we only go to 179
final double[] world = { -180, 90, 179, 90, 179, -90, -180, -90, -180, 90 };
final LinearRing rWorld = gf.createLinearRing(new PackedCoordinateSequence.Double(world, 2));
final Polygon pWorld = gf.createPolygon(rWorld, new LinearRing[] {});
assertEquals(Sets.newHashSet(), getSet(f.queryWithin(pWorld, EMPTY_CONSTRAINTS)));
}
}
@Test
public void testDcSearchWithContext() throws Exception {
// test a ring around dc
try (final MongoGeoIndexer f = new MongoGeoIndexer()) {
f.setConf(conf);
f.init();
final ValueFactory vf = SimpleValueFactory.getInstance();
final Resource subject = vf.createIRI("foo:subj");
final IRI predicate = GeoConstants.GEO_AS_WKT;
final Value object = vf.createLiteral("Point(-77.03524 38.889468)", GeoConstants.XMLSCHEMA_OGC_WKT);
final Resource context = vf.createIRI("foo:context");
final Statement statement = vf.createStatement(subject, predicate, object, context);
f.storeStatement(convertStatement(statement));
f.flush();
final double[] IN = { -78, 39, -77, 39, -77, 38, -78, 38, -78, 39 };
final LinearRing r1 = gf.createLinearRing(new PackedCoordinateSequence.Double(IN, 2));
final Polygon p1 = gf.createPolygon(r1, new LinearRing[] {});
// query with correct context
assertEquals(Sets.newHashSet(statement), getSet(f.queryWithin(p1, new StatementConstraints().setContext(context))));
// query with wrong context
assertEquals(Sets.newHashSet(),
getSet(f.queryWithin(p1, new StatementConstraints().setContext(vf.createIRI("foo:context2")))));
}
}
@Test
public void testDcSearchWithSubject() throws Exception {
// test a ring around dc
try (final MongoGeoIndexer f = new MongoGeoIndexer()) {
f.setConf(conf);
f.init();
final ValueFactory vf = SimpleValueFactory.getInstance();
final Resource subject = vf.createIRI("foo:subj");
final IRI predicate = GeoConstants.GEO_AS_WKT;
final Value object = vf.createLiteral("Point(-77.03524 38.889468)", GeoConstants.XMLSCHEMA_OGC_WKT);
final Resource context = vf.createIRI("foo:context");
final Statement statement = vf.createStatement(subject, predicate, object, context);
f.storeStatement(convertStatement(statement));
f.flush();
final double[] IN = { -78, 39, -77, 39, -77, 38, -78, 38, -78, 39 };
final LinearRing r1 = gf.createLinearRing(new PackedCoordinateSequence.Double(IN, 2));
final Polygon p1 = gf.createPolygon(r1, new LinearRing[] {});
// query with correct subject
assertEquals(Sets.newHashSet(statement), getSet(f.queryWithin(p1, new StatementConstraints().setSubject(subject))));
// query with wrong subject
assertEquals(Sets.newHashSet(), getSet(f.queryWithin(p1, new StatementConstraints().setSubject(vf.createIRI("foo:subj2")))));
}
}
@Test
public void testDcSearchWithSubjectAndContext() throws Exception {
// test a ring around dc
try (final MongoGeoIndexer f = new MongoGeoIndexer()) {
f.setConf(conf);
f.init();
final ValueFactory vf = SimpleValueFactory.getInstance();
final Resource subject = vf.createIRI("foo:subj");
final IRI predicate = GeoConstants.GEO_AS_WKT;
final Value object = vf.createLiteral("Point(-77.03524 38.889468)", GeoConstants.XMLSCHEMA_OGC_WKT);
final Resource context = vf.createIRI("foo:context");
final Statement statement = vf.createStatement(subject, predicate, object, context);
f.storeStatement(convertStatement(statement));
f.flush();
final double[] IN = { -78, 39, -77, 39, -77, 38, -78, 38, -78, 39 };
final LinearRing r1 = gf.createLinearRing(new PackedCoordinateSequence.Double(IN, 2));
final Polygon p1 = gf.createPolygon(r1, new LinearRing[] {});
// query with correct context subject
assertEquals(Sets.newHashSet(statement),
getSet(f.queryWithin(p1, new StatementConstraints().setContext(context).setSubject(subject))));
// query with wrong context
assertEquals(Sets.newHashSet(),
getSet(f.queryWithin(p1, new StatementConstraints().setContext(vf.createIRI("foo:context2")))));
// query with wrong subject
assertEquals(Sets.newHashSet(), getSet(f.queryWithin(p1, new StatementConstraints().setSubject(vf.createIRI("foo:subj2")))));
}
}
@Test
public void testDcSearchWithPredicate() throws Exception {
// test a ring around dc
try (final MongoGeoIndexer f = new MongoGeoIndexer()) {
f.setConf(conf);
f.init();
final ValueFactory vf = SimpleValueFactory.getInstance();
final Resource subject = vf.createIRI("foo:subj");
final IRI predicate = GeoConstants.GEO_AS_WKT;
final Value object = vf.createLiteral("Point(-77.03524 38.889468)", GeoConstants.XMLSCHEMA_OGC_WKT);
final Resource context = vf.createIRI("foo:context");
final Statement statement = vf.createStatement(subject, predicate, object, context);
f.storeStatement(convertStatement(statement));
f.flush();
final double[] IN = { -78, 39, -77, 39, -77, 38, -78, 38, -78, 39 };
final LinearRing r1 = gf.createLinearRing(new PackedCoordinateSequence.Double(IN, 2));
final Polygon p1 = gf.createPolygon(r1, new LinearRing[] {});
// query with correct Predicate
assertEquals(Sets.newHashSet(statement),
getSet(f.queryWithin(p1, new StatementConstraints().setPredicates(Collections.singleton(predicate)))));
// query with wrong predicate
assertEquals(Sets.newHashSet(),
getSet(f.queryWithin(p1, new StatementConstraints().setPredicates(Collections.singleton(vf.createIRI("other:pred"))))));
}
}
// @Test
public void testAntiMeridianSearch() throws Exception {
// verify that a search works if the bounding box crosses the anti meridian
try (final MongoGeoIndexer f = new MongoGeoIndexer()) {
f.setConf(conf);
f.init();
final ValueFactory vf = SimpleValueFactory.getInstance();
final Resource context = vf.createIRI("foo:context");
final Resource subjectEast = vf.createIRI("foo:subj:east");
final IRI predicateEast = GeoConstants.GEO_AS_WKT;
final Value objectEast = vf.createLiteral("Point(179 0)", GeoConstants.XMLSCHEMA_OGC_WKT);
final Statement statementEast = vf.createStatement(subjectEast, predicateEast, objectEast, context);
f.storeStatement(convertStatement(statementEast));
final Resource subjectWest = vf.createIRI("foo:subj:west");
final IRI predicateWest = GeoConstants.GEO_AS_WKT;
final Value objectWest = vf.createLiteral("Point(-179 0)", GeoConstants.XMLSCHEMA_OGC_WKT);
final Statement statementWest = vf.createStatement(subjectWest, predicateWest, objectWest, context);
f.storeStatement(convertStatement(statementWest));
f.flush();
final double[] ONE = { 178.1, 1, -178, 1, -178, -1, 178.1, -1, 178.1, 1 };
final LinearRing r1 = gf.createLinearRing(new PackedCoordinateSequence.Double(ONE, 2));
final Polygon p1 = gf.createPolygon(r1, new LinearRing[] {});
assertEquals(Sets.newHashSet(statementEast, statementWest), getSet(f.queryWithin(p1, EMPTY_CONSTRAINTS)));
}
}
}