Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -50,27 +50,29 @@ public void extractChildReferencesFromEhrComposition(RCMRMT030101UKEhrCompositio

public void extractChildReferencesFromCompoundStatement(RCMRMT030101UKCompoundStatement compoundStatement,
List<Reference> entryReferences) {
if (compoundStatement != null) {
if (isDiagnosticReport(compoundStatement)) {
addDiagnosticReportEntry(compoundStatement, entryReferences);
} else {

compoundStatement.getComponent().forEach(component -> {
addObservationStatementEntry(
component.getObservationStatement(), entryReferences, compoundStatement);
addPlanStatementEntry(component.getPlanStatement(), entryReferences);
addRequestStatementEntry(component.getRequestStatement(), entryReferences);
addLinkSetEntry(component.getLinkSet(), entryReferences);
addMedicationEntry(component.getMedicationStatement(), entryReferences);
if (compoundStatement == null) {
return;
}

if (isDiagnosticReport(compoundStatement)) {
addDiagnosticReportEntry(compoundStatement, entryReferences);
return;
}

if (isNotIgnoredResource(compoundStatement, entryReferences)) {
addNarrativeStatementEntry(component.getNarrativeStatement(), entryReferences);
}
compoundStatement.getComponent().forEach(component -> {
addObservationStatementEntry(component.getObservationStatement(), entryReferences, compoundStatement);
addPlanStatementEntry(component.getPlanStatement(), entryReferences);
addRequestStatementEntry(component.getRequestStatement(), entryReferences);
addLinkSetEntry(component.getLinkSet(), entryReferences);
addMedicationEntry(component.getMedicationStatement(), entryReferences);

extractChildReferencesFromCompoundStatement(component.getCompoundStatement(), entryReferences);
});
if (isNotIgnoredResource(compoundStatement, entryReferences)) {
addNarrativeStatementEntry(component.getNarrativeStatement(), entryReferences);
}
}

extractChildReferencesFromCompoundStatement(component.getCompoundStatement(), entryReferences);
});
}

public void extractChildReferencesFromTemplate(RCMRMT030101UKCompoundStatement compoundStatement,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import static java.nio.charset.StandardCharsets.UTF_8;

import java.io.File;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.JAXBElement;
Expand All @@ -16,12 +18,26 @@
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class XmlUnmarshallUtil {

private static final ConcurrentMap<Class<?>, JAXBContext> CONTEXT_CACHE = new ConcurrentHashMap<>();

private static JAXBContext getContext(Class<?> clazz) {
return CONTEXT_CACHE.computeIfAbsent(clazz, c -> {
try {
return JAXBContext.newInstance(c);

Check warning on line 26 in gp2gp-translator/src/main/java/uk/nhs/adaptors/pss/translator/util/XmlUnmarshallUtil.java

View workflow job for this annotation

GitHub Actions / pitest

2 different changes can be made to a lambda on line 26 without causing a test to fail

removed last varargs argument in call to newInstance in 1st lambda in getContext (covered by 14 tests VarargsMutator) replaced return value with null for 1st lambda in getContext (covered by 14 tests NullReturnValsMutator)
} catch (JAXBException e) {
throw new RuntimeException(e);
}
});
}

public static <T> T unmarshallFile(File xmlFile, Class<T> destinationClass) throws JAXBException {
Unmarshaller unmarshaller = createUnmarshaller(destinationClass);

Unmarshaller unmarshaller = getContext(destinationClass).createUnmarshaller();
JAXBElement<T> unmarshalledMessage = (JAXBElement) unmarshaller.unmarshal(xmlFile);
return unmarshalledMessage.getValue();
}


public static <T> T unmarshallString(String xmlString, Class<T> destinationClass) throws JAXBException {
Unmarshaller unmarshaller = createUnmarshaller(destinationClass);
JAXBElement<T> unmarshalledMessage = (JAXBElement) unmarshaller.unmarshal(
Expand Down
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file still has places where we have assertions such as: assertThat(references.size()).isOne() which is less efficient than assertThat(references).hasSize(1)

Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,54 @@ public class ResourceReferenceUtilTest {

private static final String XML_RESOURCES_COMPOSITION = "xml/ResourceReference/EhrComposition/";
private static final String XML_RESOURCES_COMPOUND = "xml/ResourceReference/CompoundStatement/";
private static final int ONE = 1;
private static final int TWO = 2;

private static final int THREE = 3;
private static final int FOUR = 4;

@Mock
private DatabaseImmunizationChecker immunizationChecker;

@InjectMocks
private ResourceReferenceUtil resourceReferenceUtil;

@Test
public void testNarrativeStatementReferencedAtCompoundStatementLevel() {
final RCMRMT030101UKCompoundStatement compoundStatement
= unmarshallCompoundStatementElement("compound_statement_with_narrative_statement.xml");

List<Reference> references = new ArrayList<>();
resourceReferenceUtil.extractChildReferencesFromCompoundStatement(compoundStatement, references);

assertThat(references).hasSize(ONE);
assertThat(references.getFirst().getReference()).isEqualTo("Observation/07F5EAC0-90B5-11EC-B1E5-0800200C9A66");
}

@Test
public void testPlanAndRequestStatementReferencedAtCompoundStatementLevel() {
final RCMRMT030101UKCompoundStatement compoundStatement
= unmarshallCompoundStatementElement("compound_statement_with_plan_and_request_statement.xml");

List<Reference> references = new ArrayList<>();
resourceReferenceUtil.extractChildReferencesFromCompoundStatement(compoundStatement, references);

assertThat(references).hasSize(FOUR);
assertThat(references.get(2).getReference()).isEqualTo("ProcedureRequest/3316531F-5705-424C-9E1A-EE694FB411B4");
assertThat(references.get(THREE).getReference()).isEqualTo("ReferralRequest/B4303C92-4D1C-11E3-A2DD-010000000161");
}

@Test
public void testPlanStatementReferencedAtEhrCompositionLevel() {
final RCMRMT030101UKEhrComposition ehrComposition
= unmarshallEhrCompositionElement("ehr_composition_with_plan_statement.xml");

List<Reference> references = new ArrayList<>();
resourceReferenceUtil.extractChildReferencesFromEhrComposition(ehrComposition, references);

assertThat(references).hasSize(THREE);
assertThat(references.get(2).getReference()).isEqualTo("ProcedureRequest/3316531F-5705-424C-9E1A-EE694FB411B4");
}

@Test
public void testMedicationResourcesReferencedAtEhrCompositionLevel() {
final RCMRMT030101UKEhrComposition ehrComposition = unmarshallEhrCompositionElement("ehr_composition_medication.xml");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<CompoundStatement xmlns="urn:hl7-org:v3" classCode="TOPIC" moodCode="EVN">
<id root="3D8A2760-90B4-11EC-B1E5-0800200C9A66"/>
<code code="14L..00" codeSystem="2.16.840.1.113883.2.1.6.2"
displayName="H/O: drug allergy"/>
<statusCode code="COMPLETE"/>
<effectiveTime>
<center value="19781231"/>
</effectiveTime>
<availabilityTime value="19781231"/>
<component typeCode="COMP" contextConductionInd="true">
<CompoundStatement classCode="CATEGORY" moodCode="EVN">
<id root="07F5EAC0-90B5-11EC-B1E5-0800200C9A66"/>
<code code="1234" codeSystem="2.16.840.1.113883.2.1.6.3"
displayName="H/O: drug allergy"/>
<statusCode code="COMPLETE"/>
<effectiveTime>
<center value="19781231"/>
</effectiveTime>
<availabilityTime value="19781231"/>
<component typeCode="COMP" contextConductionInd="true">
<CompoundStatement classCode="CLUSTER" moodCode="EVN">
<id root="COMPOUND_STATEMENT_CHILD_ID_1"/>
<code code="123038009" codeSystem="2.16.840.1.113883.2.1.3.2.4.15"
displayName="specimen (specimen)"/>
<statusCode code="COMPLETE"/>
<effectiveTime>
<center nullFlavor="NI"/>
</effectiveTime>
<availabilityTime value="20100225154100"/>
<specimen typeCode="SPC">
<specimenRole classCode="SPEC">
<id root="SPECIMEN_ROLE_ID_1"/>
<id root="2.16.840.1.113883.2.1.4.5.2" extension="SPECIMEN_ROLE_ID_EXTENSION"/>
<effectiveTime>
<center value="20100223000000"/>
</effectiveTime>
<specimenSpecimenMaterial determinerCode="INSTANCE" classCode="MAT">
<desc>EINE KLEINE</desc>
</specimenSpecimenMaterial>
</specimenRole>
</specimen>
<component typeCode="COMP" contextConductionInd="true">
<NarrativeStatement classCode="OBS" moodCode="EVN">
<id root="07F5EAC0-90B5-11EC-B1E5-0800200C9A66"/>
<text mediaType="text/x-h7uk-pmip">CommentType:LAB SPECIMEN COMMENT(E271)
CommentDate:20020330092100

Received Date: 2002-03-30 09:21
</text>
<statusCode code="COMPLETE"/>
<availabilityTime value="20020330000000"/>
</NarrativeStatement>
</component>
</CompoundStatement>
</component>
<component typeCode="COMP" contextConductionInd="true">
<ObservationStatement classCode="OBS" moodCode="EVN">
<id root="3DCC9FC9-1873-4004-9789-C4E5C52B02B9"/>
<referenceRange typeCode="REFV">
<referenceInterpretationRange classCode="OBS" moodCode="EVN.CRT">
<text>Test Range 1</text>
<value>
<low value="10.5" unit="L"/>
<high value="12.2" unit="L"/>
</value>
</referenceInterpretationRange>
</referenceRange>
<code code="1683.00" codeSystem="2.16.840.1.113883.2.1.6.2"
displayName="Tired all the time">
<translation code="267032009" codeSystem="2.16.840.1.113883.2.1.3.2.4.15"
displayName="Tired all the time"/>
</code>
<statusCode code="COMPLETE"/>
<effectiveTime>
<center nullFlavor="NI"/>
</effectiveTime>
<availabilityTime value="201101111533"/>
<pertinentInformation typeCode="PERT">
<sequenceNumber value="+1"/>
<pertinentAnnotation classCode="OBS" moodCode="EVN">
<text>Notes on the tired all the time entry</text>
</pertinentAnnotation>
</pertinentInformation>
</ObservationStatement>
</component>
<component typeCode="COMP" contextConductionInd="true">
<NarrativeStatement classCode="OBS" moodCode="EVN">
<id root="278ADD5F-2AC7-48DC-966A-0BA7C029C793"/>
<text>Comments - Aaaargh</text>
<statusCode code="COMPLETE"/>
<availabilityTime value="201101111533"/>
</NarrativeStatement>
</component>
</CompoundStatement>
</component>
</CompoundStatement>
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
<CompoundStatement xmlns="urn:hl7-org:v3" classCode="TOPIC" moodCode="EVN">
<id root="3D8A2760-90B4-11EC-B1E5-0800200C9A66"/>
<code code="14L..00" codeSystem="2.16.840.1.113883.2.1.6.2"
displayName="H/O: drug allergy"/>
<statusCode code="COMPLETE"/>
<effectiveTime>
<center value="19781231"/>
</effectiveTime>
<availabilityTime value="19781231"/>
<component typeCode="COMP" contextConductionInd="true">
<CompoundStatement classCode="CATEGORY" moodCode="EVN">
<id root="07F5EAC0-90B5-11EC-B1E5-0800200C9A66"/>
<code code="1234" codeSystem="2.16.840.1.113883.2.1.6.3"
displayName="H/O: drug allergy"/>
<statusCode code="COMPLETE"/>
<effectiveTime>
<center value="19781231"/>
</effectiveTime>
<availabilityTime value="19781231"/>
<component typeCode="COMP">
<MedicationStatement xmlns="urn:hl7-org:v3" classCode="SBADM" moodCode="INT">
<id root="B4D70A6D-2EE4-41B6-B1FB-F9F0AD84C503" />
<statusCode code="ACTIVE" />
<effectiveTime>
<high value="20060426" />
<center nullFlavor="NI" />
</effectiveTime>
<availabilityTime value="20100115" />
<consumable typeCode="CSM">
<manufacturedProduct classCode="MANU">
<manufacturedMaterial classCode="MMAT" determinerCode="KIND">
<code code="RACA57NEMIS" codeSystem="2.16.840.1.113883.2.1.6.9" displayName="Ramipril 10mg capsules">
<translation code="318906001" codeSystem="2.16.840.1.113883.2.1.3.2.4.15" displayName="Ramipril 10mg capsules" />
</code>
<quantity value="28" unit="1">
<translation value="28">
<originalText>capsule</originalText>
</translation>
</quantity>
</manufacturedMaterial>
</manufacturedProduct>
</consumable>
<component typeCode="COMP">
<ehrSupplyAuthorise classCode="SPLY" moodCode="INT">
<id root="A0A70B62-2649-4C8F-B3AB-618B8257C942" />
<code code="9bG0.00" codeSystem="2.16.840.1.113883.2.1.6.2" displayName="NHS prescription" />
<statusCode code="ACTIVE" />
<effectiveTime>
<center nullFlavor="NI" />
</effectiveTime>
<availabilityTime value="20100114" />
<repeatNumber value="6" />
<quantity value="28" unit="1">
<translation value="28">
<originalText>capsule</originalText>
</translation>
</quantity>
<pertinentInformation typeCode="PERT">
<pertinentSupplyAnnotation classCode="OBS" moodCode="EVN">
<text>Pharmacy Text: Repeat Dispensing Pharmacy Note. 1</text>
</pertinentSupplyAnnotation>
</pertinentInformation>
<pertinentInformation typeCode="PERT">
<pertinentSupplyAnnotation classCode="OBS" moodCode="EVN">
<text>Pharmacy Text: Repeat Dispensing Pharmacy Note. 2</text>
</pertinentSupplyAnnotation>
</pertinentInformation>
</ehrSupplyAuthorise>
</component>
<component typeCode="COMP">
<ehrSupplyPrescribe classCode="SPLY" moodCode="RQO">
<id root="9B4B797A-D674-4362-B666-2ADC8551EEDA"/>
<code code="394823007" displayName="NHS Prescription" codeSystem="2.16.840.1.113883.2.1.3.2.4.15"/>
<statusCode code="COMPLETE"/>
<availabilityTime value="20060426"/>
<quantity value="1" unit="1">
<translation value="1">
<originalText>tablet(s)</originalText>
</translation>
</quantity>
<inFulfillmentOf typeCode="FLFS">
<priorMedicationRef moodCode="INT">
<id root="TEST_ID"/>
</priorMedicationRef>
</inFulfillmentOf>
</ehrSupplyPrescribe>
</component>
</MedicationStatement>
</component>
<component typeCode="COMP" >
<PlanStatement classCode="OBS" moodCode="INT">
<id root="3316531F-5705-424C-9E1A-EE694FB411B4" />
<code code="282653015" codeSystem="2.16.840.1.113883.2.1.3.2.4.15" displayName="Medication review">
</code>
<statusCode code="COMPLETE" />
<effectiveTime>
<center value="20110115"/>
</effectiveTime>
<availabilityTime value="20100115100646"/>
<Participant typeCode="PRF" contextControlCode="OP">
<agentRef classCode="AGNT">
<id root="2D70F602-6BB1-47E0-B2EC-39912A59787D"/>
</agentRef>
</Participant>
</PlanStatement>
</component>
<component>
<RequestStatement classCode="OBS" moodCode="RQO">
<id root="B4303C92-4D1C-11E3-A2DD-010000000161"/>
<code code="8HV6." codeSystem="2.16.840.1.113883.2.1.3.2.4.14" displayName="Reason Code">
<translation code="183885007" codeSystem="2.16.840.1.113883.2.1.3.2.4.15" displayName="Reason Code 1"/>
<translation code="8HV6.00" codeSystem="2.16.840.1.113883.2.1.6.2" displayName="Reason Code 2"/>
</code>
<text>Test request statement text
New line</text>
<statusCode code="COMPLETE"/>
<effectiveTime>
<center value="20050406" nullFlavor="NI"/>
</effectiveTime>
<availabilityTime value="20100101123000"/>
<priorityCode code="394848005" displayName="Normal" codeSystem="2.16.840.1.113883.2.1.3.2.4.15"><originalText>Routine</originalText></priorityCode>
<responsibleParty typeCode="RESP">
<agentRef classCode="AGNT">
<id root="B8CA3710-4D1C-11E3-9E6B-010000001205"/>
</agentRef>
</responsibleParty>
<Participant typeCode="PPRF" contextControlCode="OP">
<agentRef classCode="AGNT">
<id root="58341512-03F3-4C8E-B41C-A8FCA3886BBB"/>
</agentRef>
</Participant>
</RequestStatement>
</component>
</CompoundStatement>
</component>
</CompoundStatement>
Loading