ca.uhn.hl7v2.util.ParseTester Maven / Gradle / Ivy
package ca.uhn.hl7v2.util;
import ca.uhn.hl7v2.parser.*;
import ca.uhn.hl7v2.HL7Exception;
import ca.uhn.hl7v2.model.Message;
import java.io.*;
import java.util.ArrayList;
/**
* Tests correctness of message parsing by testing equivalence of re-encoded
* form with original.
* @author Bryan Tripp
*/
public class ParseTester {
private static GenericParser parser = new GenericParser();
private BufferedReader source;
private String context;
/** Creates a new instance of ParseTester */
public ParseTester() {
}
/**
* Checks whether the given message parses correctly with a GenericParser.
* Failure indicates that the parsed and re-encoded message is semantically
* different than the original, or that the message could not be parsed. This
* may stem from an error in the parser, or from an error in the message. This
* may also arise from unexpected message components (e.g. Z-segments) although
* in future HAPI versions these will be parsed as well.
* @param message an XML or ER7 encoded message string
* @return null if it parses correctly, an HL7Exception otherwise
*/
public static HL7Exception parsesCorrectly(String context, String message) {
HL7Exception problem = null;
try {
Message m = parser.parse(message);
String encoding = parser.getEncoding(message);
String result = parser.encode(m, encoding);
if (!EncodedMessageComparator.equivalent(message, result)) {
problem = new HL7Exception(context + ": Original differs semantically from parsed/encoded message.\r\n-----Original:------------\r\n"
+ message + " \r\n------ Parsed/Encoded: ----------\r\n" + result + " \r\n-----Original Standardized: ---------\r\n"
+ EncodedMessageComparator.standardize(message) + " \r\n---------------------\r\n");
}
} catch (Exception e) {
problem = new HL7Exception(context + ": " + e.getMessage() + " in message: \r\n-------------\r\n" + message + "\r\n-------------");;
}
return problem;
}
/**
* Sets the source of message data (messages must be delimited by blank lines)
*/
public void setSource(Reader source) {
this.source = new BufferedReader(new CommentFilterReader(source));
}
/**
* Sets a description of the context of the messages (e.g. file name) that can be
* reported within error messages.
*/
public void setContext(String description) {
this.context = description;
}
/**
* Sets the source reader to point to the given file, and tests
* all the messages therein (if a directory, processes all contained
* files recursively).
*/
public HL7Exception[] testAll(File source) throws IOException {
ArrayList list = new ArrayList();
System.out.println("Testing " + source.getPath());
if (source.isDirectory()) {
File[] contents = source.listFiles();
for (int i = 0; i < contents.length; i++) {
HL7Exception[] exceptions = testAll(contents[i]);
for (int j = 0; j < exceptions.length; j++) {
list.add(exceptions[j]);
}
}
} else if (source.isFile()) {
FileReader in = new FileReader(source);
setSource(in);
setContext(source.getAbsolutePath());
HL7Exception[] exceptions = testAll();
for (int i = 0; i < exceptions.length; i++) {
list.add(exceptions[i]);
}
} else {
System.out.println("Warning: " + source.getPath() + " is not a normal file");
}
return (HL7Exception[]) list.toArray(new HL7Exception[0]);
}
/**
* Tests all remaining messages available from the currrent source.
*/
public HL7Exception[] testAll() throws IOException {
ArrayList list = new ArrayList();
String message = null;
while ((message = getNextMessage()).length() > 0) {
HL7Exception e = parsesCorrectly(this.context, message);
if (e != null) list.add(e);
}
return (HL7Exception[]) list.toArray(new HL7Exception[0]);
}
/**
* Retrieves the next message (setSource() must be called first). The next message
* is interpreted as everything up to the next blank line, not including
* C or C++ style comments (or blank lines themselves). An empty string
* indicates that there are no more messages.
*/
public String getNextMessage() throws IOException {
if (this.source == null) throw new IOException("Message source is null -- call setSource() first");
StringBuffer message = new StringBuffer();
boolean started = false; //got at least one non-blank line
boolean finished = false; //got a blank line after started, or end of stream
while (!finished) {
String line = this.source.readLine();
if (line == null || (started && line.trim().length() == 0)) {
finished = true;
} else {
if (line.trim().length() > 0) {
started = true;
message.append(line);
message.append("\r");
}
}
}
if (message.toString().trim().length() == 0) {
return "";
} else {
return message.toString(); // can't trim by default (will omit final end-segment)
}
}
/**
* Command line tool for testing messages in files.
*/
public static void main(String args[]) {
if (args.length != 1
|| args[0].equalsIgnoreCase("-?")
|| args[0].equalsIgnoreCase("-h")
|| args[0].equalsIgnoreCase("-help")) {
System.out.println("USAGE:");
System.out.println(" ParseTester