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