Search in sources :

Example 21 with HL7Exception

use of ca.uhn.hl7v2.HL7Exception in project openmrs-core by openmrs.

the class ORUR01Handler method getForm.

/**
 * needs to find a Form based on information in MSH-21. example: 16^AMRS.ELD.FORMID
 *
 * @param msh
 * @return
 * @should pass if return value is null when uuid and id is null
 * @should pass if return value is not null when uuid or id is not null
 * @throws HL7Exception
 */
public Form getForm(MSH msh) throws HL7Exception {
    String uuid = null;
    String id = null;
    for (EI identifier : msh.getMessageProfileIdentifier()) {
        if (identifier != null && identifier.getNamespaceID() != null) {
            String identifierType = identifier.getNamespaceID().getValue();
            if (OpenmrsUtil.nullSafeEquals(identifierType, HL7Constants.HL7_FORM_UUID)) {
                uuid = identifier.getEntityIdentifier().getValue();
            } else if (OpenmrsUtil.nullSafeEquals(identifierType, HL7Constants.HL7_FORM_ID)) {
                id = identifier.getEntityIdentifier().getValue();
            } else {
                log.warn("Form identifier type of " + identifierType + " unknown to ORU R01 processor.");
            }
        }
    }
    Form form = null;
    if (uuid == null && id == null) {
        return form;
    }
    // prefer uuid over id
    if (uuid != null) {
        form = Context.getFormService().getFormByUuid(uuid);
    }
    // if uuid did not work ...
    if (id != null) {
        try {
            Integer formId = Integer.parseInt(id);
            form = Context.getFormService().getForm(formId);
        } catch (NumberFormatException e) {
            throw new HL7Exception(Context.getMessageSourceService().getMessage("ORUR01.error.parseFormId"), e);
        }
    }
    return form;
}
Also used : EI(ca.uhn.hl7v2.model.v25.datatype.EI) Form(org.openmrs.Form) HL7Exception(ca.uhn.hl7v2.HL7Exception)

Example 22 with HL7Exception

use of ca.uhn.hl7v2.HL7Exception in project openmrs-core by openmrs.

the class ORUR01Handler method processMessage.

/**
 * Processes an ORU R01 event message
 *
 * @should create encounter and obs from hl7 message
 * @should create basic concept proposal
 * @should create concept proposal and with obs alongside
 * @should not create problem list observation with concept proposals
 * @should append to an existing encounter
 * @should create obs group for OBRs
 * @should create obs valueCodedName
 * @should fail on empty concept proposals
 * @should fail on empty concept answers
 * @should set value_Coded matching a boolean concept for obs if the answer is 0 or 1 and
 *         Question datatype is coded
 * @should set value as boolean for obs if the answer is 0 or 1 and Question datatype is Boolean
 * @should set value_Numeric for obs if Question datatype is Numeric and the answer is either 0
 *         or 1
 * @should set value_Numeric for obs if Question datatype is Numeric
 * @should fail if question datatype is coded and a boolean is not a valid answer
 * @should fail if question datatype is neither Boolean nor numeric nor coded
 * @should create an encounter and find the provider by identifier
 * @should create an encounter and find the provider by personId
 * @should create an encounter and find the provider by uuid
 * @should create an encounter and find the provider by providerId
 * @should fail if the provider name type code is not specified and is not a personId
 * @should understand form uuid if present
 * @should prefer form uuid over id if both are present
 * @should prefer form id if uuid is not found
 * @should set complex data for obs with complex concepts
 */
