[[hl7terser-language]]
= HL7 Terser Language
//THIS FILE IS COPIED: EDIT THE SOURCE FILE:
:page-source: components/camel-hl7/src/main/docs/hl7terser-language.adoc
:docTitle: HL7 Terser
:artifactId: camel-hl7
:description: Get the value of an HL7 message field specified by terse location specification syntax.
:since: 2.11
:supportLevel: Stable
include::{cq-version}@camel-quarkus:ROOT:partial$reference/languages/hl7terser.adoc[opts=optional]

*Since Camel {since}*

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


== 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())
----

include::{page-component-version}@camel-spring-boot::page$hl7-starter.adoc[]
