Clover coverage report - dom4j - 1.6.1
Coverage timestamp: ma mei 16 2005 14:23:01 GMT+01:00
file stats: LOC: 413   Methods: 29
NCLOC: 229   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
DefaultXPath.java 61,8% 69,7% 72,4% 68,6%
coverage coverage
 1    /*
 2    * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
 3    *
 4    * This software is open source.
 5    * See the bottom of this file for the licence.
 6    */
 7   
 8    package org.dom4j.xpath;
 9   
 10    import java.io.Serializable;
 11    import java.util.Collections;
 12    import java.util.Comparator;
 13    import java.util.HashMap;
 14    import java.util.HashSet;
 15    import java.util.Iterator;
 16    import java.util.List;
 17    import java.util.Map;
 18   
 19    import org.dom4j.InvalidXPathException;
 20    import org.dom4j.Node;
 21    import org.dom4j.NodeFilter;
 22    import org.dom4j.XPathException;
 23   
 24    import org.jaxen.FunctionContext;
 25    import org.jaxen.JaxenException;
 26    import org.jaxen.NamespaceContext;
 27    import org.jaxen.SimpleNamespaceContext;
 28    import org.jaxen.VariableContext;
 29    import org.jaxen.XPath;
 30    import org.jaxen.dom4j.Dom4jXPath;
 31   
 32    /**
 33    * <p>
 34    * Default implementation of {@link org.dom4j.XPath}which uses the <a
 35    * href="http://jaxen.org">Jaxen </a> project.
 36    * </p>
 37    *
 38    * @author bob mcwhirter
 39    * @author <a href="mailto:jstrachan@apache.org">James Strachan </a>
 40    */
 41    public class DefaultXPath implements org.dom4j.XPath, NodeFilter, Serializable {
 42    private String text;
 43   
 44    private XPath xpath;
 45   
 46    private NamespaceContext namespaceContext;
 47   
 48    /**
 49    * Construct an XPath
 50    *
 51    * @param text
 52    * DOCUMENT ME!
 53    *
 54    * @throws InvalidXPathException
 55    * DOCUMENT ME!
 56    */
 57  592 public DefaultXPath(String text) throws InvalidXPathException {
 58  592 this.text = text;
 59  592 this.xpath = parse(text);
 60    }
 61   
 62  11 public String toString() {
 63  11 return "[XPath: " + xpath + "]";
 64    }
 65   
 66    // XPath interface
 67   
 68    /**
 69    * Retrieve the textual XPath string used to initialize this Object
 70    *
 71    * @return The XPath string
 72    */
 73  0 public String getText() {
 74  0 return text;
 75    }
 76   
 77  0 public FunctionContext getFunctionContext() {
 78  0 return xpath.getFunctionContext();
 79    }
 80   
 81  0 public void setFunctionContext(FunctionContext functionContext) {
 82  0 xpath.setFunctionContext(functionContext);
 83    }
 84   
 85  0 public NamespaceContext getNamespaceContext() {
 86  0 return namespaceContext;
 87    }
 88   
 89  4 public void setNamespaceURIs(Map map) {
 90  4 setNamespaceContext(new SimpleNamespaceContext(map));
 91    }
 92   
 93  8 public void setNamespaceContext(NamespaceContext namespaceContext) {
 94  8 this.namespaceContext = namespaceContext;
 95  8 xpath.setNamespaceContext(namespaceContext);
 96    }
 97   
 98  0 public VariableContext getVariableContext() {
 99  0 return xpath.getVariableContext();
 100    }
 101   
 102  7 public void setVariableContext(VariableContext variableContext) {
 103  7 xpath.setVariableContext(variableContext);
 104    }
 105   
 106  7 public Object evaluate(Object context) {
 107  7 try {
 108  7 setNSContext(context);
 109   
 110  7 List answer = xpath.selectNodes(context);
 111   
 112  7 if ((answer != null) && (answer.size() == 1)) {
 113  6 return answer.get(0);
 114    }
 115   
 116  1 return answer;
 117    } catch (JaxenException e) {
 118  0 handleJaxenException(e);
 119   
 120  0 return null;
 121    }
 122    }
 123   
 124  0 public Object selectObject(Object context) {
 125  0 return evaluate(context);
 126    }
 127   
 128  289 public List selectNodes(Object context) {
 129  289 try {
 130  289 setNSContext(context);
 131   
 132  289 return xpath.selectNodes(context);
 133    } catch (JaxenException e) {
 134  1 handleJaxenException(e);
 135   
 136  0 return Collections.EMPTY_LIST;
 137    }
 138    }
 139   
 140  0 public List selectNodes(Object context, org.dom4j.XPath sortXPath) {
 141  0 List answer = selectNodes(context);
 142  0 sortXPath.sort(answer);
 143   
 144  0 return answer;
 145    }
 146   
 147  2 public List selectNodes(Object context, org.dom4j.XPath sortXPath,
 148    boolean distinct) {
 149  2 List answer = selectNodes(context);
 150  2 sortXPath.sort(answer, distinct);
 151   
 152  2 return answer;
 153    }
 154   
 155  71 public Node selectSingleNode(Object context) {
 156  71 try {
 157  71 setNSContext(context);
 158   
 159  71 Object answer = xpath.selectSingleNode(context);
 160   
 161  71 if (answer instanceof Node) {
 162  71 return (Node) answer;
 163    }
 164   
 165  0 if (answer == null) {
 166  0 return null;
 167    }
 168   
 169  0 throw new XPathException("The result of the XPath expression is "
 170    + "not a Node. It was: " + answer + " of type: "
 171    + answer.getClass().getName());
 172    } catch (JaxenException e) {
 173  0 handleJaxenException(e);
 174   
 175  0 return null;
 176    }
 177    }
 178   
 179  2151 public String valueOf(Object context) {
 180  2151 try {
 181  2151 setNSContext(context);
 182   
 183  2151 return xpath.stringValueOf(context);
 184    } catch (JaxenException e) {
 185  0 handleJaxenException(e);
 186   
 187  0 return "";
 188    }
 189    }
 190   
 191  38 public Number numberValueOf(Object context) {
 192  38 try {
 193  38 setNSContext(context);
 194   
 195  38 return xpath.numberValueOf(context);
 196    } catch (JaxenException e) {
 197  0 handleJaxenException(e);
 198   
 199  0 return null;
 200    }
 201    }
 202   
 203  2 public boolean booleanValueOf(Object context) {
 204  2 try {
 205  2 setNSContext(context);
 206   
 207  2 return xpath.booleanValueOf(context);
 208    } catch (JaxenException e) {
 209  0 handleJaxenException(e);
 210   
 211  0 return false;
 212    }
 213    }
 214   
 215    /**
 216    * <p>
 217    * <code>sort</code> sorts the given List of Nodes using this XPath
 218    * expression as a {@link Comparator}.
 219    * </p>
 220    *
 221    * @param list
 222    * is the list of Nodes to sort
 223    */
 224  0 public void sort(List list) {
 225  0 sort(list, false);
 226    }
 227   
 228    /**
 229    * <p>
 230    * <code>sort</code> sorts the given List of Nodes using this XPath
 231    * expression as a {@link Comparator}and optionally removing duplicates.
 232    * </p>
 233    *
 234    * @param list
 235    * is the list of Nodes to sort
 236    * @param distinct
 237    * if true then duplicate values (using the sortXPath for
 238    * comparisions) will be removed from the List
 239    */
 240  2 public void sort(List list, boolean distinct) {
 241  2 if ((list != null) && !list.isEmpty()) {
 242  2 int size = list.size();
 243  2 HashMap sortValues = new HashMap(size);
 244   
 245  2 for (int i = 0; i < size; i++) {
 246  1958 Object object = list.get(i);
 247   
 248  1958 if (object instanceof Node) {
 249  1958 Node node = (Node) object;
 250  1958 Object expression = getCompareValue(node);
 251  1958 sortValues.put(node, expression);
 252    }
 253    }
 254   
 255  2 sort(list, sortValues);
 256   
 257  2 if (distinct) {
 258  1 removeDuplicates(list, sortValues);
 259    }
 260    }
 261    }
 262   
 263  12 public boolean matches(Node node) {
 264  12 try {
 265  12 setNSContext(node);
 266   
 267  12 List answer = xpath.selectNodes(node);
 268   
 269  12 if ((answer != null) && (answer.size() > 0)) {
 270  6 Object item = answer.get(0);
 271   
 272  6 if (item instanceof Boolean) {
 273  0 return ((Boolean) item).booleanValue();
 274    }
 275   
 276  6 return answer.contains(node);
 277    }
 278   
 279  6 return false;
 280    } catch (JaxenException e) {
 281  0 handleJaxenException(e);
 282   
 283  0 return false;
 284    }
 285    }
 286   
 287    /**
 288    * Sorts the list based on the sortValues for each node
 289    *
 290    * @param list
 291    * DOCUMENT ME!
 292    * @param sortValues
 293    * DOCUMENT ME!
 294    */
 295  2 protected void sort(List list, final Map sortValues) {
 296  2 Collections.sort(list, new Comparator() {
 297  9366 public int compare(Object o1, Object o2) {
 298  9366 o1 = sortValues.get(o1);
 299  9366 o2 = sortValues.get(o2);
 300   
 301  9366 if (o1 == o2) {
 302  978 return 0;
 303  8388 } else if (o1 instanceof Comparable) {
 304  8388 Comparable c1 = (Comparable) o1;
 305   
 306  8388 return c1.compareTo(o2);
 307  0 } else if (o1 == null) {
 308  0 return 1;
 309  0 } else if (o2 == null) {
 310  0 return -1;
 311    } else {
 312  0 return o1.equals(o2) ? 0 : (-1);
 313    }
 314    }
 315    });
 316    }
 317   
 318    // Implementation methods
 319   
 320    /**
 321    * Removes items from the list which have duplicate values
 322    *
 323    * @param list
 324    * DOCUMENT ME!
 325    * @param sortValues
 326    * DOCUMENT ME!
 327    */
 328  1 protected void removeDuplicates(List list, Map sortValues) {
 329    // remove distinct
 330  1 HashSet distinctValues = new HashSet();
 331   
 332  1 for (Iterator iter = list.iterator(); iter.hasNext();) {
 333  979 Object node = iter.next();
 334  979 Object value = sortValues.get(node);
 335   
 336  979 if (distinctValues.contains(value)) {
 337  956 iter.remove();
 338    } else {
 339  23 distinctValues.add(value);
 340    }
 341    }
 342    }
 343   
 344    /**
 345    * DOCUMENT ME!
 346    *
 347    * @param node
 348    * DOCUMENT ME!
 349    *
 350    * @return the node expression used for sorting comparisons
 351    */
 352  1958 protected Object getCompareValue(Node node) {
 353  1958 return valueOf(node);
 354    }
 355   
 356  592 protected static XPath parse(String text) {
 357  592 try {
 358  592 return new Dom4jXPath(text);
 359    } catch (JaxenException e) {
 360  4 throw new InvalidXPathException(text, e.getMessage());
 361    } catch (Throwable t) {
 362  0 throw new InvalidXPathException(text, t);
 363    }
 364    }
 365   
 366  2570 protected void setNSContext(Object context) {
 367  2570 if (namespaceContext == null) {
 368  2561 xpath.setNamespaceContext(DefaultNamespaceContext.create(context));
 369    }
 370    }
 371   
 372  1 protected void handleJaxenException(JaxenException exception)
 373    throws XPathException {
 374  1 throw new XPathException(text, exception);
 375    }
 376    }
 377   
 378    /*
 379    * Redistribution and use of this software and associated documentation
 380    * ("Software"), with or without modification, are permitted provided that the
 381    * following conditions are met:
 382    *
 383    * 1. Redistributions of source code must retain copyright statements and
 384    * notices. Redistributions must also contain a copy of this document.
 385    *
 386    * 2. Redistributions in binary form must reproduce the above copyright notice,
 387    * this list of conditions and the following disclaimer in the documentation
 388    * and/or other materials provided with the distribution.
 389    *
 390    * 3. The name "DOM4J" must not be used to endorse or promote products derived
 391    * from this Software without prior written permission of MetaStuff, Ltd. For
 392    * written permission, please contact dom4j-info@metastuff.com.
 393    *
 394    * 4. Products derived from this Software may not be called "DOM4J" nor may
 395    * "DOM4J" appear in their names without prior written permission of MetaStuff,
 396    * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd.
 397    *
 398    * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org
 399    *
 400    * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND
 401    * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 402    * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 403    * ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE
 404    * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 405    * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 406    * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 407    * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 408    * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 409    * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 410    * POSSIBILITY OF SUCH DAMAGE.
 411    *
 412    * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
 413    */