Search in sources :

Example 31 with DocumentReference

use of org.hl7.fhir.r4.model.DocumentReference in project hl7v2-fhir-converter by LinuxForHealth.

the class Hl7DocumentReferenceFHIRConversionTest method doc_ref_date_test.

@ParameterizedTest
@ValueSource(strings = { "MDM^T02", "MDM^T06" })
void doc_ref_date_test(String segment) {
    String documentReferenceMessage = "MSH|^~\\&|HL7Soup|Instance1|MCM|Instance2|200911021022|Security|" + segment + "^MDM_T02|64322|P|2.6|123|456|ER|AL|USA|ASCII|en|2.6|56789^NID^UID|MCM||||\n" + "PID|1||000054321^^^MRN|||||||||||||M|CAT|||||N\n" + "PV1|1|I||||||||||||||||||||||||||||||||||||||||||\n" + "ORC|NW|||PGN001|SC|D|1|||MS|MS|||||\n" + "OBR|1||||||20170825010500|||||||||||||002|||||F||||||||\n" + "TXA|1||TEXT|||20180117144200|201801180346||<PHYSID1>||||||||||AV|||<PHYSID2>||\n" + "OBX|1|ST|100||This is content|||||||X\n";
    DocumentReference report = ResourceUtils.getDocumentReference(ftv, documentReferenceMessage);
    InstantType date = report.getDateElement();
    // TXA.6
    assertThat(date.toString()).containsPattern("2018-01-17T14:42");
}
Also used : InstantType(org.hl7.fhir.r4.model.InstantType) DocumentReference(org.hl7.fhir.r4.model.DocumentReference) ValueSource(org.junit.jupiter.params.provider.ValueSource) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest)

Example 32 with DocumentReference

use of org.hl7.fhir.r4.model.DocumentReference in project hl7v2-fhir-converter by LinuxForHealth.

the class Hl7MDMMessageTest method noMixingOfParamsInDocumentReference.

