Note: This page should be changed into Wiki format.

HL7 V3 API Overview

Introduction

The new HL7 V3 messaging framework is based on an object-oriented data model, the RIM, and on defined data types. Because the data model is well defined, the derived messages are unambiguous and standardized. Additionally, the V3 messaging framework provides "meta" files that define how messages are translated from the RIM model to an XML V3 message format and vice versa.

The RIM data model, HL7 data types, and the Meta file message definitions enable the HL7 V3 API to systematically parse and build V3 messages without requiring "hard coded" pre-existing knowledge of message structure. Given the proper Meta file and the actual V3 XML message, the API can process the message regardless of the message type and message contents. As new message types and their resultant Meta files are added to the HL7 V3 domain, the API will be able to parse and build these messages without any API changes!

As a result of the message parsing process, the API will generate an in-memory graph of RIM objects that represents the V3 XML message contents. The developer can then leverage the RIM objects as needed to extract the pertinent message values. In order to build a V3 XML message, the API requires an in-memory RIM graph to drive the transformation process.

Though the design of the API is elegant, the implementation and the various domain concepts are complicated. Before one can understand the low level mechanics of the API, there are other concepts that you should become familiar with:
  • HL7 V3 messaging, including the RIM and HL7 Data Types
  • HL7 meta information as found in the HMD and MIF meta files
  • XML SAX parsing
  • XML XSLT transformations
  • Java Reflection and Generics
In general, a deep understanding of the API is not necessary to actually use the API. The API comes with a demo package that contains examples of how the API can be used to parse and build messages. You can jump right in by inspecting the demo driver code and see how the API is used. By inspecting the ANT build file you can ascertain the typical input parameters required: a V3 message file, a message type, a Meta file (MIF or HMD), and a RIM file.

Specifically, look at org.hl7.demo.DemoDriver. This class first loads the Meta information for a particular message type. It then parses a message into memory, and optionally persists the in memory object graph using Hibernate. The class then reverses the process and reads the in memory RIM graph back out to a new XML V3 message that reflects the original parsed message.

Other sets of example code will be provided as the API evolves thru beta and into a production release.

Roll up your sleeves, there is a lot under the hood. See the resources section at the end of this document for links to online resources that may aid in becoming familiar with some of the API building block concepts.

Meta Information and Loader

HL7 provides 2 formats (HMD and MIF) for specifying message Meta data (structure, format, and constraints). They are both XML based. HMD stands for Hierarchical Message Definition. MIF stands for Model Interchange Format.

Note:

This document was written when our meta information was parsed from HMD files. Now we use MIF files and the HMD parser is depreciated. Keep this in mind as you read this section. Where ever it refers to HMD think to yourself MIF instead. (Peter Hendler 11/04/2006)

The API supports both format types. The Meta Loader processes the Meta file via a JDOM parser. As key Meta elements are encountered within the input Meta file, Meta classes are created that mirror the attributes and other Meta class associations specified in the file. These Meta classes drive how the RIM object graph is built when messages are actually parsed.

The current Meta loader classes are found in the org.hl7.meta package. This package may become obsolete as another Meta file parsing API from the HL7 tools SIG may be utilized instead. However, for those interested, see the MifMessageTypeLoader class under the impl directory.

RIM Classes

The source files for these classes are automatically generated from the XSLT transform of definition files. The RIM classes are based on high level abstractions such as patients, observations, procedures, roles, acts, etc.

The RIM classes are found in the org.hl7.rim package. Actual implementations are found one level lower in the impl directory.

Data Types

The source files for the data types are hand crafted and contain many specialized methods. These classes also make heavy use of Java Generics (introduced in Java 1.5). Some example data type classes include abstractions such as coded elements (CE), timestamps (TS), physical quantities (PQ), etc.

The HL7 data type classes are found in org.hl7.types package. Actual implementations are found one level lower in the impl directory.

Message Parser

The main parsing classes (content handlers) are found in the org.hl7.xml.parser package. Presenter classes are located one level higher.

