Clover coverage report - QedeqKernelSe Coverage Report
Coverage timestamp: Do Dez 29 2005 18:38:29 CET
file stats: LOC: 356   Methods: 17
NCLOC: 180   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
XPathLocationParser.java 94,4% 94,3% 70,6% 91,1%
coverage coverage
 1    /* $Id: XPathLocationParser.java,v 1.12 2005/12/14 18:24:26 m31 Exp $
 2    *
 3    * This file is part of the project "Hilbert II" - http://www.qedeq.org
 4    *
 5    * Copyright 2000-2005, Michael Meyling <mime@qedeq.org>.
 6    *
 7    * "Hilbert II" is free software; you can redistribute
 8    * it and/or modify it under the terms of the GNU General Public
 9    * License as published by the Free Software Foundation; either
 10    * version 2 of the License, or (at your option) any later version.
 11    *
 12    * This program is distributed in the hope that it will be useful,
 13    * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15    * GNU General Public License for more details.
 16    */
 17    package org.qedeq.kernel.xml.tracker;
 18   
 19    import java.io.File;
 20    import java.io.FileInputStream;
 21    import java.io.IOException;
 22    import java.util.ArrayList;
 23    import java.util.HashMap;
 24    import java.util.List;
 25    import java.util.Map;
 26   
 27    import javax.xml.parsers.ParserConfigurationException;
 28    import javax.xml.parsers.SAXParser;
 29    import javax.xml.parsers.SAXParserFactory;
 30   
 31    import org.qedeq.kernel.dto.elli.Enumerator;
 32    import org.qedeq.kernel.log.Trace;
 33    import org.qedeq.kernel.utility.TextInput;
 34    import org.qedeq.kernel.xml.parser.SaxEntityResolver;
 35    import org.xml.sax.Attributes;
 36    import org.xml.sax.ContentHandler;
 37    import org.xml.sax.InputSource;
 38    import org.xml.sax.Locator;
 39    import org.xml.sax.SAXException;
 40    import org.xml.sax.XMLReader;
 41   
 42    /**
 43    * Parser for XML files. This class uses features specific for Xerces.
 44    *
 45    * @version $Revision: 1.12 $
 46    * @author Michael Meyling
 47    */
 48    public final class XPathLocationParser implements ContentHandler {
 49   
 50    /** Namespaces feature id (http://xml.org/sax/features/namespaces). */
 51    private static final String NAMESPACES_FEATURE_ID = "http://xml.org/sax/features/namespaces";
 52   
 53    /** Validation feature id (http://xml.org/sax/features/validation). */
 54    private static final String VALIDATION_FEATURE_ID = "http://xml.org/sax/features/validation";
 55   
 56    /** SAX parser. */
 57    private XMLReader reader;
 58   
 59    /** Position locator during parsing. */
 60    private Locator locator;
 61   
 62    /** Search for this simple XPath expression. */
 63    private final SimpleXPath find;
 64   
 65    /** We are currently at this position. */
 66    private SimpleXPath current;
 67   
 68    /**
 69    * We are currently at this position if we count only occurrences and take every element. The
 70    * elements are all named "*".
 71    */
 72    private SimpleXPath summary;
 73   
 74    /** This object is parsed. */
 75    private TextInput xml;
 76   
 77    /** Element stack. */
 78    private final List elements;
 79   
 80    /** Current stack level. */
 81    private int level;
 82   
 83    /**
 84    * Constructor.
 85    *
 86    * @param xpath XML file path.
 87    * @throws ParserConfigurationException Severe parser configuration problem.
 88    * @throws SAXException
 89    */
 90  409 public XPathLocationParser(final String xpath) throws ParserConfigurationException,
 91    SAXException {
 92  409 super();
 93   
 94  409 find = new SimpleXPath(xpath);
 95  409 elements = new ArrayList(20);
 96  409 level = 0;
 97   
 98  409 final String factoryImpl = System.getProperty("javax.xml.parsers.SAXParserFactory");
 99  409 if (factoryImpl == null) {
 100  0 System.setProperty("javax.xml.parsers.SAXParserFactory",
 101    "org.apache.xerces.jaxp.SAXParserFactoryImpl");
 102    }
 103  409 SAXParserFactory factory = SAXParserFactory.newInstance();
 104  409 factory.setNamespaceAware(false);
 105  409 factory.setValidating(false);
 106   
 107  409 factory.setFeature(NAMESPACES_FEATURE_ID, false);
 108  409 factory.setFeature(VALIDATION_FEATURE_ID, false);
 109   
 110  409 final SAXParser parser = factory.newSAXParser();
 111   
 112  409 reader = parser.getXMLReader();
 113  409 reader.setEntityResolver(new SaxEntityResolver());
 114   
 115    // set parser features
 116  409 reader.setFeature(NAMESPACES_FEATURE_ID, false);
 117  409 reader.setFeature(VALIDATION_FEATURE_ID, false);
 118    }
 119   
 120    /**
 121    * Parses XML file.
 122    *
 123    * @param fileName Parse this input.
 124    * @throws SAXException Syntactical or semantical problem occurred.
 125    * @throws IOException Technical problem occurred.
 126    */
 127  409 public final void parse(final String fileName) throws SAXException, IOException {
 128  409 final File file = new File(fileName);
 129  409 parse(file);
 130    }
 131   
 132    /**
 133    * Parses XML file.
 134    *
 135    * @param file Parse this input.
 136    * @throws SAXException Syntactical or semantical problem occurred.
 137    * @throws IOException Technical problem occurred.
 138    */
 139  409 public final void parse(final File file) throws SAXException, IOException {
 140  409 final TextInput source = new TextInput(file, file.getCanonicalPath());
 141  409 parse(source);
 142    }
 143   
 144    /**
 145    * Parses XML file.
 146    *
 147    * @param input Parse this input.
 148    * @throws SAXException Syntactical or semantical problem occurred.
 149    * @throws IOException Technical problem occurred.
 150    */
 151  409 public final void parse(final TextInput input) throws SAXException, IOException {
 152  409 xml = input;
 153  409 elements.clear();
 154  409 level = 0;
 155  409 try {
 156  409 current = new SimpleXPath();
 157  409 summary = new SimpleXPath();
 158  409 reader.setContentHandler(this);
 159  409 reader.parse(new InputSource(new FileInputStream(input.getLocalAddress())));
 160  409 xml = null;
 161    } catch (SAXException e) {
 162  0 Trace.trace(this, "parse", e);
 163  0 throw e;
 164    }
 165    }
 166   
 167    /*
 168    * (non-Javadoc)
 169    *
 170    * @see org.xml.sax.ContentHandler#endDocument()
 171    */
 172  409 public void endDocument() throws SAXException {
 173  409 elements.clear();
 174  409 level = 0;
 175    }
 176   
 177    /*
 178    * (non-Javadoc)
 179    *
 180    * @see org.xml.sax.ContentHandler#startDocument()
 181    */
 182  409 public void startDocument() throws SAXException {
 183  409 elements.clear();
 184  409 level = 0;
 185    }
 186   
 187    /*
 188    * (non-Javadoc)
 189    *
 190    * @see org.xml.sax.ContentHandler#characters(char[], int, int)
 191    */
 192  168695 public void characters(final char[] ch, final int start, final int length) throws SAXException {
 193    }
 194   
 195    /*
 196    * (non-Javadoc)
 197    *
 198    * @see org.xml.sax.ContentHandler#ignorableWhitespace(char[], int, int)
 199    */
 200  0 public void ignorableWhitespace(final char[] ch, final int start, final int length)
 201    throws SAXException {
 202    }
 203   
 204    /*
 205    * (non-Javadoc)
 206    *
 207    * @see org.xml.sax.ContentHandler#endPrefixMapping(java.lang.String)
 208    */
 209  0 public void endPrefixMapping(final String prefix) throws SAXException {
 210    }
 211   
 212    /*
 213    * (non-Javadoc)
 214    *
 215    * @see org.xml.sax.ContentHandler#skippedEntity(java.lang.String)
 216    */
 217  0 public void skippedEntity(final String name) throws SAXException {
 218    }
 219   
 220    /**
 221    * Receive a Locator object for document events. Store the locator for use with other document
 222    * events.
 223    *
 224    * @param locator A locator for all SAX document events.
 225    * @see org.xml.sax.ContentHandler#setDocumentLocator
 226    * @see org.xml.sax.Locator
 227    */
 228  409 public final void setDocumentLocator(final Locator locator) {
 229  409 this.locator = locator;
 230    }
 231   
 232    /*
 233    * (non-Javadoc)
 234    *
 235    * @see org.xml.sax.ContentHandler#processingInstruction(java.lang.String, java.lang.String)
 236    */
 237  0 public void processingInstruction(final String target, final String data) throws SAXException {
 238    }
 239   
 240    /*
 241    * (non-Javadoc)
 242    *
 243    * @see org.xml.sax.ContentHandler#startPrefixMapping(java.lang.String, java.lang.String)
 244    */
 245  0 public void startPrefixMapping(final String prefix, final String uri) throws SAXException {
 246    }
 247   
 248    /*
 249    * (non-Javadoc)
 250    *
 251    * @see org.xml.sax.ContentHandler#startElement(java.lang.String, java.lang.String,
 252    * java.lang.String, org.xml.sax.Attributes)
 253    */
 254  56710 public void startElement(final String namespaceURI, final String localName, final String qName,
 255    final Attributes atts) throws SAXException {
 256  56710 final String method = "startElement(String, String, Attributes)";
 257  56710 level++;
 258  56710 summary.addElement("*", addOccurence("*"));
 259  56710 current.addElement(qName, addOccurence(qName));
 260   
 261  56710 if (find.matchesElements(current, summary)) {
 262  409 Trace.trace(this, method, "matching elements");
 263  409 Trace.traceParam(this, method, qName, current);
 264  409 xml.setRow(locator.getLineNumber());
 265  409 xml.setColumn(locator.getColumnNumber());
 266   
 267  409 try {
 268  409 xml.skipBackToBeginOfXmlTag();
 269    } catch (RuntimeException e) {
 270  0 Trace.trace(this, method, e);
 271    }
 272  409 find.setStartLocation(new SourcePosition(xml.getLocalAddress(), xml.getRow(), xml
 273    .getColumn()));
 274  409 if (find.getAttribute() != null) {
 275  38 xml.read(); // skip <
 276  38 xml.readNextXmlName(); // must be element name
 277  38 String tag;
 278  38 do {
 279  48 xml.skipWhiteSpace();
 280  48 int row = xml.getRow();
 281  48 int col = xml.getColumn();
 282  48 try {
 283  48 tag = xml.readNextXmlName();
 284    } catch (IllegalArgumentException e) {
 285  0 break; // TODO mime 20050621: create named exception in readNextXmlName
 286    }
 287  48 if (tag.equals(find.getAttribute())) {
 288  38 find.setStartLocation(new SourcePosition(xml.getLocalAddress(), row, col));
 289  38 xml.readNextAttributeValue();
 290  38 find.setEndLocation(new SourcePosition(xml.getLocalAddress(), xml.getRow(),
 291    xml.getColumn()));
 292  38 break;
 293    }
 294  10 xml.readNextAttributeValue();
 295    } while (true);
 296    }
 297    }
 298    }
 299   
 300    /**
 301    * Add element occurrence.
 302    *
 303    * @param name Element that occurred.
 304    * @return Number of occurrences including this one.
 305    */
 306  113420 private int addOccurence(final String name) {
 307  113420 while (level < elements.size()) {
 308  28412 elements.remove(elements.size() - 1);
 309    }
 310  113420 while (level > elements.size()) {
 311  31093 elements.add(new HashMap());
 312    }
 313  113420 final Map levelMap = (Map) elements.get(level - 1);
 314  113420 final Enumerator counter;
 315  113420 if (levelMap.containsKey(name)) {
 316  37333 counter = (Enumerator) levelMap.get(name);
 317  37333 counter.increaseNumber();
 318    } else {
 319  76087 counter = new Enumerator(1);
 320  76087 levelMap.put(name, counter);
 321    }
 322  113420 if (name.equals("*")) {
 323    }
 324  113420 return counter.getNumber();
 325    }
 326   
 327    /*
 328    * (non-Javadoc)
 329    *
 330    * @see org.xml.sax.ContentHandler#endElement(java.lang.String, java.lang.String,
 331    * java.lang.String)
 332    */
 333  56710 public void endElement(final String namespaceURI, final String localName, final String qName)
 334    throws SAXException {
 335  56710 level--;
 336  56710 if (find.matchesElements(current, summary) && find.getAttribute() == null) {
 337  371 xml.setRow(locator.getLineNumber());
 338  371 xml.setColumn(locator.getColumnNumber());
 339    // xml.skipForwardToEndOfXmlTag(); // TODO mime 20050810: remove? comment in?
 340  371 find.setEndLocation(new SourcePosition(xml.getLocalAddress(), xml.getRow(), xml
 341    .getColumn()));
 342    }
 343  56710 current.deleteLastElement();
 344  56710 summary.deleteLastElement();
 345    }
 346   
 347    /**
 348    * Get searched XPath. Possibly the start and end location are set.
 349    *
 350    * @return Searched XPath.
 351    */
 352  409 public SimpleXPath getFind() {
 353  409 return find;
 354    }
 355   
 356    }