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