1# SPDX-FileCopyrightText: 2023 spdx contributors
2#
3# SPDX-License-Identifier: Apache-2.0
4from datetime import datetime
5from enum import Enum
6
7from beartype.typing import Any, List
8from semantic_version import Version
9
10from spdx_tools.spdx3.model.creation_info import CreationInfo
11from spdx_tools.spdx3.model.hash import Hash
12from spdx_tools.spdx3.payload import Payload
13from spdx_tools.spdx.casing_tools import snake_case_to_camel_case
14from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string
15
16
17def convert_payload_to_json_ld_list_of_elements(payload: Payload) -> List:
18 element_list = []
19
20 for element in payload.get_full_map().values():
21 element_dict = _convert_to_json_ld_dict(element)
22 element_list.append(element_dict)
23
24 return element_list
25
26
27def _convert_to_json_ld_dict(element: Any, alt_creation_info=False, alt_hash=False):
28 if not element:
29 return None
30
31 if isinstance(element, (str, int, tuple)):
32 return element
33
34 if isinstance(element, Version):
35 return str(element)
36
37 if isinstance(element, datetime):
38 return datetime_to_iso_string(element)
39
40 if isinstance(element, Enum):
41 return snake_case_to_camel_case(element.name)
42
43 if isinstance(element, list):
44 return [_convert_to_json_ld_dict(item) for item in element if item]
45
46 if alt_hash and isinstance(element, Hash):
47 hash_dict = {element.algorithm.name: element.hash_value}
48 if element.comment:
49 hash_dict["comment"] = element.comment
50 return hash_dict
51
52 # if issubclass(element.__class__, Element):
53 # element_dict = {"@type": element.__class__.__name__}
54 # else:
55 # element_dict = {} # typing of non-Element classes should be handled by the @context, I think
56
57 element_dict = {"@type": element.__class__.__name__}
58
59 for attribute_name in vars(element):
60 attribute_value = getattr(element, attribute_name)
61
62 if alt_creation_info and isinstance(attribute_value, CreationInfo):
63 for creation_info_attr_name in vars(attribute_value):
64 creation_info_attr_value = getattr(attribute_value, creation_info_attr_name)
65 element_dict[snake_case_to_camel_case(creation_info_attr_name)] = _convert_to_json_ld_dict(
66 creation_info_attr_value
67 )
68
69 elif attribute_value:
70 if attribute_name == "_spdx_id":
71 attribute_name = "@id"
72 elif attribute_name == "_from_element":
73 attribute_name = "from"
74 else:
75 attribute_name = snake_case_to_camel_case(attribute_name)
76
77 element_dict[attribute_name] = _convert_to_json_ld_dict(attribute_value)
78
79 return element_dict