| 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 | } |