Package ca.uhn.hl7v2.protocol.impl

Source Code of ca.uhn.hl7v2.protocol.impl.ApplicationRouterImpl

/*
* Created on 21-Apr-2004
*/
package ca.uhn.hl7v2.protocol.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ca.uhn.hl7v2.HL7Exception;
import ca.uhn.hl7v2.app.DefaultApplication;
import ca.uhn.hl7v2.app.Responder;
import ca.uhn.hl7v2.model.Message;
import ca.uhn.hl7v2.model.Segment;
import ca.uhn.hl7v2.parser.GenericParser;
import ca.uhn.hl7v2.parser.Parser;
import ca.uhn.hl7v2.protocol.ApplicationRouter;
import ca.uhn.hl7v2.protocol.ReceivingApplication;
import ca.uhn.hl7v2.protocol.Transportable;
import ca.uhn.hl7v2.util.Terser;

/**
* <p>A default implementation of <code>ApplicationRouter</code> </p> 
*
* <p>Note that ParseChecker is used for each inbound message, iff the system
* property ca.uhn.hl7v2.protocol.impl.check_parse = "TRUE".  </p>
*
* @author <a href="mailto:bryan.tripp@uhn.on.ca">Bryan Tripp</a>
* @version $Revision: 1.2 $ updated on $Date: 2009-09-01 00:22:23 $ by $Author: jamesagnew $
*/
public class ApplicationRouterImpl implements ApplicationRouter {

    private static final Logger log = LoggerFactory.getLogger(ApplicationRouterImpl.class);
   
    /**
     * Key under which raw message text is stored in metadata Map sent to
     * <code>ReceivingApplication</code>s.
     */
    public static String RAW_MESSAGE_KEY = "raw-message";

    private List<Binding> myBindings;
    private Parser myParser;
   

    /**
     * Creates an instance that uses a <code>GenericParser</code>.
     */
    public ApplicationRouterImpl() {
        init(new GenericParser());
    }
   
    /**
     * Creates an instance that uses the specified <code>Parser</code>.
     * @param theParser the parser used for converting between Message and
     *      Transportable
     */
    public ApplicationRouterImpl(Parser theParser) {
        init(theParser);
    }
   
    private void init(Parser theParser) {
        myBindings = new ArrayList<Binding>(20);
        myParser = theParser;
    }

    /**
     * @see ca.uhn.hl7v2.protocol.ApplicationRouter#processMessage(ca.uhn.hl7v2.protocol.Transportable)
     */
    public Transportable processMessage(Transportable theMessage) throws HL7Exception {
        String[] result = processMessage(theMessage.getMessage(), theMessage.getMetadata());
        Transportable response = new TransportableImpl(result[0]);
       
        if (result[1] != null) {
            response.getMetadata().put("MSH-18", result[1]);
        }
       
        return response;
    }
   
    /**
     * Processes an incoming message string and returns the response message string.
     * Message processing consists of parsing the message, finding an appropriate
     * Application and processing the message with it, and encoding the response.
     * Applications are chosen from among those registered using
     * <code>bindApplication</code>
     *
     * @return {text, charset}
     */
    private String[] processMessage(String incomingMessageString, Map<String, Object> theMetadata) throws HL7Exception {
        Logger rawOutbound = LoggerFactory.getLogger("ca.uhn.hl7v2.raw.outbound");
        Logger rawInbound = LoggerFactory.getLogger("ca.uhn.hl7v2.raw.inbound");
       
        log.info( "ApplicationRouterImpl got message: {}", incomingMessageString );
        rawInbound.info(incomingMessageString);
       
        Message incomingMessageObject = null;
        String outgoingMessageString = null;
        String outgoingMessageCharset = null;
        try {
            incomingMessageObject = myParser.parse(incomingMessageString);
        }
        catch (HL7Exception e) {
            outgoingMessageString = Responder.logAndMakeErrorMessage(e, myParser.getCriticalResponseData(incomingMessageString), myParser, myParser.getEncoding(incomingMessageString));
        }
       
        if (outgoingMessageString == null) {
            try {
                //optionally check integrity of parse
                String check = System.getProperty("ca.uhn.hl7v2.protocol.impl.check_parse");
                if (check != null && check.equals("TRUE")) {
                    ParseChecker.checkParse(incomingMessageString, incomingMessageObject, myParser);
                }
               
                //message validation (in terms of optionality, cardinality) would go here ***
               
                ReceivingApplication app = findApplication(incomingMessageObject);
                theMetadata.put(RAW_MESSAGE_KEY, incomingMessageString);
               
                log.debug("Sending message to application: {}", app.toString());
                Message response = app.processMessage(incomingMessageObject, theMetadata);
               
                //Here we explicitly use the same encoding as that of the inbound message - this is important with GenericParser, which might use a different encoding by default
                outgoingMessageString = myParser.encode(response, myParser.getEncoding(incomingMessageString));
               
                Terser t = new Terser(response);
                outgoingMessageCharset = t.get("MSH-18");
            }
            catch (Exception e) {
                outgoingMessageString = Responder.logAndMakeErrorMessage(e, (Segment) incomingMessageObject.get("MSH"), myParser, myParser.getEncoding(incomingMessageString));
            }
        }
       
        log.info( "ApplicationRouterImpl sending message: {}", outgoingMessageString );
        rawOutbound.info(outgoingMessageString);
       
        return new String[] {outgoingMessageString, outgoingMessageCharset};
    }
   

