View Javadoc
1   /*
2    * Copyright 2011 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.openehealth.ipf.platform.camel.ihe.hl7v2ws;
17  
18  import java.io.IOException;
19  
20  import ca.uhn.hl7v2.AcknowledgmentCode;
21  import ca.uhn.hl7v2.HL7Exception;
22  import ca.uhn.hl7v2.model.Message;
23  import org.apache.camel.Exchange;
24  import org.openehealth.ipf.commons.ihe.hl7v2.Hl7v2TransactionConfiguration;
25  import org.openehealth.ipf.commons.ihe.hl7v2.NakFactory;
26  import org.openehealth.ipf.modules.hl7.message.MessageUtils;
27  import org.openehealth.ipf.platform.camel.core.util.Exchanges;
28  import org.openehealth.ipf.platform.camel.ihe.hl7v2.Hl7v2ConfigurationHolder;
29  import org.openehealth.ipf.platform.camel.ihe.hl7v2.Hl7v2MarshalUtils;
30  import org.openehealth.ipf.platform.camel.ihe.ws.AbstractWebService;
31  import org.slf4j.Logger;
32  import org.slf4j.LoggerFactory;
33  
34  import static org.apache.commons.lang3.StringUtils.trimToEmpty;
35  import static org.openehealth.ipf.commons.ihe.hl7v2ws.Utils.render;
36  import static org.openehealth.ipf.platform.camel.core.util.Exchanges.resultMessage;
37  
38  /**
39   * Generic implementation of an HL7v2-based Web Service.
40   * 
41   * @author Dmytro Rud
42   * @author Mitko Kolev
43   * @author Stefan Ivanov
44   */
45  public abstract class AbstractHl7v2WebService extends AbstractWebService {
46      private static final Logger LOG = LoggerFactory.getLogger(AbstractHl7v2WebService.class);
47  
48      private Hl7v2TransactionConfiguration config = null;
49      private NakFactory nakFactory = null;
50  
51  
52      /**
53       * Configures HL7v2-related parameters of this Web Service.
54       * This method is supposed to be called only once, directly after
55       * an instance of this class has been created.  In other words,
56       * this is a kind of "post-constructor".
57       *
58       * @param configurationHolder
59       *      source of HL7v2-related configuration parameters.
60       */
61      void setHl7v2Configuration(Hl7v2ConfigurationHolder configurationHolder) {
62          if ((this.config != null) || (this.nakFactory != null)) {
63              throw new IllegalStateException("multiple calls to this method are not allowed");
64          }
65  
66          this.config = configurationHolder.getHl7v2TransactionConfiguration();
67          this.nakFactory = configurationHolder.getNakFactory();
68      }
69  
70  
71      protected String doProcess(String request) {
72          // parse request
73          Message msg;
74          try {
75              msg = config.getParser().parse(trimToEmpty(request).replaceAll("\n", "\r\n"));
76              config.checkRequestAcceptance(msg);
77          } catch (HL7Exception e) {
78              LOG.error(formatErrMsg("Request not acceptable"), e);
79              return render(nakFactory.createDefaultNak(e));
80          }
81  
82          Message originalRequest = MessageUtils.copy(msg);
83  
84          // play the route, handle its outcomes and check response acceptance
85          try {
86              Exchange exchange = super.process(msg);
87              Exception exception = Exchanges.extractException(exchange);
88              if (exception != null) {
89                  throw exception;
90              }
91  
92              // check response existence and acceptance
93              if ((msg = Hl7v2MarshalUtils.extractHapiMessage(
94                      resultMessage(exchange),
95                      exchange.getProperty(Exchange.CHARSET_NAME, String.class),
96                      config.getParser())) != null) {
97                  config.checkResponseAcceptance(msg);
98                  return render(msg);
99              } else {
100                 throw new Exception("Could not extract HAPI message object from exchange");
101             }
102 
103         } catch (Exception e) {
104             LOG.error(formatErrMsg("Message processing failed, response missing or not acceptable"), e);
105             try {
106                 return render(nakFactory.createNak(originalRequest, e));
107             } catch (HL7Exception e1) {
108                 return render(MessageUtils.defaultNak(e1, AcknowledgmentCode.AE, msg.getVersion()));
109             } catch (IOException e2) {
110                 return render(MessageUtils.defaultNak(new HL7Exception(e2), AcknowledgmentCode.AE, msg.getVersion()));
111             }
112         }
113     }
114 
115 
116     /**
117      * Creates a message from the input <code>text</code >with prefix the sending
118      * application in the transaction configuration.
119      * 
120      * @param text
121      *            input text used for logging
122      * @return a String with prefix the sending application
123      */
124     protected String formatErrMsg(String text) {
125         return config.getSendingApplication() + ": " + text;
126     }
127     
128 }