View Javadoc
1   package ca.uhn.hl7v2.util;
2   
3   import java.io.InputStream;
4   import java.io.Reader;
5   import java.util.Iterator;
6   
7   import ca.uhn.hl7v2.DefaultHapiContext;
8   import ca.uhn.hl7v2.HL7Exception;
9   import ca.uhn.hl7v2.HapiContext;
10  import ca.uhn.hl7v2.HapiContextSupport;
11  import ca.uhn.hl7v2.model.Message;
12  import ca.uhn.hl7v2.parser.EncodingNotSupportedException;
13  import ca.uhn.hl7v2.util.Hl7InputStreamMessageStringIterator.ParseFailureError;
14  import ca.uhn.hl7v2.validation.impl.ValidationContextFactory;
15  
16  /**
17   * <p>
18   * Reads from an {@link InputStream} containing a stream of encoded HL7 messages
19   * and iterates over those messages. This class is geared towards reading from
20   * files, and tries to be very lenient about the format of the stream,
21   * specifically concerning control characters and line endings. It should be
22   * safe to provide a stream containing Windows or Unix line endings (which will
23   * be treated as segment delimiters). It is also safe to provide a stream containing
24   * MLLP control blocks before and after each message (although these will not be
25   * validated! Do not use this class to read MLLP messages from a socket stream!)
26   * </p>
27   * <p>
28   * The input stream could, for example, be a FileInputStream reading from a text
29   * file containing a number of HL7 messages in plain text format.
30   * </p>
31   * <p>
32   * Usage note: If an IOException occurs while reading from the stream or a
33   * message parsing exception occurs, it will be thrown as an unchecked
34   * {@link ParseFailureError}
35   * </p>
36   */
37  public class Hl7InputStreamMessageIterator extends HapiContextSupport implements Iterator<Message> {
38  
39  	private Class<? extends Message> myMessageType;
40  	private final Hl7InputStreamMessageStringIterator myWrapped;
41  
42  	/**
43  	 * Constructor
44  	 * 
45  	 * @param theInputStream
46  	 *            The input stream to read from
47  	 */
48  	public Hl7InputStreamMessageIterator(InputStream theInputStream) {
49          this(theInputStream, new DefaultHapiContext(ValidationContextFactory.noValidation()));
50  	}
51  
52  	/**
53  	 * Constructor
54  	 * 
55  	 * @param theReader
56  	 *            The reader to read from
57  	 */
58  	public Hl7InputStreamMessageIterator(Reader theReader) {
59  		this(theReader, new DefaultHapiContext(ValidationContextFactory.noValidation()));
60  	}
61  
62  	/**
63  	 * Constructor
64  	 * 
65  	 * @param theInputStream
66  	 *            The input stream to read from
67  	 * @param theHapiContext
68  	 * 			 The HapiContext from which to obtain the parser
69  	 */
70  	public Hl7InputStreamMessageIterator(InputStream theInputStream, HapiContext theHapiContext) {
71  	    super(theHapiContext);
72  		myWrapped = new Hl7InputStreamMessageStringIterator(theInputStream);
73  	}
74  
75  	/**
76  	 * Constructor
77  	 * 
78  	 * @param theReader
79  	 *            The reader to read from
80  	 * @param theHapiContext
81  	 * 			 The HapiContext from which to obtain the parser
82  	 */
83  	public Hl7InputStreamMessageIterator(Reader theReader, HapiContext theHapiContext) {
84          super(theHapiContext);
85  		myWrapped = new Hl7InputStreamMessageStringIterator(theReader);
86  	}
87  
88  	/**
89  	 * Factory method which returns an instance which reads from a file on the
90  	 * classpath
91  	 */
92  	public static Hl7InputStreamMessageIterator getForClasspathResource(String theClasspath) {
93  		InputStream is = Hl7InputStreamMessageIterator.class.getResourceAsStream(theClasspath);
94  		if (is == null) {
95  			throw new IllegalArgumentException("Can't find resource: " + theClasspath);
96  		}
97  		return new Hl7InputStreamMessageIterator(is);
98  	}
99  	
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 (HL7Exception e) {
121 			throw new ParseFailureError("Failed to parse message", e);
122 		}
123         return retVal;
124 	}
125 
126 	/**
127 	 * Unsupported method!
128 	 * 
129 	 * @throws UnsupportedOperationException
130 	 *             If called
131 	 */
132 	public void remove() {
133 		throw new UnsupportedOperationException();
134 	}
135 
136 	/**
137 	 * If set to true, any lines beginning with a hash (#) will be ignored. This allows
138 	 * you to place comments in a file to be read if needed.
139 	 */
140 	public void setIgnoreComments(boolean theIgnoreComments) {
141 		myWrapped.setIgnoreComments(theIgnoreComments);
142 	}
143 
144 	/**
145 	 * If set (default is <code>null</code>), all messages will be parsed into
146 	 * instances of this type. 
147 	 */
148 	public void setMessageType(Class<? extends Message> theMessageType) {
149 		myMessageType = theMessageType;
150 	}
151 
152 }