HL7 Programming using .NET and NHAPI - Advanced Message Validation using NHAPI Tools

This is part of my HL7 article series. In this tutorial, we will look at another framework called NHAPI Tools that builds on top of the NHAPI framework and provides many additional capabilities including more advanced message validation features. If you want to ramp up on the prerequisite knowledge/background required to following along, have a look at my earlier articles in this tutorial series.

Tools for Tutorial

Overview of Validation Mechanisms offered by NHAPI Tools

We saw in my previous tutorial "HL7 Programming using .NET and NHAPI - Message Validation" that the built-in features to support message validation are not as extensive in the NHAPI Toolkit when compared to the original HAPI HL7 toolkit for Java on which it is based upon. However, this toolkit offers a flexibile design which enables developers to address these limitations by extending the core validation framework if/when necessary. NHAPI Tools is a very useful framework that builds on top of the flexible design provided by NHAPI and provides many additional capabilities for HL7 software developers in the .NET ecosystem. You will recall that I had earlier used this toolkit to transmit HL7 messages to a remote party. NHAPI Tools provides many other useful features like this including support for generation of acknowledgement messages, support for custom message segments as well as ability to read HL7 message data directly from files. In this tutorial, I will review some of the message validation features built into this framework. Let us get started.

App.config and Runtime Configurability

Before we proceed further, we need to understand how application configuration works in general within the .NET framework. This is a huge topic in itself and I will simply cover just enough here to make sense of how NHAPI toolkit utilizes this as foundation to provide a "runtime configurability" approach to message validation.

The Microsoft .NET framework uses a common approach that forms the basis of application configuration for nearly all types of applications that can be developed using the framework. These include console applications, desktop applications, mobile applications, windows services as well as web applications. A framework of classes and interfaces (found in the "System.Configuration" namespace) provide us with very useful abstractions for reading and writing application configuration data from/to nearly every type of data store such as files, databases, memory, etc. Among these various approaches, file-based application configuration are the most common. Examples of configuration files include "app.config", "web.config" and "machine.config". These .NET configuration files at their core are essentially XML format files with a constrained XML schema definition that permits both predefined configuration sections and optionally any custom configuration sections tailored for a specific application or a library. Each configuration section helps store very specific configuration details regarding some aspect of program behavior. For instance, it is common for .NET applications to contain key/value pairs in the "appSettings" section to specify settings such as location of dependencies required by the application such as email servers, user credentials, etc. They may also contain database-related connection information usually in the "connectionStrings" section of these files.

NHAPI Tools Validation Framework Design

The NHAPI Tools framework uses the flexibility offered by .NET configuration framework to dynamically configure the message validation rules that we want to utilize during message processing. It utilizes the .NET assembly loader as well as the Activator class in the .NET framework to instantiate message validation rules which are specified using custom configuration sections within the app.config file. Message validation rules can be specified both as concrete C# classes or specified simply as configuration settings. These rules are then dynamically loaded through a process called "reflection" and are loaded into the validation contexts that are then used by the message parsers.

The illustration above shows the overall design of the validation framework provided by NHAPI Tools and how it extends on the NHAPI base validation framework that I had covered in my earlier tutorial titled "HL7 Programming using .NET and NHAPI - Message Validation". As you can see, this toolkit provides some additional rule classes as well as two new validation contexts that enable control over both the specificity as well as run-time configurability of validation rules pertaining to HL7-related encoding as well as message, segment and field data. Let us look at how these work using a couple of small but focused examples.

“We patronize the animals for their incompleteness, for their tragic fate of having taken form so far below ourselves. And therein we err, and greatly err. For the animal shall not be measured by man. In a world older and more complete than ours, they are more finished and complete, gifted with extensions of the senses we have lost or never attained, living by voices we shall never hear. They are not brethren, they are not underlings; they are other Nations, caught with ourselves in the net of life and time, fellow prisoners of the splendour and travail of the earth.” ~ Henry Beston

