Coverage Report - ca.uhn.hl7v2.parser.GenericParser
 
Classes in this File Line Coverage Branch Coverage Complexity
GenericParser
54%
38/70
70%
14/20
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  
 }