allowing queries with bnodes
diff --git a/impl.sparql/src/main/java/org/apache/commons/rdf/impl/sparql/SparqlBNode.java b/impl.sparql/src/main/java/org/apache/commons/rdf/impl/sparql/SparqlBNode.java
index c74aa06..f55f7af 100644
--- a/impl.sparql/src/main/java/org/apache/commons/rdf/impl/sparql/SparqlBNode.java
+++ b/impl.sparql/src/main/java/org/apache/commons/rdf/impl/sparql/SparqlBNode.java
@@ -32,7 +32,7 @@
*/
class SparqlBNode extends BlankNode {
- private final static Iri internalBNodeId = new Iri("urn:x-internalid:fdmpoihdfw");
+ final static Iri internalBNodeId = new Iri("urn:x-internalid:fdmpoihdfw");
final ImmutableGraph context;
private final int isoDistinguisher;
diff --git a/impl.sparql/src/main/java/org/apache/commons/rdf/impl/sparql/SparqlClient.java b/impl.sparql/src/main/java/org/apache/commons/rdf/impl/sparql/SparqlClient.java
index ca3f619..e522924 100644
--- a/impl.sparql/src/main/java/org/apache/commons/rdf/impl/sparql/SparqlClient.java
+++ b/impl.sparql/src/main/java/org/apache/commons/rdf/impl/sparql/SparqlClient.java
@@ -1,21 +1,26 @@
/*
- * To change this license header, choose License Headers in Project Properties.
- * To change this template file, choose Tools | Templates
- * and open the template in the editor.
+ * Copyright 2015 The Apache Software Foundation.
+ *
+ * Licensed 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.commons.rdf.impl.sparql;
import java.io.IOException;
import java.io.InputStream;
-import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
-import java.util.Enumeration;
import java.util.HashMap;
-import java.util.Hashtable;
import java.util.List;
import java.util.Map;
-import java.util.logging.Level;
-import java.util.logging.Logger;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
@@ -27,12 +32,9 @@
import org.apache.http.util.EntityUtils;
import javax.xml.parsers.*;
import org.apache.commons.rdf.BlankNode;
-import org.apache.commons.rdf.BlankNodeOrIri;
import org.apache.commons.rdf.Iri;
import org.apache.commons.rdf.Language;
-import org.apache.commons.rdf.Literal;
import org.apache.commons.rdf.RdfTerm;
-import org.apache.commons.rdf.Triple;
import org.apache.commons.rdf.impl.utils.AbstractLiteral;
import org.xml.sax.*;
import org.xml.sax.helpers.*;
diff --git a/impl.sparql/src/main/java/org/apache/commons/rdf/impl/sparql/SparqlGraph.java b/impl.sparql/src/main/java/org/apache/commons/rdf/impl/sparql/SparqlGraph.java
index 720f7df..7a4c48d 100644
--- a/impl.sparql/src/main/java/org/apache/commons/rdf/impl/sparql/SparqlGraph.java
+++ b/impl.sparql/src/main/java/org/apache/commons/rdf/impl/sparql/SparqlGraph.java
@@ -26,7 +26,6 @@
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.concurrent.Callable;
-import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.rdf.BlankNode;
import org.apache.commons.rdf.BlankNodeOrIri;
@@ -50,7 +49,6 @@
private static final Logger log = Logger.getLogger(SparqlGraph.class.getName());
final SparqlClient sparqlClient;
-
/**
* Constructs a Graph representing the default graph at the specified
@@ -64,27 +62,8 @@
protected Iterator<Triple> performFilter(final BlankNodeOrIri filterSubject,
final Iri filterPredicate, final RdfTerm filterObject) {
try {
- final StringBuilder queryBuilder = new StringBuilder();
- queryBuilder.append("SELECT ?s ?p ?o WHERE { ");
- if (filterSubject == null) {
- queryBuilder.append("?s");
- } else {
- queryBuilder.append(asSparqlTerm(filterSubject));
- }
- queryBuilder.append(' ');
- if (filterPredicate == null) {
- queryBuilder.append("?p");
- } else {
- queryBuilder.append(asSparqlTerm(filterPredicate));
- }
- queryBuilder.append(' ');
- if (filterObject == null) {
- queryBuilder.append("?o");
- } else {
- queryBuilder.append(asSparqlTerm(filterObject));
- }
- queryBuilder.append(" }");
- final List<Map<String, RdfTerm>> sparqlResults = sparqlClient.queryResultSet(queryBuilder.toString());
+ String query = createQuery(filterSubject, filterPredicate, filterObject);
+ final List<Map<String, RdfTerm>> sparqlResults = sparqlClient.queryResultSet(query);
//first to triples without bnode-conversion
//rawTriples contains the triples with the BNodes from the result set
final Collection<Triple> rawTriples = new ArrayList<>();
@@ -231,57 +210,10 @@
* @return
*/
private Set<ImmutableGraph> expandContext(Collection<Triple> startContext) throws IOException {
- final Collection<String> triplePatterns = new ArrayList<>();
- int varCounter = 0;
- final Map<BlankNode, String> bNodeVarNameMap = new HashMap<>();
- for (Triple t : startContext) {
- final StringBuilder builder = new StringBuilder();
- {
- final BlankNodeOrIri s = t.getSubject();
- String varName;
- if (s instanceof BlankNode) {
- if (bNodeVarNameMap.containsKey(s)) {
- varName = bNodeVarNameMap.get(s);
- } else {
- varName = "v" + (varCounter++);
- bNodeVarNameMap.put((BlankNode) s, varName);
-
- }
- builder.append('?');
- builder.append(varName);
- } else {
- builder.append(asSparqlTerm(s));
- }
- }
- builder.append(' ');
- builder.append(asSparqlTerm(t.getPredicate()));
- builder.append(' ');
- {
- final RdfTerm o = t.getObject();
- String varName;
- if (o instanceof BlankNode) {
- if (bNodeVarNameMap.containsKey(o)) {
- varName = bNodeVarNameMap.get(o);
- } else {
- varName = "v" + (varCounter++);
- bNodeVarNameMap.put((BlankNode) o, varName);
- }
- builder.append('?');
- builder.append(varName);
- } else {
- builder.append(asSparqlTerm(o));
- }
- }
- builder.append('.');
- triplePatterns.add(builder.toString());
- }
final StringBuilder queryBuilder = new StringBuilder();
queryBuilder.append("SELECT * WHERE {\n ");
- for (String triplePattern : triplePatterns) {
- queryBuilder.append(triplePattern);
- queryBuilder.append('\n');
- }
+ Map<BlankNode, String> bNodeVarNameMap = writeTriplePattern(queryBuilder, startContext);
Set<BlankNode> bNodesInContext = bNodeVarNameMap.keySet();
for (BlankNode bNode : bNodesInContext) {
final String bNodeVarLabel = bNodeVarNameMap.get(bNode);
@@ -404,6 +336,49 @@
}
}
+ private String createQuery(final BlankNodeOrIri filterSubject, final Iri filterPredicate, final RdfTerm filterObject) {
+ final StringBuilder queryBuilder = new StringBuilder();
+ queryBuilder.append("SELECT ?s ?p ?o WHERE { ");
+ if (filterSubject == null) {
+ queryBuilder.append("?s");
+ } else {
+ if (filterSubject instanceof SparqlBNode) {
+ queryBuilder.append("?sn");
+ } else {
+ queryBuilder.append(asSparqlTerm(filterSubject));
+ }
+ }
+ queryBuilder.append(' ');
+ if (filterPredicate == null) {
+ queryBuilder.append("?p");
+ } else {
+ queryBuilder.append(asSparqlTerm(filterPredicate));
+ }
+ queryBuilder.append(' ');
+ if (filterObject == null) {
+ queryBuilder.append("?o");
+ } else {
+ if (filterObject instanceof SparqlBNode) {
+ queryBuilder.append("?on");
+ } else {
+ queryBuilder.append(asSparqlTerm(filterObject));
+ }
+ }
+ queryBuilder.append(" .\n");
+ if (filterSubject instanceof SparqlBNode) {
+ //expand bnode context
+ writeTriplePattern(queryBuilder, ((SparqlBNode) filterSubject).context, "sn");
+ }
+
+ if (filterObject instanceof SparqlBNode) {
+ //expand bnode context
+ writeTriplePattern(queryBuilder, ((SparqlBNode) filterObject).context, "on");
+ }
+
+ queryBuilder.append(" }");
+ return queryBuilder.toString();
+ }
+
@Override
protected int performSize() {
try {
@@ -427,7 +402,7 @@
throw new AlienBNodeException();
}
//this requires adding additional clauses to the graph pattern
- throw new UnsupportedOperationException("Not supported yet.");
+ throw new RuntimeException("SparqlBNodes should have been handled earlier");
}
private String asSparqlTerm(BlankNodeOrIri term) {
@@ -446,10 +421,80 @@
}
}
+
+ private Map<BlankNode, String> writeTriplePattern(StringBuilder queryBuilder, Collection<Triple> triples) {
+ return writeTriplePattern(queryBuilder, triples, null);
+ }
+
+ private Map<BlankNode, String> writeTriplePattern(StringBuilder queryBuilder, Collection<Triple> triples, String varLabelForInternalBNodeId) {
+ final Collection<String> triplePatterns = new ArrayList<>();
+ int varCounter = 0;
+ final Map<BlankNode, String> bNodeVarNameMap = new HashMap<>();
+ for (Triple t : triples) {
+ final StringBuilder builder = new StringBuilder();
+ {
+ final BlankNodeOrIri s = t.getSubject();
+ String varName;
+ if (s instanceof BlankNode) {
+ if (bNodeVarNameMap.containsKey(s)) {
+ varName = bNodeVarNameMap.get(s);
+ } else {
+ varName = "v" + (varCounter++);
+ bNodeVarNameMap.put((BlankNode) s, varName);
+ }
+ builder.append('?');
+ builder.append(varName);
+ } else {
+ if (s.equals(SparqlBNode.internalBNodeId)) {
+ builder.append('?');
+ builder.append(varLabelForInternalBNodeId);
+ } else {
+ builder.append(asSparqlTerm(s));
+ }
+
+ }
+ }
+ builder.append(' ');
+ builder.append(asSparqlTerm(t.getPredicate()));
+ builder.append(' ');
+ {
+ final RdfTerm o = t.getObject();
+ String varName;
+ if (o instanceof BlankNode) {
+ if (bNodeVarNameMap.containsKey(o)) {
+ varName = bNodeVarNameMap.get(o);
+ } else {
+ varName = "v" + (varCounter++);
+ bNodeVarNameMap.put((BlankNode) o, varName);
+ }
+ builder.append('?');
+ builder.append(varName);
+ } else {
+ if (o.equals(SparqlBNode.internalBNodeId)) {
+ builder.append('?');
+ builder.append(varLabelForInternalBNodeId);
+ } else {
+ builder.append(asSparqlTerm(o));
+ }
+ }
+ }
+ builder.append('.');
+ triplePatterns.add(builder.toString());
+
+ }
+ for (String triplePattern : triplePatterns) {
+
+ queryBuilder.append(triplePattern);
+ queryBuilder.append('\n');
+ }
+ return bNodeVarNameMap;
+
+ }
+
private static class AlienBNodeException extends RuntimeException {
public AlienBNodeException() {
}
}
-}
\ No newline at end of file
+}
diff --git a/impl.sparql/src/test/java/org/apache/commons/rdf/impl/sparql/BNodeCircleTest.java b/impl.sparql/src/test/java/org/apache/commons/rdf/impl/sparql/BNodeCircleTest.java
index 5208d34..9329c9b 100644
--- a/impl.sparql/src/test/java/org/apache/commons/rdf/impl/sparql/BNodeCircleTest.java
+++ b/impl.sparql/src/test/java/org/apache/commons/rdf/impl/sparql/BNodeCircleTest.java
@@ -1,35 +1,38 @@
/*
- * To change this license header, choose License Headers in Project Properties.
- * To change this template file, choose Tools | Templates
- * and open the template in the editor.
+ * Copyright 2015 The Apache Software Foundation.
+ *
+ * Licensed 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.commons.rdf.impl.sparql;
import com.hp.hpl.jena.query.DatasetAccessor;
import com.hp.hpl.jena.query.DatasetAccessorFactory;
-import java.io.File;
import java.io.IOException;
import java.net.ServerSocket;
import org.apache.jena.fuseki.EmbeddedFusekiServer;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import java.io.InputStream;
-import java.util.HashSet;
import java.util.Iterator;
-import java.util.Set;
import org.apache.commons.rdf.BlankNode;
import org.apache.commons.rdf.BlankNodeOrIri;
import org.apache.commons.rdf.Graph;
import org.apache.commons.rdf.Iri;
-import org.apache.commons.rdf.Language;
-import org.apache.commons.rdf.Literal;
import org.apache.commons.rdf.RdfTerm;
import org.apache.commons.rdf.Triple;
-import org.apache.commons.rdf.impl.utils.PlainLiteralImpl;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
-import org.junit.Ignore;
import org.junit.Test;
/**
@@ -71,10 +74,24 @@
@Test
public void nullFilter() {
final Graph graph = new SparqlGraph("http://localhost:" + serverPort + "/ds/query");
+ final Iterator<Triple> iter = graph.filter(null, null, null);
+ Assert.assertTrue(iter.hasNext());
+ final Triple triple1 = iter.next();
+ final BlankNodeOrIri subject = triple1.getSubject();
+ final RdfTerm object = triple1.getObject();
+ Assert.assertTrue(subject instanceof BlankNode);
+ Assert.assertTrue(object instanceof BlankNode);
+ Assert.assertNotEquals(subject, object);
+ Assert.assertTrue(iter.hasNext());
+ }
+
+ @Test
+ public void foafKnowsFilter() {
+ final Graph graph = new SparqlGraph("http://localhost:" + serverPort + "/ds/query");
final Iri foafKnows = new Iri("http://xmlns.com/foaf/0.1/knows");
- final Iterator<Triple> iter = graph.filter(null, null, null);
+ final Iterator<Triple> iter = graph.filter(null, foafKnows, null);
Assert.assertTrue(iter.hasNext());
final Triple triple1 = iter.next();
final BlankNodeOrIri subject = triple1.getSubject();
diff --git a/impl.sparql/src/test/java/org/apache/commons/rdf/impl/sparql/BNodeTest.java b/impl.sparql/src/test/java/org/apache/commons/rdf/impl/sparql/BNodeTest.java
index a376fcd..f0a4aff 100644
--- a/impl.sparql/src/test/java/org/apache/commons/rdf/impl/sparql/BNodeTest.java
+++ b/impl.sparql/src/test/java/org/apache/commons/rdf/impl/sparql/BNodeTest.java
@@ -1,35 +1,38 @@
/*
- * To change this license header, choose License Headers in Project Properties.
- * To change this template file, choose Tools | Templates
- * and open the template in the editor.
+ * Copyright 2015 The Apache Software Foundation.
+ *
+ * Licensed 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.commons.rdf.impl.sparql;
import com.hp.hpl.jena.query.DatasetAccessor;
import com.hp.hpl.jena.query.DatasetAccessorFactory;
-import java.io.File;
import java.io.IOException;
import java.net.ServerSocket;
import org.apache.jena.fuseki.EmbeddedFusekiServer;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import java.io.InputStream;
-import java.util.HashSet;
import java.util.Iterator;
-import java.util.Set;
import org.apache.commons.rdf.BlankNode;
import org.apache.commons.rdf.BlankNodeOrIri;
import org.apache.commons.rdf.Graph;
import org.apache.commons.rdf.Iri;
-import org.apache.commons.rdf.Language;
-import org.apache.commons.rdf.Literal;
import org.apache.commons.rdf.RdfTerm;
import org.apache.commons.rdf.Triple;
-import org.apache.commons.rdf.impl.utils.PlainLiteralImpl;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
-import org.junit.Ignore;
import org.junit.Test;
/**
@@ -105,7 +108,6 @@
Assert.assertEquals(namedThing, knownThing);
}
- @Ignore
@Test
public void filter1() {
final Graph graph = new SparqlGraph("http://localhost:" + serverPort + "/ds/query");
diff --git a/impl.sparql/src/test/java/org/apache/commons/rdf/impl/sparql/SimilarBNodes.java b/impl.sparql/src/test/java/org/apache/commons/rdf/impl/sparql/SimilarBNodes.java
index 1f52c4b..6300281 100644
--- a/impl.sparql/src/test/java/org/apache/commons/rdf/impl/sparql/SimilarBNodes.java
+++ b/impl.sparql/src/test/java/org/apache/commons/rdf/impl/sparql/SimilarBNodes.java
@@ -1,13 +1,20 @@
+/*
+ * Copyright 2015 The Apache Software Foundation.
+ *
+ * Licensed 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.commons.rdf.impl.sparql;
-/*
- * To change this license header, choose License Headers in Project Properties.
- * To change this template file, choose Tools | Templates
- * and open the template in the editor.
- */
-
-
-import org.apache.commons.rdf.impl.sparql.*;
import com.hp.hpl.jena.query.DatasetAccessor;
import com.hp.hpl.jena.query.DatasetAccessorFactory;
import java.io.IOException;
@@ -21,7 +28,6 @@
import org.apache.commons.rdf.BlankNodeOrIri;
import org.apache.commons.rdf.Graph;
import org.apache.commons.rdf.Iri;
-import org.apache.commons.rdf.RdfTerm;
import org.apache.commons.rdf.Triple;
import org.junit.AfterClass;
import org.junit.Assert;
diff --git a/impl.sparql/src/test/java/org/apache/commons/rdf/impl/sparql/SparqlGraphTest.java b/impl.sparql/src/test/java/org/apache/commons/rdf/impl/sparql/SparqlGraphTest.java
index e75bc2c..0c39e9d 100644
--- a/impl.sparql/src/test/java/org/apache/commons/rdf/impl/sparql/SparqlGraphTest.java
+++ b/impl.sparql/src/test/java/org/apache/commons/rdf/impl/sparql/SparqlGraphTest.java
@@ -1,13 +1,22 @@
/*
- * To change this license header, choose License Headers in Project Properties.
- * To change this template file, choose Tools | Templates
- * and open the template in the editor.
+ * Copyright 2015 The Apache Software Foundation.
+ *
+ * Licensed 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.commons.rdf.impl.sparql;
import com.hp.hpl.jena.query.DatasetAccessor;
import com.hp.hpl.jena.query.DatasetAccessorFactory;
-import java.io.File;
import java.io.IOException;
import java.net.ServerSocket;
import org.apache.jena.fuseki.EmbeddedFusekiServer;