Clover coverage report - QedeqKernelSe Coverage Report
Coverage timestamp: Sa Okt 21 2006 08:24:31 CEST
file stats: LOC: 356   Methods: 17
NCLOC: 179   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.13 2006/10/20 20:23:06 m31 Exp $
 2    *
 3    * This file is part of the project "Hilbert II" - http://www.qedeq.org
 4    *
 5    * Copyright 2000-2006, 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.IOException;
 21    import java.util.ArrayList;
 22    import java.util.HashMap;
 23    import java.util.List;
 24    import java.util.Map;
 25   
 26    import javax.xml.parsers.ParserConfigurationException;
 27    import javax.xml.parsers.SAXParser;
 28    import javax.xml.parsers.SAXParserFactory;
 29   
 30    import org.qedeq.kernel.dto.elli.Enumerator;
 31    import org.qedeq.kernel.log.Trace;
 32    import org.qedeq.kernel.utility.TextInput;
 33    import org.qedeq.kernel.xml.parser.SaxEntityResolver;
 34    import org.xml.sax.Attributes;
 35    import org.xml.sax.ContentHandler;
 36    import org.xml.sax.InputSource;
 37    import org.xml.sax.Locator;
 38    import org.xml.sax.SAXException;
 39    import org.xml.sax.XMLReader;
 40   
 41    /**
 42    * Parser for XML files. This class uses features specific for Xerces.
 43    *
 44    * @version $Revision: 1.13 $
 45    * @author Michael Meyling
 46    */
 47    public final class XPathLocationParser implements ContentHandler {
 48   
 49    /** Namespaces feature id (http://xml.org/sax/features/namespaces). */
 50    private static final String NAMESPACES_FEATURE_ID = "http://xml.org/sax/features/namespaces";
 51   
 52    /** Validation feature id (http://xml.org/sax/features/validation). */
 53    private static final String VALIDATION_FEATURE_ID = "http://xml.org/sax/features/validation";
 54   
 55    /** SAX parser. */
 56    private XMLReader reader;
 57   
 58    /** Position locator during parsing. */
 59    private Locator locator;
 60   
 61    /** Search for this simple XPath expression. */
 62    private final SimpleXPath find;
 63   
 64    /** We are currently at this position. */
 65    private SimpleXPath current;
 66   
 67    /**
 68    * We are currently at this position if we count only occurrences and take every element. The
 69    * elements are all named "*".
 70    */
 71    private SimpleXPath summary;
 72   
 73    /** This object is parsed. */
 74    private TextInput xml;
 75   
 76    /** Element stack. */
 77    private final List elements;
 78   
 79    /** Current stack level. */
 80    private int level;
 81   
 82    /**
 83    * Constructor.
 84    *
 85    * @param xpath XML file path.
 86    * @throws ParserConfigurationException Severe parser configuration problem.
 87    * @throws SAXException
 88    */
 89  2316 public XPathLocationParser(final String xpath) throws ParserConfigurationException,
 90    SAXException {
 91  2316 super();
 92   
 93  2316 find = new SimpleXPath(xpath);
 94  2316 elements = new ArrayList(20);
 95  2316 level = 0;
 96   
 97  2316 final String factoryImpl = System.getProperty("javax.xml.parsers.SAXParserFactory");
 98  2316 if (factoryImpl == null) {
 99  0 System.setProperty("javax.xml.parsers.SAXParserFactory",
 100    "org.apache.xerces.jaxp.SAXParserFactoryImpl");
 101    }
 102  2316 SAXParserFactory factory = SAXParserFactory.newInstance();
 103  2316 factory.setNamespaceAware(false);
 104  2316 factory.setValidating(false);
 105   
 106  2316 factory.setFeature(NAMESPACES_FEATURE_ID, false);
 107  2316 factory.setFeature(VALIDATION_FEATURE_ID, false);
 108   
 109  2316 final SAXParser parser = factory.newSAXParser();
 110   
 111  2316 reader = parser.getXMLReader();
 112  2316 reader.setEntityResolver(new SaxEntityResolver());
 113   
 114    // set parser features
 115  2316 reader.setFeature(NAMESPACES_FEATURE_ID, false);
 116  2316 reader.setFeature(VALIDATION_FEATURE_ID, false);
 117    }
 118   
 119    /**
 120    * Parses XML file.
 121    *
 122    * @param fileName Parse this input.
 123    * @throws SAXException Syntactical or semantical problem occurred.
 124    * @throws IOException Technical problem occurred.
 125    */
 126  2316 public final void parse(final String fileName) throws SAXException, IOException {
 127  2316 final File file = new File(fileName);
 128  2316 parse(file);
 129    }
 130   
 131    /**
 132    * Parses XML file.
 133    *
 134    * @param file Parse this input.
 135    * @throws SAXException Syntactical or semantical problem occurred.
 136    * @throws IOException Technical problem occurred.
 137    */
 138  2316 public final void parse(final File file) throws SAXException, IOException {
 139  2316 final TextInput source = new TextInput(file);
 140  2316 parse(source);
 141    }
 142   
 143    /**
 144    * Parses XML file.
 145    *
 146    * @param input Parse this input.
 147    * @throws SAXException Syntactical or semantical problem occurred.
 148    * @throws IOException Technical problem occurred.
 149    */
 150  2316 public final void parse(final TextInput input) throws SAXException, IOException {
 151  2316 xml = input;
 152  2316 elements.clear();
 153  2316 level = 0;
 154  2316 try {
 155  2316 current = new SimpleXPath();
 156  2316 summary = new SimpleXPath();
 157  2316 reader.setContentHandler(this);
 158    // TODO mime 20060609: what if input has no local address (e.g. == null)?
 159  2316 reader.parse(new InputSource(input.getLocalAddress().openStream()));
 160  2316 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  2316 public void endDocument() throws SAXException {
 173  2316 elements.clear();
 174  2316 level = 0;
 175    }
 176   
 177    /*
 178    * (non-Javadoc)
 179    *
 180    * @see org.xml.sax.ContentHandler#startDocument()
 181    */
 182  2316 public void startDocument() throws SAXException {
 183  2316 elements.clear();
 184  2316 level = 0;
 185    }
 186   
 187    /*
 188    * (non-Javadoc)
 189    *
 190    * @see org.xml.sax.ContentHandler#characters(char[], int, int)
 191    */
 192  10103877 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  2316 public final void setDocumentLocator(final Locator locator) {
 229  2316 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  4233553 public void startElement(final String namespaceURI, final String localName, final String qName,
 255    final Attributes atts) throws SAXException {
 256  4233553 final String method = "startElement(String, String, Attributes)";
 257  4233553 level++;
 258  4233553 summary.addElement("*", addOccurence("*"));
 259  4233553 current.addElement(qName, addOccurence(qName));
 260   
 261  4233553 if (find.matchesElements(current, summary)) {
 262  2316 Trace.trace(this, method, "matching elements");
 263  2316 Trace.traceParam(this, method, qName, current);
 264  2316 xml.setRow(locator.getLineNumber());
 265  2316 xml.setColumn(locator.getColumnNumber());
 266   
 267  2316 try {
 268  2316 xml.skipBackToBeginOfXmlTag();
 269    } catch (RuntimeException e) {
 270  0 Trace.trace(this, method, e);
 271    }
 272  2316 find.setStartLocation(new SourcePosition(xml.getLocalAddress(), xml.getRow(), xml
 273    .getColumn()));
 274  2316 if (find.getAttribute() != null) {
 275  280 xml.read(); // skip <
 276  280 xml.readNextXmlName(); // must be element name
 277  280 String tag;
 278  280 do {
 279  389 xml.skipWhiteSpace();
 280  389 int row = xml.getRow();
 281  389 int col = xml.getColumn();
 282  389 try {
 283  389 tag = xml.readNextXmlName();
 284    } catch (IllegalArgumentException e) {
 285  0 break; // TODO mime 20050621: create named exception in readNextXmlName
 286    }
 287  389 if (tag.equals(find.getAttribute())) {
 288  280 find.setStartLocation(new SourcePosition(xml.getLocalAddress(), row, col));
 289  280 xml.readNextAttributeValue();
 290  280 find.setEndLocation(new SourcePosition(xml.getLocalAddress(), xml.getRow(),
 291    xml.getColumn()));
 292  280 break;
 293    }
 294  109 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  8467106 private int addOccurence(final String name) {
 307  8467106 while (level < elements.size()) {
 308  2206884 elements.remove(elements.size() - 1);
 309    }
 310  8467106 while (level > elements.size()) {
 311  2217193 elements.add(new HashMap());
 312    }
 313  8467106 final Map levelMap = (Map) elements.get(level - 1);
 314  8467106 final Enumerator counter;
 315  8467106 if (levelMap.containsKey(name)) {
 316  3186339 counter = (Enumerator) levelMap.get(name);
 317  3186339 counter.increaseNumber();
 318    } else {
 319  5280767 counter = new Enumerator(1);
 320  5280767 levelMap.put(name, counter);
 321    }
 322  8467106 if (name.equals("*")) {
 323    }
 324  8467106 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  4233553 public void endElement(final String namespaceURI, final String localName, final String qName)
 334    throws SAXException {
 335  4233553 level--;
 336  4233553 if (find.matchesElements(current, summary) && find.getAttribute() == null) {
 337  2036 xml.setRow(locator.getLineNumber());
 338  2036 xml.setColumn(locator.getColumnNumber());
 339    // xml.skipForwardToEndOfXmlTag(); // TODO mime 20050810: remove? comment in?
 340  2036 find.setEndLocation(new SourcePosition(xml.getLocalAddress(), xml.getRow(), xml
 341    .getColumn()));
 342    }
 343  4233553 current.deleteLastElement();
 344  4233553 summary.deleteLastElement();
 345    }
 346   
 347    /**
 348    * Get searched XPath. Possibly the start and end location are set.
 349    *
 350    * @return Searched XPath.
 351    */
 352  2316 public SimpleXPath getFind() {
 353  2316 return find;
 354    }
 355   
 356    }