Skip to content

Commit 37e7375

Browse files
committed
NRL-1554 Add new content retrieval mechanism extension
1 parent 734e158 commit 37e7375

File tree

10 files changed

+329
-24
lines changed

10 files changed

+329
-24
lines changed

api/consumer/swagger.yaml

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -810,10 +810,12 @@ components:
810810
extension:
811811
type: array
812812
items:
813-
$ref: "#/components/schemas/ContentStabilityExtension"
813+
oneOf:
814+
- $ref: "#/components/schemas/ContentStabilityExtension"
815+
- $ref: "#/components/schemas/RetrievalMechanismExtension"
814816
description: Additional extension for content stability.
815817
minItems: 1
816-
maxItems: 1
818+
maxItems: 2
817819
required:
818820
- attachment
819821
- format
@@ -975,6 +977,53 @@ components:
975977
- system
976978
- code
977979
- display
980+
RetrievalMechanismExtension:
981+
allOf:
982+
- $ref: "#/components/schemas/Extension"
983+
- type: object
984+
properties:
985+
url:
986+
type: string
987+
enum:
988+
- "https://fhir.nhs.uk/England/StructureDefinition/Extension-England-RetrievalMechanism"
989+
valueCodeableConcept:
990+
$ref: "#/components/schemas/RetrievalMechanismExtensionValueCodeableConcept"
991+
required:
992+
- url
993+
- valueCodeableConcept
994+
RetrievalMechanismExtensionValueCodeableConcept:
995+
allOf:
996+
- $ref: "#/components/schemas/CodeableConcept"
997+
- type: object
998+
properties:
999+
coding:
1000+
type: array
1001+
items:
1002+
$ref: "#/components/schemas/RetrievalMechanismExtensionCoding"
1003+
minItems: 1
1004+
maxItems: 1
1005+
required:
1006+
- coding
1007+
RetrievalMechanismExtensionCoding:
1008+
allOf:
1009+
- $ref: "#/components/schemas/Coding"
1010+
- type: object
1011+
properties:
1012+
system:
1013+
type: string
1014+
enum:
1015+
- "https://fhir.nhs.uk/England/CodeSystem/England-RetrievalMechanism"
1016+
code:
1017+
type: string
1018+
enum: ["SSP", "Direct", "NDR"]
1019+
display:
1020+
type: string
1021+
enum:
1022+
["Spine Secure Proxy", "National Document Repository", "Direct"]
1023+
required:
1024+
- system
1025+
- code
1026+
- display
9781027
NRLFormatCode:
9791028
allOf:
9801029
- $ref: "#/components/schemas/Coding"

api/producer/swagger.yaml

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1415,10 +1415,12 @@ components:
14151415
extension:
14161416
type: array
14171417
items:
1418-
$ref: "#/components/schemas/ContentStabilityExtension"
1418+
oneOf:
1419+
- $ref: "#/components/schemas/ContentStabilityExtension"
1420+
- $ref: "#/components/schemas/RetrievalMechanismExtension"
14191421
description: Additional extension for content stability.
14201422
minItems: 1
1421-
maxItems: 1
1423+
maxItems: 2
14221424
required:
14231425
- attachment
14241426
- format
@@ -1631,6 +1633,53 @@ components:
16311633
- system
16321634
- code
16331635
- display
1636+
RetrievalMechanismExtension:
1637+
allOf:
1638+
- $ref: "#/components/schemas/Extension"
1639+
- type: object
1640+
properties:
1641+
url:
1642+
type: string
1643+
enum:
1644+
- "https://fhir.nhs.uk/England/StructureDefinition/Extension-England-RetrievalMechanism"
1645+
valueCodeableConcept:
1646+
$ref: "#/components/schemas/RetrievalMechanismExtensionValueCodeableConcept"
1647+
required:
1648+
- url
1649+
- valueCodeableConcept
1650+
RetrievalMechanismExtensionValueCodeableConcept:
1651+
allOf:
1652+
- $ref: "#/components/schemas/CodeableConcept"
1653+
- type: object
1654+
properties:
1655+
coding:
1656+
type: array
1657+
items:
1658+
$ref: "#/components/schemas/RetrievalMechanismExtensionCoding"
1659+
minItems: 1
1660+
maxItems: 1
1661+
required:
1662+
- coding
1663+
RetrievalMechanismExtensionCoding:
1664+
allOf:
1665+
- $ref: "#/components/schemas/Coding"
1666+
- type: object
1667+
properties:
1668+
system:
1669+
type: string
1670+
enum:
1671+
- "https://fhir.nhs.uk/England/CodeSystem/England-RetrievalMechanism"
1672+
code:
1673+
type: string
1674+
enum: ["SSP", "Direct", "NDR"]
1675+
display:
1676+
type: string
1677+
enum:
1678+
["Spine Secure Proxy", "National Document Repository", "Direct"]
1679+
required:
1680+
- system
1681+
- code
1682+
- display
16341683
NRLFormatCode:
16351684
allOf:
16361685
- $ref: "#/components/schemas/Coding"

