compressedfhir 0.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of compressedfhir might be problematic. Click here for more details.

Files changed (41) hide show
  1. compressedfhir/__init__.py +0 -0
  2. compressedfhir/fhir/__init__.py +0 -0
  3. compressedfhir/fhir/base_resource_list.py +165 -0
  4. compressedfhir/fhir/fhir_bundle.py +291 -0
  5. compressedfhir/fhir/fhir_bundle_entry.py +234 -0
  6. compressedfhir/fhir/fhir_bundle_entry_list.py +82 -0
  7. compressedfhir/fhir/fhir_bundle_entry_request.py +71 -0
  8. compressedfhir/fhir/fhir_bundle_entry_response.py +64 -0
  9. compressedfhir/fhir/fhir_bundle_entry_search.py +75 -0
  10. compressedfhir/fhir/fhir_identifier.py +84 -0
  11. compressedfhir/fhir/fhir_link.py +63 -0
  12. compressedfhir/fhir/fhir_meta.py +47 -0
  13. compressedfhir/fhir/fhir_resource.py +163 -0
  14. compressedfhir/fhir/fhir_resource_list.py +143 -0
  15. compressedfhir/fhir/fhir_resource_map.py +193 -0
  16. compressedfhir/fhir/test/__init__.py +0 -0
  17. compressedfhir/fhir/test/test_bundle_entry.py +129 -0
  18. compressedfhir/fhir/test/test_bundle_entry_list.py +187 -0
  19. compressedfhir/fhir/test/test_bundle_entry_request.py +74 -0
  20. compressedfhir/fhir/test/test_bundle_entry_response.py +65 -0
  21. compressedfhir/fhir/test/test_fhir_bundle.py +245 -0
  22. compressedfhir/fhir/test/test_fhir_resource.py +225 -0
  23. compressedfhir/fhir/test/test_fhir_resource_list.py +160 -0
  24. compressedfhir/fhir/test/test_fhir_resource_map.py +293 -0
  25. compressedfhir/py.typed +0 -0
  26. compressedfhir/utilities/__init__.py +0 -0
  27. compressedfhir/utilities/compressed_dict/__init__.py +0 -0
  28. compressedfhir/utilities/compressed_dict/v1/__init__.py +0 -0
  29. compressedfhir/utilities/compressed_dict/v1/compressed_dict.py +635 -0
  30. compressedfhir/utilities/compressed_dict/v1/compressed_dict_access_error.py +2 -0
  31. compressedfhir/utilities/compressed_dict/v1/compressed_dict_storage_mode.py +50 -0
  32. compressedfhir/utilities/compressed_dict/v1/test/__init__.py +0 -0
  33. compressedfhir/utilities/compressed_dict/v1/test/test_compressed_dict.py +360 -0
  34. compressedfhir/utilities/fhir_json_encoder.py +30 -0
  35. compressedfhir/utilities/json_helpers.py +181 -0
  36. compressedfhir-0.0.1.dist-info/METADATA +28 -0
  37. compressedfhir-0.0.1.dist-info/RECORD +41 -0
  38. compressedfhir-0.0.1.dist-info/WHEEL +5 -0
  39. compressedfhir-0.0.1.dist-info/licenses/LICENSE +201 -0
  40. compressedfhir-0.0.1.dist-info/top_level.txt +2 -0
  41. tests/__init__.py +0 -0