// An example message for reference:
// "MSH|^~\\&|HNAM|W|RAD_IMAGING_REPORT|W|20180118111520||MDM^T06|<MESSAGEID>|P|2.6\n"
// + "PID|||1234^^^^MR||DOE^JANE^|||F||||||||||||||||||||||\n"
// + "PV1|1|O|2GY^2417^W||||ATT_ID^ATT_LN^ATT_MI^ATT_FN^^^MD|REF_ID^REF_LN^REF_MI^REF_FN^^^MD|CONSULTING_ID^CONSULTING_LN^CONSULTING_MI^CONSULTING_FN^^^MD||||||||ADM_ID^ADM_LN^ADM_MI^ADM_FN^^^MD|OTW|<HospitalID>|||||||||||||||||||||||||20180115102400|20180118104500\n"
// + "ORC|NW|622470H432|||||^^^^^R|||||123456789^MILLER^BOB|123D432^^^Family Practice Clinic||||||||FAMILY PRACTICE CLINIC\n"
// + "OBR|1|622470H432|102397CE432|LAMIKP^AMIKACIN LEVEL, PEAK^83718||20170725143849|20180102||||L|||||123456789^MILLER^BOB|||REASON_TEXT_1|||||RAD|O||^^^^^R||||REASON_ID_1^REASON_TEXT_1|RESP_ID1&RESP_FAMILY_1&RESP_GIVEN1||TECH_1_ID&TECH_1_FAMILY&TECH_1_GIVEN|TRANS_1_ID&TRANS_1_FAMILY&TRANS_1_GIVEN\n"
// + "ORC|NW|9494138H600|||||^^^^^R|||||1992779250^TEST^DOCTOR\n"
// + "OBR|1|9494138H600^ORDER_PLACER_NAMESPACE_2|1472232CE600|83718^HIGH-DENSITY LIPOPROTEIN (HDL)^NAMING2||20150909170243|||||L|||||1992779250^TEST^DOCTOR||||||||CAT|A||^^^20180204^^R||||REASON_ID_2^REASON_TEXT_2|RESP_ID2&RESP_FAMILY_2&RESP_GIVEN2||TECH_2_ID&TECH_2_FAMILY&TECH_2_GIVEN|TRANS_2_ID&TRANS_2_FAMILY&TRANS_2_GIVEN\n"
// + "TXA|1|05^Operative Report|TX|201801171442|5566^PAPLast^PAPFirst^J^^MD|201801171442|201801180346||<PHYSID>|<PHYSID>|MODL|<MESSAGEID>||4466^TRANSCLast^TRANSCFirst^J^^MD|<MESSAGEID>||P||AV\n"
// + "OBX|1|TX|05^Operative Report||                        <HOSPITAL NAME>||||||P\n"
// + "OBX|2|TX|05^Operative Report||                             <HOSPITAL ADDRESS2>||||||P\n"
// + "OBX|3|TX|05^Operative Report||                              <HOSPITAL ADDRESS2>||||||P\n";
// This test assures we don't have data mixing in the placer / filler identifiers.
@ParameterizedTest
@ValueSource(strings = { "MDM^T02", "MDM^T06" })
void noMixingOfParamsInDocumentReference(String message) throws IOException {
    String hl7message = "MSH|^~\\&|HNAM|W|RAD_IMAGING_REPORT|W|20180118111520||MDM^T02|" + message + "|P|2.6\n" + "PID|||1234^^^^MR||DOE^JANE^|||F||||||||||||||||||||||\n" + "PV1|1|O|2GY^2417^W||||D||||||||||OTW|<HospitalID>|||||||||||||||||||||||||20180115102400|20180118104500\n" + // We expect a filler of OBR 3.1 and no system because OBR 3.2 is the matched field and is empty (System in ORC 3.2 is ignored.)
    "ORC|NW||^SYS-AAA-ORC32||||^^^^^R|||||1992779250^TEST^DOCTOR-AAA|||||||||\n" + "OBR|1|ID-AAA-OBR21|ID-AAA-OBR31|LAMIKP^AMIKACIN LEVEL, PEAK^83718|||||||L|||||||||||||RAD|O||^^^^^R||||||||\n" + // We expect a filler of OBR 3.1 and system because OBR 3.2 is the matched field and has a system
    "ORC|NW|ID-BBB-ORC21|||||^^^^^R|||||1992779251^TEST^DOCTOR-BBB\n" + "OBR|1|ID-BBB-OBR21^SYS-BBB-OBR22|ID-BBB-OBR31^SYS-BBB-OBR32|83718^HIGH-DENSITY LIPOPROTEIN (HDL)^NAMING2||||||||||||||||||||CAT|A||^^^20180204^^R||||||||\n" + "TXA|1|05^Operative Report|TX|201801171442|5566^PAPLast^PAPFirst^J^^MD|201801171442|201801180346||<PHYSID>|<PHYSID>|MODL|<MESSAGEID>||4466^TRANSCLast^TRANSCFirst^J^^MD|<MESSAGEID>||P||AV\n" + "OBX|1|TX|05^Operative Report||                        <HOSPITAL NAME>||||||P\n" + "OBX|2|TX|05^Operative Report||                             <HOSPITAL ADDRESS2>||||||P\n" + "OBX|3|TX|05^Operative Report||                              <HOSPITAL ADDRESS2>||||||P\n";
    List<BundleEntryComponent> e = ResourceUtils.createFHIRBundleFromHL7MessageReturnEntryList(ftv, hl7message);
    // Check for the expected resources
    List<Resource> encounterResource = ResourceUtils.getResourceList(e, ResourceType.Encounter);
    // from EVN, PV1
    assertThat(encounterResource).hasSize(1);
    List<Resource> patientResource = ResourceUtils.getResourceList(e, ResourceType.Patient);
    // from PID
    assertThat(patientResource).hasSize(1);
    // Two ServiceRequests from the two ORC's.  One references Dr AAA the other references Dr BBB
    List<Resource> serviceRequests = ResourceUtils.getResourceList(e, ResourceType.ServiceRequest);
    // from TXA, OBX(type TX)
    assertThat(serviceRequests).hasSize(2);
    ServiceRequest srDrAAA = ResourceUtils.getResourceServiceRequest(serviceRequests.get(0), ResourceUtils.context);
    ServiceRequest srDrBBB = ResourceUtils.getResourceServiceRequest(serviceRequests.get(1), ResourceUtils.context);
    // Figure out which is first and reassign if needed for testing
    if (!srDrAAA.getRequester().getDisplay().contains("DOCTOR-AAA TEST")) {
        ServiceRequest temp = srDrAAA;
        srDrAAA = srDrBBB;
        srDrBBB = temp;
    }
    // Three ID's for srDrAAA
    // Map of String arrays of expected (Value, System)
    HashMap<String, List<String>> matchSrDrAAAidValuesSystems = new HashMap<String, List<String>>();
    matchSrDrAAAidValuesSystems.put("VN", Arrays.asList("20180118111520", ""));
    matchSrDrAAAidValuesSystems.put("FILL", Arrays.asList("ID-AAA-OBR31", ""));
    matchSrDrAAAidValuesSystems.put("PLAC", Arrays.asList("ID-AAA-OBR21", ""));
    List<Identifier> identifiers = srDrAAA.getIdentifier();
    // Validate the note contents and references
    for (int idIndex = 0; idIndex < identifiers.size(); idIndex++) {
        // condIndex is index for condition
        // Get the list of Observation references
        Identifier ident = identifiers.get(idIndex);
        String code = ident.getType().getCodingFirstRep().getCode();
        assertThat(ident.getValue()).hasToString(matchSrDrAAAidValuesSystems.get(code).get(0));
        String system = ident.getSystem() == null ? "" : ident.getSystem();
        assertThat(system).hasToString(matchSrDrAAAidValuesSystems.get(code).get(1));
    }
    // Three ID's for srDrBBB
    // Map of String arrays of expected (Value, System)
    HashMap<String, List<String>> matchSrDrBBBidValuesSystems = new HashMap<String, List<String>>();
    matchSrDrBBBidValuesSystems.put("VN", Arrays.asList("20180118111520", ""));
    matchSrDrBBBidValuesSystems.put("FILL", Arrays.asList("ID-BBB-OBR31", "urn:id:SYS-BBB-OBR32"));
    matchSrDrBBBidValuesSystems.put("PLAC", Arrays.asList("ID-BBB-ORC21", ""));
    identifiers = srDrBBB.getIdentifier();
    // Validate the note contents and references
    for (int idIndex = 0; idIndex < identifiers.size(); idIndex++) {
        // condIndex is index for condition
        // Get the list of Observation references
        Identifier ident = identifiers.get(idIndex);
        String code = ident.getType().getCodingFirstRep().getCode();
        assertThat(ident.getValue()).hasToString(matchSrDrBBBidValuesSystems.get(code).get(0));
        String system = ident.getSystem() == null ? "" : ident.getSystem();
        assertThat(system).hasToString(matchSrDrBBBidValuesSystems.get(code).get(1));
    }
    List<Resource> documentReferenceResource = ResourceUtils.getResourceList(e, ResourceType.DocumentReference);
    // from TXA, OBX(type TX)
    assertThat(documentReferenceResource).hasSize(1);
    DocumentReference docRef = ResourceUtils.getResourceDocumentReference(documentReferenceResource.get(0), ResourceUtils.context);
    // TODO: Solve the problem of data bleed when there is more than one ServiceRequest
    // Three ID's for DocRef
    // Map of String arrays of expected (Value, System)
    HashMap<String, List<String>> matchDocRefIdValuesSystems = new HashMap<String, List<String>>();
    matchDocRefIdValuesSystems.put("EntityId", Arrays.asList("<MESSAGEID>", ""));
    // What we get - mix of SR1 and SR2
    matchDocRefIdValuesSystems.put("FILL", Arrays.asList("ID-AAA-OBR31", "urn:id:SYS-BBB-OBR32"));
    // matchDocRefIdValuesSystems.put("FILL", Arrays.asList("ID-BBB-OBR31","urn:id:SYS-BBB-OBR32")); // What we think it should be
    matchDocRefIdValuesSystems.put("PLAC", Arrays.asList("ID-BBB-ORC21", ""));
    identifiers = docRef.getIdentifier();
    // Validate the note contents and references
    for (int idIndex = 0; idIndex < identifiers.size(); idIndex++) {
        // condIndex is index for condition
        // Get the list of Observation references
        Identifier ident = identifiers.get(idIndex);
        if (ident.hasType()) {
            String code = ident.getType().getCodingFirstRep().getCode();
            assertThat(ident.getValue()).hasToString(matchDocRefIdValuesSystems.get(code).get(0));
            String system = ident.getSystem() == null ? "" : ident.getSystem();
            assertThat(system).hasToString(matchDocRefIdValuesSystems.get(code).get(1));
        }
    }
    List<Resource> practitioners = ResourceUtils.getResourceList(e, ResourceType.Practitioner);
    assertThat(practitioners).hasSize(7);
    // Confirm that no extra resources are created
    assertThat(e.size()).isEqualTo(12);
}
Also used : HashMap(java.util.HashMap) Resource(org.hl7.fhir.r4.model.Resource) ServiceRequest(org.hl7.fhir.r4.model.ServiceRequest) BundleEntryComponent(org.hl7.fhir.r4.model.Bundle.BundleEntryComponent) Identifier(org.hl7.fhir.r4.model.Identifier) List(java.util.List) DocumentReference(org.hl7.fhir.r4.model.DocumentReference) ValueSource(org.junit.jupiter.params.provider.ValueSource) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest)

