From 8ca27948d921c8b84f143d449fe88f85d3017d06 Mon Sep 17 00:00:00 2001 From: Alex Nelson Date: Wed, 10 Nov 2021 14:31:18 -0500 Subject: [PATCH 01/10] Adjust formatting for existing arguments This is to prepare for a coming long-named flag specification. References: * [UCO OC-65] (CP-13) UCO needs subclasses of ObservableObject Signed-off-by: Alex Nelson --- case_utils/case_sparql_construct/__init__.py | 17 ++++++++++++++--- case_utils/case_sparql_select/__init__.py | 17 ++++++++++++++--- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/case_utils/case_sparql_construct/__init__.py b/case_utils/case_sparql_construct/__init__.py index f53df06..c119a0c 100644 --- a/case_utils/case_sparql_construct/__init__.py +++ b/case_utils/case_sparql_construct/__init__.py @@ -30,9 +30,20 @@ def main() -> None: parser = argparse.ArgumentParser() - parser.add_argument("-d", "--debug", action="store_true") - parser.add_argument("--disallow-empty-results", action="store_true", help="Raise error if no results are returned for query.") - parser.add_argument("--output-format", help="Override extension-based format guesser.") + parser.add_argument( + "-d", + "--debug", + action="store_true" + ) + parser.add_argument( + "--disallow-empty-results", + action="store_true", + help="Raise error if no results are returned for query." + ) + parser.add_argument( + "--output-format", + help="Override extension-based format guesser." + ) parser.add_argument("out_graph") parser.add_argument("in_sparql") parser.add_argument("in_graph", nargs="+") diff --git a/case_utils/case_sparql_select/__init__.py b/case_utils/case_sparql_select/__init__.py index 7bbb809..dc01f86 100644 --- a/case_utils/case_sparql_select/__init__.py +++ b/case_utils/case_sparql_select/__init__.py @@ -44,9 +44,20 @@ def main() -> None: parser = argparse.ArgumentParser() - parser.add_argument("-d", "--debug", action="store_true") - parser.add_argument("--disallow-empty-results", action="store_true", help="Raise error if no results are returned for query.") - parser.add_argument("out_table", help="Expected extensions are .html for HTML tables or .md for Markdown tables.") + parser.add_argument( + "-d", + "--debug", + action="store_true" + ) + parser.add_argument( + "--disallow-empty-results", + action="store_true", + help="Raise error if no results are returned for query." + ) + parser.add_argument( + "out_table", + help="Expected extensions are .html for HTML tables or .md for Markdown tables." + ) parser.add_argument("in_sparql") parser.add_argument("in_graph", nargs="+") args = parser.parse_args() From 9af628a47c101d628b04c8e6bef293c48bdf44cb Mon Sep 17 00:00:00 2001 From: Alex Nelson Date: Wed, 10 Nov 2021 14:35:44 -0500 Subject: [PATCH 02/10] Configure logging before argument parsing This is to prepare for a coming function lookup of built ontology versions to use. References: * [UCO OC-65] (CP-13) UCO needs subclasses of ObservableObject Signed-off-by: Alex Nelson --- case_utils/case_sparql_construct/__init__.py | 9 ++++++--- case_utils/case_sparql_select/__init__.py | 7 +++++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/case_utils/case_sparql_construct/__init__.py b/case_utils/case_sparql_construct/__init__.py index c119a0c..c129a6a 100644 --- a/case_utils/case_sparql_construct/__init__.py +++ b/case_utils/case_sparql_construct/__init__.py @@ -18,8 +18,9 @@ __version__ = "0.1.0" import argparse -import os import logging +import os +import sys import typing import rdflib.plugins.sparql # type: ignore @@ -30,6 +31,10 @@ def main() -> None: parser = argparse.ArgumentParser() + + # Configure debug logging before running parse_args, because there could be an error raised before the construction of the argument parser. + logging.basicConfig(level=logging.DEBUG if ("--debug" in sys.argv or "-d" in sys.argv) else logging.INFO) + parser.add_argument( "-d", "--debug", @@ -49,8 +54,6 @@ def main() -> None: parser.add_argument("in_graph", nargs="+") args = parser.parse_args() - logging.basicConfig(level=logging.DEBUG if args.debug else logging.INFO) - in_graph = rdflib.Graph() for in_graph_filename in args.in_graph: in_graph.parse(in_graph_filename) diff --git a/case_utils/case_sparql_select/__init__.py b/case_utils/case_sparql_select/__init__.py index dc01f86..f5b3862 100644 --- a/case_utils/case_sparql_select/__init__.py +++ b/case_utils/case_sparql_select/__init__.py @@ -32,6 +32,7 @@ import binascii import logging import os +import sys import pandas as pd # type: ignore import rdflib.plugins.sparql # type: ignore @@ -44,6 +45,10 @@ def main() -> None: parser = argparse.ArgumentParser() + + # Configure debug logging before running parse_args, because there could be an error raised before the construction of the argument parser. + logging.basicConfig(level=logging.DEBUG if ("--debug" in sys.argv or "-d" in sys.argv) else logging.INFO) + parser.add_argument( "-d", "--debug", @@ -62,8 +67,6 @@ def main() -> None: parser.add_argument("in_graph", nargs="+") args = parser.parse_args() - logging.basicConfig(level=logging.DEBUG if args.debug else logging.INFO) - graph = rdflib.Graph() for in_graph_filename in args.in_graph: graph.parse(in_graph_filename) From 16a5a2ba52b6317d346bd4d999ef0f8fec3f3da5 Mon Sep 17 00:00:00 2001 From: Alex Nelson Date: Wed, 10 Nov 2021 14:57:13 -0500 Subject: [PATCH 03/10] Build subclass hierarchy as additional static resource References: * [UCO OC-65] (CP-13) UCO needs subclasses of ObservableObject Signed-off-by: Alex Nelson --- Makefile | 2 + case_utils/ontology/Makefile | 34 +++++++++++++++- case_utils/ontology/src/README.md | 1 + case_utils/ontology/src/subclasses_ttl.py | 47 +++++++++++++++++++++++ 4 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 case_utils/ontology/src/README.md create mode 100644 case_utils/ontology/src/subclasses_ttl.py diff --git a/Makefile b/Makefile index fa526f6..aacc5ea 100644 --- a/Makefile +++ b/Makefile @@ -56,10 +56,12 @@ all: \ # Do not rebuild the current ontology file if it is already present. It is expected not to change once built. # touch -c: Do not create the file if it does not exist. This will convince the recursive make nothing needs to be done if the file is present. touch -c case_utils/ontology/case-$(case_version).ttl + touch -c case_utils/ontology/case-$(case_version)-subclasses.ttl $(MAKE) \ --directory case_utils/ontology # Confirm the current monolithic file is in place. test -r case_utils/ontology/case-$(case_version).ttl + test -r case_utils/ontology/case-$(case_version)-subclasses.ttl touch $@ check: \ diff --git a/case_utils/ontology/Makefile b/case_utils/ontology/Makefile index bd53acb..ab4e5db 100644 --- a/case_utils/ontology/Makefile +++ b/case_utils/ontology/Makefile @@ -24,6 +24,9 @@ RDF_TOOLKIT_JAR := $(case_srcdir)/lib/rdf-toolkit.jar case_version := $(shell python3 version_info.py) all: \ + case-$(case_version)-subclasses.ttl + +.PRECIOUS: \ case-$(case_version).ttl case-$(case_version).ttl: \ @@ -45,5 +48,34 @@ case-$(case_version).ttl: \ --target-format turtle mv _$@ $@ +case-$(case_version)-subclasses.ttl: \ + case-$(case_version).ttl \ + src/subclasses_ttl.py + # The CASE ontology test venv is made by the earlier build step + # of case_monolithic.ttl. However, unless a new ontology + # release is being made, that step will have been skipped. + # This recursive Make call guarantees the virtual environment is + # set up. + $(MAKE) \ + --directory $(case_srcdir)/tests \ + .venv.done.log + #TODO This cleanup step should be removed after the 0.3.0 release of CASE-Utility-SHACL-Inheritance-Reviewer. + test ! -d $(uco_srcdir)/dependencies/CASE-Utility-SHACL-Inheritance-Reviewer/build \ + || rm -rf \ + $(uco_srcdir)/dependencies/CASE-Utility-SHACL-Inheritance-Reviewer/build + source $(case_srcdir)/tests/venv/bin/activate \ + && python3 src/subclasses_ttl.py \ + __$@ \ + $< + java -jar $(RDF_TOOLKIT_JAR) \ + --inline-blank-nodes \ + --source __$@ \ + --source-format turtle \ + --target _$@ \ + --target-format turtle + rm __$@ + mv _$@ $@ + clean: - @rm -f case-$(case_version).ttl + @rm -f \ + case-$(case_version)*.ttl diff --git a/case_utils/ontology/src/README.md b/case_utils/ontology/src/README.md new file mode 100644 index 0000000..6068cc0 --- /dev/null +++ b/case_utils/ontology/src/README.md @@ -0,0 +1 @@ +This directory is not intended to be exported as part of the `case_utils` package. diff --git a/case_utils/ontology/src/subclasses_ttl.py b/case_utils/ontology/src/subclasses_ttl.py new file mode 100644 index 0000000..893d458 --- /dev/null +++ b/case_utils/ontology/src/subclasses_ttl.py @@ -0,0 +1,47 @@ +#!/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. + +""" +This script creates an excerpt of an ontology graph that consists solely of all rdfs:subClassOf statements. +""" + +__version__ = "0.1.0" + +import argparse + +import rdflib + +def main() -> None: + parser = argparse.ArgumentParser() + parser.add_argument("out_ttl") + parser.add_argument("in_ttl", nargs="+") + args = parser.parse_args() + + in_graph = rdflib.Graph() + out_graph = rdflib.Graph() + + in_ttl : str + for in_ttl in args.in_ttl: + in_graph.parse(in_ttl) + + for triple in in_graph.triples(( + None, + rdflib.RDFS.subClassOf, + None + )): + out_graph.add(triple) + + out_graph.serialize(args.out_ttl) + +if __name__ == "__main__": + main() From f4ec1751d04da79eb9d3f414dd937e62ef900815 Mon Sep 17 00:00:00 2001 From: Alex Nelson Date: Wed, 10 Nov 2021 15:04:52 -0500 Subject: [PATCH 04/10] Build case-0.5.0-subclasses.ttl References: * [UCO OC-65] (CP-13) UCO needs subclasses of ObservableObject Signed-off-by: Alex Nelson --- case_utils/ontology/case-0.5.0-subclasses.ttl | 1568 +++++++++++++++++ 1 file changed, 1568 insertions(+) create mode 100644 case_utils/ontology/case-0.5.0-subclasses.ttl diff --git a/case_utils/ontology/case-0.5.0-subclasses.ttl b/case_utils/ontology/case-0.5.0-subclasses.ttl new file mode 100644 index 0000000..15da4a3 --- /dev/null +++ b/case_utils/ontology/case-0.5.0-subclasses.ttl @@ -0,0 +1,1568 @@ +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix xs: . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf rdfs:Resource ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf + , + + ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf + , + + ; + . + + + rdfs:subClassOf + , + + ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf + , + + ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf + , + + ; + . + + + rdfs:subClassOf + , + + ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf + , + + ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf + , + + ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf + , + + ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf ; + . + + + rdfs:subClassOf rdfs:Resource ; + . + + + rdfs:subClassOf rdfs:Resource ; + . + + + rdfs:subClassOf rdfs:Resource ; + . + + + rdfs:subClassOf rdfs:Resource ; + . + + + rdfs:subClassOf rdfs:Resource ; + . + + + rdfs:subClassOf rdfs:Resource ; + . + + + rdfs:subClassOf rdfs:Resource ; + . + + + rdfs:subClassOf rdfs:Resource ; + . + + + rdfs:subClassOf rdfs:Resource ; + . + + + rdfs:subClassOf rdfs:Resource ; + . + + + rdfs:subClassOf rdfs:Resource ; + . + + + rdfs:subClassOf rdfs:Resource ; + . + + + rdfs:subClassOf rdfs:Resource ; + . + + + rdfs:subClassOf rdfs:Resource ; + . + + + rdfs:subClassOf rdfs:Resource ; + . + + + rdfs:subClassOf rdfs:Resource ; + . + + + rdfs:subClassOf rdfs:Resource ; + . + + + rdfs:subClassOf rdfs:Resource ; + . + + + rdfs:subClassOf rdfs:Resource ; + . + + + rdfs:subClassOf rdfs:Resource ; + . + + + rdfs:subClassOf rdfs:Resource ; + . + + + rdfs:subClassOf rdfs:Resource ; + . + + + rdfs:subClassOf rdfs:Resource ; + . + + + rdfs:subClassOf rdfs:Resource ; + . + + + rdfs:subClassOf rdfs:Resource ; + . + + + rdfs:subClassOf rdfs:Resource ; + . + + + rdfs:subClassOf rdfs:Resource ; + . + + + rdfs:subClassOf rdfs:Resource ; + . + + + rdfs:subClassOf rdfs:Resource ; + . + + + rdfs:subClassOf rdfs:Resource ; + . + + + rdfs:subClassOf rdfs:Resource ; + . + + + rdfs:subClassOf rdfs:Resource ; + . + + + rdfs:subClassOf rdfs:Resource ; + . + + + rdfs:subClassOf rdfs:Resource ; + . + + + rdfs:subClassOf rdfs:Resource ; + . + + + rdfs:subClassOf rdfs:Resource ; + . + + + rdfs:subClassOf rdfs:Resource ; + . + + + rdfs:subClassOf rdfs:Resource ; + . + + + rdfs:subClassOf rdfs:Resource ; + . + + + rdfs:subClassOf rdfs:Resource ; + . + + + rdfs:subClassOf rdfs:Resource ; + . + + + rdfs:subClassOf rdfs:Resource ; + . + From 6eb2be4124648963964398d9af5cd0bceca89e8e Mon Sep 17 00:00:00 2001 From: Alex Nelson Date: Wed, 10 Nov 2021 15:26:04 -0500 Subject: [PATCH 05/10] Load subclass hierarchy when subClassOf used in query References: * [UCO OC-65] (CP-13) UCO needs subclasses of ObservableObject Signed-off-by: Alex Nelson --- README.md | 2 ++ case_utils/case_sparql_construct/__init__.py | 15 ++++++++- case_utils/case_sparql_select/__init__.py | 16 +++++++++- case_utils/ontology/__init__.py | 32 +++++++++++++++++++ .../case_utils/case_sparql_construct/Makefile | 2 ++ tests/case_utils/case_sparql_select/Makefile | 2 ++ 6 files changed, 67 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1367780..e7d036b 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,8 @@ case_file --disable-hashes sample.txt.json sample.txt Two commands are provided to generate output from a SPARQL query and one or more input graphs. Input graphs can be any graph, such as instance data or supplementary ontology files that supply custom class definitions or other external ontologies. +These commands can be used with any RDF files to run arbitrary SPARQL queries. They have one additional behavior tailored to CASE: If a path query is used for subclasses, the CASE subclass hierarchy will be loaded to supplement the input graph. An expected use case of this feature is subclasses of `ObservableObject`. For instance, if a data graph included an object with only the class `uco-observable:File` specified, the query `?x a/rdfs:subClassOf* uco-observable:ObservableObject` would match `?x` against that object. + #### `case_sparql_construct` diff --git a/case_utils/case_sparql_construct/__init__.py b/case_utils/case_sparql_construct/__init__.py index c129a6a..abcdd27 100644 --- a/case_utils/case_sparql_construct/__init__.py +++ b/case_utils/case_sparql_construct/__init__.py @@ -25,7 +25,9 @@ import rdflib.plugins.sparql # type: ignore -import case_utils +import case_utils.ontology + +from case_utils.ontology.version_info import * _logger = logging.getLogger(os.path.basename(__file__)) @@ -35,11 +37,19 @@ def main() -> None: # Configure debug logging before running parse_args, because there could be an error raised before the construction of the argument parser. logging.basicConfig(level=logging.DEBUG if ("--debug" in sys.argv or "-d" in sys.argv) else logging.INFO) + built_version_choices_list = ["none", "case-" + CURRENT_CASE_VERSION] + parser.add_argument( "-d", "--debug", action="store_true" ) + parser.add_argument( + "--built-version", + choices=tuple(built_version_choices_list), + default="case-"+CURRENT_CASE_VERSION, + help="Ontology version to use to supplement query, such as for subclass querying. Does not require networking to use. Default is most recent CASE release." + ) parser.add_argument( "--disallow-empty-results", action="store_true", @@ -72,6 +82,9 @@ def main() -> None: construct_query_text = in_fh.read().strip() assert not construct_query_text is None + if "subClassOf" in construct_query_text: + case_utils.ontology.load_subclass_hierarchy(in_graph, built_version=args.built_version) + construct_query_object = rdflib.plugins.sparql.prepareQuery(construct_query_text, initNs=nsdict) # https://rdfextras.readthedocs.io/en/latest/working_with.html diff --git a/case_utils/case_sparql_select/__init__.py b/case_utils/case_sparql_select/__init__.py index f5b3862..12404f1 100644 --- a/case_utils/case_sparql_select/__init__.py +++ b/case_utils/case_sparql_select/__init__.py @@ -30,6 +30,7 @@ import argparse import binascii +import importlib.resources import logging import os import sys @@ -37,7 +38,9 @@ import pandas as pd # type: ignore import rdflib.plugins.sparql # type: ignore -import case_utils +import case_utils.ontology + +from case_utils.ontology.version_info import * NS_XSD = rdflib.XSD @@ -49,11 +52,19 @@ def main() -> None: # Configure debug logging before running parse_args, because there could be an error raised before the construction of the argument parser. logging.basicConfig(level=logging.DEBUG if ("--debug" in sys.argv or "-d" in sys.argv) else logging.INFO) + built_version_choices_list = ["none", "case-" + CURRENT_CASE_VERSION] + parser.add_argument( "-d", "--debug", action="store_true" ) + parser.add_argument( + "--built-version", + choices=tuple(built_version_choices_list), + default="case-"+CURRENT_CASE_VERSION, + help="Ontology version to use to supplement query, such as for subclass querying. Does not require networking to use. Default is most recent CASE release." + ) parser.add_argument( "--disallow-empty-results", action="store_true", @@ -79,6 +90,9 @@ def main() -> None: select_query_text = in_fh.read().strip() _logger.debug("select_query_text = %r." % select_query_text) + if "subClassOf" in select_query_text: + case_utils.ontology.load_subclass_hierarchy(graph, built_version=args.built_version) + # Build columns list from SELECT line. select_query_text_lines = select_query_text.split("\n") select_line = [line for line in select_query_text_lines if line.startswith("SELECT ")][0] diff --git a/case_utils/ontology/__init__.py b/case_utils/ontology/__init__.py index 081745d..eb14af5 100644 --- a/case_utils/ontology/__init__.py +++ b/case_utils/ontology/__init__.py @@ -1,3 +1,5 @@ +#!/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 @@ -8,3 +10,33 @@ # reliability, or any other characteristic. # # We would appreciate acknowledgement if the software is used. + +__version__ = "0.1.0" + +import importlib.resources +import logging +import os + +import rdflib + +# Yes, this next import is self-referential (/circular). But, it does work with importlib. +import case_utils.ontology + +from .version_info import * + +_logger = logging.getLogger(os.path.basename(__file__)) + +def load_subclass_hierarchy( + graph : rdflib.Graph, + *, + built_version : str = "case-"+CURRENT_CASE_VERSION +) -> None: + """ + Adds all ontology rdfs:subClassOf statements from the version referred to by built_version. + """ + if built_version != "none": + _logger.debug("Loading subclass hierarchy.") + ttl_filename = built_version + "-subclasses.ttl" + _logger.debug("ttl_filename = %r.", ttl_filename) + ttl_data = importlib.resources.read_text(case_utils.ontology, ttl_filename) + graph.parse(data=ttl_data) diff --git a/tests/case_utils/case_sparql_construct/Makefile b/tests/case_utils/case_sparql_construct/Makefile index d0dabb3..dac64fe 100644 --- a/tests/case_utils/case_sparql_construct/Makefile +++ b/tests/case_utils/case_sparql_construct/Makefile @@ -37,6 +37,8 @@ clean: output.%: \ $(tests_srcdir)/.venv.done.log \ $(top_srcdir)/case_utils/case_sparql_construct/__init__.py \ + $(top_srcdir)/case_utils/ontology/__init__.py \ + $(top_srcdir)/case_utils/ontology/version_info.py \ input-1.sparql \ input-2.ttl \ input-3.json diff --git a/tests/case_utils/case_sparql_select/Makefile b/tests/case_utils/case_sparql_select/Makefile index 6070739..7422a23 100644 --- a/tests/case_utils/case_sparql_select/Makefile +++ b/tests/case_utils/case_sparql_select/Makefile @@ -53,6 +53,8 @@ clean: output.%: \ $(tests_srcdir)/.venv.done.log \ $(top_srcdir)/case_utils/case_sparql_select/__init__.py \ + $(top_srcdir)/case_utils/ontology/__init__.py \ + $(top_srcdir)/case_utils/ontology/version_info.py \ input-1.sparql \ input-2.ttl \ input-3.json From 6ae59f31957f179de374dd91f2759edddb4b8ce1 Mon Sep 17 00:00:00 2001 From: Alex Nelson Date: Wed, 10 Nov 2021 16:39:21 -0500 Subject: [PATCH 06/10] Move W3C test data files to "w3-" prefixed files References: * [UCO OC-65] (CP-13) UCO needs subclasses of ObservableObject Signed-off-by: Alex Nelson --- .../case_sparql_construct/.gitignore | 3 +- .../case_utils/case_sparql_construct/Makefile | 21 +++++----- .../case_sparql_construct/README.md | 15 +++---- .../test_case_sparql_construct.py | 10 ++--- .../{input-1.sparql => w3-input-1.sparql} | 0 .../{input-2.ttl => w3-input-2.ttl} | 0 .../{input-3.json => w3-input-3.json} | 0 ...heck-output.html => .check-w3-output.html} | 0 .../{.check-output.md => .check-w3-output.md} | 0 .../case_utils/case_sparql_select/.gitignore | 3 +- tests/case_utils/case_sparql_select/Makefile | 40 +++++++++---------- .../{input-1.sparql => w3-input-1.sparql} | 0 .../{input-2.ttl => w3-input-2.ttl} | 0 .../{input-3.json => w3-input-3.json} | 0 14 files changed, 46 insertions(+), 46 deletions(-) rename tests/case_utils/case_sparql_construct/{input-1.sparql => w3-input-1.sparql} (100%) rename tests/case_utils/case_sparql_construct/{input-2.ttl => w3-input-2.ttl} (100%) rename tests/case_utils/case_sparql_construct/{input-3.json => w3-input-3.json} (100%) rename tests/case_utils/case_sparql_select/{.check-output.html => .check-w3-output.html} (100%) rename tests/case_utils/case_sparql_select/{.check-output.md => .check-w3-output.md} (100%) rename tests/case_utils/case_sparql_select/{input-1.sparql => w3-input-1.sparql} (100%) rename tests/case_utils/case_sparql_select/{input-2.ttl => w3-input-2.ttl} (100%) rename tests/case_utils/case_sparql_select/{input-3.json => w3-input-3.json} (100%) diff --git a/tests/case_utils/case_sparql_construct/.gitignore b/tests/case_utils/case_sparql_construct/.gitignore index 6553b72..1ca1147 100644 --- a/tests/case_utils/case_sparql_construct/.gitignore +++ b/tests/case_utils/case_sparql_construct/.gitignore @@ -1,2 +1 @@ -output.json -output.ttl +w3-output.* diff --git a/tests/case_utils/case_sparql_construct/Makefile b/tests/case_utils/case_sparql_construct/Makefile index dac64fe..222f1d7 100644 --- a/tests/case_utils/case_sparql_construct/Makefile +++ b/tests/case_utils/case_sparql_construct/Makefile @@ -18,11 +18,12 @@ top_srcdir := $(shell cd ../../.. ; pwd) tests_srcdir := $(top_srcdir)/tests all: \ - output.ttl + w3-output.json \ + w3-output.ttl check: \ - output.json \ - output.ttl + w3-output.json \ + w3-output.ttl source $(tests_srcdir)/venv/bin/activate \ && pytest \ --log-level=DEBUG @@ -34,18 +35,18 @@ clean: output.* \ _* -output.%: \ +w3-output.%: \ $(tests_srcdir)/.venv.done.log \ $(top_srcdir)/case_utils/case_sparql_construct/__init__.py \ $(top_srcdir)/case_utils/ontology/__init__.py \ $(top_srcdir)/case_utils/ontology/version_info.py \ - input-1.sparql \ - input-2.ttl \ - input-3.json + w3-input-1.sparql \ + w3-input-2.ttl \ + w3-input-3.json source $(tests_srcdir)/venv/bin/activate \ && case_sparql_construct \ _$@ \ - input-1.sparql \ - input-2.ttl \ - input-3.json + w3-input-1.sparql \ + w3-input-2.ttl \ + w3-input-3.json mv _$@ $@ diff --git a/tests/case_utils/case_sparql_construct/README.md b/tests/case_utils/case_sparql_construct/README.md index bab41ac..7a36679 100644 --- a/tests/case_utils/case_sparql_construct/README.md +++ b/tests/case_utils/case_sparql_construct/README.md @@ -1,16 +1,17 @@ # Test of CASE SPARQL CONSTRUCT query runner +The tests in this directory confirms `case_sparql_construct` satisfies a base set of expected command line functionality. + ## Test procedure -The tests in this directory confirms `case_sparql_construct` satisfies a base set of expected command line functionality. -1. Inputs - `input-2.ttl` and `input-3.json` contain a small graph split across two files, and `input-1.sparql` contains a SPARQL `CONSTRUCT` query. -2. Outputs - `output.ttl` is generated by using `case_sparql_construct` to run `input-1.sparql` against the two `input-*.*` graph files. This affirms that `case_sparql_construct` can read multiple input files of differing formats. -3. Output verification - two name-pairs should have vcard records generated. The test `test_templates_with_blank_nodes_result()` confirms those pairs are in the output graph. +1. Inputs - `w3-input-2.ttl` and `w3-input-3.json` contain a small graph split across two files, and `w3-input-1.sparql` contains a SPARQL `CONSTRUCT` query. +2. Outputs - `w3-output.ttl` is generated by using `case_sparql_construct` to run `w3-input-1.sparql` against the two `w3-input-*.*` graph files. This affirms that `case_sparql_construct` can read multiple input files of differing formats. +3. Output verification - two name-pairs should have vcard records generated. The tests `test_w3_templates_with_blank_nodes_result_json()` and `_turtle()` confirm those pairs are in the output graphs. ## References -The data and query used in `input-2.ttl`, `input-3.json` and `input.sparql` are copied from ["SPARQL Query Language for RDF", Section 10.2.1](https://www.w3.org/TR/rdf-sparql-query/#tempatesWithBNodes), with these modifications: -* `input-2.ttl` contains the original example's `_:a` (Alice) records, but drops the `_:b` (Bob) records. -* `input-3.json` is a conversion of the original Turtle example's `_:b` records to JSON-LD. +The data and query used in `w3-input-2.ttl`, `w3-input-3.json` and `w3-input.sparql` are copied from ["SPARQL Query Language for RDF", Section 10.2.1](https://www.w3.org/TR/rdf-sparql-query/#tempatesWithBNodes), with these modifications: +* `w3-input-2.ttl` contains the original example's `_:a` (Alice) records, but drops the `_:b` (Bob) records. +* `w3-input-3.json` is a conversion of the original Turtle example's `_:b` records to JSON-LD. diff --git a/tests/case_utils/case_sparql_construct/test_case_sparql_construct.py b/tests/case_utils/case_sparql_construct/test_case_sparql_construct.py index 1d919c1..e1b220a 100644 --- a/tests/case_utils/case_sparql_construct/test_case_sparql_construct.py +++ b/tests/case_utils/case_sparql_construct/test_case_sparql_construct.py @@ -17,7 +17,7 @@ import case_utils -def _test_templates_with_blank_nodes_result( +def _test_w3_templates_with_blank_nodes_result( filename : str ) -> None: ground_truth_positive = { @@ -52,8 +52,8 @@ def _test_templates_with_blank_nodes_result( )) assert computed == ground_truth_positive -def test_templates_with_blank_nodes_result_json() -> None: - _test_templates_with_blank_nodes_result("output.json") +def test_w3_templates_with_blank_nodes_result_json() -> None: + _test_w3_templates_with_blank_nodes_result("w3-output.json") -def test_templates_with_blank_nodes_result_turtle() -> None: - _test_templates_with_blank_nodes_result("output.ttl") +def test_w3_templates_with_blank_nodes_result_turtle() -> None: + _test_w3_templates_with_blank_nodes_result("w3-output.ttl") diff --git a/tests/case_utils/case_sparql_construct/input-1.sparql b/tests/case_utils/case_sparql_construct/w3-input-1.sparql similarity index 100% rename from tests/case_utils/case_sparql_construct/input-1.sparql rename to tests/case_utils/case_sparql_construct/w3-input-1.sparql diff --git a/tests/case_utils/case_sparql_construct/input-2.ttl b/tests/case_utils/case_sparql_construct/w3-input-2.ttl similarity index 100% rename from tests/case_utils/case_sparql_construct/input-2.ttl rename to tests/case_utils/case_sparql_construct/w3-input-2.ttl diff --git a/tests/case_utils/case_sparql_construct/input-3.json b/tests/case_utils/case_sparql_construct/w3-input-3.json similarity index 100% rename from tests/case_utils/case_sparql_construct/input-3.json rename to tests/case_utils/case_sparql_construct/w3-input-3.json diff --git a/tests/case_utils/case_sparql_select/.check-output.html b/tests/case_utils/case_sparql_select/.check-w3-output.html similarity index 100% rename from tests/case_utils/case_sparql_select/.check-output.html rename to tests/case_utils/case_sparql_select/.check-w3-output.html diff --git a/tests/case_utils/case_sparql_select/.check-output.md b/tests/case_utils/case_sparql_select/.check-w3-output.md similarity index 100% rename from tests/case_utils/case_sparql_select/.check-output.md rename to tests/case_utils/case_sparql_select/.check-w3-output.md diff --git a/tests/case_utils/case_sparql_select/.gitignore b/tests/case_utils/case_sparql_select/.gitignore index a85ef3b..1ca1147 100644 --- a/tests/case_utils/case_sparql_select/.gitignore +++ b/tests/case_utils/case_sparql_select/.gitignore @@ -1,2 +1 @@ -output.html -output.md +w3-output.* diff --git a/tests/case_utils/case_sparql_select/Makefile b/tests/case_utils/case_sparql_select/Makefile index 7422a23..b24f584 100644 --- a/tests/case_utils/case_sparql_select/Makefile +++ b/tests/case_utils/case_sparql_select/Makefile @@ -18,28 +18,28 @@ top_srcdir := $(shell cd ../../.. ; pwd) tests_srcdir := $(top_srcdir)/tests all: \ - output.html \ - output.md + w3-output.html \ + w3-output.md .PHONY: \ - check-html \ - check-markdown + check-w3-html \ + check-w3-markdown .PRECIOUS: \ - output.% + w3-output.% check: \ - check-html \ - check-markdown + check-w3-html \ + check-w3-markdown -check-html: \ - .check-output.html \ - output.html +check-w3-html: \ + .check-w3-output.html \ + w3-output.html diff $^ -check-markdown: \ - .check-output.md \ - output.md +check-w3-markdown: \ + .check-w3-output.md \ + w3-output.md diff $^ clean: @@ -50,18 +50,18 @@ clean: *.md \ _* -output.%: \ +w3-output.%: \ $(tests_srcdir)/.venv.done.log \ $(top_srcdir)/case_utils/case_sparql_select/__init__.py \ $(top_srcdir)/case_utils/ontology/__init__.py \ $(top_srcdir)/case_utils/ontology/version_info.py \ - input-1.sparql \ - input-2.ttl \ - input-3.json + w3-input-1.sparql \ + w3-input-2.ttl \ + w3-input-3.json source $(tests_srcdir)/venv/bin/activate \ && case_sparql_select \ _$@ \ - input-1.sparql \ - input-2.ttl \ - input-3.json + w3-input-1.sparql \ + w3-input-2.ttl \ + w3-input-3.json mv _$@ $@ diff --git a/tests/case_utils/case_sparql_select/input-1.sparql b/tests/case_utils/case_sparql_select/w3-input-1.sparql similarity index 100% rename from tests/case_utils/case_sparql_select/input-1.sparql rename to tests/case_utils/case_sparql_select/w3-input-1.sparql diff --git a/tests/case_utils/case_sparql_select/input-2.ttl b/tests/case_utils/case_sparql_select/w3-input-2.ttl similarity index 100% rename from tests/case_utils/case_sparql_select/input-2.ttl rename to tests/case_utils/case_sparql_select/w3-input-2.ttl diff --git a/tests/case_utils/case_sparql_select/input-3.json b/tests/case_utils/case_sparql_select/w3-input-3.json similarity index 100% rename from tests/case_utils/case_sparql_select/input-3.json rename to tests/case_utils/case_sparql_select/w3-input-3.json From 4cf096712c97a3142a350f2fefb0d30fcaa4e496 Mon Sep 17 00:00:00 2001 From: Alex Nelson Date: Wed, 10 Nov 2021 16:57:38 -0500 Subject: [PATCH 07/10] Add subclass tests for case_sparql_* commands References: * [UCO OC-65] (CP-13) UCO needs subclasses of ObservableObject Signed-off-by: Alex Nelson --- .../case_sparql_construct/.gitignore | 1 + .../case_utils/case_sparql_construct/Makefile | 33 ++++++++++++ .../case_sparql_construct/README.md | 19 +++++-- .../case_sparql_construct/subclass.json | 16 ++++++ .../case_sparql_construct/subclass.sparql | 9 ++++ .../test_case_sparql_construct.py | 38 ++++++++++++++ .../.check-subclass-explicit-none.md | 3 ++ .../.check-subclass-implicit-any.md | 4 ++ .../case_utils/case_sparql_select/.gitignore | 1 + tests/case_utils/case_sparql_select/Makefile | 52 ++++++++++++++++++- .../case_sparql_select/subclass.json | 16 ++++++ .../case_sparql_select/subclass.sparql | 5 ++ 12 files changed, 193 insertions(+), 4 deletions(-) create mode 100644 tests/case_utils/case_sparql_construct/subclass.json create mode 100644 tests/case_utils/case_sparql_construct/subclass.sparql create mode 100644 tests/case_utils/case_sparql_select/.check-subclass-explicit-none.md create mode 100644 tests/case_utils/case_sparql_select/.check-subclass-implicit-any.md create mode 100644 tests/case_utils/case_sparql_select/subclass.json create mode 100644 tests/case_utils/case_sparql_select/subclass.sparql diff --git a/tests/case_utils/case_sparql_construct/.gitignore b/tests/case_utils/case_sparql_construct/.gitignore index 1ca1147..376ddf7 100644 --- a/tests/case_utils/case_sparql_construct/.gitignore +++ b/tests/case_utils/case_sparql_construct/.gitignore @@ -1 +1,2 @@ +subclass-*.ttl w3-output.* diff --git a/tests/case_utils/case_sparql_construct/Makefile b/tests/case_utils/case_sparql_construct/Makefile index 222f1d7..d749fe7 100644 --- a/tests/case_utils/case_sparql_construct/Makefile +++ b/tests/case_utils/case_sparql_construct/Makefile @@ -18,10 +18,14 @@ top_srcdir := $(shell cd ../../.. ; pwd) tests_srcdir := $(top_srcdir)/tests all: \ + subclass-explicit-none.ttl \ + subclass-implicit-any.ttl \ w3-output.json \ w3-output.ttl check: \ + subclass-explicit-none.ttl \ + subclass-implicit-any.ttl \ w3-output.json \ w3-output.ttl source $(tests_srcdir)/venv/bin/activate \ @@ -35,6 +39,35 @@ clean: output.* \ _* +subclass-explicit-none.ttl: \ + $(tests_srcdir)/.venv.done.log \ + $(top_srcdir)/case_utils/case_sparql_construct/__init__.py \ + $(top_srcdir)/case_utils/ontology/__init__.py \ + $(top_srcdir)/case_utils/ontology/version_info.py \ + subclass.json \ + subclass.sparql + source $(tests_srcdir)/venv/bin/activate \ + && case_sparql_construct \ + --built-version none \ + _$@ \ + subclass.sparql \ + subclass.json + mv _$@ $@ + +subclass-implicit-any.ttl: \ + $(tests_srcdir)/.venv.done.log \ + $(top_srcdir)/case_utils/case_sparql_construct/__init__.py \ + $(top_srcdir)/case_utils/ontology/__init__.py \ + $(top_srcdir)/case_utils/ontology/version_info.py \ + subclass.json \ + subclass.sparql + source $(tests_srcdir)/venv/bin/activate \ + && case_sparql_construct \ + _$@ \ + subclass.sparql \ + subclass.json + mv _$@ $@ + w3-output.%: \ $(tests_srcdir)/.venv.done.log \ $(top_srcdir)/case_utils/case_sparql_construct/__init__.py \ diff --git a/tests/case_utils/case_sparql_construct/README.md b/tests/case_utils/case_sparql_construct/README.md index 7a36679..9c125f8 100644 --- a/tests/case_utils/case_sparql_construct/README.md +++ b/tests/case_utils/case_sparql_construct/README.md @@ -1,17 +1,30 @@ -# Test of CASE SPARQL CONSTRUCT query runner +# Tests of CASE SPARQL CONSTRUCT query runner The tests in this directory confirms `case_sparql_construct` satisfies a base set of expected command line functionality. -## Test procedure +## Test 1 - CONSTRUCT from W3C example + + +### Test procedure 1. Inputs - `w3-input-2.ttl` and `w3-input-3.json` contain a small graph split across two files, and `w3-input-1.sparql` contains a SPARQL `CONSTRUCT` query. 2. Outputs - `w3-output.ttl` is generated by using `case_sparql_construct` to run `w3-input-1.sparql` against the two `w3-input-*.*` graph files. This affirms that `case_sparql_construct` can read multiple input files of differing formats. 3. Output verification - two name-pairs should have vcard records generated. The tests `test_w3_templates_with_blank_nodes_result_json()` and `_turtle()` confirm those pairs are in the output graphs. -## References +### References The data and query used in `w3-input-2.ttl`, `w3-input-3.json` and `w3-input.sparql` are copied from ["SPARQL Query Language for RDF", Section 10.2.1](https://www.w3.org/TR/rdf-sparql-query/#tempatesWithBNodes), with these modifications: * `w3-input-2.ttl` contains the original example's `_:a` (Alice) records, but drops the `_:b` (Bob) records. * `w3-input-3.json` is a conversion of the original Turtle example's `_:b` records to JSON-LD. + + +## Test 2 - CASE subclass inference + + +### Test procedure + +1. Inputs - `subclass.json` contain a small graph with two resources that are `ObservableObject`s. `kb:file-1` is explicitly an `ObservableObject`. `kb:file-2` is implicitly an `ObservableObject`, by way of `File` being a subclass of `ObservableObject`. `subclass.sparql` queries for all `ObservableObject`s, to construct an additional extending statement that they are also [`prov:Entity`](https://www.w3.org/TR/prov-o/#Entity)s. +2. Outputs - `subclass-implicit-any.ttl` is the constructed graph that uses CASE's subclass hierarchy. `subclass-explicit-none.ttl` is the constructed graph that foregoes any implicit CASE ontology structure, via the `--built-version none` flag. +3. Output verification - See the tests `test_subclass_templates_result_default_case` and `test_subclass_templates_result_no_case`, that verify foregoing the CASE subclass structure means one node is missed by the `CONSTRUCT` query. diff --git a/tests/case_utils/case_sparql_construct/subclass.json b/tests/case_utils/case_sparql_construct/subclass.json new file mode 100644 index 0000000..57646b1 --- /dev/null +++ b/tests/case_utils/case_sparql_construct/subclass.json @@ -0,0 +1,16 @@ +{ + "@context": { + "kb": "http://example.org/kb/", + "uco-observable": "https://unifiedcyberontology.org/ontology/uco/observable#" + }, + "@graph": [ + { + "@id": "kb:file-1", + "@type": "uco-observable:ObservableObject" + }, + { + "@id": "kb:file-2", + "@type": "uco-observable:File" + } + ] +} diff --git a/tests/case_utils/case_sparql_construct/subclass.sparql b/tests/case_utils/case_sparql_construct/subclass.sparql new file mode 100644 index 0000000..b0b1868 --- /dev/null +++ b/tests/case_utils/case_sparql_construct/subclass.sparql @@ -0,0 +1,9 @@ +PREFIX prov: +PREFIX uco-observable: +CONSTRUCT { + ?nEntity a prov:Entity . +} +WHERE +{ + ?nEntity a/rdfs:subClassOf* uco-observable:ObservableObject . +} diff --git a/tests/case_utils/case_sparql_construct/test_case_sparql_construct.py b/tests/case_utils/case_sparql_construct/test_case_sparql_construct.py index e1b220a..b111d9e 100644 --- a/tests/case_utils/case_sparql_construct/test_case_sparql_construct.py +++ b/tests/case_utils/case_sparql_construct/test_case_sparql_construct.py @@ -17,6 +17,27 @@ import case_utils +def _test_subclass_templates_result( + filename : str, + expected : typing.Set[str] +) -> None: + computed : typing.Set[str] = set() + + graph = rdflib.Graph() + graph.parse(filename) + + query_string = """\ +PREFIX prov: +SELECT ?nEntity +WHERE { + ?nEntity a prov:Entity +} +""" + for result in graph.query(query_string): + n_entity = result[0] + computed.add(n_entity.toPython()) + assert expected == computed + def _test_w3_templates_with_blank_nodes_result( filename : str ) -> None: @@ -57,3 +78,20 @@ def test_w3_templates_with_blank_nodes_result_json() -> None: def test_w3_templates_with_blank_nodes_result_turtle() -> None: _test_w3_templates_with_blank_nodes_result("w3-output.ttl") + +def test_subclass_templates_result_default_case() -> None: + _test_subclass_templates_result( + "subclass-implicit-any.ttl", + { + "http://example.org/kb/file-1", + "http://example.org/kb/file-2" + } + ) + +def test_subclass_templates_result_no_case() -> None: + _test_subclass_templates_result( + "subclass-explicit-none.ttl", + { + "http://example.org/kb/file-1" + } + ) diff --git a/tests/case_utils/case_sparql_select/.check-subclass-explicit-none.md b/tests/case_utils/case_sparql_select/.check-subclass-explicit-none.md new file mode 100644 index 0000000..5d9d1ef --- /dev/null +++ b/tests/case_utils/case_sparql_select/.check-subclass-explicit-none.md @@ -0,0 +1,3 @@ +| | ?nFile | +|----|------------------------------| +| 0 | http://example.org/kb/file-1 | \ No newline at end of file diff --git a/tests/case_utils/case_sparql_select/.check-subclass-implicit-any.md b/tests/case_utils/case_sparql_select/.check-subclass-implicit-any.md new file mode 100644 index 0000000..251fcf6 --- /dev/null +++ b/tests/case_utils/case_sparql_select/.check-subclass-implicit-any.md @@ -0,0 +1,4 @@ +| | ?nFile | +|----|------------------------------| +| 0 | http://example.org/kb/file-1 | +| 1 | http://example.org/kb/file-2 | \ No newline at end of file diff --git a/tests/case_utils/case_sparql_select/.gitignore b/tests/case_utils/case_sparql_select/.gitignore index 1ca1147..0ae4849 100644 --- a/tests/case_utils/case_sparql_select/.gitignore +++ b/tests/case_utils/case_sparql_select/.gitignore @@ -1 +1,2 @@ +subclass-*.md w3-output.* diff --git a/tests/case_utils/case_sparql_select/Makefile b/tests/case_utils/case_sparql_select/Makefile index b24f584..22a849b 100644 --- a/tests/case_utils/case_sparql_select/Makefile +++ b/tests/case_utils/case_sparql_select/Makefile @@ -18,19 +18,40 @@ top_srcdir := $(shell cd ../../.. ; pwd) tests_srcdir := $(top_srcdir)/tests all: \ + subclass-explicit-none.md \ + subclass-implicit-any.md \ w3-output.html \ w3-output.md .PHONY: \ + check-subclass \ + check-subclass-explicit-none \ + check-subclass-implicit-any \ check-w3-html \ check-w3-markdown .PRECIOUS: \ + subclass-% \ w3-output.% check: \ check-w3-html \ - check-w3-markdown + check-w3-markdown \ + check-subclass + +check-subclass: \ + check-subclass-explicit-none \ + check-subclass-implicit-any + +check-subclass-explicit-none: \ + .check-subclass-explicit-none.md \ + subclass-explicit-none.md + diff $^ + +check-subclass-implicit-any: \ + .check-subclass-implicit-any.md \ + subclass-implicit-any.md + diff $^ check-w3-html: \ .check-w3-output.html \ @@ -50,6 +71,35 @@ clean: *.md \ _* +subclass-explicit-none.md: \ + $(tests_srcdir)/.venv.done.log \ + $(top_srcdir)/case_utils/case_sparql_select/__init__.py \ + $(top_srcdir)/case_utils/ontology/__init__.py \ + $(top_srcdir)/case_utils/ontology/version_info.py \ + subclass.json \ + subclass.sparql + source $(tests_srcdir)/venv/bin/activate \ + && case_sparql_select \ + --built-version none \ + _$@ \ + subclass.sparql \ + subclass.json + mv _$@ $@ + +subclass-implicit-any.md: \ + $(tests_srcdir)/.venv.done.log \ + $(top_srcdir)/case_utils/case_sparql_select/__init__.py \ + $(top_srcdir)/case_utils/ontology/__init__.py \ + $(top_srcdir)/case_utils/ontology/version_info.py \ + subclass.json \ + subclass.sparql + source $(tests_srcdir)/venv/bin/activate \ + && case_sparql_select \ + _$@ \ + subclass.sparql \ + subclass.json + mv _$@ $@ + w3-output.%: \ $(tests_srcdir)/.venv.done.log \ $(top_srcdir)/case_utils/case_sparql_select/__init__.py \ diff --git a/tests/case_utils/case_sparql_select/subclass.json b/tests/case_utils/case_sparql_select/subclass.json new file mode 100644 index 0000000..57646b1 --- /dev/null +++ b/tests/case_utils/case_sparql_select/subclass.json @@ -0,0 +1,16 @@ +{ + "@context": { + "kb": "http://example.org/kb/", + "uco-observable": "https://unifiedcyberontology.org/ontology/uco/observable#" + }, + "@graph": [ + { + "@id": "kb:file-1", + "@type": "uco-observable:ObservableObject" + }, + { + "@id": "kb:file-2", + "@type": "uco-observable:File" + } + ] +} diff --git a/tests/case_utils/case_sparql_select/subclass.sparql b/tests/case_utils/case_sparql_select/subclass.sparql new file mode 100644 index 0000000..9c52721 --- /dev/null +++ b/tests/case_utils/case_sparql_select/subclass.sparql @@ -0,0 +1,5 @@ +PREFIX uco-observable: +SELECT ?nFile +WHERE { + ?nFile a/rdfs:subClassOf* uco-observable:ObservableObject . +} From 8fe74619d636ea11275cc5702b7e3164003aef47 Mon Sep 17 00:00:00 2001 From: Alex Nelson Date: Wed, 10 Nov 2021 16:59:18 -0500 Subject: [PATCH 08/10] Load subclass hierarchy to prepare for case_file implying ObservableObject superclass References: * [UCO OC-65] (CP-13) UCO needs subclasses of ObservableObject Signed-off-by: Alex Nelson --- tests/case_utils/case_file/test_case_file.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/case_utils/case_file/test_case_file.py b/tests/case_utils/case_file/test_case_file.py index acbad79..19ba199 100644 --- a/tests/case_utils/case_file/test_case_file.py +++ b/tests/case_utils/case_file/test_case_file.py @@ -18,6 +18,8 @@ import pytest import rdflib.plugins.sparql # type: ignore +import case_utils.ontology + _logger = logging.getLogger(os.path.basename(__file__)) IRI_UCO_CORE = "https://unifiedcyberontology.org/ontology/uco/core#" @@ -42,6 +44,8 @@ def load_graph( ) -> rdflib.Graph: in_graph = rdflib.Graph() in_graph.parse(filename) + # The queries in this test rely on the subclass hierarchy. Load it. + case_utils.ontology.load_subclass_hierarchy(in_graph) return in_graph @pytest.fixture From fcfdd4bce3c01b44116948ecd13236ed13dbaa23 Mon Sep 17 00:00:00 2001 From: Alex Nelson Date: Wed, 10 Nov 2021 17:01:56 -0500 Subject: [PATCH 09/10] Use ObservableObject subclass File for case_file References: * [UCO OC-65] (CP-13) UCO needs subclasses of ObservableObject Signed-off-by: Alex Nelson --- case_utils/case_file/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/case_utils/case_file/__init__.py b/case_utils/case_file/__init__.py index a25481d..3ac56ac 100644 --- a/case_utils/case_file/__init__.py +++ b/case_utils/case_file/__init__.py @@ -85,7 +85,7 @@ def create_file_node( graph.add(( n_file, NS_RDF.type, - NS_UCO_OBSERVABLE.ObservableObject + NS_UCO_OBSERVABLE.File )) basename = os.path.basename(filepath) From 6f9458f41114fb932e156fd3bcca39219b2882df Mon Sep 17 00:00:00 2001 From: Alex Nelson Date: Wed, 10 Nov 2021 17:05:30 -0500 Subject: [PATCH 10/10] Regenerate Make-managed files References: * [UCO OC-65] (CP-13) UCO needs subclasses of ObservableObject Signed-off-by: Alex Nelson --- tests/case_utils/case_file/kb.json | 4 +-- tests/case_utils/case_file/kb.ttl | 4 +-- .../case_file/sample.txt-disable_hashes.ttl | 2 +- .../case_file/sample.txt-nocompact.json | 26 +++++++++---------- tests/case_utils/case_file/sample.txt.json | 26 +++++++++---------- tests/case_utils/case_file/sample.txt.ttl | 2 +- 6 files changed, 32 insertions(+), 32 deletions(-) diff --git a/tests/case_utils/case_file/kb.json b/tests/case_utils/case_file/kb.json index 5f3863b..eadf906 100644 --- a/tests/case_utils/case_file/kb.json +++ b/tests/case_utils/case_file/kb.json @@ -10,7 +10,7 @@ "@graph": [ { "@id": "kb:file-69751792-9d04-5f5f-8791-99ca3729cd3c", - "@type": "uco-observable:ObservableObject", + "@type": "uco-observable:File", "uco-core:hasFacet": { "@type": "uco-observable:FileFacet", "uco-observable:fileName": "sample.txt", @@ -26,7 +26,7 @@ }, { "@id": "kb:file-9477a6eb-3a94-590b-b51e-6ce6892f0941", - "@type": "uco-observable:ObservableObject", + "@type": "uco-observable:File", "uco-core:hasFacet": [ { "@type": "uco-observable:ContentDataFacet", diff --git a/tests/case_utils/case_file/kb.ttl b/tests/case_utils/case_file/kb.ttl index 0fb50ca..f82b0f3 100644 --- a/tests/case_utils/case_file/kb.ttl +++ b/tests/case_utils/case_file/kb.ttl @@ -9,7 +9,7 @@ @prefix xsd: . kb:file-69751792-9d04-5f5f-8791-99ca3729cd3c - a uco-observable:ObservableObject ; + a uco-observable:File ; uco-core:hasFacet [ a uco-observable:FileFacet ; uco-observable:fileName "sample.txt" ; @@ -19,7 +19,7 @@ kb:file-69751792-9d04-5f5f-8791-99ca3729cd3c . kb:file-9477a6eb-3a94-590b-b51e-6ce6892f0941 - a uco-observable:ObservableObject ; + a uco-observable:File ; uco-core:hasFacet [ a uco-observable:ContentDataFacet ; diff --git a/tests/case_utils/case_file/sample.txt-disable_hashes.ttl b/tests/case_utils/case_file/sample.txt-disable_hashes.ttl index 0bc4d82..2b526be 100644 --- a/tests/case_utils/case_file/sample.txt-disable_hashes.ttl +++ b/tests/case_utils/case_file/sample.txt-disable_hashes.ttl @@ -7,7 +7,7 @@ @prefix xsd: . kb:file-69751792-9d04-5f5f-8791-99ca3729cd3c - a uco-observable:ObservableObject ; + a uco-observable:File ; uco-core:hasFacet [ a uco-observable:FileFacet ; uco-observable:fileName "sample.txt" ; diff --git a/tests/case_utils/case_file/sample.txt-nocompact.json b/tests/case_utils/case_file/sample.txt-nocompact.json index 6d2569b..c14fdf3 100644 --- a/tests/case_utils/case_file/sample.txt-nocompact.json +++ b/tests/case_utils/case_file/sample.txt-nocompact.json @@ -13,18 +13,18 @@ "@graph": [ { "@id": "http://example.org/kb/file-4216a9f3-45fc-55aa-8e48-a9f828173625", - "@type": "https://unifiedcyberontology.org/ontology/uco/observable#ObservableObject", + "@type": "https://unifiedcyberontology.org/ontology/uco/observable#File", "https://unifiedcyberontology.org/ontology/uco/core#hasFacet": [ { - "@id": "_:Ncbd74ec540fa42b09802cdf033ec0e86" + "@id": "_:N44ce7f76801a429d9aabefe1046da060" }, { - "@id": "_:N1b091168b6e746ca8ffef67ba546f52c" + "@id": "_:Ndd6e8785860848aeb6823b493c6420a7" } ] }, { - "@id": "_:Ncbd74ec540fa42b09802cdf033ec0e86", + "@id": "_:N44ce7f76801a429d9aabefe1046da060", "@type": "https://unifiedcyberontology.org/ontology/uco/observable#FileFacet", "https://unifiedcyberontology.org/ontology/uco/observable#fileName": "sample.txt", "https://unifiedcyberontology.org/ontology/uco/observable#modifiedTime": { @@ -34,26 +34,26 @@ "https://unifiedcyberontology.org/ontology/uco/observable#sizeInBytes": 4 }, { - "@id": "_:N1b091168b6e746ca8ffef67ba546f52c", + "@id": "_:Ndd6e8785860848aeb6823b493c6420a7", "@type": "https://unifiedcyberontology.org/ontology/uco/observable#ContentDataFacet", "https://unifiedcyberontology.org/ontology/uco/observable#hash": [ { - "@id": "_:Nf0f6ff73c49045ffa53e2fc83249d20b" + "@id": "_:N334acc4a58624aa29968e0d155bd34c7" }, { - "@id": "_:Na2470e1f29914026a1690b0e9386cc1f" + "@id": "_:Na1176e4f42e442b2bd4167202aa93383" }, { - "@id": "_:Nd8473ff30e87456d8dcd034729ba27ed" + "@id": "_:N400f582d54af4f8190253677f57de728" }, { - "@id": "_:Ncaa10f1e5cf84d8286f1d1c536b9fa06" + "@id": "_:Nef2949777f2b4b34a46a7d99ea01f44e" } ], "https://unifiedcyberontology.org/ontology/uco/observable#sizeInBytes": 4 }, { - "@id": "_:Nf0f6ff73c49045ffa53e2fc83249d20b", + "@id": "_:N334acc4a58624aa29968e0d155bd34c7", "@type": "https://unifiedcyberontology.org/ontology/uco/types#Hash", "https://unifiedcyberontology.org/ontology/uco/types#hashMethod": { "@type": "https://unifiedcyberontology.org/ontology/uco/vocabulary#HashNameVocab", @@ -65,7 +65,7 @@ } }, { - "@id": "_:Na2470e1f29914026a1690b0e9386cc1f", + "@id": "_:Na1176e4f42e442b2bd4167202aa93383", "@type": "https://unifiedcyberontology.org/ontology/uco/types#Hash", "https://unifiedcyberontology.org/ontology/uco/types#hashMethod": { "@type": "https://unifiedcyberontology.org/ontology/uco/vocabulary#HashNameVocab", @@ -77,7 +77,7 @@ } }, { - "@id": "_:Nd8473ff30e87456d8dcd034729ba27ed", + "@id": "_:N400f582d54af4f8190253677f57de728", "@type": "https://unifiedcyberontology.org/ontology/uco/types#Hash", "https://unifiedcyberontology.org/ontology/uco/types#hashMethod": { "@type": "https://unifiedcyberontology.org/ontology/uco/vocabulary#HashNameVocab", @@ -89,7 +89,7 @@ } }, { - "@id": "_:Ncaa10f1e5cf84d8286f1d1c536b9fa06", + "@id": "_:Nef2949777f2b4b34a46a7d99ea01f44e", "@type": "https://unifiedcyberontology.org/ontology/uco/types#Hash", "https://unifiedcyberontology.org/ontology/uco/types#hashMethod": { "@type": "https://unifiedcyberontology.org/ontology/uco/vocabulary#HashNameVocab", diff --git a/tests/case_utils/case_file/sample.txt.json b/tests/case_utils/case_file/sample.txt.json index c2b4f6e..f9b1b2d 100644 --- a/tests/case_utils/case_file/sample.txt.json +++ b/tests/case_utils/case_file/sample.txt.json @@ -13,18 +13,18 @@ "@graph": [ { "@id": "kb:file-a44b2ee3-968f-5528-883a-fa65ac45ce2c", - "@type": "uco-observable:ObservableObject", + "@type": "uco-observable:File", "uco-core:hasFacet": [ { - "@id": "_:N4acc005af38245cb843d4a7009cce7df" + "@id": "_:N2767c0726ce542be9a1ad27b1f7ae944" }, { - "@id": "_:Nc02deac289534fbf93c061d03bbb589d" + "@id": "_:N78869d50bb384b24b8fd147d9bfe7e51" } ] }, { - "@id": "_:N4acc005af38245cb843d4a7009cce7df", + "@id": "_:N2767c0726ce542be9a1ad27b1f7ae944", "@type": "uco-observable:FileFacet", "uco-observable:fileName": "sample.txt", "uco-observable:modifiedTime": { @@ -34,26 +34,26 @@ "uco-observable:sizeInBytes": 4 }, { - "@id": "_:Nc02deac289534fbf93c061d03bbb589d", + "@id": "_:N78869d50bb384b24b8fd147d9bfe7e51", "@type": "uco-observable:ContentDataFacet", "uco-observable:hash": [ { - "@id": "_:Nbbf71d61d9fa4615bc074268fd60b4b5" + "@id": "_:N6407c0f0a27545e0a15a7e147e862003" }, { - "@id": "_:N6741cf44d9da464191c6a0014dbb602b" + "@id": "_:Na90e92d493a84c78802a307bbbdaafda" }, { - "@id": "_:N3b6cc89816394294bc260958408d74de" + "@id": "_:Nfe3e54d32dcc4ef79934ca120dc3d59e" }, { - "@id": "_:Nfc008212dd584b16a8d4d50df33f0a47" + "@id": "_:N80c90d89e47b4f30b585752201376e22" } ], "uco-observable:sizeInBytes": 4 }, { - "@id": "_:Nbbf71d61d9fa4615bc074268fd60b4b5", + "@id": "_:N6407c0f0a27545e0a15a7e147e862003", "@type": "uco-types:Hash", "uco-types:hashMethod": { "@type": "uco-vocabulary:HashNameVocab", @@ -65,7 +65,7 @@ } }, { - "@id": "_:N6741cf44d9da464191c6a0014dbb602b", + "@id": "_:Na90e92d493a84c78802a307bbbdaafda", "@type": "uco-types:Hash", "uco-types:hashMethod": { "@type": "uco-vocabulary:HashNameVocab", @@ -77,7 +77,7 @@ } }, { - "@id": "_:N3b6cc89816394294bc260958408d74de", + "@id": "_:Nfe3e54d32dcc4ef79934ca120dc3d59e", "@type": "uco-types:Hash", "uco-types:hashMethod": { "@type": "uco-vocabulary:HashNameVocab", @@ -89,7 +89,7 @@ } }, { - "@id": "_:Nfc008212dd584b16a8d4d50df33f0a47", + "@id": "_:N80c90d89e47b4f30b585752201376e22", "@type": "uco-types:Hash", "uco-types:hashMethod": { "@type": "uco-vocabulary:HashNameVocab", diff --git a/tests/case_utils/case_file/sample.txt.ttl b/tests/case_utils/case_file/sample.txt.ttl index 16029aa..faecc50 100644 --- a/tests/case_utils/case_file/sample.txt.ttl +++ b/tests/case_utils/case_file/sample.txt.ttl @@ -9,7 +9,7 @@ @prefix xsd: . kb:file-9477a6eb-3a94-590b-b51e-6ce6892f0941 - a uco-observable:ObservableObject ; + a uco-observable:File ; uco-core:hasFacet [ a uco-observable:ContentDataFacet ;