TopQuadrant / shacl

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

How to express the exactly one or none condition on a shape list? #118

Closed sfontanel closed 3 years ago

sfontanel commented 3 years ago

Hi! I apologize in advance if I got something wrong in my examples but i am a shacl newbie :) . In my java project I'm using the latest library org.topbraid.shacl. I have the following requirement: I need to allow just zero or exactly one valid shape on a list of shapes. I tried to use the https://www.w3.org/TR/shacl/#XoneConstraintComponent and it works fine for the the "exactly one requirement" part :)

So I tried to reach my objective using logical operators ; I executed the shacl validator it and it seems to work as expected however I'm not sure to be in the right direction..

I give a simplified example starting from a library test cases for the XoneConstraintComponent:

This is the xone example simplified:

ex:XoneConstraintExampleShape rdf:type sh:NodeShape ; sh:targetClass ex:Person ; sh:xone ( [ sh:property [ sh:path ex:fullName ; sh:minCount 1 ; ] ; ] [ sh:property [ sh:path ex:firstName ; sh:minCount 1 ; ] ; ] ) ; .

Now, suppose that I would like a ex:Person to be validated successfully also if no one of those properties is present (in my real example the list of properties may include more than 2 properties). How could I solve it? If I set minCount to zero on the firstName and fullName shapes the xone returns correctly false because they are both true if a person has not such properties.

So I used the approach that You can see in the fragment in the attachment. myapproach.txt

Is this syntactically works? The shacl in my application that uses the same approach seems to work. Thank you very much! Stefano

HolgerKnublauch commented 3 years ago

Hi Stefano

(for future reference I would suggest to use some more generic place such as StackOverflow for general modeling questions, as the question is not really specific to the TopBraid API. Thanks).

If I understand your requirements correctly, can't you use

ex:XoneConstraintExampleShape
      rdf:type sh:NodeShape ;
      sh:targetClass ex:Person ;
      sh:xone (
          [
              sh:property [
                  sh:path ex:fullName ;
                  sh:minCount 1 ;
              ] ;
          ]
          [
              sh:property [
                  sh:path ex:firstName ;
                  sh:minCount 1 ;
              ] ;
          ]
          [
              sh:property [
                  sh:path [ sh:alternativePath ( ex:firstName ex:fullName ) ] ;
                  sh:maxCount 0 ;
              ]
          ]
      ) ;

This would mean "either it has fullName OR firstName OR neither firstName or fullName".

sfontanel commented 3 years ago

Hi Holger, thank you for your suggestion! Your proposal supports my requirements and it's also much simpler :) I'm sorry I wrote in the wrong place.

A last question before You close the issue: nesting logical constructs as in my example is syntactically correct or not? Thank you very much! Stefano

HolgerKnublauch commented 3 years ago

Yes it looks correct from a cursory view, but you may just as well try it out. Note that you never need sh:and - you can just pull up the two property shapes into the parent node shape, e.g.

[ sh:and ( [ ...A... ] [ ...B... ] ) ]

can be rewritten as

[ ...A... ...B... ]

because constraints are always ANDed together in their parent shape.