@Override
public Message processMessage(Message message) throws ApplicationException {
    if (!(message instanceof ORU_R01)) {
        throw new ApplicationException(Context.getMessageSourceService().getMessage("ORUR01.error.invalidMessage"));
    }
    log.debug("Processing ORU_R01 message");
    Message response;
    try {
        ORU_R01 oru = (ORU_R01) message;
        response = processORU_R01(oru);
    } catch (ClassCastException e) {
        log.warn("Error casting " + message.getClass().getName() + " to ORU_R01", e);
        throw new ApplicationException(Context.getMessageSourceService().getMessage("ORUR01.error.invalidMessageType ", new Object[] { message.getClass().getName() }, null), e);
    } catch (HL7Exception e) {
        log.warn("Error while processing ORU_R01 message", e);
        throw new ApplicationException(Context.getMessageSourceService().getMessage("ORUR01.error.WhileProcessing"), e);
    }
    log.debug("Finished processing ORU_R01 message");
    return response;
}
Also used : ApplicationException(ca.uhn.hl7v2.app.ApplicationException) Message(ca.uhn.hl7v2.model.Message) ORU_R01(ca.uhn.hl7v2.model.v25.message.ORU_R01) HL7Exception(ca.uhn.hl7v2.HL7Exception)

Example 23 with HL7Exception

use of ca.uhn.hl7v2.HL7Exception in project openmrs-core by openmrs.

the class ORUR01Handler method parseObs.

/**
 * Creates the Obs pojo from the OBX message
 *
 * @param encounter The Encounter object this Obs is a member of
 * @param obx The hl7 obx message
 * @param obr The parent hl7 or message
 * @param uid unique string for this message for any error reporting purposes
 * @return Obs pojo with all values filled in
 * @throws HL7Exception if there is a parsing exception
 * @throws ProposingConceptException if the answer to this obs is a proposed concept
 * @should add comments to an observation from NTE segments
 * @should add multiple comments for an observation as one comment
 * @should add comments to an observation group
 */
