Return-Path: X-Original-To: apmail-jena-commits-archive@www.apache.org Delivered-To: apmail-jena-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id D52E8F787 for ; Mon, 2 Sep 2013 06:47:10 +0000 (UTC) Received: (qmail 21003 invoked by uid 500); 2 Sep 2013 06:47:10 -0000 Delivered-To: apmail-jena-commits-archive@jena.apache.org Received: (qmail 20976 invoked by uid 500); 2 Sep 2013 06:47:10 -0000 Mailing-List: contact commits-help@jena.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@jena.apache.org Delivered-To: mailing list commits@jena.apache.org Received: (qmail 20969 invoked by uid 99); 2 Sep 2013 06:47:10 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 02 Sep 2013 06:47:10 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 02 Sep 2013 06:46:50 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 40C352388999; Mon, 2 Sep 2013 06:46:25 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1519358 [2/5] - in /jena/trunk/jena-spatial: ./ src/ src/main/ src/main/java/ src/main/java/examples/ src/main/java/jena/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/jena/ src/main/java/org/apache/jena/query/ src/... Date: Mon, 02 Sep 2013 06:46:21 -0000 To: commits@jena.apache.org From: jpz6311whu@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20130902064625.40C352388999@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Added: jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/SpatialIndexException.java URL: http://svn.apache.org/viewvc/jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/SpatialIndexException.java?rev=1519358&view=auto ============================================================================== --- jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/SpatialIndexException.java (added) +++ jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/SpatialIndexException.java Mon Sep 2 06:46:19 2013 @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.jena.query.spatial; + +import com.hp.hpl.jena.query.QueryExecException; + +public class SpatialIndexException extends QueryExecException +{ + public SpatialIndexException() { super() ; } + public SpatialIndexException(Throwable cause) { super(cause) ; } + public SpatialIndexException(String msg) { super(msg) ; } + public SpatialIndexException(String msg, Throwable cause) { super(msg, cause) ; } + +} + Propchange: jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/SpatialIndexException.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/SpatialIndexLucene.java URL: http://svn.apache.org/viewvc/jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/SpatialIndexLucene.java?rev=1519358&view=auto ============================================================================== --- jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/SpatialIndexLucene.java (added) +++ jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/SpatialIndexLucene.java Mon Sep 2 06:46:19 2013 @@ -0,0 +1,258 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.jena.query.spatial; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.lucene.analysis.Analyzer; +import org.apache.lucene.analysis.standard.StandardAnalyzer; +import org.apache.lucene.document.Document; +import org.apache.lucene.document.Field; +import org.apache.lucene.document.FieldType; +import org.apache.lucene.index.DirectoryReader; +import org.apache.lucene.index.IndexReader; +import org.apache.lucene.index.IndexWriter; +import org.apache.lucene.index.IndexWriterConfig; +import org.apache.lucene.index.IndexableField; +import org.apache.lucene.queries.function.ValueSource; +import org.apache.lucene.queryparser.classic.ParseException; +import org.apache.lucene.search.Filter; +import org.apache.lucene.search.IndexSearcher; +import org.apache.lucene.search.MatchAllDocsQuery; +import org.apache.lucene.search.ScoreDoc; +import org.apache.lucene.search.Sort; +import org.apache.lucene.search.TopDocs; +import org.apache.lucene.spatial.SpatialStrategy; +import org.apache.lucene.spatial.prefix.RecursivePrefixTreeStrategy; +import org.apache.lucene.spatial.prefix.tree.GeohashPrefixTree; +import org.apache.lucene.spatial.prefix.tree.SpatialPrefixTree; +import org.apache.lucene.spatial.query.SpatialArgs; +import org.apache.lucene.spatial.query.SpatialOperation; +import org.apache.lucene.store.Directory; +import org.apache.lucene.util.Version; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.hp.hpl.jena.graph.Node; +import com.hp.hpl.jena.graph.NodeFactory; +import com.hp.hpl.jena.sparql.util.NodeFactoryExtra; +import com.spatial4j.core.shape.Point; +import com.spatial4j.core.shape.Shape; + +public class SpatialIndexLucene implements SpatialIndex { + private static Logger log = LoggerFactory + .getLogger(SpatialIndexLucene.class); + + private static int MAX_N = 10000; + public static final Version VER = Version.LUCENE_43; + + public static final FieldType ftIRI; + static { + ftIRI = new FieldType(); + ftIRI.setTokenized(false); + ftIRI.setStored(true); + ftIRI.setIndexed(true); + ftIRI.freeze(); + } + // public static final FieldType ftText = TextField.TYPE_NOT_STORED ; + // Bigger index, easier to debug! + // public static final FieldType ftText = TextField.TYPE_STORED ; + + private final EntityDefinition docDef; + private final Directory directory; + private IndexWriter indexWriter; + private Analyzer analyzer = new StandardAnalyzer(VER); + + /** + * The Lucene spatial {@link SpatialStrategy} encapsulates an approach to + * indexing and searching shapes, and providing distance values for them. + * It's a simple API to unify different approaches. You might use more than + * one strategy for a shape as each strategy has its strengths and + * weaknesses. + *

