/**
The contents of this file are subject to the Mozilla Public License Version 1.1
(the "License"); you may not use this file except in compliance with the License.
You may obtain a copy of the License at http://www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the
specific language governing rights and limitations under the License.
The Original Code is "Parser.java". Description:
"Parses HL7 message Strings into HL7 Message objects and
encodes HL7 Message objects into HL7 message Strings"
The Initial Developer of the Original Code is University Health Network. Copyright (C)
2001. All Rights Reserved.
Contributor(s): ______________________________________.
Alternatively, the contents of this file may be used under the terms of the
GNU General Public License (the "GPL"), in which case the provisions of the GPL are
applicable instead of those above. If you wish to allow use of your version of this
file only under the terms of the GPL and not to allow others to use your version
of this file under the MPL, indicate your decision by deleting the provisions above
and replace them with the notice and other provisions required by the GPL License.
If you do not delete the provisions above, a recipient may use your version of
this file under either the MPL or the GPL.
*/
package ca.uhn.hl7v2.parser;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import ca.uhn.hl7v2.HL7Exception;
import ca.uhn.hl7v2.VersionLogger;
import ca.uhn.hl7v2.model.GenericMessage;
import ca.uhn.hl7v2.model.Group;
import ca.uhn.hl7v2.model.Message;
import ca.uhn.hl7v2.model.Segment;
import ca.uhn.hl7v2.model.Type;
import ca.uhn.hl7v2.validation.MessageValidator;
import ca.uhn.hl7v2.validation.ValidationContext;
import ca.uhn.hl7v2.validation.ValidationException;
import ca.uhn.hl7v2.validation.impl.DefaultValidation;
import ca.uhn.hl7v2.validation.impl.ValidationContextFactory;
import ca.uhn.log.HapiLog;
import ca.uhn.log.HapiLogFactory;
/**
* Parses HL7 message Strings into HL7 Message objects and
* encodes HL7 Message objects into HL7 message Strings.
* @author Bryan Tripp (bryan_tripp@sourceforge.net)
*/
public abstract class Parser {
private static final HapiLog log = HapiLogFactory.getHapiLog(Parser.class);
private static Map Returns a minimal amount of data from a message string, including only the
* data needed to send a response to the remote system. This includes the
* following fields:
* null
*/
public ValidationContext getValidationContext() {
return myContext;
}
/**
* @param theContext the set of validation rules to be applied to messages parsed or
* encoded by this parser (defaults to ValidationContextFactory.DefaultValidation)
*/
public void setValidationContext(ValidationContext theContext) {
myContext = theContext;
myValidator = new MessageValidator(theContext, true);
}
/**
* Returns a String representing the encoding of the given message, if
* the encoding is recognized. For example if the given message appears
* to be encoded using HL7 2.x XML rules then "XML" would be returned.
* If the encoding is not recognized then null is returned. That this
* method returns a specific encoding does not guarantee that the
* message is correctly encoded (e.g. well formed XML) - just that
* it is not encoded using any other encoding than the one returned.
* Returns null if the encoding is not recognized.
*/
public abstract String getEncoding(String message);
/**
* Returns true if and only if the given encoding is supported
* by this Parser.
*/
public abstract boolean supportsEncoding(String encoding);
/**
* @return the preferred encoding of this Parser
*/
public abstract String getDefaultEncoding();
/**
* Parses a message string and returns the corresponding Message object.
*
* @param message a String that contains an HL7 message
* @return a HAPI Message object parsed from the given String
* @throws HL7Exception if the message is not correctly formatted.
* @throws EncodingNotSupportedException if the message encoded
* is not supported by this parser.
*/
public Message parse(String message) throws HL7Exception, EncodingNotSupportedException {
String encoding = getEncoding(message);
if (!supportsEncoding(encoding)) {
throw new EncodingNotSupportedException(
"Can't parse message beginning " + message.substring(0, Math.min(message.length(), 50)));
}
String version = getVersion(message);
if (!validVersion(version)) {
throw new HL7Exception("Can't process message of version '" + version + "' - version not recognized",
HL7Exception.UNSUPPORTED_VERSION_ID);
}
myValidator.validate(message, encoding.equals("XML"), version);
Message result = doParse(message, version);
myValidator.validate(result);
result.setParser(this);
return result;
}
/**
* Parses a message string and returns the corresponding Message object.
*
* @param message a String that contains an HL7 message
* @return a HAPI Message object parsed from the given String
* @throws HL7Exception if the message is not correctly formatted.
* @throws EncodingNotSupportedException if the message encoded
* is not supported by this parser.
*/
public Message parseForSpecificPackage(String message, String packageName) throws HL7Exception, EncodingNotSupportedException {
String encoding = getEncoding(message);
if (!supportsEncoding(encoding)) {
throw new EncodingNotSupportedException(
"Can't parse message beginning " + message.substring(0, Math.min(message.length(), 50)));
}
String version = getVersion(message);
if (!validVersion(version)) {
throw new HL7Exception("Can't process message of version '" + version + "' - version not recognized",
HL7Exception.UNSUPPORTED_VERSION_ID);
}
myValidator.validate(message, encoding.equals("XML"), version);
Message result = doParseForSpecificPackage(message, version, packageName);
myValidator.validate(result);
result.setParser(this);
return result;
}
/**
* Parses a message string and returns the corresponding Message object.
* Unexpected segments added at the end of their group.
*
* @throws HL7Exception
* if the message is not correctly formatted.
* @throws EncodingNotSupportedException
* if the message encoded is not supported by this parser.
*/
public Message doParseForSpecificPackage(String message, String version, String packageName) throws HL7Exception, EncodingNotSupportedException {
Message m = null;
return m;
}
/**
* Called by parse() to perform implementation-specific parsing work.
*
* @param message a String that contains an HL7 message
* @param version the name of the HL7 version to which the message belongs (eg "2.5")
* @return a HAPI Message object parsed from the given String
* @throws HL7Exception if the message is not correctly formatted.
* @throws EncodingNotSupportedException if the message encoded
* is not supported by this parser.
*/
protected abstract Message doParse(String message, String version)
throws HL7Exception, EncodingNotSupportedException;
/**
* Formats a Message object into an HL7 message string using the given
* encoding.
*
* @param source a Message object from which to construct an encoded message string
* @param encoding the name of the HL7 encoding to use (eg "XML"; most implementations support only
* one encoding)
* @return the encoded message
* @throws HL7Exception if the data fields in the message do not permit encoding
* (e.g. required fields are null)
* @throws EncodingNotSupportedException if the requested encoding is not
* supported by this parser.
*/
public String encode(Message source, String encoding) throws HL7Exception, EncodingNotSupportedException {
myValidator.validate(source);
String result = doEncode(source, encoding);
myValidator.validate(result, encoding.equals("XML"), source.getVersion());
return result;
}
/**
* Called by encode(Message, String) to perform implementation-specific encoding work.
*
* @param source a Message object from which to construct an encoded message string
* @param encoding the name of the HL7 encoding to use (eg "XML"; most implementations support only
* one encoding)
* @return the encoded message
* @throws HL7Exception if the data fields in the message do not permit encoding
* (e.g. required fields are null)
* @throws EncodingNotSupportedException if the requested encoding is not
* supported by this parser.
*/
protected abstract String doEncode(Message source, String encoding)
throws HL7Exception, EncodingNotSupportedException;
/**
* Formats a Message object into an HL7 message string using this parser's
* default encoding.
*
* @param source a Message object from which to construct an encoded message string
* @param encoding the name of the encoding to use (eg "XML"; most implementations support only one
* encoding)
* @return the encoded message
* @throws HL7Exception if the data fields in the message do not permit encoding
* (e.g. required fields are null)
*/
public String encode(Message source) throws HL7Exception {
String encoding = getDefaultEncoding();
myValidator.validate(source);
String result = doEncode(source);
myValidator.validate(result, encoding.equals("XML"), source.getVersion());
return result;
}
/**
* Called by encode(Message) to perform implementation-specific encoding work.
*
* @param source a Message object from which to construct an encoded message string
* @return the encoded message
* @throws HL7Exception if the data fields in the message do not permit encoding
* (e.g. required fields are null)
* @throws EncodingNotSupportedException if the requested encoding is not
* supported by this parser.
*/
protected abstract String doEncode(Message source) throws HL7Exception;
/**
*
* This method is intended for use when there is an error parsing a message,
* (so the Message object is unavailable) but an error message must be sent
* back to the remote system including some of the information in the inbound
* message. This method parses only that required information, hopefully
* avoiding the condition that caused the original error.