spdx_tools.spdx3.writer.json_ld.owl_to_context
1# SPDX-FileCopyrightText: 2023 spdx contributors 2# 3# SPDX-License-Identifier: Apache-2.0 4import json 5import os.path 6 7# current workflow: markdown files + spec_parser -> model.ttl -> convert to json_ld: SPDX_OWL.json -> 8# use the function below to generate context.json 9# properties with Enum range should look like this (probably), so that their values are automatically appended 10# with the Enum URI: 11# "annotationType": { 12# "@id": "core:annotationType", 13# "@type": "@vocab", 14# "@context": { 15# "@vocab": "core:AnnotationType/" 16# } 17# }, 18 19PROPERTIES_WITH_ENUM_RANGE = [ 20 "safetyRiskAssessment", 21 "sensitivePersonalInformation", 22 "annotationType", 23 "externalIdentifierType", 24 "externalReferenceType", 25 "algorithm", 26 "scope", 27 "profile", 28 "completeness", 29 "relationshipType", 30 "confidentialityLevel", 31 "datasetAvailability", 32 "decisionType", 33 "justificationType", 34 "catalogType", 35 "conditionality", 36 "sbomType", 37 "softwareLinkage", 38 "purpose", 39] 40 41REFERENCE_PROPERTY_TYPES = [ 42 "core:Element", 43 "core:Agent", 44] 45 46 47def convert_spdx_owl_to_jsonld_context(spdx_owl: str = "SPDX_OWL.json"): 48 with open(spdx_owl, "r") as infile: 49 owl_dict = json.load(infile) 50 51 context_dict = owl_dict["@context"] 52 53 for node in owl_dict["@graph"]: 54 # print(node) 55 node_type = node.get("@type") 56 if not node_type: 57 # print(node) 58 continue 59 60 if "owl:NamedIndividual" in node_type: 61 continue 62 elif node_type in ["owl:DatatypeProperty", "owl:ObjectProperty"]: 63 name = node["@id"].split(":")[-1] 64 type_id = node["rdfs:range"]["@id"] 65 66 if name in context_dict and context_dict[name]["@id"].startswith("core"): 67 # if in doubt, prioritize core properties 68 continue 69 70 if name in PROPERTIES_WITH_ENUM_RANGE: 71 if name == "profile": 72 # FIXME: since the allowed values for the profile enum collide with 73 # our namespaces, we need to explicitly remap their meaning in the context 74 context_dict[name] = { 75 "@id": node["@id"], 76 "@type": "@vocab", 77 "@context": { 78 "core": "https://spdx.org/rdf/Core/ProfileIdentifierType/core", 79 "software": "https://spdx.org/rdf/Core/ProfileIdentifierType/software", 80 "licensing": "https://spdx.org/rdf/Core/ProfileIdentifierType/licensing", 81 "security": "https://spdx.org/rdf/Core/ProfileIdentifierType/security", 82 "build": "https://spdx.org/rdf/Core/ProfileIdentifierType/build", 83 "ai": "https://spdx.org/rdf/Core/ProfileIdentifierType/ai", 84 "dataset": "https://spdx.org/rdf/Core/ProfileIdentifierType/dataset", 85 "usage": "https://spdx.org/rdf/Core/ProfileIdentifierType/usage", 86 "extension": "https://spdx.org/rdf/Core/ProfileIdentifierType/extension", 87 }, 88 } 89 else: 90 context_dict[name] = { 91 "@id": node["@id"], 92 "@type": "@vocab", 93 "@context": {"@vocab": type_id + "/"}, 94 } 95 elif node_type == "owl:ObjectProperty" and type_id in REFERENCE_PROPERTY_TYPES: 96 context_dict[name] = {"@id": node["@id"], "@type": "@id"} 97 else: 98 context_dict[name] = {"@id": node["@id"], "@type": type_id} 99 100 elif node_type == "owl:Class": 101 name = node["@id"].split(":")[-1] 102 context_dict[name] = node["@id"] 103 104 elif isinstance(node_type, list): 105 name = node["@id"].split(":")[-1] 106 context_dict[name] = node["@id"] 107 108 else: 109 print(f"unknown node_type: {node_type}") 110 111 with open(os.path.join(os.path.dirname(__file__), "context.json"), "w") as infile: 112 json.dump(context_dict, infile) 113 114 115if __name__ == "__main__": 116 convert_spdx_owl_to_jsonld_context("SPDX_OWL.json")
PROPERTIES_WITH_ENUM_RANGE =
['safetyRiskAssessment', 'sensitivePersonalInformation', 'annotationType', 'externalIdentifierType', 'externalReferenceType', 'algorithm', 'scope', 'profile', 'completeness', 'relationshipType', 'confidentialityLevel', 'datasetAvailability', 'decisionType', 'justificationType', 'catalogType', 'conditionality', 'sbomType', 'softwareLinkage', 'purpose']
REFERENCE_PROPERTY_TYPES =
['core:Element', 'core:Agent']
def
convert_spdx_owl_to_jsonld_context(spdx_owl: str = 'SPDX_OWL.json'):
48def convert_spdx_owl_to_jsonld_context(spdx_owl: str = "SPDX_OWL.json"): 49 with open(spdx_owl, "r") as infile: 50 owl_dict = json.load(infile) 51 52 context_dict = owl_dict["@context"] 53 54 for node in owl_dict["@graph"]: 55 # print(node) 56 node_type = node.get("@type") 57 if not node_type: 58 # print(node) 59 continue 60 61 if "owl:NamedIndividual" in node_type: 62 continue 63 elif node_type in ["owl:DatatypeProperty", "owl:ObjectProperty"]: 64 name = node["@id"].split(":")[-1] 65 type_id = node["rdfs:range"]["@id"] 66 67 if name in context_dict and context_dict[name]["@id"].startswith("core"): 68 # if in doubt, prioritize core properties 69 continue 70 71 if name in PROPERTIES_WITH_ENUM_RANGE: 72 if name == "profile": 73 # FIXME: since the allowed values for the profile enum collide with 74 # our namespaces, we need to explicitly remap their meaning in the context 75 context_dict[name] = { 76 "@id": node["@id"], 77 "@type": "@vocab", 78 "@context": { 79 "core": "https://spdx.org/rdf/Core/ProfileIdentifierType/core", 80 "software": "https://spdx.org/rdf/Core/ProfileIdentifierType/software", 81 "licensing": "https://spdx.org/rdf/Core/ProfileIdentifierType/licensing", 82 "security": "https://spdx.org/rdf/Core/ProfileIdentifierType/security", 83 "build": "https://spdx.org/rdf/Core/ProfileIdentifierType/build", 84 "ai": "https://spdx.org/rdf/Core/ProfileIdentifierType/ai", 85 "dataset": "https://spdx.org/rdf/Core/ProfileIdentifierType/dataset", 86 "usage": "https://spdx.org/rdf/Core/ProfileIdentifierType/usage", 87 "extension": "https://spdx.org/rdf/Core/ProfileIdentifierType/extension", 88 }, 89 } 90 else: 91 context_dict[name] = { 92 "@id": node["@id"], 93 "@type": "@vocab", 94 "@context": {"@vocab": type_id + "/"}, 95 } 96 elif node_type == "owl:ObjectProperty" and type_id in REFERENCE_PROPERTY_TYPES: 97 context_dict[name] = {"@id": node["@id"], "@type": "@id"} 98 else: 99 context_dict[name] = {"@id": node["@id"], "@type": type_id} 100 101 elif node_type == "owl:Class": 102 name = node["@id"].split(":")[-1] 103 context_dict[name] = node["@id"] 104 105 elif isinstance(node_type, list): 106 name = node["@id"].split(":")[-1] 107 context_dict[name] = node["@id"] 108 109 else: 110 print(f"unknown node_type: {node_type}") 111 112 with open(os.path.join(os.path.dirname(__file__), "context.json"), "w") as infile: 113 json.dump(context_dict, infile)