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