Search code examples
javacarriage-returnhl7segment

How to find if HL7 Segment has ended or not if Carriage return is not present


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


Solution

  • 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