    /**
     * @see ca.uhn.hl7v2.protocol.ApplicationRouter#hasActiveBinding(ca.uhn.hl7v2.protocol.ApplicationRouter.AppRoutingData)
     */
    public boolean hasActiveBinding(AppRoutingData theRoutingData) {
        boolean result = false;
        ReceivingApplication app = findDestination(theRoutingData);
        if (app != null) {
            result = true;
        }
        return result;
    }
   
    /**
     * @param theRoutingData
     * @return the application from the binding with a WILDCARD match, if one exists
     */
    private ReceivingApplication findDestination(AppRoutingData theRoutingData) {
        ReceivingApplication result = null;
        for (int i = 0; i < myBindings.size() && result == null; i++) {
            Binding binding = (Binding) myBindings.get(i);
            if (matches(theRoutingData, binding.routingData) && binding.active) {
                result = binding.application;
            }
        }
        return result;       
    }
   
    /**
     * @param theRoutingData
     * @return the binding with an EXACT match on routing data if one exists
     */
    private Binding findBinding(AppRoutingData theRoutingData) {
        Binding result = null;
        for (int i = 0; i < myBindings.size() && result == null; i++) {
            Binding binding = (Binding) myBindings.get(i);
            if ( theRoutingData.equals(binding.routingData) ) {
                result = binding;
            }
        }
        return result;       
       
    }

    /**
     * @see ca.uhn.hl7v2.protocol.ApplicationRouter#bindApplication(
     *      ca.uhn.hl7v2.protocol.ApplicationRouter.AppRoutingData, ca.uhn.hl7v2.protocol.ReceivingApplication)
     */
    public void bindApplication(AppRoutingData theRoutingData, ReceivingApplication theApplication) {
        Binding binding = new Binding(theRoutingData, true, theApplication);
        myBindings.add(binding);
    }

    /**
     * @see ca.uhn.hl7v2.protocol.ApplicationRouter#disableBinding(ca.uhn.hl7v2.protocol.ApplicationRouter.AppRoutingData)
     */
    public void disableBinding(AppRoutingData theRoutingData) {
        Binding b = findBinding(theRoutingData);
        if (b != null) {
            b.active = false;
        }
    }

    /**
     * @see ca.uhn.hl7v2.protocol.ApplicationRouter#enableBinding(ca.uhn.hl7v2.protocol.ApplicationRouter.AppRoutingData)
     */
    public void enableBinding(AppRoutingData theRoutingData) {
        Binding b = findBinding(theRoutingData);
        if (b != null) {
            b.active = true;
        }
    }

    /**
     * @see ca.uhn.hl7v2.protocol.ApplicationRouter#getParser()
     */
    public Parser getParser() {
        return myParser;
    }
   
    /**
     * @param theMessageData routing data related to a particular message
     * @param theReferenceData routing data related to a binding, which may include
     *      wildcards
     * @param exact if true, each field must match exactly
     * @return true if the message data is consist with the reference data, ie all
     *      values either match or are wildcards in the reference
     */
    public static boolean matches(AppRoutingData theMessageData,
                AppRoutingData theReferenceData) {
                   
        boolean result = false;
       
        ApplicationRouter.AppRoutingData ref = theReferenceData;
        ApplicationRouter.AppRoutingData msg = theMessageData;
       
        if (matches(msg.getMessageType(), ref.getMessageType())
            && matches(msg.getTriggerEvent(), ref.getTriggerEvent())
            && matches(msg.getProcessingId(), ref.getProcessingId())
            && matches(msg.getVersion(), ref.getVersion())) {
       
            result = true;
        }
       
        return result;       
    }

    //support method for matches(AppRoutingData theMessageData, AppRoutingData theReferenceData)
    private static boolean matches(String theMessageData, String theReferenceData) {
        boolean result = false;
        if (theMessageData.equals(theReferenceData) ||
                theReferenceData.equals("*") ||
                Pattern.matches(theReferenceData, theMessageData)) {
            result = true;
        }
        return result;
    }
   
    /**
     * Returns the first Application that has been bound to messages of this type. 
     */
    private ReceivingApplication findApplication(Message theMessage) throws HL7Exception {
        Terser t = new Terser(theMessage);
        AppRoutingData msgData =
            new AppRoutingDataImpl(t.get("/MSH-9-1"), t.get("/MSH-9-2"), t.get("/MSH-11-1"), t.get("/MSH-12"));
           
        ReceivingApplication app = findDestination(msgData);
       
        //have to send back an application reject if no apps available to process
        if (app == null)
            app = new AppWrapper(new DefaultApplication());
        return app;
    }
   
    /**
     * A structure for bindings between routing data and applications. 
     */
    private static class Binding {
        public AppRoutingData routingData;
        public boolean active;
        public ReceivingApplication application;
       
        public Binding(AppRoutingData theRoutingData, boolean isActive, ReceivingApplication theApplication) {
            routingData = theRoutingData;
            active = isActive;
            application = theApplication;
        }
    }
   
}
TOP

Related Classes of ca.uhn.hl7v2.protocol.impl.ApplicationRouterImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.