File without changes
File without changes
@@ -0,0 +1,165 @@
1
+ import copy
2
+ import json
3
+ from contextlib import contextmanager
4
+ from typing import (
5
+ Deque,
6
+ List,
7
+ AsyncGenerator,
8
+ Optional,
9
+ Any,
10
+ Dict,
11
+ Iterator,
12
+ override,
13
+ Iterable,
14
+ Generator,
15
+ )
16
+
17
+ from compressedfhir.utilities.compressed_dict.v1.compressed_dict import (
18
+ CompressedDict,
19
+ )
20
+ from compressedfhir.utilities.fhir_json_encoder import FhirJSONEncoder
21
+
22
+
23
+ class BaseResourceList[T: CompressedDict[str, Any]](Deque[T]):
24
+ """
25
+ Represents a list of FHIR resources.
26
+ """
27
+
28
+ __slots__: List[str] = []
29
+
30
+ def __init__(
31
+ self,
32
+ iterable: Iterable[T] | None = None,
33
+ maxlen: Optional[int] = None,
34
+ ) -> None:
35
+ # if iterable is not None:
36
+ # assert all([isinstance(r, CompressedDict) for r in iterable]), f"type {type(next(iter(iterable)))}"
37
+ super().__init__(iterable, maxlen=maxlen) if iterable else super().__init__()
38
+
39
+ @override
40
+ def append(self, x: T, /) -> None:
41
+ super().append(x)
42
+ # assert isinstance(x, CompressedDict), f"{type(x)} is not a CompressedDict"
43
+
44
+ def json(self) -> str:
45
+ """
46
+ Convert the list of FhirResource objects to a JSON string.
47
+
48
+ :return: JSON string representation of the list.
49
+ """
50
+ return json.dumps([r.dict() for r in self], cls=FhirJSONEncoder)
51
+
52
+ def get_resources(self) -> "BaseResourceList[T]":
53
+ """
54
+ Get all resources in the list.
55
+
56
+ :return: A list of FhirResource objects.
57
+ """
58
+ # this is here to keep compatibility with FhirResourceMap
59
+ return self
60
+
61
+ async def consume_resource_batch_async(
62
+ self,
63
+ *,
64
+ batch_size: Optional[int],
65
+ ) -> AsyncGenerator["BaseResourceList[T]", None]:
66
+ """
67
+ Consume resources in batches asynchronously.
68
+
69
+ :param batch_size: The size of each batch.
70
+ :return: An async generator yielding batches of FhirResourceList.
71
+ """
72
+ batch: BaseResourceList[T]
73
+ if batch_size is None:
74
+ batch = BaseResourceList[T]()
75
+ while self:
76
+ batch.append(self.popleft())
77
+ yield batch
78
+ elif batch_size <= 0:
79
+ raise ValueError("Batch size must be greater than 0.")
80
+ else:
81
+ while self:
82
+ batch = BaseResourceList[T]()
83
+ for _ in range(min(batch_size, len(self))):
84
+ batch.append(self.popleft())
85
+ yield batch
86
+
87
+ def consume_resource_batch(
88
+ self,
89
+ *,
90
+ batch_size: Optional[int],
91
+ ) -> Generator["BaseResourceList[T]", None, None]:
92
+ """
93
+ Consume resources in batches asynchronously.
94
+
95
+ :param batch_size: The size of each batch.
96
+ :return: An async generator yielding batches of FhirResourceList.
97
+ """
98
+ batch: BaseResourceList[T]
99
+ if batch_size is None:
100
+ batch = BaseResourceList[T]()
101
+ while self:
102
+ batch.append(self.popleft())
103
+ yield batch
104
+ elif batch_size <= 0:
105
+ raise ValueError("Batch size must be greater than 0.")
106
+ else:
107
+ while self:
108
+ batch = BaseResourceList[T]()
109
+ for _ in range(min(batch_size, len(self))):
110
+ batch.append(self.popleft())
111
+ yield batch
112
+
113
+ def __deepcopy__(self, memo: Dict[int, Any]) -> "BaseResourceList[T]":
114
+ """
115
+ Create a copy of the FhirResourceList.
116
+
117
+ :return: A new FhirResourceList object with the same resources.
118
+ """
119
+ return BaseResourceList[T]([copy.deepcopy(r) for r in self])
120
+
121
+ def __repr__(self) -> str:
122
+ """
123
+ Return a string representation of the FhirResourceList.
124
+
125
+ :return: A string representation of the FhirResourceList.
126
+ """
127
+ return f"FhirResourceList(resources: {len(self)})"
128
+
129
+ @contextmanager
130
+ def transaction(self) -> Iterator["BaseResourceList[T]"]:
131
+ """
132
+ Opens a transaction for all resources in the list.
133
+
134
+ Deserializes the dictionary before entering the context
135
+ Serializes the dictionary after exiting the context
136
+
137
+ Raises:
138
+ CompressedDictAccessError: If methods are called outside the context
139
+
140
+ """
141
+ try:
142
+ self.start_transaction()
143
+
144
+ yield self
145
+
146
+ finally:
147
+ self.end_transaction()
148
+
149
+ def start_transaction(self) -> "BaseResourceList[T]":
150
+ """
151
+ Starts a transaction for each resource in the list. Use transaction() for a contextmanager for simpler usage.
152
+ """
153
+
154
+ for resource in self:
155
+ resource.start_transaction()
156
+ return self
157
+
158
+ def end_transaction(self) -> "BaseResourceList[T]":
159
+ """
160
+ Ends a transaction. Use transaction() for a context_manager for simpler usage.
161
+
162
+ """
163
+ for resource in self:
164
+ resource.end_transaction()
165
+ return self
@@ -0,0 +1,291 @@
1
+ import copy
2
+ import json
3
+ from typing import Any, Dict, List, Optional, cast, OrderedDict
4
+
5
+ from compressedfhir.fhir.fhir_bundle_entry import FhirBundleEntry
6
+ from compressedfhir.fhir.fhir_bundle_entry_list import FhirBundleEntryList
7
+ from compressedfhir.fhir.fhir_identifier import FhirIdentifier
8
+ from compressedfhir.fhir.fhir_link import FhirLink
9
+ from compressedfhir.fhir.fhir_meta import FhirMeta
10
+ from compressedfhir.fhir.fhir_resource import FhirResource
11
+ from compressedfhir.utilities.compressed_dict.v1.compressed_dict_storage_mode import (
12
+ CompressedDictStorageMode,
13
+ )
14
+ from compressedfhir.utilities.fhir_json_encoder import FhirJSONEncoder
15
+ from compressedfhir.utilities.json_helpers import FhirClientJsonHelpers
16
+
17
+
18
+ class FhirBundle:
19
+ """
20
+ FhirBundle represents a FHIR Bundle resource.
21
+ """
22
+
23
+ __slots__ = [
24
+ "entry",
25
+ "total",
26
+ "id_",
27
+ "identifier",
28
+ "timestamp",
29
+ "type_",
30
+ "link",
31
+ "meta",
32
+ ]
33
+
34
+ def __init__(
35
+ self,
36
+ *,
37
+ id_: Optional[str] = None,
38
+ identifier: Optional[FhirIdentifier] = None,
39
+ timestamp: Optional[str] = None,
40
+ type_: str,
41
+ entry: Optional[FhirBundleEntryList] = None,
42
+ total: Optional[int] = None,
43
+ link: Optional[List[FhirLink]] = None,
44
+ meta: Optional[FhirMeta] = None,
45
+ ) -> None:
46
+ """
47
+ Initializes a FhirBundle object.
48
+
49
+
50
+ :param id_: The ID of the Bundle.
51
+ :param identifier: The identifier of the Bundle.
52
+ :param timestamp: The timestamp of the Bundle.
53
+ :param type_: The type of the Bundle (e.g., "searchset").
54
+ :param entry: The entries in the Bundle.
55
+ :param total: The total number of entries in the Bundle.
56
+ :param link: The links associated with the Bundle.
57
+ :param meta: The metadata associated with the Bundle.
58
+ """
59
+ self.entry: FhirBundleEntryList = entry or FhirBundleEntryList()
60
+ self.total: Optional[int] = total
61
+ self.id_: Optional[str] = id_
62
+ self.identifier: Optional[FhirIdentifier] = identifier
63
+ self.timestamp: Optional[str] = timestamp
64
+ self.type_: str = type_
65
+ self.link: Optional[List[FhirLink]] = link
66
+ self.meta: Optional[FhirMeta] = meta
67
+
68
+ def dict(self) -> OrderedDict[str, Any]:
69
+ entries: List[Dict[str, Any]] | None = (
70
+ [entry.dict() for entry in self.entry] if self.entry else None
71
+ )
72
+ result: OrderedDict[str, Any] = OrderedDict[str, Any](
73
+ {"type": self.type_, "resourceType": "Bundle"}
74
+ )
75
+
76
+ if self.id_ is not None:
77
+ result["id"] = self.id_
78
+ if self.identifier is not None:
79
+ result["identifier"] = self.identifier.dict()
80
+ if self.timestamp is not None:
81
+ result["timestamp"] = self.timestamp
82
+ if self.total is not None:
83
+ result["total"] = self.total
84
+ if entries and len(entries) > 0:
85
+ result["entry"] = entries
86
+ if self.link:
87
+ result["link"] = [link.dict() for link in self.link]
88
+ if self.meta:
89
+ result["meta"] = self.meta.dict()
90
+ return FhirClientJsonHelpers.remove_empty_elements_from_ordered_dict(result)
91
+
92
+ @classmethod
93
+ def construct(
94
+ cls,
95
+ *,
96
+ id_: Optional[str] = None,
97
+ identifier: Optional[FhirIdentifier] = None,
98
+ timestamp: Optional[str] = None,
99
+ type_: str,
100
+ entry: Optional[FhirBundleEntryList] = None,
101
+ total: Optional[int] = None,
102
+ link: Optional[List[FhirLink]] = None,
103
+ meta: Optional[FhirMeta] = None,
104
+ ) -> "FhirBundle":
105
+ """
106
+ Constructs a FhirBundle object from keyword arguments.
107
+
108
+ :param id_: The ID of the Bundle.
109
+ :param identifier: The identifier of the Bundle.
110
+ :param timestamp: The timestamp of the Bundle.
111
+ :param type_: The type of the Bundle (e.g., "searchset").
112
+ :param entry: The entries in the Bundle.
113
+ :param total: The total number of entries in the Bundle.
114
+ :param link: The links associated with the Bundle.
115
+ :param meta: The metadata associated with the Bundle.
116
+ """
117
+ return cls(
118
+ id_=id_,
119
+ identifier=identifier,
120
+ timestamp=timestamp,
121
+ type_=type_,
122
+ entry=entry,
123
+ total=total,
124
+ link=link,
125
+ meta=meta,
126
+ )
127
+
128
+ @classmethod
129
+ def from_dict(
130
+ cls,
131
+ data: OrderedDict[str, Any] | Dict[str, Any],
132
+ storage_mode: CompressedDictStorageMode,
133
+ ) -> "FhirBundle":
134
+ """
135
+ Creates a FhirBundle object from a dictionary.
136
+
137
+ :param data: A dictionary containing the Bundle data.
138
+ :param storage_mode: The storage mode for the Bundle.
139
+ :return: A FhirBundle object.
140
+ """
141
+ bundle = cls(
142
+ id_=data.get("id") if isinstance(data.get("id"), str) else None,
143
+ identifier=(
144
+ FhirIdentifier.from_dict(data["identifier"])
145
+ if "identifier" in data
146
+ else None
147
+ ),
148
+ timestamp=(
149
+ data.get("timestamp")
150
+ if isinstance(data.get("timestamp"), str)
151
+ else None
152
+ ),
153
+ type_=(
154
+ cast(str, data.get("type"))
155
+ if isinstance(data.get("type"), str)
156
+ else "collection"
157
+ ),
158
+ total=data.get("total") if isinstance(data.get("total"), int) else None,
159
+ entry=(
160
+ FhirBundleEntryList(
161
+ [
162
+ FhirBundleEntry.from_dict(entry, storage_mode=storage_mode)
163
+ for entry in data.get("entry", [])
164
+ ]
165
+ )
166
+ if "entry" in data
167
+ else FhirBundleEntryList()
168
+ ),
169
+ link=[FhirLink.from_dict(link) for link in data.get("link", [])],
170
+ meta=data.get("meta"),
171
+ )
172
+ return bundle
173
+
174
+ @staticmethod
175
+ def add_diagnostics_to_operation_outcomes(
176
+ *, resource: FhirResource, diagnostics_coding: List[Dict[str, Any]]
177
+ ) -> FhirResource:
178
+ """
179
+ Adds diagnostic coding to OperationOutcome resources to identify which call resulted in that OperationOutcome
180
+ being returned by the server
181
+
182
+
183
+ :param resource: The resource to add the diagnostics to
184
+ :param diagnostics_coding: The diagnostics coding to add
185
+ :return: The resource with the diagnostics added
186
+ """
187
+ with resource.transaction():
188
+ if resource.resource_type == "OperationOutcome":
189
+ issues = resource.get("issue")
190
+ if issues:
191
+ for issue in issues:
192
+ coding: List[Dict[str, Any]] = issue.setdefault(
193
+ "details", {}
194
+ ).setdefault("coding", [])
195
+ coding.extend(diagnostics_coding)
196
+ return resource
197
+
198
+ def json(self) -> str:
199
+ """
200
+ Converts the Bundle to a JSON string.
201
+
202
+ :return: JSON string representation of the Bundle
203
+ """
204
+ bundle_dict = self.dict()
205
+ return json.dumps(bundle_dict, cls=FhirJSONEncoder)
206
+
207
+ def copy(self) -> "FhirBundle":
208
+ return copy.deepcopy(self)
209
+
210
+ def __deepcopy__(self, memo: Dict[int, Any]) -> "FhirBundle":
211
+ """
212
+ Creates a copy of the Bundle.
213
+
214
+ :return: A new FhirBundle object with the same attributes
215
+ """
216
+ return FhirBundle(
217
+ entry=copy.deepcopy(self.entry) if self.entry else None,
218
+ total=self.total,
219
+ id_=self.id_,
220
+ identifier=copy.deepcopy(self.identifier) if self.identifier else None,
221
+ timestamp=self.timestamp,
222
+ type_=self.type_,
223
+ link=[copy.deepcopy(link) for link in self.link] if self.link else None,
224
+ )
225
+
226
+ def __repr__(self) -> str:
227
+ """
228
+ Returns a string representation of the Bundle.
229
+
230
+ :return: String representation of the Bundle
231
+ """
232
+ properties: List[str] = []
233
+ if self.id_:
234
+ properties.append(f"id_={self.id_}")
235
+ if self.type_:
236
+ properties.append(f"type_={self.type_}")
237
+ if self.timestamp:
238
+ properties.append(f"timestamp={self.timestamp}")
239
+ if self.total:
240
+ properties.append(f"total={self.total}")
241
+ if self.entry:
242
+ properties.append(f"entry={len(self.entry)}")
243
+ if self.link:
244
+ properties.append(f"link={len(self.link)}")
245
+
246
+ return f"FhirBundle({', '.join(properties)})"
247
+
248
+ def get_count_by_resource_type(self) -> Dict[str, int]:
249
+ """
250
+ Gets the count of resources by resource type.
251
+
252
+ :return: The count of resources by resource type
253
+ """
254
+ resources_by_type: Dict[str, int] = dict()
255
+ if self.entry is None:
256
+ return resources_by_type
257
+
258
+ entry: FhirBundleEntry
259
+ for entry in [e for e in self.entry if e is not None]:
260
+ if entry.resource is not None:
261
+ resource = entry.resource
262
+ resource_type: str = resource.resource_type or "unknown"
263
+ if resource_type not in resources_by_type:
264
+ resources_by_type[resource_type] = 0
265
+ resources_by_type[resource_type] += 1
266
+ return resources_by_type
267
+
268
+ @property
269
+ def id(self) -> Optional[str]:
270
+ """Get the ID of the Bundle."""
271
+ return self.id_
272
+
273
+ @id.setter
274
+ def id(self, value: Optional[str]) -> None:
275
+ """Set the ID of the Bundle."""
276
+ self.id_ = value
277
+
278
+ @property
279
+ def resource_type(self) -> str:
280
+ """Get the resource type of the Bundle."""
281
+ return "Bundle"
282
+
283
+ def to_plain_dict(self) -> Dict[str, Any]:
284
+ """
285
+ Converts the Bundle to a plain dictionary.
286
+
287
+ :return: Plain dictionary representation of the Bundle
288
+ """
289
+ return cast(
290
+ Dict[str, Any], json.loads(json.dumps(self.dict(), cls=FhirJSONEncoder))
291
+ )
@@ -0,0 +1,234 @@
1
+ import copy
2
+ import json
3
+ from typing import Any, Dict, Optional, List, OrderedDict
4
+
5
+ from compressedfhir.fhir.fhir_bundle_entry_search import FhirBundleEntrySearch
6
+ from compressedfhir.fhir.fhir_link import FhirLink
7
+ from compressedfhir.fhir.fhir_bundle_entry_request import FhirBundleEntryRequest
8
+ from compressedfhir.fhir.fhir_bundle_entry_response import (
9
+ FhirBundleEntryResponse,
10
+ )
11
+ from compressedfhir.fhir.fhir_resource import FhirResource
12
+ from compressedfhir.utilities.compressed_dict.v1.compressed_dict import (
13
+ CompressedDict,
14
+ )
15
+ from compressedfhir.utilities.compressed_dict.v1.compressed_dict_storage_mode import (
16
+ CompressedDictStorageMode,
17
+ )
18
+ from compressedfhir.utilities.fhir_json_encoder import FhirJSONEncoder
19
+ from compressedfhir.utilities.json_helpers import FhirClientJsonHelpers
20
+
21
+
22
+ class FhirBundleEntry:
23
+ """
24
+ Represents a single entry in a FHIR Bundle.
25
+ """
26
+
27
+ __slots__ = [
28
+ "_resource",
29
+ "request",
30
+ "response",
31
+ "fullUrl",
32
+ "link",
33
+ "search",
34
+ "storage_mode",
35
+ ]
36
+
37
+ # noinspection PyPep8Naming
38
+ def __init__(
39
+ self,
40
+ *,
41
+ fullUrl: Optional[str] = None,
42
+ resource: Dict[str, Any] | FhirResource | OrderedDict[str, Any] | None,
43
+ request: Optional[FhirBundleEntryRequest] = None,
44
+ response: Optional[FhirBundleEntryResponse] = None,
45
+ link: Optional[List[FhirLink]] = None,
46
+ search: Optional[FhirBundleEntrySearch] = None,
47
+ storage_mode: CompressedDictStorageMode = CompressedDictStorageMode.default(),
48
+ ) -> None:
49
+ """
50
+ Initializes a BundleEntry object.
51
+
52
+ :param fullUrl: The full URL of the entry.
53
+ :param resource: The FHIR resource associated with the entry.
54
+ :param request: The request information associated with the entry.
55
+ :param response: The response information associated with the entry.
56
+ :param storage_mode: The storage mode for the resource.
57
+ """
58
+ self._resource: Optional[FhirResource] = (
59
+ resource
60
+ if isinstance(resource, CompressedDict)
61
+ else (
62
+ FhirResource(initial_dict=resource, storage_mode=storage_mode)
63
+ if resource is not None
64
+ else None
65
+ )
66
+ )
67
+ self.request: Optional[FhirBundleEntryRequest] = request
68
+ self.response: Optional[FhirBundleEntryResponse] = response
69
+ self.fullUrl: Optional[str] = fullUrl
70
+ self.link: Optional[List[FhirLink]] = link
71
+ self.search: Optional[FhirBundleEntrySearch] = search
72
+ self.storage_mode: CompressedDictStorageMode = storage_mode
73
+
74
+ # noinspection PyPep8Naming
75
+ @classmethod
76
+ def construct(
77
+ cls,
78
+ *,
79
+ fullUrl: Optional[str] = None,
80
+ resource: Dict[str, Any] | FhirResource | OrderedDict[str, Any] | None,
81
+ request: Optional[FhirBundleEntryRequest] = None,
82
+ response: Optional[FhirBundleEntryResponse] = None,
83
+ link: Optional[List[FhirLink]] = None,
84
+ search: Optional[FhirBundleEntrySearch] = None,
85
+ storage_mode: CompressedDictStorageMode = CompressedDictStorageMode.default(),
86
+ ) -> "FhirBundleEntry":
87
+ """
88
+ Constructs a BundleEntry object with the given parameters.
89
+
90
+ :param fullUrl: The full URL of the entry.
91
+ :param resource: The FHIR resource associated with the entry.
92
+ :param request: The request information associated with the entry.
93
+ :param response: The response information associated with the entry.
94
+ :param link: The links associated with the entry.
95
+ :param search: The search information associated with the entry.
96
+ :param storage_mode: The storage mode for the resource.
97
+ """
98
+ return cls(
99
+ fullUrl=fullUrl,
100
+ resource=resource,
101
+ request=request,
102
+ response=response,
103
+ link=link,
104
+ search=search,
105
+ storage_mode=storage_mode,
106
+ )
107
+
108
+ @property
109
+ def resource(self) -> Optional[FhirResource]:
110
+ """
111
+ Returns the FHIR resource associated with the entry.
112
+
113
+ :return: The FHIR resource.
114
+ """
115
+ return self._resource
116
+
117
+ @resource.setter
118
+ def resource(self, value: Dict[str, Any] | FhirResource | None) -> None:
119
+ """
120
+ Sets the FHIR resource associated with the entry.
121
+
122
+ :param value: The FHIR resource to set.
123
+ """
124
+ if value is not None:
125
+ if isinstance(value, CompressedDict):
126
+ self._resource = value
127
+ else:
128
+ if self._resource is None:
129
+ self._resource = FhirResource(
130
+ initial_dict=value, storage_mode=self.storage_mode
131
+ )
132
+ else:
133
+ self._resource.replace(value=value)
134
+ else:
135
+ self._resource = None
136
+
137
+ def dict(self) -> OrderedDict[str, Any]:
138
+ result: OrderedDict[str, Any] = OrderedDict[str, Any]()
139
+ if self.fullUrl is not None:
140
+ result["fullUrl"] = self.fullUrl
141
+ if self.resource is not None:
142
+ result["resource"] = self.resource.dict()
143
+ if self.request is not None:
144
+ result["request"] = self.request.dict()
145
+ if self.response is not None:
146
+ result["response"] = self.response.dict()
147
+ if self.link is not None:
148
+ result["link"] = [link.dict() for link in self.link]
149
+ if self.search is not None:
150
+ result["search"] = self.search.dict()
151
+ return FhirClientJsonHelpers.remove_empty_elements_from_ordered_dict(result)
152
+
153
+ @classmethod
154
+ def from_dict(
155
+ cls,
156
+ d: OrderedDict[str, Any] | Dict[str, Any],
157
+ storage_mode: CompressedDictStorageMode,
158
+ ) -> "FhirBundleEntry":
159
+ return cls(
160
+ fullUrl=d["fullUrl"] if "fullUrl" in d else None,
161
+ resource=(
162
+ FhirResource(initial_dict=d["resource"], storage_mode=storage_mode)
163
+ if "resource" in d
164
+ else None
165
+ ),
166
+ request=(
167
+ FhirBundleEntryRequest.from_dict(d["request"])
168
+ if "request" in d
169
+ else None
170
+ ),
171
+ response=(
172
+ FhirBundleEntryResponse.from_dict(d["response"])
173
+ if "response" in d
174
+ else None
175
+ ),
176
+ link=(
177
+ [FhirLink.from_dict(link) for link in d["link"]]
178
+ if "link" in d
179
+ else None
180
+ ),
181
+ search=(
182
+ FhirBundleEntrySearch.from_dict(d["search"]) if "search" in d else None
183
+ ),
184
+ storage_mode=storage_mode,
185
+ )
186
+
187
+ def json(self) -> str:
188
+ """
189
+ Converts the BundleEntry object to a JSON string.
190
+
191
+ :return: A JSON string representation of the BundleEntry.
192
+ """
193
+ return json.dumps(obj=self.dict(), cls=FhirJSONEncoder)
194
+
195
+ def __deepcopy__(self, memo: Dict[int, Any]) -> "FhirBundleEntry":
196
+ """
197
+ Creates a copy of the BundleEntry object.
198
+
199
+ :return: A new BundleEntry object with the same attributes.
200
+ """
201
+ return FhirBundleEntry(
202
+ fullUrl=self.fullUrl,
203
+ resource=copy.deepcopy(self.resource) if self.resource else None,
204
+ request=copy.deepcopy(self.request) if self.request else None,
205
+ response=copy.deepcopy(self.response) if self.response else None,
206
+ link=[copy.deepcopy(link) for link in self.link] if self.link else None,
207
+ search=copy.deepcopy(self.search) if self.search else None,
208
+ storage_mode=self.storage_mode,
209
+ )
210
+
211
+ def __repr__(self) -> str:
212
+ """
213
+ Returns a string representation of the BundleEntry object.
214
+
215
+ :return: A string representation of the BundleEntry.
216
+ """
217
+ return (
218
+ f"BundleEntry({self.resource.resource_type}/{self.resource.id})"
219
+ if self.resource
220
+ else f"BundleEntry(Empty)"
221
+ )
222
+
223
+ def copy(self) -> "FhirBundleEntry":
224
+ """
225
+ Creates a copy of the BundleEntry object.
226
+
227
+ :return: A new BundleEntry object with the same attributes.
228
+ """
229
+ return copy.deepcopy(self)
230
+
231
+ @property
232
+ def resource_type_and_id(self) -> Optional[str]:
233
+ """Get the key from the resource."""
234
+ return self.resource.resource_type_and_id if self.resource else None