spdx_tools.spdx.writer.rdf.package_writer

  1# SPDX-FileCopyrightText: 2023 spdx contributors
  2#
  3# SPDX-License-Identifier: Apache-2.0
  4from beartype.typing import Dict
  5from rdflib import DOAP, RDF, RDFS, XSD, BNode, Graph, Literal, URIRef
  6
  7from spdx_tools.spdx.casing_tools import snake_case_to_camel_case
  8from spdx_tools.spdx.model import ExternalPackageRef, Package, PackageVerificationCode
  9from spdx_tools.spdx.model.package import CATEGORY_TO_EXTERNAL_PACKAGE_REF_TYPES
 10from spdx_tools.spdx.rdfschema.namespace import REFERENCE_NAMESPACE, SPDX_NAMESPACE
 11from spdx_tools.spdx.writer.rdf.checksum_writer import add_checksum_to_graph
 12from spdx_tools.spdx.writer.rdf.license_expression_writer import add_license_expression_or_none_or_no_assertion
 13from spdx_tools.spdx.writer.rdf.writer_utils import (
 14    add_datetime_to_graph,
 15    add_literal_or_no_assertion_or_none,
 16    add_namespace_to_spdx_id,
 17    add_optional_literal,
 18)
 19
 20
 21def add_package_to_graph(
 22    package: Package, graph: Graph, doc_namespace: str, external_doc_ref_to_namespace: Dict[str, str]
 23):
 24    package_resource = URIRef(add_namespace_to_spdx_id(package.spdx_id, doc_namespace, external_doc_ref_to_namespace))
 25    graph.add((package_resource, RDF.type, SPDX_NAMESPACE.Package))
 26
 27    graph.add((package_resource, SPDX_NAMESPACE.name, Literal(package.name)))
 28    add_optional_literal(package.version, graph, package_resource, SPDX_NAMESPACE.versionInfo)
 29    add_optional_literal(package.file_name, graph, package_resource, SPDX_NAMESPACE.packageFileName)
 30    add_optional_literal(package.supplier, graph, package_resource, SPDX_NAMESPACE.supplier)
 31    add_optional_literal(package.originator, graph, package_resource, SPDX_NAMESPACE.originator)
 32    add_literal_or_no_assertion_or_none(
 33        package.download_location, graph, package_resource, SPDX_NAMESPACE.downloadLocation
 34    )
 35    graph.add((package_resource, SPDX_NAMESPACE.filesAnalyzed, Literal(package.files_analyzed, datatype=XSD.boolean)))
 36    add_package_verification_code_to_graph(package.verification_code, graph, package_resource)
 37    for checksum in package.checksums:
 38        add_checksum_to_graph(checksum, graph, package_resource)
 39
 40    add_optional_literal(package.homepage, graph, package_resource, DOAP.homepage)
 41    add_optional_literal(package.source_info, graph, package_resource, SPDX_NAMESPACE.sourceInfo)
 42    add_license_expression_or_none_or_no_assertion(
 43        package.license_concluded, graph, package_resource, SPDX_NAMESPACE.licenseConcluded, doc_namespace
 44    )
 45    add_license_expression_or_none_or_no_assertion(
 46        package.license_info_from_files, graph, package_resource, SPDX_NAMESPACE.licenseInfoFromFiles, doc_namespace
 47    )
 48    add_license_expression_or_none_or_no_assertion(
 49        package.license_declared, graph, package_resource, SPDX_NAMESPACE.licenseDeclared, doc_namespace
 50    )
 51    add_optional_literal(package.license_comment, graph, package_resource, SPDX_NAMESPACE.licenseComments)
 52    add_optional_literal(package.copyright_text, graph, package_resource, SPDX_NAMESPACE.copyrightText)
 53    add_optional_literal(package.summary, graph, package_resource, SPDX_NAMESPACE.summary)
 54    add_optional_literal(package.description, graph, package_resource, SPDX_NAMESPACE.description)
 55    add_optional_literal(package.comment, graph, package_resource, RDFS.comment)
 56    for external_reference in package.external_references:
 57        add_external_package_ref_to_graph(external_reference, graph, package_resource, doc_namespace)
 58    for attribution_text in package.attribution_texts:
 59        add_optional_literal(attribution_text, graph, package_resource, SPDX_NAMESPACE.attributionText)
 60    if package.primary_package_purpose:
 61        graph.add(
 62            (
 63                package_resource,
 64                SPDX_NAMESPACE.primaryPackagePurpose,
 65                SPDX_NAMESPACE[f"purpose_{snake_case_to_camel_case(package.primary_package_purpose.name)}"],
 66            )
 67        )
 68
 69    add_datetime_to_graph(package.release_date, graph, package_resource, SPDX_NAMESPACE.releaseDate)
 70    add_datetime_to_graph(package.built_date, graph, package_resource, SPDX_NAMESPACE.builtDate)
 71    add_datetime_to_graph(package.valid_until_date, graph, package_resource, SPDX_NAMESPACE.validUntilDate)
 72
 73
 74def add_package_verification_code_to_graph(
 75    package_verification_code: PackageVerificationCode, graph: Graph, package_node: URIRef
 76):
 77    if not package_verification_code:
 78        return
 79    package_verification_code_node = BNode()
 80    graph.add((package_verification_code_node, RDF.type, SPDX_NAMESPACE.PackageVerificationCode))
 81    graph.add(
 82        (
 83            package_verification_code_node,
 84            SPDX_NAMESPACE.packageVerificationCodeValue,
 85            Literal(package_verification_code.value),
 86        )
 87    )
 88    for excluded_file in package_verification_code.excluded_files:
 89        graph.add(
 90            (
 91                package_verification_code_node,
 92                SPDX_NAMESPACE.packageVerificationCodeExcludedFile,
 93                Literal(excluded_file),
 94            )
 95        )
 96
 97    graph.add((package_node, SPDX_NAMESPACE.packageVerificationCode, package_verification_code_node))
 98
 99