The message parser utilizes a SAX parser when parsing the XM nodes of the input HL7 V3 message. As SAX events fire, data from the SAX event is used to query Meta classes for Meta data. The specific Meta data allows the parser to instantiate a node as a RIM object or HL7 data type object. The Meta data also denotes where to attach the instantiated object. Reflection is used to find the correct “setter” method to “add” the object to the growing RIM graph in memory. When an instance of a RIM class or data type is needed, it is created by a properties based factory.

Since there are many flavors of objects (RIM classes, data types, CMETS or Common Message Element Types) we need specialized content handlers. The specialized content handlers can be dynamically "switched out" during message parsing. See the DynamicContentHandler class.

Specialized handlers (Presenters) are included for each RIM and data type class. Presenters are called by intermediate content handlers. Examples of these intermediate content handlers include: TreeContentHandler, DataTypeContentHandler, and SimpleTypeContentHandler, and others as well.

As Sax events fire, they are handled by MessageElementContentHandler which in turn can dynamically “suspendWith” to temporarily trade places with a specialized “presenter” class. The final object is handed back down the call stack to a “resultReceiver” with a call to “notifyResult”. Eventually, the returned partial result is added to the growing RIM graph by using reflection to find the correct “setter” method on the parent object.

Once the entire message is parsed, the resulting object graph is the entire in memory representation of the RIM Graph.

Message Builder

The message building classes are mostly found in the org.hl7.xml.builder package. The message builder’s design resembles the parser in that it relies on small specialized content handlers (which in this case are called “builders” instead of “presenters”).

If you look inside a presenter class you will find an inner class of type “builder”. This design choice was made so that once a presenter is written it is able to handle both message parsing and message building.

The message builder uses a clever “trick” to generate the XML output.  Instead of writing many print statements, another approach was taken utilizing the "Identify transform" feature of XSLT transforms.

The “Identity transform” is a special case where the incoming XML message is sent through the XSLT transform machinery, but no actual transform is done. The newly generated output is exactly the same as the XML input: but the output isn't simply copied. The input generated SAX events and these events were used to create the XML output. Since no transform is performed, the resulting message is the same as the input message.

If you could read or parse the in memory RIM graph and pretend to be a SAX XMLReader, essentially generating the same events as if you were reading an XML stream, then you could use that reader in an identity transform to create XML output. That is the approach that was taken in the message builder (credit: Gunther Schadow).

The mechanism that masquerades as a SAX XML reader is made up of the classes XMLSpeaker and XMLRimGraphSpeaker. As the SAX events are emitted by “parsing” the in memory RIM graph, they are handled by “MessageBuilders”. The message builders are then dynamically switched for one another as appropriate. Finally one of the builders emits a SAX event to an internal member of type “org.xml.sax.ContentHandler”. This member happens to be the "_contentHandler" member from the abstract class XMLSpeaker. Once this event fires, the XSLT transform takes over and the XML for that particular node is created. Pretty nifty.

Persistence

Persistence is accomplished by Hibernate

Hpath Query Language

There is now a language that can navigate the RIM graph in memory. It is called Hpath. One of the ANT targets called demoGUI allows you to load a message into an in memory RIM graph, and then keep trying Hpath expressions to see the results. Hpath is a lot like Xpath. If a RIM object has a method for example getTitle, then the corresponding Hpath expression would add SomeObject.title to navigate down to the Title item. If the Title is a CS value then you would be able to further navigate like this SomeObject.title.code

Validation

TBD.

Constraint Checking

TBD

Resources

Information on XML is widely available in books and on the web. Some websites, such as w3schools offer online tutorials on XML and XSLT.

Information on HL7 version 3 is harder to come by. There is at least one introductory book for sale by HL7. There are some documentation materials on the HL7 web site. For more information on data types, see HL7 data types.

It is valuable to attend an HL7 meeting and take a tutorial on Version 3 and the RIM (Reference Information Model). This information and understanding is the biggest hurdle a newcomer will have to overcome before they can understand and use this API.

Information about Java Reflection can be found in the Java Reflection Tutorial. Information about Java Generics can be found in the Java Generics Tutorial.

Bored? Check out the SAX Project for more information on SAX parsing.