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;
}
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;
}
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;
}
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 — 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;
}
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;
}
Aggregations