sparna-git / shacl-play

SHACL validation UI, SHACL documentation generator, SHACL generator from RDF.
http://shacl-play.sparna.fr
GNU Lesser General Public License v3.0
24 stars 15 forks source link

Generation of Shacl Shapes with min max cardinalities. #153

Closed arrascue closed 1 month ago

arrascue commented 1 month ago

Hi, We have been using Shacl Play to generate some shapes and recently tried to generate cardinality shapes, i.e. the one that have min and max cardinality.

We saw this is extracted from restrictions like this one:

brick:Storey a owl:Class ;
        rdfs:subClassOf [
                a owl:Restriction ;
                owl:onProperty ex:hasSpace ;
                owl:minCardinality "1"^^xsd:nonNegativeInteger ;
                owl:maxCardinality "5"^^xsd:nonNegativeInteger ;
                owl:onClass brick:Space
            ] .

ex:hasSpace a owl:ObjectProperty ;
    rdfs:range brick:Space .

This is translated into the following shape:

brick:Storey-hasSpace
        a            sh:PropertyShape ;
        sh:class     brick:Space ;
        sh:maxCount  5 ;
        sh:minCount  1 ;
        sh:path      ex:hasSpace .

This works as expected. However there are cases in which we would like to make the shape more precise and instead of using brick:Space, we would like to use a subclass of it:

brick:Storey a owl:Class ;
        rdfs:subClassOf [
                a owl:Restriction ;
                owl:onProperty ex:hasSpace ;
                owl:minCardinality "1"^^xsd:nonNegativeInteger ;
                owl:maxCardinality "5"^^xsd:nonNegativeInteger ;
                owl:onClass brick:Room
            ] .

ex:hasSpace a owl:ObjectProperty ;
    rdfs:range brick:Space .

brick:Room rdfs:subClassOf  brick:Space .

Although I have specified a more concrete class in the restriction, the superclass class used as the range of the predicate seems to precede.

We were wondering whether this is an intentional design choice of the tool's authors. If yes, what is the motivation behind it?

meandor commented 1 month ago

uh nice, we would also need this!

Janakiram916 commented 1 month ago

Yeah I do have the same question. Why the value of owl:onClass in restriction was preceded by the range of object property used in the restriction. As of my investigation I landed in the following script: (https://github.com/sparna-git/owl2shacl/blob/c012a0870403f124c35fe6f7207d68bd77875df6/owl2sh-semi-closed.ttl#L336)

owl2sh-semi-closed:owlMaxCardinality2shMaxCount
  rdf:type sh:SPARQLRule ;
  rdfs:comment "For each owl:maxCardinality restriction, create a corresponding sh:maxCount constraint." ;
  rdfs:label "owl:maxCardinality to sh:maxCount" ;
  sh:construct """
      CONSTRUCT {
        ?propertyShape sh:maxCount ?maxCount .
        # ?restriction owl2sh-semi-closed:mappedTo ?propertyShape .
      }
      WHERE {
        $this rdfs:subClassOf ?restriction .
        ?restriction a owl:Restriction .
        FILTER isBlank(?restriction) .
        ?restriction owl:onProperty ?property .
        ?restriction owl:maxCardinality|owl:cardinality ?raw .
        BIND (xsd:integer(?raw) AS ?maxCount) .
        BIND (owl2sh-semi-closed:getPropertyShape(?property, $this) AS ?propertyShape) .
      }
      """ ;
  sh:order 6 ;
  sh:prefixes <http://data.sparna.fr/ontologies/owl2sh-semi-closed> ;

and the use of sparql function owl2sh-semi-closed:getPropertyShape(?property, $this) within the above mentioned SPARQL rule is the cause of this issue.

My assumption, we wouldn't have this problem, If the SPARQLRule didn't depend on the above function.

tfrancart commented 1 month ago

I think this is supported but with owl:maxQualifiedCardinality and not owl:maxCardinality : https://github.com/sparna-git/owl2shacl/blob/c012a0870403f124c35fe6f7207d68bd77875df6/owl2sh-semi-closed.ttl#L358

Indeed the rulesets are maintained externaly in this repo : https://github.com/sparna-git/owl2shacl - you can adapt/fork them and pass another rule URL when converting your OWL ontology.

Also, note the SHACL generation utility from an RDF graph analysis, (versus from an OWL ontology) : https://shacl-play.sparna.fr/play/generate

arrascue commented 1 month ago

@tfrancart We tried the qualified cardinalities and it worked for our use-case. Thank you.

Janakiram916 commented 1 month ago

Yes It also worked for us.