001/**
002The 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. 
004You may obtain a copy of the License at http://www.mozilla.org/MPL/ 
005Software distributed under the License is distributed on an "AS IS" basis, 
006WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the 
007specific language governing rights and limitations under the License. 
008
009The Original Code is "DefaultHapiContext.java".  Description: 
010"Default implementation of HAPI configuration and factory" 
011
012The Initial Developer of the Original Code is University Health Network. Copyright (C) 
0132001.  All Rights Reserved. 
014
015Contributor(s): ______________________________________. 
016
017Alternatively, the contents of this file may be used under the terms of the 
018GNU General Public License (the  "GPL"), in which case the provisions of the GPL are 
019applicable instead of those above.  If you wish to allow use of your version of this 
020file only under the terms of the GPL and not to allow others to use your version 
021of this file under the MPL, indicate your decision by deleting  the provisions above 
022and replace  them with the notice and other provisions required by the GPL License.  
023If you do not delete the provisions above, a recipient may use your version of 
024this file under either the MPL or the GPL. 
025 */
026package ca.uhn.hl7v2;
027
028import java.io.IOException;
029import java.util.concurrent.ExecutorService;
030
031import ca.uhn.hl7v2.app.Connection;
032import ca.uhn.hl7v2.app.ConnectionHub;
033import ca.uhn.hl7v2.app.ServerConfiguration;
034import ca.uhn.hl7v2.app.SimpleServer;
035import ca.uhn.hl7v2.app.TwoPortService;
036import ca.uhn.hl7v2.concurrent.DefaultExecutorService;
037import ca.uhn.hl7v2.conf.store.CodeStoreRegistry;
038import ca.uhn.hl7v2.conf.store.DefaultCodeStoreRegistry;
039import ca.uhn.hl7v2.conf.store.ProfileStore;
040import ca.uhn.hl7v2.conf.store.ProfileStoreFactory;
041import ca.uhn.hl7v2.llp.LowerLayerProtocol;
042import ca.uhn.hl7v2.llp.MinLowerLayerProtocol;
043import ca.uhn.hl7v2.parser.DefaultModelClassFactory;
044import ca.uhn.hl7v2.parser.DefaultXMLParser;
045import ca.uhn.hl7v2.parser.GenericParser;
046import ca.uhn.hl7v2.parser.ModelClassFactory;
047import ca.uhn.hl7v2.parser.ParserConfiguration;
048import ca.uhn.hl7v2.parser.PipeParser;
049import ca.uhn.hl7v2.parser.XMLParser;
050import ca.uhn.hl7v2.util.SocketFactory;
051import ca.uhn.hl7v2.util.StandardSocketFactory;
052import ca.uhn.hl7v2.validation.DefaultValidationExceptionHandler;
053import ca.uhn.hl7v2.validation.DefaultValidator;
054import ca.uhn.hl7v2.validation.ReportingValidationExceptionHandler;
055import ca.uhn.hl7v2.validation.ValidationContext;
056import ca.uhn.hl7v2.validation.ValidationExceptionHandlerFactory;
057import ca.uhn.hl7v2.validation.Validator;
058import ca.uhn.hl7v2.validation.builder.ValidationRuleBuilder;
059import ca.uhn.hl7v2.validation.impl.ValidationContextFactory;
060
061/**
062 * Default implementation for {@link HapiContext}.
063 * 
064 * With this class you can configure HAPI and obtain all major HAPI business
065 * objects that are initialized accordingly. All configuration objects already
066 * have reasonable defaults.
067 * <p>
068 * When using Spring Framework for initializing objects, you can use the factory
069 * methods like this:
070 * 
071 * <pre>
072 * &lt;!-- Define the context --&gt;
073 * &lt;bean id="hapiContext" class="ca.uhn.hl7v2.DefaultHapiContext"&gt;
074 *    ...
075 * &lt;/bean&gt;
076 * 
077 * &lt;!-- Obtain the default PipeParser instance --&gt;
078 * &lt;bean id="pipeParser" factory-bean="hapiContext" factory-method="getPipeParser"/&gt;
079 * ...
080 * </pre>
081 * 
082 */
083public class DefaultHapiContext implements HapiContext {
084
085    private ExecutorService executorService;
086    private ParserConfiguration parserConfiguration;
087    private ValidationContext validationContext;
088    private ValidationRuleBuilder validationRuleBuilder;
089    private ModelClassFactory modelClassFactory;
090    private ConnectionHub connectionHub;
091    private LowerLayerProtocol llp;
092    private SocketFactory socketFactory;
093    private ProfileStore profileStore;
094    private CodeStoreRegistry codeStoreRegistry;
095    private PipeParser pipeParser;
096    private XMLParser xmlParser;
097    private GenericParser genericParser;
098    private Validator<?> validator;
099    private ValidationExceptionHandlerFactory<?> validationExceptionHandlerFactory;
100        private ServerConfiguration serverConfiguration;
101
102    public DefaultHapiContext() {
103        this(new DefaultModelClassFactory());
104    }
105
106    public DefaultHapiContext(ExecutorService executorService) {
107        this();
108        setExecutorService(executorService);
109    }
110
111    public DefaultHapiContext(ModelClassFactory modelClassFactory) {
112        this(new ParserConfiguration(), ValidationContextFactory.defaultValidation(),
113                modelClassFactory);
114    }
115
116    public DefaultHapiContext(ValidationContext validationContext) {
117        this(new ParserConfiguration(), validationContext, new DefaultModelClassFactory());
118    }
119
120    public DefaultHapiContext(ValidationRuleBuilder builder) {
121        this(new ParserConfiguration(), builder, new DefaultModelClassFactory());
122    }
123
124    public DefaultHapiContext(ParserConfiguration parserConfiguration,
125            ValidationContext validationContext, ModelClassFactory modelClassFactory) {
126        VersionLogger.init();
127        setParserConfiguration(parserConfiguration);
128        setValidationContext(validationContext);
129        setModelClassFactory(modelClassFactory);
130        setLowerLayerProtocol(new MinLowerLayerProtocol(false));
131        setSocketFactory(new StandardSocketFactory());
132        setValidationExceptionHandlerFactory(new ReportingValidationExceptionHandler(true));
133        setProfileStore(ProfileStoreFactory.getProfileStore());
134        setCodeStoreRegistry(new DefaultCodeStoreRegistry());
135        setServerConfiguration(new ServerConfiguration());
136    }
137
138    public DefaultHapiContext(ParserConfiguration parserConfiguration,
139            ValidationRuleBuilder builder, ModelClassFactory modelClassFactory) {
140        VersionLogger.init();
141        setParserConfiguration(parserConfiguration);
142        setValidationRuleBuilder(builder);
143        setModelClassFactory(modelClassFactory);
144        setLowerLayerProtocol(new MinLowerLayerProtocol(false));
145        setSocketFactory(new StandardSocketFactory());
146        setProfileStore(ProfileStoreFactory.getProfileStore());
147        setCodeStoreRegistry(new DefaultCodeStoreRegistry());
148        setServerConfiguration(new ServerConfiguration());
149    }
150
151    public DefaultHapiContext(HapiContext context) {
152        this(context.getParserConfiguration(), context.getValidationContext(), context
153                .getModelClassFactory());
154    }
155
156    public void close() throws IOException {
157        getConnectionHub().discardAll();
158        if (DefaultExecutorService.isDefaultService(executorService)) {
159            executorService.shutdownNow();
160        }
161    }
162
163    public synchronized ExecutorService getExecutorService() {
164        if (executorService == null) {
165            executorService = DefaultExecutorService.getDefaultService();
166            Runtime.getRuntime().addShutdownHook(new Thread() {
167
168                @Override
169                public void run() {
170                    executorService.shutdownNow();
171                }
172
173            });
174        }
175        return executorService;
176    }
177
178    public synchronized void setExecutorService(ExecutorService executorService) {
179        this.executorService = executorService;
180    }
181
182    public ConnectionHub getConnectionHub() {
183        if (this.connectionHub == null) {
184            this.connectionHub = ConnectionHub.getNewInstance(this);
185        }
186        return this.connectionHub;
187    }
188
189    public ParserConfiguration getParserConfiguration() {
190        return parserConfiguration;
191    }
192
193    public void setParserConfiguration(ParserConfiguration configuration) {
194        if (configuration == null)
195            throw new IllegalArgumentException("ParserConfiguration must not be null");
196        this.parserConfiguration = configuration;
197    }
198
199    /**
200     * Returns the ValidationContext. If none has been explicitly set,
201     * {@link #getValidationRuleBuilder()} is called in order to to contruct a
202     * context. If this is also null, the ca.uhn.hl7v2.validation.context_class
203     * system property is evaluated, otherwise it returns the DefaultValidation
204     * context.
205     */
206    public ValidationContext getValidationContext() {
207        if (validationContext == null) {
208
209            if (getValidationRuleBuilder() != null) {
210                setValidationContext(ValidationContextFactory
211                        .fromBuilder(getValidationRuleBuilder()));
212            } else {
213                try {
214                    setValidationContext(ValidationContextFactory.getContext());
215                } catch (HL7Exception e) {
216                    setValidationContext(ValidationContextFactory.defaultValidation());
217                }
218            }
219        }
220        return validationContext;
221    }
222
223    public void setValidationContext(ValidationContext context) {
224        this.validationContext = context;
225    }
226
227    public void setValidationContext(String contextClassName) {
228        try {
229            this.validationContext = ValidationContextFactory.customValidation(contextClassName);
230        } catch (HL7Exception e) {
231            throw new IllegalArgumentException(e);
232        }
233    }
234
235    public ValidationRuleBuilder getValidationRuleBuilder() {
236        return validationRuleBuilder;
237    }
238
239    public void setValidationRuleBuilder(ValidationRuleBuilder validationRuleBuilder) {
240        this.validationRuleBuilder = validationRuleBuilder;
241        setValidationContext(ValidationContextFactory.fromBuilder(validationRuleBuilder));
242    }
243
244    public void setValidationRuleBuilder(String builderClassName) {
245        try {
246            setValidationRuleBuilder(ValidationContextFactory.customBuilder(builderClassName));
247        } catch (HL7Exception e) {
248            throw new IllegalArgumentException(e);
249        }
250    }
251
252    public ModelClassFactory getModelClassFactory() {
253        return modelClassFactory == null ? new DefaultModelClassFactory() : modelClassFactory;
254    }
255
256    public void setModelClassFactory(ModelClassFactory modelClassFactory) {
257        this.modelClassFactory = modelClassFactory;
258    }
259    
260    public ProfileStore getProfileStore() {
261        return profileStore;
262    }
263
264    public void setProfileStore(ProfileStore profileStore) {
265        this.profileStore = profileStore;
266    }
267
268    public CodeStoreRegistry getCodeStoreRegistry() {
269        return codeStoreRegistry;
270    }
271
272    public void setCodeStoreRegistry(CodeStoreRegistry codeStoreRegistry) {
273        this.codeStoreRegistry = codeStoreRegistry;
274    }
275    
276    public ca.uhn.hl7v2.conf.check.Validator getConformanceValidator() {
277        return new ca.uhn.hl7v2.conf.check.DefaultValidator(this);
278    }
279
280    public synchronized PipeParser getPipeParser() {
281        if (pipeParser == null) {
282            pipeParser = new PipeParser(this);
283        }
284        return pipeParser;
285    }
286
287    public synchronized XMLParser getXMLParser() {
288        if (xmlParser == null) {
289            xmlParser = new DefaultXMLParser(this);
290        }
291        return xmlParser;
292    }
293
294    public synchronized GenericParser getGenericParser() {
295        if (genericParser == null) {
296            genericParser = new GenericParser(this);
297        }
298        return genericParser;
299    }
300
301    @SuppressWarnings("unchecked")
302    public synchronized <R> Validator<R> getMessageValidator() {
303        if (validator == null) {
304            validator = new DefaultValidator<R>(this);
305        }
306        return (Validator<R>) validator;
307    }
308
309    @SuppressWarnings("unchecked")
310    public <R> ValidationExceptionHandlerFactory<R> getValidationExceptionHandlerFactory() {
311        if (validationExceptionHandlerFactory == null) {
312                validationExceptionHandlerFactory = new DefaultValidationExceptionHandler(this);
313        }
314        return (ValidationExceptionHandlerFactory<R>) validationExceptionHandlerFactory;
315    }
316
317    public <R> void setValidationExceptionHandlerFactory(
318            ValidationExceptionHandlerFactory<R> factory) {
319        if (factory == null) {
320                throw new NullPointerException("ValidationExceptionHandlerFactory can not be null");
321        }
322        this.validationExceptionHandlerFactory = factory;
323    }
324
325    public LowerLayerProtocol getLowerLayerProtocol() {
326        return llp;
327    }
328
329    public void setLowerLayerProtocol(LowerLayerProtocol llp) {
330        this.llp = llp;
331    }
332
333    public SocketFactory getSocketFactory() {
334        return socketFactory;
335    }
336
337    public void setSocketFactory(SocketFactory socketFactory) {
338        this.socketFactory = socketFactory;
339    }
340
341    public SimpleServer newServer(int port, boolean tls) {
342        return new SimpleServer(this, port, tls);
343    }
344
345    public TwoPortService newServer(int port1, int port2, boolean tls) {
346        return new TwoPortService(this, port1, port2, tls);
347    }
348
349        public Connection newClient(String host, int port, boolean tls) throws HL7Exception {
350                return getConnectionHub().attach(this, host, port, tls);
351        }
352
353        public Connection newClient(String host, int outboundPort, int inboundPort, boolean tls) throws HL7Exception {
354                return getConnectionHub().attach(this, host, outboundPort, inboundPort, tls);
355        }
356
357    public Connection newLazyClient(String host, int port, boolean tls) throws HL7Exception {
358        return getConnectionHub().attachLazily(this, host, port, tls);
359    }
360
361    public Connection newLazyClient(String host, int outboundPort, int inboundPort, boolean tls) throws HL7Exception {
362        return getConnectionHub().attachLazily(this, host, outboundPort, inboundPort, tls);
363    }
364
365        public ServerConfiguration getServerConfiguration() {
366                return this.serverConfiguration;
367        }
368
369        public void setServerConfiguration(ServerConfiguration theServerConfiguration) {
370                if (theServerConfiguration==null) {
371                        throw new NullPointerException("Server configuration can not be null");
372                }
373                serverConfiguration = theServerConfiguration;
374        }
375}