layer/nrlf/consumer/fhir/r4/model.py

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# generated by datamodel-codegen:
22
# filename: swagger.yaml
3-
# timestamp: 2025-06-13T14:43:32+00:00
3+
# timestamp: 2025-08-07T11:40:24+00:00
44

55
from __future__ import annotations
66

@@ -240,6 +240,12 @@ class ContentStabilityExtensionCoding(Coding):
240240
display: Literal["Static", "Dynamic"]
241241

242242

243+
class RetrievalMechanismExtensionCoding(Coding):
244+
system: Literal["https://fhir.nhs.uk/England/CodeSystem/England-RetrievalMechanism"]
245+
code: Literal["SSP", "Direct", "NDR"]
246+
display: Literal["Spine Secure Proxy", "National Document Repository", "Direct"]
247+
248+
243249
class NRLFormatCode(Coding):
244250
system: Annotated[
245251
Literal["https://fhir.nhs.uk/England/CodeSystem/England-NRLFormatCode"],
@@ -501,6 +507,12 @@ class ContentStabilityExtensionValueCodeableConcept(CodeableConcept):
501507
]
502508

503509

510+
class RetrievalMechanismExtensionValueCodeableConcept(CodeableConcept):
511+
coding: Annotated[
512+
List[RetrievalMechanismExtensionCoding], Field(max_length=1, min_length=1)
513+
]
514+
515+
504516
class RequestHeader(Parent):
505517
odsCode: RequestHeaderOdsCode
506518

@@ -574,6 +586,13 @@ class ContentStabilityExtension(Extension):
574586
valueCodeableConcept: ContentStabilityExtensionValueCodeableConcept
575587

576588

589+
class RetrievalMechanismExtension(Extension):
590+
url: Literal[
591+
"https://fhir.nhs.uk/England/StructureDefinition/Extension-England-RetrievalMechanism"
592+
]
593+
valueCodeableConcept: RetrievalMechanismExtensionValueCodeableConcept
594+
595+
577596
class OperationOutcome(Parent):
578597
resourceType: Literal["OperationOutcome"]
579598
id: Annotated[
@@ -633,7 +652,8 @@ class DocumentReferenceContent(Parent):
633652
),
634653
]
635654
extension: Annotated[
636-
List[ContentStabilityExtension], Field(max_length=1, min_length=1)
655+
List[Union[ContentStabilityExtension, RetrievalMechanismExtension]],
656+
Field(max_length=2, min_length=1),
637657
]
638658

639659

layer/nrlf/core/constants.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,14 @@ def coding_value(self):
673673
CONTENT_STABILITY_SYSTEM_URL = (
674674
"https://fhir.nhs.uk/England/CodeSystem/England-NRLContentStability"
675675
)
676+
CONTENT_RETRIEVAL_SYSTEM_URL = (
677+
"https://fhir.nhs.uk/England/CodeSystem/England-RetrievalMechanism"
678+
)
679+
CONTENT_RETRIEVAL_CODE_MAP = {
680+
"Direct": "Direct",
681+
"SSP": "Spine Secure Proxy",
682+
"NDR": "National Document Repository",
683+
}
676684
CONTENT_FORMAT_CODE_URL = "https://fhir.nhs.uk/England/CodeSystem/England-NRLFormatCode"
677685
CONTENT_FORMAT_CODE_MAP = {
678686
"urn:nhs-ic:record-contact": "Contact details (HTTP Unsecured)",

layer/nrlf/core/errors.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,24 @@
33
from pydantic import ValidationError
44
from pydantic_core import ErrorDetails
55

6-
from nrlf.core.constants import CONTENT_FORMAT_CODE_URL, CONTENT_STABILITY_SYSTEM_URL
6+
from nrlf.core.constants import (
7+
CONTENT_FORMAT_CODE_URL,
8+
CONTENT_RETRIEVAL_SYSTEM_URL,
9+
CONTENT_STABILITY_SYSTEM_URL,
10+
)
711
from nrlf.core.response import Response
812
from nrlf.core.types import CodeableConcept
913
from nrlf.producer.fhir.r4 import model as producer_model
1014
from nrlf.producer.fhir.r4.model import OperationOutcome, OperationOutcomeIssue
1115

1216

1317
def format_error_location(loc: List) -> str:
18+
# List of extension class names to exclude from error paths
19+
exclude_classes = {"ContentStabilityExtension", "RetrievalMechanismExtension"}
20+
filtered_loc = [each for each in loc if each not in exclude_classes]
21+
1422
formatted_loc = ""
15-
for each in loc:
23+
for each in filtered_loc:
1624
if isinstance(each, int):
1725
formatted_loc = f"{formatted_loc}[{each}]"
1826
else:
@@ -26,7 +34,7 @@ def append_value_set_url(loc_string: str) -> str:
2634

2735
if "content" in loc_string:
2836
if "extension" in loc_string:
29-
return f". See ValueSet: {CONTENT_STABILITY_SYSTEM_URL}"
37+
return f". See ValueSets: {CONTENT_STABILITY_SYSTEM_URL} & {CONTENT_RETRIEVAL_SYSTEM_URL}"
3038
if "format" in loc_string:
3139
return f". See ValueSet: {CONTENT_FORMAT_CODE_URL}"
3240

layer/nrlf/core/tests/test_pydantic_errors.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,11 @@ def test_validate_content_multiple_content_stability_extensions():
9999
document_ref_data["content"][0]["extension"][0]
100100
)
101101

