Previous section   Next section

Additional Steps

This chapter discusses the additional steps needed to add HL7 processing to a production. It includes the following topics:
Be sure to perform these tasks in the same namespace that contains your production. When you create rule sets, transformations, and search tables, do not use reserved package names; see “Reserved Package Names” in Developing Ensemble Productions.
Also see “Overriding the Validation Logic” in Ensemble Virtual Documents.

Defining Routing Rule Sets for HL7

When creating a routing rule set for an HL7 interface, your goal is to tell Ensemble what to do with the source message based on the segments found within it. Sometimes it matters which segments are found; sometimes it matters which values are found within those segments.
In ordinary rule sets, each rule returns a value to the business process that invoked the rule set. In a routing rule set, a rule usually directs an HL7 message to a destination, possibly transforming the HL7 message before sending it.
For information on using the rule editor, see “Creating and Editing Rules Sets” in Developing Business Rules.
  1. When you create a new HL7 routing process using the Business Rule Wizard, Ensemble creates a new, empty routing rule set to accompany the new routing process. Its information tables contain the following values:
    • Package Name — The package that contains the production class. For example, if you used the wizard to add a routing process to a production called
      TestRule.MyTest
      , the associated routing rule has a Package Name of:
      TestRule
    • Rule Name — The simple Routing Rule Name that you chose in the wizard, such as:
      MyRule
      The combination of the Package Name and Rule Name identify the rule uniquely within the Ensemble namespace. The full name for any rule definition is the Package Name and Rule Name connected by a dot (.) as in:
      TestRule.MyRule
      This full name, rather than the Rule Name, is the correct value to use in the BusinessRuleName field when configuring an HL7 routing process. The Business Process Wizard sets this up automatically.
    • Routing Engine Class — The default Router Class from the wizard; do not change it:
      EnsLib.HL7.MsgRouter.RoutingEngine
  2. You may also enter additional fields for your own rule reporting purposes:
    • Report Group — Value to be used to group rules for reporting
    • Report Name — Display value for the rule report group
    • Short Description — Optional short description of this Rule Definition.
  3. See “Using the Rule Constraint Editor” in Developing Business Rules for details on entering the constraints of a routing rule.
  4. Once you have created a new rule, you may add Conditions and Actions to it. For details, see chapter “Creating and Editing Rule Sets” in Developing Business Rules. As you add Conditions to each rule, remember these tips:
    • Conditions evaluate AND operators first, then OR.
    • Conditions can refer to properties of the HL7 message object. Within Conditions, the special variable
      Document
      represents the HL7 message object, as in the following examples. For HL7 batch documents, you can use the special variable
      Document.Parent
      to represent the parent message object.
      Document.Name
      Document.Parent.DocType
      Document.{PIDgrp.PV1grp.PV1:18}
      Document.{PIDgrp.PID:PatientName.familylastname}
      Document.{ORCgrp(1).OBRuniongrp.OBRunion.OBR:4.3}
      
      Note:
      For compatibility with past releases, the special variables
      HL7
      and
      HL7.Parent
      are supported as alternatives to
      Document
      and
      Document.Parent
      .
      A dot separates the
      Document
      variable from the property name. This name may be:
      • Any of the class properties: DocType, TypeCategory, BuildMapStatus, or Name.
      • A virtual property, referenced using any of the following conventions:
        Details are available in the “Syntax Guide” section of Ensemble Virtual Documents. However, you do not need to enter properties by typing; you can browse for properties as described in “Creating and Editing Rule Sets” in Developing Business Rules.
  5. Complete the instructions in the next several topics for creating any Source, Target, or Transform items that your routing rule set needs. The items might be:
    As you create items, return to the Message Routing Rule Editor to add them to the appropriate fields of the rule definition.
  6. Return to the diagram on the Production Configuration page. Select the corresponding HL7 routing process. In the BusinessRuleName field, enter the full name of the new routing rule set.

Defining DTL Data Transformations for HL7

