package org.wso2.carbon.business.messaging.hl7.store.admin;
import ca.uhn.hl7v2.HL7Exception;
import ca.uhn.hl7v2.model.Message;
import ca.uhn.hl7v2.parser.DefaultXMLParser;
import ca.uhn.hl7v2.parser.EncodingNotSupportedException;
import ca.uhn.hl7v2.parser.PipeParser;
import ca.uhn.hl7v2.util.Terser;
import ca.uhn.hl7v2.validation.impl.NoValidation;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axiom.soap.impl.llom.soap11.SOAP11Factory;
import org.apache.axis2.AxisFault;
import org.apache.axis2.Constants;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.description.AxisService;
import org.apache.axis2.description.TransportOutDescription;
import org.apache.axis2.engine.AxisEngine;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.synapse.MessageContext;
import org.apache.synapse.config.SynapseConfiguration;
import org.apache.synapse.core.SynapseEnvironment;
import org.apache.synapse.core.axis2.Axis2MessageContext;
import org.apache.synapse.core.axis2.Axis2SynapseEnvironment;
import org.apache.synapse.core.axis2.ProxyService;
import org.apache.synapse.message.store.MessageStore;
import org.apache.synapse.util.PayloadHelper;
import org.wso2.carbon.business.messaging.hl7.common.HL7Constants;
import org.wso2.carbon.business.messaging.hl7.common.HL7Utils;
import org.wso2.carbon.business.messaging.hl7.store.JDBCStore;
import org.wso2.carbon.business.messaging.hl7.store.entity.PersistentHL7Message;
import org.wso2.carbon.business.messaging.hl7.store.entity.TransferableHL7Message;
import org.wso2.carbon.business.messaging.hl7.store.jpa.JPAStore;
import org.wso2.carbon.business.messaging.hl7.store.util.SerializableMessageContext;
import org.wso2.carbon.business.messaging.hl7.store.util.SerializerUtils;
import org.wso2.carbon.business.messaging.hl7.transport.HL7TransportOutInfo;
import org.wso2.carbon.mediation.initializer.AbstractServiceBusAdmin;
import javax.xml.stream.XMLStreamException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class HL7StoreAdminService extends AbstractServiceBusAdmin {
private static Log log = LogFactory.getLog(HL7StoreAdminService.class);
public static int MSGS_PER_PAGE = 100;
/**
* Get all the Current Message store names defined in the configuration
*
* @return array of Strings that contains MessageStore names
* @throws AxisFault
*/
public String[] getHL7StoreNames() throws AxisFault {
SynapseConfiguration configuration = getSynapseConfiguration();
assert configuration != null;
Collection<String> hl7Stores = new ArrayList<String>();
Collection<String> allStores = configuration.getMessageStores().keySet();
for(String name: allStores) {
if(getClassName(name).equals(JPAStore.class.getName()) ||
getClassName(name).equals(JDBCStore.class.getName())) {
hl7Stores.add(name);
}
}
return hl7Stores.toArray(new String[hl7Stores.size()]);
}
/**
* Get the number of messages in the Message store with given name
*
* @param name of the MessageStore
* @return number of message stores in the given store
* @throws AxisFault if Message store does not exists
*/
public int getSize(String name) throws AxisFault {
MessageStore store = getMessageStoreImpl(name);
if (store != null) {
return store.size();
} else {
handleException(log, "Message Store " + name + " does not exist !!!", null);
}
//This code block will never reach as handleException method will always returns a Exception
return 0;
}
/**
* Get the implementation class name of the MessageStore
*
* @param name of the MessageStore
* @return implementation class name of the Message Store
* @throws AxisFault
*/
public String getClassName(String name) throws AxisFault {
MessageStore store = getMessageStoreImpl(name);
if (store != null) {
return store.getClass().getName();
} else {
handleException(log, "Message Store " + name + " does not exist !!!", null);
}
//This code block will never reach as handleException method will always returns a Exception
return null;
}
public List<TransferableHL7Message> getMessages(String storeName) throws AxisFault {
JPAStore store = (JPAStore) getMessageStoreImpl(storeName);
if(store != null) {
return getTransferableMessages(store, store.getMessages());
} else {
handleException(log, "Message Store " + storeName + " does not exist !!!", null);
}
return null;
}
public String[] getHL7Proxies(String storeName) {
JPAStore store = (JPAStore) getMessageStoreImpl(storeName);
Collection<ProxyService> services = store.getSynapseEnvironment().getSynapseConfiguration().getProxyServices();
ArrayList<String> serviceNames = new ArrayList<String>();
for(ProxyService service: services) {
serviceNames.add(service.getName());
}
return serviceNames.toArray(new String[serviceNames.size()]);
}
private void handleError(String msg) {
log.error(msg);
}
public List<TransferableHL7Message> search(String storeName, String query) throws AxisFault {
JPAStore store = (JPAStore) getMessageStoreImpl(storeName);
if(store != null) {
return getTransferableMessages(store, store.search(query));
} else {
handleException(log, "Message Store " + storeName + " does not exist !!!", null);
}
return null;
}
public int getSearchSize(String storeName, String query) throws AxisFault {
JPAStore store = (JPAStore) getMessageStoreImpl(storeName);
if(store != null) {
List<PersistentHL7Message> results = store.search(query);
return getTransferableMessages(store, results).size();
} else {
handleException(log, "Message Store " + storeName + " does not exist !!!", null);
}
return 0;
}
private boolean isTrueProxyParameter(String storeName, String proxyName, String parameterName) {
JPAStore store = (JPAStore) getMessageStoreImpl(storeName);
SynapseEnvironment synapseEnvironment = store.getSynapseEnvironment();
ProxyService service = synapseEnvironment.getSynapseConfiguration().getProxyService(proxyName);
if(service.getParameterMap().containsKey(parameterName)) {
return Boolean.valueOf((String) service.getParameterMap().get(parameterName));
} else {
return false;
}
}
public boolean sendMessage(String msg, String storeName, String proxyName) {
OMElement message = null;
Message hl7Message = null;
String hl7MessageStr = null;
String xmlMessage = null;
String messageControlerID = null;
boolean validationPassed = true;
msg = msg.replaceAll("\n", "\r\n");
try {
PipeParser parser = new PipeParser();
if (!isTrueProxyParameter(storeName, proxyName, HL7Constants.HL7_VALIDATE_MESSAGE)) {
parser.setValidationContext(new NoValidation());
}
hl7Message = new PipeParser().parse(msg);
hl7MessageStr = hl7Message.encode();
xmlMessage = new DefaultXMLParser().encode(hl7Message);
message = HL7Utils.generateHL7MessageElement(xmlMessage);
} catch (HL7Exception e) {
if(isTrueProxyParameter(storeName, proxyName, HL7Constants.HL7_BUILD_RAW_MESSAGE)) {
validationPassed = false;
xmlMessage = "<rawMessage>" + StringEscapeUtils.escapeXml(hl7MessageStr) + "</rawMessage>";
try {
message = HL7Utils.generateHL7MessageElement(xmlMessage);
} catch (XMLStreamException e2) {
handleError("Could not build XML from message. " + e.getMessage());
return false;
}
} else {
handleError("Could not build XML from message. " + e.getMessage());
return false;
}
} catch (XMLStreamException e) {
handleError("Could not build XML from message. " + e.getMessage());
return false;
}
try {
Terser terser = new Terser(hl7Message);
messageControlerID = terser.get("/MSH-10");
if (messageControlerID == null || messageControlerID .length() == 0) {
handleError("MSH segment missing required field: Control ID (MSH-10)");
return false;
}
} catch (HL7Exception e) {
handleError("MSH segment missing required field: Control ID (MSH-10)");
return false;
}
JPAStore store = (JPAStore) getMessageStoreImpl(storeName);
SynapseEnvironment synapseEnvironment = store.getSynapseEnvironment();
if (proxyName == null || proxyName.equals("")) {
handleError("Proxy service name not specified");
}
// Prepare axis2 message context
org.apache.axis2.context.MessageContext axis2MsgCtx =
new org.apache.axis2.context.MessageContext();
HL7TransportOutInfo outinfo = new HL7TransportOutInfo();
outinfo.setMessageControllerID(messageControlerID);
axis2MsgCtx.setProperty(Constants.OUT_TRANSPORT_INFO, outinfo);
ConfigurationContext configurationContext = ((Axis2SynapseEnvironment) synapseEnvironment).
getAxis2ConfigurationContext();
axis2MsgCtx.setConfigurationContext(configurationContext);
axis2MsgCtx.setIncomingTransportName(Constants.TRANSPORT_LOCAL);
axis2MsgCtx.setServerSide(true);
axis2MsgCtx.setProperty(HL7Constants.HL7_MESSAGE_OBJECT, hl7Message);
axis2MsgCtx.setProperty(HL7Constants.HL7_VALIDATION_PASSED, validationPassed);
axis2MsgCtx.setProperty(HL7Constants.HL7_PASS_THROUGH_INVALID_MESSAGES, isTrueProxyParameter(storeName,
proxyName,HL7Constants.HL7_PASS_THROUGH_INVALID_MESSAGES));
//there's no transport out when message is injected to proxy via HL7 Store UI
TransportOutDescription dummyTransportOut = new TransportOutDescription("Dummy Transport Out");
dummyTransportOut.setSender(new DummyTransportSender());
axis2MsgCtx.setTransportOut(dummyTransportOut);
try {
AxisService axisService = configurationContext.getAxisConfiguration().
getService(proxyName);
if (axisService == null) {
handleError("Proxy Service: " + proxyName + " not found");
}
axis2MsgCtx.setAxisService(axisService);
} catch (AxisFault axisFault) {
handleError("Error occurred while attempting to find the Proxy Service");
return false;
}
SOAPEnvelope envelope = new SOAP11Factory().createSOAPEnvelope();
try {
PayloadHelper.setXMLPayload(envelope, message.cloneOMElement());
axis2MsgCtx.setEnvelope(envelope);
} catch (AxisFault axisFault) {
handleError("Error in setting the message payload : " + message);
return false;
}
try {
if (log.isDebugEnabled()) {
log.debug("injecting message to proxy service : " + proxyName);
}
AxisEngine.receive(axis2MsgCtx);
} catch (AxisFault axisFault) {
handleError("Error occurred while invoking proxy service : " + proxyName);
return false;
}
return true;
}
private List<TransferableHL7Message> getTransferableMessages(JPAStore store, List<PersistentHL7Message> persistentHL7Messages) throws AxisFault {
List<TransferableHL7Message> transferableHL7Messages = new ArrayList<TransferableHL7Message>();
for(PersistentHL7Message message: persistentHL7Messages) {
transferableHL7Messages.add(getTransferableHL7Message(store, message));
}
return transferableHL7Messages;
}
private TransferableHL7Message getTransferableHL7Message(JPAStore store, PersistentHL7Message message) throws AxisFault {
org.apache.axis2.context.MessageContext axis2Mc = store.newAxis2Mc();
MessageContext synapseMc = store.newSynapseMc(axis2Mc);
try {
SerializableMessageContext serializableMessageContext = (SerializableMessageContext) SerializerUtils.deserialize(message.getMessage());
MessageContext persistedMc = SerializerUtils.toMessageContext(serializableMessageContext, axis2Mc, synapseMc);
Message hl7Message = (Message) ((Axis2MessageContext) persistedMc).getAxis2MessageContext().getProperty(HL7Constants.HL7_MESSAGE_OBJECT);
TransferableHL7Message transferableHL7Message = new TransferableHL7Message(message.getId(),
message.getStoreName(),
message.getMessageId(),
message.getControlId(),
hl7Message.encode(),
persistedMc.getEnvelope().getBody().getFirstElement().getFirstElement().toString(),
message.getDate().toString(),
message.getTimestamp());
return transferableHL7Message;
} catch (HL7Exception e) {
handleException(log, "Could not encode HL7 message.", null);
} catch (ClassNotFoundException e) {
handleException(log, "Could not deserialize message context.", null);
} catch (IOException e) {
handleException(log, "Could not deserialize message context.", null);
}
return null;
}
public List<TransferableHL7Message> getMessagesPaginated(String storeName, int pageNumber) throws HL7Exception, IOException, ClassNotFoundException {
JPAStore store = (JPAStore) getMessageStoreImpl(storeName);
if(store != null) {
return getTransferableMessages(store, store.getMessages(pageNumber, MSGS_PER_PAGE));
} else {
handleException(log, "Message Store " + storeName + " does not exist", null);
}
return null;
}
public TransferableHL7Message getMessage(String storeName, String messageId) throws HL7Exception, IOException, ClassNotFoundException {
JPAStore store = (JPAStore) getMessageStoreImpl(storeName);
if(store != null) {
return getTransferableHL7Message(store, store.getMessage(messageId));
} else {
handleException(log, "Message Store " + storeName + " does not exist !!!", null);
}
return null;
}
public boolean updateMessage(String storeName, String messageId, String er7Payload, String xmlPayload) {
JPAStore store = (JPAStore) getMessageStoreImpl(storeName);
return false;
}
public boolean flushMessages(String storeName) {
JPAStore store = (JPAStore) getMessageStoreImpl(storeName);
if(store.flushMessages() > 0) {
return true;
} else {
return false;
}
}
private void handleException(Log log, String message, Exception e)
throws AxisFault {
if (e == null) {
AxisFault exception =
new AxisFault(message);
log.error(message, exception);
throw exception;
} else {
message = message + " :: " + e.getMessage();
log.error(message, e);
throw new AxisFault(message, e);
}
}
private MessageStore getMessageStoreImpl(String name) {
SynapseConfiguration configuration = getSynapseConfiguration();
assert configuration != null;
assert configuration.getMessageStore(name) instanceof JPAStore;
return configuration.getMessageStore(name);
}
}