[[hl7terser-language]]
= HL7 Terser Language
:page-source: components/camel-hl7/src/main/docs/hl7terser-language.adoc

*Since Camel 2.11*

http://hl7api.sourceforge.net[HAPI] provides a
http://hl7api.sourceforge.net/base/apidocs/ca/uhn/hl7v2/util/Terser.html[Terser]
class that provides access to fields using a commonly used terse
location specification syntax. The Terser language allows to use this
syntax to extract values from messages and to use them as expressions
and predicates for filtering, content-based routing etc.

== HL7 Terser Language options

// language options: START
The HL7 Terser language supports 1 options, which are listed below.



[width="100%",cols="2,1m,1m,6",options="header"]
|===
| Name | Default | Java Type | Description
| trim | true | Boolean | Whether to trim the value to remove leading and trailing whitespaces and line breaks
|===
// language options: END

// spring-boot-auto-configure options: START
== Spring Boot Auto-Configuration

When using Spring Boot make sure to use the following Maven dependency to have support for auto configuration:

[source,xml]
----
<dependency>
  <groupId>org.apache.camel.springboot</groupId>
  <artifactId>camel-hl7-starter</artifactId>
  <version>x.x.x</version>
  <!-- use the same version as your Camel core version -->
</dependency>
----


The component supports 2 options, which are listed below.



[width="100%",cols="2,5,^1,2",options="header"]
|===
| Name | Description | Default | Type
| *camel.language.hl7terser.enabled* | Whether to enable auto configuration of the hl7terser language. This is enabled by default. |  | Boolean
| *camel.language.hl7terser.trim* | Whether to trim the value to remove leading and trailing whitespaces and line breaks | true | Boolean
|===
// spring-boot-auto-configure options: END

== Samples:

[source,java]
----
   import static org.apache.camel.component.hl7.HL7.hl7terser;

   // extract patient ID from field QRD-8 in the QRY_A19 message above and put into message header
   from("direct:test1")
      .setHeader("PATIENT_ID", hl7terser("QRD-8(0)-1"))
      .to("mock:test1");

   // continue processing if extracted field equals a message header
   from("direct:test2")
      .filter(hl7terser("QRD-8(0)-1").isEqualTo(header("PATIENT_ID"))
      .to("mock:test2");
----

== HL7 Validation predicate

Often it is preferable to first parse a HL7v2 message and in a separate
step validate it against a HAPI
http://hl7api.sourceforge.net/base/apidocs/ca/uhn/hl7v2/validation/ValidationContext.html[ValidationContext].

Sample:

[source,java]
----
import static org.apache.camel.component.hl7.HL7.messageConformsTo;
import ca.uhn.hl7v2.validation.impl.DefaultValidation;

   // Use standard or define your own validation rules
   ValidationContext defaultContext = new DefaultValidation();

   // Throws PredicateValidationException if message does not validate
   from("direct:test1")
      .validate(messageConformsTo(defaultContext))
      .to("mock:test1");
----

== HL7 Validation predicate using the HapiContext

The HAPI Context is always configured with a
http://hl7api.sourceforge.net/base/apidocs/ca/uhn/hl7v2/validation/ValidationContext.html[ValidationContext]
(or a
http://hl7api.sourceforge.net/base/apidocs/ca/uhn/hl7v2/validation/builder/ValidationRuleBuilder.html[ValidationRuleBuilder]),
so you can access the validation rules indirectly. Furthermore, when
unmarshalling the HL7DataFormat forwards the configured HAPI context in
the `CamelHL7Context` header, and the validation rules of this context
can be easily reused:

[source,java]
----
import static org.apache.camel.component.hl7.HL7.messageConformsTo;
import static org.apache.camel.component.hl7.HL7.messageConforms

  HapiContext hapiContext = new DefaultHapiContext();
  hapiContext.getParserConfiguration().setValidating(false); // don't validate during parsing

  // customize HapiContext some more ... e.g. enforce that PID-8 in ADT_A01 messages of version 2.4 is not empty
  ValidationRuleBuilder builder = new ValidationRuleBuilder() {
      @Override
      protected void configure() {
         forVersion(Version.V24)
              .message("ADT", "A01")
              .terser("PID-8", not(empty()));
         }
      };
  hapiContext.setValidationRuleBuilder(builder);

  HL7DataFormat hl7 = new HL7DataFormat();
  hl7.setHapiContext(hapiContext);

  from("direct:test1")
     .unmarshal(hl7)                // uses the GenericParser returned from the HapiContext
     .validate(messageConforms())   // uses the validation rules returned from the HapiContext
                                    // equivalent with .validate(messageConformsTo(hapiContext))
     // route continues from here
----

== HL7 Acknowledgement expression

A common task in HL7v2 processing is to generate an acknowledgement
message as response to an incoming HL7v2 message, e.g. based on a
validation result. The `ack` expression lets us accomplish this very
elegantly:

[source,java]
----
import static org.apache.camel.component.hl7.HL7.messageConformsTo;
import static org.apache.camel.component.hl7.HL7.ack;
import ca.uhn.hl7v2.validation.impl.DefaultValidation;

  // Use standard or define your own validation rules
   ValidationContext defaultContext = new DefaultValidation();

   from("direct:test1")
      .onException(Exception.class)
         .handled(true)
         .transform(ack()) // auto-generates negative ack because of exception in Exchange
         .end()
      .validate(messageConformsTo(defaultContext))
      // do something meaningful here

      // acknowledgement
      .transform(ack())
----
