TopQuadrant / shacl

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

sh:Rules Entailment Regime only partly run before SHACL validation #111

Closed mucaho closed 3 years ago

mucaho commented 3 years ago

For the following minimum reproducible example:

# data_shapes_file.ttl

@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix ex: <http://example.com/> .

### DATA

ex:a ex:p ex:b .

### SHAPES

<http://example.com/>
    sh:entailment sh:Rules ;
    sh:declare [
        sh:prefix "ex" ;
        sh:namespace "http://example.com/"^^xsd:anyURI ;
    ] .

ex:TestShape
    a sh:NodeShape ;
    sh:targetNode ex:a ;
    # Inference rules that should be run before validation
    sh:rule [ # changing this to a triple rule has no effect on bug
        a sh:SPARQLRule ;
        sh:prefixes <http://example.com/> ;
        sh:construct """
            CONSTRUCT {
                ex:a ex:q ex:b .
            }
            WHERE {
                ex:a ex:p ex:b .
            }
        """ ;
        sh:order 0 ; # changing this to -2 has no effect on bug
    ] ;
    sh:rule [ # changing this to a triple rule has no effect on bug
        a sh:SPARQLRule ;
        sh:prefixes <http://example.com/> ;
        sh:construct """
            CONSTRUCT {
                ex:a ex:r ex:b .
            }
            WHERE {
                ex:a ex:q ex:b .
            }
        """ ;
        sh:order 1 ; # changing this to -1 has no effect on bug
    ] ;
    # Validation that should be done after all inference rules
    sh:property [
        sh:path ex:p ;
        sh:minCount 1 ;
    ] ;
    sh:property [
        sh:path ex:q ;
        sh:minCount 1 ;
    ] ;
    sh:property [
        sh:path ex:r ;
        sh:minCount 1 ;
    ] .

One would expect all rounds of SHACL rules to be executed prior to the run of SHACL validation, as described in the SHACL-AF W3C technical report on the sh:Rules Entailment Regime.

However, running $ ./shaclvalidate.sh -datafile data_shapes_file.ttl produces the following, (imo) erroneous validation report:

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

[ a            sh:ValidationReport ;
  sh:conforms  false ;
  sh:result    [ a                             sh:ValidationResult ;
                 sh:focusNode                  ex:a ;
                 sh:resultMessage              "Property needs to have at least 1 values, but found 0" ;
                 sh:resultPath                 ex:r ;
                 sh:resultSeverity             sh:Violation ;
                 sh:sourceConstraintComponent  sh:MinCountConstraintComponent ;
                 sh:sourceShape                [] 
               ]
] .

For reference, the triples do get correctly inferred by $ ./shaclinfer.sh -datafile data_shapes_file.ttl:

@prefix rdf:   <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix owl:   <http://www.w3.org/2002/07/owl#> .
@prefix xsd:   <http://www.w3.org/2001/XMLSchema#> .
@prefix rdfs:  <http://www.w3.org/2000/01/rdf-schema#> .

<http://example.com/a>
        <http://example.com/q>  <http://example.com/b> ;
        <http://example.com/r>  <http://example.com/b> .

I am running the latest SHACL API v1.3.2 on x64 linux.

HolgerKnublauch commented 3 years ago

Thank you, this seems to be a bug in the API. It works correctly when I change RulesEntailment as follows

    Dataset newDataset = new DatasetWithDifferentDefaultModel(unionDataModel, dataset);
    RuleEngine engine = new RuleEngine(newDataset, shapesGraphURI, shapesGraph, inferencesModel);

which means that the engine will actually see the previous inferences (from your first rule) when it executes the second rule.

I am changing this in our internal code base and the change will go live the next time I synch our code base with the open source repo. I am long overdue doing so, but I cannot promise when yet (I just returned from 3 weeks of vacation and have plenty of things to catch up on).

Could you meanwhile apply the change above in your local copy to confirm the suggested fix?

mucaho commented 3 years ago

Thank you!

Putting the above example in a test.ttl file, adapting the ValidationExample test file to use the new example file, as well as adding the proposed changes into the RuleEntailment class does indeed fix the issue for me:

java [...] org.topbraid.shacl.ValidationExample
@base          <http://example.org/random> .
@prefix dash: <http://datashapes.org/dash#> .
@prefix ex:   <http://example.com/> .
@prefix owl:  <http://www.w3.org/2002/07/owl#> .
@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#> .
@prefix swa:  <http://topbraid.org/swa#> .
@prefix tosh: <http://topbraid.org/tosh#> .
@prefix xsd:  <http://www.w3.org/2001/XMLSchema#> .

[ rdf:type     sh:ValidationReport ;
  sh:conforms  true
] .

Process finished with exit code 0

On current master efc9fcc8bf2047d2e6172301fd42a280629e725f

HolgerKnublauch commented 3 years ago

Thanks for the confirmation. I have now applied the same fix to the public repo. I believe this closes the ticket. Let me know otherwise.