private Obs parseObs(Encounter encounter, OBX obx, OBR obr, String uid) throws HL7Exception, ProposingConceptException {
    if (log.isDebugEnabled()) {
        log.debug("parsing observation: " + obx);
    }
    Varies[] values = obx.getObservationValue();
    // bail out if no values were found
    if (values == null || values.length < 1) {
        return null;
    }
    String hl7Datatype = values[0].getName();
    if (log.isDebugEnabled()) {
        log.debug("  datatype = " + hl7Datatype);
    }
    Concept concept = getConcept(obx.getObservationIdentifier(), uid);
    if (log.isDebugEnabled()) {
        log.debug("  concept = " + concept.getConceptId());
    }
    ConceptName conceptName = getConceptName(obx.getObservationIdentifier());
    if (log.isDebugEnabled()) {
        log.debug("  concept-name = " + conceptName);
    }
    Date datetime = getDatetime(obx);
    if (log.isDebugEnabled()) {
        log.debug("  timestamp = " + datetime);
    }
    if (datetime == null) {
        datetime = encounter.getEncounterDatetime();
    }
    Obs obs = new Obs();
    obs.setPerson(encounter.getPatient());
    obs.setConcept(concept);
    obs.setEncounter(encounter);
    obs.setObsDatetime(datetime);
    obs.setLocation(encounter.getLocation());
    obs.setCreator(encounter.getCreator());
    obs.setDateCreated(encounter.getDateCreated());
    // set comments if there are any
    StringBuilder comments = new StringBuilder();
    ORU_R01_OBSERVATION parent = (ORU_R01_OBSERVATION) obx.getParent();
    // iterate over all OBX NTEs
    for (int i = 0; i < parent.getNTEReps(); i++) {
        for (FT obxComment : parent.getNTE(i).getComment()) {
            if (comments.length() > 0) {
                comments.append(" ");
            }
            comments = comments.append(obxComment.getValue());
        }
    }
    // only set comments if there are any
    if (StringUtils.hasText(comments.toString())) {
        obs.setComment(comments.toString());
    }
    Type obx5 = values[0].getData();
    if ("NM".equals(hl7Datatype)) {
        String value = ((NM) obx5).getValue();
        if (value == null || value.length() == 0) {
            log.warn("Not creating null valued obs for concept " + concept);
            return null;
        } else if ("0".equals(value) || "1".equals(value)) {
            concept = concept.hydrate(concept.getConceptId().toString());
            obs.setConcept(concept);
            if (concept.getDatatype().isBoolean()) {
                obs.setValueBoolean("1".equals(value));
            } else if (concept.getDatatype().isNumeric()) {
                try {
                    obs.setValueNumeric(Double.valueOf(value));
                } catch (NumberFormatException e) {
                    throw new HL7Exception(Context.getMessageSourceService().getMessage("ORUR01.error.notnumericConcept", new Object[] { value, concept.getConceptId(), conceptName.getName(), uid }, null), e);
                }
            } else if (concept.getDatatype().isCoded()) {
                Concept answer = "1".equals(value) ? Context.getConceptService().getTrueConcept() : Context.getConceptService().getFalseConcept();
                boolean isValidAnswer = false;
                Collection<ConceptAnswer> conceptAnswers = concept.getAnswers();
                if (conceptAnswers != null && !conceptAnswers.isEmpty()) {
                    for (ConceptAnswer conceptAnswer : conceptAnswers) {
                        if (conceptAnswer.getAnswerConcept().getId().equals(answer.getId())) {
                            obs.setValueCoded(answer);
                            isValidAnswer = true;
                            break;
                        }
                    }
                }
                // answer the boolean answer concept was't found
                if (!isValidAnswer) {
                    throw new HL7Exception(Context.getMessageSourceService().getMessage("ORUR01.error.invalidAnswer", new Object[] { answer.toString(), uid }, null));
                }
            } else {
                // throw this exception to make sure that the handler doesn't silently ignore bad hl7 message
                throw new HL7Exception(Context.getMessageSourceService().getMessage("ORUR01.error.CannotSetBoolean", new Object[] { obs.getConcept().getConceptId() }, null));
            }
        } else {
            try {
                obs.setValueNumeric(Double.valueOf(value));
            } catch (NumberFormatException e) {
                throw new HL7Exception(Context.getMessageSourceService().getMessage("ORUR01.error.notnumericConcept", new Object[] { value, concept.getConceptId(), conceptName.getName(), uid }, null), e);
            }
        }
    } else if ("CWE".equals(hl7Datatype)) {
        log.debug("  CWE observation");
        CWE value = (CWE) obx5;
        String valueIdentifier = value.getIdentifier().getValue();
        log.debug("    value id = " + valueIdentifier);
        String valueName = value.getText().getValue();
        log.debug("    value name = " + valueName);
        if (isConceptProposal(valueIdentifier)) {
            if (log.isDebugEnabled()) {
                log.debug("Proposing concept");
            }
            throw new ProposingConceptException(concept, valueName);
        } else {
            log.debug("    not proposal");
            try {
                Concept valueConcept = getConcept(value, uid);
                obs.setValueCoded(valueConcept);
                if (HL7Constants.HL7_LOCAL_DRUG.equals(value.getNameOfAlternateCodingSystem().getValue())) {
                    Drug valueDrug = new Drug();
                    valueDrug.setDrugId(Integer.valueOf(value.getAlternateIdentifier().getValue()));
                    obs.setValueDrug(valueDrug);
                } else {
                    ConceptName valueConceptName = getConceptName(value);
                    if (valueConceptName != null) {
                        if (log.isDebugEnabled()) {
                            log.debug("    value concept-name-id = " + valueConceptName.getConceptNameId());
                            log.debug("    value concept-name = " + valueConceptName.getName());
                        }
                        obs.setValueCodedName(valueConceptName);
                    }
                }
            } catch (NumberFormatException e) {
                throw new HL7Exception(Context.getMessageSourceService().getMessage("ORUR01.error.InvalidConceptId", new Object[] { valueIdentifier, valueName }, null));
            }
        }
        if (log.isDebugEnabled()) {
            log.debug("  Done with CWE");
        }
    } else if ("CE".equals(hl7Datatype)) {
        CE value = (CE) obx5;
        String valueIdentifier = value.getIdentifier().getValue();
        String valueName = value.getText().getValue();
        if (isConceptProposal(valueIdentifier)) {
            throw new ProposingConceptException(concept, valueName);
        } else {
            try {
                obs.setValueCoded(getConcept(value, uid));
                obs.setValueCodedName(getConceptName(value));
            } catch (NumberFormatException e) {
                throw new HL7Exception(Context.getMessageSourceService().getMessage("ORUR01.error.InvalidConceptId", new Object[] { valueIdentifier, valueName }, null));
            }
        }
    } else if ("DT".equals(hl7Datatype)) {
        DT value = (DT) obx5;
        if (value != null) {
            Date valueDate = getDate(value.getYear(), value.getMonth(), value.getDay(), 0, 0, 0);
            obs.setValueDatetime(valueDate);
        } else {
            log.warn("Not creating null valued obs for concept " + concept);
            return null;
        }
    } else if ("TS".equals(hl7Datatype)) {
        DTM value = ((TS) obx5).getTime();
        if (value != null) {
            Date valueDate = getDate(value.getYear(), value.getMonth(), value.getDay(), value.getHour(), value.getMinute(), value.getSecond());
            obs.setValueDatetime(valueDate);
        } else {
            log.warn("Not creating null valued obs for concept " + concept);
            return null;
        }
    } else if ("TM".equals(hl7Datatype)) {
        TM value = (TM) obx5;
        if (value != null) {
            Date valueTime = getDate(0, 0, 0, value.getHour(), value.getMinute(), value.getSecond());
            obs.setValueDatetime(valueTime);
        } else {
            log.warn("Not creating null valued obs for concept " + concept);
            return null;
        }
    } else if ("ST".equals(hl7Datatype)) {
        ST value = (ST) obx5;
        if (value == null || value.getValue() == null || value.getValue().trim().length() == 0) {
            log.warn("Not creating null valued obs for concept " + concept);
            return null;
        }
        obs.setValueText(value.getValue());
    } else if ("ED".equals(hl7Datatype)) {
        ED value = (ED) obx5;
        if (value == null || value.getData() == null || !StringUtils.hasText(value.getData().getValue())) {
            log.warn("Not creating null valued obs for concept " + concept);
            return null;
        }
        // we need to hydrate the concept so that the EncounterSaveHandler
        // doesn't fail since it needs to check if it is a concept numeric
        Concept c = Context.getConceptService().getConcept(obs.getConcept().getConceptId());
        obs.setConcept(c);
        String title = null;
        if (obs.getValueCodedName() != null) {
            title = obs.getValueCodedName().getName();
        }
        if (!StringUtils.hasText(title)) {
            title = c.getName().getName();
        }
        obs.setComplexData(new ComplexData(title, value.getData().getValue()));
    } else {
        // do we need to support BIT just in case it slips thru?
        throw new HL7Exception(Context.getMessageSourceService().getMessage("ORUR01.error.UpsupportedObsType", new Object[] { hl7Datatype }, null));
    }
    return obs;
}
Also used : FT(ca.uhn.hl7v2.model.v25.datatype.FT) CWE(ca.uhn.hl7v2.model.v25.datatype.CWE) DT(ca.uhn.hl7v2.model.v25.datatype.DT) ComplexData(org.openmrs.obs.ComplexData) ConceptName(org.openmrs.ConceptName) ED(ca.uhn.hl7v2.model.v25.datatype.ED) Concept(org.openmrs.Concept) ORU_R01_OBSERVATION(ca.uhn.hl7v2.model.v25.group.ORU_R01_OBSERVATION) Drug(org.openmrs.Drug) Obs(org.openmrs.Obs) ST(ca.uhn.hl7v2.model.v25.datatype.ST) CE(ca.uhn.hl7v2.model.v25.datatype.CE) ConceptAnswer(org.openmrs.ConceptAnswer) Date(java.util.Date) RelationshipType(org.openmrs.RelationshipType) EncounterType(org.openmrs.EncounterType) Type(ca.uhn.hl7v2.model.Type) PersonAttributeType(org.openmrs.PersonAttributeType) HL7Exception(ca.uhn.hl7v2.HL7Exception) Collection(java.util.Collection) TM(ca.uhn.hl7v2.model.v25.datatype.TM) DTM(ca.uhn.hl7v2.model.v25.datatype.DTM) DTM(ca.uhn.hl7v2.model.v25.datatype.DTM) Varies(ca.uhn.hl7v2.model.Varies) NM(ca.uhn.hl7v2.model.v25.datatype.NM) TS(ca.uhn.hl7v2.model.v25.datatype.TS)

