View Javadoc

1   /*
2    * Created on 3-May-2004
3    */
4   package ca.uhn.hl7v2.protocol.impl;
5   
6   import java.util.ArrayList;
7   import java.util.HashMap;
8   import java.util.List;
9   import java.util.Map;
10  
11  import ca.uhn.hl7v2.HL7Exception;
12  import ca.uhn.hl7v2.model.Message;
13  import ca.uhn.hl7v2.parser.GenericParser;
14  import ca.uhn.hl7v2.parser.Parser;
15  import ca.uhn.hl7v2.protocol.Initiator;
16  import ca.uhn.hl7v2.protocol.Processor;
17  import ca.uhn.hl7v2.protocol.Transportable;
18  import ca.uhn.hl7v2.util.Terser;
19  
20  /**
21   * Default implementation of <code>Initiator</code>. 
22   * 
23   * @author <a href="mailto:bryan.tripp@uhn.on.ca">Bryan Tripp</a>
24   * @version $Revision: 1.1 $ updated on $Date: 2007-02-19 02:24:26 $ by $Author: jamesagnew $
25   */
26  public class InitiatorImpl implements Initiator {
27  
28      private final List<String> myMetadataFields;
29      private final Parser myParser;
30      private final Processor myProcessor;
31      private int myMaxRetries;
32      private long myRetryInterval;
33      private long myReceiveTimeout;
34      
35      /**
36       * Creates an instance that uses a <code>GenericParser</code>
37       * @param theProcessor the <code>Processor</code> used to communicate 
38       *  with the remote system
39       */
40      public InitiatorImpl(Processor theProcessor) {
41          myMetadataFields = new ArrayList<String>(20);
42          myMetadataFields.add("MSH-18"); //add character set by default
43          myParser = new GenericParser();
44          myProcessor = theProcessor;
45          init();
46      }
47      
48      /**
49       * Creates an instance that uses the given <code>Parser</code>
50       * @param theParser parser to use for parsing and encoding messages
51       * @param theProcessor the <code>Processor</code> used to communicate 
52       *  with the remote system
53       */
54      public InitiatorImpl(Parser theParser, Processor theProcessor) {
55          myMetadataFields = new ArrayList<String>(20);
56          myParser = theParser;
57          myProcessor = theProcessor;
58          init();
59      }
60      
61      private void init() {
62          myMaxRetries = 3;
63          myRetryInterval = 3000;
64          myReceiveTimeout = 10000;
65      }
66      
67      
68      /**
69       * @param theMaxRetries max number of retries for initial message delivery 
70       */
71      public void setMaxRetries(int theMaxRetries) {
72          myMaxRetries = theMaxRetries;
73      }
74      
75      public int getMaxRetries() {
76          return myMaxRetries;
77      }
78      
79      /**
80       * @param theRetryIntervalMillis milliseconds between retries of message delivery 
81       */
82      public void setRetryInterval(long theRetryIntervalMillis) {
83          myRetryInterval = theRetryIntervalMillis;
84      }
85      
86      public long getRetryInterval() {
87          return myRetryInterval;
88      }
89      
90      /**
91       * @param theReceiveTimeout the length of time we wait for responses (defaults 
92       *      to 10 seconds)
93       */
94      public void setReceiveTimeout(long theReceiveTimeout) {
95          myReceiveTimeout = theReceiveTimeout;
96      }
97      
98      public long getReceiveTimeout() {
99          return myReceiveTimeout;
100     }
101     
102     /**
103      * @see ca.uhn.hl7v2.protocol.Initiator#sendAndReceive(ca.uhn.hl7v2.model.Message)
104      */
105     public Message sendAndReceive(Message theMessage) throws HL7Exception {
106         Terser t = new Terser(theMessage);
107         String appAckNeeded = t.get("/MSH-16");
108         String msgId = t.get("/MSH-10");
109         
110         String messageText = getParser().encode(theMessage);
111         Map<String, Object> metadata = getMetadata(theMessage);
112         Transportable out = new TransportableImpl(messageText, metadata);
113         
114         if (needAck(appAckNeeded)) {
115             myProcessor.reserve(msgId, getReceiveTimeout());
116         }
117         
118         myProcessor.send(out, getMaxRetries(), getRetryInterval());
119         
120         Message in = null;
121         if (needAck(appAckNeeded)) { 
122             Transportable received = myProcessor.receive(msgId, getReceiveTimeout());
123             if (received != null && received.getMessage() != null) {
124                 in = getParser().parse(received.getMessage());
125             }
126         }
127         
128         return in;
129     }
130     
131     /**
132      * @param theAckCode from MSH-16
133      * @return true if the code indicates that we should wait for an ACK and try 
134      *      to return it to the caller 
135      */
136     private boolean needAck(String theAckCode) {
137         boolean need = false;
138         if (theAckCode == null 
139             || theAckCode.equals("") 
140             || theAckCode.equals(Processor.AL) 
141             || theAckCode.equals(Processor.ER)) 
142         {
143             need = true; 
144         }        
145         return need;
146     }
147     
148     private Map<String, Object> getMetadata(Message theMessage) throws HL7Exception {
149         Map<String, Object> md = new HashMap<String, Object>();
150         Terser t = new Terser(theMessage);
151 
152         //snapshot so concurrent changes won't break our iteration
153         String[] fields = getMetadataFields().toArray(new String[0]);
154         
155         for (int i = 0; i < fields.length; i++) {
156             String field = fields[i].toString();
157             String val = t.get(field); 
158             md.put(field, val);
159         }
160         
161         return md;
162     }
163 
164     /** 
165      * @see ca.uhn.hl7v2.protocol.Initiator#getParser()
166      */
167     public Parser getParser() {
168         return myParser;
169     }
170 
171     /** 
172      * @see ca.uhn.hl7v2.protocol.Initiator#getUnderlyingProcessor()
173      */
174     public Processor getUnderlyingProcessor() {
175         return myProcessor;
176     }
177 
178     /**
179      * @see ca.uhn.hl7v2.protocol.Initiator#getMetadataFields()
180      */
181     public List<String> getMetadataFields() {
182         return myMetadataFields;
183     }
184 
185 
186 }