Daily using/supporting

Get Firefox browser!
Get Thunderbird!
Get Opera browser!
Get The Gimp!
Get Inkscape!
Get LibreOffice!
Get Videolan!
Get Linux!
Get Mandriva!
Get Joomla!
Hacker Emblem

Archives

Which topics would you like us to cover more?

Latest comments

Latest tweets

about 2 days ago Using REDIPS.drag to add drag and drop to your .Net webapplication #li #dib0 http://t.co/n8zY3s7d
about 8 days ago http://t.co/cknQcDbo #Kindle
about 16 days ago Freedom isn't the ability to choose what to do or say, but the ability to choose what not to do or say #freedom
12 Apr 2012 Force the use of a networking adapter using C# #li #dib0 http://t.co/ZTJOPzOz
9 Apr 2012 Mandriva 2010.2 and USB devices in Virtualbox http://t.co/fwq9gbHB
9 Apr 2012 Execute a http request to you own site with PHP http://t.co/DIvWPrpd
Home Architecture, security and coding How to create an application supporting multiple HL7 version using nHapi
How to create an application supporting multiple HL7 version using nHapi
Written by Division by Zero   
Monday, 15 March 2010 14:37

This is a question I received. So, here's an example. I can't give a lot of code details, but I think a generic overview and description of a possible solution would help.

First, let's take a look at a possible application design.

HL7 nHapi application

1. Network layer

The first layer is the network handling. Of course this is application specific. The actual network handling probably is listening to a specific port on the network, receiving a single connection, receiving multiple and synchronous HL7 messages on this connection. Note: the messages will be send with MLLP.

2. Service layer

The service layer will parse the HL7 message to a business object. In the image above this will be a "Person". First the complete message, still available as plain text, must be parsed to a nHapi message object. Here's an example:

 IMessage hl7Message = null;
PipeParser hl7Parser = new PipeParser();
hl7Message = hl7Parser.Parse(message); 

The IMessage object will give us enough information to determine which version of HL7 is used and what kind of message is received. I've used the factory design pattern twice in this example. First to get the right parser for the right HL7 version. The second is to get the right parser for this message.

 private IParser GetParserOnHl7Message(IMessage hl7Message)
 {
 IParser parser = null;

 switch (hl7Message.Version)
 {
 case "2.4" :
 parser = GetMessageParser(hl7Message);
 break;
 default :
 throw new NotImplementedException("HL7 version not supported.");
 }

 return parser;
 } 

Now that we have the right message for the right version we can interpret the message and create our business object.

ADT_A01 message = (ADT_A01)msg;
Person person = new Person();
person.Name = GetPatientName(message.PID.GetPatientName());
 
private string GetPatientName(XPN name)
{
List names = patientNames.Where(xpn => string.Compare(xpn.NameTypeCode.Value, "D") == 0).ToList();
 if (names.Count > 0)
 name = names[0];
 else
 name = patientNames.First();
return name.FamilyName.Surname.Value;
}

This example shows you how to get the "display name" from the HL7 message. This is mostly a safe bet, but not always the right data. To really interpret the message in a right way you actually have to read the HL7 specs. And if you need to implement something like this example, reading the specs is a very good idea.

3. Other layers

The other layers kinda speak for themselves. Now you have a business object you can perform any business operation needed for you application. The example inserts, updates or deletes a record in/from the database in order to keep the list of patients in sync with the central information system.

Remember: this is a very basic and short example. HL7 is able to do a lot and has quite complex messages. But this is basically what you need to do for every messages. After you processed the message HL7 prescribes that you send an acknowledge message to tell the server that the message was processed correctly or not. See my post about ack/nack messages.

If you have any questions or want to discuss something about this topic, please use this forum.

 

Comments  

 
0 # Misza 2010-04-30 01:41
Could you send me more code ? :)
Reply | Reply with quote | Quote
 
 
0 # Bas 2010-04-30 09:47
Hi,

If you have a more specific question, maybe I can help you with it. I certainly will try. You can post your question here if you'd like! :-)
Reply | Reply with quote | Quote
 
 
0 # Misza 2010-04-30 12:11
Could you write me, some code from this example. How can I implement, HL7VersionFacto ry and ParserFactory ? Please write me more example code. Thx
Reply | Reply with quote | Quote
 
 
0 # Bas 2010-04-30 14:33
That's quite a big question you're asking me!
I didn't have much time, but I've posted a little example solution on this blog:
dib0.nl/.../132-nhapi-example