102+
# Add a third duplicate contentStability extension
103+
document_ref_data["content"][0]["extension"].append(
104+
document_ref_data["content"][0]["extension"][0]
105+
)
106+
102107
with pytest.raises(ParseError) as error:
103108
validator.validate(document_ref_data)
104109

@@ -116,7 +121,7 @@ def test_validate_content_multiple_content_stability_extensions():
116121
}
117122
]
118123
},
119-
"diagnostics": "Failed to parse DocumentReference resource (content[0].extension: List should have at most 1 item after validation, not 2. See ValueSet: https://fhir.nhs.uk/England/CodeSystem/England-NRLContentStability)",
124+
"diagnostics": "Failed to parse DocumentReference resource (content[0].extension: List should have at most 2 items after validation, not 3. See ValueSets: https://fhir.nhs.uk/England/CodeSystem/England-NRLContentStability & https://fhir.nhs.uk/England/CodeSystem/England-RetrievalMechanism)",
120125
"expression": ["content[0].extension"],
121126
}
122127

@@ -133,7 +138,6 @@ def test_validate_content_invalid_content_stability_code():
133138
validator.validate(document_ref_data)
134139

135140
exc = error.value
136-
assert len(exc.issues) == 1
137141
assert exc.issues[0].model_dump(exclude_none=True) == {
138142
"severity": "error",
139143
"code": "invalid",
@@ -146,7 +150,7 @@ def test_validate_content_invalid_content_stability_code():
146150
}
147151
]
148152
},
149-
"diagnostics": "Failed to parse DocumentReference resource (content[0].extension[0].valueCodeableConcept.coding[0].code: Input should be 'static' or 'dynamic'. See ValueSet: https://fhir.nhs.uk/England/CodeSystem/England-NRLContentStability)",
153+
"diagnostics": "Failed to parse DocumentReference resource (content[0].extension[0].valueCodeableConcept.coding[0].code: Input should be 'static' or 'dynamic'. See ValueSets: https://fhir.nhs.uk/England/CodeSystem/England-NRLContentStability & https://fhir.nhs.uk/England/CodeSystem/England-RetrievalMechanism)",
150154
"expression": ["content[0].extension[0].valueCodeableConcept.coding[0].code"],
151155
}
152156

@@ -163,7 +167,6 @@ def test_validate_content_invalid_content_stability_display():
163167
validator.validate(document_ref_data)
164168

165169
exc = error.value
166-
assert len(exc.issues) == 1
167170
assert exc.issues[0].model_dump(exclude_none=True) == {
168171
"severity": "error",
169172
"code": "invalid",
@@ -176,7 +179,7 @@ def test_validate_content_invalid_content_stability_display():
176179
}
177180
]
178181
},
179-
"diagnostics": "Failed to parse DocumentReference resource (content[0].extension[0].valueCodeableConcept.coding[0].display: Input should be 'Static' or 'Dynamic'. See ValueSet: https://fhir.nhs.uk/England/CodeSystem/England-NRLContentStability)",
182+
"diagnostics": "Failed to parse DocumentReference resource (content[0].extension[0].valueCodeableConcept.coding[0].display: Input should be 'Static' or 'Dynamic'. See ValueSets: https://fhir.nhs.uk/England/CodeSystem/England-NRLContentStability & https://fhir.nhs.uk/England/CodeSystem/England-RetrievalMechanism)",
180183
"expression": [
181184
"content[0].extension[0].valueCodeableConcept.coding[0].display"
182185
],
@@ -195,7 +198,6 @@ def test_validate_content_invalid_content_stability_system():
195198
validator.validate(document_ref_data)
196199

197200
exc = error.value
198-
assert len(exc.issues) == 1
199201
assert exc.issues[0].model_dump(exclude_none=True) == {
200202
"severity": "error",
201203
"code": "invalid",
@@ -224,7 +226,6 @@ def test_validate_content_invalid_content_stability_url():
224226
validator.validate(document_ref_data)
225227

226228
exc = error.value
227-
assert len(exc.issues) == 1
228229
assert exc.issues[0].model_dump(exclude_none=True) == {
229230
"severity": "error",
230231
"code": "invalid",

0 commit comments

Comments
 (0)