View Javadoc
1   /*
2    * Copyright 2014 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  
17  package org.openehealth.ipf.platform.camel.hl7;
18  
19  import ca.uhn.hl7v2.AcknowledgmentCode;
20  import ca.uhn.hl7v2.ErrorCode;
21  import ca.uhn.hl7v2.HL7Exception;
22  import ca.uhn.hl7v2.HapiContext;
23  import ca.uhn.hl7v2.model.Message;
24  import ca.uhn.hl7v2.parser.GenericParser;
25  import ca.uhn.hl7v2.parser.Parser;
26  import org.apache.camel.Exchange;
27  import org.apache.camel.Expression;
28  import org.apache.camel.Predicate;
29  import org.apache.camel.Processor;
30  import org.apache.camel.builder.ValueBuilder;
31  import org.apache.camel.component.hl7.HL7;
32  import org.openehealth.ipf.modules.hl7.validation.Validator;
33  import org.openehealth.ipf.platform.camel.core.adapter.ValidatorAdapter;
34  
35  import static java.util.Objects.requireNonNull;
36  
37  /**
38   * Factory class for commonly used HL7-related expressions, predicates and
39   * processors.
40   */
41  public final class HL7v2 {
42  
43      private static final Parser FALLBACK = new GenericParser();
44  
45      private HL7v2() {
46      }
47  
48      /**
49       * @return Expression that extracts data from HL7 messages based on a HAPI Terser expression
50       */
51      public static ValueBuilder get(String terserSpec) {
52          return HL7.terser(terserSpec);
53      }
54  
55      /**
56       * @return Expression that sets data in a HL7 messages based on a HAPI Terser expression
57       */
58      public static Expression set(String terserSpec, Expression value) {
59          return new TerserSetExpression(terserSpec, value);
60      }
61  
62      /**
63       * @return Expression that creates an acknowledgement to a message
64       */
65      public static ValueBuilder ack() {
66          return new ValueBuilder(HL7.ack());
67      }
68  
69      /**
70       * @return Expression that creates an acknowledgement to a message using a given code
71       */
72      public static ValueBuilder ack(AcknowledgmentCode acknowledgmentCode) {
73          return ack(acknowledgmentCode, null, ErrorCode.APPLICATION_INTERNAL_ERROR);
74      }
75  
76      /**
77       * @return Expression that creates an acknowledgement to a message using a given code, message and error details
78       */
79      public static ValueBuilder ack(AcknowledgmentCode acknowledgmentCode, String message, ErrorCode errorCode) {
80          return new ValueBuilder(HL7.ack(acknowledgmentCode, message, errorCode));
81      }
82  
83      /**
84       * Returns a response to the message in the body, using the provided event type and trigger event
85       *
86       * @param eventType    event type, e.g. ADT
87       * @param triggerEvent trigger event, e.g. A01
88       * @return expression that generates the response for the body message
89       */
90      public static ValueBuilder response(String eventType, String triggerEvent) {
91          return new ValueBuilder(new ResponseExpression(eventType, triggerEvent));
92      }
93  
94      /**
95       * Returns a constant response message. Useful for mocks and tests only
96       *
97       * @param message constant message
98       * @return expression that generates a static message using the same HapiContext as the message
99       * in the body
100      */
101     public static ValueBuilder staticResponse(String message) {
102         return new ValueBuilder(new StaticResponseExpression(message));
103     }
104 
105     /**
106      * Returns a validating Camel processor for a message. The actual validation rules
107      * to be used is defined in the message's HapiContext. Unlike {@link #messageConforms()}, this processor
108      * throws an exception with details about the validation result instead of just returning true or false.
109      *
110      * @return a validating Camel processor for a message
111      */
112     public static Processor validatingProcessor() {
113         return validatingProcessor(null);
114     }
115 
116     /**
117      * Returns a validating Camel processor for a message. The actual validation rules
118      * to be used is defined in the message's HapiContext. Unlike {@link #messageConforms()}, this processor
119      * throws an exception with details about the validation result instead of just returning true or false.
120      *
121      * @param context HAPI context
122      *
123      * @return a validating Camel processor for a message
124      */
125     public static Processor validatingProcessor(final HapiContext context) {
126         return exchange -> {
127             if (! ValidatorAdapter.validationEnabled(exchange)) {
128                 return;
129             }
130 
131             Message msg = bodyMessage(exchange);
132             Validator.validate(msg, context);
133         };
134     }
135 
136     /**
137      * @return Predicate that returns true if the message validates successfully
138      */
139     public static Predicate messageConforms() {
140         return HL7.messageConforms();
141     }
142 
143     /**
144      * @return Predicate that returns true if the message validates successfully using a dedicated HapiContext
145      */
146     public static Predicate messageConformsTo(HapiContext hapiContext) {
147         return HL7.messageConformsTo(hapiContext);
148     }
149 
150     /**
151      * @return Predicate that returns true if the message validates successfully using an expression that returns
152      * a {@link ca.uhn.hl7v2.validation.ValidationContext}.
153      */
154     public static Predicate messageConformsTo(Expression expression) {
155         return HL7.messageConformsTo(expression);
156     }
157 
158     /**
159      * Returns the HAPI Message from the message body. If the body is a string, it is parsed on the fly
160      *
161      * @param exchange exchange
162      * @return HAPI message
163      * @throws ca.uhn.hl7v2.HL7Exception
164      */
165     public static Message bodyMessage(Exchange exchange) throws HL7Exception {
166         Object body = exchange.getIn().getBody();
167         Message message;
168 
169         if (body instanceof Message) {
170             message = (Message) body;
171         } else if (body instanceof String) {
172             HapiContext context = exchange.getIn().getHeader("CamelHL7Context", HapiContext.class);
173             Parser parser = context != null ? context.getGenericParser() : FALLBACK;
174             message = parser.parse((String) body);
175         } else {
176             // try type conversion
177             message = exchange.getIn().getBody(Message.class);
178         }
179         requireNonNull(message, "Exchange does not contain or can be converted to the required 'ca.uhn.hl7v2.model.Message' type");
180         return message;
181     }
182 
183 
184 }