org.openmrs.module.pacsintegration.converter.OrderToPacsConverter.java Source code

Java tutorial

Introduction

Here is the source code for org.openmrs.module.pacsintegration.converter.OrderToPacsConverter.java

Source

/**
 * The contents of this file are subject to the OpenMRS Public License
 * Version 1.0 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://license.openmrs.org
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific language governing rights and limitations
 * under the License.
 *
 * Copyright (C) OpenMRS, LLC.  All Rights Reserved.
 */
package org.openmrs.module.pacsintegration.converter;

import ca.uhn.hl7v2.HL7Exception;
import ca.uhn.hl7v2.model.v23.message.ORM_O01;
import ca.uhn.hl7v2.model.v23.segment.MSH;
import ca.uhn.hl7v2.model.v23.segment.OBR;
import ca.uhn.hl7v2.model.v23.segment.ORC;
import ca.uhn.hl7v2.model.v23.segment.PID;
import ca.uhn.hl7v2.model.v23.segment.PV1;
import ca.uhn.hl7v2.parser.Parser;
import ca.uhn.hl7v2.parser.PipeParser;
import org.apache.commons.lang.StringUtils;
import org.openmrs.ConceptMap;
import org.openmrs.ConceptMapType;
import org.openmrs.ConceptSource;
import org.openmrs.Location;
import org.openmrs.LocationAttribute;
import org.openmrs.LocationAttributeType;
import org.openmrs.Order;
import org.openmrs.PatientIdentifierType;
import org.openmrs.Provider;
import org.openmrs.api.AdministrationService;
import org.openmrs.api.ConceptService;
import org.openmrs.api.LocationService;
import org.openmrs.api.PatientService;
import org.openmrs.module.emrapi.EmrApiProperties;
import org.openmrs.module.radiologyapp.RadiologyConstants;
import org.openmrs.module.radiologyapp.RadiologyOrder;
import org.openmrs.module.radiologyapp.RadiologyProperties;
import org.openmrs.module.pacsintegration.PacsIntegrationConstants;
import org.openmrs.module.pacsintegration.PacsIntegrationProperties;
import org.openmrs.module.pacsintegration.util.HL7Utils;

import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Set;

public class OrderToPacsConverter {

    private Parser parser = new PipeParser();

    private PatientService patientService;

    private AdministrationService adminService;

    private ConceptService conceptService;

    private LocationService locationService;

    private EmrApiProperties emrApiProperties;

    private RadiologyProperties radiologyProperties;

    private PacsIntegrationProperties pacsIntegrationProperties;

    public String convertToPacsFormat(RadiologyOrder order, String orderControl) throws HL7Exception {

        // TODO: some kind of null checking and checking for invalid values

        ORM_O01 message = new ORM_O01();

        // handle the MSH component
        MSH msh = message.getMSH();
        HL7Utils.populateMessageHeader(msh, new Date(), "ORM", "O01",
                adminService.getGlobalProperty(PacsIntegrationConstants.GP_SENDING_FACILITY));

        // handle the patient component
        PID pid = message.getPATIENT().getPID();
        pid.getPatientIDInternalID(0).getID()
                .setValue(order.getPatient().getPatientIdentifier(getPatientIdentifierType()).getIdentifier());
        pid.getPatientName().getFamilyName().setValue(StringUtils.substring(order.getPatient().getFamilyName(), 0,
                PacsIntegrationConstants.MAX_LENGTH_FAMILY_NAME));
        pid.getPatientName().getGivenName().setValue(StringUtils.substring(order.getPatient().getGivenName(), 0,
                PacsIntegrationConstants.MAX_LENGTH_GIVEN_NAME));
        pid.getDateOfBirth().getTimeOfAnEvent()
                .setValue(order.getPatient().getBirthdate() != null
                        ? HL7Utils.getHl7DateFormat().format(order.getPatient().getBirthdate())
                        : "");
        pid.getSex().setValue(order.getPatient().getGender());
        // TODO: do we need patient admission ID / account number

        PV1 pv1 = message.getPATIENT().getPATIENT_VISIT().getPV1();

        // TODO: do we need patient class
        if (order.getExamLocation() != null) {

            // set the location code if one has been specified
            String locationCode = getLocationCode(order.getExamLocation());
            if (StringUtils.isNotBlank(locationCode)) {
                pv1.getAssignedPatientLocation().getPointOfCare().setValue(locationCode);
            }

            pv1.getAssignedPatientLocation().getLocationType().setValue(order.getExamLocation().getName());
        }

        if (order.getEncounter() != null) {
            Set<Provider> referringProviders = order.getEncounter()
                    .getProvidersByRole(emrApiProperties.getOrderingProviderEncounterRole());
            if (referringProviders != null && referringProviders.size() > 0) {
                // note that if there are multiple clinicians associated with the encounter, we only sent the first one
                Provider referringProvider = referringProviders.iterator().next();
                pv1.getReferringDoctor(0).getIDNumber().setValue(referringProvider.getIdentifier());
                pv1.getReferringDoctor(0).getFamilyName().setValue(referringProvider.getPerson().getFamilyName());
                pv1.getReferringDoctor(0).getGivenName().setValue(referringProvider.getPerson().getGivenName());
            }
        }

        ORC orc = message.getORDER().getORC();
        orc.getOrderControl().setValue(orderControl);

        OBR obr = message.getORDER().getORDER_DETAIL().getOBR();
        obr.getFillerOrderNumber().getEntityIdentifier().setValue(order.getOrderNumber());
        obr.getUniversalServiceIdentifier().getIdentifier().setValue(getProcedureCode(order));

        obr.getUniversalServiceIdentifier().getText()
                .setValue(StringUtils.substring(
                        order.getConcept().getFullySpecifiedName(getDefaultLocale()).getName(), 0,
                        PacsIntegrationConstants.MAX_LENGTH_PROCEDURE_TYPE_DESCRIPTION));

        // note that we are just sending modality here, not the device location
        obr.getPlacerField2().setValue(getModalityCode(order));
        obr.getQuantityTiming().getPriority().setValue(order.getUrgency().equals(Order.Urgency.STAT) ? "STAT" : "");
        obr.getScheduledDateTime().getTimeOfAnEvent()
                .setValue(HL7Utils.getHl7DateFormat().format(order.getDateActivated()));

        // break the reason for study up by lines
        if (StringUtils.isNotBlank(order.getClinicalHistory())) {
            int i = 0;
            for (String line : order.getClinicalHistory().split("\r\n")) {
                obr.getReasonForStudy(i).getText().setValue(line);
                i++;
            }
        }

        return parser.encode(message);
    }