Example 33 with DocumentReference

use of org.hl7.fhir.r4.model.DocumentReference in project hl7v2-fhir-converter by LinuxForHealth.

the class Hl7IdentifierFHIRConversionTest method documentReferenceIdentifierTest2.

@Test
void documentReferenceIdentifierTest2() {
    // Filler from OBR, placer from TXA-14
    String documentReferenceMessage = "MSH|^~\\&|HL7Soup|Instance1|MCM|Instance2|200911021022|Security|MDM^T02|64322|P|2.6|123|456|ER|AL|USA|ASCII|en|2.6|56789^NID^UID|MCM||||\n" + "PID|1||000054321^^^MRN|||||||||||||M|CAT|||||N\n" + "PV1|1|I|||||||||||||||||||||||||||||||||||||||||||\n" + "ORC|NW|||PGN001|SC|D|1||20170825010500|MS|MS||||20170825010500|\n" + "OBR|1||CD_000000^OE|2244^General Order|||20170825010500||||||Relevant Clinical Information|||||||002|||||F|||550600^Tsadok550600^Janetary~660600^Merrit660600^Darren^F~770600^Das770600^Surjya^P~880600^Winter880600^Oscar^||||770600&Das770600&Surjya&P^^^6N^1234^A|\n" + "TXA|1||B45678|||||||||||PON001^IE||\n";
    DocumentReference report = ResourceUtils.getDocumentReference(ftv, documentReferenceMessage);
    // Expect 3 identifiers
    assertThat(report.hasIdentifier()).isTrue();
    assertThat(report.getIdentifier()).hasSize(3);
    List<Identifier> identifiers = report.getIdentifier();
    // Match the three id's to position; we can't depend on an order.
    int posExtId = getIdentifierPositionByValue("200911021022", identifiers);
    assertThat(posExtId).isNotSameAs(-1);
    int posFILLER = getIdentifierPositionByValue("CD_000000", identifiers);
    assertThat(posFILLER).isNotSameAs(-1);
    int posPLACER = getIdentifierPositionByValue("PON001", identifiers);
    assertThat(posPLACER).isNotSameAs(-1);
    // Identifier 1: extID from MSH-7
    Identifier identifier = report.getIdentifier().get(posExtId);
    String value = identifier.getValue();
    String system = identifier.getSystem();
    // MSH-7
    assertThat(value).isEqualTo("200911021022");
    assertThat(system).isEqualTo("urn:id:extID");
    // Identifier 2: Filler
    Identifier identifier2 = report.getIdentifier().get(posFILLER);
    value = identifier2.getValue();
    system = identifier2.getSystem();
    // OBR.3.1
    assertThat(value).isEqualTo("CD_000000");
    // OBR.3.2
    assertThat(system).isEqualTo("urn:id:OE");
    CodeableConcept type = identifier2.getType();
    Coding coding = type.getCoding().get(0);
    assertThat(type.getText()).isNull();
    assertThat(coding.getSystem()).isEqualTo("http://terminology.hl7.org/CodeSystem/v2-0203");
    assertThat(coding.getCode()).isEqualTo("FILL");
    assertThat(coding.getDisplay()).isEqualTo("Filler Identifier");
    // Identifier 3: Placer
    Identifier identifier3 = report.getIdentifier().get(posPLACER);
    value = identifier3.getValue();
    system = identifier3.getSystem();
    // TXA-14.1
    assertThat(value).isEqualTo("PON001");
    // TXA.14.2
    assertThat(system).isEqualTo("urn:id:IE");
    type = identifier3.getType();
    coding = type.getCoding().get(0);
    assertThat(type.getText()).isNull();
    assertThat(coding.getSystem()).isEqualTo("http://terminology.hl7.org/CodeSystem/v2-0203");
    assertThat(coding.getCode()).isEqualTo("PLAC");
    assertThat(coding.getDisplay()).isEqualTo("Placer Identifier");
}
Also used : Identifier(org.hl7.fhir.r4.model.Identifier) Coding(org.hl7.fhir.r4.model.Coding) DocumentReference(org.hl7.fhir.r4.model.DocumentReference) CodeableConcept(org.hl7.fhir.r4.model.CodeableConcept) Test(org.junit.jupiter.api.Test)