Example 24 with HL7Exception

use of ca.uhn.hl7v2.HL7Exception in project openmrs-core by openmrs.

the class HL7Util method parseHL7Timestamp.

/**
 * Converts an HL7 timestamp into a java.util.Date object. HL7 timestamps can be created with
 * varying levels of precision &mdash; e.g., just the year or just the year and month, etc.
 * Since java.util.Date cannot store a partial value, we fill in defaults like January, 01 at
 * midnight within the current timezone.
 *
 * @param s HL7 timestamp to be parsed
 * @return Date object
 * @throws HL7Exception
 * @should fail on 78
 * @should handle 1978
 * @should fail on 19784
 * @should handle 197804
 * @should fail on 197841
 * @should handle 19780411
 * @should fail on 197804116
 * @should handle 1978041106
 * @should fail on 19780411065
 * @should handle 197804110615
 * @should fail on 1978041106153
 * @should handle 19780411061538
 * @should handle 19780411061538.1
 * @should handle 19780411061538.12
 * @should handle 19780411061538.123
 * @should handle 19780411061538.1234
 * @should fail on 197804110615-5
 * @should handle 197804110615-05
 * @should handle 197804110615-0200
 * @should not flub dst with 20091225123000
 */
public static Date parseHL7Timestamp(String s) throws HL7Exception {
    // HL7 dates must at least contain year and cannot exceed 24 bytes
    if (s == null || s.length() < 4 || s.length() > 24) {
        throw new HL7Exception("Invalid date '" + s + "'");
    }
    StringBuilder dateString = new StringBuilder();
    // year
    dateString.append(s.substring(0, 4));
    if (s.length() >= 6) {
        // month
        dateString.append(s.substring(4, 6));
    } else {
        dateString.append("01");
    }
    if (s.length() >= 8) {
        // day
        dateString.append(s.substring(6, 8));
    } else {
        dateString.append("01");
    }
    // Parse timezone (optional in HL7 format)
    String timeZoneOffset;
    try {
        Date parsedDay = new SimpleDateFormat("yyyyMMdd").parse(s.substring(0, 8));
        timeZoneOffset = getTimeZoneOffset(s, parsedDay);
    } catch (ParseException e) {
        throw new HL7Exception("Error parsing date: '" + s.substring(0, 8) + "' for time zone offset'" + s + "'", e);
    }
    // remove the timezone from the string
    s = s.replace(timeZoneOffset, "");
    if (s.length() >= 10) {
        // hour
        dateString.append(s.substring(8, 10));
    } else {
        dateString.append("00");
    }
    if (s.length() >= 12) {
        // minute
        dateString.append(s.substring(10, 12));
    } else {
        dateString.append("00");
    }
    if (s.length() >= 14) {
        // seconds
        dateString.append(s.substring(12, 14));
    } else {
        dateString.append("00");
    }
    if (s.length() >= 15 && s.charAt(14) != '.') {
        // decimal point
        throw new HL7Exception("Invalid date format '" + s + "'");
    } else {
        dateString.append(".");
    }
    if (s.length() >= 16) {
        // tenths
        dateString.append(s.substring(15, 16));
    } else {
        dateString.append("0");
    }
    if (s.length() >= 17) {
        // hundredths
        dateString.append(s.substring(16, 17));
    } else {
        dateString.append("0");
    }
    if (s.length() >= 18) {
        // milliseconds
        dateString.append(s.subSequence(17, 18));
    } else {
        dateString.append("0");
    }
    dateString.append(timeZoneOffset);
    Date date;
    try {
        date = new SimpleDateFormat(TIMESTAMP_FORMAT).parse(dateString.toString());
    } catch (ParseException e) {
        throw new HL7Exception("Error parsing date '" + s + "'");
    }
    return date;
}
Also used : HL7Exception(ca.uhn.hl7v2.HL7Exception) ParseException(java.text.ParseException) SimpleDateFormat(java.text.SimpleDateFormat) Date(java.util.Date)

