001package ca.uhn.hl7v2.util; 002 003import java.io.InputStream; 004import java.io.Reader; 005import java.util.Iterator; 006 007import ca.uhn.hl7v2.DefaultHapiContext; 008import ca.uhn.hl7v2.HL7Exception; 009import ca.uhn.hl7v2.HapiContext; 010import ca.uhn.hl7v2.HapiContextSupport; 011import ca.uhn.hl7v2.model.Message; 012import ca.uhn.hl7v2.parser.EncodingNotSupportedException; 013import ca.uhn.hl7v2.util.Hl7InputStreamMessageStringIterator.ParseFailureError; 014import ca.uhn.hl7v2.validation.impl.ValidationContextFactory; 015 016/** 017 * <p> 018 * Reads from an {@link InputStream} containing a stream of encoded HL7 messages 019 * and iterates over those messages. This class is geared towards reading from 020 * files, and tries to be very lenient about the format of the stream, 021 * specifically concerning control characters and line endings. It should be 022 * safe to provide a stream containing Windows or Unix line endings (which will 023 * be treated as segment delimiters). It is also safe to provide a stream containing 024 * MLLP control blocks before and after each message (although these will not be 025 * validated! Do not use this class to read MLLP messages from a socket stream!) 026 * </p> 027 * <p> 028 * The input stream could, for example, be a FileInputStream reading from a text 029 * file containing a number of HL7 messages in plain text format. 030 * </p> 031 * <p> 032 * Usage note: If an IOException occurs while reading from the stream or a 033 * message parsing exception occurs, it will be thrown as an unchecked 034 * {@link ParseFailureError} 035 * </p> 036 */ 037public class Hl7InputStreamMessageIterator extends HapiContextSupport implements Iterator<Message> { 038 039 private Class<? extends Message> myMessageType; 040 private Hl7InputStreamMessageStringIterator myWrapped; 041 042 /** 043 * Constructor 044 * 045 * @param theInputStream 046 * The input stream to read from 047 */ 048 public Hl7InputStreamMessageIterator(InputStream theInputStream) { 049 this(theInputStream, new DefaultHapiContext(ValidationContextFactory.noValidation())); 050 } 051 052 /** 053 * Constructor 054 * 055 * @param theReader 056 * The reader to read from 057 */ 058 public Hl7InputStreamMessageIterator(Reader theReader) { 059 this(theReader, new DefaultHapiContext(ValidationContextFactory.noValidation())); 060 } 061 062 /** 063 * Constructor 064 * 065 * @param theInputStream 066 * The input stream to read from 067 * @param theHapiContext 068 * The HapiContext from which to obtain the parser 069 */ 070 public Hl7InputStreamMessageIterator(InputStream theInputStream, HapiContext theHapiContext) { 071 super(theHapiContext); 072 myWrapped = new Hl7InputStreamMessageStringIterator(theInputStream); 073 } 074 075 /** 076 * Constructor 077 * 078 * @param theReader 079 * The reader to read from 080 * @param theHapiContext 081 * The HapiContext from which to obtain the parser 082 */ 083 public Hl7InputStreamMessageIterator(Reader theReader, HapiContext theHapiContext) { 084 super(theHapiContext); 085 myWrapped = new Hl7InputStreamMessageStringIterator(theReader); 086 } 087 088 /** 089 * Factory method which returns an instance which reads from a file on the 090 * classpath 091 */ 092 public static Hl7InputStreamMessageIterator getForClasspathResource(String theClasspath) { 093 InputStream is = Hl7InputStreamMessageIterator.class.getResourceAsStream(theClasspath); 094 if (is == null) { 095 throw new IllegalArgumentException("Can't find resource: " + theClasspath); 096 } 097 return new Hl7InputStreamMessageIterator(is); 098 } 099 100 /** 101 * {@inheritDoc} 102 */ 103 public boolean hasNext() { 104 return myWrapped.hasNext(); 105 } 106 107 /** 108 * {@inheritDoc} 109 */ 110 public Message next() { 111 String nextString = myWrapped.next(); 112 Message retVal; 113 try { 114 if (myMessageType != null) { 115 retVal = ReflectionUtil.instantiateMessage(myMessageType, getHapiContext().getModelClassFactory()); 116 retVal.parse(nextString); 117 } else { 118 retVal = getHapiContext().getPipeParser().parse(nextString); 119 } 120 } catch (EncodingNotSupportedException e) { 121 throw new Hl7InputStreamMessageStringIterator.ParseFailureError("Failed to parse message", e); 122 } catch (HL7Exception e) { 123 throw new Hl7InputStreamMessageStringIterator.ParseFailureError("Failed to parse message", e); 124 } 125 return retVal; 126 } 127 128 /** 129 * Unsupported method! 130 * 131 * @throws UnsupportedOperationException 132 * If called 133 */ 134 public void remove() { 135 throw new UnsupportedOperationException(); 136 } 137 138 /** 139 * If set to true, any lines beginning with a hash (#) will be ignored. This allows 140 * you to place comments in a file to be read if needed. 141 */ 142 public void setIgnoreComments(boolean theIgnoreComments) { 143 myWrapped.setIgnoreComments(theIgnoreComments); 144 } 145 146 /** 147 * If set (default is <code>null</code>), all messages will be parsed into 148 * instances of this type. 149 */ 150 public void setMessageType(Class<? extends Message> theMessageType) { 151 myMessageType = theMessageType; 152 } 153 154}