ucoProject / UCO

This repository is for development of the Unified Cyber Ontology.
Apache License 2.0
73 stars 34 forks source link

Issue 571: Reduce UCO OWL RDF List review scope to OWL Sequences #572

Closed ajnelson-nist closed 5 months ago

ajnelson-nist commented 7 months ago

This Pull Request resolves all requirements of Issue #571 .

Coordination

ajnelson-nist commented 7 months ago

When testing CASE-Corpora, I found an error in an OWL assertion I'd written:

dcat:Dataset
        rdfs:comment "Within CASE-Corpora, the property hasDatasetDirectory is a unique identifier for a Dataset."@en ;
        owl:hasKey case-corpora:hasDatasetDirectory ;
        . 

This turns out to be incorrect. owl:hasKey is a sequence-valued predicate. Instead of dcat:Dataset owl:hasKey case-corpora:hasDatasetDirectory ., it should be dcat:Dataset owl:hasKey ( case-corpora:hasDatasetDirectory ) ..

The SHACL validation report from state a65ebe9 (brought in via the unstable branch) read like this:

@prefix case-corpora: <http://example.org/ontology/case-corpora/> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix uco-owl: <https://ontology.unifiedcyberontology.org/owl/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

[] a sh:ValidationReport ;
    sh:conforms false ;
    sh:result [ a sh:ValidationResult ;
            sh:detail [ a sh:ValidationResult ;
                    sh:focusNode case-corpora:hasDatasetDirectory ;
                    sh:resultMessage "Node case-corpora:hasDatasetDirectory does not conform to exactly one shape in [ rdf:type sh:NodeShape ; sh:hasValue rdf:nil ] , [ rdf:type sh:NodeShape ; sh:nodeKind sh:BlankNode ; sh:property [ rdf:type sh:PropertyShape ; sh:path [ sh:oneOrMorePath rdf:rest ] ; sh:xone ( [ rdf:type sh:NodeShape ; sh:hasValue rdf:nil ] [ rdf:type sh:NodeShape ; sh:nodeKind sh:BlankNode ; sh:property [ rdf:type sh:PropertyShape ; sh:maxCount Literal(\"1\", datatype=xsd:integer) ; sh:minCount Literal(\"1\", datatype=xsd:integer) ; sh:path rdf:first ] ] ) ] ]" ;
                    sh:resultSeverity sh:Violation ;
                    sh:sourceConstraintComponent sh:XoneConstraintComponent ;
                    sh:sourceShape uco-owl:Sequence-shape ;
                    sh:value case-corpora:hasDatasetDirectory ] ;
            sh:focusNode case-corpora:hasDatasetDirectory ;
            sh:resultMessage "Value does not conform to Shape uco-owl:Sequence-shape. See details for more information." ;
            sh:resultSeverity sh:Violation ;
            sh:sourceConstraintComponent sh:NodeConstraintComponent ;
            sh:sourceShape uco-owl:hasKey-objects-shape ;
            sh:value case-corpora:hasDatasetDirectory ] .

It is a bit obscuring for the sh:focusNode and sh:value to be the same part of the triple.

ajnelson-nist commented 7 months ago

I think it will be a better user experience to spell the shapes for each sequence-valued property like this instead:


# Replace this ...
uco-owl:hasKey-objects-shape
       a sh:NodeShape ;
       sh:node uco-owl:Sequence-shape ;
       sh:targetObjectsOf owl:hasKey ;
       .

# ... with this:
uco-owl:hasKey-subjects-shape
       a sh:NodeShape ;
       sh:property [
               a sh:PropertyShape ;
               sh:node uco-owl:Sequence-shape ;
               sh:path owl:hasKey ;
       ] ;
       sh:targetSubjectsOf owl:hasKey ;
       .

Here is how that same validation report on the incorrect hasKey usage now reads:

@prefix case-corpora: <http://example.org/ontology/case-corpora/> .
@prefix dcat: <http://www.w3.org/ns/dcat#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix uco-owl: <https://ontology.unifiedcyberontology.org/owl/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

[] a sh:ValidationReport ;
    sh:conforms false ;
    sh:result [ a sh:ValidationResult ;
            sh:detail [ a sh:ValidationResult ;
                    sh:focusNode case-corpora:hasDatasetDirectory ;
                    sh:resultMessage "Node case-corpora:hasDatasetDirectory does not conform to exactly one shape in [ rdf:type sh:NodeShape ; sh:hasValue rdf:nil ] , [ rdf:type sh:NodeShape ; sh:nodeKind sh:BlankNode ; sh:property [ rdf:type sh:PropertyShape ; sh:path [ sh:oneOrMorePath rdf:rest ] ; sh:xone ( [ rdf:type sh:NodeShape ; sh:hasValue rdf:nil ] [ rdf:type sh:NodeShape ; sh:nodeKind sh:BlankNode ; sh:property [ rdf:type sh:PropertyShape ; sh:maxCount Literal(\"1\", datatype=xsd:integer) ; sh:minCount Literal(\"1\", datatype=xsd:integer) ; sh:path rdf:first ] ] ) ] ]" ;
                    sh:resultSeverity sh:Violation ;
                    sh:sourceConstraintComponent sh:XoneConstraintComponent ;
                    sh:sourceShape uco-owl:Sequence-shape ;
                    sh:value case-corpora:hasDatasetDirectory ] ;
            sh:focusNode dcat:Dataset ;
            sh:resultMessage "Value does not conform to Shape uco-owl:Sequence-shape. See details for more information." ;
            sh:resultPath owl:hasKey ;
            sh:resultSeverity sh:Violation ;
            sh:sourceConstraintComponent sh:NodeConstraintComponent ;
            sh:sourceShape [ a sh:PropertyShape ;
                    sh:node uco-owl:Sequence-shape ;
                    sh:path owl:hasKey ] ;
            sh:value case-corpora:hasDatasetDirectory ] .

The whole flagged triple can now be found with sh:focusNode, sh:resultPath, and sh:value.