Each interface may require some number of data transformations.
Important:
Do not manually change HL7 escape sequences in the data transformation; Ensemble handles these automatically.
You use the Data Transformation Builder page to create data transformations (navigate to Ensemble > Build > Data Transformations). For general information on using this page, see Developing DTL Transformations.
The following figure shows this page, displaying MsgRouter.ADTLastNameTransform from the ENSDEMO namespace:
images/ehl72_dtl_editor_sample.png
Note the following tips:
  • Have Developing DTL Transformations handy. This book explains how to add each kind of DTL action.
  • Be clear about the value you want for the create option of the data transformation class. create may have one of the following values:
    • new
      — Create a new object of the target type, before executing the elements within the data transformation. Any source segments that you do not explicitly assign to the target object are ignored. This is the default.
    • copy
      — Create a copy of the source object to use as the target object, before executing the elements within the transform.
    • existing
      — Use an existing object, provided by the caller of the data transformation, as the target object.
    To create a target object that is an exact copy of the source, do not use an action like this:
    <assign property='target' value='source' />
    
    
    Instead use the
    create='copy'
    attribute in the data transformation class.
  • Ensure that the data transformation class identifies the correct schema category for:
    • The sourceDocType attribute
    • The targetDocType attribute
    The schema category may be the same or different for the source and target objects.
  • Ensure that the Transform tab specifies the scripting language that you want to use for all the expressions and code actions within that data transformation. ObjectScript is the default language.
  • Use assign actions to assign HL7 segments from the source message to the target message by drag and drop operations.
    Possibly, you will want to use a combination of techniques. You can first generate a line of code by dragging, then fine-tune the code by editing the text.
  • The data transformation can refer to properties of the HL7 message object, including:
    • The class properties DocType, TypeCategory, BuildMapStatus, and Name.
    • Virtual document properties as described in “Curly Bracket {} Syntax” in the “Syntax Guide” section of Ensemble Virtual Documents.
    Within the data transformation class code, the special variables
    source
    and
    target
    represent the respective HL7 message objects, as in the following examples:
    source.Name
    target.DocType
    source.{PIDgrp.PV1grp.PV1:18}
    target.{PIDgrp.PID:PatientName.familylastname}
    source.{ORCgrp(1).OBRuniongrp.OBRunion.OBR:4.3}
  • Assign any literal string values, or make conditional assignments. See the chapter “Syntax Rules” in Developing DTL Transformations.
    Note:
    A string literal cannot include XML reserved characters. It also cannot include separator characters used by HL7.
    Also, the HL7 null mapping code
    ""
    requires special handling. The following example tests for the null mapping code in the source message and replaces it with a blank string in the target message:
    <if condition='source.{PV1:7().4}=""""""'>
    <true>
    <assign property='target.{PV1:7().4}' value='""' />
    </true>
    </if>
    
    For details, see “Null Mapping Codes” in the chapter “Syntax for a Routing Production.”
  • For simple calculations, the DTL data transformation can:
    • Invoke Ensemble utility functions
    • Use ObjectScript or Caché Basic expressions in the DTL code action
    • Invoke the DTL sql action
    For more complex calculations, you can write your own class methods and invoke them from a code action, or from the value string in another DTL element.
  • Include descriptions of the transformation and each action.
  • Compiling the data transformation also saves it.
  • To use the DTL data transformation in the production, simply enter its full package and class name in the Transform field of a routing rule set.

Null Mapping Codes

There are HL7 applications that use a null mapping convention. According to this convention, the source application can send a field that consists of two consecutive double-quote characters (
""
) to signify if you have data in this field, delete it from your application.
Many target applications do not expect these instructions and are not designed to respond to them. If this is the case, and the double quotes are saved in the target application as actual patient data, the application users see double-quote characters on their screens. This can be annoying and misleading.
When your source application uses a null mapping convention, your HL7 data transformation can check for null mapping entries in HL7 fields and replace them with empty strings, or otherwise fill in data for the benefit of the target application.
The following <if> statement represents the simplest case. It checks for a null mapping in the source and replaces it with an empty string in the target. The <if> condition tests for the null mapping code
""
using a string of 2 quoted quotes. This results in a total of 6 double-quote characters, not including the single quotes that wrap the entire condition value. (Count carefully!)
<if condition='source.{PV1:7().4}=""""""'>
<true>
<assign property='target.{PV1:7().4}' value='""' />
</true>
</if>
In the above example, the <assign> value indicates a empty string using 2 consecutive double-quote characters, with single quotes wrapping the entire value.
The following syntax is equally valid:
<if condition='source.{PV1:7().4}=&quot;&quot;&quot;&quot;&quot;&quot;'>
<true>
<assign property='target.{PV1:7().4}' value='&quot;&quot;' />
</true>
</if>
You can achieve more sophisticated goals for handling null mappings. The following example takes alternative actions based on whether there is actually a value in {PV1:3}. If the field contains a null mapping code the <true> element executes. Otherwise the <false> element executes.
<if condition='source.{PV1:3}=""""""'>
<true>
<assign property='target.{PV1:3.1}' value='source.{PV1:PatientType}' />
<assign property='target.{PV1:3.2}' value='source.{PV1:PatientType}' />
</true>
<false>
<code><![CDATA[
 // Dr Chart pulls subfields as follows:
 // 1 location, 2 desc, 3 room, 4 bed, 5 wing, 6 floor
]]></code>
<assign property='target.{PV1:3.1}' value='source.{PV1:3.1}' />
<assign property='target.{PV1:3.2}' value='source.{PV1:3.1}' />
<assign property='target.{PV1:3.3}' value='source.{PV1:3.2}'  />
<assign property='target.{PV1:3.4.1}' value='source.{PV1:3.3}'  />
<assign property='target.{PV1:3.5}' value='source.{PV1:3.1}'  />
</false>
</if>

Defining HL7 Search Tables

The HL7 search table class, EnsLib.HL7.SearchTable, automatically indexes popular HL7 properties; see the subsection “Properties That Are Indexed by Default.”
If you need more items to search, you can create a subclass. The subclass inherits the
Identifier
property, plus the infrastructure that makes search tables work. For details, see “Defining a Search Table Class” in Ensemble Virtual Documents.
For HL7, Ensemble supports an additional value for
PropType
. You can use
DateTime:HL7
in addition to the types listed in Ensemble Virtual Documents.

