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() {
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(() -> executorService.shutdownNow()));
155        }
156        return executorService;
157    }
158
159    public synchronized void setExecutorService(ExecutorService executorService) {
160        this.executorService = executorService;
161    }
162
163    public ConnectionHub getConnectionHub() {
164        if (this.connectionHub == null) {
165            this.connectionHub = ConnectionHub.getNewInstance(this);
166        }
167        return this.connectionHub;
168    }
169
170    public ParserConfiguration getParserConfiguration() {
171        return parserConfiguration;
172    }
173
174    public void setParserConfiguration(ParserConfiguration configuration) {
175        if (configuration == null)
176            throw new IllegalArgumentException("ParserConfiguration must not be null");
177        this.parserConfiguration = configuration;
178    }
179
180    /**
181     * Returns the ValidationContext. If none has been explicitly set,
182     * {@link #getValidationRuleBuilder()} is called in order to to contruct a
183     * context. If this is also null, the ca.uhn.hl7v2.validation.context_class
184     * system property is evaluated, otherwise it returns the DefaultValidation
185     * context.
186     */
187    public ValidationContext getValidationContext() {
188        if (validationContext == null) {
189
190            if (getValidationRuleBuilder() != null) {
191                setValidationContext(ValidationContextFactory
192                        .fromBuilder(getValidationRuleBuilder()));
193            } else {
194                try {
195                    setValidationContext(ValidationContextFactory.getContext());
196                } catch (HL7Exception e) {
197                    setValidationContext(ValidationContextFactory.defaultValidation());
198                }
199            }
200        }
201        return validationContext;
202    }
203
204    public void setValidationContext(ValidationContext context) {
205        this.validationContext = context;
206    }
207
208    public void setValidationContext(String contextClassName) {
209        try {
210            this.validationContext = ValidationContextFactory.customValidation(contextClassName);
211        } catch (HL7Exception e) {
212            throw new IllegalArgumentException(e);
213        }
214    }
215
216    public ValidationRuleBuilder getValidationRuleBuilder() {
217        return validationRuleBuilder;
218    }
219
220    public void setValidationRuleBuilder(ValidationRuleBuilder validationRuleBuilder) {
221        this.validationRuleBuilder = validationRuleBuilder;
222        setValidationContext(ValidationContextFactory.fromBuilder(validationRuleBuilder));
223    }
224
225    public void setValidationRuleBuilder(String builderClassName) {
226        try {
227            setValidationRuleBuilder(ValidationContextFactory.customBuilder(builderClassName));
228        } catch (HL7Exception e) {
229            throw new IllegalArgumentException(e);
230        }
231    }
232
233    public ModelClassFactory getModelClassFactory() {
234        return modelClassFactory == null ? new DefaultModelClassFactory() : modelClassFactory;
235    }
236
237    public void setModelClassFactory(ModelClassFactory modelClassFactory) {
238        this.modelClassFactory = modelClassFactory;
239    }
240    
241    public ProfileStore getProfileStore() {
242        return profileStore;
243    }
244
245    public void setProfileStore(ProfileStore profileStore) {
246        this.profileStore = profileStore;
247    }
248
249    public CodeStoreRegistry getCodeStoreRegistry() {
250        return codeStoreRegistry;
251    }
252
253    public void setCodeStoreRegistry(CodeStoreRegistry codeStoreRegistry) {
254        this.codeStoreRegistry = codeStoreRegistry;
255    }
256    
257    public ca.uhn.hl7v2.conf.check.Validator getConformanceValidator() {
258        return new ca.uhn.hl7v2.conf.check.DefaultValidator(this);
259    }
260
261    public synchronized PipeParser getPipeParser() {
262        if (pipeParser == null) {
263            pipeParser = new PipeParser(this);
264        }
265        return pipeParser;
266    }
267
268    public synchronized XMLParser getXMLParser() {
269        if (xmlParser == null) {
270            xmlParser = new DefaultXMLParser(this);
271        }
272        return xmlParser;
273    }
274
275    public synchronized GenericParser getGenericParser() {
276        if (genericParser == null) {
277            genericParser = new GenericParser(this);
278        }
279        return genericParser;
280    }
281
282    @SuppressWarnings("unchecked")
283    public synchronized <R> Validator<R> getMessageValidator() {
284        if (validator == null) {
285            validator = new DefaultValidator<R>(this);
286        }
287        return (Validator<R>) validator;
288    }
289
290    @SuppressWarnings("unchecked")
291    public <R> ValidationExceptionHandlerFactory<R> getValidationExceptionHandlerFactory() {
292        if (validationExceptionHandlerFactory == null) {
293                validationExceptionHandlerFactory = new DefaultValidationExceptionHandler(this);
294        }
295        return (ValidationExceptionHandlerFactory<R>) validationExceptionHandlerFactory;
296    }
297
298    public <R> void setValidationExceptionHandlerFactory(
299            ValidationExceptionHandlerFactory<R> factory) {
300        if (factory == null) {
301                throw new NullPointerException("ValidationExceptionHandlerFactory can not be null");
302        }
303        this.validationExceptionHandlerFactory = factory;
304    }
305
306    public LowerLayerProtocol getLowerLayerProtocol() {
307        return llp;
308    }
309
310    public void setLowerLayerProtocol(LowerLayerProtocol llp) {
311        this.llp = llp;
312    }
313
314    public SocketFactory getSocketFactory() {
315        return socketFactory;
316    }
317
318    public void setSocketFactory(SocketFactory socketFactory) {
319        this.socketFactory = socketFactory;
320    }
321
322    public SimpleServer newServer(int port, boolean tls) {
323        return new SimpleServer(this, port, tls);
324    }
325    
326    public SimpleServer newServer(int port, boolean tls, boolean acceptAll) {
327        return new SimpleServer(this, port, tls, acceptAll);
328    }
329
330    public TwoPortService newServer(int port1, int port2, boolean tls) {
331        return new TwoPortService(this, port1, port2, tls);
332    }
333
334        public Connection newClient(String host, int port, boolean tls) throws HL7Exception {
335                return getConnectionHub().attach(this, host, port, tls);
336        }
337
338        public Connection newClient(String host, int outboundPort, int inboundPort, boolean tls) throws HL7Exception {
339                return getConnectionHub().attach(this, host, outboundPort, inboundPort, tls);
340        }
341
342    public Connection newLazyClient(String host, int port, boolean tls) throws HL7Exception {
343        return getConnectionHub().attachLazily(this, host, port, tls);
344    }
345
346    public Connection newLazyClient(String host, int outboundPort, int inboundPort, boolean tls) throws HL7Exception {
347        return getConnectionHub().attachLazily(this, host, outboundPort, inboundPort, tls);
348    }
349
350        public ServerConfiguration getServerConfiguration() {
351                if (this.serverConfiguration == null) {
352                        serverConfiguration = new ServerConfiguration();
353                }
354                return this.serverConfiguration;
355        }
356
357        public void setServerConfiguration(ServerConfiguration theServerConfiguration) {
358                if (theServerConfiguration==null) {
359                        throw new NullPointerException("Server configuration can not be null");
360                }
361                serverConfiguration = theServerConfiguration;
362        }
363
364    public Message newMessage(String eventType, String triggerEvent, Version version) throws HL7Exception {
365        try {
366            String structure = getModelClassFactory().getMessageStructureForEvent(eventType + "_" + triggerEvent, version);
367            Class<? extends Message> messageClass = getModelClassFactory().getMessageClass(structure, version.getVersion(), false);
368            Message msg = newMessage(messageClass);
369            ((AbstractMessage) msg).initQuickstart(eventType, triggerEvent, "P");
370            return msg;
371        } catch (IOException e) {
372            throw new HL7Exception(e);
373        }
374    }
375
376    public <T extends Message> T newMessage(Class<T> clazz) throws HL7Exception {
377        T msg = ReflectionUtil.instantiateMessage(clazz, getModelClassFactory());
378        msg.setParser(getGenericParser());
379        return msg;
380    }
381
382}