001/*
002 * Created on 21-Apr-2004
003 */
004package ca.uhn.hl7v2.protocol.impl;
005
006import java.io.IOException;
007import java.util.ArrayList;
008import java.util.List;
009import java.util.StringTokenizer;
010
011import org.slf4j.Logger;
012import org.slf4j.LoggerFactory;
013
014import ca.uhn.hl7v2.HL7Exception;
015import ca.uhn.hl7v2.model.Message;
016import ca.uhn.hl7v2.parser.Parser;
017
018/**
019 * A debugging utility that logs raw messages and parsed/encoded versions, and warnings about 
020 * apparent discrepancies between them.  This information is all logged to HapiLog under 
021 * the name of this class, at the "info" level.  
022 * 
023 * @author <a href="mailto:bryan.tripp@uhn.on.ca">Bryan Tripp</a>
024 * @version $Revision: 1.1 $ updated on $Date: 2007-02-19 02:24:26 $ by $Author: jamesagnew $
025 */
026public class ParseChecker {
027
028    private static final Logger log = LoggerFactory.getLogger(ParseChecker.class);
029
030    /**
031     * Encodes the given message and compares it to the given string.  Any differences
032     * are noted in the file [hapi.home]/parse_check.txt.  Ignores extra field delimiters.
033     */
034    public static void checkParse(String originalMessageText, Message parsedMessage, Parser parser)
035            throws HL7Exception, IOException {
036        log.info("ParseChecker is checking parse integrity (turn this off if you are not testing)");
037        String newMessageText = parser.encode(parsedMessage);
038        
039        log.info("******************* Comparing Messages ****************\r\n");
040        log.info("Original:           {}", originalMessageText);
041        log.info("Parsed and Encoded: {}", newMessageText);
042        
043        if (!originalMessageText.equals(newMessageText)) {
044            //check each segment
045            StringTokenizer tok = new StringTokenizer(originalMessageText, "\r");
046            List<String> one = new ArrayList<String>();
047            while (tok.hasMoreTokens()) {
048                String seg = tok.nextToken();
049                if (seg.length() > 4)
050                    one.add(seg);
051            }
052            tok = new StringTokenizer(newMessageText, "\r");
053            List<String> two = new ArrayList<String>();
054            while (tok.hasMoreTokens()) {
055                String seg = tok.nextToken();
056                if (seg.length() > 4)
057                    two.add(stripExtraDelimiters(seg, seg.charAt(3)));
058            }
059            
060            if (one.size() != two.size()) {
061                log.info("Warning: inbound and parsed messages have different numbers of segments: \r\n");
062                log.info("Original: {}", originalMessageText);
063                log.info("Parsed:   {}", newMessageText);
064            }
065            else {
066                //check each segment
067                for (int i = 0; i < one.size(); i++) {
068                    String origSeg = one.get(i);
069                    String newSeg = two.get(i);
070                    if (!origSeg.equals(newSeg)) {
071                        log.info("Warning: inbound and parsed message segment differs: \r\n");
072                        log.info("Original: {}", origSeg);
073                        log.info("Parsed:   {}", newSeg);
074                    }
075                }
076            }
077        }
078        else {
079            log.info("No differences found");
080        }
081        
082        log.info("********************  End Comparison  ******************\r\n");
083        
084    }
085    
086    /**
087     * Removes unecessary delimiters from the end of a field or segment.
088     * This is cut-and-pasted from PipeParser (just making it public in
089     * PipeParser would kind of cloud the purpose of PipeParser).
090     */
091    private static String stripExtraDelimiters(String in, char delim) {
092        char[] chars = in.toCharArray();
093        
094        //search from back end for first occurance of non-delimiter ...
095        int c = chars.length - 1;
096        boolean found = false;
097        while (c >= 0 && !found) {
098            if (chars[c--] != delim)
099                found = true;
100        }
101        
102        String ret = "";
103        if (found)
104            ret = String.valueOf(chars, 0, c + 2);
105        return ret;
106    }
107    
108    
109}