001    /*
002     * Created on 21-Apr-2004
003     */
004    package ca.uhn.hl7v2.protocol.impl;
005    
006    import java.io.IOException;
007    import java.util.ArrayList;
008    import java.util.List;
009    import java.util.StringTokenizer;
010    
011    import org.slf4j.Logger;
012    import org.slf4j.LoggerFactory;
013    
014    import ca.uhn.hl7v2.HL7Exception;
015    import ca.uhn.hl7v2.model.Message;
016    import 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     */
026    public 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    }