Skip to content

Commit 9ab93ae

Browse files
Merge pull request #1005 from NHSDigital/feature/eema1-NRL-1554-ContentRetrievalMechanismExtension
NRL-1554 Add new content retrieval mechanism extension
2 parents f18961f + 1ffa66a commit 9ab93ae

17 files changed

+1402
-86
lines changed

api/consumer/swagger.yaml

Lines changed: 53 additions & 3 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"
814-
description: Additional extension for content stability.
813+
oneOf:
814+
- $ref: "#/components/schemas/ContentStabilityExtension"
815+
- $ref: "#/components/schemas/RetrievalMechanismExtension"
816+
- $ref: "#/components/schemas/Extension"
817+
description: Additional extensions which include Content Stability and Retrieval Mechanism.
815818
minItems: 1
816-
maxItems: 1
817819
required:
818820
- attachment
819821
- format
@@ -975,6 +977,52 @@ 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", "LDR"]
1019+
display:
1020+
type: string
1021+
enum: ["Spine Secure Proxy", "Direct", "Large Document Retrieval"]
1022+
required:
1023+
- system
1024+
- code
1025+
- display
9781026
NRLFormatCode:
9791027
allOf:
9801028
- $ref: "#/components/schemas/Coding"
@@ -990,12 +1038,14 @@ components:
9901038
enum:
9911039
- "urn:nhs-ic:record-contact"
9921040
- "urn:nhs-ic:unstructured"
1041+
- "urn:nhs-ic:structured"
9931042
description: The code representing the format of the document.
9941043
display:
9951044
type: string
9961045
enum:
9971046
- "Contact details (HTTP Unsecured)"
9981047
- "Unstructured Document"
1048+
- "Structured Document"
9991049
description: The display text for the code.
10001050
required:
10011051
- system

api/producer/swagger.yaml

Lines changed: 53 additions & 3 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"
1419-
description: Additional extension for content stability.
1418+
oneOf:
1419+
- $ref: "#/components/schemas/ContentStabilityExtension"
1420+
- $ref: "#/components/schemas/RetrievalMechanismExtension"
1421+
- $ref: "#/components/schemas/Extension"
1422+
description: Additional extensions which include Content Stability and Retrieval Mechanism.
14201423
minItems: 1
1421-
maxItems: 1
14221424
required:
14231425
- attachment
14241426
- format
@@ -1631,6 +1633,52 @@ 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", "LDR"]
1675+
display:
1676+
type: string
1677+
enum: ["Spine Secure Proxy", "Direct", "Large Document Retrieval"]
1678+
required:
1679+
- system
1680+
- code
1681+
- display
16341682
NRLFormatCode:
16351683
allOf:
16361684
- $ref: "#/components/schemas/Coding"
@@ -1646,12 +1694,14 @@ components:
16461694
enum:
16471695
- "urn:nhs-ic:record-contact"
16481696
- "urn:nhs-ic:unstructured"
1697+
- "urn:nhs-ic:structured"
16491698
description: The code representing the format of the document.
16501699
display:
16511700
type: string
16521701
enum:
16531702
- "Contact details (HTTP Unsecured)"
16541703
- "Unstructured Document"
1704+
- "Structured Document"
16551705
description: The display text for the code.
16561706
required:
16571707
- system

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-09-05T08:22:10+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", "LDR"]
246+
display: Literal["Spine Secure Proxy", "Direct", "Large Document Retrieval"]
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, Extension]],
656+
Field(min_length=1),
637657
]
638658

639659

