jenkins-bot has submitted this change and it was merged.
Change subject: Add support for wktLiteral parsing
......................................................................
Add support for wktLiteral parsing
Bug: T123612
Change-Id: I9931a584c5aaa7a8cd22e31c94eca2cff5baae15
---
M blazegraph/pom.xml
M
blazegraph/src/main/java/com/bigdata/rdf/internal/NormalizingInlineUriHandler.java
M
blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/WikibaseContextListener.java
M
blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/WikibaseExtensionFactory.java
M
blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/WikibaseInlineUriFactory.java
M
blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/WikibaseVocabulary.java
A
blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/geo/GeoAroundService.java
A
blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/geo/GeoBoxService.java
A blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/geo/GeoService.java
A
blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/inline/literal/WKTSerializer.java
M
blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/inline/uri/ValuePropertiesInlineUriHandler.java
M
blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/inline/uri/WikibaseStyleStatementInlineUriHandler.java
M
blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/label/LabelService.java
A
blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/vocabulary/GeoSparqlVocabularyDecl.java
M
blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/vocabulary/ProvenanceVocabularyDecl.java
M
blazegraph/src/test/java/org/wikidata/query/rdf/blazegraph/AbstractRandomizedBlazegraphStorageTestCase.java
M
blazegraph/src/test/java/org/wikidata/query/rdf/blazegraph/AbstractRandomizedBlazegraphTestBase.java
A
blazegraph/src/test/java/org/wikidata/query/rdf/blazegraph/WikibaseGeoUnitTest.java
M common/src/main/java/org/wikidata/query/rdf/common/WikibasePoint.java
M common/src/test/java/org/wikidata/query/rdf/common/WikibasePointUnitTest.java
M dist/src/script/RWStore.properties
M dist/src/script/runBlazegraph.sh
M pom.xml
M testTools/src/main/java/org/wikidata/query/rdf/test/Matchers.java
M testTools/src/main/java/org/wikidata/query/rdf/test/StatementHelper.java
A
tools/src/test/java/org/wikidata/query/rdf/tool/WikibaseGeoExtensionIntegrationTest.java
M tools/src/test/java/org/wikidata/query/rdf/tool/rdf/MungerUnitTest.java
M tools/src/test/resources/blazegraph/RWStore.properties
28 files changed, 848 insertions(+), 32 deletions(-)
Approvals:
Smalyshev: Looks good to me, approved
jenkins-bot: Verified
diff --git a/blazegraph/pom.xml b/blazegraph/pom.xml
index de48f58..550ca38 100644
--- a/blazegraph/pom.xml
+++ b/blazegraph/pom.xml
@@ -32,8 +32,7 @@
<!-- Blazegraph needs http client to run services. -->
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-client</artifactId>
- <version>9.2.10.v20150310</version>
- <scope>test</scope>
+ <version>${jetty.version}</version>
</dependency>
<dependency>
<groupId>org.wikidata.query.rdf</groupId>
diff --git
a/blazegraph/src/main/java/com/bigdata/rdf/internal/NormalizingInlineUriHandler.java
b/blazegraph/src/main/java/com/bigdata/rdf/internal/NormalizingInlineUriHandler.java
index 3aae2ac..c715ea1 100644
---
a/blazegraph/src/main/java/com/bigdata/rdf/internal/NormalizingInlineUriHandler.java
+++
b/blazegraph/src/main/java/com/bigdata/rdf/internal/NormalizingInlineUriHandler.java
@@ -38,7 +38,7 @@
@Override
@SuppressWarnings({"unchecked", "rawtypes"})
- protected URIExtensionIV createInlineIV(URI uri) {
+ public URIExtensionIV createInlineIV(URI uri) {
String prefix = getNamespace();
if (uri.stringValue().startsWith(prefix)) {
AbstractLiteralIV localNameIv =
next.createInlineIV(uri.stringValue().substring(prefix.length()));
diff --git
a/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/WikibaseContextListener.java
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/WikibaseContextListener.java
index e4ebc30..0cd9293 100644
---
a/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/WikibaseContextListener.java
+++
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/WikibaseContextListener.java
@@ -8,7 +8,9 @@
import org.slf4j.LoggerFactory;
import org.wikidata.query.rdf.blazegraph.constraints.WikibaseDateBOp;
import org.wikidata.query.rdf.blazegraph.constraints.WikibaseNowBOp;
+import org.wikidata.query.rdf.blazegraph.geo.GeoService;
import org.wikidata.query.rdf.blazegraph.label.LabelService;
+import org.wikidata.query.rdf.common.uri.GeoSparql;
import org.wikidata.query.rdf.common.uri.OWL;
import org.wikidata.query.rdf.common.uri.Ontology;
import org.wikidata.query.rdf.common.uri.Provenance;
@@ -49,6 +51,7 @@
public static void initializeServices() {
ServiceRegistry.getInstance().setDefaultServiceFactory(new
DisableRemotesServiceFactory());
LabelService.register();
+ GeoService.register();
// Override date functions so that we can handle them
// via WikibaseDate
@@ -81,7 +84,7 @@
return new WikibaseNowBOp(globals);
}
});
- addPrefixes(WikibaseUris.WIKIDATA);
+ addPrefixes(WikibaseUris.getURISystem());
log.warn("Wikibase services initialized.");
}
@@ -106,6 +109,7 @@
defaultDecls.put("prov", Provenance.NAMESPACE);
defaultDecls.put("skos", SKOS.NAMESPACE);
defaultDecls.put("owl", OWL.NAMESPACE);
+ defaultDecls.put("geo", GeoSparql.NAMESPACE);
}
@Override
diff --git
a/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/WikibaseExtensionFactory.java
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/WikibaseExtensionFactory.java
index 3eed04f..816542d 100644
---
a/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/WikibaseExtensionFactory.java
+++
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/WikibaseExtensionFactory.java
@@ -3,8 +3,9 @@
import java.util.Collection;
import java.util.Iterator;
-//import org.slf4j.Logger;
-//import org.slf4j.LoggerFactory;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.wikidata.query.rdf.blazegraph.inline.literal.WikibaseDateExtension;
import com.bigdata.rdf.internal.DefaultExtensionFactory;
@@ -19,7 +20,7 @@
* Setup inline value extensions to Blazegraph for Wikidata.
*/
public class WikibaseExtensionFactory extends DefaultExtensionFactory {
- // private static final Logger log =
LoggerFactory.getLogger(WikibaseExtensionFactory.class);
+ private static final Logger log =
LoggerFactory.getLogger(WikibaseExtensionFactory.class);
@Override
@SuppressWarnings("rawtypes")
@@ -33,7 +34,8 @@
}
}
extensions.add(new
WikibaseDateExtension<BigdataLiteral>(resolver));
- // log.warn("Installed Wikidata date extensions");
}
+ // extensions.add(new WikibaseGeoExtension<BigdataLiteral>(resolver));
+ // log.warn("Installed Wikidata date extensions");
}
}
diff --git
a/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/WikibaseInlineUriFactory.java
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/WikibaseInlineUriFactory.java
index cb65723..c148491 100644
---
a/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/WikibaseInlineUriFactory.java
+++
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/WikibaseInlineUriFactory.java
@@ -29,9 +29,7 @@
*/
public class WikibaseInlineUriFactory extends InlineURIFactory {
public WikibaseInlineUriFactory() {
- // TODO lookup wikibase host and default to wikidata
- final WikibaseUris uris = WikibaseUris.WIKIDATA;
-
+ WikibaseUris uris = WikibaseUris.getURISystem();
/*
* Order matters here because some of these are prefixes of each other.
*/
diff --git
a/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/WikibaseVocabulary.java
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/WikibaseVocabulary.java
index 6ab30cc..796f303 100644
---
a/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/WikibaseVocabulary.java
+++
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/WikibaseVocabulary.java
@@ -1,6 +1,7 @@
package org.wikidata.query.rdf.blazegraph;
import org.wikidata.query.rdf.blazegraph.vocabulary.CommonValuesVocabularyDecl;
+import org.wikidata.query.rdf.blazegraph.vocabulary.GeoSparqlVocabularyDecl;
import org.wikidata.query.rdf.blazegraph.vocabulary.OntologyVocabularyDecl;
import org.wikidata.query.rdf.blazegraph.vocabulary.ProvenanceVocabularyDecl;
import org.wikidata.query.rdf.blazegraph.vocabulary.SchemaDotOrgVocabularyDecl;
@@ -8,7 +9,7 @@
import org.wikidata.query.rdf.common.uri.WikibaseUris;
import com.bigdata.rdf.vocab.DefaultBigdataVocabulary;
-import com.bigdata.rdf.vocab.core.BigdataCoreVocabulary_v20151210;
+import com.bigdata.rdf.vocab.core.BigdataCoreVocabulary_v20160317;
/**
* Versioned vocabulary classes for wikibase. All classes need a namespace and
a
@@ -19,7 +20,7 @@
/**
* Current vocabulary class.
*/
- public static final Class VOCABULARY_CLASS = V001.class;
+ public static final Class VOCABULARY_CLASS = V002.class;
protected WikibaseVocabulary() {
// prevents calls from subclass
@@ -47,7 +48,7 @@
@Override
protected void addValues() {
// TODO lookup wikibase host and default to wikidata
- addDecl(new WikibaseUrisVocabularyDecl(WikibaseUris.WIKIDATA));
+ addDecl(new
WikibaseUrisVocabularyDecl(WikibaseUris.getURISystem()));
addDecl(new OntologyVocabularyDecl());
addDecl(new SchemaDotOrgVocabularyDecl());
addDecl(new ProvenanceVocabularyDecl());
@@ -57,10 +58,10 @@
}
/**
- * Class for BG 2.0.
- * Inherits different vocabulary
+ * Class for BG 2.0 with geospatial.
+ * Inherits different vocabulary and adds geospatial types.
*/
- public static class V002 extends BigdataCoreVocabulary_v20151210 {
+ public static class V002 extends BigdataCoreVocabulary_v20160317 {
public V002() {
}
@@ -71,11 +72,12 @@
@Override
protected void addValues() {
// TODO lookup wikibase host and default to wikidata
- addDecl(new WikibaseUrisVocabularyDecl(WikibaseUris.WIKIDATA));
+ addDecl(new
WikibaseUrisVocabularyDecl(WikibaseUris.getURISystem()));
addDecl(new OntologyVocabularyDecl());
addDecl(new SchemaDotOrgVocabularyDecl());
addDecl(new ProvenanceVocabularyDecl());
addDecl(new CommonValuesVocabularyDecl());
+ addDecl(new GeoSparqlVocabularyDecl());
super.addValues();
}
}
diff --git
a/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/geo/GeoAroundService.java
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/geo/GeoAroundService.java
new file mode 100644
index 0000000..e432b06
--- /dev/null
+++
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/geo/GeoAroundService.java
@@ -0,0 +1,116 @@
+package org.wikidata.query.rdf.blazegraph.geo;
+
+import org.openrdf.model.URI;
+import org.openrdf.model.impl.URIImpl;
+import org.wikidata.query.rdf.common.uri.GeoSparql;
+import org.wikidata.query.rdf.common.uri.Ontology;
+
+import com.bigdata.rdf.model.BigdataValueFactory;
+import com.bigdata.rdf.sparql.ast.ConstantNode;
+import com.bigdata.rdf.sparql.ast.DummyConstantNode;
+import com.bigdata.rdf.sparql.ast.JoinGroupNode;
+import com.bigdata.rdf.sparql.ast.StatementPatternNode;
+import com.bigdata.rdf.sparql.ast.TermNode;
+import com.bigdata.rdf.sparql.ast.eval.ServiceParams;
+import com.bigdata.rdf.sparql.ast.service.ServiceCallCreateParams;
+import com.bigdata.rdf.store.AbstractTripleStore;
+import com.bigdata.rdf.vocab.Vocabulary;
+import com.bigdata.service.geospatial.GeoSpatial;
+import com.bigdata.service.geospatial.GeoSpatial.GeoFunction;
+
+/**
+ * Implements a service to do geospatial search.
+ *
+ * This class searches for items around certain point.
+ *
+ * Example:
+ *
+ * SELECT * WHERE {
+ * wd:Q90 wdt:P625 ?parisLoc .
+ *
+ * SERVICE wikibase:around {
+ * ?place wdt:P625 ?location .
+ * bd:serviceParam wikibase:center ?parisLoc .
+ * bd:serviceParam wikibase:radius "1" .
+ * }
+ * }
+ */
+public class GeoAroundService extends GeoService {
+
+ /**
+ * The URI service key.
+ */
+ public static final URI SERVICE_KEY = new URIImpl(
+ Ontology.NAMESPACE + "around");
+
+ /**
+ * wikibase:center parameter name.
+ */
+ public static final URIImpl CENTER_PARAM = new URIImpl(
+ Ontology.NAMESPACE + "center");
+
+ /**
+ * wikibase:radius parameter name.
+ */
+ public static final URIImpl RADIUS_PARAM = new URIImpl(
+ Ontology.NAMESPACE + "radius");
+
+ @Override
+ protected JoinGroupNode buildServiceNode(ServiceCallCreateParams params,
+ ServiceParams serviceParams) {
+ final AbstractTripleStore store = params.getTripleStore();
+ final Vocabulary voc = store.getVocabulary();
+ BigdataValueFactory vf = store.getValueFactory();
+
+ final StatementPatternNode pattern = getPatternNode(params);
+ final TermNode searchVar = pattern.s();
+ final TermNode predicate = pattern.p();
+ final TermNode locationVar = pattern.o();
+
+ final JoinGroupNode newGroup = new JoinGroupNode();
+ // ?var geo:search "inCircle" .
+ newGroup.addArg(new StatementPatternNode(
+ searchVar,
+ new DummyConstantNode(vf.asValue(GeoSpatial.SEARCH)),
+ new
DummyConstantNode(vf.createLiteral(GeoFunction.IN_CIRCLE.toString()))
+ ));
+ // ?var geo:predicate wdt:P625 .
+ newGroup.addArg(new StatementPatternNode(
+ searchVar,
+ new
DummyConstantNode(vf.asValue(GeoSpatial.PREDICATE)),
+ predicate
+ ));
+ // ?var geo:searchDatatype ogc:wktLiteral .
+ newGroup.addArg(new StatementPatternNode(
+ searchVar,
+ new
DummyConstantNode(vf.asValue(GeoSpatial.SEARCH_DATATYPE)),
+ new ConstantNode(
+ voc.getConstant(new
URIImpl(GeoSparql.WKT_LITERAL)))));
+
+ // ?var geo:spatialCircleCenter ?parisLoc .
+ newGroup.addArg(new StatementPatternNode(
+ searchVar,
+ new
DummyConstantNode(vf.asValue(GeoSpatial.SPATIAL_CIRCLE_CENTER)),
+ getParam(serviceParams, CENTER_PARAM)
+ ));
+ // ?var geo:spatialCircleRadius "1" .
+ newGroup.addArg(new StatementPatternNode(
+ searchVar,
+ new
DummyConstantNode(vf.asValue(GeoSpatial.SPATIAL_CIRCLE_RADIUS)),
+ getParam(serviceParams, RADIUS_PARAM)
+ ));
+ // ?var geo:locationValue ?location .
+ newGroup.addArg(new StatementPatternNode(
+ searchVar,
+ new
DummyConstantNode(vf.asValue(GeoSpatial.LOCATION_VALUE)),
+ locationVar));
+ // ?var geo:coordSystem "0" .
+ newGroup.addArg(new StatementPatternNode(
+ searchVar,
+ new
DummyConstantNode(vf.asValue(GeoSpatial.COORD_SYSTEM)),
+ getGlobeNode(vf, serviceParams)
+ ));
+
+ return newGroup;
+ }
+}
diff --git
a/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/geo/GeoBoxService.java
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/geo/GeoBoxService.java
new file mode 100644
index 0000000..fa87f9b
--- /dev/null
+++
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/geo/GeoBoxService.java
@@ -0,0 +1,116 @@
+package org.wikidata.query.rdf.blazegraph.geo;
+
+import org.openrdf.model.URI;
+import org.openrdf.model.impl.URIImpl;
+import org.wikidata.query.rdf.common.uri.GeoSparql;
+import org.wikidata.query.rdf.common.uri.Ontology;
+
+import com.bigdata.rdf.model.BigdataValueFactory;
+import com.bigdata.rdf.sparql.ast.ConstantNode;
+import com.bigdata.rdf.sparql.ast.DummyConstantNode;
+import com.bigdata.rdf.sparql.ast.JoinGroupNode;
+import com.bigdata.rdf.sparql.ast.StatementPatternNode;
+import com.bigdata.rdf.sparql.ast.TermNode;
+import com.bigdata.rdf.sparql.ast.eval.ServiceParams;
+import com.bigdata.rdf.sparql.ast.service.ServiceCallCreateParams;
+import com.bigdata.rdf.store.AbstractTripleStore;
+import com.bigdata.rdf.vocab.Vocabulary;
+import com.bigdata.service.geospatial.GeoSpatial;
+import com.bigdata.service.geospatial.GeoSpatial.GeoFunction;
+
+/**
+ * Implements a service to do geospatial search.
+ *
+ * This class searches for items around certain point.
+ *
+ * Example:
+ *
+ * SELECT * WHERE {
+ * wd:Q90 wdt:P625 ?parisLoc .
+ *
+ * SERVICE wikibase:box {
+ * ?place wdt:P625 ?location .
+ * bd:serviceParam wikibase:cornerSouthWest "Point(48.0
2.0)"^^ogc:wktLiteral .
+ * bd:serviceParam wikibase:cornerNorthEast "Point(49.0
3.0)"^^ogc:wktLiteral .
+ * }
+ * }
+ */
+public class GeoBoxService extends GeoService {
+
+ /**
+ * The URI service key.
+ */
+ public static final URI SERVICE_KEY = new URIImpl(
+ Ontology.NAMESPACE + "box");
+
+ /**
+ * wikibase:center parameter name.
+ */
+ public static final URIImpl NE_PARAM = new URIImpl(
+ Ontology.NAMESPACE + "cornerNorthEast");
+
+ /**
+ * wikibase:radius parameter name.
+ */
+ public static final URIImpl SW_PARAM = new URIImpl(
+ Ontology.NAMESPACE + "cornerSouthWest");
+
+ @Override
+ protected JoinGroupNode buildServiceNode(ServiceCallCreateParams params,
+ ServiceParams serviceParams) {
+ final AbstractTripleStore store = params.getTripleStore();
+ final Vocabulary voc = store.getVocabulary();
+ BigdataValueFactory vf = store.getValueFactory();
+
+ final StatementPatternNode pattern = getPatternNode(params);
+ final TermNode searchVar = pattern.s();
+ final TermNode predicate = pattern.p();
+ final TermNode locationVar = pattern.o();
+
+ final JoinGroupNode newGroup = new JoinGroupNode();
+ // ?var geo:search "inCircle" .
+ newGroup.addArg(new StatementPatternNode(
+ searchVar,
+ new DummyConstantNode(vf.asValue(GeoSpatial.SEARCH)),
+ new
DummyConstantNode(vf.createLiteral(GeoFunction.IN_RECTANGLE.toString()))
+ ));
+ // ?var geo:predicate wdt:P625 .
+ newGroup.addArg(new StatementPatternNode(
+ searchVar,
+ new
DummyConstantNode(vf.asValue(GeoSpatial.PREDICATE)),
+ predicate
+ ));
+ // ?var geo:searchDatatype ogc:wktLiteral .
+ newGroup.addArg(new StatementPatternNode(
+ searchVar,
+ new
DummyConstantNode(vf.asValue(GeoSpatial.SEARCH_DATATYPE)),
+ new ConstantNode(
+ voc.getConstant(new
URIImpl(GeoSparql.WKT_LITERAL)))));
+
+ // ?var geo:spatialCircleCenter ?parisLoc .
+ newGroup.addArg(new StatementPatternNode(
+ searchVar,
+ new
DummyConstantNode(vf.asValue(GeoSpatial.SPATIAL_RECTANGLE_NORTH_EAST)),
+ getParam(serviceParams, NE_PARAM)
+ ));
+ // ?var geo:spatialCircleRadius "1" .
+ newGroup.addArg(new StatementPatternNode(
+ searchVar,
+ new
DummyConstantNode(vf.asValue(GeoSpatial.SPATIAL_RECTANGLE_SOUTH_WEST)),
+ getParam(serviceParams, SW_PARAM)
+ ));
+ // ?var geo:locationValue ?location .
+ newGroup.addArg(new StatementPatternNode(
+ searchVar,
+ new
DummyConstantNode(vf.asValue(GeoSpatial.LOCATION_VALUE)),
+ locationVar));
+ // ?var geo:coordSystem "2" .
+ newGroup.addArg(new StatementPatternNode(
+ searchVar,
+ new
DummyConstantNode(vf.asValue(GeoSpatial.COORD_SYSTEM)),
+ getGlobeNode(vf, serviceParams)
+ ));
+
+ return newGroup;
+ }
+}
diff --git
a/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/geo/GeoService.java
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/geo/GeoService.java
new file mode 100644
index 0000000..f781b5b
--- /dev/null
+++
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/geo/GeoService.java
@@ -0,0 +1,234 @@
+package org.wikidata.query.rdf.blazegraph.geo;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.jetty.client.HttpClient;
+import org.openrdf.model.URI;
+import org.openrdf.model.impl.URIImpl;
+import org.wikidata.query.rdf.blazegraph.inline.literal.WKTSerializer;
+import org.wikidata.query.rdf.common.uri.Ontology;
+import com.bigdata.bop.IVariable;
+import com.bigdata.bop.IVariableOrConstant;
+import com.bigdata.rdf.model.BigdataURI;
+import com.bigdata.rdf.model.BigdataValue;
+import com.bigdata.rdf.model.BigdataValueFactory;
+import com.bigdata.rdf.sparql.ast.DummyConstantNode;
+import com.bigdata.rdf.sparql.ast.IGroupMemberNode;
+import com.bigdata.rdf.sparql.ast.JoinGroupNode;
+import com.bigdata.rdf.sparql.ast.StatementPatternNode;
+import com.bigdata.rdf.sparql.ast.TermNode;
+import com.bigdata.rdf.sparql.ast.eval.AbstractServiceFactory;
+import com.bigdata.rdf.sparql.ast.eval.GeoSpatialServiceFactory;
+import com.bigdata.rdf.sparql.ast.eval.ServiceParams;
+import com.bigdata.rdf.sparql.ast.service.BigdataServiceCall;
+import com.bigdata.rdf.sparql.ast.service.IServiceOptions;
+import com.bigdata.rdf.sparql.ast.service.ServiceCallCreateParams;
+import com.bigdata.rdf.sparql.ast.service.ServiceNode;
+import com.bigdata.rdf.sparql.ast.service.ServiceRegistry;
+import com.bigdata.rdf.store.BD;
+import com.bigdata.service.geospatial.GeoSpatial;
+import com.bigdata.service.geospatial.GeoSpatialSearchException;
+
+/**
+ * Implements a service to do geospatial search.
+ * Base class for geospatial search wrappers.
+ */
+@SuppressWarnings("checkstyle:classfanoutcomplexity")
+public abstract class GeoService extends AbstractServiceFactory {
+
+ /**
+ * Delegate Blazegraph geosearch service.
+ */
+ private final GeoSpatialServiceFactory blazegraphService;
+
+ /**
+ * wikibase:globe parameter name.
+ */
+ public static final URIImpl GLOBE_PARAM = new URIImpl(
+ Ontology.NAMESPACE + "globe");
+
+ public GeoService() {
+ super();
+ blazegraphService = new GeoSpatialServiceFactory();
+ }
+
+ /**
+ * Register the service so it is recognized by Blazegraph.
+ */
+ public static void register() {
+ ServiceRegistry.getInstance().add(GeoAroundService.SERVICE_KEY, new
GeoAroundService());
+ ServiceRegistry.getInstance().add(GeoBoxService.SERVICE_KEY, new
GeoBoxService());
+ }
+
+ @Override
+ public IServiceOptions getServiceOptions() {
+ return blazegraphService.getServiceOptions();
+ }
+
+ /**
+ * Get service parameter by name.
+ *
+ * @param serviceParams
+ * @param paramName
+ * @return
+ */
+ protected TermNode getParam(ServiceParams serviceParams, URI paramName) {
+ TermNode node = serviceParams.get(paramName, null);
+ if (node == null) {
+ throw new IllegalArgumentException("Parameter " + paramName
+ + " is required.");
+ }
+ return node;
+ }
+
+ /**
+ * Create service parameters for delegate service call.
+ * @param params
+ * @param serviceParams
+ * @return
+ */
+ protected abstract JoinGroupNode buildServiceNode(ServiceCallCreateParams
params,
+ ServiceParams serviceParams);
+
+ /**
+ * Create globe node with appropriate value for coordSystem.
+ * @param vf
+ * @param serviceParams
+ * @return
+ */
+ protected TermNode getGlobeNode(BigdataValueFactory vf, ServiceParams
serviceParams) {
+ final TermNode globeNode = serviceParams.get(GLOBE_PARAM, null);
+ if (globeNode == null) {
+ return new
DummyConstantNode(vf.createLiteral(WKTSerializer.NO_GLOBE));
+ }
+ if (!globeNode.isConstant()) {
+ // FIXME: add support for this
+ throw new IllegalArgumentException("Non-constant globe value is
not supported yet.");
+ }
+ BigdataValue v = globeNode.getValue();
+ if (v instanceof BigdataURI) {
+ WKTSerializer ser = new WKTSerializer();
+ try {
+ return new
DummyConstantNode(vf.createLiteral(ser.trimCoordURI(v.stringValue())));
+ } catch (GeoSpatialSearchException e) {
+ // Unexpectedly wrong URI - still pass it along
+ return globeNode;
+ }
+ }
+ return globeNode;
+ }
+
+ /**
+ * Extract pattern node from parameters.
+ *
+ * Pattern node looks like:
+ * ?place wdt:P625 ?location .
+ * Both variables would be bound by the service.
+ * @param params
+ * @return
+ */
+ protected StatementPatternNode getPatternNode(ServiceCallCreateParams
params) {
+ ServiceNode serviceNode = params.getServiceNode();
+ if (serviceNode == null)
+ throw new IllegalArgumentException();
+
+ List<StatementPatternNode> patterns =
getStatementPatterns(serviceNode);
+
+ if (patterns.size() == 0) {
+ throw new IllegalArgumentException("This service requires
arguments");
+ }
+
+ StatementPatternNode pattern = patterns.get(0);
+
+ if (pattern == null) {
+ throw new IllegalArgumentException();
+ }
+
+ if (!pattern.s().isVariable()) {
+ throw new IllegalArgumentException(
+ "Search pattern subject must be a variable");
+ }
+
+ if (!pattern.p().isConstant()) {
+ // FIXME: may be not necessary?
+ throw new IllegalArgumentException(
+ "Search pattern predicate must be a constant");
+ }
+
+ if (!pattern.o().isVariable()) {
+ throw new IllegalArgumentException(
+ "Search pattern object must be a variable");
+ }
+
+ return pattern;
+ }
+
+ @Override
+ public BigdataServiceCall create(ServiceCallCreateParams params,
+ ServiceParams serviceParams) {
+ if (params == null)
+ throw new IllegalArgumentException();
+
+ final JoinGroupNode newGroup = buildServiceNode(params, serviceParams);
+ final BigdataValueFactory vf =
params.getTripleStore().getValueFactory();
+
+ ServiceNode newServiceNode = new ServiceNode(
+ new DummyConstantNode(vf.asValue(GeoSpatial.SEARCH)),
newGroup);
+
+ // Call delegate service
+ HttpClient client = params.getClientConnectionManager();
+ return (BigdataServiceCall)
ServiceRegistry.getInstance().toServiceCall(
+ params.getTripleStore(), client,
+ GeoSpatial.SEARCH, newServiceNode, params.getStats());
+ }
+
+ /**
+ * Returns the statement patterns contained in the service node.
+ *
+ * @param serviceNode
+ * @return
+ */
+ protected List<StatementPatternNode> getStatementPatterns(final
ServiceNode serviceNode) {
+
+ final List<StatementPatternNode> statementPatterns =
+ new ArrayList<StatementPatternNode>();
+
+ for (IGroupMemberNode child : serviceNode.getGraphPattern()) {
+
+ if (child instanceof StatementPatternNode) {
+ statementPatterns.add((StatementPatternNode)child);
+ } else {
+ throw new GeoSpatialSearchException("Nested groups are not
allowed.");
+ }
+ }
+
+ return statementPatterns;
+ }
+
+ @Override
+ public Set<IVariable<?>> getRequiredBound(final ServiceNode serviceNode) {
+ /**
+ * This method extracts exactly those variables that are incoming,
+ * i.e. must be bound before executing the execution of the service.
+ *
+ * Those can be only in service parameters.
+ */
+ final Set<IVariable<?>> requiredBound = new HashSet<IVariable<?>>();
+ for (StatementPatternNode sp : getStatementPatterns(serviceNode)) {
+
+ final TermNode subj = sp.s();
+ final IVariableOrConstant<?> object = sp.o().getValueExpression();
+
+ if (subj.isConstant() && BD.SERVICE_PARAM.equals(subj.getValue()))
{
+ if (object instanceof IVariable<?>) {
+ requiredBound.add((IVariable<?>)object); // the subject
var is what we return
+ }
+ }
+ }
+
+ return requiredBound;
+ }
+}
diff --git
a/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/inline/literal/WKTSerializer.java
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/inline/literal/WKTSerializer.java
new file mode 100644
index 0000000..c39f0fd
--- /dev/null
+++
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/inline/literal/WKTSerializer.java
@@ -0,0 +1,142 @@
+package org.wikidata.query.rdf.blazegraph.inline.literal;
+
+import org.openrdf.model.URI;
+import org.openrdf.model.impl.URIImpl;
+import org.wikidata.query.rdf.common.WikibasePoint;
+import org.wikidata.query.rdf.common.WikibasePoint.CoordinateOrder;
+import org.wikidata.query.rdf.common.uri.GeoSparql;
+import org.wikidata.query.rdf.common.uri.WikibaseUris;
+
+import com.bigdata.rdf.internal.IV;
+import com.bigdata.rdf.internal.impl.literal.XSDNumericIV;
+import com.bigdata.rdf.model.BigdataValueFactory;
+import com.bigdata.rdf.sparql.ast.DummyConstantNode;
+import com.bigdata.service.geospatial.GeoSpatialSearchException;
+import com.bigdata.service.geospatial.IGeoSpatialLiteralSerializer;
+
+/**
+ * Serializer class for WKT format.
+ * See https://portal.opengeospatial.org/files/?artifact_id=47664
+ * and http://postgis.refractions.net/documentation/manual-1.3SVN/ch04.html
+ *
+ * Internal storage follows longitude-latitude order for this format.
+ */
+public class WKTSerializer implements IGeoSpatialLiteralSerializer {
+
+ /**
+ * Prefix for globe URIs.
+ */
+ private final String urlPrefix;
+
+ /**
+ * This is put in coordinate field when there's no globe.
+ */
+ public static final String NO_GLOBE = System.getProperty(
+ WKTSerializer.class.getName() + ".noGlobe", "0");
+
+ /**
+ * URI of the wkt literal datatype.
+ */
+ private static final URI WKT_LITERAL_URI = new
URIImpl(GeoSparql.WKT_LITERAL);
+
+ public WKTSerializer() {
+ // FIXME: we need a way to handle non-wikidata URIs
+ urlPrefix = WikibaseUris.getURISystem().entity() + "Q";
+ }
+
+ @Override
+ public String fromComponents(Object[] components) {
+ if (components == null)
+ return "";
+
+ if (components.length != 3)
+ throw new GeoSpatialSearchException(
+ "Expected component string of lenth 2, but was " +
components.length);
+
+ String[] strComponents = new String[3];
+ strComponents[0] = components[0].toString();
+ strComponents[1] = components[1].toString();
+ strComponents[2] = components[2].toString();
+
+ WikibasePoint point;
+ if (strComponents[2].equals(NO_GLOBE)) {
+ point = new WikibasePoint(strComponents, null,
CoordinateOrder.LONG_LAT);
+ } else {
+ point = new WikibasePoint(strComponents, urlPrefix +
strComponents[2], CoordinateOrder.LONG_LAT);
+ }
+
+ return point.toString();
+ }
+
+ /**
+ * Cut off prefix for the coordinate system URI.
+ * E.g. http://www.wikidata.org/entity/Q
+ * @param uri
+ * @return
+ */
+ public String trimCoordURI(String uri) {
+ if (!uri.startsWith(urlPrefix)) {
+ throw new GeoSpatialSearchException("Invalid coordinate URI for
the WKT value");
+ }
+ return uri.substring(urlPrefix.length());
+ }
+
+ @Override
+ public String[] toComponents(String literalString) {
+ if (literalString == null) {
+ return new String[0];
+ }
+
+ String[] comps = new String[3];
+ WikibasePoint point = new WikibasePoint(literalString);
+ // Should be in sync with RWStore.properties config
+ // and AbstractRandomizedBlazegraphStorageTestCase.java
+ comps[0] = point.getLongitude();
+ comps[1] = point.getLatitude();
+ String globe = point.getGlobe();
+ comps[2] = globe != null ? trimCoordURI(globe) : NO_GLOBE;
+
+ return comps;
+ }
+
+ @Override
+ public IV<?, ?> serializeCoordSystem(BigdataValueFactory vf, Object
coordinateSystem) {
+ // Returns URI with prefix, so you can match it with entities
+ return DummyConstantNode.toDummyIV(vf.createURI(urlPrefix +
coordinateSystem.toString()));
+ }
+
+ @Override
+ public IV<?, ?> serializeCustomFields(BigdataValueFactory vf, Object...
arg1) {
+ throw new IllegalArgumentException("Custom fields are not supported
for this format");
+ }
+
+ @Override
+ public IV<?, ?> serializeLatitude(BigdataValueFactory vf, Object latitude)
{
+ return new XSDNumericIV((Double)latitude);
+ }
+
+ @Override
+ public IV<?, ?> serializeLocation(BigdataValueFactory vf, Object lat,
Object lon) {
+ // FIXME: this does not look really useful. Maybe needs to produce
exception too.
+ WikibasePoint p = new WikibasePoint(new String[] {lat.toString(),
lon.toString()},
+ null, CoordinateOrder.LAT_LONG);
+ return DummyConstantNode.toDummyIV(vf.createLiteral(p.toString(),
WKT_LITERAL_URI));
+ }
+
+ @Override
+ public IV<?, ?> serializeLocationAndTime(BigdataValueFactory arg0,
+ Object arg1, Object arg2, Object arg3) {
+ throw new IllegalArgumentException("Time fields are not supported for
this format");
+ }
+
+ @Override
+ public IV<?, ?> serializeLongitude(BigdataValueFactory vf, Object
longitude) {
+ return new XSDNumericIV((Double)longitude);
+ }
+
+ @Override
+ public IV<?, ?> serializeTime(BigdataValueFactory arg0, Object arg1) {
+ throw new IllegalArgumentException("Time fields are not supported for
this format");
+ }
+
+}
diff --git
a/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/inline/uri/ValuePropertiesInlineUriHandler.java
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/inline/uri/ValuePropertiesInlineUriHandler.java
index aa54cc7..d7f7a8e 100644
---
a/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/inline/uri/ValuePropertiesInlineUriHandler.java
+++
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/inline/uri/ValuePropertiesInlineUriHandler.java
@@ -11,6 +11,7 @@
* InlineURIHandler for value and qualifier properties. Can't just use
* InlineUnsignedIntegerURIHandler because values can end in -value. Those we
* represent as negative numbers.
+ * @deprecated
*/
public class ValuePropertiesInlineUriHandler extends InlineURIHandler {
/**
diff --git
a/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/inline/uri/WikibaseStyleStatementInlineUriHandler.java
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/inline/uri/WikibaseStyleStatementInlineUriHandler.java
index 52f3010..1c158a4 100644
---
a/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/inline/uri/WikibaseStyleStatementInlineUriHandler.java
+++
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/inline/uri/WikibaseStyleStatementInlineUriHandler.java
@@ -26,6 +26,7 @@
* statements to get scattered along the index which causes mighty right
* amplification during loads and updates and probably doesn't help query
* performance either.
+ * @deprecated
*/
public class WikibaseStyleStatementInlineUriHandler extends InlineURIHandler {
private static final Logger log =
Logger.getLogger(WikibaseStyleStatementInlineUriHandler.class);
diff --git
a/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/label/LabelService.java
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/label/LabelService.java
index 146ec53..939ac94 100644
---
a/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/label/LabelService.java
+++
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/label/LabelService.java
@@ -528,7 +528,7 @@
*/
private WikibaseUris uris() {
// TODO lookup wikibase host and default to wikidata
- return WikibaseUris.WIKIDATA;
+ return WikibaseUris.getURISystem();
}
/**
diff --git
a/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/vocabulary/GeoSparqlVocabularyDecl.java
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/vocabulary/GeoSparqlVocabularyDecl.java
new file mode 100644
index 0000000..8a76852
--- /dev/null
+++
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/vocabulary/GeoSparqlVocabularyDecl.java
@@ -0,0 +1,17 @@
+package org.wikidata.query.rdf.blazegraph.vocabulary;
+
+import com.bigdata.rdf.vocab.BaseVocabularyDecl;
+import static org.wikidata.query.rdf.common.uri.GeoSparql.NAMESPACE;
+import static org.wikidata.query.rdf.common.uri.GeoSparql.WKT_LITERAL;
+
+
+/**
+ * Vocabulary containing the URIs from
+ * {@linkplain org.wikidata.query.rdf.common.uri.GeoSparql} that are imported
+ * into Blazegraph.
+ */
+public class GeoSparqlVocabularyDecl extends BaseVocabularyDecl {
+ public GeoSparqlVocabularyDecl() {
+ super(NAMESPACE, WKT_LITERAL);
+ }
+}
diff --git
a/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/vocabulary/ProvenanceVocabularyDecl.java
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/vocabulary/ProvenanceVocabularyDecl.java
index 7379334..2ffa987 100644
---
a/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/vocabulary/ProvenanceVocabularyDecl.java
+++
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/vocabulary/ProvenanceVocabularyDecl.java
@@ -8,7 +8,7 @@
/**
* Vocabulary containing the URIs from
- * {@linkplain org.wikidata.query.rdf.common.uri.Ontology} that are imported
+ * {@linkplain org.wikidata.query.rdf.common.uri.Provenance} that are imported
* into Blazegraph.
*/
public class ProvenanceVocabularyDecl extends BaseVocabularyDecl {
diff --git
a/blazegraph/src/test/java/org/wikidata/query/rdf/blazegraph/AbstractRandomizedBlazegraphStorageTestCase.java
b/blazegraph/src/test/java/org/wikidata/query/rdf/blazegraph/AbstractRandomizedBlazegraphStorageTestCase.java
index 52358bd..3e31ba7 100644
---
a/blazegraph/src/test/java/org/wikidata/query/rdf/blazegraph/AbstractRandomizedBlazegraphStorageTestCase.java
+++
b/blazegraph/src/test/java/org/wikidata/query/rdf/blazegraph/AbstractRandomizedBlazegraphStorageTestCase.java
@@ -10,6 +10,8 @@
import org.junit.After;
import org.junit.AfterClass;
import org.junit.runner.RunWith;
+import org.wikidata.query.rdf.blazegraph.inline.literal.WKTSerializer;
+import org.wikidata.query.rdf.common.uri.GeoSparql;
import com.bigdata.bop.engine.QueryEngine;
import com.bigdata.bop.fed.QueryEngineFactory;
@@ -80,6 +82,17 @@
WikibaseInlineUriFactory.class.getName());
properties.setProperty("com.bigdata.rdf.store.AbstractTripleStore.extensionFactoryClass",
WikibaseExtensionFactory.class.getName());
+
properties.setProperty("com.bigdata.rdf.store.AbstractTripleStore.geoSpatial",
"true");
+
properties.setProperty("com.bigdata.rdf.store.AbstractTripleStore.geoSpatialDefaultDatatype",
"http://www.opengis.net/ont/geosparql#wktLiteral");
+
properties.setProperty("com.bigdata.rdf.store.AbstractTripleStore.geoSpatialDatatypeConfig.0",
+ "{\"config\": "
+ + "{ \"uri\": \"" + GeoSparql.WKT_LITERAL + "\", "
+ + "\"literalSerializer\": \"" +
WKTSerializer.class.getName() + "\", "
+ + "\"fields\": [ "
+ + "{ \"valueType\": \"DOUBLE\", \"multiplier\":
\"1000000000\", \"serviceMapping\": \"LONGITUDE\" }, "
+ + "{ \"valueType\": \"DOUBLE\", \"multiplier\":
\"1000000000\", \"serviceMapping\": \"LATITUDE\" }, "
+ + "{ \"valueType\": \"LONG\", \"serviceMapping\":
\"COORD_SYSTEM\" } "
+ + "]}}");
store = new TempTripleStore(temporaryStore(), properties, null);
return store;
}
diff --git
a/blazegraph/src/test/java/org/wikidata/query/rdf/blazegraph/AbstractRandomizedBlazegraphTestBase.java
b/blazegraph/src/test/java/org/wikidata/query/rdf/blazegraph/AbstractRandomizedBlazegraphTestBase.java
index 0052d05..c05adad 100644
---
a/blazegraph/src/test/java/org/wikidata/query/rdf/blazegraph/AbstractRandomizedBlazegraphTestBase.java
+++
b/blazegraph/src/test/java/org/wikidata/query/rdf/blazegraph/AbstractRandomizedBlazegraphTestBase.java
@@ -30,7 +30,7 @@
/**
* Which uris this test uses.
*/
- private WikibaseUris uris = WikibaseUris.WIKIDATA;
+ private WikibaseUris uris = WikibaseUris.getURISystem();
/**
* The uris this test uses.
diff --git
a/blazegraph/src/test/java/org/wikidata/query/rdf/blazegraph/WikibaseGeoUnitTest.java
b/blazegraph/src/test/java/org/wikidata/query/rdf/blazegraph/WikibaseGeoUnitTest.java
new file mode 100644
index 0000000..632039d
--- /dev/null
+++
b/blazegraph/src/test/java/org/wikidata/query/rdf/blazegraph/WikibaseGeoUnitTest.java
@@ -0,0 +1,34 @@
+package org.wikidata.query.rdf.blazegraph;
+
+import static org.hamcrest.Matchers.instanceOf;
+
+import org.junit.Test;
+import org.openrdf.model.impl.LiteralImpl;
+import org.openrdf.model.impl.URIImpl;
+import org.wikidata.query.rdf.common.uri.GeoSparql;
+import org.wikidata.query.rdf.common.uri.Ontology;
+
+import com.bigdata.rdf.internal.impl.literal.LiteralExtensionIV;
+import com.bigdata.rdf.model.BigdataStatement;
+
+public class WikibaseGeoUnitTest extends AbstractRandomizedBlazegraphTestBase {
+
+ @Test
+ public void geoExtension() {
+ BigdataStatement statement = roundTrip(Ontology.Geo.GLOBE,
Ontology.Geo.LATITUDE,
+ new LiteralImpl("Point(1.2 3.4)", new
URIImpl(GeoSparql.WKT_LITERAL)));
+ assertThat(statement.getObject().getIV(),
instanceOf(LiteralExtensionIV.class));
+ assertEquals(statement.getObject().toString(),
+ "\"Point(1.2 3.4)\"^^<" + GeoSparql.WKT_LITERAL + ">");
+ }
+
+ @Test
+ public void geoExtensionGlobe() {
+ String point = "<" + uris().entity() + "Q1234> Point(5.6 7.8)";
+ BigdataStatement statement = roundTrip(Ontology.Geo.GLOBE,
Ontology.Geo.LATITUDE,
+ new LiteralImpl(point, new URIImpl(GeoSparql.WKT_LITERAL)));
+ assertThat(statement.getObject().getIV(),
instanceOf(LiteralExtensionIV.class));
+ assertEquals(statement.getObject().toString(),
+ "\"" + point + "\"^^<" + GeoSparql.WKT_LITERAL + ">");
+ }
+}
diff --git
a/common/src/main/java/org/wikidata/query/rdf/common/WikibasePoint.java
b/common/src/main/java/org/wikidata/query/rdf/common/WikibasePoint.java
index db509dd..fad817f 100644
--- a/common/src/main/java/org/wikidata/query/rdf/common/WikibasePoint.java
+++ b/common/src/main/java/org/wikidata/query/rdf/common/WikibasePoint.java
@@ -41,9 +41,9 @@
/**
* Default coordinate order in the system.
- * FIXME: for now it's lat-long, needs to be changed to long-lat.
+ * WKT requires long-lat order, but format 0.0.1 had lat-long.
*/
- public static final CoordinateOrder DEFAULT_ORDER =
CoordinateOrder.LAT_LONG;
+ public static final CoordinateOrder DEFAULT_ORDER =
CoordinateOrder.LONG_LAT;
/**
* Get longitude.
diff --git
a/common/src/test/java/org/wikidata/query/rdf/common/WikibasePointUnitTest.java
b/common/src/test/java/org/wikidata/query/rdf/common/WikibasePointUnitTest.java
index 8b6a474..6b1ba67 100644
---
a/common/src/test/java/org/wikidata/query/rdf/common/WikibasePointUnitTest.java
+++
b/common/src/test/java/org/wikidata/query/rdf/common/WikibasePointUnitTest.java
@@ -12,7 +12,7 @@
@Test
public void fromStringDefault() {
- pointFromString("Point(12.34 56.98)", "12.34", "56.98", null);
+ pointFromString("Point(56.98 12.34)", "12.34", "56.98", null);
}
@Test
@@ -27,7 +27,7 @@
@Test
public void fromStringGlobe() {
- pointFromString("<On the Moon> Point(12.34 56.98)", "12.34", "56.98",
"On the Moon");
+ pointFromString("<On the Moon> Point(56.98 12.34)", "12.34", "56.98",
"On the Moon");
}
@Test
diff --git a/dist/src/script/RWStore.properties
b/dist/src/script/RWStore.properties
index 399e21f..2a44870 100644
--- a/dist/src/script/RWStore.properties
+++ b/dist/src/script/RWStore.properties
@@ -14,7 +14,7 @@
com.bigdata.rdf.store.AbstractTripleStore.axiomsClass=com.bigdata.rdf.axioms.NoAxioms
# Use our private vocabularies
-com.bigdata.rdf.store.AbstractTripleStore.vocabularyClass=org.wikidata.query.rdf.blazegraph.WikibaseVocabulary$V001
+com.bigdata.rdf.store.AbstractTripleStore.vocabularyClass=org.wikidata.query.rdf.blazegraph.WikibaseVocabulary$V002
com.bigdata.rdf.store.AbstractTripleStore.inlineURIFactory=org.wikidata.query.rdf.blazegraph.WikibaseInlineUriFactory
com.bigdata.rdf.store.AbstractTripleStore.extensionFactoryClass=org.wikidata.query.rdf.blazegraph.WikibaseExtensionFactory
@@ -41,3 +41,15 @@
# See https://jira.blazegraph.com/browse/BLZG-1385 - reduce LRU cache timeout
com.bigdata.journal.AbstractJournal.historicalIndexCacheCapacity=20
com.bigdata.journal.AbstractJournal.historicalIndexCacheTimeout=5
+# Geospatial ON
+com.bigdata.rdf.store.AbstractTripleStore.geoSpatial=true
+com.bigdata.rdf.store.AbstractTripleStore.geoSpatialDefaultDatatype=http\://www.opengis.net/ont/geosparql#wktLiteral
+com.bigdata.rdf.store.AbstractTripleStore.geoSpatialIncludeBuiltinDatatypes=false
+com.bigdata.rdf.store.AbstractTripleStore.geoSpatialDatatypeConfig.0={"config":
\
+{"uri":"http://www.opengis.net/ont/geosparql#wktLiteral",\
+
"literalSerializer":"org.wikidata.query.rdf.blazegraph.inline.literal.WKTSerializer",\
+ "fields":[\
+
{"valueType":"DOUBLE","multiplier":"1000000000","serviceMapping":"LONGITUDE"},\
+
{"valueType":"DOUBLE","multiplier":"1000000000","serviceMapping":"LATITUDE"},\
+
{"valueType":"LONG","multiplier":"1","minValue":"0","serviceMapping":"COORD_SYSTEM"}\
+ ]}}
diff --git a/dist/src/script/runBlazegraph.sh b/dist/src/script/runBlazegraph.sh
index caead8d..2a8f252 100755
--- a/dist/src/script/runBlazegraph.sh
+++ b/dist/src/script/runBlazegraph.sh
@@ -23,12 +23,16 @@
pushd $DIR
+# Q-id of the default globe
+DEFAULT_GLOBE=2
+
echo "Running Blazegraph from `pwd` on :$PORT/$CONTEXT"
java -server -XX:+UseG1GC ${MEMORY}
-Dcom.bigdata.rdf.sail.webapp.ConfigParams.propertyFile=RWStore.properties \
-Dorg.eclipse.jetty.server.Request.maxFormContentSize=200000000 \
-Dcom.bigdata.rdf.sparql.ast.QueryHints.analytic=true \
-Dcom.bigdata.rdf.sparql.ast.QueryHints.analyticMaxMemoryPerQuery=1073741824 \
-DASTOptimizerClass=org.wikidata.query.rdf.blazegraph.WikibaseOptimizers \
+
-Dorg.wikidata.query.rdf.blazegraph.inline.literal.WKTSerializer.noGlobe=$DEFAULT_GLOBE
\
-jar jetty-runner*.jar \
--host localhost \
--port $PORT \
diff --git a/pom.xml b/pom.xml
index 9809254..1cc63df 100644
--- a/pom.xml
+++ b/pom.xml
@@ -57,8 +57,9 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- <blazegraph.version>2.0.1</blazegraph.version>
+ <blazegraph.version>2.1.0</blazegraph.version>
<sesame.version>2.8.1</sesame.version>
+ <jetty.version>9.2.9.v20150224</jetty.version>
</properties>
<distributionManagement>
diff --git a/testTools/src/main/java/org/wikidata/query/rdf/test/Matchers.java
b/testTools/src/main/java/org/wikidata/query/rdf/test/Matchers.java
index fc3f466..913b0f4 100644
--- a/testTools/src/main/java/org/wikidata/query/rdf/test/Matchers.java
+++ b/testTools/src/main/java/org/wikidata/query/rdf/test/Matchers.java
@@ -34,7 +34,7 @@
*/
public static Matcher<BindingSet> binds(String name, String value) {
if (value.startsWith("P")) {
- value = WikibaseUris.WIKIDATA.property(PropertyType.CLAIM) + value;
+ value = WikibaseUris.getURISystem().property(PropertyType.CLAIM) +
value;
}
return new BindsMatcher<URI>(name, equalTo(uri(value)));
}
diff --git
a/testTools/src/main/java/org/wikidata/query/rdf/test/StatementHelper.java
b/testTools/src/main/java/org/wikidata/query/rdf/test/StatementHelper.java
index af81124..1f385f4 100644
--- a/testTools/src/main/java/org/wikidata/query/rdf/test/StatementHelper.java
+++ b/testTools/src/main/java/org/wikidata/query/rdf/test/StatementHelper.java
@@ -46,7 +46,7 @@
throw new IllegalArgumentException("Illegal object: " + o);
}
if (p instanceof String && p.startsWith("P")) {
- p = WikibaseUris.WIKIDATA.property(PropertyType.CLAIM) + p;
+ p = WikibaseUris.getURISystem().property(PropertyType.CLAIM) + p;
}
return new StatementImpl(uri(s), uri(p), oValue);
}
@@ -102,7 +102,7 @@
*/
public static URI uri(String r) {
if (r.startsWith("Q") || r.startsWith("P")) {
- return new URIImpl(WikibaseUris.WIKIDATA.entity() + r);
+ return new URIImpl(WikibaseUris.getURISystem().entity() + r);
}
return new URIImpl(r);
}
diff --git
a/tools/src/test/java/org/wikidata/query/rdf/tool/WikibaseGeoExtensionIntegrationTest.java
b/tools/src/test/java/org/wikidata/query/rdf/tool/WikibaseGeoExtensionIntegrationTest.java
new file mode 100644
index 0000000..0600f9c
--- /dev/null
+++
b/tools/src/test/java/org/wikidata/query/rdf/tool/WikibaseGeoExtensionIntegrationTest.java
@@ -0,0 +1,108 @@
+package org.wikidata.query.rdf.tool;
+
+import static org.wikidata.query.rdf.test.Matchers.binds;
+
+import org.junit.Test;
+import org.openrdf.model.impl.URIImpl;
+import org.openrdf.query.BindingSet;
+import org.openrdf.query.QueryEvaluationException;
+import org.openrdf.query.TupleQueryResult;
+
+public class WikibaseGeoExtensionIntegrationTest extends
AbstractUpdateIntegrationTestBase {
+
+ private final String moonURI = uris().entity() + "Q405";
+
+ private void insertPoints() {
+ String query = "INSERT {\n" +
+ "<http://Berlin> wdt:P625 \"Point(13.38333
52.516666)\"^^geo:wktLiteral .\n" +
+ "<http://Bremen> wdt:P625 \"Point(8.808888
53.07694)\"^^geo:wktLiteral .\n" +
+ "<http://Barcelona> wdt:P625 \"Point(2.17694
41.3825)\"^^geo:wktLiteral .\n" +
+ "<http://SanFrancisco> wdt:P625 \"Point(-122.43333
37.76666)\"^^geo:wktLiteral .\n" +
+ "<http://Johannesburg> wdt:P625 \"Point(2.77777 -26.145
)\"^^geo:wktLiteral .\n" +
+ "<http://MoonBerlin> wdt:P625 \"<" + moonURI + ">
Point(13.38333 52.516666)\"^^geo:wktLiteral .\n" +
+ "<http://MoonBremen> wdt:P625 \"<" + moonURI + ">
Point(8.808888 53.07694)\"^^geo:wktLiteral .\n" +
+ "} WHERE {}";
+ rdfRepository().update(query);
+ }
+
+ private void resultsAre(TupleQueryResult results, String var, String...
matches) throws QueryEvaluationException {
+ BindingSet result;
+ for (String match : matches) {
+ result = results.next();
+ assertThat(result, binds(var, new URIImpl(match)));
+ }
+ assertFalse(results.hasNext());
+ }
+
+ @Test
+ public void circleSearch() throws QueryEvaluationException {
+ insertPoints();
+
+ TupleQueryResult results = rdfRepository().query(
+ "SELECT * WHERE {\n" +
+ "SERVICE wikibase:around {\n" +
+ " ?place wdt:P625 ?location .\n" +
+ " bd:serviceParam wikibase:center \"Point(13.38333
52.516666)\"^^geo:wktLiteral .\n" +
+ " bd:serviceParam wikibase:radius \"320\" .}} ORDER BY
?place\n "
+ );
+
+ resultsAre(results, "place", "http://Berlin", "http://Bremen");
+
+ results = rdfRepository().query(
+ "SELECT * WHERE {\n" +
+ "SERVICE wikibase:around {\n" +
+ " ?place wdt:P625 ?location .\n" +
+ " bd:serviceParam wikibase:center \"Point(13.38333
52.516666)\"^^geo:wktLiteral .\n" +
+ " bd:serviceParam wikibase:radius \"2000\" .}} ORDER BY
?place\n "
+ );
+
+ resultsAre(results, "place", "http://Barcelona", "http://Berlin",
"http://Bremen");
+ }
+
+ @Test
+ public void circleSearchGlobe() throws QueryEvaluationException {
+ insertPoints();
+ TupleQueryResult results = rdfRepository().query(
+ "SELECT * WHERE {\n" +
+ "SERVICE wikibase:around {\n" +
+ " ?place wdt:P625 ?location .\n" +
+ " bd:serviceParam wikibase:center \"Point(13.38333
52.516666)\"^^geo:wktLiteral .\n" +
+ " bd:serviceParam wikibase:globe <" + moonURI + ">.\n " +
+ " bd:serviceParam wikibase:radius \"320\" .}} ORDER BY
?place\n "
+ );
+
+ resultsAre(results, "place", "http://MoonBerlin", "http://MoonBremen");
+ }
+
+ @Test
+ public void circleSearchGlobeNumber() throws QueryEvaluationException {
+ insertPoints();
+
+ TupleQueryResult results = rdfRepository().query(
+ "SELECT * WHERE {\n" +
+ "SERVICE wikibase:around {\n" +
+ " ?place wdt:P625 ?location .\n" +
+ " bd:serviceParam wikibase:center \"Point(13.38333
52.516666)\"^^geo:wktLiteral .\n" +
+ " bd:serviceParam wikibase:globe \"405\" .\n " +
+ " bd:serviceParam wikibase:radius \"320\" .}} ORDER BY
?place\n "
+ );
+
+ resultsAre(results, "place", "http://MoonBerlin", "http://MoonBremen");
+ }
+
+ @Test
+ public void boxSearch() throws QueryEvaluationException {
+ insertPoints();
+ TupleQueryResult results = rdfRepository().query(
+ "SELECT * WHERE {\n" +
+ "SERVICE wikibase:box {\n" +
+ " ?place wdt:P625 ?location .\n" +
+ " bd:serviceParam wikibase:cornerSouthWest \"Point(-180
-50)\"^^geo:wktLiteral .\n" +
+ " bd:serviceParam wikibase:cornerNorthEast \"Point(180
50)\"^^geo:wktLiteral .\n" +
+ " }} ORDER BY ?place\n "
+ );
+
+ resultsAre(results, "place", "http://Barcelona",
"http://Johannesburg", "http://SanFrancisco");
+ }
+
+}
diff --git
a/tools/src/test/java/org/wikidata/query/rdf/tool/rdf/MungerUnitTest.java
b/tools/src/test/java/org/wikidata/query/rdf/tool/rdf/MungerUnitTest.java
index 4f3d9bf..a04be9f 100644
--- a/tools/src/test/java/org/wikidata/query/rdf/tool/rdf/MungerUnitTest.java
+++ b/tools/src/test/java/org/wikidata/query/rdf/tool/rdf/MungerUnitTest.java
@@ -322,7 +322,7 @@
@Test
public void coordinateSwitch() {
List<Statement> result = entity("Q23")
- .remove(statement(uris.entityData() + "Q23",
SchemaDotOrg.SOFTWARE_VERSION, new LiteralImpl("0.0.2")))
+ .remove(statement(uris.entityData() + "Q23",
SchemaDotOrg.SOFTWARE_VERSION, new LiteralImpl("0.0.1")))
.remove(statement("Q23", uris.property(PropertyType.DIRECT) +
"P9", new LiteralImpl("Point(1.2 3.4)", new URIImpl(GeoSparql.WKT_LITERAL))))
.testWithoutShuffle();
Statement expected = statement("Q23",
uris.property(PropertyType.DIRECT) + "P9", new LiteralImpl("Point(3.4 1.2)",
new URIImpl(GeoSparql.WKT_LITERAL)));
diff --git a/tools/src/test/resources/blazegraph/RWStore.properties
b/tools/src/test/resources/blazegraph/RWStore.properties
index 6088420..5f9aeca 100644
--- a/tools/src/test/resources/blazegraph/RWStore.properties
+++ b/tools/src/test/resources/blazegraph/RWStore.properties
@@ -23,10 +23,22 @@
com.bigdata.rdf.store.AbstractTripleStore.axiomsClass=com.bigdata.rdf.axioms.NoAxioms
# Use the default vocabulary for now.
-com.bigdata.rdf.store.AbstractTripleStore.vocabularyClass=org.wikidata.query.rdf.blazegraph.WikibaseVocabulary$V001
+com.bigdata.rdf.store.AbstractTripleStore.vocabularyClass=org.wikidata.query.rdf.blazegraph.WikibaseVocabulary$V002
com.bigdata.rdf.store.AbstractTripleStore.inlineURIFactory=org.wikidata.query.rdf.blazegraph.WikibaseInlineUriFactory
com.bigdata.rdf.store.AbstractTripleStore.extensionFactoryClass=org.wikidata.query.rdf.blazegraph.WikibaseExtensionFactory
# These seem to be ubiquitous overwrites. Not sure why they aren't the
default but it works.
com.bigdata.namespace.kb.lex.com.bigdata.btree.BTree.branchingFactor=400
com.bigdata.namespace.kb.spo.com.bigdata.btree.BTree.branchingFactor=1024
+# Geospatial ON
+com.bigdata.rdf.store.AbstractTripleStore.geoSpatial=true
+com.bigdata.rdf.store.AbstractTripleStore.geoSpatialDefaultDatatype=http\://www.opengis.net/ont/geosparql#wktLiteral
+com.bigdata.rdf.store.AbstractTripleStore.geoSpatialIncludeBuiltinDatatypes=false
+com.bigdata.rdf.store.AbstractTripleStore.geoSpatialDatatypeConfig.0={"config":
\
+{"uri":"http://www.opengis.net/ont/geosparql#wktLiteral",\
+
"literalSerializer":"org.wikidata.query.rdf.blazegraph.inline.literal.WKTSerializer",\
+ "fields":[\
+
{"valueType":"DOUBLE","multiplier":"1000000000","serviceMapping":"LONGITUDE"},\
+
{"valueType":"DOUBLE","multiplier":"1000000000","serviceMapping":"LATITUDE"},\
+
{"valueType":"LONG","multiplier":"1","minValue":"0","serviceMapping":"COORD_SYSTEM"}\
+ ]}}
--
To view, visit https://gerrit.wikimedia.org/r/264854
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I9931a584c5aaa7a8cd22e31c94eca2cff5baae15
Gerrit-PatchSet: 22
Gerrit-Project: wikidata/query/rdf
Gerrit-Branch: master
Gerrit-Owner: Smalyshev <[email protected]>
Gerrit-Reviewer: Smalyshev <[email protected]>
Gerrit-Reviewer: jenkins-bot <>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits