Clover coverage report - QedeqKernelSe Coverage Report
Coverage timestamp: Do Mai 10 2007 03:16:40 CEST
file stats: LOC: 425   Methods: 24
NCLOC: 225   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
SimpleXPath.java 55,6% 68% 79,2% 65,2%
coverage coverage
 1    /* $Id: SimpleXPath.java,v 1.14 2007/05/10 00:37:49 m31 Exp $
 2    *
 3    * This file is part of the project "Hilbert II" - http://www.qedeq.org
 4    *
 5    * Copyright 2000-2007, 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   
 18    package org.qedeq.kernel.xml.tracker;
 19   
 20    import java.util.ArrayList;
 21    import java.util.List;
 22    import java.util.StringTokenizer;
 23   
 24    import org.qedeq.kernel.common.SourcePosition;
 25    import org.qedeq.kernel.utility.EqualsUtility;
 26   
 27   
 28    /**
 29    * Simple XPath like description of a location in an XML file.
 30    *
 31    * @version $Revision: 1.14 $
 32    * @author Michael Meyling
 33    */
 34    public class SimpleXPath {
 35   
 36    /** List with element names. */
 37    private final List elements;
 38   
 39    /** List with element occurrence numbers. */
 40    private final List numbers;
 41   
 42    /** Attribute of element. */
 43    private String attribute;
 44   
 45    /** Starting position in source. */
 46    private SourcePosition start;
 47   
 48    /** Ending position in source. */
 49    private SourcePosition end;
 50   
 51    /**
 52    * Constructor with simple XPath string as parameter.
 53    * This is not the standard XPath definition but it is similar to a subset of
 54    * the abbreviation XPath notation.
 55    * <p>
 56    * <code>/element1/element2[3]@attribute</code> is an example for such
 57    * a notation. This selects from the first occurrence of <code>element1</code>
 58    * and from the third occurrence of subnode <code>element2</code> the attribute
 59    * <code>attribute</code>. The attribute is optional. It is always exactly one node or
 60    * the attribute of one node specified.
 61    * <p>
 62    * The general syntax could be described as follows:
 63    * {"/"<em>element</em>"["<em>index</em>"]"}+
 64    * ["@"<em>attribute</em>]
 65    *
 66    *
 67    * @param xpath String with the syntax as described above. If the syntax is violated
 68    * RuntimeExceptions may occur.
 69    */
 70  29017 public SimpleXPath(final String xpath) {
 71  29017 elements = new ArrayList();
 72  29017 numbers = new ArrayList();
 73  29017 attribute = null;
 74  29017 init(xpath);
 75    }
 76   
 77    /**
 78    * Empty constructor.
 79    */
 80  86879 public SimpleXPath() {
 81  86879 elements = new ArrayList();
 82  86879 numbers = new ArrayList();
 83  86879 attribute = null;
 84    }
 85   
 86    /**
 87    * Copy constructor.
 88    *
 89    * @param original XPath to copy.
 90    */
 91  300195 public SimpleXPath(final SimpleXPath original) {
 92  300195 elements = new ArrayList();
 93  300195 numbers = new ArrayList();
 94  300195 attribute = null;
 95  300195 init(original.toString());
 96    }
 97   
 98    /**
 99    * Initialize all object attributes according to XPath parameter.
 100    *
 101    * @see SimpleXPath#SimpleXPath(String)
 102    *
 103    * @param xpath String with the syntax as described above. If the syntax is violated
 104    * RuntimeExceptions may occur.
 105    */
 106  329212 private void init(final String xpath) {
 107  329212 final StringTokenizer tokenizer = new StringTokenizer(xpath, "/");
 108  329212 while (tokenizer.hasMoreTokens()) {
 109  1581843 String token = tokenizer.nextToken();
 110  1581843 if (!tokenizer.hasMoreTokens() && token.indexOf('@') >= 0) {
 111  3357 attribute = token.substring(token.indexOf('@') + 1);
 112  3357 token = token.substring(0, token.indexOf('@'));
 113    }
 114  1581843 if (token.indexOf('[') < 0) {
 115  1028470 elements.add(token);
 116  1028470 numbers.add(new Integer(1));
 117    } else {
 118  553373 final StringTokenizer getnu = new StringTokenizer(token, "[]");
 119  553373 elements.add(getnu.nextToken());
 120  553373 numbers.add(new Integer(getnu.nextToken()));
 121    }
 122    }
 123    }
 124   
 125    /**
 126    * Get number of collected exceptions.
 127    *
 128    * @return Number of collected exceptions.
 129    */
 130  263758639 public final int size() {
 131  263758639 return elements.size();
 132    }
 133   
 134    /**
 135    * Get <code>i</code>-th Element name.
 136    *
 137    * @param i Starts with 0 and must be smaller than {@link #size()}.
 138    * @return Wanted element name.
 139    */
 140  122524104 public final String getElementName(final int i) {
 141  122524104 return (String) elements.get(i);
 142    }
 143   
 144    /**
 145    * Get <code>i</code>-th occurrence number.
 146    *
 147    * @param i Starts with 0 and must be smaller than {@link #size()}.
 148    * @return Wanted element occurrence number.
 149    */
 150  82268527 public final int getElementOccurrence(final int i) {
 151  82268527 return ((Integer) numbers.get(i)).intValue();
 152    }
 153   
 154    /**
 155    * Add new element to end of XPath.
 156    *
 157    * @param elementName element to add.
 158    */
 159  0 public final void addElement(final String elementName) {
 160  0 attribute = null;
 161  0 elements.add(elementName);
 162  0 numbers.add(new Integer(1));
 163    }
 164   
 165    /**
 166    * Add new element to end of XPath.
 167    *
 168    * @param elementName element to add.
 169    * @param occurrence Occurrence number of element. Starts with 1.
 170    */
 171  124609732 public final void addElement(final String elementName, final int occurrence) {
 172  124609732 attribute = null;
 173  124609732 elements.add(elementName);
 174  124609732 numbers.add(new Integer(occurrence));
 175    }
 176   
 177    /**
 178    * Get last XPath element name.
 179    *
 180    * @return Last element name. Could be <code>null</code> if no elements exist.
 181    */
 182  0 public final String getLastElement() {
 183  0 int size = elements.size();
 184  0 if (size <= 0) {
 185  0 return null;
 186    }
 187  0 return (String) elements.get(size - 1);
 188    }
 189   
 190    /**
 191    * Get XPath element name before last.
 192    *
 193    * @return Before last element name. Could be <code>null</code> if no more than one element
 194    * exist.
 195    */
 196  0 public final String getBeforeLastElement() {
 197  0 int size = elements.size();
 198  0 if (size <= 1) {
 199  0 return null;
 200    }
 201  0 return (String) elements.get(size - 2);
 202    }
 203   
 204    /**
 205    * Delete last XPath element if any.
 206    */
 207  124348249 public void deleteLastElement() {
 208  124348249 int size = elements.size();
 209  124348249 if (size > 0) {
 210  124348249 elements.remove(size - 1);
 211  124348249 numbers.remove(size - 1);
 212  124348249 attribute = null;
 213    }
 214    }
 215   
 216    /**
 217    * Set attribute.
 218    *
 219    * @param attribute Attribute, maybe <code>null</code>.
 220    */
 221  693911 public final void setAttribute(final String attribute) {
 222  693911 this.attribute = attribute;
 223    }
 224   
 225    /**
 226    * Get attribute.
 227    *
 228    * @return Attribute, maybe <code>null</code>.
 229    */
 230  426077 public final String getAttribute() {
 231  426077 return attribute;
 232    }
 233   
 234    /**
 235    * Set starting location of XPath.
 236    *
 237    * @param position Starting point of this XPath.
 238    */
 239  32128 public final void setStartLocation(final SourcePosition position) {
 240  32128 start = position;
 241    }
 242   
 243    /**
 244    * Get start location.
 245    *
 246    * @return File position.
 247    */
 248  28999 public final SourcePosition getStartLocation() {
 249  28999 return start;
 250    }
 251   
 252    /**
 253    * Set ending location of XPath.
 254    *
 255    * @param position Ending point of this XPath.
 256    */
 257  28962 public final void setEndLocation(final SourcePosition position) {
 258  28962 end = position;
 259    }
 260   
 261    /**
 262    * Get end location.
 263    *
 264    * @return File position.
 265    */
 266  28978 public final SourcePosition getEndLocation() {
 267  28978 return end;
 268    }
 269   
 270  53 public final boolean equals(final Object obj) {
 271  53 if (!(obj instanceof SimpleXPath)) {
 272  0 return false;
 273    }
 274  53 final SimpleXPath other = (SimpleXPath) obj;
 275  53 if (!EqualsUtility.equals(this.getAttribute(), other.getAttribute())) {
 276  19 return false;
 277    }
 278  34 final int size = this.size();
 279  34 if (size != other.size()) {
 280  15 return false;
 281    }
 282   
 283  19 for (int i = 0; i < size; i++) {
 284  51 if (!EqualsUtility.equals(this.getElementName(i), other.getElementName(i))) {
 285  7 return false;
 286    }
 287  44 if (this.getElementOccurrence(i) != other.getElementOccurrence(i)) {
 288  1 return false;
 289    }
 290    }
 291  11 return true;
 292    }
 293   
 294    /**
 295    * Are the elements and occurrences of this and another element equal? No special treatment
 296    * of "*" elements.
 297    *
 298    * @param other Compare with this object.
 299    * @return Are the elements of this and the parameter object equal?
 300    */
 301  0 public final boolean equalsElements(final SimpleXPath other) {
 302  0 final int size = this.size();
 303  0 if (size != other.size()) {
 304  0 return false;
 305    }
 306   
 307  0 for (int i = 0; i < size; i++) {
 308  0 if (!EqualsUtility.equals(this.getElementName(i), other.getElementName(i))) {
 309  0 return false;
 310    }
 311  0 if (getElementOccurrence(i) != other.getElementOccurrence(i)) {
 312  0 return false;
 313    }
 314    }
 315  0 return true;
 316    }
 317   
 318    /**
 319    * Match the elements and occurrences of this finder object and current elements?
 320    * This object may contain "*" elements.
 321    *
 322    * @param current Compare with this current elements. These elements should not
 323    * contain "*" elements.
 324    * @param currentSummary Contains only "*" elements. This parameter must be identify the same
 325    * XPath as <code>current</code>
 326    * @return Match the elements of this finder object and the parameter objects?
 327    */
 328  123825848 public final boolean matchesElements(final SimpleXPath current,
 329    final SimpleXPath currentSummary) {
 330  123825848 final int size = current.size();
 331  123825848 if (size != size()) {
 332  109920356 return false;
 333    }
 334  13905492 if (size != currentSummary.size()) {
 335  0 throw new IllegalArgumentException("summary size doesn't match");
 336    }
 337   
 338  13905492 for (int i = 0; i < size; i++) {
 339  40226918 if ("*".equals(getElementName(i))) {
 340  0 if (getElementOccurrence(i) != currentSummary.getElementOccurrence(i)) {
 341  0 return false;
 342    }
 343  0 continue;
 344    }
 345  40226918 if (!EqualsUtility.equals(current.getElementName(i), getElementName(i))) {
 346  332460 return false;
 347    }
 348  39894458 if (current.getElementOccurrence(i) != getElementOccurrence(i)) {
 349  13515108 return false;
 350    }
 351    }
 352  57924 return true;
 353    }
 354   
 355    /**
 356    * Match the elements and occurrences of this finder object and current elements?
 357    * This object may contain "*" elements. Checks only to current.size().
 358    *
 359    * @param current Compare with this current elements. These elements should not
 360    * contain "*" elements.
 361    * @param currentSummary Contains only "*" elements. This parameter must be identify the same
 362    * XPath as <code>current</code>
 363    * @return Match the elements of this finder object and the parameter objects?
 364    */
 365  0 public final boolean matchesElementsBegining(final SimpleXPath current,
 366    final SimpleXPath currentSummary) {
 367  0 final int size = current.size();
 368  0 if (size > size()) {
 369  0 return false;
 370    }
 371  0 if (size != currentSummary.size()) {
 372  0 throw new IllegalArgumentException("summary size doesn't match");
 373    }
 374   
 375  0 for (int i = 0; i < size; i++) {
 376  0 if ("*".equals(getElementName(i))) {
 377  0 if (getElementOccurrence(i) != currentSummary.getElementOccurrence(i)) {
 378  0 return false;
 379    }
 380  0 continue;
 381    }
 382  0 if (!EqualsUtility.equals(current.getElementName(i), getElementName(i))) {
 383  0 return false;
 384    }
 385  0 if (current.getElementOccurrence(i) != getElementOccurrence(i)) {
 386  0 return false;
 387    }
 388    }
 389  0 return true;
 390    }
 391   
 392  358104 public final String toString() {
 393  358104 final StringBuffer buffer = new StringBuffer();
 394  358104 for (int i = 0; i < size(); i++) {
 395  1843064 if (i != 0) {
 396  1484960 buffer.append("/");
 397    }
 398  1843064 buffer.append(getElementName(i));
 399  1843064 if (getElementOccurrence(i) != 1) {
 400  636275 buffer.append("[");
 401  636275 buffer.append(getElementOccurrence(i));
 402  636275 buffer.append("]");
 403    }
 404    }
 405  358104 if (getAttribute() != null) {
 406  6502 buffer.append("@");
 407  6502 buffer.append(getAttribute());
 408    }
 409  358104 return buffer.toString();
 410    }
 411   
 412  46 public final int hashCode() {
 413  46 int code = 0;
 414  46 if (attribute != null) {
 415  14 code ^= attribute.hashCode();
 416    }
 417  46 for (int i = 0; i < size(); i++) {
 418  164 code ^= i + 1;
 419  164 code ^= getElementName(i).hashCode();
 420  164 code ^= getElementOccurrence(i);
 421    }
 422  46 return code;
 423    }
 424   
 425    }