Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TRUNK-5764:Upgrade the ca.uhn.hapi libraries #3227

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions api/id_file
@@ -0,0 +1 @@
200
47 changes: 30 additions & 17 deletions api/src/main/java/org/openmrs/hl7/handler/ADTA28Handler.java
Expand Up @@ -12,8 +12,21 @@
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import ca.uhn.hl7v2.HL7Exception;
import ca.uhn.hl7v2.model.Message;
import ca.uhn.hl7v2.model.v25.datatype.CX;
import ca.uhn.hl7v2.model.v25.datatype.ID;
import ca.uhn.hl7v2.model.v25.datatype.TS;
import ca.uhn.hl7v2.model.v25.datatype.XPN;
import ca.uhn.hl7v2.model.v25.message.ADT_A05;
import ca.uhn.hl7v2.model.v25.segment.MSH;
import ca.uhn.hl7v2.model.v25.segment.PID;
import ca.uhn.hl7v2.protocol.ReceivingApplication;
import ca.uhn.hl7v2.protocol.ReceivingApplicationException;
import org.openmrs.Location;
import org.openmrs.Patient;
import org.openmrs.PatientIdentifier;
Expand All @@ -27,18 +40,6 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ca.uhn.hl7v2.HL7Exception;
import ca.uhn.hl7v2.app.Application;
import ca.uhn.hl7v2.app.ApplicationException;
import ca.uhn.hl7v2.model.Message;
import ca.uhn.hl7v2.model.v25.datatype.CX;
import ca.uhn.hl7v2.model.v25.datatype.ID;
import ca.uhn.hl7v2.model.v25.datatype.TS;
import ca.uhn.hl7v2.model.v25.datatype.XPN;
import ca.uhn.hl7v2.model.v25.message.ADT_A05;
import ca.uhn.hl7v2.model.v25.segment.MSH;
import ca.uhn.hl7v2.model.v25.segment.PID;

