diff --git a/service/src/main/java/uk/nhs/adaptors/gp2gp/ehr/mapper/CodeableConceptCdMapper.java b/service/src/main/java/uk/nhs/adaptors/gp2gp/ehr/mapper/CodeableConceptCdMapper.java index 1080c196d..5881a7266 100644 --- a/service/src/main/java/uk/nhs/adaptors/gp2gp/ehr/mapper/CodeableConceptCdMapper.java +++ b/service/src/main/java/uk/nhs/adaptors/gp2gp/ehr/mapper/CodeableConceptCdMapper.java @@ -4,6 +4,7 @@ import java.util.List; import java.util.Optional; import java.util.function.BiFunction; +import java.util.function.Function; import org.apache.commons.lang3.StringUtils; import org.hl7.fhir.dstu3.model.AllergyIntolerance; @@ -152,7 +153,7 @@ public String mapCodeableConceptToCdForBloodPressure(CodeableConcept codeableCon var mainCode = getSnomedCodeCoding(codeableConcept); builder.nullFlavor(mainCode.isEmpty()); - var originalText = findOriginalText(codeableConcept, mainCode); + var originalText = findOriginalTextUsingNestedDisplayExtension(codeableConcept, mainCode); originalText.ifPresent(builder::mainOriginalText); if (mainCode.isPresent()) { @@ -324,7 +325,11 @@ private List getNonSnomedCodeCodings(CodeableConcept codeableConcept) { return nonSnomedCodeCodings; } - private Optional findOriginalText(CodeableConcept codeableConcept, Optional coding) { + private Optional findOriginalText( + CodeableConcept codeableConcept, + Optional coding, + Function> getOriginalTextFromDescriptionExtension) { + if (coding.isPresent()) { if (codeableConcept.hasText()) { return Optional.ofNullable(codeableConcept.getText()); @@ -332,7 +337,7 @@ private Optional findOriginalText(CodeableConcept codeableConcept, Optio if (coding.get().hasDisplay()) { return getCodingDisplayName(coding.get()); } else { - var extension = retrieveDescriptionExtension(coding.get()); + var extension = getOriginalTextFromDescriptionExtension.apply(coding.get()); return extension.stream() .filter(displayExtension -> DESCRIPTION_DISPLAY.equals(displayExtension.getUrl())) .map(extension1 -> extension1.getValue().toString()) @@ -344,6 +349,24 @@ private Optional findOriginalText(CodeableConcept codeableConcept, Optio } } + private Optional findOriginalText(CodeableConcept codeableConcept, Optional coding) { + return findOriginalText( + codeableConcept, + coding, + codingParameter -> retrieveDescriptionExtension(codingParameter).stream().toList() + ); + } + + private Optional findOriginalTextUsingNestedDisplayExtension(CodeableConcept codeableConcept, Optional coding) { + return findOriginalText( + codeableConcept, + coding, + codingParameter -> retrieveDescriptionExtension(codingParameter) + .map(Extension::getExtension) + .orElseGet(Collections::emptyList) + ); + } + private Optional findOriginalTextForAllergy( CodeableConcept codeableConcept, Optional coding, diff --git a/service/src/test/java/uk/nhs/adaptors/gp2gp/ehr/mapper/CodeableConceptCdMapperTest.java b/service/src/test/java/uk/nhs/adaptors/gp2gp/ehr/mapper/CodeableConceptCdMapperTest.java index f6da40e6a..e63b48ae8 100644 --- a/service/src/test/java/uk/nhs/adaptors/gp2gp/ehr/mapper/CodeableConceptCdMapperTest.java +++ b/service/src/test/java/uk/nhs/adaptors/gp2gp/ehr/mapper/CodeableConceptCdMapperTest.java @@ -10,6 +10,7 @@ import org.hl7.fhir.dstu3.model.Medication; import org.hl7.fhir.dstu3.model.Observation; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; @@ -227,6 +228,555 @@ void When_MappingStubbedCodeableConceptAsActiveAllergy_Expect_HL7CdObjectXml(Str .isEqualToIgnoringWhitespace(expectedOutput); } + @Nested + class WhenMappingStubbedCodeableConceptForBloodPressure { + @Test + void When_WithoutCoding_Expect_NullFlavorCdXmlWithoutOriginalText() { + var inputJson = """ + { + "resourceType": "Observation" + }"""; + var expectedOutput = """ + + """; + var codeableConcept = fhirParseService.parseResource(inputJson, Observation.class).getCode(); + + var outputMessage = codeableConceptCdMapper.mapCodeableConceptToCdForBloodPressure(codeableConcept); + + assertThat(outputMessage).isEqualToIgnoringWhitespace(expectedOutput); + } + + @Test + void When_WithSnomedCodingWithDisplay_Expect_SnomedCdXmlWithOriginalText() { + var inputJson = """ + { + "resourceType": "Observation", + "code": { + "coding": [ + { + "system": "http://snomed.info/sct", + "display": "Prothrombin time", + "code": "852471000000107" + } + ] + } + }"""; + var expectedOutput = """ + + Prothrombin time + """; + var codeableConcept = fhirParseService.parseResource(inputJson, Observation.class).getCode(); + + var outputMessage = codeableConceptCdMapper.mapCodeableConceptToCdForBloodPressure(codeableConcept); + + assertThat(outputMessage).isEqualToIgnoringWhitespace(expectedOutput); + } + + @Test + void When_WithSnomedCodingWithoutDisplayWithDescriptionExtensionWithoutDisplay_Expect_SnomedCdXml() { + var inputJson = """ + { + "resourceType": "Observation", + "code": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "852471000000107", + "extension": [ + { + "url": "https://fhir.nhs.uk/STU3/StructureDefinition/Extension-coding-sctdescid", + "extension": [ + { + "url": "descriptionId", + "valueId": "12345789" + } + ] + } + ] + } + ] + } + }"""; + var expectedOutput = """ + + """; + var codeableConcept = fhirParseService.parseResource(inputJson, Observation.class).getCode(); + + var outputMessage = codeableConceptCdMapper.mapCodeableConceptToCdForBloodPressure(codeableConcept); + + assertThat(outputMessage).isEqualToIgnoringWhitespace(expectedOutput); + } + + @Test + void When_WithSnomedCodingNoDisplayWithDescriptionExtensionWithDisplay_Expect_SnomedCdXmlWithOriginalTextFromExtensionDisplay() { + var inputJson = """ + { + "resourceType": "Observation", + "code": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "852471000000107", + "extension": [ + { + "url": "https://fhir.nhs.uk/STU3/StructureDefinition/Extension-coding-sctdescid", + "extension": [ + { + "url": "descriptionDisplay", + "valueString": "Prothrombin time (observed)" + } + ] + } + ] + } + ] + } + }"""; + var expectedOutput = """ + + Prothrombin time (observed) + """; + var codeableConcept = fhirParseService.parseResource(inputJson, Observation.class).getCode(); + + var outputMessage = codeableConceptCdMapper.mapCodeableConceptToCdForBloodPressure(codeableConcept); + + assertThat(outputMessage).isEqualToIgnoringWhitespace(expectedOutput); + } + + @Test + void When_WithNonSnomedCodingWithText_Expect_NullFlavorUnkCDWithOriginalTextFromText() { + var inputJson = """ + { + "resourceType": "Observation", + "code": { + "coding": [ + { + "system": "http://read.info/readv2", + "code": "42Q5.00", + "display": "Prothrombin time" + } + ], + "text": "Prothrombin time (observed)" + } + }"""; + var expectedOutput = """ + + Prothrombin time (observed) + """; + var codeableConcept = fhirParseService.parseResource(inputJson, Observation.class).getCode(); + + var outputMessage = codeableConceptCdMapper.mapCodeableConceptToCdForBloodPressure(codeableConcept); + + assertThat(outputMessage).isEqualToIgnoringWhitespace(expectedOutput); + } + + @Test + void When_WithNonSnomedCodingNoTextWithDisplay_Expect_NullFlavorCdXmlWithOriginalTextFromDisplay() { + var inputJson = """ + { + "resourceType": "Observation", + "code": { + "coding": [ + { + "system": "http://read.info/readv2", + "code": "42Q5.00", + "display": "Prothrombin time" + } + ] + } + }"""; + + var expectedOutput = """ + + Prothrombin time + """; + var codeableConcept = fhirParseService.parseResource(inputJson, Observation.class).getCode(); + + var outputMessage = codeableConceptCdMapper.mapCodeableConceptToCdForBloodPressure(codeableConcept); + + assertThat(outputMessage).isEqualToIgnoringWhitespace(expectedOutput); + } + + @Test + void When_WithNonSnomedCodingWithDescriptionExtensionWithoutDisplay_Expect_SnomedCdXmlWithOriginalTextFromDisplay() { + var inputJson = """ + { + "resourceType": "Observation", + "code": { + "coding": [ + { + "system": "http://read.info/readv2", + "code": "42Q5.00", + "display": "Prothrombin time", + "extension": [ + { + "url": "https://fhir.nhs.uk/STU3/StructureDefinition/Extension-coding-sctdescid", + "extension": [ + { + "url": "descriptioÍnId", + "valueId": "12345789" + } + ] + } + ] + } + ] + } + }"""; + var expectedOutput = """ + + Prothrombin time + """; + var codeableConcept = fhirParseService.parseResource(inputJson, Observation.class).getCode(); + + var outputMessage = codeableConceptCdMapper.mapCodeableConceptToCdForBloodPressure(codeableConcept); + + assertThat(outputMessage).isEqualToIgnoringWhitespace(expectedOutput); + } + + @Test + void When_WithNonSnomedCodingWithDescriptionExtensionWithDisplayExtension_Expect_SnomedCdXmlWithOriginalTextFromDisplayExtension() { + var inputJson = """ + { + "resourceType": "Observation", + "code": { + "coding": [ + { + "system": "http://read.info/readv2", + "code": "42Q5.00", + "display": "Prothrombin time", + "extension": [ + { + "url": "https://fhir.nhs.uk/STU3/StructureDefinition/Extension-coding-sctdescid", + "extension": [ + { + "url": "descriptionDisplay", + "valueString": "Prothrombin time (observed)" + } + ] + } + ] + } + ] + } + }"""; + var expectedOutput = """ + + Prothrombin time (observed) + """; + var codeableConcept = fhirParseService.parseResource(inputJson, Observation.class).getCode(); + + var outputMessage = codeableConceptCdMapper.mapCodeableConceptToCdForBloodPressure(codeableConcept); + + assertThat(outputMessage).isEqualToIgnoringWhitespace(expectedOutput); + } + } + + @Nested + class WhenMappingToNullFlavorCodeableConcept { + @Test + void When_WithSnomedCodingNoTextNoDisplayWithDescriptionExtensionWithDisplayExtension_Expect_SnomedCdXmlWithoutOriginalText() { + var inputJson = """ + { + "resourceType": "Observation", + "code": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "852471000000107", + "extension": [ + { + "url": "https://fhir.nhs.uk/STU3/StructureDefinition/Extension-coding-sctdescid", + "extension": [ + { + "url": "descriptionDisplay", + "valueString": "Prothrombin time (observed)" + } + ] + } + ] + } + ] + } + }"""; + + var expectedOutput = """ + + """; + var codeableConcept = fhirParseService.parseResource(inputJson, Observation.class).getCode(); + + var outputMessage = codeableConceptCdMapper.mapToNullFlavorCodeableConcept(codeableConcept); + + assertThat(outputMessage).isEqualToIgnoringWhitespace(expectedOutput); + } + + @Test + void When_WithSnomedCodingNoTextNoDisplayWithNonDescriptionExtension_Expect_SnomedCdXmlWithoutOriginalText() { + var inputJson = """ + { + "resourceType": "Observation", + "code": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "852471000000107", + "extension": [ + { + "url": "https://fhir.nhs.uk/STU3/StructureDefinition/Extension-coding-sctdescid", + "extension": [ + { + "url": "descriptionDisplay", + "valueString": "Prothrombin time (observed)" + } + ] + } + ] + } + ] + } + }"""; + + var expectedOutput = """ + + """; + var codeableConcept = fhirParseService.parseResource(inputJson, Observation.class).getCode(); + + var outputMessage = codeableConceptCdMapper.mapToNullFlavorCodeableConcept(codeableConcept); + + assertThat(outputMessage).isEqualToIgnoringWhitespace(expectedOutput); + } + + @Test + void When_WithNonSnomedCodingWithText_Expect_SnomedCdXmlWithOriginalTexFromText() { + var inputJson = """ + { + "resourceType": "Observation", + "code": { + "coding": [ + { + "system": "http://read.info/readv2", + "code": "42Q5.00", + "display": "Observed Prothrombin time" + } + ], + "text": "Prothrombin time (observed)" + } + }"""; + + var expectedOutput = """ + + Prothrombin time (observed) + """; + var codeableConcept = fhirParseService.parseResource(inputJson, Observation.class).getCode(); + + var outputMessage = codeableConceptCdMapper.mapToNullFlavorCodeableConcept(codeableConcept); + + assertThat(outputMessage).isEqualToIgnoringWhitespace(expectedOutput); + } + + @Test + void When_WithNonSnomedCodingWithNoTextWithNonDescriptionExtension_Expect_SnomedCdXmlWithOriginalTextFromDisplay() { + var inputJson = """ + { + "resourceType": "Observation", + "code": { + "coding": [ + { + "system": "http://read.info/readv2", + "code": "42Q5.00", + "display": "Observed Prothrombin time", + "extension": [ + { + "url": "https://fhir.nhs.uk/STU3/StructureDefinition/Extension-some-otherUrl", + "extension": [ + { + "url": "descriptionDisplay", + "valueString": "Prothrombin time" + } + ] + } + ] + } + ] + } + }"""; + + var expectedOutput = """ + + Observed Prothrombin time + """; + var codeableConcept = fhirParseService.parseResource(inputJson, Observation.class).getCode(); + + var outputMessage = codeableConceptCdMapper.mapToNullFlavorCodeableConcept(codeableConcept); + + assertThat(outputMessage).isEqualToIgnoringWhitespace(expectedOutput); + } + + @Test + void When_WithNonSnomedCodingWithNoDisplayNoTextWithDescriptionExtNoDisplayExt_Expect_SnomedCdXmlWithoutOriginalText() { + var inputJson = """ + { + "resourceType": "Observation", + "code": { + "coding": [ + { + "system": "http://read.info/readv2", + "code": "42Q5.00", + "extension": [ + { + "url": "https://fhir.nhs.uk/STU3/StructureDefinition/Extension-coding-sctdescid", + "extension": [ + { + "url": "descriptionId", + "valueString": "123456789" + } + ] + } + ] + } + ] + } + }"""; + + var expectedOutput = """ + + """; + var codeableConcept = fhirParseService.parseResource(inputJson, Observation.class).getCode(); + + var outputMessage = codeableConceptCdMapper.mapToNullFlavorCodeableConcept(codeableConcept); + + assertThat(outputMessage).isEqualToIgnoringWhitespace(expectedOutput); + } + + @Test + void When_WithNonSnomedCodingWithDisplayNoTextWithDescriptionExtNoDisplayExt_Expect_SnomedCdXmlWithOriginalTextFromDisplay() { + var inputJson = """ + { + "resourceType": "Observation", + "code": { + "coding": [ + { + "system": "http://read.info/readv2", + "code": "42Q5.00", + "display": "Observed Prothrombin time", + "extension": [ + { + "url": "https://fhir.nhs.uk/STU3/StructureDefinition/Extension-coding-sctdescid", + "extension": [ + { + "url": "descriptionId", + "valueString": "123456789" + } + ] + } + ] + } + ] + } + }"""; + + var expectedOutput = """ + + Observed Prothrombin time + """; + var codeableConcept = fhirParseService.parseResource(inputJson, Observation.class).getCode(); + + var outputMessage = codeableConceptCdMapper.mapToNullFlavorCodeableConcept(codeableConcept); + + assertThat(outputMessage).isEqualToIgnoringWhitespace(expectedOutput); + } + + @Test + void When_WithNonSnomedCodingNoTextWithDescriptionExtWithDisplayExt_Expect_SnomedCdXmlWithOriginalTextFromDisplayExtension() { + var inputJson = """ + { + "resourceType": "Observation", + "code": { + "coding": [ + { + "system": "http://read.info/readv2", + "code": "42Q5.00", + "display": "Observed Prothrombin time", + "extension": [ + { + "url": "https://fhir.nhs.uk/STU3/StructureDefinition/Extension-coding-sctdescid", + "extension": [ + { + "url": "descriptionDisplay", + "valueString": "Prothrombin time" + } + ] + } + ] + } + ] + } + }"""; + + var expectedOutput = """ + + Prothrombin time + """; + var codeableConcept = fhirParseService.parseResource(inputJson, Observation.class).getCode(); + + var outputMessage = codeableConceptCdMapper.mapToNullFlavorCodeableConcept(codeableConcept); + + assertThat(outputMessage).isEqualToIgnoringWhitespace(expectedOutput); + } + + @Test + void When_WithNonSnomedCodingNoTextNoDescriptionExtension_Expect_SnomedCdXmlWithOriginalTextFromDisplay() { + var inputJson = """ + { + "resourceType": "Observation", + "code": { + "coding": [ + { + "system": "http://read.info/readv2", + "code": "42Q5.00", + "display": "Observed Prothrombin time" + } + ] + } + }"""; + + var expectedOutput = """ + + Observed Prothrombin time + """; + var codeableConcept = fhirParseService.parseResource(inputJson, Observation.class).getCode(); + + var outputMessage = codeableConceptCdMapper.mapToNullFlavorCodeableConcept(codeableConcept); + + assertThat(outputMessage).isEqualToIgnoringWhitespace(expectedOutput); + } + + @Test + void When_WithNonSnomedCodingNoDisplayNoTextNoDescriptionExtension_Expect_SnomedCdXmlWithNoOriginalText() { + var inputJson = """ + { + "resourceType": "Observation", + "code": { + "coding": [ + { + "system": "http://read.info/readv2", + "code": "42Q5.00" + } + ] + } + }"""; + + var expectedOutput = """ + + """; + var codeableConcept = fhirParseService.parseResource(inputJson, Observation.class).getCode(); + + var outputMessage = codeableConceptCdMapper.mapToNullFlavorCodeableConcept(codeableConcept); + + assertThat(outputMessage).isEqualToIgnoringWhitespace(expectedOutput); + } + } + @ParameterizedTest @MethodSource("getTestArgumentsForTopicRelatedProblem") @SneakyThrows