Properties That Are Indexed by Default

When you choose EnsLib.HL7.SearchTable as your search table class, it enables Ensemble to search HL7 messages for the following virtual properties.
Choose... To refer to this value...
MSHTypeName
The message structure name. To create this string, Ensemble concatenates the following values from the HL7 message:
  • The MSH message header segment
    Field 9 (message type)
    Subfield 1 (message type: ADT, ORM, etc)
  • The literal character
    _
  • The MSH message header segment
    Field 9 (message type)
    Subfield 2 (trigger event: A01, A12, O01_2, etc)
The result is a message structure name in the format ADT_A01, ADT_A12, ORM_O01_2, etc.
MSHControlID
The unique identifying number for this message. Ensemble retrieves this value from:
  • The MSH message header segment
    Field 10 (message control ID)
Ensemble interprets this value as a case-sensitive string.
PatientID
The patient identifier for this message. This is a field whose location has shifted as the HL7 standard has evolved. For this reason, Ensemble looks for this value in all of the following locations. That way, the patient identifier can be found regardless of which HL7 schema category the message conforms to:
  • The PID patient identifier segment
    Field 2 (patient external identifier)
    Subfield 1 (patient identifier)
  • The PID patient identifier segment
    Field 3 (patient identifier list), all entries in the list
    Subfield 1 (patient identifier)
  • The PID patient identifier segment
    Field 4 (patient identifier list), all entries in the list
    Subfield 1 (patient identifier)
PatientName
The PID patient identifier segment
Field 5 (patient name)
PatientAcct
The PID patient identifier segment
Field 18 (patient account number)
Subfield 1 (ID)

Examples

The following example consists of one virtual property path that uses {} syntax. This <Item> element refers to the value at Segment 1, Field 10 of the HL7 message:
<Item DocType=""
      PropName="MSHControlID"
      PropType="String:CaseSensitive"
      StoreNulls="true" >
      {1:10}
</Item>
The following more complex <Item> element uses the ObjectScript _ operator to concatenate three strings. From left to right, these are:
  • The value within Segment 1, Field 4
  • A literal
    -
    character
  • The value within Segment 1, Field 3
<Item DocType=""
      PropName="SendingFacilApp" >
      {1:4}_"-"_{1:3}
</Item>
The following <Item> example uses most of the possible syntax options: concatenation, virtual properties, a literal hyphen character (
-
), and the ObjectScript string function $PIECE:
XData SearchSpec [ XMLNamespace="http://www.intersystems.com/EnsSearchTable" ]
{
<Items>
 <Item DocType="Mater:ORM_O01 "
       PropName="RelationKey" >
 $P(
 {ORCgrp(1).OBRuniongrp.OBRunion.OBR:UniversalServiceID.text},"-",1,2
 )_"-"_{MSH:12}
 </Item>
</Items>}
The following sample search table class provides several examples of valid <Item> entries. This class inherits from EnsLib.HL7.SearchTable, as is required for HL7 search tables. Comments above each group of <Item> entries describe the purpose of that set of entries. For details about {} or [] syntax, see the “Syntax Guide” section of Ensemble Virtual Documents.
Class Demo.HL7.MsgRouter.SearchTable Extends EnsLib.HL7.SearchTable
{

XData SearchSpec [ XMLNamespace="http://www.intersystems.com/EnsSearchTable" ]
{
  <Items>
   <!-- Items that do not depend on DocType, indexing any HL7 message -->
   <Item DocType="" PropName="SendingFacilApp" >{1:4}_"|"_{1:3}</Item>
   <Item DocType="" PropName="RecvingFacilApp" >{1:6}_"|"_{1:5}</Item>
   <Item DocType="" PropName="MSHDateTime" PropType="DateTime:HL7" >{1:7}</Item>

   <!-- Get fields from named segments found in any HL7 message -->
   <Item DocType="" PropName="PatientName" >[PID:5]</Item>
   <Item DocType="" PropName="InsuranceCo" >[IN1:4]</Item>

   <!-- Get patient name from any HL7 message declared type ADT_A05 -->
   <Item DocType=":ADT_A05" PropName="PatientName" >{3:5}</Item>

   <!-- Get specific field from specific segment when the        -->
   <!-- HL7 message is assigned a specific DocType. Only in this -->
   <!-- case can you use names for segments, instead of numbers. -->
   <Item DocType="Demo.HL7.MsgRouter.Schema:ORM_O01 " PropName="ServiceId" >
     {ORCgrp().OBRuniongrp.OBRunion.OBR:UniversalServiceID.text}
   </Item>
   <Item DocType="2.3.1:ORU_R01 " PropName="ServiceId" >
     {PIDgrpgrp().ORCgrp(1).OBR:UniversalServiceID.text}
   </Item>
  </Items>
}

}
Previous section   Next section