001/**
002 The contents of this file are subject to the Mozilla Public License Version 1.1
003 (the "License"); you may not use this file except in compliance with the License.
004 You may obtain a copy of the License at http://www.mozilla.org/MPL/
005 Software distributed under the License is distributed on an "AS IS" basis,
006 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the
007 specific language governing rights and limitations under the License.
008
009 The Original Code is "HapiContext.java".  Description:
010 "HAPI configuration and factory"
011
012 The Initial Developer of the Original Code is University Health Network. Copyright (C)
013 2001.  All Rights Reserved.
014
015 Contributor(s): ______________________________________.
016
017 Alternatively, the contents of this file may be used under the terms of the
018 GNU General Public License (the  "GPL"), in which case the provisions of the GPL are
019 applicable instead of those above.  If you wish to allow use of your version of this
020 file only under the terms of the GPL and not to allow others to use your version
021 of this file under the MPL, indicate your decision by deleting  the provisions above
022 and replace  them with the notice and other provisions required by the GPL License.
023 If you do not delete the provisions above, a recipient may use your version of
024 this file under either the MPL or the GPL.
025 */
026package ca.uhn.hl7v2;
027
028import java.io.Closeable;
029import java.util.concurrent.ExecutorService;
030
031import ca.uhn.hl7v2.app.Connection;
032import ca.uhn.hl7v2.app.ConnectionHub;
033import ca.uhn.hl7v2.app.HL7Service;
034import ca.uhn.hl7v2.app.ServerConfiguration;
035import ca.uhn.hl7v2.conf.store.CodeStoreRegistry;
036import ca.uhn.hl7v2.conf.store.ProfileStore;
037import ca.uhn.hl7v2.llp.LowerLayerProtocol;
038import ca.uhn.hl7v2.model.Message;
039import ca.uhn.hl7v2.parser.*;
040import ca.uhn.hl7v2.util.SocketFactory;
041import ca.uhn.hl7v2.validation.ValidationContext;
042import ca.uhn.hl7v2.validation.ValidationExceptionHandlerFactory;
043import ca.uhn.hl7v2.validation.Validator;
044import ca.uhn.hl7v2.validation.builder.ValidationRuleBuilder;
045
046/**
047 * Interface that provides a starting point for
048 * <ul>
049 * <li>Configuring HAPI core services (e.g. parsing)
050 * <li>Obtaining correspondingly configured instances of HAPI core services
051 * </ul>
052 * <p/>
053 * HapiContext instances are not supposed to be singletons, i.e. if necessary, it is possible to
054 * have several HapiContexts within one application.
055 * <p/>
056 * HapiContext objects maintains the following configuration information
057 * <ul>
058 * <li>{@link ExecutorService}: thread executors used for the HAPI networking features in
059 * ca.uhn.hl7v2.app
060 * <li>{@link LowerLayerProtocol}: MLLP protocol used for the HAPI networking features in
061 * ca.uhn.hl7v2.app
062 * <li>{@link SocketFactory}: Socket factory used for the HAPI networking features in
063 * ca.uhn.hl7v2.app
064 * <li>{@link ParserConfiguration}: detail configuration for all HL7 parsers
065 * <li>{@link ModelClassFactory}: lookup for message model classes during parsing or message
066 * creation
067 * <li>{@link ValidationContext}: validation rules used during parsing or during a dedcated
068 * validation step
069 * <li>{@link ValidationRuleBuilder}: alternative way of providing a ValidationContext
070 * <li>{@link ValidationExceptionHandlerFactory}: factory for exception handler used during message validation
071 * </ul>
072 * <p/>
073 * HapiContext serves as factory for HAPI objects that refer to this configuration. Changing the
074 * configuration automatically influence all HAPI objects that were created and will be created
075 * using the given factory instance:
076 * <ul>
077 * <li>{@link PipeParser}
078 * <li>{@link XMLParser}
079 * <li>{@link GenericParser}
080 * <li>{@link Validator}
081 * <li>{@link ConnectionHub}
082 * <li>{@link ca.uhn.hl7v2.app.SimpleServer}
083 * <li>{@link ca.uhn.hl7v2.app.TwoPortService}
084 * </ul>
085 */
086public interface HapiContext extends Closeable {
087
088    /**
089     * @return the {@link ExecutorService} to be used by all services that spawn threads
090     */
091    ExecutorService getExecutorService();
092
093    /**
094     * @param executorService the {@link ExecutorService} to be used by all services that spawn
095     *                        threads
096     */
097    void setExecutorService(ExecutorService executorService);
098
099    /**
100     * @return a new ConnectionHub instance
101     * @deprecated use {@link #newClient(String, int, boolean)}
102     */
103    ConnectionHub getConnectionHub();
104
105    /**
106     * @return the {@link ParserConfiguration} to be used by all parsers obtained from this class.
107     */
108    ParserConfiguration getParserConfiguration();
109
110    /**
111     * @return the {@link ServerConfiguration} to be used by all HL7 servers obtained from this class.
112     * @see #newServer(int, boolean)
113     * @see #newServer(int, int, boolean)
114     */
115    ServerConfiguration getServerConfiguration();
116
117    /**
118     * Sets the {@link ServerConfiguration} to be used by all HL7 servers obtained from this class.
119     *
120     * @see #newServer(int, boolean)
121     * @see #newServer(int, int, boolean)
122     */
123    void setServerConfiguration(ServerConfiguration theServerConfiguration);
124
125    /**
126     * @param configuration {@link ParserConfiguration} to be used by all parsers obtained from this
127     *                      class.
128     */
129    void setParserConfiguration(ParserConfiguration configuration);
130
131    /**
132     * @return the {@link ValidationContext} to be used by all parsers obtained from this class.
133     */
134    ValidationContext getValidationContext();
135
136    /**
137     * @param context {@link ValidationContext} to be used by all parsers obtained from this class.
138     */
139    void setValidationContext(ValidationContext context);
140
141    /**
142     * Sets a default {@link ValidationContext}. Note that a default {@link ValidationRuleBuilder}
143     * has precedence of this ValidationContext.
144     *
145     * @param contextClassName class name of the {@link ValidationContext} to be used by all parsers
146     *                         obtained from this class.
147     */
148    void setValidationContext(String contextClassName);
149
150    /**
151     * @return the {@link ValidationRuleBuilder} to be used by all parsers obtained from this class.
152     */
153    ValidationRuleBuilder getValidationRuleBuilder();
154
155    /**
156     * Sets a default {@link ValidationRuleBuilder}. Note that this {@link ValidationRuleBuilder}
157     * has precedence over a default {@link ValidationContext} set with
158     * {@link #setValidationContext(ValidationContext)} or {@link #setValidationContext(String)}
159     *
160     * @param ruleBuilder {@link ValidationRuleBuilder} to be used by all parsers obtained from this
161     *                    class.
162     */
163    void setValidationRuleBuilder(ValidationRuleBuilder ruleBuilder);
164
165    /**
166     * Sets a new instance of {@link ValidationRuleBuilder} as default. Note that this
167     * {@link ValidationRuleBuilder} has precedence over a default {@link ValidationContext} set
168     * with {@link #setValidationContext(ValidationContext)} or
169     * {@link #setValidationContext(String)}
170     *
171     * @param builderClassName class name of the {@link ValidationRuleBuilder} to be used by all
172     *                         parsers obtained from this class.
173     */
174    void setValidationRuleBuilder(String builderClassName);
175
176    /**
177     * @return the {@link ModelClassFactory} to be used by all parsers obtained from this class.
178     */
179    ModelClassFactory getModelClassFactory();
180
181    /**
182     * @param modelClassFactory the {@link ModelClassFactory} to be used by all parsers obtained
183     *                          from this class.
184     */
185    void setModelClassFactory(ModelClassFactory modelClassFactory);
186
187    /**
188     * @return the {@link ProfileStore} to be used for loading conformance profile files
189     */
190    ProfileStore getProfileStore();
191
192    /**
193     * @param store the {@link ProfileStore} to be used for loading conformance profile files
194     */
195    void setProfileStore(ProfileStore store);
196
197    /**
198     * @return the {@link CodeStoreRegistry} to be used for serving codes for conformance profiles
199     */
200    CodeStoreRegistry getCodeStoreRegistry();
201
202    /**
203     * @param store the {@link CodeStoreRegistry} to be used for serving codes for conformance profiles
204     */
205    void setCodeStoreRegistry(CodeStoreRegistry store);
206
207    // Default instances of business objects
208
209    /**
210     * @return a new PipeParser instance initialized as set with
211     * {@link #setModelClassFactory(ModelClassFactory)},
212     * {@link #setValidationContext(String)} and
213     * {@link #setParserConfiguration(ParserConfiguration)}.
214     */
215    PipeParser getPipeParser();
216
217    /**
218     * @return a new XMLParser instance initialized as set with
219     * {@link #setModelClassFactory(ModelClassFactory)},
220     * {@link #setValidationContext(String)} and
221     * {@link #setParserConfiguration(ParserConfiguration)}.
222     */
223    XMLParser getXMLParser();
224
225    /**
226     * @return a new GenericParser instance initialized as set with
227     * {@link #setModelClassFactory(ModelClassFactory)},
228     * {@link #setValidationContext(String)} and
229     * {@link #setParserConfiguration(ParserConfiguration)}.
230     */
231    GenericParser getGenericParser();
232
233    /**
234     * Returns a ca.uhn.hl7v2.conf.check.Validator instance. It is recommended to
235     * use {@link #getMessageValidator()} and configure a Validation rule that checks
236     * a message against a conformance profile
237     *
238     * @return a ca.uhn.hl7v2.conf.check.Validator instance initialized as set with
239     * {@link #setCodeStoreRegistry(CodeStoreRegistry)}
240     */
241    ca.uhn.hl7v2.conf.check.Validator getConformanceValidator();
242
243    /**
244     * @return a MessageValidator instance initialized with the {@link ValidationContext} as set
245     * using {@link #setValidationContext(ValidationContext)}. For each validation it will
246     * use a new instance of {@link ca.uhn.hl7v2.validation.ValidationExceptionHandler ValidationExceptionHandler} as obtained by
247     * {@link #getValidationExceptionHandlerFactory()}.
248     */
249    <R> Validator<R> getMessageValidator();
250
251    <R> ValidationExceptionHandlerFactory<R> getValidationExceptionHandlerFactory();
252
253    /**
254     * @param factory a {@link ValidationExceptionHandlerFactory} that is used to create
255     *                a {@link ca.uhn.hl7v2.validation.ValidationExceptionHandler ValidationExceptionHandler} during message validation.
256     */
257    <R> void setValidationExceptionHandlerFactory(ValidationExceptionHandlerFactory<R> factory);
258
259    /**
260     * @return the {@link LowerLayerProtocol} instance used by all HL7 MLLP operations
261     */
262    LowerLayerProtocol getLowerLayerProtocol();
263
264    /**
265     * @param llp the {@link LowerLayerProtocol} instance used by all HL7 MLLP operations
266     */
267    void setLowerLayerProtocol(LowerLayerProtocol llp);
268
269    /**
270     * @return the {@link SocketFactory} instance used by HL7 networking operations
271     */
272    SocketFactory getSocketFactory();
273
274    /**
275     * @param socketFactory the {@link SocketFactory} instance used by HL7 networking operations
276     */
277    void setSocketFactory(SocketFactory socketFactory);
278
279    /**
280     * Construct a new HL7 Server which will listen for incoming connections
281     *
282     * @param port The port on which to listen for new connections
283     * @param tls  Whether or not to use SSL/TLS
284     * @return HL7 service running on the configured port using the default parser and executor
285     * service instances provided by this interface. Note that the returned service <b>will not
286     * be started</b>, and must manually be started using {@link HL7Service#start()} or
287     * {@link HL7Service#startAndWait()}
288     * @see <a href="http://hl7api.sourceforge.net/xref/ca/uhn/hl7v2/examples/SendAndReceiveAMessage.html">here</a> for an example of how to use this method
289     * @see #setSocketFactory(SocketFactory)
290     */
291    HL7Service newServer(int port, boolean tls);
292
293    /**
294    * Construct a new HL7 Server which will listen for incoming connections
295    * and will pass all messages to the responders, even if the message control id is not 
296    * known to the server
297    *
298    * @param port The port on which to listen for new connections
299    * @param tls  Whether or not to use SSL/TLS
300    * @param acceptAll  Whether or not to accept all messages
301    * @return HL7 service running on the configured port using the default parser and executor
302    * service instances provided by this interface. Note that the returned service <b>will not
303    * be started</b>, and must manually be started using {@link HL7Service#start()} or
304    * {@link HL7Service#startAndWait()}
305    * @see <a href="http://hl7api.sourceforge.net/xref/ca/uhn/hl7v2/examples/SendAndReceiveAMessage.html">here<> for an example of how to use this method
306    * @see #setSocketFactory(SocketFactory)
307    */
308    HL7Service newServer(int port, boolean tls, boolean acceptAll);
309
310    /**
311     * Construct a new HL7 Server which will listen for a pair of connections (one for
312     * incoming messages, one for outgoing)
313     *
314     * @param inboundPort  The port on which to listen for connections for inbound messages
315     * @param outboundPort The port on which to listen for connections for outgoing messages
316     * @param tls          Whether or not to use SSL/TLS
317     * @return HL7 service running on the configured ports using the default parser and executor
318     * service instances provided by this interface. Note that the returned service <b>will not
319     * be started</b>, and must manually be started using {@link HL7Service#start()} or
320     * {@link HL7Service#startAndWait()}
321     * @see <a href="http://hl7api.sourceforge.net/xref/ca/uhn/hl7v2/examples/SendAndReceiveAMessage.html">here</a> for an example of how to use this method
322     * @see #setSocketFactory(SocketFactory)
323     */
324    HL7Service newServer(int inboundPort, int outboundPort, boolean tls);
325
326    /**
327     * Construct a new HL7 Client which will connect to an external TCP server for
328     * the purpose of sending messages (and receiving responses). Unless otherwise
329     * stated, the connection is established by the time this method
330     * returns, or an exception should be thrown if the connection can not be
331     * established. If a connection to this server already exists, it is reused.
332     * <p>
333     * Note that connections are pooled by the HapiContext by default. If multiple
334     * concurrent connections to the same server are required, the easiest way
335     * to accomplish this is currently to create multiple HapiContext instances.
336     * </p>
337     *
338     * @param host The host IP/hostname to connect to
339     * @param port The port to connect to
340     * @param tls  Whether or not to use SSL/TLS
341     * @return Returns a connection which can be used to transmit messages. Note that this method
342     * will attempt to connect to the specified address, and will throw an exception
343     * if it fails to connect.
344     * @throws HL7Exception If the connection can not be initialized for any reason
345     * @see <a href="http://hl7api.sourceforge.net/xref/ca/uhn/hl7v2/examples/SendAndReceiveAMessage.html">here</a> for an example of how to use this method
346     */
347    Connection newClient(String host, int port, boolean tls) throws HL7Exception;
348
349    /**
350     * Construct a new HL7 Client which will connect to an external TCP server for
351     * the purpose of sending messages (and receiving responses). The connection
352     * should be established by the time the first message is sent.
353     * <p>
354     * Note that connections are pooled by the HapiContext by default. If multiple
355     * concurrent connections to the same server are required, the easiest way
356     * to accomplish this is currently to create multiple HapiContext instances.
357     * </p>
358     *
359     * @param host The host IP/hostname to connect to
360     * @param port The port to connect to
361     * @param tls  Whether or not to use SSL/TLS
362     * @return Returns a connection which can be used to transmit messages.
363     * @throws HL7Exception If the connection can not be initialized for any reason
364     * @see <a href="http://hl7api.sourceforge.net/xref/ca/uhn/hl7v2/examples/SendAndReceiveAMessage.html">here</a> for an example of how to use this method
365     */
366    Connection newLazyClient(String host, int port, boolean tls) throws HL7Exception;
367
368    /**
369     * Construct a new HL7 two-port client which will connect to an external TCP server for
370     * the purpose of sending messages (and receiving responses). Unless otherwise
371     * stated, the connection is established by the time this method
372     * returns, or an exception should be thrown if the connection can not be
373     * established. If a connection to this server already exists, it is reused.
374     * <p>
375     * Note that connections are pooled by the HapiContext by default. If multiple
376     * concurrent connections to the same server are required, the easiest way
377     * to accomplish this is currently to create multiple HapiContext instances.
378     * </p>
379     *
380     * @param host         The host IP/hostname to connect to
381     * @param outboundPort The port to connect to for outgoing messages
382     * @param inboundPort  The port to connect to for inbound (response) messages
383     * @param tls          Whether or not to use SSL/TLS
384     * @return Returns a connection which can be used to transmit messages. Note that this method
385     * will attempt to connect to the specified address, and will throw an exception
386     * if it fails to connect.
387     * @throws HL7Exception If the connection can not be initialized for any reason
388     */
389    Connection newClient(String host, int outboundPort, int inboundPort, boolean tls) throws HL7Exception;
390
391    /**
392     * Construct a new HL7 two-port client which will connect to an external TCP server for
393     * the purpose of sending messages (and receiving responses). The connection
394     * should be established by the time the first message is sent.
395     * <p>
396     * Note that connections are pooled by the HapiContext by default. If multiple
397     * concurrent connections to the same server are required, the easiest way
398     * to accomplish this is currently to create multiple HapiContext instances.
399     * </p>
400     *
401     * @param host         The host IP/hostname to connect to
402     * @param outboundPort The port to connect to for outgoing messages
403     * @param inboundPort  The port to connect to for inbound (response) messages
404     * @param tls          Whether or not to use SSL/TLS
405     * @return Returns a connection which can be used to transmit messages.
406     * @throws HL7Exception If the connection can not be initialized for any reason
407     */
408    Connection newLazyClient(String host, int outboundPort, int inboundPort, boolean tls) throws HL7Exception;
409
410    /**
411     * Creates a new message of the given event type, trigger and version, and initializes the message header
412     *
413     * @param eventType    event type, e.g. ADT
414     * @param triggerEvent trigger event, e.g. A01
415     * @param version      HL7v2 version
416     * @return Message object of the type determined by the underlying model class factory
417     * @throws HL7Exception if no message object could be created
418     */
419    Message newMessage(String eventType, String triggerEvent, Version version) throws HL7Exception;
420
421    /**
422     * Creates a new message of the provided message structure class, without further initializing the message
423     *
424     * @param clazz message structure class
425     * @param <T>   message structure class type
426     * @return the created message instance
427     * @throws HL7Exception
428     */
429    <T extends Message> T newMessage(Class<T> clazz) throws HL7Exception;
430}