I hope it helps!
Reply | Reply with quote | Quote
 
 
0 # Misza 2010-05-05 13:26
Thanks for example and for your help. I write application supporting multiple HL7 version, it must read the message, parse and create a business object, also it must create a message for every version.
Reply | Reply with quote | Quote
 
 
0 # Bas 2010-05-05 14:42
You're welcome! Glad I could help you :-)

With the example I posted, you can do just that. It reads a message and is able to parse multiple HL7 versions (as an example the parsing of one message type of one version was supplied).

Using the IAck implementation for a specific version, you are able to create an Ack message for every HL7 version.

If you have any questions of run in to any problems, let me know. Maybe I can help you with them.
Reply | Reply with quote | Quote
 
 
0 # Misza 2010-05-06 10:49
Hi! I don't want create ackMessage, I want
create ADT, ORU, and ORM message. I know hl7 version, eventCode (example 2.3 ADT_A01) and I want create interface to create hl7message for every version. In my application, I've database tables, Order and Order_position. I get data from this table and create message. I can read version, eventCode from this table. Have you got any suggestion ?
Reply | Reply with quote | Quote
 
 
0 # Bas 2010-05-06 21:02
Thanks for your clarification. I had to think about the best way of doing this.

I think the best way is to use the factory pattern again, like the example I posted earlier. But now you start with the data from your database. With the version and event type the factory returns a hl7 specific parser (you'll have to write a specific parser for every hl7 version and event type). This parser returns an IMessage (from the nHapi library). This IMessage object you can parse to an actual message. Like this:
string version = "2.5";
string eventType = "ADT";
IMessageCreator creator = Hl7Factory.GetMessageCreat or(version, eventType);
IMessage hl7Message = creator.CreateMessage("Put you data here as a string or an object created on the data from the database");

// Parse the message to an actual hl7 messsage
PipeParser parser = new PipeParser();
string actualMessage = parser.Encode(hl7Messa ge);

There is a slightly more extensive example in the Quickstart Guide for nHapi, by Chad Chenoweth. You can download a copy from my site:
www.dib0.nl/.../nhapi_1_0.pdf
or a copy from a sourceforge mirror:
www.google.nl/.../

I hope this helps. If you have any more questions, please let me know.
Reply | Reply with quote | Quote
 
 
0 # CapitalHealth 2010-08-20 21:06
I am trying to create a ORU_R01 message and attach a pdf file as a OBX segment into it. I am not finding a way to do it. Could you help me how to go about it.

Since there is no PID and OBX section in ORU_R01, I am not sure how I will have to attach these data segment into a message. Any help is appreciated.

Thanks,
Reply | Reply with quote | Quote
 
 
+2 # Bas 2010-08-21 10:06
Hi,

The ORU_R01 message doesn't contain the PID and OBX segments directly. This is because it is possible to send more than one observationresu lt. If you use the Terser you can access the segments like this:

ORU_R01 msg = new ORU_R01();

Terser terser = new Terser(msg);
PID pid = (PID) terser.getSegment("/.PATIENT_RESULT/PATIENT/PID");
pid.AdministrativeS ex.Value = "M";

OBX obx = (OBX)terser.getSegment("/.PATIENT_RESULT/ORDER_OBSERVATI ON/OBSERVATION(0)/OBX");
obx.ObservationIden tifier.Identifier.Value = "1";

I hope this is helpful. If you have any questions or want an example (I need more time to create one) let me know!
Reply | Reply with quote | Quote
 
 
0 # CapitalHealth 2010-08-22 22:36
Thanks for your response. It helped me a lot. But I am still struggling with what exactly I need to do to create this message. Below is my code I had done so far (of course with your help) and a sample message that is what I need to create. The Pdf Report Data is where my encoded pdf data should be attached.

I hope you will be able to help me out with this. Thanks a million:

Sample message:

MSH|^~\&|Application Name|Hospital Name||44|200006 23134511||ORU^R01|20000623134511135475|P|2.3
PID||12345678|69619||John^Smith|| 19550101|M
ORC|RE||||A
OBR|||144137|Report Name|||201002221034|||||||||||||| |201006281344|||F||||||Som e Study|472^LastN ame^FirstName
OBX|1|ED|REPORT_NAME ||Pdf Report Data
Reply | Reply with quote | Quote
 
 
0 # CapitalHealth 2010-08-22 22:50
ORU_R01 msg = new ORU_R01();
Terser terser = new Terser(msg);
//PID:
PID pid = (PID)terser.getSegment("/.PATIENT_RESULT/PATIENT/PID");
pid.AdministrativeS ex.Value = "M";

//OBX
OBX obx = (OBX)terser.getSegment("/.PATIENT_RESULT/ORDER_OBSERVATI ON/OBSERVATION(0)/OBX");
obx.ObservationIden tifier.Identifier.Value = "Report Name";
obx.ValueType.Value = "ED";
obx.SetIDOBX.Value = "1";

// Load the pdf file (report) and attach it as embedded data within OBX segment
string strFileName = "PdfReport.pdf";
string strEncodedpdf = string.Empty;
FileInfo fileInfo = new FileInfo(strFil eName);
if (fileInfo.Exists)
{
//Read file into strEncodedpdf
}
// How to attached 'strEncodedpdf' into OBX.5 segment ???

// Create a MLLP string
PipeParser p = new PipeParser();
string mllpMsg = (char)11+ p.Encode(msg) + (char)28+ (char)13;
Reply | Reply with quote | Quote
 
 
+1 # Bas 2010-08-23 10:58
Hi CaptainHealth,

It's kinda hard to explain how to add a PDf file to a HL7 message. To show you I've created a little demo solution. In this solution there is a HL7 V2.3 and a V2.4 example. There are multiple ways of creating and editing messages.

In the example you'll get two different ways to handle an ORU_R01 message. You can download the demo here: www.dib0.nl/.../oruexample.zip.

Good luck! I hope this will help you. Let me know if you have any more questions. And let me know if this did help you (always good to hear)!
Reply | Reply with quote | Quote
 
 
0 # CapitalHealth 2010-08-23 16:24
Your Example is excellent and I think it will work!

I am going to work on the integrating my application. Once that works, I will post the result. But I expect the integration to go smooth.
Reply | Reply with quote | Quote
 
 
0 # CapitalHealth 2010-12-04 11:18
Your help was great. However, I am still struggling to understand HL7 messaging. Is there a document that describes what string values should I use in Terser to extract various segments ? For example you used the following code:

OBX obx = (OBX)terser.getSegment("/.PATIENT_RESULT/ORDER_OBSERVATI ON/OBSERVATION(0)/OBX");

Where did you know the you should use:
"/.PATIENT_RESULT/ORDER_OBSERVATI ON/OBSERVATION(0)/OBX" ?

Now I am trying to modify other segments and I am stuck again.

Thanks for your help.
Reply | Reply with quote | Quote
 
 
0 # Bas 2010-12-04 11:30
Hi CaptainHealth,

At first I apologize for this late reaction. I just found your previous post in my log-files. Somehow it didn't get through my security test. In the mean time the problems with comments are fixed, so I've added your comment.

Well It's all in the HL7 specs. They require some time to get to know them and learn how to read them. I believe the first introduction of the spec is a guide on how to read the rest of the specs.

You are able to get them at hl7.org (the international organization) or your local hl7 organization.
Reply | Reply with quote | Quote
 
 
0 # Xyler 2011-07-30 23:03
Hello Captain:
I need to parse ORU_R01 HL7 2.3.1 message and store the result in our SQL database.

Please guide me how to decode the lab result. thank you so much.
Reply | Reply with quote | Quote
 
 
0 # Bas 2011-07-31 15:15
Hi Xyler,

Thank you for your question. This kinda depends on what data you'll get and how you want to store it. Here's an example on how to get the data from the OBX segment:
NHapi.Base.Model.Varies v = msg.GetRESPONSE().GetORDER_OBSERV ATION(0).GetOBSERVATION( 0).OBX.GetObservationV alue(0);
NHapi.Model.V23.Datatype.ED ed = (NHapi.Model.V23.Datatype.ED)v.Data;
byte[] pdFileContent = Convert.FromBase64Strin g(ed.Data2.Value);

In the example you see that there are no repetitions here (this is an assumption). The actual data can be stored as different types. Here it is stored as a ED field. In this field all the information on the pdf (this is what I used) is stored as well as the form of encoding used.

I hope this will help you. If you have any questions, please let me know!
Reply | Reply with quote | Quote
 

Add comment


Security code
Refresh

I think, therefore I am. - R. Descartes


© 2009 - 2012, Division by Zero

Template based on the empire template by joomlashack 

Valid XHTML 1.0 Strict  Valid CSS!  Creative Commons License
This work by Division by Zero is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Netherlands License.