Example 34 with DocumentReference

use of org.hl7.fhir.r4.model.DocumentReference in project hl7v2-fhir-converter by LinuxForHealth.

the class Hl7IdentifierFHIRConversionTest method documentReferenceIdentifierTest.

@Test
void documentReferenceIdentifierTest() {
    // Filler and placer from ORC, extID from MSH-7
    String documentReference = "MSH|^~\\&|HL7Soup|Instance1|MCM|Instance2|200911021022|Security|MDM^T02|64322|P|2.6|123|456|ER|AL|USA|ASCII|en|2.6|56789^NID^UID|MCM||||\n" + "PID|1||000054321^^^MRN|||||||||||||M|CAT|||||N\n" + "PV1|1|I|||||||||||||||||||||||||||||||||||||||||||\n" + "ORC|NW|PON001^LE|FON001^OE|PGN001|SC|D|1||20170825010500|MS|MS||||20170825010500|\n" + "OBR|1||CD_000000^IE|2244^General Order|||20170825010500||||||Relevant Clinical Information|||||||002|||||F|||550600^Tsadok550600^Janetary~660600^Merrit660600^Darren^F~770600^Das770600^Surjya^P~880600^Winter880600^Oscar^||||770600&Das770600&Surjya&P^^^6N^1234^A|\n" + "TXA|1||B45678||||||\n";
    DocumentReference report = ResourceUtils.getDocumentReference(ftv, documentReference);
    // Expect 3 identifiers
    assertThat(report.hasIdentifier()).isTrue();
    assertThat(report.getIdentifier()).hasSize(3);
    List<Identifier> identifiers = report.getIdentifier();
    // Match the three id's to position; we can't depend on an order.
    int posExtId = getIdentifierPositionByValue("200911021022", identifiers);
    assertThat(posExtId).isNotSameAs(-1);
    int posFILLER = getIdentifierPositionByValue("FON001", identifiers);
    assertThat(posFILLER).isNotSameAs(-1);
    int posPLACER = getIdentifierPositionByValue("PON001", identifiers);
    assertThat(posPLACER).isNotSameAs(-1);
    // Identifier 1: extID from MSH-7
    Identifier identifier = report.getIdentifier().get(posExtId);
    String value = identifier.getValue();
    String system = identifier.getSystem();
    // MSH-7
    assertThat(value).isEqualTo("200911021022");
    assertThat(system).isEqualTo("urn:id:extID");
    // Identifier 2: Filler
    Identifier identifier2 = report.getIdentifier().get(posFILLER);
    value = identifier2.getValue();
    system = identifier2.getSystem();
    // ORC.3.1
    assertThat(value).isEqualTo("FON001");
    // ORC.3.2
    assertThat(system).isEqualTo("urn:id:OE");
    CodeableConcept type = identifier2.getType();
    Coding coding = type.getCoding().get(0);
    assertThat(type.getText()).isNull();
    assertThat(coding.getSystem()).isEqualTo("http://terminology.hl7.org/CodeSystem/v2-0203");
    assertThat(coding.getCode()).isEqualTo("FILL");
    assertThat(coding.getDisplay()).isEqualTo("Filler Identifier");
    // Identifier 3: Placer
    Identifier identifier3 = report.getIdentifier().get(posPLACER);
    value = identifier3.getValue();
    system = identifier3.getSystem();
    // ORC.2.1
    assertThat(value).isEqualTo("PON001");
    // ORC.2.2
    assertThat(system).isEqualTo("urn:id:LE");
    type = identifier3.getType();
    coding = type.getCoding().get(0);
    assertThat(type.getText()).isNull();
    assertThat(coding.getSystem()).isEqualTo("http://terminology.hl7.org/CodeSystem/v2-0203");
    assertThat(coding.getCode()).isEqualTo("PLAC");
    assertThat(coding.getDisplay()).isEqualTo("Placer Identifier");
}
Also used : Identifier(org.hl7.fhir.r4.model.Identifier) Coding(org.hl7.fhir.r4.model.Coding) DocumentReference(org.hl7.fhir.r4.model.DocumentReference) CodeableConcept(org.hl7.fhir.r4.model.CodeableConcept) Test(org.junit.jupiter.api.Test)

