diff --git a/ontology/uco/action/action.ttl b/ontology/uco/action/action.ttl index 80b67a3d..07f251a5 100644 --- a/ontology/uco/action/action.ttl +++ b/ontology/uco/action/action.ttl @@ -350,6 +350,31 @@ action:ArrayOfAction sh:targetClass action:ArrayOfAction ; . +action:Technique + a + owl:Class , + sh:NodeShape + ; + rdfs:subClassOf core:UcoType ; + rdfs:label "Technique"@en ; + rdfs:comment "A technique is a class of actions joined by some common characteristics. uco-action:Technique itself is a metaclass. A Technique instance is an owl:Class that is a subclass of uco-action:Action."@en ; + sh:property + [ + rdfs:comment "This shape confirms a Technique is an eventual subclass of Action. The Action class itself is not a Technique."@en ; + sh:hasValue action:Action ; + sh:path [ + sh:oneOrMorePath rdfs:subClassOf ; + ] ; + ] , + [ + rdfs:comment "This shape will find violations after RDFS or OWL-RL inferencing, but might not find some violations without inferencing."@en ; + sh:nodeKind sh:Literal ; + sh:path action:techniqueID ; + ] + ; + sh:targetClass action:Technique ; + . + action:action a owl:ObjectProperty ; rdfs:label "action"@en ; @@ -511,6 +536,20 @@ action:subaction rdfs:range action:Action ; . +action:techniqueID + a owl:DatatypeProperty ; + rdfs:label "techniqueID"@en ; + rdfs:comment "An identifier for a technique within some cataloguing system. At the general level of UCO, techniqueID is left optional and minimally-described aside from needing to be Literal-valued. Specializations of Technique should also consider specializing a corresponding subproperty of techniqueID to enable support of global review of technique identifiers."@en ; + rdfs:domain action:Technique ; + . + +action:techniqueID-subjects-shape + a sh:NodeShape ; + rdfs:comment "This shape enforces that action:techniqueID is only used on Techniques."@en ; + sh:class action:Technique ; + sh:targetSubjectsOf action:techniqueID ; + . + action:trend a owl:DatatypeProperty ; rdfs:label "trend"@en ; diff --git a/ontology/uco/core/core.ttl b/ontology/uco/core/core.ttl index b4f59e84..e8fe0020 100644 --- a/ontology/uco/core/core.ttl +++ b/ontology/uco/core/core.ttl @@ -487,7 +487,7 @@ core:UcoThing ; rdfs:subClassOf owl:Thing ; rdfs:label "UcoThing"@en ; - rdfs:comment "UcoThing is the top-level class within UCO."@en ; + rdfs:comment "UcoThing is the top-level class for individuals within UCO."@en ; rdfs:seeAlso core:UcoThing-identifier-regex-shape ; sh:sparql [ a sh:SPARQLConstraint ; @@ -505,6 +505,16 @@ core:UcoThing sh:targetClass core:UcoThing ; . +core:UcoThing-disjointWith-UcoType-shape + a sh:NodeShape ; + sh:message "core:UcoThing and core:UcoType are disjoint classes."@en ; + sh:not [ + a sh:NodeShape ; + sh:class core:UcoType ; + ] ; + sh:targetClass core:UcoThing ; + . + core:UcoThing-identifier-regex-shape a sh:NodeShape ; rdfs:comment "This shape is given an independent IRI for applications that have sufficient controls in place to deactivate this advisory of node identification practice."@en ; @@ -533,6 +543,25 @@ core:UcoThing-identifier-regex-shape sh:targetClass core:UcoThing ; . +core:UcoType + a + owl:Class , + sh:NodeShape + ; + rdfs:subClassOf owl:Thing ; + rdfs:label "UcoType"@en ; + rdfs:comment "UcoThing is the top-level class for metaclasses within UCO. An instance of core:UcoType is also an instance of owl:Class, and is or specializes core:UcoThing."@en ; + owl:disjointWith core:UcoThing ; + sh:class owl:Class ; + sh:property [ + sh:hasValue core:UcoThing ; + sh:path [ + sh:zeroOrMorePath rdfs:subClassOf ; + ] ; + ] ; + sh:targetClass core:UcoType ; + . + core:confidence a owl:DatatypeProperty ; rdfs:label "confidence"@en ; diff --git a/tests/examples/Makefile b/tests/examples/Makefile index 441fce4e..a7cb2823 100644 --- a/tests/examples/Makefile +++ b/tests/examples/Makefile @@ -24,6 +24,7 @@ all: \ action_inheritance_PASS_validation.ttl \ action_inheritance_XFAIL_validation.ttl \ action_result_PASS_validation.ttl \ + all-technique \ alternate_data_stream_PASS_validation.ttl \ co_PASS_validation.ttl \ co_XFAIL_validation.ttl \ @@ -58,7 +59,14 @@ all: \ relationship_XFAIL_validation.ttl \ thread_PASS_validation.ttl \ thread_XFAIL_validation.ttl \ - uco_thing_XFAIL_validation.ttl + uco_thing_XFAIL_validation.ttl \ + uco_type_PASS_validation.ttl \ + uco_type_XFAIL_validation.ttl + +.PHONY: \ + all-technique \ + check-technique \ + clean-technique .PRECIOUS: \ %_validation.ttl @@ -98,11 +106,18 @@ all: \ rm __$@ mv _$@ $@ +all-technique: \ + $(top_srcdir)/.venv.done.log \ + $(tests_srcdir)/uco_monolithic.ttl + $(MAKE) \ + --directory technique + check: \ action_inheritance_PASS_validation.ttl \ action_inheritance_XFAIL_validation.ttl \ action_result_PASS_validation.ttl \ alternate_data_stream_PASS_validation.ttl \ + check-technique \ co_PASS_validation.ttl \ co_XFAIL_validation.ttl \ configuration_setting_PASS_validation.ttl \ @@ -136,11 +151,25 @@ check: \ relationship_XFAIL_validation.ttl \ thread_PASS_validation.ttl \ thread_XFAIL_validation.ttl \ - uco_thing_XFAIL_validation.ttl + uco_thing_XFAIL_validation.ttl \ + uco_type_PASS_validation.ttl \ + uco_type_XFAIL_validation.ttl source $(top_srcdir)/venv/bin/activate \ && pytest \ --log-level=DEBUG -clean: +check-technique: \ + all-technique + $(MAKE) \ + --directory technique \ + check + +clean: \ + clean-technique @rm -f \ *_validation.ttl + +clean-technique: + @$(MAKE) \ + --directory technique \ + clean diff --git a/tests/examples/technique/.gitignore b/tests/examples/technique/.gitignore new file mode 100644 index 00000000..c8dd22b3 --- /dev/null +++ b/tests/examples/technique/.gitignore @@ -0,0 +1 @@ +generated-* diff --git a/tests/examples/technique/Makefile b/tests/examples/technique/Makefile new file mode 100644 index 00000000..6af51a2f --- /dev/null +++ b/tests/examples/technique/Makefile @@ -0,0 +1,196 @@ +#!/usr/bin/make -f + +# Portions of this file contributed by NIST are governed by the +# following statement: +# +# This software was developed at the National Institute of Standards +# and Technology by employees of the Federal Government in the course +# of their official duties. Pursuant to Title 17 Section 105 of the +# United States Code, this software is not subject to copyright +# protection within the United States. NIST assumes no responsibility +# whatsoever for its use by other parties, and makes no guarantees, +# expressed or implied, about its quality, reliability, or any other +# characteristic. +# +# We would appreciate acknowledgement if the software is used. + +SHELL := /bin/bash + +top_srcdir := $(shell cd ../../.. ; pwd) + +all: \ + check + +check: \ + technique_ontology_XFAIL_validation.ttl \ + technique_ontology_XFAIL_rdfs_validation.ttl \ + technique_ontology_XFAIL_owlrl_validation.ttl \ + technique_data_PASS_validation.ttl \ + technique_data_XFAIL_validation.ttl + +clean: + @rm -f \ + _* \ + generated-* + +generated-shapes.ttl: \ + $(top_srcdir)/.venv.done.log \ + $(top_srcdir)/tests/uco_monolithic.ttl \ + $(top_srcdir)/tests/thing.ttl \ + technique_shapes_PASS.ttl + source $(top_srcdir)/venv/bin/activate \ + && rdfpipe \ + --output-format turtle \ + $(top_srcdir)/tests/uco_monolithic.ttl \ + technique_shapes_PASS.ttl \ + > _$@ + source $(top_srcdir)/venv/bin/activate \ + && pyshacl \ + --format turtle \ + --metashacl \ + --shacl _$@ \ + $(top_srcdir)/tests/thing.ttl + mv _$@ $@ + +generated-tbox.ttl: \ + $(top_srcdir)/.venv.done.log \ + $(top_srcdir)/tests/uco_monolithic.ttl \ + generated-shapes.ttl \ + technique_ontology_PASS.ttl + source $(top_srcdir)/venv/bin/activate \ + && rdfpipe \ + --output-format turtle \ + $(top_srcdir)/tests/uco_monolithic.ttl \ + technique_ontology_PASS.ttl \ + > _$@ + source $(top_srcdir)/venv/bin/activate \ + && pyshacl \ + --format turtle \ + --shacl generated-shapes.ttl \ + _$@ + mv _$@ $@ + +technique_data_PASS_validation.ttl: \ + generated-tbox.ttl \ + technique_data_PASS.json + source $(top_srcdir)/venv/bin/activate \ + && pyshacl \ + --format turtle \ + --ont-graph generated-tbox.ttl \ + --output __$@ \ + --shacl generated-shapes.ttl \ + technique_data_PASS.json + java -jar $(top_srcdir)/lib/rdf-toolkit.jar \ + --inline-blank-nodes \ + --source __$@ \ + --source-format turtle \ + --target _$@ \ + --target-format turtle + rm __$@ + mv _$@ $@ + +technique_data_XFAIL_validation.ttl: \ + generated-tbox.ttl \ + technique_data_XFAIL.json + source $(top_srcdir)/venv/bin/activate \ + && pyshacl \ + --format turtle \ + --ont-graph generated-tbox.ttl \ + --output __$@ \ + --shacl generated-shapes.ttl \ + technique_data_XFAIL.json \ + ; test 1 -eq $$? + java -jar $(top_srcdir)/lib/rdf-toolkit.jar \ + --inline-blank-nodes \ + --source __$@ \ + --source-format turtle \ + --target _$@ \ + --target-format turtle + rm __$@ + mv _$@ $@ + +technique_ontology_XFAIL_owlrl_validation.ttl: \ + $(top_srcdir)/.venv.done.log \ + $(top_srcdir)/tests/uco_monolithic.ttl \ + generated-shapes.ttl \ + technique_ontology_XFAIL.ttl + source $(top_srcdir)/venv/bin/activate \ + && rdfpipe \ + --output-format turtle \ + $(top_srcdir)/tests/uco_monolithic.ttl \ + technique_ontology_XFAIL.ttl \ + > _$@ + source $(top_srcdir)/venv/bin/activate \ + && pyshacl \ + --format turtle \ + --inference owlrl \ + --output __$@ \ + --shacl generated-shapes.ttl \ + _$@ \ + ; test 1 -eq $$? + rm _$@ + java -jar $(top_srcdir)/lib/rdf-toolkit.jar \ + --inline-blank-nodes \ + --source __$@ \ + --source-format turtle \ + --target _$@ \ + --target-format turtle + rm __$@ + mv _$@ $@ + +technique_ontology_XFAIL_rdfs_validation.ttl: \ + $(top_srcdir)/.venv.done.log \ + $(top_srcdir)/tests/uco_monolithic.ttl \ + generated-shapes.ttl \ + technique_ontology_XFAIL.ttl + source $(top_srcdir)/venv/bin/activate \ + && rdfpipe \ + --output-format turtle \ + $(top_srcdir)/tests/uco_monolithic.ttl \ + technique_ontology_XFAIL.ttl \ + > _$@ + source $(top_srcdir)/venv/bin/activate \ + && pyshacl \ + --format turtle \ + --inference rdfs \ + --output __$@ \ + --shacl generated-shapes.ttl \ + _$@ \ + ; test 1 -eq $$? + rm _$@ + java -jar $(top_srcdir)/lib/rdf-toolkit.jar \ + --inline-blank-nodes \ + --source __$@ \ + --source-format turtle \ + --target _$@ \ + --target-format turtle + rm __$@ + mv _$@ $@ + +technique_ontology_XFAIL_validation.ttl: \ + $(top_srcdir)/.venv.done.log \ + $(top_srcdir)/tests/uco_monolithic.ttl \ + generated-shapes.ttl \ + technique_ontology_XFAIL.ttl + source $(top_srcdir)/venv/bin/activate \ + && rdfpipe \ + --output-format turtle \ + $(top_srcdir)/tests/uco_monolithic.ttl \ + technique_ontology_XFAIL.ttl \ + > _$@ + source $(top_srcdir)/venv/bin/activate \ + && pyshacl \ + --format turtle \ + --output __$@ \ + --shacl generated-shapes.ttl \ + _$@ \ + ; test 1 -eq $$? + rm _$@ + java -jar $(top_srcdir)/lib/rdf-toolkit.jar \ + --inline-blank-nodes \ + --source __$@ \ + --source-format turtle \ + --target _$@ \ + --target-format turtle + rm __$@ + mv _$@ $@ diff --git a/tests/examples/technique/README.md b/tests/examples/technique/README.md new file mode 100644 index 00000000..d59aa3f2 --- /dev/null +++ b/tests/examples/technique/README.md @@ -0,0 +1,22 @@ +# Tests of Technique metaclass + +The test matrix for PASS conditions is as follows: + +* `uco-action:Technique` is: + + - Not specialized (see `ex0:Technique-A`) + - Specialized (see `ex1:Technique`, `ex2:AdaptedTechnique`) + +* Each of the above degrees of `Technique` specialization is instantiated with some `Action` subclass. + + - No specialization (see `ex0:Technique-A`) + - One level of specialization (see `ex1:Technique-T0001`, `ex2:AT-0001`) + - Two levels of specialization, using the same Technique-subclass (see `ex1:T0002`) + - Two levels of specialization, using different Technique-subclasses (see `ex2:AT-0099`) + +* Each of the above instantiations by some degree of `Technique` specialization is instantiated. + + - No specialization (see `kb:Action-a34208f4-31ea-4d78-95c9-153a73fbb628`) + - One level of specialization (see `kb:Action-c44d57af-a6c3-4350-b08b-0dac5f3b7aca`) + - Two levels of specialization, using the same Technique-subclass (see `kb:Action-8f84a98c-2ab5-454d-9c2f-443fe64b7158`) + - Two levels of specialization, using different Technique-subclasses (see `kb:Action-f6625d7d-978d-4562-83d7-23d9ac398073`) diff --git a/tests/examples/technique/technique_data_PASS.json b/tests/examples/technique/technique_data_PASS.json new file mode 100644 index 00000000..a6bf7670 --- /dev/null +++ b/tests/examples/technique/technique_data_PASS.json @@ -0,0 +1,53 @@ +{ + "@context": { + "ex0": "http://example/ontology/", + "ex1": "http://example.com/framework/", + "ex2": "http://example.org/operations/", + "kb": "http://example.org/kb/", + "owl": "http://www.w3.org/2002/07/owl#", + "rdfs": "http://www.w3.org/2000/01/rdf-schema#", + "uco-action": "https://ontology.unifiedcyberontology.org/uco/action/" + }, + "@graph": [ + { + "@id": "kb:Action-8f84a98c-2ab5-454d-9c2f-443fe64b7158", + "@type": "ex1:Technique-T0002", + "uco-action:object": { + "@id": "kb:Device-765e3d23-ce91-459d-b5ec-6c60d37df842" + } + }, + { + "@id": "kb:Action-a34208f4-31ea-4d78-95c9-153a73fbb628", + "@type": "ex0:Technique-A" + }, + { + "@id": "kb:Action-c44d57af-a6c3-4350-b08b-0dac5f3b7aca", + "@type": "ex1:Technique-T0001", + "uco-action:object": { + "@id": "kb:Device-765e3d23-ce91-459d-b5ec-6c60d37df842" + } + }, + { + "@id": "kb:Action-dd609c02-176d-40ed-9858-ead8bdc47757", + "@type": "ex2:AT-0001" + }, + { + "@id": "kb:Action-f6625d7d-978d-4562-83d7-23d9ac398073", + "@type": "ex2:AT-0099", + "uco-action:instrument": { + "@id": "kb:Device-e79fb51b-6c45-4e70-9e79-9f600509ca6c" + }, + "uco-action:object": { + "@id": "kb:Device-765e3d23-ce91-459d-b5ec-6c60d37df842" + } + }, + { + "@id": "kb:Device-765e3d23-ce91-459d-b5ec-6c60d37df842", + "@type": "ex1:YDevice" + }, + { + "@id": "kb:Device-e79fb51b-6c45-4e70-9e79-9f600509ca6c", + "@type": "ex2:ZDevice" + } + ] +} diff --git a/tests/examples/technique/technique_data_PASS_validation.ttl b/tests/examples/technique/technique_data_PASS_validation.ttl new file mode 100644 index 00000000..33496ff0 --- /dev/null +++ b/tests/examples/technique/technique_data_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/technique/technique_data_XFAIL.json b/tests/examples/technique/technique_data_XFAIL.json new file mode 100644 index 00000000..d288d406 --- /dev/null +++ b/tests/examples/technique/technique_data_XFAIL.json @@ -0,0 +1,33 @@ +{ + "@context": { + "ex0": "http://example/ontology/", + "ex1": "http://example.com/framework/", + "ex2": "http://example.org/operations/", + "kb": "http://example.org/kb/", + "owl": "http://www.w3.org/2002/07/owl#", + "rdfs": "http://www.w3.org/2000/01/rdf-schema#", + "uco-action": "https://ontology.unifiedcyberontology.org/uco/action/" + }, + "@graph": [ + { + "@id": "kb:Action-8f84a98c-2ab5-454d-9c2f-443fe64b7158", + "@type": "ex1:Technique-T0002" + }, + { + "@id": "kb:Action-c44d57af-a6c3-4350-b08b-0dac5f3b7aca", + "@type": "ex1:Technique-T0001" + }, + { + "@id": "kb:Action-f6625d7d-978d-4562-83d7-23d9ac398073", + "@type": "ex2:AT-0099" + }, + { + "@id": "kb:Device-765e3d23-ce91-459d-b5ec-6c60d37df842", + "@type": "ex1:YDevice" + }, + { + "@id": "kb:Device-e79fb51b-6c45-4e70-9e79-9f600509ca6c", + "@type": "ex2:ZDevice" + } + ] +} diff --git a/tests/examples/technique/technique_data_XFAIL_validation.ttl b/tests/examples/technique/technique_data_XFAIL_validation.ttl new file mode 100644 index 00000000..32c3a5dc --- /dev/null +++ b/tests/examples/technique/technique_data_XFAIL_validation.ttl @@ -0,0 +1,80 @@ +@prefix ex1: . +@prefix ex2: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix uco-action: . +@prefix xsd: . + +[] + a sh:ValidationReport ; + sh:conforms "false"^^xsd:boolean ; + sh:result + [ + a sh:ValidationResult ; + sh:focusNode ; + sh:resultMessage "Focus node does not conform to shape MinCount 1: [ sh:class ex1:YDevice ]" ; + sh:resultPath uco-action:object ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:QualifiedMinCountConstraintComponent ; + sh:sourceShape [ + rdfs:comment "This property shape enforces that execution of this Technique involves some Y-device as action-input."@en ; + sh:path uco-action:object ; + sh:qualifiedMinCount "1"^^xsd:integer ; + sh:qualifiedValueShape [ + sh:class ex1:YDevice ; + ] ; + ] ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode ; + sh:resultMessage "Focus node does not conform to shape MinCount 1: [ sh:class ex1:YDevice ]" ; + sh:resultPath uco-action:object ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:QualifiedMinCountConstraintComponent ; + sh:sourceShape [ + rdfs:comment "This property shape enforces that execution of this Technique involves some Y-device as action-input."@en ; + sh:path uco-action:object ; + sh:qualifiedMinCount "1"^^xsd:integer ; + sh:qualifiedValueShape [ + sh:class ex1:YDevice ; + ] ; + ] ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode ; + sh:resultMessage "Focus node does not conform to shape MinCount 1: [ sh:class ex1:YDevice ]" ; + sh:resultPath uco-action:object ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:QualifiedMinCountConstraintComponent ; + sh:sourceShape [ + rdfs:comment "This property shape enforces that execution of this Technique involves some Y-device as action-input."@en ; + sh:path uco-action:object ; + sh:qualifiedMinCount "1"^^xsd:integer ; + sh:qualifiedValueShape [ + sh:class ex1:YDevice ; + ] ; + ] ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode ; + sh:resultMessage "Focus node does not conform to shape MinCount 1: [ sh:class ex2:ZDevice ]" ; + sh:resultPath uco-action:instrument ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:QualifiedMinCountConstraintComponent ; + sh:sourceShape [ + rdfs:comment "This property shape enforces that execution of this AdaptedTechnique involves some Z-device as action-instrument."@en ; + sh:path uco-action:instrument ; + sh:qualifiedMinCount "1"^^xsd:integer ; + sh:qualifiedValueShape [ + sh:class ex2:ZDevice ; + ] ; + ] ; + ] + ; + . + diff --git a/tests/examples/technique/technique_ontology_PASS.ttl b/tests/examples/technique/technique_ontology_PASS.ttl new file mode 100644 index 00000000..fb4f39c3 --- /dev/null +++ b/tests/examples/technique/technique_ontology_PASS.ttl @@ -0,0 +1,152 @@ +@prefix ex0: . +@prefix ex1: . +@prefix ex2: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix uco-action: . +@prefix uco-observable: . +@prefix xsd: . + +ex1:Technique + a owl:Class ; + rdfs:subClassOf + uco-action:Technique , + [ + a owl:Restriction ; + rdfs:comment + "(Technical demonstration: Instances of the metaclass can have a datatype property assigned.)"@en , + "This Restriction states, but does not enforce, that an Technique (as defined by Organization 1) has a technique ID. SHACL validation handles enforcement."@en + ; + owl:onProperty ex2:techniqueID ; + owl:cardinality "1"^^xsd:nonNegativeInteger ; + ] + ; + rdfs:comment + "(Technical demonstration: Technique is subclassed.)"@en , + "A Technique in Organization 1 is a member of Organization 1's Framework, indexed with a technique ID."@en + ; + . + +ex1:Technique-T0001 + a + ex1:Technique , + owl:Class + ; + rdfs:subClassOf + uco-action:Action , + [ + a owl:Restriction ; + rdfs:comment "This Restriction states, but does not enforce, that execution of this AdaptedTechnique involves some Y-Device as action-input. SHACL validation handles enforcement."@en ; + owl:onProperty uco-action:object ; + owl:someValuesFrom ex1:YDevice ; + ] + ; + rdfs:comment + "(Technical demonstration: Technique-subclass is instantiated.)"@en , + "A technique where X is done to a Y-device."@en + ; + ex1:techniqueID "T0001" ; + . + +ex1:Technique-T0002 + a + ex1:Technique , + owl:Class + ; + rdfs:subClassOf ex1:Technique-T0001 ; + rdfs:comment + "(Technical demonstration: Technique-subclass is instantiated, specializing another instance of the same Technique-subclass.)"@en , + "A technique where X is done more thoroughly to a Y-device."@en + ; + ex1:techniqueID "T0001" ; + . + +ex1:YDevice + a owl:Class ; + rdfs:subClassOf uco-observable:Device ; + . + +ex1:techniqueID + a owl:DatatypeProperty ; + rdfs:subPropertyOf uco-action:techniqueID ; + rdfs:domain ex1:Technique ; + rdfs:range xsd:string ; + . + +ex2:AT-0001 + a + ex2:AdaptedTechnique , + owl:Class + ; + rdfs:subClassOf uco-action:Action ; + rdfs:comment + "(Technical demonstration: A Technique-subclass instance that directly specializes uco-action:Action.)"@en , + "A procedure where logging is configured to store data in an instance of Example-L Logging Service."@en + ; + ex2:techniqueID "AT-0001" ; + . + +ex2:AT-0099 + a + ex2:AdaptedTechnique , + owl:Class + ; + rdfs:subClassOf + ex1:Technique-T0001 , + [ + a owl:Restriction ; + rdfs:comment "This Restriction states, but does not enforce, that execution of this AdaptedTechnique involves some Z-Device as action-instrument. SHACL validation handles enforcement."@en ; + owl:onProperty uco-action:instrument ; + owl:someValuesFrom ex2:ZDevice ; + ] + ; + rdfs:comment + "(Technical demonstration: Technique-subclass is instantiated, specializing an instance of a different Technique-subclass. Note that the class ex2:AT-0099 is not required to be assigned a ex1:techniqueID, nor to be typed as a ex1:Technique or uco-action:Technique.)"@en , + "A procedure where X is done to a Y-device using a Z-device."@en + ; + ex2:techniqueID "AT-0099" ; + . + +ex2:AdaptedTechnique + a owl:Class ; + rdfs:subClassOf + uco-action:Technique , + [ + a owl:Restriction ; + rdfs:comment + "(Technical demonstration: Instances of the metaclass can have a datatype property assigned.)"@en , + "This Restriction states, but does not enforce, that an AdaptedTechnique has an Organization 2 techniqueID. SHACL validation handles enforcement."@en + ; + owl:onProperty ex2:techniqueID ; + owl:cardinality "1"^^xsd:nonNegativeInteger ; + ] + ; + rdfs:comment + "(Technical demonstration: Technique is subclassed, again.)"@en , + "A Standard Operating Procedure in Organization 2 is a Technique in Organization 2's operations manual, indexed with a procedure ID."@en + ; + . + +ex2:ZDevice + a owl:Class ; + rdfs:subClassOf uco-observable:Device ; + . + +ex2:techniqueID + a owl:DatatypeProperty ; + rdfs:subPropertyOf uco-action:techniqueID ; + rdfs:comment "(Technical demonstration: Assignment of a Technique identifier is done with an OWL Datatype Property.)"@en ; + rdfs:domain ex2:AdaptedTechnique ; + rdfs:range xsd:string ; + . + +ex0:Technique-A + a + owl:Class , + uco-action:Technique + ; + rdfs:subClassOf uco-action:Action ; + rdfs:comment "(Technical demonstration: Technique is instantiated.)"@en ; + . + diff --git a/tests/examples/technique/technique_ontology_XFAIL.ttl b/tests/examples/technique/technique_ontology_XFAIL.ttl new file mode 100644 index 00000000..7ff9faef --- /dev/null +++ b/tests/examples/technique/technique_ontology_XFAIL.ttl @@ -0,0 +1,121 @@ +@prefix ex0: . +@prefix ex1: . +@prefix ex2: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix uco-action: . +@prefix uco-core: . +@prefix uco-observable: . +@prefix xsd: . + +ex1:Technique + a owl:Class ; + rdfs:subClassOf + uco-action:Technique , + [ + a owl:Restriction ; + owl:onProperty ex2:techniqueID ; + owl:cardinality "1"^^xsd:nonNegativeInteger ; + ] + ; + rdfs:comment "(No difference from ex1:Technique in PASS graph.)"@en ; + . + +ex1:Technique-T0003 + a + ex1:Technique , + owl:Class + ; + rdfs:subClassOf uco-action:Action ; + rdfs:comment "(Technical demonstration: Technique XFAILS due to techniqueID absence.)"@en ; + . + +ex1:techniqueID + a owl:DatatypeProperty ; + rdfs:subPropertyOf uco-action:techniqueID ; + rdfs:comment "(No difference from ex1:techniqueID in PASS graph.)"@en ; + rdfs:domain ex1:Technique ; + rdfs:range xsd:string ; + . + +ex2:AT-0033 + a + ex2:AdaptedTechnique , + owl:Class + ; + rdfs:subClassOf uco-action:Action ; + rdfs:comment "(Technical demonstration: Technique XFAILs due to techniqueID absence."@en ; + . + +ex2:AT-0044 + a + ex2:AdaptedTechnique , + owl:Class + ; + rdfs:subClassOf ex1:Technique-T0003 ; + rdfs:comment "(Technical demonstration: Technique XFAILs due to techniqueID absence. Subclassing a ex1:Technique has no influence."@en ; + . + +ex2:AT-0055 + a + ex2:AdaptedTechnique , + owl:Class + ; + rdfs:subClassOf uco-action:Action ; + rdfs:comment "(Technical demonstration: Technique XFAILs due to techniqueID incorrect node-kind.)"@en ; + ex2:techniqueAltID ex2:P-5555 ; + ex2:techniqueID "AT-0055" ; + . + +ex2:AdaptedTechnique + a owl:Class ; + rdfs:subClassOf + uco-action:Technique , + [ + a owl:Restriction ; + owl:onProperty ex2:techniqueID ; + owl:cardinality "1"^^xsd:nonNegativeInteger ; + ] + ; + rdfs:comment "(No difference from ex2:AdaptedTechnique in PASS graph.)"@en ; + . + +ex2:techniqueAltID + a owl:ObjectProperty ; + rdfs:subPropertyOf uco-action:techniqueID ; + rdfs:comment "(Technical demonstration: Assignment of a Technique identifier must be done with an OWL Datatype Property. RDFS or OWL-RL inferencing enables detecting this modeling error.)"@en ; + rdfs:domain ex2:AdaptedTechnique ; + . + +ex2:techniqueID + a owl:DatatypeProperty ; + rdfs:subPropertyOf uco-action:techniqueID ; + rdfs:comment + "(No difference from ex2:techniqueID in PASS graph.)"@en , + "(Technical demonstration: Assignment of a Technique identifier is done with an OWL datatype Property.)"@en + ; + rdfs:domain ex2:AdaptedTechnique ; + rdfs:range xsd:string ; + . + +ex0:Technique-B + a + owl:Class , + uco-action:Technique + ; + rdfs:comment + "(Technical demonstration: Technique XFAILs due to not specializing uco-action:Action.)"@en , + "(Technical demonstration: Technique XFAILs due to not specializing uco-core:UcoThing.)"@en + ; + . + +ex0:Technique-C + a + owl:Class , + uco-action:Technique + ; + rdfs:subClassOf uco-core:UcoObject ; + rdfs:comment "(Technical demonstration: Technique XFAILs due to not specializing uco-action:Action.)"@en ; + . + diff --git a/tests/examples/technique/technique_ontology_XFAIL_owlrl_validation.ttl b/tests/examples/technique/technique_ontology_XFAIL_owlrl_validation.ttl new file mode 100644 index 00000000..09d7d9ef --- /dev/null +++ b/tests/examples/technique/technique_ontology_XFAIL_owlrl_validation.ttl @@ -0,0 +1,123 @@ +@prefix core: . +@prefix ex1: . +@prefix ex2: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix uco-action: . +@prefix xsd: . + +[] + a sh:ValidationReport ; + sh:conforms "false"^^xsd:boolean ; + sh:result + [ + a sh:ValidationResult ; + sh:focusNode ex1:Technique-T0003 ; + sh:resultMessage "Less than 1 values on ex1:Technique-T0003->ex1:techniqueID" ; + sh:resultPath ex1:techniqueID ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:MinCountConstraintComponent ; + sh:sourceShape [ + rdfs:comment "This property shape enforces that an instance of an Organization 1 Technique has techniqueID assigned. (Recall that an instance of ex1:Technique is an OWL Class.)"@en ; + sh:maxCount "1"^^xsd:integer ; + sh:minCount "1"^^xsd:integer ; + sh:path ex1:techniqueID ; + ] ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode ex2:AT-0033 ; + sh:resultMessage "Less than 1 values on ex2:AT-0033->ex2:techniqueID" ; + sh:resultPath ex2:techniqueID ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:MinCountConstraintComponent ; + sh:sourceShape [ + rdfs:comment "This property shape enforces that an instance of an Organization 2 AdaptedTechnique has Organization 2's techniqueID assigned. (Recall that an instance of ex2:AdaptedTechnique is an OWL Class.)"@en ; + sh:maxCount "1"^^xsd:integer ; + sh:minCount "1"^^xsd:integer ; + sh:path ex2:techniqueID ; + ] ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode ex2:AT-0044 ; + sh:resultMessage "Less than 1 values on ex2:AT-0044->ex2:techniqueID" ; + sh:resultPath ex2:techniqueID ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:MinCountConstraintComponent ; + sh:sourceShape [ + rdfs:comment "This property shape enforces that an instance of an Organization 2 AdaptedTechnique has Organization 2's techniqueID assigned. (Recall that an instance of ex2:AdaptedTechnique is an OWL Class.)"@en ; + sh:maxCount "1"^^xsd:integer ; + sh:minCount "1"^^xsd:integer ; + sh:path ex2:techniqueID ; + ] ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode ex2:AT-0055 ; + sh:resultMessage "Value is not of Node Kind sh:Literal" ; + sh:resultPath uco-action:techniqueID ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:NodeKindConstraintComponent ; + sh:sourceShape [ + rdfs:comment "This shape will find violations after RDFS or OWL-RL inferencing, but might not find some violations without inferencing."@en ; + sh:nodeKind sh:Literal ; + sh:path uco-action:techniqueID ; + ] ; + sh:value ex2:P-5555 ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode ; + sh:resultMessage "Node ex0:Technique-B->[ sh:oneOrMorePath rdfs:subClassOf ] does not contain a value in the set: ['uco-action:Action']" ; + sh:resultPath [ + sh:oneOrMorePath rdfs:subClassOf ; + ] ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:HasValueConstraintComponent ; + sh:sourceShape [ + rdfs:comment "This shape confirms a Technique is an eventual subclass of Action. The Action class itself is not a Technique."@en ; + sh:hasValue uco-action:Action ; + sh:path [ + sh:oneOrMorePath rdfs:subClassOf ; + ] ; + ] ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode ; + sh:resultMessage "Node ex0:Technique-B->[ sh:zeroOrMorePath rdfs:subClassOf ] does not contain a value in the set: ['core:UcoThing']" ; + sh:resultPath [ + sh:zeroOrMorePath rdfs:subClassOf ; + ] ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:HasValueConstraintComponent ; + sh:sourceShape [ + sh:hasValue core:UcoThing ; + sh:path [ + sh:zeroOrMorePath rdfs:subClassOf ; + ] ; + ] ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode ; + sh:resultMessage "Node ex0:Technique-C->[ sh:oneOrMorePath rdfs:subClassOf ] does not contain a value in the set: ['uco-action:Action']" ; + sh:resultPath [ + sh:oneOrMorePath rdfs:subClassOf ; + ] ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:HasValueConstraintComponent ; + sh:sourceShape [ + rdfs:comment "This shape confirms a Technique is an eventual subclass of Action. The Action class itself is not a Technique."@en ; + sh:hasValue uco-action:Action ; + sh:path [ + sh:oneOrMorePath rdfs:subClassOf ; + ] ; + ] ; + ] + ; + . + diff --git a/tests/examples/technique/technique_ontology_XFAIL_rdfs_validation.ttl b/tests/examples/technique/technique_ontology_XFAIL_rdfs_validation.ttl new file mode 100644 index 00000000..09d7d9ef --- /dev/null +++ b/tests/examples/technique/technique_ontology_XFAIL_rdfs_validation.ttl @@ -0,0 +1,123 @@ +@prefix core: . +@prefix ex1: . +@prefix ex2: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix uco-action: . +@prefix xsd: . + +[] + a sh:ValidationReport ; + sh:conforms "false"^^xsd:boolean ; + sh:result + [ + a sh:ValidationResult ; + sh:focusNode ex1:Technique-T0003 ; + sh:resultMessage "Less than 1 values on ex1:Technique-T0003->ex1:techniqueID" ; + sh:resultPath ex1:techniqueID ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:MinCountConstraintComponent ; + sh:sourceShape [ + rdfs:comment "This property shape enforces that an instance of an Organization 1 Technique has techniqueID assigned. (Recall that an instance of ex1:Technique is an OWL Class.)"@en ; + sh:maxCount "1"^^xsd:integer ; + sh:minCount "1"^^xsd:integer ; + sh:path ex1:techniqueID ; + ] ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode ex2:AT-0033 ; + sh:resultMessage "Less than 1 values on ex2:AT-0033->ex2:techniqueID" ; + sh:resultPath ex2:techniqueID ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:MinCountConstraintComponent ; + sh:sourceShape [ + rdfs:comment "This property shape enforces that an instance of an Organization 2 AdaptedTechnique has Organization 2's techniqueID assigned. (Recall that an instance of ex2:AdaptedTechnique is an OWL Class.)"@en ; + sh:maxCount "1"^^xsd:integer ; + sh:minCount "1"^^xsd:integer ; + sh:path ex2:techniqueID ; + ] ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode ex2:AT-0044 ; + sh:resultMessage "Less than 1 values on ex2:AT-0044->ex2:techniqueID" ; + sh:resultPath ex2:techniqueID ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:MinCountConstraintComponent ; + sh:sourceShape [ + rdfs:comment "This property shape enforces that an instance of an Organization 2 AdaptedTechnique has Organization 2's techniqueID assigned. (Recall that an instance of ex2:AdaptedTechnique is an OWL Class.)"@en ; + sh:maxCount "1"^^xsd:integer ; + sh:minCount "1"^^xsd:integer ; + sh:path ex2:techniqueID ; + ] ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode ex2:AT-0055 ; + sh:resultMessage "Value is not of Node Kind sh:Literal" ; + sh:resultPath uco-action:techniqueID ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:NodeKindConstraintComponent ; + sh:sourceShape [ + rdfs:comment "This shape will find violations after RDFS or OWL-RL inferencing, but might not find some violations without inferencing."@en ; + sh:nodeKind sh:Literal ; + sh:path uco-action:techniqueID ; + ] ; + sh:value ex2:P-5555 ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode ; + sh:resultMessage "Node ex0:Technique-B->[ sh:oneOrMorePath rdfs:subClassOf ] does not contain a value in the set: ['uco-action:Action']" ; + sh:resultPath [ + sh:oneOrMorePath rdfs:subClassOf ; + ] ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:HasValueConstraintComponent ; + sh:sourceShape [ + rdfs:comment "This shape confirms a Technique is an eventual subclass of Action. The Action class itself is not a Technique."@en ; + sh:hasValue uco-action:Action ; + sh:path [ + sh:oneOrMorePath rdfs:subClassOf ; + ] ; + ] ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode ; + sh:resultMessage "Node ex0:Technique-B->[ sh:zeroOrMorePath rdfs:subClassOf ] does not contain a value in the set: ['core:UcoThing']" ; + sh:resultPath [ + sh:zeroOrMorePath rdfs:subClassOf ; + ] ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:HasValueConstraintComponent ; + sh:sourceShape [ + sh:hasValue core:UcoThing ; + sh:path [ + sh:zeroOrMorePath rdfs:subClassOf ; + ] ; + ] ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode ; + sh:resultMessage "Node ex0:Technique-C->[ sh:oneOrMorePath rdfs:subClassOf ] does not contain a value in the set: ['uco-action:Action']" ; + sh:resultPath [ + sh:oneOrMorePath rdfs:subClassOf ; + ] ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:HasValueConstraintComponent ; + sh:sourceShape [ + rdfs:comment "This shape confirms a Technique is an eventual subclass of Action. The Action class itself is not a Technique."@en ; + sh:hasValue uco-action:Action ; + sh:path [ + sh:oneOrMorePath rdfs:subClassOf ; + ] ; + ] ; + ] + ; + . + diff --git a/tests/examples/technique/technique_ontology_XFAIL_validation.ttl b/tests/examples/technique/technique_ontology_XFAIL_validation.ttl new file mode 100644 index 00000000..1bfca560 --- /dev/null +++ b/tests/examples/technique/technique_ontology_XFAIL_validation.ttl @@ -0,0 +1,109 @@ +@prefix core: . +@prefix ex1: . +@prefix ex2: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix uco-action: . +@prefix xsd: . + +[] + a sh:ValidationReport ; + sh:conforms "false"^^xsd:boolean ; + sh:result + [ + a sh:ValidationResult ; + sh:focusNode ex1:Technique-T0003 ; + sh:resultMessage "Less than 1 values on ex1:Technique-T0003->ex1:techniqueID" ; + sh:resultPath ex1:techniqueID ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:MinCountConstraintComponent ; + sh:sourceShape [ + rdfs:comment "This property shape enforces that an instance of an Organization 1 Technique has techniqueID assigned. (Recall that an instance of ex1:Technique is an OWL Class.)"@en ; + sh:maxCount "1"^^xsd:integer ; + sh:minCount "1"^^xsd:integer ; + sh:path ex1:techniqueID ; + ] ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode ex2:AT-0033 ; + sh:resultMessage "Less than 1 values on ex2:AT-0033->ex2:techniqueID" ; + sh:resultPath ex2:techniqueID ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:MinCountConstraintComponent ; + sh:sourceShape [ + rdfs:comment "This property shape enforces that an instance of an Organization 2 AdaptedTechnique has Organization 2's techniqueID assigned. (Recall that an instance of ex2:AdaptedTechnique is an OWL Class.)"@en ; + sh:maxCount "1"^^xsd:integer ; + sh:minCount "1"^^xsd:integer ; + sh:path ex2:techniqueID ; + ] ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode ex2:AT-0044 ; + sh:resultMessage "Less than 1 values on ex2:AT-0044->ex2:techniqueID" ; + sh:resultPath ex2:techniqueID ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:MinCountConstraintComponent ; + sh:sourceShape [ + rdfs:comment "This property shape enforces that an instance of an Organization 2 AdaptedTechnique has Organization 2's techniqueID assigned. (Recall that an instance of ex2:AdaptedTechnique is an OWL Class.)"@en ; + sh:maxCount "1"^^xsd:integer ; + sh:minCount "1"^^xsd:integer ; + sh:path ex2:techniqueID ; + ] ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode ; + sh:resultMessage "Node ex0:Technique-B->[ sh:oneOrMorePath rdfs:subClassOf ] does not contain a value in the set: ['uco-action:Action']" ; + sh:resultPath [ + sh:oneOrMorePath rdfs:subClassOf ; + ] ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:HasValueConstraintComponent ; + sh:sourceShape [ + rdfs:comment "This shape confirms a Technique is an eventual subclass of Action. The Action class itself is not a Technique."@en ; + sh:hasValue uco-action:Action ; + sh:path [ + sh:oneOrMorePath rdfs:subClassOf ; + ] ; + ] ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode ; + sh:resultMessage "Node ex0:Technique-B->[ sh:zeroOrMorePath rdfs:subClassOf ] does not contain a value in the set: ['core:UcoThing']" ; + sh:resultPath [ + sh:zeroOrMorePath rdfs:subClassOf ; + ] ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:HasValueConstraintComponent ; + sh:sourceShape [ + sh:hasValue core:UcoThing ; + sh:path [ + sh:zeroOrMorePath rdfs:subClassOf ; + ] ; + ] ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode ; + sh:resultMessage "Node ex0:Technique-C->[ sh:oneOrMorePath rdfs:subClassOf ] does not contain a value in the set: ['uco-action:Action']" ; + sh:resultPath [ + sh:oneOrMorePath rdfs:subClassOf ; + ] ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:HasValueConstraintComponent ; + sh:sourceShape [ + rdfs:comment "This shape confirms a Technique is an eventual subclass of Action. The Action class itself is not a Technique."@en ; + sh:hasValue uco-action:Action ; + sh:path [ + sh:oneOrMorePath rdfs:subClassOf ; + ] ; + ] ; + ] + ; + . + diff --git a/tests/examples/technique/technique_shapes_PASS.ttl b/tests/examples/technique/technique_shapes_PASS.ttl new file mode 100644 index 00000000..023b61f1 --- /dev/null +++ b/tests/examples/technique/technique_shapes_PASS.ttl @@ -0,0 +1,59 @@ +@prefix ex1: . +@prefix ex2: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix sh-ex1: . +@prefix sh-ex2: . +@prefix uco-action: . +@prefix xsd: . + +sh-ex1:Technique-T0001-shape + a sh:NodeShape ; + sh:property [ + rdfs:comment "This property shape enforces that execution of this Technique involves some Y-device as action-input."@en ; + sh:path uco-action:object ; + sh:qualifiedMinCount "1"^^xsd:integer ; + sh:qualifiedValueShape [ + sh:class ex1:YDevice ; + ] ; + ] ; + sh:targetClass ex1:Technique-T0001 ; + . + +sh-ex1:Technique-shape + a sh:NodeShape ; + sh:property [ + rdfs:comment "This property shape enforces that an instance of an Organization 1 Technique has techniqueID assigned. (Recall that an instance of ex1:Technique is an OWL Class.)"@en ; + sh:maxCount "1"^^xsd:integer ; + sh:minCount "1"^^xsd:integer ; + sh:path ex1:techniqueID ; + ] ; + sh:targetClass ex1:Technique ; + . + +sh-ex2:AT-0099-shape + a sh:NodeShape ; + sh:property [ + rdfs:comment "This property shape enforces that execution of this AdaptedTechnique involves some Z-device as action-instrument."@en ; + sh:path uco-action:instrument ; + sh:qualifiedMinCount "1"^^xsd:integer ; + sh:qualifiedValueShape [ + sh:class ex2:ZDevice ; + ] ; + ] ; + sh:targetClass ex2:AT-0099 ; + . + +sh-ex2:AdaptedTechnique-shape + a sh:NodeShape ; + sh:property [ + rdfs:comment "This property shape enforces that an instance of an Organization 2 AdaptedTechnique has Organization 2's techniqueID assigned. (Recall that an instance of ex2:AdaptedTechnique is an OWL Class.)"@en ; + sh:maxCount "1"^^xsd:integer ; + sh:minCount "1"^^xsd:integer ; + sh:path ex2:techniqueID ; + ] ; + sh:targetClass ex2:AdaptedTechnique ; + . + diff --git a/tests/examples/test_validation.py b/tests/examples/test_validation.py index b8f051e0..9273cef0 100644 --- a/tests/examples/test_validation.py +++ b/tests/examples/test_validation.py @@ -619,3 +619,17 @@ def uco_thing_XFAIL_validation() -> None: "uco_thing_XFAIL_validation.ttl", False, ) + +def uco_type_PASS_validation() -> None: + confirm_validation_results( + "uco_type_PASS_validation.ttl", + expected_focus_node_severities={ + "http://example.org/kb/Thing-1", str(NS_SH.Info) + } + ) + +def uco_type_XFAIL_validation() -> None: + confirm_validation_results( + "uco_type_XFAIL_validation.ttl", + False, + ) diff --git a/tests/examples/uco_type_PASS.json b/tests/examples/uco_type_PASS.json new file mode 100644 index 00000000..a6970b72 --- /dev/null +++ b/tests/examples/uco_type_PASS.json @@ -0,0 +1,29 @@ +{ + "@context": { + "core": "https://ontology.unifiedcyberontology.org/uco/core/", + "kb": "http://example.org/kb/", + "owl": "http://www.w3.org/2002/07/owl#", + "rdfs": "http://www.w3.org/2000/01/rdf-schema#" + }, + "@graph": [ + { + "@id": "kb:UcoType-1", + "@type": [ + "owl:Class", + "core:UcoType" + ], + "rdfs:subClassOf": { + "@id": "core:UcoThing" + } + }, + { + "@id": "kb:Thing-1", + "@type": "kb:UcoType-1", + "rdfs:comment": "Triggers Info-severity violation of IRI not ending with UUID." + }, + { + "@id": "kb:Thing-dec9123e-9e4a-4bd3-bd1a-d7a3834c7340", + "@type": "kb:UcoType-1" + } + ] +} diff --git a/tests/examples/uco_type_PASS_validation.ttl b/tests/examples/uco_type_PASS_validation.ttl new file mode 100644 index 00000000..66d5c3d2 --- /dev/null +++ b/tests/examples/uco_type_PASS_validation.ttl @@ -0,0 +1,41 @@ +@prefix core: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix xsd: . + +[] + a sh:ValidationReport ; + sh:conforms "true"^^xsd:boolean ; + sh:result [ + a sh:ValidationResult ; + sh:focusNode ; + sh:resultMessage "UcoThings are suggested to end with a UUID." ; + sh:resultSeverity sh:Info ; + sh:sourceConstraint [ + a sh:SPARQLConstraint ; + rdfs:seeAlso ; + sh:message "UcoThings are suggested to end with a UUID."@en ; + sh:select ''' + PREFIX rdfs: + PREFIX core: + SELECT $this + WHERE { + $this a/rdfs:subClassOf* core:UcoThing . + FILTER ( + ! REGEX ( + STR($this), + "[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[0-9a-f]{4}-[0-9a-f]{12}$", + "i" + ) + ) + } + ''' ; + ] ; + sh:sourceConstraintComponent sh:SPARQLConstraintComponent ; + sh:sourceShape core:UcoThing-identifier-regex-shape ; + sh:value ; + ] ; + . + diff --git a/tests/examples/uco_type_XFAIL.json b/tests/examples/uco_type_XFAIL.json new file mode 100644 index 00000000..eb16563d --- /dev/null +++ b/tests/examples/uco_type_XFAIL.json @@ -0,0 +1,42 @@ +{ + "@context": { + "action": "https://ontology.unifiedcyberontology.org/uco/action/", + "core": "https://ontology.unifiedcyberontology.org/uco/core/", + "kb": "http://example.org/kb/", + "owl": "http://www.w3.org/2002/07/owl#", + "rdfs": "http://www.w3.org/2000/01/rdf-schema#" + }, + "@graph": [ + { + "@id": "kb:Technique-4b05a7c7-fbb2-4731-8a84-9abe8c108a35", + "@type": [ + "owl:Class", + "action:Technique" + ], + "rdfs:comment": [ + "Triggers violation from not subclassing UcoThing.", + "Triggers violation from not subclassing Action." + ] + }, + { + "@id": "kb:Technique-db4c2ac7-0fa0-4f74-9058-242a40d71a63", + "@type": [ + "owl:Class", + "action:ActionPattern", + "action:Technique" + ], + "rdfs:comment": "Triggers violation from instantiating both UcoThing and UcoType.", + "rdfs:subClassOf": { + "@id": "action:Action" + } + }, + { + "@id": "kb:UcoType-0", + "@type": "core:UcoType", + "rdfs:comment": [ + "Triggers violation from not instantiating owl:Class.", + "Triggers violation from not subclassing UcoThing." + ] + } + ] +} diff --git a/tests/examples/uco_type_XFAIL_validation.ttl b/tests/examples/uco_type_XFAIL_validation.ttl new file mode 100644 index 00000000..cfbb2dc5 --- /dev/null +++ b/tests/examples/uco_type_XFAIL_validation.ttl @@ -0,0 +1,82 @@ +@prefix action: . +@prefix core: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix xsd: . + +[] + a sh:ValidationReport ; + sh:conforms "false"^^xsd:boolean ; + sh:result + [ + a sh:ValidationResult ; + sh:focusNode ; + sh:resultMessage "Node kb:Technique-4b05a7c7-fbb2-4731-8a84-9abe8c108a35->[ sh:oneOrMorePath rdfs:subClassOf ] does not contain a value in the set: ['action:Action']" ; + sh:resultPath [ + sh:oneOrMorePath rdfs:subClassOf ; + ] ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:HasValueConstraintComponent ; + sh:sourceShape [ + rdfs:comment "This shape confirms a Technique is an eventual subclass of Action. The Action class itself is not a Technique."@en ; + sh:hasValue action:Action ; + sh:path [ + sh:oneOrMorePath rdfs:subClassOf ; + ] ; + ] ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode ; + sh:resultMessage "Node kb:Technique-4b05a7c7-fbb2-4731-8a84-9abe8c108a35->[ sh:zeroOrMorePath rdfs:subClassOf ] does not contain a value in the set: ['core:UcoThing']" ; + sh:resultPath [ + sh:zeroOrMorePath rdfs:subClassOf ; + ] ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:HasValueConstraintComponent ; + sh:sourceShape [ + sh:hasValue core:UcoThing ; + sh:path [ + sh:zeroOrMorePath rdfs:subClassOf ; + ] ; + ] ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode ; + sh:resultMessage "core:UcoThing and core:UcoType are disjoint classes."@en ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:NotConstraintComponent ; + sh:sourceShape core:UcoThing-disjointWith-UcoType-shape ; + sh:value ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode ; + sh:resultMessage "Node kb:UcoType-0->[ sh:zeroOrMorePath rdfs:subClassOf ] does not contain a value in the set: ['core:UcoThing']" ; + sh:resultPath [ + sh:zeroOrMorePath rdfs:subClassOf ; + ] ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:HasValueConstraintComponent ; + sh:sourceShape [ + sh:hasValue core:UcoThing ; + sh:path [ + sh:zeroOrMorePath rdfs:subClassOf ; + ] ; + ] ; + ] , + [ + a sh:ValidationResult ; + sh:focusNode ; + sh:resultMessage "Value does not have class owl:Class" ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:ClassConstraintComponent ; + sh:sourceShape core:UcoType ; + sh:value ; + ] + ; + . + diff --git a/tests/test_uco_monolithic.py b/tests/test_uco_monolithic.py index 3503a35e..4795499d 100644 --- a/tests/test_uco_monolithic.py +++ b/tests/test_uco_monolithic.py @@ -271,11 +271,11 @@ def test_semi_open_vocabulary_owl_shacl_alignment(graph: Graph) -> None: raise -def test_only_one_uco_class_is_owl_thing_direct_subclass(graph: Graph) -> None: +def test_only_two_uco_classes_are_owl_thing_direct_subclass(graph: Graph) -> None: """ - UCO expects all classes defined in UCO namespaces (i.e. excluding the "import review" ontologies) are subclasses of core:UcoThing. Within OWL, absence of an rdfs:subClassOf statement implies being a subclass of owl:Thing. Review UCO for any accidental omission of rdfs:subClassOf. + UCO expects all classes defined in UCO namespaces (i.e. excluding the "import review" ontologies) are subclasses of core:UcoThing or core:UcoType. Within OWL, absence of an rdfs:subClassOf statement implies being a subclass of owl:Thing. Review UCO for any accidental omission of rdfs:subClassOf. """ - expected: Set[URIRef] = {NS_UCO_CORE.UcoThing} + expected: Set[URIRef] = {NS_UCO_CORE.UcoThing, NS_UCO_CORE.UcoType} computed: Set[URIRef] = set() # Create temporary graph where subClassOf statements for non-UCO classes are removed.