I'm encountering an issue when using SHACL with sh:closed true
in combination with inheritance. Specifically, the problem arises when a subclass has properties that the super class does not.
Here is an example ontology:
onto:prop a owl:DatatypeProperty .
onto:SuperClass a owl:Class .
onto:SubClass
a owl:Class ;
rdfs:subClassOf onto:SuperClass,
[
a owl:Restriction ;
owl:onProperty onto:Prop ;
owl:cardinality 1
] .
Example Data:
This statement should evaluate as correct:
ex:ExampleCorrect a onto:SubClass ;
onto:prop "Text" .
However, these should be incorrect:
ex:ExampleWrong a onto:SubClass ;
onto:other 1 .
ex:ExampleWrongSuperClass a onto:SuperClass ;
onto:prop "Text" .
Solutions:
These are the types of shapes I would construct if I wanted to prevent additional properties to be used:
onto:SuperClass_Shape
a sh:NodeShape ;
sh:closed true ;
sh:targetClass onto:SuperClass .
onto:SubClass_Shape
a sh:NodeShape ;
sh:targetClass onto:SubClass ;
sh:closed true ;
sh:property [
a sh:PropertyShape ;
sh:maxCount 1 ;
sh:minCount 1 ;
sh:path onto:prop ;
sh:severity sh:Violation
] .
But because the onto:SuperClass_Shape
does not enumerate the property onto:prop
and sh:closed true
is applied , this results in a violation.
I know it is also possible target only a node instead of targeting a whole class as I did above.
onto:SubClass_Shape
a sh:NodeShape ;
sh:targetNode ex:ExampleCorrect .
But I have thousands of nodes that I want to evaluate at the same time. Enumerating all the data IRIs does not seem like a good solution to me.
I understand that my aim is somewhat contradictory to the logic of SHACL and RDF inheritance.
How can I structure the SHACL shapes to allow the subclass to have its own properties without violating the superclass's closed shape restrictions?
I want to prevent additional properties in all classes but still allow flexibility in sub-classes to define its own properties.
Any suggestions or insights would be appreciated!
sh:closed was (unfortunately) not designed to take subclass relationships into account. But many people have run into similar problems are you did, and there is the extension dash:closedByTypes to address it.
https://datashapes.org/constraints.html#ClosedByTypesConstraintComponent
To use that, you would need a SHACL engine with SHACL-SPARQL support.
The upcoming SHACL 1.2 WG may bring something like this into the SHACL Core vocabulary, see https://github.com/w3c/shacl/issues/43