0

I am working on a tool which will construct a HL7 message in following Way :

Message will start with : 0B Segment will end with : OD And Message will end with : 1C0D

So, here i have reached so far, i am able to add OB and add 1C0D in the end of the HL7 Message. I am also able to add OD before at the end of the segment. I am accomplishing with the of code where i will check if Character before Segment name is 0D or not.

But the issue is if text in the message is somewhat like this ...PID| my code will add 0D before PID| which is not correct it should check if its the start of the segment or not.

Please help if someone has worked on similar requirement.

Link to my code is : Arraylist Sublist IndexOutOfBounds Exception

Luke Girvin
  • 13,221
  • 9
  • 64
  • 84
  • 1
    Do you need to create HL7 messages from scratch? Otherwise you could use HAPI (http://hl7api.sourceforge.net/) for that, it's much simpler. – Baderous Jan 16 '16 at 14:56
  • No i don't need to Create the message from Scratch. I just wanted to append Hex Codes at the start and end of the message as well as at the end of Segment. So that it can get processed in our environment. – Vinayak Bamane Jan 16 '16 at 15:27

1 Answers1

2

I had some time to look at this problem. As far as I could understand, you have some piece of code that generates the HL7v2 segments for you and then you want to create a message with the following delimiters:

  1. Segment delimiter: 0x0D (or 13 in ASCII), which is the Carriage Return. It's the segment separator, as per HL7v2 standard;
  2. Message start delimiter: 0x0B (ASCII 11 - Vertical Tab);
  3. Message finish delimiter: 0x1C0D. My guess is that this value is supposed to be the concatenation of 0x1C (ASCII 28 - File Separator) and 0x0D (ASCII 13 - Carriage Return).

With #1 you get HL7v2 messages standard-compliant. With #2 and #3 you are able to clearly define delimiters for the message so that it can be processed and parsed later by some custom processor.

So I took a shot writing some simple code and here's the result:

public class App 
{
    public static void main( String[] args ) throws Exception
    {
        String msg = "MSH|^~\\&|HIS|RIH|EKG|EKG|199904140038||ADT^A01||P|2.5" +
                     "PID|0001|00009874|00001122|A00977|SMITH^JOHN^M|MOM|19581119|F|NOTREAL^LINDA^M|C|564 SPRING ST^^NEEDHAM^MA^02494^US" +
                     "AL1||SEV|001^POLLEN";

        String[] segments = msg.split("(?=PID|AL1)");
        System.out.println("Initial message:");
        for (String s : segments)
            System.out.println(s);

        byte hexStartMessage = 0x0B;
        byte hexFinishMessage1 = 0x1C;
        byte hexFinishMessage2 = 0x0D;
        byte hexFinishSegment = 0x0D;

        String finalMessage = Byte.toString(hexStartMessage) + 
                intersperse(segments, hexFinishSegment) + 
                Byte.toString(hexFinishMessage1) + 
                Byte.toString(hexFinishMessage2);

        System.out.println("\nFinal message:\n" + finalMessage);           
    }

    public static String intersperse(String[] segments, byte delimiter) throws UnsupportedEncodingException {
        // uncomment this line if you wish to show the delimiter in the output
        //System.out.printf("Byte Delimiter: %s", String.format("%04x", (int)delimiter));
        StringBuilder sb = new StringBuilder();
        String defaultDelimiter = "";
        for (String segment : segments) {
            sb.append(defaultDelimiter).append(segment);
            defaultDelimiter = Byte.toString(delimiter);
        }
        return sb.toString();
    }
}

I picked up a simple HL7v2 message and I splitted it in segments, according to the segments (name) used in the message, with the help of a regex with a lookahead strategy. This means that, for your messages you'll need to know the segments that are going to be used (you can get that from the standard).

I then interspersed the segment delimiter between each segment (at its end) and added the message start and end delimiters. In this case, for the message end delimiters, I used the 0x1C and 0x0D values separated, but if you need to use a single value then you only need to change the final appends.

Here's the output:

Initial message:
MSH|^~\&|HIS|RIH|EKG|EKG|199904140038||ADT^A01||P|2.5
PID|0001|00009874|00001122|A00977|SMITH^JOHN^M|MOM|19581119|F|NOTREAL^LINDA^M|C|564 SPRING ST^^NEEDHAM^MA^02494^US
AL1||SEV|001^POLLEN

Final message:
11MSH|^~\&|HIS|RIH|EKG|EKG|199904140038||ADT^A01||P|2.5
PID|0001|00009874|00001122|A00977|SMITH^JOHN^M|MOM|19581119|F|NOTREAL^LINDA^M|C|564 SPRING ST^^NEEDHAM^MA^02494^US
AL1||SEV|001^POLLEN2813

As you see, the final message begins with value 11 (0x0B) and ends with 28 (0x1C) and 13 (0x0D). The 13 (0x0D) at the end of each segment is not shown because Java's System.out.println() recognizes it as being the '\r' character and starts a new line because I'm running in Mac OS X. If you try to intersperse the segments with any other character (ex: 0x25 = '%') you'll notice that the final message is printed in a single line:

11MSH|^~\&|HIS|RIH|EKG|EKG|199904140038||ADT^A01||P|2.5%PID|0001|00009874|00001122|A00977|SMITH^JOHN^M|MOM|19581119|F|NOTREAL^LINDA^M|C|564 SPRING ST^^NEEDHAM^MA^02494^US%AL1||SEV|001^POLLEN2813 

If I run in Ubuntu, you get to see the message in one line with the segment delimiter:

11MSH|^~\&|HIS|RIH|EKG|EKG|199904140038||ADT^A01||P|2.513PID|0001|00009874|00001122|A00977|SMITH^JOHN^M|MOM|19581119|F|NOTREAL^LINDA^M|C|564 SPRING ST^^NEEDHAM^MA^02494^US13AL1||SEV|001^POLLEN2813
Community
  • 1
  • 1
Baderous
  • 1,069
  • 1
  • 11
  • 32
  • 1
    Hello Thanks for your help on this topic. I have done some changes to your code and i am able to see proper Hex codes such as 0B, 1C0D and 0D. Below is the code String hexStartMessage = "\u000b"; String hexFinishMessage1 = "\u001C"; //String hexFinishMessage2 = "\r"; String hexFinishSegment = "\r"; public static String intersperse(String[] segments, String delimiter) throws UnsupportedEncodingException – Vinayak Bamane Jan 21 '16 at 09:40
  • The only issue which i am facing now is "\r" is adding adding 0D as well as 0A so if we can get rid of that we are good to go. Please let me know your thoughts. – Vinayak Bamane Jan 21 '16 at 09:42
  • 0A is the decimal 10, which is the Line Feed. How do you know that 0A is added? Are you opening the final message in some file editor? If so, it may be adding it, by translating \r to \r\n: http://stackoverflow.com/a/3098328/1252603 – Baderous Jan 21 '16 at 11:38
  • Yes i checked using Hex Editor. One more issue which i facing now is if my message contains OBR word anywhere in the message it is considering it as a OBR segment and adding 0D before OBR. I dont know how this is happening even after adding condition as OBR|. – Vinayak Bamane Jan 21 '16 at 12:32
  • After applying your changes to my code I wrote the message to a binary file with: `byte[] msgBytes = finalMessage.getBytes(Charset.forName("UTF-8")); FileOutputStream fos = new FileOutputStream("msg"); fos.write(msgBytes);` Using Vim to open the message as text message (`vim msg`), I can use its hex dump (http://vi.stackexchange.com/a/2234) and see the 0d0a at the end of the message. But if I open as binary (http://stackoverflow.com/a/3860538/1252603) it doesn't have the 0a. – Baderous Jan 21 '16 at 17:21
  • For the OBR, you'll have to adjust the regex to check for something unique to the segment name. Your message must have something like `OBR|TestOBR|2`, that's why it's splitting the segment in two. With a segment delimiter it'd be much easier. :) – Baderous Jan 21 '16 at 17:22