/* HL7 using HAPI to handle ADT A28 Messages
*
* ADT/ACK - Add person or patient information (Event A28)
Expand Down Expand Up @@ -92,7 +93,7 @@
*
* NOTE: The ones with (*) could be useful in the near future.
*/
public class ADTA28Handler implements Application {
public class ADTA28Handler implements ReceivingApplication<Message> {

private static final Logger log = LoggerFactory.getLogger(ADTA28Handler.class);

Expand All @@ -111,12 +112,12 @@ public boolean canProcess(Message message) {
* Processes an ADT A28 event message
*/
@Override
public Message processMessage(Message message) throws ApplicationException {
public Message processMessage(Message message, Map<String, Object> metadata) throws ReceivingApplicationException {

log.debug("Processing ADT_A28 message");

if (!(message instanceof ADT_A05)) {
throw new ApplicationException("Invalid message sent to ADT_A28 handler");
throw new ReceivingApplicationException("Invalid message sent to ADT_A28 handler");
}

Message response;
Expand All @@ -126,11 +127,11 @@ public Message processMessage(Message message) throws ApplicationException {
}
catch (ClassCastException e) {
log.error("Error casting " + message.getClass().getName() + " to ADT_A28", e);
throw new ApplicationException("Invalid message type for handler");
throw new ReceivingApplicationException("Invalid message type for handler");
}
catch (HL7Exception e) {
log.error("Error while processing ADT_A28 message", e);
throw new ApplicationException(e);
throw new ReceivingApplicationException(e);
}

log.debug("Finished processing ADT_A28 message");
Expand Down Expand Up @@ -337,4 +338,16 @@ private Date tsToDate(TS ts) throws HL7Exception {

return cal.getTime();
}

/**
* Processes an ORU R01 event message
*
* This function is indented for backwards-compatibility and should not be used for new development
*
* @deprecated See {@link #processMessage(Message, Map)}
*/
@Deprecated
public Message processMessage(Message message) throws ReceivingApplicationException {
return processMessage(message, new HashMap<>());
}
}
85 changes: 49 additions & 36 deletions api/src/main/java/org/openmrs/hl7/handler/ORUR01Handler.java
Expand Up @@ -13,43 +13,14 @@
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;

import org.openmrs.Concept;
import org.openmrs.ConceptAnswer;
import org.openmrs.ConceptName;
import org.openmrs.ConceptProposal;
import org.openmrs.Drug;
import org.openmrs.Encounter;
import org.openmrs.EncounterRole;
import org.openmrs.EncounterType;
import org.openmrs.Form;
import org.openmrs.Location;
import org.openmrs.Obs;
import org.openmrs.Patient;
import org.openmrs.Person;
import org.openmrs.PersonAttribute;
import org.openmrs.PersonAttributeType;
import org.openmrs.Provider;
import org.openmrs.Relationship;
import org.openmrs.RelationshipType;
import org.openmrs.User;
import org.openmrs.api.context.Context;
import org.openmrs.hl7.HL7Constants;
import org.openmrs.hl7.HL7InQueueProcessor;
import org.openmrs.obs.ComplexData;
import org.openmrs.util.OpenmrsConstants;
import org.openmrs.util.OpenmrsUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import ca.uhn.hl7v2.HL7Exception;
import ca.uhn.hl7v2.app.Application;
import ca.uhn.hl7v2.app.ApplicationException;
import ca.uhn.hl7v2.model.DataTypeException;
import ca.uhn.hl7v2.model.Message;
import ca.uhn.hl7v2.model.Type;
Expand Down Expand Up @@ -84,6 +55,36 @@
import ca.uhn.hl7v2.model.v25.segment.PV1;
import ca.uhn.hl7v2.parser.EncodingCharacters;
import ca.uhn.hl7v2.parser.PipeParser;
import ca.uhn.hl7v2.protocol.ReceivingApplication;
import ca.uhn.hl7v2.protocol.ReceivingApplicationException;
import org.openmrs.Concept;
import org.openmrs.ConceptAnswer;
import org.openmrs.ConceptName;
import org.openmrs.ConceptProposal;
import org.openmrs.Drug;
import org.openmrs.Encounter;
import org.openmrs.EncounterRole;
import org.openmrs.EncounterType;
import org.openmrs.Form;
import org.openmrs.Location;
import org.openmrs.Obs;
import org.openmrs.Patient;
import org.openmrs.Person;
import org.openmrs.PersonAttribute;
import org.openmrs.PersonAttributeType;
import org.openmrs.Provider;
import org.openmrs.Relationship;
import org.openmrs.RelationshipType;
import org.openmrs.User;
import org.openmrs.api.context.Context;
import org.openmrs.hl7.HL7Constants;
import org.openmrs.hl7.HL7InQueueProcessor;
import org.openmrs.obs.ComplexData;
import org.openmrs.util.OpenmrsConstants;
import org.openmrs.util.OpenmrsUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

/**
* Parses ORUR01 messages into openmrs Encounter objects Usage: GenericParser parser = new
Expand All @@ -93,7 +94,7 @@
*
* @see HL7InQueueProcessor
*/
public class ORUR01Handler implements Application {
public class ORUR01Handler implements ReceivingApplication<Message> {

private static final Logger log = LoggerFactory.getLogger(ORUR01Handler.class);

Expand Down Expand Up @@ -141,10 +142,10 @@ public boolean canProcess(Message message) {
* <strong>Should</strong> set complex data for obs with complex concepts
*/
@Override
public Message processMessage(Message message) throws ApplicationException {
public Message processMessage(Message message, Map<String, Object> metadata) throws ReceivingApplicationException{

if (!(message instanceof ORU_R01)) {
throw new ApplicationException(Context.getMessageSourceService().getMessage("ORUR01.error.invalidMessage"));
throw new ReceivingApplicationException(Context.getMessageSourceService().getMessage("ORUR01.error.invalidMessage"));
}

log.debug("Processing ORU_R01 message");
Expand All @@ -156,12 +157,12 @@ public Message processMessage(Message message) throws ApplicationException {
}
catch (ClassCastException e) {
log.warn("Error casting " + message.getClass().getName() + " to ORU_R01", e);
throw new ApplicationException(Context.getMessageSourceService().getMessage("ORUR01.error.invalidMessageType ",
throw new ReceivingApplicationException(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);
throw new ReceivingApplicationException(Context.getMessageSourceService().getMessage("ORUR01.error.WhileProcessing"), e);
}

log.debug("Finished processing ORU_R01 message");
Expand Down Expand Up @@ -1280,4 +1281,16 @@ private void updateHealthCenter(Patient patient, PV1 pv1) {
}
log.debug("finished discharge to location method");
}

/**
* Processes an ORU R01 event message
*
* This function is indented for backwards-compatibility and should not be used for new development
*
* @deprecated See {@link #processMessage(Message, Map)}
*/
@Deprecated
public Message processMessage(Message message) throws ReceivingApplicationException {
return processMessage(message, new HashMap<>());
}
}
68 changes: 43 additions & 25 deletions api/src/main/java/org/openmrs/hl7/impl/HL7ServiceImpl.java
Expand Up @@ -27,6 +27,25 @@
import java.util.List;
import java.util.Map;

import ca.uhn.hl7v2.HL7Exception;
import ca.uhn.hl7v2.model.Message;
import ca.uhn.hl7v2.model.v25.datatype.CX;
import ca.uhn.hl7v2.model.v25.datatype.ID;
import ca.uhn.hl7v2.model.v25.datatype.PL;
import ca.uhn.hl7v2.model.v25.datatype.TS;
import ca.uhn.hl7v2.model.v25.datatype.XCN;
import ca.uhn.hl7v2.model.v25.datatype.XPN;
import ca.uhn.hl7v2.model.v25.segment.NK1;
import ca.uhn.hl7v2.model.v25.segment.PID;
import ca.uhn.hl7v2.parser.EncodingNotSupportedException;
import ca.uhn.hl7v2.parser.GenericParser;
import ca.uhn.hl7v2.protocol.ApplicationRouter;
import ca.uhn.hl7v2.protocol.ReceivingApplication;
import ca.uhn.hl7v2.protocol.Transportable;
import ca.uhn.hl7v2.protocol.impl.AppRoutingDataImpl;
import ca.uhn.hl7v2.protocol.impl.ApplicationRouterImpl;
import ca.uhn.hl7v2.protocol.impl.TransportableImpl;
import ca.uhn.hl7v2.util.Terser;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.openmrs.Location;
Expand Down Expand Up @@ -60,22 +79,6 @@
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional;

import ca.uhn.hl7v2.HL7Exception;
import ca.uhn.hl7v2.app.Application;
import ca.uhn.hl7v2.app.ApplicationException;
import ca.uhn.hl7v2.app.MessageTypeRouter;
import ca.uhn.hl7v2.model.Message;
import ca.uhn.hl7v2.model.v25.datatype.CX;
import ca.uhn.hl7v2.model.v25.datatype.ID;
import ca.uhn.hl7v2.model.v25.datatype.PL;
import ca.uhn.hl7v2.model.v25.datatype.TS;
import ca.uhn.hl7v2.model.v25.datatype.XCN;
import ca.uhn.hl7v2.model.v25.datatype.XPN;
import ca.uhn.hl7v2.model.v25.segment.NK1;
import ca.uhn.hl7v2.model.v25.segment.PID;
import ca.uhn.hl7v2.parser.EncodingNotSupportedException;
import ca.uhn.hl7v2.parser.GenericParser;

/**
* OpenMRS HL7 API default methods This class shouldn't be instantiated by itself. Use the
* {@link org.openmrs.api.context.Context}
Expand All @@ -93,7 +96,7 @@ public class HL7ServiceImpl extends BaseOpenmrsService implements HL7Service {

private GenericParser parser;

private MessageTypeRouter router;
private ApplicationRouter router;

/**
* Private constructor to only support on singleton instance.
Expand Down Expand Up @@ -137,7 +140,7 @@ public void setParser(GenericParser parser) {
*
* @param router the router to use
*/
public void setRouter(MessageTypeRouter router) {
public void setRouter(ApplicationRouter router) {
this.router = router;
}

Expand Down Expand Up @@ -831,18 +834,31 @@ public Message processHL7Message(Message message) throws HL7Exception {

Message response;
try {
if (!router.canProcess(message)) {
Copy link
Member

@ibacher ibacher Aug 4, 2020

Choose a reason for hiding this comment

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

See my comments below first, but some comments on here:

We should maintain something like the router.canProcess(message) here. The original check was fairly simple and we can get close to it with something like this:

private boolean canProcess(Message message) {
	Terser t = new Terser(message);
	ApplicationRouter.AppRoutingData routingData = new AppRoutingDataImpl(t.get("/MSH-9-1"), t.get("/MSH-9-2"), "*", "*");

    return router.hasActiveBinding(routingData);
}

Unfortunately, also, a Message object doesn't necessarily implement the Transportable interface, so we cannot directly cast either the message to a Transportable nor the result to a Message. Fortunately, translating a Message into a Transportable shouldn't be hard:

Transportable transportable = new TransportableImpl(message.encode());

And, likewise, to convert the Transportable result back to a corresponding message:

Message responseMessage = message.getParser().parse(response.getMessage());

Alternatively, we could use:

router.getParser().parse(response.getMessage());

if (!canProcess(message)) {
throw new HL7Exception("No route for hl7 message: " + message.getName()
+ ". Make sure you have a module installed that registers a hl7handler for this type");
}
response = router.processMessage(message);
Transportable transportable = new TransportableImpl(message.encode());
response = message.getParser().parse(router.processMessage(transportable).getMessage());
}
catch (ApplicationException e) {
catch (HL7Exception e) {
throw new HL7Exception("Error while processing HL7 message: " + message.getName(), e);
}

return response;
}

private boolean canProcess(Message message) {
Terser t = new Terser(message);
ApplicationRouter.AppRoutingData routingData = null;
try {
routingData = new AppRoutingDataImpl(t.get("/MSH-9-1"), t.get("/MSH-9-2"), "*", "*");
} catch (HL7Exception e) {
e.printStackTrace();
}

return router.hasActiveBinding(routingData);
}

/**
* Sets the given handlers as router applications that are available to HAPI when it is parsing
Expand All @@ -854,18 +870,20 @@ public Message processHL7Message(Message message) throws HL7Exception {
*
* @param handlers a map from MessageName to Application object
*/
public void setHL7Handlers(Map<String, Application> handlers) {
public void setHL7Handlers(Map<String, ReceivingApplication> handlers) {
// loop over all the given handlers and add them to the router
for (Map.Entry<String, Application> entry : handlers.entrySet()) {
for (Map.Entry<String, ReceivingApplication> entry : handlers.entrySet()) {
String messageName = entry.getKey();
if (!messageName.contains("_")) {
throw new APIException("Hl7Service.invalid.messageName", (Object[]) null);
}

String messageType = messageName.split("_")[0];
String triggerEvent = messageName.split("_")[1];

router.registerApplication(messageType, triggerEvent, entry.getValue());
router = new ApplicationRouterImpl();
// * means all processingIds and versionIds which seems equivalent to what we had before
ApplicationRouter.AppRoutingData routingData = new AppRoutingDataImpl(messageType, triggerEvent, "*", "*");
router.bindApplication(routingData, entry.getValue());
}
}

Expand Down
2 changes: 1 addition & 1 deletion api/src/main/resources/applicationContext-service.xml
Expand Up @@ -322,7 +322,7 @@
<bean class="ca.uhn.hl7v2.parser.GenericParser"/>
</property>
<property name="router">
<bean class="ca.uhn.hl7v2.app.MessageTypeRouter"/>
<bean class="ca.uhn.hl7v2.protocol.impl.ApplicationRouterImpl"/>
</property>
<property name="HL7Handlers">
<map>
Expand Down