diff --git a/ontology/uco/core/core.ttl b/ontology/uco/core/core.ttl
index d2689b66..5ab836a7 100644
--- a/ontology/uco/core/core.ttl
+++ b/ontology/uco/core/core.ttl
@@ -1,8 +1,11 @@
+# imports: http://www.w3.org/TR/skos-reference/skos-owl1-dl.rdf
+
@prefix core: .
@prefix owl: .
@prefix rdf: .
@prefix rdfs: .
@prefix sh: .
+@prefix skos: .
@prefix types: .
@prefix xsd: .
@@ -10,6 +13,7 @@
a owl:Ontology ;
rdfs:label "uco-core"@en ;
rdfs:comment "This ontology defines classes and properties that are shared across the various UCO ontologies. At a high-level, the UCO core ontology provides base classes, relationship-oriented classes, content-aggregation classes, and shared classes."@en ;
+ owl:imports ;
.
core:Annotation
@@ -317,6 +321,13 @@ core:Relationship
sh:targetClass core:Relationship ;
.
+core:TaxonomicConcept
+ a owl:Class ;
+ rdfs:subClassOf skos:Concept ;
+ rdfs:label "TaxonomicConcept"@en ;
+ rdfs:comment "Taxonomic Concept is a mix-in class that enables UCO as an OWL ontology to use SKOS taxonomic individuals. [based on https://www.w3.org/2006/07/SWD/SKOS/skos-and-owl/master.html#Hybrids]"@en ;
+ .
+
core:UcoObject
a
owl:Class ,
diff --git a/ontology/uco/master/uco.ttl b/ontology/uco/master/uco.ttl
index c9d4397f..4a2cc753 100644
--- a/ontology/uco/master/uco.ttl
+++ b/ontology/uco/master/uco.ttl
@@ -1,3 +1,4 @@
+# imports: http://www.w3.org/TR/skos-reference/skos-owl1-dl.rdf
# imports: https://ontology.unifiedcyberontology.org/co
# imports: https://ontology.unifiedcyberontology.org/owl
# imports: https://ontology.unifiedcyberontology.org/uco/action
@@ -26,6 +27,7 @@
a owl:Ontology ;
rdfs:label "uco-master"@en ;
owl:imports
+ ,
,
,
,
diff --git a/ontology/uco/observable/observable.ttl b/ontology/uco/observable/observable.ttl
index 0c747c3e..ba344497 100644
--- a/ontology/uco/observable/observable.ttl
+++ b/ontology/uco/observable/observable.ttl
@@ -8,6 +8,7 @@
@prefix action: .
@prefix co: .
@prefix core: .
+@prefix dcterms: .
@prefix identity: .
@prefix location: .
@prefix observable: .
@@ -15,6 +16,7 @@
@prefix rdf: .
@prefix rdfs: .
@prefix sh: .
+@prefix skos: .
@prefix types: .
@prefix vocabulary: .
@prefix xsd: .
@@ -1749,6 +1751,11 @@ observable:ContentDataFacet
rdfs:label "ContentDataFacet"@en ;
rdfs:comment "A content data facet is a grouping of characteristics unique to a block of digital data."@en ;
sh:property
+ [
+ sh:class dcterms:FileFormat ;
+ sh:nodeKind sh:IRI ;
+ sh:path observable:mimeType ;
+ ] ,
[
sh:class observable:ObservableObject ;
sh:maxCount "1"^^xsd:integer ;
@@ -1796,11 +1803,6 @@ observable:ContentDataFacet
sh:nodeKind sh:Literal ;
sh:path observable:mimeClass ;
] ,
- [
- sh:datatype xsd:string ;
- sh:nodeKind sh:Literal ;
- sh:path observable:mimeType ;
- ] ,
[
sh:datatype vocabulary:EndiannessTypeVocab ;
sh:message "Value is outside the default vocabulary EndiannessTypeVocab." ;
@@ -10964,10 +10966,37 @@ observable:mimeClass
.
observable:mimeType
- a owl:DatatypeProperty ;
+ a owl:ObjectProperty ;
rdfs:label "mimeType"@en ;
- rdfs:comment "MIME type of the data. For example 'text/html' or 'audio/mp3'."@en ;
- rdfs:range xsd:string ;
+ rdfs:comment "MIME type of the data. The text form of '${type}/${subtype}' (for example, 'text/html' or 'audio/mp3') can be used to find a UCO-provisioned set of types from the UCO Media Types Taxonomy. For interoperability with non-UCO resources, dcterms:FileFormat is this property's required range. The more-specific UCO classes types:IANAMediaType or types:NonIANAMediaType should be used when available."@en ;
+ rdfs:range dcterms:FileFormat ;
+ rdfs:seeAlso
+ types:IANAMediaType ,
+ types:NonIANAMediaType ,
+
+ ;
+ .
+
+observable:mimeType-class-types-MIMEFormat
+ a sh:PropertyShape ;
+ rdfs:comment "This shape is given an IRI in order to facilitate deactivation on request."@en ;
+ rdfs:seeAlso sh:deactivated ;
+ sh:class types:MIMEFormat ;
+ sh:message "Value is not an instance of types:MIMEFormat or one of its subclasses. Please consider using a value having type types:IANAMediaType or types:NonIANAMediaType."@en ;
+ sh:path observable:mimeType ;
+ sh:severity sh:Info ;
+ sh:targetSubjectsOf observable:mimeType ;
+ .
+
+observable:mimeType-notation
+ a sh:PropertyShape ;
+ rdfs:comment "This shape is intended to be deactivated by using overriding shapes in the UCO Mime Taxonomy."@en ;
+ rdfs:seeAlso ;
+ sh:message "The used mimeType value is not a concept with a skos:notation. Some consumers of this data expect a string with the MIME 'type/subtype' format to be supplied with skos:notation. Please either add the skos:notation to your input graph or incorporate the UCO MIME Taxonomy."@en ;
+ sh:minCount "1"^^xsd:integer ;
+ sh:path skos:notation ;
+ sh:severity sh:Warning ;
+ sh:targetObjectsOf observable:mimeType ;
.
observable:minorImageVersion
diff --git a/ontology/uco/types/types.ttl b/ontology/uco/types/types.ttl
index 8bcc917c..83991e9c 100644
--- a/ontology/uco/types/types.ttl
+++ b/ontology/uco/types/types.ttl
@@ -4,6 +4,8 @@
@prefix co: .
@prefix core: .
+@prefix dcterms: .
+@prefix observable: .
@prefix owl: .
@prefix rdf: .
@prefix rdfs: .
@@ -22,6 +24,11 @@
;
.
+dcterms:FileFormat
+ a owl:Class ;
+ rdfs:comment "UCO extends dcterms:FileFormat to be an OWL Class in addition to its native definition of an RDF Class."@en ;
+ .
+
types:ControlledDictionary
a
owl:Class ,
@@ -167,16 +174,41 @@ types:Hash
sh:targetClass types:Hash ;
.
+types:IANAMediaType
+ a owl:Class ;
+ rdfs:subClassOf types:MIMEFormat ;
+ rdfs:label "IANAMediaType"@en ;
+ owl:disjointWith types:NonIANAMediaType ;
+ .
+
types:Identifier
a rdfs:Datatype ;
rdfs:comment "An identifier is a string conformant to the specified UUID-based format for UCO object identifiers."@en ;
.
+types:MIMEFormat
+ a owl:Class ;
+ rdfs:subClassOf
+ dcterms:FileFormat ,
+ core:TaxonomicConcept
+ ;
+ rdfs:label "MIMEFormat"@en ;
+ rdfs:comment "This class should be considered an intermediary, 'abstract' class, and should not have individuals defined that are not a member of one of its subclasses. This class has two purposes. First, to encode for interoperability with existing frameworks, without relying on RDFS inference, that a UCO MIMEFormat individual is both a SKOS Concept (via core:TaxonomicConcept) and Dublin Core Terms FileFormat. Second, to guarantee a concept to be used as a UCO MIME type has exactly one skos:notation. Note that strict SHACL enforcement of the skos:notation presence is not within the UCO Types ontology, but is instead a part of the shapes provided by the UCO MIME Taxonomy. The warning about skos:notation in the Observable namespace is deactivated on importing the taxonomy's shapes."@en ;
+ rdfs:seeAlso observable:mimeType-notation ;
+ .
+
types:NativeFormatString
a rdfs:Datatype ;
rdfs:comment "Specifies data in its native format of some external language. The data may be encoded in Base64 per [RFC4648]. Data encoded in Base64 must be denoted as such using the encoded property."@en ;
.
+types:NonIANAMediaType
+ a owl:Class ;
+ rdfs:subClassOf types:MIMEFormat ;
+ rdfs:label "NonIANAMediaType"@en ;
+ owl:disjointWith types:IANAMediaType ;
+ .
+
types:StructuredText
a rdfs:Datatype ;
rdfs:comment "Expresses string-based data in some information structuring format (e.g., HTML5)."@en ;
diff --git a/tests/examples/Makefile b/tests/examples/Makefile
index 2af81c99..9f052c82 100644
--- a/tests/examples/Makefile
+++ b/tests/examples/Makefile
@@ -29,6 +29,9 @@ all: \
location_XFAIL_validation.ttl \
message_thread_PASS_validation.ttl \
message_thread_XFAIL_validation.ttl \
+ mime_PASS_validation.ttl \
+ mime_XFAIL_validation.ttl \
+ mime_prefix_PASS_validation.ttl \
owl_axiom_PASS_validation.ttl \
owl_axiom_XFAIL_validation.ttl \
owl_properties_PASS_validation.ttl \
@@ -90,6 +93,9 @@ check: \
location_XFAIL_validation.ttl \
message_thread_PASS_validation.ttl \
message_thread_XFAIL_validation.ttl \
+ mime_PASS_validation.ttl \
+ mime_XFAIL_validation.ttl \
+ mime_prefix_PASS_validation.ttl \
owl_axiom_PASS_validation.ttl \
owl_axiom_XFAIL_validation.ttl \
owl_properties_PASS_validation.ttl \
diff --git a/tests/examples/mime_PASS.json b/tests/examples/mime_PASS.json
new file mode 100644
index 00000000..ad0fbcea
--- /dev/null
+++ b/tests/examples/mime_PASS.json
@@ -0,0 +1,152 @@
+{
+ "@context": {
+ "core": "https://ontology.unifiedcyberontology.org/uco/core/",
+ "dcterms": "http://purl.org/dc/terms/",
+ "kb": "http://example.org/kb/",
+ "observable": "https://ontology.unifiedcyberontology.org/uco/observable/",
+ "rdfs": "http://www.w3.org/2000/01/rdf-schema#",
+ "skos": "http://www.w3.org/2004/02/skos/core#",
+ "types": "https://ontology.unifiedcyberontology.org/uco/types/"
+ },
+ "@graph": [
+ {
+ "@id": "urn:example:mime:dcterms:application/gzip",
+ "@type": "dcterms:FileFormat",
+ "rdfs:comment": "This is a custom media type individual, designed for just this unit test. A larger taxonomy of individuals should be used outside of testing contexts.",
+ "skos:notation": "application/gzip"
+ },
+ {
+ "@id": "urn:example:mime:uco:application/gzip",
+ "@type": "types:IANAMediaType",
+ "rdfs:comment": "This is a custom media type individual, designed for just this unit test. A larger taxonomy of individuals should be used outside of testing contexts.",
+ "skos:exactMatch": {
+ "@id": "urn:example:mime:dcterms:application/gzip"
+ },
+ "skos:notation": "application/gzip"
+ },
+ {
+ "@id": "urn:example:mime:uco:application/tar",
+ "@type": "types:NonIANAMediaType",
+ "rdfs:comment": "This is a custom media type individual, designed for just this unit test. A larger taxonomy of individuals should be used outside of testing contexts.",
+ "skos:notation": "application/tar"
+ },
+ {
+ "@id": "urn:example:mime:uco:application/tar+gzip",
+ "@type": "types:NonIANAMediaType",
+ "rdfs:comment": "This is a custom media type individual, designed for just this unit test. A larger taxonomy of individuals should be used outside of testing contexts.",
+ "skos:broader": [
+ {
+ "@id": "urn:example:mime:uco:application/gzip"
+ },
+ {
+ "@id": "urn:example:mime:uco:application/tar"
+ }
+ ],
+ "skos:notation": "application/tar+gzip"
+ },
+ {
+ "@id": "urn:example:mime:uco:image/example.image.type.without.notation",
+ "@type": "types:NonIANAMediaType",
+ "rdfs:comment": "This is a custom media type individual, designed for just this unit test. A larger taxonomy of individuals should be used outside of testing contexts."
+ },
+ {
+ "@id": "kb:file-1",
+ "@type": "observable:File",
+ "core:hasFacet": [
+ {
+ "@type": "observable:ContentDataFacet",
+ "observable:mimeType": {
+ "@id": "urn:example:mime:dcterms:application/gzip"
+ }
+ },
+ {
+ "@type": "observable:FileFacet",
+ "observable:fileName": "1.gz"
+ }
+ ],
+ "rdfs:comment": "This file node should trigger an sh:Info-severity result."
+ },
+ {
+ "@id": "kb:file-2",
+ "@type": "observable:File",
+ "core:hasFacet": [
+ {
+ "@type": "observable:ContentDataFacet",
+ "observable:mimeType": {
+ "@id": "urn:example:mime:uco:application/gzip"
+ }
+ },
+ {
+ "@type": "observable:FileFacet",
+ "observable:fileName": "2.gz"
+ }
+ ]
+ },
+ {
+ "@id": "kb:file-3",
+ "@type": "observable:File",
+ "core:hasFacet": [
+ {
+ "@type": "observable:ContentDataFacet",
+ "observable:mimeType": {
+ "@id": "urn:example:mime:uco:application/tar"
+ }
+ },
+ {
+ "@type": "observable:FileFacet",
+ "observable:fileName": "3.tar"
+ }
+ ]
+ },
+ {
+ "@id": "kb:file-4",
+ "@type": "observable:File",
+ "core:hasFacet": [
+ {
+ "@type": "observable:ContentDataFacet",
+ "observable:mimeType": {
+ "@id": "urn:example:mime:uco:application/tar+gzip"
+ }
+ },
+ {
+ "@type": "observable:FileFacet",
+ "observable:fileName": "4.tar.gz"
+ }
+ ]
+ },
+ {
+ "@id": "kb:file-5",
+ "@type": "observable:File",
+ "core:hasFacet": [
+ {
+ "@type": "observable:ContentDataFacet",
+ "observable:mimeType": {
+ "@id": "urn:example:mime:uco:image/example.image.type.without.notation"
+ }
+ },
+ {
+ "@type": "observable:FileFacet",
+ "observable:fileName": "5.dat"
+ }
+ ],
+ "rdfs:comment": "This file node should trigger an sh:Warning-severity result."
+ },
+ {
+ "@id": "kb:file-6",
+ "@type": "observable:File",
+ "core:hasFacet": [
+ {
+ "@type": "observable:ContentDataFacet",
+ "observable:mimeType": {
+ "@id": "urn:example:mime:uco:image/example.image.type.without.notation"
+ }
+ },
+ {
+ "@type": "observable:FileFacet",
+ "observable:fileName": "6.dat"
+ }
+ ],
+ "rdfs:comment": "This file node should trigger an sh:Warning-severity result."
+ }
+ ]
+}
diff --git a/tests/examples/mime_PASS_validation.ttl b/tests/examples/mime_PASS_validation.ttl
new file mode 100644
index 00000000..98fae107
--- /dev/null
+++ b/tests/examples/mime_PASS_validation.ttl
@@ -0,0 +1,37 @@
+@prefix observable: .
+@prefix owl: .
+@prefix rdf: .
+@prefix rdfs: .
+@prefix sh: .
+@prefix skos: .
+@prefix xsd: .
+
+[]
+ a sh:ValidationReport ;
+ sh:conforms "true"^^xsd:boolean ;
+ sh:result
+ [
+ a sh:ValidationResult ;
+ sh:focusNode ;
+ sh:resultMessage "The used mimeType value is not a concept with a skos:notation. Some consumers of this data expect a string with the MIME 'type/subtype' format to be supplied with skos:notation. Please either add the skos:notation to your input graph or incorporate the UCO MIME Taxonomy."@en ;
+ sh:resultPath skos:notation ;
+ sh:resultSeverity sh:Warning ;
+ sh:sourceConstraintComponent sh:MinCountConstraintComponent ;
+ sh:sourceShape observable:mimeType-notation ;
+ ] ,
+ [
+ a sh:ValidationResult ;
+ sh:focusNode [
+ a observable:ContentDataFacet ;
+ observable:mimeType ;
+ ] ;
+ sh:resultMessage "Value is not an instance of types:MIMEFormat or one of its subclasses. Please consider using a value having type types:IANAMediaType or types:NonIANAMediaType."@en ;
+ sh:resultPath observable:mimeType ;
+ sh:resultSeverity sh:Info ;
+ sh:sourceConstraintComponent sh:ClassConstraintComponent ;
+ sh:sourceShape observable:mimeType-class-types-MIMEFormat ;
+ sh:value ;
+ ]
+ ;
+ .
+
diff --git a/tests/examples/mime_XFAIL.json b/tests/examples/mime_XFAIL.json
new file mode 100644
index 00000000..6f86ea64
--- /dev/null
+++ b/tests/examples/mime_XFAIL.json
@@ -0,0 +1,28 @@
+{
+ "@context": {
+ "core": "https://ontology.unifiedcyberontology.org/uco/core/",
+ "dcterms": "http://purl.org/dc/terms/",
+ "kb": "http://example.org/kb/",
+ "observable": "https://ontology.unifiedcyberontology.org/uco/observable/",
+ "rdfs": "http://www.w3.org/2000/01/rdf-schema#",
+ "skos": "http://www.w3.org/2004/02/skos/core#",
+ "types": "https://ontology.unifiedcyberontology.org/uco/types/"
+ },
+ "@graph": [
+ {
+ "@id": "kb:file-7",
+ "@type": "observable:File",
+ "core:hasFacet": [
+ {
+ "@type": "observable:ContentDataFacet",
+ "observable:mimeType": "application/gzip"
+ },
+ {
+ "@type": "observable:FileFacet",
+ "observable:fileName": "7.gz"
+ }
+ ],
+ "rdfs:comment": "This file node errantly uses a literal instead of object reference."
+ }
+ ]
+}
diff --git a/tests/examples/mime_XFAIL_validation.ttl b/tests/examples/mime_XFAIL_validation.ttl
new file mode 100644
index 00000000..d4d56dcb
--- /dev/null
+++ b/tests/examples/mime_XFAIL_validation.ttl
@@ -0,0 +1,72 @@
+@prefix dcterms: .
+@prefix observable: .
+@prefix owl: .
+@prefix rdf: .
+@prefix rdfs: .
+@prefix sh: .
+@prefix skos: .
+@prefix xsd: .
+
+[]
+ a sh:ValidationReport ;
+ sh:conforms "false"^^xsd:boolean ;
+ sh:result
+ [
+ a sh:ValidationResult ;
+ sh:focusNode "application/gzip" ;
+ sh:resultMessage "The used mimeType value is not a concept with a skos:notation. Some consumers of this data expect a string with the MIME 'type/subtype' format to be supplied with skos:notation. Please either add the skos:notation to your input graph or incorporate the UCO MIME Taxonomy."@en ;
+ sh:resultPath skos:notation ;
+ sh:resultSeverity sh:Warning ;
+ sh:sourceConstraintComponent sh:MinCountConstraintComponent ;
+ sh:sourceShape observable:mimeType-notation ;
+ ] ,
+ [
+ a sh:ValidationResult ;
+ sh:focusNode [
+ a observable:ContentDataFacet ;
+ observable:mimeType "application/gzip" ;
+ ] ;
+ sh:resultMessage "Value does not have class dcterms:FileFormat" ;
+ sh:resultPath observable:mimeType ;
+ sh:resultSeverity sh:Violation ;
+ sh:sourceConstraintComponent sh:ClassConstraintComponent ;
+ sh:sourceShape [
+ sh:class dcterms:FileFormat ;
+ sh:nodeKind sh:IRI ;
+ sh:path observable:mimeType ;
+ ] ;
+ sh:value "application/gzip" ;
+ ] ,
+ [
+ a sh:ValidationResult ;
+ sh:focusNode [
+ a observable:ContentDataFacet ;
+ observable:mimeType "application/gzip" ;
+ ] ;
+ sh:resultMessage "Value is not an instance of types:MIMEFormat or one of its subclasses. Please consider using a value having type types:IANAMediaType or types:NonIANAMediaType."@en ;
+ sh:resultPath observable:mimeType ;
+ sh:resultSeverity sh:Info ;
+ sh:sourceConstraintComponent sh:ClassConstraintComponent ;
+ sh:sourceShape observable:mimeType-class-types-MIMEFormat ;
+ sh:value "application/gzip" ;
+ ] ,
+ [
+ a sh:ValidationResult ;
+ sh:focusNode [
+ a observable:ContentDataFacet ;
+ observable:mimeType "application/gzip" ;
+ ] ;
+ sh:resultMessage "Value is not of Node Kind sh:IRI" ;
+ sh:resultPath observable:mimeType ;
+ sh:resultSeverity sh:Violation ;
+ sh:sourceConstraintComponent sh:NodeKindConstraintComponent ;
+ sh:sourceShape [
+ sh:class dcterms:FileFormat ;
+ sh:nodeKind sh:IRI ;
+ sh:path observable:mimeType ;
+ ] ;
+ sh:value "application/gzip" ;
+ ]
+ ;
+ .
+
diff --git a/tests/examples/mime_prefix_PASS.json b/tests/examples/mime_prefix_PASS.json
new file mode 100644
index 00000000..047ba475
--- /dev/null
+++ b/tests/examples/mime_prefix_PASS.json
@@ -0,0 +1,36 @@
+{
+ "@context": {
+ "core": "https://ontology.unifiedcyberontology.org/uco/core/",
+ "ex-mime": "urn:example:mime:custom:",
+ "kb": "http://example.org/kb/",
+ "observable": "https://ontology.unifiedcyberontology.org/uco/observable/",
+ "observable:mimeType": {
+ "@type": "@id"
+ },
+ "rdfs": "http://www.w3.org/2000/01/rdf-schema#",
+ "skos": "http://www.w3.org/2004/02/skos/core#",
+ "types": "https://ontology.unifiedcyberontology.org/uco/types/"
+ },
+ "@graph": [
+ {
+ "@id": "ex-mime:application/gzip",
+ "@type": "types:IANAMediaType",
+ "rdfs:comment": "This is a custom media type individual, designed for just this unit test. A larger taxonomy of individuals should be used outside of testing contexts.",
+ "skos:notation": "application/gzip"
+ },
+ {
+ "@id": "kb:file-8",
+ "@type": "observable:File",
+ "core:hasFacet": [
+ {
+ "@type": "observable:ContentDataFacet",
+ "observable:mimeType": "ex-mime:application/gzip"
+ },
+ {
+ "@type": "observable:FileFacet",
+ "observable:fileName": "8.gz"
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/examples/mime_prefix_PASS_validation.ttl b/tests/examples/mime_prefix_PASS_validation.ttl
new file mode 100644
index 00000000..33496ff0
--- /dev/null
+++ b/tests/examples/mime_prefix_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/test_mime.py b/tests/examples/test_mime.py
new file mode 100644
index 00000000..822f5648
--- /dev/null
+++ b/tests/examples/test_mime.py
@@ -0,0 +1,98 @@
+#!/usr/bin/env python3
+
+# 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 and is in the public domain. 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.
+
+import typing
+
+import pytest
+import rdflib
+
+NS_UCO_CORE = rdflib.Namespace("https://ontology.unifiedcyberontology.org/uco/core/")
+NS_UCO_OBSERVABLE = rdflib.Namespace("https://ontology.unifiedcyberontology.org/uco/observable/")
+
+NSDICT = {
+ "core": NS_UCO_CORE,
+ "observable": NS_UCO_OBSERVABLE,
+ "skos": rdflib.SKOS
+}
+
+@pytest.fixture
+def mime_pass_graph() -> rdflib.Graph:
+ graph = rdflib.Graph()
+ graph.parse("mime_PASS.json", format="json-ld")
+ return graph
+
+
+def test_mime_file_names(mime_pass_graph: rdflib.Graph) -> None:
+ expected: typing.Set[str] = {
+ "1.gz",
+ "2.gz",
+ "3.tar",
+ "4.tar.gz",
+ "5.dat",
+ "6.dat",
+ }
+ computed: typing.Set[str] = set()
+
+ query = rdflib.plugins.sparql.prepareQuery("""\
+SELECT ?lFileName
+WHERE {
+ ?nFile core:hasFacet/observable:fileName ?lFileName .
+}
+""", initNs=NSDICT)
+ for result in mime_pass_graph.query(query):
+ computed.add(str(result[0]))
+ assert expected == computed
+
+
+def test_mime_gzip_files(mime_pass_graph: rdflib.Graph) -> None:
+ expected: typing.Set[str] = {
+ "1.gz",
+ "2.gz",
+ "4.tar.gz",
+ }
+ computed: typing.Set[str] = set()
+
+ query = rdflib.plugins.sparql.prepareQuery("""\
+SELECT ?lFileName
+WHERE {
+ ?nFile core:hasFacet/observable:fileName ?lFileName .
+ ?nFile core:hasFacet/observable:mimeType ?nMimeType .
+
+ ?nMimeType skos:exactMatch*/skos:broader*/skos:notation "application/gzip" .
+}
+""", initNs=NSDICT)
+ for result in mime_pass_graph.query(query):
+ computed.add(str(result[0]))
+ assert expected == computed
+
+
+
+def test_mime_tar_files(mime_pass_graph: rdflib.Graph) -> None:
+ expected: typing.Set[str] = {
+ "3.tar",
+ "4.tar.gz",
+ }
+ computed: typing.Set[str] = set()
+
+ query = rdflib.plugins.sparql.prepareQuery("""\
+SELECT ?lFileName
+WHERE {
+ ?nFile core:hasFacet/observable:fileName ?lFileName .
+ ?nFile core:hasFacet/observable:mimeType ?nMimeType .
+
+ ?nMimeType skos:exactMatch*/skos:broader*/skos:notation "application/tar" .
+}
+""", initNs=NSDICT)
+ for result in mime_pass_graph.query(query):
+ computed.add(str(result[0]))
+ assert expected == computed
diff --git a/tests/examples/test_validation.py b/tests/examples/test_validation.py
index 30addef8..b8e48922 100644
--- a/tests/examples/test_validation.py
+++ b/tests/examples/test_validation.py
@@ -30,10 +30,12 @@
NS_CO = rdflib.Namespace("http://purl.org/co/")
NS_SH = rdflib.SH
+NS_SKOS = rdflib.SKOS
NS_UCO_ACTION = rdflib.Namespace("https://ontology.unifiedcyberontology.org/uco/action/")
NS_UCO_CO = rdflib.Namespace("https://ontology.unifiedcyberontology.org/co/")
NS_UCO_CORE = rdflib.Namespace("https://ontology.unifiedcyberontology.org/uco/core/")
NS_UCO_LOCATION = rdflib.Namespace("https://ontology.unifiedcyberontology.org/uco/location/")
+NS_UCO_OBSERVABLE = rdflib.Namespace("https://ontology.unifiedcyberontology.org/uco/observable/")
NS_UCO_TYPES = rdflib.Namespace("https://ontology.unifiedcyberontology.org/uco/types/")
NSDICT = {"sh": NS_SH}
@@ -320,6 +322,33 @@ def test_message_thread_PASS_validation():
def test_message_thread_XFAIL_validation():
confirm_validation_results("message_thread_XFAIL_validation.ttl", False)
+def test_mime_PASS_validation() -> None:
+ confirm_validation_results(
+ "mime_PASS_validation.ttl",
+ True,
+ expected_result_paths={
+ str(NS_SKOS.notation),
+ str(NS_UCO_OBSERVABLE.mimeType)
+ }
+ )
+
+def test_mime_XFAIL_validation() -> None:
+ confirm_validation_results(
+ "mime_XFAIL_validation.ttl",
+ False,
+ expected_result_paths={
+ str(NS_SKOS.notation),
+ str(NS_UCO_OBSERVABLE.mimeType)
+ }
+ )
+
+def test_mime_prefix_PASS_validation() -> None:
+ confirm_validation_results(
+ "mime_prefix_PASS_validation.ttl",
+ True,
+ expected_focus_node_severities=set()
+ )
+
def test_owl_axiom_PASS() -> None:
confirm_validation_results(
"owl_axiom_PASS_validation.ttl",