From d3c67336316c19338b4337abb2e7aa16064d68e0 Mon Sep 17 00:00:00 2001 From: Jeen Broekstra Date: Mon, 29 Oct 2018 11:03:10 +1100 Subject: [PATCH 01/54] eclipse/rdf4j#78 fix join optimizer messing with bind/subselect combo Signed-off-by: Jeen Broekstra --- evaluation/pom.xml | 6 +++ .../evaluation/impl/QueryJoinOptimizer.java | 12 +++--- .../impl/QueryJoinOptimizerTest.java | 41 +++++++++++++++++++ 3 files changed, 53 insertions(+), 6 deletions(-) diff --git a/evaluation/pom.xml b/evaluation/pom.xml index 4fa7d5bc9..ae756843b 100644 --- a/evaluation/pom.xml +++ b/evaluation/pom.xml @@ -59,6 +59,7 @@ junit junit + test org.mapdb @@ -68,6 +69,11 @@ com.google.guava guava + + org.assertj + assertj-core + test + diff --git a/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/QueryJoinOptimizer.java b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/QueryJoinOptimizer.java index 63532ff53..66d484f80 100644 --- a/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/QueryJoinOptimizer.java +++ b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/QueryJoinOptimizer.java @@ -92,15 +92,15 @@ public void meet(Join node) { // Reorder the subselects and extensions to a more optimal sequence List priorityArgs = new ArrayList(joinArgs.size()); - // first get all subselects and order them - List orderedSubselects = reorderSubselects(getSubSelects(joinArgs)); - joinArgs.removeAll(orderedSubselects); - priorityArgs.addAll(orderedSubselects); - - // second get all extensions (BIND clause) + // get all extensions (BIND clause) List orderedExtensions = getExtensions(joinArgs); joinArgs.removeAll(orderedExtensions); priorityArgs.addAll(orderedExtensions); + + // get all subselects and order them + List orderedSubselects = reorderSubselects(getSubSelects(joinArgs)); + joinArgs.removeAll(orderedSubselects); + priorityArgs.addAll(orderedSubselects); // We order all remaining join arguments based on cardinality and // variable frequency statistics diff --git a/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/QueryJoinOptimizerTest.java b/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/QueryJoinOptimizerTest.java index fce9a4529..83d735c1f 100644 --- a/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/QueryJoinOptimizerTest.java +++ b/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/QueryJoinOptimizerTest.java @@ -9,6 +9,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; +import static org.assertj.core.api.Assertions.assertThat; import org.eclipse.rdf4j.RDF4JException; import org.eclipse.rdf4j.query.MalformedQueryException; @@ -16,6 +17,7 @@ import org.eclipse.rdf4j.query.UnsupportedQueryLanguageException; import org.eclipse.rdf4j.query.algebra.BinaryTupleOperator; import org.eclipse.rdf4j.query.algebra.Extension; +import org.eclipse.rdf4j.query.algebra.Join; import org.eclipse.rdf4j.query.algebra.QueryModelNode; import org.eclipse.rdf4j.query.algebra.QueryRoot; import org.eclipse.rdf4j.query.algebra.TupleExpr; @@ -109,6 +111,32 @@ public void testSES2116JoinBind() Assert.assertTrue("Extension must be evaluated before StatementPattern", leaf.getParentNode() instanceof Extension); } + @Test + public void bindSubselectJoinOrder() throws Exception + { + String query = "SELECT * WHERE {\n" + + " BIND (bnode() as ?ct01) \n" + + " { SELECT ?s WHERE {\n" + + " ?s ?p ?o .\n" + + " }\n" + + " LIMIT 10\n" + + " }\n" + + "}"; + + SPARQLParser parser = new SPARQLParser(); + ParsedQuery q = parser.parseQuery(query, null); + QueryJoinOptimizer opt = new QueryJoinOptimizer(); + QueryRoot optRoot = new QueryRoot(q.getTupleExpr()); + opt.optimize(optRoot, null, null); + + JoinFinder joinFinder = new JoinFinder(); + optRoot.visit(joinFinder); + Join join = joinFinder.getJoin(); + + assertThat(join.getLeftArg()).as("BIND clause should be left-most argument of join").isInstanceOf(Extension.class); + } + + private TupleExpr findLeaf(TupleExpr expr) { if (expr instanceof UnaryTupleOperator) { return findLeaf(((UnaryTupleOperator)expr).getArg()); @@ -136,4 +164,17 @@ private void testOptimizer(String expectedQuery, String actualQuery) private void assertQueryModelTrees(QueryModelNode expected, QueryModelNode actual) { assertEquals(expected, actual); } + + class JoinFinder extends AbstractQueryModelVisitor { + + private Join join; + + public void meet(Join join) { + this.join = join; + } + + public Join getJoin() { + return join; + } + } } From 89107e1300d385276b1f0c5c16dc56e4fcaef58a Mon Sep 17 00:00:00 2001 From: Jeen Broekstra Date: Sat, 17 Nov 2018 11:06:28 +1100 Subject: [PATCH 02/54] eclipse/rdf4j#1168 fix handling of language tags in concat function Signed-off-by: Jeen Broekstra --- evaluation/pom.xml | 28 +++-- .../evaluation/function/string/Concat.java | 37 +++--- .../function/string/ConcatTest.java | 105 ++++++++++++++++++ 3 files changed, 137 insertions(+), 33 deletions(-) create mode 100644 evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/ConcatTest.java diff --git a/evaluation/pom.xml b/evaluation/pom.xml index 4fa7d5bc9..a581bbdf0 100644 --- a/evaluation/pom.xml +++ b/evaluation/pom.xml @@ -1,4 +1,6 @@ - + 4.0.0 @@ -29,7 +31,8 @@ rdf4j-query ${project.version} - + ${project.groupId} rdf4j-repository-sparql @@ -45,7 +48,7 @@ rdf4j-util ${project.version} - + org.slf4j slf4j-api @@ -59,7 +62,14 @@ junit junit + test + + + org.assertj + assertj-core + test + org.mapdb mapdb @@ -69,12 +79,12 @@ guava - - - - com.github.siom79.japicmp - japicmp-maven-plugin - + + + + com.github.siom79.japicmp + japicmp-maven-plugin + diff --git a/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/Concat.java b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/Concat.java index 0ffddac65..4a28d2c20 100644 --- a/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/Concat.java +++ b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/Concat.java @@ -15,6 +15,7 @@ import org.eclipse.rdf4j.model.vocabulary.XMLSchema; import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; import org.eclipse.rdf4j.query.algebra.evaluation.function.Function; +import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil; /** * The SPARQL built-in {@link Function} CONCAT, as defined in @@ -36,23 +37,25 @@ public Literal evaluate(ValueFactory valueFactory, Value... args) } StringBuilder concatBuilder = new StringBuilder(); - String languageTag = null; - + String commonLanguageTag = null; boolean useLanguageTag = true; - boolean useDatatype = true; for (Value arg : args) { if (arg instanceof Literal) { Literal lit = (Literal)arg; + if (!QueryEvaluationUtil.isStringLiteral(lit)) { + throw new ValueExprEvaluationException("unexpected datatype for CONCAT operand: " + lit); + } + // verify that every literal argument has the same language tag. If // not, the operator result should not use a language tag. if (useLanguageTag && Literals.isLanguageLiteral(lit)) { - if (languageTag == null) { - languageTag = lit.getLanguage().get(); + if (commonLanguageTag == null) { + commonLanguageTag = lit.getLanguage().get(); } - else if (!languageTag.equals(lit.getLanguage())) { - languageTag = null; + else if (!commonLanguageTag.equals(lit.getLanguage().orElse(null))) { + commonLanguageTag = null; useLanguageTag = false; } } @@ -60,32 +63,18 @@ else if (!languageTag.equals(lit.getLanguage())) { useLanguageTag = false; } - // check datatype: concat only expects plain, language-tagged or - // string-typed literals. If all arguments are of type xsd:string, - // the result also should be, - // otherwise the result will not have a datatype. - if (lit.getDatatype() == null) { - useDatatype = false; - } - else if (!lit.getDatatype().equals(XMLSchema.STRING)) { - throw new ValueExprEvaluationException("unexpected data type for concat operand: " + arg); - } - concatBuilder.append(lit.getLabel()); } else { throw new ValueExprEvaluationException( - "unexpected argument type for concat operator: " + arg); + "unexpected argument type for CONCAT operator: " + arg); } } Literal result = null; - if (useDatatype) { - result = valueFactory.createLiteral(concatBuilder.toString(), XMLSchema.STRING); - } - else if (useLanguageTag) { - result = valueFactory.createLiteral(concatBuilder.toString(), languageTag); + if (useLanguageTag) { + result = valueFactory.createLiteral(concatBuilder.toString(), commonLanguageTag); } else { result = valueFactory.createLiteral(concatBuilder.toString()); diff --git a/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/ConcatTest.java b/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/ConcatTest.java new file mode 100644 index 000000000..447be91b0 --- /dev/null +++ b/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/ConcatTest.java @@ -0,0 +1,105 @@ +/******************************************************************************* + * Copyright (c) 2018 Eclipse RDF4J contributors. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.function.string; + +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.BooleanLiteral; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; +import org.junit.Before; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.fail; + +public class ConcatTest { + + private Concat concatFunc; + + private static final ValueFactory vf = SimpleValueFactory.getInstance(); + + private static final Literal foo = vf.createLiteral("foo"); + + private static final Literal bar = vf.createLiteral("bar"); + + private static final Literal foo_en = vf.createLiteral("foo", "en"); + + private static final Literal bar_en = vf.createLiteral("bar", "en"); + + private static final Literal foo_nl = vf.createLiteral("foo", "nl"); + + @Before + public void setUp() + throws Exception + { + concatFunc = new Concat(); + } + + @Test + public void stringLiteralHandling() { + Literal result = concatFunc.evaluate(vf, foo, bar); + + assertThat(result.stringValue()).isEqualTo("foobar"); + assertThat(result.getDatatype()).isEqualTo(XMLSchema.STRING); + assertThat(result.getLanguage().isPresent()).isFalse(); + } + + @Test + public void commonLanguageLiteralHandling() { + Literal result = concatFunc.evaluate(vf, foo_en, bar_en); + + assertThat(result.stringValue()).isEqualTo("foobar"); + assertThat(result.getDatatype()).isEqualTo(RDF.LANGSTRING); + assertThat(result.getLanguage().get()).isEqualTo("en"); + + } + + @Test + public void mixedLanguageLiteralHandling() { + Literal result = concatFunc.evaluate(vf, foo_nl, bar_en); + + assertThat(result.stringValue()).isEqualTo("foobar"); + assertThat(result.getDatatype()).isEqualTo(XMLSchema.STRING); + assertThat(result.getLanguage().isPresent()).isFalse(); + } + + @Test + public void mixedLiteralHandling() { + Literal result = concatFunc.evaluate(vf, foo, bar_en); + + assertThat(result.stringValue()).isEqualTo("foobar"); + assertThat(result.getDatatype()).isEqualTo(XMLSchema.STRING); + assertThat(result.getLanguage().isPresent()).isFalse(); + } + + @Test + public void nonStringLiteralHandling() { + try { + concatFunc.evaluate(vf, RDF.TYPE, BooleanLiteral.TRUE); + fail("CONCAT expected to fail on non-stringliteral argument"); + } + catch (ValueExprEvaluationException e) { + // ignore, expected + } + } + + @Test + public void nonLiteralHandling() { + try { + concatFunc.evaluate(vf, RDF.TYPE, bar_en); + fail("CONCAT expected to fail on non-literal argument"); + } + catch (ValueExprEvaluationException e) { + // ignore, expected + } + } + +} From 0803e012c114fc83368c151f9e82f8ad64724e4e Mon Sep 17 00:00:00 2001 From: Jeen Broekstra Date: Tue, 11 Dec 2018 20:14:02 +1100 Subject: [PATCH 03/54] eclipse/rdf4j#1196 temporarily disable tests involving ESIntegTestCase Signed-off-by: Jeen Broekstra --- .../rdf4j/sail/elasticsearch/ElasticsearchIndexTest.java | 2 ++ .../sail/elasticsearch/ElasticsearchSailGeoSPARQLTest.java | 1 + .../elasticsearch/ElasticsearchSailIndexedPropertiesTest.java | 2 ++ .../eclipse/rdf4j/sail/elasticsearch/ElasticsearchSailTest.java | 2 ++ 4 files changed, 7 insertions(+) diff --git a/compliance/elasticsearch/src/test/java/org/eclipse/rdf4j/sail/elasticsearch/ElasticsearchIndexTest.java b/compliance/elasticsearch/src/test/java/org/eclipse/rdf4j/sail/elasticsearch/ElasticsearchIndexTest.java index 5d91f8aee..7fd2cefaa 100644 --- a/compliance/elasticsearch/src/test/java/org/eclipse/rdf4j/sail/elasticsearch/ElasticsearchIndexTest.java +++ b/compliance/elasticsearch/src/test/java/org/eclipse/rdf4j/sail/elasticsearch/ElasticsearchIndexTest.java @@ -41,10 +41,12 @@ import org.elasticsearch.test.ESIntegTestCase.SuppressLocalMode; import org.junit.After; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; @ClusterScope(numDataNodes = 1) @SuppressLocalMode +@Ignore("timeouts on JIPP due to ES cluster being spun up - see https://github.com/eclipse/rdf4j/issues/1196") public class ElasticsearchIndexTest extends ESIntegTestCase { private static final ValueFactory vf = SimpleValueFactory.getInstance(); diff --git a/compliance/elasticsearch/src/test/java/org/eclipse/rdf4j/sail/elasticsearch/ElasticsearchSailGeoSPARQLTest.java b/compliance/elasticsearch/src/test/java/org/eclipse/rdf4j/sail/elasticsearch/ElasticsearchSailGeoSPARQLTest.java index 23387680f..9fd040233 100644 --- a/compliance/elasticsearch/src/test/java/org/eclipse/rdf4j/sail/elasticsearch/ElasticsearchSailGeoSPARQLTest.java +++ b/compliance/elasticsearch/src/test/java/org/eclipse/rdf4j/sail/elasticsearch/ElasticsearchSailGeoSPARQLTest.java @@ -28,6 +28,7 @@ @ClusterScope(numDataNodes = 1) @SuppressLocalMode +@Ignore("timeouts on JIPP due to ES cluster being spun up - see https://github.com/eclipse/rdf4j/issues/1196") public class ElasticsearchSailGeoSPARQLTest extends ESIntegTestCase { AbstractLuceneSailGeoSPARQLTest delegateTest; diff --git a/compliance/elasticsearch/src/test/java/org/eclipse/rdf4j/sail/elasticsearch/ElasticsearchSailIndexedPropertiesTest.java b/compliance/elasticsearch/src/test/java/org/eclipse/rdf4j/sail/elasticsearch/ElasticsearchSailIndexedPropertiesTest.java index 87f69b66d..fc62a637b 100644 --- a/compliance/elasticsearch/src/test/java/org/eclipse/rdf4j/sail/elasticsearch/ElasticsearchSailIndexedPropertiesTest.java +++ b/compliance/elasticsearch/src/test/java/org/eclipse/rdf4j/sail/elasticsearch/ElasticsearchSailIndexedPropertiesTest.java @@ -23,10 +23,12 @@ import org.elasticsearch.test.ESIntegTestCase.SuppressLocalMode; import org.junit.After; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; @ClusterScope(numDataNodes = 1) @SuppressLocalMode +@Ignore("timeouts on JIPP due to ES cluster being spun up - see https://github.com/eclipse/rdf4j/issues/1196") public class ElasticsearchSailIndexedPropertiesTest extends ESIntegTestCase { AbstractLuceneSailIndexedPropertiesTest delegateTest; diff --git a/compliance/elasticsearch/src/test/java/org/eclipse/rdf4j/sail/elasticsearch/ElasticsearchSailTest.java b/compliance/elasticsearch/src/test/java/org/eclipse/rdf4j/sail/elasticsearch/ElasticsearchSailTest.java index ee4e37645..a48724d38 100644 --- a/compliance/elasticsearch/src/test/java/org/eclipse/rdf4j/sail/elasticsearch/ElasticsearchSailTest.java +++ b/compliance/elasticsearch/src/test/java/org/eclipse/rdf4j/sail/elasticsearch/ElasticsearchSailTest.java @@ -23,10 +23,12 @@ import org.elasticsearch.test.ESIntegTestCase.SuppressLocalMode; import org.junit.After; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; @ClusterScope(numDataNodes = 1) @SuppressLocalMode +@Ignore("timeouts on JIPP due to ES cluster being spun up - see https://github.com/eclipse/rdf4j/issues/1196") public class ElasticsearchSailTest extends ESIntegTestCase { AbstractLuceneSailTest delegateTest; From c2622e1e2821d52e868229341d20b29fdc63f39c Mon Sep 17 00:00:00 2001 From: Jeen Broekstra Date: Wed, 12 Dec 2018 09:54:32 +1100 Subject: [PATCH 04/54] eclipse/rdf4j#1195 bump maven shade plugin version Signed-off-by: Jeen Broekstra --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1a0a13970..93665f3fb 100644 --- a/pom.xml +++ b/pom.xml @@ -753,7 +753,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.0.0 + 3.2.1 From 0c158671a8064c0477ea278176869fdc4be30ea6 Mon Sep 17 00:00:00 2001 From: Bart Hanssens Date: Wed, 19 Dec 2018 18:37:42 +0100 Subject: [PATCH 05/54] Upgrade to latest Mockito 2 Signed-off-by: Bart Hanssens --- .../function/geosparql/GeometricBinaryFunctionTest.java | 2 +- .../geosparql/GeometricRelationFunctionTest.java | 2 +- .../function/geosparql/GeometricUnaryFunctionTest.java | 2 +- pom.xml | 9 +++++---- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/geosparql/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/GeometricBinaryFunctionTest.java b/geosparql/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/GeometricBinaryFunctionTest.java index 7f1943688..08c11880d 100644 --- a/geosparql/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/GeometricBinaryFunctionTest.java +++ b/geosparql/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/GeometricBinaryFunctionTest.java @@ -14,7 +14,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; -import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.junit.MockitoJUnitRunner; @RunWith(MockitoJUnitRunner.class) public abstract class GeometricBinaryFunctionTest { diff --git a/geosparql/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/GeometricRelationFunctionTest.java b/geosparql/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/GeometricRelationFunctionTest.java index 8f11201e7..2cf7616e0 100644 --- a/geosparql/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/GeometricRelationFunctionTest.java +++ b/geosparql/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/GeometricRelationFunctionTest.java @@ -14,7 +14,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; -import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.junit.MockitoJUnitRunner; @RunWith(MockitoJUnitRunner.class) public abstract class GeometricRelationFunctionTest { diff --git a/geosparql/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/GeometricUnaryFunctionTest.java b/geosparql/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/GeometricUnaryFunctionTest.java index fe32be311..32c0c2ff4 100644 --- a/geosparql/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/GeometricUnaryFunctionTest.java +++ b/geosparql/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/GeometricUnaryFunctionTest.java @@ -14,7 +14,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; -import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.junit.MockitoJUnitRunner; @RunWith(MockitoJUnitRunner.class) public abstract class GeometricUnaryFunctionTest { diff --git a/pom.xml b/pom.xml index 3e4860b0b..9091d1b94 100644 --- a/pom.xml +++ b/pom.xml @@ -484,10 +484,9 @@ test - org.mockito mockito-core - 1.10.19 + 2.23.4 test @@ -496,7 +495,6 @@ 3.9.1 test - com.github.jsonld-java jsonld-java @@ -799,6 +797,9 @@ 1.8 + + META-INF/**/module-info + org.apache.logging.log4j:log4j-api org.elasticsearch:elasticsearch @@ -813,7 +814,7 @@ org.codehaus.mojo extra-enforcer-rules - 1.0-beta-6 + 1.0 From e6f3c12b67058cd9a907def76a4ebc00c4527f90 Mon Sep 17 00:00:00 2001 From: Bart Hanssens Date: Thu, 20 Dec 2018 13:22:31 +0100 Subject: [PATCH 06/54] Remove unused cglib Signed-off-by: Bart Hanssens --- pom.xml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/pom.xml b/pom.xml index 9091d1b94..e291e9e57 100644 --- a/pom.xml +++ b/pom.xml @@ -424,12 +424,6 @@ - - - cglib - cglib - 3.1 - com.google.guava guava From b8b438ed071f1d9ee11751d443764feb906fe323 Mon Sep 17 00:00:00 2001 From: Bart Hanssens Date: Thu, 20 Dec 2018 20:04:49 +0100 Subject: [PATCH 07/54] Updated lucene version in config Signed-off-by: Bart Hanssens --- compliance/solr/solr/cores/embedded/conf/solrconfig.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compliance/solr/solr/cores/embedded/conf/solrconfig.xml b/compliance/solr/solr/cores/embedded/conf/solrconfig.xml index fe32b1f0b..f16445486 100644 --- a/compliance/solr/solr/cores/embedded/conf/solrconfig.xml +++ b/compliance/solr/solr/cores/embedded/conf/solrconfig.xml @@ -1,6 +1,6 @@ - 5.0.0 + 6.0.0 target/test-data From be80565e7d09a49f6d56ca505ce925b658a5d66f Mon Sep 17 00:00:00 2001 From: Jeen Broekstra Date: Mon, 24 Dec 2018 11:23:20 +1100 Subject: [PATCH 08/54] fix reactor order and include shacl in shaded jar Signed-off-by: Jeen Broekstra --- pom.xml | 2 +- storage/pom.xml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 93665f3fb..a88b2cf5b 100644 --- a/pom.xml +++ b/pom.xml @@ -68,8 +68,8 @@ sail-spin solr spin - storage shacl + storage diff --git a/storage/pom.xml b/storage/pom.xml index 8e2473777..d6acfa979 100644 --- a/storage/pom.xml +++ b/storage/pom.xml @@ -430,6 +430,7 @@ org.eclipse.rdf4j:rdf4j-sail-* org.eclipse.rdf4j:rdf4j-lucene-spin org.eclipse.rdf4j:rdf4j-spin + org.eclipse.rdf4j:rdf4j-shacl From 44994ef2365c52bf5ec691cc5923bb4f8299e2c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Avard=20Ottestad?= Date: Sun, 9 Dec 2018 18:38:16 +0100 Subject: [PATCH 09/54] eclipse/rdf4j#1197 add statements with correct graph MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håvard Ottestad --- ...SchemaCachingRDFSInferencerConnection.java | 62 ++++++++++--------- 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/SchemaCachingRDFSInferencerConnection.java b/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/SchemaCachingRDFSInferencerConnection.java index c2ff00234..52b8a51a1 100644 --- a/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/SchemaCachingRDFSInferencerConnection.java +++ b/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/SchemaCachingRDFSInferencerConnection.java @@ -196,10 +196,10 @@ private void addStatement(boolean actuallyAdd, Resource subject, IRI predicate, } if (sail.useAllRdfsRules) { - addInferredStatement(subject, RDF.TYPE, RDFS.RESOURCE); + addInferredStatement(subject, RDF.TYPE, RDFS.RESOURCE, resources); if (object instanceof Resource) { - addInferredStatement((Resource)object, RDF.TYPE, RDFS.RESOURCE); + addInferredStatement((Resource)object, RDF.TYPE, RDFS.RESOURCE, resources); } } @@ -208,13 +208,13 @@ private void addStatement(boolean actuallyAdd, Resource subject, IRI predicate, try { int i = Integer.parseInt(predicate.getLocalName().substring(1)); if (i >= 1) { - addInferredStatement(subject, RDFS.MEMBER, object); + addInferredStatement(subject, RDFS.MEMBER, object, resources); - addInferredStatement(predicate, RDF.TYPE, RDFS.RESOURCE); - addInferredStatement(predicate, RDF.TYPE, RDFS.CONTAINERMEMBERSHIPPROPERTY); - addInferredStatement(predicate, RDF.TYPE, RDF.PROPERTY); - addInferredStatement(predicate, RDFS.SUBPROPERTYOF, predicate); - addInferredStatement(predicate, RDFS.SUBPROPERTYOF, RDFS.MEMBER); + addInferredStatement(predicate, RDF.TYPE, RDFS.RESOURCE, resources); + addInferredStatement(predicate, RDF.TYPE, RDFS.CONTAINERMEMBERSHIPPROPERTY, resources); + addInferredStatement(predicate, RDF.TYPE, RDF.PROPERTY, resources); + addInferredStatement(predicate, RDFS.SUBPROPERTYOF, predicate, resources); + addInferredStatement(predicate, RDFS.SUBPROPERTYOF, RDFS.MEMBER, resources); } } @@ -241,32 +241,38 @@ private void addStatement(boolean actuallyAdd, Resource subject, IRI predicate, sail.resolveTypes((Resource)object).stream().peek(inferredType -> { if (sail.useAllRdfsRules && inferredType.equals(RDFS.CLASS)) { - addInferredStatement(subject, RDFS.SUBCLASSOF, RDFS.RESOURCE); + addInferredStatement(subject, RDFS.SUBCLASSOF, RDFS.RESOURCE, resources); } }).filter(inferredType -> !inferredType.equals(object)).forEach( - inferredType -> addInferredStatement(subject, RDF.TYPE, inferredType)); + inferredType -> addInferredStatement(subject, RDF.TYPE, inferredType, resources)); } - sail.resolveProperties(predicate).stream().filter( - inferredProperty -> !inferredProperty.equals(predicate)).filter( - inferredPropery -> inferredPropery instanceof IRI).map( - inferredPropery -> ((IRI)inferredPropery)).forEach( - inferredProperty -> addInferredStatement(subject, inferredProperty, - object)); + sail.resolveProperties(predicate) + .stream() + .filter(inferredProperty -> !inferredProperty.equals(predicate)) + .filter(inferredPropery -> inferredPropery instanceof IRI) + .map(inferredPropery -> ((IRI) inferredPropery)) + .forEach(inferredProperty -> addInferredStatement(subject, inferredProperty, object, resources)); if (object instanceof Resource) { - sail.resolveRangeTypes(predicate).stream().peek(inferredType -> { - if (sail.useAllRdfsRules && inferredType.equals(RDFS.CLASS)) { - addInferredStatement(((Resource)object), RDFS.SUBCLASSOF, RDFS.RESOURCE); - } - }).forEach(inferredType -> addInferredStatement(((Resource)object), RDF.TYPE, inferredType)); + sail.resolveRangeTypes(predicate) + .stream() + .peek(inferredType -> { + if (sail.useAllRdfsRules && inferredType.equals(RDFS.CLASS)) { + addInferredStatement(((Resource) object), RDFS.SUBCLASSOF, RDFS.RESOURCE, resources); + } + }) + .forEach(inferredType -> addInferredStatement(((Resource) object), RDF.TYPE, inferredType, resources)); } - sail.resolveDomainTypes(predicate).stream().peek(inferredType -> { - if (sail.useAllRdfsRules && inferredType.equals(RDFS.CLASS)) { - addInferredStatement(subject, RDFS.SUBCLASSOF, RDFS.RESOURCE); - } - }).forEach(inferredType -> addInferredStatement((subject), RDF.TYPE, inferredType)); + sail.resolveDomainTypes(predicate) + .stream() + .peek(inferredType -> { + if (sail.useAllRdfsRules && inferredType.equals(RDFS.CLASS)) { + addInferredStatement(subject, RDFS.SUBCLASSOF, RDFS.RESOURCE, resources); + } + }) + .forEach(inferredType -> addInferredStatement((subject), RDF.TYPE, inferredType, resources)); } @@ -522,8 +528,7 @@ void addAxiomStatements() { statement = vf.createStatement(RDFS.CONTAINERMEMBERSHIPPROPERTY, RDFS.SUBCLASSOF, RDFS.RESOURCE); processForSchemaCache(statement); addInferredStatement(statement.getSubject(), statement.getPredicate(), statement.getObject()); - statement = vf.createStatement(RDFS.CONTAINERMEMBERSHIPPROPERTY, RDFS.SUBCLASSOF, - RDFS.CONTAINERMEMBERSHIPPROPERTY); + statement = vf.createStatement(RDFS.CONTAINERMEMBERSHIPPROPERTY, RDFS.SUBCLASSOF, RDFS.CONTAINERMEMBERSHIPPROPERTY); processForSchemaCache(statement); addInferredStatement(statement.getSubject(), statement.getPredicate(), statement.getObject()); statement = vf.createStatement(RDFS.CONTAINERMEMBERSHIPPROPERTY, RDFS.SUBCLASSOF, RDF.PROPERTY); @@ -718,7 +723,6 @@ public void rollback() sail.rolledBackAfterModifyingSchemaCache = true; } - statementsRemoved = false; statementsRemoved = false; sail.releaseExclusiveWriteLock(); From 57f512c8de6ba205177cb9690333f2821a43b322 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Avard=20Ottestad?= Date: Tue, 11 Dec 2018 22:08:08 +0100 Subject: [PATCH 10/54] fixed tests locally instead of in the test suite and also added a new test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håvard Ottestad --- ...FSchemaMemoryRepositoryConnectionTest.java | 124 +++++++++++++++++ ...erencerNativeRepositoryConnectionTest.java | 129 ++++++++++++++++++ 2 files changed, 253 insertions(+) diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/SchemaCachingRDFSInferencerRDFSchemaMemoryRepositoryConnectionTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/SchemaCachingRDFSInferencerRDFSchemaMemoryRepositoryConnectionTest.java index 1f11d7c04..947ca4619 100644 --- a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/SchemaCachingRDFSInferencerRDFSchemaMemoryRepositoryConnectionTest.java +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/SchemaCachingRDFSInferencerRDFSchemaMemoryRepositoryConnectionTest.java @@ -8,11 +8,22 @@ package org.eclipse.rdf4j.repository.sail.memory; import org.eclipse.rdf4j.IsolationLevel; +import org.eclipse.rdf4j.common.iteration.Iterations; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.model.vocabulary.RDFS; import org.eclipse.rdf4j.repository.RDFSchemaRepositoryConnectionTest; import org.eclipse.rdf4j.repository.Repository; import org.eclipse.rdf4j.repository.sail.SailRepository; import org.eclipse.rdf4j.sail.inferencer.fc.SchemaCachingRDFSInferencer; import org.eclipse.rdf4j.sail.memory.MemoryStore; +import org.junit.Ignore; +import org.junit.Test; + +import java.util.stream.Stream; + +import static org.junit.Assert.assertEquals; public class SchemaCachingRDFSInferencerRDFSchemaMemoryRepositoryConnectionTest extends RDFSchemaRepositoryConnectionTest @@ -29,4 +40,117 @@ protected Repository createRepository() { return new SailRepository(new SchemaCachingRDFSInferencer(new MemoryStore(), true)); } + + @Ignore + @Test + @Override + public void testDefaultContext() + throws Exception + { + // ignore + } + + @Ignore + @Test + @Override + public void testDefaultInsertContext() + throws Exception + { + // ignore + } + + @Ignore + @Test + @Override + public void testExclusiveNullContext() + throws Exception + { + // ignore + } + + + @Override + @Test + @Ignore + public void testQueryDefaultGraph() + throws Exception + { + // ignore + } + + + @Override + @Test + @Ignore + public void testDeleteDefaultGraph() + throws Exception + { + // ignore + } + + @Override + @Test + @Ignore + public void testContextStatementsNotDuplicated() + throws Exception + { + // ignore + } + + @Override + @Test + @Ignore + public void testContextStatementsNotDuplicated2() + throws Exception + { + // ignore + } + + + @Test + public void testContextTbox() + { + +// Man subClassOf Human g1 +// Human subClassOf Animal g2 +// -> Man subClassOf Animal ?? + + IRI man = vf.createIRI("http://example.org/Man"); + IRI human = vf.createIRI("http://example.org/Human"); + IRI animal = vf.createIRI("http://example.org/Animal"); + IRI bob = vf.createIRI("http://example.org/bob"); + + IRI graph1 = vf.createIRI("http://example.org/graph1"); + IRI graph2 = vf.createIRI("http://example.org/graph2"); + IRI graph3 = vf.createIRI("http://example.org/graph3"); + + + testCon.add(man, RDFS.SUBCLASSOF, human, graph1); + testCon.add(human, RDFS.SUBCLASSOF, animal, graph2); + testCon.add(bob, RDF.TYPE, man, graph3); + + + /* + The SchemaCachingRDFSInferencer correctly adds inferred A-box statements to the correct graph, + but does not add inferred T-box statements to the correct graph. + */ + + + System.out.println("-----------"); + try (Stream stream = Iterations.stream(testCon.getStatements(man, RDFS.SUBCLASSOF, null,true))) { + stream.forEach(System.out::println); + } + System.out.println("-----------"); + try (Stream stream = Iterations.stream(testCon.getStatements(bob, RDF.TYPE, null,true))) { + stream + .peek(statement -> assertEquals(statement.getContext(), graph3)) + .forEach(System.out::println); + } + + System.out.println("-----------"); + + + } + + } diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/SchemaCachingRDFSInferencerNativeRepositoryConnectionTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/SchemaCachingRDFSInferencerNativeRepositoryConnectionTest.java index 6332cb060..ed3ed0f19 100644 --- a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/SchemaCachingRDFSInferencerNativeRepositoryConnectionTest.java +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/SchemaCachingRDFSInferencerNativeRepositoryConnectionTest.java @@ -9,14 +9,29 @@ import java.io.File; import java.io.IOException; +import java.util.stream.Stream; import org.eclipse.rdf4j.IsolationLevel; import org.eclipse.rdf4j.common.io.FileUtil; +import org.eclipse.rdf4j.common.iteration.Iterations; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.vocabulary.FOAF; +import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.model.vocabulary.RDFS; import org.eclipse.rdf4j.repository.RDFSchemaRepositoryConnectionTest; import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryResult; import org.eclipse.rdf4j.repository.sail.SailRepository; import org.eclipse.rdf4j.sail.inferencer.fc.SchemaCachingRDFSInferencer; import org.eclipse.rdf4j.sail.nativerdf.NativeStore; +import org.junit.Ignore; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; public class SchemaCachingRDFSInferencerNativeRepositoryConnectionTest extends RDFSchemaRepositoryConnectionTest @@ -48,4 +63,118 @@ public void tearDown() FileUtil.deleteDir(dataDir); } } + + + + @Ignore + @Test + @Override + public void testDefaultContext() + throws Exception + { + // ignore + } + + @Ignore + @Test + @Override + public void testDefaultInsertContext() + throws Exception + { + // ignore + } + + @Ignore + @Test + @Override + public void testExclusiveNullContext() + throws Exception + { + // ignore + } + + + @Override + @Test + @Ignore + public void testQueryDefaultGraph() + throws Exception + { + // ignore + } + + + @Override + @Test + @Ignore + public void testDeleteDefaultGraph() + throws Exception + { + // ignore + } + + @Override + @Test + @Ignore + public void testContextStatementsNotDuplicated() + throws Exception + { + // ignore + } + + @Override + @Test + @Ignore + public void testContextStatementsNotDuplicated2() + throws Exception + { + // ignore + } + + + @Test + public void testContextTbox() + { + +// Man subClassOf Human g1 +// Human subClassOf Animal g2 +// -> Man subClassOf Animal ?? + + IRI man = vf.createIRI("http://example.org/Man"); + IRI human = vf.createIRI("http://example.org/Human"); + IRI animal = vf.createIRI("http://example.org/Animal"); + IRI bob = vf.createIRI("http://example.org/bob"); + + IRI graph1 = vf.createIRI("http://example.org/graph1"); + IRI graph2 = vf.createIRI("http://example.org/graph2"); + IRI graph3 = vf.createIRI("http://example.org/graph3"); + + + testCon.add(man, RDFS.SUBCLASSOF, human, graph1); + testCon.add(human, RDFS.SUBCLASSOF, animal, graph2); + testCon.add(bob, RDF.TYPE, man, graph3); + + + /* + The SchemaCachingRDFSInferencer correctly adds inferred A-box statements to the correct graph, + but does not add inferred T-box statements to the correct graph. + */ + + + System.out.println("-----------"); + try (Stream stream = Iterations.stream(testCon.getStatements(man, RDFS.SUBCLASSOF, null,true))) { + stream.forEach(System.out::println); + } + System.out.println("-----------"); + try (Stream stream = Iterations.stream(testCon.getStatements(bob, RDF.TYPE, null,true))) { + stream + .peek(statement -> assertEquals(statement.getContext(), graph3)) + .forEach(System.out::println); + } + + System.out.println("-----------"); + + + } + } From 06a0721bd87a20b593f832af0baafcf94fff5261 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Avard=20Ottestad?= Date: Sun, 16 Dec 2018 13:00:48 +0100 Subject: [PATCH 11/54] eclipse/rdf4j#1197 make inferred context behaviour configurable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håvard Ottestad --- ...FSchemaMemoryRepositoryConnectionTest.java | 4 +- ...erencerNativeRepositoryConnectionTest.java | 5 +- .../rdf4j/sail/fc/InferredContextTest.java | 83 +++++++++++++++++++ ...chingRDFSInferencerMemInferencingTest.java | 3 +- .../fc/SchemaCachingRDFSInferencer.java | 14 ++++ ...SchemaCachingRDFSInferencerConnection.java | 43 ++++++---- 6 files changed, 131 insertions(+), 21 deletions(-) create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/sail/fc/InferredContextTest.java diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/SchemaCachingRDFSInferencerRDFSchemaMemoryRepositoryConnectionTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/SchemaCachingRDFSInferencerRDFSchemaMemoryRepositoryConnectionTest.java index 947ca4619..89eb71df5 100644 --- a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/SchemaCachingRDFSInferencerRDFSchemaMemoryRepositoryConnectionTest.java +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/SchemaCachingRDFSInferencerRDFSchemaMemoryRepositoryConnectionTest.java @@ -37,7 +37,9 @@ public SchemaCachingRDFSInferencerRDFSchemaMemoryRepositoryConnectionTest( @Override protected Repository createRepository() { - return new SailRepository(new SchemaCachingRDFSInferencer(new MemoryStore(), true)); + SchemaCachingRDFSInferencer sail = new SchemaCachingRDFSInferencer(new MemoryStore(), true); + sail.setAddInferredStatementsToDefaultContext(false); + return new SailRepository(sail); } diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/SchemaCachingRDFSInferencerNativeRepositoryConnectionTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/SchemaCachingRDFSInferencerNativeRepositoryConnectionTest.java index ed3ed0f19..4077750b4 100644 --- a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/SchemaCachingRDFSInferencerNativeRepositoryConnectionTest.java +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/SchemaCachingRDFSInferencerNativeRepositoryConnectionTest.java @@ -48,8 +48,9 @@ protected Repository createRepository() throws IOException { dataDir = FileUtil.createTempDir("nativestore"); - return new SailRepository( - new SchemaCachingRDFSInferencer(new NativeStore(dataDir, "spoc"), true)); + SchemaCachingRDFSInferencer sail = new SchemaCachingRDFSInferencer(new NativeStore(dataDir, "spoc"), true); + sail.setAddInferredStatementsToDefaultContext(false); + return new SailRepository(sail); } @Override diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/fc/InferredContextTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/fc/InferredContextTest.java new file mode 100644 index 000000000..2c0ca5fc0 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/fc/InferredContextTest.java @@ -0,0 +1,83 @@ +package org.eclipse.rdf4j.sail.fc; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.model.BNode; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.model.vocabulary.RDFS; +import org.eclipse.rdf4j.sail.SailException; +import org.eclipse.rdf4j.sail.inferencer.fc.SchemaCachingRDFSInferencer; +import org.eclipse.rdf4j.sail.inferencer.fc.SchemaCachingRDFSInferencerConnection; +import org.eclipse.rdf4j.sail.memory.MemoryStore; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class InferredContextTest { + + SimpleValueFactory vf = SimpleValueFactory.getInstance(); + + BNode bNode = vf.createBNode(); + BNode type = vf.createBNode(); + BNode context = vf.createBNode(); + + + @Test + public void testInferrecContextNull() { + SchemaCachingRDFSInferencer sail = new SchemaCachingRDFSInferencer(new MemoryStore()); + + sail.initialize(); + sail.setAddInferredStatementsToDefaultContext(true); + + + try (SchemaCachingRDFSInferencerConnection connection = sail.getConnection()) { + connection.begin(); + connection.addStatement(bNode, RDF.TYPE, type, context); + connection.commit(); + + assertFalse(connection.hasStatement(bNode, RDF.TYPE, RDFS.RESOURCE, true, context)); + assertTrue(connection.hasStatement(bNode, RDF.TYPE, RDFS.RESOURCE, true)); + + } + + } + + @Test + public void testInferrecContextNoNull() { + SchemaCachingRDFSInferencer sail = new SchemaCachingRDFSInferencer(new MemoryStore()); + + sail.initialize(); + sail.setAddInferredStatementsToDefaultContext(false); + + try (SchemaCachingRDFSInferencerConnection connection = sail.getConnection()) { + connection.begin(); + connection.addStatement(bNode, RDF.TYPE, type, context); + connection.commit(); + + assertTrue(connection.hasStatement(bNode, RDF.TYPE, RDFS.RESOURCE, true, context)); + + try (CloseableIteration statements = connection.getStatements(bNode, RDF.TYPE, RDFS.RESOURCE, true)) { + while (statements.hasNext()) { + Statement next = statements.next(); + assertEquals("Context should be equal", context, next.getContext()); + } + } + } + + } + + @Test + public void testDefaultBehaviour() { + SchemaCachingRDFSInferencer sail = new SchemaCachingRDFSInferencer(new MemoryStore()); + + assertTrue( + "Current default behaviour should be to add all statements to default context", + sail.isAddInferredStatementsToDefaultContext() + ); + + } + +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/SchemaCachingRDFSInferencerMemInferencingTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/SchemaCachingRDFSInferencerMemInferencingTest.java index d9908a543..1fd106dd7 100644 --- a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/SchemaCachingRDFSInferencerMemInferencingTest.java +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/SchemaCachingRDFSInferencerMemInferencingTest.java @@ -29,7 +29,8 @@ public class SchemaCachingRDFSInferencerMemInferencingTest extends InferencingTe @Override protected Sail createSail() { - Sail sailStack = new SchemaCachingRDFSInferencer(new MemoryStore(), true); + SchemaCachingRDFSInferencer sailStack = new SchemaCachingRDFSInferencer(new MemoryStore(), true); + sailStack.setAddInferredStatementsToDefaultContext(false); return sailStack; } diff --git a/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/SchemaCachingRDFSInferencer.java b/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/SchemaCachingRDFSInferencer.java index f448a5aec..c8cc65282 100644 --- a/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/SchemaCachingRDFSInferencer.java +++ b/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/SchemaCachingRDFSInferencer.java @@ -93,6 +93,13 @@ public class SchemaCachingRDFSInferencer extends NotifyingSailWrapper { // The previous transaction rolled back boolean rolledBackAfterModifyingSchemaCache; + // Inferred statements can either be added to the default context + // or to the context that the original inserted statement has + // for the time being, the default behaviour will be to adde the + // statements to the default context. + // THIS BEHAVIOUR WILL BE SWITCHED ON THE NEXT MAJOR RELEASE + private boolean addInferredStatementsToDefaultContext = true; + /** * Instantiate a SchemaCachingRDFSInferencer. * @@ -615,4 +622,11 @@ public List getSupportedIsolationLevels() { return levels; } + public boolean isAddInferredStatementsToDefaultContext() { + return addInferredStatementsToDefaultContext; + } + + public void setAddInferredStatementsToDefaultContext(boolean addInferredStatementsToDefaultContext) { + this.addInferredStatementsToDefaultContext = addInferredStatementsToDefaultContext; + } } diff --git a/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/SchemaCachingRDFSInferencerConnection.java b/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/SchemaCachingRDFSInferencerConnection.java index 52b8a51a1..2b0562740 100644 --- a/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/SchemaCachingRDFSInferencerConnection.java +++ b/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/SchemaCachingRDFSInferencerConnection.java @@ -187,19 +187,28 @@ public void addStatement(Resource subject, IRI predicate, Value object, Resource // actuallyAdd private void addStatement(boolean actuallyAdd, Resource subject, IRI predicate, Value object, - Resource... resources) + Resource... context) throws SailException { + + Resource[] inferredContext; + if(sail.isAddInferredStatementsToDefaultContext()){ + inferredContext = new Resource[0]; + } else { + inferredContext = context; + } + + sail.acquireExclusiveWriteLock(); if (sail.schema == null) { processForSchemaCache(sail.getValueFactory().createStatement(subject, predicate, object)); } if (sail.useAllRdfsRules) { - addInferredStatement(subject, RDF.TYPE, RDFS.RESOURCE, resources); + addInferredStatement(subject, RDF.TYPE, RDFS.RESOURCE, inferredContext); if (object instanceof Resource) { - addInferredStatement((Resource)object, RDF.TYPE, RDFS.RESOURCE, resources); + addInferredStatement((Resource)object, RDF.TYPE, RDFS.RESOURCE, inferredContext); } } @@ -208,13 +217,13 @@ private void addStatement(boolean actuallyAdd, Resource subject, IRI predicate, try { int i = Integer.parseInt(predicate.getLocalName().substring(1)); if (i >= 1) { - addInferredStatement(subject, RDFS.MEMBER, object, resources); + addInferredStatement(subject, RDFS.MEMBER, object, inferredContext); - addInferredStatement(predicate, RDF.TYPE, RDFS.RESOURCE, resources); - addInferredStatement(predicate, RDF.TYPE, RDFS.CONTAINERMEMBERSHIPPROPERTY, resources); - addInferredStatement(predicate, RDF.TYPE, RDF.PROPERTY, resources); - addInferredStatement(predicate, RDFS.SUBPROPERTYOF, predicate, resources); - addInferredStatement(predicate, RDFS.SUBPROPERTYOF, RDFS.MEMBER, resources); + addInferredStatement(predicate, RDF.TYPE, RDFS.RESOURCE, inferredContext); + addInferredStatement(predicate, RDF.TYPE, RDFS.CONTAINERMEMBERSHIPPROPERTY, inferredContext); + addInferredStatement(predicate, RDF.TYPE, RDF.PROPERTY, inferredContext); + addInferredStatement(predicate, RDFS.SUBPROPERTYOF, predicate, inferredContext); + addInferredStatement(predicate, RDFS.SUBPROPERTYOF, RDFS.MEMBER, inferredContext); } } @@ -230,7 +239,7 @@ private void addStatement(boolean actuallyAdd, Resource subject, IRI predicate, } if (actuallyAdd) { - connection.addStatement(subject, predicate, object, resources); + connection.addStatement(subject, predicate, object, context); } @@ -241,10 +250,10 @@ private void addStatement(boolean actuallyAdd, Resource subject, IRI predicate, sail.resolveTypes((Resource)object).stream().peek(inferredType -> { if (sail.useAllRdfsRules && inferredType.equals(RDFS.CLASS)) { - addInferredStatement(subject, RDFS.SUBCLASSOF, RDFS.RESOURCE, resources); + addInferredStatement(subject, RDFS.SUBCLASSOF, RDFS.RESOURCE, inferredContext); } }).filter(inferredType -> !inferredType.equals(object)).forEach( - inferredType -> addInferredStatement(subject, RDF.TYPE, inferredType, resources)); + inferredType -> addInferredStatement(subject, RDF.TYPE, inferredType, inferredContext)); } sail.resolveProperties(predicate) @@ -252,27 +261,27 @@ private void addStatement(boolean actuallyAdd, Resource subject, IRI predicate, .filter(inferredProperty -> !inferredProperty.equals(predicate)) .filter(inferredPropery -> inferredPropery instanceof IRI) .map(inferredPropery -> ((IRI) inferredPropery)) - .forEach(inferredProperty -> addInferredStatement(subject, inferredProperty, object, resources)); + .forEach(inferredProperty -> addInferredStatement(subject, inferredProperty, object, inferredContext)); if (object instanceof Resource) { sail.resolveRangeTypes(predicate) .stream() .peek(inferredType -> { if (sail.useAllRdfsRules && inferredType.equals(RDFS.CLASS)) { - addInferredStatement(((Resource) object), RDFS.SUBCLASSOF, RDFS.RESOURCE, resources); + addInferredStatement(((Resource) object), RDFS.SUBCLASSOF, RDFS.RESOURCE, inferredContext); } }) - .forEach(inferredType -> addInferredStatement(((Resource) object), RDF.TYPE, inferredType, resources)); + .forEach(inferredType -> addInferredStatement(((Resource) object), RDF.TYPE, inferredType, inferredContext)); } sail.resolveDomainTypes(predicate) .stream() .peek(inferredType -> { if (sail.useAllRdfsRules && inferredType.equals(RDFS.CLASS)) { - addInferredStatement(subject, RDFS.SUBCLASSOF, RDFS.RESOURCE, resources); + addInferredStatement(subject, RDFS.SUBCLASSOF, RDFS.RESOURCE, inferredContext); } }) - .forEach(inferredType -> addInferredStatement((subject), RDF.TYPE, inferredType, resources)); + .forEach(inferredType -> addInferredStatement((subject), RDF.TYPE, inferredType, inferredContext)); } From 01e0651f19979fc607c7b30c15fae5c524c15634 Mon Sep 17 00:00:00 2001 From: Jeen Broekstra Date: Thu, 27 Dec 2018 11:34:03 +1100 Subject: [PATCH 12/54] GH-1230 migrate compliance tests to rdf4j-storage Signed-off-by: Jeen Broekstra --- compliance/pom.xml | 3 +- compliance/sparql/pom.xml | 242 +++++ .../sparql/ArbitraryLengthPathTest.java | 137 +++ .../sparql/MemoryComplexSPARQLQueryTest.java | 27 + .../parser/sparql/MemorySPARQLUpdateTest.java | 29 + .../parser/sparql/SPARQLEmbeddedServer.java | 129 +++ .../sparql/SPARQLServiceEvaluationTest.java | 827 ++++++++++++++++++ .../parser/sparql/manifest/EarlReport.java | 186 ++++ .../W3CApprovedSPARQL10QueryTest.java | 74 ++ .../W3CApprovedSPARQL10SyntaxTest.java | 50 ++ .../W3CApprovedSPARQL11QueryTest.java | 70 ++ .../W3CApprovedSPARQL11SyntaxTest.java | 58 ++ .../W3CApprovedSPARQL11UpdateTest.java | 61 ++ .../FederationSPARQL10QueryTest.java | 73 ++ .../FederationSPARQL11QueryTest.java | 75 ++ .../sail/federation/FederationSparqlTest.java | 52 ++ .../src/test/resources/logback-test.xml | 15 + 17 files changed, 2107 insertions(+), 1 deletion(-) create mode 100644 compliance/sparql/pom.xml create mode 100644 compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/ArbitraryLengthPathTest.java create mode 100644 compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/MemoryComplexSPARQLQueryTest.java create mode 100644 compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/MemorySPARQLUpdateTest.java create mode 100644 compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/SPARQLEmbeddedServer.java create mode 100644 compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/SPARQLServiceEvaluationTest.java create mode 100644 compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/EarlReport.java create mode 100644 compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/W3CApprovedSPARQL10QueryTest.java create mode 100644 compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/W3CApprovedSPARQL10SyntaxTest.java create mode 100644 compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/W3CApprovedSPARQL11QueryTest.java create mode 100644 compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/W3CApprovedSPARQL11SyntaxTest.java create mode 100644 compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/W3CApprovedSPARQL11UpdateTest.java create mode 100644 compliance/sparql/src/test/java/org/eclipse/rdf4j/sail/federation/FederationSPARQL10QueryTest.java create mode 100644 compliance/sparql/src/test/java/org/eclipse/rdf4j/sail/federation/FederationSPARQL11QueryTest.java create mode 100644 compliance/sparql/src/test/java/org/eclipse/rdf4j/sail/federation/FederationSparqlTest.java create mode 100644 compliance/sparql/src/test/resources/logback-test.xml diff --git a/compliance/pom.xml b/compliance/pom.xml index 58cfabd86..f28046b0b 100644 --- a/compliance/pom.xml +++ b/compliance/pom.xml @@ -13,7 +13,8 @@ model - lucene + sparql + lucene elasticsearch solr store diff --git a/compliance/sparql/pom.xml b/compliance/sparql/pom.xml new file mode 100644 index 000000000..fb4368650 --- /dev/null +++ b/compliance/sparql/pom.xml @@ -0,0 +1,242 @@ + + + 4.0.0 + + + org.eclipse.rdf4j + rdf4j-storage-compliance + 2.5-SNAPSHOT + + + rdf4j-sparql-compliance + war + + RDF4J SPARQL query parser compliance tests + Tests for the SPARQL query language implementation + + + + 2.4.2 + 7.0.2.v20100331 + + + + ${project.groupId} + rdf4j-model + ${project.version} + + + + ${project.groupId} + rdf4j-sparql-testsuite + ${project.version} + + + + ${project.groupId} + rdf4j-rio-api + ${project.version} + + + + ${project.groupId} + rdf4j-rio-turtle + ${project.version} + runtime + + + + ${project.groupId} + rdf4j-rio-rdfxml + ${project.version} + runtime + + + + ${project.groupId} + rdf4j-query + ${project.version} + + + + ${project.groupId} + rdf4j-queryresultio-api + ${project.version} + + + + ${project.groupId} + rdf4j-queryresultio-sparqlxml + ${project.version} + runtime + + + + ${project.groupId} + rdf4j-queryparser-api + ${project.version} + + + + ${project.groupId} + rdf4j-queryparser-sparql + ${project.version} + runtime + + + + ${project.groupId} + rdf4j-repository-api + ${project.version} + + + + ${project.groupId} + rdf4j-repository-dataset + ${project.version} + + + + ${project.groupId} + rdf4j-repository-contextaware + ${project.version} + + + + ${project.groupId} + rdf4j-repository-sail + ${project.version} + + + + ${project.groupId} + rdf4j-sail-api + ${project.version} + + + + ${project.groupId} + rdf4j-http-server + ${rdf4j.server.version} + war + + + + ${project.groupId} + rdf4j-sail-memory + ${project.version} + + + + ${project.groupId} + rdf4j-util + ${project.version} + + + + ${project.groupId} + rdf4j-sail-federation + ${project.version} + + + + org.slf4j + slf4j-api + + + + ch.qos.logback + logback-classic + test + + + + junit + junit + compile + + + + ${project.groupId} + rdf4j-http-protocol + ${project.version} + + + + ${project.groupId} + rdf4j-repository-manager + ${project.version} + + + + + org.eclipse.jetty + jetty-server + ${jetty.version} + + + + org.eclipse.jetty + jetty-webapp + ${jetty.version} + + + + org.mortbay.jetty + jetty-jsp-2.1 + ${jetty.version} + runtime + + + + org.slf4j + jcl-over-slf4j + test + + + org.slf4j + log4j-over-slf4j + test + + + + + + + org.apache.maven.plugins + maven-war-plugin + + ${project.build.directory}/rdf4j-server + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + org.apache.maven.plugins + maven-failsafe-plugin + + + integration-tests + integration-test + + integration-test + + + + verify + verify + + verify + + + + + + + diff --git a/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/ArbitraryLengthPathTest.java b/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/ArbitraryLengthPathTest.java new file mode 100644 index 000000000..2fc7736f3 --- /dev/null +++ b/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/ArbitraryLengthPathTest.java @@ -0,0 +1,137 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.sparql; + +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.model.vocabulary.RDFS; +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.memory.MemoryStore; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import junit.framework.TestCase; + +/** + * @author james + */ +public class ArbitraryLengthPathTest extends TestCase { + + private Repository repo; + + private RepositoryConnection con; + + @Before + public void setUp() + throws Exception + { + repo = new SailRepository(new MemoryStore()); + repo.initialize(); + con = repo.getConnection(); + } + + @After + public void tearDown() + throws Exception + { + con.close(); + repo.shutDown(); + } + + @Test + public void test10() + throws Exception + { + populate(10); + String sparql = "ASK { * }"; + assertTrue(con.prepareBooleanQuery(QueryLanguage.SPARQL, sparql).evaluate()); + } + + @Test + public void test100() + throws Exception + { + populate(100); + String sparql = "ASK { * }"; + assertTrue(con.prepareBooleanQuery(QueryLanguage.SPARQL, sparql).evaluate()); + } + + @Test + public void test1000() + throws Exception + { + populate(1000); + String sparql = "ASK { * }"; + assertTrue(con.prepareBooleanQuery(QueryLanguage.SPARQL, sparql).evaluate()); + } + + @Test + public void test10000() + throws Exception + { + populate(10000); + String sparql = "ASK { * }"; + assertTrue(con.prepareBooleanQuery(QueryLanguage.SPARQL, sparql).evaluate()); + } + + @Test + public void test100000() + throws Exception + { + populate(100000); + String sparql = "ASK { * }"; + assertTrue(con.prepareBooleanQuery(QueryLanguage.SPARQL, sparql).evaluate()); + } + + @Test + public void testDirection() + throws Exception + { + ValueFactory vf = con.getValueFactory(); + con.add(vf.createIRI("urn:test:a"), vf.createIRI("urn:test:rel"), vf.createIRI("urn:test:b")); + con.add(vf.createIRI("urn:test:b"), vf.createIRI("urn:test:rel"), vf.createIRI("urn:test:a")); + String sparql = "ASK { * . * }"; + assertTrue(con.prepareBooleanQuery(QueryLanguage.SPARQL, sparql).evaluate()); + } + + @Test + public void testSimilarPatterns() + throws Exception + { + ValueFactory vf = con.getValueFactory(); + con.add(vf.createIRI("urn:test:a"), RDF.TYPE, vf.createIRI("urn:test:c")); + con.add(vf.createIRI("urn:test:b"), RDF.TYPE, vf.createIRI("urn:test:d")); + con.add(vf.createIRI("urn:test:c"), RDFS.SUBCLASSOF, vf.createIRI("urn:test:e")); + con.add(vf.createIRI("urn:test:d"), RDFS.SUBCLASSOF, vf.createIRI("urn:test:f")); + String sparql = "ASK { \n" + + " values (?expectedTargetClass55555 ?expectedTargetClass5544T) {( )}.\n" + + " a ?linkTargetClass55555 .\n" + + " ?linkTargetClass55555 rdfs:subClassOf* ?expectedTargetClass55555 .\n" + + " a ?linkTargetClass55556 .\n" + + " ?linkTargetClass55556 rdfs:subClassOf* ?expectedTargetClass5544T . }"; + assertTrue(con.prepareBooleanQuery(QueryLanguage.SPARQL, sparql).evaluate()); + } + + private void populate(int n) + throws RepositoryException + { + ValueFactory vf = con.getValueFactory(); + for (int i = 0; i < n; i++) { + con.add(vf.createIRI("urn:test:root"), vf.createIRI("urn:test:hasChild"), + vf.createIRI("urn:test:node" + i)); + } + con.add(vf.createIRI("urn:test:root"), vf.createIRI("urn:test:hasChild"), + vf.createIRI("urn:test:node-end")); + } + +} diff --git a/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/MemoryComplexSPARQLQueryTest.java b/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/MemoryComplexSPARQLQueryTest.java new file mode 100644 index 000000000..1c08edf45 --- /dev/null +++ b/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/MemoryComplexSPARQLQueryTest.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.sparql; + +import org.eclipse.rdf4j.query.parser.sparql.ComplexSPARQLQueryTest; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.memory.MemoryStore; + +/** + * @author jeen + */ +public class MemoryComplexSPARQLQueryTest extends ComplexSPARQLQueryTest { + + @Override + protected Repository newRepository() + throws Exception + { + return new SailRepository(new MemoryStore()); + } + +} diff --git a/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/MemorySPARQLUpdateTest.java b/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/MemorySPARQLUpdateTest.java new file mode 100644 index 000000000..272b878fa --- /dev/null +++ b/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/MemorySPARQLUpdateTest.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.sparql; + +import org.eclipse.rdf4j.query.parser.sparql.SPARQLUpdateTest; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.memory.MemoryStore; + +/** + * Test SPARQL 1.1 Update functionality on an in-memory store. + * + * @author Jeen Broekstra + */ +public class MemorySPARQLUpdateTest extends SPARQLUpdateTest { + + @Override + protected Repository newRepository() + throws Exception + { + return new SailRepository(new MemoryStore()); + } + +} diff --git a/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/SPARQLEmbeddedServer.java b/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/SPARQLEmbeddedServer.java new file mode 100644 index 000000000..bbfc2fdf3 --- /dev/null +++ b/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/SPARQLEmbeddedServer.java @@ -0,0 +1,129 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.sparql; + +import java.io.File; +import java.util.List; + +import org.eclipse.jetty.server.Connector; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.nio.BlockingChannelConnector; +import org.eclipse.jetty.webapp.WebAppContext; +import org.eclipse.rdf4j.http.protocol.Protocol; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.repository.config.RepositoryConfig; +import org.eclipse.rdf4j.repository.config.RepositoryConfigException; +import org.eclipse.rdf4j.repository.config.RepositoryConfigUtil; +import org.eclipse.rdf4j.repository.http.HTTPRepository; +import org.eclipse.rdf4j.repository.manager.SystemRepository; +import org.eclipse.rdf4j.repository.sail.config.SailRepositoryConfig; +import org.eclipse.rdf4j.sail.memory.config.MemoryStoreConfig; + +/** + * An embedded http server for SPARQL query testing. Initializes a memory store repository for each specified + * repositoryId. + * + * @author Andreas Schwarte + */ +public class SPARQLEmbeddedServer { + + private static final String HOST = "localhost"; + + private static final int PORT = 18080; + + private static final String SERVER_CONTEXT = "/rdf4j-server"; + + private final List repositoryIds; + + private final Server jetty; + + /** + * @param repositoryIds + */ + public SPARQLEmbeddedServer(List repositoryIds) { + this.repositoryIds = repositoryIds; + System.clearProperty("DEBUG"); + + jetty = new Server(); + + Connector conn = new BlockingChannelConnector(); + conn.setHost(HOST); + conn.setPort(PORT); + jetty.addConnector(conn); + + WebAppContext webapp = new WebAppContext(); + webapp.setContextPath(SERVER_CONTEXT); + // warPath configured in pom.xml maven-war-plugin configuration + webapp.setWar("./target/rdf4j-server"); + jetty.setHandler(webapp); + } + + /** + * @return the url to the repository with given id + */ + public String getRepositoryUrl(String repoId) { + return Protocol.getRepositoryLocation(getServerUrl(), repoId); + } + + /** + * @return the server url + */ + public String getServerUrl() { + return "http://" + HOST + ":" + PORT + SERVER_CONTEXT; + } + + public void start() + throws Exception + { + File dataDir = new File(System.getProperty("user.dir") + "/target/datadir"); + dataDir.mkdirs(); + System.setProperty("org.eclipse.rdf4j.appdata.basedir", dataDir.getAbsolutePath()); + + jetty.start(); + + createTestRepositories(); + } + + public void stop() + throws Exception + { + Repository systemRepo = new HTTPRepository( + Protocol.getRepositoryLocation(getServerUrl(), SystemRepository.ID)); + RepositoryConnection con = systemRepo.getConnection(); + try { + con.clear(); + } + finally { + con.close(); + systemRepo.shutDown(); + } + + jetty.stop(); + System.clearProperty("org.mortbay.log.class"); + } + + private void createTestRepositories() + throws RepositoryException, RepositoryConfigException + { + Repository systemRep = new HTTPRepository( + Protocol.getRepositoryLocation(getServerUrl(), SystemRepository.ID)); + + // create a memory store for each provided repository id + for (String repId : repositoryIds) { + MemoryStoreConfig memStoreConfig = new MemoryStoreConfig(); + memStoreConfig.setPersist(false); + SailRepositoryConfig sailRepConfig = new SailRepositoryConfig(memStoreConfig); + RepositoryConfig repConfig = new RepositoryConfig(repId, sailRepConfig); + + RepositoryConfigUtil.updateRepositoryConfigs(systemRep, repConfig); + } + + } +} diff --git a/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/SPARQLServiceEvaluationTest.java b/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/SPARQLServiceEvaluationTest.java new file mode 100644 index 000000000..4a522bf1c --- /dev/null +++ b/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/SPARQLServiceEvaluationTest.java @@ -0,0 +1,827 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.sparql; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Optional; +import java.util.Set; + +import junit.framework.TestCase; + +import org.eclipse.rdf4j.common.io.IOUtil; +import org.eclipse.rdf4j.common.iteration.Iterations; +import org.eclipse.rdf4j.common.text.StringUtil; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.model.util.Literals; +import org.eclipse.rdf4j.model.util.Models; +import org.eclipse.rdf4j.model.vocabulary.FOAF; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.BooleanQuery; +import org.eclipse.rdf4j.query.GraphQuery; +import org.eclipse.rdf4j.query.GraphQueryResult; +import org.eclipse.rdf4j.query.MalformedQueryException; +import org.eclipse.rdf4j.query.Query; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.query.QueryResults; +import org.eclipse.rdf4j.query.TupleQuery; +import org.eclipse.rdf4j.query.TupleQueryResult; +import org.eclipse.rdf4j.query.dawg.DAWGTestResultSetUtil; +import org.eclipse.rdf4j.query.impl.MutableTupleQueryResult; +import org.eclipse.rdf4j.query.impl.TupleQueryResultBuilder; +import org.eclipse.rdf4j.query.resultio.QueryResultFormat; +import org.eclipse.rdf4j.query.resultio.QueryResultIO; +import org.eclipse.rdf4j.query.resultio.TupleQueryResultFormat; +import org.eclipse.rdf4j.query.resultio.TupleQueryResultParser; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.repository.http.HTTPRepository; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.rio.RDFFormat; +import org.eclipse.rdf4j.rio.RDFParseException; +import org.eclipse.rdf4j.rio.RDFParser; +import org.eclipse.rdf4j.rio.Rio; +import org.eclipse.rdf4j.rio.RDFParser.DatatypeHandling; +import org.eclipse.rdf4j.rio.helpers.StatementCollector; +import org.eclipse.rdf4j.sail.memory.MemoryStore; +import org.junit.After; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Test suite for evaluation of SPARQL queries involving SERVICE clauses. The test suite starts up an embedded + * Jetty server running RDF4J Server, which functions as the SPARQL endpoint to test against. The test is configured + * to execute the W3C service tests located in rdf4j-sparql-testsuite/src/main/resources/testcases-service + * + * @author Jeen Broekstra + * @author Andreas Schwarte + */ +public class SPARQLServiceEvaluationTest extends TestCase { + + static final Logger logger = LoggerFactory.getLogger(SPARQLServiceEvaluationTest.class); + + /** + * The maximal number of endpoints occurring in a (single) test case + */ + protected static final int MAX_ENDPOINTS = 3; + + private SPARQLEmbeddedServer server; + + private SailRepository localRepository; + + private List remoteRepositories; + + public SPARQLServiceEvaluationTest() { + + } + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() + throws Exception + { + // set up the server: the maximal number of endpoints must be known + List repositoryIds = new ArrayList(MAX_ENDPOINTS); + for (int i = 1; i <= MAX_ENDPOINTS; i++) + repositoryIds.add("endpoint" + i); + server = new SPARQLEmbeddedServer(repositoryIds); + + try { + server.start(); + } + catch (Exception e) { + server.stop(); + throw e; + } + + remoteRepositories = new ArrayList(MAX_ENDPOINTS); + for (int i = 1; i <= MAX_ENDPOINTS; i++) { + HTTPRepository r = new HTTPRepository(getRepositoryUrl(i)); + r.initialize(); + remoteRepositories.add(r); + } + + localRepository = new SailRepository(new MemoryStore()); + localRepository.initialize(); + } + + /** + * Get the repository url, initialized repositories are called endpoint1 endpoint2 .. + * endpoint%MAX_ENDPOINTS% + * + * @param i + * the index of the repository, starting with 1 + * @return + */ + protected String getRepositoryUrl(int i) { + return server.getRepositoryUrl("endpoint" + i); + } + + /** + * Get the repository, initialized repositories are called endpoint1 endpoint2 .. endpoint%MAX_ENDPOINTS% + * + * @param i + * the index of the repository, starting with 1 + * @return + */ + public HTTPRepository getRepository(int i) { + return remoteRepositories.get(i - 1); + } + + /** + * Prepare a particular test, and load the specified data. Note: the repositories are cleared before + * loading data + * + * @param localData + * a local data file that is added to local repository, use null if there is no local data + * @param endpointData + * a list of endpoint data files, dataFile at index is loaded to endpoint%i%, use empty list for no + * remote data + * @throws Exception + */ + protected void prepareTest(String localData, List endpointData) + throws Exception + { + + if (endpointData.size() > MAX_ENDPOINTS) + throw new RuntimeException("MAX_ENDPOINTs to low, " + endpointData.size() + + " repositories needed. Adjust configuration"); + + if (localData != null) { + loadDataSet(localRepository, localData); + } + + int i = 1; // endpoint id, start with 1 + for (String s : endpointData) { + loadDataSet(getRepository(i++), s); + } + + } + + /** + * Load a dataset. Note: the repositories are cleared before loading data + * + * @param rep + * @param datasetFile + * @throws RDFParseException + * @throws RepositoryException + * @throws IOException + */ + protected void loadDataSet(Repository rep, String datasetFile) + throws RDFParseException, RepositoryException, IOException + { + logger.debug("loading dataset..."); + InputStream dataset = SPARQLServiceEvaluationTest.class.getResourceAsStream(datasetFile); + + if (dataset == null) + throw new IllegalArgumentException("Datasetfile " + datasetFile + " not found."); + + RepositoryConnection con = rep.getConnection(); + try { + con.clear(); + con.add(dataset, "", Rio.getParserFormatForFileName(datasetFile).orElseThrow( + Rio.unsupportedFormat(datasetFile))); + } + finally { + dataset.close(); + con.close(); + } + logger.debug("dataset loaded."); + } + + /** + * @throws java.lang.Exception + */ + @After + public void tearDown() + throws Exception + { + try { + localRepository.shutDown(); + } + finally { + server.stop(); + } + } + + /** + * Verify that BIND clause alias from the SERVICE clause gets added to the result set. + * @see #646 + */ + @Test + public void testValuesBindClauseHandling() + throws Exception + { + String query = "select * { service <" + getRepositoryUrl(1) + + "> { Bind(1 as ?val) . VALUES ?x {1 2} . } }"; + + try (RepositoryConnection conn = localRepository.getConnection()) { + TupleQuery tq = conn.prepareTupleQuery(query); + TupleQueryResult tqr = tq.evaluate(); + + assertNotNull(tqr); + assertTrue(tqr.hasNext()); + + List result = QueryResults.asList(tqr); + assertEquals(2, result.size()); + for (BindingSet bs : result) { + assertTrue(bs.hasBinding("val")); + assertEquals(1, Literals.getIntValue(bs.getValue("val"), 0)); + assertTrue(bs.hasBinding("x")); + int x = Literals.getIntValue(bs.getValue("x"), 0); + assertTrue(x == 1 || x == 2); + } + } + } + + /** + * Verify that all relevant variable names from the SERVICE clause get added to the result set when + * a BIND clause is present. + * @see #703 + */ + @Test + public void testVariableNameHandling() + throws Exception + { + String query = "select * { service <" + getRepositoryUrl(1) + + "> { ?s ?p ?o . Bind(str(?o) as ?val) . } }"; + + // add some data to the remote endpoint (we don't care about the exact contents) + prepareTest(null, Arrays.asList("/testcases-service/data13.ttl")); + try (RepositoryConnection conn = localRepository.getConnection()) { + TupleQuery tq = conn.prepareTupleQuery(query); + TupleQueryResult tqr = tq.evaluate(); + + assertNotNull(tqr); + assertTrue(tqr.hasNext()); + + List result = QueryResults.asList(tqr); + assertTrue(result.size() > 0); + for (BindingSet bs : result) { + assertTrue(bs.hasBinding("val")); + assertTrue(bs.hasBinding("s")); + assertTrue(bs.hasBinding("p")); + assertTrue(bs.hasBinding("o")); + } + } + } + + @Test + public void testSimpleServiceQuery() + throws RepositoryException + { + // test setup + String EX_NS = "http://example.org/"; + ValueFactory f = localRepository.getValueFactory(); + IRI bob = f.createIRI(EX_NS, "bob"); + IRI alice = f.createIRI(EX_NS, "alice"); + IRI william = f.createIRI(EX_NS, "william"); + + // clears the repository and adds new data + try { + prepareTest("/testcases-service/simple-default-graph.ttl", + Arrays.asList("/testcases-service/simple.ttl")); + } + catch (Exception e1) { + fail(e1.getMessage()); + } + + StringBuilder qb = new StringBuilder(); + qb.append(" SELECT * \n"); + qb.append(" WHERE { \n"); + qb.append(" SERVICE <" + getRepositoryUrl(1) + "> { \n"); + qb.append(" ?X <" + FOAF.NAME + "> ?Y \n "); + qb.append(" } \n "); + qb.append(" ?X a <" + FOAF.PERSON + "> . \n"); + qb.append(" } \n"); + + RepositoryConnection conn = localRepository.getConnection(); + try { + TupleQuery tq = conn.prepareTupleQuery(QueryLanguage.SPARQL, qb.toString()); + + TupleQueryResult tqr = tq.evaluate(); + + assertNotNull(tqr); + assertTrue(tqr.hasNext()); + + int count = 0; + while (tqr.hasNext()) { + BindingSet bs = tqr.next(); + count++; + + Value x = bs.getValue("X"); + Value y = bs.getValue("Y"); + + assertFalse(william.equals(x)); + + assertTrue(bob.equals(x) || alice.equals(x)); + if (bob.equals(x)) { + f.createLiteral("Bob").equals(y); + } + else if (alice.equals(x)) { + f.createLiteral("Alice").equals(y); + } + } + + assertEquals(2, count); + + } + catch (MalformedQueryException e) { + fail(e.getMessage()); + } + catch (QueryEvaluationException e) { + fail(e.getMessage()); + } + finally { + conn.close(); + } + } + + @Test + public void test1() + throws Exception + { + prepareTest("/testcases-service/data01.ttl", Arrays.asList("/testcases-service/data01endpoint.ttl")); + execute("/testcases-service/service01.rq", "/testcases-service/service01.srx", false); + } + + @Test + public void test2() + throws Exception + { + prepareTest(null, Arrays.asList("/testcases-service/data02endpoint1.ttl", + "/testcases-service/data02endpoint2.ttl")); + execute("/testcases-service/service02.rq", "/testcases-service/service02.srx", false); + } + + @Test + public void test3() + throws Exception + { + prepareTest(null, Arrays.asList("/testcases-service/data03endpoint1.ttl", + "/testcases-service/data03endpoint2.ttl")); + execute("/testcases-service/service03.rq", "/testcases-service/service03.srx", false); + } + + @Test + public void test4() + throws Exception + { + prepareTest("/testcases-service/data04.ttl", Arrays.asList("/testcases-service/data04endpoint.ttl")); + execute("/testcases-service/service04.rq", "/testcases-service/service04.srx", false); + } + + @Test + public void test5() + throws Exception + { + prepareTest("/testcases-service/data05.ttl", Arrays.asList("/testcases-service/data05endpoint1.ttl", + "/testcases-service/data05endpoint2.ttl")); + execute("/testcases-service/service05.rq", "/testcases-service/service05.srx", false); + } + + @Test + public void test6() + throws Exception + { + prepareTest(null, Arrays.asList("/testcases-service/data06endpoint1.ttl")); + execute("/testcases-service/service06.rq", "/testcases-service/service06.srx", false); + } + + @Test + public void test7() + throws Exception + { + // clears the repository and adds new data + execute + prepareTest("/testcases-service/data07.ttl", Collections. emptyList()); + execute("/testcases-service/service07.rq", "/testcases-service/service07.srx", false); + } + + @Test + public void test8() + throws Exception + { + /* test where the SERVICE expression is to be evaluated as ASK request */ + prepareTest("/testcases-service/data08.ttl", Arrays.asList("/testcases-service/data08endpoint.ttl")); + execute("/testcases-service/service08.rq", "/testcases-service/service08.srx", false); + } + + @Test + public void test9() + throws Exception + { + /* test where the service endpoint is bound at runtime through BIND */ + prepareTest(null, Arrays.asList("/testcases-service/data09endpoint.ttl")); + execute("/testcases-service/service09.rq", "/testcases-service/service09.srx", false); + } + + @Test + public void test10() + throws Exception + { + /* test how we deal with blank node */ + prepareTest("/testcases-service/data10.ttl", Arrays.asList("/testcases-service/data10endpoint.ttl")); + execute("/testcases-service/service10.rq", "/testcases-service/service10.srx", false); + } + + @Test + public void test11() + throws Exception + { + /* test vectored join with more intermediate results */ + // clears the repository and adds new data + execute + prepareTest("/testcases-service/data11.ttl", Arrays.asList("/testcases-service/data11endpoint.ttl")); + execute("/testcases-service/service11.rq", "/testcases-service/service11.srx", false); + } + + // test on remote DBpedia endpoint disabled. Only enable for manual testing, + // should not be enabled for + // Surefire or Hudson. + // /** + // * This is a manual test to see the Fallback in action. Query asks + // * DBpedia, which does not support BINDINGS + // * + // * @throws Exception + // */ + // public void testFallbackWithDBpedia() throws Exception { + // /* test vectored join with more intermediate results */ + // // clears the repository and adds new data + execute + // prepareTest("/testcases-service/data12.ttl", + // Collections.emptyList()); + // execute("/testcases-service/service12.rq", + // "/testcases-service/service12.srx", false); + // } + + @Test + public void test13() + throws Exception + { + /* test for bug SES-899: cross product is required */ + prepareTest(null, Arrays.asList("/testcases-service/data13.ttl")); + execute("/testcases-service/service13.rq", "/testcases-service/service13.srx", false); + } + + @Test + public void testEmptyServiceBlock() + throws Exception + { + /* test for bug SES-900: nullpointer for empty service block */ + prepareTest(null, Arrays.asList("/testcases-service/data13.ttl")); + execute("/testcases-service/service14.rq", "/testcases-service/service14.srx", false); + } + + @Test + public void testNotProjectedCount() + throws Exception + { + /* test projection of subqueries - SES-1000 */ + prepareTest(null, Arrays.asList("/testcases-service/data17endpoint1.ttl")); + execute("/testcases-service/service17.rq", "/testcases-service/service17.srx", false); + } + + @Test + public void testNonAsciiCharHandling() + throws Exception + { + /* SES-1056 */ + prepareTest(null, Arrays.asList("/testcases-service/data18endpoint1.rdf")); + execute("/testcases-service/service18.rq", "/testcases-service/service18.srx", false); + } + + /** + * Execute a testcase, both queryFile and expectedResultFile must be files located on the class path. + * + * @param queryFile + * @param expectedResultFile + * @param checkOrder + * @throws Exception + */ + private void execute(String queryFile, String expectedResultFile, boolean checkOrder) + throws Exception + { + RepositoryConnection conn = localRepository.getConnection(); + String queryString = readQueryString(queryFile); + + try { + Query query = conn.prepareQuery(QueryLanguage.SPARQL, queryString); + + if (query instanceof TupleQuery) { + TupleQueryResult queryResult = ((TupleQuery)query).evaluate(); + + TupleQueryResult expectedResult = readExpectedTupleQueryResult(expectedResultFile); + + compareTupleQueryResults(queryResult, expectedResult, checkOrder); + + } + else if (query instanceof GraphQuery) { + GraphQueryResult gqr = ((GraphQuery)query).evaluate(); + Set queryResult = Iterations.asSet(gqr); + + Set expectedResult = readExpectedGraphQueryResult(expectedResultFile); + + compareGraphs(queryResult, expectedResult); + + } + else if (query instanceof BooleanQuery) { + // TODO implement if needed + throw new RuntimeException("Not yet supported " + query.getClass()); + } + else { + throw new RuntimeException("Unexpected query type: " + query.getClass()); + } + } + finally { + conn.close(); + } + } + + /** + * Read the query string from the specified resource + * + * @param queryResource + * @return + * @throws RepositoryException + * @throws IOException + */ + private String readQueryString(String queryResource) + throws RepositoryException, IOException + { + InputStream stream = SPARQLServiceEvaluationTest.class.getResourceAsStream(queryResource); + try { + return IOUtil.readString(new InputStreamReader(stream, "UTF-8")); + } + finally { + stream.close(); + } + } + + /** + * Read the expected tuple query result from the specified resource + * + * @param queryResource + * @return + * @throws RepositoryException + * @throws IOException + */ + private TupleQueryResult readExpectedTupleQueryResult(String resultFile) + throws Exception + { + Optional tqrFormat = QueryResultIO.getParserFormatForFileName(resultFile); + + if (tqrFormat.isPresent()) { + InputStream in = SPARQLServiceEvaluationTest.class.getResourceAsStream(resultFile); + try { + TupleQueryResultParser parser = QueryResultIO.createTupleParser(tqrFormat.get()); + parser.setValueFactory(SimpleValueFactory.getInstance()); + + TupleQueryResultBuilder qrBuilder = new TupleQueryResultBuilder(); + parser.setQueryResultHandler(qrBuilder); + + parser.parseQueryResult(in); + return qrBuilder.getQueryResult(); + } + finally { + in.close(); + } + } + else { + Set resultGraph = readExpectedGraphQueryResult(resultFile); + return DAWGTestResultSetUtil.toTupleQueryResult(resultGraph); + } + } + + /** + * Read the expected graph query result from the specified resource + * + * @param resultFile + * @return + * @throws Exception + */ + private Set readExpectedGraphQueryResult(String resultFile) + throws Exception + { + RDFFormat rdfFormat = Rio.getParserFormatForFileName(resultFile).orElseThrow( + Rio.unsupportedFormat(resultFile)); + + RDFParser parser = Rio.createParser(rdfFormat); + parser.setDatatypeHandling(DatatypeHandling.IGNORE); + parser.setPreserveBNodeIDs(true); + parser.setValueFactory(SimpleValueFactory.getInstance()); + + Set result = new LinkedHashSet(); + parser.setRDFHandler(new StatementCollector(result)); + + InputStream in = SPARQLServiceEvaluationTest.class.getResourceAsStream(resultFile); + try { + parser.parse(in, null); // TODO check + } + finally { + in.close(); + } + + return result; + } + + /** + * Compare two tuple query results + * + * @param queryResult + * @param expectedResult + * @param checkOrder + * @throws Exception + */ + private void compareTupleQueryResults(TupleQueryResult queryResult, TupleQueryResult expectedResult, + boolean checkOrder) + throws Exception + { + // Create MutableTupleQueryResult to be able to re-iterate over the + // results + MutableTupleQueryResult queryResultTable = new MutableTupleQueryResult(queryResult); + MutableTupleQueryResult expectedResultTable = new MutableTupleQueryResult(expectedResult); + + boolean resultsEqual; + + resultsEqual = QueryResults.equals(queryResultTable, expectedResultTable); + + if (checkOrder) { + // also check the order in which solutions occur. + queryResultTable.beforeFirst(); + expectedResultTable.beforeFirst(); + + while (queryResultTable.hasNext()) { + BindingSet bs = queryResultTable.next(); + BindingSet expectedBs = expectedResultTable.next(); + + if (!bs.equals(expectedBs)) { + resultsEqual = false; + break; + } + } + } + + if (!resultsEqual) { + queryResultTable.beforeFirst(); + expectedResultTable.beforeFirst(); + + /* + * StringBuilder message = new StringBuilder(128); message.append("\n============ "); + * message.append(getName()); message.append(" =======================\n"); message.append( + * "Expected result: \n"); while (expectedResultTable.hasNext()) { + * message.append(expectedResultTable.next()); message.append("\n"); } + * message.append("============="); StringUtil.appendN('=', getName().length(), message); + * message.append("========================\n"); message.append("Query result: \n"); while + * (queryResultTable.hasNext()) { message.append(queryResultTable.next()); message.append("\n"); } + * message.append("============="); StringUtil.appendN('=', getName().length(), message); + * message.append("========================\n"); + */ + + List queryBindings = Iterations.asList(queryResultTable); + + List expectedBindings = Iterations.asList(expectedResultTable); + + List missingBindings = new ArrayList(expectedBindings); + missingBindings.removeAll(queryBindings); + + List unexpectedBindings = new ArrayList(queryBindings); + unexpectedBindings.removeAll(expectedBindings); + + StringBuilder message = new StringBuilder(128); + message.append("\n============ "); + message.append(getName()); + message.append(" =======================\n"); + + if (!missingBindings.isEmpty()) { + + message.append("Missing bindings: \n"); + for (BindingSet bs : missingBindings) { + message.append(bs); + message.append("\n"); + } + + message.append("============="); + StringUtil.appendN('=', getName().length(), message); + message.append("========================\n"); + } + + if (!unexpectedBindings.isEmpty()) { + message.append("Unexpected bindings: \n"); + for (BindingSet bs : unexpectedBindings) { + message.append(bs); + message.append("\n"); + } + + message.append("============="); + StringUtil.appendN('=', getName().length(), message); + message.append("========================\n"); + } + + if (checkOrder && missingBindings.isEmpty() && unexpectedBindings.isEmpty()) { + message.append("Results are not in expected order.\n"); + message.append(" =======================\n"); + message.append("query result: \n"); + for (BindingSet bs : queryBindings) { + message.append(bs); + message.append("\n"); + } + message.append(" =======================\n"); + message.append("expected result: \n"); + for (BindingSet bs : expectedBindings) { + message.append(bs); + message.append("\n"); + } + message.append(" =======================\n"); + + System.out.print(message.toString()); + } + + logger.error(message.toString()); + fail(message.toString()); + } + /* + * debugging only: print out result when test succeeds else { queryResultTable.beforeFirst(); + * List queryBindings = Iterations.asList(queryResultTable); StringBuilder message = new + * StringBuilder(128); message.append("\n============ "); message.append(getName()); message.append( + * " =======================\n"); message.append(" =======================\n"); message.append( + * "query result: \n"); for (BindingSet bs: queryBindings) { message.append(bs); message.append("\n"); + * } System.out.print(message.toString()); } + */ + } + + /** + * Compare two graphs + * + * @param queryResult + * @param expectedResult + * @throws Exception + */ + private void compareGraphs(Set queryResult, Set expectedResult) + throws Exception + { + if (!Models.isomorphic(expectedResult, queryResult)) { + // Don't use RepositoryUtil.difference, it reports incorrect diffs + /* + * Collection unexpectedStatements = RepositoryUtil.difference(queryResult, + * expectedResult); Collection missingStatements = + * RepositoryUtil.difference(expectedResult, queryResult); StringBuilder message = new + * StringBuilder(128); message.append("\n=======Diff: "); message.append(getName()); + * message.append("========================\n"); if (!unexpectedStatements.isEmpty()) { + * message.append("Unexpected statements in result: \n"); for (Statement st : + * unexpectedStatements) { message.append(st.toString()); message.append("\n"); } + * message.append("============="); for (int i = 0; i < getName().length(); i++) { + * message.append("="); } message.append("========================\n"); } if + * (!missingStatements.isEmpty()) { message.append("Statements missing in result: \n"); for + * (Statement st : missingStatements) { message.append(st.toString()); message.append("\n"); } + * message.append("============="); for (int i = 0; i < getName().length(); i++) { + * message.append("="); } message.append("========================\n"); } + */ + StringBuilder message = new StringBuilder(128); + message.append("\n============ "); + message.append(getName()); + message.append(" =======================\n"); + message.append("Expected result: \n"); + for (Statement st : expectedResult) { + message.append(st.toString()); + message.append("\n"); + } + message.append("============="); + StringUtil.appendN('=', getName().length(), message); + message.append("========================\n"); + + message.append("Query result: \n"); + for (Statement st : queryResult) { + message.append(st.toString()); + message.append("\n"); + } + message.append("============="); + StringUtil.appendN('=', getName().length(), message); + message.append("========================\n"); + + logger.error(message.toString()); + fail(message.toString()); + } + } + +} diff --git a/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/EarlReport.java b/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/EarlReport.java new file mode 100644 index 000000000..6802a6ea9 --- /dev/null +++ b/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/EarlReport.java @@ -0,0 +1,186 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.sparql.manifest; + +import java.io.File; +import java.io.FileOutputStream; +import java.text.SimpleDateFormat; +import java.util.Date; + +import junit.framework.AssertionFailedError; +import junit.framework.Test; +import junit.framework.TestListener; +import junit.framework.TestResult; + +import org.eclipse.rdf4j.model.BNode; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.vocabulary.DC; +import org.eclipse.rdf4j.model.vocabulary.DCTERMS; +import org.eclipse.rdf4j.model.vocabulary.DOAP; +import org.eclipse.rdf4j.model.vocabulary.EARL; +import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.parser.sparql.manifest.SPARQL11SyntaxTest; +import org.eclipse.rdf4j.query.parser.sparql.manifest.SPARQLQueryTest; +import org.eclipse.rdf4j.query.parser.sparql.manifest.SPARQLUpdateConformanceTest; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.rio.RDFFormat; +import org.eclipse.rdf4j.rio.RDFWriterFactory; +import org.eclipse.rdf4j.rio.RDFWriterRegistry; +import org.eclipse.rdf4j.rio.Rio; +import org.eclipse.rdf4j.sail.memory.MemoryStore; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author Arjohn Kampman + */ +public class EarlReport { + + protected static Repository earlRepository; + + protected static ValueFactory vf; + + protected static RepositoryConnection con; + + protected static Resource projectNode; + + protected static Resource asserterNode; + + private static Logger logger = LoggerFactory.getLogger(EarlReport.class); + + public static void main(String[] args) + throws Exception + { + earlRepository = new SailRepository(new MemoryStore()); + earlRepository.initialize(); + vf = earlRepository.getValueFactory(); + con = earlRepository.getConnection(); + con.begin(); + + con.setNamespace("rdf", RDF.NAMESPACE); + con.setNamespace("xsd", XMLSchema.NAMESPACE); + con.setNamespace("doap", DOAP.NAMESPACE); + con.setNamespace("earl", EARL.NAMESPACE); + con.setNamespace("dcterms", DCTERMS.NAMESPACE); + + projectNode = vf.createBNode(); + BNode releaseNode = vf.createBNode(); + con.add(projectNode, RDF.TYPE, DOAP.PROJECT); + con.add(projectNode, DOAP.NAME, vf.createLiteral("OpenRDF Sesame")); + con.add(projectNode, DOAP.RELEASE, releaseNode); + con.add(projectNode, DOAP.HOMEPAGE, vf.createIRI("http://www.openrdf.org/")); + con.add(releaseNode, RDF.TYPE, DOAP.VERSION); + con.add(releaseNode, DOAP.NAME, vf.createLiteral("Sesame 2.7.0")); + SimpleDateFormat xsdDataFormat = new SimpleDateFormat("yyyy-MM-dd"); + String currentDate = xsdDataFormat.format(new Date()); + con.add(releaseNode, DOAP.CREATED, vf.createLiteral(currentDate, XMLSchema.DATE)); + + asserterNode = vf.createBNode(); + con.add(asserterNode, RDF.TYPE, EARL.SOFTWARE); + con.add(asserterNode, DC.TITLE, vf.createLiteral("OpenRDF SPARQL 1.1 compliance tests")); + + TestResult testResult = new TestResult(); + EarlTestListener listener = new EarlTestListener(); + testResult.addListener(listener); + + logger.info("running query evaluation tests.."); + W3CApprovedSPARQL11QueryTest.suite().run(testResult); + + logger.info("running syntax tests..."); + W3CApprovedSPARQL11SyntaxTest.suite().run(testResult); + + logger.info("running update tests..."); + W3CApprovedSPARQL11UpdateTest.suite().run(testResult); + logger.info("tests complete, generating EARL report..."); + + con.commit(); + + RDFWriterFactory factory = RDFWriterRegistry.getInstance().get(RDFFormat.TURTLE).orElseThrow( + Rio.unsupportedFormat(RDFFormat.TURTLE)); + File outFile = File.createTempFile("sesame-sparql-compliance", + "." + RDFFormat.TURTLE.getDefaultFileExtension()); + FileOutputStream out = new FileOutputStream(outFile); + try { + con.export(factory.getWriter(out)); + } + finally { + out.close(); + } + + con.close(); + earlRepository.shutDown(); + + logger.info("EARL output written to " + outFile); + } + + protected static class EarlTestListener implements TestListener { + + private int errorCount; + + private int failureCount; + + public void startTest(Test test) { + errorCount = failureCount = 0; + } + + public void endTest(Test test) { + String testURI = null; + ; + if (test instanceof SPARQLQueryTest) { + testURI = ((SPARQLQueryTest)test).testURI; + } + else if (test instanceof SPARQL11SyntaxTest) { + testURI = ((SPARQL11SyntaxTest)test).testURI; + } + else if (test instanceof SPARQLUpdateConformanceTest) { + testURI = ((SPARQLUpdateConformanceTest)test).testURI; + } + else { + throw new RuntimeException("Unexpected test type: " + test.getClass()); + } + + try { + BNode testNode = vf.createBNode(); + BNode resultNode = vf.createBNode(); + con.add(testNode, RDF.TYPE, EARL.ASSERTION); + con.add(testNode, EARL.ASSERTEDBY, asserterNode); + con.add(testNode, EARL.MODE, EARL.AUTOMATIC); + con.add(testNode, EARL.SUBJECT, projectNode); + con.add(testNode, EARL.TEST, vf.createIRI(testURI)); + con.add(testNode, EARL.RESULT, resultNode); + con.add(resultNode, RDF.TYPE, EARL.TESTRESULT); + + if (errorCount > 0) { + con.add(resultNode, EARL.OUTCOME, EARL.FAIL); + } + else if (failureCount > 0) { + con.add(resultNode, EARL.OUTCOME, EARL.FAIL); + } + else { + con.add(resultNode, EARL.OUTCOME, EARL.PASS); + } + } + catch (RepositoryException e) { + throw new RuntimeException(e); + } + } + + public void addError(Test test, Throwable t) { + errorCount++; + } + + public void addFailure(Test test, AssertionFailedError error) { + failureCount++; + } + } +} diff --git a/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/W3CApprovedSPARQL10QueryTest.java b/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/W3CApprovedSPARQL10QueryTest.java new file mode 100644 index 000000000..761fc6bc3 --- /dev/null +++ b/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/W3CApprovedSPARQL10QueryTest.java @@ -0,0 +1,74 @@ +/******************************************************************************* + * Copyright (c) 2016 Eclipse RDF4J contributors. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.sparql.manifest; + +import junit.framework.Test; + +import org.eclipse.rdf4j.query.Dataset; +import org.eclipse.rdf4j.query.parser.sparql.manifest.SPARQL11ManifestTest; +import org.eclipse.rdf4j.query.parser.sparql.manifest.SPARQLQueryTest; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.dataset.DatasetRepository; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.memory.MemoryStore; + +/** + * Checks conformance of SPARQL query evaluation against the W3C-approved SPARQL 1.0 query test cases + * + * @author Jeen Broekstra + */ +public class W3CApprovedSPARQL10QueryTest extends SPARQLQueryTest { + + public static Test suite() + throws Exception + { + return SPARQL10ManifestTest.suite(new Factory() { + + public W3CApprovedSPARQL10QueryTest createSPARQLQueryTest(String testURI, String name, + String queryFileURL, String resultFileURL, Dataset dataSet, boolean laxCardinality) + { + return createSPARQLQueryTest(testURI, name, queryFileURL, resultFileURL, dataSet, + laxCardinality, false); + } + + public W3CApprovedSPARQL10QueryTest createSPARQLQueryTest(String testURI, String name, + String queryFileURL, String resultFileURL, Dataset dataSet, boolean laxCardinality, + boolean checkOrder) + { + String[] ignoredTests = { + // incompatible with SPARQL 1.1 - syntax for decimals was modified + "Basic - Term 6", + // incompatible with SPARQL 1.1 - syntax for decimals was modified + "Basic - Term 7", + // Test is incorrect: assumes timezoned date is comparable with non-timezoned + "date-2"}; + + return new W3CApprovedSPARQL10QueryTest(testURI, name, queryFileURL, resultFileURL, dataSet, + laxCardinality, checkOrder, ignoredTests); + } + }); + + } + + protected W3CApprovedSPARQL10QueryTest(String testURI, String name, String queryFileURL, + String resultFileURL, Dataset dataSet, boolean laxCardinality, String... ignoredTests) + { + this(testURI, name, queryFileURL, resultFileURL, dataSet, laxCardinality, false, ignoredTests); + } + + protected W3CApprovedSPARQL10QueryTest(String testURI, String name, String queryFileURL, + String resultFileURL, Dataset dataSet, boolean laxCardinality, boolean checkOrder, + String... ignoredTests) + { + super(testURI, name, queryFileURL, resultFileURL, dataSet, laxCardinality, checkOrder, ignoredTests); + } + + protected Repository newRepository() { + return new DatasetRepository(new SailRepository(new MemoryStore())); + } +} diff --git a/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/W3CApprovedSPARQL10SyntaxTest.java b/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/W3CApprovedSPARQL10SyntaxTest.java new file mode 100644 index 000000000..23b3fd053 --- /dev/null +++ b/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/W3CApprovedSPARQL10SyntaxTest.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright (c) 2016 Eclipse RDF4J contributors. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.sparql.manifest; + +import junit.framework.Test; + +import org.eclipse.rdf4j.query.MalformedQueryException; +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.query.parser.ParsedOperation; +import org.eclipse.rdf4j.query.parser.QueryParserUtil; +import org.eclipse.rdf4j.query.parser.sparql.manifest.SPARQL11SyntaxTest; + +/** + * Checks conformance of SPARQL query parsing against the W3C-approved SPARQL 1.0 test cases + * + * @author Jeen Broekstra + */ +public class W3CApprovedSPARQL10SyntaxTest extends SPARQL11SyntaxTest { + + public static Test suite() + throws Exception + { + return SPARQL11SyntaxTest.suite(new Factory() { + + public SPARQL11SyntaxTest createSPARQLSyntaxTest(String testURI, String testName, + String testAction, boolean positiveTest) + { + return new W3CApprovedSPARQL10SyntaxTest(testURI, testName, testAction, positiveTest); + } + }, false); + } + + public W3CApprovedSPARQL10SyntaxTest(String testURI, String name, String queryFileURL, + boolean positiveTest) + { + super(testURI, name, queryFileURL, positiveTest); + } + + protected ParsedOperation parseOperation(String operation, String fileURL) + throws MalformedQueryException + { + return QueryParserUtil.parseOperation(QueryLanguage.SPARQL, operation, fileURL); + } + +} diff --git a/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/W3CApprovedSPARQL11QueryTest.java b/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/W3CApprovedSPARQL11QueryTest.java new file mode 100644 index 000000000..b494025a7 --- /dev/null +++ b/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/W3CApprovedSPARQL11QueryTest.java @@ -0,0 +1,70 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.sparql.manifest; + +import junit.framework.Test; + +import org.eclipse.rdf4j.query.Dataset; +import org.eclipse.rdf4j.query.parser.sparql.manifest.SPARQL11ManifestTest; +import org.eclipse.rdf4j.query.parser.sparql.manifest.SPARQLQueryTest; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.dataset.DatasetRepository; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.memory.MemoryStore; + +public class W3CApprovedSPARQL11QueryTest extends SPARQLQueryTest { + + public static Test suite() + throws Exception + { + return SPARQL11ManifestTest.suite(new Factory() { + + public W3CApprovedSPARQL11QueryTest createSPARQLQueryTest(String testURI, String name, + String queryFileURL, String resultFileURL, Dataset dataSet, boolean laxCardinality) + { + return createSPARQLQueryTest(testURI, name, queryFileURL, resultFileURL, dataSet, + laxCardinality, false); + } + + public W3CApprovedSPARQL11QueryTest createSPARQLQueryTest(String testURI, String name, + String queryFileURL, String resultFileURL, Dataset dataSet, boolean laxCardinality, + boolean checkOrder) + { + String[] ignoredTests = { + // test case incompatible with RDF 1.1 - see + // http://lists.w3.org/Archives/Public/public-sparql-dev/2013AprJun/0006.html + "STRDT TypeErrors", + // test case incompatible with RDF 1.1 - see + // http://lists.w3.org/Archives/Public/public-sparql-dev/2013AprJun/0006.html + "STRLANG TypeErrors", + // known issue: SES-937 + "sq03 - Subquery within graph pattern, graph variable is not bound" }; + + return new W3CApprovedSPARQL11QueryTest(testURI, name, queryFileURL, resultFileURL, dataSet, + laxCardinality, checkOrder, ignoredTests); + } + }, true, true, false, "service"); + } + + protected W3CApprovedSPARQL11QueryTest(String testURI, String name, String queryFileURL, + String resultFileURL, Dataset dataSet, boolean laxCardinality, String... ignoredTests) + { + this(testURI, name, queryFileURL, resultFileURL, dataSet, laxCardinality, false, ignoredTests); + } + + protected W3CApprovedSPARQL11QueryTest(String testURI, String name, String queryFileURL, + String resultFileURL, Dataset dataSet, boolean laxCardinality, boolean checkOrder, + String... ignoredTests) + { + super(testURI, name, queryFileURL, resultFileURL, dataSet, laxCardinality, checkOrder, ignoredTests); + } + + protected Repository newRepository() { + return new DatasetRepository(new SailRepository(new MemoryStore())); + } +} diff --git a/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/W3CApprovedSPARQL11SyntaxTest.java b/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/W3CApprovedSPARQL11SyntaxTest.java new file mode 100644 index 000000000..8c9ea9dba --- /dev/null +++ b/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/W3CApprovedSPARQL11SyntaxTest.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.sparql.manifest; + +import junit.framework.Test; + +import org.eclipse.rdf4j.query.MalformedQueryException; +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.query.parser.ParsedOperation; +import org.eclipse.rdf4j.query.parser.QueryParserUtil; +import org.eclipse.rdf4j.query.parser.sparql.manifest.SPARQL11SyntaxTest; + +public class W3CApprovedSPARQL11SyntaxTest extends SPARQL11SyntaxTest { + + public static Test suite() + throws Exception + { + return SPARQL11SyntaxTest.suite(new Factory() { + + public SPARQL11SyntaxTest createSPARQLSyntaxTest(String testURI, String testName, + String testAction, boolean positiveTest) + { + return new W3CApprovedSPARQL11SyntaxTest(testURI, testName, testAction, positiveTest); + } + }, false); + } + + public W3CApprovedSPARQL11SyntaxTest(String testURI, String name, String queryFileURL, + boolean positiveTest) + { + super(testURI, name, queryFileURL, positiveTest); + } + + protected ParsedOperation parseOperation(String operation, String fileURL) + throws MalformedQueryException + { + return QueryParserUtil.parseOperation(QueryLanguage.SPARQL, operation, fileURL); + } + + @Override + protected void runTest() + throws Exception + { + if (this.getName().contains("syntax-update-54")) { + // we skip this negative syntax test because it is an unnecessarily restrictive test that is almost + // impossible to implement correctly, and which in practice Sesame handles correctly simply by + // assigning different blank node ids. + } + else { + super.runTest(); + } + } +} diff --git a/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/W3CApprovedSPARQL11UpdateTest.java b/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/W3CApprovedSPARQL11UpdateTest.java new file mode 100644 index 000000000..923792e49 --- /dev/null +++ b/compliance/sparql/src/test/java/org/eclipse/rdf4j/query/parser/sparql/manifest/W3CApprovedSPARQL11UpdateTest.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.parser.sparql.manifest; + +import java.util.Map; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.query.parser.sparql.manifest.SPARQL11ManifestTest; +import org.eclipse.rdf4j.query.parser.sparql.manifest.SPARQLUpdateConformanceTest; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.contextaware.ContextAwareRepository; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.memory.MemoryStore; +import junit.framework.Test; + +import junit.framework.Test; + +/** + * @author Jeen Broekstra + */ +public class W3CApprovedSPARQL11UpdateTest extends SPARQLUpdateConformanceTest { + + public W3CApprovedSPARQL11UpdateTest(String testURI, String name, String requestFile, IRI defaultGraphURI, + Map inputNamedGraphs, IRI resultDefaultGraphURI, + Map resultNamedGraphs) + { + super(testURI, name, requestFile, defaultGraphURI, inputNamedGraphs, resultDefaultGraphURI, + resultNamedGraphs); + } + + public static Test suite() + throws Exception + { + return SPARQL11ManifestTest.suite(new Factory() { + + public W3CApprovedSPARQL11UpdateTest createSPARQLUpdateConformanceTest(String testURI, + String name, String requestFile, IRI defaultGraphURI, Map inputNamedGraphs, + IRI resultDefaultGraphURI, Map resultNamedGraphs) + { + return new W3CApprovedSPARQL11UpdateTest(testURI, name, requestFile, defaultGraphURI, + inputNamedGraphs, resultDefaultGraphURI, resultNamedGraphs); + } + + }, true, true, false); + } + + @Override + protected Repository newRepository() + throws Exception + { + SailRepository repo = new SailRepository(new MemoryStore()); + + return repo; + } + +} diff --git a/compliance/sparql/src/test/java/org/eclipse/rdf4j/sail/federation/FederationSPARQL10QueryTest.java b/compliance/sparql/src/test/java/org/eclipse/rdf4j/sail/federation/FederationSPARQL10QueryTest.java new file mode 100644 index 000000000..1470ec0ed --- /dev/null +++ b/compliance/sparql/src/test/java/org/eclipse/rdf4j/sail/federation/FederationSPARQL10QueryTest.java @@ -0,0 +1,73 @@ +/******************************************************************************* + * Copyright (c) 2016 Eclipse RDF4J contributors. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.sail.federation; + +import junit.framework.Test; + +import org.eclipse.rdf4j.query.Dataset; +import org.eclipse.rdf4j.query.parser.sparql.manifest.SPARQL10ManifestTest; +import org.eclipse.rdf4j.query.parser.sparql.manifest.SPARQLQueryTest; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.dataset.DatasetRepository; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.memory.MemoryStore; + +public class FederationSPARQL10QueryTest extends SPARQLQueryTest { + + public static Test suite() + throws Exception + { + return SPARQL10ManifestTest.suite(new Factory() { + + public FederationSPARQL10QueryTest createSPARQLQueryTest(String testURI, String name, + String queryFileURL, String resultFileURL, Dataset dataSet, boolean laxCardinality) + { + return createSPARQLQueryTest(testURI, name, queryFileURL, resultFileURL, dataSet, + laxCardinality, false); + } + + public FederationSPARQL10QueryTest createSPARQLQueryTest(String testURI, String name, + String queryFileURL, String resultFileURL, Dataset dataSet, boolean laxCardinality, + boolean checkOrder) + { + String[] ignoredTests = { + // incompatible with SPARQL 1.1 - syntax for decimals was modified + "Basic - Term 6", + // incompatible with SPARQL 1.1 - syntax for decimals was modified + "Basic - Term 7", + // Test is incorrect: assumes timezoned date is comparable with non-timezoned + "date-2"}; + + return new FederationSPARQL10QueryTest(testURI, name, queryFileURL, resultFileURL, dataSet, + laxCardinality, checkOrder, ignoredTests); + } + }); + + } + + protected FederationSPARQL10QueryTest(String testURI, String name, String queryFileURL, + String resultFileURL, Dataset dataSet, boolean laxCardinality, String... ignoredTests) + { + this(testURI, name, queryFileURL, resultFileURL, dataSet, laxCardinality, false, ignoredTests); + } + + protected FederationSPARQL10QueryTest(String testURI, String name, String queryFileURL, + String resultFileURL, Dataset dataSet, boolean laxCardinality, boolean checkOrder, + String... ignoredTests) + { + super(testURI, name, queryFileURL, resultFileURL, dataSet, laxCardinality, checkOrder, ignoredTests); + } + + protected Repository newRepository() { + Federation sail = new Federation(); + sail.addMember(new SailRepository(new MemoryStore())); + sail.addMember(new SailRepository(new MemoryStore())); + sail.addMember(new SailRepository(new MemoryStore())); + return new DatasetRepository(new SailRepository(sail)); + } +} diff --git a/compliance/sparql/src/test/java/org/eclipse/rdf4j/sail/federation/FederationSPARQL11QueryTest.java b/compliance/sparql/src/test/java/org/eclipse/rdf4j/sail/federation/FederationSPARQL11QueryTest.java new file mode 100644 index 000000000..8ada6c6b7 --- /dev/null +++ b/compliance/sparql/src/test/java/org/eclipse/rdf4j/sail/federation/FederationSPARQL11QueryTest.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.sail.federation; + +import org.eclipse.rdf4j.query.Dataset; +import org.eclipse.rdf4j.query.parser.sparql.manifest.SPARQL11ManifestTest; +import org.eclipse.rdf4j.query.parser.sparql.manifest.SPARQLQueryTest; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.dataset.DatasetRepository; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.memory.MemoryStore; + +import junit.framework.Test; + +public class FederationSPARQL11QueryTest extends SPARQLQueryTest { + + public static Test suite() + throws Exception + { + return SPARQL11ManifestTest.suite(new Factory() { + + public SPARQLQueryTest createSPARQLQueryTest(String testURI, String name, String queryFileURL, + String resultFileURL, Dataset dataSet, boolean laxCardinality) + { + return new FederationSPARQL11QueryTest(testURI, name, queryFileURL, resultFileURL, dataSet, + laxCardinality); + } + + public SPARQLQueryTest createSPARQLQueryTest(String testURI, String name, String queryFileURL, + String resultFileURL, Dataset dataSet, boolean laxCardinality, boolean checkOrder) + { + String[] ignoredTests = { + // test case incompatible with RDF 1.1 - see + // http://lists.w3.org/Archives/Public/public-sparql-dev/2013AprJun/0006.html + "STRDT TypeErrors", + // test case incompatible with RDF 1.1 - see + // http://lists.w3.org/Archives/Public/public-sparql-dev/2013AprJun/0006.html + "STRLANG TypeErrors", + // known issue: SES-937 + "sq03 - Subquery within graph pattern, graph variable is not bound", + }; + + return new FederationSPARQL11QueryTest(testURI, name, queryFileURL, resultFileURL, dataSet, + laxCardinality, checkOrder, ignoredTests); + } + // skip 'service' tests for now since they require presence of remote sparql endpoints. + }, true, true, false, "service"); + } + + public FederationSPARQL11QueryTest(String testURI, String name, String queryFileURL, String resultFileURL, + Dataset dataSet, boolean laxCardinality, String... ignoredTests) + { + super(testURI, name, queryFileURL, resultFileURL, dataSet, laxCardinality, ignoredTests); + } + + public FederationSPARQL11QueryTest(String testURI, String name, String queryFileURL, String resultFileURL, + Dataset dataSet, boolean laxCardinality, boolean checkOrder, String... ignoredTests) + { + super(testURI, name, queryFileURL, resultFileURL, dataSet, laxCardinality, checkOrder, ignoredTests); + } + + @Override + protected Repository newRepository() { + Federation sail = new Federation(); + sail.addMember(new SailRepository(new MemoryStore())); + sail.addMember(new SailRepository(new MemoryStore())); + sail.addMember(new SailRepository(new MemoryStore())); + return new DatasetRepository(new SailRepository(sail)); + } +} diff --git a/compliance/sparql/src/test/java/org/eclipse/rdf4j/sail/federation/FederationSparqlTest.java b/compliance/sparql/src/test/java/org/eclipse/rdf4j/sail/federation/FederationSparqlTest.java new file mode 100644 index 000000000..18315e31d --- /dev/null +++ b/compliance/sparql/src/test/java/org/eclipse/rdf4j/sail/federation/FederationSparqlTest.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright (c) 2016 Eclipse RDF4J contributors. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.sail.federation; + +import static org.junit.Assert.assertFalse; + +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.query.TupleQuery; +import org.eclipse.rdf4j.query.TupleQueryResult; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.sail.memory.MemoryStore; +import org.junit.Test; + +public class FederationSparqlTest { + + @Test + public void test181Issue() + throws Exception + { + SailRepository repo1 = new SailRepository(new MemoryStore()); + SailRepository repo2 = new SailRepository(new MemoryStore()); + Federation fed = new Federation(); + fed.addMember(repo1); + fed.addMember(repo2); + SailRepository repoFed = new SailRepository(fed); + repoFed.initialize(); + + try (RepositoryConnection conn = repo1.getConnection()) { + conn.add(getClass().getResource("/testcases-sparql-1.0-w3c/data-r2/algebra/var-scope-join-1.ttl"), + null, null, conn.getValueFactory().createIRI("http://example/g1")); + } + try (RepositoryConnection conn = repo2.getConnection()) { + conn.add(getClass().getResource("/testcases-sparql-1.0-w3c/data-r2/algebra/var-scope-join-1.ttl"), + null, null, conn.getValueFactory().createIRI("http://example/g2")); + } + + String query = "PREFIX : SELECT * { graph :g1 {?X :name 'paul'} { graph :g2 {?Y :name 'george' . OPTIONAL { ?X :email ?Z } } } }"; + boolean hasResults; + try (RepositoryConnection conn = repoFed.getConnection()) { + TupleQuery tq = conn.prepareTupleQuery(QueryLanguage.SPARQL, query); + TupleQueryResult tqr = tq.evaluate(); + hasResults = tqr.hasNext(); + } + assertFalse(hasResults); + } +} diff --git a/compliance/sparql/src/test/resources/logback-test.xml b/compliance/sparql/src/test/resources/logback-test.xml new file mode 100644 index 000000000..4a6f17fbf --- /dev/null +++ b/compliance/sparql/src/test/resources/logback-test.xml @@ -0,0 +1,15 @@ + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %msg%n + + + + + + + + + From d6da3c7933df593b95a721c810c693a909109d60 Mon Sep 17 00:00:00 2001 From: Jeen Broekstra Date: Thu, 27 Dec 2018 12:00:18 +1100 Subject: [PATCH 13/54] GH-1230 renamed sail-model compliance tests to avoid conflict with rdf4j-model-compliance in rdf4j client repo Signed-off-by: Jeen Broekstra --- compliance/pom.xml | 2 +- compliance/{model => sail-model}/pom.xml | 8 ++++---- .../org/eclipse/rdf4j/model/SailModelNamespacesTest.java | 0 .../test/java/org/eclipse/rdf4j/model/SailModelTest.java | 0 .../src/test/resources/logback-test.xml | 0 5 files changed, 5 insertions(+), 5 deletions(-) rename compliance/{model => sail-model}/pom.xml (89%) rename compliance/{model => sail-model}/src/test/java/org/eclipse/rdf4j/model/SailModelNamespacesTest.java (100%) rename compliance/{model => sail-model}/src/test/java/org/eclipse/rdf4j/model/SailModelTest.java (100%) rename compliance/{model => sail-model}/src/test/resources/logback-test.xml (100%) diff --git a/compliance/pom.xml b/compliance/pom.xml index f28046b0b..ad417edbf 100644 --- a/compliance/pom.xml +++ b/compliance/pom.xml @@ -12,7 +12,7 @@ pom - model + sail-model sparql lucene elasticsearch diff --git a/compliance/model/pom.xml b/compliance/sail-model/pom.xml similarity index 89% rename from compliance/model/pom.xml rename to compliance/sail-model/pom.xml index 27b4dedaf..9ebe831de 100644 --- a/compliance/model/pom.xml +++ b/compliance/sail-model/pom.xml @@ -8,15 +8,15 @@ 2.5-SNAPSHOT - rdf4j-model-compliance + rdf4j-sail-model-compliance - RDF4J Model compliance test - Tests for RDF4J Model + RDF4J SAIL Model compliance test + Tests for RDF4J SaIL Model ${project.groupId} - rdf4j-runtime + rdf4j-sail-model ${project.version} diff --git a/compliance/model/src/test/java/org/eclipse/rdf4j/model/SailModelNamespacesTest.java b/compliance/sail-model/src/test/java/org/eclipse/rdf4j/model/SailModelNamespacesTest.java similarity index 100% rename from compliance/model/src/test/java/org/eclipse/rdf4j/model/SailModelNamespacesTest.java rename to compliance/sail-model/src/test/java/org/eclipse/rdf4j/model/SailModelNamespacesTest.java diff --git a/compliance/model/src/test/java/org/eclipse/rdf4j/model/SailModelTest.java b/compliance/sail-model/src/test/java/org/eclipse/rdf4j/model/SailModelTest.java similarity index 100% rename from compliance/model/src/test/java/org/eclipse/rdf4j/model/SailModelTest.java rename to compliance/sail-model/src/test/java/org/eclipse/rdf4j/model/SailModelTest.java diff --git a/compliance/model/src/test/resources/logback-test.xml b/compliance/sail-model/src/test/resources/logback-test.xml similarity index 100% rename from compliance/model/src/test/resources/logback-test.xml rename to compliance/sail-model/src/test/resources/logback-test.xml From 25aa4952c4886be44c909e241189714a1a02ca8f Mon Sep 17 00:00:00 2001 From: Jeen Broekstra Date: Thu, 27 Dec 2018 13:18:53 +1100 Subject: [PATCH 14/54] GH-1230 remove reference to obsolete http-compliance module Signed-off-by: Jeen Broekstra --- compliance/pom.xml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/compliance/pom.xml b/compliance/pom.xml index ad417edbf..24147a1aa 100644 --- a/compliance/pom.xml +++ b/compliance/pom.xml @@ -28,12 +28,6 @@ - - ${project.groupId} - rdf4j-http-compliance - ${project.version} - - ${project.groupId} rdf4j-rio-testsuite From 6e10859f4499063a0b5fa829aea3b49c6a313979 Mon Sep 17 00:00:00 2001 From: Jeen Broekstra Date: Thu, 27 Dec 2018 14:50:47 +1100 Subject: [PATCH 15/54] GH-1230 reorg compliance/testsuites Signed-off-by: Jeen Broekstra --- .../sail/EvaluationStrategyTest.java | 136 +++++++++++++ .../memory/MemoryEvaluationStrategyTest.java | 2 +- .../memory/MemoryOptimisticIsolationTest.java | 12 +- .../SpinMemoryRepositoryConnectionTest.java | 26 --- ...pinRDFSMemoryRepositoryConnectionTest.java | 27 --- .../NativeEvaluationStrategyTest.java | 2 +- .../NativeOptimisticIsolationTest.java | 12 +- .../sail/CustomGraphQueryInferencerTest.java | 187 ++++++++++++++++++ .../rdf4j/sail/memory/MemInferencingTest.java | 6 +- ...chingRDFSInferencerMemInferencingTest.java | 32 +-- .../nativerdf/NativeStoreInferencingTest.java | 7 +- 11 files changed, 371 insertions(+), 78 deletions(-) create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/EvaluationStrategyTest.java create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/sail/CustomGraphQueryInferencerTest.java diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/EvaluationStrategyTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/EvaluationStrategyTest.java new file mode 100644 index 000000000..6091c78bc --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/EvaluationStrategyTest.java @@ -0,0 +1,136 @@ +/******************************************************************************* + * Copyright (c) 2016 Eclipse RDF4J contributors. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.repository.sail; + +import static org.junit.Assert.assertEquals; + +import java.util.List; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.vocabulary.RDFS; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryResults; +import org.eclipse.rdf4j.query.algebra.evaluation.impl.ExtendedEvaluationStrategy; +import org.eclipse.rdf4j.query.algebra.evaluation.impl.ExtendedEvaluationStrategyFactory; +import org.eclipse.rdf4j.query.algebra.evaluation.impl.StrictEvaluationStrategy; +import org.eclipse.rdf4j.query.algebra.evaluation.impl.StrictEvaluationStrategyFactory; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.config.RepositoryConfig; +import org.eclipse.rdf4j.repository.config.RepositoryImplConfig; +import org.eclipse.rdf4j.repository.manager.RepositoryManager; +import org.eclipse.rdf4j.repository.manager.RepositoryProvider; +import org.eclipse.rdf4j.repository.sail.config.SailRepositoryConfig; +import org.eclipse.rdf4j.sail.base.config.BaseSailConfig; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +/** + * Test cases for behavior of {@link StrictEvaluationStrategy} and {@link ExtendedEvaluationStrategy} on base + * Sail implementations. + * + * @author Jeen Broekstra + */ +public abstract class EvaluationStrategyTest { + + @BeforeClass + public static void setUpClass() + throws Exception + { + System.setProperty("org.eclipse.rdf4j.repository.debug", "true"); + } + + @Rule + public TemporaryFolder tempDir = new TemporaryFolder(); + + private Repository strictRepo; + + private Repository extendedRepo; + + private RepositoryManager manager; + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() + throws Exception + { + manager = RepositoryProvider.getRepositoryManager(tempDir.newFolder()); + + BaseSailConfig strictStoreConfig = getBaseSailConfig(); + strictStoreConfig.setEvaluationStrategyFactoryClassName( + StrictEvaluationStrategyFactory.class.getName()); + + strictRepo = createRepo(strictStoreConfig, "test-strict"); + + BaseSailConfig extendedStoreConfig = getBaseSailConfig(); + extendedStoreConfig.setEvaluationStrategyFactoryClassName( + ExtendedEvaluationStrategyFactory.class.getName()); + + extendedRepo = createRepo(extendedStoreConfig, "test-extended"); + } + + private Repository createRepo(BaseSailConfig config, String id) { + RepositoryImplConfig ric = new SailRepositoryConfig(config); + manager.addRepositoryConfig(new RepositoryConfig(id, ric)); + + return manager.getRepository(id); + } + + @Test + public void testDatetimeSubtypesStrict() { + ValueFactory vf = strictRepo.getValueFactory(); + + try (RepositoryConnection conn = strictRepo.getConnection()) { + Literal l1 = vf.createLiteral("2009", XMLSchema.GYEAR); + Literal l2 = vf.createLiteral("2009-01", XMLSchema.GYEARMONTH); + IRI s1 = vf.createIRI("urn:s1"); + IRI s2 = vf.createIRI("urn:s2"); + conn.add(s1, RDFS.LABEL, l1); + conn.add(s2, RDFS.LABEL, l2); + + String query = "SELECT * WHERE { ?s rdfs:label ?l . FILTER(?l >= \"2008\"^^xsd:gYear) }"; + + List result = QueryResults.asList(conn.prepareTupleQuery(query).evaluate()); + assertEquals(1, result.size()); + } + } + + @Test + public void testDatetimeSubtypesExtended() { + ValueFactory vf = extendedRepo.getValueFactory(); + + try (RepositoryConnection conn = extendedRepo.getConnection()) { + Literal l1 = vf.createLiteral("2009", XMLSchema.GYEAR); + Literal l2 = vf.createLiteral("2009-01", XMLSchema.GYEARMONTH); + IRI s1 = vf.createIRI("urn:s1"); + IRI s2 = vf.createIRI("urn:s2"); + conn.add(s1, RDFS.LABEL, l1); + conn.add(s2, RDFS.LABEL, l2); + + String query = "SELECT * WHERE { ?s rdfs:label ?l . FILTER(?l >= \"2008\"^^xsd:gYear) }"; + + List result = QueryResults.asList(conn.prepareTupleQuery(query).evaluate()); + assertEquals(2, result.size()); + } + } + + /** + * Gets a configuration object for the base Sail that should be tested. + * + * @return a {@link BaseSailConfig}. + */ + protected abstract BaseSailConfig getBaseSailConfig(); +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemoryEvaluationStrategyTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemoryEvaluationStrategyTest.java index 998595a41..7f95e6626 100644 --- a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemoryEvaluationStrategyTest.java +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemoryEvaluationStrategyTest.java @@ -7,7 +7,7 @@ *******************************************************************************/ package org.eclipse.rdf4j.repository.sail.memory; -import org.eclipse.rdf4j.repository.EvaluationStrategyTest; +import org.eclipse.rdf4j.repository.sail.EvaluationStrategyTest; import org.eclipse.rdf4j.sail.base.config.BaseSailConfig; import org.eclipse.rdf4j.sail.memory.config.MemoryStoreConfig; diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemoryOptimisticIsolationTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemoryOptimisticIsolationTest.java index 44822eebb..a3a6aa336 100644 --- a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemoryOptimisticIsolationTest.java +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemoryOptimisticIsolationTest.java @@ -8,6 +8,9 @@ package org.eclipse.rdf4j.repository.sail.memory; import org.eclipse.rdf4j.repository.OptimisticIsolationTest; +import org.eclipse.rdf4j.repository.config.RepositoryImplConfig; +import org.eclipse.rdf4j.repository.sail.config.SailRepositoryConfig; +import org.eclipse.rdf4j.repository.sail.config.SailRepositoryFactory; import org.eclipse.rdf4j.sail.memory.config.MemoryStoreFactory; import org.junit.AfterClass; import org.junit.BeforeClass; @@ -19,13 +22,18 @@ public static void setUpClass() throws Exception { System.setProperty("org.eclipse.rdf4j.repository.debug", "true"); - setSailFactory(new MemoryStoreFactory()); + setRepositoryFactory(new SailRepositoryFactory() { + @Override + public RepositoryImplConfig getConfig() { + return new SailRepositoryConfig(new MemoryStoreFactory().getConfig()); + } + }); } @AfterClass public static void tearDown() throws Exception { - setSailFactory(null); + setRepositoryFactory(null); } } diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/SpinMemoryRepositoryConnectionTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/SpinMemoryRepositoryConnectionTest.java index d1ef11eef..7fa150c29 100644 --- a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/SpinMemoryRepositoryConnectionTest.java +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/SpinMemoryRepositoryConnectionTest.java @@ -35,30 +35,4 @@ protected Repository createRepository() return new SailRepository(new SpinSail(new MemoryStore())); } - @Ignore - @Test - @Override - public void testDefaultContext() - throws Exception - { - // ignore - } - - @Ignore - @Test - @Override - public void testDefaultInsertContext() - throws Exception - { - // ignore - } - - @Ignore - @Test - @Override - public void testExclusiveNullContext() - throws Exception - { - // ignore - } } \ No newline at end of file diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/SpinRDFSMemoryRepositoryConnectionTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/SpinRDFSMemoryRepositoryConnectionTest.java index b4e01669d..e85386d45 100644 --- a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/SpinRDFSMemoryRepositoryConnectionTest.java +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/SpinRDFSMemoryRepositoryConnectionTest.java @@ -37,31 +37,4 @@ protected Repository createRepository() return new SailRepository( new SpinSail(new ForwardChainingRDFSInferencer(new DedupingInferencer(new MemoryStore())))); } - - @Ignore - @Test - @Override - public void testDefaultContext() - throws Exception - { - // ignore - } - - @Ignore - @Test - @Override - public void testDefaultInsertContext() - throws Exception - { - // ignore - } - - @Ignore - @Test - @Override - public void testExclusiveNullContext() - throws Exception - { - // ignore - } } \ No newline at end of file diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeEvaluationStrategyTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeEvaluationStrategyTest.java index 16d639a5d..3b635bfff 100644 --- a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeEvaluationStrategyTest.java +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeEvaluationStrategyTest.java @@ -7,7 +7,7 @@ *******************************************************************************/ package org.eclipse.rdf4j.repository.sail.nativerdf; -import org.eclipse.rdf4j.repository.EvaluationStrategyTest; +import org.eclipse.rdf4j.repository.sail.EvaluationStrategyTest; import org.eclipse.rdf4j.sail.base.config.BaseSailConfig; import org.eclipse.rdf4j.sail.nativerdf.config.NativeStoreConfig; diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeOptimisticIsolationTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeOptimisticIsolationTest.java index 0c81ce7c4..1a947ada3 100644 --- a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeOptimisticIsolationTest.java +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeOptimisticIsolationTest.java @@ -8,6 +8,9 @@ package org.eclipse.rdf4j.repository.sail.nativerdf; import org.eclipse.rdf4j.repository.OptimisticIsolationTest; +import org.eclipse.rdf4j.repository.config.RepositoryImplConfig; +import org.eclipse.rdf4j.repository.sail.config.SailRepositoryConfig; +import org.eclipse.rdf4j.repository.sail.config.SailRepositoryFactory; import org.eclipse.rdf4j.sail.nativerdf.config.NativeStoreFactory; import org.junit.AfterClass; import org.junit.BeforeClass; @@ -18,13 +21,18 @@ public class NativeOptimisticIsolationTest extends OptimisticIsolationTest { public static void setUpClass() throws Exception { - setSailFactory(new NativeStoreFactory()); + setRepositoryFactory(new SailRepositoryFactory() { + @Override + public RepositoryImplConfig getConfig() { + return new SailRepositoryConfig(new NativeStoreFactory().getConfig()); + } + }); } @AfterClass public static void tearDown() throws Exception { - setSailFactory(null); + setRepositoryFactory(null); } } diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/CustomGraphQueryInferencerTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/CustomGraphQueryInferencerTest.java new file mode 100644 index 000000000..a82a10b4c --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/CustomGraphQueryInferencerTest.java @@ -0,0 +1,187 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.sail; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.IOException; +import java.io.StringReader; +import java.util.Arrays; +import java.util.Collection; + +import org.eclipse.rdf4j.common.io.ResourceUtil; +import org.eclipse.rdf4j.common.iteration.Iterations; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.query.MalformedQueryException; +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.query.UnsupportedQueryLanguageException; +import org.eclipse.rdf4j.query.UpdateExecutionException; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.rio.RDFFormat; +import org.eclipse.rdf4j.rio.RDFParseException; +import org.eclipse.rdf4j.sail.inferencer.fc.CustomGraphQueryInferencer; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +@RunWith(Parameterized.class) +public abstract class CustomGraphQueryInferencerTest { + + @BeforeClass + public static void setUpClass() + throws Exception + { + System.setProperty("org.eclipse.rdf4j.repository.debug", "true"); + } + + protected static class Expectation { + + private final int initialCount, countAfterRemove, subjCount, predCount, objCount; + + public Expectation(int initialCount, int countAfterRemove, int subjCount, int predCount, + int objCount) + { + this.initialCount = initialCount; + this.countAfterRemove = countAfterRemove; + this.subjCount = subjCount; + this.predCount = predCount; + this.objCount = objCount; + } + } + + private static final String TEST_DIR_PREFIX = "/testcases/custom-query-inferencing/"; + + private static final String BASE = "http://foo.org/bar#"; + + private static final String PREDICATE = "predicate"; + + @Parameters(name = "{0}") + public static final Collection parameters() { + Expectation predExpect = new Expectation(8, 2, 0, 2, 0); + return Arrays.asList(new Object[][] { + { PREDICATE, predExpect, QueryLanguage.SPARQL }, + { "resource", new Expectation(4, 2, 2, 0, 2), QueryLanguage.SPARQL }, + { "predicate-serql", predExpect, QueryLanguage.SERQL } }); + } + + private String initial; + + private String delete; + + private String resourceFolder; + + private Expectation testData; + + private QueryLanguage language; + + protected void runTest(final CustomGraphQueryInferencer inferencer) + throws RepositoryException, RDFParseException, IOException, MalformedQueryException, + UpdateExecutionException + { + // Initialize + Repository sail = new SailRepository(inferencer); + sail.initialize(); + RepositoryConnection connection = sail.getConnection(); + try { + connection.begin(); + connection.clear(); + connection.add(new StringReader(initial), BASE, RDFFormat.TURTLE); + + // Test initial inferencer state + Collection watchPredicates = inferencer.getWatchPredicates(); + assertThat(watchPredicates).hasSize(testData.predCount); + Collection watchObjects = inferencer.getWatchObjects(); + assertThat(watchObjects).hasSize(testData.objCount); + Collection watchSubjects = inferencer.getWatchSubjects(); + assertThat(watchSubjects).hasSize(testData.subjCount); + ValueFactory factory = connection.getValueFactory(); + if (resourceFolder.startsWith(PREDICATE)) { + assertThat(watchPredicates.contains(factory.createIRI(BASE, "brotherOf"))).isTrue(); + assertThat(watchPredicates.contains(factory.createIRI(BASE, "parentOf"))).isTrue(); + } + else { + IRI bob = factory.createIRI(BASE, "Bob"); + IRI alice = factory.createIRI(BASE, "Alice"); + assertThat(watchSubjects).contains(bob, alice); + assertThat(watchObjects).contains(bob, alice); + } + + // Test initial inferencing results + assertThat(Iterations.asSet(connection.getStatements(null, null, null, true))) + .hasSize(testData.initialCount); + + // Test results after removing some statements + connection.prepareUpdate(QueryLanguage.SPARQL, delete).execute(); + assertThat(Iterations.asSet(connection.getStatements(null, null, null, true))) + .hasSize(testData.countAfterRemove); + + // Tidy up. Storage gets re-used for subsequent tests, so must clear here, + // in order to properly clear out any inferred statements. + connection.clear(); + connection.commit(); + } + finally { + connection.close(); + } + sail.shutDown(); + } + + public CustomGraphQueryInferencerTest(String resourceFolder, Expectation testData, + QueryLanguage language) + { + this.resourceFolder = resourceFolder; + this.testData = testData; + this.language = language; + } + + protected CustomGraphQueryInferencer createRepository(boolean withMatchQuery) + throws IOException, MalformedQueryException, UnsupportedQueryLanguageException, RepositoryException, + SailException, RDFParseException + { + String testFolder = TEST_DIR_PREFIX + resourceFolder; + String rule = ResourceUtil.getString(testFolder + "/rule.rq"); + String match = withMatchQuery ? ResourceUtil.getString(testFolder + "/match.rq") : ""; + initial = ResourceUtil.getString(testFolder + "/initial.ttl"); + delete = ResourceUtil.getString(testFolder + "/delete.ru"); + + NotifyingSail store = newSail(); + + return new CustomGraphQueryInferencer(store, language, rule, match); + } + + /** + * Gets an instance of the Sail that should be tested. The returned repository must not be initialized. + * + * @return an uninitialized NotifyingSail. + */ + protected abstract NotifyingSail newSail(); + + @Test + public void testCustomQueryInference() + throws RepositoryException, RDFParseException, MalformedQueryException, UpdateExecutionException, + IOException, UnsupportedQueryLanguageException, SailException + { + runTest(createRepository(true)); + } + + @Test + public void testCustomQueryInferenceImplicitMatcher() + throws RepositoryException, RDFParseException, MalformedQueryException, UpdateExecutionException, + IOException, UnsupportedQueryLanguageException, SailException + { + runTest(createRepository(false)); + } + +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/MemInferencingTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/MemInferencingTest.java index 632895fe6..78e98488d 100644 --- a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/MemInferencingTest.java +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/MemInferencingTest.java @@ -7,6 +7,8 @@ *******************************************************************************/ package org.eclipse.rdf4j.sail.memory; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.sail.SailRepository; import org.eclipse.rdf4j.sail.InferencingTest; import org.eclipse.rdf4j.sail.Sail; import org.eclipse.rdf4j.sail.inferencer.fc.ForwardChainingRDFSInferencer; @@ -14,8 +16,8 @@ public class MemInferencingTest extends InferencingTest { @Override - protected Sail createSail() { + protected Repository createRepository() { Sail sailStack = new ForwardChainingRDFSInferencer(new MemoryStore()); - return sailStack; + return new SailRepository(sailStack); } } diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/SchemaCachingRDFSInferencerMemInferencingTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/SchemaCachingRDFSInferencerMemInferencingTest.java index d9908a543..e46972ce9 100644 --- a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/SchemaCachingRDFSInferencerMemInferencingTest.java +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/SchemaCachingRDFSInferencerMemInferencingTest.java @@ -27,15 +27,17 @@ public class SchemaCachingRDFSInferencerMemInferencingTest extends InferencingTest { + private SchemaCachingRDFSInferencer sailStack; + @Override - protected Sail createSail() { - Sail sailStack = new SchemaCachingRDFSInferencer(new MemoryStore(), true); - return sailStack; + protected Repository createRepository() { + sailStack = new SchemaCachingRDFSInferencer(new MemoryStore(), true); + return new SailRepository(sailStack); } @Test public void testBlankNodePredicateInference() { - Repository sailRepository = new SailRepository(createSail()); + Repository sailRepository = createRepository(); sailRepository.initialize(); ValueFactory vf = sailRepository.getValueFactory(); @@ -43,8 +45,8 @@ public void testBlankNodePredicateInference() { BNode bNode = vf.createBNode(); connection.add(vf.createStatement(vf.createIRI("http://a"), RDFS.SUBPROPERTYOF, bNode)); // 1 connection.add(vf.createStatement(bNode, RDFS.DOMAIN, vf.createIRI("http://c"))); // 2 - connection.add(vf.createStatement(vf.createIRI("http://d"), vf.createIRI("http://a"), - vf.createIRI("http://e"))); // 3 + connection.add( + vf.createStatement(vf.createIRI("http://d"), vf.createIRI("http://a"), vf.createIRI("http://e"))); // 3 } try (RepositoryConnection connection = sailRepository.getConnection()) { @@ -58,9 +60,11 @@ public void testBlankNodePredicateInference() { @Test public void testRollback() - throws NoSuchMethodException, InvocationTargetException, IllegalAccessException + throws NoSuchMethodException, + InvocationTargetException, + IllegalAccessException { - Repository sailRepository = new SailRepository(createSail()); + Repository sailRepository = createRepository(); sailRepository.initialize(); ValueFactory vf = sailRepository.getValueFactory(); @@ -109,10 +113,11 @@ public void testRollback() @Test public void testFastInstantiate() - throws NoSuchMethodException, InvocationTargetException, IllegalAccessException + throws NoSuchMethodException, + InvocationTargetException, + IllegalAccessException { - Sail sail = createSail(); - Repository sailRepository = new SailRepository(sail); + Repository sailRepository = createRepository(); sailRepository.initialize(); ValueFactory vf = sailRepository.getValueFactory(); @@ -126,9 +131,8 @@ public void testFastInstantiate() connection.add(vf.createStatement(A, RDFS.SUBCLASSOF, C)); } - SailRepository sailRepository1 = new SailRepository( - SchemaCachingRDFSInferencer.fastInstantiateFrom( - (SchemaCachingRDFSInferencer)sail, new MemoryStore())); + SailRepository sailRepository1 = new SailRepository(SchemaCachingRDFSInferencer.fastInstantiateFrom( + (SchemaCachingRDFSInferencer)sailStack, new MemoryStore())); sailRepository1.initialize(); try (RepositoryConnection connection = sailRepository1.getConnection()) { diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreInferencingTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreInferencingTest.java index 9d7859de7..e8f537bb7 100644 --- a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreInferencingTest.java +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreInferencingTest.java @@ -9,9 +9,10 @@ import java.io.IOException; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.sail.SailRepository; import org.eclipse.rdf4j.sail.InferencingTest; import org.eclipse.rdf4j.sail.NotifyingSail; -import org.eclipse.rdf4j.sail.Sail; import org.eclipse.rdf4j.sail.inferencer.fc.ForwardChainingRDFSInferencer; import org.junit.Rule; import org.junit.rules.TemporaryFolder; @@ -22,11 +23,11 @@ public class NativeStoreInferencingTest extends InferencingTest { public TemporaryFolder tempDir = new TemporaryFolder(); @Override - protected Sail createSail() { + protected Repository createRepository() { try { NotifyingSail sailStack = new NativeStore(tempDir.newFolder("nativestore"), "spoc,posc"); sailStack = new ForwardChainingRDFSInferencer(sailStack); - return sailStack; + return new SailRepository(sailStack); } catch (IOException e) { throw new AssertionError(e); From 1454990fdbd2ef42daa874e64983e813bd0ddecc Mon Sep 17 00:00:00 2001 From: Jerven Bolleman Date: Sun, 9 Dec 2018 08:56:39 +0100 Subject: [PATCH 16/54] Fixes #1199 Replace some REGEX calls that can be expressed as string functions This is a trivial optimizer which can help public endpoints where cheaper string functions (that are easier to further optimize) instead of relatively expensive regex calls. (even if the regex is otherwise trivial in runtime costs) This is turned on per default Signed-off-by: Jerven Bolleman --- .../impl/RegexAsStringFunctionOptimizer.java | 116 +++++++++++++++ .../RegexAsStringFunctionOptimizierTest.java | 133 ++++++++++++++++++ .../rdf4j/sail/base/SailSourceConnection.java | 3 + 3 files changed, 252 insertions(+) create mode 100644 evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/RegexAsStringFunctionOptimizer.java create mode 100644 evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/RegexAsStringFunctionOptimizierTest.java diff --git a/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/RegexAsStringFunctionOptimizer.java b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/RegexAsStringFunctionOptimizer.java new file mode 100644 index 000000000..ee9c7edce --- /dev/null +++ b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/RegexAsStringFunctionOptimizer.java @@ -0,0 +1,116 @@ +/******************************************************************************* + * Copyright (c) 2018 Eclipse RDF4J contributors. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.impl; + +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.vocabulary.FN; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.Dataset; +import org.eclipse.rdf4j.query.algebra.Compare; +import org.eclipse.rdf4j.query.algebra.FunctionCall; +import org.eclipse.rdf4j.query.algebra.Regex; +import org.eclipse.rdf4j.query.algebra.TupleExpr; +import org.eclipse.rdf4j.query.algebra.ValueConstant; +import org.eclipse.rdf4j.query.algebra.ValueExpr; +import org.eclipse.rdf4j.query.algebra.Var; +import org.eclipse.rdf4j.query.algebra.evaluation.QueryOptimizer; +import org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor; + +/** + * A query optimizer that replaces REGEX with {@link FunctionCall}s that are + * equivalent operators + * + * @author Jerven Bolleman + */ +public class RegexAsStringFunctionOptimizer implements QueryOptimizer { + + private final ValueFactory vf; + + public RegexAsStringFunctionOptimizer(ValueFactory vf) { + this.vf = vf; + } + + /** + * Applies generally applicable optimizations to the supplied query: + * variable assignments are inlined. + */ + public void optimize(TupleExpr tupleExpr, Dataset dataset, BindingSet bindings) { + tupleExpr.visit(new RegexAsStringFunctionVisitor()); + } + + protected class RegexAsStringFunctionVisitor + extends AbstractQueryModelVisitor { + + @Override + public void meet(Regex node) { + final ValueExpr flagsArg = node.getFlagsArg(); + if (flagsArg == null || flagsArg.toString().isEmpty()) { + //if we have no flags then we can not be in case insensitive mode + if (node.getPatternArg() instanceof ValueConstant && node.getArg() instanceof Var) { + ValueConstant vc = (ValueConstant) node.getPatternArg(); + String regex = vc.getValue().stringValue(); + final boolean anchoredAtStart = regex.startsWith("^"); + final boolean anchoredAtEnd = regex.endsWith("$"); + + if (anchoredAtStart && anchoredAtEnd) { + equalsCandidate(node, regex); + } else if (anchoredAtStart) { + strstartsCandidate(node, regex); + } else if (anchoredAtEnd) { + strendsCandidate(node, regex); + } else { + containsCandidate(node, regex); + } + } + } + super.meet(node); + } + + private void containsCandidate(Regex node, String potential) { + if (plain(potential)) { + node.replaceWith(new FunctionCall(FN.CONTAINS.stringValue(), node.getArg(), node.getPatternArg())); + } + } + + //If we have one of these chars it is likely to be an real regex. + //If we are willing to peek in a Pattern object we could be sure + //this seems a valid start with no regexes marked as simple strings + private boolean plain(String potential) { + for (int not : new char[]{'?', '*', '+', '{', '|', '\\', '.', '[', ']', '&', '(',')'}) { + if (potential.indexOf(not) != -1) { + return false; + } + } + return true; + } + + private void strendsCandidate(Regex node, String regex) { + final String potential = regex.substring(0, regex.length() - 1); + if (plain(potential)) { + ValueConstant vc = new ValueConstant(vf.createLiteral(potential)); + node.replaceWith(new FunctionCall(FN.ENDS_WITH.stringValue(), node.getArg(), vc)); + } + } + + private void strstartsCandidate(Regex node, String regex) { + final String potential = regex.substring(1, regex.length()); + if (plain(potential)) { + ValueConstant vc = new ValueConstant(vf.createLiteral(potential)); + node.replaceWith(new FunctionCall(FN.STARTS_WITH.stringValue(), node.getArg(), vc)); + } + } + + private void equalsCandidate(Regex node, String regex) { + final String potential = regex.substring(1, regex.length() - 1); + if (plain(potential)) { + ValueConstant vc = new ValueConstant(vf.createLiteral(potential)); + node.replaceWith(new Compare(node.getArg(), vc, Compare.CompareOp.EQ)); + } + } + } +} diff --git a/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/RegexAsStringFunctionOptimizierTest.java b/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/RegexAsStringFunctionOptimizierTest.java new file mode 100644 index 000000000..c0cb63068 --- /dev/null +++ b/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/RegexAsStringFunctionOptimizierTest.java @@ -0,0 +1,133 @@ +/** ***************************************************************************** + * Copyright (c) 2018 Eclipse RDF4J contributors. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + ****************************************************************************** */ + +package org.eclipse.rdf4j.query.algebra.evaluation.impl; + +import static org.junit.Assert.assertEquals; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.query.MalformedQueryException; +import org.eclipse.rdf4j.query.QueryLanguage; +import org.eclipse.rdf4j.query.UnsupportedQueryLanguageException; +import org.eclipse.rdf4j.query.algebra.QueryModelNode; +import org.eclipse.rdf4j.query.algebra.QueryRoot; +import org.eclipse.rdf4j.query.algebra.evaluation.QueryOptimizer; +import org.eclipse.rdf4j.query.parser.ParsedQuery; +import org.eclipse.rdf4j.query.parser.QueryParserUtil; +import org.junit.Test; + +/** + * Tests to make sure the RegexAsStringFunctionOptomizer behaves. + * + * @author Jerven Bolleman + */ +public class RegexAsStringFunctionOptimizierTest { + + @Test + public void testEqualsTerm() + throws MalformedQueryException { + String unoptimizedQuery + = "SELECT ?o WHERE {?s ?p ?o . FILTER(REGEX(?o, '^a$'))}"; + String optimizedQuery = "SELECT ?o WHERE {?s ?p ?o . FILTER(?o = 'a')}"; + testOptimizer(optimizedQuery, unoptimizedQuery); + } + + @Test + public void testStrStartsTerm() + throws MalformedQueryException { + String unoptimizedQuery = "SELECT ?o WHERE {?s ?p ?o . FILTER(REGEX(?o, '^a'))}"; + String optimizedQuery = "SELECT ?o WHERE {?s ?p ?o . FILTER(strStarts(?o, 'a'))}"; + + testOptimizer(optimizedQuery, unoptimizedQuery); + } + + @Test + public void testStrEndsTerm() + throws MalformedQueryException { + String unoptimizedQuery = "SELECT ?o WHERE {?s ?p ?o . FILTER(REGEX(?o, 'a$'))}"; + String optimizedQuery = "SELECT ?o WHERE {?s ?p ?o . FILTER(strEnds(?o, 'a'))}"; + + testOptimizer(optimizedQuery, unoptimizedQuery); + } + + @Test + public void testContains() + throws MalformedQueryException { + String unoptimizedQuery + = "SELECT ?o WHERE {?s ?p ?o . FILTER(REGEX(?o, 'a'))}"; + String optimizedQuery = "SELECT ?o WHERE {?s ?p ?o . FILTER(contains(?o, 'a'))}"; + testOptimizer(optimizedQuery, unoptimizedQuery); + } + + @Test + public void testContainsWithDollar() + throws MalformedQueryException { + String unoptimizedQuery + = "SELECT ?o WHERE {?s ?p ?o . FILTER(REGEX($o, 'a'))}"; + String optimizedQuery = "SELECT ?o WHERE {?s ?p ?o . FILTER(contains(?o, 'a'))}"; + testOptimizer(optimizedQuery, unoptimizedQuery); + } + + @Test + public void testContainsWithStrangeSpacingAndCaptials() + throws MalformedQueryException { + String unoptimizedQuery + = "SELECT ?o WHERE {?s ?p ?o . FILTER(REgeX( $o , \"a\" ))}"; + String optimizedQuery = "SELECT ?o WHERE {?s ?p ?o . FILTER(contains(?o, 'a'))}"; + testOptimizer(optimizedQuery, unoptimizedQuery); + } + + @Test + public void testNotContains() + throws MalformedQueryException { + String unoptimizedQuery = "SELECT ?o WHERE {?s ?p ?o . FILTER(REGEX(?o, 'a', 'i'))}"; + + testOptimizer(unoptimizedQuery, unoptimizedQuery); + } + + @Test + public void testRealRegexDoesNotRedirect() { + + String unoptimizedQuery = "SELECT ?o WHERE {?s ?p ?o . FILTER(REGEX(?o, 'a*'))}"; + + testOptimizer(unoptimizedQuery, unoptimizedQuery); + unoptimizedQuery = "SELECT ?o WHERE {?s ?p ?o . FILTER(REGEX(?o, 'a+'))}"; + + testOptimizer(unoptimizedQuery, unoptimizedQuery); + unoptimizedQuery = "SELECT ?o WHERE {?s ?p ?o . FILTER(REGEX(?o, 'a[abc]'))}"; + + testOptimizer(unoptimizedQuery, unoptimizedQuery); + unoptimizedQuery = "SELECT ?o WHERE {?s ?p ?o . FILTER(REGEX(?o, 'a&&b'))}"; + + testOptimizer(unoptimizedQuery, unoptimizedQuery); + } + + @Test + public void testContainsAsIs() + throws MalformedQueryException { + String unoptimizedQuery = "SELECT ?o WHERE {?s ?p ?o . FILTER(contains(?o, 'a*'))}"; + + testOptimizer(unoptimizedQuery, unoptimizedQuery); + } + + private void testOptimizer(String expectedQuery, String actualQuery) + throws MalformedQueryException, UnsupportedQueryLanguageException { + ParsedQuery pq = QueryParserUtil.parseQuery(QueryLanguage.SPARQL, actualQuery, null); + QueryOptimizer opt = new RegexAsStringFunctionOptimizer(SimpleValueFactory.getInstance()); + QueryRoot optRoot = new QueryRoot(pq.getTupleExpr()); + opt.optimize(optRoot, null, null); + + ParsedQuery expectedParsedQuery = QueryParserUtil.parseQuery(QueryLanguage.SPARQL, expectedQuery, + null); + QueryRoot root = new QueryRoot(expectedParsedQuery.getTupleExpr()); + assertQueryModelTrees(root, optRoot); + } + + private void assertQueryModelTrees(QueryModelNode expected, QueryModelNode actual) { + assertEquals(expected, actual); + } +} diff --git a/sail-base/src/main/java/org/eclipse/rdf4j/sail/base/SailSourceConnection.java b/sail-base/src/main/java/org/eclipse/rdf4j/sail/base/SailSourceConnection.java index 8802748f6..142998f2c 100644 --- a/sail-base/src/main/java/org/eclipse/rdf4j/sail/base/SailSourceConnection.java +++ b/sail-base/src/main/java/org/eclipse/rdf4j/sail/base/SailSourceConnection.java @@ -40,6 +40,7 @@ import org.eclipse.rdf4j.query.algebra.evaluation.impl.OrderLimitOptimizer; import org.eclipse.rdf4j.query.algebra.evaluation.impl.QueryJoinOptimizer; import org.eclipse.rdf4j.query.algebra.evaluation.impl.QueryModelNormalizer; +import org.eclipse.rdf4j.query.algebra.evaluation.impl.RegexAsStringFunctionOptimizer; import org.eclipse.rdf4j.query.algebra.evaluation.impl.SameTermFilterOptimizer; import org.eclipse.rdf4j.query.algebra.evaluation.impl.StrictEvaluationStrategy; import org.eclipse.rdf4j.query.algebra.evaluation.impl.StrictEvaluationStrategyFactory; @@ -240,6 +241,8 @@ protected CloseableIteration eva new BindingAssigner().optimize(tupleExpr, dataset, bindings); new ConstantOptimizer(strategy).optimize(tupleExpr, dataset, bindings); + //The regex as string function optimizer works better if the constants are resolved + new RegexAsStringFunctionOptimizer(vf).optimize(tupleExpr, dataset, bindings); new CompareOptimizer().optimize(tupleExpr, dataset, bindings); new ConjunctiveConstraintSplitter().optimize(tupleExpr, dataset, bindings); new DisjunctiveConstraintOptimizer().optimize(tupleExpr, dataset, bindings); From 09ba537ad1236aa3e78682ea66d9fb28119bfc17 Mon Sep 17 00:00:00 2001 From: Jeen Broekstra Date: Sun, 30 Dec 2018 11:51:12 +1100 Subject: [PATCH 17/54] GH-1225 marked inferencer deprecated Signed-off-by: Jeen Broekstra --- .../sail/inferencer/fc/ForwardChainingRDFSInferencer.java | 4 ++++ .../fc/ForwardChainingRDFSInferencerConnection.java | 4 ++++ .../fc/config/ForwardChainingRDFSInferencerConfig.java | 1 + .../fc/config/ForwardChainingRDFSInferencerFactory.java | 1 + 4 files changed, 10 insertions(+) diff --git a/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/ForwardChainingRDFSInferencer.java b/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/ForwardChainingRDFSInferencer.java index 647117148..c867e2023 100644 --- a/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/ForwardChainingRDFSInferencer.java +++ b/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/ForwardChainingRDFSInferencer.java @@ -17,7 +17,11 @@ * RDF Semantics Recommendation (10 February * 2004). This inferencer can be used to add RDF Schema semantics to any Sail that returns * {@link InferencerConnection}s from their {@link Sail#getConnection()} method. + * + * @deprecated since 2.5. This inferencer implementation will be phased out. Consider switching to the + * {@link SchemaCachingRDFSInferencer} instead. */ +@Deprecated public class ForwardChainingRDFSInferencer extends AbstractForwardChainingInferencer { /*--------------* * Constructors * diff --git a/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/ForwardChainingRDFSInferencerConnection.java b/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/ForwardChainingRDFSInferencerConnection.java index 1e9fb185f..d703f8f78 100644 --- a/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/ForwardChainingRDFSInferencerConnection.java +++ b/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/ForwardChainingRDFSInferencerConnection.java @@ -26,7 +26,11 @@ * RDF Semantics Recommendation (10 February * 2004). This inferencer can be used to add RDF Schema semantics to any Sail that returns * {@link InferencerConnection}s from their {@link Sail#getConnection()} method. + * + * @deprecated since 2.5. This inferencer implementation will be phased out. Consider switching to the + * {@link SchemaCachingRDFSInferencer} instead. */ +@Deprecated class ForwardChainingRDFSInferencerConnection extends AbstractForwardChainingInferencerConnection { /*-----------* * Variables * diff --git a/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/config/ForwardChainingRDFSInferencerConfig.java b/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/config/ForwardChainingRDFSInferencerConfig.java index 0c73b4c79..890cb0f34 100644 --- a/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/config/ForwardChainingRDFSInferencerConfig.java +++ b/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/config/ForwardChainingRDFSInferencerConfig.java @@ -13,6 +13,7 @@ /** * @author Arjohn Kampman */ +@Deprecated public class ForwardChainingRDFSInferencerConfig extends AbstractDelegatingSailImplConfig { public ForwardChainingRDFSInferencerConfig() { diff --git a/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/config/ForwardChainingRDFSInferencerFactory.java b/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/config/ForwardChainingRDFSInferencerFactory.java index ba67b0010..33c956be5 100644 --- a/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/config/ForwardChainingRDFSInferencerFactory.java +++ b/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/config/ForwardChainingRDFSInferencerFactory.java @@ -18,6 +18,7 @@ * * @author Arjohn Kampman */ +@Deprecated public class ForwardChainingRDFSInferencerFactory implements SailFactory { /** From 93db00dd00826c24c6576278fb526d47a87ee521 Mon Sep 17 00:00:00 2001 From: Jeen Broekstra Date: Tue, 1 Jan 2019 13:55:41 +1100 Subject: [PATCH 18/54] GH-1230 fix compile failure due to merge Signed-off-by: Jeen Broekstra --- .../solr/solr/cores/embedded/conf/schema.xml | 81 ------------------- ...FSchemaMemoryRepositoryConnectionTest.java | 28 ------- ...erencerNativeRepositoryConnectionTest.java | 30 ------- ...chingRDFSInferencerMemInferencingTest.java | 16 ++-- 4 files changed, 7 insertions(+), 148 deletions(-) delete mode 100644 compliance/solr/solr/cores/embedded/conf/schema.xml diff --git a/compliance/solr/solr/cores/embedded/conf/schema.xml b/compliance/solr/solr/cores/embedded/conf/schema.xml deleted file mode 100644 index c66ef5175..000000000 --- a/compliance/solr/solr/cores/embedded/conf/schema.xml +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - - - - - - - - - - id - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/SchemaCachingRDFSInferencerRDFSchemaMemoryRepositoryConnectionTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/SchemaCachingRDFSInferencerRDFSchemaMemoryRepositoryConnectionTest.java index 89eb71df5..4ce43ace4 100644 --- a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/SchemaCachingRDFSInferencerRDFSchemaMemoryRepositoryConnectionTest.java +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/SchemaCachingRDFSInferencerRDFSchemaMemoryRepositoryConnectionTest.java @@ -43,34 +43,6 @@ protected Repository createRepository() { } - @Ignore - @Test - @Override - public void testDefaultContext() - throws Exception - { - // ignore - } - - @Ignore - @Test - @Override - public void testDefaultInsertContext() - throws Exception - { - // ignore - } - - @Ignore - @Test - @Override - public void testExclusiveNullContext() - throws Exception - { - // ignore - } - - @Override @Test @Ignore diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/SchemaCachingRDFSInferencerNativeRepositoryConnectionTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/SchemaCachingRDFSInferencerNativeRepositoryConnectionTest.java index 4077750b4..5c6c9d075 100644 --- a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/SchemaCachingRDFSInferencerNativeRepositoryConnectionTest.java +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/SchemaCachingRDFSInferencerNativeRepositoryConnectionTest.java @@ -65,36 +65,6 @@ public void tearDown() } } - - - @Ignore - @Test - @Override - public void testDefaultContext() - throws Exception - { - // ignore - } - - @Ignore - @Test - @Override - public void testDefaultInsertContext() - throws Exception - { - // ignore - } - - @Ignore - @Test - @Override - public void testExclusiveNullContext() - throws Exception - { - // ignore - } - - @Override @Test @Ignore diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/SchemaCachingRDFSInferencerMemInferencingTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/SchemaCachingRDFSInferencerMemInferencingTest.java index f83fc7af3..e6aa61bb5 100644 --- a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/SchemaCachingRDFSInferencerMemInferencingTest.java +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/SchemaCachingRDFSInferencerMemInferencingTest.java @@ -7,6 +7,11 @@ *******************************************************************************/ package org.eclipse.rdf4j.sail.memory; +import static junit.framework.TestCase.assertFalse; +import static junit.framework.TestCase.assertTrue; + +import java.lang.reflect.InvocationTargetException; + import org.eclipse.rdf4j.model.BNode; import org.eclipse.rdf4j.model.IRI; import org.eclipse.rdf4j.model.ValueFactory; @@ -16,20 +21,13 @@ import org.eclipse.rdf4j.repository.RepositoryConnection; import org.eclipse.rdf4j.repository.sail.SailRepository; import org.eclipse.rdf4j.sail.InferencingTest; -import org.eclipse.rdf4j.sail.Sail; import org.eclipse.rdf4j.sail.inferencer.fc.SchemaCachingRDFSInferencer; import org.junit.Test; -import java.lang.reflect.InvocationTargetException; - -import static junit.framework.TestCase.assertFalse; -import static junit.framework.TestCase.assertTrue; - public class SchemaCachingRDFSInferencerMemInferencingTest extends InferencingTest { - private SchemaCachingRDFSInferencer sailStack; - @Override + protected Repository createRepository() { SchemaCachingRDFSInferencer sailStack = new SchemaCachingRDFSInferencer(new MemoryStore(), true); sailStack.setAddInferredStatementsToDefaultContext(false); return new SailRepository(sailStack); @@ -132,7 +130,7 @@ public void testFastInstantiate() } SailRepository sailRepository1 = new SailRepository(SchemaCachingRDFSInferencer.fastInstantiateFrom( - (SchemaCachingRDFSInferencer)sailStack, new MemoryStore())); + (SchemaCachingRDFSInferencer)((SailRepository)sailRepository).getSail(), new MemoryStore())); sailRepository1.initialize(); try (RepositoryConnection connection = sailRepository1.getConnection()) { From 1a082f5ccce5cc991e20defe1e2be0113774d4a0 Mon Sep 17 00:00:00 2001 From: Jeen Broekstra Date: Sat, 5 Jan 2019 14:16:13 +1100 Subject: [PATCH 19/54] eclipse/rdf4j#1226 SPI/Factory for Schema Caching Inferencer Signed-off-by: Jeen Broekstra --- .../fc/SchemaCachingRDFSInferencer.java | 10 +++- .../SchemaCachingRDFSInferencerConfig.java | 28 ++++++++++ .../SchemaCachingRDFSInferencerFactory.java | 54 +++++++++++++++++++ .../org.eclipse.rdf4j.sail.config.SailFactory | 1 + 4 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/config/SchemaCachingRDFSInferencerConfig.java create mode 100644 inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/config/SchemaCachingRDFSInferencerFactory.java diff --git a/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/SchemaCachingRDFSInferencer.java b/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/SchemaCachingRDFSInferencer.java index c8cc65282..87c5090d3 100644 --- a/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/SchemaCachingRDFSInferencer.java +++ b/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/SchemaCachingRDFSInferencer.java @@ -44,7 +44,7 @@ *

*

* This reasoner is not a rule based reasoner and will be up to 80x faster than the - * ForwardChainingRDFSInferencer, as well as being more complete. + * {@link ForwardChainingRDFSInferencer}, as well as being more complete. *

*

* The sail puts no limitations on isolation level for read transactions, however all write/delete/update @@ -100,6 +100,14 @@ public class SchemaCachingRDFSInferencer extends NotifyingSailWrapper { // THIS BEHAVIOUR WILL BE SWITCHED ON THE NEXT MAJOR RELEASE private boolean addInferredStatementsToDefaultContext = true; + /** + * Instantiate a new SchemaCachingRDFSInferencer + */ + public SchemaCachingRDFSInferencer() { + super(); + schema = null; + } + /** * Instantiate a SchemaCachingRDFSInferencer. * diff --git a/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/config/SchemaCachingRDFSInferencerConfig.java b/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/config/SchemaCachingRDFSInferencerConfig.java new file mode 100644 index 000000000..5e0bbf20c --- /dev/null +++ b/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/config/SchemaCachingRDFSInferencerConfig.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2019 Eclipse RDF4J contributors. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.sail.inferencer.fc.config; + +import org.eclipse.rdf4j.sail.config.AbstractDelegatingSailImplConfig; +import org.eclipse.rdf4j.sail.config.SailImplConfig; +import org.eclipse.rdf4j.sail.inferencer.fc.SchemaCachingRDFSInferencer; + +/** + * {@link SailImplConfig} for the {@link SchemaCachingRDFSInferencer} + * + * @author Jeen Broekstra + */ +public class SchemaCachingRDFSInferencerConfig extends AbstractDelegatingSailImplConfig { + + public SchemaCachingRDFSInferencerConfig() { + super(SchemaCachingRDFSInferencerFactory.SAIL_TYPE); + } + + public SchemaCachingRDFSInferencerConfig(SailImplConfig delegate) { + super(SchemaCachingRDFSInferencerFactory.SAIL_TYPE, delegate); + } +} diff --git a/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/config/SchemaCachingRDFSInferencerFactory.java b/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/config/SchemaCachingRDFSInferencerFactory.java new file mode 100644 index 000000000..6e6c7af74 --- /dev/null +++ b/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/config/SchemaCachingRDFSInferencerFactory.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2019 Eclipse RDF4J contributors. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.sail.inferencer.fc.config; + +import org.eclipse.rdf4j.sail.Sail; +import org.eclipse.rdf4j.sail.config.SailConfigException; +import org.eclipse.rdf4j.sail.config.SailFactory; +import org.eclipse.rdf4j.sail.config.SailImplConfig; +import org.eclipse.rdf4j.sail.inferencer.fc.ForwardChainingRDFSInferencer; +import org.eclipse.rdf4j.sail.inferencer.fc.SchemaCachingRDFSInferencer; + +/** + * A {@link SailFactory} that creates {@link SchemaCachingRDFSInferencer}s based on RDF configuration data. + * + * @author Jeen Broekstra + */ +public class SchemaCachingRDFSInferencerFactory implements SailFactory { + + /** + * The type of repositories that are created by this factory. + * + * @see SailFactory#getSailType() + */ + public static final String SAIL_TYPE = "rdf4j:SchemaCachingRDFSInferencer"; + + /** + * Returns the Sail's type: rdf4j:SchemaCachingRDFSInferencer. + */ + @Override + public String getSailType() { + return SAIL_TYPE; + } + + @Override + public SailImplConfig getConfig() { + return new ForwardChainingRDFSInferencerConfig(); + } + + @Override + public Sail getSail(SailImplConfig config) + throws SailConfigException + { + if (!SAIL_TYPE.equals(config.getType())) { + throw new SailConfigException("Invalid Sail type: " + config.getType()); + } + + return new SchemaCachingRDFSInferencer(); + } +} diff --git a/inferencer/src/main/resources/META-INF/services/org.eclipse.rdf4j.sail.config.SailFactory b/inferencer/src/main/resources/META-INF/services/org.eclipse.rdf4j.sail.config.SailFactory index 56e9d202d..641aaa97e 100644 --- a/inferencer/src/main/resources/META-INF/services/org.eclipse.rdf4j.sail.config.SailFactory +++ b/inferencer/src/main/resources/META-INF/services/org.eclipse.rdf4j.sail.config.SailFactory @@ -1,3 +1,4 @@ +org.eclipse.rdf4j.sail.inferencer.fc.config.SchemaCachingRDFSInferencerFactory org.eclipse.rdf4j.sail.inferencer.fc.config.ForwardChainingRDFSInferencerFactory org.eclipse.rdf4j.sail.inferencer.fc.config.DirectTypeHierarchyInferencerFactory org.eclipse.rdf4j.sail.inferencer.fc.config.CustomGraphQueryInferencerFactory From 928be956c9c4680e4ef1a323b55c82822ec10866 Mon Sep 17 00:00:00 2001 From: Jeen Broekstra Date: Sat, 5 Jan 2019 16:29:01 +1100 Subject: [PATCH 20/54] use correct config class Signed-off-by: Jeen Broekstra --- .../fc/config/SchemaCachingRDFSInferencerFactory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/config/SchemaCachingRDFSInferencerFactory.java b/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/config/SchemaCachingRDFSInferencerFactory.java index 6e6c7af74..0d08a7985 100644 --- a/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/config/SchemaCachingRDFSInferencerFactory.java +++ b/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/config/SchemaCachingRDFSInferencerFactory.java @@ -38,7 +38,7 @@ public String getSailType() { @Override public SailImplConfig getConfig() { - return new ForwardChainingRDFSInferencerConfig(); + return new SchemaCachingRDFSInferencerConfig(); } @Override From 3036fbef04ab3d4ceeaf70cbd43cbbf3bdd95373 Mon Sep 17 00:00:00 2001 From: Jeen Broekstra Date: Sat, 5 Jan 2019 16:30:51 +1100 Subject: [PATCH 21/54] add persistence test and fix default condition under which to test --- ...FSchemaMemoryRepositoryConnectionTest.java | 1 - ...chingRDFSInferencerMemInferencingTest.java | 36 ++++++++++++++++++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/SchemaCachingRDFSInferencerRDFSchemaMemoryRepositoryConnectionTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/SchemaCachingRDFSInferencerRDFSchemaMemoryRepositoryConnectionTest.java index 4ce43ace4..0cfad764f 100644 --- a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/SchemaCachingRDFSInferencerRDFSchemaMemoryRepositoryConnectionTest.java +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/SchemaCachingRDFSInferencerRDFSchemaMemoryRepositoryConnectionTest.java @@ -38,7 +38,6 @@ public SchemaCachingRDFSInferencerRDFSchemaMemoryRepositoryConnectionTest( @Override protected Repository createRepository() { SchemaCachingRDFSInferencer sail = new SchemaCachingRDFSInferencer(new MemoryStore(), true); - sail.setAddInferredStatementsToDefaultContext(false); return new SailRepository(sail); } diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/SchemaCachingRDFSInferencerMemInferencingTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/SchemaCachingRDFSInferencerMemInferencingTest.java index e6aa61bb5..cfbb746e7 100644 --- a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/SchemaCachingRDFSInferencerMemInferencingTest.java +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/SchemaCachingRDFSInferencerMemInferencingTest.java @@ -10,8 +10,10 @@ import static junit.framework.TestCase.assertFalse; import static junit.framework.TestCase.assertTrue; +import java.io.File; import java.lang.reflect.InvocationTargetException; +import org.assertj.core.util.Files; import org.eclipse.rdf4j.model.BNode; import org.eclipse.rdf4j.model.IRI; import org.eclipse.rdf4j.model.ValueFactory; @@ -29,10 +31,42 @@ public class SchemaCachingRDFSInferencerMemInferencingTest extends InferencingTe @Override protected Repository createRepository() { SchemaCachingRDFSInferencer sailStack = new SchemaCachingRDFSInferencer(new MemoryStore(), true); - sailStack.setAddInferredStatementsToDefaultContext(false); + //sailStack.setAddInferredStatementsToDefaultContext(false); return new SailRepository(sailStack); } + @Test + public void testPersistence() { + File datadir = Files.newTemporaryFolder(); + + SchemaCachingRDFSInferencer sailStack = new SchemaCachingRDFSInferencer(new MemoryStore(datadir), true); + SailRepository repo = new SailRepository(sailStack); + repo.initialize(); + ValueFactory vf = repo.getValueFactory(); + + IRI s1= vf.createIRI("foo:s1"); + IRI c2 = vf.createIRI("foo:c2"); + IRI c1 = vf.createIRI("foo:c1"); + + try (RepositoryConnection conn = repo.getConnection()) { + conn.begin(); + conn.add(s1, RDF.TYPE, c1); + conn.add(c1, RDFS.SUBCLASSOF, c2); + conn.commit(); + assertTrue(conn.hasStatement(s1, RDF.TYPE, c2, true)); + } + repo.shutDown(); + + // re-init +// sailStack = new SchemaCachingRDFSInferencer(new MemoryStore(datadir), true); +// repo = new SailRepository(sailStack); + repo.initialize(); + + try (RepositoryConnection conn = repo.getConnection()) { + assertTrue(conn.hasStatement(s1, RDF.TYPE, c2, true)); + } + } + @Test public void testBlankNodePredicateInference() { Repository sailRepository = createRepository(); From 19ce3287a3ab468a70f64f41e503bec0c766285d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Avard=20Ottestad?= Date: Sun, 6 Jan 2019 15:17:30 +0100 Subject: [PATCH 22/54] eclipse/rdf4j#1234 fixed handling of updates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håvard Ottestad --- ...FSchemaMemoryRepositoryConnectionTest.java | 138 +++++++++++++++--- ...SchemaCachingRDFSInferencerConnection.java | 6 + 2 files changed, 127 insertions(+), 17 deletions(-) diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/SchemaCachingRDFSInferencerRDFSchemaMemoryRepositoryConnectionTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/SchemaCachingRDFSInferencerRDFSchemaMemoryRepositoryConnectionTest.java index 0cfad764f..8caa4a4f9 100644 --- a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/SchemaCachingRDFSInferencerRDFSchemaMemoryRepositoryConnectionTest.java +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/SchemaCachingRDFSInferencerRDFSchemaMemoryRepositoryConnectionTest.java @@ -15,7 +15,10 @@ import org.eclipse.rdf4j.model.vocabulary.RDFS; import org.eclipse.rdf4j.repository.RDFSchemaRepositoryConnectionTest; import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryResult; import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; +import org.eclipse.rdf4j.sail.inferencer.fc.ForwardChainingRDFSInferencer; import org.eclipse.rdf4j.sail.inferencer.fc.SchemaCachingRDFSInferencer; import org.eclipse.rdf4j.sail.memory.MemoryStore; import org.junit.Ignore; @@ -23,21 +26,24 @@ import java.util.stream.Stream; +import static junit.framework.TestCase.assertTrue; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThat; public class SchemaCachingRDFSInferencerRDFSchemaMemoryRepositoryConnectionTest - extends RDFSchemaRepositoryConnectionTest -{ + extends RDFSchemaRepositoryConnectionTest { public SchemaCachingRDFSInferencerRDFSchemaMemoryRepositoryConnectionTest( - IsolationLevel level) - { + IsolationLevel level) { super(level); } @Override protected Repository createRepository() { SchemaCachingRDFSInferencer sail = new SchemaCachingRDFSInferencer(new MemoryStore(), true); + sail.setAddInferredStatementsToDefaultContext(false); + return new SailRepository(sail); } @@ -46,8 +52,7 @@ protected Repository createRepository() { @Test @Ignore public void testQueryDefaultGraph() - throws Exception - { + throws Exception { // ignore } @@ -56,8 +61,7 @@ public void testQueryDefaultGraph() @Test @Ignore public void testDeleteDefaultGraph() - throws Exception - { + throws Exception { // ignore } @@ -65,8 +69,7 @@ public void testDeleteDefaultGraph() @Test @Ignore public void testContextStatementsNotDuplicated() - throws Exception - { + throws Exception { // ignore } @@ -74,15 +77,13 @@ public void testContextStatementsNotDuplicated() @Test @Ignore public void testContextStatementsNotDuplicated2() - throws Exception - { + throws Exception { // ignore } @Test - public void testContextTbox() - { + public void testContextTbox() { // Man subClassOf Human g1 // Human subClassOf Animal g2 @@ -110,13 +111,13 @@ public void testContextTbox() System.out.println("-----------"); - try (Stream stream = Iterations.stream(testCon.getStatements(man, RDFS.SUBCLASSOF, null,true))) { + try (Stream stream = Iterations.stream(testCon.getStatements(man, RDFS.SUBCLASSOF, null, true))) { stream.forEach(System.out::println); } System.out.println("-----------"); - try (Stream stream = Iterations.stream(testCon.getStatements(bob, RDF.TYPE, null,true))) { + try (Stream stream = Iterations.stream(testCon.getStatements(bob, RDF.TYPE, null, true))) { stream - .peek(statement -> assertEquals(statement.getContext(), graph3)) + .peek(statement -> assertEquals(graph3, statement.getContext())) .forEach(System.out::println); } @@ -126,4 +127,107 @@ public void testContextTbox() } + @Test + public void testUpdateInsertData() { + + SailRepository sail = new SailRepository(new SchemaCachingRDFSInferencer(new MemoryStore())); + sail.initialize(); + + + try (SailRepositoryConnection connection = sail.getConnection()) { + + IRI foo_s1 = connection.getValueFactory().createIRI("foo:s1"); + IRI foo_C2 = connection.getValueFactory().createIRI("foo:C2"); + + + connection.begin(); + connection.prepareUpdate("insert data { a . rdfs:subClassOf } ").execute(); + connection.commit(); + + assertTrue(connection.hasStatement(foo_s1, RDF.TYPE, foo_C2, true)); + + + } + + } + + @Test + public void testUpdateInsert() { + + SailRepository sail = new SailRepository(new SchemaCachingRDFSInferencer(new MemoryStore())); + sail.initialize(); + + + try (SailRepositoryConnection connection = sail.getConnection()) { + + IRI foo_s1 = connection.getValueFactory().createIRI("foo:s1"); + IRI foo_C2 = connection.getValueFactory().createIRI("foo:C2"); + + connection.begin(); + connection.prepareUpdate("insert { a . rdfs:subClassOf } where {?a ?b ?c}").execute(); + connection.commit(); + + assertTrue(connection.hasStatement(foo_s1, RDF.TYPE, foo_C2, true)); + + } + + } + + @Test + public void testInsert() { + + SailRepository sail = new SailRepository(new SchemaCachingRDFSInferencer(new MemoryStore())); + sail.initialize(); + + + try (SailRepositoryConnection connection = sail.getConnection()) { + + IRI foo_s1 = connection.getValueFactory().createIRI("foo:s1"); + IRI foo_C2 = connection.getValueFactory().createIRI("foo:C2"); + IRI foo_C1 = connection.getValueFactory().createIRI("foo:C1"); + + + connection.begin(); + connection.add(foo_s1, RDF.TYPE, foo_C1); + connection.add(foo_C1, RDFS.SUBCLASSOF, foo_C2); + connection.commit(); + + assertTrue(connection.hasStatement(foo_s1, RDF.TYPE, foo_C2, true)); + + + } + + } + + @Test + public void testUpdateRemove() { + + SailRepository sail = new SailRepository(new SchemaCachingRDFSInferencer(new MemoryStore())); + sail.initialize(); + + + try (SailRepositoryConnection connection = sail.getConnection()) { + + IRI foo_s1 = connection.getValueFactory().createIRI("foo:s1"); + IRI foo_C2 = connection.getValueFactory().createIRI("foo:C2"); + + + connection.begin(); + connection.prepareUpdate("insert data { a . rdfs:subClassOf } ").execute(); + connection.commit(); + + assertTrue(connection.hasStatement(foo_s1, RDF.TYPE, foo_C2, true)); + + connection.begin(); + connection.prepareUpdate("delete data { a . rdfs:subClassOf } ").execute(); + connection.commit(); + + assertFalse(connection.hasStatement(foo_s1, RDF.TYPE, foo_C2, true)); + + + } + + } + + } diff --git a/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/SchemaCachingRDFSInferencerConnection.java b/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/SchemaCachingRDFSInferencerConnection.java index 2b0562740..4fac78e5a 100644 --- a/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/SchemaCachingRDFSInferencerConnection.java +++ b/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/SchemaCachingRDFSInferencerConnection.java @@ -22,6 +22,7 @@ import org.eclipse.rdf4j.sail.SailConnectionListener; import org.eclipse.rdf4j.sail.SailException; import org.eclipse.rdf4j.sail.UnknownSailTransactionStateException; +import org.eclipse.rdf4j.sail.UpdateContext; import org.eclipse.rdf4j.sail.inferencer.InferencerConnection; import org.eclipse.rdf4j.sail.inferencer.InferencerConnectionWrapper; import org.slf4j.Logger; @@ -810,4 +811,9 @@ public void statementRemoved(Statement st) { statementsRemoved = true; } + @Override + public void addStatement(UpdateContext modify, Resource subj, IRI pred, Value obj, Resource... contexts) throws SailException { + addStatement(false, subj, pred, obj, contexts); + super.addStatement(modify, subj, pred, obj, contexts); + } } From 11bafb7dfc9ad8ba933f1e7fa068d64ebeb282ea Mon Sep 17 00:00:00 2001 From: Jeen Broekstra Date: Mon, 7 Jan 2019 19:48:04 +1100 Subject: [PATCH 23/54] eclipse/rdf4j#1226 added isolation level compliance tests for inferencer Signed-off-by: Jeen Broekstra --- .../rdf4j/sail/fc/InferredContextTest.java | 1 - ...chingRDFSInferencerIsolationLevelTest.java | 32 +++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 compliance/store/src/test/java/org/eclipse/rdf4j/sail/fc/SchemaCachingRDFSInferencerIsolationLevelTest.java diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/fc/InferredContextTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/fc/InferredContextTest.java index 2c0ca5fc0..b6db36c56 100644 --- a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/fc/InferredContextTest.java +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/fc/InferredContextTest.java @@ -32,7 +32,6 @@ public void testInferrecContextNull() { sail.initialize(); sail.setAddInferredStatementsToDefaultContext(true); - try (SchemaCachingRDFSInferencerConnection connection = sail.getConnection()) { connection.begin(); connection.addStatement(bNode, RDF.TYPE, type, context); diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/fc/SchemaCachingRDFSInferencerIsolationLevelTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/fc/SchemaCachingRDFSInferencerIsolationLevelTest.java new file mode 100644 index 000000000..f616ad54b --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/fc/SchemaCachingRDFSInferencerIsolationLevelTest.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2019 Eclipse RDF4J contributors. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.sail.fc; + +import org.eclipse.rdf4j.sail.Sail; +import org.eclipse.rdf4j.sail.SailException; +import org.eclipse.rdf4j.sail.SailIsolationLevelTest; +import org.eclipse.rdf4j.sail.inferencer.fc.SchemaCachingRDFSInferencer; +import org.eclipse.rdf4j.sail.memory.MemoryStore; + +/** + * An extension of {@link SailIsolationLevelTest} for testing the {@link SchemaCachingRDFSInferencer}. + */ +public class SchemaCachingRDFSInferencerIsolationLevelTest extends SailIsolationLevelTest { + + /*---------* + * Methods * + *---------*/ + + @Override + protected Sail createSail() + throws SailException + { + // TODO we are testing the inferencer, not the store. We should use a mock here instead of a real memory store. + return new SchemaCachingRDFSInferencer(new MemoryStore()); + } +} From dcd14e75b240cce575b5c0904d1e9f4070b04c69 Mon Sep 17 00:00:00 2001 From: Jeen Broekstra Date: Sun, 13 Jan 2019 12:15:41 +1100 Subject: [PATCH 24/54] rename initialize() to init(), replace usage, clean up tests --- .../rdf4j/sail/memory/MemoryStoreTest.java | 2 +- .../memory/PersistentMemoryStoreTest.java | 23 +++++-------------- .../nativerdf/NativeStoreContextTest.java | 2 +- .../rdf4j/sail/nativerdf/NativeStoreTest.java | 4 ++-- .../rdf4j/sail/federation/Federation.java | 14 ++++++++--- .../rdf4j/repository/sail/SailRepository.java | 2 +- .../java/org/eclipse/rdf4j/sail/Sail.java | 18 +++++++++++++++ .../rdf4j/sail/helpers/AbstractSail.java | 9 +++++++- 8 files changed, 48 insertions(+), 26 deletions(-) diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/MemoryStoreTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/MemoryStoreTest.java index 8b1815d07..90cea23cd 100644 --- a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/MemoryStoreTest.java +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/MemoryStoreTest.java @@ -26,7 +26,7 @@ protected NotifyingSail createSail() throws SailException { NotifyingSail sail = new MemoryStore(); - sail.initialize(); + sail.init(); return sail; } } diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/PersistentMemoryStoreTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/PersistentMemoryStoreTest.java index a9f69be22..6edac4c5b 100644 --- a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/PersistentMemoryStoreTest.java +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/memory/PersistentMemoryStoreTest.java @@ -8,13 +8,13 @@ package org.eclipse.rdf4j.sail.memory; -import java.io.File; import java.io.IOException; -import org.eclipse.rdf4j.common.io.FileUtil; import org.eclipse.rdf4j.sail.NotifyingSail; import org.eclipse.rdf4j.sail.RDFNotifyingStoreTest; import org.eclipse.rdf4j.sail.SailException; +import org.junit.Rule; +import org.junit.rules.TemporaryFolder; /** * An extension of RDFStoreTest for testing the class @@ -22,16 +22,16 @@ */ public class PersistentMemoryStoreTest extends RDFNotifyingStoreTest { - private volatile File dataDir; + @Rule + public TemporaryFolder tempDir = new TemporaryFolder(); @Override protected NotifyingSail createSail() throws SailException { try { - dataDir = FileUtil.createTempDir(PersistentMemoryStoreTest.class.getSimpleName()); - NotifyingSail sail = new MemoryStore(dataDir); - sail.initialize(); + NotifyingSail sail = new MemoryStore(tempDir.newFolder(PersistentMemoryStoreTest.class.getSimpleName())); + sail.init(); return sail; } catch (IOException e) { @@ -39,15 +39,4 @@ protected NotifyingSail createSail() } } - @Override - public void tearDown() - throws Exception - { - try { - super.tearDown(); - } - finally { - FileUtil.deleteDir(dataDir); - } - } } diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreContextTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreContextTest.java index 41c848a45..027a0b008 100644 --- a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreContextTest.java +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreContextTest.java @@ -37,7 +37,7 @@ protected NotifyingSail createSail() { try { NotifyingSail sail = new NativeStore(tempDir.newFolder("nativestore"), "spoc,posc"); - sail.initialize(); + sail.init(); return sail; } catch (IOException e) { diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreTest.java index f08b6bbd5..c00a61ae6 100644 --- a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreTest.java +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreTest.java @@ -41,7 +41,7 @@ protected NotifyingSail createSail() { try { NotifyingSail sail = new NativeStore(tempDir.newFolder("nativestore"), "spoc,posc"); - sail.initialize(); + sail.init(); return sail; } catch (IOException e) { @@ -61,7 +61,7 @@ public void testGetNamespacePersistence() con.close(); sail.shutDown(); - sail.initialize(); + sail.init(); con = sail.getConnection(); assertEquals(RDF.NAMESPACE, con.getNamespace("rdf")); diff --git a/federation/src/main/java/org/eclipse/rdf4j/sail/federation/Federation.java b/federation/src/main/java/org/eclipse/rdf4j/sail/federation/Federation.java index 4b0e298e2..2172b4994 100644 --- a/federation/src/main/java/org/eclipse/rdf4j/sail/federation/Federation.java +++ b/federation/src/main/java/org/eclipse/rdf4j/sail/federation/Federation.java @@ -254,20 +254,28 @@ public void setHttpClient(HttpClient client) { } } - @Override + @Deprecated public void initialize() throws SailException + { + init(); + } + + + @Override + public void init() + throws SailException { for (Repository member : members) { try { - member.initialize(); + member.init(); } catch (RepositoryException e) { throw new SailException(e); } } } - + @Override public void shutDown() throws SailException diff --git a/repository-sail/src/main/java/org/eclipse/rdf4j/repository/sail/SailRepository.java b/repository-sail/src/main/java/org/eclipse/rdf4j/repository/sail/SailRepository.java index a558c84f3..00e8c39cc 100644 --- a/repository-sail/src/main/java/org/eclipse/rdf4j/repository/sail/SailRepository.java +++ b/repository-sail/src/main/java/org/eclipse/rdf4j/repository/sail/SailRepository.java @@ -150,7 +150,7 @@ protected void initializeInternal() throws RepositoryException { try { - sail.initialize(); + sail.init(); } catch (SailLockedException e) { String l = e.getLockedBy(); diff --git a/sail-api/src/main/java/org/eclipse/rdf4j/sail/Sail.java b/sail-api/src/main/java/org/eclipse/rdf4j/sail/Sail.java index 2da686e58..e22769faf 100644 --- a/sail-api/src/main/java/org/eclipse/rdf4j/sail/Sail.java +++ b/sail-api/src/main/java/org/eclipse/rdf4j/sail/Sail.java @@ -48,9 +48,27 @@ public interface Sail { * If the Sail could not be initialized. * @throws IllegalStateException * If the Sail has already been initialized. + * @deprecated Use {{@link #init()} instead. */ + @Deprecated void initialize() throws SailException; + + /** + * Initializes the Sail. Care should be taken that required initialization parameters have been set before + * this method is called. Please consult the specific Sail implementation for information about the + * relevant parameters. + * + * @throws SailException + * If the Sail could not be initialized. + * @throws IllegalStateException + * If the Sail has already been initialized. + * + * @since 2.5 + */ + default void init() throws SailException { + initialize(); + } /** * Shuts down the Sail, giving it the opportunity to synchronize any stale data. Care should be taken that diff --git a/sail-api/src/main/java/org/eclipse/rdf4j/sail/helpers/AbstractSail.java b/sail-api/src/main/java/org/eclipse/rdf4j/sail/helpers/AbstractSail.java index 597a22027..fe47111fd 100644 --- a/sail-api/src/main/java/org/eclipse/rdf4j/sail/helpers/AbstractSail.java +++ b/sail-api/src/main/java/org/eclipse/rdf4j/sail/helpers/AbstractSail.java @@ -173,8 +173,15 @@ protected boolean isInitialized() { return initialized; } + @Override - public void initialize() + public void initialize() throws SailException + { + init(); + } + + @Override + public void init() throws SailException { initializationLock.writeLock().lock(); From 81de2113e1285aa469cade203dcc6fe957bb6e83 Mon Sep 17 00:00:00 2001 From: Jeen Broekstra Date: Sun, 13 Jan 2019 14:14:22 +1100 Subject: [PATCH 25/54] revert to use of deprecated Repository.initialize() pending merge --- .../main/java/org/eclipse/rdf4j/sail/federation/Federation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/federation/src/main/java/org/eclipse/rdf4j/sail/federation/Federation.java b/federation/src/main/java/org/eclipse/rdf4j/sail/federation/Federation.java index 2172b4994..ceb3c83b7 100644 --- a/federation/src/main/java/org/eclipse/rdf4j/sail/federation/Federation.java +++ b/federation/src/main/java/org/eclipse/rdf4j/sail/federation/Federation.java @@ -268,7 +268,7 @@ public void init() { for (Repository member : members) { try { - member.init(); + member.initialize(); } catch (RepositoryException e) { throw new SailException(e); From 65d1fd51ba4a2b1eb3e2fcd254a38211fa9ada71 Mon Sep 17 00:00:00 2001 From: Jeen Broekstra Date: Sun, 13 Jan 2019 17:12:15 +1100 Subject: [PATCH 26/54] refactor to remove public use of Repository API in SAIL constructor [WIP] --- .../eclipse/rdf4j/sail/shacl/ShaclSail.java | 127 ++++++++++--- .../rdf4j/sail/shacl/ShaclSailConnection.java | 96 +++++++--- .../sail/shacl/ReduceNumberOfPlansTest.java | 104 +++++----- .../eclipse/rdf4j/sail/shacl/ShaclTest.java | 89 ++++----- .../eclipse/rdf4j/sail/shacl/TempTest.java | 66 +++---- .../sail/shacl/TrackAddedStatementsTest.java | 178 ++++++++---------- .../org/eclipse/rdf4j/sail/shacl/Utils.java | 66 +++++-- .../rdf4j/sail/shacl/VisulizerTest.java | 18 +- .../benchmark/DatatypeBenchmarkEmpty.java | 4 +- .../benchmark/DatatypeBenchmarkPrefilled.java | 4 +- .../benchmark/MinCountBenchmarkEmpty.java | 4 +- .../benchmark/MinCountBenchmarkPrefilled.java | 4 +- .../MinCountPrefilledVsEmptyBenchmark.java | 16 +- 13 files changed, 451 insertions(+), 325 deletions(-) diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSail.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSail.java index 16083929a..de8e26216 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSail.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSail.java @@ -8,65 +8,119 @@ package org.eclipse.rdf4j.sail.shacl; -import org.apache.commons.io.FileUtils; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.List; + import org.apache.commons.io.IOUtils; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnection; import org.eclipse.rdf4j.repository.sail.SailRepository; import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; import org.eclipse.rdf4j.sail.NotifyingSail; import org.eclipse.rdf4j.sail.NotifyingSailConnection; +import org.eclipse.rdf4j.sail.Sail; import org.eclipse.rdf4j.sail.SailException; +import org.eclipse.rdf4j.sail.config.SailConfigException; import org.eclipse.rdf4j.sail.helpers.NotifyingSailWrapper; +import org.eclipse.rdf4j.sail.memory.MemoryStore; import org.eclipse.rdf4j.sail.shacl.AST.NodeShape; -import java.io.IOException; -import java.util.List; - /** + * A {@link Sail} implementation that adds support for the Shapes Constraint Language (SHACL) + * * @author Heshan Jayasinghe + * @see SHACL W3C Recommendation */ public class ShaclSail extends NotifyingSailWrapper { + /** + * The virtual context identifier for persisting the SHACL shapes information. + */ + public final static IRI SHAPE_GRAPH = SimpleValueFactory.getInstance().createIRI("http://rdf4j.org/schema/schacl#ShapeGraph"); + public List nodeShapes; + boolean debugPrintPlans = false; ShaclSailConfig config = new ShaclSailConfig(); + private static String SH_OR_UPDATE_QUERY; + private static String SH_OR_NODE_SHAPE_UPDATE_QUERY; + /** + * an initialized {@link Repository} for storing/retrieving Shapes data + */ + private SailRepository shapesRepo; + static { try { - SH_OR_UPDATE_QUERY = IOUtils.toString(ShaclSail.class.getClassLoader().getResourceAsStream("shacl-sparql-inference/sh_or.rq"), "UTF-8"); - SH_OR_NODE_SHAPE_UPDATE_QUERY = IOUtils.toString(ShaclSail.class.getClassLoader().getResourceAsStream("shacl-sparql-inference/sh_or_node_shape.rq"), "UTF-8"); - } catch (IOException e) { + SH_OR_UPDATE_QUERY = IOUtils.toString( + ShaclSail.class.getClassLoader().getResourceAsStream("shacl-sparql-inference/sh_or.rq"), + "UTF-8"); + SH_OR_NODE_SHAPE_UPDATE_QUERY = IOUtils.toString( + ShaclSail.class.getClassLoader().getResourceAsStream( + "shacl-sparql-inference/sh_or_node_shape.rq"), + "UTF-8"); + } + catch (IOException e) { throw new IllegalStateException(e); } } - public ShaclSail(NotifyingSail baseSail, SailRepository shaclSail) { + public ShaclSail(NotifyingSail baseSail) { super(baseSail); - try (SailRepositoryConnection shaclSailConnection = shaclSail.getConnection()) { - runInferencingSparqlQueries(shaclSailConnection); - nodeShapes = NodeShape.Factory.getShapes(shaclSailConnection); + String path = null; + if (baseSail.getDataDir() != null) { + path = baseSail.getDataDir().getPath(); + } + else { + try { + path = Files.createTempDirectory("shacl-shapes").toString(); + } catch (IOException e) { + throw new SailConfigException(e); + } } + if (path.endsWith("/")) { + path = path.substring(0, path.length() -1); + } + path = path + "-shapes-graph/"; + + shapesRepo = new SailRepository(new MemoryStore(new File(path))); + shapesRepo.initialize(); } - private void runInferencingSparqlQueries(SailRepositoryConnection shaclSailConnection) { - + @Override + public void initialize() throws SailException { + super.initialize(); + try (SailRepositoryConnection shapesRepoConnection = shapesRepo.getConnection()) { + runInferencingSparqlQueries(shapesRepoConnection); + nodeShapes = NodeShape.Factory.getShapes(shapesRepoConnection); + } + } - long prevSize; - long currentSize= shaclSailConnection.size(); - do { - prevSize = currentSize; - shaclSailConnection.prepareUpdate(SH_OR_NODE_SHAPE_UPDATE_QUERY).execute(); - shaclSailConnection.prepareUpdate(SH_OR_UPDATE_QUERY).execute(); - currentSize = shaclSailConnection.size(); - }while(prevSize != currentSize); + @Override + public void shutDown() throws SailException { + try { + shapesRepo.shutDown(); + } + finally { + shapesRepo = null; + } + super.shutDown(); } + + @Override - public NotifyingSailConnection getConnection() - throws SailException { + public NotifyingSailConnection getConnection() throws SailException { return new ShaclSailConnection(this, super.getConnection(), super.getConnection()); } @@ -85,6 +139,33 @@ public boolean isDebugPrintPlans() { public void setDebugPrintPlans(boolean debugPrintPlans) { this.debugPrintPlans = debugPrintPlans; } + + protected void addShapesStatement(Resource subj, IRI pred, Value obj) { + try (RepositoryConnection conn = shapesRepo.getConnection()) { + conn.add(subj, pred, obj); + } + } + + + protected void removeShapesStatements(Resource subj, IRI pred, Value obj) { + try (RepositoryConnection conn = shapesRepo.getConnection()) { + conn.remove(subj, pred, obj); + } + } + + private void runInferencingSparqlQueries(SailRepositoryConnection shaclSailConnection) { + + long prevSize; + long currentSize = shaclSailConnection.size(); + do { + prevSize = currentSize; + shaclSailConnection.prepareUpdate(SH_OR_NODE_SHAPE_UPDATE_QUERY).execute(); + shaclSailConnection.prepareUpdate(SH_OR_UPDATE_QUERY).execute(); + currentSize = shaclSailConnection.size(); + } + while (prevSize != currentSize); + } + } class ShaclSailConfig { diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java index 219a0099b..f5ee0d97b 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java @@ -11,7 +11,10 @@ import org.eclipse.rdf4j.IsolationLevel; import org.eclipse.rdf4j.IsolationLevels; import org.eclipse.rdf4j.common.iteration.Iterations; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Resource; import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.Value; import org.eclipse.rdf4j.repository.Repository; import org.eclipse.rdf4j.repository.RepositoryConnection; import org.eclipse.rdf4j.repository.sail.SailRepository; @@ -39,7 +42,9 @@ public class ShaclSailConnection extends NotifyingSailConnectionWrapper { private final Logger logger = LoggerFactory.getLogger(getClass()); private NotifyingSailConnection previousStateConnection; + private Repository addedStatements; + private Repository removedStatements; public final ShaclSail sail; @@ -47,9 +52,12 @@ public class ShaclSailConnection extends NotifyingSailConnectionWrapper { public Stats stats; private HashSet addedStatementsSet = new HashSet<>(); + private HashSet removedStatementsSet = new HashSet<>(); - ShaclSailConnection(ShaclSail sail, NotifyingSailConnection connection, NotifyingSailConnection previousStateConnection) { + ShaclSailConnection(ShaclSail sail, NotifyingSailConnection connection, + NotifyingSailConnection previousStateConnection) + { super(connection); this.previousStateConnection = previousStateConnection; this.sail = sail; @@ -58,23 +66,23 @@ public class ShaclSailConnection extends NotifyingSailConnectionWrapper { addConnectionListener(new SailConnectionListener() { - @Override - public void statementAdded(Statement statement) { - boolean add = addedStatementsSet.add(statement); - if (!add) { - removedStatementsSet.remove(statement); - } + @Override + public void statementAdded(Statement statement) { + boolean add = addedStatementsSet.add(statement); + if (!add) { + removedStatementsSet.remove(statement); + } - } + } - @Override - public void statementRemoved(Statement statement) { - boolean add = removedStatementsSet.add(statement); - if (!add) { - addedStatementsSet.remove(statement); - } - } - } + @Override + public void statementRemoved(Statement statement) { + boolean add = removedStatementsSet.add(statement); + if (!add) { + addedStatementsSet.remove(statement); + } + } + } ); } @@ -98,8 +106,7 @@ public void begin() throws SailException { } @Override - public void begin(IsolationLevel level) - throws SailException { + public void begin(IsolationLevel level) throws SailException { assert addedStatements == null; assert removedStatements == null; @@ -107,7 +114,7 @@ public void begin(IsolationLevel level) stats = new Stats(); // start two transactions, synchronize on underlying sail so that we get two transactions immediatly successivley - synchronized (sail){ + synchronized (sail) { super.begin(level); previousStateConnection.begin(IsolationLevels.SNAPSHOT); } @@ -123,8 +130,7 @@ private SailRepository getNewMemorySail() { } @Override - public void commit() - throws SailException { + public void commit() throws SailException { synchronized (sail) { try { boolean valid = validate(); @@ -133,15 +139,39 @@ public void commit() if (!valid) { rollback(); throw new SailException("Failed SHACL validation"); - } else { + } + else { super.commit(); } - } finally { + } + finally { cleanup(); } } } + @Override + public void addStatement(Resource subj, IRI pred, Value obj, Resource... contexts) throws SailException { + if (contexts.length == 1 && contexts[0].equals(ShaclSail.SHAPE_GRAPH)) { + sail.addShapesStatement(subj, pred, obj); + } + else { + super.addStatement(subj, pred, obj, contexts); + } + } + + @Override + public void removeStatements(Resource subj, IRI pred, Value obj, Resource... contexts) + throws SailException + { + if (contexts.length == 1 && contexts[0].equals(ShaclSail.SHAPE_GRAPH)) { + sail.removeShapesStatements(subj, pred, obj); + } + else { + super.removeStatements(subj, pred, obj, contexts); + } + } + @Override public void rollback() throws SailException { synchronized (sail) { @@ -166,7 +196,6 @@ private void cleanup() { stats = null; } - private boolean validate() { if (!sail.config.validationEnabled) { @@ -185,7 +214,13 @@ private boolean validate() { boolean valid = collect.size() == 0; if (!valid) { - logger.warn("SHACL not valid. The following experimental debug results were produced: \n\tNodeShape: {} \n\t\t{}", nodeShape.toString(), String.join("\n\t\t", collect.stream().map(a -> a.toString()+" -cause-> "+a.getCause()).collect(Collectors.toList()))); + logger.warn( + "SHACL not valid. The following experimental debug results were produced: \n\tNodeShape: {} \n\t\t{}", + nodeShape.toString(), + String.join("\n\t\t", + collect.stream().map( + a -> a.toString() + " -cause-> " + a.getCause()).collect( + Collectors.toList()))); } allValid = allValid && valid; } @@ -200,20 +235,20 @@ void fillAddedAndRemovedStatementRepositories() { addedStatements = getNewMemorySail(); removedStatements = getNewMemorySail(); - addedStatementsSet.forEach(stats::added); removedStatementsSet.forEach(stats::removed); - try (RepositoryConnection connection = addedStatements.getConnection()) { connection.begin(IsolationLevels.NONE); - addedStatementsSet.stream().filter(statement -> !removedStatementsSet.contains(statement)).forEach(connection::add); + addedStatementsSet.stream().filter( + statement -> !removedStatementsSet.contains(statement)).forEach(connection::add); connection.commit(); } try (RepositoryConnection connection = removedStatements.getConnection()) { connection.begin(IsolationLevels.NONE); - removedStatementsSet.stream().filter(statement -> !addedStatementsSet.contains(statement)).forEach(connection::add); + removedStatementsSet.stream().filter( + statement -> !addedStatementsSet.contains(statement)).forEach(connection::add); connection.commit(); } } @@ -226,10 +261,10 @@ synchronized public void close() throws SailException { super.close(); } - public class Stats { boolean hasAdded; + boolean hasRemoved; public void added(Statement statement) { @@ -250,4 +285,3 @@ public boolean hasRemoved() { } } } - diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ReduceNumberOfPlansTest.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ReduceNumberOfPlansTest.java index 564cd476f..95215371d 100644 --- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ReduceNumberOfPlansTest.java +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ReduceNumberOfPlansTest.java @@ -8,114 +8,114 @@ package org.eclipse.rdf4j.sail.shacl; +import static junit.framework.TestCase.assertEquals; + +import java.io.IOException; +import java.util.List; +import java.util.stream.Collectors; + +import org.eclipse.rdf4j.RDF4JException; import org.eclipse.rdf4j.model.IRI; import org.eclipse.rdf4j.model.ValueFactory; import org.eclipse.rdf4j.model.vocabulary.RDF; -import org.eclipse.rdf4j.repository.sail.SailRepository; -import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; +import org.eclipse.rdf4j.rio.RDFParseException; +import org.eclipse.rdf4j.rio.UnsupportedRDFormatException; import org.eclipse.rdf4j.sail.memory.MemoryStore; import org.eclipse.rdf4j.sail.shacl.planNodes.PlanNode; import org.junit.Test; -import java.util.List; -import java.util.stream.Collectors; - -import static junit.framework.TestCase.assertEquals; - /** * @author Håvard Ottestad */ public class ReduceNumberOfPlansTest { @Test - public void testAddingTypeStatement() { - SailRepository shaclSail = new SailRepository(new ShaclSail(new MemoryStore(), Utils.getSailRepository("reduceNumberOfPlansTest/shacl.ttl"))); + public void testAddingTypeStatement() + throws RDFParseException, UnsupportedRDFormatException, IOException + { + ShaclSail shaclSail = new ShaclSail(new MemoryStore()); shaclSail.initialize(); + Utils.loadShapeData(shaclSail, "reduceNumberOfPlansTest/shacl.ttl"); - - try (SailRepositoryConnection connection = shaclSail.getConnection()) { - + try (ShaclSailConnection connection = (ShaclSailConnection)shaclSail.getConnection()) { connection.begin(); - ShaclSailConnection sailConnection = (ShaclSailConnection) connection.getSailConnection(); - - sailConnection.fillAddedAndRemovedStatementRepositories(); - List collect = sailConnection.sail.nodeShapes.stream().flatMap(shape -> shape.generatePlans(sailConnection, shape, false).stream()).collect(Collectors.toList()); + connection.fillAddedAndRemovedStatementRepositories(); + List collect = shaclSail.nodeShapes.stream().flatMap( + shape -> shape.generatePlans(connection, shape, false).stream()).collect( + Collectors.toList()); assertEquals(0, collect.size()); IRI person1 = Utils.Ex.createIri(); - connection.add(person1, RDF.TYPE, Utils.Ex.Person); - sailConnection.fillAddedAndRemovedStatementRepositories(); + connection.addStatement(person1, RDF.TYPE, Utils.Ex.Person); + connection.fillAddedAndRemovedStatementRepositories(); - List collect2 = sailConnection.sail.nodeShapes.stream().flatMap(shape -> shape.generatePlans(sailConnection, shape, false).stream()).collect(Collectors.toList()); + List collect2 = shaclSail.nodeShapes.stream().flatMap( + shape -> shape.generatePlans(connection, shape, false).stream()).collect( + Collectors.toList()); assertEquals(2, collect2.size()); - ValueFactory vf = connection.getValueFactory(); - connection.add(person1, Utils.Ex.ssn, vf.createLiteral("a")); - connection.add(person1, Utils.Ex.ssn, vf.createLiteral("b")); - connection.add(person1, Utils.Ex.name, vf.createLiteral("c")); - + ValueFactory vf = shaclSail.getValueFactory(); + connection.addStatement(person1, Utils.Ex.ssn, vf.createLiteral("a")); + connection.addStatement(person1, Utils.Ex.ssn, vf.createLiteral("b")); + connection.addStatement(person1, Utils.Ex.name, vf.createLiteral("c")); connection.commit(); - } } @Test - public void testRemovingPredicate() { - SailRepository shaclSail = new SailRepository(new ShaclSail(new MemoryStore(), Utils.getSailRepository("reduceNumberOfPlansTest/shacl.ttl"))); + public void testRemovingPredicate() throws RDF4JException, UnsupportedRDFormatException, IOException { + ShaclSail shaclSail = new ShaclSail(new MemoryStore()); shaclSail.initialize(); + Utils.loadShapeData(shaclSail, "reduceNumberOfPlansTest/shacl.ttl"); - - try (SailRepositoryConnection connection = shaclSail.getConnection()) { + try (ShaclSailConnection connection = (ShaclSailConnection)shaclSail.getConnection()) { connection.begin(); - ShaclSailConnection sailConnection = (ShaclSailConnection) connection.getSailConnection(); - IRI person1 = Utils.Ex.createIri(); - ValueFactory vf = connection.getValueFactory(); - connection.add(person1, RDF.TYPE, Utils.Ex.Person); - connection.add(person1, Utils.Ex.ssn, vf.createLiteral("a")); - connection.add(person1, Utils.Ex.ssn, vf.createLiteral("b")); - connection.add(person1, Utils.Ex.name, vf.createLiteral("c")); - - + ValueFactory vf = shaclSail.getValueFactory(); + connection.addStatement(person1, RDF.TYPE, Utils.Ex.Person); + connection.addStatement(person1, Utils.Ex.ssn, vf.createLiteral("a")); + connection.addStatement(person1, Utils.Ex.ssn, vf.createLiteral("b")); + connection.addStatement(person1, Utils.Ex.name, vf.createLiteral("c")); connection.commit(); - connection.begin(); + connection.removeStatements(person1, Utils.Ex.ssn, vf.createLiteral("b")); - connection.remove(person1, Utils.Ex.ssn, vf.createLiteral("b")); - - sailConnection.fillAddedAndRemovedStatementRepositories(); + connection.fillAddedAndRemovedStatementRepositories(); - List collect1 = sailConnection.sail.nodeShapes.stream().flatMap(shape -> shape.generatePlans(sailConnection, shape, false).stream()).collect(Collectors.toList()); + List collect1 = shaclSail.nodeShapes.stream().flatMap( + shape -> shape.generatePlans(connection, shape, false).stream()).collect( + Collectors.toList()); assertEquals(1, collect1.size()); - connection.remove(person1, Utils.Ex.ssn, vf.createLiteral("a")); + connection.removeStatements(person1, Utils.Ex.ssn, vf.createLiteral("a")); + connection.fillAddedAndRemovedStatementRepositories(); - sailConnection.fillAddedAndRemovedStatementRepositories(); - - List collect2 = sailConnection.sail.nodeShapes.stream().flatMap(shape -> shape.generatePlans(sailConnection, shape, false).stream()).collect(Collectors.toList()); + List collect2 = shaclSail.nodeShapes.stream().flatMap( + shape -> shape.generatePlans(connection, shape, false).stream()).collect( + Collectors.toList()); assertEquals(1, collect2.size()); - connection.remove(person1, Utils.Ex.name, vf.createLiteral("c")); - sailConnection.fillAddedAndRemovedStatementRepositories(); + connection.removeStatements(person1, Utils.Ex.name, vf.createLiteral("c")); + connection.fillAddedAndRemovedStatementRepositories(); - List collect3 = sailConnection.sail.nodeShapes.stream().flatMap(shape -> shape.generatePlans(sailConnection, shape, false).stream()).collect(Collectors.toList()); + List collect3 = shaclSail.nodeShapes.stream().flatMap( + shape -> shape.generatePlans(connection, shape, false).stream()).collect( + Collectors.toList()); assertEquals(2, collect3.size()); - connection.rollback(); - } } diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java index b7b830779..3ae7f1e88 100644 --- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java @@ -35,23 +35,18 @@ @RunWith(Parameterized.class) public class ShaclTest { - static final List testCasePaths = Arrays.asList( - "test-cases/datatype/simple", - "test-cases/minCount/simple", - "test-cases/maxCount/simple", - "test-cases/or/inheritance", - "test-cases/or/inheritance-deep", - "test-cases/or/inheritance-deep-minCountMaxCount", - "test-cases/or/inheritanceNodeShape", - "test-cases/or/datatype", - "test-cases/or/minCountMaxCount", - "test-cases/or/maxCount", - "test-cases/or/minCount" + static final List testCasePaths = Arrays.asList("test-cases/datatype/simple", + "test-cases/minCount/simple", "test-cases/maxCount/simple", "test-cases/or/inheritance", + "test-cases/or/inheritance-deep", "test-cases/or/inheritance-deep-minCountMaxCount", + "test-cases/or/inheritanceNodeShape", "test-cases/or/datatype", "test-cases/or/minCountMaxCount", + "test-cases/or/maxCount", "test-cases/or/minCount" ); private final String testCasePath; + private final String path; + private final ExpectedResult expectedResult; public ShaclTest(String testCasePath, String path, ExpectedResult expectedResult) { @@ -64,8 +59,6 @@ public ShaclTest(String testCasePath, String path, ExpectedResult expectedResult LoggingNode.loggingEnabled = true; } - - @Parameterized.Parameters(name = "{2} - {1}") public static Collection data() { @@ -73,17 +66,13 @@ public static Collection data() { } @Test - public void test() { - + public void test() throws Exception { runTestCase(testCasePath, path, expectedResult); - } @Test - public void testSingleTransaction() { - + public void testSingleTransaction() throws Exception { runTestCaseSingleTransaction(testCasePath, path, expectedResult); - } static List findTestCases(String testCase, String baseCase) { @@ -97,7 +86,8 @@ static List findTestCases(String testCase, String baseCase) { ret.add(path); try { resourceAsStream.close(); - } catch (IOException e) { + } + catch (IOException e) { throw new RuntimeException(e); } } @@ -107,30 +97,23 @@ static List findTestCases(String testCase, String baseCase) { } - static Collection getTestsToRun() { List ret = new ArrayList<>(); - for (String testCasePath : testCasePaths) { for (ExpectedResult baseCase : ExpectedResult.values()) { findTestCases(testCasePath, baseCase.name()).forEach(path -> { - Object[] temp = {testCasePath, path, baseCase}; + Object[] temp = { testCasePath, path, baseCase }; ret.add(temp); }); } } - return ret; } - - - - - void runTestCase(String shaclPath, String dataPath, ExpectedResult expectedResult) { + void runTestCase(String shaclPath, String dataPath, ExpectedResult expectedResult) throws Exception { if (!dataPath.endsWith("/")) { dataPath = dataPath + "/"; @@ -140,13 +123,13 @@ void runTestCase(String shaclPath, String dataPath, ExpectedResult expectedResul shaclPath = shaclPath + "/"; } - String shaclFile = shaclPath + "shacl.ttl"; System.out.println(shaclFile); - ShaclSail innerShaclSail = new ShaclSail(new MemoryStore(), Utils.getSailRepository(shaclFile)); - innerShaclSail.setDebugPrintPlans(true); - SailRepository shaclSail = new SailRepository(innerShaclSail); - shaclSail.initialize(); + ShaclSail shaclSail = new ShaclSail(new MemoryStore()); + shaclSail.setDebugPrintPlans(true); + SailRepository shaclRepository = new SailRepository(shaclSail); + shaclRepository.initialize(); + Utils.loadShapeData(shaclRepository, shaclFile); boolean exception = false; boolean ran = false; @@ -162,16 +145,18 @@ void runTestCase(String shaclPath, String dataPath, ExpectedResult expectedResul ran = true; System.out.println(name); - try (SailRepositoryConnection connection = shaclSail.getConnection()) { + try (SailRepositoryConnection connection = shaclRepository.getConnection()) { connection.begin(); String query = IOUtil.readString(resourceAsStream); connection.prepareUpdate(query).execute(); connection.commit(); - } catch (RepositoryException sailException) { + } + catch (RepositoryException sailException) { exception = true; System.out.println(sailException.getMessage()); - } catch (IOException e) { + } + catch (IOException e) { e.printStackTrace(); } @@ -179,14 +164,17 @@ void runTestCase(String shaclPath, String dataPath, ExpectedResult expectedResul if (ran) { if (expectedResult == ExpectedResult.valid) { assertFalse("Expected transaction to succeed", exception); - } else { + } + else { assertTrue("Expected transaction to fail", exception); } } } - void runTestCaseSingleTransaction(String shaclPath, String dataPath, ExpectedResult expectedResult) { + void runTestCaseSingleTransaction(String shaclPath, String dataPath, ExpectedResult expectedResult) + throws Exception + { if (!dataPath.endsWith("/")) { dataPath = dataPath + "/"; @@ -196,13 +184,15 @@ void runTestCaseSingleTransaction(String shaclPath, String dataPath, ExpectedRes shaclPath = shaclPath + "/"; } - SailRepository shaclSail = new SailRepository(new ShaclSail(new MemoryStore(), Utils.getSailRepository(shaclPath + "shacl.ttl"))); - shaclSail.initialize(); + ShaclSail shaclSail = new ShaclSail(new MemoryStore()); + SailRepository shaclRepository = new SailRepository(shaclSail); + shaclRepository.initialize(); + Utils.loadShapeData(shaclRepository, shaclPath + "shacl.ttl"); boolean exception = false; boolean ran = false; - try (SailRepositoryConnection shaclSailConnection = shaclSail.getConnection()) { + try (SailRepositoryConnection shaclSailConnection = shaclRepository.getConnection()) { shaclSailConnection.begin(IsolationLevels.SNAPSHOT); for (int j = 0; j < 100; j++) { @@ -220,7 +210,8 @@ void runTestCaseSingleTransaction(String shaclPath, String dataPath, ExpectedRes String query = IOUtil.readString(resourceAsStream); shaclSailConnection.prepareUpdate(query).execute(); - } catch (IOException e) { + } + catch (IOException e) { e.printStackTrace(); } } @@ -228,7 +219,8 @@ void runTestCaseSingleTransaction(String shaclPath, String dataPath, ExpectedRes try { shaclSailConnection.commit(); - } catch (RepositoryException sailException) { + } + catch (RepositoryException sailException) { exception = true; System.out.println(sailException.getMessage()); } @@ -236,7 +228,8 @@ void runTestCaseSingleTransaction(String shaclPath, String dataPath, ExpectedRes if (ran) { if (expectedResult == ExpectedResult.valid) { assertFalse(exception); - } else { + } + else { assertTrue(exception); } } @@ -244,8 +237,8 @@ void runTestCaseSingleTransaction(String shaclPath, String dataPath, ExpectedRes } enum ExpectedResult { - valid, invalid + valid, + invalid } - } diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/TempTest.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/TempTest.java index b067fbb44..c926583ae 100644 --- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/TempTest.java +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/TempTest.java @@ -13,7 +13,6 @@ import org.eclipse.rdf4j.repository.RepositoryException; import org.eclipse.rdf4j.repository.sail.SailRepository; import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; -import org.eclipse.rdf4j.sail.memory.MemoryStore; import org.eclipse.rdf4j.sail.shacl.planNodes.LoggingNode; import org.junit.Test; @@ -27,12 +26,12 @@ public class TempTest { } @Test - public void a() { + public void a() throws Exception { - SailRepository shaclSail = new SailRepository(new ShaclSail(new MemoryStore(), Utils.getSailRepository("shacl.ttl"))); - shaclSail.initialize(); + SailRepository shaclRepository = Utils.getInitializedShaclRepository("shacl.ttl"); + shaclRepository.initialize(); - try (SailRepositoryConnection connection = shaclSail.getConnection()) { + try (SailRepositoryConnection connection = shaclRepository.getConnection()) { connection.begin(); connection.add(RDFS.RESOURCE, RDF.TYPE, RDFS.RESOURCE); @@ -70,12 +69,11 @@ public void a() { } @Test - public void b() { + public void b() throws Exception { + SailRepository shaclRepository = Utils.getInitializedShaclRepository("shacl.ttl"); + shaclRepository.initialize(); - SailRepository shaclSail = new SailRepository(new ShaclSail(new MemoryStore(), Utils.getSailRepository("shacl.ttl"))); - shaclSail.initialize(); - - try (SailRepositoryConnection connection = shaclSail.getConnection()) { + try (SailRepositoryConnection connection = shaclRepository.getConnection()) { connection.begin(); // @@ -104,12 +102,11 @@ public void b() { @Test(expected = RepositoryException.class) - public void maxCount() { - - SailRepository shaclSail = new SailRepository(new ShaclSail(new MemoryStore(), Utils.getSailRepository("shaclMax.ttl"))); - shaclSail.initialize(); + public void maxCount() throws Exception { + SailRepository shaclRepository = Utils.getInitializedShaclRepository("shaclMax.ttl"); + shaclRepository.initialize(); - try (SailRepositoryConnection connection = shaclSail.getConnection()) { + try (SailRepositoryConnection connection = shaclRepository.getConnection()) { connection.begin(); // connection.add(RDFS.RESOURCE, RDF.TYPE, RDFS.RESOURCE); @@ -144,12 +141,12 @@ public void maxCount() { @Test - public void minCount() { + public void minCount() throws Exception { - SailRepository shaclSail = new SailRepository(new ShaclSail(new MemoryStore(), Utils.getSailRepository("shacl.ttl"))); - shaclSail.initialize(); + SailRepository shaclRepository = Utils.getInitializedShaclRepository("shacl.ttl"); + shaclRepository.initialize(); - try (SailRepositoryConnection connection = shaclSail.getConnection()) { + try (SailRepositoryConnection connection = shaclRepository.getConnection()) { connection.begin(); // connection.add(RDFS.RESOURCE, RDF.TYPE, RDFS.RESOURCE); @@ -175,12 +172,12 @@ public void minCount() { @Test - public void leftOuterJoin() { + public void leftOuterJoin() throws Exception { - SailRepository shaclSail = new SailRepository(new ShaclSail(new MemoryStore(), Utils.getSailRepository("shacl.ttl"))); - shaclSail.initialize(); + SailRepository shaclRepository = Utils.getInitializedShaclRepository("shacl.ttl"); + shaclRepository.initialize(); - try (SailRepositoryConnection connection = shaclSail.getConnection()) { + try (SailRepositoryConnection connection = shaclRepository.getConnection()) { connection.begin(); connection.add(RDFS.RESOURCE, RDF.TYPE, RDFS.CLASS); @@ -215,12 +212,12 @@ public void leftOuterJoin() { } @Test(expected = RepositoryException.class) - public void testShapeWithoutTargetClassRemove() { + public void testShapeWithoutTargetClassRemove() throws Exception { - SailRepository shaclSail = new SailRepository(new ShaclSail(new MemoryStore(), Utils.getSailRepository("shacleNoTargetClass.ttl"))); - shaclSail.initialize(); + SailRepository shaclRepository = Utils.getInitializedShaclRepository("shacleNoTargetClass.ttl"); + shaclRepository.initialize(); - try (SailRepositoryConnection connection = shaclSail.getConnection()) { + try (SailRepositoryConnection connection = shaclRepository.getConnection()) { connection.begin(); connection.add(RDFS.CLASS, RDFS.LABEL, connection.getValueFactory().createLiteral("class1")); @@ -238,12 +235,12 @@ public void testShapeWithoutTargetClassRemove() { @Test(expected = RepositoryException.class) - public void testShapeWithoutTargetClassAdd() { + public void testShapeWithoutTargetClassAdd() throws Exception { - SailRepository shaclSail = new SailRepository(new ShaclSail(new MemoryStore(), Utils.getSailRepository("shacleNoTargetClass.ttl"))); - shaclSail.initialize(); + SailRepository shaclRepository = Utils.getInitializedShaclRepository("shacleNoTargetClass.ttl"); + shaclRepository.initialize(); - try (SailRepositoryConnection connection = shaclSail.getConnection()) { + try (SailRepositoryConnection connection = shaclRepository.getConnection()) { connection.begin(); connection.add(RDFS.CLASS, RDFS.LABEL, connection.getValueFactory().createLiteral("class1")); @@ -260,12 +257,11 @@ public void testShapeWithoutTargetClassAdd() { } @Test - public void testShapeWithoutTargetClassValid() { + public void testShapeWithoutTargetClassValid() throws Exception { - SailRepository shaclSail = new SailRepository(new ShaclSail(new MemoryStore(), Utils.getSailRepository("shacleNoTargetClass.ttl"))); - shaclSail.initialize(); + SailRepository shaclRepository = Utils.getInitializedShaclRepository("shacleNoTargetClass.ttl"); - try (SailRepositoryConnection connection = shaclSail.getConnection()) { + try (SailRepositoryConnection connection = shaclRepository.getConnection()) { connection.begin(); connection.commit(); diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/TrackAddedStatementsTest.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/TrackAddedStatementsTest.java index b5ca56370..473f880ff 100644 --- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/TrackAddedStatementsTest.java +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/TrackAddedStatementsTest.java @@ -8,6 +8,10 @@ package org.eclipse.rdf4j.sail.shacl; +import static junit.framework.TestCase.assertEquals; +import static junit.framework.TestCase.assertNotNull; +import static junit.framework.TestCase.assertNull; + import org.eclipse.rdf4j.common.iteration.Iterations; import org.eclipse.rdf4j.model.vocabulary.RDF; import org.eclipse.rdf4j.model.vocabulary.RDFS; @@ -15,14 +19,9 @@ import org.eclipse.rdf4j.repository.RepositoryConnection; import org.eclipse.rdf4j.repository.sail.SailRepository; import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; -import org.eclipse.rdf4j.sail.memory.MemoryStore; import org.eclipse.rdf4j.sail.shacl.planNodes.LoggingNode; import org.junit.Test; -import static junit.framework.TestCase.assertEquals; -import static junit.framework.TestCase.assertNotNull; -import static junit.framework.TestCase.assertNull; - /** * @author Håvard Ottestad */ @@ -33,36 +32,35 @@ public class TrackAddedStatementsTest { } @Test - public void testCleanup() { + public void testCleanup() throws Exception { - SailRepository shaclSail = new SailRepository(new ShaclSail(new MemoryStore(), Utils.getSailRepository("empty.ttl"))); - shaclSail.initialize(); + SailRepository shaclRepository = Utils.getInitializedShaclRepository("empty.ttl"); + shaclRepository.initialize(); - try (SailRepositoryConnection connection = shaclSail.getConnection()) { + try (SailRepositoryConnection connection = shaclRepository.getConnection()) { connection.add(RDFS.RESOURCE, RDF.TYPE, RDFS.RESOURCE); - ShaclSailConnection shaclSailConnection = (ShaclSailConnection) connection.getSailConnection(); + ShaclSailConnection shaclSailConnection = (ShaclSailConnection)connection.getSailConnection(); assertNull(shaclSailConnection.getAddedStatements()); assertNull(shaclSailConnection.getAddedStatements()); - } } @Test - public void testTransactions() { + public void testTransactions() throws Exception { - SailRepository shaclSail = new SailRepository(new ShaclSail(new MemoryStore(), Utils.getSailRepository("empty.ttl"))); - shaclSail.initialize(); + SailRepository shaclRepository = Utils.getInitializedShaclRepository("empty.ttl"); + shaclRepository.initialize(); - try (SailRepositoryConnection connection = shaclSail.getConnection()) { + try (SailRepositoryConnection connection = shaclRepository.getConnection()) { connection.begin(); connection.add(RDFS.RESOURCE, RDF.TYPE, RDFS.RESOURCE); - ShaclSailConnection shaclSailConnection = (ShaclSailConnection) connection.getSailConnection(); + ShaclSailConnection shaclSailConnection = (ShaclSailConnection)connection.getSailConnection(); shaclSailConnection.fillAddedAndRemovedStatementRepositories(); assertNotNull(shaclSailConnection.getAddedStatements()); @@ -75,16 +73,16 @@ public void testTransactions() { } @Test - public void testRollback() { + public void testRollback() throws Exception { - SailRepository shaclSail = new SailRepository(new ShaclSail(new MemoryStore(), Utils.getSailRepository("empty.ttl"))); - shaclSail.initialize(); + SailRepository shaclRepository = Utils.getInitializedShaclRepository("empty.ttl"); + shaclRepository.initialize(); - try (SailRepositoryConnection connection = shaclSail.getConnection()) { + try (SailRepositoryConnection connection = shaclRepository.getConnection()) { connection.begin(); connection.add(RDFS.RESOURCE, RDF.TYPE, RDFS.RESOURCE); - ShaclSailConnection shaclSailConnection = (ShaclSailConnection) connection.getSailConnection(); + ShaclSailConnection shaclSailConnection = (ShaclSailConnection)connection.getSailConnection(); shaclSailConnection.fillAddedAndRemovedStatementRepositories(); assertNotNull(shaclSailConnection.getAddedStatements()); @@ -100,18 +98,17 @@ public void testRollback() { assertNull(shaclSailConnection.getAddedStatements()); assertNull(shaclSailConnection.getRemovedStatements()); - } } @Test - public void testValidationFailedCleanup() { + public void testValidationFailedCleanup() throws Exception { - SailRepository shaclSail = new SailRepository(new ShaclSail(new MemoryStore(), Utils.getSailRepository("shacl.ttl"))); - shaclSail.initialize(); + SailRepository shaclRepository = Utils.getInitializedShaclRepository("shacl.ttl"); + shaclRepository.initialize(); - try (SailRepositoryConnection connection = shaclSail.getConnection()) { + try (SailRepositoryConnection connection = shaclRepository.getConnection()) { connection.begin(); @@ -119,11 +116,12 @@ public void testValidationFailedCleanup() { try { connection.commit(); - } catch (Throwable e) { + } + catch (Throwable e) { System.out.println(e.getMessage()); } - ShaclSailConnection shaclSailConnection = (ShaclSailConnection) connection.getSailConnection(); + ShaclSailConnection shaclSailConnection = (ShaclSailConnection)connection.getSailConnection(); assertNull(shaclSailConnection.getAddedStatements()); assertNull(shaclSailConnection.getRemovedStatements()); @@ -133,12 +131,12 @@ public void testValidationFailedCleanup() { } @Test - public void testValidationFailedCausesRollback() { + public void testValidationFailedCausesRollback() throws Exception { - SailRepository shaclSail = new SailRepository(new ShaclSail(new MemoryStore(), Utils.getSailRepository("shacl.ttl"))); - shaclSail.initialize(); + SailRepository shaclRepository = Utils.getInitializedShaclRepository("shacl.ttl"); + shaclRepository.initialize(); - try (SailRepositoryConnection connection = shaclSail.getConnection()) { + try (SailRepositoryConnection connection = shaclRepository.getConnection()) { connection.begin(); @@ -146,49 +144,46 @@ public void testValidationFailedCausesRollback() { try { connection.commit(); - } catch (Throwable e) { + } + catch (Throwable e) { System.out.println(e.getMessage()); } assertEquals(0, size(connection)); - } } @Test - public void testCleanupOnClose() { + public void testCleanupOnClose() throws Exception { - SailRepository shaclSail = new SailRepository(new ShaclSail(new MemoryStore(), Utils.getSailRepository("shacl.ttl"))); - shaclSail.initialize(); + SailRepository shaclRepository = Utils.getInitializedShaclRepository("shacl.ttl"); + shaclRepository.initialize(); - SailRepositoryConnection connection = shaclSail.getConnection(); + SailRepositoryConnection connection = shaclRepository.getConnection(); connection.begin(); connection.add(RDFS.RESOURCE, RDF.TYPE, RDFS.RESOURCE); connection.close(); - ShaclSailConnection shaclSailConnection = (ShaclSailConnection) connection.getSailConnection(); + ShaclSailConnection shaclSailConnection = (ShaclSailConnection)connection.getSailConnection(); assertNull(shaclSailConnection.getAddedStatements()); assertNull(shaclSailConnection.getRemovedStatements()); - - assertEquals(0, size(shaclSail)); - + assertEquals(0, size(shaclRepository)); } - @Test - public void testAddRemoveAddRemove() { + public void testAddRemoveAddRemove() throws Exception { - SailRepository shaclSail = new SailRepository(new ShaclSail(new MemoryStore(), Utils.getSailRepository("empty.ttl"))); - shaclSail.initialize(); + SailRepository shaclRepository = Utils.getInitializedShaclRepository("empty.ttl"); + shaclRepository.initialize(); - try (SailRepositoryConnection connection = shaclSail.getConnection()) { + try (SailRepositoryConnection connection = shaclRepository.getConnection()) { connection.add(RDFS.RESOURCE, RDF.TYPE, RDFS.RESOURCE); connection.begin(); @@ -197,8 +192,7 @@ public void testAddRemoveAddRemove() { connection.add(RDFS.RESOURCE, RDF.TYPE, RDFS.RESOURCE); connection.remove(RDFS.RESOURCE, RDF.TYPE, RDFS.RESOURCE); - - ShaclSailConnection shaclSailConnection = (ShaclSailConnection) connection.getSailConnection(); + ShaclSailConnection shaclSailConnection = (ShaclSailConnection)connection.getSailConnection(); shaclSailConnection.fillAddedAndRemovedStatementRepositories(); assertEquals(0, size(shaclSailConnection.getAddedStatements())); @@ -208,82 +202,76 @@ public void testAddRemoveAddRemove() { } - } @Test - public void testAdd() { + public void testAdd() throws Exception { - SailRepository shaclSail = new SailRepository(new ShaclSail(new MemoryStore(), Utils.getSailRepository("empty.ttl"))); - shaclSail.initialize(); + SailRepository shaclRepository = Utils.getInitializedShaclRepository("empty.ttl"); + shaclRepository.initialize(); - try (SailRepositoryConnection connection = shaclSail.getConnection()) { + try (SailRepositoryConnection connection = shaclRepository.getConnection()) { connection.begin(); //System.out.println(size(connection)); connection.add(RDFS.RESOURCE, RDF.TYPE, RDFS.RESOURCE); -// System.out.println(size(connection)); + // System.out.println(size(connection)); connection.remove(RDFS.RESOURCE, RDF.TYPE, RDFS.RESOURCE); -// System.out.println(size(connection)); + // System.out.println(size(connection)); connection.add(RDFS.RESOURCE, RDF.TYPE, RDFS.RESOURCE); -// System.out.println(size(connection)); + // System.out.println(size(connection)); - ShaclSailConnection shaclSailConnection = (ShaclSailConnection) connection.getSailConnection(); + ShaclSailConnection shaclSailConnection = (ShaclSailConnection)connection.getSailConnection(); shaclSailConnection.fillAddedAndRemovedStatementRepositories(); assertEquals(1, size(shaclSailConnection.getAddedStatements())); assertEquals(0, size(shaclSailConnection.getRemovedStatements())); - connection.commit(); System.out.println(size(connection)); - } } @Test - public void testAddRemove() { + public void testAddRemove() throws Exception { - SailRepository shaclSail = new SailRepository(new ShaclSail(new MemoryStore(), Utils.getSailRepository("empty.ttl"))); - shaclSail.initialize(); + SailRepository shaclRepository = Utils.getInitializedShaclRepository("empty.ttl"); + shaclRepository.initialize(); - try (SailRepositoryConnection connection = shaclSail.getConnection()) { + try (SailRepositoryConnection connection = shaclRepository.getConnection()) { connection.begin(); -// System.out.println(size(connection)); + // System.out.println(size(connection)); connection.add(RDFS.RESOURCE, RDF.TYPE, RDFS.RESOURCE); -// System.out.println(size(connection)); + // System.out.println(size(connection)); connection.remove(RDFS.RESOURCE, RDF.TYPE, RDFS.RESOURCE); -// System.out.println(size(connection)); - + // System.out.println(size(connection)); - ShaclSailConnection shaclSailConnection = (ShaclSailConnection) connection.getSailConnection(); + ShaclSailConnection shaclSailConnection = (ShaclSailConnection)connection.getSailConnection(); shaclSailConnection.fillAddedAndRemovedStatementRepositories(); assertEquals(0, size(shaclSailConnection.getAddedStatements())); assertEquals(0, size(shaclSailConnection.getRemovedStatements())); - connection.commit(); System.out.println(size(connection)); - } } @Test - public void testRemove() { + public void testRemove() throws Exception { - SailRepository shaclSail = new SailRepository(new ShaclSail(new MemoryStore(), Utils.getSailRepository("empty.ttl"))); - shaclSail.initialize(); + SailRepository shaclRepository = Utils.getInitializedShaclRepository("empty.ttl"); + shaclRepository.initialize(); - try (SailRepositoryConnection connection = shaclSail.getConnection()) { + try (SailRepositoryConnection connection = shaclRepository.getConnection()) { connection.add(RDFS.RESOURCE, RDF.TYPE, RDFS.RESOURCE); connection.begin(); @@ -293,7 +281,7 @@ public void testRemove() { connection.remove(RDFS.RESOURCE, RDF.TYPE, RDFS.RESOURCE); connection.remove(RDFS.RESOURCE, RDF.TYPE, RDFS.RESOURCE); - ShaclSailConnection shaclSailConnection = (ShaclSailConnection) connection.getSailConnection(); + ShaclSailConnection shaclSailConnection = (ShaclSailConnection)connection.getSailConnection(); shaclSailConnection.fillAddedAndRemovedStatementRepositories(); assertEquals(0, size(shaclSailConnection.getAddedStatements())); @@ -305,18 +293,18 @@ public void testRemove() { } @Test - public void testRemoveWithoutAdding() { + public void testRemoveWithoutAdding() throws Exception { - SailRepository shaclSail = new SailRepository(new ShaclSail(new MemoryStore(), Utils.getSailRepository("empty.ttl"))); - shaclSail.initialize(); + SailRepository shaclRepository = Utils.getInitializedShaclRepository("empty.ttl"); + shaclRepository.initialize(); - try (SailRepositoryConnection connection = shaclSail.getConnection()) { + try (SailRepositoryConnection connection = shaclRepository.getConnection()) { connection.begin(); connection.remove(RDFS.RESOURCE, RDF.TYPE, RDFS.RESOURCE); - ShaclSailConnection shaclSailConnection = (ShaclSailConnection) connection.getSailConnection(); + ShaclSailConnection shaclSailConnection = (ShaclSailConnection)connection.getSailConnection(); shaclSailConnection.fillAddedAndRemovedStatementRepositories(); assertEquals(0, size(shaclSailConnection.getAddedStatements())); @@ -328,42 +316,41 @@ public void testRemoveWithoutAdding() { } @Test - public void testSingleRemove() { + public void testSingleRemove() throws Exception { - SailRepository shaclSail = new SailRepository(new ShaclSail(new MemoryStore(), Utils.getSailRepository("empty.ttl"))); - shaclSail.initialize(); + SailRepository shaclRepository = Utils.getInitializedShaclRepository("empty.ttl"); + shaclRepository.initialize(); - try (SailRepositoryConnection connection = shaclSail.getConnection()) { + try (SailRepositoryConnection connection = shaclRepository.getConnection()) { connection.add(RDFS.RESOURCE, RDF.TYPE, RDFS.RESOURCE); connection.begin(); connection.remove(RDFS.RESOURCE, RDF.TYPE, RDFS.RESOURCE); - ShaclSailConnection shaclSailConnection = (ShaclSailConnection) connection.getSailConnection(); + ShaclSailConnection shaclSailConnection = (ShaclSailConnection)connection.getSailConnection(); shaclSailConnection.fillAddedAndRemovedStatementRepositories(); assertEquals(0, size(shaclSailConnection.getAddedStatements())); assertEquals(1, size(shaclSailConnection.getRemovedStatements())); - connection.commit(); } } @Test - public void testSingleAdd() { + public void testSingleAdd() throws Exception { - SailRepository shaclSail = new SailRepository(new ShaclSail(new MemoryStore(), Utils.getSailRepository("empty.ttl"))); - shaclSail.initialize(); + SailRepository shaclRepository = Utils.getInitializedShaclRepository("empty.ttl"); + shaclRepository.initialize(); - try (SailRepositoryConnection connection = shaclSail.getConnection()) { + try (SailRepositoryConnection connection = shaclRepository.getConnection()) { connection.begin(); connection.add(RDFS.RESOURCE, RDF.TYPE, RDFS.RESOURCE); - ShaclSailConnection shaclSailConnection = (ShaclSailConnection) connection.getSailConnection(); + ShaclSailConnection shaclSailConnection = (ShaclSailConnection)connection.getSailConnection(); shaclSailConnection.fillAddedAndRemovedStatementRepositories(); assertEquals(1, size(shaclSailConnection.getAddedStatements())); @@ -374,14 +361,15 @@ public void testSingleAdd() { } } - private static long size(RepositoryConnection connection) { - return Iterations.stream(connection.getStatements(null, null, null)).peek(System.out::println).count(); + return Iterations.stream(connection.getStatements(null, null, null)).peek( + System.out::println).count(); } private static long size(Repository repo) { try (RepositoryConnection connection = repo.getConnection()) { - return Iterations.stream(connection.getStatements(null, null, null)).peek(System.out::println).count(); + return Iterations.stream(connection.getStatements(null, null, null)).peek( + System.out::println).count(); } } diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/Utils.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/Utils.java index 68b8177e8..8dd54b7c5 100644 --- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/Utils.java +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/Utils.java @@ -8,40 +8,80 @@ package org.eclipse.rdf4j.sail.shacl; +import java.io.IOException; +import java.io.InputStream; +import java.util.UUID; + +import org.eclipse.rdf4j.RDF4JException; import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.Statement; import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.repository.RepositoryConnection; import org.eclipse.rdf4j.repository.sail.SailRepository; -import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; import org.eclipse.rdf4j.rio.RDFFormat; +import org.eclipse.rdf4j.rio.Rio; +import org.eclipse.rdf4j.rio.UnsupportedRDFormatException; +import org.eclipse.rdf4j.sail.SailConnection; import org.eclipse.rdf4j.sail.memory.MemoryStore; -import java.io.IOException; -import java.util.UUID; - /** * @author Håvard Ottestad */ public class Utils { - public static SailRepository getSailRepository(String resourceName) { - SailRepository sailRepository = new SailRepository(new MemoryStore()); - sailRepository.initialize(); - try (SailRepositoryConnection connection = sailRepository.getConnection()) { - connection.add(Utils.class.getClassLoader().getResourceAsStream(resourceName), "", RDFFormat.TURTLE); - } catch (IOException | NullPointerException e) { - System.out.println("Error reading: " + resourceName); - throw new RuntimeException(e); + public static void loadShapeData(ShaclSail sail, String resourceName) + throws RDF4JException, UnsupportedRDFormatException, IOException + { + InputStream shapesData = Utils.class.getResourceAsStream("/" + resourceName); + Model shapes = Rio.parse(shapesData, "", RDFFormat.TURTLE, ShaclSail.SHAPE_GRAPH); + try (SailConnection conn = sail.getConnection()) { + conn.begin(); + for (Statement st : shapes) { + conn.addStatement(st.getSubject(), st.getPredicate(), st.getContext(), ShaclSail.SHAPE_GRAPH); + } + conn.commit(); } - return sailRepository; + } + public static void loadShapeData(SailRepository repo, String resourceName) + throws RDF4JException, UnsupportedRDFormatException, IOException + { + InputStream shapesData = Utils.class.getResourceAsStream("/" + resourceName); + Model shapes = Rio.parse(shapesData, "", RDFFormat.TURTLE, ShaclSail.SHAPE_GRAPH); + try (RepositoryConnection conn = repo.getConnection()) { + conn.begin(); + for (Statement st : shapes) { + conn.add(st.getSubject(), st.getPredicate(), st.getContext(), ShaclSail.SHAPE_GRAPH); + } + conn.commit(); + } + + } + + public static SailRepository getInitializedShaclRepository(String shapeData) throws Exception { + SailRepository repo = new SailRepository(new ShaclSail(new MemoryStore())); + repo.initialize(); + Utils.loadShapeData(repo, shapeData); + return repo; + } + + public static ShaclSail getInitializedShaclSail(String shapeData) throws Exception { + ShaclSail sail = new ShaclSail(new MemoryStore()); + sail.initialize(); + Utils.loadShapeData(sail, shapeData); + return sail; + } static class Ex { public final static String ns = "http://example.com/ns#"; public final static IRI Person = createIri("Person"); + public final static IRI ssn = createIri("ssn"); + public final static IRI name = createIri("name"); public static IRI createIri(String name) { diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/VisulizerTest.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/VisulizerTest.java index b62036599..bdcb6d944 100644 --- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/VisulizerTest.java +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/VisulizerTest.java @@ -13,12 +13,10 @@ public class VisulizerTest { @Test - public void datatype() { + public void datatype() throws Exception { - ShaclSail shaclSail = new ShaclSail(new MemoryStore(), Utils.getSailRepository("shaclDatatype.ttl")); - shaclSail.initialize(); - + ShaclSail shaclSail = Utils.getInitializedShaclSail("shaclDatatype.ttl"); try (NotifyingSailConnection connection = shaclSail.getConnection()) { SimpleValueFactory vf = SimpleValueFactory.getInstance(); @@ -43,12 +41,10 @@ public void datatype() { } @Test - public void maxCount() { - + public void maxCount() throws Exception { - ShaclSail shaclSail = new ShaclSail(new MemoryStore(), Utils.getSailRepository("shaclMax.ttl")); - shaclSail.initialize(); + ShaclSail shaclSail = Utils.getInitializedShaclSail("shaclMax.ttl"); try (NotifyingSailConnection connection = shaclSail.getConnection()) { SimpleValueFactory vf = SimpleValueFactory.getInstance(); @@ -72,12 +68,10 @@ public void maxCount() { } @Test(expected = SailException.class) - public void minCount() { - + public void minCount() throws Exception { - ShaclSail shaclSail = new ShaclSail(new MemoryStore(), Utils.getSailRepository("shacl.ttl")); - shaclSail.initialize(); + ShaclSail shaclSail = Utils.getInitializedShaclSail("shacl.ttl"); try (NotifyingSailConnection connection = shaclSail.getConnection()) { SimpleValueFactory vf = SimpleValueFactory.getInstance(); diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/DatatypeBenchmarkEmpty.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/DatatypeBenchmarkEmpty.java index 72d56da00..1fc38253b 100644 --- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/DatatypeBenchmarkEmpty.java +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/DatatypeBenchmarkEmpty.java @@ -87,9 +87,9 @@ public void tearDown() { @Benchmark - public void shacl() { + public void shacl() throws Exception { - SailRepository repository = new SailRepository(new ShaclSail(new MemoryStore(), Utils.getSailRepository("shaclDatatype.ttl"))); + SailRepository repository = new SailRepository(Utils.getInitializedShaclSail("shaclDatatype.ttl")); repository.initialize(); diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/DatatypeBenchmarkPrefilled.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/DatatypeBenchmarkPrefilled.java index edf057865..4ed8efd88 100644 --- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/DatatypeBenchmarkPrefilled.java +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/DatatypeBenchmarkPrefilled.java @@ -58,7 +58,7 @@ public class DatatypeBenchmarkPrefilled { @Setup(Level.Invocation) - public void setUp() { + public void setUp() throws Exception { allStatements = new ArrayList<>(10); SimpleValueFactory vf = SimpleValueFactory.getInstance(); @@ -88,7 +88,7 @@ public void setUp() { } - ShaclSail shaclRepo = new ShaclSail(new MemoryStore(), Utils.getSailRepository("shaclDatatype.ttl")); + ShaclSail shaclRepo = Utils.getInitializedShaclSail("shaclDatatype.ttl"); this.shaclRepo = new SailRepository(shaclRepo); this.shaclRepo.initialize(); diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/MinCountBenchmarkEmpty.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/MinCountBenchmarkEmpty.java index 15b3b741a..f6e5a4a48 100644 --- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/MinCountBenchmarkEmpty.java +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/MinCountBenchmarkEmpty.java @@ -84,9 +84,9 @@ public void tearDown() { @Benchmark - public void shacl() { + public void shacl() throws Exception { - SailRepository repository = new SailRepository(new ShaclSail(new MemoryStore(), Utils.getSailRepository("shacl.ttl"))); + SailRepository repository = new SailRepository(Utils.getInitializedShaclSail("shacl.ttl")); repository.initialize(); diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/MinCountBenchmarkPrefilled.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/MinCountBenchmarkPrefilled.java index 8834d958c..6725fcbc3 100644 --- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/MinCountBenchmarkPrefilled.java +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/MinCountBenchmarkPrefilled.java @@ -57,7 +57,7 @@ public class MinCountBenchmarkPrefilled { @Setup(Level.Invocation) - public void setUp() { + public void setUp() throws Exception { allStatements = new ArrayList<>(10); SimpleValueFactory vf = SimpleValueFactory.getInstance(); @@ -87,7 +87,7 @@ public void setUp() { } - ShaclSail shaclRepo = new ShaclSail(new MemoryStore(), Utils.getSailRepository("shacl.ttl")); + ShaclSail shaclRepo = Utils.getInitializedShaclSail("shacl.ttl"); this.shaclRepo = new SailRepository(shaclRepo); this.shaclRepo.initialize(); diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/MinCountPrefilledVsEmptyBenchmark.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/MinCountPrefilledVsEmptyBenchmark.java index 49f7bd6e6..94d1d3477 100644 --- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/MinCountPrefilledVsEmptyBenchmark.java +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/MinCountPrefilledVsEmptyBenchmark.java @@ -51,7 +51,7 @@ public class MinCountPrefilledVsEmptyBenchmark { @Setup(Level.Invocation) - public void setUp() { + public void setUp() throws Exception { allStatements = new ArrayList<>(10); @@ -82,7 +82,7 @@ public void setUp() { } - ShaclSail shaclRepo = new ShaclSail(new MemoryStore(), Utils.getSailRepository("shacl.ttl")); + ShaclSail shaclRepo = Utils.getInitializedShaclSail("shacl.ttl"); this.shaclRepo = new SailRepository(shaclRepo); this.shaclRepo.initialize(); @@ -122,9 +122,9 @@ public void shaclPrefilled() { @Benchmark - public void shaclEmpty() { + public void shaclEmpty() throws Exception { - ShaclSail shaclRepo = new ShaclSail(new MemoryStore(), Utils.getSailRepository("shacl.ttl")); + ShaclSail shaclRepo = Utils.getInitializedShaclSail("shacl.ttl"); SailRepository repository = new SailRepository(shaclRepo); repository.initialize(); @@ -144,9 +144,9 @@ public void shaclEmpty() { } @Benchmark - public void shaclEmptyJustInitialize() { + public void shaclEmptyJustInitialize() throws Exception { - ShaclSail shaclRepo = new ShaclSail(new MemoryStore(), Utils.getSailRepository("shacl.ttl")); + ShaclSail shaclRepo = Utils.getInitializedShaclSail("shacl.ttl"); SailRepository repository = new SailRepository(shaclRepo); repository.initialize(); @@ -155,9 +155,9 @@ public void shaclEmptyJustInitialize() { @Benchmark - public void shaclEmptyJustInitializeAndEmptyTransaction() { + public void shaclEmptyJustInitializeAndEmptyTransaction() throws Exception { - ShaclSail shaclRepo = new ShaclSail(new MemoryStore(), Utils.getSailRepository("shacl.ttl")); + ShaclSail shaclRepo = Utils.getInitializedShaclSail("shacl.ttl"); SailRepository repository = new SailRepository(shaclRepo); repository.initialize(); From 5a2f5ae7e333979755deee60b8082f4fd5b9ec6c Mon Sep 17 00:00:00 2001 From: Jeen Broekstra Date: Sun, 13 Jan 2019 17:28:36 +1100 Subject: [PATCH 27/54] fixed missing license header --- .../java/org/eclipse/rdf4j/sail/shacl/VisulizerTest.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/VisulizerTest.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/VisulizerTest.java index bdcb6d944..3604e9277 100644 --- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/VisulizerTest.java +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/VisulizerTest.java @@ -1,3 +1,11 @@ +/******************************************************************************* + * Copyright (c) 2018 Eclipse RDF4J contributors. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ + package org.eclipse.rdf4j.sail.shacl; import org.eclipse.rdf4j.model.BNode; From ddd8b19847cefc7a6a2509574a6d519ca39ec4dc Mon Sep 17 00:00:00 2001 From: Jeen Broekstra Date: Mon, 14 Jan 2019 19:47:44 +1100 Subject: [PATCH 28/54] fixed shape upload and per-connection update of NodeShape list --- .../eclipse/rdf4j/sail/shacl/ShaclSail.java | 47 +++++++++---------- .../rdf4j/sail/shacl/ShaclSailConnection.java | 31 ++++++++++-- .../sail/shacl/ReduceNumberOfPlansTest.java | 10 ++-- .../org/eclipse/rdf4j/sail/shacl/Utils.java | 4 +- 4 files changed, 56 insertions(+), 36 deletions(-) diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSail.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSail.java index de8e26216..513d689da 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSail.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSail.java @@ -12,6 +12,7 @@ import java.io.IOException; import java.nio.file.Files; import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; import org.apache.commons.io.IOUtils; import org.eclipse.rdf4j.model.IRI; @@ -35,16 +36,18 @@ * A {@link Sail} implementation that adds support for the Shapes Constraint Language (SHACL) * * @author Heshan Jayasinghe + * @author Håvard Ottestad * @see SHACL W3C Recommendation */ public class ShaclSail extends NotifyingSailWrapper { /** - * The virtual context identifier for persisting the SHACL shapes information. + * The virtual context identifier for persisting the SHACL shapes information. */ - public final static IRI SHAPE_GRAPH = SimpleValueFactory.getInstance().createIRI("http://rdf4j.org/schema/schacl#ShapeGraph"); - - public List nodeShapes; + public final static IRI SHAPE_GRAPH = SimpleValueFactory.getInstance().createIRI( + "http://rdf4j.org/schema/schacl#ShapeGraph"); + + private List nodeShapes; boolean debugPrintPlans = false; @@ -58,7 +61,7 @@ public class ShaclSail extends NotifyingSailWrapper { * an initialized {@link Repository} for storing/retrieving Shapes data */ private SailRepository shapesRepo; - + static { try { SH_OR_UPDATE_QUERY = IOUtils.toString( @@ -83,16 +86,17 @@ public ShaclSail(NotifyingSail baseSail) { } else { try { - path = Files.createTempDirectory("shacl-shapes").toString(); - } catch (IOException e) { + path = Files.createTempDirectory("shacl-shapes").toString(); + } + catch (IOException e) { throw new SailConfigException(e); } } if (path.endsWith("/")) { - path = path.substring(0, path.length() -1); + path = path.substring(0, path.length() - 1); } path = path + "-shapes-graph/"; - + shapesRepo = new SailRepository(new MemoryStore(new File(path))); shapesRepo.initialize(); } @@ -100,12 +104,16 @@ public ShaclSail(NotifyingSail baseSail) { @Override public void initialize() throws SailException { super.initialize(); + refreshShapes(); + } + + protected void refreshShapes() throws SailException { try (SailRepositoryConnection shapesRepoConnection = shapesRepo.getConnection()) { runInferencingSparqlQueries(shapesRepoConnection); nodeShapes = NodeShape.Factory.getShapes(shapesRepoConnection); } } - + @Override public void shutDown() throws SailException { try { @@ -116,12 +124,10 @@ public void shutDown() throws SailException { } super.shutDown(); } - - @Override public NotifyingSailConnection getConnection() throws SailException { - return new ShaclSailConnection(this, super.getConnection(), super.getConnection()); + return new ShaclSailConnection(this, super.getConnection(), super.getConnection(), shapesRepo.getConnection()); } public void disableValidation() { @@ -140,20 +146,11 @@ public void setDebugPrintPlans(boolean debugPrintPlans) { this.debugPrintPlans = debugPrintPlans; } - protected void addShapesStatement(Resource subj, IRI pred, Value obj) { - try (RepositoryConnection conn = shapesRepo.getConnection()) { - conn.add(subj, pred, obj); - } + protected List getNodeShapes() { + return nodeShapes; } - - protected void removeShapesStatements(Resource subj, IRI pred, Value obj) { - try (RepositoryConnection conn = shapesRepo.getConnection()) { - conn.remove(subj, pred, obj); - } - } - - private void runInferencingSparqlQueries(SailRepositoryConnection shaclSailConnection) { + private void runInferencingSparqlQueries(SailRepositoryConnection shaclSailConnection) { long prevSize; long currentSize = shaclSailConnection.size(); diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java index f5ee0d97b..5dcb2380a 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java @@ -18,6 +18,7 @@ import org.eclipse.rdf4j.repository.Repository; import org.eclipse.rdf4j.repository.RepositoryConnection; import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; import org.eclipse.rdf4j.sail.NotifyingSailConnection; import org.eclipse.rdf4j.sail.SailConnectionListener; import org.eclipse.rdf4j.sail.SailException; @@ -47,6 +48,8 @@ public class ShaclSailConnection extends NotifyingSailConnectionWrapper { private Repository removedStatements; + private boolean isShapeRefreshNeeded = false; + public final ShaclSail sail; public Stats stats; @@ -55,11 +58,14 @@ public class ShaclSailConnection extends NotifyingSailConnectionWrapper { private HashSet removedStatementsSet = new HashSet<>(); + private SailRepositoryConnection shapesConnection; + ShaclSailConnection(ShaclSail sail, NotifyingSailConnection connection, - NotifyingSailConnection previousStateConnection) + NotifyingSailConnection previousStateConnection, SailRepositoryConnection shapesConnection) { super(connection); this.previousStateConnection = previousStateConnection; + this.shapesConnection = shapesConnection; this.sail = sail; if (sail.config.validationEnabled) { @@ -116,6 +122,7 @@ public void begin(IsolationLevel level) throws SailException { // start two transactions, synchronize on underlying sail so that we get two transactions immediatly successivley synchronized (sail) { super.begin(level); + shapesConnection.begin(IsolationLevels.SERIALIZABLE); previousStateConnection.begin(IsolationLevels.SNAPSHOT); } @@ -141,6 +148,8 @@ public void commit() throws SailException { throw new SailException("Failed SHACL validation"); } else { + shapesConnection.commit(); + refreshShapes(); super.commit(); } } @@ -153,7 +162,8 @@ public void commit() throws SailException { @Override public void addStatement(Resource subj, IRI pred, Value obj, Resource... contexts) throws SailException { if (contexts.length == 1 && contexts[0].equals(ShaclSail.SHAPE_GRAPH)) { - sail.addShapesStatement(subj, pred, obj); + shapesConnection.add(subj, pred, obj); + isShapeRefreshNeeded = true; } else { super.addStatement(subj, pred, obj, contexts); @@ -165,7 +175,8 @@ public void removeStatements(Resource subj, IRI pred, Value obj, Resource... con throws SailException { if (contexts.length == 1 && contexts[0].equals(ShaclSail.SHAPE_GRAPH)) { - sail.removeShapesStatements(subj, pred, obj); + shapesConnection.remove(subj, pred, obj); + isShapeRefreshNeeded = true; } else { super.removeStatements(subj, pred, obj, contexts); @@ -177,6 +188,7 @@ public void rollback() throws SailException { synchronized (sail) { previousStateConnection.commit(); cleanup(); + shapesConnection.rollback(); super.rollback(); } } @@ -194,8 +206,16 @@ private void cleanup() { addedStatementsSet.clear(); removedStatementsSet.clear(); stats = null; + isShapeRefreshNeeded = false; } + private void refreshShapes() { + if (isShapeRefreshNeeded) { + this.sail.refreshShapes(); + isShapeRefreshNeeded = false; + } + } + private boolean validate() { if (!sail.config.validationEnabled) { @@ -206,7 +226,8 @@ private boolean validate() { boolean allValid = true; - for (NodeShape nodeShape : sail.nodeShapes) { + final List nodeShapes = NodeShape.Factory.getShapes(shapesConnection); + for (NodeShape nodeShape : nodeShapes) { List planNodes = nodeShape.generatePlans(this, nodeShape, sail.debugPrintPlans); for (PlanNode planNode : planNodes) { try (Stream stream = Iterations.stream(planNode.iterator())) { @@ -258,6 +279,8 @@ synchronized public void close() throws SailException { if (isActive()) { rollback(); } + shapesConnection.close(); + previousStateConnection.close(); super.close(); } diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ReduceNumberOfPlansTest.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ReduceNumberOfPlansTest.java index 95215371d..856889d80 100644 --- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ReduceNumberOfPlansTest.java +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ReduceNumberOfPlansTest.java @@ -41,7 +41,7 @@ public void testAddingTypeStatement() connection.begin(); connection.fillAddedAndRemovedStatementRepositories(); - List collect = shaclSail.nodeShapes.stream().flatMap( + List collect = shaclSail.getNodeShapes().stream().flatMap( shape -> shape.generatePlans(connection, shape, false).stream()).collect( Collectors.toList()); @@ -51,7 +51,7 @@ public void testAddingTypeStatement() connection.addStatement(person1, RDF.TYPE, Utils.Ex.Person); connection.fillAddedAndRemovedStatementRepositories(); - List collect2 = shaclSail.nodeShapes.stream().flatMap( + List collect2 = shaclSail.getNodeShapes().stream().flatMap( shape -> shape.generatePlans(connection, shape, false).stream()).collect( Collectors.toList()); @@ -92,7 +92,7 @@ public void testRemovingPredicate() throws RDF4JException, UnsupportedRDFormatEx connection.fillAddedAndRemovedStatementRepositories(); - List collect1 = shaclSail.nodeShapes.stream().flatMap( + List collect1 = shaclSail.getNodeShapes().stream().flatMap( shape -> shape.generatePlans(connection, shape, false).stream()).collect( Collectors.toList()); assertEquals(1, collect1.size()); @@ -101,7 +101,7 @@ public void testRemovingPredicate() throws RDF4JException, UnsupportedRDFormatEx connection.fillAddedAndRemovedStatementRepositories(); - List collect2 = shaclSail.nodeShapes.stream().flatMap( + List collect2 = shaclSail.getNodeShapes().stream().flatMap( shape -> shape.generatePlans(connection, shape, false).stream()).collect( Collectors.toList()); assertEquals(1, collect2.size()); @@ -109,7 +109,7 @@ public void testRemovingPredicate() throws RDF4JException, UnsupportedRDFormatEx connection.removeStatements(person1, Utils.Ex.name, vf.createLiteral("c")); connection.fillAddedAndRemovedStatementRepositories(); - List collect3 = shaclSail.nodeShapes.stream().flatMap( + List collect3 = shaclSail.getNodeShapes().stream().flatMap( shape -> shape.generatePlans(connection, shape, false).stream()).collect( Collectors.toList()); assertEquals(2, collect3.size()); diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/Utils.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/Utils.java index 8dd54b7c5..7596ecec1 100644 --- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/Utils.java +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/Utils.java @@ -38,7 +38,7 @@ public static void loadShapeData(ShaclSail sail, String resourceName) try (SailConnection conn = sail.getConnection()) { conn.begin(); for (Statement st : shapes) { - conn.addStatement(st.getSubject(), st.getPredicate(), st.getContext(), ShaclSail.SHAPE_GRAPH); + conn.addStatement(st.getSubject(), st.getPredicate(), st.getObject(), ShaclSail.SHAPE_GRAPH); } conn.commit(); } @@ -53,7 +53,7 @@ public static void loadShapeData(SailRepository repo, String resourceName) try (RepositoryConnection conn = repo.getConnection()) { conn.begin(); for (Statement st : shapes) { - conn.add(st.getSubject(), st.getPredicate(), st.getContext(), ShaclSail.SHAPE_GRAPH); + conn.add(st.getSubject(), st.getPredicate(), st.getObject(), ShaclSail.SHAPE_GRAPH); } conn.commit(); } From 1628cf9e38f21cbb11de5a3b4ce14e7076195e48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Avard=20Ottestad?= Date: Wed, 16 Jan 2019 10:34:22 +0100 Subject: [PATCH 29/54] eclipse/rdf4j#1113 fixed code to support loading of shacl shapes after initialization but with the limitations that they can not be modified once they are loaded. Also added an exception if someone attempts to validate without having added shapes. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håvard Ottestad --- .../sail/shacl/NoShapesLoadedException.java | 8 ++ .../eclipse/rdf4j/sail/shacl/ShaclSail.java | 79 ++++++++++-------- .../rdf4j/sail/shacl/ShaclSailConnection.java | 81 ++++++++++--------- .../sail/shacl/RuntimeModifyShapesTest.java | 62 ++++++++++++++ .../sail/shacl/TrackAddedStatementsTest.java | 43 +++++----- shacl/src/test/resources/empty.ttl | 16 ++++ 6 files changed, 193 insertions(+), 96 deletions(-) create mode 100644 shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/NoShapesLoadedException.java create mode 100644 shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/RuntimeModifyShapesTest.java diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/NoShapesLoadedException.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/NoShapesLoadedException.java new file mode 100644 index 000000000..eaf48baa9 --- /dev/null +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/NoShapesLoadedException.java @@ -0,0 +1,8 @@ +package org.eclipse.rdf4j.sail.shacl; + +public class NoShapesLoadedException extends RuntimeException { + + public NoShapesLoadedException() { + super("Load shapes by adding them to named graph <"+ShaclSail.SHAPE_GRAPH+"> in the first transaction after initialization!"); + } +} diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSail.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSail.java index 513d689da..33dc4001f 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSail.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSail.java @@ -8,19 +8,10 @@ package org.eclipse.rdf4j.sail.shacl; -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; - import org.apache.commons.io.IOUtils; import org.eclipse.rdf4j.model.IRI; -import org.eclipse.rdf4j.model.Resource; -import org.eclipse.rdf4j.model.Value; import org.eclipse.rdf4j.model.impl.SimpleValueFactory; import org.eclipse.rdf4j.repository.Repository; -import org.eclipse.rdf4j.repository.RepositoryConnection; import org.eclipse.rdf4j.repository.sail.SailRepository; import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; import org.eclipse.rdf4j.sail.NotifyingSail; @@ -32,9 +23,14 @@ import org.eclipse.rdf4j.sail.memory.MemoryStore; import org.eclipse.rdf4j.sail.shacl.AST.NodeShape; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.List; + /** * A {@link Sail} implementation that adds support for the Shapes Constraint Language (SHACL) - * + * * @author Heshan Jayasinghe * @author Håvard Ottestad * @see SHACL W3C Recommendation @@ -44,10 +40,12 @@ public class ShaclSail extends NotifyingSailWrapper { /** * The virtual context identifier for persisting the SHACL shapes information. */ - public final static IRI SHAPE_GRAPH = SimpleValueFactory.getInstance().createIRI( - "http://rdf4j.org/schema/schacl#ShapeGraph"); + @SuppressWarnings("WeakerAccess") + public final static IRI SHAPE_GRAPH = SimpleValueFactory + .getInstance() + .createIRI("http://rdf4j.org/schema/schacl#ShapeGraph"); - private List nodeShapes; + List nodeShapes; boolean debugPrintPlans = false; @@ -65,14 +63,18 @@ public class ShaclSail extends NotifyingSailWrapper { static { try { SH_OR_UPDATE_QUERY = IOUtils.toString( - ShaclSail.class.getClassLoader().getResourceAsStream("shacl-sparql-inference/sh_or.rq"), - "UTF-8"); + ShaclSail + .class + .getClassLoader() + .getResourceAsStream("shacl-sparql-inference/sh_or.rq"), + "UTF-8"); SH_OR_NODE_SHAPE_UPDATE_QUERY = IOUtils.toString( - ShaclSail.class.getClassLoader().getResourceAsStream( - "shacl-sparql-inference/sh_or_node_shape.rq"), - "UTF-8"); - } - catch (IOException e) { + ShaclSail + .class + .getClassLoader() + .getResourceAsStream("shacl-sparql-inference/sh_or_node_shape.rq"), + "UTF-8"); + } catch (IOException e) { throw new IllegalStateException(e); } @@ -83,12 +85,10 @@ public ShaclSail(NotifyingSail baseSail) { String path = null; if (baseSail.getDataDir() != null) { path = baseSail.getDataDir().getPath(); - } - else { + } else { try { path = Files.createTempDirectory("shacl-shapes").toString(); - } - catch (IOException e) { + } catch (IOException e) { throw new SailConfigException(e); } } @@ -104,22 +104,32 @@ public ShaclSail(NotifyingSail baseSail) { @Override public void initialize() throws SailException { super.initialize(); - refreshShapes(); + try (SailRepositoryConnection shapesRepoConnection = shapesRepo.getConnection()) { + refreshShapes(shapesRepoConnection); + } + } - protected void refreshShapes() throws SailException { - try (SailRepositoryConnection shapesRepoConnection = shapesRepo.getConnection()) { - runInferencingSparqlQueries(shapesRepoConnection); - nodeShapes = NodeShape.Factory.getShapes(shapesRepoConnection); + void refreshShapes(SailRepositoryConnection shapesRepoConnection) throws SailException { + try (SailRepositoryConnection beforeCommitConnection = shapesRepo.getConnection()) { + long size = beforeCommitConnection.size(); + if (size > 0) { + // Our inferencer both adds and removes statements. + // To support updates I recommend having two graphs, one raw one with the unmodified data. + // Then copy all that data into a new graph, run inferencing on that graph and use it to generate the java objects + throw new IllegalStateException("ShaclSail does not support modifying shapes that are already loaded or loading more shapes"); + } } + + runInferencingSparqlQueries(shapesRepoConnection); + nodeShapes = NodeShape.Factory.getShapes(shapesRepoConnection); } - + @Override public void shutDown() throws SailException { try { shapesRepo.shutDown(); - } - finally { + } finally { shapesRepo = null; } super.shutDown(); @@ -142,11 +152,12 @@ public boolean isDebugPrintPlans() { return debugPrintPlans; } + @SuppressWarnings("WeakerAccess") public void setDebugPrintPlans(boolean debugPrintPlans) { this.debugPrintPlans = debugPrintPlans; } - - protected List getNodeShapes() { + + List getNodeShapes() { return nodeShapes; } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java index 5dcb2380a..4413c9156 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java @@ -49,7 +49,7 @@ public class ShaclSailConnection extends NotifyingSailConnectionWrapper { private Repository removedStatements; private boolean isShapeRefreshNeeded = false; - + public final ShaclSail sail; public Stats stats; @@ -61,8 +61,7 @@ public class ShaclSailConnection extends NotifyingSailConnectionWrapper { private SailRepositoryConnection shapesConnection; ShaclSailConnection(ShaclSail sail, NotifyingSailConnection connection, - NotifyingSailConnection previousStateConnection, SailRepositoryConnection shapesConnection) - { + NotifyingSailConnection previousStateConnection, SailRepositoryConnection shapesConnection) { super(connection); this.previousStateConnection = previousStateConnection; this.shapesConnection = shapesConnection; @@ -72,23 +71,23 @@ public class ShaclSailConnection extends NotifyingSailConnectionWrapper { addConnectionListener(new SailConnectionListener() { - @Override - public void statementAdded(Statement statement) { - boolean add = addedStatementsSet.add(statement); - if (!add) { - removedStatementsSet.remove(statement); - } + @Override + public void statementAdded(Statement statement) { + boolean add = addedStatementsSet.add(statement); + if (!add) { + removedStatementsSet.remove(statement); + } - } + } - @Override - public void statementRemoved(Statement statement) { - boolean add = removedStatementsSet.add(statement); - if (!add) { - addedStatementsSet.remove(statement); - } - } - } + @Override + public void statementRemoved(Statement statement) { + boolean add = removedStatementsSet.add(statement); + if (!add) { + addedStatementsSet.remove(statement); + } + } + } ); } @@ -139,21 +138,26 @@ private SailRepository getNewMemorySail() { @Override public void commit() throws SailException { synchronized (sail) { + + refreshShapes(shapesConnection); + + if ((!addedStatementsSet.isEmpty() || !removedStatementsSet.isEmpty()) && sail.nodeShapes.isEmpty()) { + throw new NoShapesLoadedException(); + } + try { boolean valid = validate(); previousStateConnection.commit(); if (!valid) { rollback(); + refreshShapes(shapesConnection); throw new SailException("Failed SHACL validation"); - } - else { + } else { shapesConnection.commit(); - refreshShapes(); super.commit(); } - } - finally { + } finally { cleanup(); } } @@ -164,21 +168,18 @@ public void addStatement(Resource subj, IRI pred, Value obj, Resource... context if (contexts.length == 1 && contexts[0].equals(ShaclSail.SHAPE_GRAPH)) { shapesConnection.add(subj, pred, obj); isShapeRefreshNeeded = true; - } - else { + } else { super.addStatement(subj, pred, obj, contexts); } } @Override public void removeStatements(Resource subj, IRI pred, Value obj, Resource... contexts) - throws SailException - { + throws SailException { if (contexts.length == 1 && contexts[0].equals(ShaclSail.SHAPE_GRAPH)) { shapesConnection.remove(subj, pred, obj); isShapeRefreshNeeded = true; - } - else { + } else { super.removeStatements(subj, pred, obj, contexts); } } @@ -209,13 +210,13 @@ private void cleanup() { isShapeRefreshNeeded = false; } - private void refreshShapes() { + private void refreshShapes(SailRepositoryConnection shapesRepoConnection) { if (isShapeRefreshNeeded) { - this.sail.refreshShapes(); + this.sail.refreshShapes(shapesRepoConnection); isShapeRefreshNeeded = false; } } - + private boolean validate() { if (!sail.config.validationEnabled) { @@ -236,12 +237,12 @@ private boolean validate() { boolean valid = collect.size() == 0; if (!valid) { logger.warn( - "SHACL not valid. The following experimental debug results were produced: \n\tNodeShape: {} \n\t\t{}", - nodeShape.toString(), - String.join("\n\t\t", - collect.stream().map( - a -> a.toString() + " -cause-> " + a.getCause()).collect( - Collectors.toList()))); + "SHACL not valid. The following experimental debug results were produced: \n\tNodeShape: {} \n\t\t{}", + nodeShape.toString(), + String.join("\n\t\t", + collect.stream().map( + a -> a.toString() + " -cause-> " + a.getCause()).collect( + Collectors.toList()))); } allValid = allValid && valid; } @@ -262,14 +263,14 @@ void fillAddedAndRemovedStatementRepositories() { try (RepositoryConnection connection = addedStatements.getConnection()) { connection.begin(IsolationLevels.NONE); addedStatementsSet.stream().filter( - statement -> !removedStatementsSet.contains(statement)).forEach(connection::add); + statement -> !removedStatementsSet.contains(statement)).forEach(connection::add); connection.commit(); } try (RepositoryConnection connection = removedStatements.getConnection()) { connection.begin(IsolationLevels.NONE); removedStatementsSet.stream().filter( - statement -> !addedStatementsSet.contains(statement)).forEach(connection::add); + statement -> !addedStatementsSet.contains(statement)).forEach(connection::add); connection.commit(); } } diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/RuntimeModifyShapesTest.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/RuntimeModifyShapesTest.java new file mode 100644 index 000000000..b74c0baa9 --- /dev/null +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/RuntimeModifyShapesTest.java @@ -0,0 +1,62 @@ +package org.eclipse.rdf4j.sail.shacl; + +import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.model.vocabulary.RDFS; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; +import org.eclipse.rdf4j.rio.RDFFormat; +import org.eclipse.rdf4j.sail.memory.MemoryStore; +import org.junit.Test; + +import java.io.IOException; + +public class RuntimeModifyShapesTest { + + @Test(expected = NoShapesLoadedException.class) + public void checkForExceptionWhenValidatingWithoutShapes() { + + SailRepository sailRepository = new SailRepository(new ShaclSail(new MemoryStore())); + sailRepository.initialize(); + + try (SailRepositoryConnection connection = sailRepository.getConnection()) { + connection.begin(); + connection.add(RDFS.RESOURCE, RDF.TYPE, RDFS.RESOURCE); + connection.commit(); + } + + + } + + @Test() + public void checkForNoExceptionWithEmptyTransaction() { + + SailRepository sailRepository = new SailRepository(new ShaclSail(new MemoryStore())); + sailRepository.initialize(); + + try (SailRepositoryConnection connection = sailRepository.getConnection()) { + connection.begin(); + connection.commit(); + } + + + } + + @Test(expected = IllegalStateException.class) + public void checkForExceptionWhenModifyingShapes() throws IOException { + + SailRepository sailRepository = new SailRepository(new ShaclSail(new MemoryStore())); + sailRepository.initialize(); + + try (SailRepositoryConnection connection = sailRepository.getConnection()) { + connection.begin(); + connection.add(RuntimeModifyShapesTest.class.getClassLoader().getResourceAsStream("empty.ttl"), "http://example.com/", RDFFormat.TURTLE, ShaclSail.SHAPE_GRAPH); + connection.commit(); + connection.begin(); + connection.add(RuntimeModifyShapesTest.class.getClassLoader().getResourceAsStream("shacl.ttl"), "http://example.com/", RDFFormat.TURTLE, ShaclSail.SHAPE_GRAPH); + connection.commit(); + } + + + } + +} diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/TrackAddedStatementsTest.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/TrackAddedStatementsTest.java index 473f880ff..50a1a2831 100644 --- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/TrackAddedStatementsTest.java +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/TrackAddedStatementsTest.java @@ -8,10 +8,6 @@ package org.eclipse.rdf4j.sail.shacl; -import static junit.framework.TestCase.assertEquals; -import static junit.framework.TestCase.assertNotNull; -import static junit.framework.TestCase.assertNull; - import org.eclipse.rdf4j.common.iteration.Iterations; import org.eclipse.rdf4j.model.vocabulary.RDF; import org.eclipse.rdf4j.model.vocabulary.RDFS; @@ -22,6 +18,10 @@ import org.eclipse.rdf4j.sail.shacl.planNodes.LoggingNode; import org.junit.Test; +import static junit.framework.TestCase.assertEquals; +import static junit.framework.TestCase.assertNotNull; +import static junit.framework.TestCase.assertNull; + /** * @author Håvard Ottestad */ @@ -41,7 +41,7 @@ public void testCleanup() throws Exception { connection.add(RDFS.RESOURCE, RDF.TYPE, RDFS.RESOURCE); - ShaclSailConnection shaclSailConnection = (ShaclSailConnection)connection.getSailConnection(); + ShaclSailConnection shaclSailConnection = (ShaclSailConnection) connection.getSailConnection(); assertNull(shaclSailConnection.getAddedStatements()); assertNull(shaclSailConnection.getAddedStatements()); @@ -60,7 +60,7 @@ public void testTransactions() throws Exception { connection.begin(); connection.add(RDFS.RESOURCE, RDF.TYPE, RDFS.RESOURCE); - ShaclSailConnection shaclSailConnection = (ShaclSailConnection)connection.getSailConnection(); + ShaclSailConnection shaclSailConnection = (ShaclSailConnection) connection.getSailConnection(); shaclSailConnection.fillAddedAndRemovedStatementRepositories(); assertNotNull(shaclSailConnection.getAddedStatements()); @@ -82,7 +82,7 @@ public void testRollback() throws Exception { connection.begin(); connection.add(RDFS.RESOURCE, RDF.TYPE, RDFS.RESOURCE); - ShaclSailConnection shaclSailConnection = (ShaclSailConnection)connection.getSailConnection(); + ShaclSailConnection shaclSailConnection = (ShaclSailConnection) connection.getSailConnection(); shaclSailConnection.fillAddedAndRemovedStatementRepositories(); assertNotNull(shaclSailConnection.getAddedStatements()); @@ -116,12 +116,11 @@ public void testValidationFailedCleanup() throws Exception { try { connection.commit(); - } - catch (Throwable e) { + } catch (Throwable e) { System.out.println(e.getMessage()); } - ShaclSailConnection shaclSailConnection = (ShaclSailConnection)connection.getSailConnection(); + ShaclSailConnection shaclSailConnection = (ShaclSailConnection) connection.getSailConnection(); assertNull(shaclSailConnection.getAddedStatements()); assertNull(shaclSailConnection.getRemovedStatements()); @@ -144,8 +143,7 @@ public void testValidationFailedCausesRollback() throws Exception { try { connection.commit(); - } - catch (Throwable e) { + } catch (Throwable e) { System.out.println(e.getMessage()); } @@ -168,7 +166,7 @@ public void testCleanupOnClose() throws Exception { connection.close(); - ShaclSailConnection shaclSailConnection = (ShaclSailConnection)connection.getSailConnection(); + ShaclSailConnection shaclSailConnection = (ShaclSailConnection) connection.getSailConnection(); assertNull(shaclSailConnection.getAddedStatements()); assertNull(shaclSailConnection.getRemovedStatements()); @@ -192,7 +190,7 @@ public void testAddRemoveAddRemove() throws Exception { connection.add(RDFS.RESOURCE, RDF.TYPE, RDFS.RESOURCE); connection.remove(RDFS.RESOURCE, RDF.TYPE, RDFS.RESOURCE); - ShaclSailConnection shaclSailConnection = (ShaclSailConnection)connection.getSailConnection(); + ShaclSailConnection shaclSailConnection = (ShaclSailConnection) connection.getSailConnection(); shaclSailConnection.fillAddedAndRemovedStatementRepositories(); assertEquals(0, size(shaclSailConnection.getAddedStatements())); @@ -223,7 +221,7 @@ public void testAdd() throws Exception { connection.add(RDFS.RESOURCE, RDF.TYPE, RDFS.RESOURCE); // System.out.println(size(connection)); - ShaclSailConnection shaclSailConnection = (ShaclSailConnection)connection.getSailConnection(); + ShaclSailConnection shaclSailConnection = (ShaclSailConnection) connection.getSailConnection(); shaclSailConnection.fillAddedAndRemovedStatementRepositories(); assertEquals(1, size(shaclSailConnection.getAddedStatements())); @@ -252,7 +250,7 @@ public void testAddRemove() throws Exception { connection.remove(RDFS.RESOURCE, RDF.TYPE, RDFS.RESOURCE); // System.out.println(size(connection)); - ShaclSailConnection shaclSailConnection = (ShaclSailConnection)connection.getSailConnection(); + ShaclSailConnection shaclSailConnection = (ShaclSailConnection) connection.getSailConnection(); shaclSailConnection.fillAddedAndRemovedStatementRepositories(); assertEquals(0, size(shaclSailConnection.getAddedStatements())); @@ -281,7 +279,7 @@ public void testRemove() throws Exception { connection.remove(RDFS.RESOURCE, RDF.TYPE, RDFS.RESOURCE); connection.remove(RDFS.RESOURCE, RDF.TYPE, RDFS.RESOURCE); - ShaclSailConnection shaclSailConnection = (ShaclSailConnection)connection.getSailConnection(); + ShaclSailConnection shaclSailConnection = (ShaclSailConnection) connection.getSailConnection(); shaclSailConnection.fillAddedAndRemovedStatementRepositories(); assertEquals(0, size(shaclSailConnection.getAddedStatements())); @@ -304,12 +302,13 @@ public void testRemoveWithoutAdding() throws Exception { connection.remove(RDFS.RESOURCE, RDF.TYPE, RDFS.RESOURCE); - ShaclSailConnection shaclSailConnection = (ShaclSailConnection)connection.getSailConnection(); + ShaclSailConnection shaclSailConnection = (ShaclSailConnection) connection.getSailConnection(); shaclSailConnection.fillAddedAndRemovedStatementRepositories(); assertEquals(0, size(shaclSailConnection.getAddedStatements())); assertEquals(0, size(shaclSailConnection.getRemovedStatements())); + connection.commit(); } @@ -328,7 +327,7 @@ public void testSingleRemove() throws Exception { connection.remove(RDFS.RESOURCE, RDF.TYPE, RDFS.RESOURCE); - ShaclSailConnection shaclSailConnection = (ShaclSailConnection)connection.getSailConnection(); + ShaclSailConnection shaclSailConnection = (ShaclSailConnection) connection.getSailConnection(); shaclSailConnection.fillAddedAndRemovedStatementRepositories(); assertEquals(0, size(shaclSailConnection.getAddedStatements())); @@ -350,7 +349,7 @@ public void testSingleAdd() throws Exception { connection.add(RDFS.RESOURCE, RDF.TYPE, RDFS.RESOURCE); - ShaclSailConnection shaclSailConnection = (ShaclSailConnection)connection.getSailConnection(); + ShaclSailConnection shaclSailConnection = (ShaclSailConnection) connection.getSailConnection(); shaclSailConnection.fillAddedAndRemovedStatementRepositories(); assertEquals(1, size(shaclSailConnection.getAddedStatements())); @@ -363,13 +362,13 @@ public void testSingleAdd() throws Exception { private static long size(RepositoryConnection connection) { return Iterations.stream(connection.getStatements(null, null, null)).peek( - System.out::println).count(); + System.out::println).count(); } private static long size(Repository repo) { try (RepositoryConnection connection = repo.getConnection()) { return Iterations.stream(connection.getStatements(null, null, null)).peek( - System.out::println).count(); + System.out::println).count(); } } diff --git a/shacl/src/test/resources/empty.ttl b/shacl/src/test/resources/empty.ttl index e69de29bb..2831367f0 100644 --- a/shacl/src/test/resources/empty.ttl +++ b/shacl/src/test/resources/empty.ttl @@ -0,0 +1,16 @@ +@base . +@prefix ex: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix xsd: . + +ex:PersonShape + a sh:NodeShape ; + sh:property [ + sh:path rdfs:label ; + sh:minCount 0 ; + + ] . + From c3b523acc88043054ba2d892295a8ceceffde3af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Avard=20Ottestad?= Date: Wed, 16 Jan 2019 10:53:56 +0100 Subject: [PATCH 30/54] eclipse/rdf4j#1113 option for disabling NoShapesLoadedException MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håvard Ottestad --- .../org/eclipse/rdf4j/sail/shacl/ShaclSail.java | 11 ++++++++++- .../rdf4j/sail/shacl/ShaclSailConnection.java | 2 +- .../sail/shacl/RuntimeModifyShapesTest.java | 2 +- .../sail/shacl/TrackAddedStatementsTest.java | 13 +++++++++++++ shacl/src/test/resources/empty.ttl | 16 ---------------- 5 files changed, 25 insertions(+), 19 deletions(-) diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSail.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSail.java index 33dc4001f..25d19c757 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSail.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSail.java @@ -45,9 +45,10 @@ public class ShaclSail extends NotifyingSailWrapper { .getInstance() .createIRI("http://rdf4j.org/schema/schacl#ShapeGraph"); - List nodeShapes; + private List nodeShapes; boolean debugPrintPlans = false; + private boolean ignoreNoShapesLoadedException = false; ShaclSailConfig config = new ShaclSailConfig(); @@ -152,6 +153,14 @@ public boolean isDebugPrintPlans() { return debugPrintPlans; } + public boolean isIgnoreNoShapesLoadedException() { + return ignoreNoShapesLoadedException; + } + + public void setIgnoreNoShapesLoadedException(boolean ignoreNoShapesLoadedException) { + this.ignoreNoShapesLoadedException = ignoreNoShapesLoadedException; + } + @SuppressWarnings("WeakerAccess") public void setDebugPrintPlans(boolean debugPrintPlans) { this.debugPrintPlans = debugPrintPlans; diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java index 4413c9156..e1b450253 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java @@ -141,7 +141,7 @@ public void commit() throws SailException { refreshShapes(shapesConnection); - if ((!addedStatementsSet.isEmpty() || !removedStatementsSet.isEmpty()) && sail.nodeShapes.isEmpty()) { + if (!sail.isIgnoreNoShapesLoadedException() && ((!addedStatementsSet.isEmpty() || !removedStatementsSet.isEmpty()) && sail.getNodeShapes().isEmpty())) { throw new NoShapesLoadedException(); } diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/RuntimeModifyShapesTest.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/RuntimeModifyShapesTest.java index b74c0baa9..a973ae279 100644 --- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/RuntimeModifyShapesTest.java +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/RuntimeModifyShapesTest.java @@ -49,7 +49,7 @@ public void checkForExceptionWhenModifyingShapes() throws IOException { try (SailRepositoryConnection connection = sailRepository.getConnection()) { connection.begin(); - connection.add(RuntimeModifyShapesTest.class.getClassLoader().getResourceAsStream("empty.ttl"), "http://example.com/", RDFFormat.TURTLE, ShaclSail.SHAPE_GRAPH); + connection.add(RuntimeModifyShapesTest.class.getClassLoader().getResourceAsStream("shaclDatatype.ttl"), "http://example.com/", RDFFormat.TURTLE, ShaclSail.SHAPE_GRAPH); connection.commit(); connection.begin(); connection.add(RuntimeModifyShapesTest.class.getClassLoader().getResourceAsStream("shacl.ttl"), "http://example.com/", RDFFormat.TURTLE, ShaclSail.SHAPE_GRAPH); diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/TrackAddedStatementsTest.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/TrackAddedStatementsTest.java index 50a1a2831..be3127954 100644 --- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/TrackAddedStatementsTest.java +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/TrackAddedStatementsTest.java @@ -35,6 +35,7 @@ public class TrackAddedStatementsTest { public void testCleanup() throws Exception { SailRepository shaclRepository = Utils.getInitializedShaclRepository("empty.ttl"); + ((ShaclSail) shaclRepository.getSail()).setIgnoreNoShapesLoadedException(true); shaclRepository.initialize(); try (SailRepositoryConnection connection = shaclRepository.getConnection()) { @@ -54,6 +55,7 @@ public void testCleanup() throws Exception { public void testTransactions() throws Exception { SailRepository shaclRepository = Utils.getInitializedShaclRepository("empty.ttl"); + ((ShaclSail) shaclRepository.getSail()).setIgnoreNoShapesLoadedException(true); shaclRepository.initialize(); try (SailRepositoryConnection connection = shaclRepository.getConnection()) { @@ -76,6 +78,7 @@ public void testTransactions() throws Exception { public void testRollback() throws Exception { SailRepository shaclRepository = Utils.getInitializedShaclRepository("empty.ttl"); + ((ShaclSail) shaclRepository.getSail()).setIgnoreNoShapesLoadedException(true); shaclRepository.initialize(); try (SailRepositoryConnection connection = shaclRepository.getConnection()) { @@ -106,6 +109,7 @@ public void testRollback() throws Exception { public void testValidationFailedCleanup() throws Exception { SailRepository shaclRepository = Utils.getInitializedShaclRepository("shacl.ttl"); + ((ShaclSail) shaclRepository.getSail()).setIgnoreNoShapesLoadedException(true); shaclRepository.initialize(); try (SailRepositoryConnection connection = shaclRepository.getConnection()) { @@ -133,6 +137,7 @@ public void testValidationFailedCleanup() throws Exception { public void testValidationFailedCausesRollback() throws Exception { SailRepository shaclRepository = Utils.getInitializedShaclRepository("shacl.ttl"); + ((ShaclSail) shaclRepository.getSail()).setIgnoreNoShapesLoadedException(true); shaclRepository.initialize(); try (SailRepositoryConnection connection = shaclRepository.getConnection()) { @@ -157,6 +162,7 @@ public void testValidationFailedCausesRollback() throws Exception { public void testCleanupOnClose() throws Exception { SailRepository shaclRepository = Utils.getInitializedShaclRepository("shacl.ttl"); + ((ShaclSail) shaclRepository.getSail()).setIgnoreNoShapesLoadedException(true); shaclRepository.initialize(); SailRepositoryConnection connection = shaclRepository.getConnection(); @@ -179,6 +185,7 @@ public void testCleanupOnClose() throws Exception { public void testAddRemoveAddRemove() throws Exception { SailRepository shaclRepository = Utils.getInitializedShaclRepository("empty.ttl"); + ((ShaclSail) shaclRepository.getSail()).setIgnoreNoShapesLoadedException(true); shaclRepository.initialize(); try (SailRepositoryConnection connection = shaclRepository.getConnection()) { @@ -206,6 +213,7 @@ public void testAddRemoveAddRemove() throws Exception { public void testAdd() throws Exception { SailRepository shaclRepository = Utils.getInitializedShaclRepository("empty.ttl"); + ((ShaclSail) shaclRepository.getSail()).setIgnoreNoShapesLoadedException(true); shaclRepository.initialize(); try (SailRepositoryConnection connection = shaclRepository.getConnection()) { @@ -238,6 +246,7 @@ public void testAdd() throws Exception { public void testAddRemove() throws Exception { SailRepository shaclRepository = Utils.getInitializedShaclRepository("empty.ttl"); + ((ShaclSail) shaclRepository.getSail()).setIgnoreNoShapesLoadedException(true); shaclRepository.initialize(); try (SailRepositoryConnection connection = shaclRepository.getConnection()) { @@ -267,6 +276,7 @@ public void testAddRemove() throws Exception { public void testRemove() throws Exception { SailRepository shaclRepository = Utils.getInitializedShaclRepository("empty.ttl"); + ((ShaclSail) shaclRepository.getSail()).setIgnoreNoShapesLoadedException(true); shaclRepository.initialize(); try (SailRepositoryConnection connection = shaclRepository.getConnection()) { @@ -294,6 +304,7 @@ public void testRemove() throws Exception { public void testRemoveWithoutAdding() throws Exception { SailRepository shaclRepository = Utils.getInitializedShaclRepository("empty.ttl"); + ((ShaclSail) shaclRepository.getSail()).setIgnoreNoShapesLoadedException(true); shaclRepository.initialize(); try (SailRepositoryConnection connection = shaclRepository.getConnection()) { @@ -318,6 +329,7 @@ public void testRemoveWithoutAdding() throws Exception { public void testSingleRemove() throws Exception { SailRepository shaclRepository = Utils.getInitializedShaclRepository("empty.ttl"); + ((ShaclSail) shaclRepository.getSail()).setIgnoreNoShapesLoadedException(true); shaclRepository.initialize(); try (SailRepositoryConnection connection = shaclRepository.getConnection()) { @@ -342,6 +354,7 @@ public void testSingleRemove() throws Exception { public void testSingleAdd() throws Exception { SailRepository shaclRepository = Utils.getInitializedShaclRepository("empty.ttl"); + ((ShaclSail) shaclRepository.getSail()).setIgnoreNoShapesLoadedException(true); shaclRepository.initialize(); try (SailRepositoryConnection connection = shaclRepository.getConnection()) { diff --git a/shacl/src/test/resources/empty.ttl b/shacl/src/test/resources/empty.ttl index 2831367f0..e69de29bb 100644 --- a/shacl/src/test/resources/empty.ttl +++ b/shacl/src/test/resources/empty.ttl @@ -1,16 +0,0 @@ -@base . -@prefix ex: . -@prefix owl: . -@prefix rdf: . -@prefix rdfs: . -@prefix sh: . -@prefix xsd: . - -ex:PersonShape - a sh:NodeShape ; - sh:property [ - sh:path rdfs:label ; - sh:minCount 0 ; - - ] . - From 296db5ba9f6843e2b9cb890a19cac5f7a5550fa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Avard=20Ottestad?= Date: Thu, 17 Jan 2019 14:50:50 +0100 Subject: [PATCH 31/54] eclipse/rdf4j#1182 use logger instead of println MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håvard Ottestad --- .../rdf4j/sail/shacl/ShaclSailConnection.java | 2 +- .../sail/shacl/planNodes/FilterPlanNode.java | 15 ++++++++------- .../sail/shacl/planNodes/LoggingNode.java | 18 ++++++++++-------- .../shacl/planNodes/PushBasedLoggingNode.java | 15 ++++++++------- .../eclipse/rdf4j/sail/shacl/ShaclTest.java | 2 +- shacl/src/test/resources/logback-test.xml | 5 +++++ 6 files changed, 33 insertions(+), 24 deletions(-) diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java index 219a0099b..8a9eaf576 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java @@ -36,7 +36,7 @@ */ public class ShaclSailConnection extends NotifyingSailConnectionWrapper { - private final Logger logger = LoggerFactory.getLogger(getClass()); + private static final Logger logger = LoggerFactory.getLogger(ShaclSailConnection.class); private NotifyingSailConnection previousStateConnection; private Repository addedStatements; diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/FilterPlanNode.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/FilterPlanNode.java index 955df2184..1bcebd81e 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/FilterPlanNode.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/FilterPlanNode.java @@ -10,8 +10,11 @@ import org.apache.commons.lang.StringEscapeUtils; +import org.apache.commons.lang.StringUtils; import org.eclipse.rdf4j.common.iteration.CloseableIteration; import org.eclipse.rdf4j.sail.SailException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.Arrays; import java.util.List; @@ -22,6 +25,9 @@ */ public abstract class FilterPlanNode implements ParentProvider { + static private final Logger logger = LoggerFactory.getLogger(FilterPlanNode.class); + + PlanNode parent; T trueNode; @@ -84,7 +90,7 @@ private void calculateNext() { } else { if (falseNode != null) { if(LoggingNode.loggingEnabled){ - System.out.println(leadingSpace() + that.getClass().getSimpleName() + ";falseNode: " + " " + temp.toString()); + logger.debug(leadingSpace() + that.getClass().getSimpleName() + ";falseNode: " + " " + temp.toString()); } falseNode.push(temp); @@ -177,11 +183,6 @@ public String getId() { private String leadingSpace() { - StringBuilder ret = new StringBuilder(); - int depth = parent.depth()+1; - while (--depth > 0) { - ret.append(" "); - } - return ret.toString(); + return StringUtils.leftPad("", parent.depth(), " "); } } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/LoggingNode.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/LoggingNode.java index 2a419721f..3dc14f724 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/LoggingNode.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/LoggingNode.java @@ -8,9 +8,12 @@ package org.eclipse.rdf4j.sail.shacl.planNodes; +import org.apache.commons.lang.StringUtils; import org.eclipse.rdf4j.common.iteration.CloseableIteration; import org.eclipse.rdf4j.common.iteration.Iterations; import org.eclipse.rdf4j.sail.SailException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.Iterator; import java.util.List; @@ -22,6 +25,9 @@ */ public class LoggingNode implements PlanNode { + static private final Logger logger = LoggerFactory.getLogger(LoggingNode.class); + + PlanNode parent; boolean pullAll = true; @@ -93,7 +99,7 @@ public void close() throws SailException { public boolean hasNext() throws SailException { boolean hasNext = parentIterator.hasNext(); - //System.out.println(leadingSpace()+parent.getClass().getSimpleName()+".hasNext() : "+hasNext); +// logger.debug(leadingSpace()+parent.getClass().getSimpleName()+".hasNext() : "+hasNext); return hasNext; } @@ -105,7 +111,7 @@ public Tuple next() throws SailException { assert next != null; - System.out.println(leadingSpace() + parent.getClass().getSimpleName() + ".next(): " + " " + next.toString()); + logger.debug(leadingSpace() + parent.getClass().getSimpleName() + ".next(): " + " " + next.toString()); return next; } @@ -140,11 +146,7 @@ public IteratorData getIteratorDataType() { } private String leadingSpace() { - StringBuilder ret = new StringBuilder(); - int depth = depth(); - while (--depth > 0) { - ret.append(" "); - } - return ret.toString(); + return StringUtils.leftPad("", depth(), " "); } + } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/PushBasedLoggingNode.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/PushBasedLoggingNode.java index bef66b402..d1a086eb0 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/PushBasedLoggingNode.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/PushBasedLoggingNode.java @@ -1,12 +1,18 @@ package org.eclipse.rdf4j.sail.shacl.planNodes; +import org.apache.commons.lang.StringUtils; import org.eclipse.rdf4j.common.iteration.CloseableIteration; import org.eclipse.rdf4j.sail.SailException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.List; public class PushBasedLoggingNode implements SupportsParentProvider, PushBasedPlanNode, PlanNode { + static private final Logger logger = LoggerFactory.getLogger(PushBasedLoggingNode.class); + + private final PushBasedPlanNode parent; private List parents; @@ -43,7 +49,7 @@ public IteratorData getIteratorDataType() { @Override public void push(Tuple t) { if(LoggingNode.loggingEnabled){ - System.out.println(leadingSpace() + parent.getClass().getSimpleName() + ".next(): " + " " + t.toString()); + logger.debug(leadingSpace() + parent.getClass().getSimpleName() + ".next(): " + " " + t.toString()); } parent.push(t); } @@ -61,11 +67,6 @@ public void receiveParentProvider(ParentProvider parentProvider) { } private String leadingSpace() { - StringBuilder ret = new StringBuilder(); - int depth = depth(); - while (--depth > 0) { - ret.append(" "); - } - return ret.toString(); + return StringUtils.leftPad("", depth(), " "); } } diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java index b7b830779..7ddb909ce 100644 --- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java @@ -130,7 +130,7 @@ static Collection getTestsToRun() { - void runTestCase(String shaclPath, String dataPath, ExpectedResult expectedResult) { + private void runTestCase(String shaclPath, String dataPath, ExpectedResult expectedResult) { if (!dataPath.endsWith("/")) { dataPath = dataPath + "/"; diff --git a/shacl/src/test/resources/logback-test.xml b/shacl/src/test/resources/logback-test.xml index 86b31ec4b..b7fa0fbed 100644 --- a/shacl/src/test/resources/logback-test.xml +++ b/shacl/src/test/resources/logback-test.xml @@ -11,5 +11,10 @@ + + + + + From 94de1617357171feea1bfccb61cfffea6b0b2b11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Avard=20Ottestad?= Date: Thu, 17 Jan 2019 14:19:57 +0100 Subject: [PATCH 32/54] eclipse/rdf4j#1246 close unclosed resource MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håvard Ottestad --- .../rdf4j/sail/base/SailSourceBranch.java | 28 ++++++++++++------- .../rdf4j/sail/shacl/ShaclSailConnection.java | 1 + 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/sail-base/src/main/java/org/eclipse/rdf4j/sail/base/SailSourceBranch.java b/sail-base/src/main/java/org/eclipse/rdf4j/sail/base/SailSourceBranch.java index e5d1abbe6..b177a48a8 100644 --- a/sail-base/src/main/java/org/eclipse/rdf4j/sail/base/SailSourceBranch.java +++ b/sail-base/src/main/java/org/eclipse/rdf4j/sail/base/SailSourceBranch.java @@ -132,18 +132,26 @@ public void close() semaphore.lock(); try { try { - SailDataset toCloseSnapshot = snapshot; - snapshot = null; - if (toCloseSnapshot != null) { - toCloseSnapshot.close(); + try { + SailDataset toCloseSnapshot = snapshot; + snapshot = null; + if (toCloseSnapshot != null) { + toCloseSnapshot.close(); + } + } finally { + SailSink toCloseSerializable = serializable; + serializable = null; + if (toCloseSerializable != null) { + toCloseSerializable.close(); + } } - } - finally { - SailSink toCloseSerializable = serializable; - serializable = null; - if (toCloseSerializable != null) { - toCloseSerializable.close(); + } finally { + SailSink toClosePrepared = prepared; + prepared = null; + if (toClosePrepared != null) { + toClosePrepared.close(); } + } } finally { diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java index 3f3403835..b314d8f27 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java @@ -218,6 +218,7 @@ synchronized public void close() throws SailException { if (isActive()) { rollback(); } + previousStateConnection.close(); super.close(); } From 0f0c3e1167558d55e4fda5c850df7068b75fb554 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Avard=20Ottestad?= Date: Thu, 17 Jan 2019 14:15:00 +0100 Subject: [PATCH 33/54] eclipse/rdf4j#1246 shutdown repo to cause error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håvard Ottestad --- .../eclipse/rdf4j/sail/shacl/ShaclTest.java | 33 +++++++++++-------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java index 7ddb909ce..b5162ef90 100644 --- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java @@ -9,6 +9,7 @@ package org.eclipse.rdf4j.sail.shacl; import org.eclipse.rdf4j.IsolationLevels; +import org.eclipse.rdf4j.common.concurrent.locks.Properties; import org.eclipse.rdf4j.common.io.IOUtil; import org.eclipse.rdf4j.repository.RepositoryException; import org.eclipse.rdf4j.repository.sail.SailRepository; @@ -154,28 +155,32 @@ private void runTestCase(String shaclPath, String dataPath, ExpectedResult expec for (int j = 0; j < 100; j++) { String name = dataPath + "query" + j + ".rq"; - InputStream resourceAsStream = ShaclTest.class.getClassLoader().getResourceAsStream(name); - if (resourceAsStream == null) { - continue; - } + try (InputStream resourceAsStream = ShaclTest.class.getClassLoader().getResourceAsStream(name)) { + if (resourceAsStream == null) { + continue; + } - ran = true; - System.out.println(name); + ran = true; + System.out.println(name); - try (SailRepositoryConnection connection = shaclSail.getConnection()) { - connection.begin(); - String query = IOUtil.readString(resourceAsStream); - connection.prepareUpdate(query).execute(); - connection.commit(); - } catch (RepositoryException sailException) { - exception = true; - System.out.println(sailException.getMessage()); + try (SailRepositoryConnection connection = shaclSail.getConnection()) { + connection.begin(IsolationLevels.SNAPSHOT); + String query = IOUtil.readString(resourceAsStream); + connection.prepareUpdate(query).execute(); + connection.commit(); + } catch (RepositoryException sailException) { + exception = true; + System.out.println(sailException.getMessage()); + } } catch (IOException e) { e.printStackTrace(); } } + + shaclSail.shutDown(); + if (ran) { if (expectedResult == ExpectedResult.valid) { assertFalse("Expected transaction to succeed", exception); From 2f3f553d080fe54d745d7ba19b47f50446986c9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Avard=20Ottestad?= Date: Sat, 19 Jan 2019 09:52:58 +0100 Subject: [PATCH 34/54] ignore code generated during mvn install MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håvard Ottestad --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 3ea441184..a064d64f8 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,4 @@ dependency-reduced-pom.xml # NetBean files **/nb-configuration.xml **/nbactions*.xml +compliance/sparql/overlays From 33b68a3c7752e451ab662ef928e6e5d9e3f42133 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Avard=20Ottestad?= Date: Thu, 17 Jan 2019 15:19:45 +0100 Subject: [PATCH 35/54] eclipse/rdf4j#998 log which shape caused the issue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håvard Ottestad --- .../sail/shacl/AST/DatatypePropertyShape.java | 3 +- .../sail/shacl/AST/MaxCountPropertyShape.java | 3 +- .../sail/shacl/AST/MinCountPropertyShape.java | 3 +- .../rdf4j/sail/shacl/AST/OrPropertyShape.java | 3 +- .../rdf4j/sail/shacl/AST/PropertyShape.java | 4 + .../sail/shacl/planNodes/EnrichWithShape.java | 85 +++++++++++++++++++ .../rdf4j/sail/shacl/planNodes/Tuple.java | 26 +++++- 7 files changed, 120 insertions(+), 7 deletions(-) create mode 100644 shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/EnrichWithShape.java diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/DatatypePropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/DatatypePropertyShape.java index 930413292..6dff1017a 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/DatatypePropertyShape.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/DatatypePropertyShape.java @@ -21,6 +21,7 @@ import org.eclipse.rdf4j.sail.shacl.planNodes.BulkedExternalInnerJoin; import org.eclipse.rdf4j.sail.shacl.planNodes.DatatypeFilter; import org.eclipse.rdf4j.sail.shacl.planNodes.DirectTupleFromFilter; +import org.eclipse.rdf4j.sail.shacl.planNodes.EnrichWithShape; import org.eclipse.rdf4j.sail.shacl.planNodes.InnerJoin; import org.eclipse.rdf4j.sail.shacl.planNodes.LoggingNode; import org.eclipse.rdf4j.sail.shacl.planNodes.PushBasedLoggingNode; @@ -87,7 +88,7 @@ public PlanNode getPlan(ShaclSailConnection shaclSailConnection, NodeShape nodeS logger.info(planAsGraphvizDot); } - return new LoggingNode(invalidValues); + return new EnrichWithShape(new LoggingNode(invalidValues), this); } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MaxCountPropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MaxCountPropertyShape.java index 058f98e89..174a9291a 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MaxCountPropertyShape.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MaxCountPropertyShape.java @@ -21,6 +21,7 @@ import org.eclipse.rdf4j.sail.shacl.planNodes.BufferedTupleFromFilter; import org.eclipse.rdf4j.sail.shacl.planNodes.BulkedExternalLeftOuterJoin; import org.eclipse.rdf4j.sail.shacl.planNodes.DirectTupleFromFilter; +import org.eclipse.rdf4j.sail.shacl.planNodes.EnrichWithShape; import org.eclipse.rdf4j.sail.shacl.planNodes.GroupByCount; import org.eclipse.rdf4j.sail.shacl.planNodes.LoggingNode; import org.eclipse.rdf4j.sail.shacl.planNodes.MaxCountFilter; @@ -102,7 +103,7 @@ public PlanNode getPlan(ShaclSailConnection shaclSailConnection, NodeShape nodeS logger.info(planAsGraphvizDot); } - return new LoggingNode(mergeNode1); + return new EnrichWithShape(new LoggingNode(mergeNode1), this); } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MinCountPropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MinCountPropertyShape.java index b7baea64b..f03ef3697 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MinCountPropertyShape.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MinCountPropertyShape.java @@ -21,6 +21,7 @@ import org.eclipse.rdf4j.sail.shacl.ShaclSailConnection; import org.eclipse.rdf4j.sail.shacl.planNodes.BulkedExternalLeftOuterJoin; import org.eclipse.rdf4j.sail.shacl.planNodes.DirectTupleFromFilter; +import org.eclipse.rdf4j.sail.shacl.planNodes.EnrichWithShape; import org.eclipse.rdf4j.sail.shacl.planNodes.GroupByCount; import org.eclipse.rdf4j.sail.shacl.planNodes.LeftOuterJoin; import org.eclipse.rdf4j.sail.shacl.planNodes.LoggingNode; @@ -143,7 +144,7 @@ public PlanNode getPlan(ShaclSailConnection shaclSailConnection, NodeShape nodeS logger.info(planAsGraphvizDot); } - return new LoggingNode(filteredStatements2); + return new EnrichWithShape(new LoggingNode(filteredStatements2), this); } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/OrPropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/OrPropertyShape.java index 642fbe2f6..62ae1ea96 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/OrPropertyShape.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/OrPropertyShape.java @@ -17,6 +17,7 @@ import org.eclipse.rdf4j.repository.Repository; import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; import org.eclipse.rdf4j.sail.shacl.ShaclSailConnection; +import org.eclipse.rdf4j.sail.shacl.planNodes.EnrichWithShape; import org.eclipse.rdf4j.sail.shacl.planNodes.EqualsJoin; import org.eclipse.rdf4j.sail.shacl.planNodes.InnerJoin; import org.eclipse.rdf4j.sail.shacl.planNodes.IteratorData; @@ -116,7 +117,7 @@ else if (iteratorDataTypes.get(0) == IteratorData.aggregated) { logger.info(planAsGraphiz); } - return ret; + return new EnrichWithShape(ret, this); } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PropertyShape.java index 6350fac8e..838b6d251 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PropertyShape.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PropertyShape.java @@ -82,6 +82,10 @@ public String getPlanAsGraphvizDot(PlanNode planNode, ShaclSailConnection shaclS } + public Resource getId() { + return id; + } + static class Factory { static List getPropertyShapes(Resource ShapeId, SailRepositoryConnection connection, NodeShape nodeShape) { diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/EnrichWithShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/EnrichWithShape.java new file mode 100644 index 000000000..66d7bb492 --- /dev/null +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/EnrichWithShape.java @@ -0,0 +1,85 @@ +/******************************************************************************* + * Copyright (c) 2019 Eclipse RDF4J contributors. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.sail.shacl.planNodes; + +import org.apache.commons.lang.StringEscapeUtils; +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.sail.SailException; +import org.eclipse.rdf4j.sail.shacl.AST.PropertyShape; + +/** + * @author Håvard Mikkelsen Ottestad + */ +public class EnrichWithShape implements PlanNode { + + private final PropertyShape propertyShape; + private final PlanNode parent; + + public EnrichWithShape(PlanNode parent, PropertyShape propertyShape) { + this.parent = parent; + this.propertyShape = propertyShape; + } + + @Override + public CloseableIteration iterator() { + return new CloseableIteration() { + + CloseableIteration parentIterator = parent.iterator(); + + @Override + public boolean hasNext() throws SailException { + return parentIterator.hasNext(); + } + + @Override + public Tuple next() throws SailException { + Tuple next = parentIterator.next(); + next.addCausedByPropertyShape(propertyShape); + return next; + } + + @Override + public void remove() throws SailException { + parentIterator.remove(); + } + + @Override + public void close() throws SailException { + parentIterator.close(); + } + }; + } + + @Override + public int depth() { + return parent.depth(); + } + + @Override + public void getPlanAsGraphvizDot(StringBuilder stringBuilder) { + stringBuilder.append(getId()).append(" [label=\"").append(StringEscapeUtils.escapeJava(this.toString())).append("\"];").append("\n"); + stringBuilder.append(parent.getId()).append(" -> ").append(getId()).append("\n"); + parent.getPlanAsGraphvizDot(stringBuilder); + } + + @Override + public String getId() { + return System.identityHashCode(this)+""; + } + + + @Override + public IteratorData getIteratorDataType() { + return parent.getIteratorDataType(); + } + + @Override + public String toString() { + return "EnrichWithShape"; + } +} diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/Tuple.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/Tuple.java index 425a81ed0..66f766676 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/Tuple.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/Tuple.java @@ -10,18 +10,23 @@ import org.eclipse.rdf4j.model.Value; import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.sail.shacl.AST.PropertyShape; +import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; +import java.util.Deque; import java.util.List; import java.util.Objects; import java.util.stream.Collectors; /** - * @author Heshan Jayasinghe + * @author Heshan Jayasinghe, Håvard Mikkelsen Ottestad */ public class Tuple implements Comparable { + Deque causedByPropertyShapes; + private List history = new ArrayList<>(); public List line = new ArrayList<>(); @@ -54,7 +59,22 @@ public List getlist() { @Override public String toString() { - return "Tuple{" + "line=" + Arrays.toString(line.toArray()) +"}"; + String propertyShapeDescrption = ""; + if(causedByPropertyShapes != null){ + + String join = String.join(" , ", causedByPropertyShapes.stream().map(p -> p.getClass().getSimpleName() + " <" + p.getId() + ">").collect(Collectors.toList())); + + propertyShapeDescrption = ", propertyShapes= "+ join; + } + + return "Tuple{" + "line=" + Arrays.toString(line.toArray()) +propertyShapeDescrption+"}"; + } + + public void addCausedByPropertyShape(PropertyShape propertyShape) { + if(causedByPropertyShapes == null){ + causedByPropertyShapes = new ArrayDeque<>(); + } + causedByPropertyShapes.addFirst(propertyShape); } @Override @@ -103,7 +123,7 @@ public int compareTo(Tuple o) { public String getCause(){ - return "[ "+ String.join(" , ", history.stream().distinct().map(Object::toString).collect(Collectors.toList()))+" ]"; + return " [ "+ String.join(" , ", history.stream().distinct().map(Object::toString).collect(Collectors.toList()))+" ]"; } public void addHistory(Tuple tuple) { From f375da7926c5c1c736da0887d014d82c82b14b9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Avard=20Ottestad?= Date: Thu, 17 Jan 2019 16:13:43 +0100 Subject: [PATCH 36/54] eclipse/rdf4j#998 support SHACL RDF report format MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håvard Ottestad --- .../sail/shacl/AST/DatatypePropertyShape.java | 5 ++ .../sail/shacl/AST/MaxCountPropertyShape.java | 5 ++ .../sail/shacl/AST/MinCountPropertyShape.java | 5 ++ .../rdf4j/sail/shacl/AST/NodeShape.java | 4 + .../rdf4j/sail/shacl/AST/OrPropertyShape.java | 5 ++ .../eclipse/rdf4j/sail/shacl/AST/Path.java | 4 + .../sail/shacl/AST/PathPropertyShape.java | 4 +- .../rdf4j/sail/shacl/AST/PropertyShape.java | 8 ++ .../rdf4j/sail/shacl/AST/SimplePath.java | 4 + .../rdf4j/sail/shacl/ShaclSailConnection.java | 19 +++-- .../shacl/ShaclSailValidationException.java | 73 ++++++++++++++++++ .../rdf4j/sail/shacl/planNodes/Tuple.java | 4 + .../eclipse/rdf4j/sail/shacl/ShaclTest.java | 9 +++ .../sail/shacl/ValidationReportTest.java | 77 +++++++++++++++++++ shacl/src/test/resources/shacl.ttl | 8 +- 15 files changed, 222 insertions(+), 12 deletions(-) create mode 100644 shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailValidationException.java create mode 100644 shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ValidationReportTest.java diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/DatatypePropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/DatatypePropertyShape.java index 6dff1017a..a10a2cbf0 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/DatatypePropertyShape.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/DatatypePropertyShape.java @@ -96,4 +96,9 @@ public PlanNode getPlan(ShaclSailConnection shaclSailConnection, NodeShape nodeS public boolean requiresEvaluation(Repository addedStatements, Repository removedStatements) { return true; } + + @Override + public Resource getSourceConstraintComponent() { + return SHACL.DATATYPE_CONSTRAINT_COMPONENT; + } } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MaxCountPropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MaxCountPropertyShape.java index 174a9291a..0fcafc16b 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MaxCountPropertyShape.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MaxCountPropertyShape.java @@ -111,4 +111,9 @@ public PlanNode getPlan(ShaclSailConnection shaclSailConnection, NodeShape nodeS public boolean requiresEvaluation(Repository addedStatements, Repository removedStatements) { return true; } + + @Override + public Resource getSourceConstraintComponent() { + return SHACL.MAX_COUNT_CONSTRAINT_COMPONENT; + } } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MinCountPropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MinCountPropertyShape.java index f03ef3697..54fcc13b8 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MinCountPropertyShape.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MinCountPropertyShape.java @@ -163,4 +163,9 @@ public boolean requiresEvaluation(Repository addedStatements, Repository removed return super.requiresEvaluation(addedStatements, removedStatements) | requiresEvalutation; } + + @Override + public Resource getSourceConstraintComponent() { + return SHACL.MIN_COUNT_CONSTRAINT_COMPONENT; + } } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/NodeShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/NodeShape.java index ccab5f411..f71d4f966 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/NodeShape.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/NodeShape.java @@ -76,6 +76,10 @@ public String getQuery() { return "?a ?b ?c"; } + public Resource getId() { + return id; + } + public static class Factory { diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/OrPropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/OrPropertyShape.java index 62ae1ea96..b30cdb407 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/OrPropertyShape.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/OrPropertyShape.java @@ -126,4 +126,9 @@ else if (iteratorDataTypes.get(0) == IteratorData.aggregated) { public boolean requiresEvaluation(Repository addedStatements, Repository removedStatements) { return true; } + + @Override + public Resource getSourceConstraintComponent() { + return SHACL.OR_CONSTRAINT_COMPONENT; + } } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/Path.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/Path.java index 0b5d779a6..5b6251691 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/Path.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/Path.java @@ -25,4 +25,8 @@ abstract public class Path implements RequiresEvalutation, QueryGenerator { } + + public Resource getId() { + return id; + } } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PathPropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PathPropertyShape.java index 89ba2065c..f1ee7bbc1 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PathPropertyShape.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PathPropertyShape.java @@ -54,6 +54,8 @@ public boolean requiresEvaluation(Repository addedStatements, Repository removed } - + public Path getPath() { + return path; + } } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PropertyShape.java index 838b6d251..e3ccdcaeb 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PropertyShape.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PropertyShape.java @@ -86,6 +86,14 @@ public Resource getId() { return id; } + public NodeShape getNodeShape() { + return nodeShape; + } + + public Resource getSourceConstraintComponent() { + throw new IllegalStateException("Missing implementetion in extending class!"); + } + static class Factory { static List getPropertyShapes(Resource ShapeId, SailRepositoryConnection connection, NodeShape nodeShape) { diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/SimplePath.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/SimplePath.java index 40a09727f..8d2e19fa1 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/SimplePath.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/SimplePath.java @@ -62,4 +62,8 @@ public String getQuery() { return "?a <" + path + "> ?c. "; } + + public IRI getPath() { + return path; + } } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java index 980e11ae0..7fd6d700b 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java @@ -26,6 +26,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.stream.Collectors; @@ -127,12 +130,13 @@ public void commit() throws SailException { synchronized (sail) { try { - boolean valid = validate(); + List invalidTuples = validate(); + boolean valid = invalidTuples.isEmpty(); previousStateConnection.commit(); if (!valid) { rollback(); - throw new SailException("Failed SHACL validation"); + throw new ShaclSailValidationException(invalidTuples); } else { super.commit(); } @@ -167,15 +171,15 @@ private void cleanup() { } - private boolean validate() { + private List validate() { if (!sail.config.validationEnabled) { - return true; + return Collections.emptyList(); } fillAddedAndRemovedStatementRepositories(); - boolean allValid = true; + List ret = new ArrayList<>(); for (NodeShape nodeShape : sail.nodeShapes) { List planNodes = nodeShape.generatePlans(this, nodeShape, sail.debugPrintPlans); @@ -183,16 +187,17 @@ private boolean validate() { try (Stream stream = Iterations.stream(planNode.iterator())) { List collect = stream.collect(Collectors.toList()); + ret.addAll(collect); + boolean valid = collect.size() == 0; if (!valid) { logger.warn("SHACL not valid. The following experimental debug results were produced: \n\tNodeShape: {} \n\t\t{}", nodeShape.toString(), String.join("\n\t\t", collect.stream().map(a -> a.toString()+" -cause-> "+a.getCause()).collect(Collectors.toList()))); } - allValid = allValid && valid; } } } - return allValid; + return ret; } void fillAddedAndRemovedStatementRepositories() { diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailValidationException.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailValidationException.java new file mode 100644 index 000000000..9c0252633 --- /dev/null +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailValidationException.java @@ -0,0 +1,73 @@ +package org.eclipse.rdf4j.sail.shacl; + +import org.eclipse.rdf4j.model.BNode; +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.impl.LinkedHashModel; +import org.eclipse.rdf4j.model.impl.LinkedHashModelFactory; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.model.util.ModelBuilder; +import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.model.vocabulary.SHACL; +import org.eclipse.rdf4j.sail.SailException; +import org.eclipse.rdf4j.sail.shacl.AST.PathPropertyShape; +import org.eclipse.rdf4j.sail.shacl.AST.PropertyShape; +import org.eclipse.rdf4j.sail.shacl.AST.SimplePath; +import org.eclipse.rdf4j.sail.shacl.planNodes.Tuple; + +import java.util.List; + +public class ShaclSailValidationException extends SailException { + + List invalidTuples; + + public ShaclSailValidationException(List invalidTuples) { + super("Failed SHACL validation"); + this.invalidTuples = invalidTuples; + } + + public Model validationReportAsModel() { + + SimpleValueFactory vf = SimpleValueFactory.getInstance(); + + LinkedHashModel ret = new LinkedHashModelFactory().createEmptyModel(); + + ret.setNamespace(SHACL.PREFIX, SHACL.NAMESPACE); + + ModelBuilder validationReport = new ModelBuilder().subject(vf.createBNode()) + .add(RDF.TYPE, SHACL.VALIDATION_REPORT) + .add(SHACL.CONFORMS, false); + + + for (Tuple invalidTuple : invalidTuples) { + + BNode resultSubject = vf.createBNode(); + ModelBuilder result = new ModelBuilder().subject(resultSubject) + .add(RDF.TYPE, SHACL.VALIDATION_RESULT); + + + for (PropertyShape causedByPropertyShape : invalidTuple.getCausedByPropertyShapes()) { + result.add(SHACL.SOURCE_CONSTRAINT_COMPONENT, causedByPropertyShape.getSourceConstraintComponent()); + result.add(SHACL.SOURCE_SHAPE, causedByPropertyShape.getId()); + if (causedByPropertyShape instanceof PathPropertyShape) { + PathPropertyShape causeByPathPropertyShape = (PathPropertyShape) causedByPropertyShape; + if (causeByPathPropertyShape.getPath() != null) { + result.add(SHACL.RESULT_PATH, ((SimplePath) causeByPathPropertyShape.getPath()).getPath()); + } + } + } + + if (invalidTuple.line.size() > 0) { + result.add(SHACL.FOCUS_NODE, invalidTuple.line.get(0)); + } + + validationReport.add(SHACL.RESULT, resultSubject); + + ret.addAll(result.build()); + + } + ret.addAll(validationReport.build()); + + return ret; + + } +} diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/Tuple.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/Tuple.java index 66f766676..2216718bd 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/Tuple.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/Tuple.java @@ -77,6 +77,10 @@ public void addCausedByPropertyShape(PropertyShape propertyShape) { causedByPropertyShapes.addFirst(propertyShape); } + public Deque getCausedByPropertyShapes() { + return causedByPropertyShapes; + } + @Override public boolean equals(Object o) { if (this == o) { diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java index b5162ef90..0cf34eace 100644 --- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java @@ -11,9 +11,12 @@ import org.eclipse.rdf4j.IsolationLevels; import org.eclipse.rdf4j.common.concurrent.locks.Properties; import org.eclipse.rdf4j.common.io.IOUtil; +import org.eclipse.rdf4j.model.Model; import org.eclipse.rdf4j.repository.RepositoryException; import org.eclipse.rdf4j.repository.sail.SailRepository; import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; +import org.eclipse.rdf4j.rio.RDFFormat; +import org.eclipse.rdf4j.rio.Rio; import org.eclipse.rdf4j.sail.memory.MemoryStore; import org.eclipse.rdf4j.sail.shacl.planNodes.LoggingNode; import org.junit.Test; @@ -172,6 +175,12 @@ private void runTestCase(String shaclPath, String dataPath, ExpectedResult expec exception = true; System.out.println(sailException.getMessage()); + System.out.println("\n############################################"); + System.out.println("\tValidation Report\n"); + ShaclSailValidationException cause = (ShaclSailValidationException) sailException.getCause(); + Model validationReport = cause.validationReportAsModel(); + Rio.write(validationReport, System.out, RDFFormat.TURTLE); + System.out.println("\n############################################"); } } catch (IOException e) { e.printStackTrace(); diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ValidationReportTest.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ValidationReportTest.java new file mode 100644 index 000000000..15d3b8331 --- /dev/null +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ValidationReportTest.java @@ -0,0 +1,77 @@ +package org.eclipse.rdf4j.sail.shacl; + +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.util.Models; +import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.model.vocabulary.RDFS; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; +import org.eclipse.rdf4j.rio.RDFFormat; +import org.eclipse.rdf4j.rio.Rio; +import org.eclipse.rdf4j.sail.memory.MemoryStore; +import org.junit.Test; + +import java.io.IOException; +import java.io.StringReader; + +import static junit.framework.TestCase.assertTrue; + +public class ValidationReportTest { + + @Test + public void simpleFirstTest() throws IOException { + SailRepository shaclSail = new SailRepository(new ShaclSail(new MemoryStore(), Utils.getSailRepository("shacl.ttl"))); + shaclSail.initialize(); + + try (SailRepositoryConnection connection = shaclSail.getConnection()) { + + connection.begin(); + connection.add(RDFS.RESOURCE, RDF.TYPE, RDFS.RESOURCE); + connection.add(RDFS.RESOURCE, RDFS.LABEL, connection.getValueFactory().createLiteral("a")); + connection.add(RDFS.CLASS, RDF.TYPE, RDFS.RESOURCE); + connection.add(RDF.SUBJECT, RDF.TYPE, RDFS.RESOURCE); + + connection.commit(); + + } catch (RepositoryException e){ + ShaclSailValidationException cause = (ShaclSailValidationException) e.getCause(); + Model actual = cause.validationReportAsModel(); + + actual.setNamespace(RDF.PREFIX, RDF.NAMESPACE); + actual.setNamespace(RDFS.PREFIX, RDFS.NAMESPACE); + actual.setNamespace("ex", "http://example.com/ns#"); + + Rio.write(actual, System.out, RDFFormat.TURTLE); + + + Model expected = Rio.parse(new StringReader("" + + "@prefix ex: .\n" + + "@prefix rdf: .\n" + + "@prefix rdfs: .\n" + + "@prefix sh: .\n" + + "\n" + + "_:node1d1e5rk4ux13 a sh:ValidationResult;\n" + + " sh:focusNode rdf:subject;\n" + + " sh:resultPath rdfs:label;\n" + + " sh:sourceConstraintComponent sh:MinCountConstraintComponent;\n" + + " sh:sourceShape ex:PersonShapeProperty .\n" + + "\n" + + "_:node1d1e5rk4ux14 a sh:ValidationResult;\n" + + " sh:focusNode rdfs:Class;\n" + + " sh:resultPath rdfs:label;\n" + + " sh:sourceConstraintComponent sh:MinCountConstraintComponent;\n" + + " sh:sourceShape ex:PersonShapeProperty .\n" + + "\n" + + "_:node1d1e5rk4ux12 a sh:ValidationReport;\n" + + " sh:conforms false;\n" + + " sh:result _:node1d1e5rk4ux13, _:node1d1e5rk4ux14 .\n" + + ""), "", RDFFormat.TURTLE); + + + assertTrue(Models.isomorphic(expected, actual)); + + } + } + +} diff --git a/shacl/src/test/resources/shacl.ttl b/shacl/src/test/resources/shacl.ttl index 24f46d3fb..641e113bb 100644 --- a/shacl/src/test/resources/shacl.ttl +++ b/shacl/src/test/resources/shacl.ttl @@ -9,9 +9,9 @@ ex:PersonShape a sh:NodeShape ; sh:targetClass rdfs:Resource ; - sh:property [ - sh:path rdfs:label ; - sh:minCount 1 ; + sh:property ex:PersonShapeProperty . - ] . +ex:PersonShapeProperty + sh:path rdfs:label ; + sh:minCount 1 . \ No newline at end of file From 0032ae9ee345b40f5e74f7e51d049caa7bf5bdb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Avard=20Ottestad?= Date: Fri, 18 Jan 2019 12:38:51 +0100 Subject: [PATCH 37/54] eclipse/rdf4j#998 support sh:or better MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håvard Ottestad --- .../rdf4j/sail/shacl/AST/OrPropertyShape.java | 2 +- .../sail/shacl/planNodes/EqualsJoin.java | 2 + .../rdf4j/sail/shacl/planNodes/TrimTuple.java | 1 + .../rdf4j/sail/shacl/planNodes/Tuple.java | 6 +++ .../sail/shacl/planNodes/TupleHelper.java | 2 + .../eclipse/rdf4j/sail/shacl/ShaclTest.java | 15 ++---- .../sail/shacl/ValidationReportTest.java | 47 +++++++++++++++++++ .../test-cases/or/datatype/shacl.ttl | 8 ++-- 8 files changed, 68 insertions(+), 15 deletions(-) diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/OrPropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/OrPropertyShape.java index b30cdb407..b2ec7c523 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/OrPropertyShape.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/OrPropertyShape.java @@ -84,7 +84,7 @@ public PlanNode getPlan(ShaclSailConnection shaclSailConnection, NodeShape nodeS } - PlanNode ret = null; + PlanNode ret; if (iteratorDataTypes.get(0) == IteratorData.tripleBased) { diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/EqualsJoin.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/EqualsJoin.java index 821f7cf33..c042f2aba 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/EqualsJoin.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/EqualsJoin.java @@ -61,6 +61,8 @@ void calculateNext() { if (nextLeft.line == nextRight.line || nextLeft.line.equals(nextRight.line)) { if(useAsFilter){ next = nextLeft; + next.addAllCausedByPropertyShape(nextRight.getCausedByPropertyShapes()); + next.addHistory(nextRight); }else{ next = TupleHelper.join(nextLeft, nextRight); } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/TrimTuple.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/TrimTuple.java index 0bcdce5f2..5619c284c 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/TrimTuple.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/TrimTuple.java @@ -57,6 +57,7 @@ public Tuple next() throws SailException { } tuple.addHistory(next); + tuple.addAllCausedByPropertyShape(next.getCausedByPropertyShapes()); return tuple; } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/Tuple.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/Tuple.java index 2216718bd..d102af3e0 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/Tuple.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/Tuple.java @@ -134,4 +134,10 @@ public void addHistory(Tuple tuple) { history.addAll(tuple.history); history.add(tuple); } + + public void addAllCausedByPropertyShape(Deque causedByPropertyShapes) { + if(causedByPropertyShapes != null) { + this.causedByPropertyShapes.addAll(causedByPropertyShapes); + } + } } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/TupleHelper.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/TupleHelper.java index 316b02cf0..09b164cdf 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/TupleHelper.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/TupleHelper.java @@ -30,6 +30,8 @@ public static Tuple join(Tuple left, Tuple right) { Tuple tuple = new Tuple(newLine); tuple.addHistory(left); tuple.addHistory(right); + tuple.addAllCausedByPropertyShape(left.getCausedByPropertyShapes()); + tuple.addAllCausedByPropertyShape(right.getCausedByPropertyShapes()); return tuple; } diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java index 0cf34eace..4c1feddcf 100644 --- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java @@ -39,7 +39,7 @@ @RunWith(Parameterized.class) public class ShaclTest { - static final List testCasePaths = Arrays.asList( + private static final List testCasePaths = Arrays.asList( "test-cases/datatype/simple", "test-cases/minCount/simple", "test-cases/maxCount/simple", @@ -62,14 +62,9 @@ public ShaclTest(String testCasePath, String path, ExpectedResult expectedResult this.testCasePath = testCasePath; this.path = path; this.expectedResult = expectedResult; - } - - { LoggingNode.loggingEnabled = true; } - - @Parameterized.Parameters(name = "{2} - {1}") public static Collection data() { @@ -90,7 +85,7 @@ public void testSingleTransaction() { } - static List findTestCases(String testCase, String baseCase) { + private static List findTestCases(String testCase, String baseCase) { List ret = new ArrayList<>(); @@ -112,7 +107,7 @@ static List findTestCases(String testCase, String baseCase) { } - static Collection getTestsToRun() { + private static Collection getTestsToRun() { List ret = new ArrayList<>(); @@ -134,7 +129,7 @@ static Collection getTestsToRun() { - private void runTestCase(String shaclPath, String dataPath, ExpectedResult expectedResult) { + private static void runTestCase(String shaclPath, String dataPath, ExpectedResult expectedResult) { if (!dataPath.endsWith("/")) { dataPath = dataPath + "/"; @@ -200,7 +195,7 @@ private void runTestCase(String shaclPath, String dataPath, ExpectedResult expec } - void runTestCaseSingleTransaction(String shaclPath, String dataPath, ExpectedResult expectedResult) { + private static void runTestCaseSingleTransaction(String shaclPath, String dataPath, ExpectedResult expectedResult) { if (!dataPath.endsWith("/")) { dataPath = dataPath + "/"; diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ValidationReportTest.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ValidationReportTest.java index 15d3b8331..db60429f5 100644 --- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ValidationReportTest.java +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ValidationReportTest.java @@ -1,5 +1,7 @@ package org.eclipse.rdf4j.sail.shacl; +import org.apache.commons.io.IOUtils; +import org.eclipse.rdf4j.common.io.IOUtil; import org.eclipse.rdf4j.model.Model; import org.eclipse.rdf4j.model.util.Models; import org.eclipse.rdf4j.model.vocabulary.RDF; @@ -74,4 +76,49 @@ public void simpleFirstTest() throws IOException { } } + + @Test + public void nestedLogicalOrSupport() throws IOException { + SailRepository shaclSail = new SailRepository(new ShaclSail(new MemoryStore(), Utils.getSailRepository("test-cases/or/datatype/shacl.ttl"))); + shaclSail.initialize(); + + try (SailRepositoryConnection connection = shaclSail.getConnection()) { + + connection.begin(); + connection.prepareUpdate(IOUtils.toString(ValidationReportTest.class.getClassLoader().getResourceAsStream("test-cases/or/datatype/invalid/case1/query1.rq"), "utf-8")).execute(); + connection.commit(); + + } catch (RepositoryException e){ + ShaclSailValidationException cause = (ShaclSailValidationException) e.getCause(); + Model actual = cause.validationReportAsModel(); + + actual.setNamespace(RDF.PREFIX, RDF.NAMESPACE); + actual.setNamespace(RDFS.PREFIX, RDFS.NAMESPACE); + actual.setNamespace("ex", "http://example.com/ns#"); + + Rio.write(actual, System.out, RDFFormat.TURTLE); + + + Model expected = Rio.parse(new StringReader("" + + "@prefix ex: .\n" + + "@prefix rdf: .\n" + + "@prefix sh: .\n" + + "\n" + + "_:node1d1gbve96x12 a sh:ValidationResult;\n" + + " sh:focusNode ex:validPerson1;\n" + + " sh:resultPath ex:age;\n" + + " sh:sourceConstraintComponent sh:DatatypeConstraintComponent, sh:OrConstraintComponent;\n" + + " sh:sourceShape _:node1d1gbve7vx1, _:node1d1gbve7vx3, _:node1d1gbve7vx5 .\n" + + "\n" + + "_:node1d1gbve96x11 a sh:ValidationReport;\n" + + " sh:conforms false;\n" + + " sh:result _:node1d1gbve96x12 ." + + ""), "", RDFFormat.TURTLE); + + + assertTrue(Models.isomorphic(expected, actual)); + + } + } + } diff --git a/shacl/src/test/resources/test-cases/or/datatype/shacl.ttl b/shacl/src/test/resources/test-cases/or/datatype/shacl.ttl index 088b9aafd..2be46060e 100644 --- a/shacl/src/test/resources/test-cases/or/datatype/shacl.ttl +++ b/shacl/src/test/resources/test-cases/or/datatype/shacl.ttl @@ -12,12 +12,12 @@ ex:PersonShape sh:property [ sh:or ( [ - sh:path ex:age ; - sh:datatype xsd:integer ; + sh:path ex:age ; + sh:datatype xsd:integer ; ] [ - sh:path ex:age ; - sh:datatype xsd:long ; + sh:path ex:age ; + sh:datatype xsd:long ; ] ) ; ] . From c9da13e7a0d5572c35c892d914154c7288e7ae1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Avard=20Ottestad?= Date: Fri, 18 Jan 2019 14:31:18 +0100 Subject: [PATCH 38/54] eclipse/rdf4j#998 support for nested validation results MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håvard Ottestad --- .../sail/shacl/AST/DatatypePropertyShape.java | 5 +- .../sail/shacl/AST/MaxCountPropertyShape.java | 5 +- .../sail/shacl/AST/MinCountPropertyShape.java | 5 +- .../rdf4j/sail/shacl/AST/OrPropertyShape.java | 5 +- .../rdf4j/sail/shacl/AST/PropertyShape.java | 3 +- .../rdf4j/sail/shacl/AST/SimplePath.java | 2 +- .../shacl/ShaclSailValidationException.java | 68 +++++------- .../sail/shacl/SourceConstraintComponent.java | 22 ++++ .../rdf4j/sail/shacl/planNodes/Tuple.java | 4 + .../sail/shacl/results/ModelInterface.java | 16 +++ .../sail/shacl/results/ValidationReport.java | 50 +++++++++ .../sail/shacl/results/ValidationResult.java | 101 ++++++++++++++++++ .../sail/shacl/ValidationReportTest.java | 43 +++++--- .../test-cases/or/datatype/shacl.ttl | 25 +++-- 14 files changed, 278 insertions(+), 76 deletions(-) create mode 100644 shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/SourceConstraintComponent.java create mode 100644 shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/results/ModelInterface.java create mode 100644 shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/results/ValidationReport.java create mode 100644 shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/results/ValidationResult.java diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/DatatypePropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/DatatypePropertyShape.java index a10a2cbf0..3caf8fe36 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/DatatypePropertyShape.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/DatatypePropertyShape.java @@ -16,6 +16,7 @@ import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; import org.eclipse.rdf4j.sail.shacl.ShaclSailConnection; +import org.eclipse.rdf4j.sail.shacl.SourceConstraintComponent; import org.eclipse.rdf4j.sail.shacl.planNodes.BufferedSplitter; import org.eclipse.rdf4j.sail.shacl.planNodes.BufferedTupleFromFilter; import org.eclipse.rdf4j.sail.shacl.planNodes.BulkedExternalInnerJoin; @@ -98,7 +99,7 @@ public boolean requiresEvaluation(Repository addedStatements, Repository removed } @Override - public Resource getSourceConstraintComponent() { - return SHACL.DATATYPE_CONSTRAINT_COMPONENT; + public SourceConstraintComponent getSourceConstraintComponent() { + return SourceConstraintComponent.DatatypeConstraintComponent; } } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MaxCountPropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MaxCountPropertyShape.java index 0fcafc16b..9ef46e4c3 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MaxCountPropertyShape.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MaxCountPropertyShape.java @@ -18,6 +18,7 @@ import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; import org.eclipse.rdf4j.sail.shacl.ShaclSailConnection; +import org.eclipse.rdf4j.sail.shacl.SourceConstraintComponent; import org.eclipse.rdf4j.sail.shacl.planNodes.BufferedTupleFromFilter; import org.eclipse.rdf4j.sail.shacl.planNodes.BulkedExternalLeftOuterJoin; import org.eclipse.rdf4j.sail.shacl.planNodes.DirectTupleFromFilter; @@ -113,7 +114,7 @@ public boolean requiresEvaluation(Repository addedStatements, Repository removed } @Override - public Resource getSourceConstraintComponent() { - return SHACL.MAX_COUNT_CONSTRAINT_COMPONENT; + public SourceConstraintComponent getSourceConstraintComponent() { + return SourceConstraintComponent.MaxCountConstraintComponent; } } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MinCountPropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MinCountPropertyShape.java index 54fcc13b8..7667a298d 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MinCountPropertyShape.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MinCountPropertyShape.java @@ -19,6 +19,7 @@ import org.eclipse.rdf4j.repository.RepositoryConnection; import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; import org.eclipse.rdf4j.sail.shacl.ShaclSailConnection; +import org.eclipse.rdf4j.sail.shacl.SourceConstraintComponent; import org.eclipse.rdf4j.sail.shacl.planNodes.BulkedExternalLeftOuterJoin; import org.eclipse.rdf4j.sail.shacl.planNodes.DirectTupleFromFilter; import org.eclipse.rdf4j.sail.shacl.planNodes.EnrichWithShape; @@ -165,7 +166,7 @@ public boolean requiresEvaluation(Repository addedStatements, Repository removed } @Override - public Resource getSourceConstraintComponent() { - return SHACL.MIN_COUNT_CONSTRAINT_COMPONENT; + public SourceConstraintComponent getSourceConstraintComponent() { + return SourceConstraintComponent.MinCountConstraintComponent; } } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/OrPropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/OrPropertyShape.java index b2ec7c523..0be285b89 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/OrPropertyShape.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/OrPropertyShape.java @@ -17,6 +17,7 @@ import org.eclipse.rdf4j.repository.Repository; import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; import org.eclipse.rdf4j.sail.shacl.ShaclSailConnection; +import org.eclipse.rdf4j.sail.shacl.SourceConstraintComponent; import org.eclipse.rdf4j.sail.shacl.planNodes.EnrichWithShape; import org.eclipse.rdf4j.sail.shacl.planNodes.EqualsJoin; import org.eclipse.rdf4j.sail.shacl.planNodes.InnerJoin; @@ -128,7 +129,7 @@ public boolean requiresEvaluation(Repository addedStatements, Repository removed } @Override - public Resource getSourceConstraintComponent() { - return SHACL.OR_CONSTRAINT_COMPONENT; + public SourceConstraintComponent getSourceConstraintComponent() { + return SourceConstraintComponent.OrConstraintComponent; } } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PropertyShape.java index e3ccdcaeb..dcb18b9a2 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PropertyShape.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PropertyShape.java @@ -15,6 +15,7 @@ import org.eclipse.rdf4j.repository.Repository; import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; import org.eclipse.rdf4j.sail.shacl.ShaclSailConnection; +import org.eclipse.rdf4j.sail.shacl.SourceConstraintComponent; import org.eclipse.rdf4j.sail.shacl.planNodes.PlanNode; import java.util.ArrayList; @@ -90,7 +91,7 @@ public NodeShape getNodeShape() { return nodeShape; } - public Resource getSourceConstraintComponent() { + public SourceConstraintComponent getSourceConstraintComponent() { throw new IllegalStateException("Missing implementetion in extending class!"); } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/SimplePath.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/SimplePath.java index 8d2e19fa1..a139ab962 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/SimplePath.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/SimplePath.java @@ -26,7 +26,7 @@ */ public class SimplePath extends Path { - private IRI path; + private final IRI path; SimplePath(Resource id, SailRepositoryConnection connection) { super(id); diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailValidationException.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailValidationException.java index 9c0252633..36f412377 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailValidationException.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailValidationException.java @@ -1,73 +1,57 @@ package org.eclipse.rdf4j.sail.shacl; -import org.eclipse.rdf4j.model.BNode; import org.eclipse.rdf4j.model.Model; -import org.eclipse.rdf4j.model.impl.LinkedHashModel; -import org.eclipse.rdf4j.model.impl.LinkedHashModelFactory; -import org.eclipse.rdf4j.model.impl.SimpleValueFactory; -import org.eclipse.rdf4j.model.util.ModelBuilder; -import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.model.Resource; import org.eclipse.rdf4j.model.vocabulary.SHACL; import org.eclipse.rdf4j.sail.SailException; -import org.eclipse.rdf4j.sail.shacl.AST.PathPropertyShape; import org.eclipse.rdf4j.sail.shacl.AST.PropertyShape; -import org.eclipse.rdf4j.sail.shacl.AST.SimplePath; import org.eclipse.rdf4j.sail.shacl.planNodes.Tuple; +import org.eclipse.rdf4j.sail.shacl.results.ValidationReport; +import org.eclipse.rdf4j.sail.shacl.results.ValidationResult; +import java.util.ArrayDeque; import java.util.List; public class ShaclSailValidationException extends SailException { - List invalidTuples; + private List invalidTuples; - public ShaclSailValidationException(List invalidTuples) { + ShaclSailValidationException(List invalidTuples) { super("Failed SHACL validation"); this.invalidTuples = invalidTuples; } + @SuppressWarnings("WeakerAccess") public Model validationReportAsModel() { - SimpleValueFactory vf = SimpleValueFactory.getInstance(); + ValidationReport validationReport = getValidationReport(); - LinkedHashModel ret = new LinkedHashModelFactory().createEmptyModel(); + Model model = validationReport.asModel(); + model.setNamespace(SHACL.PREFIX, SHACL.NAMESPACE); + return model; - ret.setNamespace(SHACL.PREFIX, SHACL.NAMESPACE); - ModelBuilder validationReport = new ModelBuilder().subject(vf.createBNode()) - .add(RDF.TYPE, SHACL.VALIDATION_REPORT) - .add(SHACL.CONFORMS, false); + } + @SuppressWarnings("WeakerAccess") + public ValidationReport getValidationReport() { + ValidationReport validationReport = new ValidationReport(false); for (Tuple invalidTuple : invalidTuples) { - - BNode resultSubject = vf.createBNode(); - ModelBuilder result = new ModelBuilder().subject(resultSubject) - .add(RDF.TYPE, SHACL.VALIDATION_RESULT); - - - for (PropertyShape causedByPropertyShape : invalidTuple.getCausedByPropertyShapes()) { - result.add(SHACL.SOURCE_CONSTRAINT_COMPONENT, causedByPropertyShape.getSourceConstraintComponent()); - result.add(SHACL.SOURCE_SHAPE, causedByPropertyShape.getId()); - if (causedByPropertyShape instanceof PathPropertyShape) { - PathPropertyShape causeByPathPropertyShape = (PathPropertyShape) causedByPropertyShape; - if (causeByPathPropertyShape.getPath() != null) { - result.add(SHACL.RESULT_PATH, ((SimplePath) causeByPathPropertyShape.getPath()).getPath()); - } + ValidationResult parent = null; + ArrayDeque propertyShapes = new ArrayDeque<>(invalidTuple.getCausedByPropertyShapes()); + + while (!propertyShapes.isEmpty()) { + ValidationResult validationResult = new ValidationResult(propertyShapes.pop(), (Resource) invalidTuple.line.get(0)); + if (parent == null) { + validationReport.addValidationResult(validationResult); + } else { + parent.setDetail(validationResult); } + parent = validationResult; } - if (invalidTuple.line.size() > 0) { - result.add(SHACL.FOCUS_NODE, invalidTuple.line.get(0)); - } - - validationReport.add(SHACL.RESULT, resultSubject); - - ret.addAll(result.build()); - } - ret.addAll(validationReport.build()); - - return ret; - + return validationReport; } } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/SourceConstraintComponent.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/SourceConstraintComponent.java new file mode 100644 index 000000000..215c9bdff --- /dev/null +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/SourceConstraintComponent.java @@ -0,0 +1,22 @@ +package org.eclipse.rdf4j.sail.shacl; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.vocabulary.SHACL; + +public enum SourceConstraintComponent { + MaxCountConstraintComponent(SHACL.MAX_COUNT_CONSTRAINT_COMPONENT), + DatatypeConstraintComponent(SHACL.DATATYPE_CONSTRAINT_COMPONENT), + OrConstraintComponent(SHACL.OR_CONSTRAINT_COMPONENT), + MinCountConstraintComponent(SHACL.MIN_COUNT_CONSTRAINT_COMPONENT); + + private final IRI iri; + + SourceConstraintComponent(IRI iri) { + this.iri = iri; + } + + public IRI getIri() { + return iri; + } + +} diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/Tuple.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/Tuple.java index d102af3e0..734d65f45 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/Tuple.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/Tuple.java @@ -137,6 +137,10 @@ public void addHistory(Tuple tuple) { public void addAllCausedByPropertyShape(Deque causedByPropertyShapes) { if(causedByPropertyShapes != null) { + if(this.causedByPropertyShapes == null){ + this.causedByPropertyShapes = new ArrayDeque<>(); + } + this.causedByPropertyShapes.addAll(causedByPropertyShapes); } } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/results/ModelInterface.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/results/ModelInterface.java new file mode 100644 index 000000000..af767842b --- /dev/null +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/results/ModelInterface.java @@ -0,0 +1,16 @@ +package org.eclipse.rdf4j.sail.shacl.results; + +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.impl.LinkedHashModelFactory; + +public interface ModelInterface { + + default Model asModel(){ + return asModel(new LinkedHashModelFactory().createEmptyModel()); + } + + Model asModel(Model model); + Resource getId(); + +} diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/results/ValidationReport.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/results/ValidationReport.java new file mode 100644 index 000000000..2db6dbf97 --- /dev/null +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/results/ValidationReport.java @@ -0,0 +1,50 @@ +package org.eclipse.rdf4j.sail.shacl.results; + +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.impl.LinkedHashModelFactory; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.model.vocabulary.SHACL; + +import java.util.ArrayList; +import java.util.List; + +public class ValidationReport implements ModelInterface{ + + private Resource id = SimpleValueFactory.getInstance().createBNode(); + + private boolean conforms; + + private List validationResult = new ArrayList<>(); + + + public ValidationReport(boolean conforms) { + this.conforms = conforms; + } + + public void addValidationResult(ValidationResult validationResult){ + this.validationResult.add(validationResult); + } + + @Override + public Model asModel(Model model) { + + SimpleValueFactory vf = SimpleValueFactory.getInstance(); + + model.add(getId(), SHACL.CONFORMS, vf.createLiteral(conforms)); + model.add(getId(), RDF.TYPE, SHACL.VALIDATION_REPORT); + + for (ValidationResult result : validationResult) { + model.add(getId(), SHACL.RESULT, result.getId()); + result.asModel(model); + } + + return model; + } + + @Override + public Resource getId() { + return id; + } +} diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/results/ValidationResult.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/results/ValidationResult.java new file mode 100644 index 000000000..1dd6ff9e0 --- /dev/null +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/results/ValidationResult.java @@ -0,0 +1,101 @@ +package org.eclipse.rdf4j.sail.shacl.results; + +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.model.vocabulary.SHACL; +import org.eclipse.rdf4j.sail.shacl.AST.Path; +import org.eclipse.rdf4j.sail.shacl.AST.PathPropertyShape; +import org.eclipse.rdf4j.sail.shacl.AST.PropertyShape; +import org.eclipse.rdf4j.sail.shacl.AST.SimplePath; +import org.eclipse.rdf4j.sail.shacl.SourceConstraintComponent; + +import java.util.ArrayList; +import java.util.List; + +public class ValidationResult implements ModelInterface { + + private Resource id = SimpleValueFactory.getInstance().createBNode(); + + private SourceConstraintComponent sourceConstraintComponent; + private PropertyShape sourceShape; + private Path path; + private ValidationResult detail; + private Resource focusNode; + + public ValidationResult(PropertyShape sourceShape, Resource focusNode) { + this.sourceShape = sourceShape; + this.focusNode = focusNode; + this.sourceConstraintComponent = sourceShape.getSourceConstraintComponent(); + if (sourceShape instanceof PathPropertyShape) { + this.path = ((PathPropertyShape) sourceShape).getPath(); + } + + } + + + public void setDetail(ValidationResult detail) { + this.detail = detail; + } + + public ValidationResult getDetail() { + return detail; + } + + public List getDetails(){ + + ArrayList validationResults = new ArrayList<>(); + + ValidationResult temp = detail; + while(temp != null){ + validationResults.add(temp); + temp = temp.detail; + } + + return validationResults; + + } + + @Override + public Model asModel(Model model) { + + model.add(getId(), RDF.TYPE, SHACL.VALIDATION_RESULT); + + model.add(getId(), SHACL.FOCUS_NODE, getFocusNode()); + model.add(getId(), SHACL.SOURCE_CONSTRAINT_COMPONENT, getSourceConstraintComponent().getIri()); + model.add(getId(), SHACL.SOURCE_SHAPE, getSourceShapeResource()); + + if (getPath() != null) { + model.add(getId(), SHACL.RESULT_PATH, ((SimplePath) getPath()).getPath()); + } + + if(detail != null){ + model.add(getId(), SHACL.DETAIL, detail.getId()); + detail.asModel(model); + } + + return model; + } + + private Path getPath() { + return path; + } + + private Resource getSourceShapeResource() { + return sourceShape.getId(); + } + + private Resource getFocusNode() { + return focusNode; + } + + @Override + public Resource getId() { + return id; + } + + public SourceConstraintComponent getSourceConstraintComponent() { + return sourceConstraintComponent; + } +} diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ValidationReportTest.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ValidationReportTest.java index db60429f5..73bfb3c84 100644 --- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ValidationReportTest.java +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ValidationReportTest.java @@ -53,21 +53,23 @@ public void simpleFirstTest() throws IOException { "@prefix rdfs: .\n" + "@prefix sh: .\n" + "\n" + - "_:node1d1e5rk4ux13 a sh:ValidationResult;\n" + + "_:node1d1gi0h02x12 a sh:ValidationReport;\n" + + " sh:conforms false;\n" + + " sh:result _:node1d1gi0h02x13 .\n" + + "\n" + + "_:node1d1gi0h02x13 a sh:ValidationResult;\n" + " sh:focusNode rdf:subject;\n" + " sh:resultPath rdfs:label;\n" + " sh:sourceConstraintComponent sh:MinCountConstraintComponent;\n" + " sh:sourceShape ex:PersonShapeProperty .\n" + "\n" + - "_:node1d1e5rk4ux14 a sh:ValidationResult;\n" + + "_:node1d1gi0h02x12 sh:result _:node1d1gi0h02x14 .\n" + + "\n" + + "_:node1d1gi0h02x14 a sh:ValidationResult;\n" + " sh:focusNode rdfs:Class;\n" + " sh:resultPath rdfs:label;\n" + " sh:sourceConstraintComponent sh:MinCountConstraintComponent;\n" + - " sh:sourceShape ex:PersonShapeProperty .\n" + - "\n" + - "_:node1d1e5rk4ux12 a sh:ValidationReport;\n" + - " sh:conforms false;\n" + - " sh:result _:node1d1e5rk4ux13, _:node1d1e5rk4ux14 .\n" + + " sh:sourceShape ex:PersonShapeProperty ." + ""), "", RDFFormat.TURTLE); @@ -104,15 +106,30 @@ public void nestedLogicalOrSupport() throws IOException { "@prefix rdf: .\n" + "@prefix sh: .\n" + "\n" + - "_:node1d1gbve96x12 a sh:ValidationResult;\n" + + "_:node1d1giv2b9x25 a sh:ValidationReport;\n" + + " sh:conforms false;\n" + + " sh:result _:node1d1giv2b9x26 .\n" + + "\n" + + "_:node1d1giv2b9x26 a sh:ValidationResult;\n" + + " sh:detail _:node1d1giv2b9x27 .\n" + + "\n" + + "_:node1d1giv2b9x27 a sh:ValidationResult;\n" + + " sh:detail _:node1d1giv2b9x28 .\n" + + "\n" + + "_:node1d1giv2b9x28 a sh:ValidationResult;\n" + " sh:focusNode ex:validPerson1;\n" + " sh:resultPath ex:age;\n" + - " sh:sourceConstraintComponent sh:DatatypeConstraintComponent, sh:OrConstraintComponent;\n" + - " sh:sourceShape _:node1d1gbve7vx1, _:node1d1gbve7vx3, _:node1d1gbve7vx5 .\n" + + " sh:sourceConstraintComponent sh:DatatypeConstraintComponent;\n" + + " sh:sourceShape ex:personShapeAgeLong .\n" + "\n" + - "_:node1d1gbve96x11 a sh:ValidationReport;\n" + - " sh:conforms false;\n" + - " sh:result _:node1d1gbve96x12 ." + + "_:node1d1giv2b9x27 sh:focusNode ex:validPerson1;\n" + + " sh:resultPath ex:age;\n" + + " sh:sourceConstraintComponent sh:DatatypeConstraintComponent;\n" + + " sh:sourceShape ex:personShapeAgeInteger .\n" + + "\n" + + "_:node1d1giv2b9x26 sh:focusNode ex:validPerson1;\n" + + " sh:sourceConstraintComponent sh:OrConstraintComponent;\n" + + " sh:sourceShape ex:personShapeOr ." + ""), "", RDFFormat.TURTLE); diff --git a/shacl/src/test/resources/test-cases/or/datatype/shacl.ttl b/shacl/src/test/resources/test-cases/or/datatype/shacl.ttl index 2be46060e..649c12ae8 100644 --- a/shacl/src/test/resources/test-cases/or/datatype/shacl.ttl +++ b/shacl/src/test/resources/test-cases/or/datatype/shacl.ttl @@ -9,16 +9,19 @@ ex:PersonShape a sh:NodeShape ; sh:targetClass ex:Person ; - sh:property [ + sh:property ex:personShapeOr. + + +ex:personShapeOr sh:or ( - [ - sh:path ex:age ; - sh:datatype xsd:integer ; - ] - [ - sh:path ex:age ; - sh:datatype xsd:long ; - ] - ) ; - ] . + ex:personShapeAgeInteger + ex:personShapeAgeLong + ) . + +ex:personShapeAgeInteger + sh:path ex:age ; + sh:datatype xsd:integer . +ex:personShapeAgeLong + sh:path ex:age ; + sh:datatype xsd:long . \ No newline at end of file From 4b763ada1ce2db11596e0807673922a7e5b05aa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Avard=20Ottestad?= Date: Thu, 17 Jan 2019 20:03:23 +0100 Subject: [PATCH 39/54] eclipse/rdf4j#1109 reuse plan from datatype to implement minLength and maxLength MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håvard Ottestad --- .../sail/shacl/AST/DatatypePropertyShape.java | 37 +++------- .../shacl/AST/MaxLengthPropertyShape.java | 68 +++++++++++++++++++ .../shacl/AST/MinLengthPropertyShape.java | 67 ++++++++++++++++++ .../rdf4j/sail/shacl/AST/PropertyShape.java | 16 +++++ .../shacl/AST/StandardisedPlanHelper.java | 59 ++++++++++++++++ .../sail/shacl/planNodes/MaxLengthFilter.java | 42 ++++++++++++ .../sail/shacl/planNodes/MinLengthFilter.java | 43 ++++++++++++ .../eclipse/rdf4j/sail/shacl/ShaclTest.java | 2 + .../maxLength/simple/invalid/case1/query1.rq | 14 ++++ .../maxLength/simple/invalid/case2/query1.rq | 14 ++++ .../maxLength/simple/invalid/case2/query2.rq | 13 ++++ .../maxLength/simple/invalid/case3/query1.rq | 13 ++++ .../maxLength/simple/invalid/case3/query2.rq | 12 ++++ .../maxLength/simple/invalid/case4/query1.rq | 13 ++++ .../maxLength/simple/invalid/case4/query2.rq | 14 ++++ .../maxLength/simple/invalid/case5/query1.rq | 12 ++++ .../maxLength/simple/invalid/case5/query2.rq | 18 +++++ .../test-cases/maxLength/simple/shacl.ttl | 16 +++++ .../maxLength/simple/valid/case1/query1.rq | 13 ++++ .../maxLength/simple/valid/case2/query1.rq | 13 ++++ .../maxLength/simple/valid/case2/query2.rq | 14 ++++ .../maxLength/simple/valid/case3/query1.rq | 13 ++++ .../maxLength/simple/valid/case3/query2.rq | 15 ++++ .../maxLength/simple/valid/case4/query1.rq | 13 ++++ .../minLength/simple/invalid/case1/query1.rq | 14 ++++ .../minLength/simple/invalid/case2/query1.rq | 14 ++++ .../minLength/simple/invalid/case2/query2.rq | 13 ++++ .../minLength/simple/invalid/case3/query1.rq | 13 ++++ .../minLength/simple/invalid/case3/query2.rq | 12 ++++ .../minLength/simple/invalid/case4/query1.rq | 13 ++++ .../minLength/simple/invalid/case4/query2.rq | 14 ++++ .../minLength/simple/invalid/case5/query1.rq | 12 ++++ .../minLength/simple/invalid/case5/query2.rq | 18 +++++ .../test-cases/minLength/simple/shacl.ttl | 16 +++++ .../minLength/simple/valid/case1/query1.rq | 13 ++++ .../minLength/simple/valid/case2/query1.rq | 13 ++++ .../minLength/simple/valid/case2/query2.rq | 14 ++++ .../minLength/simple/valid/case3/query1.rq | 13 ++++ .../minLength/simple/valid/case3/query2.rq | 15 ++++ .../minLength/simple/valid/case4/query1.rq | 13 ++++ 40 files changed, 745 insertions(+), 29 deletions(-) create mode 100644 shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MaxLengthPropertyShape.java create mode 100644 shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MinLengthPropertyShape.java create mode 100644 shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/StandardisedPlanHelper.java create mode 100644 shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MaxLengthFilter.java create mode 100644 shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MinLengthFilter.java create mode 100644 shacl/src/test/resources/test-cases/maxLength/simple/invalid/case1/query1.rq create mode 100644 shacl/src/test/resources/test-cases/maxLength/simple/invalid/case2/query1.rq create mode 100644 shacl/src/test/resources/test-cases/maxLength/simple/invalid/case2/query2.rq create mode 100644 shacl/src/test/resources/test-cases/maxLength/simple/invalid/case3/query1.rq create mode 100644 shacl/src/test/resources/test-cases/maxLength/simple/invalid/case3/query2.rq create mode 100644 shacl/src/test/resources/test-cases/maxLength/simple/invalid/case4/query1.rq create mode 100644 shacl/src/test/resources/test-cases/maxLength/simple/invalid/case4/query2.rq create mode 100644 shacl/src/test/resources/test-cases/maxLength/simple/invalid/case5/query1.rq create mode 100644 shacl/src/test/resources/test-cases/maxLength/simple/invalid/case5/query2.rq create mode 100644 shacl/src/test/resources/test-cases/maxLength/simple/shacl.ttl create mode 100644 shacl/src/test/resources/test-cases/maxLength/simple/valid/case1/query1.rq create mode 100644 shacl/src/test/resources/test-cases/maxLength/simple/valid/case2/query1.rq create mode 100644 shacl/src/test/resources/test-cases/maxLength/simple/valid/case2/query2.rq create mode 100644 shacl/src/test/resources/test-cases/maxLength/simple/valid/case3/query1.rq create mode 100644 shacl/src/test/resources/test-cases/maxLength/simple/valid/case3/query2.rq create mode 100644 shacl/src/test/resources/test-cases/maxLength/simple/valid/case4/query1.rq create mode 100644 shacl/src/test/resources/test-cases/minLength/simple/invalid/case1/query1.rq create mode 100644 shacl/src/test/resources/test-cases/minLength/simple/invalid/case2/query1.rq create mode 100644 shacl/src/test/resources/test-cases/minLength/simple/invalid/case2/query2.rq create mode 100644 shacl/src/test/resources/test-cases/minLength/simple/invalid/case3/query1.rq create mode 100644 shacl/src/test/resources/test-cases/minLength/simple/invalid/case3/query2.rq create mode 100644 shacl/src/test/resources/test-cases/minLength/simple/invalid/case4/query1.rq create mode 100644 shacl/src/test/resources/test-cases/minLength/simple/invalid/case4/query2.rq create mode 100644 shacl/src/test/resources/test-cases/minLength/simple/invalid/case5/query1.rq create mode 100644 shacl/src/test/resources/test-cases/minLength/simple/invalid/case5/query2.rq create mode 100644 shacl/src/test/resources/test-cases/minLength/simple/shacl.ttl create mode 100644 shacl/src/test/resources/test-cases/minLength/simple/valid/case1/query1.rq create mode 100644 shacl/src/test/resources/test-cases/minLength/simple/valid/case2/query1.rq create mode 100644 shacl/src/test/resources/test-cases/minLength/simple/valid/case2/query2.rq create mode 100644 shacl/src/test/resources/test-cases/minLength/simple/valid/case3/query1.rq create mode 100644 shacl/src/test/resources/test-cases/minLength/simple/valid/case3/query2.rq create mode 100644 shacl/src/test/resources/test-cases/minLength/simple/valid/case4/query1.rq diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/DatatypePropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/DatatypePropertyShape.java index 3caf8fe36..5931cc649 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/DatatypePropertyShape.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/DatatypePropertyShape.java @@ -25,6 +25,7 @@ import org.eclipse.rdf4j.sail.shacl.planNodes.EnrichWithShape; import org.eclipse.rdf4j.sail.shacl.planNodes.InnerJoin; import org.eclipse.rdf4j.sail.shacl.planNodes.LoggingNode; +import org.eclipse.rdf4j.sail.shacl.planNodes.MinLengthFilter; import org.eclipse.rdf4j.sail.shacl.planNodes.PushBasedLoggingNode; import org.eclipse.rdf4j.sail.shacl.planNodes.UnionNode; import org.eclipse.rdf4j.sail.shacl.planNodes.PlanNode; @@ -55,36 +56,14 @@ public class DatatypePropertyShape extends PathPropertyShape { @Override public PlanNode getPlan(ShaclSailConnection shaclSailConnection, NodeShape nodeShape, boolean printPlans, boolean assumeBaseSailValid) { - PlanNode addedByShape = new LoggingNode(nodeShape.getPlanAddedStatements(shaclSailConnection, nodeShape)); + PlanNode invalidValues = StandardisedPlanHelper.getGenericSingleObjectPlan( + shaclSailConnection, + nodeShape, + (parent, trueNode, falseNode) -> new DatatypeFilter(parent, trueNode, falseNode, datatype), + this + ); - BufferedSplitter bufferedSplitter = new BufferedSplitter(addedByShape); - - PlanNode addedByPath = new LoggingNode(new Select(shaclSailConnection.getAddedStatements(), path.getQuery())); - - // this is essentially pushing the filter down below the join - DirectTupleFromFilter invalidValuesDirectOnPath = new DirectTupleFromFilter(); - new DatatypeFilter(addedByPath, null, new PushBasedLoggingNode(invalidValuesDirectOnPath), datatype); - - BufferedTupleFromFilter discardedRight = new BufferedTupleFromFilter(); - - - PlanNode top = new LoggingNode(new InnerJoin(bufferedSplitter.getPlanNode(), invalidValuesDirectOnPath, null, discardedRight)); - - - if (nodeShape instanceof TargetClass) { - PlanNode typeFilterPlan = new LoggingNode(((TargetClass) nodeShape).getTypeFilterPlan(shaclSailConnection.getPreviousStateConnection(), discardedRight)); - - top = new LoggingNode(new UnionNode(top, typeFilterPlan)); - } - - PlanNode bulkedEcternalInnerJoin = new LoggingNode(new BulkedExternalInnerJoin(bufferedSplitter.getPlanNode(), shaclSailConnection.getPreviousStateConnection(), path.getQuery())); - - top = new LoggingNode(new UnionNode(top, bulkedEcternalInnerJoin)); - - DirectTupleFromFilter invalidValues = new DirectTupleFromFilter(); - new DatatypeFilter(top, null, invalidValues, datatype); - - if(printPlans){ + if (printPlans) { String planAsGraphvizDot = getPlanAsGraphvizDot(invalidValues, shaclSailConnection); logger.info(planAsGraphvizDot); } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MaxLengthPropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MaxLengthPropertyShape.java new file mode 100644 index 000000000..6e7399632 --- /dev/null +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MaxLengthPropertyShape.java @@ -0,0 +1,68 @@ +/******************************************************************************* + * Copyright (c) 2018 Eclipse RDF4J contributors. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.sail.shacl.AST; + + +import org.eclipse.rdf4j.common.iteration.Iterations; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.impl.SimpleLiteral; +import org.eclipse.rdf4j.model.vocabulary.SHACL; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; +import org.eclipse.rdf4j.sail.shacl.ShaclSailConnection; +import org.eclipse.rdf4j.sail.shacl.planNodes.MaxLengthFilter; +import org.eclipse.rdf4j.sail.shacl.planNodes.MinLengthFilter; +import org.eclipse.rdf4j.sail.shacl.planNodes.PlanNode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.stream.Stream; + +/** + * @author Håvard Ottestad + */ +public class MaxLengthPropertyShape extends PathPropertyShape { + + private final long maxLength; + private static final Logger logger = LoggerFactory.getLogger(MaxLengthPropertyShape.class); + + MaxLengthPropertyShape(Resource id, SailRepositoryConnection connection, NodeShape nodeShape) { + super(id, connection, nodeShape); + + try (Stream stream = Iterations.stream(connection.getStatements(id, SHACL.MAX_LENGTH, null, true))) { + maxLength = stream.map(Statement::getObject).map(v -> ((SimpleLiteral) v).integerValue().longValue()).findAny().orElseThrow(() -> new RuntimeException("Expected to find sh:minLength on " + id)); + } + + } + + + @Override + public PlanNode getPlan(ShaclSailConnection shaclSailConnection, NodeShape nodeShape, boolean printPlans, boolean assumeBaseSailValid) { + + PlanNode invalidValues = StandardisedPlanHelper.getGenericSingleObjectPlan( + shaclSailConnection, + nodeShape, + (parent, trueNode, falseNode) -> new MaxLengthFilter(parent, trueNode, falseNode, maxLength), + this + ); + + if (printPlans) { + String planAsGraphvizDot = getPlanAsGraphvizDot(invalidValues, shaclSailConnection); + logger.info(planAsGraphvizDot); + } + + return invalidValues; + + } + + @Override + public boolean requiresEvaluation(Repository addedStatements, Repository removedStatements) { + return true; + } +} diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MinLengthPropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MinLengthPropertyShape.java new file mode 100644 index 000000000..4b8d9bcad --- /dev/null +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MinLengthPropertyShape.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * Copyright (c) 2018 Eclipse RDF4J contributors. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.sail.shacl.AST; + + +import org.eclipse.rdf4j.common.iteration.Iterations; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.impl.SimpleLiteral; +import org.eclipse.rdf4j.model.vocabulary.SHACL; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; +import org.eclipse.rdf4j.sail.shacl.ShaclSailConnection; +import org.eclipse.rdf4j.sail.shacl.planNodes.MinLengthFilter; +import org.eclipse.rdf4j.sail.shacl.planNodes.PlanNode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.stream.Stream; + +/** + * @author Håvard Ottestad + */ +public class MinLengthPropertyShape extends PathPropertyShape { + + private final long minLength; + private static final Logger logger = LoggerFactory.getLogger(MinLengthPropertyShape.class); + + MinLengthPropertyShape(Resource id, SailRepositoryConnection connection, NodeShape nodeShape) { + super(id, connection, nodeShape); + + try (Stream stream = Iterations.stream(connection.getStatements(id, SHACL.MIN_LENGTH, null, true))) { + minLength = stream.map(Statement::getObject).map(v -> ((SimpleLiteral) v).integerValue().longValue()).findAny().orElseThrow(() -> new RuntimeException("Expected to find sh:minLength on " + id)); + } + + } + + + @Override + public PlanNode getPlan(ShaclSailConnection shaclSailConnection, NodeShape nodeShape, boolean printPlans, boolean assumeBaseSailValid) { + + PlanNode invalidValues = StandardisedPlanHelper.getGenericSingleObjectPlan( + shaclSailConnection, + nodeShape, + (parent, trueNode, falseNode) -> new MinLengthFilter(parent, trueNode, falseNode, minLength), + this + ); + + if (printPlans) { + String planAsGraphvizDot = getPlanAsGraphvizDot(invalidValues, shaclSailConnection); + logger.info(planAsGraphvizDot); + } + + return invalidValues; + + } + + @Override + public boolean requiresEvaluation(Repository addedStatements, Repository removedStatements) { + return true; + } +} diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PropertyShape.java index dcb18b9a2..89d85f043 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PropertyShape.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PropertyShape.java @@ -132,6 +132,14 @@ static List getPropertyShapesInner(SailRepositoryConnection conne if (hasOr(propertyShapeId, connection)) { propertyShapes.add(new OrPropertyShape(propertyShapeId, connection, nodeShape)); } + + if (hasMinLength(propertyShapeId, connection)) { + propertyShapes.add(new MinLengthPropertyShape(propertyShapeId, connection, nodeShape)); + } + + if (hasMaxLength(propertyShapeId, connection)) { + propertyShapes.add(new MaxLengthPropertyShape(propertyShapeId, connection, nodeShape)); + } return propertyShapes; } @@ -152,6 +160,14 @@ private static boolean hasDatatype(Resource id, SailRepositoryConnection connect return connection.hasStatement(id, SHACL.DATATYPE, null, true); } + private static boolean hasMinLength(Resource id, SailRepositoryConnection connection) { + return connection.hasStatement(id, SHACL.MIN_LENGTH, null, true); + } + + private static boolean hasMaxLength(Resource id, SailRepositoryConnection connection) { + return connection.hasStatement(id, SHACL.MAX_LENGTH, null, true); + } + } } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/StandardisedPlanHelper.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/StandardisedPlanHelper.java new file mode 100644 index 000000000..ae75968f5 --- /dev/null +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/StandardisedPlanHelper.java @@ -0,0 +1,59 @@ +package org.eclipse.rdf4j.sail.shacl.AST; + +import org.eclipse.rdf4j.sail.shacl.ShaclSailConnection; +import org.eclipse.rdf4j.sail.shacl.planNodes.BufferedSplitter; +import org.eclipse.rdf4j.sail.shacl.planNodes.BufferedTupleFromFilter; +import org.eclipse.rdf4j.sail.shacl.planNodes.BulkedExternalInnerJoin; +import org.eclipse.rdf4j.sail.shacl.planNodes.DirectTupleFromFilter; +import org.eclipse.rdf4j.sail.shacl.planNodes.InnerJoin; +import org.eclipse.rdf4j.sail.shacl.planNodes.LoggingNode; +import org.eclipse.rdf4j.sail.shacl.planNodes.PlanNode; +import org.eclipse.rdf4j.sail.shacl.planNodes.PushBasedLoggingNode; +import org.eclipse.rdf4j.sail.shacl.planNodes.PushBasedPlanNode; +import org.eclipse.rdf4j.sail.shacl.planNodes.Select; +import org.eclipse.rdf4j.sail.shacl.planNodes.UnionNode; + +public class StandardisedPlanHelper { + + interface FilterAttacher { + void attachFilter(PlanNode parent, PushBasedPlanNode trueNode, PushBasedPlanNode falseNode); + } + + static public PlanNode getGenericSingleObjectPlan(ShaclSailConnection shaclSailConnection, NodeShape nodeShape, FilterAttacher filterAttacher, PathPropertyShape pathPropertyShape) { + PlanNode addedByShape = new LoggingNode(nodeShape.getPlanAddedStatements(shaclSailConnection, nodeShape)); + + BufferedSplitter bufferedSplitter = new BufferedSplitter(addedByShape); + + PlanNode addedByPath = new LoggingNode(new Select(shaclSailConnection.getAddedStatements(), pathPropertyShape.path.getQuery())); + + // this is essentially pushing the filter down below the join + DirectTupleFromFilter invalidValuesDirectOnPath = new DirectTupleFromFilter(); + + filterAttacher.attachFilter(addedByPath, null, new PushBasedLoggingNode(invalidValuesDirectOnPath)); + + + BufferedTupleFromFilter discardedRight = new BufferedTupleFromFilter(); + + + PlanNode top = new LoggingNode(new InnerJoin(bufferedSplitter.getPlanNode(), invalidValuesDirectOnPath, null, discardedRight)); + + + if (nodeShape instanceof TargetClass) { + PlanNode typeFilterPlan = new LoggingNode(((TargetClass) nodeShape).getTypeFilterPlan(shaclSailConnection.getPreviousStateConnection(), discardedRight)); + + top = new LoggingNode(new UnionNode(top, typeFilterPlan)); + } + + PlanNode bulkedEcternalInnerJoin = new LoggingNode(new BulkedExternalInnerJoin(bufferedSplitter.getPlanNode(), shaclSailConnection.getPreviousStateConnection(), pathPropertyShape.path.getQuery())); + + top = new LoggingNode(new UnionNode(top, bulkedEcternalInnerJoin)); + + DirectTupleFromFilter invalidValues = new DirectTupleFromFilter(); + filterAttacher.attachFilter(top, null, invalidValues); + + + return new LoggingNode(invalidValues); + } + + +} diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MaxLengthFilter.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MaxLengthFilter.java new file mode 100644 index 000000000..6a52e4fca --- /dev/null +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MaxLengthFilter.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2018 Eclipse RDF4J contributors. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ + +package org.eclipse.rdf4j.sail.shacl.planNodes; + + +import org.eclipse.rdf4j.model.Literal; + +/** + * @author Håvard Ottestad + */ +public class MaxLengthFilter extends FilterPlanNode { + + private final long maxLength; + + public MaxLengthFilter(PlanNode parent, PushBasedPlanNode trueNode, PushBasedPlanNode falseNode, long maxLength) { + super(parent, trueNode, falseNode); + this.maxLength = maxLength; + } + + @Override + boolean checkTuple(Tuple t) { + if(! (t.line.get(1) instanceof Literal)) return false; + + Literal literal = (Literal) t.line.get(1); + + return literal.stringValue().length() <= maxLength; + } + + + @Override + public String toString() { + return "MaxLengthFilter{" + + "maxLength=" + maxLength + + '}'; + } +} diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MinLengthFilter.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MinLengthFilter.java new file mode 100644 index 000000000..ed5ed8ae2 --- /dev/null +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MinLengthFilter.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2018 Eclipse RDF4J contributors. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ + +package org.eclipse.rdf4j.sail.shacl.planNodes; + + +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Resource; + +/** + * @author Håvard Ottestad + */ +public class MinLengthFilter extends FilterPlanNode { + + private final long minLength; + + public MinLengthFilter(PlanNode parent, PushBasedPlanNode trueNode, PushBasedPlanNode falseNode, long minLength) { + super(parent, trueNode, falseNode); + this.minLength = minLength; + } + + @Override + boolean checkTuple(Tuple t) { + if(! (t.line.get(1) instanceof Literal)) return false; + + Literal literal = (Literal) t.line.get(1); + + return literal.stringValue().length() >= minLength; + } + + + @Override + public String toString() { + return "MinLengthFilter{" + + "minLength=" + minLength + + '}'; + } +} diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java index 4c1feddcf..9bb5931c5 100644 --- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java @@ -41,6 +41,8 @@ public class ShaclTest { private static final List testCasePaths = Arrays.asList( "test-cases/datatype/simple", + "test-cases/minLength/simple", + "test-cases/maxLength/simple", "test-cases/minCount/simple", "test-cases/maxCount/simple", "test-cases/or/inheritance", diff --git a/shacl/src/test/resources/test-cases/maxLength/simple/invalid/case1/query1.rq b/shacl/src/test/resources/test-cases/maxLength/simple/invalid/case1/query1.rq new file mode 100644 index 000000000..99675763d --- /dev/null +++ b/shacl/src/test/resources/test-cases/maxLength/simple/invalid/case1/query1.rq @@ -0,0 +1,14 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person ; + ex:phoneNumber "123456789". + + +} diff --git a/shacl/src/test/resources/test-cases/maxLength/simple/invalid/case2/query1.rq b/shacl/src/test/resources/test-cases/maxLength/simple/invalid/case2/query1.rq new file mode 100644 index 000000000..93fb59468 --- /dev/null +++ b/shacl/src/test/resources/test-cases/maxLength/simple/invalid/case2/query1.rq @@ -0,0 +1,14 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person ; + ex:phoneNumber "12345678". + + +} diff --git a/shacl/src/test/resources/test-cases/maxLength/simple/invalid/case2/query2.rq b/shacl/src/test/resources/test-cases/maxLength/simple/invalid/case2/query2.rq new file mode 100644 index 000000000..097f85ec5 --- /dev/null +++ b/shacl/src/test/resources/test-cases/maxLength/simple/invalid/case2/query2.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 ex:phoneNumber "123456789". + + +} diff --git a/shacl/src/test/resources/test-cases/maxLength/simple/invalid/case3/query1.rq b/shacl/src/test/resources/test-cases/maxLength/simple/invalid/case3/query1.rq new file mode 100644 index 000000000..097f85ec5 --- /dev/null +++ b/shacl/src/test/resources/test-cases/maxLength/simple/invalid/case3/query1.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 ex:phoneNumber "123456789". + + +} diff --git a/shacl/src/test/resources/test-cases/maxLength/simple/invalid/case3/query2.rq b/shacl/src/test/resources/test-cases/maxLength/simple/invalid/case3/query2.rq new file mode 100644 index 000000000..93fb72304 --- /dev/null +++ b/shacl/src/test/resources/test-cases/maxLength/simple/invalid/case3/query2.rq @@ -0,0 +1,12 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person . + +} diff --git a/shacl/src/test/resources/test-cases/maxLength/simple/invalid/case4/query1.rq b/shacl/src/test/resources/test-cases/maxLength/simple/invalid/case4/query1.rq new file mode 100644 index 000000000..097f85ec5 --- /dev/null +++ b/shacl/src/test/resources/test-cases/maxLength/simple/invalid/case4/query1.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 ex:phoneNumber "123456789". + + +} diff --git a/shacl/src/test/resources/test-cases/maxLength/simple/invalid/case4/query2.rq b/shacl/src/test/resources/test-cases/maxLength/simple/invalid/case4/query2.rq new file mode 100644 index 000000000..b34873e78 --- /dev/null +++ b/shacl/src/test/resources/test-cases/maxLength/simple/invalid/case4/query2.rq @@ -0,0 +1,14 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 + ex:phoneNumber "12345678" ; + a ex:Person . + +} diff --git a/shacl/src/test/resources/test-cases/maxLength/simple/invalid/case5/query1.rq b/shacl/src/test/resources/test-cases/maxLength/simple/invalid/case5/query1.rq new file mode 100644 index 000000000..fde66e82d --- /dev/null +++ b/shacl/src/test/resources/test-cases/maxLength/simple/invalid/case5/query1.rq @@ -0,0 +1,12 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 ex:phoneNumber "123456789". + +} diff --git a/shacl/src/test/resources/test-cases/maxLength/simple/invalid/case5/query2.rq b/shacl/src/test/resources/test-cases/maxLength/simple/invalid/case5/query2.rq new file mode 100644 index 000000000..32e20f1db --- /dev/null +++ b/shacl/src/test/resources/test-cases/maxLength/simple/invalid/case5/query2.rq @@ -0,0 +1,18 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 + ex:phoneNumber "12345678" ; + a ex:Person . + +ex:validPerson2 + ex:phoneNumber "12345678" ; + a ex:Person . + +} diff --git a/shacl/src/test/resources/test-cases/maxLength/simple/shacl.ttl b/shacl/src/test/resources/test-cases/maxLength/simple/shacl.ttl new file mode 100644 index 000000000..86309d8e2 --- /dev/null +++ b/shacl/src/test/resources/test-cases/maxLength/simple/shacl.ttl @@ -0,0 +1,16 @@ +@base . +@prefix ex: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix xsd: . + +ex:PersonShape + a sh:NodeShape ; + sh:targetClass ex:Person ; + sh:property [ + sh:path ex:phoneNumber ; + sh:maxLength 8 ; + ] . + diff --git a/shacl/src/test/resources/test-cases/maxLength/simple/valid/case1/query1.rq b/shacl/src/test/resources/test-cases/maxLength/simple/valid/case1/query1.rq new file mode 100644 index 000000000..bb337418e --- /dev/null +++ b/shacl/src/test/resources/test-cases/maxLength/simple/valid/case1/query1.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person ; + ex:phoneNumber "12345678". + +} diff --git a/shacl/src/test/resources/test-cases/maxLength/simple/valid/case2/query1.rq b/shacl/src/test/resources/test-cases/maxLength/simple/valid/case2/query1.rq new file mode 100644 index 000000000..bb337418e --- /dev/null +++ b/shacl/src/test/resources/test-cases/maxLength/simple/valid/case2/query1.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person ; + ex:phoneNumber "12345678". + +} diff --git a/shacl/src/test/resources/test-cases/maxLength/simple/valid/case2/query2.rq b/shacl/src/test/resources/test-cases/maxLength/simple/valid/case2/query2.rq new file mode 100644 index 000000000..204e6f78a --- /dev/null +++ b/shacl/src/test/resources/test-cases/maxLength/simple/valid/case2/query2.rq @@ -0,0 +1,14 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 ex:phoneNumber "1234567". + + +} + diff --git a/shacl/src/test/resources/test-cases/maxLength/simple/valid/case3/query1.rq b/shacl/src/test/resources/test-cases/maxLength/simple/valid/case3/query1.rq new file mode 100644 index 000000000..46e35c92a --- /dev/null +++ b/shacl/src/test/resources/test-cases/maxLength/simple/valid/case3/query1.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 ex:phoneNumber "12345678". +. + +} diff --git a/shacl/src/test/resources/test-cases/maxLength/simple/valid/case3/query2.rq b/shacl/src/test/resources/test-cases/maxLength/simple/valid/case3/query2.rq new file mode 100644 index 000000000..2128eec50 --- /dev/null +++ b/shacl/src/test/resources/test-cases/maxLength/simple/valid/case3/query2.rq @@ -0,0 +1,15 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + + +ex:validPerson2 + ex:phoneNumber "1234567" ; + a ex:Person . + +} diff --git a/shacl/src/test/resources/test-cases/maxLength/simple/valid/case4/query1.rq b/shacl/src/test/resources/test-cases/maxLength/simple/valid/case4/query1.rq new file mode 100644 index 000000000..989884ede --- /dev/null +++ b/shacl/src/test/resources/test-cases/maxLength/simple/valid/case4/query1.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person ; + ex:phoneNumber "12345678"@en, "12345678"^^xsd:xmlLiteral. + +} diff --git a/shacl/src/test/resources/test-cases/minLength/simple/invalid/case1/query1.rq b/shacl/src/test/resources/test-cases/minLength/simple/invalid/case1/query1.rq new file mode 100644 index 000000000..7b22cda5e --- /dev/null +++ b/shacl/src/test/resources/test-cases/minLength/simple/invalid/case1/query1.rq @@ -0,0 +1,14 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person ; + ex:phoneNumber "1234567". + + +} diff --git a/shacl/src/test/resources/test-cases/minLength/simple/invalid/case2/query1.rq b/shacl/src/test/resources/test-cases/minLength/simple/invalid/case2/query1.rq new file mode 100644 index 000000000..93fb59468 --- /dev/null +++ b/shacl/src/test/resources/test-cases/minLength/simple/invalid/case2/query1.rq @@ -0,0 +1,14 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person ; + ex:phoneNumber "12345678". + + +} diff --git a/shacl/src/test/resources/test-cases/minLength/simple/invalid/case2/query2.rq b/shacl/src/test/resources/test-cases/minLength/simple/invalid/case2/query2.rq new file mode 100644 index 000000000..352a6135d --- /dev/null +++ b/shacl/src/test/resources/test-cases/minLength/simple/invalid/case2/query2.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 ex:phoneNumber "1234567". + + +} diff --git a/shacl/src/test/resources/test-cases/minLength/simple/invalid/case3/query1.rq b/shacl/src/test/resources/test-cases/minLength/simple/invalid/case3/query1.rq new file mode 100644 index 000000000..352a6135d --- /dev/null +++ b/shacl/src/test/resources/test-cases/minLength/simple/invalid/case3/query1.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 ex:phoneNumber "1234567". + + +} diff --git a/shacl/src/test/resources/test-cases/minLength/simple/invalid/case3/query2.rq b/shacl/src/test/resources/test-cases/minLength/simple/invalid/case3/query2.rq new file mode 100644 index 000000000..93fb72304 --- /dev/null +++ b/shacl/src/test/resources/test-cases/minLength/simple/invalid/case3/query2.rq @@ -0,0 +1,12 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person . + +} diff --git a/shacl/src/test/resources/test-cases/minLength/simple/invalid/case4/query1.rq b/shacl/src/test/resources/test-cases/minLength/simple/invalid/case4/query1.rq new file mode 100644 index 000000000..352a6135d --- /dev/null +++ b/shacl/src/test/resources/test-cases/minLength/simple/invalid/case4/query1.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 ex:phoneNumber "1234567". + + +} diff --git a/shacl/src/test/resources/test-cases/minLength/simple/invalid/case4/query2.rq b/shacl/src/test/resources/test-cases/minLength/simple/invalid/case4/query2.rq new file mode 100644 index 000000000..b34873e78 --- /dev/null +++ b/shacl/src/test/resources/test-cases/minLength/simple/invalid/case4/query2.rq @@ -0,0 +1,14 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 + ex:phoneNumber "12345678" ; + a ex:Person . + +} diff --git a/shacl/src/test/resources/test-cases/minLength/simple/invalid/case5/query1.rq b/shacl/src/test/resources/test-cases/minLength/simple/invalid/case5/query1.rq new file mode 100644 index 000000000..0d56cb83e --- /dev/null +++ b/shacl/src/test/resources/test-cases/minLength/simple/invalid/case5/query1.rq @@ -0,0 +1,12 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 ex:phoneNumber "1234567". + +} diff --git a/shacl/src/test/resources/test-cases/minLength/simple/invalid/case5/query2.rq b/shacl/src/test/resources/test-cases/minLength/simple/invalid/case5/query2.rq new file mode 100644 index 000000000..32e20f1db --- /dev/null +++ b/shacl/src/test/resources/test-cases/minLength/simple/invalid/case5/query2.rq @@ -0,0 +1,18 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 + ex:phoneNumber "12345678" ; + a ex:Person . + +ex:validPerson2 + ex:phoneNumber "12345678" ; + a ex:Person . + +} diff --git a/shacl/src/test/resources/test-cases/minLength/simple/shacl.ttl b/shacl/src/test/resources/test-cases/minLength/simple/shacl.ttl new file mode 100644 index 000000000..c9ea6351c --- /dev/null +++ b/shacl/src/test/resources/test-cases/minLength/simple/shacl.ttl @@ -0,0 +1,16 @@ +@base . +@prefix ex: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix xsd: . + +ex:PersonShape + a sh:NodeShape ; + sh:targetClass ex:Person ; + sh:property [ + sh:path ex:phoneNumber ; + sh:minLength 8 ; + ] . + diff --git a/shacl/src/test/resources/test-cases/minLength/simple/valid/case1/query1.rq b/shacl/src/test/resources/test-cases/minLength/simple/valid/case1/query1.rq new file mode 100644 index 000000000..bb337418e --- /dev/null +++ b/shacl/src/test/resources/test-cases/minLength/simple/valid/case1/query1.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person ; + ex:phoneNumber "12345678". + +} diff --git a/shacl/src/test/resources/test-cases/minLength/simple/valid/case2/query1.rq b/shacl/src/test/resources/test-cases/minLength/simple/valid/case2/query1.rq new file mode 100644 index 000000000..bb337418e --- /dev/null +++ b/shacl/src/test/resources/test-cases/minLength/simple/valid/case2/query1.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person ; + ex:phoneNumber "12345678". + +} diff --git a/shacl/src/test/resources/test-cases/minLength/simple/valid/case2/query2.rq b/shacl/src/test/resources/test-cases/minLength/simple/valid/case2/query2.rq new file mode 100644 index 000000000..03ec5755f --- /dev/null +++ b/shacl/src/test/resources/test-cases/minLength/simple/valid/case2/query2.rq @@ -0,0 +1,14 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 ex:phoneNumber "123456789". + + +} + diff --git a/shacl/src/test/resources/test-cases/minLength/simple/valid/case3/query1.rq b/shacl/src/test/resources/test-cases/minLength/simple/valid/case3/query1.rq new file mode 100644 index 000000000..46e35c92a --- /dev/null +++ b/shacl/src/test/resources/test-cases/minLength/simple/valid/case3/query1.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 ex:phoneNumber "12345678". +. + +} diff --git a/shacl/src/test/resources/test-cases/minLength/simple/valid/case3/query2.rq b/shacl/src/test/resources/test-cases/minLength/simple/valid/case3/query2.rq new file mode 100644 index 000000000..a1d5eef82 --- /dev/null +++ b/shacl/src/test/resources/test-cases/minLength/simple/valid/case3/query2.rq @@ -0,0 +1,15 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + + +ex:validPerson2 + ex:phoneNumber "123456789" ; + a ex:Person . + +} diff --git a/shacl/src/test/resources/test-cases/minLength/simple/valid/case4/query1.rq b/shacl/src/test/resources/test-cases/minLength/simple/valid/case4/query1.rq new file mode 100644 index 000000000..989884ede --- /dev/null +++ b/shacl/src/test/resources/test-cases/minLength/simple/valid/case4/query1.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person ; + ex:phoneNumber "12345678"@en, "12345678"^^xsd:xmlLiteral. + +} From 1c4cbf4fdfe010c79c51467f6521f03c536924e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Avard=20Ottestad?= Date: Thu, 17 Jan 2019 20:24:53 +0100 Subject: [PATCH 40/54] eclipse/rdf4j#1109 support for pattern MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håvard Ottestad --- .../sail/shacl/AST/PatternPropertyShape.java | 73 +++++++++++++++ .../rdf4j/sail/shacl/AST/PropertyShape.java | 8 ++ .../sail/shacl/planNodes/PatternFilter.java | 88 +++++++++++++++++++ .../eclipse/rdf4j/sail/shacl/ShaclTest.java | 1 + .../maxLength/simple/valid/case4/query1.rq | 2 +- .../minLength/simple/valid/case4/query1.rq | 2 +- .../pattern/simple/invalid/case1/query1.rq | 14 +++ .../pattern/simple/invalid/case2/query1.rq | 14 +++ .../pattern/simple/invalid/case2/query2.rq | 13 +++ .../pattern/simple/invalid/case3/query1.rq | 13 +++ .../pattern/simple/invalid/case3/query2.rq | 12 +++ .../pattern/simple/invalid/case4/query1.rq | 13 +++ .../pattern/simple/invalid/case4/query2.rq | 14 +++ .../pattern/simple/invalid/case5/query1.rq | 12 +++ .../pattern/simple/invalid/case5/query2.rq | 18 ++++ .../test-cases/pattern/simple/shacl.ttl | 23 +++++ .../pattern/simple/valid/case1/query1.rq | 13 +++ .../pattern/simple/valid/case2/query1.rq | 13 +++ .../pattern/simple/valid/case2/query2.rq | 14 +++ .../pattern/simple/valid/case3/query1.rq | 13 +++ .../pattern/simple/valid/case3/query2.rq | 15 ++++ .../pattern/simple/valid/case4/query1.rq | 14 +++ .../pattern/simple/valid/case5/query1.rq | 14 +++ 23 files changed, 414 insertions(+), 2 deletions(-) create mode 100644 shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PatternPropertyShape.java create mode 100644 shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/PatternFilter.java create mode 100644 shacl/src/test/resources/test-cases/pattern/simple/invalid/case1/query1.rq create mode 100644 shacl/src/test/resources/test-cases/pattern/simple/invalid/case2/query1.rq create mode 100644 shacl/src/test/resources/test-cases/pattern/simple/invalid/case2/query2.rq create mode 100644 shacl/src/test/resources/test-cases/pattern/simple/invalid/case3/query1.rq create mode 100644 shacl/src/test/resources/test-cases/pattern/simple/invalid/case3/query2.rq create mode 100644 shacl/src/test/resources/test-cases/pattern/simple/invalid/case4/query1.rq create mode 100644 shacl/src/test/resources/test-cases/pattern/simple/invalid/case4/query2.rq create mode 100644 shacl/src/test/resources/test-cases/pattern/simple/invalid/case5/query1.rq create mode 100644 shacl/src/test/resources/test-cases/pattern/simple/invalid/case5/query2.rq create mode 100644 shacl/src/test/resources/test-cases/pattern/simple/shacl.ttl create mode 100644 shacl/src/test/resources/test-cases/pattern/simple/valid/case1/query1.rq create mode 100644 shacl/src/test/resources/test-cases/pattern/simple/valid/case2/query1.rq create mode 100644 shacl/src/test/resources/test-cases/pattern/simple/valid/case2/query2.rq create mode 100644 shacl/src/test/resources/test-cases/pattern/simple/valid/case3/query1.rq create mode 100644 shacl/src/test/resources/test-cases/pattern/simple/valid/case3/query2.rq create mode 100644 shacl/src/test/resources/test-cases/pattern/simple/valid/case4/query1.rq create mode 100644 shacl/src/test/resources/test-cases/pattern/simple/valid/case5/query1.rq diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PatternPropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PatternPropertyShape.java new file mode 100644 index 000000000..d013bc3e9 --- /dev/null +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PatternPropertyShape.java @@ -0,0 +1,73 @@ +/******************************************************************************* + * Copyright (c) 2018 Eclipse RDF4J contributors. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.sail.shacl.AST; + + +import org.eclipse.rdf4j.common.iteration.Iterations; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.vocabulary.SHACL; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; +import org.eclipse.rdf4j.sail.shacl.ShaclSailConnection; +import org.eclipse.rdf4j.sail.shacl.planNodes.PatternFilter; +import org.eclipse.rdf4j.sail.shacl.planNodes.PlanNode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Optional; +import java.util.stream.Stream; + +/** + * @author Håvard Ottestad + */ +public class PatternPropertyShape extends PathPropertyShape { + + private final String pattern; + private final Optional flags; + private static final Logger logger = LoggerFactory.getLogger(PatternPropertyShape.class); + + PatternPropertyShape(Resource id, SailRepositoryConnection connection, NodeShape nodeShape) { + super(id, connection, nodeShape); + + try (Stream stream = Iterations.stream(connection.getStatements(id, SHACL.PATTERN, null, true))) { + pattern = stream.map(Statement::getObject).map(Value::stringValue).findAny().orElseThrow(() -> new RuntimeException("Expected to find sh:pattern on " + id)); + } + + try (Stream stream = Iterations.stream(connection.getStatements(id, SHACL.FLAGS, null, true))) { + flags = stream.map(Statement::getObject).map(Value::stringValue).findAny(); + } + + } + + + @Override + public PlanNode getPlan(ShaclSailConnection shaclSailConnection, NodeShape nodeShape, boolean printPlans, boolean assumeBaseSailValid) { + + PlanNode invalidValues = StandardisedPlanHelper.getGenericSingleObjectPlan( + shaclSailConnection, + nodeShape, + (parent, trueNode, falseNode) -> new PatternFilter(parent, trueNode, falseNode, pattern, flags), + this + ); + + if (printPlans) { + String planAsGraphvizDot = getPlanAsGraphvizDot(invalidValues, shaclSailConnection); + logger.info(planAsGraphvizDot); + } + + return invalidValues; + + } + + @Override + public boolean requiresEvaluation(Repository addedStatements, Repository removedStatements) { + return true; + } +} diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PropertyShape.java index 89d85f043..156a79b95 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PropertyShape.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PropertyShape.java @@ -140,6 +140,10 @@ static List getPropertyShapesInner(SailRepositoryConnection conne if (hasMaxLength(propertyShapeId, connection)) { propertyShapes.add(new MaxLengthPropertyShape(propertyShapeId, connection, nodeShape)); } + + if (hasPattern(propertyShapeId, connection)) { + propertyShapes.add(new PatternPropertyShape(propertyShapeId, connection, nodeShape)); + } return propertyShapes; } @@ -168,6 +172,10 @@ private static boolean hasMaxLength(Resource id, SailRepositoryConnection connec return connection.hasStatement(id, SHACL.MAX_LENGTH, null, true); } + private static boolean hasPattern(Resource id, SailRepositoryConnection connection) { + return connection.hasStatement(id, SHACL.PATTERN, null, true); + } + } } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/PatternFilter.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/PatternFilter.java new file mode 100644 index 000000000..9bb1d59d1 --- /dev/null +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/PatternFilter.java @@ -0,0 +1,88 @@ +/******************************************************************************* + * Copyright (c) 2018 Eclipse RDF4J contributors. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ + +package org.eclipse.rdf4j.sail.shacl.planNodes; + + +import org.eclipse.rdf4j.model.Literal; + +import java.util.Optional; +import java.util.regex.Pattern; + +/** + * @author Håvard Ottestad + */ +public class PatternFilter extends FilterPlanNode { + + private final Pattern pattern; + + + public PatternFilter(PlanNode parent, PushBasedPlanNode trueNode, PushBasedPlanNode falseNode, String pattern, Optional flags) { + super(parent, trueNode, falseNode); + if (flags.isPresent()) { + + int flag = 0b0; + + String flagsString = flags.get(); + + if (flagsString.contains("i")) { + flag = flag | Pattern.CASE_INSENSITIVE; + } + + if (flagsString.contains("d")) { + flag = flag | Pattern.UNIX_LINES; + } + + if (flagsString.contains("m")) { + flag = flag | Pattern.MULTILINE; + } + + if (flagsString.contains("s")) { + flag = flag | Pattern.DOTALL; + } + + if (flagsString.contains("u")) { + flag = flag | Pattern.UNICODE_CASE; + } + + if (flagsString.contains("x")) { + flag = flag | Pattern.COMMENTS; + } + + if (flagsString.contains("U")) { + flag = flag | Pattern.UNICODE_CHARACTER_CLASS; + } + + this.pattern = Pattern.compile(pattern, flag); + + } else { + this.pattern = Pattern.compile(pattern); + + } + + } + + @Override + boolean checkTuple(Tuple t) { + if (!(t.line.get(1) instanceof Literal)) { + return false; + } + + Literal literal = (Literal) t.line.get(1); + + return pattern.matcher(literal.stringValue()).matches(); + } + + + @Override + public String toString() { + return "PatternFilter{" + + "pattern=" + pattern + + '}'; + } +} diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java index 9bb5931c5..232c71e0f 100644 --- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java @@ -43,6 +43,7 @@ public class ShaclTest { "test-cases/datatype/simple", "test-cases/minLength/simple", "test-cases/maxLength/simple", + "test-cases/pattern/simple", "test-cases/minCount/simple", "test-cases/maxCount/simple", "test-cases/or/inheritance", diff --git a/shacl/src/test/resources/test-cases/maxLength/simple/valid/case4/query1.rq b/shacl/src/test/resources/test-cases/maxLength/simple/valid/case4/query1.rq index 989884ede..871848524 100644 --- a/shacl/src/test/resources/test-cases/maxLength/simple/valid/case4/query1.rq +++ b/shacl/src/test/resources/test-cases/maxLength/simple/valid/case4/query1.rq @@ -8,6 +8,6 @@ PREFIX xsd: INSERT DATA { ex:validPerson1 a ex:Person ; - ex:phoneNumber "12345678"@en, "12345678"^^xsd:xmlLiteral. + ex:phoneNumber "12345678"@en, "22345678"^^xsd:xmlLiteral. } diff --git a/shacl/src/test/resources/test-cases/minLength/simple/valid/case4/query1.rq b/shacl/src/test/resources/test-cases/minLength/simple/valid/case4/query1.rq index 989884ede..871848524 100644 --- a/shacl/src/test/resources/test-cases/minLength/simple/valid/case4/query1.rq +++ b/shacl/src/test/resources/test-cases/minLength/simple/valid/case4/query1.rq @@ -8,6 +8,6 @@ PREFIX xsd: INSERT DATA { ex:validPerson1 a ex:Person ; - ex:phoneNumber "12345678"@en, "12345678"^^xsd:xmlLiteral. + ex:phoneNumber "12345678"@en, "22345678"^^xsd:xmlLiteral. } diff --git a/shacl/src/test/resources/test-cases/pattern/simple/invalid/case1/query1.rq b/shacl/src/test/resources/test-cases/pattern/simple/invalid/case1/query1.rq new file mode 100644 index 000000000..008966840 --- /dev/null +++ b/shacl/src/test/resources/test-cases/pattern/simple/invalid/case1/query1.rq @@ -0,0 +1,14 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person ; + ex:uuid "invalid". + + +} diff --git a/shacl/src/test/resources/test-cases/pattern/simple/invalid/case2/query1.rq b/shacl/src/test/resources/test-cases/pattern/simple/invalid/case2/query1.rq new file mode 100644 index 000000000..37d57a177 --- /dev/null +++ b/shacl/src/test/resources/test-cases/pattern/simple/invalid/case2/query1.rq @@ -0,0 +1,14 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person ; + ex:uuid "4db83088-7bd1-4861-b12c-210002db48bf". + + +} diff --git a/shacl/src/test/resources/test-cases/pattern/simple/invalid/case2/query2.rq b/shacl/src/test/resources/test-cases/pattern/simple/invalid/case2/query2.rq new file mode 100644 index 000000000..e1a440205 --- /dev/null +++ b/shacl/src/test/resources/test-cases/pattern/simple/invalid/case2/query2.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 ex:uuid "invalid". + + +} diff --git a/shacl/src/test/resources/test-cases/pattern/simple/invalid/case3/query1.rq b/shacl/src/test/resources/test-cases/pattern/simple/invalid/case3/query1.rq new file mode 100644 index 000000000..e1a440205 --- /dev/null +++ b/shacl/src/test/resources/test-cases/pattern/simple/invalid/case3/query1.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 ex:uuid "invalid". + + +} diff --git a/shacl/src/test/resources/test-cases/pattern/simple/invalid/case3/query2.rq b/shacl/src/test/resources/test-cases/pattern/simple/invalid/case3/query2.rq new file mode 100644 index 000000000..93fb72304 --- /dev/null +++ b/shacl/src/test/resources/test-cases/pattern/simple/invalid/case3/query2.rq @@ -0,0 +1,12 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person . + +} diff --git a/shacl/src/test/resources/test-cases/pattern/simple/invalid/case4/query1.rq b/shacl/src/test/resources/test-cases/pattern/simple/invalid/case4/query1.rq new file mode 100644 index 000000000..e1a440205 --- /dev/null +++ b/shacl/src/test/resources/test-cases/pattern/simple/invalid/case4/query1.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 ex:uuid "invalid". + + +} diff --git a/shacl/src/test/resources/test-cases/pattern/simple/invalid/case4/query2.rq b/shacl/src/test/resources/test-cases/pattern/simple/invalid/case4/query2.rq new file mode 100644 index 000000000..2d4c22456 --- /dev/null +++ b/shacl/src/test/resources/test-cases/pattern/simple/invalid/case4/query2.rq @@ -0,0 +1,14 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 + ex:uuid "4db83088-7bd1-4861-b12c-210002db48bf" ; + a ex:Person . + +} diff --git a/shacl/src/test/resources/test-cases/pattern/simple/invalid/case5/query1.rq b/shacl/src/test/resources/test-cases/pattern/simple/invalid/case5/query1.rq new file mode 100644 index 000000000..fa6df85b8 --- /dev/null +++ b/shacl/src/test/resources/test-cases/pattern/simple/invalid/case5/query1.rq @@ -0,0 +1,12 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 ex:uuid "invalid". + +} diff --git a/shacl/src/test/resources/test-cases/pattern/simple/invalid/case5/query2.rq b/shacl/src/test/resources/test-cases/pattern/simple/invalid/case5/query2.rq new file mode 100644 index 000000000..c8b5b12c3 --- /dev/null +++ b/shacl/src/test/resources/test-cases/pattern/simple/invalid/case5/query2.rq @@ -0,0 +1,18 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 + ex:uuid "4db83088-7bd1-4861-b12c-210002db48bf" ; + a ex:Person . + +ex:validPerson2 + ex:uuid "4db83088-7bd1-4861-b12c-210002db48bf" ; + a ex:Person . + +} diff --git a/shacl/src/test/resources/test-cases/pattern/simple/shacl.ttl b/shacl/src/test/resources/test-cases/pattern/simple/shacl.ttl new file mode 100644 index 000000000..168fbc3fa --- /dev/null +++ b/shacl/src/test/resources/test-cases/pattern/simple/shacl.ttl @@ -0,0 +1,23 @@ +@base . +@prefix ex: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix xsd: . + +ex:PersonShape + a sh:NodeShape ; + sh:targetClass ex:Person ; + sh:property [ + sh:path ex:uuid ; + sh:flags "i"; + sh:pattern "([0-9a-f]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12})" ; + ], + [ + sh:path ex:usedForTestingOptionalFlag ; + sh:pattern "([0-9a-f]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12})" ; + ] + + . + diff --git a/shacl/src/test/resources/test-cases/pattern/simple/valid/case1/query1.rq b/shacl/src/test/resources/test-cases/pattern/simple/valid/case1/query1.rq new file mode 100644 index 000000000..f73006e96 --- /dev/null +++ b/shacl/src/test/resources/test-cases/pattern/simple/valid/case1/query1.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person ; + ex:uuid "4db83088-7bd1-4861-b12c-210002db48bf". + +} diff --git a/shacl/src/test/resources/test-cases/pattern/simple/valid/case2/query1.rq b/shacl/src/test/resources/test-cases/pattern/simple/valid/case2/query1.rq new file mode 100644 index 000000000..f73006e96 --- /dev/null +++ b/shacl/src/test/resources/test-cases/pattern/simple/valid/case2/query1.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person ; + ex:uuid "4db83088-7bd1-4861-b12c-210002db48bf". + +} diff --git a/shacl/src/test/resources/test-cases/pattern/simple/valid/case2/query2.rq b/shacl/src/test/resources/test-cases/pattern/simple/valid/case2/query2.rq new file mode 100644 index 000000000..08b3dbeab --- /dev/null +++ b/shacl/src/test/resources/test-cases/pattern/simple/valid/case2/query2.rq @@ -0,0 +1,14 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 ex:uuid "3db83088-7bd1-4861-b12c-210002db48bf". + + +} + diff --git a/shacl/src/test/resources/test-cases/pattern/simple/valid/case3/query1.rq b/shacl/src/test/resources/test-cases/pattern/simple/valid/case3/query1.rq new file mode 100644 index 000000000..7b33aaa55 --- /dev/null +++ b/shacl/src/test/resources/test-cases/pattern/simple/valid/case3/query1.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 ex:uuid "4db83088-7bd1-4861-b12c-210002db48bf". +. + +} diff --git a/shacl/src/test/resources/test-cases/pattern/simple/valid/case3/query2.rq b/shacl/src/test/resources/test-cases/pattern/simple/valid/case3/query2.rq new file mode 100644 index 000000000..e63a150dc --- /dev/null +++ b/shacl/src/test/resources/test-cases/pattern/simple/valid/case3/query2.rq @@ -0,0 +1,15 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + + +ex:validPerson2 + ex:uuid "3db83088-7bd1-4861-b12c-210002db48bf" ; + a ex:Person . + +} diff --git a/shacl/src/test/resources/test-cases/pattern/simple/valid/case4/query1.rq b/shacl/src/test/resources/test-cases/pattern/simple/valid/case4/query1.rq new file mode 100644 index 000000000..336f457be --- /dev/null +++ b/shacl/src/test/resources/test-cases/pattern/simple/valid/case4/query1.rq @@ -0,0 +1,14 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person ; + ex:uuid "4db83088-7bd1-4861-b12c-210002db48bf"@en, "3db83088-7bd1-4861-b12c-210002db48bf"^^xsd:xmlLiteral. + +} + diff --git a/shacl/src/test/resources/test-cases/pattern/simple/valid/case5/query1.rq b/shacl/src/test/resources/test-cases/pattern/simple/valid/case5/query1.rq new file mode 100644 index 000000000..85e8caf5e --- /dev/null +++ b/shacl/src/test/resources/test-cases/pattern/simple/valid/case5/query1.rq @@ -0,0 +1,14 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person ; + ex:usedForTestingOptionalFlag "4db83088-7bd1-4861-b12c-210002db48bf" ; + ex:uuid "4Db83088-7bd1-4861-b12c-210002db48bf". + +} From c699a14bcf965cfbc38606d7e6c5d4c388420934 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Avard=20Ottestad?= Date: Thu, 17 Jan 2019 21:08:56 +0100 Subject: [PATCH 41/54] eclipse/rdf4j#1109 support for language in MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håvard Ottestad --- .../shacl/AST/LanguageInPropertyShape.java | 70 +++++++++++++++++++ .../rdf4j/sail/shacl/AST/OrPropertyShape.java | 18 ----- .../rdf4j/sail/shacl/AST/PropertyShape.java | 29 ++++++++ .../shacl/planNodes/LanguageInFilter.java | 49 +++++++++++++ .../eclipse/rdf4j/sail/shacl/ShaclTest.java | 1 + .../languageIn/simple/invalid/case1/query1.rq | 13 ++++ .../languageIn/simple/invalid/case2/query1.rq | 14 ++++ .../languageIn/simple/invalid/case2/query2.rq | 13 ++++ .../languageIn/simple/invalid/case3/query1.rq | 13 ++++ .../languageIn/simple/invalid/case3/query2.rq | 12 ++++ .../languageIn/simple/invalid/case4/query1.rq | 13 ++++ .../languageIn/simple/invalid/case4/query2.rq | 14 ++++ .../languageIn/simple/invalid/case5/query1.rq | 12 ++++ .../languageIn/simple/invalid/case5/query2.rq | 18 +++++ .../test-cases/languageIn/simple/shacl.ttl | 16 +++++ .../languageIn/simple/valid/case1/query1.rq | 13 ++++ .../languageIn/simple/valid/case2/query1.rq | 13 ++++ .../languageIn/simple/valid/case2/query2.rq | 14 ++++ .../languageIn/simple/valid/case3/query1.rq | 13 ++++ .../languageIn/simple/valid/case3/query2.rq | 15 ++++ .../pattern/simple/invalid/case6/query1.rq | 14 ++++ 21 files changed, 369 insertions(+), 18 deletions(-) create mode 100644 shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/LanguageInPropertyShape.java create mode 100644 shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/LanguageInFilter.java create mode 100644 shacl/src/test/resources/test-cases/languageIn/simple/invalid/case1/query1.rq create mode 100644 shacl/src/test/resources/test-cases/languageIn/simple/invalid/case2/query1.rq create mode 100644 shacl/src/test/resources/test-cases/languageIn/simple/invalid/case2/query2.rq create mode 100644 shacl/src/test/resources/test-cases/languageIn/simple/invalid/case3/query1.rq create mode 100644 shacl/src/test/resources/test-cases/languageIn/simple/invalid/case3/query2.rq create mode 100644 shacl/src/test/resources/test-cases/languageIn/simple/invalid/case4/query1.rq create mode 100644 shacl/src/test/resources/test-cases/languageIn/simple/invalid/case4/query2.rq create mode 100644 shacl/src/test/resources/test-cases/languageIn/simple/invalid/case5/query1.rq create mode 100644 shacl/src/test/resources/test-cases/languageIn/simple/invalid/case5/query2.rq create mode 100644 shacl/src/test/resources/test-cases/languageIn/simple/shacl.ttl create mode 100644 shacl/src/test/resources/test-cases/languageIn/simple/valid/case1/query1.rq create mode 100644 shacl/src/test/resources/test-cases/languageIn/simple/valid/case2/query1.rq create mode 100644 shacl/src/test/resources/test-cases/languageIn/simple/valid/case2/query2.rq create mode 100644 shacl/src/test/resources/test-cases/languageIn/simple/valid/case3/query1.rq create mode 100644 shacl/src/test/resources/test-cases/languageIn/simple/valid/case3/query2.rq create mode 100644 shacl/src/test/resources/test-cases/pattern/simple/invalid/case6/query1.rq diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/LanguageInPropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/LanguageInPropertyShape.java new file mode 100644 index 000000000..1fdb14871 --- /dev/null +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/LanguageInPropertyShape.java @@ -0,0 +1,70 @@ +/******************************************************************************* + * Copyright (c) 2018 Eclipse RDF4J contributors. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.sail.shacl.AST; + + +import org.eclipse.rdf4j.common.iteration.Iterations; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.vocabulary.SHACL; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; +import org.eclipse.rdf4j.sail.shacl.ShaclSailConnection; +import org.eclipse.rdf4j.sail.shacl.planNodes.LanguageInFilter; +import org.eclipse.rdf4j.sail.shacl.planNodes.PlanNode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * @author Håvard Ottestad + */ +public class LanguageInPropertyShape extends PathPropertyShape { + + private final List languageIn; + private static final Logger logger = LoggerFactory.getLogger(LanguageInPropertyShape.class); + + LanguageInPropertyShape(Resource id, SailRepositoryConnection connection, NodeShape nodeShape) { + super(id, connection, nodeShape); + + try (Stream stream = Iterations.stream(connection.getStatements(id, SHACL.LANGUAGE_IN, null, true))) { + Resource orList = stream.map(Statement::getObject).map(v -> (Resource) v).findAny().orElseThrow(() -> new RuntimeException("Expected to find sh:languageIn on " + id)); + languageIn = toList(connection, orList).stream().map(Value::stringValue).collect(Collectors.toList()); + } + + } + + + @Override + public PlanNode getPlan(ShaclSailConnection shaclSailConnection, NodeShape nodeShape, boolean printPlans, boolean assumeBaseSailValid) { + + PlanNode invalidValues = StandardisedPlanHelper.getGenericSingleObjectPlan( + shaclSailConnection, + nodeShape, + (parent, trueNode, falseNode) -> new LanguageInFilter(parent, trueNode, falseNode, languageIn), + this + ); + + if (printPlans) { + String planAsGraphvizDot = getPlanAsGraphvizDot(invalidValues, shaclSailConnection); + logger.info(planAsGraphvizDot); + } + + return invalidValues; + + } + + @Override + public boolean requiresEvaluation(Repository addedStatements, Repository removedStatements) { + return true; + } +} diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/OrPropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/OrPropertyShape.java index 0be285b89..71011a82b 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/OrPropertyShape.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/OrPropertyShape.java @@ -52,26 +52,8 @@ public class OrPropertyShape extends PropertyShape { } - private static List toList(SailRepositoryConnection connection, Resource orList) { - List ret = new ArrayList<>(); - while (!orList.equals(RDF.NIL)) { - try (Stream stream = Iterations.stream(connection.getStatements(orList, RDF.FIRST, null))) { - Value value = stream.map(Statement::getObject).findAny().get(); - ret.add(value); - } - - try (Stream stream = Iterations.stream(connection.getStatements(orList, RDF.REST, null))) { - orList = stream.map(Statement::getObject).map(v -> (Resource) v).findAny().get(); - } - - } - return ret; - - - } - @Override public PlanNode getPlan(ShaclSailConnection shaclSailConnection, NodeShape nodeShape, boolean printPlans, boolean assumeBaseSailValid) { diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PropertyShape.java index 156a79b95..9a643c5bb 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PropertyShape.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PropertyShape.java @@ -11,6 +11,8 @@ import org.eclipse.rdf4j.common.iteration.Iterations; import org.eclipse.rdf4j.model.Resource; import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.vocabulary.RDF; import org.eclipse.rdf4j.model.vocabulary.SHACL; import org.eclipse.rdf4j.repository.Repository; import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; @@ -83,6 +85,26 @@ public String getPlanAsGraphvizDot(PlanNode planNode, ShaclSailConnection shaclS } + static List toList(SailRepositoryConnection connection, Resource orList) { + List ret = new ArrayList<>(); + while (!orList.equals(RDF.NIL)) { + try (Stream stream = Iterations.stream(connection.getStatements(orList, RDF.FIRST, null))) { + Value value = stream.map(Statement::getObject).findAny().get(); + ret.add(value); + } + + try (Stream stream = Iterations.stream(connection.getStatements(orList, RDF.REST, null))) { + orList = stream.map(Statement::getObject).map(v -> (Resource) v).findAny().get(); + } + + } + + + return ret; + + + } + public Resource getId() { return id; } @@ -144,6 +166,10 @@ static List getPropertyShapesInner(SailRepositoryConnection conne if (hasPattern(propertyShapeId, connection)) { propertyShapes.add(new PatternPropertyShape(propertyShapeId, connection, nodeShape)); } + + if (hasLanguageIn(propertyShapeId, connection)) { + propertyShapes.add(new LanguageInPropertyShape(propertyShapeId, connection, nodeShape)); + } return propertyShapes; } @@ -175,6 +201,9 @@ private static boolean hasMaxLength(Resource id, SailRepositoryConnection connec private static boolean hasPattern(Resource id, SailRepositoryConnection connection) { return connection.hasStatement(id, SHACL.PATTERN, null, true); } + private static boolean hasLanguageIn(Resource id, SailRepositoryConnection connection) { + return connection.hasStatement(id, SHACL.LANGUAGE_IN, null, true); + } } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/LanguageInFilter.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/LanguageInFilter.java new file mode 100644 index 000000000..41d8e6ab2 --- /dev/null +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/LanguageInFilter.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2018 Eclipse RDF4J contributors. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ + +package org.eclipse.rdf4j.sail.shacl.planNodes; + + +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Resource; + +import java.util.Arrays; +import java.util.List; +import java.util.Optional; + +/** + * @author Håvard Ottestad + */ +public class LanguageInFilter extends FilterPlanNode { + + private final List languageIn; + + public LanguageInFilter(PlanNode parent, PushBasedPlanNode trueNode, PushBasedPlanNode falseNode, List languageIn) { + super(parent, trueNode, falseNode); + this.languageIn = languageIn; + } + + @Override + boolean checkTuple(Tuple t) { + if(! (t.line.get(1) instanceof Literal)) return false; + + Optional language = ((Literal) t.line.get(1)).getLanguage(); + if(!language.isPresent()) return false; + + return languageIn.contains(language.get()); + + } + + + @Override + public String toString() { + return "LanguageInFilter{" + + "languageIn=" + Arrays.toString(languageIn.toArray()) + + '}'; + } +} diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java index 232c71e0f..bf6c1c4b4 100644 --- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java @@ -44,6 +44,7 @@ public class ShaclTest { "test-cases/minLength/simple", "test-cases/maxLength/simple", "test-cases/pattern/simple", + "test-cases/languageIn/simple", "test-cases/minCount/simple", "test-cases/maxCount/simple", "test-cases/or/inheritance", diff --git a/shacl/src/test/resources/test-cases/languageIn/simple/invalid/case1/query1.rq b/shacl/src/test/resources/test-cases/languageIn/simple/invalid/case1/query1.rq new file mode 100644 index 000000000..9618efb03 --- /dev/null +++ b/shacl/src/test/resources/test-cases/languageIn/simple/invalid/case1/query1.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person ; + ex:label "människa"@se. + +} diff --git a/shacl/src/test/resources/test-cases/languageIn/simple/invalid/case2/query1.rq b/shacl/src/test/resources/test-cases/languageIn/simple/invalid/case2/query1.rq new file mode 100644 index 000000000..5da6c03f7 --- /dev/null +++ b/shacl/src/test/resources/test-cases/languageIn/simple/invalid/case2/query1.rq @@ -0,0 +1,14 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person ; + ex:label "human"@en. + + +} diff --git a/shacl/src/test/resources/test-cases/languageIn/simple/invalid/case2/query2.rq b/shacl/src/test/resources/test-cases/languageIn/simple/invalid/case2/query2.rq new file mode 100644 index 000000000..e17a1efc9 --- /dev/null +++ b/shacl/src/test/resources/test-cases/languageIn/simple/invalid/case2/query2.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 ex:label "människa"@se. + + +} diff --git a/shacl/src/test/resources/test-cases/languageIn/simple/invalid/case3/query1.rq b/shacl/src/test/resources/test-cases/languageIn/simple/invalid/case3/query1.rq new file mode 100644 index 000000000..e17a1efc9 --- /dev/null +++ b/shacl/src/test/resources/test-cases/languageIn/simple/invalid/case3/query1.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 ex:label "människa"@se. + + +} diff --git a/shacl/src/test/resources/test-cases/languageIn/simple/invalid/case3/query2.rq b/shacl/src/test/resources/test-cases/languageIn/simple/invalid/case3/query2.rq new file mode 100644 index 000000000..93fb72304 --- /dev/null +++ b/shacl/src/test/resources/test-cases/languageIn/simple/invalid/case3/query2.rq @@ -0,0 +1,12 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person . + +} diff --git a/shacl/src/test/resources/test-cases/languageIn/simple/invalid/case4/query1.rq b/shacl/src/test/resources/test-cases/languageIn/simple/invalid/case4/query1.rq new file mode 100644 index 000000000..e17a1efc9 --- /dev/null +++ b/shacl/src/test/resources/test-cases/languageIn/simple/invalid/case4/query1.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 ex:label "människa"@se. + + +} diff --git a/shacl/src/test/resources/test-cases/languageIn/simple/invalid/case4/query2.rq b/shacl/src/test/resources/test-cases/languageIn/simple/invalid/case4/query2.rq new file mode 100644 index 000000000..5dbd7fecf --- /dev/null +++ b/shacl/src/test/resources/test-cases/languageIn/simple/invalid/case4/query2.rq @@ -0,0 +1,14 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 + ex:label "human"@en ; + a ex:Person . + +} diff --git a/shacl/src/test/resources/test-cases/languageIn/simple/invalid/case5/query1.rq b/shacl/src/test/resources/test-cases/languageIn/simple/invalid/case5/query1.rq new file mode 100644 index 000000000..c6956fd06 --- /dev/null +++ b/shacl/src/test/resources/test-cases/languageIn/simple/invalid/case5/query1.rq @@ -0,0 +1,12 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 ex:label "människa"@se. + +} diff --git a/shacl/src/test/resources/test-cases/languageIn/simple/invalid/case5/query2.rq b/shacl/src/test/resources/test-cases/languageIn/simple/invalid/case5/query2.rq new file mode 100644 index 000000000..9de958708 --- /dev/null +++ b/shacl/src/test/resources/test-cases/languageIn/simple/invalid/case5/query2.rq @@ -0,0 +1,18 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 + ex:label "human"@en ; + a ex:Person . + +ex:validPerson2 + ex:label "human"@en ; + a ex:Person . + +} diff --git a/shacl/src/test/resources/test-cases/languageIn/simple/shacl.ttl b/shacl/src/test/resources/test-cases/languageIn/simple/shacl.ttl new file mode 100644 index 000000000..0e641f022 --- /dev/null +++ b/shacl/src/test/resources/test-cases/languageIn/simple/shacl.ttl @@ -0,0 +1,16 @@ +@base . +@prefix ex: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix xsd: . + +ex:PersonShape + a sh:NodeShape ; + sh:targetClass ex:Person ; + sh:property [ + sh:path ex:label ; + sh:languageIn ( "en" "no" ) ; + ] . + diff --git a/shacl/src/test/resources/test-cases/languageIn/simple/valid/case1/query1.rq b/shacl/src/test/resources/test-cases/languageIn/simple/valid/case1/query1.rq new file mode 100644 index 000000000..f96b5ba20 --- /dev/null +++ b/shacl/src/test/resources/test-cases/languageIn/simple/valid/case1/query1.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person ; + ex:label "human"@en, "menneske"@no. + +} diff --git a/shacl/src/test/resources/test-cases/languageIn/simple/valid/case2/query1.rq b/shacl/src/test/resources/test-cases/languageIn/simple/valid/case2/query1.rq new file mode 100644 index 000000000..4f6df8516 --- /dev/null +++ b/shacl/src/test/resources/test-cases/languageIn/simple/valid/case2/query1.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person ; + ex:label "human"@en. + +} diff --git a/shacl/src/test/resources/test-cases/languageIn/simple/valid/case2/query2.rq b/shacl/src/test/resources/test-cases/languageIn/simple/valid/case2/query2.rq new file mode 100644 index 000000000..00596fbf2 --- /dev/null +++ b/shacl/src/test/resources/test-cases/languageIn/simple/valid/case2/query2.rq @@ -0,0 +1,14 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 ex:label "menneske"@no. + + +} + diff --git a/shacl/src/test/resources/test-cases/languageIn/simple/valid/case3/query1.rq b/shacl/src/test/resources/test-cases/languageIn/simple/valid/case3/query1.rq new file mode 100644 index 000000000..d1ab87a2d --- /dev/null +++ b/shacl/src/test/resources/test-cases/languageIn/simple/valid/case3/query1.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 ex:label "human"@en. +. + +} diff --git a/shacl/src/test/resources/test-cases/languageIn/simple/valid/case3/query2.rq b/shacl/src/test/resources/test-cases/languageIn/simple/valid/case3/query2.rq new file mode 100644 index 000000000..704ada177 --- /dev/null +++ b/shacl/src/test/resources/test-cases/languageIn/simple/valid/case3/query2.rq @@ -0,0 +1,15 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + + +ex:validPerson2 + ex:label "menneske"@no ; + a ex:Person . + +} diff --git a/shacl/src/test/resources/test-cases/pattern/simple/invalid/case6/query1.rq b/shacl/src/test/resources/test-cases/pattern/simple/invalid/case6/query1.rq new file mode 100644 index 000000000..122003009 --- /dev/null +++ b/shacl/src/test/resources/test-cases/pattern/simple/invalid/case6/query1.rq @@ -0,0 +1,14 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person ; + ex:uuid 1. + + +} From 3b2d80fdb5e306f1ea80a31186876d2b2e8b7405 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Avard=20Ottestad?= Date: Thu, 17 Jan 2019 21:39:49 +0100 Subject: [PATCH 42/54] eclipse/rdf4j#1110 support nodeKind MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håvard Ottestad --- .../sail/shacl/AST/NodeKindPropertyShape.java | 94 +++++++++++++++++++ .../rdf4j/sail/shacl/AST/PropertyShape.java | 9 ++ .../shacl/planNodes/LanguageInFilter.java | 4 +- .../sail/shacl/planNodes/MaxLengthFilter.java | 5 +- .../sail/shacl/planNodes/MinLengthFilter.java | 5 +- .../sail/shacl/planNodes/NodeKindFilter.java | 73 ++++++++++++++ .../sail/shacl/planNodes/PatternFilter.java | 7 +- .../eclipse/rdf4j/sail/shacl/ShaclTest.java | 4 +- .../nodeKind/simple/invalid/case1/query1.rq | 14 +++ .../nodeKind/simple/invalid/case2/query1.rq | 14 +++ .../nodeKind/simple/invalid/case2/query2.rq | 13 +++ .../nodeKind/simple/invalid/case3/query1.rq | 13 +++ .../nodeKind/simple/invalid/case3/query2.rq | 12 +++ .../nodeKind/simple/invalid/case4/query1.rq | 13 +++ .../nodeKind/simple/invalid/case4/query2.rq | 14 +++ .../nodeKind/simple/invalid/case5/query1.rq | 12 +++ .../nodeKind/simple/invalid/case5/query2.rq | 18 ++++ .../test-cases/nodeKind/simple/shacl.ttl | 16 ++++ .../nodeKind/simple/valid/case1/query1.rq | 13 +++ .../nodeKind/simple/valid/case2/query1.rq | 13 +++ .../nodeKind/simple/valid/case2/query2.rq | 14 +++ .../nodeKind/simple/valid/case3/query1.rq | 13 +++ .../nodeKind/simple/valid/case3/query2.rq | 15 +++ .../nodeKind/simple/valid/case4/query1.rq | 13 +++ .../nodeKind/simple/valid/case5/query1.rq | 13 +++ .../nodeKindMinLength/invalid/case1/query1.rq | 13 +++ .../nodeKindMinLength/invalid/case2/query1.rq | 13 +++ .../nodeKindMinLength/invalid/case3/query1.rq | 13 +++ .../nodeKindMinLength/invalid/case3/query2.rq | 21 +++++ .../nodeKindMinLength/invalid/case4/query1.rq | 13 +++ .../nodeKindMinLength/invalid/case4/query2.rq | 21 +++++ .../test-cases/or/nodeKindMinLength/shacl.ttl | 24 +++++ .../nodeKindMinLength/valid/case1/query1.rq | 13 +++ .../nodeKindMinLength/valid/case2/query1.rq | 13 +++ .../nodeKindMinLength/valid/case2/query2.rq | 21 +++++ 35 files changed, 584 insertions(+), 15 deletions(-) create mode 100644 shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/NodeKindPropertyShape.java create mode 100644 shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/NodeKindFilter.java create mode 100644 shacl/src/test/resources/test-cases/nodeKind/simple/invalid/case1/query1.rq create mode 100644 shacl/src/test/resources/test-cases/nodeKind/simple/invalid/case2/query1.rq create mode 100644 shacl/src/test/resources/test-cases/nodeKind/simple/invalid/case2/query2.rq create mode 100644 shacl/src/test/resources/test-cases/nodeKind/simple/invalid/case3/query1.rq create mode 100644 shacl/src/test/resources/test-cases/nodeKind/simple/invalid/case3/query2.rq create mode 100644 shacl/src/test/resources/test-cases/nodeKind/simple/invalid/case4/query1.rq create mode 100644 shacl/src/test/resources/test-cases/nodeKind/simple/invalid/case4/query2.rq create mode 100644 shacl/src/test/resources/test-cases/nodeKind/simple/invalid/case5/query1.rq create mode 100644 shacl/src/test/resources/test-cases/nodeKind/simple/invalid/case5/query2.rq create mode 100644 shacl/src/test/resources/test-cases/nodeKind/simple/shacl.ttl create mode 100644 shacl/src/test/resources/test-cases/nodeKind/simple/valid/case1/query1.rq create mode 100644 shacl/src/test/resources/test-cases/nodeKind/simple/valid/case2/query1.rq create mode 100644 shacl/src/test/resources/test-cases/nodeKind/simple/valid/case2/query2.rq create mode 100644 shacl/src/test/resources/test-cases/nodeKind/simple/valid/case3/query1.rq create mode 100644 shacl/src/test/resources/test-cases/nodeKind/simple/valid/case3/query2.rq create mode 100644 shacl/src/test/resources/test-cases/nodeKind/simple/valid/case4/query1.rq create mode 100644 shacl/src/test/resources/test-cases/nodeKind/simple/valid/case5/query1.rq create mode 100644 shacl/src/test/resources/test-cases/or/nodeKindMinLength/invalid/case1/query1.rq create mode 100644 shacl/src/test/resources/test-cases/or/nodeKindMinLength/invalid/case2/query1.rq create mode 100644 shacl/src/test/resources/test-cases/or/nodeKindMinLength/invalid/case3/query1.rq create mode 100644 shacl/src/test/resources/test-cases/or/nodeKindMinLength/invalid/case3/query2.rq create mode 100644 shacl/src/test/resources/test-cases/or/nodeKindMinLength/invalid/case4/query1.rq create mode 100644 shacl/src/test/resources/test-cases/or/nodeKindMinLength/invalid/case4/query2.rq create mode 100644 shacl/src/test/resources/test-cases/or/nodeKindMinLength/shacl.ttl create mode 100644 shacl/src/test/resources/test-cases/or/nodeKindMinLength/valid/case1/query1.rq create mode 100644 shacl/src/test/resources/test-cases/or/nodeKindMinLength/valid/case2/query1.rq create mode 100644 shacl/src/test/resources/test-cases/or/nodeKindMinLength/valid/case2/query2.rq diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/NodeKindPropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/NodeKindPropertyShape.java new file mode 100644 index 000000000..8b7c90fbb --- /dev/null +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/NodeKindPropertyShape.java @@ -0,0 +1,94 @@ +/******************************************************************************* + * Copyright (c) 2018 Eclipse RDF4J contributors. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.sail.shacl.AST; + + +import org.eclipse.rdf4j.common.iteration.Iterations; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.impl.SimpleLiteral; +import org.eclipse.rdf4j.model.vocabulary.SHACL; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; +import org.eclipse.rdf4j.sail.shacl.ShaclSailConnection; +import org.eclipse.rdf4j.sail.shacl.planNodes.MinLengthFilter; +import org.eclipse.rdf4j.sail.shacl.planNodes.NodeKindFilter; +import org.eclipse.rdf4j.sail.shacl.planNodes.PlanNode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.stream.Stream; + +/** + * @author Håvard Ottestad + */ +public class NodeKindPropertyShape extends PathPropertyShape { + + private final NodeKind nodeKind; + private static final Logger logger = LoggerFactory.getLogger(NodeKindPropertyShape.class); + + NodeKindPropertyShape(Resource id, SailRepositoryConnection connection, NodeShape nodeShape) { + super(id, connection, nodeShape); + + try (Stream stream = Iterations.stream(connection.getStatements(id, SHACL.NODE_KIND_PROP, null, true))) { + nodeKind = stream.map(Statement::getObject).map(v -> (Resource) v).map(NodeKind::from).findAny().orElseThrow(() -> new RuntimeException("Expected to find sh:nodeKind on " + id)); + } + + } + + public enum NodeKind{ + + BlankNode(SHACL.BLANK_NODE), + IRI(SHACL.IRI), + Literal(SHACL.LITERAL), + BlankNodeOrIRI(SHACL.BLANK_NODE_OR_IRI), + BlankNodeOrLiteral(SHACL.BLANK_NODE_OR_LITERAL), + IRIOrLiteral(SHACL.IRI_OR_LITERAL), + ; + + IRI iri; + NodeKind(IRI iri) { + this.iri = iri; + } + + public static NodeKind from(Resource resource){ + for (NodeKind value : NodeKind.values()) { + if(value.iri.equals(resource)) return value; + } + + throw new IllegalStateException("Unknown nodeKind: "+resource); + } + } + + + + @Override + public PlanNode getPlan(ShaclSailConnection shaclSailConnection, NodeShape nodeShape, boolean printPlans, boolean assumeBaseSailValid) { + + PlanNode invalidValues = StandardisedPlanHelper.getGenericSingleObjectPlan( + shaclSailConnection, + nodeShape, + (parent, trueNode, falseNode) -> new NodeKindFilter(parent, trueNode, falseNode, nodeKind), + this + ); + + if (printPlans) { + String planAsGraphvizDot = getPlanAsGraphvizDot(invalidValues, shaclSailConnection); + logger.info(planAsGraphvizDot); + } + + return invalidValues; + + } + + @Override + public boolean requiresEvaluation(Repository addedStatements, Repository removedStatements) { + return true; + } +} diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PropertyShape.java index 9a643c5bb..172db6315 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PropertyShape.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PropertyShape.java @@ -170,6 +170,10 @@ static List getPropertyShapesInner(SailRepositoryConnection conne if (hasLanguageIn(propertyShapeId, connection)) { propertyShapes.add(new LanguageInPropertyShape(propertyShapeId, connection, nodeShape)); } + + if (hasNodeKind(propertyShapeId, connection)) { + propertyShapes.add(new NodeKindPropertyShape(propertyShapeId, connection, nodeShape)); + } return propertyShapes; } @@ -201,10 +205,15 @@ private static boolean hasMaxLength(Resource id, SailRepositoryConnection connec private static boolean hasPattern(Resource id, SailRepositoryConnection connection) { return connection.hasStatement(id, SHACL.PATTERN, null, true); } + private static boolean hasLanguageIn(Resource id, SailRepositoryConnection connection) { return connection.hasStatement(id, SHACL.LANGUAGE_IN, null, true); } + private static boolean hasNodeKind(Resource id, SailRepositoryConnection connection) { + return connection.hasStatement(id, SHACL.NODE_KIND_PROP, null, true); + } + } } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/LanguageInFilter.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/LanguageInFilter.java index 41d8e6ab2..7026d8352 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/LanguageInFilter.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/LanguageInFilter.java @@ -33,9 +33,7 @@ boolean checkTuple(Tuple t) { if(! (t.line.get(1) instanceof Literal)) return false; Optional language = ((Literal) t.line.get(1)).getLanguage(); - if(!language.isPresent()) return false; - - return languageIn.contains(language.get()); + return language.filter(languageIn::contains).isPresent(); } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MaxLengthFilter.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MaxLengthFilter.java index 6a52e4fca..1fe63630c 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MaxLengthFilter.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MaxLengthFilter.java @@ -10,6 +10,7 @@ import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; /** * @author Håvard Ottestad @@ -25,9 +26,7 @@ public MaxLengthFilter(PlanNode parent, PushBasedPlanNode trueNode, PushBasedPla @Override boolean checkTuple(Tuple t) { - if(! (t.line.get(1) instanceof Literal)) return false; - - Literal literal = (Literal) t.line.get(1); + Value literal = t.line.get(1); return literal.stringValue().length() <= maxLength; } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MinLengthFilter.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MinLengthFilter.java index ed5ed8ae2..4f660a5c6 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MinLengthFilter.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MinLengthFilter.java @@ -11,6 +11,7 @@ import org.eclipse.rdf4j.model.Literal; import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Value; /** * @author Håvard Ottestad @@ -26,9 +27,7 @@ public MinLengthFilter(PlanNode parent, PushBasedPlanNode trueNode, PushBasedPla @Override boolean checkTuple(Tuple t) { - if(! (t.line.get(1) instanceof Literal)) return false; - - Literal literal = (Literal) t.line.get(1); + Value literal = t.line.get(1); return literal.stringValue().length() >= minLength; } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/NodeKindFilter.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/NodeKindFilter.java new file mode 100644 index 000000000..6672b4ba8 --- /dev/null +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/NodeKindFilter.java @@ -0,0 +1,73 @@ +/******************************************************************************* + * Copyright (c) 2018 Eclipse RDF4J contributors. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ + +package org.eclipse.rdf4j.sail.shacl.planNodes; + + +import org.eclipse.rdf4j.model.BNode; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.vocabulary.SHACL; +import org.eclipse.rdf4j.sail.shacl.AST.NodeKindPropertyShape; + +/** + * @author Håvard Ottestad + */ +public class NodeKindFilter extends FilterPlanNode { + + private final NodeKindPropertyShape.NodeKind nodeKind; + + public NodeKindFilter(PlanNode parent, PushBasedPlanNode trueNode, PushBasedPlanNode falseNode, NodeKindPropertyShape.NodeKind nodeKind) { + super(parent, trueNode, falseNode); + this.nodeKind = nodeKind; + } + + @Override + boolean checkTuple(Tuple t) { + + Value value = t.line.get(1); +/* + BlankNode(SHACL.BLANK_NODE), + IRI(SHACL.IRI), + Literal(SHACL.LITERAL), + BlankNodeOrIRI(SHACL.BLANK_NODE_OR_IRI), + BlankNodeOrLiteral(SHACL.BLANK_NODE_OR_LITERAL), + IRIOrLiteral(SHACL.IRI_OR_LITERAL), +*/ + + + + switch (nodeKind) { + case IRI: + return value instanceof IRI; + case Literal: + return value instanceof Literal; + case BlankNode: + return value instanceof BNode; + case IRIOrLiteral: + return value instanceof IRI || value instanceof Literal; + case BlankNodeOrIRI: + return value instanceof BNode || value instanceof IRI; + case BlankNodeOrLiteral: + return value instanceof BNode || value instanceof Literal; + } + + throw new IllegalStateException("Unknown nodeKind"); + + } + + + @Override + public String toString() { + return "NodeKindFilter{" + + "nodeKind=" + nodeKind + + '}'; + } +} diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/PatternFilter.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/PatternFilter.java index 9bb1d59d1..fc021e326 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/PatternFilter.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/PatternFilter.java @@ -10,6 +10,7 @@ import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Value; import java.util.Optional; import java.util.regex.Pattern; @@ -69,11 +70,7 @@ public PatternFilter(PlanNode parent, PushBasedPlanNode trueNode, PushBasedPlanN @Override boolean checkTuple(Tuple t) { - if (!(t.line.get(1) instanceof Literal)) { - return false; - } - - Literal literal = (Literal) t.line.get(1); + Value literal = t.line.get(1); return pattern.matcher(literal.stringValue()).matches(); } diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java index bf6c1c4b4..e67572b84 100644 --- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java @@ -45,6 +45,7 @@ public class ShaclTest { "test-cases/maxLength/simple", "test-cases/pattern/simple", "test-cases/languageIn/simple", + "test-cases/nodeKind/simple", "test-cases/minCount/simple", "test-cases/maxCount/simple", "test-cases/or/inheritance", @@ -54,7 +55,8 @@ public class ShaclTest { "test-cases/or/datatype", "test-cases/or/minCountMaxCount", "test-cases/or/maxCount", - "test-cases/or/minCount" + "test-cases/or/minCount", + "test-cases/or/nodeKindMinLength" ); diff --git a/shacl/src/test/resources/test-cases/nodeKind/simple/invalid/case1/query1.rq b/shacl/src/test/resources/test-cases/nodeKind/simple/invalid/case1/query1.rq new file mode 100644 index 000000000..ebd071d80 --- /dev/null +++ b/shacl/src/test/resources/test-cases/nodeKind/simple/invalid/case1/query1.rq @@ -0,0 +1,14 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person ; + ex:knows "1234567". + + +} diff --git a/shacl/src/test/resources/test-cases/nodeKind/simple/invalid/case2/query1.rq b/shacl/src/test/resources/test-cases/nodeKind/simple/invalid/case2/query1.rq new file mode 100644 index 000000000..ac61ae35d --- /dev/null +++ b/shacl/src/test/resources/test-cases/nodeKind/simple/invalid/case2/query1.rq @@ -0,0 +1,14 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person ; + ex:knows []. + + +} diff --git a/shacl/src/test/resources/test-cases/nodeKind/simple/invalid/case2/query2.rq b/shacl/src/test/resources/test-cases/nodeKind/simple/invalid/case2/query2.rq new file mode 100644 index 000000000..5ea65f270 --- /dev/null +++ b/shacl/src/test/resources/test-cases/nodeKind/simple/invalid/case2/query2.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 ex:knows "1234567". + + +} diff --git a/shacl/src/test/resources/test-cases/nodeKind/simple/invalid/case3/query1.rq b/shacl/src/test/resources/test-cases/nodeKind/simple/invalid/case3/query1.rq new file mode 100644 index 000000000..5ea65f270 --- /dev/null +++ b/shacl/src/test/resources/test-cases/nodeKind/simple/invalid/case3/query1.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 ex:knows "1234567". + + +} diff --git a/shacl/src/test/resources/test-cases/nodeKind/simple/invalid/case3/query2.rq b/shacl/src/test/resources/test-cases/nodeKind/simple/invalid/case3/query2.rq new file mode 100644 index 000000000..93fb72304 --- /dev/null +++ b/shacl/src/test/resources/test-cases/nodeKind/simple/invalid/case3/query2.rq @@ -0,0 +1,12 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person . + +} diff --git a/shacl/src/test/resources/test-cases/nodeKind/simple/invalid/case4/query1.rq b/shacl/src/test/resources/test-cases/nodeKind/simple/invalid/case4/query1.rq new file mode 100644 index 000000000..5ea65f270 --- /dev/null +++ b/shacl/src/test/resources/test-cases/nodeKind/simple/invalid/case4/query1.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 ex:knows "1234567". + + +} diff --git a/shacl/src/test/resources/test-cases/nodeKind/simple/invalid/case4/query2.rq b/shacl/src/test/resources/test-cases/nodeKind/simple/invalid/case4/query2.rq new file mode 100644 index 000000000..6bf4fa2cb --- /dev/null +++ b/shacl/src/test/resources/test-cases/nodeKind/simple/invalid/case4/query2.rq @@ -0,0 +1,14 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 + ex:knows ex:pete ; + a ex:Person . + +} diff --git a/shacl/src/test/resources/test-cases/nodeKind/simple/invalid/case5/query1.rq b/shacl/src/test/resources/test-cases/nodeKind/simple/invalid/case5/query1.rq new file mode 100644 index 000000000..2976785b4 --- /dev/null +++ b/shacl/src/test/resources/test-cases/nodeKind/simple/invalid/case5/query1.rq @@ -0,0 +1,12 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 ex:knows "1234567". + +} diff --git a/shacl/src/test/resources/test-cases/nodeKind/simple/invalid/case5/query2.rq b/shacl/src/test/resources/test-cases/nodeKind/simple/invalid/case5/query2.rq new file mode 100644 index 000000000..44a8b9a22 --- /dev/null +++ b/shacl/src/test/resources/test-cases/nodeKind/simple/invalid/case5/query2.rq @@ -0,0 +1,18 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 + ex:knows [], ex:pete ; + a ex:Person . + +ex:validPerson2 + ex:knows [] ; + a ex:Person . + +} diff --git a/shacl/src/test/resources/test-cases/nodeKind/simple/shacl.ttl b/shacl/src/test/resources/test-cases/nodeKind/simple/shacl.ttl new file mode 100644 index 000000000..1b72d30e9 --- /dev/null +++ b/shacl/src/test/resources/test-cases/nodeKind/simple/shacl.ttl @@ -0,0 +1,16 @@ +@base . +@prefix ex: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix xsd: . + +ex:PersonShape + a sh:NodeShape ; + sh:targetClass ex:Person ; + sh:property [ + sh:path ex:knows ; + sh:nodeKind sh:BlankNodeOrIRI ; + ] . + diff --git a/shacl/src/test/resources/test-cases/nodeKind/simple/valid/case1/query1.rq b/shacl/src/test/resources/test-cases/nodeKind/simple/valid/case1/query1.rq new file mode 100644 index 000000000..7b2e68408 --- /dev/null +++ b/shacl/src/test/resources/test-cases/nodeKind/simple/valid/case1/query1.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person ; + ex:knows [], ex:peter. + +} diff --git a/shacl/src/test/resources/test-cases/nodeKind/simple/valid/case2/query1.rq b/shacl/src/test/resources/test-cases/nodeKind/simple/valid/case2/query1.rq new file mode 100644 index 000000000..1756cb0a8 --- /dev/null +++ b/shacl/src/test/resources/test-cases/nodeKind/simple/valid/case2/query1.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person ; + ex:knows []. + +} diff --git a/shacl/src/test/resources/test-cases/nodeKind/simple/valid/case2/query2.rq b/shacl/src/test/resources/test-cases/nodeKind/simple/valid/case2/query2.rq new file mode 100644 index 000000000..e9d98cbb3 --- /dev/null +++ b/shacl/src/test/resources/test-cases/nodeKind/simple/valid/case2/query2.rq @@ -0,0 +1,14 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 ex:knows ex:pete. + + +} + diff --git a/shacl/src/test/resources/test-cases/nodeKind/simple/valid/case3/query1.rq b/shacl/src/test/resources/test-cases/nodeKind/simple/valid/case3/query1.rq new file mode 100644 index 000000000..0af6f7052 --- /dev/null +++ b/shacl/src/test/resources/test-cases/nodeKind/simple/valid/case3/query1.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 ex:knows []. +. + +} diff --git a/shacl/src/test/resources/test-cases/nodeKind/simple/valid/case3/query2.rq b/shacl/src/test/resources/test-cases/nodeKind/simple/valid/case3/query2.rq new file mode 100644 index 000000000..9c42e9a20 --- /dev/null +++ b/shacl/src/test/resources/test-cases/nodeKind/simple/valid/case3/query2.rq @@ -0,0 +1,15 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + + +ex:validPerson2 + ex:knows ex:pete ; + a ex:Person . + +} diff --git a/shacl/src/test/resources/test-cases/nodeKind/simple/valid/case4/query1.rq b/shacl/src/test/resources/test-cases/nodeKind/simple/valid/case4/query1.rq new file mode 100644 index 000000000..1e1db0745 --- /dev/null +++ b/shacl/src/test/resources/test-cases/nodeKind/simple/valid/case4/query1.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person ; + ex:knows ex:peter. + +} diff --git a/shacl/src/test/resources/test-cases/nodeKind/simple/valid/case5/query1.rq b/shacl/src/test/resources/test-cases/nodeKind/simple/valid/case5/query1.rq new file mode 100644 index 000000000..1756cb0a8 --- /dev/null +++ b/shacl/src/test/resources/test-cases/nodeKind/simple/valid/case5/query1.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person ; + ex:knows []. + +} diff --git a/shacl/src/test/resources/test-cases/or/nodeKindMinLength/invalid/case1/query1.rq b/shacl/src/test/resources/test-cases/or/nodeKindMinLength/invalid/case1/query1.rq new file mode 100644 index 000000000..6d5b58389 --- /dev/null +++ b/shacl/src/test/resources/test-cases/or/nodeKindMinLength/invalid/case1/query1.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person ; + ex:iriOrMinLength5String "abc". + +} diff --git a/shacl/src/test/resources/test-cases/or/nodeKindMinLength/invalid/case2/query1.rq b/shacl/src/test/resources/test-cases/or/nodeKindMinLength/invalid/case2/query1.rq new file mode 100644 index 000000000..1938b081b --- /dev/null +++ b/shacl/src/test/resources/test-cases/or/nodeKindMinLength/invalid/case2/query1.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person ; + ex:iriOrMinLength5String []. + +} diff --git a/shacl/src/test/resources/test-cases/or/nodeKindMinLength/invalid/case3/query1.rq b/shacl/src/test/resources/test-cases/or/nodeKindMinLength/invalid/case3/query1.rq new file mode 100644 index 000000000..c23d0b273 --- /dev/null +++ b/shacl/src/test/resources/test-cases/or/nodeKindMinLength/invalid/case3/query1.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person ; + ex:iriOrMinLength5String "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis id elementum turpis. Suspendisse metus.". + +} diff --git a/shacl/src/test/resources/test-cases/or/nodeKindMinLength/invalid/case3/query2.rq b/shacl/src/test/resources/test-cases/or/nodeKindMinLength/invalid/case3/query2.rq new file mode 100644 index 000000000..31c001dfb --- /dev/null +++ b/shacl/src/test/resources/test-cases/or/nodeKindMinLength/invalid/case3/query2.rq @@ -0,0 +1,21 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +DELETE{ + +ex:validPerson1 ex:iriOrMinLength5String "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis id elementum turpis. Suspendisse metus.". + + +} + +INSERT { +ex:validPerson1 ex:iriOrMinLength5String "Lorem ipsum". + +} +WHERE{?a ?b ?c.} + + diff --git a/shacl/src/test/resources/test-cases/or/nodeKindMinLength/invalid/case4/query1.rq b/shacl/src/test/resources/test-cases/or/nodeKindMinLength/invalid/case4/query1.rq new file mode 100644 index 000000000..c23d0b273 --- /dev/null +++ b/shacl/src/test/resources/test-cases/or/nodeKindMinLength/invalid/case4/query1.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person ; + ex:iriOrMinLength5String "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis id elementum turpis. Suspendisse metus.". + +} diff --git a/shacl/src/test/resources/test-cases/or/nodeKindMinLength/invalid/case4/query2.rq b/shacl/src/test/resources/test-cases/or/nodeKindMinLength/invalid/case4/query2.rq new file mode 100644 index 000000000..3854ff265 --- /dev/null +++ b/shacl/src/test/resources/test-cases/or/nodeKindMinLength/invalid/case4/query2.rq @@ -0,0 +1,21 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +DELETE{ + +ex:validPerson1 ex:iriOrMinLength5String "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis id elementum turpis. Suspendisse metus.". + + +} + +INSERT { +ex:validPerson1 ex:iriOrMinLength5String []. + +} +WHERE{?a ?b ?c.} + + diff --git a/shacl/src/test/resources/test-cases/or/nodeKindMinLength/shacl.ttl b/shacl/src/test/resources/test-cases/or/nodeKindMinLength/shacl.ttl new file mode 100644 index 000000000..3a6347d0f --- /dev/null +++ b/shacl/src/test/resources/test-cases/or/nodeKindMinLength/shacl.ttl @@ -0,0 +1,24 @@ +@base . +@prefix ex: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix xsd: . + +ex:PersonShape + a sh:NodeShape ; + sh:targetClass ex:Person ; + sh:property [ + sh:or ( + [ + sh:path ex:iriOrMinLength5String ; + sh:nodeKind sh:IRI ; + ] + [ + sh:path ex:iriOrMinLength5String ; + sh:minLength 100 ; + ] + ) ; + ] . + diff --git a/shacl/src/test/resources/test-cases/or/nodeKindMinLength/valid/case1/query1.rq b/shacl/src/test/resources/test-cases/or/nodeKindMinLength/valid/case1/query1.rq new file mode 100644 index 000000000..6654cc371 --- /dev/null +++ b/shacl/src/test/resources/test-cases/or/nodeKindMinLength/valid/case1/query1.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person ; + ex:iriOrMinLength5String "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis id elementum turpis. Suspendisse metus.", ex:pete. + +} diff --git a/shacl/src/test/resources/test-cases/or/nodeKindMinLength/valid/case2/query1.rq b/shacl/src/test/resources/test-cases/or/nodeKindMinLength/valid/case2/query1.rq new file mode 100644 index 000000000..c23d0b273 --- /dev/null +++ b/shacl/src/test/resources/test-cases/or/nodeKindMinLength/valid/case2/query1.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person ; + ex:iriOrMinLength5String "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis id elementum turpis. Suspendisse metus.". + +} diff --git a/shacl/src/test/resources/test-cases/or/nodeKindMinLength/valid/case2/query2.rq b/shacl/src/test/resources/test-cases/or/nodeKindMinLength/valid/case2/query2.rq new file mode 100644 index 000000000..ef00f32b8 --- /dev/null +++ b/shacl/src/test/resources/test-cases/or/nodeKindMinLength/valid/case2/query2.rq @@ -0,0 +1,21 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +DELETE{ + +ex:validPerson1 ex:iriOrMinLength5String "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis id elementum turpis. Suspendisse metus.". + + +} + +INSERT { +ex:validPerson1 ex:iriOrMinLength5String ex:pete. + +} +WHERE{?a ?b ?c.} + + From 19ea6bd3b833a35d636c6dcb31ff90287e31dbe2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Avard=20Ottestad?= Date: Fri, 18 Jan 2019 12:15:06 +0100 Subject: [PATCH 43/54] eclipse/rdf4j#1247 support implicit and MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håvard Ottestad --- .../rdf4j/sail/shacl/AST/OrPropertyShape.java | 35 ++++++++++++------- .../eclipse/rdf4j/sail/shacl/ShaclTest.java | 3 +- .../or/implicitAnd/invalid/case1/query1.rq | 13 +++++++ .../or/implicitAnd/invalid/case2/query1.rq | 13 +++++++ .../test-cases/or/implicitAnd/shacl.ttl | 26 ++++++++++++++ .../or/implicitAnd/valid/case1/query1.rq | 13 +++++++ .../or/implicitAnd/valid/case2/query1.rq | 13 +++++++ 7 files changed, 103 insertions(+), 13 deletions(-) create mode 100644 shacl/src/test/resources/test-cases/or/implicitAnd/invalid/case1/query1.rq create mode 100644 shacl/src/test/resources/test-cases/or/implicitAnd/invalid/case2/query1.rq create mode 100644 shacl/src/test/resources/test-cases/or/implicitAnd/shacl.ttl create mode 100644 shacl/src/test/resources/test-cases/or/implicitAnd/valid/case1/query1.rq create mode 100644 shacl/src/test/resources/test-cases/or/implicitAnd/valid/case2/query1.rq diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/OrPropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/OrPropertyShape.java index 71011a82b..d4793d67a 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/OrPropertyShape.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/OrPropertyShape.java @@ -11,8 +11,6 @@ import org.eclipse.rdf4j.common.iteration.Iterations; import org.eclipse.rdf4j.model.Resource; import org.eclipse.rdf4j.model.Statement; -import org.eclipse.rdf4j.model.Value; -import org.eclipse.rdf4j.model.vocabulary.RDF; import org.eclipse.rdf4j.model.vocabulary.SHACL; import org.eclipse.rdf4j.repository.Repository; import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; @@ -24,10 +22,11 @@ import org.eclipse.rdf4j.sail.shacl.planNodes.IteratorData; import org.eclipse.rdf4j.sail.shacl.planNodes.LoggingNode; import org.eclipse.rdf4j.sail.shacl.planNodes.PlanNode; +import org.eclipse.rdf4j.sail.shacl.planNodes.UnionNode; +import org.eclipse.rdf4j.sail.shacl.planNodes.Unique; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -37,7 +36,7 @@ */ public class OrPropertyShape extends PropertyShape { - private final List or; + private final List> or; private static final Logger logger = LoggerFactory.getLogger(OrPropertyShape.class); @@ -47,9 +46,9 @@ public class OrPropertyShape extends PropertyShape { try (Stream stream = Iterations.stream(connection.getStatements(id, SHACL.OR, null, true))) { Resource orList = stream.map(Statement::getObject).map(v -> (Resource) v).findAny().orElseThrow(() -> new RuntimeException("Expected to find sh:or on " + id)); - or = toList(connection, orList).stream().map(v -> PropertyShape.Factory.getPropertyShapesInner(connection, nodeShape, (Resource) v).get(0)).collect(Collectors.toList()); + or = toList(connection, orList).stream().map(v -> PropertyShape.Factory.getPropertyShapesInner(connection, nodeShape, (Resource) v)).collect(Collectors.toList()); } - + System.out.println(); } @@ -58,9 +57,17 @@ public class OrPropertyShape extends PropertyShape { @Override public PlanNode getPlan(ShaclSailConnection shaclSailConnection, NodeShape nodeShape, boolean printPlans, boolean assumeBaseSailValid) { - List plannodes = or.stream().map(shape -> shape.getPlan(shaclSailConnection, nodeShape, false, false)).collect(Collectors.toList()); + List> plannodes = + or + .stream() + .map(shapes -> shapes.stream().map(shape -> shape.getPlan(shaclSailConnection, nodeShape, false, false)).collect(Collectors.toList())) + .collect(Collectors.toList()); - List iteratorDataTypes = plannodes.stream().map(PlanNode::getIteratorDataType).distinct().collect(Collectors.toList()); + List iteratorDataTypes = + plannodes + .stream() + .flatMap(shapes -> shapes.stream().map(PlanNode::getIteratorDataType)) + .distinct().collect(Collectors.toList()); if (iteratorDataTypes.size() > 1) { throw new UnsupportedOperationException("No support for OR shape with mix between aggregate and raw triples"); @@ -72,10 +79,10 @@ public PlanNode getPlan(ShaclSailConnection shaclSailConnection, NodeShape nodeS if (iteratorDataTypes.get(0) == IteratorData.tripleBased) { - EqualsJoin equalsJoin = new EqualsJoin(plannodes.get(0), plannodes.get(1), true); + EqualsJoin equalsJoin = new EqualsJoin(unionAll(plannodes.get(0)), unionAll(plannodes.get(1)), true); for (int i = 2; i < or.size(); i++) { - equalsJoin = new EqualsJoin(equalsJoin, plannodes.get(i), true); + equalsJoin = new EqualsJoin(equalsJoin, unionAll(plannodes.get(i)), true); } ret = new LoggingNode(equalsJoin); @@ -83,10 +90,10 @@ public PlanNode getPlan(ShaclSailConnection shaclSailConnection, NodeShape nodeS else if (iteratorDataTypes.get(0) == IteratorData.aggregated) { - PlanNode equalsJoin = new LoggingNode(new InnerJoin(plannodes.get(0), plannodes.get(1), null, null)); + PlanNode equalsJoin = new LoggingNode(new InnerJoin(unionAll(plannodes.get(0)), unionAll(plannodes.get(1)), null, null)); for (int i = 2; i < or.size(); i++) { - equalsJoin = new LoggingNode(new InnerJoin(equalsJoin, plannodes.get(i), null, null)); + equalsJoin = new LoggingNode(new InnerJoin(equalsJoin, unionAll(plannodes.get(i)), null, null)); } ret = new LoggingNode(equalsJoin); @@ -105,6 +112,10 @@ else if (iteratorDataTypes.get(0) == IteratorData.aggregated) { } + private PlanNode unionAll(List planNodes) { + return new Unique(new UnionNode(planNodes.toArray(new PlanNode[0]))); + } + @Override public boolean requiresEvaluation(Repository addedStatements, Repository removedStatements) { return true; diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java index e67572b84..937e423ea 100644 --- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java @@ -56,7 +56,8 @@ public class ShaclTest { "test-cases/or/minCountMaxCount", "test-cases/or/maxCount", "test-cases/or/minCount", - "test-cases/or/nodeKindMinLength" + "test-cases/or/nodeKindMinLength", + "test-cases/or/implicitAnd" ); diff --git a/shacl/src/test/resources/test-cases/or/implicitAnd/invalid/case1/query1.rq b/shacl/src/test/resources/test-cases/or/implicitAnd/invalid/case1/query1.rq new file mode 100644 index 000000000..5311a970d --- /dev/null +++ b/shacl/src/test/resources/test-cases/or/implicitAnd/invalid/case1/query1.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person ; + ex:iriOr10LengthEnglishNorwegianLiteral 12345678901. + +} diff --git a/shacl/src/test/resources/test-cases/or/implicitAnd/invalid/case2/query1.rq b/shacl/src/test/resources/test-cases/or/implicitAnd/invalid/case2/query1.rq new file mode 100644 index 000000000..5311a970d --- /dev/null +++ b/shacl/src/test/resources/test-cases/or/implicitAnd/invalid/case2/query1.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person ; + ex:iriOr10LengthEnglishNorwegianLiteral 12345678901. + +} diff --git a/shacl/src/test/resources/test-cases/or/implicitAnd/shacl.ttl b/shacl/src/test/resources/test-cases/or/implicitAnd/shacl.ttl new file mode 100644 index 000000000..ebfef52c6 --- /dev/null +++ b/shacl/src/test/resources/test-cases/or/implicitAnd/shacl.ttl @@ -0,0 +1,26 @@ +@base . +@prefix ex: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix xsd: . + +ex:PersonShape + a sh:NodeShape ; + sh:targetClass ex:Person ; + sh:property [ + sh:or ( + [ + sh:path ex:iriOr10LengthEnglishNorwegianLiteral ; + sh:nodeKind sh:IRI ; + ] + [ + sh:path ex:iriOr10LengthEnglishNorwegianLiteral ; + sh:minLength 10 ; + sh:nodeKind sh:Literal ; + sh:languageIn ("no" "en") ; + ] + ) ; + ] . + diff --git a/shacl/src/test/resources/test-cases/or/implicitAnd/valid/case1/query1.rq b/shacl/src/test/resources/test-cases/or/implicitAnd/valid/case1/query1.rq new file mode 100644 index 000000000..811cedf03 --- /dev/null +++ b/shacl/src/test/resources/test-cases/or/implicitAnd/valid/case1/query1.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person ; + ex:iriOr10LengthEnglishNorwegianLiteral "12345678901"@no . + +} diff --git a/shacl/src/test/resources/test-cases/or/implicitAnd/valid/case2/query1.rq b/shacl/src/test/resources/test-cases/or/implicitAnd/valid/case2/query1.rq new file mode 100644 index 000000000..372734428 --- /dev/null +++ b/shacl/src/test/resources/test-cases/or/implicitAnd/valid/case2/query1.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person ; + ex:iriOr10LengthEnglishNorwegianLiteral ex:pete. + +} From 260a53a092c4a71546eb2569e47ecbd45be4d1ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Avard=20Ottestad?= Date: Sat, 19 Jan 2019 12:41:43 +0100 Subject: [PATCH 44/54] fixes after rebase MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håvard Ottestad --- .../sail/shacl/AST/LanguageInPropertyShape.java | 10 +++++++++- .../rdf4j/sail/shacl/AST/MaxLengthPropertyShape.java | 12 +++++++++++- .../rdf4j/sail/shacl/AST/MinLengthPropertyShape.java | 10 +++++++++- .../rdf4j/sail/shacl/AST/NodeKindPropertyShape.java | 10 +++++++++- .../rdf4j/sail/shacl/AST/PatternPropertyShape.java | 10 +++++++++- .../rdf4j/sail/shacl/SourceConstraintComponent.java | 7 ++++++- 6 files changed, 53 insertions(+), 6 deletions(-) diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/LanguageInPropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/LanguageInPropertyShape.java index 1fdb14871..f89853ad3 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/LanguageInPropertyShape.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/LanguageInPropertyShape.java @@ -16,7 +16,10 @@ import org.eclipse.rdf4j.repository.Repository; import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; import org.eclipse.rdf4j.sail.shacl.ShaclSailConnection; +import org.eclipse.rdf4j.sail.shacl.SourceConstraintComponent; +import org.eclipse.rdf4j.sail.shacl.planNodes.EnrichWithShape; import org.eclipse.rdf4j.sail.shacl.planNodes.LanguageInFilter; +import org.eclipse.rdf4j.sail.shacl.planNodes.LoggingNode; import org.eclipse.rdf4j.sail.shacl.planNodes.PlanNode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -59,7 +62,7 @@ public PlanNode getPlan(ShaclSailConnection shaclSailConnection, NodeShape nodeS logger.info(planAsGraphvizDot); } - return invalidValues; + return new EnrichWithShape(new LoggingNode(invalidValues), this); } @@ -67,4 +70,9 @@ public PlanNode getPlan(ShaclSailConnection shaclSailConnection, NodeShape nodeS public boolean requiresEvaluation(Repository addedStatements, Repository removedStatements) { return true; } + + @Override + public SourceConstraintComponent getSourceConstraintComponent() { + return SourceConstraintComponent.LanguageInConstraintComponent; + } } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MaxLengthPropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MaxLengthPropertyShape.java index 6e7399632..2c2771bee 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MaxLengthPropertyShape.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MaxLengthPropertyShape.java @@ -16,6 +16,9 @@ import org.eclipse.rdf4j.repository.Repository; import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; import org.eclipse.rdf4j.sail.shacl.ShaclSailConnection; +import org.eclipse.rdf4j.sail.shacl.SourceConstraintComponent; +import org.eclipse.rdf4j.sail.shacl.planNodes.EnrichWithShape; +import org.eclipse.rdf4j.sail.shacl.planNodes.LoggingNode; import org.eclipse.rdf4j.sail.shacl.planNodes.MaxLengthFilter; import org.eclipse.rdf4j.sail.shacl.planNodes.MinLengthFilter; import org.eclipse.rdf4j.sail.shacl.planNodes.PlanNode; @@ -57,7 +60,7 @@ public PlanNode getPlan(ShaclSailConnection shaclSailConnection, NodeShape nodeS logger.info(planAsGraphvizDot); } - return invalidValues; + return new EnrichWithShape(new LoggingNode(invalidValues), this); } @@ -65,4 +68,11 @@ public PlanNode getPlan(ShaclSailConnection shaclSailConnection, NodeShape nodeS public boolean requiresEvaluation(Repository addedStatements, Repository removedStatements) { return true; } + + @Override + public SourceConstraintComponent getSourceConstraintComponent() { + + return SourceConstraintComponent.MaxLengthConstraintComponent; + } + } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MinLengthPropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MinLengthPropertyShape.java index 4b8d9bcad..5fbd163ee 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MinLengthPropertyShape.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MinLengthPropertyShape.java @@ -16,6 +16,9 @@ import org.eclipse.rdf4j.repository.Repository; import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; import org.eclipse.rdf4j.sail.shacl.ShaclSailConnection; +import org.eclipse.rdf4j.sail.shacl.SourceConstraintComponent; +import org.eclipse.rdf4j.sail.shacl.planNodes.EnrichWithShape; +import org.eclipse.rdf4j.sail.shacl.planNodes.LoggingNode; import org.eclipse.rdf4j.sail.shacl.planNodes.MinLengthFilter; import org.eclipse.rdf4j.sail.shacl.planNodes.PlanNode; import org.slf4j.Logger; @@ -56,7 +59,7 @@ public PlanNode getPlan(ShaclSailConnection shaclSailConnection, NodeShape nodeS logger.info(planAsGraphvizDot); } - return invalidValues; + return new EnrichWithShape(new LoggingNode(invalidValues), this); } @@ -64,4 +67,9 @@ public PlanNode getPlan(ShaclSailConnection shaclSailConnection, NodeShape nodeS public boolean requiresEvaluation(Repository addedStatements, Repository removedStatements) { return true; } + + @Override + public SourceConstraintComponent getSourceConstraintComponent() { + return SourceConstraintComponent.MinLengthConstraintComponent; + } } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/NodeKindPropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/NodeKindPropertyShape.java index 8b7c90fbb..a2f3e1ccc 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/NodeKindPropertyShape.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/NodeKindPropertyShape.java @@ -17,6 +17,9 @@ import org.eclipse.rdf4j.repository.Repository; import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; import org.eclipse.rdf4j.sail.shacl.ShaclSailConnection; +import org.eclipse.rdf4j.sail.shacl.SourceConstraintComponent; +import org.eclipse.rdf4j.sail.shacl.planNodes.EnrichWithShape; +import org.eclipse.rdf4j.sail.shacl.planNodes.LoggingNode; import org.eclipse.rdf4j.sail.shacl.planNodes.MinLengthFilter; import org.eclipse.rdf4j.sail.shacl.planNodes.NodeKindFilter; import org.eclipse.rdf4j.sail.shacl.planNodes.PlanNode; @@ -83,7 +86,7 @@ public PlanNode getPlan(ShaclSailConnection shaclSailConnection, NodeShape nodeS logger.info(planAsGraphvizDot); } - return invalidValues; + return new EnrichWithShape(new LoggingNode(invalidValues), this); } @@ -91,4 +94,9 @@ public PlanNode getPlan(ShaclSailConnection shaclSailConnection, NodeShape nodeS public boolean requiresEvaluation(Repository addedStatements, Repository removedStatements) { return true; } + + @Override + public SourceConstraintComponent getSourceConstraintComponent() { + return SourceConstraintComponent.NodeKindConstraintComponent; + } } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PatternPropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PatternPropertyShape.java index d013bc3e9..801e7f0a5 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PatternPropertyShape.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PatternPropertyShape.java @@ -16,6 +16,9 @@ import org.eclipse.rdf4j.repository.Repository; import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; import org.eclipse.rdf4j.sail.shacl.ShaclSailConnection; +import org.eclipse.rdf4j.sail.shacl.SourceConstraintComponent; +import org.eclipse.rdf4j.sail.shacl.planNodes.EnrichWithShape; +import org.eclipse.rdf4j.sail.shacl.planNodes.LoggingNode; import org.eclipse.rdf4j.sail.shacl.planNodes.PatternFilter; import org.eclipse.rdf4j.sail.shacl.planNodes.PlanNode; import org.slf4j.Logger; @@ -62,7 +65,7 @@ public PlanNode getPlan(ShaclSailConnection shaclSailConnection, NodeShape nodeS logger.info(planAsGraphvizDot); } - return invalidValues; + return new EnrichWithShape(new LoggingNode(invalidValues), this); } @@ -70,4 +73,9 @@ public PlanNode getPlan(ShaclSailConnection shaclSailConnection, NodeShape nodeS public boolean requiresEvaluation(Repository addedStatements, Repository removedStatements) { return true; } + + @Override + public SourceConstraintComponent getSourceConstraintComponent() { + return SourceConstraintComponent.PatternConstraintComponent; + } } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/SourceConstraintComponent.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/SourceConstraintComponent.java index 215c9bdff..97fc87180 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/SourceConstraintComponent.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/SourceConstraintComponent.java @@ -7,7 +7,12 @@ public enum SourceConstraintComponent { MaxCountConstraintComponent(SHACL.MAX_COUNT_CONSTRAINT_COMPONENT), DatatypeConstraintComponent(SHACL.DATATYPE_CONSTRAINT_COMPONENT), OrConstraintComponent(SHACL.OR_CONSTRAINT_COMPONENT), - MinCountConstraintComponent(SHACL.MIN_COUNT_CONSTRAINT_COMPONENT); + MinCountConstraintComponent(SHACL.MIN_COUNT_CONSTRAINT_COMPONENT), + LanguageInConstraintComponent(SHACL.LANGUAGE_IN_CONSTRAINT_COMPONENT), + MaxLengthConstraintComponent(SHACL.MAX_LENGTH_CONSTRAINT_COMPONENT), + MinLengthConstraintComponent(SHACL.MIN_LENGTH_CONSTRAINT_COMPONENT), + NodeKindConstraintComponent(SHACL.NODE_KIND_CONSTRAINT_COMPONENT), + PatternConstraintComponent(SHACL.PATTERN_CONSTRAINT_COMPONENT); private final IRI iri; From 59f71f68dc53cbec2959427ccfb5d4a48b2d5e7d Mon Sep 17 00:00:00 2001 From: Jeen Broekstra Date: Sun, 20 Jan 2019 13:46:36 +1100 Subject: [PATCH 45/54] eclipse/rdf4j#1113 moved graph name constant and fixed compliance test setup --- .../rdf4j/sail/shacl/SHACLComplianceTest.java | 43 +------ .../sail/shacl/NoShapesLoadedException.java | 7 +- .../eclipse/rdf4j/sail/shacl/ShaclSail.java | 47 ++++--- .../rdf4j/sail/shacl/ShaclSailConnection.java | 117 ++++++++++++------ .../sail/shacl/RuntimeModifyShapesTest.java | 5 +- .../org/eclipse/rdf4j/sail/shacl/Utils.java | 9 +- 6 files changed, 117 insertions(+), 111 deletions(-) diff --git a/compliance/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/SHACLComplianceTest.java b/compliance/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/SHACLComplianceTest.java index d3bd646f2..bb9971680 100644 --- a/compliance/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/SHACLComplianceTest.java +++ b/compliance/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/SHACLComplianceTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2018 Eclipse RDF4J contributors, Aduna, and others. + * Copyright (c) 2018 Eclipse RDF4J contributors. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Distribution License v1.0 * which accompanies this distribution, and is available at @@ -8,11 +8,6 @@ package org.eclipse.rdf4j.sail.shacl; import org.eclipse.rdf4j.model.Model; -import org.eclipse.rdf4j.model.Resource; -import org.eclipse.rdf4j.model.impl.LinkedHashModel; -import org.eclipse.rdf4j.model.vocabulary.RDF; -import org.eclipse.rdf4j.model.vocabulary.SHACL; -import org.eclipse.rdf4j.repository.sail.SailRepository; import org.eclipse.rdf4j.sail.NotifyingSail; import org.eclipse.rdf4j.sail.Sail; import org.eclipse.rdf4j.sail.memory.MemoryStore; @@ -62,39 +57,9 @@ protected NotifyingSail newDataSail() { return new MemoryStore(); } - protected SailRepository createShapesRepository() { - SailRepository repo = new SailRepository(new MemoryStore()); - repo.initialize(); - return repo; - } - @Override - protected Sail newSail(Model shapesGraph) { - SailRepository shapesRep = createShapesRepository(); - if (shapesGraph != null) { - try { - upload(shapesRep, shapesGraph); - } - catch (Exception exc) { - try { - shapesRep.shutDown(); - shapesRep = null; - } - catch (Exception e2) { - logger.error(e2.toString(), e2); - } - throw exc; - } - } - Model infer = new LinkedHashModel(); - for (Resource subj : shapesGraph.filter(null, RDF.TYPE, SHACL.NODE_SHAPE).subjects()) { - infer.add(subj, RDF.TYPE, SHACL.SHAPE); - } - for (Resource subj : shapesGraph.filter(null, RDF.TYPE, SHACL.PROPERTY_SHAPE).subjects()) { - infer.add(subj, RDF.TYPE, SHACL.SHAPE); - } - upload(shapesRep, infer); - return new ShaclSail(newDataSail(), shapesRep); + protected Sail newSail() { + return new ShaclSail(newDataSail()); } - + } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/NoShapesLoadedException.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/NoShapesLoadedException.java index eaf48baa9..33f99ca24 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/NoShapesLoadedException.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/NoShapesLoadedException.java @@ -1,8 +1,13 @@ package org.eclipse.rdf4j.sail.shacl; +import org.eclipse.rdf4j.model.vocabulary.RDF4J; + public class NoShapesLoadedException extends RuntimeException { + private static final long serialVersionUID = 1L; + public NoShapesLoadedException() { - super("Load shapes by adding them to named graph <"+ShaclSail.SHAPE_GRAPH+"> in the first transaction after initialization!"); + super("Load shapes by adding them to named graph <" + RDF4J.SHACL_SHAPE_GRAPH + + "> in the first transaction after initialization!"); } } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSail.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSail.java index 25d19c757..3c946d316 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSail.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSail.java @@ -11,6 +11,7 @@ import org.apache.commons.io.IOUtils; import org.eclipse.rdf4j.model.IRI; import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.model.vocabulary.RDF4J; import org.eclipse.rdf4j.repository.Repository; import org.eclipse.rdf4j.repository.sail.SailRepository; import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; @@ -29,7 +30,9 @@ import java.util.List; /** - * A {@link Sail} implementation that adds support for the Shapes Constraint Language (SHACL) + * A {@link Sail} implementation that adds support for the Shapes Constraint Language (SHACL). + *

+ * The ShaclSail looks for SHACL shape data in a special named graph {@link RDF4J#SHACL_SHAPE_GRAPH}. * * @author Heshan Jayasinghe * @author Håvard Ottestad @@ -37,17 +40,10 @@ */ public class ShaclSail extends NotifyingSailWrapper { - /** - * The virtual context identifier for persisting the SHACL shapes information. - */ - @SuppressWarnings("WeakerAccess") - public final static IRI SHAPE_GRAPH = SimpleValueFactory - .getInstance() - .createIRI("http://rdf4j.org/schema/schacl#ShapeGraph"); - private List nodeShapes; boolean debugPrintPlans = false; + private boolean ignoreNoShapesLoadedException = false; ShaclSailConfig config = new ShaclSailConfig(); @@ -64,18 +60,14 @@ public class ShaclSail extends NotifyingSailWrapper { static { try { SH_OR_UPDATE_QUERY = IOUtils.toString( - ShaclSail - .class - .getClassLoader() - .getResourceAsStream("shacl-sparql-inference/sh_or.rq"), - "UTF-8"); + ShaclSail.class.getClassLoader().getResourceAsStream("shacl-sparql-inference/sh_or.rq"), + "UTF-8"); SH_OR_NODE_SHAPE_UPDATE_QUERY = IOUtils.toString( - ShaclSail - .class - .getClassLoader() - .getResourceAsStream("shacl-sparql-inference/sh_or_node_shape.rq"), - "UTF-8"); - } catch (IOException e) { + ShaclSail.class.getClassLoader().getResourceAsStream( + "shacl-sparql-inference/sh_or_node_shape.rq"), + "UTF-8"); + } + catch (IOException e) { throw new IllegalStateException(e); } @@ -86,10 +78,12 @@ public ShaclSail(NotifyingSail baseSail) { String path = null; if (baseSail.getDataDir() != null) { path = baseSail.getDataDir().getPath(); - } else { + } + else { try { path = Files.createTempDirectory("shacl-shapes").toString(); - } catch (IOException e) { + } + catch (IOException e) { throw new SailConfigException(e); } } @@ -118,7 +112,8 @@ void refreshShapes(SailRepositoryConnection shapesRepoConnection) throws SailExc // Our inferencer both adds and removes statements. // To support updates I recommend having two graphs, one raw one with the unmodified data. // Then copy all that data into a new graph, run inferencing on that graph and use it to generate the java objects - throw new IllegalStateException("ShaclSail does not support modifying shapes that are already loaded or loading more shapes"); + throw new IllegalStateException( + "ShaclSail does not support modifying shapes that are already loaded or loading more shapes"); } } @@ -130,7 +125,8 @@ void refreshShapes(SailRepositoryConnection shapesRepoConnection) throws SailExc public void shutDown() throws SailException { try { shapesRepo.shutDown(); - } finally { + } + finally { shapesRepo = null; } super.shutDown(); @@ -138,7 +134,8 @@ public void shutDown() throws SailException { @Override public NotifyingSailConnection getConnection() throws SailException { - return new ShaclSailConnection(this, super.getConnection(), super.getConnection(), shapesRepo.getConnection()); + return new ShaclSailConnection(this, super.getConnection(), super.getConnection(), + shapesRepo.getConnection()); } public void disableValidation() { diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java index ace3b7021..3ce2f4422 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java @@ -8,6 +8,13 @@ package org.eclipse.rdf4j.sail.shacl; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + import org.eclipse.rdf4j.IsolationLevel; import org.eclipse.rdf4j.IsolationLevels; import org.eclipse.rdf4j.common.iteration.Iterations; @@ -15,6 +22,7 @@ import org.eclipse.rdf4j.model.Resource; import org.eclipse.rdf4j.model.Statement; import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.vocabulary.RDF4J; import org.eclipse.rdf4j.repository.Repository; import org.eclipse.rdf4j.repository.RepositoryConnection; import org.eclipse.rdf4j.repository.sail.SailRepository; @@ -22,6 +30,7 @@ import org.eclipse.rdf4j.sail.NotifyingSailConnection; import org.eclipse.rdf4j.sail.SailConnectionListener; import org.eclipse.rdf4j.sail.SailException; +import org.eclipse.rdf4j.sail.UpdateContext; import org.eclipse.rdf4j.sail.helpers.NotifyingSailConnectionWrapper; import org.eclipse.rdf4j.sail.memory.MemoryStore; import org.eclipse.rdf4j.sail.shacl.AST.NodeShape; @@ -30,14 +39,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.Stream; - /** * @author Heshan Jayasinghe */ @@ -64,7 +65,8 @@ public class ShaclSailConnection extends NotifyingSailConnectionWrapper { private SailRepositoryConnection shapesConnection; ShaclSailConnection(ShaclSail sail, NotifyingSailConnection connection, - NotifyingSailConnection previousStateConnection, SailRepositoryConnection shapesConnection) { + NotifyingSailConnection previousStateConnection, SailRepositoryConnection shapesConnection) + { super(connection); this.previousStateConnection = previousStateConnection; this.shapesConnection = shapesConnection; @@ -74,23 +76,23 @@ public class ShaclSailConnection extends NotifyingSailConnectionWrapper { addConnectionListener(new SailConnectionListener() { - @Override - public void statementAdded(Statement statement) { - boolean add = addedStatementsSet.add(statement); - if (!add) { - removedStatementsSet.remove(statement); - } + @Override + public void statementAdded(Statement statement) { + boolean add = addedStatementsSet.add(statement); + if (!add) { + removedStatementsSet.remove(statement); + } - } + } - @Override - public void statementRemoved(Statement statement) { - boolean add = removedStatementsSet.add(statement); - if (!add) { - addedStatementsSet.remove(statement); - } - } - } + @Override + public void statementRemoved(Statement statement) { + boolean add = removedStatementsSet.add(statement); + if (!add) { + addedStatementsSet.remove(statement); + } + } + } ); } @@ -144,7 +146,10 @@ public void commit() throws SailException { refreshShapes(shapesConnection); - if (!sail.isIgnoreNoShapesLoadedException() && ((!addedStatementsSet.isEmpty() || !removedStatementsSet.isEmpty()) && sail.getNodeShapes().isEmpty())) { + if (!sail.isIgnoreNoShapesLoadedException() + && ((!addedStatementsSet.isEmpty() || !removedStatementsSet.isEmpty()) + && sail.getNodeShapes().isEmpty())) + { throw new NoShapesLoadedException(); } @@ -157,33 +162,65 @@ public void commit() throws SailException { rollback(); refreshShapes(shapesConnection); throw new ShaclSailValidationException(invalidTuples); - } else { + } + else { shapesConnection.commit(); super.commit(); } - } finally { + } + finally { cleanup(); } } } + @Override + public void addStatement(UpdateContext modify, Resource subj, IRI pred, Value obj, Resource... contexts) + throws SailException + { + if (contexts.length == 1 && contexts[0].equals(RDF4J.SHACL_SHAPE_GRAPH)) { + shapesConnection.add(subj, pred, obj); + isShapeRefreshNeeded = true; + } + else { + super.addStatement(modify, subj, pred, obj, contexts); + } + } + + @Override + public void removeStatement(UpdateContext modify, Resource subj, IRI pred, Value obj, + Resource... contexts) + throws SailException + { + if (contexts.length == 1 && contexts[0].equals(RDF4J.SHACL_SHAPE_GRAPH)) { + shapesConnection.remove(subj, pred, obj); + isShapeRefreshNeeded = true; + } + else { + super.removeStatement(modify, subj, pred, obj, contexts); + } + } + @Override public void addStatement(Resource subj, IRI pred, Value obj, Resource... contexts) throws SailException { - if (contexts.length == 1 && contexts[0].equals(ShaclSail.SHAPE_GRAPH)) { + if (contexts.length == 1 && contexts[0].equals(RDF4J.SHACL_SHAPE_GRAPH)) { shapesConnection.add(subj, pred, obj); isShapeRefreshNeeded = true; - } else { + } + else { super.addStatement(subj, pred, obj, contexts); } } @Override public void removeStatements(Resource subj, IRI pred, Value obj, Resource... contexts) - throws SailException { - if (contexts.length == 1 && contexts[0].equals(ShaclSail.SHAPE_GRAPH)) { + throws SailException + { + if (contexts.length == 1 && contexts[0].equals(RDF4J.SHACL_SHAPE_GRAPH)) { shapesConnection.remove(subj, pred, obj); isShapeRefreshNeeded = true; - } else { + } + else { super.removeStatements(subj, pred, obj, contexts); } } @@ -243,12 +280,12 @@ private List validate() { boolean valid = collect.size() == 0; if (!valid) { logger.warn( - "SHACL not valid. The following experimental debug results were produced: \n\tNodeShape: {} \n\t\t{}", - nodeShape.toString(), - String.join("\n\t\t", - collect.stream().map( - a -> a.toString() + " -cause-> " + a.getCause()).collect( - Collectors.toList()))); + "SHACL not valid. The following experimental debug results were produced: \n\tNodeShape: {} \n\t\t{}", + nodeShape.toString(), + String.join("\n\t\t", + collect.stream().map( + a -> a.toString() + " -cause-> " + a.getCause()).collect( + Collectors.toList()))); } } } @@ -268,14 +305,14 @@ void fillAddedAndRemovedStatementRepositories() { try (RepositoryConnection connection = addedStatements.getConnection()) { connection.begin(IsolationLevels.NONE); addedStatementsSet.stream().filter( - statement -> !removedStatementsSet.contains(statement)).forEach(connection::add); + statement -> !removedStatementsSet.contains(statement)).forEach(connection::add); connection.commit(); } try (RepositoryConnection connection = removedStatements.getConnection()) { connection.begin(IsolationLevels.NONE); removedStatementsSet.stream().filter( - statement -> !addedStatementsSet.contains(statement)).forEach(connection::add); + statement -> !addedStatementsSet.contains(statement)).forEach(connection::add); connection.commit(); } } diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/RuntimeModifyShapesTest.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/RuntimeModifyShapesTest.java index a973ae279..debb7cdad 100644 --- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/RuntimeModifyShapesTest.java +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/RuntimeModifyShapesTest.java @@ -1,6 +1,7 @@ package org.eclipse.rdf4j.sail.shacl; import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.model.vocabulary.RDF4J; import org.eclipse.rdf4j.model.vocabulary.RDFS; import org.eclipse.rdf4j.repository.sail.SailRepository; import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; @@ -49,10 +50,10 @@ public void checkForExceptionWhenModifyingShapes() throws IOException { try (SailRepositoryConnection connection = sailRepository.getConnection()) { connection.begin(); - connection.add(RuntimeModifyShapesTest.class.getClassLoader().getResourceAsStream("shaclDatatype.ttl"), "http://example.com/", RDFFormat.TURTLE, ShaclSail.SHAPE_GRAPH); + connection.add(RuntimeModifyShapesTest.class.getClassLoader().getResourceAsStream("shaclDatatype.ttl"), "http://example.com/", RDFFormat.TURTLE, RDF4J.SHACL_SHAPE_GRAPH); connection.commit(); connection.begin(); - connection.add(RuntimeModifyShapesTest.class.getClassLoader().getResourceAsStream("shacl.ttl"), "http://example.com/", RDFFormat.TURTLE, ShaclSail.SHAPE_GRAPH); + connection.add(RuntimeModifyShapesTest.class.getClassLoader().getResourceAsStream("shacl.ttl"), "http://example.com/", RDFFormat.TURTLE, RDF4J.SHACL_SHAPE_GRAPH); connection.commit(); } diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/Utils.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/Utils.java index a95b78906..460701095 100644 --- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/Utils.java +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/Utils.java @@ -17,6 +17,7 @@ import org.eclipse.rdf4j.model.Model; import org.eclipse.rdf4j.model.Statement; import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.model.vocabulary.RDF4J; import org.eclipse.rdf4j.repository.RepositoryConnection; import org.eclipse.rdf4j.repository.sail.SailRepository; import org.eclipse.rdf4j.rio.RDFFormat; @@ -34,11 +35,11 @@ public static void loadShapeData(ShaclSail sail, String resourceName) throws RDF4JException, UnsupportedRDFormatException, IOException { InputStream shapesData = Utils.class.getResourceAsStream("/" + resourceName); - Model shapes = Rio.parse(shapesData, "", RDFFormat.TURTLE, ShaclSail.SHAPE_GRAPH); + Model shapes = Rio.parse(shapesData, "", RDFFormat.TURTLE, RDF4J.SHACL_SHAPE_GRAPH); try (SailConnection conn = sail.getConnection()) { conn.begin(); for (Statement st : shapes) { - conn.addStatement(st.getSubject(), st.getPredicate(), st.getObject(), ShaclSail.SHAPE_GRAPH); + conn.addStatement(st.getSubject(), st.getPredicate(), st.getObject(), RDF4J.SHACL_SHAPE_GRAPH); } conn.commit(); } @@ -49,11 +50,11 @@ public static void loadShapeData(SailRepository repo, String resourceName) throws RDF4JException, UnsupportedRDFormatException, IOException { InputStream shapesData = Utils.class.getResourceAsStream("/" + resourceName); - Model shapes = Rio.parse(shapesData, "", RDFFormat.TURTLE, ShaclSail.SHAPE_GRAPH); + Model shapes = Rio.parse(shapesData, "", RDFFormat.TURTLE, RDF4J.SHACL_SHAPE_GRAPH); try (RepositoryConnection conn = repo.getConnection()) { conn.begin(); for (Statement st : shapes) { - conn.add(st.getSubject(), st.getPredicate(), st.getObject(), ShaclSail.SHAPE_GRAPH); + conn.add(st.getSubject(), st.getPredicate(), st.getObject(), RDF4J.SHACL_SHAPE_GRAPH); } conn.commit(); } From 411913a112a2d925dbbac8fede751e12be637450 Mon Sep 17 00:00:00 2001 From: Jeen Broekstra Date: Sun, 20 Jan 2019 15:52:40 +1100 Subject: [PATCH 46/54] eclipse/rdf4j#1113 added config and factory class for ShaclSail --- .../eclipse/rdf4j/sail/shacl/ShaclSail.java | 4 ++ .../sail/shacl/config/ShaclSailConfig.java | 26 ++++++++++ .../sail/shacl/config/ShaclSailFactory.java | 49 +++++++++++++++++++ 3 files changed, 79 insertions(+) create mode 100644 shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/config/ShaclSailConfig.java create mode 100644 shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/config/ShaclSailFactory.java diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSail.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSail.java index 3c946d316..086dbcb94 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSail.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSail.java @@ -96,6 +96,10 @@ public ShaclSail(NotifyingSail baseSail) { shapesRepo.initialize(); } + public ShaclSail() { + super(); + } + @Override public void initialize() throws SailException { super.initialize(); diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/config/ShaclSailConfig.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/config/ShaclSailConfig.java new file mode 100644 index 000000000..c8a9d52f4 --- /dev/null +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/config/ShaclSailConfig.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2019 Eclipse RDF4J contributors. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.sail.shacl.config; + +import org.eclipse.rdf4j.sail.config.AbstractDelegatingSailImplConfig; +import org.eclipse.rdf4j.sail.config.SailImplConfig; +import org.eclipse.rdf4j.sail.shacl.ShaclSail; + + +/** + * A {@link SailImplConfig} for {@link ShaclSail}. + * + * @author Jeen Broekstra + * + */ +public class ShaclSailConfig extends AbstractDelegatingSailImplConfig { + + public ShaclSailConfig() { + super(ShaclSailFactory.SAIL_TYPE); + } +} diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/config/ShaclSailFactory.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/config/ShaclSailFactory.java new file mode 100644 index 000000000..44d5bfaa4 --- /dev/null +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/config/ShaclSailFactory.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2019 Eclipse RDF4J contributors. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ +package org.eclipse.rdf4j.sail.shacl.config; + +import org.eclipse.rdf4j.sail.Sail; +import org.eclipse.rdf4j.sail.config.SailConfigException; +import org.eclipse.rdf4j.sail.config.SailFactory; +import org.eclipse.rdf4j.sail.config.SailImplConfig; +import org.eclipse.rdf4j.sail.shacl.ShaclSail; + +/** + * Factory class for creation of {@link ShaclSail}s as part of a Sail stack. + * + * @author Jeen Broekstra + */ +public class ShaclSailFactory implements SailFactory { + + /** + * The type of Sails that are created by this factory. + * + * @see SailFactory#getSailType() + */ + public static final String SAIL_TYPE = "rdf4j:ShaclSail"; + + @Override + public String getSailType() { + return SAIL_TYPE; + } + + @Override + public SailImplConfig getConfig() { + return new ShaclSailConfig(); + } + + @Override + public Sail getSail(SailImplConfig config) throws SailConfigException { + if (!SAIL_TYPE.equals(config.getType())) { + throw new SailConfigException("Invalid Sail type: " + config.getType()); + } + + return new ShaclSail(); + } + +} From 4572f8dff60312a1ad8dac73d269a4f77135355f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Avard=20Ottestad?= Date: Sun, 20 Jan 2019 10:58:28 +0100 Subject: [PATCH 47/54] various cleanup and fix for sh:or MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håvard Ottestad --- .../shacl/AST/LanguageInPropertyShape.java | 2 +- .../shacl/AST/MaxLengthPropertyShape.java | 2 +- .../shacl/AST/MinLengthPropertyShape.java | 2 +- .../sail/shacl/AST/NodeKindPropertyShape.java | 2 +- .../rdf4j/sail/shacl/AST/NodeShape.java | 5 ++++ .../rdf4j/sail/shacl/AST/OrPropertyShape.java | 30 +++++++++++++++---- .../sail/shacl/AST/PathPropertyShape.java | 9 ++++++ .../rdf4j/sail/shacl/AST/PlanGenerator.java | 3 ++ .../rdf4j/sail/shacl/AST/PropertyShape.java | 5 ++++ .../rdf4j/sail/shacl/AST/SimplePath.java | 19 ++++++++++++ .../shacl/ShaclSailValidationException.java | 14 +++++++++ .../sail/shacl/SourceConstraintComponent.java | 8 +++++ .../sail/shacl/planNodes/EnrichWithShape.java | 1 + .../shacl/planNodes/LanguageInFilter.java | 3 +- .../sail/shacl/planNodes/MaxLengthFilter.java | 3 +- .../sail/shacl/planNodes/MinLengthFilter.java | 2 +- .../sail/shacl/planNodes/NodeKindFilter.java | 3 +- .../sail/shacl/planNodes/PatternFilter.java | 3 +- .../sail/shacl/results/ModelInterface.java | 8 +++++ .../sail/shacl/results/ValidationReport.java | 24 +++++++++++++++ .../sail/shacl/results/ValidationResult.java | 30 ++++++++++++++++++- .../eclipse/rdf4j/sail/shacl/ShaclTest.java | 3 +- .../sail/shacl/ValidationReportTest.java | 7 +++++ .../rdf4j/sail/shacl/VisulizerTest.java | 8 +++++ .../invalid/case1/query1.rq | 14 +++++++++ .../or/datatypeDifferentPaths/shacl.ttl | 27 +++++++++++++++++ .../valid/case1/query1.rq | 14 +++++++++ .../valid/case2/query1.rq | 13 ++++++++ .../valid/case3/query1.rq | 13 ++++++++ .../valid/case4/query1.rq | 13 ++++++++ 30 files changed, 273 insertions(+), 17 deletions(-) create mode 100644 shacl/src/test/resources/test-cases/or/datatypeDifferentPaths/invalid/case1/query1.rq create mode 100644 shacl/src/test/resources/test-cases/or/datatypeDifferentPaths/shacl.ttl create mode 100644 shacl/src/test/resources/test-cases/or/datatypeDifferentPaths/valid/case1/query1.rq create mode 100644 shacl/src/test/resources/test-cases/or/datatypeDifferentPaths/valid/case2/query1.rq create mode 100644 shacl/src/test/resources/test-cases/or/datatypeDifferentPaths/valid/case3/query1.rq create mode 100644 shacl/src/test/resources/test-cases/or/datatypeDifferentPaths/valid/case4/query1.rq diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/LanguageInPropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/LanguageInPropertyShape.java index f89853ad3..a1e08c8a6 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/LanguageInPropertyShape.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/LanguageInPropertyShape.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2018 Eclipse RDF4J contributors. + * Copyright (c) 2019 Eclipse RDF4J contributors. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Distribution License v1.0 * which accompanies this distribution, and is available at diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MaxLengthPropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MaxLengthPropertyShape.java index 2c2771bee..d71f4bdad 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MaxLengthPropertyShape.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MaxLengthPropertyShape.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2018 Eclipse RDF4J contributors. + * Copyright (c) 2019 Eclipse RDF4J contributors. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Distribution License v1.0 * which accompanies this distribution, and is available at diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MinLengthPropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MinLengthPropertyShape.java index 5fbd163ee..21d01f8a4 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MinLengthPropertyShape.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MinLengthPropertyShape.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2018 Eclipse RDF4J contributors. + * Copyright (c) 2019 Eclipse RDF4J contributors. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Distribution License v1.0 * which accompanies this distribution, and is available at diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/NodeKindPropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/NodeKindPropertyShape.java index a2f3e1ccc..ea629b5a5 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/NodeKindPropertyShape.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/NodeKindPropertyShape.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2018 Eclipse RDF4J contributors. + * Copyright (c) 2019 Eclipse RDF4J contributors. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Distribution License v1.0 * which accompanies this distribution, and is available at diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/NodeShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/NodeShape.java index f71d4f966..0c030aaee 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/NodeShape.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/NodeShape.java @@ -57,6 +57,11 @@ public PlanNode getPlanRemovedStatements(ShaclSailConnection shaclSailConnection return new TrimTuple(new LoggingNode(new Select(shaclSailConnection.getRemovedStatements(), getQuery())), 1); } + @Override + public List getPaths() { + throw new IllegalStateException(); + } + public List generatePlans(ShaclSailConnection shaclSailConnection, NodeShape nodeShape, boolean printPlans) { return propertyShapes.stream() .filter(propertyShape -> propertyShape.requiresEvaluation(shaclSailConnection.getAddedStatements(), shaclSailConnection.getRemovedStatements())) diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/OrPropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/OrPropertyShape.java index d4793d67a..4fa2d21ce 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/OrPropertyShape.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/OrPropertyShape.java @@ -12,6 +12,7 @@ import org.eclipse.rdf4j.model.Resource; import org.eclipse.rdf4j.model.Statement; import org.eclipse.rdf4j.model.vocabulary.SHACL; +import org.eclipse.rdf4j.query.algebra.In; import org.eclipse.rdf4j.repository.Repository; import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; import org.eclipse.rdf4j.sail.shacl.ShaclSailConnection; @@ -69,15 +70,27 @@ public PlanNode getPlan(ShaclSailConnection shaclSailConnection, NodeShape nodeS .flatMap(shapes -> shapes.stream().map(PlanNode::getIteratorDataType)) .distinct().collect(Collectors.toList()); + + if (iteratorDataTypes.size() > 1) { throw new UnsupportedOperationException("No support for OR shape with mix between aggregate and raw triples"); } - PlanNode ret; + IteratorData iteratorData = iteratorDataTypes.get(0); + + if (iteratorData == IteratorData.tripleBased) { + + List collect = getPaths().stream().distinct().collect(Collectors.toList()); + if(collect.size()>1){ + iteratorData = IteratorData.aggregated; + } + } + PlanNode ret; - if (iteratorDataTypes.get(0) == IteratorData.tripleBased) { + + if (iteratorData == IteratorData.tripleBased) { EqualsJoin equalsJoin = new EqualsJoin(unionAll(plannodes.get(0)), unionAll(plannodes.get(1)), true); @@ -88,15 +101,15 @@ public PlanNode getPlan(ShaclSailConnection shaclSailConnection, NodeShape nodeS ret = new LoggingNode(equalsJoin); } - else if (iteratorDataTypes.get(0) == IteratorData.aggregated) { + else if (iteratorData == IteratorData.aggregated) { - PlanNode equalsJoin = new LoggingNode(new InnerJoin(unionAll(plannodes.get(0)), unionAll(plannodes.get(1)), null, null)); + PlanNode innerJoin = new LoggingNode(new InnerJoin(unionAll(plannodes.get(0)), unionAll(plannodes.get(1)), null, null)); for (int i = 2; i < or.size(); i++) { - equalsJoin = new LoggingNode(new InnerJoin(equalsJoin, unionAll(plannodes.get(i)), null, null)); + innerJoin = new LoggingNode(new InnerJoin(innerJoin, unionAll(plannodes.get(i)), null, null)); } - ret = new LoggingNode(equalsJoin); + ret = new LoggingNode(innerJoin); }else{ throw new IllegalStateException("Should not get here!"); @@ -112,6 +125,11 @@ else if (iteratorDataTypes.get(0) == IteratorData.aggregated) { } + @Override + public List getPaths() { + return or.stream().flatMap(a -> a.stream().flatMap(b -> b.getPaths().stream())).collect(Collectors.toList()); + } + private PlanNode unionAll(List planNodes) { return new Unique(new UnionNode(planNodes.toArray(new PlanNode[0]))); } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PathPropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PathPropertyShape.java index f1ee7bbc1..03a85b964 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PathPropertyShape.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PathPropertyShape.java @@ -15,6 +15,10 @@ import org.eclipse.rdf4j.sail.shacl.planNodes.PlanNode; import org.eclipse.rdf4j.sail.shacl.planNodes.Select; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + /** * The AST (Abstract Syntax Tree) node that represents the sh:path on a property nodeShape. * @@ -47,6 +51,11 @@ public PlanNode getPlanRemovedStatements(ShaclSailConnection shaclSailConnection return new Select(shaclSailConnection.getRemovedStatements(), path.getQuery()); } + @Override + public List getPaths() { + return Collections.singletonList(path); + } + @Override public boolean requiresEvaluation(Repository addedStatements, Repository removedStatements) { diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PlanGenerator.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PlanGenerator.java index 17e4c45e8..1837b5009 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PlanGenerator.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PlanGenerator.java @@ -11,6 +11,8 @@ import org.eclipse.rdf4j.sail.shacl.ShaclSailConnection; import org.eclipse.rdf4j.sail.shacl.planNodes.PlanNode; +import java.util.List; + /** * @author Heshan Jayasinghe */ @@ -22,5 +24,6 @@ public interface PlanGenerator { PlanNode getPlanRemovedStatements(ShaclSailConnection shaclSailConnection, NodeShape nodeShape); + List getPaths(); } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PropertyShape.java index 172db6315..12e52b73e 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PropertyShape.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PropertyShape.java @@ -57,6 +57,11 @@ public PlanNode getPlanRemovedStatements(ShaclSailConnection shaclSailConnection throw new IllegalStateException("Should never get here!!!"); } + @Override + public List getPaths() { + throw new IllegalStateException(); + } + @Override public boolean requiresEvaluation(Repository addedStatements, Repository removedStatements) { return false; diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/SimplePath.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/SimplePath.java index a139ab962..7c3bce63f 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/SimplePath.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/SimplePath.java @@ -17,6 +17,7 @@ import org.eclipse.rdf4j.repository.RepositoryConnection; import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; +import java.util.Objects; import java.util.stream.Stream; /** @@ -66,4 +67,22 @@ public String getQuery() { public IRI getPath() { return path; } + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + SimplePath that = (SimplePath) o; + return Objects.equals(path, that.path); + } + + @Override + public int hashCode() { + return Objects.hash(path); + } } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailValidationException.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailValidationException.java index 36f412377..195e2aaa0 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailValidationException.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailValidationException.java @@ -1,3 +1,11 @@ +/******************************************************************************* + * Copyright (c) 2019 Eclipse RDF4J contributors. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ + package org.eclipse.rdf4j.sail.shacl; import org.eclipse.rdf4j.model.Model; @@ -21,6 +29,9 @@ public class ShaclSailValidationException extends SailException { this.invalidTuples = invalidTuples; } + /** + * @return A Model containing the validation report as specified by the SHACL Recommendation + */ @SuppressWarnings("WeakerAccess") public Model validationReportAsModel() { @@ -33,6 +44,9 @@ public Model validationReportAsModel() { } + /** + * @return A ValidationReport Java object that describes what failed and can optionally be converted to a Model as specified by the SHACL Recommendation + */ @SuppressWarnings("WeakerAccess") public ValidationReport getValidationReport() { ValidationReport validationReport = new ValidationReport(false); diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/SourceConstraintComponent.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/SourceConstraintComponent.java index 97fc87180..a679d3470 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/SourceConstraintComponent.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/SourceConstraintComponent.java @@ -1,3 +1,11 @@ +/******************************************************************************* + * Copyright (c) 2019 Eclipse RDF4J contributors. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ + package org.eclipse.rdf4j.sail.shacl; import org.eclipse.rdf4j.model.IRI; diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/EnrichWithShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/EnrichWithShape.java index 66d7bb492..ee3ee217b 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/EnrichWithShape.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/EnrichWithShape.java @@ -5,6 +5,7 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/org/documents/edl-v10.php. *******************************************************************************/ + package org.eclipse.rdf4j.sail.shacl.planNodes; import org.apache.commons.lang.StringEscapeUtils; diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/LanguageInFilter.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/LanguageInFilter.java index 7026d8352..19aca23e6 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/LanguageInFilter.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/LanguageInFilter.java @@ -1,11 +1,12 @@ /******************************************************************************* - * Copyright (c) 2018 Eclipse RDF4J contributors. + * Copyright (c) 2019 Eclipse RDF4J contributors. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Distribution License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/org/documents/edl-v10.php. *******************************************************************************/ + package org.eclipse.rdf4j.sail.shacl.planNodes; diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MaxLengthFilter.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MaxLengthFilter.java index 1fe63630c..1d2db2550 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MaxLengthFilter.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MaxLengthFilter.java @@ -1,11 +1,12 @@ /******************************************************************************* - * Copyright (c) 2018 Eclipse RDF4J contributors. + * Copyright (c) 2019 Eclipse RDF4J contributors. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Distribution License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/org/documents/edl-v10.php. *******************************************************************************/ + package org.eclipse.rdf4j.sail.shacl.planNodes; diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MinLengthFilter.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MinLengthFilter.java index 4f660a5c6..9f4f491a9 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MinLengthFilter.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MinLengthFilter.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2018 Eclipse RDF4J contributors. + * Copyright (c) 2019 Eclipse RDF4J contributors. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Distribution License v1.0 * which accompanies this distribution, and is available at diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/NodeKindFilter.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/NodeKindFilter.java index 6672b4ba8..4988828c2 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/NodeKindFilter.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/NodeKindFilter.java @@ -1,11 +1,12 @@ /******************************************************************************* - * Copyright (c) 2018 Eclipse RDF4J contributors. + * Copyright (c) 2019 Eclipse RDF4J contributors. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Distribution License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/org/documents/edl-v10.php. *******************************************************************************/ + package org.eclipse.rdf4j.sail.shacl.planNodes; diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/PatternFilter.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/PatternFilter.java index fc021e326..e04e47bdc 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/PatternFilter.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/PatternFilter.java @@ -1,11 +1,12 @@ /******************************************************************************* - * Copyright (c) 2018 Eclipse RDF4J contributors. + * Copyright (c) 2019 Eclipse RDF4J contributors. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Distribution License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/org/documents/edl-v10.php. *******************************************************************************/ + package org.eclipse.rdf4j.sail.shacl.planNodes; diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/results/ModelInterface.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/results/ModelInterface.java index af767842b..01ce061ba 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/results/ModelInterface.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/results/ModelInterface.java @@ -1,3 +1,11 @@ +/******************************************************************************* + * Copyright (c) 2019 Eclipse RDF4J contributors. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ + package org.eclipse.rdf4j.sail.shacl.results; import org.eclipse.rdf4j.model.Model; diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/results/ValidationReport.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/results/ValidationReport.java index 2db6dbf97..2d5f8dd37 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/results/ValidationReport.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/results/ValidationReport.java @@ -1,3 +1,11 @@ +/******************************************************************************* + * Copyright (c) 2019 Eclipse RDF4J contributors. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ + package org.eclipse.rdf4j.sail.shacl.results; import org.eclipse.rdf4j.model.Model; @@ -47,4 +55,20 @@ public Model asModel(Model model) { public Resource getId() { return id; } + + + /** + * @return false if the changes violated a SHACL Shape + */ + public boolean conforms() { + return conforms; + } + + + /** + * @return list of ValidationResult with more information about each violation + */ + public List getValidationResult() { + return validationResult; + } } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/results/ValidationResult.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/results/ValidationResult.java index 1dd6ff9e0..a663f42be 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/results/ValidationResult.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/results/ValidationResult.java @@ -1,3 +1,11 @@ +/******************************************************************************* + * Copyright (c) 2019 Eclipse RDF4J contributors. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ + package org.eclipse.rdf4j.sail.shacl.results; import org.eclipse.rdf4j.model.Model; @@ -39,10 +47,16 @@ public void setDetail(ValidationResult detail) { this.detail = detail; } + /** + * @return ValidationResult with more information as to what failed. Usually for nested Shapes in eg. sh:or. + */ public ValidationResult getDetail() { return detail; } + /** + * @return all ValidationResult(s) with more information as to what failed. Usually for nested Shapes in eg. sh:or. + */ public List getDetails(){ ArrayList validationResults = new ArrayList<>(); @@ -78,14 +92,24 @@ public Model asModel(Model model) { return model; } + /** + * @return the path, as specified in the Shape, that caused the violation + */ private Path getPath() { return path; } - private Resource getSourceShapeResource() { + /** + * @return the Resource (IRI or BNode) that identifies the source shape + */ + public Resource getSourceShapeResource() { return sourceShape.getId(); } + + /** + * @return the focus node, aka. the subject, that caused the violation + */ private Resource getFocusNode() { return focusNode; } @@ -95,6 +119,10 @@ public Resource getId() { return id; } + + /** + * @return the type of the source constraint that caused the violation + */ public SourceConstraintComponent getSourceConstraintComponent() { return sourceConstraintComponent; } diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java index 937e423ea..b8e718899 100644 --- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java @@ -57,7 +57,8 @@ public class ShaclTest { "test-cases/or/maxCount", "test-cases/or/minCount", "test-cases/or/nodeKindMinLength", - "test-cases/or/implicitAnd" + "test-cases/or/implicitAnd", + "test-cases/or/datatypeDifferentPaths" ); diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ValidationReportTest.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ValidationReportTest.java index 73bfb3c84..4b47d8af6 100644 --- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ValidationReportTest.java +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ValidationReportTest.java @@ -1,3 +1,10 @@ +/******************************************************************************* + * Copyright (c) 2019 Eclipse RDF4J contributors. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ package org.eclipse.rdf4j.sail.shacl; import org.apache.commons.io.IOUtils; diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/VisulizerTest.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/VisulizerTest.java index b62036599..5a5b4dd00 100644 --- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/VisulizerTest.java +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/VisulizerTest.java @@ -1,3 +1,11 @@ +/******************************************************************************* + * Copyright (c) 2018 Eclipse RDF4J contributors. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ + package org.eclipse.rdf4j.sail.shacl; import org.eclipse.rdf4j.model.BNode; diff --git a/shacl/src/test/resources/test-cases/or/datatypeDifferentPaths/invalid/case1/query1.rq b/shacl/src/test/resources/test-cases/or/datatypeDifferentPaths/invalid/case1/query1.rq new file mode 100644 index 000000000..17fc730ab --- /dev/null +++ b/shacl/src/test/resources/test-cases/or/datatypeDifferentPaths/invalid/case1/query1.rq @@ -0,0 +1,14 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person ; + ex:age "abc"; + ex:longAge "def". + +} diff --git a/shacl/src/test/resources/test-cases/or/datatypeDifferentPaths/shacl.ttl b/shacl/src/test/resources/test-cases/or/datatypeDifferentPaths/shacl.ttl new file mode 100644 index 000000000..b5890a03b --- /dev/null +++ b/shacl/src/test/resources/test-cases/or/datatypeDifferentPaths/shacl.ttl @@ -0,0 +1,27 @@ +@base . +@prefix ex: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix xsd: . + +ex:PersonShape + a sh:NodeShape ; + sh:targetClass ex:Person ; + sh:property ex:personShapeOr. + + +ex:personShapeOr + sh:or ( + ex:personShapeAgeInteger + ex:personShapeAgeLong + ) . + +ex:personShapeAgeInteger + sh:path ex:age ; + sh:datatype xsd:integer . + +ex:personShapeAgeLong + sh:path ex:longAge ; + sh:datatype xsd:long . \ No newline at end of file diff --git a/shacl/src/test/resources/test-cases/or/datatypeDifferentPaths/valid/case1/query1.rq b/shacl/src/test/resources/test-cases/or/datatypeDifferentPaths/valid/case1/query1.rq new file mode 100644 index 000000000..73e82ff8d --- /dev/null +++ b/shacl/src/test/resources/test-cases/or/datatypeDifferentPaths/valid/case1/query1.rq @@ -0,0 +1,14 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person ; + ex:age 123 ; + ex:longAge "234"^^xsd:long. + +} diff --git a/shacl/src/test/resources/test-cases/or/datatypeDifferentPaths/valid/case2/query1.rq b/shacl/src/test/resources/test-cases/or/datatypeDifferentPaths/valid/case2/query1.rq new file mode 100644 index 000000000..3a2c5f535 --- /dev/null +++ b/shacl/src/test/resources/test-cases/or/datatypeDifferentPaths/valid/case2/query1.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person ; + ex:age 123 . + +} diff --git a/shacl/src/test/resources/test-cases/or/datatypeDifferentPaths/valid/case3/query1.rq b/shacl/src/test/resources/test-cases/or/datatypeDifferentPaths/valid/case3/query1.rq new file mode 100644 index 000000000..195f6491a --- /dev/null +++ b/shacl/src/test/resources/test-cases/or/datatypeDifferentPaths/valid/case3/query1.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person ; + ex:age "a" . + +} diff --git a/shacl/src/test/resources/test-cases/or/datatypeDifferentPaths/valid/case4/query1.rq b/shacl/src/test/resources/test-cases/or/datatypeDifferentPaths/valid/case4/query1.rq new file mode 100644 index 000000000..cb7561f08 --- /dev/null +++ b/shacl/src/test/resources/test-cases/or/datatypeDifferentPaths/valid/case4/query1.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + +ex:validPerson1 a ex:Person ; + ex:longAge "234"^^xsd:long. + +} From bcefae99bd2b61bc94d9b979382b36a3a1096fe6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Avard=20Ottestad?= Date: Sun, 20 Jan 2019 11:09:14 +0100 Subject: [PATCH 48/54] optimize imports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håvard Ottestad --- .../sail/shacl/AST/DatatypePropertyShape.java | 10 ---------- .../sail/shacl/AST/MaxCountPropertyShape.java | 3 +-- .../sail/shacl/AST/MaxLengthPropertyShape.java | 1 - .../sail/shacl/AST/NodeKindPropertyShape.java | 2 -- .../rdf4j/sail/shacl/AST/OrPropertyShape.java | 1 - .../rdf4j/sail/shacl/AST/PathPropertyShape.java | 1 - .../org/eclipse/rdf4j/sail/shacl/ShaclSail.java | 2 -- .../rdf4j/sail/shacl/ShaclSailConnection.java | 14 +++++++------- .../shacl/planNodes/BulkedExternalInnerJoin.java | 1 - .../planNodes/BulkedExternalLeftOuterJoin.java | 1 - .../sail/shacl/planNodes/LanguageInFilter.java | 1 - .../sail/shacl/planNodes/MaxLengthFilter.java | 1 - .../sail/shacl/planNodes/MinLengthFilter.java | 2 -- .../rdf4j/sail/shacl/planNodes/NodeKindFilter.java | 2 -- .../rdf4j/sail/shacl/planNodes/PatternFilter.java | 1 - .../rdf4j/sail/shacl/results/ValidationReport.java | 1 - .../rdf4j/sail/shacl/ReduceNumberOfPlansTest.java | 12 ++++++------ .../java/org/eclipse/rdf4j/sail/shacl/Utils.java | 8 ++++---- .../rdf4j/sail/shacl/ValidationReportTest.java | 2 -- .../eclipse/rdf4j/sail/shacl/VisulizerTest.java | 1 - .../shacl/benchmark/DatatypeBenchmarkEmpty.java | 1 - .../shacl/benchmark/MinCountBenchmarkEmpty.java | 1 - .../MinCountPrefilledVsEmptyBenchmark.java | 1 - 23 files changed, 18 insertions(+), 52 deletions(-) diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/DatatypePropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/DatatypePropertyShape.java index 5931cc649..574fc31c2 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/DatatypePropertyShape.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/DatatypePropertyShape.java @@ -15,21 +15,11 @@ import org.eclipse.rdf4j.repository.Repository; import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; import org.eclipse.rdf4j.sail.shacl.ShaclSailConnection; - import org.eclipse.rdf4j.sail.shacl.SourceConstraintComponent; -import org.eclipse.rdf4j.sail.shacl.planNodes.BufferedSplitter; -import org.eclipse.rdf4j.sail.shacl.planNodes.BufferedTupleFromFilter; -import org.eclipse.rdf4j.sail.shacl.planNodes.BulkedExternalInnerJoin; import org.eclipse.rdf4j.sail.shacl.planNodes.DatatypeFilter; -import org.eclipse.rdf4j.sail.shacl.planNodes.DirectTupleFromFilter; import org.eclipse.rdf4j.sail.shacl.planNodes.EnrichWithShape; -import org.eclipse.rdf4j.sail.shacl.planNodes.InnerJoin; import org.eclipse.rdf4j.sail.shacl.planNodes.LoggingNode; -import org.eclipse.rdf4j.sail.shacl.planNodes.MinLengthFilter; -import org.eclipse.rdf4j.sail.shacl.planNodes.PushBasedLoggingNode; -import org.eclipse.rdf4j.sail.shacl.planNodes.UnionNode; import org.eclipse.rdf4j.sail.shacl.planNodes.PlanNode; -import org.eclipse.rdf4j.sail.shacl.planNodes.Select; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MaxCountPropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MaxCountPropertyShape.java index 9ef46e4c3..53adce25e 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MaxCountPropertyShape.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MaxCountPropertyShape.java @@ -17,7 +17,6 @@ import org.eclipse.rdf4j.repository.Repository; import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; import org.eclipse.rdf4j.sail.shacl.ShaclSailConnection; - import org.eclipse.rdf4j.sail.shacl.SourceConstraintComponent; import org.eclipse.rdf4j.sail.shacl.planNodes.BufferedTupleFromFilter; import org.eclipse.rdf4j.sail.shacl.planNodes.BulkedExternalLeftOuterJoin; @@ -26,9 +25,9 @@ import org.eclipse.rdf4j.sail.shacl.planNodes.GroupByCount; import org.eclipse.rdf4j.sail.shacl.planNodes.LoggingNode; import org.eclipse.rdf4j.sail.shacl.planNodes.MaxCountFilter; -import org.eclipse.rdf4j.sail.shacl.planNodes.UnionNode; import org.eclipse.rdf4j.sail.shacl.planNodes.PlanNode; import org.eclipse.rdf4j.sail.shacl.planNodes.TrimTuple; +import org.eclipse.rdf4j.sail.shacl.planNodes.UnionNode; import org.eclipse.rdf4j.sail.shacl.planNodes.Unique; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MaxLengthPropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MaxLengthPropertyShape.java index d71f4bdad..3730fc263 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MaxLengthPropertyShape.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/MaxLengthPropertyShape.java @@ -20,7 +20,6 @@ import org.eclipse.rdf4j.sail.shacl.planNodes.EnrichWithShape; import org.eclipse.rdf4j.sail.shacl.planNodes.LoggingNode; import org.eclipse.rdf4j.sail.shacl.planNodes.MaxLengthFilter; -import org.eclipse.rdf4j.sail.shacl.planNodes.MinLengthFilter; import org.eclipse.rdf4j.sail.shacl.planNodes.PlanNode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/NodeKindPropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/NodeKindPropertyShape.java index ea629b5a5..2f7e94855 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/NodeKindPropertyShape.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/NodeKindPropertyShape.java @@ -12,7 +12,6 @@ import org.eclipse.rdf4j.model.IRI; import org.eclipse.rdf4j.model.Resource; import org.eclipse.rdf4j.model.Statement; -import org.eclipse.rdf4j.model.impl.SimpleLiteral; import org.eclipse.rdf4j.model.vocabulary.SHACL; import org.eclipse.rdf4j.repository.Repository; import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; @@ -20,7 +19,6 @@ import org.eclipse.rdf4j.sail.shacl.SourceConstraintComponent; import org.eclipse.rdf4j.sail.shacl.planNodes.EnrichWithShape; import org.eclipse.rdf4j.sail.shacl.planNodes.LoggingNode; -import org.eclipse.rdf4j.sail.shacl.planNodes.MinLengthFilter; import org.eclipse.rdf4j.sail.shacl.planNodes.NodeKindFilter; import org.eclipse.rdf4j.sail.shacl.planNodes.PlanNode; import org.slf4j.Logger; diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/OrPropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/OrPropertyShape.java index 4fa2d21ce..713233d71 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/OrPropertyShape.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/OrPropertyShape.java @@ -12,7 +12,6 @@ import org.eclipse.rdf4j.model.Resource; import org.eclipse.rdf4j.model.Statement; import org.eclipse.rdf4j.model.vocabulary.SHACL; -import org.eclipse.rdf4j.query.algebra.In; import org.eclipse.rdf4j.repository.Repository; import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; import org.eclipse.rdf4j.sail.shacl.ShaclSailConnection; diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PathPropertyShape.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PathPropertyShape.java index 03a85b964..f085e4b95 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PathPropertyShape.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/AST/PathPropertyShape.java @@ -15,7 +15,6 @@ import org.eclipse.rdf4j.sail.shacl.planNodes.PlanNode; import org.eclipse.rdf4j.sail.shacl.planNodes.Select; -import java.util.Arrays; import java.util.Collections; import java.util.List; diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSail.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSail.java index 086dbcb94..e97a7508e 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSail.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSail.java @@ -9,8 +9,6 @@ package org.eclipse.rdf4j.sail.shacl; import org.apache.commons.io.IOUtils; -import org.eclipse.rdf4j.model.IRI; -import org.eclipse.rdf4j.model.impl.SimpleValueFactory; import org.eclipse.rdf4j.model.vocabulary.RDF4J; import org.eclipse.rdf4j.repository.Repository; import org.eclipse.rdf4j.repository.sail.SailRepository; diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java index 3ce2f4422..fae7c5c61 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java @@ -8,13 +8,6 @@ package org.eclipse.rdf4j.sail.shacl; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.Stream; - import org.eclipse.rdf4j.IsolationLevel; import org.eclipse.rdf4j.IsolationLevels; import org.eclipse.rdf4j.common.iteration.Iterations; @@ -39,6 +32,13 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + /** * @author Heshan Jayasinghe */ diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/BulkedExternalInnerJoin.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/BulkedExternalInnerJoin.java index b17fab1fe..44bf2d754 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/BulkedExternalInnerJoin.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/BulkedExternalInnerJoin.java @@ -28,7 +28,6 @@ import org.eclipse.rdf4j.sail.NotifyingSailConnection; import org.eclipse.rdf4j.sail.SailException; - import java.util.Arrays; import java.util.LinkedList; import java.util.stream.Stream; diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/BulkedExternalLeftOuterJoin.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/BulkedExternalLeftOuterJoin.java index a76821205..48f076adf 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/BulkedExternalLeftOuterJoin.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/BulkedExternalLeftOuterJoin.java @@ -28,7 +28,6 @@ import org.eclipse.rdf4j.sail.NotifyingSailConnection; import org.eclipse.rdf4j.sail.SailException; - import java.util.Arrays; import java.util.LinkedList; import java.util.stream.Stream; diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/LanguageInFilter.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/LanguageInFilter.java index 19aca23e6..275320835 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/LanguageInFilter.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/LanguageInFilter.java @@ -11,7 +11,6 @@ import org.eclipse.rdf4j.model.Literal; -import org.eclipse.rdf4j.model.Resource; import java.util.Arrays; import java.util.List; diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MaxLengthFilter.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MaxLengthFilter.java index 1d2db2550..ac7ddcee5 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MaxLengthFilter.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MaxLengthFilter.java @@ -10,7 +10,6 @@ package org.eclipse.rdf4j.sail.shacl.planNodes; -import org.eclipse.rdf4j.model.Literal; import org.eclipse.rdf4j.model.Value; /** diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MinLengthFilter.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MinLengthFilter.java index 9f4f491a9..be7bcd6c0 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MinLengthFilter.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/MinLengthFilter.java @@ -9,8 +9,6 @@ package org.eclipse.rdf4j.sail.shacl.planNodes; -import org.eclipse.rdf4j.model.Literal; -import org.eclipse.rdf4j.model.Resource; import org.eclipse.rdf4j.model.Value; /** diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/NodeKindFilter.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/NodeKindFilter.java index 4988828c2..5838b9fd6 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/NodeKindFilter.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/NodeKindFilter.java @@ -13,9 +13,7 @@ import org.eclipse.rdf4j.model.BNode; import org.eclipse.rdf4j.model.IRI; import org.eclipse.rdf4j.model.Literal; -import org.eclipse.rdf4j.model.Resource; import org.eclipse.rdf4j.model.Value; -import org.eclipse.rdf4j.model.vocabulary.SHACL; import org.eclipse.rdf4j.sail.shacl.AST.NodeKindPropertyShape; /** diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/PatternFilter.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/PatternFilter.java index e04e47bdc..257b4aded 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/PatternFilter.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/PatternFilter.java @@ -10,7 +10,6 @@ package org.eclipse.rdf4j.sail.shacl.planNodes; -import org.eclipse.rdf4j.model.Literal; import org.eclipse.rdf4j.model.Value; import java.util.Optional; diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/results/ValidationReport.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/results/ValidationReport.java index 2d5f8dd37..f492ee0ff 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/results/ValidationReport.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/results/ValidationReport.java @@ -10,7 +10,6 @@ import org.eclipse.rdf4j.model.Model; import org.eclipse.rdf4j.model.Resource; -import org.eclipse.rdf4j.model.impl.LinkedHashModelFactory; import org.eclipse.rdf4j.model.impl.SimpleValueFactory; import org.eclipse.rdf4j.model.vocabulary.RDF; import org.eclipse.rdf4j.model.vocabulary.SHACL; diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ReduceNumberOfPlansTest.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ReduceNumberOfPlansTest.java index 856889d80..43e146f0c 100644 --- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ReduceNumberOfPlansTest.java +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ReduceNumberOfPlansTest.java @@ -8,12 +8,6 @@ package org.eclipse.rdf4j.sail.shacl; -import static junit.framework.TestCase.assertEquals; - -import java.io.IOException; -import java.util.List; -import java.util.stream.Collectors; - import org.eclipse.rdf4j.RDF4JException; import org.eclipse.rdf4j.model.IRI; import org.eclipse.rdf4j.model.ValueFactory; @@ -24,6 +18,12 @@ import org.eclipse.rdf4j.sail.shacl.planNodes.PlanNode; import org.junit.Test; +import java.io.IOException; +import java.util.List; +import java.util.stream.Collectors; + +import static junit.framework.TestCase.assertEquals; + /** * @author Håvard Ottestad */ diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/Utils.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/Utils.java index 460701095..b83ad1391 100644 --- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/Utils.java +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/Utils.java @@ -8,10 +8,6 @@ package org.eclipse.rdf4j.sail.shacl; -import java.io.IOException; -import java.io.InputStream; -import java.util.UUID; - import org.eclipse.rdf4j.RDF4JException; import org.eclipse.rdf4j.model.IRI; import org.eclipse.rdf4j.model.Model; @@ -26,6 +22,10 @@ import org.eclipse.rdf4j.sail.SailConnection; import org.eclipse.rdf4j.sail.memory.MemoryStore; +import java.io.IOException; +import java.io.InputStream; +import java.util.UUID; + /** * @author Håvard Ottestad */ diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ValidationReportTest.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ValidationReportTest.java index bbe47a1ed..2514d2379 100644 --- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ValidationReportTest.java +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ValidationReportTest.java @@ -8,7 +8,6 @@ package org.eclipse.rdf4j.sail.shacl; import org.apache.commons.io.IOUtils; -import org.eclipse.rdf4j.common.io.IOUtil; import org.eclipse.rdf4j.model.Model; import org.eclipse.rdf4j.model.util.Models; import org.eclipse.rdf4j.model.vocabulary.RDF; @@ -18,7 +17,6 @@ import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; import org.eclipse.rdf4j.rio.RDFFormat; import org.eclipse.rdf4j.rio.Rio; -import org.eclipse.rdf4j.sail.memory.MemoryStore; import org.junit.Test; import java.io.IOException; diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/VisulizerTest.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/VisulizerTest.java index 3604e9277..d85bfb5a5 100644 --- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/VisulizerTest.java +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/VisulizerTest.java @@ -15,7 +15,6 @@ import org.eclipse.rdf4j.model.vocabulary.RDFS; import org.eclipse.rdf4j.sail.NotifyingSailConnection; import org.eclipse.rdf4j.sail.SailException; -import org.eclipse.rdf4j.sail.memory.MemoryStore; import org.junit.Test; public class VisulizerTest { diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/DatatypeBenchmarkEmpty.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/DatatypeBenchmarkEmpty.java index 1fc38253b..c256fa43a 100644 --- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/DatatypeBenchmarkEmpty.java +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/DatatypeBenchmarkEmpty.java @@ -19,7 +19,6 @@ import org.eclipse.rdf4j.repository.sail.SailRepository; import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; import org.eclipse.rdf4j.sail.memory.MemoryStore; -import org.eclipse.rdf4j.sail.shacl.ShaclSail; import org.eclipse.rdf4j.sail.shacl.Utils; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/MinCountBenchmarkEmpty.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/MinCountBenchmarkEmpty.java index f6e5a4a48..0b6e508ff 100644 --- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/MinCountBenchmarkEmpty.java +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/MinCountBenchmarkEmpty.java @@ -17,7 +17,6 @@ import org.eclipse.rdf4j.repository.sail.SailRepository; import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; import org.eclipse.rdf4j.sail.memory.MemoryStore; -import org.eclipse.rdf4j.sail.shacl.ShaclSail; import org.eclipse.rdf4j.sail.shacl.Utils; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/MinCountPrefilledVsEmptyBenchmark.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/MinCountPrefilledVsEmptyBenchmark.java index 94d1d3477..fa3ced59c 100644 --- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/MinCountPrefilledVsEmptyBenchmark.java +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/MinCountPrefilledVsEmptyBenchmark.java @@ -14,7 +14,6 @@ import org.eclipse.rdf4j.model.vocabulary.RDFS; import org.eclipse.rdf4j.repository.sail.SailRepository; import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; -import org.eclipse.rdf4j.sail.memory.MemoryStore; import org.eclipse.rdf4j.sail.shacl.ShaclSail; import org.eclipse.rdf4j.sail.shacl.Utils; import org.openjdk.jmh.annotations.Benchmark; From 15bd00ceb3807f465d06e48c08fa12cc73b795a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Avard=20Ottestad?= Date: Sun, 20 Jan 2019 14:52:46 +0100 Subject: [PATCH 49/54] eclipse/rdf4j#998 configurations for enabling logging of diagnostic info and better javadoc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håvard Ottestad --- .../eclipse/rdf4j/sail/shacl/ShaclSail.java | 161 ++++++++++++++++-- .../rdf4j/sail/shacl/ShaclSailConnection.java | 20 +-- .../sail/shacl/planNodes/FilterPlanNode.java | 2 +- .../sail/shacl/planNodes/LoggingNode.java | 6 +- .../shacl/planNodes/PushBasedLoggingNode.java | 2 +- .../sail/shacl/RuntimeModifyShapesTest.java | 7 + .../eclipse/rdf4j/sail/shacl/ShaclTest.java | 2 +- .../rdf4j/sail/shacl/VisulizerTest.java | 6 +- shacl/src/test/resources/shaclDatatype.ttl | 1 + 9 files changed, 176 insertions(+), 31 deletions(-) diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSail.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSail.java index e97a7508e..6cd87c539 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSail.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSail.java @@ -21,6 +21,7 @@ import org.eclipse.rdf4j.sail.helpers.NotifyingSailWrapper; import org.eclipse.rdf4j.sail.memory.MemoryStore; import org.eclipse.rdf4j.sail.shacl.AST.NodeShape; +import org.eclipse.rdf4j.sail.shacl.planNodes.LoggingNode; import java.io.File; import java.io.IOException; @@ -32,6 +33,103 @@ *

* The ShaclSail looks for SHACL shape data in a special named graph {@link RDF4J#SHACL_SHAPE_GRAPH}. * + * + *

Working example

+ * + *
+ *import ch.qos.logback.classic.Level;
+ *import ch.qos.logback.classic.Logger;
+ *import org.eclipse.rdf4j.model.Model;
+ *import org.eclipse.rdf4j.model.vocabulary.RDF4J;
+ *import org.eclipse.rdf4j.repository.RepositoryException;
+ *import org.eclipse.rdf4j.repository.sail.SailRepository;
+ *import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection;
+ *import org.eclipse.rdf4j.rio.RDFFormat;
+ *import org.eclipse.rdf4j.rio.Rio;
+ *import org.eclipse.rdf4j.sail.memory.MemoryStore;
+ *import org.eclipse.rdf4j.sail.shacl.ShaclSail;
+ *import org.eclipse.rdf4j.sail.shacl.ShaclSailValidationException;
+ *import org.eclipse.rdf4j.sail.shacl.results.ValidationReport;
+ *import org.slf4j.LoggerFactory;
+ *
+ *import java.io.IOException;
+ *import java.io.StringReader;
+ *
+ *public class ShaclSampleCode {
+ *
+ *	public static void main(String[] args) throws IOException {
+ *
+ *		ShaclSail shaclSail = new ShaclSail(new MemoryStore());
+ *
+ *		//Logger root = (Logger) LoggerFactory.getLogger(ShaclSail.class.getName());
+ *		//root.setLevel(Level.INFO);
+ *
+ *		//shaclSail.setLogValidationPlans(true);
+ *		//shaclSail.setGlobalLogValidationExecution(true);
+ *		//shaclSail.setLogValidationViolations(true);
+ *
+ *		SailRepository sailRepository = new SailRepository(shaclSail);
+ *		sailRepository.init();
+ *
+ *		try (SailRepositoryConnection connection = sailRepository.getConnection()) {
+ *
+ *			connection.begin();
+ *
+ *			StringReader shaclRules = new StringReader(
+ *				String.join("\n", "",
+ *					"@prefix ex: <http://example.com/ns#> .",
+ *					"@prefix sh: <http://www.w3.org/ns/shacl#> .",
+ *					"@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .",
+ *					"@prefix foaf: <http://xmlns.com/foaf/0.1/>.",
+ *
+ *					"ex:PersonShape",
+ *					"	a sh:NodeShape  ;",
+ *					"	sh:targetClass foaf:Person ;",
+ *					"	sh:property ex:PersonShapeProperty .",
+ *
+ *					"ex:PersonShapeProperty ",
+ *					"	sh:path foaf:age ;",
+ *					"	sh:datatype xsd:int ;",
+ *					"	sh:maxCount 1 ;",
+ *					"	sh:minCount 1 ."
+ *				));
+ *
+ *			connection.add(shaclRules, "", RDFFormat.TURTLE, RDF4J.SHACL_SHAPE_GRAPH);
+ *			connection.commit();
+ *
+ *			connection.begin();
+ *
+ *			StringReader invalidSampleData = new StringReader(
+ *				String.join("\n", "",
+ *					"@prefix ex: <http://example.com/ns#> .",
+ *					"@prefix foaf: <http://xmlns.com/foaf/0.1/>.",
+ *					"@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .",
+ *
+ *					"ex:peter a foaf:Person ;",
+ *					"	foaf:age 20, \"30\"^^xsd:int  ."
+ *
+ *				));
+ *
+ *			connection.add(invalidSampleData, "", RDFFormat.TURTLE);
+ *			try {
+ *				connection.commit();
+ *			} catch (RepositoryException exception) {
+ *				Throwable cause = exception.getCause();
+ *				if (cause instanceof ShaclSailValidationException) {
+ *					ValidationReport validationReport = ((ShaclSailValidationException) cause).getValidationReport();
+ *					Model validationReportModel = ((ShaclSailValidationException) cause).validationReportAsModel();
+ *					// use validationReport or validationReportModel to understand validation violations
+ *
+ *					Rio.write(validationReportModel, System.out, RDFFormat.TURTLE);
+ *				}
+ *				throw exception;
+ *			}
+ *		}
+ *	}
+ *}
+ *
+ * + * * @author Heshan Jayasinghe * @author Håvard Ottestad * @see SHACL W3C Recommendation @@ -40,11 +138,8 @@ public class ShaclSail extends NotifyingSailWrapper { private List nodeShapes; - boolean debugPrintPlans = false; - private boolean ignoreNoShapesLoadedException = false; - - ShaclSailConfig config = new ShaclSailConfig(); + final ShaclSailConfig config = new ShaclSailConfig(); private static String SH_OR_UPDATE_QUERY; @@ -61,8 +156,7 @@ public class ShaclSail extends NotifyingSailWrapper { ShaclSail.class.getClassLoader().getResourceAsStream("shacl-sparql-inference/sh_or.rq"), "UTF-8"); SH_OR_NODE_SHAPE_UPDATE_QUERY = IOUtils.toString( - ShaclSail.class.getClassLoader().getResourceAsStream( - "shacl-sparql-inference/sh_or_node_shape.rq"), + ShaclSail.class.getClassLoader().getResourceAsStream("shacl-sparql-inference/sh_or_node_shape.rq"), "UTF-8"); } catch (IOException e) { @@ -140,29 +234,44 @@ public NotifyingSailConnection getConnection() throws SailException { shapesRepo.getConnection()); } + + /** + * Disable the SHACL validation on commit() + */ public void disableValidation() { config.validationEnabled = false; } + /** + * Enabled the SHACL validation on commit() + */ public void enableValidation() { config.validationEnabled = true; } - public boolean isDebugPrintPlans() { - return debugPrintPlans; + public boolean isLogValidationPlans() { + return config.logValidationPlans; } public boolean isIgnoreNoShapesLoadedException() { - return ignoreNoShapesLoadedException; + return config.ignoreNoShapesLoadedException; } + /** + * Check if shapes have been loaded into the shapes graph before other data is added + * @param ignoreNoShapesLoadedException + */ public void setIgnoreNoShapesLoadedException(boolean ignoreNoShapesLoadedException) { - this.ignoreNoShapesLoadedException = ignoreNoShapesLoadedException; + config.ignoreNoShapesLoadedException = ignoreNoShapesLoadedException; } + /** + * Log (INFO) the executed validation plans as GraphViz DOT + * @param logValidationPlans + */ @SuppressWarnings("WeakerAccess") - public void setDebugPrintPlans(boolean debugPrintPlans) { - this.debugPrintPlans = debugPrintPlans; + public void setLogValidationPlans(boolean logValidationPlans) { + config.logValidationPlans = logValidationPlans; } List getNodeShapes() { @@ -182,10 +291,38 @@ private void runInferencingSparqlQueries(SailRepositoryConnection shaclSailConne while (prevSize != currentSize); } + /** + * Log (INFO) every execution step of the SHACL validation + * This is fairly costly and should not be used in production. + * @param loggingEnabled + */ + public void setGlobalLogValidationExecution(boolean loggingEnabled) { + LoggingNode.loggingEnabled = loggingEnabled; + } + + public boolean isGlobalLogValidationExecution() { + return LoggingNode.loggingEnabled; + } + + public boolean isLogValidationViolations() { + return config.logValidationViolations; + } + + /** + * Log (INFO) a list og violations and the triples that caused the violations (BETA) + * @param logValidationViolations + */ + public void setLogValidationViolations(boolean logValidationViolations) { + config.logValidationViolations = logValidationViolations; + } + } class ShaclSailConfig { + boolean logValidationPlans = false; + boolean logValidationViolations = false; + boolean ignoreNoShapesLoadedException = false; boolean validationEnabled = true; } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java index fae7c5c61..3da1daa2a 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java @@ -203,7 +203,7 @@ public void removeStatement(UpdateContext modify, Resource subj, IRI pred, Value @Override public void addStatement(Resource subj, IRI pred, Value obj, Resource... contexts) throws SailException { - if (contexts.length == 1 && contexts[0].equals(RDF4J.SHACL_SHAPE_GRAPH)) { + if (contexts.length == 1 && RDF4J.SHACL_SHAPE_GRAPH.equals(contexts[0])) { shapesConnection.add(subj, pred, obj); isShapeRefreshNeeded = true; } @@ -270,7 +270,7 @@ private List validate() { final List nodeShapes = NodeShape.Factory.getShapes(shapesConnection); for (NodeShape nodeShape : nodeShapes) { - List planNodes = nodeShape.generatePlans(this, nodeShape, sail.debugPrintPlans); + List planNodes = nodeShape.generatePlans(this, nodeShape, sail.config.logValidationPlans); for (PlanNode planNode : planNodes) { try (Stream stream = Iterations.stream(planNode.iterator())) { List collect = stream.collect(Collectors.toList()); @@ -278,14 +278,14 @@ private List validate() { ret.addAll(collect); boolean valid = collect.size() == 0; - if (!valid) { - logger.warn( - "SHACL not valid. The following experimental debug results were produced: \n\tNodeShape: {} \n\t\t{}", - nodeShape.toString(), - String.join("\n\t\t", - collect.stream().map( - a -> a.toString() + " -cause-> " + a.getCause()).collect( - Collectors.toList()))); + if (!valid && sail.config.logValidationViolations) { + logger.info( + "SHACL not valid. The following experimental debug results were produced: \n\tNodeShape: {} \n\t\t{}", + nodeShape.toString(), + collect + .stream() + .map(a -> a.toString() + " -cause-> " + a.getCause()) + .collect(Collectors.joining("\n\t\t"))); } } } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/FilterPlanNode.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/FilterPlanNode.java index 1bcebd81e..41f11e132 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/FilterPlanNode.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/FilterPlanNode.java @@ -90,7 +90,7 @@ private void calculateNext() { } else { if (falseNode != null) { if(LoggingNode.loggingEnabled){ - logger.debug(leadingSpace() + that.getClass().getSimpleName() + ";falseNode: " + " " + temp.toString()); + logger.info(leadingSpace() + that.getClass().getSimpleName() + ";falseNode: " + " " + temp.toString()); } falseNode.push(temp); diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/LoggingNode.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/LoggingNode.java index 3dc14f724..53ee6b934 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/LoggingNode.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/LoggingNode.java @@ -30,7 +30,7 @@ public class LoggingNode implements PlanNode { PlanNode parent; - boolean pullAll = true; + private boolean pullAll = true; public static boolean loggingEnabled = false; @@ -99,7 +99,7 @@ public void close() throws SailException { public boolean hasNext() throws SailException { boolean hasNext = parentIterator.hasNext(); -// logger.debug(leadingSpace()+parent.getClass().getSimpleName()+".hasNext() : "+hasNext); +// logger.info(leadingSpace()+parent.getClass().getSimpleName()+".hasNext() : "+hasNext); return hasNext; } @@ -111,7 +111,7 @@ public Tuple next() throws SailException { assert next != null; - logger.debug(leadingSpace() + parent.getClass().getSimpleName() + ".next(): " + " " + next.toString()); + logger.info(leadingSpace() + parent.getClass().getSimpleName() + ".next(): " + " " + next.toString()); return next; } diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/PushBasedLoggingNode.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/PushBasedLoggingNode.java index d1a086eb0..9426bfa45 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/PushBasedLoggingNode.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/planNodes/PushBasedLoggingNode.java @@ -49,7 +49,7 @@ public IteratorData getIteratorDataType() { @Override public void push(Tuple t) { if(LoggingNode.loggingEnabled){ - logger.debug(leadingSpace() + parent.getClass().getSimpleName() + ".next(): " + " " + t.toString()); + logger.info(leadingSpace() + parent.getClass().getSimpleName() + ".next(): " + " " + t.toString()); } parent.push(t); } diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/RuntimeModifyShapesTest.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/RuntimeModifyShapesTest.java index debb7cdad..b07ff91dc 100644 --- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/RuntimeModifyShapesTest.java +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/RuntimeModifyShapesTest.java @@ -1,3 +1,10 @@ +/******************************************************************************* + * Copyright (c) 2019 Eclipse RDF4J contributors. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ package org.eclipse.rdf4j.sail.shacl; import org.eclipse.rdf4j.model.vocabulary.RDF; diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java index 1183dd68f..8d29282dd 100644 --- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java @@ -139,7 +139,7 @@ private static void runTestCase(String shaclPath, String dataPath, ExpectedResul String shaclFile = shaclPath + "shacl.ttl"; System.out.println(shaclFile); ShaclSail shaclSail = new ShaclSail(new MemoryStore()); - shaclSail.setDebugPrintPlans(true); + shaclSail.setLogValidationPlans(true); SailRepository shaclRepository = new SailRepository(shaclSail); shaclRepository.initialize(); Utils.loadShapeData(shaclRepository, shaclFile); diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/VisulizerTest.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/VisulizerTest.java index d85bfb5a5..806ebd5c4 100644 --- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/VisulizerTest.java +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/VisulizerTest.java @@ -33,7 +33,7 @@ public void datatype() throws Exception { connection.addStatement(bNode, FOAF.AGE, vf.createLiteral(3)); connection.commit(); - shaclSail.setDebugPrintPlans(true); + shaclSail.setLogValidationPlans(true); connection.begin(); BNode bNode2 = vf.createBNode(); @@ -61,7 +61,7 @@ public void maxCount() throws Exception { connection.addStatement(bNode, RDFS.LABEL, vf.createLiteral("")); connection.commit(); - shaclSail.setDebugPrintPlans(true); + shaclSail.setLogValidationPlans(true); connection.begin(); BNode bNode2 = vf.createBNode(); @@ -88,7 +88,7 @@ public void minCount() throws Exception { connection.addStatement(bNode, RDFS.LABEL, vf.createLiteral("")); connection.commit(); - shaclSail.setDebugPrintPlans(true); + shaclSail.setLogValidationPlans(true); connection.begin(); BNode bNode2 = vf.createBNode(); diff --git a/shacl/src/test/resources/shaclDatatype.ttl b/shacl/src/test/resources/shaclDatatype.ttl index af2d61a07..19bb0acb8 100644 --- a/shacl/src/test/resources/shaclDatatype.ttl +++ b/shacl/src/test/resources/shaclDatatype.ttl @@ -5,6 +5,7 @@ @prefix rdfs: . @prefix sh: . @prefix xsd: . +@prefix foaf: . ex:PersonShape a sh:NodeShape ; From ecdc07aaf9021a3084e0bbc6a771bcb5f728134c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Avard=20Ottestad?= Date: Mon, 21 Jan 2019 20:56:10 +0100 Subject: [PATCH 50/54] eclipse/rdf4j#998 list supported shacl predicates, with test to make sure the list is kept up-to-date MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håvard Ottestad --- .../eclipse/rdf4j/sail/shacl/ShaclSail.java | 26 ++++++++++ .../eclipse/rdf4j/sail/shacl/ShaclTest.java | 48 +++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSail.java b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSail.java index 6cd87c539..345e86331 100644 --- a/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSail.java +++ b/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSail.java @@ -9,7 +9,9 @@ package org.eclipse.rdf4j.sail.shacl; import org.apache.commons.io.IOUtils; +import org.eclipse.rdf4j.model.IRI; import org.eclipse.rdf4j.model.vocabulary.RDF4J; +import org.eclipse.rdf4j.model.vocabulary.SHACL; import org.eclipse.rdf4j.repository.Repository; import org.eclipse.rdf4j.repository.sail.SailRepository; import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; @@ -26,6 +28,8 @@ import java.io.File; import java.io.IOException; import java.nio.file.Files; +import java.util.Arrays; +import java.util.Collections; import java.util.List; /** @@ -192,6 +196,28 @@ public ShaclSail() { super(); } + /** + * Lists the predicates that have been implemented in the ShaclSail. All of these, and all combinations, should work, please report any bugs. + * @return List of IRIs (SHACL predicates) + */ + public static List getSupportedShaclPredicates() { + return Arrays.asList( + SHACL.TARGET_CLASS, + SHACL.PATH, + SHACL.PROPERTY, + SHACL.OR, + SHACL.MIN_COUNT, + SHACL.MAX_COUNT, + SHACL.MIN_LENGTH, + SHACL.MAX_LENGTH, + SHACL.PATTERN, + SHACL.FLAGS, + SHACL.NODE_KIND_PROP, + SHACL.LANGUAGE_IN, + SHACL.DATATYPE + ); + } + @Override public void initialize() throws SailException { super.initialize(); diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java index 8d29282dd..9d32ca1b3 100644 --- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java @@ -10,7 +10,9 @@ import org.eclipse.rdf4j.IsolationLevels; import org.eclipse.rdf4j.common.io.IOUtil; +import org.eclipse.rdf4j.model.IRI; import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.vocabulary.SHACL; import org.eclipse.rdf4j.repository.RepositoryException; import org.eclipse.rdf4j.repository.sail.SailRepository; import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; @@ -18,6 +20,8 @@ import org.eclipse.rdf4j.rio.Rio; import org.eclipse.rdf4j.sail.memory.MemoryStore; import org.eclipse.rdf4j.sail.shacl.planNodes.LoggingNode; +import org.junit.AfterClass; +import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @@ -27,9 +31,13 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.HashSet; import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; import static junit.framework.TestCase.assertTrue; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; /** @@ -78,6 +86,16 @@ public static Collection data() { return getTestsToRun(); } + private static HashSet staticShaclPredicates = new HashSet<>(ShaclSail.getSupportedShaclPredicates()); + + + @AfterClass + public static void afterClass(){ + + + assertTrue("No test uses the following predicate that the ShaclSail announces as supported: "+Arrays.toString(staticShaclPredicates.toArray()), staticShaclPredicates.isEmpty()); + } + @Test public void test() throws Exception { runTestCase(testCasePath, path, expectedResult); @@ -88,6 +106,36 @@ public void testSingleTransaction() throws Exception { runTestCaseSingleTransaction(testCasePath, path, expectedResult); } + @Test + public void testShaclSailSupportedPredicatesDocumentation() throws IOException { + + HashSet shaclPredicates = new HashSet<>(ShaclSail.getSupportedShaclPredicates()); + + Model parse = getShacl(); + + + Set predicatesInUseInTest = parse.predicates().stream().filter(p -> p.getNamespace().equals(SHACL.NAMESPACE)).collect(Collectors.toSet()); + + for (IRI predicate : predicatesInUseInTest) { + assertTrue("Predicate used in test but not listed in ShaclSail: "+predicate, shaclPredicates.contains(predicate)); + staticShaclPredicates.remove(predicate); + } + + + } + + private Model getShacl() throws IOException { + String shaclPath = testCasePath; + + if (!shaclPath.endsWith("/")) { + shaclPath = shaclPath + "/"; + } + + String shaclFile = shaclPath + "shacl.ttl"; + + return Rio.parse(ShaclTest.class.getClassLoader().getResourceAsStream(shaclFile), "", RDFFormat.TURTLE); + } + private static List findTestCases(String testCase, String baseCase) { List ret = new ArrayList<>(); From e16a97ab699488b15eba802991097ca0e849864f Mon Sep 17 00:00:00 2001 From: Bart Hanssens Date: Tue, 22 Jan 2019 09:42:40 +0000 Subject: [PATCH 51/54] Upgraded assertj-core Signed-off-by: Bart Hanssens --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 4a61e85a5..d0885235c 100644 --- a/pom.xml +++ b/pom.xml @@ -486,7 +486,7 @@ org.assertj assertj-core - 3.9.1 + 3.11.1 test From 602b55299a02451441034d9a2510c9df2a3301c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Avard=20Ottestad?= Date: Tue, 22 Jan 2019 13:31:07 +0100 Subject: [PATCH 52/54] eclipse/rdf4j#998 simplify tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håvard Ottestad --- .../rdf4j/sail/shacl/AbstractShaclTest.java | 263 ++++++++++++++++++ ...lSupportedPredicatesDocumentationTest.java | 78 ++++++ .../eclipse/rdf4j/sail/shacl/ShaclTest.java | 251 +---------------- 3 files changed, 344 insertions(+), 248 deletions(-) create mode 100644 shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/AbstractShaclTest.java create mode 100644 shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclSailSupportedPredicatesDocumentationTest.java diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/AbstractShaclTest.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/AbstractShaclTest.java new file mode 100644 index 000000000..ec8330c35 --- /dev/null +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/AbstractShaclTest.java @@ -0,0 +1,263 @@ +/******************************************************************************* + * Copyright (c) 2018 Eclipse RDF4J contributors. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ + +package org.eclipse.rdf4j.sail.shacl; + +import org.eclipse.rdf4j.IsolationLevels; +import org.eclipse.rdf4j.common.io.IOUtil; +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; +import org.eclipse.rdf4j.rio.RDFFormat; +import org.eclipse.rdf4j.rio.Rio; +import org.eclipse.rdf4j.sail.memory.MemoryStore; +import org.eclipse.rdf4j.sail.shacl.planNodes.LoggingNode; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +import static junit.framework.TestCase.assertTrue; +import static org.junit.Assert.assertFalse; + +/** + * @author Håvard Ottestad + */ +@RunWith(Parameterized.class) +abstract public class AbstractShaclTest { + + private static final List testCasePaths = Arrays.asList( + "test-cases/datatype/simple", + "test-cases/minLength/simple", + "test-cases/maxLength/simple", + "test-cases/pattern/simple", + "test-cases/languageIn/simple", + "test-cases/nodeKind/simple", + "test-cases/minCount/simple", + "test-cases/maxCount/simple", + "test-cases/or/inheritance", + "test-cases/or/inheritance-deep", + "test-cases/or/inheritance-deep-minCountMaxCount", + "test-cases/or/inheritanceNodeShape", + "test-cases/or/datatype", + "test-cases/or/minCountMaxCount", + "test-cases/or/maxCount", + "test-cases/or/minCount", + "test-cases/or/nodeKindMinLength", + "test-cases/or/implicitAnd", + "test-cases/or/datatypeDifferentPaths" + + ); + + final String testCasePath; + final String path; + final ExpectedResult expectedResult; + + public AbstractShaclTest(String testCasePath, String path, ExpectedResult expectedResult) { + this.testCasePath = testCasePath; + this.path = path; + this.expectedResult = expectedResult; + LoggingNode.loggingEnabled = true; + } + + @Parameterized.Parameters(name = "{2} - {1}") + public static Collection data() { + + return getTestsToRun(); + } + + + private static List findTestCases(String testCase, String baseCase) { + + List ret = new ArrayList<>(); + + for (int i = 0; i < 1000; i++) { + String path = testCase + "/" + baseCase + "/case" + i; + InputStream resourceAsStream = AbstractShaclTest.class.getClassLoader().getResourceAsStream(path); + if (resourceAsStream != null) { + ret.add(path); + try { + resourceAsStream.close(); + } + catch (IOException e) { + throw new RuntimeException(e); + } + } + } + + return ret; + + } + + private static Collection getTestsToRun() { + List ret = new ArrayList<>(); + + for (String testCasePath : testCasePaths) { + for (ExpectedResult baseCase : ExpectedResult.values()) { + findTestCases(testCasePath, baseCase.name()).forEach(path -> { + Object[] temp = { testCasePath, path, baseCase }; + ret.add(temp); + + }); + } + } + + return ret; + } + + static void runTestCase(String shaclPath, String dataPath, ExpectedResult expectedResult) throws Exception { + + if (!dataPath.endsWith("/")) { + dataPath = dataPath + "/"; + } + + if (!shaclPath.endsWith("/")) { + shaclPath = shaclPath + "/"; + } + + String shaclFile = shaclPath + "shacl.ttl"; + System.out.println(shaclFile); + ShaclSail shaclSail = new ShaclSail(new MemoryStore()); + shaclSail.setLogValidationPlans(true); + SailRepository shaclRepository = new SailRepository(shaclSail); + shaclRepository.initialize(); + Utils.loadShapeData(shaclRepository, shaclFile); + + boolean exception = false; + boolean ran = false; + + for (int j = 0; j < 100; j++) { + + String name = dataPath + "query" + j + ".rq"; + try (InputStream resourceAsStream = AbstractShaclTest.class.getClassLoader().getResourceAsStream(name)) { + if (resourceAsStream == null) { + continue; + } + + ran = true; + System.out.println(name); + + try (SailRepositoryConnection connection = shaclRepository.getConnection()) { + connection.begin(IsolationLevels.SNAPSHOT); + String query = IOUtil.readString(resourceAsStream); + connection.prepareUpdate(query).execute(); + connection.commit(); + } catch (RepositoryException sailException) { + exception = true; + System.out.println(sailException.getMessage()); + + System.out.println("\n############################################"); + System.out.println("\tValidation Report\n"); + ShaclSailValidationException cause = (ShaclSailValidationException) sailException.getCause(); + Model validationReport = cause.validationReportAsModel(); + Rio.write(validationReport, System.out, RDFFormat.TURTLE); + System.out.println("\n############################################"); + } + } catch (IOException e) { + e.printStackTrace(); + } + + } + + shaclSail.shutDown(); + + if (ran) { + if (expectedResult == ExpectedResult.valid) { + assertFalse("Expected transaction to succeed", exception); + } else { + assertTrue("Expected transaction to fail", exception); + } + } + + } + + static void runTestCaseSingleTransaction(String shaclPath, String dataPath, ExpectedResult expectedResult) + throws Exception + { + + if (!dataPath.endsWith("/")) { + dataPath = dataPath + "/"; + } + + if (!shaclPath.endsWith("/")) { + shaclPath = shaclPath + "/"; + } + + ShaclSail shaclSail = new ShaclSail(new MemoryStore()); + SailRepository shaclRepository = new SailRepository(shaclSail); + shaclRepository.initialize(); + Utils.loadShapeData(shaclRepository, shaclPath + "shacl.ttl"); + + boolean exception = false; + boolean ran = false; + + try (SailRepositoryConnection shaclSailConnection = shaclRepository.getConnection()) { + shaclSailConnection.begin(IsolationLevels.SNAPSHOT); + + for (int j = 0; j < 100; j++) { + + String name = dataPath + "query" + j + ".rq"; + InputStream resourceAsStream = AbstractShaclTest.class.getClassLoader().getResourceAsStream(name); + if (resourceAsStream == null) { + continue; + } + + ran = true; + System.out.println(name); + + try { + String query = IOUtil.readString(resourceAsStream); + shaclSailConnection.prepareUpdate(query).execute(); + + } catch (IOException e) { + e.printStackTrace(); + } + } + + try { + shaclSailConnection.commit(); + + } catch (RepositoryException sailException) { + exception = true; + System.out.println(sailException.getMessage()); + } + } + if (ran) { + if (expectedResult == ExpectedResult.valid) { + assertFalse(exception); + } + else { + assertTrue(exception); + } + } + + } + + String getShaclPath() { + String shaclPath = testCasePath; + + if (!shaclPath.endsWith("/")) { + shaclPath = shaclPath + "/"; + } + + return shaclPath + "shacl.ttl"; + } + + enum ExpectedResult { + valid, + invalid + } + +} diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclSailSupportedPredicatesDocumentationTest.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclSailSupportedPredicatesDocumentationTest.java new file mode 100644 index 000000000..8da04f279 --- /dev/null +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclSailSupportedPredicatesDocumentationTest.java @@ -0,0 +1,78 @@ +/******************************************************************************* + * Copyright (c) 2018 Eclipse RDF4J contributors. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + *******************************************************************************/ + +package org.eclipse.rdf4j.sail.shacl; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.vocabulary.SHACL; +import org.eclipse.rdf4j.rio.RDFFormat; +import org.eclipse.rdf4j.rio.Rio; +import org.junit.AfterClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.io.IOException; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Collectors; + +import static junit.framework.TestCase.assertTrue; + +/** + * @author Håvard Ottestad + */ +@RunWith(Parameterized.class) +public class ShaclSailSupportedPredicatesDocumentationTest extends AbstractShaclTest { + + + private static HashSet staticShaclPredicates = new HashSet<>(ShaclSail.getSupportedShaclPredicates()); + + public ShaclSailSupportedPredicatesDocumentationTest(String testCasePath, String path, ExpectedResult expectedResult) { + super(testCasePath, path, expectedResult); + } + + + @AfterClass + public static void afterClass() { + + assertTrue("No test uses the following predicate that the ShaclSail announces as supported: " + Arrays.toString(staticShaclPredicates.toArray()), staticShaclPredicates.isEmpty()); + } + + + @Test + public void testShaclSailSupportedPredicatesDocumentation() throws IOException { + + HashSet shaclPredicates = new HashSet<>(ShaclSail.getSupportedShaclPredicates()); + + Model parse = getShacl(); + + + Set predicatesInUseInTest = parse.predicates().stream().filter(p -> p.getNamespace().equals(SHACL.NAMESPACE)).collect(Collectors.toSet()); + + for (IRI predicate : predicatesInUseInTest) { + assertTrue("Predicate used in test but not listed in ShaclSail: " + predicate, shaclPredicates.contains(predicate)); + staticShaclPredicates.remove(predicate); + } + + + } + + + private Model getShacl() throws IOException { + String shaclFile = getShaclPath(); + + return Rio.parse(ShaclSailSupportedPredicatesDocumentationTest.class.getClassLoader().getResourceAsStream(shaclFile), "", RDFFormat.TURTLE); + } + + + + +} diff --git a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java index 9d32ca1b3..7d1d8e59e 100644 --- a/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java +++ b/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShaclTest.java @@ -44,57 +44,13 @@ * @author Håvard Ottestad */ @RunWith(Parameterized.class) -public class ShaclTest { +public class ShaclTest extends AbstractShaclTest{ - private static final List testCasePaths = Arrays.asList( - "test-cases/datatype/simple", - "test-cases/minLength/simple", - "test-cases/maxLength/simple", - "test-cases/pattern/simple", - "test-cases/languageIn/simple", - "test-cases/nodeKind/simple", - "test-cases/minCount/simple", - "test-cases/maxCount/simple", - "test-cases/or/inheritance", - "test-cases/or/inheritance-deep", - "test-cases/or/inheritance-deep-minCountMaxCount", - "test-cases/or/inheritanceNodeShape", - "test-cases/or/datatype", - "test-cases/or/minCountMaxCount", - "test-cases/or/maxCount", - "test-cases/or/minCount", - "test-cases/or/nodeKindMinLength", - "test-cases/or/implicitAnd", - "test-cases/or/datatypeDifferentPaths" - ); - - private final String testCasePath; - private final String path; - private final ExpectedResult expectedResult; - - public ShaclTest(String testCasePath, String path, ExpectedResult expectedResult) { - this.testCasePath = testCasePath; - this.path = path; - this.expectedResult = expectedResult; - LoggingNode.loggingEnabled = true; - } - - @Parameterized.Parameters(name = "{2} - {1}") - public static Collection data() { - - return getTestsToRun(); + public ShaclTest(String testCasePath, String path, AbstractShaclTest.ExpectedResult expectedResult) { + super(testCasePath, path, expectedResult); } - private static HashSet staticShaclPredicates = new HashSet<>(ShaclSail.getSupportedShaclPredicates()); - - - @AfterClass - public static void afterClass(){ - - - assertTrue("No test uses the following predicate that the ShaclSail announces as supported: "+Arrays.toString(staticShaclPredicates.toArray()), staticShaclPredicates.isEmpty()); - } @Test public void test() throws Exception { @@ -106,205 +62,4 @@ public void testSingleTransaction() throws Exception { runTestCaseSingleTransaction(testCasePath, path, expectedResult); } - @Test - public void testShaclSailSupportedPredicatesDocumentation() throws IOException { - - HashSet shaclPredicates = new HashSet<>(ShaclSail.getSupportedShaclPredicates()); - - Model parse = getShacl(); - - - Set predicatesInUseInTest = parse.predicates().stream().filter(p -> p.getNamespace().equals(SHACL.NAMESPACE)).collect(Collectors.toSet()); - - for (IRI predicate : predicatesInUseInTest) { - assertTrue("Predicate used in test but not listed in ShaclSail: "+predicate, shaclPredicates.contains(predicate)); - staticShaclPredicates.remove(predicate); - } - - - } - - private Model getShacl() throws IOException { - String shaclPath = testCasePath; - - if (!shaclPath.endsWith("/")) { - shaclPath = shaclPath + "/"; - } - - String shaclFile = shaclPath + "shacl.ttl"; - - return Rio.parse(ShaclTest.class.getClassLoader().getResourceAsStream(shaclFile), "", RDFFormat.TURTLE); - } - - private static List findTestCases(String testCase, String baseCase) { - - List ret = new ArrayList<>(); - - for (int i = 0; i < 1000; i++) { - String path = testCase + "/" + baseCase + "/case" + i; - InputStream resourceAsStream = ShaclTest.class.getClassLoader().getResourceAsStream(path); - if (resourceAsStream != null) { - ret.add(path); - try { - resourceAsStream.close(); - } - catch (IOException e) { - throw new RuntimeException(e); - } - } - } - - return ret; - - } - - private static Collection getTestsToRun() { - List ret = new ArrayList<>(); - - for (String testCasePath : testCasePaths) { - for (ExpectedResult baseCase : ExpectedResult.values()) { - findTestCases(testCasePath, baseCase.name()).forEach(path -> { - Object[] temp = { testCasePath, path, baseCase }; - ret.add(temp); - - }); - } - } - - return ret; - } - - private static void runTestCase(String shaclPath, String dataPath, ExpectedResult expectedResult) throws Exception { - - if (!dataPath.endsWith("/")) { - dataPath = dataPath + "/"; - } - - if (!shaclPath.endsWith("/")) { - shaclPath = shaclPath + "/"; - } - - String shaclFile = shaclPath + "shacl.ttl"; - System.out.println(shaclFile); - ShaclSail shaclSail = new ShaclSail(new MemoryStore()); - shaclSail.setLogValidationPlans(true); - SailRepository shaclRepository = new SailRepository(shaclSail); - shaclRepository.initialize(); - Utils.loadShapeData(shaclRepository, shaclFile); - - boolean exception = false; - boolean ran = false; - - for (int j = 0; j < 100; j++) { - - String name = dataPath + "query" + j + ".rq"; - try (InputStream resourceAsStream = ShaclTest.class.getClassLoader().getResourceAsStream(name)) { - if (resourceAsStream == null) { - continue; - } - - ran = true; - System.out.println(name); - - try (SailRepositoryConnection connection = shaclRepository.getConnection()) { - connection.begin(IsolationLevels.SNAPSHOT); - String query = IOUtil.readString(resourceAsStream); - connection.prepareUpdate(query).execute(); - connection.commit(); - } catch (RepositoryException sailException) { - exception = true; - System.out.println(sailException.getMessage()); - - System.out.println("\n############################################"); - System.out.println("\tValidation Report\n"); - ShaclSailValidationException cause = (ShaclSailValidationException) sailException.getCause(); - Model validationReport = cause.validationReportAsModel(); - Rio.write(validationReport, System.out, RDFFormat.TURTLE); - System.out.println("\n############################################"); - } - } catch (IOException e) { - e.printStackTrace(); - } - - } - - shaclSail.shutDown(); - - if (ran) { - if (expectedResult == ExpectedResult.valid) { - assertFalse("Expected transaction to succeed", exception); - } else { - assertTrue("Expected transaction to fail", exception); - } - } - - } - - private static void runTestCaseSingleTransaction(String shaclPath, String dataPath, ExpectedResult expectedResult) - throws Exception - { - - if (!dataPath.endsWith("/")) { - dataPath = dataPath + "/"; - } - - if (!shaclPath.endsWith("/")) { - shaclPath = shaclPath + "/"; - } - - ShaclSail shaclSail = new ShaclSail(new MemoryStore()); - SailRepository shaclRepository = new SailRepository(shaclSail); - shaclRepository.initialize(); - Utils.loadShapeData(shaclRepository, shaclPath + "shacl.ttl"); - - boolean exception = false; - boolean ran = false; - - try (SailRepositoryConnection shaclSailConnection = shaclRepository.getConnection()) { - shaclSailConnection.begin(IsolationLevels.SNAPSHOT); - - for (int j = 0; j < 100; j++) { - - String name = dataPath + "query" + j + ".rq"; - InputStream resourceAsStream = ShaclTest.class.getClassLoader().getResourceAsStream(name); - if (resourceAsStream == null) { - continue; - } - - ran = true; - System.out.println(name); - - try { - String query = IOUtil.readString(resourceAsStream); - shaclSailConnection.prepareUpdate(query).execute(); - - } catch (IOException e) { - e.printStackTrace(); - } - } - - try { - shaclSailConnection.commit(); - - } catch (RepositoryException sailException) { - exception = true; - System.out.println(sailException.getMessage()); - } - } - if (ran) { - if (expectedResult == ExpectedResult.valid) { - assertFalse(exception); - } - else { - assertTrue(exception); - } - } - - } - - enum ExpectedResult { - valid, - invalid - } - } From eb9203210a916dbee4633fbe0521f52d046207f3 Mon Sep 17 00:00:00 2001 From: Bart Hanssens Date: Wed, 23 Jan 2019 13:10:29 +0100 Subject: [PATCH 53/54] Use diamond inference Signed-off-by:Bart Hanssens --- .../elasticsearch/ElasticsearchIndexTest.java | 6 +-- .../datastore/DataStorePerfTest.java | 2 +- .../elasticsearch/ElasticsearchDocument.java | 2 +- .../elasticsearch/ElasticsearchIndex.java | 4 +- .../algebra/evaluation/QueryBindingSet.java | 2 +- .../TupleFunctionFederatedService.java | 14 +++--- .../impl/ConjunctiveConstraintSplitter.java | 4 +- .../evaluation/impl/ConstantOptimizer.java | 4 +- .../evaluation/impl/QueryJoinOptimizer.java | 38 +++++++-------- .../evaluation/impl/QueryModelNormalizer.java | 2 +- .../impl/SameTermFilterOptimizer.java | 2 +- .../impl/StrictEvaluationStrategy.java | 44 +++++++++--------- .../iterator/BottomUpJoinIterator.java | 6 +-- .../iterator/DescribeIteration.java | 8 ++-- .../evaluation/iterator/GroupIterator.java | 6 +-- .../iterator/HashJoinIteration.java | 10 ++-- .../evaluation/iterator/JoinIterator.java | 2 +- .../evaluation/iterator/LeftJoinIterator.java | 2 +- .../evaluation/iterator/OrderIterator.java | 2 +- .../evaluation/iterator/PathIteration.java | 8 ++-- .../iterator/SPARQLMinusIteration.java | 4 +- .../iterator/ZeroLengthPathIteration.java | 2 +- .../evaluation/util/OrderComparator.java | 4 +- .../evaluation/util/QueryOptimizerList.java | 6 +-- .../evaluation/impl/EmptyTripleSource.java | 2 +- .../evaluation/iterator/JoinIteratorTest.java | 4 +- .../iterator/OrderIteratorTest.java | 2 +- .../iterator/ZeroLengthPathIterationTest.java | 2 +- .../util/LiteralComparatorTest.java | 2 +- .../AbstractFederationConnection.java | 14 +++--- .../rdf4j/sail/federation/Federation.java | 4 +- .../rdf4j/sail/federation/PrefixHashSet.java | 4 +- .../algebra/AbstractNaryOperator.java | 6 +-- .../algebra/AbstractNaryTupleOperator.java | 4 +- .../federation/config/FederationConfig.java | 4 +- .../evaluation/FederationStrategy.java | 4 +- .../evaluation/ParallelJoinCursor.java | 2 +- .../evaluation/ParallelLeftJoinCursor.java | 6 +-- .../optimizers/FederationJoinOptimizer.java | 20 ++++---- .../optimizers/PrepareOwnedTupleExpr.java | 12 ++--- .../optimizers/QueryMultiJoinOptimizer.java | 24 +++++----- .../sail/federation/FederationQueryTest.java | 4 +- .../geosparql/DefaultSpatialAlgebra.java | 6 +-- .../fc/AbstractForwardChainingInferencer.java | 2 +- .../fc/CustomGraphQueryInferencer.java | 12 ++--- .../fc/DedupingInferencerConnection.java | 2 +- .../fc/DirectTypeHierarchyInferencer.java | 6 +-- .../fc/SchemaCachingRDFSInferencer.java | 2 +- .../sail/lucene/AbstractLuceneIndex.java | 2 +- .../sail/lucene/AbstractSearchIndex.java | 26 +++++------ .../sail/lucene/DistanceQuerySpecBuilder.java | 2 +- .../lucene/GeoRelationQuerySpecBuilder.java | 2 +- .../eclipse/rdf4j/sail/lucene/LuceneSail.java | 6 +-- .../rdf4j/sail/lucene/LuceneSailBuffer.java | 6 +-- .../sail/lucene/LuceneSailConnection.java | 10 ++-- .../rdf4j/sail/lucene/PropertyCache.java | 4 +- .../rdf4j/sail/lucene/QuerySpecBuilder.java | 14 +++--- .../rdf4j/sail/lucene/util/MapOfListMaps.java | 6 +-- .../sail/lucene/QuerySpecBuilderTest.java | 2 +- .../rdf4j/sail/lucene/LuceneDocument.java | 2 +- .../rdf4j/sail/lucene/LuceneIndex.java | 4 +- .../lucene/AbstractGenericLuceneTest.java | 10 ++-- .../rdf4j/sail/lucene/LuceneIndexTest.java | 6 +-- .../sail/memory/MemEvaluationStatistics.java | 2 +- .../rdf4j/sail/memory/MemNamespaceStore.java | 2 +- .../rdf4j/sail/memory/MemorySailStore.java | 30 ++++++------ .../sail/memory/model/MemValueFactory.java | 8 ++-- .../sail/memory/model/WeakObjectRegistry.java | 4 +- .../rdf4j/sail/nativerdf/ConcurrentCache.java | 2 +- .../rdf4j/sail/nativerdf/NamespaceStore.java | 2 +- .../rdf4j/sail/nativerdf/NativeSailStore.java | 22 ++++----- .../rdf4j/sail/nativerdf/SailSourceModel.java | 4 +- .../rdf4j/sail/nativerdf/TripleStore.java | 10 ++-- .../rdf4j/sail/nativerdf/ValueStore.java | 8 ++-- .../rdf4j/sail/nativerdf/btree/BTree.java | 2 +- .../rdf4j/sail/nativerdf/btree/Node.java | 2 +- .../sail/nativerdf/btree/RangeIterator.java | 4 +- .../repository/dataset/DatasetRepository.java | 2 +- .../sail/SailRepositoryConnection.java | 2 +- .../rdf4j/repository/sail/SailTupleQuery.java | 2 +- .../sail/helpers/SailUpdateExecutor.java | 2 +- .../common/concurrent/locks/LockManager.java | 6 +-- .../sail/helpers/AbstractNotifyingSail.java | 2 +- .../rdf4j/sail/helpers/AbstractSail.java | 6 +-- .../sail/helpers/AbstractSailConnection.java | 14 +++--- .../helpers/NotifyingSailConnectionBase.java | 2 +- .../eclipse/rdf4j/sail/base/Changeset.java | 16 +++---- .../rdf4j/sail/base/SailDatasetImpl.java | 12 ++--- .../rdf4j/sail/base/SailSourceBranch.java | 6 +-- .../rdf4j/sail/base/SailSourceConnection.java | 4 +- .../rdf4j/sail/base/UnionSailDataset.java | 2 +- .../rdf4j/sail/SailConnectionTupleQuery.java | 2 +- .../spin/SpinMagicPropertyInterpreter.java | 12 ++--- .../rdf4j/sail/spin/SpinSailConnection.java | 28 +++++------ .../rdf4j/spin/function/spif/CanInvoke.java | 6 +-- .../rdf4j/sail/solr/SolrBulkUpdater.java | 4 +- .../eclipse/rdf4j/sail/solr/SolrIndex.java | 4 +- .../rdf4j/sail/solr/SolrSearchDocument.java | 2 +- .../org/eclipse/rdf4j/spin/SpinParser.java | 46 +++++++++---------- .../org/eclipse/rdf4j/spin/SpinRenderer.java | 10 ++-- .../java/org/eclipse/rdf4j/spin/Template.java | 2 +- .../spin/function/SelectTupleFunction.java | 4 +- .../rdf4j/spin/function/SpinFunction.java | 2 +- .../spin/function/SpinTupleFunction.java | 4 +- .../rdf4j/spin/function/SpinxFunction.java | 2 +- .../rdf4j/spin/function/spif/BuildString.java | 2 +- .../rdf4j/spin/function/spif/BuildURI.java | 2 +- .../rdf4j/spin/function/spif/ForEach.java | 2 +- .../rdf4j/spin/function/spif/ParseDate.java | 2 +- .../model/evaluation/ModelTripleSource.java | 2 +- .../eclipse/rdf4j/spin/SpinParserTest.java | 2 +- .../eclipse/rdf4j/spin/SpinRendererTest.java | 2 +- 112 files changed, 379 insertions(+), 379 deletions(-) diff --git a/compliance/elasticsearch/src/test/java/org/eclipse/rdf4j/sail/elasticsearch/ElasticsearchIndexTest.java b/compliance/elasticsearch/src/test/java/org/eclipse/rdf4j/sail/elasticsearch/ElasticsearchIndexTest.java index 448130afb..fa06cbd39 100644 --- a/compliance/elasticsearch/src/test/java/org/eclipse/rdf4j/sail/elasticsearch/ElasticsearchIndexTest.java +++ b/compliance/elasticsearch/src/test/java/org/eclipse/rdf4j/sail/elasticsearch/ElasticsearchIndexTest.java @@ -259,8 +259,8 @@ public void testAddMultiple() throws Exception { // add a statement to an index - HashSet added = new HashSet(); - HashSet removed = new HashSet(); + HashSet added = new HashSet<>(); + HashSet removed = new HashSet<>(); added.add(statement11); added.add(statement12); added.add(statement21); @@ -287,7 +287,7 @@ public void testAddMultiple() assertStatement(statement22, document); // check if the text field stores all added string values - Set texts = new HashSet(); + Set texts = new HashSet<>(); texts.add("cats"); texts.add("dogs"); // FIXME diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/datastore/DataStorePerfTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/datastore/DataStorePerfTest.java index 1c9d3c28a..0a53bcefe 100644 --- a/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/datastore/DataStorePerfTest.java +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/sail/nativerdf/datastore/DataStorePerfTest.java @@ -33,7 +33,7 @@ public static void main(String[] args) System.out.println("Starting test..."); - List timeDataList = new ArrayList(); + List timeDataList = new ArrayList<>(); for (int stringCount = 1000000; stringCount <= 3000000; stringCount += 1000000) { timeDataList.add(runPerformanceTest(stringCount)); diff --git a/elasticsearch/src/main/java/org/eclipse/rdf4j/sail/elasticsearch/ElasticsearchDocument.java b/elasticsearch/src/main/java/org/eclipse/rdf4j/sail/elasticsearch/ElasticsearchDocument.java index dfbc5697d..5d293eea2 100644 --- a/elasticsearch/src/main/java/org/eclipse/rdf4j/sail/elasticsearch/ElasticsearchDocument.java +++ b/elasticsearch/src/main/java/org/eclipse/rdf4j/sail/elasticsearch/ElasticsearchDocument.java @@ -197,7 +197,7 @@ private static void addField(String name, String value, Map docu private static List makeModifiable(List l) { List modList; if (!(l instanceof ArrayList)) { - modList = new ArrayList(l.size() + 1); + modList = new ArrayList<>(l.size() + 1); modList.addAll(l); } else { diff --git a/elasticsearch/src/main/java/org/eclipse/rdf4j/sail/elasticsearch/ElasticsearchIndex.java b/elasticsearch/src/main/java/org/eclipse/rdf4j/sail/elasticsearch/ElasticsearchIndex.java index dd8e74d8c..5376a5b92 100644 --- a/elasticsearch/src/main/java/org/eclipse/rdf4j/sail/elasticsearch/ElasticsearchIndex.java +++ b/elasticsearch/src/main/java/org/eclipse/rdf4j/sail/elasticsearch/ElasticsearchIndex.java @@ -409,7 +409,7 @@ protected SearchDocument newDocument(String id, String resourceId, String contex protected SearchDocument copyDocument(SearchDocument doc) { ElasticsearchDocument esDoc = (ElasticsearchDocument)doc; Map source = esDoc.getSource(); - Map newDocument = new HashMap(source); + Map newDocument = new HashMap<>(source); return new ElasticsearchDocument(esDoc.getId(), esDoc.getType(), esDoc.getIndex(), esDoc.getVersion(), newDocument, geoContextMapper); } @@ -486,7 +486,7 @@ public Iterable getDocuments(Resource subject) * Filters the given list of fields, retaining all property fields. */ public static Set getPropertyFields(Set fields) { - Set result = new HashSet(fields.size()); + Set result = new HashSet<>(fields.size()); for (String field : fields) { if (SearchFields.isPropertyField(field)) result.add(field); diff --git a/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/QueryBindingSet.java b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/QueryBindingSet.java index 138c67265..8e08e5031 100644 --- a/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/QueryBindingSet.java +++ b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/QueryBindingSet.java @@ -39,7 +39,7 @@ public QueryBindingSet() { public QueryBindingSet(int capacity) { // Create bindings map with some extra space for new bindings and // compensating for HashMap's load factor - bindings = new HashMap(capacity * 2); + bindings = new HashMap<>(capacity * 2); } public QueryBindingSet(BindingSet bindingSet) { diff --git a/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/TupleFunctionFederatedService.java b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/TupleFunctionFederatedService.java index dc620ad45..33ec19689 100644 --- a/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/TupleFunctionFederatedService.java +++ b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/federation/TupleFunctionFederatedService.java @@ -72,7 +72,7 @@ public boolean ask(Service service, BindingSet bindings, String baseUri) throws QueryEvaluationException { try (final CloseableIteration iter = evaluate(service, - new SingletonIteration(bindings), baseUri);) + new SingletonIteration<>(bindings), baseUri);) { while (iter.hasNext()) { BindingSet bs = iter.next(); @@ -89,7 +89,7 @@ public CloseableIteration select(Service s throws QueryEvaluationException { final CloseableIteration iter, eval; - eval = evaluate(service, new SingletonIteration(bindings), + eval = evaluate(service, new SingletonIteration<>(bindings), baseUri); iter = service.isSilent() ? new SilentIteration(eval) : eval; if (service.getBindingNames().equals(projectionVars)) { @@ -170,12 +170,12 @@ public final CloseableIteration evaluate(S throws QueryEvaluationException { if (!bindings.hasNext()) { - return new EmptyIteration(); + return new EmptyIteration<>(); } TupleExpr expr = service.getArg(); if (!(expr instanceof TupleFunctionCall)) { - return new EmptyIteration(); + return new EmptyIteration<>(); } TupleFunctionCall funcCall = (TupleFunctionCall)expr; @@ -184,7 +184,7 @@ public final CloseableIteration evaluate(S List argExprs = funcCall.getArgs(); - List> resultIters = new ArrayList>(); + List> resultIters = new ArrayList<>(); while (bindings.hasNext()) { BindingSet bs = bindings.next(); Value[] argValues = new Value[argExprs.size()]; @@ -207,8 +207,8 @@ else if (argExpr instanceof ValueConstant) { argValues)); } return (resultIters.size() > 1) - ? new DistinctIteration( - new UnionIteration(resultIters)) + ? new DistinctIteration<>( + new UnionIteration<>(resultIters)) : resultIters.get(0); } diff --git a/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ConjunctiveConstraintSplitter.java b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ConjunctiveConstraintSplitter.java index b9d30b455..d18b5fd87 100644 --- a/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ConjunctiveConstraintSplitter.java +++ b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ConjunctiveConstraintSplitter.java @@ -45,7 +45,7 @@ public ConstraintVisitor(TupleExpr tupleExpr) { public void meet(Filter filter) { super.meet(filter); - List conjunctiveConstraints = new ArrayList(16); + List conjunctiveConstraints = new ArrayList<>(16); getConjunctiveConstraints(filter.getCondition(), conjunctiveConstraints); TupleExpr filterArg = filter.getArg(); @@ -64,7 +64,7 @@ public void meet(LeftJoin node) { super.meet(node); if (node.getCondition() != null) { - List conjunctiveConstraints = new ArrayList(16); + List conjunctiveConstraints = new ArrayList<>(16); getConjunctiveConstraints(node.getCondition(), conjunctiveConstraints); TupleExpr arg = node.getRightArg(); diff --git a/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ConstantOptimizer.java b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ConstantOptimizer.java index 5863a20c8..b96fec39a 100644 --- a/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ConstantOptimizer.java +++ b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ConstantOptimizer.java @@ -99,7 +99,7 @@ public void optimize(TupleExpr tupleExpr, Dataset dataset, BindingSet bindings) protected class ConstantVisitor extends VarNameCollector { - final List projElemLists = new ArrayList(); + final List projElemLists = new ArrayList<>(); @Override public void meet(ProjectionElemList projElems) { @@ -352,7 +352,7 @@ private boolean isConstant(ValueExpr expr) { protected class VarNameCollector extends AbstractQueryModelVisitor { - final Set varNames = new HashSet(); + final Set varNames = new HashSet<>(); @Override public void meet(Var var) { diff --git a/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/QueryJoinOptimizer.java b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/QueryJoinOptimizer.java index 66d484f80..2ce519b25 100644 --- a/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/QueryJoinOptimizer.java +++ b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/QueryJoinOptimizer.java @@ -58,7 +58,7 @@ public void optimize(TupleExpr tupleExpr, Dataset dataset, BindingSet bindings) protected class JoinVisitor extends AbstractQueryModelVisitor { - Set boundVars = new HashSet(); + Set boundVars = new HashSet<>(); @Override public void meet(LeftJoin leftJoin) { @@ -66,7 +66,7 @@ public void meet(LeftJoin leftJoin) { Set origBoundVars = boundVars; try { - boundVars = new HashSet(boundVars); + boundVars = new HashSet<>(boundVars); boundVars.addAll(leftJoin.getLeftArg().getBindingNames()); leftJoin.getRightArg().visit(this); @@ -81,16 +81,16 @@ public void meet(Join node) { Set origBoundVars = boundVars; try { - boundVars = new HashSet(boundVars); + boundVars = new HashSet<>(boundVars); // Recursively get the join arguments - List joinArgs = getJoinArgs(node, new ArrayList()); + List joinArgs = getJoinArgs(node, new ArrayList<>()); // Reorder the (recursive) join arguments to a more optimal sequence - List orderedJoinArgs = new ArrayList(joinArgs.size()); + List orderedJoinArgs = new ArrayList<>(joinArgs.size()); // Reorder the subselects and extensions to a more optimal sequence - List priorityArgs = new ArrayList(joinArgs.size()); + List priorityArgs = new ArrayList<>(joinArgs.size()); // get all extensions (BIND clause) List orderedExtensions = getExtensions(joinArgs); @@ -106,8 +106,8 @@ public void meet(Join node) { // variable frequency statistics if (joinArgs.size() > 0) { // Build maps of cardinalities and vars per tuple expression - Map cardinalityMap = new HashMap(); - Map> varsMap = new HashMap>(); + Map cardinalityMap = new HashMap<>(); + Map> varsMap = new HashMap<>(); for (TupleExpr tupleExpr : joinArgs) { cardinalityMap.put(tupleExpr, statistics.getCardinality(tupleExpr)); @@ -120,7 +120,7 @@ public void meet(Join node) { } // Build map of var frequences - Map varFreqMap = new HashMap(); + Map varFreqMap = new HashMap<>(); for (List varList : varsMap.values()) { getVarFreqMap(varList, varFreqMap); } @@ -192,7 +192,7 @@ protected > L getJoinArgs(TupleExpr tupleExpr, L joinA protected List getStatementPatternVars(TupleExpr tupleExpr) { List stPatterns = StatementPatternCollector.process(tupleExpr); - List varList = new ArrayList(stPatterns.size() * 4); + List varList = new ArrayList<>(stPatterns.size() * 4); for (StatementPattern sp : stPatterns) { sp.getVars(varList); } @@ -209,7 +209,7 @@ protected > M getVarFreqMap(List varList, M var } protected List getExtensions(List expressions) { - List extensions = new ArrayList(); + List extensions = new ArrayList<>(); for (TupleExpr expr : expressions) { if (expr instanceof Extension) { extensions.add((Extension)expr); @@ -219,7 +219,7 @@ protected List getExtensions(List expressions) { } protected List getSubSelects(List expressions) { - List subselects = new ArrayList(); + List subselects = new ArrayList<>(); for (TupleExpr expr : expressions) { if (TupleExprs.containsSubquery(expr)) { @@ -257,13 +257,13 @@ protected List reorderSubselects(List subselects) { return subselects; } - List result = new ArrayList(); + List result = new ArrayList<>(); if (subselects == null || subselects.size() == 0) { return result; } // Step 1: determine size of join for each pair of arguments - HashMap> joinSizes = new HashMap>(); + HashMap> joinSizes = new HashMap<>(); int maxJoinSize = 0; for (int i = 0; i < subselects.size(); i++) { @@ -285,7 +285,7 @@ protected List reorderSubselects(List subselects) { l = joinSizes.get(joinSize); } else { - l = new ArrayList(); + l = new ArrayList<>(); } TupleExpr[] tupleTuple = new TupleExpr[] { firstArg, secondArg }; l.add(tupleTuple); @@ -333,7 +333,7 @@ private TupleExpr getNextSubselect(List currentList, List // determine union of names of all elements currently in the list: this // corresponds to the projection resulting from joining all these // elements. - Set currentListNames = new HashSet(); + Set currentListNames = new HashSet<>(); for (TupleExpr expr : currentList) { currentListNames.addAll(expr.getBindingNames()); } @@ -445,7 +445,7 @@ protected double getTupleExprCardinality(TupleExpr tupleExpr, Map getConstantVars(Iterable vars) { - List constantVars = new ArrayList(); + List constantVars = new ArrayList<>(); for (Var var : vars) { if (var.hasValue()) { @@ -457,7 +457,7 @@ protected List getConstantVars(Iterable vars) { } protected List getUnboundVars(Iterable vars) { - List unboundVars = new ArrayList(); + List unboundVars = new ArrayList<>(); for (Var var : vars) { if (!var.hasValue() && !this.boundVars.contains(var.getName())) { @@ -471,7 +471,7 @@ protected List getUnboundVars(Iterable vars) { protected int getForeignVarFreq(List ownUnboundVars, Map varFreqMap) { int result = 0; - Map ownFreqMap = getVarFreqMap(ownUnboundVars, new HashMap()); + Map ownFreqMap = getVarFreqMap(ownUnboundVars, new HashMap<>()); for (Map.Entry entry : ownFreqMap.entrySet()) { Var var = entry.getKey(); diff --git a/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/QueryModelNormalizer.java b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/QueryModelNormalizer.java index e57df7786..8f62a81b1 100644 --- a/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/QueryModelNormalizer.java +++ b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/QueryModelNormalizer.java @@ -283,7 +283,7 @@ private static class BindingCollector extends AbstractQueryModelVisitor bindingNames = new HashSet(); + private final Set bindingNames = new HashSet<>(); public void setNodeToIgnore(QueryModelNode node) { this.nodeToIgnore = node; diff --git a/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/SameTermFilterOptimizer.java b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/SameTermFilterOptimizer.java index 17ef0622a..b250781dd 100644 --- a/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/SameTermFilterOptimizer.java +++ b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/SameTermFilterOptimizer.java @@ -203,7 +203,7 @@ public void meet(ProjectionElem projElem) protected static class BindingSetAssignmentCollector extends AbstractQueryModelVisitor { - private List assignments = new ArrayList(); + private List assignments = new ArrayList<>(); @Override public void meet(BindingSetAssignment bsa) { diff --git a/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/StrictEvaluationStrategy.java b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/StrictEvaluationStrategy.java index caca8cdc6..fdd4ea3fc 100644 --- a/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/StrictEvaluationStrategy.java +++ b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/StrictEvaluationStrategy.java @@ -305,7 +305,7 @@ public CloseableIteration evaluate(ZeroLen if (subj != null && obj != null) { if (!subj.equals(obj)) { - return new EmptyIteration(); + return new EmptyIteration<>(); } } @@ -362,7 +362,7 @@ public CloseableIteration evaluate(Service // create a copy of the free variables, and remove those for which // bindings are available (we can set them as constraints!) - Set freeVars = new HashSet(service.getServiceVars()); + Set freeVars = new HashSet<>(service.getServiceVars()); freeVars.removeAll(bindings.getBindingNames()); // Get bindings from values pre-bound into variables. @@ -386,9 +386,9 @@ public CloseableIteration evaluate(Service // check if triples are available (with inserted bindings) if (exists) - return new SingletonIteration(bindings); + return new SingletonIteration<>(bindings); else - return new EmptyIteration(); + return new EmptyIteration<>(); } @@ -402,7 +402,7 @@ public CloseableIteration evaluate(Service catch (QueryEvaluationException e) { // suppress exceptions if silent if (service.isSilent()) { - return new SingletonIteration(bindings); + return new SingletonIteration<>(bindings); } else { throw e; @@ -413,7 +413,7 @@ public CloseableIteration evaluate(Service // wrapped // QueryEval) if silent if (service.isSilent()) { - return new SingletonIteration(bindings); + return new SingletonIteration<>(bindings); } else { throw e; @@ -429,7 +429,7 @@ private Set getBoundVariables(Service service) { private static class BoundVarVisitor extends AbstractQueryModelVisitor { - private final Set boundVars = new HashSet(); + private final Set boundVars = new HashSet<>(); @Override public void meet(Var var) { @@ -470,7 +470,7 @@ public CloseableIteration evaluate(Stateme || isUnbound(conVar, bindings)) { // the variable must remain unbound for this solution see https://www.w3.org/TR/sparql11-query/#assignment - return new EmptyIteration(); + return new EmptyIteration<>(); } boolean allGood = false; @@ -494,7 +494,7 @@ public CloseableIteration evaluate(Stateme if (emptyGraph) { // Search zero contexts - return new EmptyIteration(); + return new EmptyIteration<>(); } else if (graphs == null || graphs.isEmpty()) { // store default behaivour @@ -517,7 +517,7 @@ else if (contextValue != null) { else { // Statement pattern specifies a context that is not part of // the dataset - return new EmptyIteration(); + return new EmptyIteration<>(); } } else { @@ -553,7 +553,7 @@ protected boolean accept(Statement st) { } catch (ClassCastException e) { // Invalid value type for subject, predicate and/or context - return new EmptyIteration(); + return new EmptyIteration<>(); } // The same variable might have been used multiple times in this @@ -735,7 +735,7 @@ public CloseableIteration evaluate(Binding { final Iterator iter = bsa.getBindingSets().iterator(); if (bindings.size() == 0) { // empty binding set - return new CloseableIteratorIteration(iter); + return new CloseableIteratorIteration<>(iter); } CloseableIteration result; @@ -824,11 +824,11 @@ public CloseableIteration evaluate(Slice s CloseableIteration result = evaluate(slice.getArg(), bindings); if (slice.hasOffset()) { - result = new OffsetIteration(result, slice.getOffset()); + result = new OffsetIteration<>(result, slice.getOffset()); } if (slice.hasLimit()) { - result = new LimitIteration(result, slice.getLimit()); + result = new LimitIteration<>(result, slice.getLimit()); } return result; @@ -846,7 +846,7 @@ public CloseableIteration evaluate(Extensi // a type error in an extension argument should be silently ignored // and // result in zero bindings. - result = new EmptyIteration(); + result = new EmptyIteration<>(); } result = new ExtensionIterator(extension, result, this); @@ -857,7 +857,7 @@ public CloseableIteration evaluate(Distinc BindingSet bindings) throws QueryEvaluationException { - return new DistinctIteration( + return new DistinctIteration<>( evaluate(distinct.getArg(), bindings)); } @@ -865,7 +865,7 @@ public CloseableIteration evaluate(Reduced BindingSet bindings) throws QueryEvaluationException { - return new ReducedIteration( + return new ReducedIteration<>( evaluate(reduced.getArg(), bindings)); } @@ -988,7 +988,7 @@ protected Iteration createIteration() } }; - return new UnionIteration(leftArg, rightArg); + return new UnionIteration<>(leftArg, rightArg); } public CloseableIteration evaluate(final Intersection intersection, @@ -1017,7 +1017,7 @@ protected Iteration createIteration() } }; - return new IntersectIteration(leftArg, rightArg); + return new IntersectIteration<>(leftArg, rightArg); } public CloseableIteration evaluate(final Difference difference, @@ -1046,21 +1046,21 @@ protected Iteration createIteration() } }; - return new SPARQLMinusIteration(leftArg, rightArg); + return new SPARQLMinusIteration<>(leftArg, rightArg); } public CloseableIteration evaluate(SingletonSet singletonSet, BindingSet bindings) throws QueryEvaluationException { - return new SingletonIteration(bindings); + return new SingletonIteration<>(bindings); } public CloseableIteration evaluate(EmptySet emptySet, BindingSet bindings) throws QueryEvaluationException { - return new EmptyIteration(); + return new EmptyIteration<>(); } public CloseableIteration evaluate(ExternalSet external, diff --git a/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/BottomUpJoinIterator.java b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/BottomUpJoinIterator.java index cbd9cdda4..d3ac39d90 100644 --- a/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/BottomUpJoinIterator.java +++ b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/BottomUpJoinIterator.java @@ -252,7 +252,7 @@ protected void add(List leftArgResults, BindingSet b) * @return map */ protected Map> makeMap() { - return new HashMap>(); + return new HashMap<>(); } /** @@ -261,7 +261,7 @@ protected Map> makeMap() { * @return list */ protected List makeList() { - return new ArrayList(); + return new ArrayList<>(); } /** @@ -270,7 +270,7 @@ protected List makeList() { * @return list */ protected List makeList(List key) { - return new ArrayList(key); + return new ArrayList<>(key); } /** diff --git a/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/DescribeIteration.java b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/DescribeIteration.java index bc6f355f8..bf9073545 100644 --- a/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/DescribeIteration.java +++ b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/DescribeIteration.java @@ -48,9 +48,9 @@ public class DescribeIteration extends LookAheadIteration nodeQueue = new ArrayDeque(); + private final Queue nodeQueue = new ArrayDeque<>(); - private final Set processedNodes = new HashSet(); + private final Set processedNodes = new HashSet<>(); private CloseableIteration currentDescribeExprIter; @@ -68,7 +68,7 @@ public DescribeIteration(Iteration sourceI { this.strategy = strategy; this.sourceIter = sourceIter; - this.describeExprNames = new ArrayList(describeExprNames); + this.describeExprNames = new ArrayList<>(describeExprNames); this.parentBindings = parentBindings; } @@ -216,7 +216,7 @@ private CloseableIteration createNextItera throws QueryEvaluationException { if (subject == null && object == null) { - return new EmptyIteration(); + return new EmptyIteration<>(); } Var subjVar = new Var(VARNAME_SUBJECT, subject); diff --git a/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/GroupIterator.java b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/GroupIterator.java index 3313a4c54..246ec5101 100644 --- a/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/GroupIterator.java +++ b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/GroupIterator.java @@ -172,7 +172,7 @@ private Set createSet(String setName) { return db.getHashSet(setName); } else { - return new HashSet(); + return new HashSet<>(); } } @@ -211,7 +211,7 @@ private Collection buildEntries() iter = strategy.evaluate(group.getArg(), parentBindings); try { - Map entries = new LinkedHashMap(); + Map entries = new LinkedHashMap<>(); if (!iter.hasNext()) { // no solutions, but if aggregates are present we still need to process them to produce a @@ -325,7 +325,7 @@ private Map getAggregates() synchronized (this) { result = aggregates; if (result == null) { - result = aggregates = new LinkedHashMap(); + result = aggregates = new LinkedHashMap<>(); for (GroupElem ge : group.getGroupElements()) { Aggregate create = create(ge.getOperator()); if (create != null) { diff --git a/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/HashJoinIteration.java b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/HashJoinIteration.java index f78101f43..bcbca73f5 100644 --- a/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/HashJoinIteration.java +++ b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/HashJoinIteration.java @@ -141,7 +141,7 @@ protected BindingSet getNextElement() Collection> values = nextHashTable.values(); boolean empty = values.isEmpty() || values.size() == 1 && values.contains(null); nextHashTableValues = hashTableValues = empty ? new EmptyIterator<>() - : new UnionIterator(values); + : new UnionIterator<>(values); if (!nextHashTableValues.hasNext()) { currentScanElem = null; closeHashValue(nextHashTableValues); @@ -321,7 +321,7 @@ protected void putHashTableEntry(Map> nextHa protected Collection makeIterationCache( CloseableIteration iter) { - return new ArrayList(); + return new ArrayList<>(); } /** @@ -335,10 +335,10 @@ protected Map> makeHashTable(int initialSize // we should probably adjust for the load factor // but we are only one rehash away and this might save a bit of memory // when we have more than one value per entry - nextHashTable = new HashMap>(initialSize); + nextHashTable = new HashMap<>(initialSize); } else { - List l = (initialSize > 0) ? new ArrayList(initialSize) : null; + List l = (initialSize > 0) ? new ArrayList<>(initialSize) : null; nextHashTable = Collections.> singletonMap( BindingSetHashKey.EMPTY, l); } @@ -353,7 +353,7 @@ protected Map> makeHashTable(int initialSize protected List makeHashValue(int currentMaxListSize) { // we pick an initial size that means we may only have to resize once // while saving memory in the case that the list doesn't reach max size - return new ArrayList(currentMaxListSize / 2 + 1); + return new ArrayList<>(currentMaxListSize / 2 + 1); } /** diff --git a/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/JoinIterator.java b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/JoinIterator.java index 5288d9d32..970a1bf5d 100644 --- a/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/JoinIterator.java +++ b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/JoinIterator.java @@ -44,7 +44,7 @@ public JoinIterator(EvaluationStrategy strategy, Join join, BindingSet bindings) leftIter = strategy.evaluate(join.getLeftArg(), bindings); // Initialize with empty iteration so that var is never null - rightIter = new EmptyIteration(); + rightIter = new EmptyIteration<>(); } /*---------* diff --git a/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/LeftJoinIterator.java b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/LeftJoinIterator.java index fe18b5d19..ea7e9a3f6 100644 --- a/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/LeftJoinIterator.java +++ b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/LeftJoinIterator.java @@ -54,7 +54,7 @@ public LeftJoinIterator(EvaluationStrategy strategy, LeftJoin join, BindingSet b leftIter = strategy.evaluate(join.getLeftArg(), bindings); // Initialize with empty iteration so that var is never null - rightIter = new EmptyIteration(); + rightIter = new EmptyIteration<>(); } /*---------* diff --git a/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/OrderIterator.java b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/OrderIterator.java index 445cdfc07..4af347d10 100644 --- a/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/OrderIterator.java +++ b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/OrderIterator.java @@ -336,7 +336,7 @@ else if (list.size() >= limit2 || !distinct && threshold == null && list.size() List> iterators = new ArrayList<>(serialized.size() + 1); serialized.forEach(queue -> iterators.add(queue.iterator())); iterators.add(sort(list).iterator()); - iterator = new SortedIterators(comparator, distinct, iterators); + iterator = new SortedIterators<>(comparator, distinct, iterators); return new LimitIteration<>(new CloseableIteratorIteration<>(iterator), limit); } diff --git a/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/PathIteration.java b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/PathIteration.java index 7fc824abf..29da10da3 100644 --- a/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/PathIteration.java +++ b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/PathIteration.java @@ -263,7 +263,7 @@ private void createIteration() if (isUnbound(startVar, bindings) || isUnbound(endVar, bindings)) { // the variable must remain unbound for this solution see https://www.w3.org/TR/sparql11-query/#assignment - currentIter = new EmptyIteration(); + currentIter = new EmptyIteration<>(); } else if (currentLength == 0L) { ZeroLengthPath zlp = new ZeroLengthPath(scope, startVar, endVar, contextVar); @@ -331,7 +331,7 @@ else if (currentLength == 1) { currentIter = this.evaluationStrategyImpl.evaluate(pathExprClone, bindings); } else { - currentIter = new EmptyIteration(); + currentIter = new EmptyIteration<>(); } currentLength++; @@ -348,11 +348,11 @@ protected boolean isUnbound(Var var, BindingSet bindings) { } protected Set makeSet() { - return new HashSet(64, 0.9f); + return new HashSet<>(64, 0.9f); } protected Queue makeQueue() { - return new ArrayDeque(); + return new ArrayDeque<>(); } protected static class ValuePair { diff --git a/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/SPARQLMinusIteration.java b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/SPARQLMinusIteration.java index aedd2ba88..6b134a752 100644 --- a/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/SPARQLMinusIteration.java +++ b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/SPARQLMinusIteration.java @@ -129,13 +129,13 @@ protected boolean accept(BindingSet object) protected Set makeSet() throws X { - return new LinkedHashSet(); + return new LinkedHashSet<>(); } protected Set makeSet(Set set) throws X { - return new HashSet(set); + return new HashSet<>(set); } protected Set makeSet(Iteration rightArg2) diff --git a/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/ZeroLengthPathIteration.java b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/ZeroLengthPathIteration.java index 7394e2b71..4ff9bc0ad 100644 --- a/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/ZeroLengthPathIteration.java +++ b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/ZeroLengthPathIteration.java @@ -173,7 +173,7 @@ private CloseableIteration createIteration } private Set makeSet() { - return new HashSet(INITIAL_CAPACITY); + return new HashSet<>(INITIAL_CAPACITY); } public Var createAnonVar(String varName) { diff --git a/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/OrderComparator.java b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/OrderComparator.java index 1a3c2e50c..6391bb218 100644 --- a/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/OrderComparator.java +++ b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/OrderComparator.java @@ -96,13 +96,13 @@ public int compare(BindingSet o1, BindingSet o2) { // we create an ordered list of binding names (using natural string order) to use for // consistent iteration over binding names and binding values. - final ArrayList o1bindingNamesOrdered = new ArrayList(o1.getBindingNames()); + final ArrayList o1bindingNamesOrdered = new ArrayList<>(o1.getBindingNames()); Collections.sort(o1bindingNamesOrdered); // binding set sizes are equal. compare on binding names. if (!o1.getBindingNames().equals(o2.getBindingNames())) { - final ArrayList o2bindingNamesOrdered = new ArrayList(o2.getBindingNames()); + final ArrayList o2bindingNamesOrdered = new ArrayList<>(o2.getBindingNames()); Collections.sort(o2bindingNamesOrdered); for (int i = 0; i < o1bindingNamesOrdered.size(); i++) { diff --git a/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/QueryOptimizerList.java b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/QueryOptimizerList.java index d5449a6ac..51c25d669 100644 --- a/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/QueryOptimizerList.java +++ b/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/QueryOptimizerList.java @@ -26,15 +26,15 @@ public class QueryOptimizerList implements QueryOptimizer { protected List optimizers; public QueryOptimizerList() { - this.optimizers = new ArrayList(8); + this.optimizers = new ArrayList<>(8); } public QueryOptimizerList(List optimizers) { - this.optimizers = new ArrayList(optimizers); + this.optimizers = new ArrayList<>(optimizers); } public QueryOptimizerList(QueryOptimizer... optimizers) { - this.optimizers = new ArrayList(optimizers.length); + this.optimizers = new ArrayList<>(optimizers.length); for (QueryOptimizer optimizer : optimizers) { this.optimizers.add(optimizer); } diff --git a/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/EmptyTripleSource.java b/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/EmptyTripleSource.java index b0a96970f..17cf08563 100644 --- a/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/EmptyTripleSource.java +++ b/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/EmptyTripleSource.java @@ -40,6 +40,6 @@ public CloseableIteration getStat IRI pred, Value obj, Resource... contexts) throws QueryEvaluationException { - return new EmptyIteration(); + return new EmptyIteration<>(); } } diff --git a/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/JoinIteratorTest.java b/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/JoinIteratorTest.java index 2d559a590..ca2347e9d 100644 --- a/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/JoinIteratorTest.java +++ b/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/JoinIteratorTest.java @@ -63,7 +63,7 @@ private void testBindingSetAssignmentJoin(int expectedSize, int n, BindingSet bi { BindingSetAssignment left = new BindingSetAssignment(); { - List leftb = new ArrayList(); + List leftb = new ArrayList<>(); for (int i = 0; i < n; i++) { QueryBindingSet b = new QueryBindingSet(); b.addBinding("a", vf.createLiteral(i)); @@ -74,7 +74,7 @@ private void testBindingSetAssignmentJoin(int expectedSize, int n, BindingSet bi BindingSetAssignment right = new BindingSetAssignment(); { - List rightb = new ArrayList(); + List rightb = new ArrayList<>(); for (int i = n; i >= 0; i--) { QueryBindingSet b = new QueryBindingSet(); b.addBinding("a", vf.createLiteral(i)); diff --git a/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/OrderIteratorTest.java b/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/OrderIteratorTest.java index 9a7b88faf..67950e99b 100644 --- a/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/OrderIteratorTest.java +++ b/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/OrderIteratorTest.java @@ -190,7 +190,7 @@ public void testRemove() public void testSorting() throws Exception { - List sorted = new ArrayList(list); + List sorted = new ArrayList<>(list); Collections.sort(sorted, cmp); for (BindingSet b : sorted) { assertEquals(b, order.next()); diff --git a/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/ZeroLengthPathIterationTest.java b/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/ZeroLengthPathIterationTest.java index d7ad4df78..25231a9ea 100644 --- a/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/ZeroLengthPathIterationTest.java +++ b/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/ZeroLengthPathIterationTest.java @@ -53,7 +53,7 @@ public CloseableIteration getStat Resource subj, IRI pred, Value obj, Resource... contexts) throws QueryEvaluationException { - return new CloseableIteratorIteration( + return new CloseableIteratorIteration<>( m.filter(subj, pred, obj, contexts).iterator()); } diff --git a/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/util/LiteralComparatorTest.java b/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/util/LiteralComparatorTest.java index 99f7b519c..78596001a 100644 --- a/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/util/LiteralComparatorTest.java +++ b/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/util/LiteralComparatorTest.java @@ -147,7 +147,7 @@ public void testOrder() { Literal en4 = vf.createLiteral("4", "en"); Literal nine = vf.createLiteral(9); - List list = new ArrayList(); + List list = new ArrayList<>(); list.add(ten); list.add(en4); list.add(nine); diff --git a/federation/src/main/java/org/eclipse/rdf4j/sail/federation/AbstractFederationConnection.java b/federation/src/main/java/org/eclipse/rdf4j/sail/federation/AbstractFederationConnection.java index 2f42d4fd2..6b75c5528 100644 --- a/federation/src/main/java/org/eclipse/rdf4j/sail/federation/AbstractFederationConnection.java +++ b/federation/src/main/java/org/eclipse/rdf4j/sail/federation/AbstractFederationConnection.java @@ -141,7 +141,7 @@ public IsolationLevel getDefaultIsolationLevel() { valueFactory = SimpleValueFactory.getInstance(); - this.members = new ArrayList(members.size()); + this.members = new ArrayList<>(members.size()); for (RepositoryConnection member : members) { this.members.add(member); } @@ -282,9 +282,9 @@ else if (candidate != null && !candidate.equals(namespace)) { public CloseableIteration getNamespacesInternal() throws SailException { - Map namespaces = new HashMap(); - Set prefixes = new HashSet(); - Set conflictedPrefixes = new HashSet(); + Map namespaces = new HashMap<>(); + Set prefixes = new HashSet<>(); + Set conflictedPrefixes = new HashSet<>(); try { for (RepositoryConnection member : members) { @@ -309,7 +309,7 @@ else if (!next.getName().equals(namespaces.get(prefix).getName())) { for (String prefix : conflictedPrefixes) { namespaces.remove(prefix); } - return new CloseableIteratorIteration(namespaces.values().iterator()); + return new CloseableIteratorIteration<>(namespaces.values().iterator()); } @Override @@ -507,14 +507,14 @@ CloseableIteration call(RepositoryConnection m private CloseableIteration union(Function function) throws SailException { - List> cursors = new ArrayList>( + List> cursors = new ArrayList<>( members.size()); try { for (RepositoryConnection member : members) { cursors.add(function.call(member)); } - UnionIteration result = new UnionIteration( + UnionIteration result = new UnionIteration<>( cursors); return new ExceptionConvertingIteration(result) { diff --git a/federation/src/main/java/org/eclipse/rdf4j/sail/federation/Federation.java b/federation/src/main/java/org/eclipse/rdf4j/sail/federation/Federation.java index ceb3c83b7..48f63bd2c 100644 --- a/federation/src/main/java/org/eclipse/rdf4j/sail/federation/Federation.java +++ b/federation/src/main/java/org/eclipse/rdf4j/sail/federation/Federation.java @@ -62,7 +62,7 @@ public class Federation implements Sail, Executor, FederatedServiceResolverClien private static final Logger LOGGER = LoggerFactory.getLogger(Federation.class); - private final List members = new ArrayList(); + private final List members = new ArrayList<>(); private final Map bloomFilters = new HashMap<>(); @@ -334,7 +334,7 @@ public void execute(Runnable command) { public SailConnection getConnection() throws SailException { - List connections = new ArrayList(members.size()); + List connections = new ArrayList<>(members.size()); boolean allGood = false; try { for (Repository member : members) { diff --git a/federation/src/main/java/org/eclipse/rdf4j/sail/federation/PrefixHashSet.java b/federation/src/main/java/org/eclipse/rdf4j/sail/federation/PrefixHashSet.java index 8a86f864f..cfe105b24 100644 --- a/federation/src/main/java/org/eclipse/rdf4j/sail/federation/PrefixHashSet.java +++ b/federation/src/main/java/org/eclipse/rdf4j/sail/federation/PrefixHashSet.java @@ -19,7 +19,7 @@ public class PrefixHashSet { private int length = Integer.MAX_VALUE; // NOPMD - private final Map> index = new HashMap>(); + private final Map> index = new HashMap<>(); public PrefixHashSet(Iterable values) { for (String value : values) { @@ -31,7 +31,7 @@ public PrefixHashSet(Iterable values) { String key = value.substring(0, length); List entry = index.get(key); if (entry == null) { - index.put(key, entry = new ArrayList()); // NOPMD + index.put(key, entry = new ArrayList<>()); // NOPMD } entry.add(value.substring(length)); } diff --git a/federation/src/main/java/org/eclipse/rdf4j/sail/federation/algebra/AbstractNaryOperator.java b/federation/src/main/java/org/eclipse/rdf4j/sail/federation/algebra/AbstractNaryOperator.java index 5790f8c10..c6b50067f 100644 --- a/federation/src/main/java/org/eclipse/rdf4j/sail/federation/algebra/AbstractNaryOperator.java +++ b/federation/src/main/java/org/eclipse/rdf4j/sail/federation/algebra/AbstractNaryOperator.java @@ -30,7 +30,7 @@ public abstract class AbstractNaryOperator extends /** * The operator's arguments. */ - private List args = new ArrayList(); + private List args = new ArrayList<>(); /*--------------* * Constructors * @@ -65,7 +65,7 @@ public AbstractNaryOperator(final List args) { * @return A copy of the current argument list. */ public List getArgs() { - return new CopyOnWriteArrayList(args); + return new CopyOnWriteArrayList<>(args); } /** @@ -159,7 +159,7 @@ public void replaceChildNode(final QueryModelNode current, final QueryModelNode @SuppressWarnings("unchecked") public AbstractNaryOperator clone() { // NOPMD final AbstractNaryOperator clone = (AbstractNaryOperator)super.clone(); - clone.args = new ArrayList(args.size()); + clone.args = new ArrayList<>(args.size()); for (Expr arg : args) { final Expr argClone = (arg == null) ? null : (Expr)arg.clone(); // NOPMD clone.addArg(argClone); diff --git a/federation/src/main/java/org/eclipse/rdf4j/sail/federation/algebra/AbstractNaryTupleOperator.java b/federation/src/main/java/org/eclipse/rdf4j/sail/federation/algebra/AbstractNaryTupleOperator.java index 9df5953af..7a89d6a51 100644 --- a/federation/src/main/java/org/eclipse/rdf4j/sail/federation/algebra/AbstractNaryTupleOperator.java +++ b/federation/src/main/java/org/eclipse/rdf4j/sail/federation/algebra/AbstractNaryTupleOperator.java @@ -48,7 +48,7 @@ public AbstractNaryTupleOperator(List args) { @Override public Set getBindingNames() { - Set bindingNames = new LinkedHashSet(16); + Set bindingNames = new LinkedHashSet<>(16); for (TupleExpr arg : getArgs()) { bindingNames.addAll(arg.getBindingNames()); @@ -59,7 +59,7 @@ public Set getBindingNames() { @Override public Set getAssuredBindingNames() { - Set bindingNames = new LinkedHashSet(16); + Set bindingNames = new LinkedHashSet<>(16); for (TupleExpr arg : getArgs()) { bindingNames.addAll(arg.getAssuredBindingNames()); diff --git a/federation/src/main/java/org/eclipse/rdf4j/sail/federation/config/FederationConfig.java b/federation/src/main/java/org/eclipse/rdf4j/sail/federation/config/FederationConfig.java index ac9ad6124..8e724d9e1 100644 --- a/federation/src/main/java/org/eclipse/rdf4j/sail/federation/config/FederationConfig.java +++ b/federation/src/main/java/org/eclipse/rdf4j/sail/federation/config/FederationConfig.java @@ -61,9 +61,9 @@ public class FederationConfig extends AbstractSailImplConfig { */ public static final IRI READ_ONLY = vf.createIRI(NAMESPACE + "readOnly"); - private List members = new ArrayList(); + private List members = new ArrayList<>(); - private final Set localPropertySpace = new HashSet(); // NOPMD + private final Set localPropertySpace = new HashSet<>(); // NOPMD private boolean distinct; diff --git a/federation/src/main/java/org/eclipse/rdf4j/sail/federation/evaluation/FederationStrategy.java b/federation/src/main/java/org/eclipse/rdf4j/sail/federation/evaluation/FederationStrategy.java index 0060604a9..448231761 100644 --- a/federation/src/main/java/org/eclipse/rdf4j/sail/federation/evaluation/FederationStrategy.java +++ b/federation/src/main/java/org/eclipse/rdf4j/sail/federation/evaluation/FederationStrategy.java @@ -119,7 +119,7 @@ public CloseableIteration evaluate(LeftJoi Set leftVars = leftJoin.getLeftArg().getBindingNames(); Set optionalVars = leftJoin.getRightArg().getBindingNames(); - final Set problemVars = new HashSet(boundVars); + final Set problemVars = new HashSet<>(boundVars); problemVars.retainAll(optionalVars); problemVars.removeAll(leftVars); @@ -143,7 +143,7 @@ public CloseableIteration evaluate(Union u CloseableIteration[] iters = new CloseableIteration[2]; iters[0] = evaluate(union.getLeftArg(), bindings); iters[1] = evaluate(union.getRightArg(), bindings); - return new UnionIteration(iters); + return new UnionIteration<>(iters); } private CloseableIteration evaluate(OwnedTupleExpr expr, diff --git a/federation/src/main/java/org/eclipse/rdf4j/sail/federation/evaluation/ParallelJoinCursor.java b/federation/src/main/java/org/eclipse/rdf4j/sail/federation/evaluation/ParallelJoinCursor.java index 773baf7d9..841407eec 100644 --- a/federation/src/main/java/org/eclipse/rdf4j/sail/federation/evaluation/ParallelJoinCursor.java +++ b/federation/src/main/java/org/eclipse/rdf4j/sail/federation/evaluation/ParallelJoinCursor.java @@ -51,7 +51,7 @@ public class ParallelJoinCursor extends LookAheadIteration> rightQueue = new QueueCursor>( + private final QueueCursor> rightQueue = new QueueCursor<>( 1024); private final List> toCloseList = new ArrayList<>(); diff --git a/federation/src/main/java/org/eclipse/rdf4j/sail/federation/evaluation/ParallelLeftJoinCursor.java b/federation/src/main/java/org/eclipse/rdf4j/sail/federation/evaluation/ParallelLeftJoinCursor.java index 604882954..15decbf2e 100644 --- a/federation/src/main/java/org/eclipse/rdf4j/sail/federation/evaluation/ParallelLeftJoinCursor.java +++ b/federation/src/main/java/org/eclipse/rdf4j/sail/federation/evaluation/ParallelLeftJoinCursor.java @@ -60,7 +60,7 @@ public class ParallelLeftJoinCursor extends LookAheadIteration> rightQueue = new QueueCursor>( + private final QueueCursor> rightQueue = new QueueCursor<>( 1024); /*--------------* @@ -111,9 +111,9 @@ private void addToRightQueue(ValueExpr condition, BindingSet leftBindings) if (condition != null) { result = new FilterCursor(result, condition, scopeBindingNames, strategy); } - CloseableIteration alt = new SingletonIteration( + CloseableIteration alt = new SingletonIteration<>( leftBindings); - rightQueue.put(new AlternativeCursor(result, alt)); + rightQueue.put(new AlternativeCursor<>(result, alt)); } @Override diff --git a/federation/src/main/java/org/eclipse/rdf4j/sail/federation/optimizers/FederationJoinOptimizer.java b/federation/src/main/java/org/eclipse/rdf4j/sail/federation/optimizers/FederationJoinOptimizer.java index 777d6c41b..8f6a152a9 100644 --- a/federation/src/main/java/org/eclipse/rdf4j/sail/federation/optimizers/FederationJoinOptimizer.java +++ b/federation/src/main/java/org/eclipse/rdf4j/sail/federation/optimizers/FederationJoinOptimizer.java @@ -88,7 +88,7 @@ private static Map> createContextToMemberMa Collection members) throws RepositoryException { - Map> contextToMemberMap = new HashMap>( + Map> contextToMemberMap = new HashMap<>( members.size() + 1); for (RepositoryConnection member : members) { try (RepositoryResult res = member.getContextIDs()) { @@ -96,7 +96,7 @@ private static Map> createContextToMemberMa Resource ctx = res.next(); List contextMembers = contextToMemberMap.get(ctx); if (contextMembers == null) { - contextMembers = new ArrayList(); + contextMembers = new ArrayList<>(); contextToMemberMap.put(ctx, contextMembers); } contextMembers.add(member); @@ -136,15 +136,15 @@ public void meetMultiJoin(NaryJoin node) throws RepositoryException { super.meetOther(node); - List> ows = new ArrayList>(); - List vars = new ArrayList(); + List> ows = new ArrayList<>(); + List vars = new ArrayList<>(); for (TupleExpr arg : node.getArgs()) { RepositoryConnection member = getSingleOwner(arg); if ((!ows.isEmpty()) && ows.get(ows.size() - 1).getOwner() == member) { ows.get(ows.size() - 1).getOperation().addArg(arg.clone()); } else { - ows.add(new Owned(member, new NaryJoin(arg.clone()))); // NOPMD + ows.add(new Owned<>(member, new NaryJoin(arg.clone()))); // NOPMD } } for (TupleExpr arg : node.getArgs()) { @@ -179,7 +179,7 @@ public void meet(Union node) throws RepositoryException { super.meet(node); - List> ows = new ArrayList>(); + List> ows = new ArrayList<>(); for (TupleExpr arg : new TupleExpr[] { node.getLeftArg(), // NOPMD node.getRightArg() }) @@ -192,7 +192,7 @@ public void meet(Union node) ows.get(idx).setOperation(union); } else { - ows.add(new Owned(member, arg.clone())); // NOPMD + ows.add(new Owned<>(member, arg.clone())); // NOPMD } } addOwners(node, ows); @@ -340,14 +340,14 @@ private RepositoryConnection getSingleOwner(Resource subj, IRI pred, Value obj, if (contextToMemberMap == null) { contextToMemberMap = createContextToMemberMap(members); } - Set results = new HashSet(); + Set results = new HashSet<>(); Collection explicitContexts; if (ctx.length > 0) { explicitContexts = Arrays.asList(ctx); } else if (dataset != null) { // all graphs - explicitContexts = new ArrayList(); + explicitContexts = new ArrayList<>(); explicitContexts.addAll(dataset.getDefaultGraphs()); explicitContexts.addAll(dataset.getNamedGraphs()); } @@ -756,7 +756,7 @@ private void addOwners(Union node, List> ows) { } private List getUnionArgs(TupleExpr union) { - return getUnionArgs(union, new ArrayList()); + return getUnionArgs(union, new ArrayList<>()); } private List getUnionArgs(TupleExpr union, List list) { diff --git a/federation/src/main/java/org/eclipse/rdf4j/sail/federation/optimizers/PrepareOwnedTupleExpr.java b/federation/src/main/java/org/eclipse/rdf4j/sail/federation/optimizers/PrepareOwnedTupleExpr.java index d781b88e2..67d7cd89d 100644 --- a/federation/src/main/java/org/eclipse/rdf4j/sail/federation/optimizers/PrepareOwnedTupleExpr.java +++ b/federation/src/main/java/org/eclipse/rdf4j/sail/federation/optimizers/PrepareOwnedTupleExpr.java @@ -58,7 +58,7 @@ public class PrepareOwnedTupleExpr extends AbstractQueryModelVisitor variables = new HashMap(); + private Map variables = new HashMap<>(); private boolean reduce; @@ -120,7 +120,7 @@ else if (reduced || reduce) { builder.append(" REDUCED"); } boolean mapping = false; - Map bindings = new HashMap(); + Map bindings = new HashMap<>(); ProjectionElemList list = new ProjectionElemList(); for (String name : patternNode.getBindingNames()) { mapping = addBindingNames(builder, mapping, bindings, list, name); @@ -246,7 +246,7 @@ public void meet(Projection node) if (patternNode == null) { return; } - Map map = new HashMap(); + Map map = new HashMap<>(); for (ProjectionElem e : node.getProjectionElemList().getElements()) { String source = variables.get(e.getSourceName()); if (source == null) { @@ -264,7 +264,7 @@ public void meet(LeftJoin node) throws RepositoryException { if (node.getCondition() == null) { - Map vars = new HashMap(); + Map vars = new HashMap<>(); StringBuilder builder = new StringBuilder(); node.getLeftArg().visit(this); if (patternNode != null) { @@ -288,7 +288,7 @@ public void meet(LeftJoin node) public void meetMultiJoin(NaryJoin node) throws RepositoryException { - Map vars = new HashMap(); + Map vars = new HashMap<>(); StringBuilder builder = new StringBuilder(); for (TupleExpr arg : node.getArgs()) { arg.visit(this); @@ -315,7 +315,7 @@ else if (builder != null) { public void meet(Join node) throws RepositoryException { - Map vars = new HashMap(); + Map vars = new HashMap<>(); StringBuilder builder = new StringBuilder(); node.getLeftArg().visit(this); if (patternNode != null) { diff --git a/federation/src/main/java/org/eclipse/rdf4j/sail/federation/optimizers/QueryMultiJoinOptimizer.java b/federation/src/main/java/org/eclipse/rdf4j/sail/federation/optimizers/QueryMultiJoinOptimizer.java index e3527bfc8..8f92ba9e0 100644 --- a/federation/src/main/java/org/eclipse/rdf4j/sail/federation/optimizers/QueryMultiJoinOptimizer.java +++ b/federation/src/main/java/org/eclipse/rdf4j/sail/federation/optimizers/QueryMultiJoinOptimizer.java @@ -57,7 +57,7 @@ public void optimize(TupleExpr tupleExpr, Dataset dataset, BindingSet bindings) protected class JoinVisitor extends AbstractQueryModelVisitor { - private Set boundVars = new HashSet(); + private Set boundVars = new HashSet<>(); @Override public void meet(LeftJoin leftJoin) { @@ -65,7 +65,7 @@ public void meet(LeftJoin leftJoin) { Set origBoundVars = boundVars; try { - boundVars = new HashSet(boundVars); + boundVars = new HashSet<>(boundVars); boundVars.addAll(leftJoin.getLeftArg().getBindingNames()); leftJoin.getRightArg().visit(this); @@ -97,14 +97,14 @@ public void meet(Join node) public void meetJoin(TupleExpr node) { Set origBoundVars = boundVars; try { - boundVars = new HashSet(boundVars); + boundVars = new HashSet<>(boundVars); // Recursively get the join arguments - List joinArgs = getJoinArgs(node, new ArrayList()); + List joinArgs = getJoinArgs(node, new ArrayList<>()); // Build maps of cardinalities and vars per tuple expression - Map cardinalityMap = new HashMap(); - Map> varsMap = new HashMap>(); + Map cardinalityMap = new HashMap<>(); + Map> varsMap = new HashMap<>(); for (TupleExpr tupleExpr : joinArgs) { cardinalityMap.put(tupleExpr, statistics.getCardinality(tupleExpr)); @@ -112,13 +112,13 @@ public void meetJoin(TupleExpr node) { } // Build map of var frequences - Map varFreqMap = new HashMap(); + Map varFreqMap = new HashMap<>(); for (List varList : varsMap.values()) { getVarFreqMap(varList, varFreqMap); } // Reorder the (recursive) join arguments to a more optimal sequence - List orderedJoinArgs = new ArrayList(joinArgs.size()); + List orderedJoinArgs = new ArrayList<>(joinArgs.size()); while (!joinArgs.isEmpty()) { TupleExpr tupleExpr = selectNextTupleExpr(joinArgs, cardinalityMap, varsMap, varFreqMap, boundVars); @@ -164,7 +164,7 @@ else if (tupleExpr instanceof Join) { protected List getStatementPatternVars(TupleExpr tupleExpr) { List stPatterns = StatementPatternCollector.process(tupleExpr); - List varList = new ArrayList(stPatterns.size() * 4); + List varList = new ArrayList<>(stPatterns.size() * 4); for (StatementPattern sp : stPatterns) { sp.getVars(varList); } @@ -248,7 +248,7 @@ protected double getTupleExprCardinality(TupleExpr tupleExpr, Map getConstantVars(Iterable vars) { - List constantVars = new ArrayList(); + List constantVars = new ArrayList<>(); for (Var var : vars) { if (var.hasValue()) { @@ -260,7 +260,7 @@ protected List getConstantVars(Iterable vars) { } protected List getUnboundVars(Iterable vars) { - List unboundVars = new ArrayList(); + List unboundVars = new ArrayList<>(); for (Var var : vars) { if (!var.hasValue() && !this.boundVars.contains(var.getName())) { @@ -274,7 +274,7 @@ protected List getUnboundVars(Iterable vars) { protected int getForeignVarFreq(List ownUnboundVars, Map varFreqMap) { int result = 0; - Map ownFreqMap = getVarFreqMap(ownUnboundVars, new HashMap()); + Map ownFreqMap = getVarFreqMap(ownUnboundVars, new HashMap<>()); for (Map.Entry entry : ownFreqMap.entrySet()) { Var var = entry.getKey(); diff --git a/federation/src/test/java/org/eclipse/rdf4j/sail/federation/FederationQueryTest.java b/federation/src/test/java/org/eclipse/rdf4j/sail/federation/FederationQueryTest.java index 40e0e56af..494ab768f 100644 --- a/federation/src/test/java/org/eclipse/rdf4j/sail/federation/FederationQueryTest.java +++ b/federation/src/test/java/org/eclipse/rdf4j/sail/federation/FederationQueryTest.java @@ -167,9 +167,9 @@ private void compareTupleQueryResults(TupleQueryResult expectedResult, TupleQuer List queryBindings = Iterations.asList(queryResultTable); List expectedBindings = Iterations.asList(expectedTable); - List missingBindings = new ArrayList(expectedBindings); + List missingBindings = new ArrayList<>(expectedBindings); missingBindings.removeAll(queryBindings); - List unexpected = new ArrayList(queryBindings); + List unexpected = new ArrayList<>(queryBindings); unexpected.removeAll(expectedBindings); StringBuilder message = new StringBuilder(128); message.append("\n============ "); diff --git a/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/DefaultSpatialAlgebra.java b/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/DefaultSpatialAlgebra.java index e0c2912bb..14f574b7d 100644 --- a/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/DefaultSpatialAlgebra.java +++ b/geosparql/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/geosparql/DefaultSpatialAlgebra.java @@ -34,7 +34,7 @@ private Shape createEmptyPoint() { } private Shape createEmptyGeometry() { - return new ShapeCollection(Collections. emptyList(), + return new ShapeCollection<>(Collections. emptyList(), SpatialSupport.getSpatialContext()); } @@ -91,7 +91,7 @@ else if (diff < 0) { p1 = p2; p2 = (Point)s1; } - return new ShapeCollection(Arrays.asList(p1, p2), SpatialSupport.getSpatialContext()); + return new ShapeCollection<>(Arrays.asList(p1, p2), SpatialSupport.getSpatialContext()); } return notSupported(); } @@ -133,7 +133,7 @@ else if (diff < 0) { p1 = p2; p2 = (Point)s1; } - return new ShapeCollection(Arrays.asList(p1, p2), SpatialSupport.getSpatialContext()); + return new ShapeCollection<>(Arrays.asList(p1, p2), SpatialSupport.getSpatialContext()); } return notSupported(); } diff --git a/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/AbstractForwardChainingInferencer.java b/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/AbstractForwardChainingInferencer.java index b709027b0..e0cba1c3f 100644 --- a/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/AbstractForwardChainingInferencer.java +++ b/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/AbstractForwardChainingInferencer.java @@ -50,7 +50,7 @@ public IsolationLevel getDefaultIsolationLevel() { @Override public List getSupportedIsolationLevels() { List supported = super.getSupportedIsolationLevels(); - List levels = new ArrayList(supported.size()); + List levels = new ArrayList<>(supported.size()); for (IsolationLevel level : supported) { if (level.isCompatibleWith(READ_COMMITTED)) { levels.add(level); diff --git a/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/CustomGraphQueryInferencer.java b/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/CustomGraphQueryInferencer.java index 472003712..73922df48 100644 --- a/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/CustomGraphQueryInferencer.java +++ b/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/CustomGraphQueryInferencer.java @@ -52,11 +52,11 @@ public class CustomGraphQueryInferencer extends NotifyingSailWrapper { private ParsedGraphQuery customMatcher; - private final Collection watchPredicates = new HashSet(); + private final Collection watchPredicates = new HashSet<>(); - private final Collection watchSubjects = new HashSet(); + private final Collection watchSubjects = new HashSet<>(); - private final Collection watchObjects = new HashSet(); + private final Collection watchObjects = new HashSet<>(); private boolean hasWatchValues; @@ -255,8 +255,8 @@ public void flushUpdates() throws SailException { super.flushUpdates(); - Collection forRemoval = new HashSet(256); - Collection forAddition = new HashSet(256); + Collection forRemoval = new HashSet<>(256); + Collection forAddition = new HashSet<>(256); Resource[] contexts = new Resource[] { null }; while (updateNeeded) { try { @@ -296,7 +296,7 @@ private void buildDeltaSets(Collection forRemoval, Collection inCommon = new HashSet(forRemoval); + Collection inCommon = new HashSet<>(forRemoval); inCommon.retainAll(forAddition); forRemoval.removeAll(inCommon); forAddition.removeAll(inCommon); diff --git a/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/DedupingInferencerConnection.java b/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/DedupingInferencerConnection.java index 98b44ef00..4a84e6d41 100644 --- a/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/DedupingInferencerConnection.java +++ b/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/DedupingInferencerConnection.java @@ -42,7 +42,7 @@ public DedupingInferencerConnection(InferencerConnection con, ValueFactory vf) { } private Set createDedupBuffer() { - return Collections.newSetFromMap(new LRUMap(MAX_SIZE)); + return Collections.newSetFromMap(new LRUMap<>(MAX_SIZE)); } @Override diff --git a/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/DirectTypeHierarchyInferencer.java b/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/DirectTypeHierarchyInferencer.java index 9bad3af07..b61a016b9 100644 --- a/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/DirectTypeHierarchyInferencer.java +++ b/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/DirectTypeHierarchyInferencer.java @@ -215,8 +215,8 @@ public void flushUpdates() try { // Determine which statements should be added and which should be // removed - Collection oldStatements = new HashSet(256); - Collection newStatements = new HashSet(256); + Collection oldStatements = new HashSet<>(256); + Collection newStatements = new HashSet<>(256); evaluateIntoStatements(DIRECT_SUBCLASSOF_MATCHER, oldStatements); evaluateIntoStatements(DIRECT_SUBPROPERTYOF_MATCHER, oldStatements); @@ -230,7 +230,7 @@ public void flushUpdates() logger.debug("new virtual properties: {}", newStatements.size()); // Remove the statements that should be retained from both sets - Collection unchangedStatements = new HashSet(oldStatements); + Collection unchangedStatements = new HashSet<>(oldStatements); unchangedStatements.retainAll(newStatements); oldStatements.removeAll(unchangedStatements); diff --git a/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/SchemaCachingRDFSInferencer.java b/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/SchemaCachingRDFSInferencer.java index 87c5090d3..25497e0fc 100644 --- a/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/SchemaCachingRDFSInferencer.java +++ b/inferencer/src/main/java/org/eclipse/rdf4j/sail/inferencer/fc/SchemaCachingRDFSInferencer.java @@ -621,7 +621,7 @@ public IsolationLevel getDefaultIsolationLevel() { @Override public List getSupportedIsolationLevels() { List supported = super.getSupportedIsolationLevels(); - List levels = new ArrayList(supported.size()); + List levels = new ArrayList<>(supported.size()); for (IsolationLevel level : supported) { if (level.isCompatibleWith(IsolationLevels.READ_COMMITTED)) { levels.add(level); diff --git a/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/AbstractLuceneIndex.java b/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/AbstractLuceneIndex.java index fb47ccdd2..3cd3d1cf7 100644 --- a/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/AbstractLuceneIndex.java +++ b/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/AbstractLuceneIndex.java @@ -17,7 +17,7 @@ public abstract class AbstractLuceneIndex extends AbstractSearchIndex { * keep a lit of old monitors that are still iterating but not closed (open iterators), will be all closed * on shutdown items are removed from list by ReaderMnitor.endReading() when closing */ - protected final Collection oldmonitors = new ArrayList(); + protected final Collection oldmonitors = new ArrayList<>(); protected abstract AbstractReaderMonitor getCurrentMonitor(); diff --git a/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/AbstractSearchIndex.java b/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/AbstractSearchIndex.java index f88243c74..a1fdddd18 100644 --- a/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/AbstractSearchIndex.java +++ b/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/AbstractSearchIndex.java @@ -206,10 +206,10 @@ public final synchronized void addRemoveStatements(Collection added, throws IOException { // Buffer per resource - MapOfListMaps rsAdded = new MapOfListMaps(); - MapOfListMaps rsRemoved = new MapOfListMaps(); + MapOfListMaps rsAdded = new MapOfListMaps<>(); + MapOfListMaps rsRemoved = new MapOfListMaps<>(); - HashSet resources = new HashSet(); + HashSet resources = new HashSet<>(); for (Statement s : added) { rsAdded.add(s.getSubject(), SearchFields.getContextID(s.getContext()), s); resources.add(s.getSubject()); @@ -227,10 +227,10 @@ public final synchronized void addRemoveStatements(Collection added, Map> stmtsToRemove = rsRemoved.get(resource); Map> stmtsToAdd = rsAdded.get(resource); - Set contextsToUpdate = new HashSet(stmtsToAdd.keySet()); + Set contextsToUpdate = new HashSet<>(stmtsToAdd.keySet()); contextsToUpdate.addAll(stmtsToRemove.keySet()); - Map docsByContext = new HashMap(); + Map docsByContext = new HashMap<>(); // is the resource in the store? // fetch the Document representing this Resource String resourceId = SearchFields.getResourceID(resource); @@ -273,7 +273,7 @@ public final synchronized void addRemoveStatements(Collection added, { List removedStatements = stmtsToRemove.get(contextId); if (removedStatements != null && !removedStatements.isEmpty()) { - removedOfResource = new HashMap>(); + removedOfResource = new HashMap<>(); for (Statement r : removedStatements) { String val = SearchFields.getLiteralPropertyValueAsString(r); if (val != null) { @@ -282,7 +282,7 @@ public final synchronized void addRemoveStatements(Collection added, String field = SearchFields.getPropertyField(r.getPredicate()); Set removedValues = removedOfResource.get(field); if (removedValues == null) { - removedValues = new HashSet(); + removedValues = new HashSet<>(); removedOfResource.put(field, removedValues); } removedValues.add(val); @@ -533,9 +533,9 @@ private Collection generateBindingSets(QuerySpec query, // duplicate answers in the original SPARQL query. // We want to avoid this, so BindingSets added to the result must be // unique. - LinkedHashSet bindingSets = new LinkedHashSet(); + LinkedHashSet bindingSets = new LinkedHashSet<>(); - Set bindingNames = new HashSet(); + Set bindingNames = new HashSet<>(); final String matchVar = query.getMatchesVariableName(); if (matchVar != null) { bindingNames.add(matchVar); @@ -675,9 +675,9 @@ private Collection generateBindingSets(DistanceQuerySpec query, // duplicate answers in the original SPARQL query. // We want to avoid this, so BindingSets added to the result must be // unique. - LinkedHashSet bindingSets = new LinkedHashSet(); + LinkedHashSet bindingSets = new LinkedHashSet<>(); - Set bindingNames = new HashSet(); + Set bindingNames = new HashSet<>(); final String subjVar = query.getSubjectVar(); if (subjVar != null) { bindingNames.add(subjVar); @@ -779,9 +779,9 @@ private Collection generateBindingSets(GeoRelationQuerySpec query, // duplicate answers in the original SPARQL query. // We want to avoid this, so BindingSets added to the result must be // unique. - LinkedHashSet bindingSets = new LinkedHashSet(); + LinkedHashSet bindingSets = new LinkedHashSet<>(); - Set bindingNames = new HashSet(); + Set bindingNames = new HashSet<>(); final String subjVar = query.getSubjectVar(); if (subjVar != null) { bindingNames.add(subjVar); diff --git a/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/DistanceQuerySpecBuilder.java b/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/DistanceQuerySpecBuilder.java index 1bedc13fb..e3eaa0a2b 100644 --- a/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/DistanceQuerySpecBuilder.java +++ b/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/DistanceQuerySpecBuilder.java @@ -48,7 +48,7 @@ public void process(TupleExpr tupleExpr, BindingSet bindings, tupleExpr.visit(new AbstractQueryModelVisitor() { - final Map specs = new HashMap(); + final Map specs = new HashMap<>(); @Override public void meet(FunctionCall f) diff --git a/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/GeoRelationQuerySpecBuilder.java b/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/GeoRelationQuerySpecBuilder.java index 4fafae1ef..4a60990d9 100644 --- a/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/GeoRelationQuerySpecBuilder.java +++ b/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/GeoRelationQuerySpecBuilder.java @@ -45,7 +45,7 @@ public void process(TupleExpr tupleExpr, BindingSet bindings, tupleExpr.visit(new AbstractQueryModelVisitor() { - final Map specs = new HashMap(); + final Map specs = new HashMap<>(); @Override public void meet(FunctionCall f) diff --git a/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/LuceneSail.java b/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/LuceneSail.java index 94486723b..842201a3b 100644 --- a/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/LuceneSail.java +++ b/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/LuceneSail.java @@ -384,8 +384,8 @@ public void initialize() throw new SailException("Could read " + INDEXEDFIELDS + ": " + indexedfieldsString, e); } ValueFactory vf = getValueFactory(); - indexedFields = new HashSet(); - indexedFieldsMapping = new HashMap(); + indexedFields = new HashSet<>(); + indexedFieldsMapping = new HashMap<>(); for (Object key : prop.keySet()) { String keyStr = key.toString(); if (keyStr.startsWith("index.")) { @@ -556,7 +556,7 @@ public void shutDown() { TupleQueryResult res = query.evaluate(); Resource current = null; ValueFactory vf = getValueFactory(); - List statements = new ArrayList(); + List statements = new ArrayList<>(); while (res.hasNext()) { BindingSet set = res.next(); Resource r = (Resource)set.getValue("s"); diff --git a/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/LuceneSailBuffer.java b/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/LuceneSailBuffer.java index 2ab04fce6..9a8f74587 100644 --- a/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/LuceneSailBuffer.java +++ b/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/LuceneSailBuffer.java @@ -91,9 +91,9 @@ public static class Operation { public static class AddRemoveOperation extends Operation { - HashSet added = new HashSet(); + HashSet added = new HashSet<>(); - HashSet removed = new HashSet(); + HashSet removed = new HashSet<>(); public void add(Statement s) { if (!removed.remove(s)) @@ -142,7 +142,7 @@ public static class ClearOperation extends Operation { } - private ArrayList operations = new ArrayList(); + private ArrayList operations = new ArrayList<>(); /** * Add this statement to the buffer diff --git a/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/LuceneSailConnection.java b/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/LuceneSailConnection.java index b083f35ff..0fadff25a 100644 --- a/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/LuceneSailConnection.java +++ b/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/LuceneSailConnection.java @@ -350,7 +350,7 @@ private CloseableIteration evalu // use externally bound variables new BindingAssigner().optimize(tupleExpr, dataset, bindings); - List queries = new ArrayList(); + List queries = new ArrayList<>(); for (SearchQueryInterpreter interpreter : sail.getSearchQueryInterpreters()) { interpreter.process(tupleExpr, bindings, queries); @@ -464,7 +464,7 @@ private void addBindingSets(SearchQueryEvaluator query, BindingSetAssignment bin } // find existing bindings within the given (sub-)query - final List assignments = new ArrayList(); + final List assignments = new ArrayList<>(); QueryModelVisitor assignmentVisitor = new AbstractQueryModelVisitor() { @Override @@ -480,7 +480,7 @@ public void meet(BindingSetAssignment node) projection.visit(assignmentVisitor); // construct a list of binding sets - List bindingSetsList = new ArrayList(); + List bindingSetsList = new ArrayList<>(); bindingSetsList.add(bindingSets); // add existing bindings to the list of binding sets and remove them from @@ -564,7 +564,7 @@ private BindingSetAssignment crossJoin(BindingSetAssignment left, BindingSetAssi Iterable rightIter = right.getBindingSets(); int leftSize = size(leftIter, 16); int rightSize = size(rightIter, 16); - List output = new ArrayList(leftSize * rightSize); + List output = new ArrayList<>(leftSize * rightSize); for (BindingSet l : leftIter) { for (BindingSet r : rightIter) { @@ -575,7 +575,7 @@ private BindingSetAssignment crossJoin(BindingSetAssignment left, BindingSetAssi } } - Set bindingNames = new HashSet(left.getBindingNames()); + Set bindingNames = new HashSet<>(left.getBindingNames()); bindingNames.addAll(right.getBindingNames()); BindingSetAssignment bindings = new BindingSetAssignment(); diff --git a/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/PropertyCache.java b/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/PropertyCache.java index e9d769d3b..c56538f8b 100644 --- a/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/PropertyCache.java +++ b/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/PropertyCache.java @@ -37,7 +37,7 @@ boolean hasProperty(String name, String value) { found = false; List docValues = doc.getProperty(name); if (docValues != null) { - cachedValues = new HashSet(docValues.size()); + cachedValues = new HashSet<>(docValues.size()); for (String docValue : docValues) { cachedValues.add(docValue); if (docValue.equals(value)) { @@ -60,7 +60,7 @@ private Set getCachedValues(String name) { private void setCachedValues(String name, Set values) { if (cachedProperties == null) { - cachedProperties = new HashMap>(); + cachedProperties = new HashMap<>(); } cachedProperties.put(name, values); } diff --git a/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/QuerySpecBuilder.java b/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/QuerySpecBuilder.java index 264168ba9..c457bbfeb 100644 --- a/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/QuerySpecBuilder.java +++ b/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/QuerySpecBuilder.java @@ -70,7 +70,7 @@ public QuerySpecBuilder(boolean incompleteQueryFails) { public Set process(TupleExpr tupleExpr, BindingSet bindings) throws SailException { - HashSet result = new HashSet(); + HashSet result = new HashSet<>(); process(tupleExpr, bindings, (Collection)(Collection)result); return result; } @@ -277,17 +277,17 @@ private StatementPattern getPattern(Var subjectVar, ArrayList private static class PatternFilter extends AbstractQueryModelVisitor { - public ArrayList typePatterns = new ArrayList(); + public ArrayList typePatterns = new ArrayList<>(); - public ArrayList matchesPatterns = new ArrayList(); + public ArrayList matchesPatterns = new ArrayList<>(); - public ArrayList queryPatterns = new ArrayList(); + public ArrayList queryPatterns = new ArrayList<>(); - public ArrayList propertyPatterns = new ArrayList(); + public ArrayList propertyPatterns = new ArrayList<>(); - public ArrayList scorePatterns = new ArrayList(); + public ArrayList scorePatterns = new ArrayList<>(); - public ArrayList snippetPatterns = new ArrayList(); + public ArrayList snippetPatterns = new ArrayList<>(); /** * Method implementing the visitor pattern that gathers all statements using a predicate from the diff --git a/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/util/MapOfListMaps.java b/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/util/MapOfListMaps.java index 051260ba7..886c7f339 100644 --- a/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/util/MapOfListMaps.java +++ b/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/util/MapOfListMaps.java @@ -24,7 +24,7 @@ public class MapOfListMaps { * */ public MapOfListMaps() { - data = new HashMap>>(); + data = new HashMap<>(); } public List get(Index1Type key1, Index2Type key2) { @@ -52,14 +52,14 @@ public void add(Index1Type key1, Index2Type key2, DataType value) { List tmpList; if (intermediateMap == null) { - intermediateMap = new HashMap>(); + intermediateMap = new HashMap<>(); data.put(key1, intermediateMap); } tmpList = intermediateMap.get(key2); if (tmpList == null) { - tmpList = new ArrayList(); + tmpList = new ArrayList<>(); intermediateMap.put(key2, tmpList); } diff --git a/lucene-api/src/test/java/org/eclipse/rdf4j/sail/lucene/QuerySpecBuilderTest.java b/lucene-api/src/test/java/org/eclipse/rdf4j/sail/lucene/QuerySpecBuilderTest.java index fa120449a..c8821e627 100644 --- a/lucene-api/src/test/java/org/eclipse/rdf4j/sail/lucene/QuerySpecBuilderTest.java +++ b/lucene-api/src/test/java/org/eclipse/rdf4j/sail/lucene/QuerySpecBuilderTest.java @@ -213,7 +213,7 @@ private void checkQuery(String queryString) private Collection process(SearchQueryInterpreter interpreter, TupleExpr tupleExpr) throws SailException { - List queries = new ArrayList(); + List queries = new ArrayList<>(); interpreter.process(tupleExpr, new QueryBindingSet(), queries); return queries; } diff --git a/lucene/src/main/java/org/eclipse/rdf4j/sail/lucene/LuceneDocument.java b/lucene/src/main/java/org/eclipse/rdf4j/sail/lucene/LuceneDocument.java index aa0356b4a..bcd605643 100644 --- a/lucene/src/main/java/org/eclipse/rdf4j/sail/lucene/LuceneDocument.java +++ b/lucene/src/main/java/org/eclipse/rdf4j/sail/lucene/LuceneDocument.java @@ -88,7 +88,7 @@ public String getContext() { @Override public Set getPropertyNames() { List fields = doc.getFields(); - Set names = new HashSet(); + Set names = new HashSet<>(); for (IndexableField field : fields) { String name = field.name(); if (SearchFields.isPropertyField(name)) diff --git a/lucene/src/main/java/org/eclipse/rdf4j/sail/lucene/LuceneIndex.java b/lucene/src/main/java/org/eclipse/rdf4j/sail/lucene/LuceneIndex.java index 5ded24fee..337bebb39 100644 --- a/lucene/src/main/java/org/eclipse/rdf4j/sail/lucene/LuceneIndex.java +++ b/lucene/src/main/java/org/eclipse/rdf4j/sail/lucene/LuceneIndex.java @@ -522,7 +522,7 @@ private static Document getDocument(LeafReader reader, Term term) private List getDocuments(Term uriTerm) throws IOException { - List result = new ArrayList(); + List result = new ArrayList<>(); IndexReader reader = getIndexReader(); List leaves = reader.leaves(); @@ -678,7 +678,7 @@ private void logIndexStats() { Document doc; int totalFields = 0; - Set ids = new HashSet(); + Set ids = new HashSet<>(); String[] idArray; int count = 0; for (int i = 0; i < reader.maxDoc(); i++) { diff --git a/lucene/src/test/java/org/eclipse/rdf4j/sail/lucene/AbstractGenericLuceneTest.java b/lucene/src/test/java/org/eclipse/rdf4j/sail/lucene/AbstractGenericLuceneTest.java index 008f160b4..4ad173b1e 100644 --- a/lucene/src/test/java/org/eclipse/rdf4j/sail/lucene/AbstractGenericLuceneTest.java +++ b/lucene/src/test/java/org/eclipse/rdf4j/sail/lucene/AbstractGenericLuceneTest.java @@ -365,7 +365,7 @@ public void testSnippetQueries() // the first result is subject 1 and has a score int results = 0; - Set expectedSubject = new HashSet(); + Set expectedSubject = new HashSet<>(); expectedSubject.add(SUBJECT_1); expectedSubject.add(SUBJECT_2); while (result.hasNext()) { @@ -432,7 +432,7 @@ public void testSnippetLimitedToPredicate() // the first result is subject 1 and has a score int results = 0; - Set expectedSnippetPart = new HashSet(); + Set expectedSnippetPart = new HashSet<>(); expectedSnippetPart.add("come"); expectedSnippetPart.add("unicorn"); String notexpected = "poor"; @@ -511,7 +511,7 @@ public void testCharlyTerm() // the first result is subject 1 and has a score int results = 0; - Set expectedSnippetPart = new HashSet(); + Set expectedSnippetPart = new HashSet<>(); expectedSnippetPart.add("come"); expectedSnippetPart.add("unicorn"); expectedSnippetPart.add("poor"); @@ -741,7 +741,7 @@ public void testFuzzyQuery() // the first result is subject 1 and has a score int results = 0; - Set expectedSubject = new HashSet(); + Set expectedSubject = new HashSet<>(); expectedSubject.add(SUBJECT_1); expectedSubject.add(SUBJECT_2); expectedSubject.add(SUBJECT_3); @@ -792,7 +792,7 @@ public void testPropertyVar() TupleQuery query = connection.prepareTupleQuery(QueryLanguage.SERQL, q); try (TupleQueryResult result = query.evaluate()) { int results = 0; - Map expectedSubject = new HashMap(); + Map expectedSubject = new HashMap<>(); expectedSubject.put(SUBJECT_1, PREDICATE_1); expectedSubject.put(SUBJECT_2, PREDICATE_1); expectedSubject.put(SUBJECT_3, PREDICATE_2); diff --git a/lucene/src/test/java/org/eclipse/rdf4j/sail/lucene/LuceneIndexTest.java b/lucene/src/test/java/org/eclipse/rdf4j/sail/lucene/LuceneIndexTest.java index a009a99d8..2660a3e1d 100644 --- a/lucene/src/test/java/org/eclipse/rdf4j/sail/lucene/LuceneIndexTest.java +++ b/lucene/src/test/java/org/eclipse/rdf4j/sail/lucene/LuceneIndexTest.java @@ -237,8 +237,8 @@ public void testAddMultiple() throws Exception { // add a statement to an index - HashSet added = new HashSet(); - HashSet removed = new HashSet(); + HashSet added = new HashSet<>(); + HashSet removed = new HashSet<>(); added.add(statement11); added.add(statement12); added.add(statement21); @@ -264,7 +264,7 @@ public void testAddMultiple() assertStatement(statement22, document); // check if the text field stores all added string values - Set texts = new HashSet(); + Set texts = new HashSet<>(); texts.add("cats"); texts.add("dogs"); // FIXME diff --git a/memory/src/main/java/org/eclipse/rdf4j/sail/memory/MemEvaluationStatistics.java b/memory/src/main/java/org/eclipse/rdf4j/sail/memory/MemEvaluationStatistics.java index 8c886d96d..0da44c239 100644 --- a/memory/src/main/java/org/eclipse/rdf4j/sail/memory/MemEvaluationStatistics.java +++ b/memory/src/main/java/org/eclipse/rdf4j/sail/memory/MemEvaluationStatistics.java @@ -84,7 +84,7 @@ public double getCardinality(StatementPattern sp) { } // Search for the smallest list that can be used by the iterator - List listSizes = new ArrayList(4); + List listSizes = new ArrayList<>(4); if (memSubj != null) { listSizes.add(memSubj.getSubjectStatementCount()); } diff --git a/memory/src/main/java/org/eclipse/rdf4j/sail/memory/MemNamespaceStore.java b/memory/src/main/java/org/eclipse/rdf4j/sail/memory/MemNamespaceStore.java index 59cc114ae..6d4f82753 100644 --- a/memory/src/main/java/org/eclipse/rdf4j/sail/memory/MemNamespaceStore.java +++ b/memory/src/main/java/org/eclipse/rdf4j/sail/memory/MemNamespaceStore.java @@ -27,7 +27,7 @@ class MemNamespaceStore implements Iterable { /** * Map storing namespace information by their prefix. */ - private final Map namespacesMap = new LinkedHashMap(16); + private final Map namespacesMap = new LinkedHashMap<>(16); /*---------* * Methods * diff --git a/memory/src/main/java/org/eclipse/rdf4j/sail/memory/MemorySailStore.java b/memory/src/main/java/org/eclipse/rdf4j/sail/memory/MemorySailStore.java index 93443b173..4c1d2c5fe 100644 --- a/memory/src/main/java/org/eclipse/rdf4j/sail/memory/MemorySailStore.java +++ b/memory/src/main/java/org/eclipse/rdf4j/sail/memory/MemorySailStore.java @@ -164,19 +164,19 @@ private CloseableIteration createStatementIterator( MemResource memSubj = valueFactory.getMemResource(subj); if (subj != null && memSubj == null) { // non-existent subject - return new EmptyIteration(); + return new EmptyIteration<>(); } MemIRI memPred = valueFactory.getMemURI(pred); if (pred != null && memPred == null) { // non-existent predicate - return new EmptyIteration(); + return new EmptyIteration<>(); } MemValue memObj = valueFactory.getMemValue(obj); if (obj != null && memObj == null) { // non-existent object - return new EmptyIteration(); + return new EmptyIteration<>(); } MemResource[] memContexts; @@ -190,14 +190,14 @@ else if (contexts.length == 1 && contexts[0] != null) { MemResource memContext = valueFactory.getMemResource(contexts[0]); if (memContext == null) { // non-existent context - return new EmptyIteration(); + return new EmptyIteration<>(); } memContexts = new MemResource[] { memContext }; smallestList = memContext.getContextStatementList(); } else { - Set contextSet = new LinkedHashSet(2 * contexts.length); + Set contextSet = new LinkedHashSet<>(2 * contexts.length); for (Resource context : contexts) { MemResource memContext = valueFactory.getMemResource(context); @@ -208,7 +208,7 @@ else if (contexts.length == 1 && contexts[0] != null) { if (contextSet.isEmpty()) { // no known contexts specified - return new EmptyIteration(); + return new EmptyIteration<>(); } memContexts = contextSet.toArray(new MemResource[contextSet.size()]); @@ -236,7 +236,7 @@ else if (contexts.length == 1 && contexts[0] != null) { } } - return new MemStatementIterator(smallestList, memSubj, memPred, memObj, explicit, + return new MemStatementIterator<>(smallestList, memSubj, memPred, memObj, explicit, snapshot, memContexts); } @@ -253,10 +253,10 @@ protected void cleanSnapshots() // long startTime = System.currentTimeMillis(); // Sets used to keep track of which lists have already been processed - HashSet processedSubjects = new HashSet(); - HashSet processedPredicates = new HashSet(); - HashSet processedObjects = new HashSet(); - HashSet processedContexts = new HashSet(); + HashSet processedSubjects = new HashSet<>(); + HashSet processedPredicates = new HashSet<>(); + HashSet processedObjects = new HashSet<>(); + HashSet processedContexts = new HashSet<>(); int lastStmtPos; Lock stReadLock = statementListLockManager.getReadLock(); @@ -514,7 +514,7 @@ public synchronized void observe(Resource subj, IRI pred, Value obj, Resource... throws SailException { if (observations == null) { - observations = new HashSet(); + observations = new HashSet<>(); } if (contexts == null) { observations.add(new StatementPattern(new Var("s", subj), new Var("p", pred), @@ -705,7 +705,7 @@ public CloseableIteration getContextIDs() // ConcurrentModificationException's (issue SES-544). // Create a list of all resources that are used as contexts - ArrayList contextIDs = new ArrayList(32); + ArrayList contextIDs = new ArrayList<>(32); Lock stLock = openStatementsReadLock(); try { @@ -728,7 +728,7 @@ public CloseableIteration getContextIDs() stLock.release(); } - return new CloseableIteratorIteration(contextIDs.iterator()); + return new CloseableIteratorIteration<>(contextIDs.iterator()); } @Override @@ -788,7 +788,7 @@ private boolean isContextResource(MemResource memResource, int snapshot) // Filter more thoroughly by considering snapshot and read-mode // parameters - try (MemStatementIterator iter = new MemStatementIterator( + try (MemStatementIterator iter = new MemStatementIterator<>( contextStatements, null, null, null, null, snapshot);) { return iter.hasNext(); diff --git a/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/MemValueFactory.java b/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/MemValueFactory.java index cc3b518ba..a4e5653b2 100644 --- a/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/MemValueFactory.java +++ b/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/MemValueFactory.java @@ -41,25 +41,25 @@ public class MemValueFactory extends AbstractValueFactory { * Registry containing the set of MemURI objects as used by a MemoryStore. This registry enables the reuse * of objects, minimizing the number of objects in main memory. */ - private final WeakObjectRegistry uriRegistry = new WeakObjectRegistry(); + private final WeakObjectRegistry uriRegistry = new WeakObjectRegistry<>(); /** * Registry containing the set of MemBNode objects as used by a MemoryStore. This registry enables the * reuse of objects, minimizing the number of objects in main memory. */ - private final WeakObjectRegistry bnodeRegistry = new WeakObjectRegistry(); + private final WeakObjectRegistry bnodeRegistry = new WeakObjectRegistry<>(); /** * Registry containing the set of MemLiteral objects as used by a MemoryStore. This registry enables the * reuse of objects, minimizing the number of objects in main memory. */ - private final WeakObjectRegistry literalRegistry = new WeakObjectRegistry(); + private final WeakObjectRegistry literalRegistry = new WeakObjectRegistry<>(); /** * Registry containing the set of namespce strings as used by MemURI objects in a MemoryStore. This * registry enables the reuse of objects, minimizing the number of objects in main memory. */ - private final WeakObjectRegistry namespaceRegistry = new WeakObjectRegistry(); + private final WeakObjectRegistry namespaceRegistry = new WeakObjectRegistry<>(); /*---------* * Methods * diff --git a/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/WeakObjectRegistry.java b/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/WeakObjectRegistry.java index 4b19f196c..8d8cc5faa 100644 --- a/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/WeakObjectRegistry.java +++ b/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/WeakObjectRegistry.java @@ -29,7 +29,7 @@ public class WeakObjectRegistry extends AbstractSet { /** * The hash map that is used to store the objects. */ - private final Map> objectMap = new WeakHashMap>(); + private final Map> objectMap = new WeakHashMap<>(); /*--------------* * Constructors * @@ -94,7 +94,7 @@ public boolean contains(Object o) { @Override public boolean add(E object) { - WeakReference ref = new WeakReference(object); + WeakReference ref = new WeakReference<>(object); ref = objectMap.put(object, ref); diff --git a/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/ConcurrentCache.java b/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/ConcurrentCache.java index 1a47fef4c..cdbd0fd88 100644 --- a/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/ConcurrentCache.java +++ b/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/ConcurrentCache.java @@ -32,7 +32,7 @@ public class ConcurrentCache { public ConcurrentCache(int capacity) { this.capacity = capacity; - this.cache = new ConcurrentHashMap((int)(capacity / LOAD_FACTOR), LOAD_FACTOR); + this.cache = new ConcurrentHashMap<>((int)(capacity / LOAD_FACTOR), LOAD_FACTOR); } public V get(Object key) { diff --git a/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/NamespaceStore.java b/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/NamespaceStore.java index 6e901ecac..7ba8d71e1 100644 --- a/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/NamespaceStore.java +++ b/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/NamespaceStore.java @@ -83,7 +83,7 @@ public NamespaceStore(File dataDir) { file = new File(dataDir, FILE_NAME); - namespacesMap = new LinkedHashMap(16); + namespacesMap = new LinkedHashMap<>(16); if (file.exists()) { readNamespacesFromFile(); diff --git a/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/NativeSailStore.java b/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/NativeSailStore.java index 8cc407a43..361f98d77 100644 --- a/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/NativeSailStore.java +++ b/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/NativeSailStore.java @@ -160,11 +160,11 @@ List getContextIDs(Resource... contexts) assert contexts.length > 0 : "contexts must not be empty"; // Filter duplicates - LinkedHashSet contextSet = new LinkedHashSet(); + LinkedHashSet contextSet = new LinkedHashSet<>(); Collections.addAll(contextSet, contexts); // Fetch IDs, filtering unknown resources from the result - List contextIDs = new ArrayList(contextSet.size()); + List contextIDs = new ArrayList<>(contextSet.size()); for (Resource context : contextSet) { if (context == null) { contextIDs.add(0); @@ -203,7 +203,7 @@ CloseableIteration createStatementIterator(R if (subj != null) { subjID = valueStore.getID(subj); if (subjID == NativeValue.UNKNOWN_ID) { - return new EmptyIteration(); + return new EmptyIteration<>(); } } @@ -211,7 +211,7 @@ CloseableIteration createStatementIterator(R if (pred != null) { predID = valueStore.getID(pred); if (predID == NativeValue.UNKNOWN_ID) { - return new EmptyIteration(); + return new EmptyIteration<>(); } } @@ -219,11 +219,11 @@ CloseableIteration createStatementIterator(R if (obj != null) { objID = valueStore.getID(obj); if (objID == NativeValue.UNKNOWN_ID) { - return new EmptyIteration(); + return new EmptyIteration<>(); } } - List contextIDList = new ArrayList(contexts.length); + List contextIDList = new ArrayList<>(contexts.length); if (contexts.length == 0) { contextIDList.add(NativeValue.UNKNOWN_ID); } @@ -242,7 +242,7 @@ CloseableIteration createStatementIterator(R } } - ArrayList perContextIterList = new ArrayList( + ArrayList perContextIterList = new ArrayList<>( contextIDList.size()); for (int contextID : contextIDList) { @@ -256,7 +256,7 @@ CloseableIteration createStatementIterator(R return perContextIterList.get(0); } else { - return new UnionIteration(perContextIterList); + return new UnionIteration<>(perContextIterList); } } @@ -547,7 +547,7 @@ private int removeStatements(Resource subj, IRI pred, Value obj, boolean explici } } - List contextIDList = new ArrayList(contexts.length); + List contextIDList = new ArrayList<>(contexts.length); if (contexts.length == 0) { contextIDList.add(NativeValue.UNKNOWN_ID); } @@ -658,11 +658,11 @@ protected Resource convert(Statement st) { }; if (btreeIter == null) { // Filtering any duplicates - ctxIter2 = new DistinctIteration(ctxIter1); + ctxIter2 = new DistinctIteration<>(ctxIter1); } else { // Filtering sorted duplicates - ctxIter2 = new ReducedIteration(ctxIter1); + ctxIter2 = new ReducedIteration<>(ctxIter1); } result = new ExceptionConvertingIteration(ctxIter2) { diff --git a/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/SailSourceModel.java b/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/SailSourceModel.java index 60e6e964b..4912a0a45 100644 --- a/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/SailSourceModel.java +++ b/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/SailSourceModel.java @@ -175,7 +175,7 @@ public synchronized int size() { @Override public Set getNamespaces() { - Set set = new LinkedHashSet(); + Set set = new LinkedHashSet<>(); try { CloseableIteration spaces; spaces = dataset().getNamespaces(); @@ -472,7 +472,7 @@ Resource[] cast(Value[] contexts) { result[i] = (Resource)contexts[i]; } else { - List list = new ArrayList(); + List list = new ArrayList<>(); for (Value v : contexts) { if (v == null || v instanceof Resource) { list.add((Resource)v); diff --git a/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/TripleStore.java b/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/TripleStore.java index 1997efdbd..693c9ea7f 100644 --- a/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/TripleStore.java +++ b/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/TripleStore.java @@ -137,7 +137,7 @@ class TripleStore implements Closeable { /** * The list of triple indexes that are used to store and retrieve triples. */ - private final List indexes = new ArrayList(); + private final List indexes = new ArrayList<>(); private final boolean forceSync; @@ -276,7 +276,7 @@ private Set getIndexSpecs() private Set parseIndexSpecList(String indexSpecStr) throws SailException { - Set indexes = new HashSet(); + Set indexes = new HashSet<>(); if (indexSpecStr != null) { StringTokenizer tok = new StringTokenizer(indexSpecStr, ", \t"); @@ -362,14 +362,14 @@ private void processUncompletedTransaction(TxnStatus txnStatus) private void reindex(Set currentIndexSpecs, Set newIndexSpecs) throws IOException, SailException { - Map currentIndexes = new HashMap(); + Map currentIndexes = new HashMap<>(); for (TripleIndex index : indexes) { currentIndexes.put(new String(index.getFieldSeq()), index); } // Determine the set of newly added indexes and initialize these using an // existing index as source - Set addedIndexSpecs = new HashSet(newIndexSpecs); + Set addedIndexSpecs = new HashSet<>(newIndexSpecs); addedIndexSpecs.removeAll(currentIndexSpecs); if (!addedIndexSpecs.isEmpty()) { @@ -409,7 +409,7 @@ private void reindex(Set currentIndexSpecs, Set newIndexSpecs) } // Determine the set of removed indexes - Set removedIndexSpecs = new HashSet(currentIndexSpecs); + Set removedIndexSpecs = new HashSet<>(currentIndexSpecs); removedIndexSpecs.removeAll(newIndexSpecs); List removedIndexExceptions = new ArrayList<>(); diff --git a/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/ValueStore.java b/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/ValueStore.java index d35f13f21..9000b335e 100644 --- a/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/ValueStore.java +++ b/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/ValueStore.java @@ -140,10 +140,10 @@ public ValueStore(File dataDir, boolean forceSync, int valueCacheSize, int value super(); dataStore = new DataStore(dataDir, FILENAME_PREFIX, forceSync); - valueCache = new ConcurrentCache(valueCacheSize); - valueIDCache = new ConcurrentCache(valueIDCacheSize); - namespaceCache = new ConcurrentCache(namespaceCacheSize); - namespaceIDCache = new ConcurrentCache(namespaceIDCacheSize); + valueCache = new ConcurrentCache<>(valueCacheSize); + valueIDCache = new ConcurrentCache<>(valueIDCacheSize); + namespaceCache = new ConcurrentCache<>(namespaceCacheSize); + namespaceIDCache = new ConcurrentCache<>(namespaceIDCacheSize); setNewRevision(); } diff --git a/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/btree/BTree.java b/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/btree/BTree.java index 51d8738dc..2e461c0ce 100644 --- a/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/btree/BTree.java +++ b/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/btree/BTree.java @@ -597,7 +597,7 @@ private List getPath(byte[] key) { assert key != null : "key must not be null"; - List path = new ArrayList(height()); + List path = new ArrayList<>(height()); Node currentNode = readRootNode(); diff --git a/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/btree/Node.java b/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/btree/Node.java index a9fc7aa7d..ec9082694 100644 --- a/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/btree/Node.java +++ b/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/btree/Node.java @@ -37,7 +37,7 @@ class Node { private boolean dataChanged; /** Registered listeners that want to be notified of changes to the node. */ - private final ConcurrentLinkedDeque listeners = new ConcurrentLinkedDeque(); + private final ConcurrentLinkedDeque listeners = new ConcurrentLinkedDeque<>(); /** * Creates a new Node object with the specified ID. diff --git a/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/btree/RangeIterator.java b/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/btree/RangeIterator.java index e5225e5d9..a72970090 100644 --- a/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/btree/RangeIterator.java +++ b/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/btree/RangeIterator.java @@ -37,12 +37,12 @@ class RangeIterator implements RecordIterator, NodeListener { /** * Tracks the parent nodes of {@link #currentNode}. */ - private final LinkedList parentNodeStack = new LinkedList(); + private final LinkedList parentNodeStack = new LinkedList<>(); /** * Tracks the index of child nodes in parent nodes. */ - private final LinkedList parentIndexStack = new LinkedList(); + private final LinkedList parentIndexStack = new LinkedList<>(); private volatile int currentIdx; diff --git a/repository-dataset/src/main/java/org/eclipse/rdf4j/repository/dataset/DatasetRepository.java b/repository-dataset/src/main/java/org/eclipse/rdf4j/repository/dataset/DatasetRepository.java index 64c1034dc..e66d9f9e9 100644 --- a/repository-dataset/src/main/java/org/eclipse/rdf4j/repository/dataset/DatasetRepository.java +++ b/repository-dataset/src/main/java/org/eclipse/rdf4j/repository/dataset/DatasetRepository.java @@ -34,7 +34,7 @@ */ public class DatasetRepository extends RepositoryWrapper { - private Map lastModified = new ConcurrentHashMap(); + private Map lastModified = new ConcurrentHashMap<>(); public DatasetRepository() { super(); diff --git a/repository-sail/src/main/java/org/eclipse/rdf4j/repository/sail/SailRepositoryConnection.java b/repository-sail/src/main/java/org/eclipse/rdf4j/repository/sail/SailRepositoryConnection.java index 8f6b99302..314a60ee3 100644 --- a/repository-sail/src/main/java/org/eclipse/rdf4j/repository/sail/SailRepositoryConnection.java +++ b/repository-sail/src/main/java/org/eclipse/rdf4j/repository/sail/SailRepositoryConnection.java @@ -488,7 +488,7 @@ public String getNamespace(String prefix) protected RepositoryResult createRepositoryResult( CloseableIteration sailIter) { - return new RepositoryResult(new SailCloseableIteration(sailIter)); + return new RepositoryResult<>(new SailCloseableIteration(sailIter)); } @Override diff --git a/repository-sail/src/main/java/org/eclipse/rdf4j/repository/sail/SailTupleQuery.java b/repository-sail/src/main/java/org/eclipse/rdf4j/repository/sail/SailTupleQuery.java index e575a4eee..3c6f0b988 100644 --- a/repository-sail/src/main/java/org/eclipse/rdf4j/repository/sail/SailTupleQuery.java +++ b/repository-sail/src/main/java/org/eclipse/rdf4j/repository/sail/SailTupleQuery.java @@ -55,7 +55,7 @@ public TupleQueryResult evaluate() getIncludeInferred()); bindingsIter2 = enforceMaxQueryTime(bindingsIter1); - result = new IteratingTupleQueryResult(new ArrayList(tupleExpr.getBindingNames()), + result = new IteratingTupleQueryResult(new ArrayList<>(tupleExpr.getBindingNames()), bindingsIter2); allGood = true; return result; diff --git a/repository-sail/src/main/java/org/eclipse/rdf4j/repository/sail/helpers/SailUpdateExecutor.java b/repository-sail/src/main/java/org/eclipse/rdf4j/repository/sail/helpers/SailUpdateExecutor.java index ed269636c..a2d755774 100644 --- a/repository-sail/src/main/java/org/eclipse/rdf4j/repository/sail/helpers/SailUpdateExecutor.java +++ b/repository-sail/src/main/java/org/eclipse/rdf4j/repository/sail/helpers/SailUpdateExecutor.java @@ -587,7 +587,7 @@ protected BindingSet convert(BindingSet sourceBinding) // check if any supplied bindings do not occur in the // bindingset // produced by the WHERE clause. If so, merge. - Set uniqueBindings = new HashSet( + Set uniqueBindings = new HashSet<>( uc.getBindingSet().getBindingNames()); uniqueBindings.removeAll(sourceBinding.getBindingNames()); if (uniqueBindings.size() > 0) { diff --git a/sail-api/src/main/java/org/eclipse/rdf4j/common/concurrent/locks/LockManager.java b/sail-api/src/main/java/org/eclipse/rdf4j/common/concurrent/locks/LockManager.java index 386add7ee..1a7aad384 100644 --- a/sail-api/src/main/java/org/eclipse/rdf4j/common/concurrent/locks/LockManager.java +++ b/sail-api/src/main/java/org/eclipse/rdf4j/common/concurrent/locks/LockManager.java @@ -65,7 +65,7 @@ private static class WeakLockReference { /** * Set of active locks. */ - private final Set activeLocks = new HashSet(); + private final Set activeLocks = new HashSet<>(); /** * Create a new set of locks. @@ -129,7 +129,7 @@ public void waitForActiveLocks() synchronized (activeLocks) { if (activeLocks.isEmpty()) return; - before = new HashSet(activeLocks); + before = new HashSet<>(activeLocks); if (now < 0) { now = System.currentTimeMillis(); } @@ -191,7 +191,7 @@ public String toString() { } } }; - weak.reference = new WeakReference(lock); + weak.reference = new WeakReference<>(lock); synchronized (activeLocks) { activeLocks.add(weak); } diff --git a/sail-api/src/main/java/org/eclipse/rdf4j/sail/helpers/AbstractNotifyingSail.java b/sail-api/src/main/java/org/eclipse/rdf4j/sail/helpers/AbstractNotifyingSail.java index 7c08ee29e..862714286 100644 --- a/sail-api/src/main/java/org/eclipse/rdf4j/sail/helpers/AbstractNotifyingSail.java +++ b/sail-api/src/main/java/org/eclipse/rdf4j/sail/helpers/AbstractNotifyingSail.java @@ -33,7 +33,7 @@ public abstract class AbstractNotifyingSail extends AbstractSail implements Noti /** * Objects that should be notified of changes to the data in this Sail. */ - private Set sailChangedListeners = new HashSet(0); + private Set sailChangedListeners = new HashSet<>(0); /*---------* * Methods * diff --git a/sail-api/src/main/java/org/eclipse/rdf4j/sail/helpers/AbstractSail.java b/sail-api/src/main/java/org/eclipse/rdf4j/sail/helpers/AbstractSail.java index fe47111fd..35d245f06 100644 --- a/sail-api/src/main/java/org/eclipse/rdf4j/sail/helpers/AbstractSail.java +++ b/sail-api/src/main/java/org/eclipse/rdf4j/sail/helpers/AbstractSail.java @@ -53,7 +53,7 @@ public abstract class AbstractSail implements Sail { * and {@link IsolationLevels#SERIALIZABLE}. Specific store implementations are expected to alter this * list according to their specific capabilities. */ - private List supportedIsolationLevels = new ArrayList(); + private List supportedIsolationLevels = new ArrayList<>(); /** * default value for the Iteration item sync threshold @@ -114,7 +114,7 @@ protected static boolean debugEnabled() { * Map used to track active connections and where these were acquired. The Throwable value may be null in * case debugging was disable at the time the connection was acquired. */ - private final Map activeConnections = new IdentityHashMap(); + private final Map activeConnections = new IdentityHashMap<>(); /* * constructors @@ -238,7 +238,7 @@ public void shutDown() // Copy the current contents of the map so that we don't have to // synchronize on activeConnections. This prevents a potential // deadlock with concurrent calls to connectionClosed() - activeConnectionsCopy = new IdentityHashMap(activeConnections); + activeConnectionsCopy = new IdentityHashMap<>(activeConnections); } // Forcefully close any connections that are still open diff --git a/sail-api/src/main/java/org/eclipse/rdf4j/sail/helpers/AbstractSailConnection.java b/sail-api/src/main/java/org/eclipse/rdf4j/sail/helpers/AbstractSailConnection.java index ecbb1dffd..8213caf90 100644 --- a/sail-api/src/main/java/org/eclipse/rdf4j/sail/helpers/AbstractSailConnection.java +++ b/sail-api/src/main/java/org/eclipse/rdf4j/sail/helpers/AbstractSailConnection.java @@ -84,17 +84,17 @@ public abstract class AbstractSailConnection implements SailConnection { */ protected final ReentrantLock updateLock = new ReentrantLock(); - private final Map activeIterations = new IdentityHashMap(); + private final Map activeIterations = new IdentityHashMap<>(); /** * Statements that are currently being removed, but not yet realized, by an active operation. */ - private final Map> removed = new HashMap>(); + private final Map> removed = new HashMap<>(); /** * Statements that are currently being added, but not yet realized, by an active operation. */ - private final Map> added = new HashMap>(); + private final Map> added = new HashMap<>(); /** * Used to indicate a removed statement from all contexts. @@ -514,12 +514,12 @@ public void startUpdate(UpdateContext op) } synchronized (removed) { assert !removed.containsKey(op); - removed.put(op, new LinkedList()); + removed.put(op, new LinkedList<>()); } synchronized (added) { assert !added.containsKey(op); - added.put(op, new LinkedList()); + added.put(op, new LinkedList<>()); } } @@ -799,7 +799,7 @@ protected org.eclipse.rdf4j.common.concurrent.locks.Lock getTransactionLock() protected CloseableIteration registerIteration( CloseableIteration iter) { - SailBaseIteration result = new SailBaseIteration(iter, this); + SailBaseIteration result = new SailBaseIteration<>(iter, this); Throwable stackTrace = debugEnabled ? new Throwable() : null; synchronized (activeIterations) { activeIterations.put(result, stackTrace); @@ -887,7 +887,7 @@ private void forceCloseActiveOperations() // Copy the current contents of the map so that we don't have to // synchronize on activeIterations. This prevents a potential // deadlock with concurrent calls to connectionClosed() - activeIterationsCopy = new IdentityHashMap(activeIterations); + activeIterationsCopy = new IdentityHashMap<>(activeIterations); activeIterations.clear(); } diff --git a/sail-api/src/main/java/org/eclipse/rdf4j/sail/helpers/NotifyingSailConnectionBase.java b/sail-api/src/main/java/org/eclipse/rdf4j/sail/helpers/NotifyingSailConnectionBase.java index 60b226168..8c446ab73 100644 --- a/sail-api/src/main/java/org/eclipse/rdf4j/sail/helpers/NotifyingSailConnectionBase.java +++ b/sail-api/src/main/java/org/eclipse/rdf4j/sail/helpers/NotifyingSailConnectionBase.java @@ -36,7 +36,7 @@ public abstract class NotifyingSailConnectionBase extends AbstractSailConnection public NotifyingSailConnectionBase(AbstractSail sailBase) { super(sailBase); - listeners = new ArrayList(0); + listeners = new ArrayList<>(0); } /*---------* diff --git a/sail-base/src/main/java/org/eclipse/rdf4j/sail/base/Changeset.java b/sail-base/src/main/java/org/eclipse/rdf4j/sail/base/Changeset.java index 7c80478ff..e7931d40c 100644 --- a/sail-base/src/main/java/org/eclipse/rdf4j/sail/base/Changeset.java +++ b/sail-base/src/main/java/org/eclipse/rdf4j/sail/base/Changeset.java @@ -129,7 +129,7 @@ public void prepare() public synchronized void addRefback(SailDatasetImpl dataset) { if (refbacks == null) { - refbacks = new HashSet(); + refbacks = new HashSet<>(); } refbacks.add(dataset); } @@ -146,7 +146,7 @@ public synchronized boolean isRefback() { public synchronized void prepend(Changeset changeset) { if (prepend == null) { - prepend = new HashSet(); + prepend = new HashSet<>(); } prepend.add(changeset); } @@ -154,11 +154,11 @@ public synchronized void prepend(Changeset changeset) { @Override public synchronized void setNamespace(String prefix, String name) { if (removedPrefixes == null) { - removedPrefixes = new HashSet(); + removedPrefixes = new HashSet<>(); } removedPrefixes.add(prefix); if (addedNamespaces == null) { - addedNamespaces = new HashMap(); + addedNamespaces = new HashMap<>(); } addedNamespaces.put(prefix, name); } @@ -169,7 +169,7 @@ public synchronized void removeNamespace(String prefix) { addedNamespaces.remove(prefix); } if (removedPrefixes == null) { - removedPrefixes = new HashSet(); + removedPrefixes = new HashSet<>(); } removedPrefixes.add(prefix); } @@ -190,7 +190,7 @@ public synchronized void observe(Resource subj, IRI pred, Value obj, Resource... throws SailConflictException { if (observations == null) { - observations = new HashSet(); + observations = new HashSet<>(); } if (contexts == null) { observations.add(new StatementPattern(new Var("s", subj), new Var("p", pred), new Var("o", obj), @@ -226,7 +226,7 @@ public synchronized void clear(Resource... contexts) { approvedContexts.removeAll(Arrays.asList(contexts)); } if (deprecatedContexts == null) { - deprecatedContexts = new HashSet(); + deprecatedContexts = new HashSet<>(); } deprecatedContexts.addAll(Arrays.asList(contexts)); } @@ -243,7 +243,7 @@ public synchronized void approve(Resource subj, IRI pred, Value obj, Resource ct approved.add(subj, pred, obj, ctx); if (ctx != null) { if (approvedContexts == null) { - approvedContexts = new HashSet(); + approvedContexts = new HashSet<>(); } approvedContexts.add(ctx); } diff --git a/sail-base/src/main/java/org/eclipse/rdf4j/sail/base/SailDatasetImpl.java b/sail-base/src/main/java/org/eclipse/rdf4j/sail/base/SailDatasetImpl.java index ae6de8cf4..54e80f5d7 100644 --- a/sail-base/src/main/java/org/eclipse/rdf4j/sail/base/SailDatasetImpl.java +++ b/sail-base/src/main/java/org/eclipse/rdf4j/sail/base/SailDatasetImpl.java @@ -95,7 +95,7 @@ public CloseableIteration getNamespaces() { final CloseableIteration namespaces; if (changes.isNamespaceCleared()) { - namespaces = new EmptyIteration(); + namespaces = new EmptyIteration<>(); } else { namespaces = derivedFrom.getNamespaces(); @@ -289,7 +289,7 @@ public CloseableIteration getStatements(Reso iter = null; } else if (contexts.length > 0 && deprecatedContexts != null) { - List remaining = new ArrayList(Arrays.asList(contexts)); + List remaining = new ArrayList<>(Arrays.asList(contexts)); remaining.removeAll(deprecatedContexts); iter = derivedFrom.getStatements(subj, pred, obj, contexts); } @@ -306,13 +306,13 @@ else if (contexts.length > 0 && deprecatedContexts != null) { } else if (approved != null) { Iterator i = approved.filter(subj, pred, obj, contexts).iterator(); - return new CloseableIteratorIteration(i); + return new CloseableIteratorIteration<>(i); } else if (iter != null) { return iter; } else { - return new EmptyIteration(); + return new EmptyIteration<>(); } } @@ -339,8 +339,8 @@ private CloseableIteration union( } final Iterator iter = included.iterator(); CloseableIteration incl; - incl = new CloseableIteratorIteration(iter); - return new UnionIteration(incl, result); + incl = new CloseableIteratorIteration<>(iter); + return new UnionIteration<>(incl, result); } } diff --git a/sail-base/src/main/java/org/eclipse/rdf4j/sail/base/SailSourceBranch.java b/sail-base/src/main/java/org/eclipse/rdf4j/sail/base/SailSourceBranch.java index 1093a1113..33bf77ef0 100644 --- a/sail-base/src/main/java/org/eclipse/rdf4j/sail/base/SailSourceBranch.java +++ b/sail-base/src/main/java/org/eclipse/rdf4j/sail/base/SailSourceBranch.java @@ -46,18 +46,18 @@ class SailSourceBranch implements SailSource { /** * The difference between this {@link SailSource} and the backing {@link SailSource}. */ - private final LinkedList changes = new LinkedList(); + private final LinkedList changes = new LinkedList<>(); /** * {@link SailSink} that have been created, but not yet {@link SailSink#flush()}ed to this * {@link SailSource}. */ - private final Collection pending = new LinkedList(); + private final Collection pending = new LinkedList<>(); /** * Set of open {@link SailDataset} for this {@link SailSource}. */ - private final Collection observers = new LinkedList(); + private final Collection observers = new LinkedList<>(); /** * The underly {@link SailSource} this {@link SailSource} is derived from. diff --git a/sail-base/src/main/java/org/eclipse/rdf4j/sail/base/SailSourceConnection.java b/sail-base/src/main/java/org/eclipse/rdf4j/sail/base/SailSourceConnection.java index 985495915..0883cdcfb 100644 --- a/sail-base/src/main/java/org/eclipse/rdf4j/sail/base/SailSourceConnection.java +++ b/sail-base/src/main/java/org/eclipse/rdf4j/sail/base/SailSourceConnection.java @@ -80,12 +80,12 @@ public boolean pendingRemovals() { /** * The state of store for outstanding operations. */ - private final Map datasets = new HashMap(); + private final Map datasets = new HashMap<>(); /** * Outstanding changes that are underway, but not yet realized, by an active operation. */ - private final Map explicitSinks = new HashMap(); + private final Map explicitSinks = new HashMap<>(); /** * Set of explicit statements that must not be inferred. diff --git a/sail-base/src/main/java/org/eclipse/rdf4j/sail/base/UnionSailDataset.java b/sail-base/src/main/java/org/eclipse/rdf4j/sail/base/UnionSailDataset.java index ee4c27a51..deb4ae20b 100644 --- a/sail-base/src/main/java/org/eclipse/rdf4j/sail/base/UnionSailDataset.java +++ b/sail-base/src/main/java/org/eclipse/rdf4j/sail/base/UnionSailDataset.java @@ -106,7 +106,7 @@ public CloseableIteration getStatements(Reso private CloseableIteration union( CloseableIteration[] items) { - return new UnionIteration(items); + return new UnionIteration<>(items); } } diff --git a/sail-spin/src/main/java/org/eclipse/rdf4j/sail/SailConnectionTupleQuery.java b/sail-spin/src/main/java/org/eclipse/rdf4j/sail/SailConnectionTupleQuery.java index 76ea3598b..31b46a9fc 100644 --- a/sail-spin/src/main/java/org/eclipse/rdf4j/sail/SailConnectionTupleQuery.java +++ b/sail-spin/src/main/java/org/eclipse/rdf4j/sail/SailConnectionTupleQuery.java @@ -50,7 +50,7 @@ public TupleQueryResult evaluate() bindingsIter = enforceMaxQueryTime(bindingsIter); - return new TupleQueryResultImpl(new ArrayList(tupleExpr.getBindingNames()), bindingsIter); + return new TupleQueryResultImpl(new ArrayList<>(tupleExpr.getBindingNames()), bindingsIter); } catch (SailException e) { throw new QueryEvaluationException(e.getMessage(), e); diff --git a/sail-spin/src/main/java/org/eclipse/rdf4j/sail/spin/SpinMagicPropertyInterpreter.java b/sail-spin/src/main/java/org/eclipse/rdf4j/sail/spin/SpinMagicPropertyInterpreter.java index a74159404..8d88e9c5b 100644 --- a/sail-spin/src/main/java/org/eclipse/rdf4j/sail/spin/SpinMagicPropertyInterpreter.java +++ b/sail-spin/src/main/java/org/eclipse/rdf4j/sail/spin/SpinMagicPropertyInterpreter.java @@ -106,8 +106,8 @@ private class PropertyScanner extends QueryModelVisitorBase { private void processGraphPattern(List sps) throws RDF4JException { - Map magicProperties = new LinkedHashMap(); - Map>> spIndex = new HashMap>>(); + Map magicProperties = new LinkedHashMap<>(); + Map>> spIndex = new HashMap<>(); for (StatementPattern sp : sps) { IRI pred = (IRI)sp.getPredicateVar().getValue(); @@ -129,12 +129,12 @@ private void processGraphPattern(List sps) String subj = sp.getSubjectVar().getName(); Map> predMap = spIndex.get(subj); if (predMap == null) { - predMap = new HashMap>(8); + predMap = new HashMap<>(8); spIndex.put(subj, predMap); } List v = predMap.get(pred); if (v == null) { - v = new ArrayList(1); + v = new ArrayList<>(1); predMap.put(pred, v); } v.add(sp); @@ -199,7 +199,7 @@ private void processGraphPattern(List sps) catch (Exception e) { throw new MalformedQueryException(e); } - Map prefixDecls = new HashMap(8); + Map prefixDecls = new HashMap<>(8); prefixDecls.put(SP.PREFIX, SP.NAMESPACE); prefixDecls.put(SPIN.PREFIX, SPIN.NAMESPACE); prefixDecls.put(SPL.PREFIX, SPL.NAMESPACE); @@ -278,7 +278,7 @@ private TupleExpr addList(List list, Var subj, public void meet(Join node) throws RDF4JException { - BGPCollector collector = new BGPCollector(this); + BGPCollector collector = new BGPCollector<>(this); node.visit(collector); processGraphPattern(collector.getStatementPatterns()); } diff --git a/sail-spin/src/main/java/org/eclipse/rdf4j/sail/spin/SpinSailConnection.java b/sail-spin/src/main/java/org/eclipse/rdf4j/sail/spin/SpinSailConnection.java index 9a40799ea..173f0989f 100644 --- a/sail-spin/src/main/java/org/eclipse/rdf4j/sail/spin/SpinSailConnection.java +++ b/sail-spin/src/main/java/org/eclipse/rdf4j/sail/spin/SpinSailConnection.java @@ -280,8 +280,8 @@ private void initRuleProperties() rulePropertyMap = parser.parseRuleProperties(tripleSource); // order rules - Set remainingRules = new HashSet(rulePropertyMap.keySet()); - List reverseOrder = new ArrayList(remainingRules.size()); + Set remainingRules = new HashSet<>(rulePropertyMap.keySet()); + List reverseOrder = new ArrayList<>(remainingRules.size()); while (!remainingRules.isEmpty()) { for (Iterator ruleIter = remainingRules.iterator(); ruleIter.hasNext();) { IRI rule = ruleIter.next(); @@ -331,7 +331,7 @@ private void initClasses() return; } - classToSuperclassMap = new HashMap>(); + classToSuperclassMap = new HashMap<>(); try (CloseableIteration stmtIter = tripleSource.getStatements( null, RDFS.SUBCLASSOF, null)) { while (stmtIter.hasNext()) { @@ -341,7 +341,7 @@ private void initClasses() IRI superclass = (IRI)stmt.getObject(); Set superclasses = getSuperclasses(cls); if (superclasses == null) { - superclasses = new HashSet(64); + superclasses = new HashSet<>(64); classToSuperclassMap.put(cls, superclasses); } superclasses.add(superclass); @@ -405,7 +405,7 @@ private void loadAxiomStatements(RDFParser parser, String file) protected void doInferencing() throws SailException { - ruleExecutions = new HashMap(); + ruleExecutions = new HashMap<>(); super.doInferencing(); ruleExecutions = null; } @@ -440,7 +440,7 @@ private int applyRulesInternal(Iterable resources) logger.debug("building class hierarchy for {}", res); // build local class hierarchy Collection remainingClasses = getClasses(res); - List classHierarchy = new ArrayList(remainingClasses.size()); + List classHierarchy = new ArrayList<>(remainingClasses.size()); while (!remainingClasses.isEmpty()) { boolean hasCycle = true; for (Iterator clsIter = remainingClasses.iterator(); clsIter.hasNext();) { @@ -484,7 +484,7 @@ private int applyRulesInternal(Iterable resources) private Collection getClasses(Resource subj) throws QueryEvaluationException { - List classes = new LinkedList(); + List classes = new LinkedList<>(); CloseableIteration classIter = TripleSources.getObjectURIs( subj, RDF.TYPE, tripleSource); Iterations.addAll(classIter, classes); @@ -495,7 +495,7 @@ private int executeConstructors(Resource subj, List classHierarchy) throws RDF4JException { int nofInferred = 0; - Set constructed = new HashSet(classHierarchy.size()); + Set constructed = new HashSet<>(classHierarchy.size()); CloseableIteration classIter = TripleSources.getObjectResources( subj, EXECUTED, tripleSource); Iterations.addAll(classIter, constructed); @@ -521,7 +521,7 @@ private int executeConstructors(Resource subj, List classHierarchy) private List getConstructorsForClass(IRI cls) throws RDF4JException { - List constructors = new ArrayList(2); + List constructors = new ArrayList<>(2); CloseableIteration constructorIter = TripleSources.getObjectResources( cls, SPIN.CONSTRUCTOR_PROPERTY, tripleSource); Iterations.addAll(constructorIter, constructors); @@ -582,17 +582,17 @@ private Map> getRulesForClass(IRI cls, List ruleProps) throws QueryEvaluationException { // NB: preserve ruleProp order! - Map> classRulesByProperty = new LinkedHashMap>( + Map> classRulesByProperty = new LinkedHashMap<>( ruleProps.size()); for (IRI ruleProp : ruleProps) { - List rules = new ArrayList(2); + List rules = new ArrayList<>(2); CloseableIteration ruleIter = TripleSources.getObjectResources( cls, ruleProp, tripleSource); Iterations.addAll(ruleIter, rules); if (!rules.isEmpty()) { if (rules.size() > 1) { // sort by comments - final Map comments = new HashMap(rules.size()); + final Map comments = new HashMap<>(rules.size()); for (Resource rule : rules) { String comment = getHighestComment(rule); if (comment != null) { @@ -708,7 +708,7 @@ private Object[] getConstraintViolationLogMessageArgs(ConstraintViolation violat private Map> getConstraintsForSubject(Resource subj, List classHierarchy) throws QueryEvaluationException { - Map> constraintsByClass = new LinkedHashMap>( + Map> constraintsByClass = new LinkedHashMap<>( classHierarchy.size()); // check each class of subj for constraints for (IRI cls : classHierarchy) { @@ -723,7 +723,7 @@ private Map> getConstraintsForSubject(Resource subj, List getConstraintsForClass(Resource cls) throws QueryEvaluationException { - List constraints = new ArrayList(2); + List constraints = new ArrayList<>(2); CloseableIteration constraintIter = TripleSources.getObjectResources( cls, SPIN.CONSTRAINT_PROPERTY, tripleSource); Iterations.addAll(constraintIter, constraints); diff --git a/sail-spin/src/main/java/org/eclipse/rdf4j/spin/function/spif/CanInvoke.java b/sail-spin/src/main/java/org/eclipse/rdf4j/spin/function/spif/CanInvoke.java index 671cd58ac..deb60ba1c 100644 --- a/sail-spin/src/main/java/org/eclipse/rdf4j/spin/function/spif/CanInvoke.java +++ b/sail-spin/src/main/java/org/eclipse/rdf4j/spin/function/spif/CanInvoke.java @@ -108,7 +108,7 @@ public Value evaluate(ValueFactory valueFactory, Value... args) FunctionRegistry.getInstance()); Map funcArgs = parser.parseArguments(func, qpTripleSource); List funcArgList = SpinParser.orderArguments(funcArgs.keySet()); - final Map argValues = new HashMap(funcArgList.size()); + final Map argValues = new HashMap<>(funcArgList.size()); for (int i = 0; i < funcArgList.size(); i++) { IRI argName = funcArgList.get(i); Argument funcArg = funcArgs.get(argName); @@ -148,12 +148,12 @@ public CloseableIteration getStat if (pred != null) { Value v = argValues.get(pred); if (v != null && (obj == null || v.equals(obj))) { - return new SingletonIteration( + return new SingletonIteration<>( vf.createStatement(subj, pred, v)); } } - return new EmptyIteration(); + return new EmptyIteration<>(); } else { return qpTripleSource.getStatements(subj, pred, obj, contexts); diff --git a/solr/src/main/java/org/eclipse/rdf4j/sail/solr/SolrBulkUpdater.java b/solr/src/main/java/org/eclipse/rdf4j/sail/solr/SolrBulkUpdater.java index bdabecfc5..1c20bca25 100644 --- a/solr/src/main/java/org/eclipse/rdf4j/sail/solr/SolrBulkUpdater.java +++ b/solr/src/main/java/org/eclipse/rdf4j/sail/solr/SolrBulkUpdater.java @@ -22,9 +22,9 @@ public class SolrBulkUpdater implements BulkUpdater { private final SolrClient client; - private final List addOrUpdateList = new ArrayList(); + private final List addOrUpdateList = new ArrayList<>(); - private final List deleteList = new ArrayList(); + private final List deleteList = new ArrayList<>(); public SolrBulkUpdater(SolrClient client) { this.client = client; diff --git a/solr/src/main/java/org/eclipse/rdf4j/sail/solr/SolrIndex.java b/solr/src/main/java/org/eclipse/rdf4j/sail/solr/SolrIndex.java index 178644296..80c49c6eb 100644 --- a/solr/src/main/java/org/eclipse/rdf4j/sail/solr/SolrIndex.java +++ b/solr/src/main/java/org/eclipse/rdf4j/sail/solr/SolrIndex.java @@ -259,7 +259,7 @@ public Iterable getDocuments(Resource subject) * Filters the given list of fields, retaining all property fields. */ public static Set getPropertyFields(Set fields) { - Set result = new HashSet(fields.size()); + Set result = new HashSet<>(fields.size()); for (String field : fields) { if (SearchFields.isPropertyField(field)) result.add(field); @@ -540,7 +540,7 @@ protected Shape parseQueryShape(String property, String value) { Shape s = super.parseQueryShape(property, value); // workaround to preserve WKT string - return (s instanceof Point) ? new WktPoint((Point)s, value) : new WktShape(s, value); + return (s instanceof Point) ? new WktPoint((Point)s, value) : new WktShape<>(s, value); } protected String toWkt(Shape s) { diff --git a/solr/src/main/java/org/eclipse/rdf4j/sail/solr/SolrSearchDocument.java b/solr/src/main/java/org/eclipse/rdf4j/sail/solr/SolrSearchDocument.java index d269b2046..ddc53956d 100644 --- a/solr/src/main/java/org/eclipse/rdf4j/sail/solr/SolrSearchDocument.java +++ b/solr/src/main/java/org/eclipse/rdf4j/sail/solr/SolrSearchDocument.java @@ -114,7 +114,7 @@ private static void addField(String name, String value, Map docu private static List makeModifiable(List l) { List modList; if (!(l instanceof ArrayList)) { - modList = new ArrayList(l.size() + 1); + modList = new ArrayList<>(l.size() + 1); modList.addAll(l); } else { diff --git a/spin/src/main/java/org/eclipse/rdf4j/spin/SpinParser.java b/spin/src/main/java/org/eclipse/rdf4j/spin/SpinParser.java index 3ae9c4513..b78bf9869 100644 --- a/spin/src/main/java/org/eclipse/rdf4j/spin/SpinParser.java +++ b/spin/src/main/java/org/eclipse/rdf4j/spin/SpinParser.java @@ -267,7 +267,7 @@ public void setStrictFunctionChecking(boolean strictFunctionChecking) { public Map parseRuleProperties(TripleSource store) throws RDF4JException { - Map rules = new HashMap(); + Map rules = new HashMap<>(); CloseableIteration rulePropIter = TripleSources.getSubjectURIs( RDFS.SUBPROPERTYOF, SPIN.RULE_PROPERTY, store); try { @@ -292,7 +292,7 @@ public Map parseRuleProperties(TripleSource store) private List getNextRules(Resource ruleProp, TripleSource store) throws RDF4JException { - List nextRules = new ArrayList(); + List nextRules = new ArrayList<>(); CloseableIteration iter = TripleSources.getObjectURIs(ruleProp, SPIN.NEXT_RULE_PROPERTY_PROPERTY, store); try { @@ -405,8 +405,8 @@ protected ParsedOperation parse(Resource queryResource, IRI queryClass, TripleSo throws RDF4JException { Boolean isQueryElseTemplate = null; - Set possibleQueryTypes = new HashSet(); - Set possibleTemplates = new HashSet(); + Set possibleQueryTypes = new HashSet<>(); + Set possibleTemplates = new HashSet<>(); CloseableIteration typeIter = TripleSources.getObjectURIs( queryResource, RDF.TYPE, store); try { @@ -465,7 +465,7 @@ else if (isQueryElseTemplate == Boolean.TRUE) { // template Set abstractTemplates; if (possibleTemplates.size() > 1) { - abstractTemplates = new HashSet(); + abstractTemplates = new HashSet<>(); for (Iterator iter = possibleTemplates.iterator(); iter.hasNext();) { IRI t = iter.next(); boolean isAbstract = TripleSources.booleanValue(t, SPIN.ABSTRACT_PROPERTY, store); @@ -490,7 +490,7 @@ else if (isQueryElseTemplate == Boolean.TRUE) { IRI templateResource = (IRI)possibleTemplates.iterator().next(); Template tmpl = getTemplate(templateResource, queryClass, abstractTemplates, store); - Map argValues = new HashMap(2 * tmpl.getArguments().size()); + Map argValues = new HashMap<>(2 * tmpl.getArguments().size()); for (Argument arg : tmpl.getArguments()) { IRI argPred = (IRI)arg.getPredicate(); Value argValue = TripleSources.singleValue(queryResource, argPred, store); @@ -534,7 +534,7 @@ private Template parseTemplateInternal(IRI tmplUri, IRI queryType, Set abst TripleSource store) throws RDF4JException { - Set possibleTmplTypes = new HashSet(); + Set possibleTmplTypes = new HashSet<>(); CloseableIteration typeIter = TripleSources.getObjectURIs( tmplUri, RDF.TYPE, store); try { @@ -606,7 +606,7 @@ else if (SP.CONSTRUCT_CLASS.equals(queryType)) { private Map parseTemplateArguments(IRI tmplUri, Set abstractTmpls, TripleSource store) throws RDF4JException { - Map args = new HashMap(); + Map args = new HashMap<>(); for (IRI abstractTmpl : abstractTmpls) { parseArguments(abstractTmpl, store, args); } @@ -653,7 +653,7 @@ public Map parseArguments(final IRI moduleUri, final TripleSource public Map call() throws RDF4JException { - Map args = new HashMap(); + Map args = new HashMap<>(); parseArguments(moduleUri, store, args); return Collections.unmodifiableMap(args); } @@ -829,7 +829,7 @@ public int compare(IRI uri1, IRI uri2) { sortedArgs.addAll(args); int numArgs = sortedArgs.size(); - List orderedArgs = new ArrayList(numArgs); + List orderedArgs = new ArrayList<>(numArgs); for (int i = 0; i < numArgs; i++) { IRI arg = toArgProperty(i); if (!sortedArgs.remove(arg)) { @@ -874,9 +874,9 @@ private class SpinVisitor { Group group; - Map vars = new HashMap(); + Map vars = new HashMap<>(); - Collection aggregates = new ArrayList(); + Collection aggregates = new ArrayList<>(); SpinVisitor(TripleSource store) { this.store = store; @@ -899,7 +899,7 @@ public void visitConstruct(Resource construct) String.format("Value of %s is not a resource", SP.TEMPLATES_PROPERTY)); } - projElems = new LinkedHashMap(); + projElems = new LinkedHashMap<>(); UnaryTupleOperator projection = visitTemplates((Resource)templates); TupleExpr whereExpr = visitWhere(construct); projection.setArg(whereExpr); @@ -915,7 +915,7 @@ public void visitDescribe(Resource describe) String.format("Value of %s is not a resource", SP.RESULT_NODES_PROPERTY)); } - projElems = new LinkedHashMap(); + projElems = new LinkedHashMap<>(); Projection projection = visitResultNodes((Resource)resultNodes); TupleExpr whereExpr = visitWhere(describe); projection.setArg(whereExpr); @@ -932,7 +932,7 @@ public void visitSelect(Resource select) } Map oldProjElems = projElems; - projElems = new LinkedHashMap(); + projElems = new LinkedHashMap<>(); Projection projection = visitResultVariables((Resource)resultVars, oldProjElems); TupleExpr whereExpr = visitWhere(select); projection.setArg(whereExpr); @@ -1013,7 +1013,7 @@ private void addSourceExpressions(UnaryTupleOperator op, Collection projElemLists = new ArrayList(); + List projElemLists = new ArrayList<>(); Iteration iter = TripleSources.listResources(templates, store); while (iter.hasNext()) { @@ -1189,7 +1189,7 @@ private ProjectionElem createProjectionElem(Value v, String projName, Value expr = TripleSources.singleValue((Resource)v, SP.EXPRESSION_PROPERTY, store); if (expr != null) { // AS - aggregates = new ArrayList(); + aggregates = new ArrayList<>(); valueExpr = visitExpression(expr); } else { @@ -1375,7 +1375,7 @@ public TupleExpr visitGroupGraphPattern(Resource group) tupleNode = new SingletonSet(); QueryRoot groupRoot = new QueryRoot(tupleNode); - Map> patternTypes = new LinkedHashMap>(); + Map> patternTypes = new LinkedHashMap<>(); Iteration groupIter = TripleSources.listResources( group, store); while (groupIter.hasNext()) { @@ -1533,7 +1533,7 @@ else if (types.contains(SP.SUB_QUERY_CLASS)) { } else if (types.contains(SP.VALUES_CLASS)) { BindingSetAssignment bsa = new BindingSetAssignment(); - Set varNames = new LinkedHashSet(); + Set varNames = new LinkedHashSet<>(); Value varNameList = TripleSources.singleValue(r, SP.VAR_NAMES_PROPERTY, store); Iteration varNameIter = TripleSources.list( (Resource)varNameList, store); @@ -1544,7 +1544,7 @@ else if (types.contains(SP.VALUES_CLASS)) { } } bsa.setBindingNames(varNames); - List bindingSets = new ArrayList(); + List bindingSets = new ArrayList<>(); Value bindingsList = TripleSources.singleValue(r, SP.BINDINGS_PROPERTY, store); Iteration bindingsIter = TripleSources.list( (Resource)bindingsList, store); @@ -1611,7 +1611,7 @@ else if (types.contains(SP.SERVICE_CLASS)) { catch (Exception e) { throw new QueryEvaluationException(e); } - Map prefixDecls = new HashMap(8); + Map prefixDecls = new HashMap<>(8); prefixDecls.put(SP.PREFIX, SP.NAMESPACE); prefixDecls.put(SPIN.PREFIX, SPIN.NAMESPACE); prefixDecls.put(SPL.PREFIX, SPL.NAMESPACE); @@ -2024,7 +2024,7 @@ private List getArgs(Resource r, IRI func, IRI... knownArgs) else { args = parseArguments(func, store).keySet(); } - Map argBindings = new HashMap(); + Map argBindings = new HashMap<>(); if (!args.isEmpty()) { for (IRI arg : args) { Value value = TripleSources.singleValue(r, arg, store); @@ -2048,7 +2048,7 @@ private List getArgs(Resource r, IRI func, IRI... knownArgs) while (value != null); } - List argValues = new ArrayList(argBindings.size()); + List argValues = new ArrayList<>(argBindings.size()); List orderedArgs = orderArguments(argBindings.keySet()); for (IRI IRI : orderedArgs) { ValueExpr argExpr = argBindings.get(IRI); diff --git a/spin/src/main/java/org/eclipse/rdf4j/spin/SpinRenderer.java b/spin/src/main/java/org/eclipse/rdf4j/spin/SpinRenderer.java index 6c527068f..a37ef33b5 100644 --- a/spin/src/main/java/org/eclipse/rdf4j/spin/SpinRenderer.java +++ b/spin/src/main/java/org/eclipse/rdf4j/spin/SpinRenderer.java @@ -448,9 +448,9 @@ private class SpinVisitor extends QueryModelVisitorBase { final Dataset dataset; - final Map varBNodes = new HashMap(); + final Map varBNodes = new HashMap<>(); - final Map namedGraphLists = new HashMap(); + final Map namedGraphLists = new HashMap<>(); ExtensionContext inlineBindings; @@ -1333,7 +1333,7 @@ public void meet(BindingSetAssignment node) Resource bindingList = valueFactory.createBNode(); handler.handleStatement(valueFactory.createStatement(subject, SP.BINDINGS_PROPERTY, bindingList)); ListContext bindingCtx = newList(bindingList); - List bindingVars = new ArrayList(node.getBindingNames()); + List bindingVars = new ArrayList<>(node.getBindingNames()); for (BindingSet bs : node.getBindingSets()) { listEntry(); ListContext setCtx = newList(subject); @@ -1426,7 +1426,7 @@ private void renderDataBlock(String data) parser.setAllowBlankNodes(false); // no blank nodes allowed parser.setRDFHandler(new RDFHandlerBase() { - final Map namedGraphLists = new HashMap(); + final Map namedGraphLists = new HashMap<>(); ListContext namedGraphContext; @@ -1791,7 +1791,7 @@ public void meet(Extension node) { extension = node; List elements = node.getElements(); // NB: preserve ExtensionElem order - extensionExprs = new LinkedHashMap(elements.size()); + extensionExprs = new LinkedHashMap<>(elements.size()); for (ExtensionElem elem : elements) { extensionExprs.put(elem.getName(), elem.getExpr()); } diff --git a/spin/src/main/java/org/eclipse/rdf4j/spin/Template.java b/spin/src/main/java/org/eclipse/rdf4j/spin/Template.java index a89dd9159..2087ec71d 100644 --- a/spin/src/main/java/org/eclipse/rdf4j/spin/Template.java +++ b/spin/src/main/java/org/eclipse/rdf4j/spin/Template.java @@ -31,7 +31,7 @@ public class Template { private ParsedOperation parsedOp; - private final List arguments = new ArrayList(4); + private final List arguments = new ArrayList<>(4); public Template(IRI IRI) { this.IRI = IRI; diff --git a/spin/src/main/java/org/eclipse/rdf4j/spin/function/SelectTupleFunction.java b/spin/src/main/java/org/eclipse/rdf4j/spin/function/SelectTupleFunction.java index d8f2c2c47..e4cc0544e 100644 --- a/spin/src/main/java/org/eclipse/rdf4j/spin/function/SelectTupleFunction.java +++ b/spin/src/main/java/org/eclipse/rdf4j/spin/function/SelectTupleFunction.java @@ -81,7 +81,7 @@ else if (parsedQuery instanceof ParsedBooleanQuery) { BooleanQuery queryOp = qp.prepare(booleanQuery); addBindings(queryOp, args); Value result = BooleanLiteral.valueOf(queryOp.evaluate()); - return new SingletonIteration, QueryEvaluationException>( + return new SingletonIteration<>( Collections.singletonList(result)); } else { @@ -134,7 +134,7 @@ public List next() } try { BindingSet bs = queryResult.next(); - List values = new ArrayList(bindingNames.size()); + List values = new ArrayList<>(bindingNames.size()); for (String bindingName : bindingNames) { values.add(bs.getValue(bindingName)); } diff --git a/spin/src/main/java/org/eclipse/rdf4j/spin/function/SpinFunction.java b/spin/src/main/java/org/eclipse/rdf4j/spin/function/SpinFunction.java index 78eb9dd9d..1976419b0 100644 --- a/spin/src/main/java/org/eclipse/rdf4j/spin/function/SpinFunction.java +++ b/spin/src/main/java/org/eclipse/rdf4j/spin/function/SpinFunction.java @@ -32,7 +32,7 @@ public class SpinFunction extends AbstractSpinFunction implements TransientFunct private ParsedQuery parsedQuery; - private final List arguments = new ArrayList(4); + private final List arguments = new ArrayList<>(4); public SpinFunction(String uri) { super(uri); diff --git a/spin/src/main/java/org/eclipse/rdf4j/spin/function/SpinTupleFunction.java b/spin/src/main/java/org/eclipse/rdf4j/spin/function/SpinTupleFunction.java index 22414498d..a677da225 100644 --- a/spin/src/main/java/org/eclipse/rdf4j/spin/function/SpinTupleFunction.java +++ b/spin/src/main/java/org/eclipse/rdf4j/spin/function/SpinTupleFunction.java @@ -36,7 +36,7 @@ public class SpinTupleFunction extends AbstractSpinFunction implements Transient private ParsedQuery parsedQuery; - private final List arguments = new ArrayList(4); + private final List arguments = new ArrayList<>(4); public SpinTupleFunction(String uri) { super(uri); @@ -75,7 +75,7 @@ public CloseableIteration, QueryEvaluationExcept BooleanQuery queryOp = qp.prepare(askQuery); addBindings(queryOp, arguments, args); Value result = BooleanLiteral.valueOf(queryOp.evaluate()); - iter = new SingletonIteration, QueryEvaluationException>( + iter = new SingletonIteration<>( Collections.singletonList(result)); } else if (parsedQuery instanceof ParsedTupleQuery) { diff --git a/spin/src/main/java/org/eclipse/rdf4j/spin/function/SpinxFunction.java b/spin/src/main/java/org/eclipse/rdf4j/spin/function/SpinxFunction.java index 3a88713e6..36a1d6dc1 100644 --- a/spin/src/main/java/org/eclipse/rdf4j/spin/function/SpinxFunction.java +++ b/spin/src/main/java/org/eclipse/rdf4j/spin/function/SpinxFunction.java @@ -31,7 +31,7 @@ public class SpinxFunction implements TransientFunction { private final String uri; - private final List arguments = new ArrayList(4); + private final List arguments = new ArrayList<>(4); private ScriptEngine scriptEngine; diff --git a/spin/src/main/java/org/eclipse/rdf4j/spin/function/spif/BuildString.java b/spin/src/main/java/org/eclipse/rdf4j/spin/function/spif/BuildString.java index 6cf76d87b..9342e4365 100644 --- a/spin/src/main/java/org/eclipse/rdf4j/spin/function/spif/BuildString.java +++ b/spin/src/main/java/org/eclipse/rdf4j/spin/function/spif/BuildString.java @@ -37,7 +37,7 @@ public Value evaluate(ValueFactory valueFactory, Value... args) } Literal s = (Literal)args[0]; String tmpl = s.getLabel(); - Map mappings = new HashMap(args.length); + Map mappings = new HashMap<>(args.length); for (int i = 1; i < args.length; i++) { mappings.put(Integer.toString(i), args[i].stringValue()); } diff --git a/spin/src/main/java/org/eclipse/rdf4j/spin/function/spif/BuildURI.java b/spin/src/main/java/org/eclipse/rdf4j/spin/function/spif/BuildURI.java index be2fe9d77..ab2edef2a 100644 --- a/spin/src/main/java/org/eclipse/rdf4j/spin/function/spif/BuildURI.java +++ b/spin/src/main/java/org/eclipse/rdf4j/spin/function/spif/BuildURI.java @@ -37,7 +37,7 @@ public Value evaluate(ValueFactory valueFactory, Value... args) } Literal s = (Literal)args[0]; String tmpl = s.getLabel(); - Map mappings = new HashMap(args.length); + Map mappings = new HashMap<>(args.length); for (int i = 1; i < args.length; i++) { mappings.put(Integer.toString(i), args[i].stringValue()); } diff --git a/spin/src/main/java/org/eclipse/rdf4j/spin/function/spif/ForEach.java b/spin/src/main/java/org/eclipse/rdf4j/spin/function/spif/ForEach.java index d92ae5b92..990ad1139 100644 --- a/spin/src/main/java/org/eclipse/rdf4j/spin/function/spif/ForEach.java +++ b/spin/src/main/java/org/eclipse/rdf4j/spin/function/spif/ForEach.java @@ -30,7 +30,7 @@ public CloseableIteration, QueryEvaluationExcept ValueFactory valueFactory, Value... args) throws QueryEvaluationException { - return new CloseableIteratorIteration, QueryEvaluationException>( + return new CloseableIteratorIteration<>( SingleValueToListTransformer.transform(Arrays. asList(args).iterator())); } } diff --git a/spin/src/main/java/org/eclipse/rdf4j/spin/function/spif/ParseDate.java b/spin/src/main/java/org/eclipse/rdf4j/spin/function/spif/ParseDate.java index 5807d95cd..b7c258cab 100644 --- a/spin/src/main/java/org/eclipse/rdf4j/spin/function/spif/ParseDate.java +++ b/spin/src/main/java/org/eclipse/rdf4j/spin/function/spif/ParseDate.java @@ -99,7 +99,7 @@ else if (dateValue.charAt(len - 6) == '+' || dateValue.charAt(len - 6) == '-') { static final class FieldAwareGregorianCalendar extends GregorianCalendar { - Set fieldsSet = new HashSet(); + Set fieldsSet = new HashSet<>(); @Override public void set(int field, int value) { diff --git a/spin/src/test/java/org/eclipse/rdf4j/model/evaluation/ModelTripleSource.java b/spin/src/test/java/org/eclipse/rdf4j/model/evaluation/ModelTripleSource.java index 566826b14..ec37025d1 100644 --- a/spin/src/test/java/org/eclipse/rdf4j/model/evaluation/ModelTripleSource.java +++ b/spin/src/test/java/org/eclipse/rdf4j/model/evaluation/ModelTripleSource.java @@ -32,7 +32,7 @@ public CloseableIteration getStat IRI pred, Value obj, Resource... contexts) throws QueryEvaluationException { - return new CloseableIteratorIteration( + return new CloseableIteratorIteration<>( model.filter(subj, pred, obj, contexts).iterator()); } diff --git a/spin/src/test/java/org/eclipse/rdf4j/spin/SpinParserTest.java b/spin/src/test/java/org/eclipse/rdf4j/spin/SpinParserTest.java index 330336521..ce9bf52b8 100644 --- a/spin/src/test/java/org/eclipse/rdf4j/spin/SpinParserTest.java +++ b/spin/src/test/java/org/eclipse/rdf4j/spin/SpinParserTest.java @@ -41,7 +41,7 @@ public class SpinParserTest { @Parameters(name = "{0}") public static Collection testData() { - List params = new ArrayList(); + List params = new ArrayList<>(); for (int i = 0;; i++) { String suffix = String.valueOf(i + 1); String testFile = "/testcases/test" + suffix + ".ttl"; diff --git a/spin/src/test/java/org/eclipse/rdf4j/spin/SpinRendererTest.java b/spin/src/test/java/org/eclipse/rdf4j/spin/SpinRendererTest.java index f68d5353a..40cf5cceb 100644 --- a/spin/src/test/java/org/eclipse/rdf4j/spin/SpinRendererTest.java +++ b/spin/src/test/java/org/eclipse/rdf4j/spin/SpinRendererTest.java @@ -46,7 +46,7 @@ public class SpinRendererTest { @Parameters(name = "{0}") public static Collection testData() { - List params = new ArrayList(); + List params = new ArrayList<>(); for (int i = 0;; i++) { String suffix = String.valueOf(i + 1); String testFile = "/testcases/test" + suffix + ".ttl"; From 237564c8810a17ad1368908a4a5b74e47da93ffa Mon Sep 17 00:00:00 2001 From: Jeen Broekstra Date: Sat, 26 Jan 2019 13:19:15 +1100 Subject: [PATCH 54/54] setting version to 3.0-SNAPSHOT --- compliance/elasticsearch/pom.xml | 2 +- compliance/geosparql/pom.xml | 2 +- compliance/lucene/pom.xml | 2 +- compliance/pom.xml | 2 +- compliance/sail-model/pom.xml | 2 +- compliance/serql/pom.xml | 2 +- compliance/shacl/pom.xml | 2 +- compliance/solr/pom.xml | 2 +- compliance/sparql/pom.xml | 2 +- compliance/store/pom.xml | 2 +- elasticsearch/pom.xml | 2 +- evaluation/pom.xml | 2 +- federation/pom.xml | 2 +- geosparql/pom.xml | 2 +- inferencer/pom.xml | 2 +- lucene-api/pom.xml | 2 +- lucene-spin/pom.xml | 2 +- lucene/pom.xml | 2 +- memory/pom.xml | 2 +- nativerdf/pom.xml | 2 +- pom.xml | 2 +- repository-dataset/pom.xml | 2 +- repository-sail/pom.xml | 2 +- sail-api/pom.xml | 2 +- sail-base/pom.xml | 2 +- sail-model/pom.xml | 2 +- sail-spin/pom.xml | 2 +- shacl/pom.xml | 2 +- solr/pom.xml | 2 +- spin/pom.xml | 2 +- storage/pom.xml | 2 +- 31 files changed, 31 insertions(+), 31 deletions(-) diff --git a/compliance/elasticsearch/pom.xml b/compliance/elasticsearch/pom.xml index 62779dec3..0e80c632a 100644 --- a/compliance/elasticsearch/pom.xml +++ b/compliance/elasticsearch/pom.xml @@ -7,7 +7,7 @@ org.eclipse.rdf4j rdf4j-storage-compliance - 2.5-SNAPSHOT + 3.0-SNAPSHOT rdf4j-elasticsearch-compliance diff --git a/compliance/geosparql/pom.xml b/compliance/geosparql/pom.xml index 0bdf35cc4..84f142467 100644 --- a/compliance/geosparql/pom.xml +++ b/compliance/geosparql/pom.xml @@ -6,7 +6,7 @@ org.eclipse.rdf4j rdf4j-storage-compliance - 2.5-SNAPSHOT + 3.0-SNAPSHOT rdf4j-geosparql-compliance diff --git a/compliance/lucene/pom.xml b/compliance/lucene/pom.xml index 5459dc308..4f50faf07 100644 --- a/compliance/lucene/pom.xml +++ b/compliance/lucene/pom.xml @@ -5,7 +5,7 @@ org.eclipse.rdf4j rdf4j-storage-compliance - 2.5-SNAPSHOT + 3.0-SNAPSHOT rdf4j-lucene-compliance diff --git a/compliance/pom.xml b/compliance/pom.xml index 24147a1aa..ce6821f1b 100644 --- a/compliance/pom.xml +++ b/compliance/pom.xml @@ -5,7 +5,7 @@ org.eclipse.rdf4j rdf4j-storage-parent - 2.5-SNAPSHOT + 3.0-SNAPSHOT rdf4j-storage-compliance diff --git a/compliance/sail-model/pom.xml b/compliance/sail-model/pom.xml index 9ebe831de..7d2d28b7f 100644 --- a/compliance/sail-model/pom.xml +++ b/compliance/sail-model/pom.xml @@ -5,7 +5,7 @@ org.eclipse.rdf4j rdf4j-storage-compliance - 2.5-SNAPSHOT + 3.0-SNAPSHOT rdf4j-sail-model-compliance diff --git a/compliance/serql/pom.xml b/compliance/serql/pom.xml index 07d7f058f..3698e3fcf 100644 --- a/compliance/serql/pom.xml +++ b/compliance/serql/pom.xml @@ -5,7 +5,7 @@ org.eclipse.rdf4j rdf4j-storage-compliance - 2.5-SNAPSHOT + 3.0-SNAPSHOT rdf4j-serql-compliance diff --git a/compliance/shacl/pom.xml b/compliance/shacl/pom.xml index 3b64a889d..7318308e7 100644 --- a/compliance/shacl/pom.xml +++ b/compliance/shacl/pom.xml @@ -6,7 +6,7 @@ org.eclipse.rdf4j rdf4j-storage-compliance - 2.5-SNAPSHOT + 3.0-SNAPSHOT rdf4j-shacl-compliance diff --git a/compliance/solr/pom.xml b/compliance/solr/pom.xml index 65112aa6a..e13ece0e1 100644 --- a/compliance/solr/pom.xml +++ b/compliance/solr/pom.xml @@ -5,7 +5,7 @@ org.eclipse.rdf4j rdf4j-storage-compliance - 2.5-SNAPSHOT + 3.0-SNAPSHOT rdf4j-solr-compliance diff --git a/compliance/sparql/pom.xml b/compliance/sparql/pom.xml index fb4368650..933e8f18d 100644 --- a/compliance/sparql/pom.xml +++ b/compliance/sparql/pom.xml @@ -6,7 +6,7 @@ org.eclipse.rdf4j rdf4j-storage-compliance - 2.5-SNAPSHOT + 3.0-SNAPSHOT rdf4j-sparql-compliance diff --git a/compliance/store/pom.xml b/compliance/store/pom.xml index fbfd5daf1..f6a2330f8 100644 --- a/compliance/store/pom.xml +++ b/compliance/store/pom.xml @@ -5,7 +5,7 @@ org.eclipse.rdf4j rdf4j-storage-compliance - 2.5-SNAPSHOT + 3.0-SNAPSHOT rdf4j-store-compliance diff --git a/elasticsearch/pom.xml b/elasticsearch/pom.xml index 0b358f82f..796fcc947 100644 --- a/elasticsearch/pom.xml +++ b/elasticsearch/pom.xml @@ -7,7 +7,7 @@ org.eclipse.rdf4j rdf4j-storage-parent - 2.5-SNAPSHOT + 3.0-SNAPSHOT rdf4j-sail-elasticsearch diff --git a/evaluation/pom.xml b/evaluation/pom.xml index 842ca51a3..2e0bfaf94 100644 --- a/evaluation/pom.xml +++ b/evaluation/pom.xml @@ -7,7 +7,7 @@ org.eclipse.rdf4j rdf4j-storage-parent - 2.5-SNAPSHOT + 3.0-SNAPSHOT rdf4j-queryalgebra-evaluation diff --git a/federation/pom.xml b/federation/pom.xml index 2a6dffc7d..9fce1126c 100644 --- a/federation/pom.xml +++ b/federation/pom.xml @@ -5,7 +5,7 @@ org.eclipse.rdf4j rdf4j-storage-parent - 2.5-SNAPSHOT + 3.0-SNAPSHOT rdf4j-sail-federation diff --git a/geosparql/pom.xml b/geosparql/pom.xml index 39b826624..60875a87e 100644 --- a/geosparql/pom.xml +++ b/geosparql/pom.xml @@ -7,7 +7,7 @@ org.eclipse.rdf4j rdf4j-storage-parent - 2.5-SNAPSHOT + 3.0-SNAPSHOT rdf4j-queryalgebra-geosparql diff --git a/inferencer/pom.xml b/inferencer/pom.xml index 5a4c150b9..7dd828a54 100644 --- a/inferencer/pom.xml +++ b/inferencer/pom.xml @@ -5,7 +5,7 @@ org.eclipse.rdf4j rdf4j-storage-parent - 2.5-SNAPSHOT + 3.0-SNAPSHOT rdf4j-sail-inferencer diff --git a/lucene-api/pom.xml b/lucene-api/pom.xml index c1558a7fb..86a6071ae 100644 --- a/lucene-api/pom.xml +++ b/lucene-api/pom.xml @@ -5,7 +5,7 @@ org.eclipse.rdf4j rdf4j-storage-parent - 2.5-SNAPSHOT + 3.0-SNAPSHOT rdf4j-sail-lucene-api diff --git a/lucene-spin/pom.xml b/lucene-spin/pom.xml index 42a00d2ee..d869f93a7 100644 --- a/lucene-spin/pom.xml +++ b/lucene-spin/pom.xml @@ -4,7 +4,7 @@ rdf4j-storage-parent org.eclipse.rdf4j - 2.5-SNAPSHOT + 3.0-SNAPSHOT rdf4j-lucene-spin RDF4J Lucene Sail Spin diff --git a/lucene/pom.xml b/lucene/pom.xml index 7f6ce053c..c6f6c989d 100644 --- a/lucene/pom.xml +++ b/lucene/pom.xml @@ -7,7 +7,7 @@ org.eclipse.rdf4j rdf4j-storage-parent - 2.5-SNAPSHOT + 3.0-SNAPSHOT rdf4j-sail-lucene diff --git a/memory/pom.xml b/memory/pom.xml index 8d712aa75..568b08db9 100644 --- a/memory/pom.xml +++ b/memory/pom.xml @@ -5,7 +5,7 @@ org.eclipse.rdf4j rdf4j-storage-parent - 2.5-SNAPSHOT + 3.0-SNAPSHOT rdf4j-sail-memory diff --git a/nativerdf/pom.xml b/nativerdf/pom.xml index cf86fd979..2d1604805 100644 --- a/nativerdf/pom.xml +++ b/nativerdf/pom.xml @@ -5,7 +5,7 @@ org.eclipse.rdf4j rdf4j-storage-parent - 2.5-SNAPSHOT + 3.0-SNAPSHOT rdf4j-sail-nativerdf diff --git a/pom.xml b/pom.xml index d0885235c..8d5348d82 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.eclipse.rdf4j rdf4j-storage-parent - 2.5-SNAPSHOT + 3.0-SNAPSHOT pom RDF4J Storage diff --git a/repository-dataset/pom.xml b/repository-dataset/pom.xml index a6874fad7..b26da7a07 100644 --- a/repository-dataset/pom.xml +++ b/repository-dataset/pom.xml @@ -5,7 +5,7 @@ org.eclipse.rdf4j rdf4j-storage-parent - 2.5-SNAPSHOT + 3.0-SNAPSHOT rdf4j-repository-dataset diff --git a/repository-sail/pom.xml b/repository-sail/pom.xml index dd084b7f2..edbc1e355 100644 --- a/repository-sail/pom.xml +++ b/repository-sail/pom.xml @@ -5,7 +5,7 @@ org.eclipse.rdf4j rdf4j-storage-parent - 2.5-SNAPSHOT + 3.0-SNAPSHOT rdf4j-repository-sail diff --git a/sail-api/pom.xml b/sail-api/pom.xml index 9d123c4e2..9f40abc3f 100644 --- a/sail-api/pom.xml +++ b/sail-api/pom.xml @@ -5,7 +5,7 @@ org.eclipse.rdf4j rdf4j-storage-parent - 2.5-SNAPSHOT + 3.0-SNAPSHOT rdf4j-sail-api diff --git a/sail-base/pom.xml b/sail-base/pom.xml index 0cbe92c79..382e2ae8f 100644 --- a/sail-base/pom.xml +++ b/sail-base/pom.xml @@ -5,7 +5,7 @@ org.eclipse.rdf4j rdf4j-storage-parent - 2.5-SNAPSHOT + 3.0-SNAPSHOT rdf4j-sail-base diff --git a/sail-model/pom.xml b/sail-model/pom.xml index 3b5e7b209..d27c7218f 100644 --- a/sail-model/pom.xml +++ b/sail-model/pom.xml @@ -5,7 +5,7 @@ org.eclipse.rdf4j rdf4j-storage-parent - 2.5-SNAPSHOT + 3.0-SNAPSHOT rdf4j-sail-model diff --git a/sail-spin/pom.xml b/sail-spin/pom.xml index acb2f3ead..2d89a9211 100644 --- a/sail-spin/pom.xml +++ b/sail-spin/pom.xml @@ -5,7 +5,7 @@ org.eclipse.rdf4j rdf4j-storage-parent - 2.5-SNAPSHOT + 3.0-SNAPSHOT rdf4j-sail-spin diff --git a/shacl/pom.xml b/shacl/pom.xml index fec633d6f..19a19b313 100644 --- a/shacl/pom.xml +++ b/shacl/pom.xml @@ -8,7 +8,7 @@ org.eclipse.rdf4j rdf4j-storage-parent - 2.5-SNAPSHOT + 3.0-SNAPSHOT rdf4j-shacl diff --git a/solr/pom.xml b/solr/pom.xml index 012623df3..94a9b2bdc 100644 --- a/solr/pom.xml +++ b/solr/pom.xml @@ -5,7 +5,7 @@ org.eclipse.rdf4j rdf4j-storage-parent - 2.5-SNAPSHOT + 3.0-SNAPSHOT rdf4j-sail-solr diff --git a/spin/pom.xml b/spin/pom.xml index ef7b90f4a..2c00e0e21 100644 --- a/spin/pom.xml +++ b/spin/pom.xml @@ -5,7 +5,7 @@ org.eclipse.rdf4j rdf4j-storage-parent - 2.5-SNAPSHOT + 3.0-SNAPSHOT rdf4j-spin diff --git a/storage/pom.xml b/storage/pom.xml index 5cfc6d36f..5699ce74b 100644 --- a/storage/pom.xml +++ b/storage/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-storage-parent - 2.5-SNAPSHOT + 3.0-SNAPSHOT rdf4j-storage RDF4J: Storage