    private String getProcedureCode(Order order) {

        if (order.getConcept() == null) {
            throw new RuntimeException("Concept must be specified on an order to send to PACS");
        }

        ConceptSource procedureCodesConceptSource = pacsIntegrationProperties.getProcedureCodesConceptSource();
        ConceptMapType sameAsConceptMapType = getSameAsConceptMapType();

        for (ConceptMap conceptMap : order.getConcept().getConceptMappings()) {
            if (conceptMap.getConceptMapType().equals(sameAsConceptMapType) && conceptMap.getConceptReferenceTerm()
                    .getConceptSource().equals(procedureCodesConceptSource)) {
                // note that this just returns the first code it finds; the assumption is that there is only one SAME-AS
                // code from the specified source for the each concept
                return conceptMap.getConceptReferenceTerm().getCode();
            }
        }

        throw new RuntimeException("No valid procedure code found for concept " + order.getConcept());
    }

    private String getModalityCode(Order order) {

        if (order.getConcept() == null) {
            throw new RuntimeException("Concept must be specified on an order to send to PACS");
        }

        if (radiologyProperties.getXrayOrderablesConcept().getSetMembers().contains(order.getConcept())) {
            return RadiologyConstants.XRAY_MODALITY_CODE;
        }
        if (radiologyProperties.getCTScanOrderablesConcept().getSetMembers().contains(order.getConcept())) {
            return RadiologyConstants.CT_SCAN_MODALITY_CODE;
        }
        if (radiologyProperties.getUltrasoundOrderablesConcept().getSetMembers().contains(order.getConcept())) {
            return RadiologyConstants.ULTRASOUND_MODALITY_CODE;
        } else {
            // TODO: double-check if McKesson PACS will have problem if no modality code is set
            return "";
        }

    }

    private PatientIdentifierType getPatientIdentifierType() {
        PatientIdentifierType patientIdentifierType = patientService.getPatientIdentifierTypeByUuid(
                adminService.getGlobalProperty(PacsIntegrationConstants.GP_PATIENT_IDENTIFIER_TYPE_UUID));
        if (patientIdentifierType == null) {
            throw new RuntimeException(
                    "No patient identifier type specified. Is pacsintegration.patientIdentifierTypeUuid properly set?");
        } else {
            return patientIdentifierType;
        }
    }

    private LocationAttributeType getLocationCodeAttributeType() {
        // we allow this to be null
        return locationService.getLocationAttributeTypeByUuid(
                adminService.getGlobalProperty(PacsIntegrationConstants.GP_LOCATION_CODE_ATTRIBUTE_TYPE_UUID));

    }

    private String getLocationCode(Location location) {

        LocationAttributeType locationCodeAttributeType = getLocationCodeAttributeType();

        if (locationCodeAttributeType == null) {
            return null;
        }

        List<LocationAttribute> locationCodes = location.getActiveAttributes(locationCodeAttributeType);

        if (locationCodes == null || locationCodes.size() == 0) {
            return null;
        }

        // there should never be more than one active location code, so we just use a get(0) here
        if (locationCodes.get(0).getValue() != null) {
            return locationCodes.get(0).getValue().toString();
        } else {
            return null;
        }
    }

    private Locale getDefaultLocale() {
        String defaultLocale = adminService.getGlobalProperty(PacsIntegrationConstants.GP_DEFAULT_LOCALE);

        if (StringUtils.isEmpty(defaultLocale)) {
            defaultLocale = "en";
        }

        return new Locale(defaultLocale);
    }

    private ConceptMapType getSameAsConceptMapType() {
        return conceptService.getConceptMapTypeByUuid(PacsIntegrationConstants.SAME_AS_CONCEPT_MAP_TYPE_UUID);
    }

    public void setPatientService(PatientService patientService) {
        this.patientService = patientService;
    }

    public void setAdminService(AdministrationService adminService) {
        this.adminService = adminService;
    }

    public void setConceptService(ConceptService conceptService) {
        this.conceptService = conceptService;
    }

    public void setLocationService(LocationService locationService) {
        this.locationService = locationService;
    }

    public void setRadiologyProperties(RadiologyProperties radiologyProperties) {
        this.radiologyProperties = radiologyProperties;
    }

    public void setEmrApiProperties(EmrApiProperties emrApiProperties) {
        this.emrApiProperties = emrApiProperties;
    }

    public void setPacsIntegrationProperties(PacsIntegrationProperties pacsIntegrationProperties) {
        this.pacsIntegrationProperties = pacsIntegrationProperties;
    }
}