Example 25 with HL7Exception

use of ca.uhn.hl7v2.HL7Exception in project openmrs-core by openmrs.

the class HL7Util method parseHL7Time.

/**
 * Converts an HL7 time into a java.util.Date object. Since the java.util.Date object cannot
 * store just the time, the date will remain at the epoch (e.g., January 1, 1970). Time more
 * precise than microseconds is ignored.
 *
 * @param s HL7 time to be converted
 * @return Date object set to time specified by HL7
 * @throws HL7Exception
 * @should fail on 197804110615
 * @should handle 0615
 * @should handle 061538
 * @should handle 061538.1
 * @should handle 061538.12
 * @should handle 061538.123
 * @should handle 061538.1234
 * @should handle 061538-0300
 */
public static Date parseHL7Time(String s) throws HL7Exception {
    String timeZoneOffset = getTimeZoneOffset(s, new Date());
    // remove the timezone from the string
    s = s.replace(timeZoneOffset, "");
    StringBuilder timeString = new StringBuilder();
    if (s.length() < 2 || s.length() > 16) {
        throw new HL7Exception("Invalid time format '" + s + "'");
    }
    // hour
    timeString.append(s.substring(0, 2));
    if (s.length() >= 4) {
        // minute
        timeString.append(s.substring(2, 4));
    } else {
        timeString.append("00");
    }
    if (s.length() >= 6) {
        // seconds
        timeString.append(s.substring(4, 6));
    } else {
        timeString.append("00");
    }
    if (s.length() >= 7 && s.charAt(6) != '.') {
        // decimal point
        throw new HL7Exception("Invalid time format '" + s + "'");
    } else {
        timeString.append(".");
    }
    if (s.length() >= 8) {
        // tenths
        timeString.append(s.substring(7, 8));
    } else {
        timeString.append("0");
    }
    if (s.length() >= 9) {
        // hundredths
        timeString.append(s.substring(8, 9));
    } else {
        timeString.append("0");
    }
    if (s.length() >= 10) {
        // milliseconds
        timeString.append(s.subSequence(9, 10));
    } else {
        timeString.append("0");
    }
    // Parse timezone (optional in HL7 format)
    timeString.append(timeZoneOffset);
    Date date;
    try {
        date = new SimpleDateFormat(TIME_FORMAT).parse(timeString.toString());
    } catch (ParseException e) {
        throw new HL7Exception("Invalid time format: '" + s + "' [" + timeString + "]", e);
    }
    return date;
}
Also used : HL7Exception(ca.uhn.hl7v2.HL7Exception) ParseException(java.text.ParseException) SimpleDateFormat(java.text.SimpleDateFormat) Date(java.util.Date)