Example 35 with DocumentReference

use of org.hl7.fhir.r4.model.DocumentReference in project summary-care-record-api by NHSDigital.

the class GetScrService method buildDocumentReference.

private DocumentReference buildDocumentReference(String nhsNumber, EventListQueryResponse response, Patient patient) {
    DocumentReference documentReference = new DocumentReference();
    documentReference.setId(randomUUID());
    documentReference.addSecurityLabel(new CodeableConcept(new Coding().setCode(response.getViewPermission().getFhirValue()).setSystem(ACS_SYSTEM)));
    documentReference.setStatus(CURRENT);
    documentReference.setType(GP_SUMMARY_SNOMED);
    documentReference.setSubject(new Reference(patient));
    DocumentReferenceContentComponent content = buildDocumentReferenceContent(nhsNumber, response.getLatestScrId());
    documentReference.addContent(content);
    documentReference.setMasterIdentifier(new Identifier().setValue(response.getLatestScrId()).setSystem(SCR_ID_SYSTEM));
    DocumentReferenceContextComponent context = new DocumentReferenceContextComponent();
    context.addEvent(GP_SUMMARY_SNOMED);
    documentReference.setContext(context);
    return documentReference;
}
Also used : Identifier(org.hl7.fhir.r4.model.Identifier) DocumentReferenceContextComponent(org.hl7.fhir.r4.model.DocumentReference.DocumentReferenceContextComponent) Coding(org.hl7.fhir.r4.model.Coding) Reference(org.hl7.fhir.r4.model.Reference) DocumentReference(org.hl7.fhir.r4.model.DocumentReference) DocumentReference(org.hl7.fhir.r4.model.DocumentReference) CodeableConcept(org.hl7.fhir.r4.model.CodeableConcept) DocumentReferenceContentComponent(org.hl7.fhir.r4.model.DocumentReference.DocumentReferenceContentComponent)

