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.util.concurrent.ExecutorService;
029
030import ca.uhn.hl7v2.app.Connection;
031import ca.uhn.hl7v2.app.ConnectionHub;
032import ca.uhn.hl7v2.app.SimpleServer;
033import ca.uhn.hl7v2.app.TwoPortService;
034import ca.uhn.hl7v2.concurrent.DefaultExecutorService;
035import ca.uhn.hl7v2.conf.store.CodeStoreRegistry;
036import ca.uhn.hl7v2.conf.store.DefaultCodeStoreRegistry;
037import ca.uhn.hl7v2.conf.store.ProfileStore;
038import ca.uhn.hl7v2.conf.store.ProfileStoreFactory;
039import ca.uhn.hl7v2.llp.LowerLayerProtocol;
040import ca.uhn.hl7v2.llp.MinLowerLayerProtocol;
041import ca.uhn.hl7v2.parser.DefaultModelClassFactory;
042import ca.uhn.hl7v2.parser.DefaultXMLParser;
043import ca.uhn.hl7v2.parser.GenericParser;
044import ca.uhn.hl7v2.parser.ModelClassFactory;
045import ca.uhn.hl7v2.parser.ParserConfiguration;
046import ca.uhn.hl7v2.parser.PipeParser;
047import ca.uhn.hl7v2.parser.XMLParser;
048import ca.uhn.hl7v2.util.SocketFactory;
049import ca.uhn.hl7v2.util.StandardSocketFactory;
050import ca.uhn.hl7v2.validation.DefaultValidationExceptionHandler;
051import ca.uhn.hl7v2.validation.DefaultValidator;
052import ca.uhn.hl7v2.validation.ReportingValidationExceptionHandler;
053import ca.uhn.hl7v2.validation.ValidationContext;
054import ca.uhn.hl7v2.validation.ValidationExceptionHandlerFactory;
055import ca.uhn.hl7v2.validation.Validator;
056import ca.uhn.hl7v2.validation.builder.ValidationRuleBuilder;
057import ca.uhn.hl7v2.validation.impl.ValidationContextFactory;
058
059/**
060 * Default implementation for {@link HapiContext}.
061 * 
062 * With this class you can configure HAPI and obtain all major HAPI business
063 * objects that are initialized accordingly. All configuration objects already
064 * have reasonable defaults.
065 * <p>
066 * When using Spring Framework for initializing objects, you can use the factory
067 * methods like this:
068 * 
069 * <pre>
070 * &lt;!-- Define the context --&gt;
071 * &lt;bean id="hapiContext" class="ca.uhn.hl7v2.DefaultHapiContext"&gt;
072 *    ...
073 * &lt;/bean&gt;
074 * 
075 * &lt;!-- Obtain the default PipeParser instance --&gt;
076 * &lt;bean id="pipeParser" factory-bean="hapiContext" factory-method="getPipeParser"/&gt;
077 * ...
078 * </pre>
079 * 
080 */
081public class DefaultHapiContext implements HapiContext {
082
083    private ExecutorService executorService;
084    private ParserConfiguration parserConfiguration;
085    private ValidationContext validationContext;
086    private ValidationRuleBuilder validationRuleBuilder;
087    private ModelClassFactory modelClassFactory;
088    private ConnectionHub connectionHub;
089    private LowerLayerProtocol llp;
090    private SocketFactory socketFactory;
091    private ProfileStore profileStore;
092    private CodeStoreRegistry codeStoreRegistry;
093    private PipeParser pipeParser;
094    private XMLParser xmlParser;
095    private GenericParser genericParser;
096    private Validator<?> validator;
097    private ValidationExceptionHandlerFactory<?> validationExceptionHandlerFactory;
098
099    public DefaultHapiContext() {
100        this(new DefaultModelClassFactory());
101    }
102
103    public DefaultHapiContext(ExecutorService executorService) {
104        this();
105        setExecutorService(executorService);
106    }
107
108    public DefaultHapiContext(ModelClassFactory modelClassFactory) {
109        this(new ParserConfiguration(), ValidationContextFactory.defaultValidation(),
110                modelClassFactory);
111    }
112
113    public DefaultHapiContext(ValidationContext validationContext) {
114        this(new ParserConfiguration(), validationContext, new DefaultModelClassFactory());
115    }
116
117    public DefaultHapiContext(ValidationRuleBuilder builder) {
118        this(new ParserConfiguration(), builder, new DefaultModelClassFactory());
119    }
120
121    public DefaultHapiContext(ParserConfiguration parserConfiguration,
122            ValidationContext validationContext, ModelClassFactory modelClassFactory) {
123        VersionLogger.init();
124        setParserConfiguration(parserConfiguration);
125        setValidationContext(validationContext);
126        setModelClassFactory(modelClassFactory);
127        setLowerLayerProtocol(new MinLowerLayerProtocol());
128        setSocketFactory(new StandardSocketFactory());
129        setValidationExceptionHandlerFactory(new ReportingValidationExceptionHandler(true));
130        setProfileStore(ProfileStoreFactory.getProfileStore());
131        setCodeStoreRegistry(new DefaultCodeStoreRegistry());
132    }
133
134    public DefaultHapiContext(ParserConfiguration parserConfiguration,
135            ValidationRuleBuilder builder, ModelClassFactory modelClassFactory) {
136        VersionLogger.init();
137        setParserConfiguration(parserConfiguration);
138        setValidationRuleBuilder(builder);
139        setModelClassFactory(modelClassFactory);
140        setLowerLayerProtocol(new MinLowerLayerProtocol());
141        setSocketFactory(new StandardSocketFactory());
142        setProfileStore(ProfileStoreFactory.getProfileStore());
143        setCodeStoreRegistry(new DefaultCodeStoreRegistry());
144    }
145
146    public DefaultHapiContext(HapiContext context) {
147        this(context.getParserConfiguration(), context.getValidationContext(), context
148                .getModelClassFactory());
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}