Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
GenericParser |
|
| 1.5384615384615385;1.538 |
1 | /** | |
2 | The contents of this file are subject to the Mozilla Public License Version 1.1 | |
3 | (the "License"); you may not use this file except in compliance with the License. | |
4 | You may obtain a copy of the License at http://www.mozilla.org/MPL/ | |
5 | Software distributed under the License is distributed on an "AS IS" basis, | |
6 | WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the | |
7 | specific language governing rights and limitations under the License. | |
8 | ||
9 | The Original Code is "GenericParser.java". Description: | |
10 | "A Parser that delegates parsing tasks to an underlying PipeParser and DefaultXMLParser" | |
11 | ||
12 | The Initial Developer of the Original Code is University Health Network. Copyright (C) | |
13 | 2001. All Rights Reserved. | |
14 | ||
15 | Contributor(s): ______________________________________. | |
16 | ||
17 | Alternatively, the contents of this file may be used under the terms of the | |
18 | GNU General Public License (the �GPL�), in which case the provisions of the GPL are | |
19 | applicable instead of those above. If you wish to allow use of your version of this | |
20 | file only under the terms of the GPL and not to allow others to use your version | |
21 | of this file under the MPL, indicate your decision by deleting the provisions above | |
22 | and replace them with the notice and other provisions required by the GPL License. | |
23 | If you do not delete the provisions above, a recipient may use your version of | |
24 | this file under either the MPL or the GPL. | |
25 | ||
26 | */ | |
27 | package ca.uhn.hl7v2.parser; | |
28 | ||
29 | import ca.uhn.hl7v2.DefaultHapiContext; | |
30 | import ca.uhn.hl7v2.HL7Exception; | |
31 | import ca.uhn.hl7v2.HapiContext; | |
32 | import ca.uhn.hl7v2.model.Message; | |
33 | import ca.uhn.hl7v2.model.Segment; | |
34 | import ca.uhn.hl7v2.model.Type; | |
35 | import ca.uhn.hl7v2.validation.ValidationContext; | |
36 | import ca.uhn.hl7v2.validation.impl.NoValidation; | |
37 | import ca.uhn.hl7v2.validation.impl.ValidationContextFactory; | |
38 | ||
39 | /** | |
40 | * A Parser that delegates parsing tasks to an underlying PipeParser and DefaultXMLParser as needed. | |
41 | * Messages to be parsed are inspected in order to determine which Parser to use. If a message is to | |
42 | * be encoded, the "primary" Parser will be used. The primary parser defaults to PipeParser, and can | |
43 | * be configured using the set...AsPrimary() methods. | |
44 | * | |
45 | * @author Bryan Tripp | |
46 | */ | |
47 | public class GenericParser extends Parser { | |
48 | ||
49 | private Parser primaryParser; | |
50 | private Parser secondaryParser; | |
51 | private final PipeParser pipeParser; | |
52 | private final XMLParser xmlParser; | |
53 | ||
54 | /** Creates a new instance of GenericParser */ | |
55 | public GenericParser() { | |
56 | 160 | this(new DefaultHapiContext()); |
57 | 160 | } |
58 | ||
59 | /** | |
60 | * @param context the HapiContext to be used | |
61 | */ | |
62 | public GenericParser(HapiContext context) { | |
63 | 375 | super(context); |
64 | 375 | pipeParser = new PipeParser(context); |
65 | 375 | xmlParser = new DefaultXMLParser(context); |
66 | 375 | setPipeParserAsPrimary(); |
67 | 375 | } |
68 | ||
69 | /** | |
70 | * Creates a new instance of GenericParser | |
71 | * | |
72 | * @param theFactory custom factory to use for model class lookup | |
73 | */ | |
74 | public GenericParser(ModelClassFactory theFactory) { | |
75 | 0 | super(theFactory); |
76 | ||
77 | 0 | pipeParser = new PipeParser(theFactory); |
78 | 0 | xmlParser = new DefaultXMLParser(theFactory); |
79 | 0 | setPipeParserAsPrimary(); |
80 | 0 | } |
81 | ||
82 | /** | |
83 | * Sets the underlying XMLParser as the primary parser, so that subsequent calls to encode() | |
84 | * will return XML encoded messages, and an attempt will be made to use the XMLParser first for | |
85 | * parsing. | |
86 | */ | |
87 | public void setXMLParserAsPrimary() { | |
88 | 0 | primaryParser = xmlParser; |
89 | 0 | secondaryParser = pipeParser; |
90 | 0 | } |
91 | ||
92 | /** | |
93 | * Sets the underlying PipeParser as the primary parser, so that subsequent calls to encode() | |
94 | * will return traditionally encoded messages, and an attempt will be made to use the PipeParser | |
95 | * first for parsing. This is the default setting. | |
96 | */ | |
97 | public void setPipeParserAsPrimary() { | |
98 | 375 | primaryParser = pipeParser; |
99 | 375 | secondaryParser = xmlParser; |
100 | 375 | } |
101 | ||
102 | /** | |
103 | * Returns true if the pipe parser is primary | |
104 | * | |
105 | * @return true if the pipe parser is primary | |
106 | */ | |
107 | public boolean isPipeParserPrimary() { | |
108 | 0 | return primaryParser == pipeParser; |
109 | } | |
110 | ||
111 | /** | |
112 | * @param theContext the set of validation rules to be applied to messages parsed or encoded by | |
113 | * this parser (defaults to ValidationContextFactory.DefaultValidation) | |
114 | * | |
115 | * @deprecated use a dedicated {@link HapiContext} and set its ValidationContext property | |
116 | */ | |
117 | public void setValidationContext(ValidationContext theContext) { | |
118 | 0 | super.setValidationContext(theContext); |
119 | ||
120 | // These parsers are not yet initialized when this is called during the Parser constructor | |
121 | 0 | if (xmlParser != null) { |
122 | 0 | pipeParser.setValidationContext(theContext); |
123 | 0 | xmlParser.setValidationContext(theContext); |
124 | } | |
125 | 0 | } |
126 | ||
127 | /** | |
128 | * Checks the encoding of the message using getEncoding(), and returns the corresponding parser | |
129 | * (either pipeParser or xmlParser). If the encoding is not recognized an HL7Exception is | |
130 | * thrown. | |
131 | */ | |
132 | private Parser getAppropriateParser(String message) throws HL7Exception { | |
133 | 2955 | String encoding = getEncoding(message); |
134 | 2955 | if ("VB".equalsIgnoreCase(encoding)) return pipeParser; |
135 | 65 | if ("XML".equalsIgnoreCase(encoding)) return xmlParser; |
136 | 15 | throw new HL7Exception("Can't find appropriate parser - encoding not recognized"); |
137 | } | |
138 | ||
139 | /** | |
140 | * Formats a Message object into an HL7 message string using the given encoding. | |
141 | * | |
142 | * @throws HL7Exception if the data fields in the message do not permit encoding (e.g. required | |
143 | * fields are null) | |
144 | * @throws EncodingNotSupportedException if the requested encoding is not supported by this | |
145 | * parser. | |
146 | */ | |
147 | protected String doEncode(Message source, String encoding) throws HL7Exception, | |
148 | EncodingNotSupportedException { | |
149 | 455 | String ret = null; |
150 | 455 | if (encoding == null) |
151 | 0 | encoding = ""; // prevent null pointer exception |
152 | 455 | if (encoding.equalsIgnoreCase("VB")) { |
153 | 445 | ret = pipeParser.doEncode(source); |
154 | 10 | } else if (encoding.equalsIgnoreCase("XML")) { |
155 | 10 | ret = xmlParser.doEncode(source); |
156 | } else { | |
157 | 0 | throw new EncodingNotSupportedException("The encoding " + encoding |
158 | 0 | + " is not supported by " + this.getClass().getName()); |
159 | } | |
160 | 455 | return ret; |
161 | } | |
162 | ||
163 | /** | |
164 | * <p> | |
165 | * Returns a minimal amount of data from a message string, including only the data needed to | |
166 | * send a response to the remote system. This includes the following fields: | |
167 | * <ul> | |
168 | * <li>field separator</li> | |
169 | * <li>encoding characters</li> | |
170 | * <li>processing ID</li> | |
171 | * <li>message control ID</li> | |
172 | * </ul> | |
173 | * This method is intended for use when there is an error parsing a message, (so the Message | |
174 | * object is unavailable) but an error message must be sent back to the remote system including | |
175 | * some of the information in the inbound message. This method parses only that required | |
176 | * information, hopefully avoiding the condition that caused the original error. | |
177 | * </p> | |
178 | */ | |
179 | public Segment getCriticalResponseData(String message) throws HL7Exception { | |
180 | 85 | return getAppropriateParser(message).getCriticalResponseData(message); |
181 | } | |
182 | ||
183 | /** | |
184 | * Returns the version ID (MSH-12) from the given message, without fully parsing the message. | |
185 | * The version is needed prior to parsing in order to determine the message class into which the | |
186 | * text of the message should be parsed. | |
187 | * | |
188 | * @throws HL7Exception if the version field can not be found. | |
189 | */ | |
190 | public String getVersion(String message) throws HL7Exception { | |
191 | 830 | return getAppropriateParser(message).getVersion(message); |
192 | } | |
193 | ||
194 | /** | |
195 | * Returns a String representing the encoding of the given message, if the encoding is | |
196 | * recognized. For example if the given message appears to be encoded using HL7 2.x XML rules | |
197 | * then "XML" would be returned. If the encoding is not recognized then null is returned. That | |
198 | * this method returns a specific encoding does not guarantee that the message is correctly | |
199 | * encoded (e.g. well formed XML) - just that it is not encoded using any other encoding than | |
200 | * the one returned. Returns null if the encoding is not recognized. | |
201 | */ | |
202 | public String getEncoding(String message) { | |
203 | 4330 | String encoding = primaryParser.getEncoding(message); |
204 | 4330 | return (encoding == null ? secondaryParser.getEncoding(message) : encoding); |
205 | } | |
206 | ||
207 | /** | |
208 | * For response messages, returns the value of MSA-2 (the message ID of the message sent by the | |
209 | * sending system). This value may be needed prior to main message parsing, so that | |
210 | * (particularly in a multi-threaded scenario) the message can be routed to the thread that sent | |
211 | * the request. We need this information first so that any parse exceptions are thrown to the | |
212 | * correct thread. Implementers of Parsers should take care to make the implementation of this | |
213 | * method very fast and robust. Returns null if MSA-2 can not be found (e.g. if the message is | |
214 | * not a response message). | |
215 | */ | |
216 | public String getAckID(String message) { | |
217 | try { | |
218 | 440 | return getAppropriateParser(message).getAckID(message); |
219 | 0 | } catch (HL7Exception e) { |
220 | 0 | return null; |
221 | } | |
222 | } | |
223 | ||
224 | /** | |
225 | * Returns true if and only if the given encoding is supported by this Parser. | |
226 | */ | |
227 | public boolean supportsEncoding(String encoding) { | |
228 | 840 | return (primaryParser.supportsEncoding(encoding) || secondaryParser.supportsEncoding(encoding)); |
229 | } | |
230 | ||
231 | /** | |
232 | * @return the preferred encoding of the current primary Parser | |
233 | */ | |
234 | public String getDefaultEncoding() { | |
235 | 110 | return primaryParser.getDefaultEncoding(); |
236 | } | |
237 | ||
238 | /** | |
239 | * Parses a message string and returns the corresponding Message object. | |
240 | * | |
241 | * @throws HL7Exception if the message is not correctly formatted. | |
242 | * @throws EncodingNotSupportedException if the message encoded is not supported by this parser. | |
243 | */ | |
244 | protected Message doParse(String message, String version) throws HL7Exception { | |
245 | 815 | return getAppropriateParser(message).doParse(message, version); |
246 | } | |
247 | ||
248 | /** | |
249 | * {@inheritDoc} | |
250 | */ | |
251 | @Override | |
252 | public Message parse(String theMessage) throws HL7Exception { | |
253 | 840 | Message retVal = super.parse(theMessage); |
254 | 785 | Parser parser = getAppropriateParser(theMessage); |
255 | 785 | retVal.setParser(parser); |
256 | 785 | return retVal; |
257 | } | |
258 | ||
259 | /** | |
260 | * Formats a Message object into an HL7 message string using this parser's default encoding. | |
261 | * | |
262 | * @throws HL7Exception if the data fields in the message do not permit encoding (e.g. required | |
263 | * fields are null) | |
264 | */ | |
265 | protected String doEncode(Message source) throws HL7Exception { | |
266 | 110 | return primaryParser.doEncode(source); |
267 | } | |
268 | ||
269 | /** | |
270 | * {@inheritDoc } | |
271 | */ | |
272 | @Override | |
273 | public String doEncode(Segment structure, EncodingCharacters encodingCharacters) | |
274 | throws HL7Exception { | |
275 | 0 | return primaryParser.doEncode(structure, encodingCharacters); |
276 | } | |
277 | ||
278 | /** | |
279 | * {@inheritDoc } | |
280 | */ | |
281 | @Override | |
282 | public String doEncode(Type type, EncodingCharacters encodingCharacters) throws HL7Exception { | |
283 | 0 | return primaryParser.doEncode(type, encodingCharacters); |
284 | } | |
285 | ||
286 | /** | |
287 | * {@inheritDoc } | |
288 | */ | |
289 | @Override | |
290 | public void parse(Type type, String string, EncodingCharacters encodingCharacters) | |
291 | throws HL7Exception { | |
292 | 10 | primaryParser.parse(type, string, encodingCharacters); |
293 | 10 | } |
294 | ||
295 | /** | |
296 | * {@inheritDoc } | |
297 | */ | |
298 | @Override | |
299 | public void parse(Segment segment, String string, EncodingCharacters encodingCharacters) | |
300 | throws HL7Exception { | |
301 | 0 | primaryParser.parse(segment, string, encodingCharacters); |
302 | 0 | } |
303 | ||
304 | @Override | |
305 | public void parse(Message message, String string) throws HL7Exception { | |
306 | 5 | primaryParser.parse(message, string); |
307 | 5 | } |
308 | ||
309 | /** | |
310 | * Convenience factory method which returns an instance that has a {@link NoValidation | |
311 | * NoValidation validation context}. | |
312 | * | |
313 | * @return instance of GenericParser without validation | |
314 | */ | |
315 | public static GenericParser getInstanceWithNoValidation() { | |
316 | 0 | return new GenericParser( |
317 | 0 | new DefaultHapiContext(ValidationContextFactory.noValidation())); |
318 | } | |
319 | ||
320 | @Override | |
321 | protected Message doParseForSpecificPackage(String theMessage, String theVersion, | |
322 | String thePackageName) throws HL7Exception, EncodingNotSupportedException { | |
323 | 0 | return primaryParser.doParseForSpecificPackage(theMessage, theVersion, thePackageName); |
324 | } | |
325 | ||
326 | public static void main(String[] args) throws HL7Exception { | |
327 | ||
328 | 0 | String msgString = "MSH|^~\\&|RAMSOFT|SENDING FACILITY|RAMSOFT|RECEIVING FACILITY|20101223202939-0400||ADT^A08|101|P|2.3.1||||||||\r" |
329 | + "EVN|A08|20101223202939-0400||||\r" | |
330 | + "PID||P12345^^^ISSUER|P12345^^^ISSUER||PATIENT^TEST^M^^^^||19741018|M|||10808 FOOTHILL BLVD^^RANCHO CUCAMONGA^CA^91730^US||(909)481-5872^^^sales@ramsoft.com|(909)481-5800x1||M||12345|286-50-9510|||\r" | |
331 | + "PV1||O||||||||||||||||||||||||||||||||||||||||||||||||||\r" | |
332 | + "AL1|1||^PORK^|\r" | |
333 | + "AL1|2||^PENICILLIN^|"; | |
334 | ||
335 | 0 | GenericParser parser = new GenericParser(); |
336 | 0 | parser.setValidationContext(ValidationContextFactory.noValidation()); |
337 | 0 | Message msg = parser.parse(msgString); |
338 | 0 | System.out.println(msg.getClass().getName()); |
339 | ||
340 | 0 | } |
341 | ||
342 | ||
343 | ||
344 | } |