Search code examples
sparqlrulesinferenceshacl

SHACL sh:rule with sh:condition in SPARQL in Topbraid Composer


The example ontology has two classes (:MyClass and :Value) and two properties (:MyObjProp and :MyDataProp).

:MyClass
  a owl:Class ;
  a sh:NodeShape ;
  rdfs:subClassOf owl:Thing ;
.
:MyDataProp
  a owl:DatatypeProperty ;
  rdfs:domain :MyClass ;
  rdfs:range xsd:string ;
.
:MyObjProp
  a owl:ObjectProperty ;
  rdfs:domain :MyClass ;
  rdfs:range :Value ;
.
:Value
  a owl:Class ;
  rdfs:subClassOf owl:Thing ;
.

Some instances were added.

:MyClass_1
  a :MyClass ;
  :MyDataProp :Value_1 ;
  :MyObjProp :Value_1 ;
.
:MyClass_2
  a :MyClass ;
  :MyObjProp :Value_2 ;
.
:Value_1
  a :Value ;
.
:Value_2
  a :Value ;
.

A NodeShape :NodeShapeRule with a sh:rule (:SPARQLRule_1) was created. This rule creates new triples. With the sh:condition the rule should be restricted to a subset of targets.

:NodeShapeRule
  a sh:NodeShape ;
  sh:rule :SPARQLRule_1 ;
  sh:targetClass :MyClass ;
.
:SPARQLRule_1
  a sh:SPARQLRule ;
  sh:condition :NodeShapeConditionSPARQL ;
  sh:construct """
    PREFIX : <http://example.org/ex#>
    CONSTRUCT
    {
        $this :MyDataProp \"New input\" .
    }
    WHERE
    {
        $this :MyObjProp ?p .
    }
    """ ;
.

For the restriction two equivalent NodeShapes were defined. The first constraint works with sh:property, the other uses sh:sparql.

:NodeShapeConditionProperty
  a sh:NodeShape ;
  sh:property [
      sh:path :MyObjProp ;
      sh:description "NodeShapeConditionProperty" ;
      sh:hasValue :Value_1 ;
    ] ;
  sh:targetClass :MyClass ;
.
:NodeShapeConditionSPARQL
  a sh:NodeShape ;
  sh:sparql [
      sh:message "NodeShapeConditionSPARQL" ;
      sh:prefixes <http://example.org/ex> ;
      sh:select """
        PREFIX : <http://example.org/ex#>
        SELECT $this
        WHERE
        {
            $this :MyObjProp ?prop .
        }
        """ ;
    ] ;
  sh:targetClass :MyClass ;
.

While doing inferencing with Topbraid Composer I received different results for both solutions. Only the solution with sh:property provides the expected response. Please, can someone explain me this behavior?

:MyClass_1 :MyDataProp "New input"

Solution

  • The right explanation is that the SPAQRL query produces a constraint violation for each result (row) in SELECT query. So if the SPARQL query returns no result (rows) then all is fine and the rule will fire. The reason for this design is that this enables SPARQL queries to return more information about the violation, e.g. the focus node ($this) and the value node (?value).

    Changing the :NodeShapeConditionSPARQL it produces violation for not existing results and then both solutions behave in the same manner.

    :NodeShapeConditionSPARQL
      a sh:NodeShape ;
      sh:sparql [
          sh:message "NodeShapeConditionSPARQL" ;
          sh:prefixes <http://example.org/ex> ;
          sh:select """
            PREFIX : <http://example.org/ex#>
            SELECT $this
            WHERE
            {
                FILTER NOT EXISTS { $this :MyObjProp ?anyProp } .
            }
            """ ;
        ] ;
      sh:targetClass :MyClass ;
    .