001    /*
002     * Created on 28-Apr-2004
003     */
004    package ca.uhn.hl7v2.preparser;
005    
006    import java.util.Properties;
007    import java.util.StringTokenizer;
008    import java.util.Vector;
009    
010    import ca.uhn.hl7v2.HL7Exception;
011    import ca.uhn.hl7v2.parser.GenericParser;
012    import ca.uhn.hl7v2.util.Terser;
013    
014    /**
015     * <p>Extracts specified fields from unparsed messages.  This class is a 
016     * facade for the ER7 and XML classes.  Use it like this: </p>
017     * 
018     * <code>
019     * String message = null; //... your ER7 or XML message string goes here
020     * String[] fieldSpecs = {"MSH-9-1", "MSH-9-2", "MSH-12"};
021     * String[] fields = PreParser.getFields(message, fieldSpecs);
022     * </code>
023     * 
024     * @author <a href="mailto:bryan.tripp@uhn.on.ca">Bryan Tripp</a>
025     * @version $Revision: 1.1 $ updated on $Date: 2007/02/19 02:24:37 $ by $Author: jamesagnew $
026     */
027    public class PreParser {
028    
029        private static GenericParser ourParser = new GenericParser();
030        
031        /**
032         * Extracts selected fields from a message.  
033         *   
034         * @param theMessageText an unparsed message from which to get fields 
035         * @param thePathSpecs Terser-like paths to fields in the message.  See documentation
036         *      for Terser.  These paths are identical except that they start with the segment
037         *      name (search flags and group names are to be omitted as they are not relevant 
038         *      with unparsed ER7 messages).  
039         * @return field values corresponding to the given paths
040         * @throws HL7Exception
041         */
042        public static String[] getFields(String theMessageText, String[] thePathSpecs) throws HL7Exception {
043            DatumPath[] paths = new DatumPath[thePathSpecs.length];
044            for (int i = 0; i < thePathSpecs.length; i++) {
045                StringTokenizer tok = new StringTokenizer(thePathSpecs[i], "-", false);
046                String segSpec = tok.nextToken();
047                tok = new StringTokenizer(segSpec, "()", false);
048                String segName = tok.nextToken();
049                if (segName.length() != 3) {
050                    throw new HL7Exception("In field path, " + segName + " is not a valid segment name");
051                }
052                int segRep = 0;
053                if (tok.hasMoreTokens()) {
054                    String rep = tok.nextToken();
055                    try {
056                        segRep = Integer.parseInt(rep);
057                    } catch (NumberFormatException e) {
058                        throw new HL7Exception("In field path, segment rep" + rep + " is not valid", e);
059                    }
060                }
061                
062                int[] indices = Terser.getIndices(thePathSpecs[i]);
063                paths[i] = new DatumPath();
064                paths[i].add(segName).add(segRep);
065                paths[i].add(indices[0]).add(indices[1]).add(indices[2]).add(indices[3]);
066                
067            }
068            return getFields(theMessageText, paths);
069        }
070        
071        /** 
072         * Gets selected fields from a message, as with String[] arg version but 
073         * using DatumPaths. 
074         */     
075        private static String[] getFields(String theMessageText, DatumPath[] thePaths) throws HL7Exception {
076            String[] fields = new String[thePaths.length];
077            String encoding = ourParser.getEncoding(theMessageText);
078            Properties props = new Properties();
079            
080            Vector mask = new Vector();
081            for (int i = 0; i < thePaths.length; i++) {
082                mask.add(thePaths[i]);
083            }
084            
085            if (encoding == null) {
086                throw new HL7Exception("Message encoding is not recognized"); 
087            }
088            
089            boolean OK = false;
090            if (encoding.equals("VB")) {
091                OK = ER7.parseMessage(props, mask, theMessageText);
092            } else if (encoding.equals("XML")) {
093                OK = XML.parseMessage(props, theMessageText, null);
094            }
095            
096            if (!OK) {
097                throw new HL7Exception("Parse failed");
098            }
099            
100            for (int i = 0; i < fields.length; i++) {
101                fields[i] = props.getProperty(thePaths[i].toString());
102            }
103            return fields;
104        }    
105    
106    }