100def add_external_package_ref_to_graph(
101    external_package_ref: ExternalPackageRef, graph: Graph, package_node: URIRef, doc_namespace: str
102):
103    external_package_ref_node = BNode()
104    graph.add((external_package_ref_node, RDF.type, SPDX_NAMESPACE.ExternalRef))
105    graph.add(
106        (
107            external_package_ref_node,
108            SPDX_NAMESPACE.referenceCategory,
109            SPDX_NAMESPACE[f"referenceCategory_{snake_case_to_camel_case(external_package_ref.category.name)}"],
110        )
111    )
112
113    if external_package_ref.reference_type in CATEGORY_TO_EXTERNAL_PACKAGE_REF_TYPES[external_package_ref.category]:
114        graph.add(
115            (
116                external_package_ref_node,
117                SPDX_NAMESPACE.referenceType,
118                REFERENCE_NAMESPACE[external_package_ref.reference_type],
119            )
120        )
121    else:
122        graph.add(
123            (
124                external_package_ref_node,
125                SPDX_NAMESPACE.referenceType,
126                URIRef(f"{doc_namespace}#{external_package_ref.reference_type}"),
127            )
128        )
129    graph.add((external_package_ref_node, SPDX_NAMESPACE.referenceLocator, Literal(external_package_ref.locator)))
130    if external_package_ref.comment:
131        graph.add((external_package_ref_node, RDFS.comment, Literal(external_package_ref.comment)))
132
133    graph.add((package_node, SPDX_NAMESPACE.externalRef, external_package_ref_node))
def add_package_to_graph( package: spdx_tools.spdx.model.package.Package, graph: rdflib.graph.Graph, doc_namespace: str, external_doc_ref_to_namespace: dict[str, str]):
22def add_package_to_graph(
23    package: Package, graph: Graph, doc_namespace: str, external_doc_ref_to_namespace: Dict[str, str]
24):
25    package_resource = URIRef(add_namespace_to_spdx_id(package.spdx_id, doc_namespace, external_doc_ref_to_namespace))
26    graph.add((package_resource, RDF.type, SPDX_NAMESPACE.Package))
27
28    graph.add((package_resource, SPDX_NAMESPACE.name, Literal(package.name)))
29    add_optional_literal(package.version, graph, package_resource, SPDX_NAMESPACE.versionInfo)
30    add_optional_literal(package.file_name, graph, package_resource, SPDX_NAMESPACE.packageFileName)
31    add_optional_literal(package.supplier, graph, package_resource, SPDX_NAMESPACE.supplier)
32    add_optional_literal(package.originator, graph, package_resource, SPDX_NAMESPACE.originator)
33    add_literal_or_no_assertion_or_none(
34        package.download_location, graph, package_resource, SPDX_NAMESPACE.downloadLocation
35    )
36    graph.add((package_resource, SPDX_NAMESPACE.filesAnalyzed, Literal(package.files_analyzed, datatype=XSD.boolean)))
37    add_package_verification_code_to_graph(package.verification_code, graph, package_resource)
38    for checksum in package.checksums:
39        add_checksum_to_graph(checksum, graph, package_resource)
40
41    add_optional_literal(package.homepage, graph, package_resource, DOAP.homepage)
42    add_optional_literal(package.source_info, graph, package_resource, SPDX_NAMESPACE.sourceInfo)
43    add_license_expression_or_none_or_no_assertion(
44        package.license_concluded, graph, package_resource, SPDX_NAMESPACE.licenseConcluded, doc_namespace
45    )
46    add_license_expression_or_none_or_no_assertion(
47        package.license_info_from_files, graph, package_resource, SPDX_NAMESPACE.licenseInfoFromFiles, doc_namespace
48    )
49    add_license_expression_or_none_or_no_assertion(
50        package.license_declared, graph, package_resource, SPDX_NAMESPACE.licenseDeclared, doc_namespace
51    )
52    add_optional_literal(package.license_comment, graph, package_resource, SPDX_NAMESPACE.licenseComments)
53    add_optional_literal(package.copyright_text, graph, package_resource, SPDX_NAMESPACE.copyrightText)
54    add_optional_literal(package.summary, graph, package_resource, SPDX_NAMESPACE.summary)
55    add_optional_literal(package.description, graph, package_resource, SPDX_NAMESPACE.description)
56    add_optional_literal(package.comment, graph, package_resource, RDFS.comment)
57    for external_reference in package.external_references:
58        add_external_package_ref_to_graph(external_reference, graph, package_resource, doc_namespace)
59    for attribution_text in package.attribution_texts:
60        add_optional_literal(attribution_text, graph, package_resource, SPDX_NAMESPACE.attributionText)
61    if package.primary_package_purpose:
62        graph.add(
63            (
64                package_resource,
65                SPDX_NAMESPACE.primaryPackagePurpose,
66                SPDX_NAMESPACE[f"purpose_{snake_case_to_camel_case(package.primary_package_purpose.name)}"],
67            )
68        )
69
70    add_datetime_to_graph(package.release_date, graph, package_resource, SPDX_NAMESPACE.releaseDate)
71    add_datetime_to_graph(package.built_date, graph, package_resource, SPDX_NAMESPACE.builtDate)
72    add_datetime_to_graph(package.valid_until_date, graph, package_resource, SPDX_NAMESPACE.validUntilDate)
def add_package_verification_code_to_graph( package_verification_code: spdx_tools.spdx.model.package.PackageVerificationCode, graph: rdflib.graph.Graph, package_node: rdflib.term.URIRef):
75def add_package_verification_code_to_graph(
76    package_verification_code: PackageVerificationCode, graph: Graph, package_node: URIRef
77):
78    if not package_verification_code:
79        return
80    package_verification_code_node = BNode()
81    graph.add((package_verification_code_node, RDF.type, SPDX_NAMESPACE.PackageVerificationCode))
82    graph.add(
83        (
84            package_verification_code_node,
85            SPDX_NAMESPACE.packageVerificationCodeValue,
86            Literal(package_verification_code.value),
87        )
88    )
89    for excluded_file in package_verification_code.excluded_files:
90        graph.add(
91            (
92                package_verification_code_node,
93                SPDX_NAMESPACE.packageVerificationCodeExcludedFile,
94                Literal(excluded_file),
95            )
96        )
97
98    graph.add((package_node, SPDX_NAMESPACE.packageVerificationCode, package_verification_code_node))
def add_external_package_ref_to_graph( external_package_ref: spdx_tools.spdx.model.package.ExternalPackageRef, graph: rdflib.graph.Graph, package_node: rdflib.term.URIRef, doc_namespace: str):
101def add_external_package_ref_to_graph(
102    external_package_ref: ExternalPackageRef, graph: Graph, package_node: URIRef, doc_namespace: str
103):
104    external_package_ref_node = BNode()
105    graph.add((external_package_ref_node, RDF.type, SPDX_NAMESPACE.ExternalRef))
106    graph.add(
107        (
108            external_package_ref_node,
109            SPDX_NAMESPACE.referenceCategory,
110            SPDX_NAMESPACE[f"referenceCategory_{snake_case_to_camel_case(external_package_ref.category.name)}"],
111        )
112    )
113
114    if external_package_ref.reference_type in CATEGORY_TO_EXTERNAL_PACKAGE_REF_TYPES[external_package_ref.category]:
115        graph.add(
116            (
117                external_package_ref_node,
118                SPDX_NAMESPACE.referenceType,
119                REFERENCE_NAMESPACE[external_package_ref.reference_type],
120            )
121        )
122    else:
123        graph.add(
124            (
125                external_package_ref_node,
126                SPDX_NAMESPACE.referenceType,
127                URIRef(f"{doc_namespace}#{external_package_ref.reference_type}"),
128            )
129        )
130    graph.add((external_package_ref_node, SPDX_NAMESPACE.referenceLocator, Literal(external_package_ref.locator)))
131    if external_package_ref.comment:
132        graph.add((external_package_ref_node, RDFS.comment, Literal(external_package_ref.comment)))
133
134    graph.add((package_node, SPDX_NAMESPACE.externalRef, external_package_ref_node))