diff --git a/ontology/owl/owl.ttl b/ontology/owl/owl.ttl index 2f5ecc72..21d7aace 100644 --- a/ontology/owl/owl.ttl +++ b/ontology/owl/owl.ttl @@ -34,6 +34,87 @@ uco-owl:Axiom-shape sh:targetClass owl:Axiom ; . +uco-owl:DataExactCardinalityQualified-shape + a sh:NodeShape ; + rdfs:comment + "This shape intentionally has no sh:targetX predicate."@en , + "This shape is named for the class expression in Table 13, row 22, of the OWL 2 mapping to RDF."@en + ; + rdfs:seeAlso ; + sh:class owl:Restriction ; + sh:property + [ + a sh:PropertyShape ; + sh:minCount "1"^^xsd:integer ; + sh:path owl:onDataRange ; + ] , + [ + a sh:PropertyShape ; + sh:minCount "1"^^xsd:integer ; + sh:path owl:onProperty ; + ] , + [ + a sh:PropertyShape ; + sh:minCount "1"^^xsd:integer ; + sh:path owl:qualifiedCardinality ; + ] + ; + . + +uco-owl:DataMaxCardinalityQualified-shape + a sh:NodeShape ; + rdfs:comment + "This shape intentionally has no sh:targetX predicate."@en , + "This shape is named for the class expression in Table 13, row 21, of the OWL 2 mapping to RDF."@en + ; + rdfs:seeAlso ; + sh:class owl:Restriction ; + sh:property + [ + a sh:PropertyShape ; + sh:minCount "1"^^xsd:integer ; + sh:path owl:maxQualifiedCardinality ; + ] , + [ + a sh:PropertyShape ; + sh:minCount "1"^^xsd:integer ; + sh:path owl:onDataRange ; + ] , + [ + a sh:PropertyShape ; + sh:minCount "1"^^xsd:integer ; + sh:path owl:onProperty ; + ] + ; + . + +uco-owl:DataMinCardinalityQualified-shape + a sh:NodeShape ; + rdfs:comment + "This shape intentionally has no sh:targetX predicate."@en , + "This shape is named for the class expression in Table 13, row 20, of the OWL 2 mapping to RDF."@en + ; + rdfs:seeAlso ; + sh:class owl:Restriction ; + sh:property + [ + a sh:PropertyShape ; + sh:minCount "1"^^xsd:integer ; + sh:path owl:minQualifiedCardinality ; + ] , + [ + a sh:PropertyShape ; + sh:minCount "1"^^xsd:integer ; + sh:path owl:onDataRange ; + ] , + [ + a sh:PropertyShape ; + sh:minCount "1"^^xsd:integer ; + sh:path owl:onProperty ; + ] + ; + . + uco-owl:DataOneOf-shape a sh:NodeShape ; sh:sparql [ @@ -189,6 +270,87 @@ uco-owl:List-shape sh:deactivated "true"^^xsd:boolean ; . +uco-owl:ObjectExactCardinalityQualified-shape + a sh:NodeShape ; + rdfs:comment + "This shape intentionally has no sh:targetX predicate."@en , + "This shape is named for the class expression in Table 13, row 11, of the OWL 2 mapping to RDF."@en + ; + rdfs:seeAlso ; + sh:class owl:Restriction ; + sh:property + [ + a sh:PropertyShape ; + sh:minCount "1"^^xsd:integer ; + sh:path owl:onClass ; + ] , + [ + a sh:PropertyShape ; + sh:minCount "1"^^xsd:integer ; + sh:path owl:onProperty ; + ] , + [ + a sh:PropertyShape ; + sh:minCount "1"^^xsd:integer ; + sh:path owl:qualifiedCardinality ; + ] + ; + . + +uco-owl:ObjectMaxCardinalityQualified-shape + a sh:NodeShape ; + rdfs:comment + "This shape intentionally has no sh:targetX predicate."@en , + "This shape is named for the class expression in Table 13, row 10, of the OWL 2 mapping to RDF."@en + ; + rdfs:seeAlso ; + sh:class owl:Restriction ; + sh:property + [ + a sh:PropertyShape ; + sh:minCount "1"^^xsd:integer ; + sh:path owl:maxQualifiedCardinality ; + ] , + [ + a sh:PropertyShape ; + sh:minCount "1"^^xsd:integer ; + sh:path owl:onClass ; + ] , + [ + a sh:PropertyShape ; + sh:minCount "1"^^xsd:integer ; + sh:path owl:onProperty ; + ] + ; + . + +uco-owl:ObjectMinCardinalityQualified-shape + a sh:NodeShape ; + rdfs:comment + "This shape intentionally has no sh:targetX predicate."@en , + "This shape is named for the class expression in Table 13, row 9, of the OWL 2 mapping to RDF."@en + ; + rdfs:seeAlso ; + sh:class owl:Restriction ; + sh:property + [ + a sh:PropertyShape ; + sh:minCount "1"^^xsd:integer ; + sh:path owl:minQualifiedCardinality ; + ] , + [ + a sh:PropertyShape ; + sh:minCount "1"^^xsd:integer ; + sh:path owl:onClass ; + ] , + [ + a sh:PropertyShape ; + sh:minCount "1"^^xsd:integer ; + sh:path owl:onProperty ; + ] + ; + . + uco-owl:ObjectProperty-shacl-constraints-shape a sh:NodeShape ; sh:sparql @@ -239,6 +401,64 @@ uco-owl:ObjectProperty-shacl-constraints-shape sh:targetClass owl:ObjectProperty ; . +uco-owl:Restriction-shape + a sh:NodeShape ; + rdfs:seeAlso + , + + ; + sh:description "This shape captures the one in-common restrictions on owl:Restriction in the OWL mapping to RDF document, between Tables 1 and 13: that Restrictions are identified as blank nodes. Note that Table 5 matching potentially IRI-identified nodes does not relax the matching patterns from Tables 1 and 13. Maximum-counts are put on properties observed to have a domain of owl:Restriction in the OWL 2 RDF-based semantics document, Table 6.2."@en ; + sh:nodeKind sh:BlankNode ; + sh:property + [ + a sh:PropertyShape ; + sh:maxCount "1"^^xsd:integer ; + sh:path owl:cardinality ; + ] , + [ + a sh:PropertyShape ; + sh:maxCount "1"^^xsd:integer ; + sh:path owl:maxCardinality ; + ] , + [ + a sh:PropertyShape ; + sh:maxCount "1"^^xsd:integer ; + sh:path owl:maxQualifiedCardinality ; + ] , + [ + a sh:PropertyShape ; + sh:maxCount "1"^^xsd:integer ; + sh:path owl:minCardinality ; + ] , + [ + a sh:PropertyShape ; + sh:maxCount "1"^^xsd:integer ; + sh:path owl:minQualifiedCardinality ; + ] , + [ + a sh:PropertyShape ; + sh:maxCount "1"^^xsd:integer ; + sh:path owl:onClass ; + ] , + [ + a sh:PropertyShape ; + sh:maxCount "1"^^xsd:integer ; + sh:path owl:onDataRange ; + ] , + [ + a sh:PropertyShape ; + sh:maxCount "1"^^xsd:integer ; + sh:path owl:onProperty ; + ] , + [ + a sh:PropertyShape ; + sh:maxCount "1"^^xsd:integer ; + sh:path owl:qualifiedCardinality ; + ] + ; + sh:targetClass owl:Restriction ; + . + uco-owl:Sequence-shape a sh:NodeShape ; rdfs:comment "This shape intentionally has no target declaration. It is instead intended to be incorporated using 'sh:node'."@en ; @@ -278,6 +498,43 @@ uco-owl:Sequence-shape ) ; . +uco-owl:cardinality-objects-shape + a sh:NodeShape ; + sh:datatype xsd:nonNegativeInteger ; + sh:nodeKind sh:Literal ; + sh:targetObjectsOf owl:cardinality ; + . + +uco-owl:cardinality-subjects-shape + a sh:NodeShape ; + rdfs:comment "This shape reflects DataExactCardinality and ObjectExactCardinality for the class expressions in Table 13, rows 14 and 25, of the OWL 2 mapping to RDF. Those rows are ambiguous if the object of owl:onProperty is not further reviewed."@en ; + rdfs:seeAlso ; + sh:class owl:Restriction ; + sh:property + [ + a sh:PropertyShape ; + sh:maxCount "0"^^xsd:integer ; + sh:path owl:onClass ; + ] , + [ + a sh:PropertyShape ; + sh:maxCount "0"^^xsd:integer ; + sh:path owl:onDataRange ; + ] , + [ + a sh:PropertyShape ; + sh:minCount "1"^^xsd:integer ; + sh:path owl:cardinality ; + ] , + [ + a sh:PropertyShape ; + sh:minCount "1"^^xsd:integer ; + sh:path owl:onProperty ; + ] + ; + sh:targetSubjectsOf owl:cardinality ; + . + uco-owl:disjointUnionOf-subjects-shape a sh:NodeShape ; sh:property [ @@ -353,6 +610,69 @@ uco-owl:intersectionOf-subjects-shape sh:targetSubjectsOf owl:intersectionOf ; . +uco-owl:maxCardinality-objects-shape + a sh:NodeShape ; + sh:datatype xsd:nonNegativeInteger ; + sh:nodeKind sh:Literal ; + sh:targetObjectsOf owl:maxCardinality ; + . + +uco-owl:maxCardinality-subjects-shape + a sh:NodeShape ; + rdfs:comment "This shape reflects DataMaxCardinality and ObjectMaxCardinality for the class expressions in Table 13, rows 13 and 24, of the OWL 2 mapping to RDF. Those rows are ambiguous if the object of owl:onProperty is not further reviewed."@en ; + rdfs:seeAlso ; + sh:class owl:Restriction ; + sh:property + [ + a sh:PropertyShape ; + sh:maxCount "0"^^xsd:integer ; + sh:path owl:minCardinality ; + ] , + [ + a sh:PropertyShape ; + sh:maxCount "0"^^xsd:integer ; + sh:path owl:onClass ; + ] , + [ + a sh:PropertyShape ; + sh:maxCount "0"^^xsd:integer ; + sh:path owl:onDataRange ; + ] , + [ + a sh:PropertyShape ; + sh:minCount "1"^^xsd:integer ; + sh:path owl:maxCardinality ; + ] , + [ + a sh:PropertyShape ; + sh:minCount "1"^^xsd:integer ; + sh:path owl:onProperty ; + ] + ; + sh:targetSubjectsOf owl:maxCardinality ; + . + +uco-owl:maxQualifiedCardinality-objects-shape + a sh:NodeShape ; + sh:datatype xsd:nonNegativeInteger ; + sh:nodeKind sh:Literal ; + sh:targetObjectsOf owl:maxQualifiedCardinality ; + . + +uco-owl:maxQualifiedCardinality-subjects-shape + a sh:NodeShape ; + sh:property [ + a sh:PropertyShape ; + sh:maxCount "0"^^xsd:integer ; + sh:path owl:minQualifiedCardinality ; + ] ; + sh:targetSubjectsOf owl:maxQualifiedCardinality ; + sh:xone ( + uco-owl:DataMaxCardinalityQualified-shape + uco-owl:ObjectMaxCardinalityQualified-shape + ) ; + . + uco-owl:members-subjects-shape a sh:NodeShape ; sh:property [ @@ -363,6 +683,69 @@ uco-owl:members-subjects-shape sh:targetSubjectsOf owl:members ; . +uco-owl:minCardinality-objects-shape + a sh:NodeShape ; + sh:datatype xsd:nonNegativeInteger ; + sh:nodeKind sh:Literal ; + sh:targetObjectsOf owl:minCardinality ; + . + +uco-owl:minCardinality-subjects-shape + a sh:NodeShape ; + rdfs:comment "This shape reflects DataMinCardinality and ObjectMinCardinality for the class expressions in Table 13, rows 12 and 23, of the OWL 2 mapping to RDF. Those rows are ambiguous if the object of owl:onProperty is not further reviewed."@en ; + rdfs:seeAlso ; + sh:class owl:Restriction ; + sh:property + [ + a sh:PropertyShape ; + sh:maxCount "0"^^xsd:integer ; + sh:path owl:maxCardinality ; + ] , + [ + a sh:PropertyShape ; + sh:maxCount "0"^^xsd:integer ; + sh:path owl:onClass ; + ] , + [ + a sh:PropertyShape ; + sh:maxCount "0"^^xsd:integer ; + sh:path owl:onDataRange ; + ] , + [ + a sh:PropertyShape ; + sh:minCount "1"^^xsd:integer ; + sh:path owl:minCardinality ; + ] , + [ + a sh:PropertyShape ; + sh:minCount "1"^^xsd:integer ; + sh:path owl:onProperty ; + ] + ; + sh:targetSubjectsOf owl:minCardinality ; + . + +uco-owl:minQualifiedCardinality-objects-shape + a sh:NodeShape ; + sh:datatype xsd:nonNegativeInteger ; + sh:nodeKind sh:Literal ; + sh:targetObjectsOf owl:minQualifiedCardinality ; + . + +uco-owl:minQualifiedCardinality-subjects-shape + a sh:NodeShape ; + sh:property [ + a sh:PropertyShape ; + sh:maxCount "0"^^xsd:integer ; + sh:path owl:maxQualifiedCardinality ; + ] ; + sh:targetSubjectsOf owl:minQualifiedCardinality ; + sh:xone ( + uco-owl:DataMinCardinalityQualified-shape + uco-owl:ObjectMinCardinalityQualified-shape + ) ; + . + uco-owl:onProperties-subjects-shape a sh:NodeShape ; sh:property [ @@ -373,6 +756,12 @@ uco-owl:onProperties-subjects-shape sh:targetSubjectsOf owl:onProperties ; . +uco-owl:onProperty-subjects-shape + a sh:NodeShape ; + sh:class owl:Restriction ; + sh:targetSubjectsOf owl:onProperty ; + . + uco-owl:oneOf-subjects-shape a sh:NodeShape ; sh:property [ @@ -401,6 +790,22 @@ uco-owl:propertyChainAxiom-subjects-shape sh:targetSubjectsOf owl:propertyChainAxiom ; . +uco-owl:qualifiedCardinality-objects-shape + a sh:NodeShape ; + sh:datatype xsd:nonNegativeInteger ; + sh:nodeKind sh:Literal ; + sh:targetObjectsOf owl:qualifiedCardinality ; + . + +uco-owl:qualifiedCardinality-subjects-shape + a sh:NodeShape ; + sh:targetSubjectsOf owl:qualifiedCardinality ; + sh:xone ( + uco-owl:DataExactCardinalityQualified-shape + uco-owl:ObjectExactCardinalityQualified-shape + ) ; + . + uco-owl:rdf-first-subjects-shape a sh:NodeShape ; sh:property diff --git a/tests/examples/Makefile b/tests/examples/Makefile index 552c0b89..eaef6963 100644 --- a/tests/examples/Makefile +++ b/tests/examples/Makefile @@ -46,6 +46,8 @@ all: \ observable_creation_time_PASS_validation.ttl \ owl_axiom_PASS_validation.ttl \ owl_axiom_XFAIL_validation.ttl \ + owl_cardinality_restrictions_PASS_validation.ttl \ + owl_cardinality_restrictions_XFAIL_validation.ttl \ owl_properties_PASS_validation.ttl \ owl_properties_XFAIL_validation.ttl \ rdf_list_PASS_validation.ttl \ @@ -123,6 +125,8 @@ check: \ observable_creation_time_PASS_validation.ttl \ owl_axiom_PASS_validation.ttl \ owl_axiom_XFAIL_validation.ttl \ + owl_cardinality_restrictions_PASS_validation.ttl \ + owl_cardinality_restrictions_XFAIL_validation.ttl \ owl_properties_PASS_validation.ttl \ owl_properties_XFAIL_validation.ttl \ rdf_list_PASS_validation.ttl \ diff --git a/tests/examples/owl_cardinality_restrictions_PASS.json b/tests/examples/owl_cardinality_restrictions_PASS.json new file mode 100644 index 00000000..292db127 --- /dev/null +++ b/tests/examples/owl_cardinality_restrictions_PASS.json @@ -0,0 +1,209 @@ +{ + "@context": { + "kb": "http://example.org/kb/", + "owl": "http://www.w3.org/2002/07/owl#", + "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#", + "rdfs": "http://www.w3.org/2000/01/rdf-schema#", + "xsd": "http://www.w3.org/2001/XMLSchema#" + }, + "@graph": [ + { + "@id": "kb:datatype-property-1", + "@type": "owl:DatatypeProperty" + }, + { + "@id": "kb:object-property-1", + "@type": "owl:ObjectProperty" + }, + { + "@id": "kb:Other-Thing", + "@type": "owl:Class" + }, + { + "@id": "kb:Thing-exact-dp", + "@type": "owl:Class", + "rdfs:subClassOf": { + "@type": "owl:Restriction", + "owl:cardinality": { + "@type": "xsd:nonNegativeInteger", + "@value": "1" + }, + "owl:onProperty": { + "@id": "kb:datatype-property-1" + } + } + }, + { + "@id": "kb:Thing-max-dp", + "@type": "owl:Class", + "rdfs:subClassOf": { + "@type": "owl:Restriction", + "owl:maxCardinality": { + "@type": "xsd:nonNegativeInteger", + "@value": "1" + }, + "owl:onProperty": { + "@id": "kb:datatype-property-1" + } + } + }, + { + "@id": "kb:Thing-min-dp", + "@type": "owl:Class", + "rdfs:subClassOf": { + "@type": "owl:Restriction", + "owl:minCardinality": { + "@type": "xsd:nonNegativeInteger", + "@value": "1" + }, + "owl:onProperty": { + "@id": "kb:datatype-property-1" + } + } + }, + { + "@id": "kb:Thing-qexact-dp", + "@type": "owl:Class", + "rdfs:subClassOf": { + "@type": "owl:Restriction", + "owl:qualifiedCardinality": { + "@type": "xsd:nonNegativeInteger", + "@value": "1" + }, + "owl:onDataRange": { + "@id": "xsd:string" + }, + "owl:onProperty": { + "@id": "kb:datatype-property-1" + } + } + }, + { + "@id": "kb:Thing-qmax-dp", + "@type": "owl:Class", + "rdfs:subClassOf": { + "@type": "owl:Restriction", + "owl:maxQualifiedCardinality": { + "@type": "xsd:nonNegativeInteger", + "@value": "1" + }, + "owl:onDataRange": { + "@id": "xsd:string" + }, + "owl:onProperty": { + "@id": "kb:object-property-1" + } + } + }, + { + "@id": "kb:Thing-qmin-dp", + "@type": "owl:Class", + "rdfs:subClassOf": { + "@type": "owl:Restriction", + "owl:minQualifiedCardinality": { + "@type": "xsd:nonNegativeInteger", + "@value": "1" + }, + "owl:onDataRange": { + "@id": "xsd:string" + }, + "owl:onProperty": { + "@id": "kb:object-property-1" + } + } + }, + { + "@id": "kb:Thing-exact-op", + "@type": "owl:Class", + "rdfs:subClassOf": { + "@type": "owl:Restriction", + "owl:cardinality": { + "@type": "xsd:nonNegativeInteger", + "@value": "1" + }, + "owl:onProperty": { + "@id": "kb:object-property-1" + } + } + }, + { + "@id": "kb:Thing-max-op", + "@type": "owl:Class", + "rdfs:subClassOf": { + "@type": "owl:Restriction", + "owl:maxCardinality": { + "@type": "xsd:nonNegativeInteger", + "@value": "1" + }, + "owl:onProperty": { + "@id": "kb:object-property-1" + } + } + }, + { + "@id": "kb:Thing-min-op", + "@type": "owl:Class", + "rdfs:subClassOf": { + "@type": "owl:Restriction", + "owl:minCardinality": { + "@type": "xsd:nonNegativeInteger", + "@value": "1" + }, + "owl:onProperty": { + "@id": "kb:object-property-1" + } + } + }, + { + "@id": "kb:Thing-qexact-op", + "@type": "owl:Class", + "rdfs:subClassOf": { + "@type": "owl:Restriction", + "owl:qualifiedCardinality": { + "@type": "xsd:nonNegativeInteger", + "@value": "1" + }, + "owl:onClass": { + "@id": "kb:Other-Thing" + }, + "owl:onProperty": { + "@id": "kb:object-property-1" + } + } + }, + { + "@id": "kb:Thing-qmax-op", + "@type": "owl:Class", + "rdfs:subClassOf": { + "@type": "owl:Restriction", + "owl:maxQualifiedCardinality": { + "@type": "xsd:nonNegativeInteger", + "@value": "1" + }, + "owl:onClass": { + "@id": "kb:Other-Thing" + }, + "owl:onProperty": { + "@id": "kb:object-property-1" + } + } + }, + { + "@id": "kb:Thing-qmin-op", + "@type": "owl:Class", + "rdfs:subClassOf": { + "@type": "owl:Restriction", + "owl:minQualifiedCardinality": { + "@type": "xsd:nonNegativeInteger", + "@value": "1" + }, + "owl:onClass": { + "@id": "kb:Other-Thing" + }, + "owl:onProperty": { + "@id": "kb:object-property-1" + } + } + } + ] +} diff --git a/tests/examples/owl_cardinality_restrictions_PASS_validation.ttl b/tests/examples/owl_cardinality_restrictions_PASS_validation.ttl new file mode 100644 index 00000000..33496ff0 --- /dev/null +++ b/tests/examples/owl_cardinality_restrictions_PASS_validation.ttl @@ -0,0 +1,11 @@ +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix xsd: . + +[] + a sh:ValidationReport ; + sh:conforms "true"^^xsd:boolean ; + . + diff --git a/tests/examples/owl_cardinality_restrictions_XFAIL.json b/tests/examples/owl_cardinality_restrictions_XFAIL.json new file mode 100644 index 00000000..0a493d3a --- /dev/null +++ b/tests/examples/owl_cardinality_restrictions_XFAIL.json @@ -0,0 +1,286 @@ +{ + "@context": { + "dcterms": "http://purl.org/dc/terms/", + "kb": "http://example.org/kb/", + "owl": "http://www.w3.org/2002/07/owl#", + "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#", + "rdfs": "http://www.w3.org/2000/01/rdf-schema#", + "xsd": "http://www.w3.org/2001/XMLSchema#" + }, + "@graph": [ + { + "@id": "kb:object-property-1", + "@type": "owl:ObjectProperty" + }, + { + "@id": "kb:Other-Thing", + "@type": "owl:Class" + }, + { + "@id": "kb:Thing-exact-xfail-1", + "@type": "owl:Class", + "rdfs:subClassOf": { + "@id": "kb:Restriction-1", + "@type": "owl:Restriction", + "dcterms:identifier": "http://example.org/kb/Restriction-1", + "rdfs:comment": "This Restriction will trigger a failure from having an IRI.", + "owl:qualifiedCardinality": { + "@type": "xsd:nonNegativeInteger", + "@value": "1" + }, + "owl:onClass": { + "@id": "kb:Other-Thing" + }, + "owl:onProperty": { + "@id": "kb:object-property-1" + } + } + }, + { + "@id": "kb:Thing-exact-xfail-2", + "@type": "owl:Class", + "rdfs:subClassOf": { + "@type": "owl:Restriction", + "dcterms:identifier": "http://example.org/kb/Thing-exact-xfail-2/Restriction", + "rdfs:comment": "This Restriction will trigger a failure from qualifiedCardinality not being typed.", + "owl:qualifiedCardinality": 1, + "owl:onClass": { + "@id": "kb:Other-Thing" + }, + "owl:onProperty": { + "@id": "kb:object-property-1" + } + } + }, + { + "@id": "kb:Thing-exact-xfail-3", + "@type": "owl:Class", + "rdfs:subClassOf": { + "@type": "owl:Restriction", + "dcterms:identifier": "http://example.org/kb/Thing-exact-xfail-3/Restriction", + "rdfs:comment": "This Restriction will trigger a failure from not having a class specified.", + "owl:qualifiedCardinality": { + "@type": "xsd:nonNegativeInteger", + "@value": "1" + }, + "owl:onProperty": { + "@id": "kb:object-property-1" + } + } + }, + { + "@id": "kb:Thing-exact-xfail-4", + "@type": "owl:Class", + "rdfs:subClassOf": { + "@type": "owl:Restriction", + "dcterms:identifier": "http://example.org/kb/Thing-exact-xfail-4/Restriction", + "rdfs:comment": "This Restriction will trigger a failure from not having a property specified.", + "owl:qualifiedCardinality": { + "@type": "xsd:nonNegativeInteger", + "@value": "1" + }, + "owl:onClass": { + "@id": "kb:Other-Thing" + } + } + }, + { + "@id": "kb:Thing-max-xfail-1", + "@type": "owl:Class", + "rdfs:subClassOf": { + "@id": "kb:Restriction-2", + "@type": "owl:Restriction", + "dcterms:identifier": "http://example.org/kb/Restriction-2", + "rdfs:comment": "This Restriction will trigger a failure from having an IRI.", + "owl:maxQualifiedCardinality": { + "@type": "xsd:nonNegativeInteger", + "@value": "1" + }, + "owl:onClass": { + "@id": "kb:Other-Thing" + }, + "owl:onProperty": { + "@id": "kb:object-property-1" + } + } + }, + { + "@id": "kb:Thing-max-xfail-2", + "@type": "owl:Class", + "rdfs:subClassOf": { + "@type": "owl:Restriction", + "dcterms:identifier": "http://example.org/kb/Thing-max-xfail-2/Restriction", + "rdfs:comment": "This Restriction will trigger a failure from maxQualifiedCardinality not being typed.", + "owl:maxQualifiedCardinality": 1, + "owl:onClass": { + "@id": "kb:Other-Thing" + }, + "owl:onProperty": { + "@id": "kb:object-property-1" + } + } + }, + { + "@id": "kb:Thing-max-xfail-3", + "@type": "owl:Class", + "rdfs:subClassOf": { + "@type": "owl:Restriction", + "dcterms:identifier": "http://example.org/kb/Thing-max-xfail-3/Restriction", + "rdfs:comment": "This Restriction will trigger a failure from not having a class specified.", + "owl:maxQualifiedCardinality": { + "@type": "xsd:nonNegativeInteger", + "@value": "1" + }, + "owl:onProperty": { + "@id": "kb:object-property-1" + } + } + }, + { + "@id": "kb:Thing-max-xfail-4", + "@type": "owl:Class", + "rdfs:subClassOf": { + "@type": "owl:Restriction", + "dcterms:identifier": "http://example.org/kb/Thing-max-xfail-4/Restriction", + "rdfs:comment": "This Restriction will trigger a failure from not having a property specified.", + "owl:maxQualifiedCardinality": { + "@type": "xsd:nonNegativeInteger", + "@value": "1" + }, + "owl:onClass": { + "@id": "kb:Other-Thing" + } + } + }, + { + "@id": "kb:Thing-min-xfail-1", + "@type": "owl:Class", + "rdfs:subClassOf": { + "@id": "kb:Restriction-3", + "@type": "owl:Restriction", + "dcterms:identifier": "http://example.org/kb/Restriction-3", + "rdfs:comment": "This Restriction will trigger a failure from having an IRI.", + "owl:minQualifiedCardinality": { + "@type": "xsd:nonNegativeInteger", + "@value": "1" + }, + "owl:onClass": { + "@id": "kb:Other-Thing" + }, + "owl:onProperty": { + "@id": "kb:object-property-1" + } + } + }, + { + "@id": "kb:Thing-min-xfail-2", + "@type": "owl:Class", + "rdfs:subClassOf": { + "@type": "owl:Restriction", + "dcterms:identifier": "http://example.org/kb/Thing-min-xfail-2/Restriction", + "rdfs:comment": "This Restriction will trigger a failure from minQualifiedCardinality not being typed.", + "owl:minQualifiedCardinality": 1, + "owl:onClass": { + "@id": "kb:Other-Thing" + }, + "owl:onProperty": { + "@id": "kb:object-property-1" + } + } + }, + { + "@id": "kb:Thing-min-xfail-3", + "@type": "owl:Class", + "rdfs:subClassOf": { + "@type": "owl:Restriction", + "dcterms:identifier": "http://example.org/kb/Thing-min-xfail-3/Restriction", + "rdfs:comment": "This Restriction will trigger a failure from not having a class specified.", + "owl:minQualifiedCardinality": { + "@type": "xsd:nonNegativeInteger", + "@value": "1" + }, + "owl:onProperty": { + "@id": "kb:object-property-1" + } + } + }, + { + "@id": "kb:Thing-min-xfail-4", + "@type": "owl:Class", + "rdfs:subClassOf": { + "@type": "owl:Restriction", + "dcterms:identifier": "http://example.org/kb/Thing-min-xfail-4/Restriction", + "rdfs:comment": "This Restriction will trigger a failure from not having a property specified.", + "owl:minQualifiedCardinality": { + "@type": "xsd:nonNegativeInteger", + "@value": "1" + }, + "owl:onClass": { + "@id": "kb:Other-Thing" + } + } + }, + { + "@id": "kb:Thing-unqualified-cardinality-with-class-xfail-1", + "@type": "owl:Class", + "rdfs:subClassOf": { + "@type": "owl:Restriction", + "dcterms:identifier": "http://example.org/kb/Thing-unqualified-cardinality-with-class-xfail-1/Restriction", + "rdfs:comment": "This Restriction will trigger a failure from specifying a class on an unqualified cardinality.", + "owl:cardinality": { + "@type": "xsd:nonNegativeInteger", + "@value": "1" + }, + "owl:onClass": { + "@id": "kb:Other-Thing" + }, + "owl:onProperty": { + "@id": "kb:object-property-1" + } + } + }, + { + "@id": "kb:Thing-plural-cardinality-xfail-1", + "@type": "owl:Class", + "rdfs:subClassOf": { + "@type": "owl:Restriction", + "dcterms:identifier": "http://example.org/kb/Thing-plural-cardinality-xfail-1/Restriction", + "rdfs:comment": "This Restriction will trigger two failures, from specifying both a minimum and maximum unqualified cardinality. (These should be in separate restrictions instead.)", + "owl:maxCardinality": { + "@type": "xsd:nonNegativeInteger", + "@value": "2" + }, + "owl:minCardinality": { + "@type": "xsd:nonNegativeInteger", + "@value": "1" + }, + "owl:onProperty": { + "@id": "kb:object-property-1" + } + } + }, + { + "@id": "kb:Thing-plural-qualified-cardinality-xfail-1", + "@type": "owl:Class", + "rdfs:subClassOf": { + "@type": "owl:Restriction", + "dcterms:identifier": "http://example.org/kb/Thing-plural-qualified-cardinality-xfail-1/Restriction", + "rdfs:comment": "This Restriction will trigger two failures, from specifying both a minimum and maximum qualified cardinality. (These should be in separate restrictions instead.)", + "owl:maxQualifiedCardinality": { + "@type": "xsd:nonNegativeInteger", + "@value": "2" + }, + "owl:minQualifiedCardinality": { + "@type": "xsd:nonNegativeInteger", + "@value": "1" + }, + "owl:onClass": { + "@id": "kb:Other-Thing" + }, + "owl:onProperty": { + "@id": "kb:object-property-1" + } + } + } + ] +} diff --git a/tests/examples/owl_cardinality_restrictions_XFAIL_validation.ttl b/tests/examples/owl_cardinality_restrictions_XFAIL_validation.ttl new file mode 100644 index 00000000..7fba08c5 --- /dev/null +++ b/tests/examples/owl_cardinality_restrictions_XFAIL_validation.ttl @@ -0,0 +1,297 @@ +@prefix ns1: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix uco-owl: . +@prefix xsd: . + +[] + a sh:ValidationReport ; + sh:conforms "false"^^xsd:boolean ; + sh:result + [ + a sh:ValidationResult ; + sh:focusNode "1"^^xsd:integer ; + sh:resultMessage "Value is not Literal with datatype xsd:nonNegativeInteger" ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:DatatypeConstraintComponent ; + sh:sourceShape uco-owl:maxQualifiedCardinality-objects-shape ; + sh:value "1"^^xsd:integer ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode "1"^^xsd:integer ; + sh:resultMessage "Value is not Literal with datatype xsd:nonNegativeInteger" ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:DatatypeConstraintComponent ; + sh:sourceShape uco-owl:minQualifiedCardinality-objects-shape ; + sh:value "1"^^xsd:integer ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode "1"^^xsd:integer ; + sh:resultMessage "Value is not Literal with datatype xsd:nonNegativeInteger" ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:DatatypeConstraintComponent ; + sh:sourceShape uco-owl:qualifiedCardinality-objects-shape ; + sh:value "1"^^xsd:integer ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode ; + sh:resultMessage "Value is not of Node Kind sh:BlankNode" ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:NodeKindConstraintComponent ; + sh:sourceShape uco-owl:Restriction-shape ; + sh:value ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode ; + sh:resultMessage "Value is not of Node Kind sh:BlankNode" ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:NodeKindConstraintComponent ; + sh:sourceShape uco-owl:Restriction-shape ; + sh:value ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode ; + sh:resultMessage "Value is not of Node Kind sh:BlankNode" ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:NodeKindConstraintComponent ; + sh:sourceShape uco-owl:Restriction-shape ; + sh:value ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode [ + a owl:Restriction ; + rdfs:comment "This Restriction will trigger a failure from not having a class specified." ; + owl:onProperty ; + ns1:identifier "http://example.org/kb/Thing-exact-xfail-3/Restriction" ; + owl:qualifiedCardinality "1"^^xsd:nonNegativeInteger ; + ] ; + sh:resultMessage 'Node [ dcterms:identifier Literal("http://example.org/kb/Thing-exact-xfail-3/Restriction") ; owl:onProperty kb:object-property-1 ; owl:qualifiedCardinality Literal("1", datatype=xsd:nonNegativeInteger) ; rdf:type owl:Restriction ; rdfs:comment Literal("This Restriction will trigger a failure from not having a class specified.") ] must conform to exactly one shape in uco-owl:DataExactCardinalityQualified-shape , uco-owl:ObjectExactCardinalityQualified-shape' ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:XoneConstraintComponent ; + sh:sourceShape uco-owl:qualifiedCardinality-subjects-shape ; + sh:value [ + a owl:Restriction ; + rdfs:comment "This Restriction will trigger a failure from not having a class specified." ; + owl:onProperty ; + ns1:identifier "http://example.org/kb/Thing-exact-xfail-3/Restriction" ; + owl:qualifiedCardinality "1"^^xsd:nonNegativeInteger ; + ] ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode [ + a owl:Restriction ; + rdfs:comment "This Restriction will trigger a failure from not having a property specified." ; + owl:onClass ; + ns1:identifier "http://example.org/kb/Thing-exact-xfail-4/Restriction" ; + owl:qualifiedCardinality "1"^^xsd:nonNegativeInteger ; + ] ; + sh:resultMessage 'Node [ dcterms:identifier Literal("http://example.org/kb/Thing-exact-xfail-4/Restriction") ; owl:onClass kb:Other-Thing ; owl:qualifiedCardinality Literal("1", datatype=xsd:nonNegativeInteger) ; rdf:type owl:Restriction ; rdfs:comment Literal("This Restriction will trigger a failure from not having a property specified.") ] must conform to exactly one shape in uco-owl:DataExactCardinalityQualified-shape , uco-owl:ObjectExactCardinalityQualified-shape' ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:XoneConstraintComponent ; + sh:sourceShape uco-owl:qualifiedCardinality-subjects-shape ; + sh:value [ + a owl:Restriction ; + rdfs:comment "This Restriction will trigger a failure from not having a property specified." ; + owl:onClass ; + ns1:identifier "http://example.org/kb/Thing-exact-xfail-4/Restriction" ; + owl:qualifiedCardinality "1"^^xsd:nonNegativeInteger ; + ] ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode [ + a owl:Restriction ; + rdfs:comment "This Restriction will trigger a failure from not having a class specified." ; + owl:onProperty ; + ns1:identifier "http://example.org/kb/Thing-max-xfail-3/Restriction" ; + owl:maxQualifiedCardinality "1"^^xsd:nonNegativeInteger ; + ] ; + sh:resultMessage 'Node [ dcterms:identifier Literal("http://example.org/kb/Thing-max-xfail-3/Restriction") ; owl:maxQualifiedCardinality Literal("1", datatype=xsd:nonNegativeInteger) ; owl:onProperty kb:object-property-1 ; rdf:type owl:Restriction ; rdfs:comment Literal("This Restriction will trigger a failure from not having a class specified.") ] must conform to exactly one shape in uco-owl:DataMaxCardinalityQualified-shape , uco-owl:ObjectMaxCardinalityQualified-shape' ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:XoneConstraintComponent ; + sh:sourceShape uco-owl:maxQualifiedCardinality-subjects-shape ; + sh:value [ + a owl:Restriction ; + rdfs:comment "This Restriction will trigger a failure from not having a class specified." ; + owl:onProperty ; + ns1:identifier "http://example.org/kb/Thing-max-xfail-3/Restriction" ; + owl:maxQualifiedCardinality "1"^^xsd:nonNegativeInteger ; + ] ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode [ + a owl:Restriction ; + rdfs:comment "This Restriction will trigger a failure from not having a property specified." ; + owl:onClass ; + ns1:identifier "http://example.org/kb/Thing-max-xfail-4/Restriction" ; + owl:maxQualifiedCardinality "1"^^xsd:nonNegativeInteger ; + ] ; + sh:resultMessage 'Node [ dcterms:identifier Literal("http://example.org/kb/Thing-max-xfail-4/Restriction") ; owl:maxQualifiedCardinality Literal("1", datatype=xsd:nonNegativeInteger) ; owl:onClass kb:Other-Thing ; rdf:type owl:Restriction ; rdfs:comment Literal("This Restriction will trigger a failure from not having a property specified.") ] must conform to exactly one shape in uco-owl:DataMaxCardinalityQualified-shape , uco-owl:ObjectMaxCardinalityQualified-shape' ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:XoneConstraintComponent ; + sh:sourceShape uco-owl:maxQualifiedCardinality-subjects-shape ; + sh:value [ + a owl:Restriction ; + rdfs:comment "This Restriction will trigger a failure from not having a property specified." ; + owl:onClass ; + ns1:identifier "http://example.org/kb/Thing-max-xfail-4/Restriction" ; + owl:maxQualifiedCardinality "1"^^xsd:nonNegativeInteger ; + ] ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode [ + a owl:Restriction ; + rdfs:comment "This Restriction will trigger a failure from not having a class specified." ; + owl:onProperty ; + ns1:identifier "http://example.org/kb/Thing-min-xfail-3/Restriction" ; + owl:minQualifiedCardinality "1"^^xsd:nonNegativeInteger ; + ] ; + sh:resultMessage 'Node [ dcterms:identifier Literal("http://example.org/kb/Thing-min-xfail-3/Restriction") ; owl:minQualifiedCardinality Literal("1", datatype=xsd:nonNegativeInteger) ; owl:onProperty kb:object-property-1 ; rdf:type owl:Restriction ; rdfs:comment Literal("This Restriction will trigger a failure from not having a class specified.") ] must conform to exactly one shape in uco-owl:DataMinCardinalityQualified-shape , uco-owl:ObjectMinCardinalityQualified-shape' ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:XoneConstraintComponent ; + sh:sourceShape uco-owl:minQualifiedCardinality-subjects-shape ; + sh:value [ + a owl:Restriction ; + rdfs:comment "This Restriction will trigger a failure from not having a class specified." ; + owl:onProperty ; + ns1:identifier "http://example.org/kb/Thing-min-xfail-3/Restriction" ; + owl:minQualifiedCardinality "1"^^xsd:nonNegativeInteger ; + ] ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode [ + a owl:Restriction ; + rdfs:comment "This Restriction will trigger a failure from not having a property specified." ; + owl:onClass ; + ns1:identifier "http://example.org/kb/Thing-min-xfail-4/Restriction" ; + owl:minQualifiedCardinality "1"^^xsd:nonNegativeInteger ; + ] ; + sh:resultMessage 'Node [ dcterms:identifier Literal("http://example.org/kb/Thing-min-xfail-4/Restriction") ; owl:minQualifiedCardinality Literal("1", datatype=xsd:nonNegativeInteger) ; owl:onClass kb:Other-Thing ; rdf:type owl:Restriction ; rdfs:comment Literal("This Restriction will trigger a failure from not having a property specified.") ] must conform to exactly one shape in uco-owl:DataMinCardinalityQualified-shape , uco-owl:ObjectMinCardinalityQualified-shape' ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:XoneConstraintComponent ; + sh:sourceShape uco-owl:minQualifiedCardinality-subjects-shape ; + sh:value [ + a owl:Restriction ; + rdfs:comment "This Restriction will trigger a failure from not having a property specified." ; + owl:onClass ; + ns1:identifier "http://example.org/kb/Thing-min-xfail-4/Restriction" ; + owl:minQualifiedCardinality "1"^^xsd:nonNegativeInteger ; + ] ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode [ + a owl:Restriction ; + rdfs:comment "This Restriction will trigger two failures, from specifying both a minimum and maximum unqualified cardinality. (These should be in separate restrictions instead.)" ; + owl:onProperty ; + ns1:identifier "http://example.org/kb/Thing-plural-cardinality-xfail-1/Restriction" ; + owl:maxCardinality "2"^^xsd:nonNegativeInteger ; + owl:minCardinality "1"^^xsd:nonNegativeInteger ; + ] ; + sh:resultMessage 'More than 0 values on [ dcterms:identifier Literal("http://example.org/kb/Thing-plural-cardinality-xfail-1/Restriction") ; owl:maxCardinality Literal("2", datatype=xsd:nonNegativeInteger) ; owl:minCardinality Literal("1", datatype=xsd:nonNegativeInteger) ; owl:onProperty kb:object-property-1 ; rdf:type owl:Restriction ; rdfs:comment Literal("This Restriction will trigger two failures, from specifying both a minimum and maximum unqualified cardinality. (These should be in separate restrictions instead.)") ]->owl:maxCardinality' ; + sh:resultPath owl:maxCardinality ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:MaxCountConstraintComponent ; + sh:sourceShape [ + a sh:PropertyShape ; + sh:maxCount "0"^^xsd:integer ; + sh:path owl:maxCardinality ; + ] ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode [ + a owl:Restriction ; + rdfs:comment "This Restriction will trigger two failures, from specifying both a minimum and maximum unqualified cardinality. (These should be in separate restrictions instead.)" ; + owl:onProperty ; + ns1:identifier "http://example.org/kb/Thing-plural-cardinality-xfail-1/Restriction" ; + owl:maxCardinality "2"^^xsd:nonNegativeInteger ; + owl:minCardinality "1"^^xsd:nonNegativeInteger ; + ] ; + sh:resultMessage 'More than 0 values on [ dcterms:identifier Literal("http://example.org/kb/Thing-plural-cardinality-xfail-1/Restriction") ; owl:maxCardinality Literal("2", datatype=xsd:nonNegativeInteger) ; owl:minCardinality Literal("1", datatype=xsd:nonNegativeInteger) ; owl:onProperty kb:object-property-1 ; rdf:type owl:Restriction ; rdfs:comment Literal("This Restriction will trigger two failures, from specifying both a minimum and maximum unqualified cardinality. (These should be in separate restrictions instead.)") ]->owl:minCardinality' ; + sh:resultPath owl:minCardinality ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:MaxCountConstraintComponent ; + sh:sourceShape [ + a sh:PropertyShape ; + sh:maxCount "0"^^xsd:integer ; + sh:path owl:minCardinality ; + ] ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode [ + a owl:Restriction ; + rdfs:comment "This Restriction will trigger two failures, from specifying both a minimum and maximum qualified cardinality. (These should be in separate restrictions instead.)" ; + owl:onProperty ; + owl:onClass ; + ns1:identifier "http://example.org/kb/Thing-plural-qualified-cardinality-xfail-1/Restriction" ; + owl:maxQualifiedCardinality "2"^^xsd:nonNegativeInteger ; + owl:minQualifiedCardinality "1"^^xsd:nonNegativeInteger ; + ] ; + sh:resultMessage 'More than 0 values on [ dcterms:identifier Literal("http://example.org/kb/Thing-plural-qualified-cardinality-xfail-1/Restriction") ; owl:maxQualifiedCardinality Literal("2", datatype=xsd:nonNegativeInteger) ; owl:minQualifiedCardinality Literal("1", datatype=xsd:nonNegativeInteger) ; owl:onClass kb:Other-Thing ; owl:onProperty kb:object-property-1 ; rdf:type owl:Restriction ; rdfs:comment Literal("This Restriction will trigger two failures, from specifying both a minimum and maximum qualified cardinality. (These should be in separate restrictions instead.)") ]->owl:maxQualifiedCardinality' ; + sh:resultPath owl:maxQualifiedCardinality ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:MaxCountConstraintComponent ; + sh:sourceShape [ + a sh:PropertyShape ; + sh:maxCount "0"^^xsd:integer ; + sh:path owl:maxQualifiedCardinality ; + ] ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode [ + a owl:Restriction ; + rdfs:comment "This Restriction will trigger two failures, from specifying both a minimum and maximum qualified cardinality. (These should be in separate restrictions instead.)" ; + owl:onProperty ; + owl:onClass ; + ns1:identifier "http://example.org/kb/Thing-plural-qualified-cardinality-xfail-1/Restriction" ; + owl:maxQualifiedCardinality "2"^^xsd:nonNegativeInteger ; + owl:minQualifiedCardinality "1"^^xsd:nonNegativeInteger ; + ] ; + sh:resultMessage 'More than 0 values on [ dcterms:identifier Literal("http://example.org/kb/Thing-plural-qualified-cardinality-xfail-1/Restriction") ; owl:maxQualifiedCardinality Literal("2", datatype=xsd:nonNegativeInteger) ; owl:minQualifiedCardinality Literal("1", datatype=xsd:nonNegativeInteger) ; owl:onClass kb:Other-Thing ; owl:onProperty kb:object-property-1 ; rdf:type owl:Restriction ; rdfs:comment Literal("This Restriction will trigger two failures, from specifying both a minimum and maximum qualified cardinality. (These should be in separate restrictions instead.)") ]->owl:minQualifiedCardinality' ; + sh:resultPath owl:minQualifiedCardinality ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:MaxCountConstraintComponent ; + sh:sourceShape [ + a sh:PropertyShape ; + sh:maxCount "0"^^xsd:integer ; + sh:path owl:minQualifiedCardinality ; + ] ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode [ + a owl:Restriction ; + rdfs:comment "This Restriction will trigger a failure from specifying a class on an unqualified cardinality." ; + owl:onProperty ; + owl:onClass ; + ns1:identifier "http://example.org/kb/Thing-unqualified-cardinality-with-class-xfail-1/Restriction" ; + owl:cardinality "1"^^xsd:nonNegativeInteger ; + ] ; + sh:resultMessage 'More than 0 values on [ dcterms:identifier Literal("http://example.org/kb/Thing-unqualified-cardinality-with-class-xfail-1/Restriction") ; owl:cardinality Literal("1", datatype=xsd:nonNegativeInteger) ; owl:onClass kb:Other-Thing ; owl:onProperty kb:object-property-1 ; rdf:type owl:Restriction ; rdfs:comment Literal("This Restriction will trigger a failure from specifying a class on an unqualified cardinality.") ]->owl:onClass' ; + sh:resultPath owl:onClass ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:MaxCountConstraintComponent ; + sh:sourceShape [ + a sh:PropertyShape ; + sh:maxCount "0"^^xsd:integer ; + sh:path owl:onClass ; + ] ; + ] + ; + . + diff --git a/tests/examples/test_validation.py b/tests/examples/test_validation.py index 609c1b77..33c5e06a 100644 --- a/tests/examples/test_validation.py +++ b/tests/examples/test_validation.py @@ -29,6 +29,8 @@ import rdflib.plugins.sparql NS_CO = rdflib.Namespace("http://purl.org/co/") +NS_DCTERMS = rdflib.DCTERMS +NS_OWL = rdflib.OWL NS_SH = rdflib.SH NS_UCO_ACTION = rdflib.Namespace("https://ontology.unifiedcyberontology.org/uco/action/") NS_UCO_CO = rdflib.Namespace("https://ontology.unifiedcyberontology.org/co/") @@ -475,6 +477,90 @@ def test_owl_axiom_XFAIL() -> None: } ) +def test_owl_cardinality_restrictions_PASS() -> None: + confirm_validation_results( + "owl_cardinality_restrictions_PASS_validation.ttl", + True, + expected_focus_node_severities=set() + ) + +def test_owl_cardinality_restrictions_XFAIL() -> None: + # This test is defined by counting the number of results. + expected_validation_result_tally: int = 17 + computed_validation_result_tally: int = 0 + + expected_focus_identifiers: typing.Dict[str, int] = { + "http://example.org/kb/Thing-exact-xfail-3/Restriction": 1, + "http://example.org/kb/Thing-exact-xfail-4/Restriction": 1, + "http://example.org/kb/Thing-max-xfail-3/Restriction": 1, + "http://example.org/kb/Thing-max-xfail-4/Restriction": 1, + "http://example.org/kb/Thing-min-xfail-3/Restriction": 1, + "http://example.org/kb/Thing-min-xfail-4/Restriction": 1, + "http://example.org/kb/Thing-unqualified-cardinality-with-class-xfail-1/Restriction": 1, + "http://example.org/kb/Thing-plural-cardinality-xfail-1/Restriction": 2, + "http://example.org/kb/Thing-plural-qualified-cardinality-xfail-1/Restriction": 2, + } + computed_focus_identifiers: typing.Dict[str, int] = dict() + # The nature of the tests pertaining to these identifiers mean the + # node references do not appear directly in the ValidationReport. + excused_identifiers: typing.Set[str] = { + "http://example.org/kb/Restriction-1", + "http://example.org/kb/Restriction-2", + "http://example.org/kb/Restriction-3", + "http://example.org/kb/Thing-exact-xfail-2/Restriction", + "http://example.org/kb/Thing-max-xfail-2/Restriction", + "http://example.org/kb/Thing-min-xfail-2/Restriction", + } + + g = load_validation_graph( + "owl_cardinality_restrictions_XFAIL_validation.ttl", + False + ) + + for triple0 in g.triples((None, NS_SH.result, None)): + computed_validation_result_tally += 1 + + # Confirm some of the test nodes triggered multiple results. + # Because OWL requires some of the triggering nodes be blank nodes, + # use dcterms:identifier to store a string-literal identifier. + for result in g.query( + """\ +PREFIX dcterms: +PREFIX sh: +SELECT ?nValidationResult ?lIdentifier +WHERE { + ?nValidationResult + a sh:ValidationResult ; + sh:focusNode ?nFocusNode ; + . + ?nFocusNode + dcterms:identifier ?lIdentifier ; + . +} +""" + ): + assert isinstance(result, rdflib.query.ResultRow) + assert isinstance(result[0], rdflib.term.BNode) + assert isinstance(result[1], rdflib.Literal) + n_validation_result: rdflib.term.BNode = result[0] + l_identifier: rdflib.Literal = result[1] + identifier_string: str = l_identifier.toPython() + if identifier_string not in computed_focus_identifiers: + computed_focus_identifiers[identifier_string] = 0 + computed_focus_identifiers[identifier_string] += 1 + + assert expected_validation_result_tally == computed_validation_result_tally + assert expected_focus_identifiers == computed_focus_identifiers + + # Confirm coverage regardless of triggering or not. + all_dcterms_identifiers: typing.Set[str] = set() + g.parse("owl_cardinality_restrictions_XFAIL.json", format="json-ld") + for l_object in g.objects(None, NS_DCTERMS.identifier): + assert isinstance(l_object, rdflib.Literal) + all_dcterms_identifiers.add(str(l_object)) + + assert all_dcterms_identifiers == excused_identifiers | {x for x in expected_focus_identifiers.keys()} + def test_owl_properties_PASS() -> None: confirm_validation_results( "owl_properties_PASS_validation.ttl",