Message Validation using Automated Contexts

The AutomatedContext is a special validation context class that simply loads all message validation rules that are located in a specific .NET assembly. The NHAPI Tools framework looks for a specific setting in the "app.config" file called "NHapiRulesNamespace" for the assembly information. I will illustrate how this validation context works by looking at a contrived example that we had seen in my earlier tutorial on basic message validation. We will specify a message validation rule class called "Hl7Ver23AdtA01MessageMustHaveEvn4DataRule" which extends the "ISpecificMessageRule" class. This rule class specifies that any HL7 verion 2.3 ADT A01 message should always contain data in the EVN-4 field.

    using NHapi.Base.Util;
    using NHapi.Base.validation;
    using NHapiTools.Base.Validation;

    namespace NhapiToolsAutomatedContextValidationOfHl7Messages.Our_Custom_Rules
    {
        public class Hl7Ver23AdtA01MessageMustHaveEvn4DataRule : ISpecificMessageRule
        {
            public string[] GetVersions()
            {
                return new[] {"2.3"};
            }
            
            public string[] GetMessageTypes()
            {
                return new[] { "ADT" };
            }

            public string[] GetTriggerEvents()
            {
                return new[] { "A01" };
            }

            public ValidationException[] test(NHapi.Base.Model.IMessage msg)
            {
                var validationResults = new ValidationException[0];
                var terser = new Terser(msg);
                var value = terser.Get("EVN-4");

                if (string.IsNullOrEmpty(value))
                {
                    validationResults = new[] { new ValidationException(Description) };
                }

                return validationResults;
            }

            public string Description => "EVN-4 must be supplied";

            public string SectionReference => string.Empty;
        }
    }

NHAPI Tools Automated Context App Config

Having specified a message validation rule, we now need to inject the rule into the message validation context used by the message parser that is used to process HL7 messages. Achieving this requires a bit of coding as well as the inclusion of the small application configuration setting which specifies the .NET assembly to look for the message validation rules (see screen capture above showing the app.config file setting that you need to use). The use of the automated context enables our application to automatically look for any HL7 message validation rules in the specified .NET assembly without having to explicitly inject them into the validation context that is used by the message parser.

    private static void DemonstrateNhapiToolsAutomatedContext()
    {
        try
        {
            //Using an automated context should automatically load all validation rules in the assembly
            //use app.config setting key "NHapiRulesNamespace" to specify which .NET assembly to load for rules
            //here, we are including the message rule class "Hl7Ver23AdtA01MessageMustHaveEvn4DataRule" in the same assembly

            const string adtMessageToValidateAgainst =
                "MSH|^~\\&|SENDING_APPLICATION|SENDING_FACILITY|RECEIVING_APPLICATION|RECEIVING_FACILITY|" +
                "20110613083617||ADT^A01|2323232223232|P|2.3||||\r" +
                "EVN|A01|20110613083617|||\r" +
                "PID|1||135769||MOUSE^MICKEY^||19281118|M|||123 Main St.^^Lake Buena Vista^FL^32830|" +
                "|(407)939-1289^^^[email protected]|||||1719|99999999||||||||||||||||||||\r" +
                "PV1|1|O|||||^^^^^^^^|^^^^^^^^"; ;

            LogToDebugConsole("*Testing parsing with NHAPI Tools Automated Context*");

            var parser = new PipeParser();

            //this should load the 
            var context = new AutomatedContext(parser.ValidationContext);
            parser.ValidationContext = context;

            //parse the message containing no event reason code data (EVN-4)
            //this should trigger a validation exception
            parser.Parse(adtMessageToValidateAgainst);
        }
        catch (System.Exception ex)
        {
            LogToDebugConsole("Validation exception should be thrown here...");
            if (ex.InnerException != null)
                LogToDebugConsole("Custom Validation: Message failed during parsing:" +
                                    ex.InnerException.Message);
        }
    }