Aggregations

Message (ca.uhn.hl7v2.model.Message)36 HL7Exception (ca.uhn.hl7v2.HL7Exception)34 Test (org.junit.Test)24 BaseContextSensitiveTest (org.openmrs.test.BaseContextSensitiveTest)24 ORU_R01 (ca.uhn.hl7v2.model.v25.message.ORU_R01)22 NK1 (ca.uhn.hl7v2.model.v25.segment.NK1)16 ORUR01Handler (org.openmrs.hl7.handler.ORUR01Handler)15 Person (org.openmrs.Person)11 ApplicationException (ca.uhn.hl7v2.app.ApplicationException)10 CX (ca.uhn.hl7v2.model.v25.datatype.CX)10 IOException (java.io.IOException)9 ArrayList (java.util.ArrayList)9 Patient (org.openmrs.Patient)7 APIException (org.openmrs.api.APIException)7 PatientIdentifierException (org.openmrs.api.PatientIdentifierException)7 Segment (ca.uhn.hl7v2.model.Segment)6 Structure (ca.uhn.hl7v2.model.Structure)6 Type (ca.uhn.hl7v2.model.Type)6 PID (ca.uhn.hl7v2.model.v25.segment.PID)6 EncodingNotSupportedException (ca.uhn.hl7v2.parser.EncodingNotSupportedException)6