TopQuadrant / shacl

SHACL API in Java based on Apache Jena
Apache License 2.0
217 stars 61 forks source link

sh:closed in a property shape is inconsistent with other implementations #171

Closed hmottestad closed 6 months ago

hmottestad commented 6 months ago

Considering the following example:

@prefix ex: <http://example.com/ns#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix sh: <http://www.w3.org/ns/shacl#> .

ex:Person
    a rdfs:Class, sh:NodeShape ;
    sh:property [
        sh:path ex:knows ;
        sh:closed true;
        sh:property
            [
                sh:path ex:name ;
            ];

    ] .

I would assume to mean that for every ex:Person that ex:knows someone then that someone can only have the predicate ex:name.

So the following should be true:

@prefix ex: <http://example.com/ns#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix sh: <http://www.w3.org/ns/shacl#> .

ex:validPerson1 a ex:Person ;
    ex:knows 
        [
            ex:name "John" ;
        ] .

The Zazuko SHACL Playground seems to agree with me https://s.zazuko.com/spVG6w and so does the old https://shacl.org/playground/.

When using the version 1.4.3 of the SHACL TopBraid API I get the following validation report:

[] a sh:ValidationReport;
  sh:conforms false;
  sh:result [ a sh:ValidationResult;
      sh:focusNode ex:validPerson1;
      sh:resultMessage "Predicate <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> is not allowed (closed shape)";
      sh:resultPath rdf:type;
      sh:resultSeverity sh:Violation;
      sh:sourceConstraintComponent sh:ClosedConstraintComponent;
      sh:sourceShape _:genid-1b9aa17a7d5f4f3cb7c0c4c438ac426111-b0;
      sh:value ex:Person
    ], [ a sh:ValidationResult;
      sh:focusNode ex:validPerson1;
      sh:resultMessage "Predicate <http://example.com/ns#knows> is not allowed (closed shape)";
      sh:resultPath ex:knows;
      sh:resultSeverity sh:Violation;
      sh:sourceConstraintComponent sh:ClosedConstraintComponent;
      sh:sourceShape _:genid-1b9aa17a7d5f4f3cb7c0c4c438ac426111-b0;
      sh:value []
    ] .
HolgerKnublauch commented 6 months ago

Thanks for this. Quite possibly this is incorrect right now. The code is looping over the focus nodes, while I believe it needs to loop over the value nodes. And the test suite only covers the case of using sh:closed in node shapes, not property shapes.

hmottestad commented 6 months ago

The validation report that the old playground creates is a bit funky.

I've added ex:test as a new predicate here to make the data invalid.

ex:validPerson1 a ex:Person ;
    ex:knows 
        [
            ex:name "John" ;
            ex:test "a";
        ] .

And here is the validation report.

[
    a sh:ValidationResult ;
    sh:resultSeverity sh:Violation ;
    sh:sourceConstraintComponent sh:ClosedConstraintComponent ;
    sh:sourceShape _:n241 ;
    sh:focusNode ex:validPerson1 ;
    sh:resultPath ex:test ;
    sh:value "a" ;
    sh:resultMessage "Predicate is not allowed (closed shape)" ;
] .

What is funky is that the blank node representing "John" isn't included. The spec doesn't really say anything about what the sh:focusNode should be for sh:closed. When used in a node shape this isn't really an issue since the focus node and the value node are the same, so overriding the typical sh:resultPath and sh:value doesn't end up loosing anything. For the property shape though the sh:value would usually be the blank node representing "John" and the sh:resultPath would be ex:knows.

In general I think it would make more sense to only allow node shapes to be closed, but I assume that that would break backwards compatibility if we change it in SHACL 1.2.