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 a pair of connections (one for
295     * incoming messages, one for outgoing)
296     *
297     * @param inboundPort  The port on which to listen for connections for inbound messages
298     * @param outboundPort The port on which to listen for connections for outgoing messages
299     * @param tls          Whether or not to use SSL/TLS
300     * @return HL7 service running on the configured ports using the default parser and executor
301     * service instances provided by this interface. Note that the returned service <b>will not
302     * be started</b>, and must manually be started using {@link HL7Service#start()} or
303     * {@link HL7Service#startAndWait()}
304     * @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
305     * @see #setSocketFactory(SocketFactory)
306     */
307    HL7Service newServer(int inboundPort, int outboundPort, boolean tls);
308
309    /**
310     * Construct a new HL7 Client which will connect to an external TCP server for
311     * the purpose of sending messages (and receiving responses). Unless otherwise
312     * stated, the connection is established by the time this method
313     * returns, or an exception should be thrown if the connection can not be
314     * established. If a connection to this server already exists, it is reused.
315     * <p>
316     * Note that connections are pooled by the HapiContext by default. If multiple
317     * concurrent connections to the same server are required, the easiest way
318     * to accomplish this is currently to create multiple HapiContext instances.
319     * </p>
320     *
321     * @param host The host IP/hostname to connect to
322     * @param port The port to connect to
323     * @param tls  Whether or not to use SSL/TLS
324     * @return Returns a connection which can be used to transmit messages. Note that this method
325     * will attempt to connect to the specified address, and will throw an exception
326     * if it fails to connect.
327     * @throws HL7Exception If the connection can not be initialized for any reason
328     * @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
329     */
330    Connection newClient(String host, int port, boolean tls) throws HL7Exception;
331
332    /**
333     * Construct a new HL7 Client which will connect to an external TCP server for
334     * the purpose of sending messages (and receiving responses). The connection
335     * should be established by the time the first message is sent.
336     * <p>
337     * Note that connections are pooled by the HapiContext by default. If multiple
338     * concurrent connections to the same server are required, the easiest way
339     * to accomplish this is currently to create multiple HapiContext instances.
340     * </p>
341     *
342     * @param host The host IP/hostname to connect to
343     * @param port The port to connect to
344     * @param tls  Whether or not to use SSL/TLS
345     * @return Returns a connection which can be used to transmit messages.
346     * @throws HL7Exception If the connection can not be initialized for any reason
347     * @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
348     */
349    Connection newLazyClient(String host, int port, boolean tls) throws HL7Exception;
350
351    /**
352     * Construct a new HL7 two-port client which will connect to an external TCP server for
353     * the purpose of sending messages (and receiving responses). Unless otherwise
354     * stated, the connection is established by the time this method
355     * returns, or an exception should be thrown if the connection can not be
356     * established. If a connection to this server already exists, it is reused.
357     * <p>
358     * Note that connections are pooled by the HapiContext by default. If multiple
359     * concurrent connections to the same server are required, the easiest way
360     * to accomplish this is currently to create multiple HapiContext instances.
361     * </p>
362     *
363     * @param host         The host IP/hostname to connect to
364     * @param outboundPort The port to connect to for outgoing messages
365     * @param inboundPort  The port to connect to for inbound (response) messages
366     * @param tls          Whether or not to use SSL/TLS
367     * @return Returns a connection which can be used to transmit messages. Note that this method
368     * will attempt to connect to the specified address, and will throw an exception
369     * if it fails to connect.
370     * @throws HL7Exception If the connection can not be initialized for any reason
371     */
372    Connection newClient(String host, int outboundPort, int inboundPort, boolean tls) throws HL7Exception;
373
374    /**
375     * Construct a new HL7 two-port client which will connect to an external TCP server for
376     * the purpose of sending messages (and receiving responses). The connection
377     * should be established by the time the first message is sent.
378     * <p>
379     * Note that connections are pooled by the HapiContext by default. If multiple
380     * concurrent connections to the same server are required, the easiest way
381     * to accomplish this is currently to create multiple HapiContext instances.
382     * </p>
383     *
384     * @param host         The host IP/hostname to connect to
385     * @param outboundPort The port to connect to for outgoing messages
386     * @param inboundPort  The port to connect to for inbound (response) messages
387     * @param tls          Whether or not to use SSL/TLS
388     * @return Returns a connection which can be used to transmit messages.
389     * @throws HL7Exception If the connection can not be initialized for any reason
390     */
391    Connection newLazyClient(String host, int outboundPort, int inboundPort, boolean tls) throws HL7Exception;
392
393    /**
394     * Creates a new message of the given event type, trigger and version, and initializes the message header
395     *
396     * @param eventType    event type, e.g. ADT
397     * @param triggerEvent trigger event, e.g. A01
398     * @param version      HL7v2 version
399     * @return Message object of the type determined by the underlying model class factory
400     * @throws HL7Exception if no message object could be created
401     */
402    Message newMessage(String eventType, String triggerEvent, Version version) throws HL7Exception;
403
404    /**
405     * Creates a new message of the provided message structure class, without further initializing the message
406     *
407     * @param clazz message structure class
408     * @param <T>   message structure class type
409     * @return the created message instance
410     * @throws HL7Exception
411     */
412    <T extends Message> T newMessage(Class<T> clazz) throws HL7Exception;
413}