layer/nrlf/core/constants.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -677,9 +677,18 @@ def coding_value(self):
677677
CONTENT_STABILITY_EXTENSION_URL = (
678678
"https://fhir.nhs.uk/England/StructureDefinition/Extension-England-ContentStability"
679679
)
680+
CONTENT_RETRIEVAL_EXTENSION_URL = "https://fhir.nhs.uk/England/StructureDefinition/Extension-England-RetrievalMechanism"
680681
CONTENT_STABILITY_SYSTEM_URL = (
681682
"https://fhir.nhs.uk/England/CodeSystem/England-NRLContentStability"
682683
)
684+
CONTENT_RETRIEVAL_SYSTEM_URL = (
685+
"https://fhir.nhs.uk/England/CodeSystem/England-RetrievalMechanism"
686+
)
687+
CONTENT_RETRIEVAL_CODE_MAP = {
688+
"Direct": "Direct",
689+
"SSP": "Spine Secure Proxy",
690+
"LDR": "Large Document Retrieval",
691+
}
683692
CONTENT_FORMAT_CODE_URL = "https://fhir.nhs.uk/England/CodeSystem/England-NRLFormatCode"
684693
CONTENT_FORMAT_CODE_MAP = {
685694
"urn:nhs-ic:record-contact": "Contact details (HTTP Unsecured)",

layer/nrlf/core/errors.py

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
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
76
from nrlf.core.response import Response
87
from nrlf.core.types import CodeableConcept
98
from nrlf.producer.fhir.r4 import model as producer_model
@@ -20,28 +19,25 @@ def format_error_location(loc: List) -> str:
2019
return formatted_loc
2120

2221

23-
def append_value_set_url(loc_string: str) -> str:
24-
if loc_string.endswith(("url", "system")):
25-
return ""
26-
27-
if "content" in loc_string:
28-
if "extension" in loc_string:
29-
return f". See ValueSet: {CONTENT_STABILITY_SYSTEM_URL}"
30-
if "format" in loc_string:
31-
return f". See ValueSet: {CONTENT_FORMAT_CODE_URL}"
32-
33-
return ""
34-
35-
36-
def diag_for_error(error: ErrorDetails) -> str:
22+
def diag_for_error(error: ErrorDetails, value_set: str, root_location: tuple) -> str:
3723
loc_string = format_error_location(error["loc"])
24+
if root_location:
25+
loc_string = format_error_location(root_location) + "." + loc_string
26+
3827
msg = f"{loc_string or 'DocumentReference'}: {error['msg']}"
39-
msg += append_value_set_url(loc_string)
28+
msg += f", see: {value_set}" if value_set else ""
4029
return msg
4130

4231

43-
def expression_for_error(error: ErrorDetails) -> Optional[str]:
44-
return format_error_location(error["loc"]) or "DocumentReference"
32+
def expression_for_error(error: ErrorDetails, root_location: tuple) -> Optional[str]:
33+
loc_string = format_error_location(error["loc"]) or "DocumentReference"
34+
if root_location and error["loc"]:
35+
loc_string = (
36+
format_error_location(root_location)
37+
+ "."
38+
+ format_error_location(error["loc"])
39+
)
40+
return loc_string
4541

4642

4743
class OperationOutcomeError(Exception):
@@ -91,15 +87,20 @@ def __init__(self, issues: List[OperationOutcomeIssue]):
9187

9288
@classmethod
9389
def from_validation_error(
94-
cls, exc: ValidationError, details: CodeableConcept, msg: str = ""
90+
cls,
91+
exc: ValidationError,
92+
details: CodeableConcept,
93+
msg: str = "",
94+
value_set: str = "",
95+
root_location: tuple = None,
9596
):
9697
issues = [
9798
producer_model.OperationOutcomeIssue(
9899
severity="error",
99100
code="invalid",
100101
details=details, # type: ignore
101-
diagnostics=f"{msg} ({diag_for_error(error)})",
102-
expression=[expression_for_error(error)], # type: ignore
102+
diagnostics=f"{msg} ({diag_for_error(error, value_set, root_location)})",
103+
expression=[expression_for_error(error, root_location)], # type: ignore
103104
)
104105
for error in exc.errors()
105106
]

0 commit comments

Comments
 (0)