`ShaclSailValidationException` in `connection.commit()` when adding SHACL rules with `sh:targetNode`
danaivach opened this issue · 3 comments
Current Behavior
RDF4J SailRepositoryConnection
throws a ShaclSailValidationException
in connection.commit()
when adding SHACL rules with sh:targetNode
combined with sh:minCount
>0 or with sh:hasValue
.
Expected Behavior
I'm flagging it as a bug because I would expect that sh:targetNode
is supported based on #1362 and #1574.
Steps To Reproduce
Code sample:
String shaclRules = "@prefix sh: <http://www.w3.org/ns/shacl#> .\n" +
"@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .\n\n" +
"<http://example.org/component/component-state-context>\n" +
" a sh:PropertyShape;\n" +
" sh:targetNode <http://example.org/component>;\n" +
" sh:path <https://saref.etsi.org/core/hasState>;\n" +
" sh:maxCount 1;\n" +
" sh:minCount 1;\n" +
" sh:hasValue \"ready\".";
ShaclSail shaclSail = new ShaclSail(new MemoryStore());
Repository repo = new SailRepository(shaclSail);
try (RepositoryConnection connection = repo.getConnection()) {
// add shapes
connection.begin();
connection.clear(RDF4J.SHACL_SHAPE_GRAPH);
connection.add(new StringReader(shaclRules), "", RDFFormat.TURTLE, RDF4J.SHACL_SHAPE_GRAPH);
connection.commit();
} catch (IOException e) {
throw new RuntimeException(e);
}
Exception:
org.eclipse.rdf4j.sail.shacl.ShaclSailValidationException: Failed SHACL validation
org.eclipse.rdf4j.repository.RepositoryException: org.eclipse.rdf4j.sail.shacl.ShaclSailValidationException: Failed SHACL validation
at org.eclipse.rdf4j.repository.sail.SailRepositoryConnection.commit(SailRepositoryConnection.java:228)
at ch.unisg.ics.interactions.hmas.interaction.validation.ShaclValidationTest.testContextValidationRDF4j(ShaclValidationTest.java:178)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
Caused by: org.eclipse.rdf4j.sail.shacl.ShaclSailValidationException: Failed SHACL validation
at org.eclipse.rdf4j.sail.shacl.ShaclSailConnection.prepare(ShaclSailConnection.java:892)
at org.eclipse.rdf4j.repository.sail.SailRepositoryConnection.commit(SailRepositoryConnection.java:225)
Version
5.0.2
Are you interested in contributing a solution yourself?
None
Anything else?
No response
Our implementation is based on the premise that a target node doesn't actually have to exist for it to violate a shape. In your case you are saying that <http://example.org/component>
has to have at least one <https://saref.etsi.org/core/hasState>
path when using sh:minCount 1
.
I'll check the specification and test cases to see if this is the correct interpretation or not.
The spec isn't exactly very clear: https://www.w3.org/TR/shacl/#targetNode
But there is a test case that is validated against the reference SHACL implementation:
- https://github.com/eclipse-rdf4j/rdf4j/blob/main/core/sail/shacl/src/test/resources/test-cases/minCount/targetNode/shacl.trig
- https://github.com/eclipse-rdf4j/rdf4j/tree/main/core/sail/shacl/src/test/resources/test-cases/minCount/targetNode/invalid/case2
There is also a test from the W3C SHACL test suite that tests for something similar: https://github.com/eclipse-rdf4j/rdf4j/blob/main/core/sail/shacl/src/test/resources/w3c/core/node/datatype-002.ttl
An issue with that test though is that it doesn't seem to differentiate between what is data and what are shapes, so the nodes are definitely present in the data graph.
Thank you. I had misinterpreted the role of the SHACL rules upon committing them, assuming that the rules will not be violated if the target node does not exist.
The ShaclSailValidationException
is indeed not raised if the conforming node is added in the graph prior to the addition of the SHACL rules.