1import json
2from importlib import resources
3from typing import Dict, Any, List
4
5from colander_data_converter.base.models import ColanderRepository
6from colander_data_converter.converters.threatr.models import ThreatrRepository
7
8resource_package = __name__
9
10
[docs]
11class ThreatrMappingLoader:
12 """
13 Loads and provides access to the Threatr to Colander mapping data.
14
15 This class is responsible for loading the mapping configuration from a JSON file
16 that defines how Threatr entities, events, and relations should be converted to
17 their Colander equivalents. The mapping data includes field mappings, type
18 conversions, and relationship definitions.
19
20 Note:
21 The mapping data is loaded once during initialization and cached for
22 subsequent use.
23
24 Attributes:
25 mapping_data: The loaded mapping data
26
27 Example:
28 >>> loader = ThreatrMappingLoader()
29 >>> mappings = loader.mapping_data
30 >>> isinstance(mappings, list)
31 True
32 """
33
[docs]
34 def __init__(self):
35 """
36 Initialize the mapping loader and load the mapping data.
37
38 Raises:
39 ValueError: If the mapping file cannot be found or parsed
40 """
41 self.mapping_data = self._load_mapping_data()
42
43 @staticmethod
44 def _load_mapping_data() -> List[Dict[str, Any]]:
45 """
46 Load the mapping data from the JSON file.
47
48 This method reads the mapping configuration from the JSON file located at
49 ``data/threatr_colander_mapping.json`` relative to this module's package.
50
51 Returns:
52 The mapping data loaded from the JSON file
53
54 Raises:
55 ValueError: If the file cannot be found or contains invalid JSON
56 FileNotFoundError: If the mapping file does not exist
57 ~json.JSONDecodeError: If the mapping file contains malformed JSON
58
59 Important:
60 The JSON file must contain a root object with a "mapping" key that holds
61 an array of mapping definitions.
62 """
63 json_file = resources.files(resource_package).joinpath("data").joinpath("threatr_colander_mapping.json")
64 try:
65 with json_file.open() as f:
66 return json.load(f).get("mapping")
67 except (FileNotFoundError, json.JSONDecodeError) as e:
68 raise ValueError(f"Failed to load mapping data: {e}")
69
70
[docs]
71class ThreatrMapper:
72 """
73 Base class for mapping between Threatr and Colander data using the mapping file.
74
75 This abstract base class provides common functionality for all Threatr to Colander
76 mappers. It initializes the mapping loader and provides access to the mapping
77 data that defines how different data formats should be converted between the
78 two systems.
79
80 Attributes:
81 mapping_loader: Instance of ThreatrMappingLoader for accessing mapping data
82
83 Note:
84 This is a base class that should be subclassed by specific mapper
85 implementations. The mapping data is loaded once and shared across
86 all mapper instances.
87
88 Example:
89 >>> class CustomMapper(ThreatrMapper):
90 ... def __init__(self):
91 ... super().__init__()
92 ...
93 >>> mapper = CustomMapper()
94 >>> hasattr(mapper, 'mapping_loader')
95 True
96 """
97
[docs]
98 def __init__(self):
99 """
100 Initialize the mapper with the mapping loader.
101
102 Creates an instance of ThreatrMappingLoader to provide access to the
103 mapping configuration data. This data will be used by subclasses to
104 perform the actual conversion between Threatr and Colander formats.
105 """
106 self.mapping_loader = ThreatrMappingLoader()
107 ColanderRepository().clear()
108 ThreatrRepository().clear()