The output of running this program is shown below. A validation exception is thrown by the HAPI pipe parser when processing any HL7 version 2.3 ADT A01 message that does not contain data within the EVN-4 field.

Demonstration of NHAPI Tools Configurable Context...
Validation rule specified in app.config called 'MandatoryFieldADT_EVN-4' should fail here...
Validation exception thrown...
Custom Validation: Message failed during parsing:EVN-4 must be supplied

“All men make mistakes, but a good man yields when he knows his course is wrong, and repairs the evil. The only crime is pride.” ~ Sophocles, Antigone

Message Validation using Configurable Contexts

Another type of validation context provided by NHAPI tools is known as "ConfigurableContext". This type of validation context takes a different approach by enabling you to specify the message rules you want to apply during message processing using a couple of custom configuration sections with the the "app.config" configuration file. Any message validation rules specified here are included as part of any message processing done by the parser. NHAPI Tools also provides a number of pre-built message validation rules called "standard validation rules" that help make life a bit easier for programmers. These special rule classes reduce the amount of coding by enabling you to provide message validation rules simply by specifying them as configuration settings within the application configuration file. As you can see from the screen capture below, all that is required is to provide a rule name and additional details such as the specific Hl7 version and the specifc message type as well as related trigger event of the message they apply towards.

NHAPI Tools Configurable Context App Config

    private static void DemonstrateConfigurableContextPidSegmentIsMissing()
    {
        try
        {
            //ADT A01 message with missing PID segment
            const string adtMessageWithPidSegmentMissing =
                "MSH|^~\\&|SENDING_APPLICATION|SENDING_FACILITY|RECEIVING_APPLICATION|RECEIVING_FACILITY|" +
                "20110613083617||ADT^A01|2323232223232|P|2.3||||\r" +
                "EVN|A01|20110613083617||Some Reason|\r" +
                "PV1|1|O|||||^^^^^^^^|^^^^^^^^"; ;

            LogToDebugConsole("Demonstration of NHAPI Tools Configurable Context...");
            LogToDebugConsole("Validation rule specified in app.config called 'MandatorySegmentADT_A01_PID' should fail here...");

            var parser = new PipeParser();

            //this should load the 
            var context = new ConfigurableContext(parser.ValidationContext);
            parser.ValidationContext = context;

            //parse the message containing PID message segment
            //this should trigger a validation exception
            parser.Parse(adtMessageWithPidSegmentMissing);
        }
        catch (System.Exception ex)
        {
            LogToDebugConsole("Validation exception thrown...");
            if (ex.InnerException != null)
                LogToDebugConsole("Configurable Context-based Validation: Message failed during parsing:" +
                                    ex.InnerException.Message);
        }
    }

The output of running the configurable context validation is shown below. A validation exception is thrown by the HAPI pipe parser when processing HL7 version 2.3 ADT A01 message that do not contain any PID message segments.

Demonstration of NHAPI Tools Configurable Context...
Validation rule specified in app.config called 'MandatorySegmentADT_A01_PID' should fail here...
Validation exception thrown...
Configurable Context-based Validation: Message failed during parsing:Segment PID not available in message

In addition to the rules shown here, NHAPI Tools offers a few additional pre-built validation rules. I will let you explore these on your own as they operate along the same principles explained in this tutorial. See the tool's GitHub page for more details.

Conclusion

In this tutorial, we looked at some additional message validation capabilities provided by NHAPI Tools. This library can be a very useful tool in our toolbag when building message validation functionality within .NET-based HL7 custom applications. It provides many benefits such as run-time configurability, additional specificity as well as helps reduce coding when dealing with common message validation requirements. In addition to the message validation-related capabilities covered in this tutorial, there are many additional features offered by this toolkit. However, I will leave them for your own exploration. In the next tutorial, I will provide a quick tour of other tools and concepts that you should be aware of such as "message conformance" and "message profiles" and why these are necessary for any HL7 integration initiative to be successful. See you then!