Repository: commons-rdf Updated Branches: refs/heads/COMMONSRDF-55 [created] bb264738a
COMMONSRDF-55: Handle Jena's urn:x-arq:DefaultGraph and friends Project: http://git-wip-us.apache.org/repos/asf/commons-rdf/repo Commit: http://git-wip-us.apache.org/repos/asf/commons-rdf/commit/bb264738 Tree: http://git-wip-us.apache.org/repos/asf/commons-rdf/tree/bb264738 Diff: http://git-wip-us.apache.org/repos/asf/commons-rdf/diff/bb264738 Branch: refs/heads/COMMONSRDF-55 Commit: bb264738aa0e3c3a8e9ae8bba0d7109cfb59adaa Parents: 5e2430f Author: Stian Soiland-Reyes <[email protected]> Authored: Fri Jan 27 17:26:59 2017 +0000 Committer: Stian Soiland-Reyes <[email protected]> Committed: Fri Jan 27 17:26:59 2017 +0000 ---------------------------------------------------------------------- .../commons/rdf/api/AbstractDatasetTest.java | 45 +++++++++++ .../commons/rdf/jena/impl/AbstractQuadLike.java | 39 +++++++-- .../rdf/jena/impl/InternalJenaFactory.java | 2 +- .../rdf/jena/DefaultGraphInQuadTest.java | 85 ++++++++++++++++++++ .../apache/commons/rdf/jena/JenaRDFTest.java | 1 - 5 files changed, 165 insertions(+), 7 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/commons-rdf/blob/bb264738/api/src/test/java/org/apache/commons/rdf/api/AbstractDatasetTest.java ---------------------------------------------------------------------- diff --git a/api/src/test/java/org/apache/commons/rdf/api/AbstractDatasetTest.java b/api/src/test/java/org/apache/commons/rdf/api/AbstractDatasetTest.java index 505994f..edde127 100644 --- a/api/src/test/java/org/apache/commons/rdf/api/AbstractDatasetTest.java +++ b/api/src/test/java/org/apache/commons/rdf/api/AbstractDatasetTest.java @@ -158,8 +158,53 @@ public abstract class AbstractDatasetTest { count++; } assertEquals(dataset.size(), count); + + // Pattern iteration which should cover multiple graphs. + + Set<Quad> aliceQuads = new HashSet<>(); + for (Quad aliceQ : dataset.iterate(null, alice, null, null)) { + aliceQuads.add(aliceQ); + } + assertTrue(aliceQuads.contains(factory.createQuad(graph1, alice, name, aliceName))); + assertTrue(aliceQuads.contains(factory.createQuad(graph1, alice, knows, bob))); + // We can't test this by Quad equality, as bnode1 might become mapped by the + // dataset + //assertTrue(aliceQuads.contains(factory.createQuad(graph1, alice, member, bnode1))); + assertTrue(aliceQuads.contains(factory.createQuad(null, alice, isPrimaryTopicOf, graph1))); + assertEquals(4, aliceQuads.size()); + + // Check the isPrimaryTopicOf statements in the default graph + int topics = 0; + for (Quad topic : dataset.iterate(null, null, isPrimaryTopicOf, null)) { + topics++; + // COMMONSRDF-55: should not be <urn:x-arq:defaultgraph> or similar + assertFalse(topic.getGraphName().isPresent()); + } + assertEquals(2, topics); } + @Test + public void streamDefaultGraphNameAlice() throws Exception { + // null below would match in ANY graph (including default graph) + Optional<? extends Quad> aliceTopic = dataset.stream(null, alice, isPrimaryTopicOf, null).findAny(); + assertTrue(aliceTopic.isPresent()); + // COMMONSRDF-55: should not be <urn:x-arq:defaultgraph> or similar + assertNull(aliceTopic.get().getGraphName().orElse(null)); + assertFalse(aliceTopic.get().getGraphName().isPresent()); + } + + + @Test + public void streamDefaultGraphNameByPattern() throws Exception { + // Explicitly select in only the default graph Optional.empty() + Optional<? extends Quad> aliceTopic = dataset.stream(Optional.empty(), null, null, null).findAny(); + assertTrue(aliceTopic.isPresent()); + // COMMONSRDF-55: should not be <urn:x-arq:defaultgraph> or similar + assertNull(aliceTopic.get().getGraphName().orElse(null)); + assertFalse(aliceTopic.get().getGraphName().isPresent()); + } + + /** * Special quad closing for RDF4J. */ http://git-wip-us.apache.org/repos/asf/commons-rdf/blob/bb264738/jena/src/main/java/org/apache/commons/rdf/jena/impl/AbstractQuadLike.java ---------------------------------------------------------------------- diff --git a/jena/src/main/java/org/apache/commons/rdf/jena/impl/AbstractQuadLike.java b/jena/src/main/java/org/apache/commons/rdf/jena/impl/AbstractQuadLike.java index 9a4c94b..3100ae6 100644 --- a/jena/src/main/java/org/apache/commons/rdf/jena/impl/AbstractQuadLike.java +++ b/jena/src/main/java/org/apache/commons/rdf/jena/impl/AbstractQuadLike.java @@ -22,12 +22,15 @@ import java.util.Objects; import java.util.Optional; import java.util.UUID; +import org.apache.commons.rdf.api.BlankNodeOrIRI; +import org.apache.commons.rdf.api.IRI; import org.apache.commons.rdf.api.QuadLike; import org.apache.commons.rdf.api.RDFTerm; import org.apache.commons.rdf.jena.JenaQuad; import org.apache.commons.rdf.jena.JenaQuadLike; import org.apache.commons.rdf.jena.JenaRDF; import org.apache.commons.rdf.jena.JenaTriple; +import org.apache.jena.graph.Factory; import org.apache.jena.graph.Triple; import org.apache.jena.sparql.core.Quad; @@ -52,6 +55,22 @@ abstract class AbstractQuadLike<S extends RDFTerm, P extends RDFTerm, O extends private static InternalJenaFactory internalJenaFactory = new InternalJenaFactory() { }; + /** + * COMMONSRDF-55 - special handling of urn:x-arq:DefaultGraph and friends + */ + private static class DefaultGraphChecker { + // Fixed UUID for comparison of defaultGraphNodeGenerated + private UUID salt = UUID.fromString("aaa6bf96-ea58-4a55-9485-3733403a1f24"); + private RDFTerm defaultGraph = internalJenaFactory.createRDFTerm(Quad.defaultGraphIRI, salt); + private RDFTerm defaultGraphNodeGenerated = internalJenaFactory.createRDFTerm(Quad.defaultGraphNodeGenerated, salt); + + public boolean isNotDefaultGraph(RDFTerm graphName) { + return !(graphName.equals(defaultGraph) || graphName.equals(defaultGraphNodeGenerated)); + } + } + + private static DefaultGraphChecker defaultGraphChecker = new DefaultGraphChecker(); + final Optional<G> graphName; final S subject; final P predicate; @@ -59,11 +78,12 @@ abstract class AbstractQuadLike<S extends RDFTerm, P extends RDFTerm, O extends org.apache.jena.sparql.core.Quad quad = null; org.apache.jena.graph.Triple triple = null; + AbstractQuadLike(final S subject, final P predicate, final O object, final Optional<G> graphName) { this.subject = Objects.requireNonNull(subject); this.predicate = Objects.requireNonNull(predicate); this.object = Objects.requireNonNull(object); - this.graphName = Objects.requireNonNull(graphName); + this.graphName = Objects.requireNonNull(graphName).filter(defaultGraphChecker::isNotDefaultGraph); } AbstractQuadLike(final S subject, final P predicate, final O object) { @@ -76,7 +96,11 @@ abstract class AbstractQuadLike<S extends RDFTerm, P extends RDFTerm, O extends this.subject = (S) internalJenaFactory.createRDFTerm(quad.getSubject(), salt); this.predicate = (P) internalJenaFactory.createRDFTerm(quad.getPredicate(), salt); this.object = (O) internalJenaFactory.createRDFTerm(quad.getObject(), salt); - this.graphName = Optional.of((G) internalJenaFactory.createRDFTerm(quad.getGraph(), salt)); + if (quad.isDefaultGraph()) { + this.graphName = Optional.empty(); + } else { + this.graphName = Optional.of((G) internalJenaFactory.createRDFTerm(quad.getGraph(), salt)); + } } @SuppressWarnings("unchecked") @@ -92,8 +116,11 @@ abstract class AbstractQuadLike<S extends RDFTerm, P extends RDFTerm, O extends public org.apache.jena.sparql.core.Quad asJenaQuad() { final JenaRDF factory = new JenaRDF(); if (quad == null) { - quad = org.apache.jena.sparql.core.Quad.create(factory.asJenaNode(graphName.orElse(null)), - factory.asJenaNode(subject), factory.asJenaNode(predicate), factory.asJenaNode(object)); + quad = org.apache.jena.sparql.core.Quad.create( + graphName.map(factory::asJenaNode).orElse(Quad.defaultGraphIRI), + factory.asJenaNode(subject), + factory.asJenaNode(predicate), + factory.asJenaNode(object)); } return quad; } @@ -102,7 +129,9 @@ abstract class AbstractQuadLike<S extends RDFTerm, P extends RDFTerm, O extends public org.apache.jena.graph.Triple asJenaTriple() { final JenaRDF factory = new JenaRDF(); if (triple == null) { - triple = org.apache.jena.graph.Triple.create(factory.asJenaNode(subject), factory.asJenaNode(predicate), + triple = org.apache.jena.graph.Triple.create( + factory.asJenaNode(subject), + factory.asJenaNode(predicate), factory.asJenaNode(object)); } return triple; http://git-wip-us.apache.org/repos/asf/commons-rdf/blob/bb264738/jena/src/main/java/org/apache/commons/rdf/jena/impl/InternalJenaFactory.java ---------------------------------------------------------------------- diff --git a/jena/src/main/java/org/apache/commons/rdf/jena/impl/InternalJenaFactory.java b/jena/src/main/java/org/apache/commons/rdf/jena/impl/InternalJenaFactory.java index 031ba7c..3e186a2 100644 --- a/jena/src/main/java/org/apache/commons/rdf/jena/impl/InternalJenaFactory.java +++ b/jena/src/main/java/org/apache/commons/rdf/jena/impl/InternalJenaFactory.java @@ -159,7 +159,7 @@ public abstract class InternalJenaFactory { } throw new ConversionException("Unrecognized node type: " + node); } - + public JenaTriple createTriple(final BlankNodeOrIRI subject, final IRI predicate, final RDFTerm object) { return new JenaTripleImpl(subject, predicate, object); } http://git-wip-us.apache.org/repos/asf/commons-rdf/blob/bb264738/jena/src/test/java/org/apache/commons/rdf/jena/DefaultGraphInQuadTest.java ---------------------------------------------------------------------- diff --git a/jena/src/test/java/org/apache/commons/rdf/jena/DefaultGraphInQuadTest.java b/jena/src/test/java/org/apache/commons/rdf/jena/DefaultGraphInQuadTest.java new file mode 100644 index 0000000..739d7a4 --- /dev/null +++ b/jena/src/test/java/org/apache/commons/rdf/jena/DefaultGraphInQuadTest.java @@ -0,0 +1,85 @@ +/** + * 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.commons.rdf.jena; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.apache.commons.rdf.api.IRI; +import org.apache.jena.graph.Node; +import org.apache.jena.graph.NodeFactory; +import org.apache.jena.sparql.core.Quad; +import org.junit.Test; + +/** + * COMMONSRDF-55: Ensure correct handling of + * Jena's default graph IRI urn:x-arq:DefaultGraph + */ +public class DefaultGraphInQuadTest { + + JenaRDF rdf = new JenaRDF(); + IRI example = rdf.createIRI("http://example.com/"); + Node exampleJena = NodeFactory.createURI("http://example.com/"); + + @Test + public void createFromNull() throws Exception { + JenaQuad q = rdf.createQuad(null, example, example, example); + assertFalse(q.getGraphName().isPresent()); + assertTrue(q.asJenaQuad().isDefaultGraph()); + assertEquals(Quad.defaultGraphIRI, q.asJenaQuad().getGraph()); + } + + @Test + public void createFromDefaultGraphIRI() throws Exception { + JenaIRI defaultGraph = (JenaIRI) rdf.asRDFTerm(Quad.defaultGraphIRI); + JenaQuad q = rdf.createQuad(defaultGraph, example, example, example); + assertTrue(q.asJenaQuad().isDefaultGraph()); + assertEquals(Quad.defaultGraphIRI, q.asJenaQuad().getGraph()); + assertFalse(q.getGraphName().isPresent()); + } + + @Test + public void defaultGraphIRI() throws Exception { + Quad jenaQuad = Quad.create(Quad.defaultGraphIRI, exampleJena, exampleJena, exampleJena); + JenaQuad q = rdf.asQuad(jenaQuad); + assertFalse(q.getGraphName().isPresent()); + assertTrue(q.asJenaQuad().isDefaultGraph()); + } + + @Test + public void defaultGraphNodeGenerated() throws Exception { + // defaultGraphNodeGenerated might appear in parser output + Quad jenaQuad = Quad.create(Quad.defaultGraphNodeGenerated, exampleJena, exampleJena, exampleJena); + JenaQuad q = rdf.asQuad(jenaQuad); + assertFalse(q.getGraphName().isPresent()); + assertTrue(q.asJenaQuad().isDefaultGraph()); + } + + @Test + public void unionGraph() throws Exception { + // unionGraph shouldn't really appear as a quad except + // in a pattern + Quad jenaQuad = Quad.create(Quad.unionGraph, exampleJena, exampleJena, exampleJena); + JenaQuad q = rdf.asQuad(jenaQuad); + // But at least we can agree it is NOT (necessarily) in the + // default graph + assertFalse(q.asJenaQuad().isDefaultGraph()); + assertTrue(q.getGraphName().isPresent()); + } +} http://git-wip-us.apache.org/repos/asf/commons-rdf/blob/bb264738/jena/src/test/java/org/apache/commons/rdf/jena/JenaRDFTest.java ---------------------------------------------------------------------- diff --git a/jena/src/test/java/org/apache/commons/rdf/jena/JenaRDFTest.java b/jena/src/test/java/org/apache/commons/rdf/jena/JenaRDFTest.java index 72986d0..fd50421 100644 --- a/jena/src/test/java/org/apache/commons/rdf/jena/JenaRDFTest.java +++ b/jena/src/test/java/org/apache/commons/rdf/jena/JenaRDFTest.java @@ -15,7 +15,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.apache.commons.rdf.jena; import org.apache.commons.rdf.api.AbstractRDFTest;
