Coverage Report - ca.uhn.hl7v2.util.Hl7InputStreamMessageStringIterator
 
Classes in this File Line Coverage Branch Coverage Complexity
Hl7InputStreamMessageStringIterator
89%
59/66
73%
34/46
5.286
Hl7InputStreamMessageStringIterator$ParseFailureError
0%
0/2
N/A
5.286
 
 1  
 package ca.uhn.hl7v2.util;
 2  
 
 3  
 import java.io.IOException;
 4  
 import java.io.InputStream;
 5  
 import java.io.InputStreamReader;
 6  
 import java.io.PushbackReader;
 7  
 import java.io.Reader;
 8  
 import java.util.Iterator;
 9  
 
 10  
 import org.slf4j.Logger;
 11  
 import org.slf4j.LoggerFactory;
 12  
 
 13  
 /**
 14  
  * <p>
 15  
  * Reads from an {@link InputStream} containing a stream of encoded HL7 messages
 16  
  * and iterates over those messages. This class is geared towards reading from
 17  
  * files, and tries to be very lenient about the format of the stream,
 18  
  * specifically concerning control characters and line endings. It should be
 19  
  * safe to provide a stream containing Windows or Unix line endings (which will
 20  
  * be treated as segment delimiters). It is also safe to provide a stream
 21  
  * containing MLLP control blocks before and after each message (although these
 22  
  * will not be validated! Do not use this class to read MLLP messages from a
 23  
  * socket stream!)
 24  
  * </p>
 25  
  * <p>
 26  
  * The input stream could, for example, be a FileInputStream reading from a text
 27  
  * file containing a number of HL7 messages in plain text format.
 28  
  * </p>
 29  
  * <p>
 30  
  * Usage note: If an IOException occurs while reading from the stream or a
 31  
  * message parsing exception occurs, it will be thrown as an unchecked
 32  
  * {@link ParseFailureError}
 33  
  * </p>
 34  
  */
 35  0
 public class Hl7InputStreamMessageStringIterator implements Iterator<String> {
 36  
 
 37  
         @SuppressWarnings("unused")
 38  5
         private static final Logger ourLog = LoggerFactory.getLogger(Hl7InputStreamMessageStringIterator.class);
 39  
         
 40  50
         private StringBuilder myBuffer = new StringBuilder();
 41  50
         private boolean myFoundMessageInBuffer = false;
 42  
         private Boolean myHasNext;
 43  
         private boolean myIgnoreComments;
 44  
         private String myNext;
 45  
         private Reader myReader;
 46  
 
 47  
         /**
 48  
          * Constructor
 49  
          * 
 50  
          * @param theInputStream
 51  
          *            The input stream to read from
 52  
          */
 53  
         public Hl7InputStreamMessageStringIterator(InputStream theInputStream) {
 54  20
                 this(new InputStreamReader(theInputStream));
 55  20
         }
 56  
 
 57  
         /**
 58  
          * Constructor
 59  
          * 
 60  
          * @param theReader
 61  
          *            The reader to read from
 62  
          */
 63  50
         public Hl7InputStreamMessageStringIterator(Reader theReader) {
 64  50
                 myReader = new PushbackReader(theReader);
 65  50
         }
 66  
 
 67  
         /**
 68  
          * {@inheritDoc}
 69  
          */
 70  
         public boolean hasNext() {
 71  370
                 if (myHasNext == null) {
 72  
 
 73  
                         int next;
 74  210
                         int prev = -1;
 75  210
                         int endOfBuffer = -1;
 76  210
                         boolean inComment = false;
 77  
                         
 78  
                         while (true) {
 79  
                                 try {
 80  72700
                                         next = myReader.read();
 81  0
                                 } catch (IOException e) {
 82  0
                                         throw new ParseFailureError("IOException reading from input", e);
 83  72700
                                 }
 84  
 
 85  72700
                                 if (next == -1) {
 86  90
                                         break;
 87  
                                 }
 88  
 
 89  72610
                                 char nextChar = (char) next;
 90  72610
                                 if (nextChar == '#' && myIgnoreComments && (prev == -1 || prev == '\n' || prev == '\r')) {
 91  20
                                         inComment = true;
 92  20
                                         continue;
 93  
                                 }
 94  
                                 
 95  
                                 // Convert '\n' or "\r\n" to '\r'
 96  72590
                                 if (nextChar == 10) {
 97  290
                                         if (myBuffer.length() > 0) {
 98  290
                                                 if (myBuffer.charAt(myBuffer.length() - 1) == 13) {
 99  
                                                         // don't append
 100  
                                                 } else {
 101  110
                                                         myBuffer.append((char) 13);
 102  
                                                 }
 103  
                                         }
 104  72300
                                 } else if (inComment) {
 105  300
                                         if (nextChar == 10 || nextChar == 13) {
 106  20
                                                 inComment = false;
 107  
                                         }
 108  
                                 } else {
 109  72000
                                         myBuffer.append(nextChar);
 110  
                                 }
 111  
                                 
 112  72590
                                 prev = next;
 113  
                                 
 114  72590
                                 int bLength = myBuffer.length();
 115  72590
                                 if (nextChar == 'H' && bLength >= 3) {
 116  575
                                         if (myBuffer.charAt(bLength - 2) == 'S') {
 117  170
                                                 if (myBuffer.charAt(bLength - 3) == 'M') {
 118  170
                                                         if (myFoundMessageInBuffer) {
 119  120
                                                                 if (myBuffer.charAt(bLength - 4) < 32) {
 120  120
                                                                         endOfBuffer = bLength - 3;
 121  120
                                                                         break;
 122  
                                                                 }
 123  
                                                         } else {
 124  
                                                                 // Delete any whitespace or other stuff before
 125  
                                                                 // the first message
 126  50
                                                                 myBuffer.delete(0, bLength - 3);
 127  50
                                                                 myFoundMessageInBuffer = true;
 128  
                                                         }
 129  
                                                 }
 130  
                                         }
 131  
                                 }
 132  
 
 133  72470
                         } // while(true)
 134  
 
 135  210
                         if (!myFoundMessageInBuffer) {
 136  0
                                 myHasNext = false;
 137  0
                                 return myHasNext;
 138  
                         }
 139  
 
 140  
                         String msgString;
 141  210
                         if (endOfBuffer > -1) {
 142  120
                                 msgString = myBuffer.substring(0, endOfBuffer);
 143  120
                                 myBuffer.delete(0, endOfBuffer);
 144  
                         } else {
 145  90
                                 msgString = myBuffer.toString();
 146  90
                                 myBuffer.setLength(0);
 147  
                         }
 148  
 
 149  210
                         if (!msgString.startsWith("MSH")) {
 150  40
                                 myHasNext = Boolean.FALSE;
 151  40
                                 return myHasNext;
 152  
                         }
 153  
 
 154  170
                         myNext = msgString;
 155  170
                         myHasNext = Boolean.TRUE;
 156  
 
 157  
                 }
 158  330
                 return myHasNext;
 159  
         }
 160  
 
 161  
         /**
 162  
          * {@inheritDoc}
 163  
          */
 164  
         public String next() {
 165  170
                 if (!hasNext()) {
 166  0
                         throw new IllegalStateException();
 167  
                 }
 168  170
                 String retVal = myNext;
 169  170
                 myNext = null;
 170  170
                 myHasNext = null;
 171  170
                 return retVal;
 172  
         }
 173  
 
 174  
         /**
 175  
          * Unsupported method!
 176  
          * 
 177  
          * @throws UnsupportedOperationException
 178  
          *             If called
 179  
          */
 180  
         public void remove() {
 181  0
                 throw new UnsupportedOperationException();
 182  
         }
 183  
 
 184  
         /**
 185  
          * If set to true, any lines beginning with a hash (#) will be ignored. This
 186  
          * allows you to place comments in a file to be read if needed.
 187  
          */
 188  
         public void setIgnoreComments(boolean theIgnoreComments) {
 189  5
                 myIgnoreComments = theIgnoreComments;
 190  5
         }
 191  
 
 192  
         public static class ParseFailureError extends RuntimeException {
 193  
 
 194  
                 private static final long serialVersionUID = 1L;
 195  
 
 196  
                 public ParseFailureError(String theMessage, Exception theCause) {
 197  0
                         super(theMessage, theCause);
 198  0
                 }
 199  
 
 200  
         }
 201  
 
 202  
 }