Coverage Report - us.daveread.utility.formatcheck.format.FormatTypeParser
 
Classes in this File Line Coverage Branch Coverage Complexity
FormatTypeParser
0%
0/153
0%
0/28
2.833
 
 1  
 package us.daveread.utility.formatcheck.format;
 2  
 
 3  
 import org.xml.sax.*;
 4  
 import org.xml.sax.helpers.*;
 5  
 import java.io.File;
 6  
 import org.apache.log4j.Logger;
 7  
 
 8  
 /**
 9  
  * <p>Title: FormatTypeParser
 10  
  * <p>Description: Parses the format definition files, setting up the
 11  
  *   classes and properties as defined in the XML.
 12  
  * <p>Copyright: Copyright (c) 2005
 13  
  * <p>This program is free software; you can redistribute it and/or modify
 14  
  * it under the terms of the GNU General Public License as published by
 15  
  * the Free Software Foundation; either version 2 of the License, or
 16  
  * (at your option) any later version.
 17  
  * <p>This program is distributed in the hope that it will be useful,
 18  
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 19  
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 20  
  * GNU General Public License for more details.
 21  
  * <p>You should have received a copy of the GNU General Public License
 22  
  * along with this program; if not, write to the Free Software
 23  
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 24  
  * </p>
 25  
  *
 26  
  * @author David Read
 27  
  * @version $Id: FormatTypeParser.java,v 1.2 2006/06/14 23:31:08 daveread Exp $
 28  
  */
 29  
 public class FormatTypeParser extends FormatType implements ContentHandler,
 30  
         ErrorHandler {
 31  
 
 32  
     /** The maximum number of errors to hold for reporting back to the user */
 33  
     private final static int MAX_ERRORS = 10;
 34  
 
 35  
     /** The XML input file being loaded */
 36  
     private File inputFile;
 37  
 
 38  
     /** The current location within the XML file */
 39  
     private Locator objcLocator;
 40  
 
 41  
     /** The current record type being loaded from the XML file */
 42  
     private RecordType currentRecordType;
 43  
 
 44  
     /** The current field type being loaded from the XML file */
 45  
     private FieldType currentFieldType;
 46  
 
 47  
     /** The current data type being loaded from the XML file */
 48  
     private DataType currentDataType;
 49  
 
 50  
     /** Logger */
 51  0
     private static final Logger logger = Logger.getLogger(FormatTypeParser.class);
 52  
 
 53  
     /**
 54  
      * The collection of error and fatal error messages being held for
 55  
      * presentation back to the user
 56  
      */
 57  
     private StringBuffer errorMessages;
 58  
 
 59  
     /**
 60  
      * Flag to stop processing of XML file (other than parsing) if errors are
 61  
      * encountered
 62  
      */
 63  
     private boolean okayToProcess;
 64  
 
 65  
     /** The number of errors held for presentation back to the user */
 66  
     private int numErrors;
 67  
 
 68  
     /**
 69  
      * Parses an XML format definition file, creating the objects required to
 70  
      * enforce the specifications in the XML definition.
 71  
      *
 72  
      * @param aInputFile File The XML format definition file
 73  
      */
 74  0
     public FormatTypeParser(File aInputFile) {
 75  
         XMLReader reader;
 76  
 
 77  0
         inputFile = aInputFile;
 78  0
         errorMessages = new StringBuffer();
 79  0
         okayToProcess = true;
 80  0
         numErrors = 0;
 81  
 
 82  0
         setName("UNDEFINED");
 83  0
         setVersion("UNDEFINED");
 84  
 
 85  0
         reader = null;
 86  
         try {
 87  0
             reader = XMLReaderFactory.createXMLReader(
 88  
                     "org.apache.xerces.parsers.SAXParser");
 89  0
             reader.setFeature(
 90  
                     "http://apache.org/xml/features/validation/schema", true);
 91  0
             reader.setFeature("http://xml.org/sax/features/namespaces", true);
 92  0
             reader.setFeature("http://xml.org/sax/features/validation", true);
 93  0
             reader.setFeature(
 94  
                     "http://apache.org/xml/features/validation/schema-full-checking", true);
 95  0
         } catch (Throwable any) {
 96  0
             logger.error("Error setting-up parser", any);
 97  0
         }
 98  
 
 99  
         /* Separate try block in case a setFeature fails, still can have a
 100  
             workable parser. */
 101  
         try {
 102  0
             reader.setContentHandler(this);
 103  0
             reader.setErrorHandler(this);
 104  0
         } catch (Throwable any) {
 105  0
             logger.error("Error setting-up handlers", any);
 106  0
         }
 107  
 
 108  
         /* Separate try block since error handling is different in this case.
 109  
             We more-or-less expect a failure here, especially if the
 110  
             customer modifies the XML definition files. */
 111  
         try {
 112  0
             reader.parse(inputFile.getAbsolutePath());
 113  0
         } catch (Throwable any) {
 114  0
             if (numErrors++ < MAX_ERRORS) {
 115  0
                 errorMessages.append("Format Definition Error:Type[" +
 116  
                                      any.getClass().getName() +
 117  
                                      "] Message[" + any.getMessage() + "]" +
 118  
                                      "\n\n");
 119  
             }
 120  0
         }
 121  0
     }
 122  
 
 123  
     /**
 124  
      * Obtain the error messages produced while parsing the XML data format file.
 125  
      *
 126  
      * @return String The error messages, separated by newlines
 127  
      */
 128  
     public String getErrorMessages() {
 129  0
         return errorMessages.toString();
 130  
     }
 131  
 
 132  
     /**
 133  
      * Process an individual element encountered in the XML file.  The method
 134  
      * determines the element type and creates to appropriate object to house
 135  
      * its information.
 136  
      *
 137  
      * @param aElementName String The element name
 138  
      * @param aAttributes Attributes The collection of element attributes
 139  
      */
 140  
     private void processElement(String aElementName, Attributes aAttributes) {
 141  
         String elementName;
 142  
 
 143  0
         if (!okayToProcess) {
 144  0
             return;
 145  
         }
 146  
 
 147  0
         elementName = aElementName.toUpperCase();
 148  
 
 149  0
         if (elementName.equals("FORMAT")) {
 150  0
             setName(aAttributes.getValue("name"));
 151  0
             setVersion(aAttributes.getValue("version"));
 152  0
         } else if (elementName.equals("RECORD")) {
 153  0
             String lId = aAttributes.getValue("id");
 154  0
             String lSeparator = aAttributes.getValue("separator");
 155  0
             String lWidth = aAttributes.getValue("width");
 156  0
             String lRequiredOccurRow = aAttributes.getValue("requiredOccurRow");
 157  0
             String lMaxWidth = aAttributes.getValue("maxWidth");
 158  
 
 159  0
             if (lSeparator == null || lSeparator.length() == 0) {
 160  0
                 currentRecordType = new RecordType(lId, Integer.parseInt(lWidth),
 161  
                         aAttributes.getValue("description"));
 162  
             } else {
 163  0
                 currentRecordType = new RecordType(lId, lSeparator,
 164  
                         aAttributes.getValue("description"));
 165  
             }
 166  
 
 167  0
             currentRecordType.setRequiredOccurRow(lRequiredOccurRow);
 168  0
             currentRecordType.setMaxWidth(lMaxWidth);
 169  0
         } else if (elementName.equals("FOLLOWS")) {
 170  0
             String lId = aAttributes.getValue("id");
 171  
 
 172  0
             currentRecordType.addFollowsId(lId);
 173  0
         } else if (elementName.equals("FIELD")) {
 174  0
             String lName = aAttributes.getValue("name");
 175  0
             String lStart = aAttributes.getValue("start");
 176  0
             String lWidth = aAttributes.getValue("width");
 177  0
             String lPadding = aAttributes.getValue("padding");
 178  0
             String lMatchLock = aAttributes.getValue("matchLock");
 179  0
             String lRequired = aAttributes.getValue("required");
 180  0
             String lGroup = aAttributes.getValue("group");
 181  0
             String lStoreVariableName = aAttributes.getValue("storeVariable");
 182  0
             String lMatchVariableName = aAttributes.getValue("matchVariable");
 183  
             int start, width, padding;
 184  
 
 185  0
             if (lStart != null && lStart.trim().length() > 0) {
 186  0
                 start = Integer.parseInt(lStart) - 1;
 187  
             } else {
 188  0
                 start = -1;
 189  
             }
 190  
 
 191  0
             if (lWidth != null && lWidth.trim().length() > 0) {
 192  0
                 width = Integer.parseInt(lWidth);
 193  
             } else {
 194  0
                 width = -1;
 195  
             }
 196  
 
 197  0
             padding = FieldType.ALIGN_NONE;
 198  0
             if (lPadding != null) {
 199  0
                 lPadding = lPadding.toUpperCase();
 200  0
                 if (lPadding.equals("LEFT")) {
 201  0
                     padding = FieldType.ALIGN_LEFT;
 202  0
                 } else if (lPadding.equals("RIGHT")) {
 203  0
                     padding = FieldType.ALIGN_RIGHT;
 204  
                 }
 205  
             }
 206  
 
 207  0
             currentFieldType = new FieldType(lName, start, width, padding);
 208  
 
 209  0
             if (lMatchLock != null) {
 210  0
                 currentFieldType.setMatchLock(lMatchLock.equals("Yes"));
 211  
             }
 212  
 
 213  0
             if (lRequired != null) {
 214  0
                 currentFieldType.setRequired(lRequired);
 215  
             }
 216  
 
 217  0
             if (lGroup != null && lGroup.trim().length() != 0) {
 218  0
                 currentFieldType.setGroup(Integer.parseInt(lGroup));
 219  
             }
 220  
 
 221  0
             currentFieldType.setVariableNameStoreValue(lStoreVariableName);
 222  0
             currentFieldType.setVariableNameMatchValue(lMatchVariableName);
 223  0
         } else if (elementName.equals("DATA")) {
 224  0
             String lType = aAttributes.getValue("type");
 225  0
             String lFormat = aAttributes.getValue("format");
 226  0
             String lDescription = aAttributes.getValue("description");
 227  0
             String lMinimum = aAttributes.getValue("minimum");
 228  0
             String lMaximum = aAttributes.getValue("maximum");
 229  
 
 230  0
             currentDataType = DataTypeFactory.makeDataType(lType, lFormat,
 231  
                     lDescription);
 232  0
             if (lMinimum != null) {
 233  0
                 currentDataType.setMinimum(Double.parseDouble(lMinimum));
 234  
             }
 235  0
             if (lMaximum != null) {
 236  0
                 currentDataType.setMaximum(Double.parseDouble(lMaximum));
 237  
             }
 238  0
             currentFieldType.setDataType(currentDataType);
 239  0
         } else if (elementName.equals("ACCEPTED")) {
 240  0
             String lValue = aAttributes.getValue("value");
 241  0
             String lDescription = aAttributes.getValue("description");
 242  
 
 243  0
             currentDataType.addAcceptedValue(new AcceptedValue(lValue,
 244  
                     lDescription));
 245  
         }
 246  0
     }
 247  
 
 248  
     /**
 249  
      * Process the completion of an XML element.  The method determines which
 250  
      * element has closed and what class instance is now complete and ready
 251  
      * to be associated with its container instance.
 252  
      *
 253  
      * @param aElementName String The element name
 254  
      */
 255  
     private void completeElement(String aElementName) {
 256  
         String elementName;
 257  
 
 258  0
         if (!okayToProcess) {
 259  0
             return;
 260  
         }
 261  
 
 262  0
         elementName = aElementName.toUpperCase();
 263  
 
 264  0
         if (elementName.equals("RECORD")) {
 265  0
             addRecordType(currentRecordType);
 266  0
             currentRecordType = null;
 267  0
         } else if (elementName.equals("FIELD")) {
 268  0
             currentRecordType.addField(currentFieldType);
 269  0
             currentFieldType = null;
 270  0
         } else if (elementName.equals("DATA")) {
 271  0
             currentFieldType.setDataType(currentDataType);
 272  0
             currentDataType = null;
 273  
         }
 274  0
     }
 275  
 
 276  
     // Begin ContentHandler Interface
 277  
 
 278  
     public void characters(char ch[], int start, int length) {
 279  0
     }
 280  
 
 281  
     public void endDocument() {
 282  0
         logger.info("endDocument Called");
 283  
 
 284  0
     }
 285  
 
 286  
     public void endElement(String namespaceURI, String localName, String qName) {
 287  0
         logger.debug("endElement:DATA:namespaceURI[" +
 288  
                      namespaceURI + "] localName[" + localName +
 289  
                      "] qName[" + qName + "]");
 290  
 
 291  0
         completeElement(localName);
 292  0
     }
 293  
 
 294  
 
 295  
     public void endPrefixMapping(String prefix) {
 296  0
         logger.debug("endPrefixMapping:DATA:prefix[" +
 297  
                      prefix + "]");
 298  0
     }
 299  
 
 300  
     public void ignorableWhitespace(char ch[], int start, int length) {
 301  0
         if (logger.isDebugEnabled()) {
 302  
             String slCharacters;
 303  0
             slCharacters = new String(ch, start, length);
 304  0
             logger.debug("ignorableWhitespace:DATA:[" +
 305  
                          slCharacters + "]");
 306  
         }
 307  0
     }
 308  
 
 309  
     public void processingInstruction(String target, String data) {
 310  0
         logger.debug("processingInstruction:DATA:target[" +
 311  
                      target + "] data[" + data + "]");
 312  0
     }
 313  
 
 314  
     public void setDocumentLocator(Locator locator) {
 315  0
         objcLocator = locator;
 316  0
         logger.debug("setDocumentLocator:DATA:getColumnNumber[" +
 317  
                      locator.getColumnNumber() + "] getLineNumber[" +
 318  
                      locator.getLineNumber() + "] getPublicId[" +
 319  
                      locator.getPublicId() +
 320  
                      "] getSystemId[" + locator.getSystemId() + "]");
 321  0
     }
 322  
 
 323  
     public void skippedEntity(String name) {
 324  0
         logger.debug("skippedEntity:DATA:name[" + name + "]");
 325  0
     }
 326  
 
 327  
     public void startDocument() {
 328  0
         logger.debug("FormatTypeParser:startDocument:DEBUG:Called");
 329  0
     }
 330  
 
 331  
     public void startElement(String namespaceURI, String localName,
 332  
                              String qName,
 333  
                              Attributes atts) {
 334  
         int ilNumAttributes, ilAttribute;
 335  
 
 336  
 //        entertainUser();
 337  
 
 338  0
         logger.debug("startElement:DATA:namespaceURI[" +
 339  
                      namespaceURI + "] localName[" + localName + "] qName[" +
 340  
                      qName + "]");
 341  
 
 342  0
         ilNumAttributes = atts.getLength();
 343  
 
 344  0
         if (logger.isDebugEnabled()) {
 345  0
             for (ilAttribute = 0; ilAttribute < ilNumAttributes; ++ilAttribute) {
 346  0
                 logger.debug("startElement:ATTRIBUTE:getLocalName[" +
 347  
                              atts.getLocalName(ilAttribute) + "] getQName[" +
 348  
                              atts.getQName(ilAttribute) + "] getType[" +
 349  
                              atts.getType(ilAttribute) + "] getURI[" +
 350  
                              atts.getURI(ilAttribute) +
 351  
                              "] getValue[" + atts.getValue(ilAttribute) + "]");
 352  
             }
 353  
         }
 354  
 
 355  0
         processElement(localName, atts);
 356  0
     }
 357  
 
 358  
     public void startPrefixMapping(String prefix, String uri) {
 359  0
         logger.debug("startPrefixMapping:DATA:prefix[" +
 360  
                      prefix + "] uri[" + uri + "]");
 361  0
     }
 362  
 
 363  
 // End ContentHandler Interface
 364  
 
 365  
 // Begin ErrorHandler Interface
 366  
 
 367  
     public void error(SAXParseException exception) {
 368  0
         logger.error("Error parsing message:Line[" +
 369  
                      exception.getLineNumber() + "]", exception);
 370  0
         okayToProcess = false;
 371  
 
 372  0
         if (numErrors++ < MAX_ERRORS) {
 373  0
             errorMessages.append("XML Parse Error:Line[" +
 374  
                                  exception.getLineNumber() +
 375  
                                  "]=" + exception + "\n\n");
 376  
         }
 377  0
     }
 378  
 
 379  
     public void fatalError(SAXParseException exception) {
 380  0
         logger.fatal("Parsing exception:Line[" +
 381  
                      exception.getLineNumber() + "]", exception);
 382  0
         okayToProcess = false;
 383  
 
 384  0
         if (numErrors++ < MAX_ERRORS) {
 385  0
             errorMessages.append("XML Parse Fatal Error:Line[" +
 386  
                                  exception.getLineNumber() + "]=" + exception +
 387  
                                  "\n\n");
 388  
         }
 389  0
     }
 390  
 
 391  
     public void warning(SAXParseException exception) {
 392  0
         logger.warn("Parse warning:Line[" +
 393  
                     exception.getLineNumber() + "]", exception);
 394  0
     }
 395  
 
 396  
 // End ErrorHandler Interface
 397  
 
 398  
 }