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

Reply via email to