Understanding HL7 Vocabulary Domains

(I originally wrote a version of this page while working on an HL7 project at the beginning of 2007. This version contains a mix of old and new material.)

After three days of staring intently at the HL7 Vocabulary Domain stuff, I finally reached an A-ha moment. So, I’m writing down my findings to crystallize my thoughts (and record them for posterity).

What is a HL7 Vocabulary Domain?

First, what do I mean by Vocabulary Domain? If you look over here you can see a variety of codes that represent different states in a variety of domain areas.

In a simple example, here is a list of codes that represent a person’s (or animal’s) gender: male (“M”), female (“F”) or undifferentiated/intersexed (“UN”).

It’s attractive (and easy) to represent this concept in Java code using an enum type:

public enum AdministrativeGender {
  M, F, UN

It might even be attractive to elaborate these domains as follows:

public enum AdministrativeGender {

  private String mnemonic;

  private AdministrativeGender(String mnemonic) {
    this.mnemonic = mnemonic;

  public String getMnemonic() {
    return this.mnemonic;

It seems like there isn’t much to understand, here, because this example is so simple. Unfortunately, things become much more complicated once we start to look at some of the hierarchical cases.

Relationship between Vocabulary Domains and Data Types

I’ve previously posted about HL7 Data Types. The HL7 data types that indicate whether or not “Vocabulary Domains” apply.

The Vocabulary Domain types are in the “coded” types:

HL7 Data Type Meaning
CS Coded Simple Value
CV Coded Value
CE Coded with Equivalents
CD Concept Descriptor

When HL7 defines its business objects (in a special file called a “mif” file), it might decide that some attribute has a specific domain type. Here’s an example of one such attribute:

<mif:attribute name="versionCode" ... >
  <mif:type name="CS"/>

This domainName tells us which set of codes is valid. If one is tempted to generate Java code of this business object, then one might also be strongly tempted to use the an enum for HL7StandardVersionCode as the type of the “versionCode” property. And in fact, that’s what we’re trying to do.

Incomprehensible Hierarchies

One of the most commonly-used hierarchies in the Vocabulary Domain is the ActCode hierarchy. The ActCode hierarchy defines certain “subclasses” of codes, such as HL7TriggerEventCode. And, in fact, several messages in CeRx are defined as having a dependency on HL7TriggerEventCode. Thus, one of the properties of that message object is defined as a “type” of HL7TriggerEventCode.

Thus, our Java code needs to recognize that, for the purposes of that type of message, certain code values for the ActCode hierarchy are of type HL7TriggerEventCode and others are not.

However, to make matters more complicated, individual code values might appear in multiple places within the hierarchy (suggesting something comparable to “multiple inheritance”), and certain “subclasses” are given non-unique names. Look, for example, at the type HL7DefinedActCodes. It appears multiple times in the ActCode hierarchy (usually with a different “concept id” and/or “mnemonic”). As a “type”, HL7DefinedActCodes is not sufficiently unique to be usable. But, in the same hierarchy, HL7TriggerEventCode is not only usable, but used. So the question is: how to separate the wheat from the chaff?

Implementations of HL7

While HL7 defines certain code sets, there are various implementations of HL7 that sometimes “embrace and extend” those code sets. Some of the HL7 implementations that we’ve worked with include:

  • CeRx
  • Necst
  • Referrals

Categories of Vocabulary Domains

In analyzing various vocabulary domains, it appears that there are some distinct “categories” of vocabulary domains.

  1. Purely structural vocabulary domains that are used in the construction of messages, but which seldom have purpose outside of those messages. Usually these code sets are “fixed values”. An example might be the type, EntityClass, which is a common code used in the message structure. EntityClassis used in constructing a message, but end users are usually unaware that the code set exists.
  2. Structural vocabulary domains that aren’t fixed, and which drive certain business rules, but which aren’t generally chosen by the user. For example, when we receive response messages from an HL7 server, the responses often contain a set of “messages” (AcknowledgementDetails) which include a form of message severity (AcknowledgementDetailType). Like most systems, the severities include “ERROR”, “WARNING”, etc.
  3. Vocabulary domains that represent “pick list” values. An important consideration for these code sets is the frequency with which the values change. Some code sets, such as AdministrativeGender, don’t change very often. They are defined by the HL7 standards process, and should only be changed when a new version of HL7 is supported. (This would probably correspond with a new software release). Other codes might change with greater frequency.

It's only fair to share...
Share on Facebook
Tweet about this on Twitter
Share on LinkedIn

Leave a Reply