diff --git a/shacl12-core/index.html b/shacl12-core/index.html index b89778b7..5b7de87b 100644 --- a/shacl12-core/index.html +++ b/shacl12-core/index.html @@ -2762,6 +2762,9 @@

Handling of Recursive Shapes

  • sh:qualifiedValueShape
  • sh:node
  • sh:memberShape
  • +
  • sh:minListLength
  • +
  • sh:maxListLength
  • +
  • sh:uniqueMembers
  • sh:xone
  • @@ -4517,6 +4520,462 @@

    sh:uniqueLang

    +
    +

    List Constraint Components

    +

    + The constraint components in this section apply to value nodes that are SHACL lists. + They specify conditions on the structure, length, and members of SHACL lists. +

    + +
    +

    sh:memberShape

    +

    + sh:memberShape specifies that all members of SHACL list value nodes must conform to the given node shape. +

    +

    + Constraint Component IRI: sh:MemberShapeConstraintComponent +

    + +
    Parameters:
    + + + + + + + + + +
    PropertySummary and Syntax Rules
    sh:memberShape + The shape that all members of the SHACL list must conform to. + The value of sh:memberShape must be a well-formed node shape. +
    +
    +
    TEXTUAL DEFINITION
    +
    + Let $memberShape be a parameter value for sh:memberShape. + Each value node v must be a SHACL list - if v is not a SHACL list there is a validation result. + If any member m of the SHACL list v does not conform to $memberShape, there is a validation result. +
    +
    +

    The remainder of this section is informative.

    +

    + Each member m of a value node v that does not conform to the $memberShape should be reported as a separate sh:detail in the validation result for v. + If v is not a valid SHACL list, this should be reported as a top-level validation result and validation of individual members should not be attempted. +

    +

    + Examples of how to generate sh:details in validation results can be found in the test cases for sh:memberShape in the SHACL test suite: memberShape-001.ttl. +

    +

    + In the following example, all values of the property ex:speakerOrder must be SHACL lists with members that are IRIs. +

    + +
    + +
    +

    sh:minListLength

    +

    + sh:minListLength specifies the minimum number of members that SHACL list value nodes must have. +

    +

    + Constraint Component IRI: sh:MinListLengthConstraintComponent +

    + +
    Parameters:
    + + + + + + + + + +
    PropertySummary and Syntax Rules
    sh:minListLength + The minimum number of members in the SHACL list. + The values of sh:minListLength in a shape are literals with datatype xsd:integer. + The values of sh:minListLength in a shape are integers greater than or equal to 0. +
    +
    +
    TEXTUAL DEFINITION
    +
    + Let $minListLength be a parameter value for sh:minListLength. + Each value node v must be a SHACL list - if v is not a SHACL list there is a validation result. + If the number of members in a list v is less than $minListLength, + there is a validation result. +
    +
    +

    The remainder of this section is informative.

    +

    + In the following example, all values of the property ex:skills must be SHACL lists with at least 1 member. + Additional test cases for sh:minListLength can be found in the SHACL test suite: minListLength-001.ttl. +

    + +
    + +
    +

    sh:maxListLength

    +

    + sh:maxListLength specifies the maximum number of members that SHACL list value nodes must have. +

    +

    + Constraint Component IRI: sh:MaxListLengthConstraintComponent +

    + +
    Parameters:
    + + + + + + + + + +
    PropertySummary and Syntax Rules
    sh:maxListLength + The maximum number of members in the SHACL list. + The values of sh:maxListLength in a shape are literals with datatype xsd:integer. + The values of sh:maxListLength in a shape are integers greater than or equal to 0. +
    +
    +
    TEXTUAL DEFINITION
    +
    + Let $maxListLength be a parameter value for sh:maxListLength. + Each value node v must be a SHACL list - if v is not a SHACL list there is a validation result. + If the number of members in the list v is greater than $maxListLength, + there is a validation result. +
    +
    +

    The remainder of this section is informative.

    +

    + In the following example, all values of the property ex:hobbies must be SHACL lists with at most 2 members. + Additional test cases for sh:maxListLength can be found in the SHACL test suite: maxListLength-001.ttl. +

    + +
    + +
    +

    sh:uniqueMembers

    +

    + sh:uniqueMembers specifies whether SHACL list value nodes must have unique members. +

    +

    + Constraint Component IRI: sh:UniqueMembersConstraintComponent +

    + +
    Parameters:
    + + + + + + + + + +
    PropertySummary and Syntax Rules
    sh:uniqueMembers + A boolean that specifies whether the members of the SHACL list must be unique. + The values of sh:uniqueMembers in a shape are literals with datatype xsd:boolean. +
    +
    +
    TEXTUAL DEFINITION
    +
    + Let $uniqueMembers be a parameter value for sh:uniqueMembers. + Each value node v must be a SHACL list - if v is not a SHACL list there is a validation result. + If $uniqueMembers is true and the list v has duplicate members, + there is a validation result. +
    +
    +

    The remainder of this section is informative.

    +

    + Each duplicate member m of a list v should be reported as a separate sh:detail in the validation result for v. If the list v is not a valid SHACL list, this should be reported as a top-level validation result and validation of unique membership should not be attempted. +

    +

    + Examples of how to generate sh:details in validation results can be found in the test cases for sh:uniqueMembers in the SHACL test suite: uniqueMembers-001.ttl. +

    +

    + In the following example, all values of the property ex:preferences must be SHACL lists with members that have unique values within each SHACL list. +

    + +
    +
    +

    Property Pair Constraint Components

    @@ -5692,196 +6151,6 @@

    sh:property

    -
    -

    sh:memberShape

    -

    - sh:memberShape requires that each value node be a SHACL list, - and that each member of that list conforms to the given node shape. -

    -

    - Constraint Component IRI: sh:MemberShapeConstraintComponent -

    - -
    Parameters:
    - - - - - - - - - -
    PropertySummary and Syntax Rules
    sh:memberShape - The shape that all members of the SHACL list must conform to. - The value of sh:memberShape must be a well-formed node shape. -
    -
    -
    TEXTUAL DEFINITION
    -
    - Let $memberShape be a value of sh:memberShape. - Each value node v must be a SHACL list - a failure MUST be produced if v is not a SHACL list. - For each member m of the list v - a failure MUST be produced if the conformance checking of m against $memberShape produces a failure. - There MUST be at most one validation result for each list v and set of triggering constraints. - - The sh:detail property SHOULD be used to specify the validation results for each member m of the list that fails conformance checking. - m SHOULD be used as the sh:focusNode for each sh:detail result. - - The sh:detail property SHOULD also be used to specify when v is not a valid SHACL list. - v SHOULD be used as the sh:focusNode for this sh:detail result. -
    -
    -

    The remainder of this section is informative.

    -

    - In the following example, all values of the property ex:speakerOrder must be RDF lists, and each member of those lists must be an IRI. - Note that sh:memberShape can be used in both property shapes (as shown) and node shapes (where it would apply to the focus node itself). - - Examples of how to generate sh:details can be found in the test cases for sh:memberShape in the SHACL test suite: memberShape-001.ttl. -

    - -
    -

    sh:qualifiedValueShape, sh:qualifiedMinCount, sh:qualifiedMaxCount

    diff --git a/shacl12-test-suite/tests/core/node/manifest.ttl b/shacl12-test-suite/tests/core/node/manifest.ttl index 6dd5e465..4cb49515 100644 --- a/shacl12-test-suite/tests/core/node/manifest.ttl +++ b/shacl12-test-suite/tests/core/node/manifest.ttl @@ -26,12 +26,14 @@ mf:include ; mf:include ; mf:include ; + mf:include ; mf:include ; mf:include ; mf:include ; mf:include ; mf:include ; mf:include ; + mf:include ; mf:include ; mf:include ; mf:include ; @@ -41,6 +43,7 @@ mf:include ; mf:include ; mf:include ; + mf:include ; mf:include ; mf:include ; mf:include ; diff --git a/shacl12-test-suite/tests/core/node/maxListLength-001.ttl b/shacl12-test-suite/tests/core/node/maxListLength-001.ttl new file mode 100644 index 00000000..5e412494 --- /dev/null +++ b/shacl12-test-suite/tests/core/node/maxListLength-001.ttl @@ -0,0 +1,63 @@ +@prefix dash: . +@prefix ex: . +@prefix mf: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix sht: . +@prefix xsd: . + +ex:ListShape + rdf:type sh:NodeShape ; + sh:maxListLength 2 ; + # Satisfies all constraints + sh:targetNode ex:list0, rdf:nil ; + # Violates maxListLength constraint + sh:targetNode ex:list1, ex:notAList ; +. + +ex:list0 + rdf:first 1 ; + rdf:rest ( 2 ) . + +ex:list1 + rdf:first 1 ; + rdf:rest ( 2 3 ) . + +<> + rdf:type mf:Manifest ; + mf:entries ( + + ) ; +. + + + rdf:type sht:Validate ; + rdfs:label "Test of sh:maxListLength on node shape 001" ; + mf:action [ + sht:dataGraph <> ; + sht:shapesGraph <> ; + ] ; + mf:result [ + rdf:type sh:ValidationReport ; + sh:conforms "false"^^xsd:boolean ; + sh:result [ + rdf:type sh:ValidationResult ; + sh:focusNode ex:list1 ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:MaxListLengthConstraintComponent ; + sh:sourceShape ex:ListShape ; + sh:value ex:list1 ; + ] ; + sh:result [ + rdf:type sh:ValidationResult ; + sh:focusNode ex:notAList ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:MaxListLengthConstraintComponent ; + sh:sourceShape ex:ListShape ; + sh:value ex:notAList ; + ] ; + ] ; + mf:status sht:approved ; +. diff --git a/shacl12-test-suite/tests/core/node/memberShape-001.ttl b/shacl12-test-suite/tests/core/node/memberShape-001.ttl index b2518285..9dde67e2 100644 --- a/shacl12-test-suite/tests/core/node/memberShape-001.ttl +++ b/shacl12-test-suite/tests/core/node/memberShape-001.ttl @@ -14,57 +14,64 @@ ex:IRIShape a sh:NodeShape ; ex:IRIListShape rdf:type sh:NodeShape ; sh:memberShape ex:IRIShape ; - sh:targetNode ( ex:Alice ex:Bob ) ; + sh:targetNode ex:list0 ; # Valid empty list - sh:targetNode () ; - # _:b1 is valid, the remainder trigger violations (including _:b3 which has no properties in this graph) - sh:targetNode _:b1, _:b2, _:b3, _:b4, _:b5, _:b6, _:b7, _:b9 ; + sh:targetNode rdf:nil ; + # ex:list1 is valid, the remainder trigger violations (including ex:list3 which has no properties in this graph) + sh:targetNode ex:list1, ex:list2, ex:list3, ex:list4, ex:list5, ex:list6, ex:list7, ex:list9 ; . -_:b1 +ex:list0 + rdf:first ex:Alice ; + rdf:rest ( + ex:Bob + ) ; +. + +ex:list1 rdf:first ex:Alice ; rdf:rest rdf:nil ; ex:extraProperty "extra" ; . -_:b2 +ex:list2 rdf:first ex:Alice ; rdf:rest ( "Bob" ) . -_:b4 +ex:list4 rdf:first ex:Alice ; . -_:b5 +ex:list5 rdf:first "Charlie" ; rdf:rest ( "Donna" ) . -_:b6 +ex:list6 rdf:first "Charlie" ; . -_:b8 rdfs:label "Malformed SHACL List" . +ex:list8 rdfs:label "Malformed SHACL List" . -_:b7 +ex:list7 rdf:first "Charlie" ; - rdf:rest _:b8 ; + rdf:rest ex:list8 ; . -# using _:b9 and _:b10 to test recursive list error -_:b9 +# using ex:list9 and ex:list10 to test recursive list error +ex:list9 rdf:first ex:Alice ; - rdf:rest _:b10 ; + rdf:rest ex:list10 ; . -_:b10 +ex:list10 rdf:first "Bob" ; - rdf:rest _:b9 . + rdf:rest ex:list9 . <> rdf:type mf:Manifest ; @@ -85,15 +92,13 @@ _:b10 sh:conforms "false"^^xsd:boolean ; sh:result [ rdf:type sh:ValidationResult ; - sh:focusNode _:b2 ; - sh:resultMessage "Value does not conform to Shape ex:IRIListShape. See details for more information." ; + sh:focusNode ex:list2 ; sh:resultSeverity sh:Violation ; sh:sourceConstraintComponent sh:MemberShapeConstraintComponent ; sh:sourceShape ex:IRIListShape ; sh:detail [ rdf:type sh:ValidationResult ; sh:focusNode "Bob" ; - sh:resultMessage "Value is not of Node Kind sh:IRI" ; sh:resultSeverity sh:Violation ; sh:sourceConstraintComponent sh:NodeKindConstraintComponent ; sh:sourceShape ex:IRIShape ; @@ -102,51 +107,29 @@ _:b10 ] ; sh:result [ rdf:type sh:ValidationResult ; - sh:focusNode _:b3 ; - sh:resultMessage "Value is a malformed SHACL List." ; + sh:focusNode ex:list3 ; sh:resultSeverity sh:Violation ; sh:sourceConstraintComponent sh:MemberShapeConstraintComponent ; sh:sourceShape ex:IRIListShape ; - sh:value _:b3 ; - sh:detail [ - rdf:type sh:ValidationResult ; - sh:focusNode _:b3 ; - sh:resultMessage "Value is a malformed SHACL List. _:b3 is missing rdf:first and rdf:rest properties." ; - sh:resultSeverity sh:Violation ; - sh:sourceConstraintComponent sh:MemberShapeConstraintComponent ; - sh:sourceShape ex:IRIListShape ; - sh:value _:b3 ; - ] ; + sh:value ex:list3 ; ] ; sh:result [ rdf:type sh:ValidationResult ; - sh:focusNode _:b4 ; - sh:resultMessage "Value does not conform to Shape ex:IRIListShape. See details for more information." ; + sh:focusNode ex:list4 ; sh:resultSeverity sh:Violation ; sh:sourceConstraintComponent sh:MemberShapeConstraintComponent ; sh:sourceShape ex:IRIListShape ; - sh:value _:b4 ; - sh:detail [ - rdf:type sh:ValidationResult ; - sh:focusNode _:b4 ; - sh:resultMessage "Value is a malformed SHACL List. _:b4 is missing rdf:rest property." ; - sh:resultSeverity sh:Violation ; - sh:sourceConstraintComponent sh:MemberShapeConstraintComponent ; - sh:sourceShape ex:IRIListShape ; - sh:value _:b4 ; - ] ; + sh:value ex:list4 ; ] ; sh:result [ rdf:type sh:ValidationResult ; - sh:focusNode _:b5 ; - sh:resultMessage "Value does not conform to Shape ex:IRIListShape. See details for more information." ; + sh:focusNode ex:list5 ; sh:resultSeverity sh:Violation ; sh:sourceConstraintComponent sh:MemberShapeConstraintComponent ; sh:sourceShape ex:IRIListShape ; sh:detail [ rdf:type sh:ValidationResult ; sh:focusNode "Charlie" ; - sh:resultMessage "Value is not of Node Kind sh:IRI" ; sh:resultSeverity sh:Violation ; sh:sourceConstraintComponent sh:NodeKindConstraintComponent ; sh:sourceShape ex:IRIShape ; @@ -154,7 +137,6 @@ _:b10 ], [ rdf:type sh:ValidationResult ; sh:focusNode "Donna" ; - sh:resultMessage "Value is not of Node Kind sh:IRI" ; sh:resultSeverity sh:Violation ; sh:sourceConstraintComponent sh:NodeKindConstraintComponent ; sh:sourceShape ex:IRIShape ; @@ -163,78 +145,27 @@ _:b10 ] ; sh:result [ rdf:type sh:ValidationResult ; - sh:focusNode _:b6 ; - sh:resultMessage "Value does not conform to Shape ex:IRIListShape. See details for more information." ; + sh:focusNode ex:list6 ; sh:resultSeverity sh:Violation ; sh:sourceConstraintComponent sh:MemberShapeConstraintComponent ; sh:sourceShape ex:IRIListShape ; - sh:detail [ - rdf:type sh:ValidationResult ; - sh:focusNode "Charlie" ; - sh:resultMessage "Value is not of Node Kind sh:IRI" ; - sh:resultSeverity sh:Violation ; - sh:sourceConstraintComponent sh:NodeKindConstraintComponent ; - sh:sourceShape ex:IRIShape ; - sh:value "Charlie" ; - ], [ - rdf:type sh:ValidationResult ; - sh:focusNode _:b6 ; - sh:resultMessage "Value is a malformed SHACL List. _:b6 is missing rdf:rest property." ; - sh:resultSeverity sh:Violation ; - sh:sourceConstraintComponent sh:MemberShapeConstraintComponent ; - sh:sourceShape ex:IRIListShape ; - sh:value _:b6 ; - ] ; + sh:value ex:list6 ; ] ; sh:result [ rdf:type sh:ValidationResult ; - sh:focusNode _:b7 ; - sh:resultMessage "Value does not conform to Shape ex:IRIListShape. See details for more information." ; + sh:focusNode ex:list7 ; sh:resultSeverity sh:Violation ; sh:sourceConstraintComponent sh:MemberShapeConstraintComponent ; sh:sourceShape ex:IRIListShape ; - sh:detail [ - rdf:type sh:ValidationResult ; - sh:focusNode "Charlie" ; - sh:resultMessage "Value is not of Node Kind sh:IRI" ; - sh:resultSeverity sh:Violation ; - sh:sourceConstraintComponent sh:NodeKindConstraintComponent ; - sh:sourceShape ex:IRIShape ; - sh:value "Charlie" ; - ], [ - rdf:type sh:ValidationResult ; - sh:focusNode _:b8 ; - sh:resultMessage "Value is a malformed SHACL List. _:b8 is missing rdf:first and rdf:rest property." ; - sh:resultSeverity sh:Violation ; - sh:sourceConstraintComponent sh:MemberShapeConstraintComponent ; - sh:sourceShape ex:IRIListShape ; - sh:value _:b8 ; - ] ; + sh:value ex:list8 ; ] ; sh:result [ rdf:type sh:ValidationResult ; - sh:focusNode _:b9 ; - sh:resultMessage "Value does not conform to Shape ex:IRIListShape. See details for more information." ; + sh:focusNode ex:list9 ; sh:resultSeverity sh:Violation ; sh:sourceConstraintComponent sh:MemberShapeConstraintComponent ; sh:sourceShape ex:IRIListShape ; - sh:detail [ - rdf:type sh:ValidationResult ; - sh:focusNode "Charlie" ; - sh:resultMessage "Value is not of Node Kind sh:IRI" ; - sh:resultSeverity sh:Violation ; - sh:sourceConstraintComponent sh:NodeKindConstraintComponent ; - sh:sourceShape ex:IRIShape ; - sh:value "Charlie" ; - ], [ - rdf:type sh:ValidationResult ; - sh:focusNode _:b10 ; - sh:resultMessage "Value is a malformed SHACL List. A list cannot have itself in the rdf:rest+ path. List _:b9 follows from _:b10." ; - sh:resultSeverity sh:Violation ; - sh:sourceConstraintComponent sh:MemberShapeConstraintComponent ; - sh:sourceShape ex:IRIListShape ; - sh:value _:b9 ; - ] ; + sh:value ex:list10 ; ] ; ] ; mf:status sht:approved ; diff --git a/shacl12-test-suite/tests/core/node/minListLength-001.ttl b/shacl12-test-suite/tests/core/node/minListLength-001.ttl new file mode 100644 index 00000000..118a7ec0 --- /dev/null +++ b/shacl12-test-suite/tests/core/node/minListLength-001.ttl @@ -0,0 +1,58 @@ +@prefix dash: . +@prefix ex: . +@prefix mf: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix sht: . +@prefix xsd: . + +ex:ListShape + rdf:type sh:NodeShape ; + sh:minListLength 1 ; + # Satisfies all constraints + sh:targetNode ex:list0 ; + # Violates minListLength constraint + sh:targetNode rdf:nil, ex:notAList ; +. + +ex:list0 + rdf:first 1 ; + rdf:rest ( 2 ) . + +<> + rdf:type mf:Manifest ; + mf:entries ( + + ) ; +. + + + rdf:type sht:Validate ; + rdfs:label "Test of sh:minListLength on node shape 001" ; + mf:action [ + sht:dataGraph <> ; + sht:shapesGraph <> ; + ] ; + mf:result [ + rdf:type sh:ValidationReport ; + sh:conforms "false"^^xsd:boolean ; + sh:result [ + rdf:type sh:ValidationResult ; + sh:focusNode rdf:nil ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:MinListLengthConstraintComponent ; + sh:sourceShape ex:ListShape ; + ] ; + sh:result [ + rdf:type sh:ValidationResult ; + sh:focusNode ex:notAList ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:MinListLengthConstraintComponent ; + sh:sourceShape ex:ListShape ; + sh:value ex:notAList ; + ] ; + ] ; + mf:status sht:approved ; +. diff --git a/shacl12-test-suite/tests/core/node/uniqueMembers-001.ttl b/shacl12-test-suite/tests/core/node/uniqueMembers-001.ttl new file mode 100644 index 00000000..287e9137 --- /dev/null +++ b/shacl12-test-suite/tests/core/node/uniqueMembers-001.ttl @@ -0,0 +1,77 @@ +@prefix dash: . +@prefix ex: . +@prefix mf: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix sht: . +@prefix xsd: . + +ex:ListShape + rdf:type sh:NodeShape ; + sh:uniqueMembers true ; + # Satisfies all constraints + sh:targetNode ex:list0, rdf:nil ; + # Violates uniqueMembers constraint + sh:targetNode ex:list1, ex:notAList ; +. + +ex:list0 + rdf:first 1 ; + rdf:rest ( 2 ) . + +ex:list1 + rdf:first 1 ; + rdf:rest ( 2 1 2 2 ) . + +<> + rdf:type mf:Manifest ; + mf:entries ( + + ) ; +. + + + rdf:type sht:Validate ; + rdfs:label "Test of sh:uniqueMembers on node shape 001" ; + mf:action [ + sht:dataGraph <> ; + sht:shapesGraph <> ; + ] ; + mf:result [ + rdf:type sh:ValidationReport ; + sh:conforms "false"^^xsd:boolean ; + sh:result [ + rdf:type sh:ValidationResult ; + sh:focusNode ex:list1 ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:UniqueMembersConstraintComponent ; + sh:sourceShape ex:ListShape ; + sh:detail [ + rdf:type sh:ValidationResult ; + sh:focusNode ex:list1 ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:UniqueMembersConstraintComponent ; + sh:sourceShape ex:ListShape ; + sh:value 1 ; + ], [ + rdf:type sh:ValidationResult ; + sh:focusNode ex:list1 ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:UniqueMembersConstraintComponent ; + sh:sourceShape ex:ListShape ; + sh:value 2 ; + ] + ] ; + sh:result [ + rdf:type sh:ValidationResult ; + sh:focusNode ex:notAList ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:UniqueMembersConstraintComponent ; + sh:sourceShape ex:ListShape ; + sh:value ex:notAList ; + ] ; + ] ; + mf:status sht:approved ; +. diff --git a/shacl12-test-suite/tests/core/property/manifest.ttl b/shacl12-test-suite/tests/core/property/manifest.ttl index b6463005..a0c3e724 100644 --- a/shacl12-test-suite/tests/core/property/manifest.ttl +++ b/shacl12-test-suite/tests/core/property/manifest.ttl @@ -26,12 +26,14 @@ mf:include ; mf:include ; mf:include ; + mf:include ; mf:include ; mf:include ; mf:include ; mf:include ; mf:include ; mf:include ; + mf:include ; mf:include ; mf:include ; mf:include ; @@ -47,4 +49,5 @@ mf:include ; mf:include ; mf:include ; + mf:include ; . \ No newline at end of file diff --git a/shacl12-test-suite/tests/core/property/maxListLength-001.ttl b/shacl12-test-suite/tests/core/property/maxListLength-001.ttl new file mode 100644 index 00000000..6b98001b --- /dev/null +++ b/shacl12-test-suite/tests/core/property/maxListLength-001.ttl @@ -0,0 +1,86 @@ +@prefix dash: . +@prefix ex: . +@prefix mf: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix sht: . +@prefix xsd: . + +ex:PersonShape + rdf:type sh:NodeShape ; + sh:targetClass ex:Person ; + sh:property ex:PersonShape-hobbies ; +. + +ex:PersonShape-hobbies + rdf:type sh:PropertyShape ; + sh:path ex:hobbies ; + sh:maxListLength 2 ; +. + +# Satisfies all constraints +ex:person1 + rdf:type ex:Person ; + ex:hobbies ( "reading" "writing" ) ; +. + +ex:person2 + rdf:type ex:Person ; + ex:hobbies rdf:nil ; +. + +# Violates maxListLength constraint +ex:person3 + rdf:type ex:Person ; + ex:hobbies _:b1 ; +. + +ex:person4 + rdf:type ex:Person ; + ex:hobbies ex:notAList ; +. + +_:b1 + rdf:first "reading" ; + rdf:rest ( "writing" "swimming" ) . + +<> + rdf:type mf:Manifest ; + mf:entries ( + + ) ; +. + + + rdf:type sht:Validate ; + rdfs:label "Test of sh:maxListLength on property shape 001" ; + mf:action [ + sht:dataGraph <> ; + sht:shapesGraph <> ; + ] ; + mf:result [ + rdf:type sh:ValidationReport ; + sh:conforms "false"^^xsd:boolean ; + sh:result [ + rdf:type sh:ValidationResult ; + sh:focusNode ex:person3 ; + sh:resultPath ex:hobbies ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:MaxListLengthConstraintComponent ; + sh:sourceShape ex:PersonShape-hobbies ; + sh:value _:b1 ; + ] ; + sh:result [ + rdf:type sh:ValidationResult ; + sh:focusNode ex:person4 ; + sh:resultPath ex:hobbies ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:MaxListLengthConstraintComponent ; + sh:sourceShape ex:PersonShape-hobbies ; + sh:value ex:notAList ; + ] ; + ] ; + mf:status sht:approved ; +. diff --git a/shacl12-test-suite/tests/core/property/memberShape-001.ttl b/shacl12-test-suite/tests/core/property/memberShape-001.ttl index 40bc2c7b..f525f1ec 100644 --- a/shacl12-test-suite/tests/core/property/memberShape-001.ttl +++ b/shacl12-test-suite/tests/core/property/memberShape-001.ttl @@ -68,16 +68,14 @@ _:b1 sh:result [ rdf:type sh:ValidationResult ; sh:focusNode ex:list2 ; - sh:resultMessage "Value does not conform to Shape ex:TestShape. See details for more information." ; sh:resultPath ex:testProperty ; sh:resultSeverity sh:Violation ; sh:sourceConstraintComponent sh:MemberShapeConstraintComponent ; - sh:sourceShape ex:TestShape ; + sh:sourceShape ex:TestShape-testProperty ; sh:value _:b1 ; sh:detail [ rdf:type sh:ValidationResult ; sh:focusNode _:bc ; - sh:resultMessage "Value is not of Node Kind sh:IRI" ; sh:resultSeverity sh:Violation ; sh:sourceConstraintComponent sh:NodeKindConstraintComponent ; sh:sourceShape ex:IRIShape ; diff --git a/shacl12-test-suite/tests/core/property/minListLength-001.ttl b/shacl12-test-suite/tests/core/property/minListLength-001.ttl new file mode 100644 index 00000000..ebe5bf8a --- /dev/null +++ b/shacl12-test-suite/tests/core/property/minListLength-001.ttl @@ -0,0 +1,80 @@ +@prefix dash: . +@prefix ex: . +@prefix mf: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix sht: . +@prefix xsd: . + +ex:PersonShape + rdf:type sh:NodeShape ; + sh:targetClass ex:Person ; + sh:property [ + sh:path ex:skills ; + sh:minListLength 1 ; + ] ; +. + +ex:PersonShape-skills + rdf:type sh:PropertyShape ; + sh:path ex:skills ; + sh:minListLength 1 ; +. + +# Satisfies all constraints +ex:person1 + rdf:type ex:Person ; + ex:skills ( "programming" "design" ) ; +. + +# Violates minListLength constraint +ex:person2 + rdf:type ex:Person ; + ex:skills rdf:nil ; +. + +ex:person3 + rdf:type ex:Person ; + ex:skills ex:notAList ; +. + +<> + rdf:type mf:Manifest ; + mf:entries ( + + ) ; +. + + + rdf:type sht:Validate ; + rdfs:label "Test of sh:minListLength on property shape 001" ; + mf:action [ + sht:dataGraph <> ; + sht:shapesGraph <> ; + ] ; + mf:result [ + rdf:type sh:ValidationReport ; + sh:conforms "false"^^xsd:boolean ; + sh:result [ + rdf:type sh:ValidationResult ; + sh:focusNode ex:person2 ; + sh:resultPath ex:skills ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:MinListLengthConstraintComponent ; + sh:sourceShape ex:PersonShape-skills ; + sh:value rdf:nil ; + ] ; + sh:result [ + rdf:type sh:ValidationResult ; + sh:focusNode ex:person3 ; + sh:resultPath ex:skills ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:MinListLengthConstraintComponent ; + sh:sourceShape ex:PersonShape-skills ; + sh:value ex:notAList ; + ] ; + ] ; + mf:status sht:approved ; +. diff --git a/shacl12-test-suite/tests/core/property/uniqueMembers-001.ttl b/shacl12-test-suite/tests/core/property/uniqueMembers-001.ttl new file mode 100644 index 00000000..2f77226a --- /dev/null +++ b/shacl12-test-suite/tests/core/property/uniqueMembers-001.ttl @@ -0,0 +1,104 @@ +@prefix dash: . +@prefix ex: . +@prefix mf: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix sht: . +@prefix xsd: . + +ex:PersonShape + rdf:type sh:NodeShape ; + sh:targetClass ex:Person ; + sh:property ex:PersonShape-preferences + ; +. + +ex:PersonShape-preferences + rdf:type sh:PropertyShape ; + sh:path ex:preferences ; + sh:uniqueMembers true ; +. + +# Satisfies all constraints +ex:person1 + rdf:type ex:Person ; + ex:preferences ( "coffee" "tea" ) ; +. + +ex:person2 + rdf:type ex:Person ; + ex:preferences rdf:nil ; +. + +# Violates uniqueMembers constraint +ex:person3 + rdf:type ex:Person ; + ex:preferences _:b1 ; +. + +ex:person4 + rdf:type ex:Person ; + ex:preferences ex:notAList ; +. + +_:b1 + rdf:first "coffee" ; + rdf:rest ( "tea" "coffee" "tea" "tea" ) . + +<> + rdf:type mf:Manifest ; + mf:entries ( + + ) ; +. + + + rdf:type sht:Validate ; + rdfs:label "Test of sh:uniqueMembers on property shape 001" ; + mf:action [ + sht:dataGraph <> ; + sht:shapesGraph <> ; + ] ; + mf:result [ + rdf:type sh:ValidationReport ; + sh:conforms "false"^^xsd:boolean ; + sh:result [ + rdf:type sh:ValidationResult ; + sh:focusNode ex:person3 ; + sh:resultPath ex:preferences ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:UniqueMembersConstraintComponent ; + sh:sourceShape ex:PersonShape-preferences ; + sh:value _:b1 ; + sh:detail [ + rdf:type sh:ValidationResult ; + sh:focusNode ex:person3 ; + sh:resultPath ex:preferences ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:UniqueMembersConstraintComponent ; + sh:sourceShape ex:PersonShape-preferences ; + sh:value "coffee" ; + ], [ + rdf:type sh:ValidationResult ; + sh:focusNode ex:person3 ; + sh:resultPath ex:preferences ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:UniqueMembersConstraintComponent ; + sh:sourceShape ex:PersonShape-preferences ; + sh:value "tea" ; + ] + ] ; + sh:result [ + rdf:type sh:ValidationResult ; + sh:focusNode ex:person4 ; + sh:resultPath ex:preferences ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:UniqueMembersConstraintComponent ; + sh:sourceShape ex:PersonShape-preferences ; + sh:value ex:notAList ; + ] ; + ] ; + mf:status sht:approved ; +. diff --git a/shacl12-vocabularies/shacl-shacl.ttl b/shacl12-vocabularies/shacl-shacl.ttl index 08c78d98..67871c82 100644 --- a/shacl12-vocabularies/shacl-shacl.ttl +++ b/shacl12-vocabularies/shacl-shacl.ttl @@ -74,7 +74,8 @@ shsh:ShapeShape sh:ignoredProperties, sh:in, sh:languageIn, sh:lessThan, sh:lessThanOrEquals, sh:maxCount, sh:maxExclusive, sh:maxInclusive, sh:maxLength, sh:memberShape, sh:minCount, sh:minExclusive, sh:minInclusive, sh:minLength, sh:node, sh:nodeKind, sh:not, sh:or, sh:pattern, sh:property, sh:qualifiedMaxCount, sh:qualifiedMinCount, sh:qualifiedValueShape, - sh:qualifiedValueShape, sh:qualifiedValueShapesDisjoint, sh:qualifiedValueShapesDisjoint, sh:uniqueLang, sh:xone ; + sh:qualifiedValueShape, sh:qualifiedValueShapesDisjoint, sh:qualifiedValueShapesDisjoint, sh:uniqueLang, sh:xone , + sh:minListLength, sh:maxListLength, sh:uniqList ; sh:targetObjectsOf sh:memberShape ; # memberShape-node sh:targetObjectsOf sh:node ; # node-node @@ -226,7 +227,24 @@ shsh:ShapeShape ] ; sh:property [ sh:path sh:memberShape ; - sh:node shsh:NodeShapeShape ; # memberShape-node + sh:node shsh:NodeShapeShape ; # memberShape-node + ] ; + sh:property [ + sh:path sh:minListLength ; + sh:datatype xsd:integer ; # minListLength-datatype + sh:maxCount 1 ; # minListLength-maxCount + sh:minInclusive 0 ; # minListLength-minInclusive + ] ; + sh:property [ + sh:path sh:maxListLength ; + sh:datatype xsd:integer ; # maxListLength-datatype + sh:maxCount 1 ; # maxListLength-maxCount + sh:minInclusive 0 ; # maxListLength-minInclusive + ] ; + sh:property [ + sh:path sh:uniqueMembers ; + sh:datatype xsd:boolean ; # uniqList-datatype + sh:maxCount 1 ; # uniqList-maxCount ] ; sh:property [ sh:path sh:nodeKind ; diff --git a/shacl12-vocabularies/shacl.ttl b/shacl12-vocabularies/shacl.ttl index 2b26c205..4223b768 100644 --- a/shacl12-vocabularies/shacl.ttl +++ b/shacl12-vocabularies/shacl.ttl @@ -907,13 +907,73 @@ sh:MemberShapeConstraintComponent-memberShape sh:node sh:NodeShape ; rdfs:isDefinedBy sh: . +sh:MinListLengthConstraintComponent + a sh:ConstraintComponent ; + rdfs:label "Minimum list length constraint component"@en ; + rdfs:comment "Specifies the minimum length of a SHACL list. A violation is reported if the value is not a valid SHACL list."@en ; + sh:parameter sh:MinListLengthConstraintComponent-minListLength ; + rdfs:isDefinedBy sh: . + +sh:MinListLengthConstraintComponent-minListLength + a sh:Parameter ; + sh:path sh:minListLength ; + sh:datatype xsd:integer ; + rdfs:isDefinedBy sh: . + +sh:MaxListLengthConstraintComponent + a sh:ConstraintComponent ; + rdfs:label "Maximum list length constraint component"@en ; + rdfs:comment "Specifies the maximum length of a SHACL list. A violation is reported if the value is not a valid SHACL list."@en ; + sh:parameter sh:MaxListLengthConstraintComponent-maxListLength ; + rdfs:isDefinedBy sh: . + +sh:MaxListLengthConstraintComponent-maxListLength + a sh:Parameter ; + sh:path sh:maxListLength ; + sh:datatype xsd:integer ; + rdfs:isDefinedBy sh: . + +sh:UniqueMembersConstraintComponent + a sh:ConstraintComponent ; + rdfs:label "Unique list members constraint component"@en ; + rdfs:comment "Specifies that all members of a SHACL list must be unique. A violation is reported if the value is not a valid SHACL list."@en ; + sh:parameter sh:UniqueMembersConstraintComponent-uniqueMembers ; + rdfs:isDefinedBy sh: . + +sh:UniqueMembersConstraintComponent-uniqueMembers + a sh:Parameter ; + sh:path sh:uniqueMembers ; + sh:datatype xsd:boolean ; + rdfs:isDefinedBy sh: . + sh:memberShape a rdf:Property ; rdfs:label "member shape"@en ; - rdfs:comment "Specifies the shape that all members of RDF lists must conform to."@en ; + rdfs:comment "Specifies the shape that all members of SHACL lists must conform to."@en ; rdfs:range sh:NodeShape ; rdfs:isDefinedBy sh: . +sh:minListLength + a rdf:Property ; + rdfs:label "Minimum list length"@en ; + rdfs:comment "Specifies the minimum length that a given SHACL list must have."@en ; + rdfs:range xsd:integer ; + rdfs:isDefinedBy sh: . + +sh:maxListLength + a rdf:Property ; + rdfs:label "Maximum list length"@en ; + rdfs:comment "Specifies the maximum length that a given SHACL list must have."@en ; + rdfs:range xsd:integer ; + rdfs:isDefinedBy sh: . + +sh:uniqueMembers + a rdf:Property ; + rdfs:label "Unique list members"@en ; + rdfs:comment "Specifies that all members of a SHACL list must be unique."@en ; + rdfs:range xsd:boolean ; + rdfs:isDefinedBy sh: . + sh:NodeConstraintComponent a sh:ConstraintComponent ; rdfs:label "Node constraint component"@en ;