Aggregations

DocumentReference (org.hl7.fhir.r4.model.DocumentReference)32 ParameterizedTest (org.junit.jupiter.params.ParameterizedTest)15 ValueSource (org.junit.jupiter.params.provider.ValueSource)15 Identifier (org.hl7.fhir.r4.model.Identifier)12 CodeableConcept (org.hl7.fhir.r4.model.CodeableConcept)10 Coding (org.hl7.fhir.r4.model.Coding)8 Attachment (org.hl7.fhir.r4.model.Attachment)7 Reference (org.hl7.fhir.r4.model.Reference)7 BundleEntryComponent (org.hl7.fhir.r4.model.Bundle.BundleEntryComponent)6 Practitioner (org.hl7.fhir.r4.model.Practitioner)6 Resource (org.hl7.fhir.r4.model.Resource)6 Complex (org.hl7.fhir.dstu2016may.formats.RdfGenerator.Complex)5 IBaseResource (org.hl7.fhir.instance.model.api.IBaseResource)5 Bundle (org.hl7.fhir.r4.model.Bundle)5 HashMap (java.util.HashMap)4 Complex (org.hl7.fhir.dstu3.utils.formats.Turtle.Complex)4 DocumentReferenceContextComponent (org.hl7.fhir.r4.model.DocumentReference.DocumentReferenceContextComponent)4 Complex (org.hl7.fhir.r4.utils.formats.Turtle.Complex)4 Test (org.junit.jupiter.api.Test)4 Identifiable (org.openehealth.ipf.commons.ihe.xds.core.metadata.Identifiable)4