+ * Note that these are initialized with a field name. + */ + private SpatialStrategy strategy; + + public SpatialIndexLucene(Directory directory, EntityDefinition def) { + this.directory = directory; + this.docDef = def; + + int maxLevels = 11;// results in sub-meter precision for geohash + // This can also be constructed from SpatialPrefixTreeFactory + SpatialPrefixTree grid = new GeohashPrefixTree(SpatialQuery.ctx, maxLevels); + + this.strategy = new RecursivePrefixTreeStrategy(grid, def.getGeoField()); + + //this.strategy = new PointVectorStrategy(ctx, def.getGeoField()); + + // force creation of the index if it don't exist + // otherwise if we get a search before data is written we get an + // exception + startIndexing(); + finishIndexing(); + } + + public Directory getDirectory() { + return directory; + } + + public Analyzer getAnalyzer() { + return analyzer; + } + + @Override + public void startIndexing() { + try { + IndexWriterConfig wConfig = new IndexWriterConfig(VER, analyzer); + indexWriter = new IndexWriter(directory, wConfig); + } catch (IOException e) { + exception(e); + } + } + + @Override + public void finishIndexing() { + try { + indexWriter.commit(); + indexWriter.close(); + indexWriter = null; + } catch (IOException e) { + exception(e); + } + } + + @Override + public void abortIndexing() { + try { + indexWriter.rollback(); + } catch (IOException ex) { + exception(ex); + } + } + + @Override + public void close() { + if (indexWriter != null) + try { + indexWriter.close(); + } catch (IOException ex) { + exception(ex); + } + } + + @Override + public void add(String entityURI, Shape... shapes) { + try { + boolean autoBatch = (indexWriter == null); + + Document doc = doc(entityURI, shapes); + if (autoBatch) + startIndexing(); + indexWriter.addDocument(doc); + if (autoBatch) + finishIndexing(); + } catch (IOException e) { + exception(e); + } + } + + private Document doc(String entityURI, Shape... shapes) { + Document doc = new Document(); + Field entField = new Field(docDef.getEntityField(), entityURI, ftIRI); + doc.add(entField); + for (Shape shape : shapes) { + for (IndexableField f : strategy.createIndexableFields(shape)) { + doc.add(f); + } + } + + return doc; + } + + @Override + public List query(Shape shape, int limit, SpatialOperation operation) { + try { + // Upgrade at Java7 ... + IndexReader indexReader = DirectoryReader.open(directory); + try { + return query$(indexReader, shape, limit, operation); + } finally { + indexReader.close(); + } + } catch (Exception ex) { + exception(ex); + return null; + } + } + + private List query$(IndexReader indexReader, Shape shape, int limit, SpatialOperation operation) throws ParseException, + IOException { + if (limit <= 0) + limit = MAX_N; + + IndexSearcher indexSearcher = new IndexSearcher(indexReader); + Point pt = shape.getCenter(); + ValueSource valueSource = strategy.makeDistanceValueSource(pt);// the + // distance + // (in + // degrees) + Sort distSort = new Sort(valueSource.getSortField(false)) + .rewrite(indexSearcher); + SpatialArgs args = new SpatialArgs(operation, shape); + args.setDistErr(0.0); + Filter filter = strategy.makeFilter(args); + TopDocs docs = indexSearcher.search(new MatchAllDocsQuery(), filter, + limit, distSort); + + List results = new ArrayList(); + + // Align and DRY with Solr. + for (ScoreDoc sd : docs.scoreDocs) { + Document doc = indexSearcher.doc(sd.doc); + String[] values = doc.getValues(docDef.getEntityField()); + for (String v : values) { + Node n = NodeFactory.createURI(v); + results.add(n); + } + } + return results; + } + + @Override + public EntityDefinition getDocDef() { + return docDef; + } + + private Node entryToNode(String v) { + // TEMP + return NodeFactoryExtra.createLiteralNode(v, null, null); + } + + private static void exception(Exception ex) { + throw new SpatialIndexException(ex); + } + + + + + +} Propchange: jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/SpatialIndexLucene.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/SpatialIndexSolr.java URL: http://svn.apache.org/viewvc/jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/SpatialIndexSolr.java?rev=1519358&view=auto ============================================================================== --- jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/SpatialIndexSolr.java (added) +++ jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/SpatialIndexSolr.java Mon Sep 2 06:46:19 2013 @@ -0,0 +1,177 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.jena.query.spatial; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.lucene.spatial.SpatialStrategy; +import org.apache.lucene.spatial.prefix.RecursivePrefixTreeStrategy; +import org.apache.lucene.spatial.prefix.tree.GeohashPrefixTree; +import org.apache.lucene.spatial.prefix.tree.SpatialPrefixTree; +import org.apache.lucene.spatial.query.SpatialOperation; +import org.apache.solr.client.solrj.SolrQuery; +import org.apache.solr.client.solrj.SolrServer; +import org.apache.solr.client.solrj.SolrServerException; +import org.apache.solr.client.solrj.response.QueryResponse; +import org.apache.solr.common.SolrDocument; +import org.apache.solr.common.SolrDocumentList; +import org.apache.solr.common.SolrInputDocument; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.hp.hpl.jena.graph.Node; +import com.hp.hpl.jena.graph.NodeFactory; +import com.hp.hpl.jena.sparql.util.NodeFactoryExtra; +import com.spatial4j.core.shape.Shape; + +public class SpatialIndexSolr implements SpatialIndex { + private static Logger log = LoggerFactory.getLogger(SpatialIndexSolr.class); + private final SolrServer solrServer; + private EntityDefinition docDef; + private SpatialPrefixTree grid; + + /** + * The Lucene spatial {@link SpatialStrategy} encapsulates an approach to + * indexing and searching shapes, and providing distance values for them. + * It's a simple API to unify different approaches. You might use more than + * one strategy for a shape as each strategy has its strengths and + * weaknesses. + *

+ * Note that these are initialized with a field name. + */ + private SpatialStrategy strategy; + + public SpatialIndexSolr(SolrServer server, EntityDefinition def) { + this.solrServer = server; + this.docDef = def; + + int maxLevels = 11;// results in sub-meter precision for geohash + // This can also be constructed from SpatialPrefixTreeFactory + grid = new GeohashPrefixTree(SpatialQuery.ctx, maxLevels); + + this.strategy = new RecursivePrefixTreeStrategy(grid, def.getGeoField()); + } + + @Override + public void startIndexing() { + } + + @Override + public void finishIndexing() { + try { + solrServer.commit(); + } catch (Exception ex) { + exception(ex); + } + } + + @Override + public void abortIndexing() { + try { + solrServer.rollback(); + } catch (Exception ex) { + exception(ex); + } + } + + @Override + public void close() { + if (solrServer != null) + solrServer.shutdown(); + } + + @Override + public void add(String entityURI, Shape... shapes) { + + // log.info("Add entity: "+entityURI) ; + try { + SolrInputDocument doc = solrDoc(entityURI, shapes); + solrServer.add(doc); + } catch (Exception e) { + exception(e); + } + } + + private SolrInputDocument solrDoc(String entityURI, Shape... shapes) { + SolrInputDocument doc = new SolrInputDocument(); + doc.addField(docDef.getEntityField(), entityURI); + if (shapes.length != 1) { + throw new SpatialIndexException( + "Solr spatial only supports indexing one shape a time, but provided: " + + shapes.length + " shapes."); + } + doc.addField(docDef.getGeoField(), SpatialQuery.ctx.toString(shapes[0])); + + return doc; + } + + @Override + public List query(Shape shape, int limit, SpatialOperation operation) { + + SolrDocumentList solrResults = solrQuery(shape, limit, operation); + List results = new ArrayList(); + + for (SolrDocument sd : solrResults) { + String uriStr = (String) sd.getFieldValue(docDef.getEntityField()); + // log.info("Entity: "+uriStr) ; + results.add(NodeFactory.createURI(uriStr)); + } + + if (limit > 0 && results.size() > limit) + results = results.subList(0, limit); + + return results; + } + + private SolrDocumentList solrQuery(Shape shape, int limit, + SpatialOperation operation) { + SolrQuery sq = new SolrQuery(); + sq.setQuery("*:*"); + sq.setFilterQueries(docDef.getGeoField() + ":\"" + operation.toString() + + "(" + SpatialQuery.ctx.toString(shape) + ") distErrPct=0\""); + //System.out.println("SolrQuery: " +sq.toString()); + try { + QueryResponse rsp = solrServer.query(sq); + SolrDocumentList docs = rsp.getResults(); + return docs; + } catch (SolrServerException e) { + exception(e); + return null; + } + } + + @Override + public EntityDefinition getDocDef() { + return docDef; + } + + private Node entryToNode(String v) { + // TEMP + return NodeFactoryExtra.createLiteralNode(v, null, null); + } + + public SolrServer getServer() { + return solrServer; + } + + private static Void exception(Exception ex) { + throw new SpatialIndexException(ex); + } +} Propchange: jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/SpatialIndexSolr.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/SpatialPredicatePair.java URL: http://svn.apache.org/viewvc/jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/SpatialPredicatePair.java?rev=1519358&view=auto ============================================================================== --- jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/SpatialPredicatePair.java (added) +++ jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/SpatialPredicatePair.java Mon Sep 2 06:46:19 2013 @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.jena.query.spatial; + +import com.hp.hpl.jena.graph.Node; + +public class SpatialPredicatePair { + + private Node latitudePredicate; + private Node longitudePredicate; + + public SpatialPredicatePair(Node latitudePredicate, Node longitudePredicate) { + super(); + this.latitudePredicate = latitudePredicate; + this.longitudePredicate = longitudePredicate; + } + + public Node getLatitudePredicate() { + return latitudePredicate; + } + + public Node getLongitudePredicate() { + return longitudePredicate; + } + + @Override + public int hashCode() { + return latitudePredicate.hashCode() * 7 + longitudePredicate.hashCode() + * 13; + } + + @Override + public boolean equals(Object otherObject) { + // a quick test to see if the objects are identical + if (this == otherObject) + return true; + + // must return false if the explicit parameter is null + if (otherObject == null) + return false; + + // if the classes don't match, they can't be equal + if (getClass() != otherObject.getClass()) + return false; + + // now we know otherObject is a non-null Employee + SpatialPredicatePair other = (SpatialPredicatePair) otherObject; + + // test whether the fields have identical values + return latitudePredicate.equals(other.latitudePredicate) + && longitudePredicate == other.longitudePredicate; + } + + @Override + public String toString(){ + return "[ " + latitudePredicate.toString() + ", " + longitudePredicate.toString() + " ]"; + } +} Propchange: jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/SpatialPredicatePair.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/SpatialPredicatePairValue.java URL: http://svn.apache.org/viewvc/jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/SpatialPredicatePairValue.java?rev=1519358&view=auto ============================================================================== --- jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/SpatialPredicatePairValue.java (added) +++ jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/SpatialPredicatePairValue.java Mon Sep 2 06:46:19 2013 @@ -0,0 +1,110 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.jena.query.spatial; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.hp.hpl.jena.graph.Node; + +public class SpatialPredicatePairValue { + + private static Logger log = LoggerFactory + .getLogger(SpatialPredicatePairValue.class); + + public SpatialPredicatePairValue(SpatialPredicatePair pair) { + this.pair = pair; + } + + private SpatialPredicatePair pair; + private Double latitudeValue; + private Double longitudeValue; + + public Double getLatitudeValue() { + return latitudeValue; + } + + public Double getLongitudeValue() { + return longitudeValue; + } + + public SpatialPredicatePair getPair() { + return pair; + } + + public void setValue(Node predicate, Double value) { + if (predicate.equals(pair.getLatitudePredicate())) { + this.latitudeValue = value; + } else if (predicate.equals(pair.getLongitudePredicate())) { + this.longitudeValue = value; + } else { + log.warn("Try to set value to a SpatialPredicatePairValue with no such predicate: " + + predicate + " :: " + value); + } + + } + + public Double getTheOtherValue(Node predicate) { + if (pair.getLatitudePredicate().equals(predicate)) { + return this.getLongitudeValue(); + } else if (predicate.equals(pair.getLongitudePredicate())) { + return this.getLatitudeValue(); + } else { + log.warn("Try to get value to a SpatialPredicatePairValue with no such predicate: " + + predicate); + return null; + } + } + + @Override + public int hashCode() { + int latitudeHashCode = latitudeValue == null ? 0 : latitudeValue + .hashCode() * 17; + int longitudeHashCode = longitudeValue == null ? 0 : longitudeValue + .hashCode() * 19; + return pair.hashCode() * 11 + latitudeHashCode + longitudeHashCode; + } + + @Override + public boolean equals(Object otherObject) { + // a quick test to see if the objects are identical + if (this == otherObject) + return true; + + // must return false if the explicit parameter is null + if (otherObject == null) + return false; + + // if the classes don't match, they can't be equal + if (getClass() != otherObject.getClass()) + return false; + + // now we know otherObject is a non-null Employee + SpatialPredicatePairValue other = (SpatialPredicatePairValue) otherObject; + + boolean latitudeValueEquals = this.latitudeValue == null ? other.latitudeValue == null + : this.latitudeValue.equals(other.latitudeValue); + boolean longitudeValueEquals = this.longitudeValue == null ? other.longitudeValue == null + : this.longitudeValue.equals(other.longitudeValue); + + // test whether the fields have identical values + return pair.equals(other.pair) && latitudeValueEquals + && longitudeValueEquals; + } +} Propchange: jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/SpatialPredicatePairValue.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/SpatialQuery.java URL: http://svn.apache.org/viewvc/jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/SpatialQuery.java?rev=1519358&view=auto ============================================================================== --- jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/SpatialQuery.java (added) +++ jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/SpatialQuery.java Mon Sep 2 06:46:19 2013 @@ -0,0 +1,135 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.jena.query.spatial; + +import org.apache.jena.query.spatial.assembler.SpatialAssembler; +import org.apache.jena.query.spatial.pfunction.library.EastPF; +import org.apache.jena.query.spatial.pfunction.library.IntersectsBoxPF; +import org.apache.jena.query.spatial.pfunction.library.IsNearByPF; +import org.apache.jena.query.spatial.pfunction.library.IsWithinBoxPF; +import org.apache.jena.query.spatial.pfunction.library.IsWithinCirclePF; +import org.apache.jena.query.spatial.pfunction.library.NorthPF; +import org.apache.jena.query.spatial.pfunction.library.SouthPF; +import org.apache.jena.query.spatial.pfunction.library.WestPF; + +import com.hp.hpl.jena.sparql.SystemARQ; +import com.hp.hpl.jena.sparql.lib.Metadata; +import com.hp.hpl.jena.sparql.mgt.ARQMgt; +import com.hp.hpl.jena.sparql.mgt.SystemInfo; +import com.hp.hpl.jena.sparql.pfunction.PropertyFunction; +import com.hp.hpl.jena.sparql.pfunction.PropertyFunctionFactory; +import com.hp.hpl.jena.sparql.pfunction.PropertyFunctionRegistry; +import com.hp.hpl.jena.sparql.util.Symbol; +import com.hp.hpl.jena.tdb.TDB; +import com.spatial4j.core.context.SpatialContext; +import com.spatial4j.core.context.jts.JtsSpatialContext; + +public class SpatialQuery +{ + private static boolean initialized = false ; + private static Object lock = new Object() ; + public static String NS = "http://jena.apache.org/spatial#" ; + public static String IRI = "http://jena.apache.org/#spatial" ; + public static final Symbol spatialIndex = Symbol.create(NS+"index") ; + public static final String PATH = "org.apache.jena.query.spatial"; + + static private String metadataLocation = "org/apache/jena/query/spatial/properties.xml" ; + static private Metadata metadata = new Metadata(metadataLocation) ; + public static final String NAME = "ARQ Spatial Query"; + + public static final String VERSION = metadata.get(PATH+".version", "unknown") ; + public static final String BUILD_DATE = metadata.get(PATH+".build.datetime", "unset") ; + + public static final SpatialContext ctx = JtsSpatialContext.GEO; + + static { init() ; } + + public static void init() + { + if ( initialized ) return ; + synchronized(lock) + { + if ( initialized ) return ; + initialized = true ; + TDB.init() ; + SpatialAssembler.init() ; + + SystemInfo sysInfo = new SystemInfo(IRI, VERSION, BUILD_DATE) ; + ARQMgt.register(PATH+".system:type=SystemInfo", sysInfo) ; + SystemARQ.registerSubSystem(sysInfo) ; + + PropertyFunctionRegistry.get().put("http://jena.apache.org/spatial#withinCircle", new PropertyFunctionFactory() { + @Override + public PropertyFunction create(String uri) { + return new IsWithinCirclePF() ; + } + }); + PropertyFunctionRegistry.get().put("http://jena.apache.org/spatial#nearby", new PropertyFunctionFactory() { + @Override + public PropertyFunction create(String uri) { + return new IsNearByPF() ; + } + }); + + PropertyFunctionRegistry.get().put("http://jena.apache.org/spatial#withinBox", new PropertyFunctionFactory() { + @Override + public PropertyFunction create(String uri) { + return new IsWithinBoxPF() ; + } + }); + + + PropertyFunctionRegistry.get().put("http://jena.apache.org/spatial#intersectBox", new PropertyFunctionFactory() { + @Override + public PropertyFunction create(String uri) { + return new IntersectsBoxPF() ; + } + }); + + PropertyFunctionRegistry.get().put("http://jena.apache.org/spatial#north", new PropertyFunctionFactory() { + @Override + public PropertyFunction create(String uri) { + return new NorthPF() ; + } + }); + + PropertyFunctionRegistry.get().put("http://jena.apache.org/spatial#south", new PropertyFunctionFactory() { + @Override + public PropertyFunction create(String uri) { + return new SouthPF() ; + } + }); + + PropertyFunctionRegistry.get().put("http://jena.apache.org/spatial#east", new PropertyFunctionFactory() { + @Override + public PropertyFunction create(String uri) { + return new EastPF() ; + } + }); + + PropertyFunctionRegistry.get().put("http://jena.apache.org/spatial#west", new PropertyFunctionFactory() { + @Override + public PropertyFunction create(String uri) { + return new WestPF() ; + } + }); + } + } +} + Propchange: jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/SpatialQuery.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/SpatialValueUtil.java URL: http://svn.apache.org/viewvc/jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/SpatialValueUtil.java?rev=1519358&view=auto ============================================================================== --- jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/SpatialValueUtil.java (added) +++ jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/SpatialValueUtil.java Mon Sep 2 06:46:19 2013 @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.jena.query.spatial; + +import com.hp.hpl.jena.datatypes.RDFDatatype; +import com.hp.hpl.jena.datatypes.xsd.XSDDatatype; +import com.hp.hpl.jena.graph.impl.LiteralLabel; + +public class SpatialValueUtil { + + public static boolean isDecimal(LiteralLabel literal) { + RDFDatatype dtype = literal.getDatatype(); + if (dtype == null) { + try { + Double.parseDouble(literal.getLexicalForm()); + return true; + } catch (NumberFormatException e) { + return false; + } + } + if ((dtype.equals(XSDDatatype.XSDfloat)) + || (dtype.equals(XSDDatatype.XSDdecimal)) + || (dtype.equals(XSDDatatype.XSDdouble) || (dtype + .equals(XSDDatatype.XSDinteger)))) + return true; + return false; + } + + public static boolean isWKTLiteral(LiteralLabel literal) { + RDFDatatype dtype = literal.getDatatype(); + if (dtype == null) + return false; + if (dtype.getURI().equals( + EntityDefinition.geosparql_wktLiteral.getURI())) + return true; + return false; + } +} Propchange: jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/SpatialValueUtil.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/assembler/EntityDefinitionAssembler.java URL: http://svn.apache.org/viewvc/jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/assembler/EntityDefinitionAssembler.java?rev=1519358&view=auto ============================================================================== --- jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/assembler/EntityDefinitionAssembler.java (added) +++ jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/assembler/EntityDefinitionAssembler.java Mon Sep 2 06:46:19 2013 @@ -0,0 +1,120 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.jena.query.spatial.assembler; + +import static org.apache.jena.query.spatial.assembler.SpatialVocab.NS; + +import java.util.List; + +import org.apache.jena.atlas.lib.StrUtils; +import org.apache.jena.atlas.logging.Log; +import org.apache.jena.query.spatial.EntityDefinition; +import org.apache.jena.query.spatial.SpatialIndexException; + +import com.hp.hpl.jena.assembler.Assembler; +import com.hp.hpl.jena.assembler.Mode; +import com.hp.hpl.jena.assembler.assemblers.AssemblerBase; +import com.hp.hpl.jena.query.ParameterizedSparqlString; +import com.hp.hpl.jena.query.Query; +import com.hp.hpl.jena.query.QueryExecution; +import com.hp.hpl.jena.query.QueryExecutionFactory; +import com.hp.hpl.jena.query.QueryFactory; +import com.hp.hpl.jena.query.QuerySolution; +import com.hp.hpl.jena.query.ResultSet; +import com.hp.hpl.jena.query.ResultSetFormatter; +import com.hp.hpl.jena.rdf.model.Model; +import com.hp.hpl.jena.rdf.model.Resource; + +public class EntityDefinitionAssembler extends AssemblerBase implements Assembler +{ + + // V1 + + /* +<#definition> a spatial:EntityDefinition ; + spatial:entityField "uri" ; + spatial:geoField "geo" ; + spatial:hasSpatialPredicatePairs ( + [ spatial:latitude <#latitude_1> ; spatial:longitude <#longitude_1> ] + [ spatial:latitude <#latitude_2> ; spatial:longitude <#longitude_2> ] + ) ; + spatial:hasWKTPredicates (<#wkt_1> <#wkt_2>) . + */ + + @Override + public EntityDefinition open(Assembler a, Resource root, Mode mode) + { + String prologue = "PREFIX : <"+NS+"> PREFIX list: " ; + Model model = root.getModel() ; + + String qs1 = StrUtils.strjoinNL(prologue, + "SELECT * {" , + " ?definition :entityField ?entityField ;" , + " :geoField ?geoField" , + "}") ; + ParameterizedSparqlString pss = new ParameterizedSparqlString(qs1) ; + pss.setIri("definition", root.getURI()) ; + + Query query1 = QueryFactory.create(pss.toString()) ; + QueryExecution qexec1 = QueryExecutionFactory.create(query1, model) ; + ResultSet rs1 = qexec1.execSelect() ; + List results = ResultSetFormatter.toList(rs1) ; + if ( results.size() == 0 ) { + //Log.warn(this, "Failed to find a valid EntityDefinition for : "+root) ; + throw new SpatialIndexException("Failed to find a valid EntityDefinition for : "+root) ; + } + + if ( results.size() !=1 ) { + Log.warn(this, "Multiple matches for EntityMap for : "+root) ; + throw new SpatialIndexException("Multiple matches for EntityDefinition for : "+root) ; + } + + QuerySolution qsol1 = results.get(0) ; + String entityField = qsol1.getLiteral("entityField").getLexicalForm() ; + String geoField = qsol1.getLiteral("geoField").getLexicalForm() ; + + EntityDefinition docDef = new EntityDefinition(entityField, geoField) ; + + String qs2 = StrUtils.strjoinNL("SELECT * { ?definition :hasSpatialPredicatePairs [ list:member [ :latitude ?latitude ; :longitude ?longitude ] ]}") ; + Query query2 = QueryFactory.create(prologue+" "+qs2) ; + QueryExecution qexec2 = QueryExecutionFactory.create(query2, model, qsol1) ; + ResultSet rs2 = qexec2.execSelect() ; + List mapEntries = ResultSetFormatter.toList(rs2) ; + + for ( QuerySolution qsol : mapEntries ) { + Resource latitude = qsol.getResource("latitude") ; + Resource longitude = qsol.getResource("longitude") ; + docDef.addSpatialPredicatePair(latitude, longitude); + } + + String qs3 = StrUtils.strjoinNL("SELECT * { ?definition :hasWKTPredicates [ list:member ?wkt ] }") ; + Query query3 = QueryFactory.create(prologue+" "+qs3) ; + QueryExecution qexec3 = QueryExecutionFactory.create(query3, model, qsol1) ; + ResultSet rs3 = qexec3.execSelect() ; + mapEntries = ResultSetFormatter.toList(rs3) ; + + for ( QuerySolution qsol : mapEntries ) { + Resource wkt = qsol.getResource("wkt") ; + docDef.addWKTPredicate(wkt); + } + + return docDef ; + } +} + Propchange: jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/assembler/EntityDefinitionAssembler.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/assembler/SpatialAssembler.java URL: http://svn.apache.org/viewvc/jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/assembler/SpatialAssembler.java?rev=1519358&view=auto ============================================================================== --- jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/assembler/SpatialAssembler.java (added) +++ jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/assembler/SpatialAssembler.java Mon Sep 2 06:46:19 2013 @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.jena.query.spatial.assembler; + +import com.hp.hpl.jena.assembler.Assembler; +import com.hp.hpl.jena.sparql.core.assembler.AssemblerUtils; + +public class SpatialAssembler +{ + public static void init() + { + AssemblerUtils.init() ; + Assembler.general.implementWith(SpatialVocab.spatialDataset, new SpatialDatasetAssembler()) ; + Assembler.general.implementWith(SpatialVocab.definition, new EntityDefinitionAssembler()) ; + Assembler.general.implementWith(SpatialVocab.spatialIndexSolr, new SpatialIndexSolrAssembler()) ; + Assembler.general.implementWith(SpatialVocab.spatialIndexLucene, new SpatialIndexLuceneAssembler()) ; + } +} + Propchange: jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/assembler/SpatialAssembler.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/assembler/SpatialDatasetAssembler.java URL: http://svn.apache.org/viewvc/jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/assembler/SpatialDatasetAssembler.java?rev=1519358&view=auto ============================================================================== --- jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/assembler/SpatialDatasetAssembler.java (added) +++ jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/assembler/SpatialDatasetAssembler.java Mon Sep 2 06:46:19 2013 @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.jena.query.spatial.assembler; + +import static org.apache.jena.query.spatial.assembler.SpatialVocab.pDataset; +import static org.apache.jena.query.spatial.assembler.SpatialVocab.pIndex; + +import org.apache.jena.query.spatial.SpatialDatasetFactory; +import org.apache.jena.query.spatial.SpatialIndex; + +import com.hp.hpl.jena.assembler.Assembler; +import com.hp.hpl.jena.assembler.Mode; +import com.hp.hpl.jena.assembler.assemblers.AssemblerBase; +import com.hp.hpl.jena.query.Dataset; +import com.hp.hpl.jena.rdf.model.Resource; +import com.hp.hpl.jena.sparql.util.graph.GraphUtils; + +public class SpatialDatasetAssembler extends AssemblerBase implements Assembler +{ +// private DatasetAssembler datasetAssembler = new DatasetAssembler() ; +// +// public static Resource getType() { return textDataset ; } + + /* +<#spatial_dataset> rdf:type spatial:SpatialDataset ; + spatial:dataset <#dataset> ; + spatial:index <#index> ; + . + + */ + + @Override + public Dataset open(Assembler a, Resource root, Mode mode) + { + Resource dataset = GraphUtils.getResourceValue(root, pDataset) ; + Resource index = GraphUtils.getResourceValue(root, pIndex) ; + + Dataset ds = (Dataset)a.open(dataset) ; + SpatialIndex textIndex = (SpatialIndex)a.open(index) ; + + Dataset dst = SpatialDatasetFactory.create(ds, textIndex) ; + return dst ; + + } +} + Propchange: jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/assembler/SpatialDatasetAssembler.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/assembler/SpatialIndexLuceneAssembler.java URL: http://svn.apache.org/viewvc/jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/assembler/SpatialIndexLuceneAssembler.java?rev=1519358&view=auto ============================================================================== --- jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/assembler/SpatialIndexLuceneAssembler.java (added) +++ jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/assembler/SpatialIndexLuceneAssembler.java Mon Sep 2 06:46:19 2013 @@ -0,0 +1,87 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.jena.query.spatial.assembler; + +import static org.apache.jena.query.spatial.assembler.SpatialVocab.pDefinition; +import static org.apache.jena.query.spatial.assembler.SpatialVocab.pDirectory; + +import java.io.File; +import java.io.IOException; + +import org.apache.jena.atlas.io.IO; +import org.apache.jena.query.spatial.EntityDefinition; +import org.apache.jena.query.spatial.SpatialDatasetFactory; +import org.apache.jena.query.spatial.SpatialIndex; +import org.apache.jena.query.spatial.SpatialIndexException; +import org.apache.jena.riot.system.IRILib; +import org.apache.lucene.store.Directory; +import org.apache.lucene.store.FSDirectory; +import org.apache.lucene.store.RAMDirectory; + +import com.hp.hpl.jena.assembler.Assembler; +import com.hp.hpl.jena.assembler.Mode; +import com.hp.hpl.jena.assembler.assemblers.AssemblerBase; +import com.hp.hpl.jena.rdf.model.RDFNode; +import com.hp.hpl.jena.rdf.model.Resource; +import com.hp.hpl.jena.sparql.util.graph.GraphUtils; + +public class SpatialIndexLuceneAssembler extends AssemblerBase +{ + /* + <#index> a :SpatialIndexLucene ; + #spatial:directory "mem" ; + spatial:directory ; + spatial:definition <#definition> ; + . + */ + + @SuppressWarnings("resource") + @Override + public SpatialIndex open(Assembler a, Resource root, Mode mode) + { + try + { + if ( ! GraphUtils.exactlyOneProperty(root, pDirectory) ) + throw new SpatialIndexException("No 'spatial:directory' property on "+root) ; + + Directory directory ; + RDFNode n = root.getProperty(pDirectory).getObject() ; + if ( n.isLiteral() ) + { + if ( ! "mem".equals(n.asLiteral().getLexicalForm()) ) + throw new SpatialIndexException("No 'spatial:directory' property on "+root+ " is a literal and not \"mem\"") ; + directory = new RAMDirectory() ; + } + else + { + Resource x = n.asResource() ; + String path = IRILib.IRIToFilename(x.getURI()) ; + File dir = new File(path) ; + directory = FSDirectory.open(dir) ; + } + + Resource r = GraphUtils.getResourceValue(root, pDefinition) ; + EntityDefinition docDef = (EntityDefinition)a.open(r) ; + + return SpatialDatasetFactory.createLuceneIndex(directory, docDef) ; + } catch (IOException e) { IO.exception(e) ; return null ;} + } + +} + Propchange: jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/assembler/SpatialIndexLuceneAssembler.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/assembler/SpatialIndexSolrAssembler.java URL: http://svn.apache.org/viewvc/jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/assembler/SpatialIndexSolrAssembler.java?rev=1519358&view=auto ============================================================================== --- jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/assembler/SpatialIndexSolrAssembler.java (added) +++ jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/assembler/SpatialIndexSolrAssembler.java Mon Sep 2 06:46:19 2013 @@ -0,0 +1,89 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.jena.query.spatial.assembler; + +import static org.apache.jena.query.spatial.assembler.SpatialVocab.pDefinition; +import static org.apache.jena.query.spatial.assembler.SpatialVocab.pServer; +import static org.apache.jena.query.spatial.assembler.SpatialVocab.pSolrHome; + +import java.io.FileNotFoundException; + +import org.apache.jena.query.spatial.EntityDefinition; +import org.apache.jena.query.spatial.SpatialDatasetFactory; +import org.apache.jena.query.spatial.SpatialIndex; +import org.apache.jena.query.spatial.SpatialIndexException; +import org.apache.jena.riot.system.IRILib; +import org.apache.solr.client.solrj.SolrServer; +import org.apache.solr.client.solrj.embedded.EmbeddedSolrServer; +import org.apache.solr.client.solrj.impl.HttpSolrServer; +import org.apache.solr.core.CoreContainer; + +import com.hp.hpl.jena.assembler.Assembler; +import com.hp.hpl.jena.assembler.Mode; +import com.hp.hpl.jena.assembler.assemblers.AssemblerBase; +import com.hp.hpl.jena.rdf.model.RDFNode; +import com.hp.hpl.jena.rdf.model.Resource; +import com.hp.hpl.jena.sparql.util.graph.GraphUtils; + +public class SpatialIndexSolrAssembler extends AssemblerBase { + /* + * <#index> a :TextIndexSolr ; text:server + * ; #text:server + * ; text:entityMap <#endMap> ; . + */ + + @Override + public SpatialIndex open(Assembler a, Resource root, Mode mode) { + String uri = GraphUtils.getResourceValue(root, pServer).getURI(); + SolrServer server; + if (uri.startsWith("embedded:")) { + try { + if ( ! GraphUtils.exactlyOneProperty(root, pSolrHome) ) + throw new SpatialIndexException("No 'spatial:solrHome' property on EmbeddedSolrServer "+root) ; + + RDFNode n = root.getProperty(pSolrHome).getObject() ; + + if (n.isLiteral()){ + throw new SpatialIndexException ("No 'spatial:solrHome' property on EmbeddedSolrServer "+root+ " is a literal and not a Resource/URI"); + } + Resource x = n.asResource() ; + String path = IRILib.IRIToFilename(x.getURI()) ; + + System.setProperty("solr.solr.home", path); + String coreName = uri.substring("embedded:".length()); + CoreContainer.Initializer initializer = new CoreContainer.Initializer(); + CoreContainer coreContainer = initializer.initialize(); + server = new EmbeddedSolrServer(coreContainer, coreName); + } catch (FileNotFoundException e) { + throw new SpatialIndexException(e); + // throw new + // SpatialIndexException("Embedded Solr server not supported (change code and dependencies to enable)") + // ; + } + } else if (uri.startsWith("http://")) { + server = new HttpSolrServer(uri); + } else + throw new SpatialIndexException( + "URI for the server must begin 'http://'"); + + Resource r = GraphUtils.getResourceValue(root, pDefinition); + EntityDefinition docDef = (EntityDefinition) a.open(r); + return SpatialDatasetFactory.createSolrIndex(server, docDef); + } +} Propchange: jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/assembler/SpatialIndexSolrAssembler.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/assembler/SpatialVocab.java URL: http://svn.apache.org/viewvc/jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/assembler/SpatialVocab.java?rev=1519358&view=auto ============================================================================== --- jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/assembler/SpatialVocab.java (added) +++ jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/assembler/SpatialVocab.java Mon Sep 2 06:46:19 2013 @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.jena.query.spatial.assembler; + +import com.hp.hpl.jena.rdf.model.Property ; +import com.hp.hpl.jena.rdf.model.Resource ; +import com.hp.hpl.jena.tdb.assembler.Vocab ; + +public class SpatialVocab +{ + public static final String NS = "http://jena.apache.org/spatial#" ; + + public static final Resource spatialDataset = Vocab.resource(NS, "SpatialDataset") ; + public static final Property pDataset = Vocab.property(NS, "dataset") ; + public static final Property pIndex = Vocab.property(NS, "index") ; + + public static final Resource spatialIndex = Vocab.resource(NS, "SpatialIndex") ; + public static final Resource spatialIndexSolr = Vocab.resource(NS, "SpatialIndexSolr") ; + public static final Resource spatialIndexLucene = Vocab.resource(NS, "SpatialIndexLucene") ; + public static final Property pServer = Vocab.property(NS, "server") ; // Solr + public static final Property pSolrHome = Vocab.property(NS, "solrHome") ; // EmbeddedSolrServer + public static final Property pDirectory = Vocab.property(NS, "directory") ; // Lucene + public static final Property pDefinition = Vocab.property(NS, "definition") ; + + // Entity definition + public static final Resource definition = Vocab.resource(NS, "EntityDefinition") ; + public static final Property pEntityField = Vocab.property(NS, "entityField") ; + public static final Property pGeoField = Vocab.property(NS, "geoField") ; + public static final Property pHasSpatialPredicatePairs = Vocab.property(NS, "hasSpatialPredicatePairs") ; + public static final Property pHasWKTPredicates = Vocab.property(NS, "hasWKTPredicates") ; + public static final Property pLatitude = Vocab.property(NS, "latitude") ; + public static final Property pLongitude = Vocab.property(NS, "longitude") ; + // public static final Property pOptional = Vocab.property(NS, "optional") ; + +} + Propchange: jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/assembler/SpatialVocab.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/pfunction/DirectionWithPointPFBase.java URL: http://svn.apache.org/viewvc/jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/pfunction/DirectionWithPointPFBase.java?rev=1519358&view=auto ============================================================================== --- jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/pfunction/DirectionWithPointPFBase.java (added) +++ jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/pfunction/DirectionWithPointPFBase.java Mon Sep 2 06:46:19 2013 @@ -0,0 +1,146 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.jena.query.spatial.pfunction; + +import java.util.List; + +import org.apache.jena.query.spatial.SpatialIndexException; +import org.apache.jena.query.spatial.SpatialValueUtil; +import org.apache.lucene.spatial.query.SpatialOperation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.hp.hpl.jena.datatypes.xsd.XSDDatatype; +import com.hp.hpl.jena.graph.Node; +import com.hp.hpl.jena.graph.impl.LiteralLabel; +import com.hp.hpl.jena.query.QueryBuildException; +import com.hp.hpl.jena.sparql.engine.ExecutionContext; +import com.hp.hpl.jena.sparql.pfunction.PropFuncArg; +import com.hp.hpl.jena.sparql.util.NodeFactoryExtra; + +public abstract class DirectionWithPointPFBase extends SpatialOperationPFBase { + + private static Logger log = LoggerFactory.getLogger(DirectionWithPointPFBase.class); + + public DirectionWithPointPFBase() { + + } + + @Override + public void build(PropFuncArg argSubject, Node predicate, + PropFuncArg argObject, ExecutionContext execCxt) { + super.build(argSubject, predicate, argObject, execCxt); + + if (!argSubject.isNode()) + throw new QueryBuildException("Subject is not a single node: " + + argSubject); + + if (argObject.isList()) { + List list = argObject.getArgList(); + if (list.size() < 2) + throw new QueryBuildException("Not enough arguments in list"); + + if (list.size() > 3) + throw new QueryBuildException("Too many arguments in list : " + + list); + } + } + + + /** Deconstruct the node or list object argument and make a SpatialMatch */ + protected SpatialMatch objectToStruct(PropFuncArg argObject) { + if (argObject.isNode()) { + log.warn("Object not a List: " + argObject); + return null; + } + + List list = argObject.getArgList(); + + if (list.size() < 2 || list.size() > 3) + throw new SpatialIndexException("Change in object list size"); + + int idx = 0; + + Node x = list.get(idx); + if (!x.isLiteral()) { + log.warn("Latitude is not a literal " + list); + return null; + } + if (!SpatialValueUtil.isDecimal(x.getLiteral())) { + log.warn("Latitude is not a decimal " + list); + return null; + } + Double latitude = Double.parseDouble(x.getLiteralLexicalForm()); + + idx++; + + x = list.get(idx); + if (!x.isLiteral()) { + log.warn("Longitude is not a literal " + list); + return null; + } + if (!SpatialValueUtil.isDecimal(x.getLiteral())) { + log.warn("Longitude is not a decimal " + list); + return null; + } + Double longitude = Double.parseDouble(x.getLiteralLexicalForm()); + + idx++; + + int limit =-1; + + if (idx < list.size()) { + x = list.get(idx); + + if (!x.isLiteral()) { + log.warn("Limit is not a literal " + list); + return null; + } + + LiteralLabel lit = x.getLiteral(); + + if (!XSDDatatype.XSDinteger.isValidLiteral(lit)) { + log.warn("Limit is not an integer " + list); + return null; + } + + int v = NodeFactoryExtra.nodeToInt(x); + limit = (v < 0) ? -1 : v; + + idx++; + if (idx < list.size()) { + log.warn("Limit is not the last parameter " + list); + return null; + } + } + + SpatialMatch match = this.getSpatialMatch(latitude, longitude, limit); + if (log.isDebugEnabled()) + log.debug("Trying SpatialMatch: " + match.toString()); + return match; + } + + protected abstract SpatialMatch getSpatialMatch(Double latitude, Double longitude, int limit); + + @Override + protected SpatialOperation getSpatialOperation() { + return SpatialOperation.IsWithin; + } + +} Propchange: jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/pfunction/DirectionWithPointPFBase.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/pfunction/SpatialMatch.java URL: http://svn.apache.org/viewvc/jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/pfunction/SpatialMatch.java?rev=1519358&view=auto ============================================================================== --- jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/pfunction/SpatialMatch.java (added) +++ jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/pfunction/SpatialMatch.java Mon Sep 2 06:46:19 2013 @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.jena.query.spatial.pfunction; + +import org.apache.jena.query.spatial.DistanceUnitsUtils; +import org.apache.jena.query.spatial.SpatialQuery; +import org.apache.lucene.spatial.query.SpatialOperation; + +import com.spatial4j.core.shape.Shape; + +public class SpatialMatch { + + private final Shape shape; + private final int limit; + private final SpatialOperation operation; + + public SpatialMatch(Double latitude, Double longitude, Double radius, + String units, int limit, SpatialOperation operation) { + + double degrees = DistanceUnitsUtils.dist2Degrees(radius, units); + this.shape = SpatialQuery.ctx.makeCircle(longitude, latitude, degrees); + //System.out.println( SpatialQuery.ctx.toString(shape) ); + this.limit = limit; + this.operation = operation; + } + + public SpatialMatch(Double latitude1, Double longitude1, Double latitude2, + Double longitude2, int limit, SpatialOperation operation) { + this.shape = SpatialQuery.ctx.makeRectangle(longitude1, longitude2, latitude1, latitude2); + this.limit = limit; + this.operation = operation; + } + + public Shape getShape() { + return shape; + } + + public int getLimit() { + return limit; + } + + public SpatialOperation getSpatialOperation() { + return operation; + } + + public String toString() { + return "(" + shape + " " + limit + " " + operation + ")"; + } + +} Propchange: jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/pfunction/SpatialMatch.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/pfunction/SpatialOperationPFBase.java URL: http://svn.apache.org/viewvc/jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/pfunction/SpatialOperationPFBase.java?rev=1519358&view=auto ============================================================================== --- jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/pfunction/SpatialOperationPFBase.java (added) +++ jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/pfunction/SpatialOperationPFBase.java Mon Sep 2 06:46:19 2013 @@ -0,0 +1,161 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.jena.query.spatial.pfunction; + +import java.util.List; + +import org.apache.jena.atlas.iterator.Iter; +import org.apache.jena.atlas.lib.InternalErrorException; +import org.apache.jena.atlas.logging.Log; +import org.apache.jena.query.spatial.DatasetGraphSpatial; +import org.apache.jena.query.spatial.SpatialIndex; +import org.apache.jena.query.spatial.SpatialQuery; +import org.apache.lucene.spatial.query.SpatialOperation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.hp.hpl.jena.graph.Node; +import com.hp.hpl.jena.sparql.core.DatasetGraph; +import com.hp.hpl.jena.sparql.core.Var; +import com.hp.hpl.jena.sparql.engine.ExecutionContext; +import com.hp.hpl.jena.sparql.engine.QueryIterator; +import com.hp.hpl.jena.sparql.engine.binding.Binding; +import com.hp.hpl.jena.sparql.engine.iterator.QueryIterExtendByVar; +import com.hp.hpl.jena.sparql.engine.iterator.QueryIterSlice; +import com.hp.hpl.jena.sparql.pfunction.PropFuncArg; +import com.hp.hpl.jena.sparql.pfunction.PropertyFunctionBase; +import com.hp.hpl.jena.sparql.util.IterLib; + +public abstract class SpatialOperationPFBase extends PropertyFunctionBase { + + private static Logger log = LoggerFactory.getLogger(SpatialOperationPFBase.class); + + protected SpatialIndex server = null; + private boolean warningIssued = false; + + public SpatialOperationPFBase() { + } + + @Override + public void build(PropFuncArg argSubject, Node predicate, + PropFuncArg argObject, ExecutionContext execCxt) { + super.build(argSubject, predicate, argObject, execCxt); + DatasetGraph dsg = execCxt.getDataset(); + server = chooseTextIndex(dsg); + } + + protected SpatialIndex chooseTextIndex(DatasetGraph dsg) { + Object obj = dsg.getContext().get(SpatialQuery.spatialIndex); + + if (obj != null) { + try { + return (SpatialIndex) obj; + } catch (ClassCastException ex) { + Log.warn(SpatialOperationWithCircleBase.class, "Context setting '" + + SpatialQuery.spatialIndex + "'is not a SpatialIndex"); + } + } + + if (dsg instanceof DatasetGraphSpatial) { + DatasetGraphSpatial x = (DatasetGraphSpatial) dsg; + return x.getSpatialIndex(); + } + Log.warn( + SpatialOperationWithCircleBase.class, + "Failed to find the spatial index : tried context and as a spatial-enabled dataset"); + return null; + } + + @Override + public QueryIterator exec(Binding binding, PropFuncArg argSubject, + Node predicate, PropFuncArg argObject, ExecutionContext execCxt) { + if (server == null) { + if (!warningIssued) { + Log.warn(getClass(), "No text index - no text search performed"); + warningIssued = true; + } + // Not a text dataset - no-op + return IterLib.result(binding, execCxt); + } + + DatasetGraph dsg = execCxt.getDataset(); + + if (!argSubject.isNode()) + throw new InternalErrorException( + "Subject is not a node (it was earlier!)"); + + Node s = argSubject.getArg(); + + if (s.isLiteral()) + // Does not match + return IterLib.noResults(execCxt); + + SpatialMatch match = objectToStruct(argObject); + + if (match == null) { + // can't match + return IterLib.noResults(execCxt); + } + + // ---- + + QueryIterator qIter = (Var.isVar(s)) ? variableSubject(binding, s, + match, execCxt) : concreteSubject(binding, s, match, execCxt); + if (match.getLimit() >= 0) + qIter = new QueryIterSlice(qIter, 0, match.getLimit(), execCxt); + return qIter; + } + + private QueryIterator variableSubject(Binding binding, Node s, + SpatialMatch match, ExecutionContext execCxt) { + + Var v = Var.alloc(s); + List r = query(match); + // Make distinct. Note interaction with limit is imperfect + r = Iter.iter(r).distinct().toList(); + QueryIterator qIter = new QueryIterExtendByVar(binding, v, + r.iterator(), execCxt); + return qIter; + } + + private QueryIterator concreteSubject(Binding binding, Node s, + SpatialMatch match, ExecutionContext execCxt) { + if (!s.isURI()) { + log.warn("Subject not a URI: " + s); + return IterLib.noResults(execCxt); + } + + List x = query(match); + if (x == null || !x.contains(s)) + return IterLib.noResults(execCxt); + else + return IterLib.result(binding, execCxt); + } + + private List query(SpatialMatch match) { + + return server.query(match.getShape(), match.getLimit(), + match.getSpatialOperation()); + } + + /** Deconstruct the node or list object argument and make a SpatialMatch */ + protected abstract SpatialMatch objectToStruct(PropFuncArg argObject); + + protected abstract SpatialOperation getSpatialOperation(); +} Propchange: jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/pfunction/SpatialOperationPFBase.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/pfunction/SpatialOperationWithBoxPFBase.java URL: http://svn.apache.org/viewvc/jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/pfunction/SpatialOperationWithBoxPFBase.java?rev=1519358&view=auto ============================================================================== --- jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/pfunction/SpatialOperationWithBoxPFBase.java (added) +++ jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/pfunction/SpatialOperationWithBoxPFBase.java Mon Sep 2 06:46:19 2013 @@ -0,0 +1,164 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.jena.query.spatial.pfunction; + +import java.util.List; + +import org.apache.jena.query.spatial.SpatialIndexException; +import org.apache.jena.query.spatial.SpatialValueUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.hp.hpl.jena.datatypes.xsd.XSDDatatype; +import com.hp.hpl.jena.graph.Node; +import com.hp.hpl.jena.graph.impl.LiteralLabel; +import com.hp.hpl.jena.query.QueryBuildException; +import com.hp.hpl.jena.sparql.engine.ExecutionContext; +import com.hp.hpl.jena.sparql.pfunction.PropFuncArg; +import com.hp.hpl.jena.sparql.util.NodeFactoryExtra; + +public abstract class SpatialOperationWithBoxPFBase extends SpatialOperationPFBase { + private static Logger log = LoggerFactory.getLogger(SpatialOperationWithCircleBase.class); + + public SpatialOperationWithBoxPFBase() { + } + + @Override + public void build(PropFuncArg argSubject, Node predicate, + PropFuncArg argObject, ExecutionContext execCxt) { + super.build(argSubject, predicate, argObject, execCxt); + + if (!argSubject.isNode()) + throw new QueryBuildException("Subject is not a single node: " + + argSubject); + + if (argObject.isList()) { + List list = argObject.getArgList(); + if (list.size() < 4) + throw new QueryBuildException("Not enough arguments in list"); + + if (list.size() > 5) + throw new QueryBuildException("Too many arguments in list : " + + list); + } + } + + /** Deconstruct the node or list object argument and make a SpatialMatch */ + protected SpatialMatch objectToStruct(PropFuncArg argObject) { + + if (argObject.isNode()) { + log.warn("Object not a List: " + argObject); + return null; + } + + List list = argObject.getArgList(); + + if (list.size() < 4 || list.size() > 5) + throw new SpatialIndexException("Change in object list size"); + + int idx = 0; + + Node x = list.get(idx); + if (!x.isLiteral()) { + log.warn("Latitude 1 is not a literal " + list); + return null; + } + if (!SpatialValueUtil.isDecimal(x.getLiteral())) { + log.warn("Latitude 1 is not a decimal " + list); + return null; + } + Double latitude1 = Double.parseDouble(x.getLiteralLexicalForm()); + + idx++; + + x = list.get(idx); + if (!x.isLiteral()) { + log.warn("Longitude 1 is not a literal " + list); + return null; + } + if (!SpatialValueUtil.isDecimal(x.getLiteral())) { + log.warn("Longitude 1 is not a decimal " + list); + return null; + } + Double longtitude1 = Double.parseDouble(x.getLiteralLexicalForm()); + + idx++; + + x = list.get(idx); + if (!x.isLiteral()) { + log.warn("Latitude 2 is not a literal " + list); + return null; + } + if (!SpatialValueUtil.isDecimal(x.getLiteral())) { + log.warn("Latitude 2 is not a decimal " + list); + return null; + } + Double latitude2 = Double.parseDouble(x.getLiteralLexicalForm()); + + idx++; + + x = list.get(idx); + if (!x.isLiteral()) { + log.warn("Longitude 2 is not a literal " + list); + return null; + } + if (!SpatialValueUtil.isDecimal(x.getLiteral())) { + log.warn("Longitude 2 is not a decimal " + list); + return null; + } + Double longtitude2 = Double.parseDouble(x.getLiteralLexicalForm()); + + idx++; + int limit =-1; + + if (idx < list.size()) { + x = list.get(idx); + + if (!x.isLiteral()) { + log.warn("Limit is not a literal " + list); + return null; + } + + LiteralLabel lit = x.getLiteral(); + + if (!XSDDatatype.XSDinteger.isValidLiteral(lit)) { + log.warn("Limit is not an integer " + list); + return null; + } + + int v = NodeFactoryExtra.nodeToInt(x); + limit = (v < 0) ? -1 : v; + + idx++; + if (idx < list.size()) { + log.warn("Limit is not the last parameter " + list); + return null; + } + } + + SpatialMatch match = new SpatialMatch(latitude1, longtitude1, + latitude2, longtitude2, limit, getSpatialOperation()); + + if (log.isDebugEnabled()) + log.debug("Trying SpatialMatch: " + match.toString()); + return match; + } + + +} Propchange: jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/pfunction/SpatialOperationWithBoxPFBase.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/pfunction/SpatialOperationWithCircleBase.java URL: http://svn.apache.org/viewvc/jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/pfunction/SpatialOperationWithCircleBase.java?rev=1519358&view=auto ============================================================================== --- jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/pfunction/SpatialOperationWithCircleBase.java (added) +++ jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/pfunction/SpatialOperationWithCircleBase.java Mon Sep 2 06:46:19 2013 @@ -0,0 +1,181 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.jena.query.spatial.pfunction; + +import java.util.List; + +import org.apache.jena.query.spatial.DistanceUnitsUtils; +import org.apache.jena.query.spatial.SpatialIndexException; +import org.apache.jena.query.spatial.SpatialValueUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.hp.hpl.jena.datatypes.xsd.XSDDatatype; +import com.hp.hpl.jena.graph.Node; +import com.hp.hpl.jena.graph.impl.LiteralLabel; +import com.hp.hpl.jena.query.QueryBuildException; +import com.hp.hpl.jena.sparql.engine.ExecutionContext; +import com.hp.hpl.jena.sparql.pfunction.PropFuncArg; +import com.hp.hpl.jena.sparql.util.NodeFactoryExtra; + +/** property function that accesses a spatial server */ +public abstract class SpatialOperationWithCircleBase extends SpatialOperationPFBase { + + private static Logger log = LoggerFactory.getLogger(SpatialOperationWithCircleBase.class); + + public SpatialOperationWithCircleBase() { + } + + @Override + public void build(PropFuncArg argSubject, Node predicate, + PropFuncArg argObject, ExecutionContext execCxt) { + super.build(argSubject, predicate, argObject, execCxt); + + if (!argSubject.isNode()) + throw new QueryBuildException("Subject is not a single node: " + + argSubject); + + if (argObject.isList()) { + List list = argObject.getArgList(); + if (list.size() < 3) + throw new QueryBuildException("Not enough arguments in list"); + + if (list.size() > 5) + throw new QueryBuildException("Too many arguments in list : " + + list); + } + } + /** Deconstruct the node or list object argument and make a NearbyMatch */ + protected SpatialMatch objectToStruct(PropFuncArg argObject) { + + // EntityDefinition docDef = server.getDocDef(); + if (argObject.isNode()) { + log.warn("Object not a List: " + argObject); + return null; + } + + List list = argObject.getArgList(); + + if (list.size() < 3 || list.size() > 5) + throw new SpatialIndexException("Change in object list size"); + + int idx = 0; + + Node x = list.get(idx); + if (!x.isLiteral()) { + log.warn("Latitude is not a literal " + list); + return null; + } + if (!SpatialValueUtil.isDecimal(x.getLiteral())) { + log.warn("Latitude is not a decimal " + list); + return null; + } + Double latitude = Double.parseDouble(x.getLiteralLexicalForm()); + + idx++; + + x = list.get(idx); + if (!x.isLiteral()) { + log.warn("Longitude is not a literal " + list); + return null; + } + if (!SpatialValueUtil.isDecimal(x.getLiteral())) { + log.warn("Longitude is not a decimal " + list); + return null; + } + Double longtitude = Double.parseDouble(x.getLiteralLexicalForm()); + + idx++; + + x = list.get(idx); + + if (!x.isLiteral()) { + log.warn("Radius is not a literal " + list); + return null; + } + if (!SpatialValueUtil.isDecimal(x.getLiteral())) { + log.warn("Radius is not a decimal " + list); + return null; + } + Double radius = Double.parseDouble(x.getLiteralLexicalForm()); + + if (radius <= 0) { + log.warn("Radius is not a correct decimal " + list); + return null; + } + + String units = "miles"; + int limit = -1; + + idx++; + + if (idx < list.size()) { + x = list.get(idx); + + if (!x.isLiteral()) { + log.warn("Units or limit is not a literal " + list); + return null; + } + if (x.getLiteralDatatype() == null + || x.getLiteralDatatype().equals(XSDDatatype.XSDstring)) { + String u = x.getLiteralLexicalForm(); + if (DistanceUnitsUtils.isSupportedUnits(u)) { + idx++; + units = u; + } else { + log.warn("Units are not a supported " + list); + return null; + } + } + } + + if (idx < list.size()) { + x = list.get(idx); + + if (!x.isLiteral()) { + log.warn("Limit is not a literal " + list); + return null; + } + + LiteralLabel lit = x.getLiteral(); + + if (!XSDDatatype.XSDinteger.isValidLiteral(lit)) { + log.warn("Limit is not an integer " + list); + return null; + } + + int v = NodeFactoryExtra.nodeToInt(x); + limit = (v < 0) ? -1 : v; + + idx++; + if (idx < list.size()) { + log.warn("Limit is not the last parameter " + list); + return null; + } + } + + SpatialMatch match = new SpatialMatch(latitude, longtitude, radius, + units, limit, this.getSpatialOperation()); + + if (log.isDebugEnabled()) + log.debug("Trying SpatialMatch: " + match.toString()); + return match; + } + +} Propchange: jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/pfunction/SpatialOperationWithCircleBase.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/pfunction/library/EastPF.java URL: http://svn.apache.org/viewvc/jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/pfunction/library/EastPF.java?rev=1519358&view=auto ============================================================================== --- jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/pfunction/library/EastPF.java (added) +++ jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/pfunction/library/EastPF.java Mon Sep 2 06:46:19 2013 @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.jena.query.spatial.pfunction.library; + +import org.apache.jena.query.spatial.SpatialQuery; +import org.apache.jena.query.spatial.pfunction.DirectionWithPointPFBase; +import org.apache.jena.query.spatial.pfunction.SpatialMatch; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class EastPF extends DirectionWithPointPFBase { + + private static Logger log = LoggerFactory.getLogger(EastPF.class); + + public EastPF() { + // TODO Auto-generated constructor stub + } + + /** Deconstruct the node or list object argument and make a SpatialMatch */ + protected SpatialMatch getSpatialMatch(Double latitude, Double longitude, + int limit) { + SpatialMatch match = new SpatialMatch(SpatialQuery.ctx.getWorldBounds().getMinY(), + longitude, SpatialQuery.ctx.getWorldBounds().getMaxY(), SpatialQuery.ctx.getWorldBounds() + .getMaxX(), limit, getSpatialOperation()); + return match; + } + +} Propchange: jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/pfunction/library/EastPF.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/pfunction/library/IntersectsBoxPF.java URL: http://svn.apache.org/viewvc/jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/pfunction/library/IntersectsBoxPF.java?rev=1519358&view=auto ============================================================================== --- jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/pfunction/library/IntersectsBoxPF.java (added) +++ jena/trunk/jena-spatial/src/main/java/org/apache/jena/query/spatial/pfunction/library/IntersectsBoxPF.java Mon Sep 2 06:46:19 2013 @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.jena.query.spatial.pfunction.library; + +import org.apache.jena.query.spatial.pfunction.SpatialOperationWithBoxPFBase; +import org.apache.lucene.spatial.query.SpatialOperation; + +public class IntersectsBoxPF extends SpatialOperationWithBoxPFBase { + + public IntersectsBoxPF() { + } + + + @Override + protected SpatialOperation getSpatialOperation() { + return SpatialOperation.Intersects; + } + +}