001 package ca.uhn.hl7v2.app; 002 003 import java.util.HashMap; 004 005 import ca.uhn.hl7v2.model.Message; 006 import ca.uhn.hl7v2.HL7Exception; 007 import ca.uhn.hl7v2.util.Terser; 008 import ca.uhn.log.HapiLog; 009 import ca.uhn.log.HapiLogFactory; 010 011 /** 012 * Routes messages to various Applications based on message type and trigger event. 013 * The router is told which Application to which to route various messages by calling 014 * the method <code>registerApplication(...)</code>. 015 * @author Bryan Tripp 016 */ 017 public class MessageTypeRouter implements Application { 018 019 private static final HapiLog log = HapiLogFactory.getHapiLog(MessageTypeRouter.class); 020 private HashMap apps; 021 022 /** Creates a new instance of MessageTypeRouter */ 023 public MessageTypeRouter() { 024 apps = new HashMap(20); 025 } 026 027 /** 028 * Returns true if at least one application has been registered to accept this 029 * type of message. Applications are registered using <code>registerApplication(...)</code>. 030 */ 031 public boolean canProcess(Message in) { 032 boolean can = false; 033 try { 034 Application matches = this.getMatchingApplication(in); 035 if (matches != null) can = true; 036 } catch (HL7Exception e) { 037 can = false; 038 } 039 return can; 040 } 041 042 /** 043 * Forwards the given message to any Applications that have been registered to 044 * accept messages of that type and trigger event. 045 * @throws ApplicationException if no such Applications are registered, or if 046 * the underlying Application throws this exception during processing. 047 */ 048 public Message processMessage(Message in) throws ApplicationException { 049 Message out; 050 try { 051 Application matchingApp = this.getMatchingApplication(in); 052 out = matchingApp.processMessage(in); 053 } catch (HL7Exception e) { 054 throw new ApplicationException("Error internally routing message: " + e.toString(), e); 055 } 056 return out; 057 } 058 059 /** 060 * Registers the given application to handle messages corresponding to the given type 061 * and trigger event. Only one application can be registered for a given message type 062 * and trigger event combination. A repeated registration for a particular combination 063 * of type and trigger event over-writes the previous one. Use "*" as a wildcard (e.g. 064 * registerApplication("ADT", "*", myApp) would register your app for all ADT messages). 065 */ 066 public synchronized void registerApplication(String messageType, String triggerEvent, Application handler) { 067 this.apps.put(getKey(messageType, triggerEvent), handler); 068 069 //status message 070 StringBuffer buf = new StringBuffer(); 071 buf.append(handler.getClass().getName()); 072 buf.append(" registered to handle "); 073 buf.append(messageType); 074 buf.append("^"); 075 buf.append(triggerEvent); 076 buf.append(" messages"); 077 log.info(buf.toString()); 078 } 079 080 /** 081 * Returns the Applications that has been registered to handle 082 * messages of the type and trigger event of the given message, or null if 083 * there are none. 084 */ 085 private Application getMatchingApplication(Message message) throws HL7Exception { 086 Terser t = new Terser(message); 087 String messageType = t.get("/MSH-9-1"); 088 String triggerEvent = t.get("/MSH-9-2"); 089 return this.getMatchingApplication(messageType, triggerEvent); 090 } 091 092 /** 093 * Returns the Applications that has been registered to handle 094 * messages of the given type and trigger event, or null if 095 * there are none. If there is not an exact match, wildcards 096 * ("*") are tried as well. 097 */ 098 private synchronized Application getMatchingApplication(String messageType, String triggerEvent) { 099 Application matchingApp = null; 100 Object o = this.apps.get(getKey(messageType, triggerEvent)); 101 if (o == null) o = this.apps.get(getKey(messageType, "*")); 102 if (o == null) o = this.apps.get(getKey("*", triggerEvent)); 103 if (o == null) o = this.apps.get(getKey("*", "*")); 104 if (o != null) matchingApp = (Application)o; 105 return matchingApp; 106 } 107 108 /** 109 * Creates reproducible hash key. 110 */ 111 private String getKey(String messageType, String triggerEvent) { 112 //create hash key string by concatenating type and trigger event 113 return messageType + "|" + triggerEvent; 114 } 115 }