Skip to content

Commit

Permalink
krasserm#53: MLLP dispatching consumer
Browse files Browse the repository at this point in the history
  • Loading branch information
unixoid committed Oct 26, 2014
1 parent 625e5ae commit a62a64b
Show file tree
Hide file tree
Showing 44 changed files with 1,268 additions and 596 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,26 @@
*/
package org.openehealth.ipf.platform.camel.ihe.hl7v2;

import ca.uhn.hl7v2.HL7Exception;
import ca.uhn.hl7v2.model.Message;
import ca.uhn.hl7v2.model.Segment;
import ca.uhn.hl7v2.parser.Parser;
import ca.uhn.hl7v2.util.Terser;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.openehealth.ipf.modules.hl7dsl.MessageAdapter;

import java.util.List;

import static org.apache.commons.lang3.ArrayUtils.INDEX_NOT_FOUND;
import static org.apache.commons.lang3.ArrayUtils.contains;
import static org.apache.commons.lang3.ArrayUtils.indexOf;
import static org.apache.commons.lang3.ArrayUtils.*;
import static org.apache.commons.lang3.Validate.*;

/**
* Endpoint-agnostic parameters of an HL7v2-based transaction.
* @author Dmytro Rud
*/
public class Hl7v2TransactionConfiguration {

private final String hl7Version;
private final String sendingApplication;
private final String sendingFacility;
Expand Down Expand Up @@ -143,19 +147,19 @@ public Hl7v2TransactionConfiguration(


/**
* Returns <code>true</code> when request messages
* of the given type belong to this transaction.
* Returns <code>true</code> when request messages
* of the given type belong to this transaction.
*/
public boolean isSupportedRequestMessageType(String messageType) {
private boolean isSupportedRequestMessageType(String messageType) {
return contains(allowedRequestMessageTypes, messageType);
}


/**
* Returns <code>true</code> when the given trigger event
* is valid for request messages of the given type.
*/
public boolean isSupportedRequestTriggerEvent(String messageType, String triggerEvent) {
private boolean isSupportedRequestTriggerEvent(String messageType, String triggerEvent) {
int index = indexOf(allowedRequestMessageTypes, messageType);
if (index == INDEX_NOT_FOUND) {
throw new IllegalArgumentException("Unknown message type " + messageType);
Expand All @@ -170,7 +174,7 @@ public boolean isSupportedRequestTriggerEvent(String messageType, String trigger
* of the given type belong to this transaction.
* "ACK" is always supported.
*/
public boolean isSupportedResponseMessageType(String messageType) {
private boolean isSupportedResponseMessageType(String messageType) {
return "ACK".equals(messageType) || contains(allowedResponseMessageTypes, messageType);
}

Expand All @@ -180,7 +184,7 @@ public boolean isSupportedResponseMessageType(String messageType) {
* is valid for response messages of the given type.
* For "ACK" message type, every trigger event is considered valid.
*/
public boolean isSupportedResponseTriggerEvent(String messageType, String triggerEvent) {
private boolean isSupportedResponseTriggerEvent(String messageType, String triggerEvent) {
if("ACK".equals(messageType)) {
return true;
}
Expand Down Expand Up @@ -245,8 +249,139 @@ public boolean isDataStartSegment(List<String> segments, int index) {
public boolean isFooterStartSegment(List<String> segments, int index) {
return false;
}




/**
* Performs transaction-specific acceptance test of the given request message.
* @param messageAdapter
* IPF {@link MessageAdapter} object.
*/
public void checkRequestAcceptance(MessageAdapter messageAdapter) throws Hl7v2AcceptanceException {
Message message = messageAdapter.getHapiMessage();
checkMessageAcceptance(message, true);
}


/**
* Performs transaction-specific acceptance test of the given response message.
* @param messageAdapter
* IPF {@link MessageAdapter} object.
*/
public void checkResponseAcceptance(MessageAdapter messageAdapter) throws Hl7v2AcceptanceException {
Message message = messageAdapter.getHapiMessage();
checkMessageAcceptance(message, false);

try {
if (! ArrayUtils.contains(
new String[] {"AA", "AR", "AE", "CA", "CR", "CE"},
new Terser(message).get("MSA-1")))
{
throw new Hl7v2AcceptanceException("Bad response: missing or invalid MSA segment", 101);
}
} catch (HL7Exception e) {
throw new Hl7v2AcceptanceException("Bad response: missing or invalid MSA segment", 207);
}
}


/**
* Performs acceptance test of the given message.
* @param message
* HAPI {@link Message} object.
* @param isRequest
* <code>true</code> iff the message is a request.
* @throws Hl7v2AcceptanceException
* when the message is not acceptable.
*/
public void checkMessageAcceptance(
Message message,
boolean isRequest) throws Hl7v2AcceptanceException
{
try {
Segment msh = (Segment) message.get("MSH");
checkMessageAcceptance(
Terser.get(msh, 9, 0, 1, 1),
Terser.get(msh, 9, 0, 2, 1),
Terser.get(msh, 9, 0, 3, 1),
Terser.get(msh, 12, 0, 1, 1),
isRequest);
} catch (HL7Exception e) {
throw new Hl7v2AcceptanceException("Missing or invalid MSH segment", 207);
}
}


/**
* Performs acceptance test of the message with the given attributes.
* @param messageType
* value from MSH-9-1, can be empty or <code>null</code>.
* @param triggerEvent
* value from MSH-9-PAI2, can be empty or <code>null</code>.
* @param messageStructure
* value from MSH-9-3, can be empty or <code>null</code>.
* @param version
* value from MSH-12, can be empty or <code>null</code>.
* @param isRequest
* <code>true</code> iff the message under consideration is a request.
* @throws Hl7v2AcceptanceException
* when the message is not acceptable.
*/
public void checkMessageAcceptance(
String messageType,
String triggerEvent,
String messageStructure,
String version,
boolean isRequest) throws Hl7v2AcceptanceException
{
if (! hl7Version.equals(version)) {
throw new Hl7v2AcceptanceException("Invalid HL7 version " + version, 203);
}

boolean messageTypeSupported = isRequest
? isSupportedRequestMessageType(messageType)
: isSupportedResponseMessageType(messageType);

if (! messageTypeSupported) {
throw new Hl7v2AcceptanceException("Invalid message type " + messageType, 200);
}

boolean triggerEventSupported = isRequest
? isSupportedRequestTriggerEvent(messageType, triggerEvent)
: isSupportedResponseTriggerEvent(messageType, triggerEvent);

if(! triggerEventSupported) {
throw new Hl7v2AcceptanceException("Invalid trigger event " + triggerEvent, 201);
}

if (! StringUtils.isEmpty(messageStructure)) {
// This may not work as the custom event map cannot be distinguished from the
// default one! This needs to be fixed for HAPI 2.1
String event = messageType + "_" + triggerEvent;
String expectedMessageStructure;
try {
expectedMessageStructure = Parser.getMessageStructureForEvent(event, version);
} catch (HL7Exception e) {
throw new Hl7v2AcceptanceException("Acceptance check failed", 204);
}

// TODO when upgrading to HAPI 2.1 remove the constant IF statements
if ("QBP_ZV1".equals(event)) {
expectedMessageStructure = "QBP_Q21";
} else if ("RSP_ZV2".equals(event)) {
expectedMessageStructure = "RSP_ZV2";
}

// the expected structure must be equal to the actual one,
// but second components may be omitted in acknowledgements
boolean bothAreEqual = messageStructure.equals(expectedMessageStructure);
boolean bothAreAcks = (messageStructure.startsWith("ACK") && expectedMessageStructure.startsWith("ACK"));
if (! (bothAreEqual || bothAreAcks)) {
throw new Hl7v2AcceptanceException("Invalid message structure " + messageStructure, 207);
}
}
}


// ----- automatically generated getters -----

public String getHl7Version() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,11 @@
import org.apache.camel.Exchange;
import org.openehealth.ipf.modules.hl7dsl.MessageAdapter;
import org.openehealth.ipf.platform.camel.core.util.Exchanges;
import org.openehealth.ipf.platform.camel.ihe.hl7v2.AcceptanceCheckUtils;
import org.openehealth.ipf.platform.camel.ihe.hl7v2.Hl7v2TransactionConfiguration;


/**
* Generic functionality for HL7v2 acceptance checking
* interceptors, a kind of Visitor.
* Generic functionality for HL7v2 acceptance checking interceptors.
* @author Dmytro Rud
*/
public class AcceptanceInterceptorUtils {
Expand All @@ -41,9 +40,8 @@ public static void processRequest(
Exchange exchange) throws Exception
{
// check input message
AcceptanceCheckUtils.checkRequestAcceptance(
exchange.getIn().getBody(MessageAdapter.class),
interceptor.getHl7v2TransactionConfiguration());
Hl7v2TransactionConfiguration config = interceptor.getHl7v2TransactionConfiguration();
config.checkRequestAcceptance(exchange.getIn().getBody(MessageAdapter.class));

// run the route
interceptor.getWrappedProcessor().process(exchange);
Expand All @@ -61,8 +59,7 @@ public static void processResponse(
interceptor.getWrappedProcessor().process(exchange);

// check output message
AcceptanceCheckUtils.checkResponseAcceptance(
Exchanges.resultMessage(exchange).getBody(MessageAdapter.class),
interceptor.getHl7v2TransactionConfiguration());
Hl7v2TransactionConfiguration config = interceptor.getHl7v2TransactionConfiguration();
config.checkResponseAcceptance(Exchanges.resultMessage(exchange).getBody(MessageAdapter.class));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@

import static org.openehealth.ipf.commons.ihe.hl7v2ws.Utils.render;
import static org.openehealth.ipf.platform.camel.core.util.Exchanges.resultMessage;
import static org.openehealth.ipf.platform.camel.ihe.hl7v2.AcceptanceCheckUtils.checkRequestAcceptance;
import static org.openehealth.ipf.platform.camel.ihe.hl7v2.AcceptanceCheckUtils.checkResponseAcceptance;
import static org.apache.commons.lang3.StringUtils.trimToEmpty;

import org.apache.camel.Exchange;
Expand Down Expand Up @@ -71,7 +69,7 @@ protected String doProcess(String request) {
MessageAdapter<?> msg;
try {
msg = MessageAdapters.make(config.getParser(), trimToEmpty(request).replaceAll("\n", "\r\n"));
checkRequestAcceptance(msg, config);
config.checkRequestAcceptance(msg);
} catch (Exception e) {
LOG.error(formatErrMsg("Request not acceptable"), e);
return render(nakFactory.createDefaultNak(e));
Expand All @@ -92,7 +90,7 @@ protected String doProcess(String request) {
resultMessage(exchange),
exchange.getProperty(Exchange.CHARSET_NAME, String.class),
config.getParser());
checkResponseAcceptance(msg, config);
config.checkResponseAcceptance(msg);
return render(msg.getHapiMessage());

} catch (Exception e) {
Expand Down
Loading

0 comments on commit a62a64b

Please sign in to comment.