diff --git a/src/si_ref_point/aboxes/constants_abox.py b/src/si_ref_point/aboxes/constants_abox.py index 62aabc7..f1cf7f9 100644 --- a/src/si_ref_point/aboxes/constants_abox.py +++ b/src/si_ref_point/aboxes/constants_abox.py @@ -10,7 +10,7 @@ from si_ref_point.tboxes.si_tbox import SiElements import si_ref_point.aboxes.symbols_format as sf from si_ref_point.settings import PKG_ROOT, CC_LICENCE, CC_LICENCE_TEXT_EN, CC_LICENCE_TEXT_FR, \ - SI_FILES_FOLDER, GITHUB_BASE_PATH + SI_FILES_FOLDER, GITHUB_BASE_PATH, SIDFWBASE, SIRPVERSION from si_ref_point.aboxes.units_abox import transform_to_graph @@ -46,6 +46,11 @@ def main(): "seven underpinning constants of the SI"), datatype=XSD.string)) ) + + # SemVer + version_iri = URIRef(SIDFWBASE + "/" + SIRPVERSION + "/constants/") + constants_graph.add((URIRef(si_graph.namespace_constants), OWL.versionIRI, version_iri)) + constants_graph.add((URIRef(si_graph.namespace_constants), OWL.versionInfo, Literal(SIRPVERSION, datatype=XSD.string))) # 2.2 Versioning (using PROVENANCE vocabulary) # The `timestamp` variable in the code is used to capture the current system time in UTC timezone. @@ -58,6 +63,9 @@ def main(): "%Y-%m-%dT%H:%M:%SZ") # used with the predicate 'startedAtTime' of the corresponding activity repo = git.Repo(PKG_ROOT, search_parent_directories=True) sha = repo.head.object.hexsha + + + # 2.2.1 Agent # declare this code as an 'agent' (in the sense of PROVENANCE) # and define URI to a specific version by using its commit on GitHub diff --git a/src/si_ref_point/aboxes/decisions_abox.py b/src/si_ref_point/aboxes/decisions_abox.py index 4062ee7..c35937c 100644 --- a/src/si_ref_point/aboxes/decisions_abox.py +++ b/src/si_ref_point/aboxes/decisions_abox.py @@ -3,9 +3,9 @@ import os import yaml from datetime import date -from rdflib import RDF, OWL, URIRef, RDFS, DCTERMS, Literal, SKOS, XSD +from rdflib import Graph, RDF, OWL, URIRef, RDFS, DCTERMS, Literal, SKOS, XSD from si_ref_point.tboxes.si_tbox import SiElements -from si_ref_point.settings import SI_FILES_FOLDER +from si_ref_point.settings import SI_FILES_FOLDER, SIDFWBASE, SIRPVERSION def cap1(instr): """Utility method""" @@ -13,19 +13,33 @@ def cap1(instr): def main(): """main of Decision A-box""" + # get the predicates and classes that are common to all cuq files si_graph = SiElements() - # Annotations to the ontology (name, Version number) - si_graph.g.add((URIRef(si_graph.namespace_decisions), RDF.type, OWL.Ontology)) - si_graph.g.add((URIRef(si_graph.namespace_decisions), SKOS.prefLabel, + # produce a separate graph for the decisions + decisions_graph = Graph() + + # 1) Define the namespaces + decisions_graph.bind("si", si_graph.namespace) + decisions_graph.bind("decisions", si_graph.namespace_decisions) + + # 2) Annotations to the ontology (name, Version number) + decisions_graph.add((URIRef(si_graph.namespace_decisions), RDF.type, OWL.Ontology)) + decisions_graph.add((URIRef(si_graph.namespace_decisions), SKOS.prefLabel, Literal("SI Reference Point - Decisions", datatype=XSD.string))) - si_graph.g.add((URIRef(si_graph.namespace_decisions), RDFS.comment, + decisions_graph.add((URIRef(si_graph.namespace_decisions), RDFS.comment, Literal("Ontology, part of the SI reference point, " "covering decisions", datatype=XSD.string))) - si_graph.g.add((URIRef(si_graph.namespace_decisions), DCTERMS.created, + decisions_graph.add((URIRef(si_graph.namespace_decisions), DCTERMS.created, Literal(str(date.today()), datatype=XSD.date))) + # SemVer + + version_iri = URIRef(SIDFWBASE + "/" + SIRPVERSION + "/decisions/") + decisions_graph.add((URIRef(si_graph.namespace_decisions), OWL.versionIRI, version_iri)) + decisions_graph.add((URIRef(si_graph.namespace_decisions), OWL.versionInfo, Literal(SIRPVERSION, datatype=XSD.string))) + # crawl through the items of the YAML file with open(os.path.join(SI_FILES_FOLDER, 'decisions.yaml'), encoding="utf8") as fp: @@ -34,44 +48,44 @@ def main(): # create an instance of scope if necessary, using the scope code as # local name [TODO] : is it really only doing it if necessary ? scope = si_graph.set_decision_uri(dec['scopeCode']) - si_graph.g.add((scope, RDF.type, si_graph.si_decision_scope)) + decisions_graph.add((scope, RDF.type, si_graph.si_decision_scope)) # add labels to scope (capitalize the first character) - si_graph.g.add((scope, RDFS.label, + decisions_graph.add((scope, RDFS.label, Literal(cap1(dec['scopeEN']), lang="en"))) - si_graph.g.add((scope, RDFS.label, + decisions_graph.add((scope, RDFS.label, Literal(cap1(dec['scopeFR']), lang="fr"))) # create instance of target if necessary using target code as local # name target = si_graph.set_decision_uri(dec['targetCode']) - si_graph.g.add((target, RDF.type, si_graph.si_decision_target)) + decisions_graph.add((target, RDF.type, si_graph.si_decision_target)) # add labels to target - si_graph.g.add((target, RDFS.label, + decisions_graph.add((target, RDFS.label, Literal(cap1(dec['targetEN']), lang="en"))) - si_graph.g.add((target, RDFS.label, + decisions_graph.add((target, RDFS.label, Literal(cap1(dec['targetFR']), lang="fr"))) # add links between target and scope - si_graph.g.add((scope, si_graph.has_target, target)) - si_graph.g.add((target, si_graph.is_target_of, scope)) + decisions_graph.add((scope, si_graph.has_target, target)) + decisions_graph.add((target, si_graph.is_target_of, scope)) # create instance of decision if necessary using decision code as local # name decision = si_graph.set_decision_uri(dec['decisionCode']) - si_graph.g.add((decision, RDF.type, si_graph.si_decision)) + decisions_graph.add((decision, RDF.type, si_graph.si_decision)) # add labels to decision - si_graph.g.add((decision, RDFS.label, + decisions_graph.add((decision, RDFS.label, Literal(cap1(dec['decisionEN']), lang="en"))) - si_graph.g.add((decision, RDFS.label, + decisions_graph.add((decision, RDFS.label, Literal(cap1(dec['decisionFR']), lang="fr"))) # add links between decision and target - si_graph.g.add((target, si_graph.has_decision, decision)) - si_graph.g.add((decision, si_graph.is_decision_of, target)) + decisions_graph.add((target, si_graph.has_decision, decision)) + decisions_graph.add((decision, si_graph.is_decision_of, target)) # add link between decision and resolution (retrieved from one of # cgpm.ttl, cipm.ttl or cctf.ttl) using the ‘correspondingResolution’ # object property - si_graph.g.add((decision, si_graph.corresponding_resolution, + decisions_graph.add((decision, si_graph.corresponding_resolution, si_graph.set_resolution_uri(dec['ID-resolution']))) if 'crossReferences' in dec: for xref in dec['crossReferences']: # add link between decision and the cross-referenced decision - si_graph.g.add((decision, SKOS.related, si_graph.set_decision_uri(xref))) + decisions_graph.add((decision, SKOS.related, si_graph.set_decision_uri(xref))) - return si_graph.g + return decisions_graph diff --git a/src/si_ref_point/aboxes/prefixes_abox.py b/src/si_ref_point/aboxes/prefixes_abox.py index 69a9656..560f803 100644 --- a/src/si_ref_point/aboxes/prefixes_abox.py +++ b/src/si_ref_point/aboxes/prefixes_abox.py @@ -8,7 +8,8 @@ from decimal import Decimal from rdflib import Graph, URIRef, RDF, OWL, SKOS, XSD, RDFS, DCTERMS, Literal, PROV from si_ref_point.tboxes.si_tbox import SiElements -from si_ref_point.settings import PKG_ROOT, CC_LICENCE, CC_LICENCE_TEXT_EN, CC_LICENCE_TEXT_FR, SI_FILES_FOLDER, GITHUB_BASE_PATH +from si_ref_point.settings import PKG_ROOT, CC_LICENCE, CC_LICENCE_TEXT_EN, CC_LICENCE_TEXT_FR, SI_FILES_FOLDER, \ + GITHUB_BASE_PATH, SIDFWBASE, SIRPVERSION def main(): @@ -20,8 +21,8 @@ def main(): prefix_graph = Graph() # 1) Define the namespaces within (base)/SI - prefix_graph.bind("prefixes",si_graph.namespace_prefixes) - prefix_graph.bind("si",si_graph.namespace) + prefix_graph.bind("prefixes", si_graph.namespace_prefixes) + prefix_graph.bind("si", si_graph.namespace) # 2) Annotations to the prefix-graph @@ -43,6 +44,11 @@ def main(): "prefixes for the SI measurement units.")) ) + # SemVer + version_iri = URIRef(SIDFWBASE + "/" + SIRPVERSION + "/prefixes/") + prefix_graph.add((URIRef(si_graph.namespace_prefixes), OWL.versionIRI, version_iri)) + prefix_graph.add((URIRef(si_graph.namespace_prefixes), OWL.versionInfo, Literal(SIRPVERSION, datatype=XSD.string))) + # 2.2 Versioning (using PROVENANCE vocabulary) timestamp = datetime.now(timezone.utc) # get the system time (in UTC) uri_timestamp = timestamp.strftime("%Y%m%d%H%M%SZ") # used to identify uniquely the produced TTL file (entity) diff --git a/src/si_ref_point/aboxes/quantities_abox.py b/src/si_ref_point/aboxes/quantities_abox.py index a18b802..78b6af7 100644 --- a/src/si_ref_point/aboxes/quantities_abox.py +++ b/src/si_ref_point/aboxes/quantities_abox.py @@ -8,7 +8,8 @@ from rdflib import Graph, RDF, OWL, URIRef, RDFS, DCTERMS, Literal, SKOS, XSD, PROV from si_ref_point.tboxes.si_tbox import SiElements from si_ref_point.aboxes.units_abox import transform_to_graph -from si_ref_point.settings import PKG_ROOT, CC_LICENCE, CC_LICENCE_TEXT_EN, CC_LICENCE_TEXT_FR, SI_FILES_FOLDER, GITHUB_BASE_PATH +from si_ref_point.settings import PKG_ROOT, CC_LICENCE, CC_LICENCE_TEXT_EN, CC_LICENCE_TEXT_FR, SI_FILES_FOLDER, \ + GITHUB_BASE_PATH, SIDFWBASE, SIRPVERSION def main(): @@ -46,6 +47,11 @@ def main(): datatype=XSD.string)) ) + # SemVer + version_iri = URIRef(SIDFWBASE + "/" + SIRPVERSION + "/quantities/") + quantities_graph.add((URIRef(si_graph.namespace_quantities), OWL.versionIRI, version_iri)) + quantities_graph.add((URIRef(si_graph.namespace_quantities), OWL.versionInfo, Literal(SIRPVERSION, datatype=XSD.string))) + # 2.2 Versioning (using PROVENANCE vocabulary) timestamp = datetime.now(timezone.utc) # get the system time (in UTC) uri_timestamp = timestamp.strftime("%Y%m%d%H%M%SZ") # used to identify uniquely the produced TTL file (entity) diff --git a/src/si_ref_point/aboxes/rb_utils.py b/src/si_ref_point/aboxes/rb_utils.py index cfcb6ac..c3cb617 100644 --- a/src/si_ref_point/aboxes/rb_utils.py +++ b/src/si_ref_point/aboxes/rb_utils.py @@ -6,7 +6,7 @@ from rdflib import Graph, Literal, Namespace, URIRef from rdflib.namespace import DCTERMS, OWL, RDF, RDFS, SKOS, XSD from si_ref_point.tboxes.rb_tbox import RES_BOD_NS -from si_ref_point.settings import SIDFWBASE +from si_ref_point.settings import SIDFWBASE, SIRPVERSION RB = Namespace(RES_BOD_NS) @@ -63,6 +63,12 @@ def add_general_description(self): ) ) + # SemVer + version_iri = URIRef(SIDFWBASE + "/" + SIRPVERSION + "/bodies/" + self.own_acronym + "#") + self.g.add((URIRef(self.OWN_NS), OWL.versionIRI, version_iri)) + self.g.add((URIRef(self.OWN_NS), OWL.versionInfo, Literal(SIRPVERSION, datatype=XSD.string))) + + self.g.add( ( URIRef(self.OWN_NS), diff --git a/src/si_ref_point/aboxes/units_abox.py b/src/si_ref_point/aboxes/units_abox.py index 2dce6bb..30e1ce8 100644 --- a/src/si_ref_point/aboxes/units_abox.py +++ b/src/si_ref_point/aboxes/units_abox.py @@ -11,7 +11,8 @@ from rdflib import Graph, URIRef, BNode, Literal, RDF, OWL, SKOS, XSD, RDFS, DCTERMS, PROV from si_ref_point.tboxes.si_tbox import SiElements import si_ref_point.aboxes.symbols_format as sf -from si_ref_point.settings import PKG_ROOT, CC_LICENCE, CC_LICENCE_TEXT_EN, CC_LICENCE_TEXT_FR, SI_FILES_FOLDER, GITHUB_BASE_PATH +from si_ref_point.settings import PKG_ROOT, CC_LICENCE, CC_LICENCE_TEXT_EN, CC_LICENCE_TEXT_FR, SI_FILES_FOLDER, \ + GITHUB_BASE_PATH, SIDFWBASE, SIRPVERSION def nest_mult(expr): @@ -171,6 +172,11 @@ def main(): datatype=XSD.string)) ) + # SemVer + version_iri = URIRef(SIDFWBASE + "/" + SIRPVERSION + "/units/") + units_graph.add((URIRef(si_graph.namespace_units), OWL.versionIRI, version_iri)) + units_graph.add((URIRef(si_graph.namespace_units), OWL.versionInfo, Literal(SIRPVERSION, datatype=XSD.string))) + # 2.2 Versioning (using PROVENANCE vocabulary) timestamp = datetime.now(timezone.utc) # get the system time (in UTC) uri_timestamp = timestamp.strftime("%Y%m%d%H%M%SZ") # used to identify uniquely the produced TTL file (entity) diff --git a/src/si_ref_point/settings.py b/src/si_ref_point/settings.py index 150961e..41cd78c 100644 --- a/src/si_ref_point/settings.py +++ b/src/si_ref_point/settings.py @@ -11,6 +11,7 @@ SKOSURL = "http://www.w3.org/2004/02/skos/core#" DCTURL = "http://purl.org/dc/terms#" SIDFWBASE = "https://si-digital-framework.org" +SIRPVERSION = "1.0.0" # Base URL for the SI Digital Framework # from this URL, sub-URLs are defined @@ -35,7 +36,7 @@ # TTL_FILES_FOLDER = TTLPATH # JSONLD_FILES_FOLDER = JLDPATH -GITHUB_BASE_PATH = "https://github.com/TheBIPM/SI-Reference-Point-2023/" +GITHUB_BASE_PATH = "https://github.com/TheBIPM/SI-Reference-Point-generation-scripts/" # SI_BROCHURE_PID="SI_Brochure_ed3_V3_01" # will be transformed into a PID '(SIDFWBASE)/SI/entities/(SI_BROCHURE_PID)' diff --git a/src/si_ref_point/tboxes/rb_tbox.py b/src/si_ref_point/tboxes/rb_tbox.py index 17bf6bd..3b3a850 100644 --- a/src/si_ref_point/tboxes/rb_tbox.py +++ b/src/si_ref_point/tboxes/rb_tbox.py @@ -2,13 +2,18 @@ from datetime import date from rdflib import URIRef, RDF, OWL, SKOS, XSD, RDFS, DCTERMS, Graph, Literal -from si_ref_point.settings import SIDFWBASE, SKOSURL +from si_ref_point.settings import SIDFWBASE, SKOSURL, SIRPVERSION RES_BOD_NS = SIDFWBASE + "/bodies#" class ResBod: def __init__(self, namespace: str = RES_BOD_NS, prefix: str = 'rb'): + + # 1) Define namespaces self.namespace = namespace + + # 2) Add annotations to the ontology + # 2.1 General annotations (type, comments etc) self._g = Graph() # a triple store as the main data structure self._g.bind(prefix, namespace) self._g.bind("skos", SKOSURL) @@ -21,6 +26,14 @@ def __init__(self, namespace: str = RES_BOD_NS, prefix: str = 'rb'): "resolutions, decisions, etc", datatype=XSD.string))) self._g.add((URIRef(RES_BOD_NS), DCTERMS.created, Literal(str(date.today()), datatype=XSD.date))) + # 2.2 Versioning + + version_iri = URIRef(SIDFWBASE + "/" + SIRPVERSION + "/bodies#") + self._g.add((URIRef(self.namespace), OWL.versionIRI, version_iri)) + self._g.add((URIRef(self.namespace), OWL.versionInfo, Literal(SIRPVERSION, datatype=XSD.string))) + + + # 3) Define classes and predicates used by different A boxes self.ResBod = self.set_uri('ResBod') self._g.add((self.ResBod, RDF.type, SKOS.Concept)) self._g.add((self.ResBod, RDFS.label, Literal('Responsible Body', lang='en'))) diff --git a/src/si_ref_point/tboxes/si_tbox.py b/src/si_ref_point/tboxes/si_tbox.py index ef95401..795c434 100644 --- a/src/si_ref_point/tboxes/si_tbox.py +++ b/src/si_ref_point/tboxes/si_tbox.py @@ -8,7 +8,9 @@ from rdflib import Graph, OWL, RDF, RDFS, URIRef, Literal, BNode, SKOS, PROV from rdflib.collection import Collection from rdflib.namespace import XSD, DCTERMS -from si_ref_point.settings import PKG_ROOT, CC_LICENCE, CC_LICENCE_TEXT_EN, CC_LICENCE_TEXT_FR, SI_FILES_FOLDER, GITHUB_BASE_PATH, SIDFWBASE +from si_ref_point.settings import PKG_ROOT, CC_LICENCE, CC_LICENCE_TEXT_EN, CC_LICENCE_TEXT_FR, SI_FILES_FOLDER, \ + GITHUB_BASE_PATH, SIDFWBASE, SIRPVERSION + RES_BOD_NS = SIDFWBASE + "/bodies#" bodies_list = ['cgpm', 'cipm', 'cctf'] @@ -36,6 +38,9 @@ def __init__(self, namespace: str = SIDFWBASE + "/SI#", ns_prefix: str = "si"): self.namespace_constants = SIDFWBASE + "/constants/" # Explicitly binding a constants namespace to the URI self.g.bind("constants", self.namespace_constants) + + # Explicitly binding a decisions namespace to the URI + self.g.bind("decisions", self.namespace_decisions) # Define the namespaces within (base)/bodies # ~/bodies @@ -94,6 +99,10 @@ def __init__(self, namespace: str = SIDFWBASE + "/SI#", ns_prefix: str = "si"): uri_timestamp = timestamp.strftime("%Y%m%d%H%M%SZ") # used to identify uniquely the produced TTL file (entity) startedAt_timestamp = timestamp.strftime("%Y-%m-%dT%H:%M:%SZ") # used with the predicate 'startedAtTime' of the corresponding activity + version_iri = URIRef(SIDFWBASE + "/" + SIRPVERSION + "/SI#") + self.g.add((URIRef(self.namespace), OWL.versionIRI, version_iri)) + self.g.add((URIRef(self.namespace), OWL.versionInfo, Literal(SIRPVERSION, datatype=XSD.string))) + ### `generate_turtle_files` repo = git.Repo(PKG_ROOT, search_parent_directories=True) sha = repo.head.object.hexsha