Coverage Report - org.jaxen.dom4j.DocumentNavigator

Classes in this File Line Coverage Branch Coverage Complexity
DocumentNavigator
81% 
88% 
2.405

 1  
 package org.jaxen.dom4j;
 2  
 
 3  
 /*
 4  
  * $Header: /home/projects/jaxen/scm/jaxen/src/java/main/org/jaxen/dom4j/DocumentNavigator.java,v 1.30 2005/06/28 13:44:45 elharo Exp $
 5  
  * $Revision: 1.30 $
 6  
  * $Date: 2005/06/28 13:44:45 $
 7  
  *
 8  
  * ====================================================================
 9  
  *
 10  
  * Copyright (C) 2000-2005 bob mcwhirter & James Strachan.
 11  
  * All rights reserved.
 12  
  *
 13  
  * Redistribution and use in source and binary forms, with or without
 14  
  * modification, are permitted provided that the following conditions
 15  
  * are met:
 16  
  *
 17  
  * 1. Redistributions of source code must retain the above copyright
 18  
  *    notice, this list of conditions, and the following disclaimer.
 19  
  *
 20  
  * 2. Redistributions in binary form must reproduce the above copyright
 21  
  *    notice, this list of conditions, and the disclaimer that follows
 22  
  *    these conditions in the documentation and/or other materials
 23  
  *    provided with the distribution.
 24  
  *
 25  
  * 3. The name "Jaxen" must not be used to endorse or promote products
 26  
  *    derived from this software without prior written permission.  For
 27  
  *    written permission, please contact license@jaxen.org.
 28  
  *
 29  
  * 4. Products derived from this software may not be called "Jaxen", nor
 30  
  *    may "Jaxen" appear in their name, without prior written permission
 31  
  *    from the Jaxen Project Management (pm@jaxen.org).
 32  
  *
 33  
  * In addition, we request (but do not require) that you include in the
 34  
  * end-user documentation provided with the redistribution and/or in the
 35  
  * software itself an acknowledgement equivalent to the following:
 36  
  *     "This product includes software developed by the
 37  
  *      Jaxen Project <http://www.jaxen.org/>."
 38  
  * Alternatively, the acknowledgment may be graphical using the logos
 39  
  * available at http://www.jaxen.org/
 40  
  *
 41  
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 42  
  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 43  
  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 44  
  * DISCLAIMED.  IN NO EVENT SHALL THE Jaxen AUTHORS OR THE PROJECT
 45  
  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 46  
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 47  
  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 48  
  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 49  
  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 50  
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 51  
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 52  
  * SUCH DAMAGE.
 53  
  *
 54  
  * ====================================================================
 55  
  * This software consists of voluntary contributions made by many
 56  
  * individuals on behalf of the Jaxen Project and was originally
 57  
  * created by bob mcwhirter <bob@werken.com> and
 58  
  * James Strachan <jstrachan@apache.org>.  For more information on the
 59  
  * Jaxen Project, please see <http://www.jaxen.org/>.
 60  
  *
 61  
  * $Id: DocumentNavigator.java,v 1.30 2005/06/28 13:44:45 elharo Exp $
 62  
 */
 63  
 
 64  
 import java.util.ArrayList;
 65  
 import java.util.HashSet;
 66  
 import java.util.Iterator;
 67  
 import java.util.List;
 68  
 
 69  
 import org.dom4j.Attribute;
 70  
 import org.dom4j.Branch;
 71  
 import org.dom4j.CDATA;
 72  
 import org.dom4j.Comment;
 73  
 import org.dom4j.Document;
 74  
 import org.dom4j.DocumentException;
 75  
 import org.dom4j.Element;
 76  
 import org.dom4j.Namespace;
 77  
 import org.dom4j.Node;
 78  
 import org.dom4j.ProcessingInstruction;
 79  
 import org.dom4j.QName;
 80  
 import org.dom4j.Text;
 81  
 import org.dom4j.io.SAXReader;
 82  
 import org.jaxen.DefaultNavigator;
 83  
 import org.jaxen.FunctionCallException;
 84  
 import org.jaxen.NamedAccessNavigator;
 85  
 import org.jaxen.Navigator;
 86  
 import org.jaxen.XPath;
 87  
 import org.jaxen.JaxenConstants;
 88  
 import org.jaxen.saxpath.SAXPathException;
 89  
 import org.jaxen.util.SingleObjectIterator;
 90  
 
 91  
 /** 
 92  
  * Interface for navigating around the DOM4J object model.
 93  
  *
 94  
  * <p>
 95  
  * This class is not intended for direct usage, but is
 96  
  * used by the Jaxen engine during evaluation.
 97  
  * </p>
 98  
  *
 99  
  * @see XPath
 100  
  *
 101  
  * @author <a href="mailto:bob@werken.com">bob mcwhirter</a>
 102  
  * @author Stephen Colebourne
 103  
  */
 104  1668
 public class DocumentNavigator extends DefaultNavigator implements NamedAccessNavigator
 105  
 {
 106  
     
 107  
     private transient SAXReader reader;
 108  
 
 109  
     /** Singleton implementation.
 110  
      */
 111  1668
     private static class Singleton
 112  
     {
 113  
         /** Singleton instance.
 114  
          */
 115  12
         private static DocumentNavigator instance = new DocumentNavigator();
 116  
     }
 117  
 
 118  
     /** Retrieve the singleton instance of this <code>DocumentNavigator</code>.
 119  
      */
 120  
     public static Navigator getInstance()
 121  
     {
 122  84
         return Singleton.instance;
 123  
     }
 124  
 
 125  
     public boolean isElement(Object obj)
 126  
     {
 127  671322
         return obj instanceof Element;
 128  
     }
 129  
 
 130  
     public boolean isComment(Object obj)
 131  
     {
 132  6588
         return obj instanceof Comment;
 133  
     }
 134  
 
 135  
     public boolean isText(Object obj)
 136  
     {
 137  453414
         return ( obj instanceof Text 
 138  
                  ||
 139  
                  obj instanceof CDATA );
 140  
     }
 141  
 
 142  
     public boolean isAttribute(Object obj)
 143  
     {
 144  26394
         return obj instanceof Attribute;
 145  
     }
 146  
 
 147  
     public boolean isProcessingInstruction(Object obj)
 148  
     {
 149  6348
         return obj instanceof ProcessingInstruction;
 150  
     }
 151  
 
 152  
     public boolean isDocument(Object obj)
 153  
     {
 154  6954
         return obj instanceof Document;
 155  
     }
 156  
 
 157  
     public boolean isNamespace(Object obj)
 158  
     {
 159  24090
         return obj instanceof Namespace;
 160  
     }
 161  
 
 162  
     public String getElementName(Object obj)
 163  
     {
 164  222420
         Element elem = (Element) obj;
 165  
 
 166  222420
         return elem.getName();
 167  
     }
 168  
 
 169  
     public String getElementNamespaceUri(Object obj)
 170  
     {
 171  221034
         Element elem = (Element) obj;
 172  
         
 173  221034
         String uri = elem.getNamespaceURI();
 174  221034
         if ( uri == null)
 175  0
             return "";
 176  
         else
 177  221034
             return uri;
 178  
     }
 179  
 
 180  
     public String getElementQName(Object obj)
 181  
     {
 182  156
         Element elem = (Element) obj;
 183  
 
 184  156
         return elem.getQualifiedName();
 185  
     }
 186  
 
 187  
     public String getAttributeName(Object obj)
 188  
     {
 189  180
         Attribute attr = (Attribute) obj;
 190  
 
 191  180
         return attr.getName();
 192  
     }
 193  
 
 194  
     public String getAttributeNamespaceUri(Object obj)
 195  
     {
 196  180
         Attribute attr = (Attribute) obj;
 197  
 
 198  180
         String uri = attr.getNamespaceURI();
 199  180
         if ( uri == null)
 200  0
             return "";
 201  
         else
 202  180
             return uri;
 203  
     }
 204  
 
 205  
     public String getAttributeQName(Object obj)
 206  
     {
 207  0
         Attribute attr = (Attribute) obj;
 208  
 
 209  0
         return attr.getQualifiedName();
 210  
     }
 211  
 
 212  
     public Iterator getChildAxisIterator(Object contextNode)
 213  
     {
 214  699954
         Iterator result = null;
 215  699954
         if ( contextNode instanceof Branch )
 216  
         {
 217  244110
             Branch node = (Branch) contextNode;
 218  244110
             result = node.nodeIterator();
 219  
         }
 220  699954
         if (result != null) {
 221  244110
             return result;
 222  
         }
 223  455844
         return JaxenConstants.EMPTY_ITERATOR;
 224  
     }
 225  
 
 226  
     /**
 227  
      * Retrieves an <code>Iterator</code> over the child elements that
 228  
      * match the supplied name.
 229  
      *
 230  
      * @param contextNode  the origin context node
 231  
      * @param localName  the local name of the children to return, always present
 232  
      * @param namespacePrefix  the prefix of the namespace of the children to return
 233  
      * @param namespaceURI  the uri of the namespace of the children to return
 234  
      * @return an Iterator that traverses the named children, or null if none
 235  
      */
 236  
     public Iterator getChildAxisIterator(
 237  
             Object contextNode, String localName, String namespacePrefix, String namespaceURI) {
 238  
 
 239  14148
         if ( contextNode instanceof Element ) {
 240  5598
             Element node = (Element) contextNode;
 241  5598
             return node.elementIterator(QName.get(localName, namespacePrefix, namespaceURI));
 242  
         }
 243  8550
         if ( contextNode instanceof Document ) {
 244  690
             Document node = (Document) contextNode;
 245  690
             Element el = node.getRootElement();
 246  690
             if (el.getName().equals(localName) == false) {
 247  90
                 return JaxenConstants.EMPTY_ITERATOR;
 248  
             }
 249  600
             if (namespaceURI != null) {
 250  60
                 if (namespaceURI.equals(el.getNamespaceURI()) == false) {
 251  6
                     return JaxenConstants.EMPTY_ITERATOR;
 252  
                 }
 253  
             }
 254  594
             return new SingleObjectIterator(el);
 255  
         }
 256  
 
 257  7860
         return JaxenConstants.EMPTY_ITERATOR;
 258  
     }
 259  
 
 260  
     public Iterator getParentAxisIterator(Object contextNode)
 261  
     {
 262  84
         if ( contextNode instanceof Document )
 263  
         {
 264  6
             return JaxenConstants.EMPTY_ITERATOR;
 265  
         }
 266  
 
 267  78
         Node node = (Node) contextNode;
 268  
 
 269  78
         Object parent = node.getParent();
 270  
 
 271  78
         if ( parent == null )
 272  
         {
 273  30
             parent = node.getDocument();
 274  
         }
 275  
         
 276  78
         return new SingleObjectIterator( parent );
 277  
     }
 278  
 
 279  
     public Iterator getAttributeAxisIterator(Object contextNode)
 280  
     {
 281  306
         if ( ! ( contextNode instanceof Element ) )
 282  
         {
 283  0
             return JaxenConstants.EMPTY_ITERATOR;
 284  
         }
 285  
 
 286  306
         Element elem = (Element) contextNode;
 287  
 
 288  306
         return elem.attributeIterator();
 289  
     }
 290  
 
 291  
     /**
 292  
      * Retrieves an <code>Iterator</code> over the attribute elements that
 293  
      * match the supplied name.
 294  
      *
 295  
      * @param contextNode  the origin context node
 296  
      * @param localName  the local name of the attributes to return, always present
 297  
      * @param namespacePrefix  the prefix of the namespace of the attributes to return
 298  
      * @param namespaceURI  the URI of the namespace of the attributes to return
 299  
      * @return an Iterator that traverses the named attributes, not null
 300  
      */
 301  
     public Iterator getAttributeAxisIterator(
 302  
             Object contextNode, String localName, String namespacePrefix, String namespaceURI) {
 303  
 
 304  3564
         if ( contextNode instanceof Element ) {
 305  3288
             Element node = (Element) contextNode;
 306  3288
             Attribute attr = node.attribute(QName.get(localName, namespacePrefix, namespaceURI));
 307  3288
             if (attr == null) {
 308  1386
                 return JaxenConstants.EMPTY_ITERATOR;
 309  
             }
 310  1902
             return new SingleObjectIterator(attr);
 311  
         }
 312  276
         return JaxenConstants.EMPTY_ITERATOR;
 313  
     }
 314  
         
 315  
     public Iterator getNamespaceAxisIterator(Object contextNode)
 316  
     {
 317  1002
         if ( ! ( contextNode instanceof Element ) )
 318  
         {
 319  624
             return JaxenConstants.EMPTY_ITERATOR;
 320  
         }
 321  
 
 322  378
         Element element = (Element) contextNode;
 323  378
         List nsList = new ArrayList();
 324  378
         HashSet prefixes = new HashSet();
 325  1368
         for ( Element context = element; context != null; context = context.getParent() ) {
 326  990
             List declaredNS = new ArrayList(context.declaredNamespaces());
 327  990
             declaredNS.add(context.getNamespace());
 328  
 
 329  990
             for ( Iterator iter = context.attributes().iterator(); iter.hasNext(); )
 330  
             {
 331  492
                 Attribute attr = (Attribute) iter.next();
 332  492
                 declaredNS.add(attr.getNamespace());
 333  
             }
 334  
 
 335  990
             for ( Iterator iter = declaredNS.iterator(); iter.hasNext(); )
 336  
             {
 337  2118
                 Namespace namespace = (Namespace) iter.next();
 338  2118
                 if (namespace != Namespace.NO_NAMESPACE)
 339  
                 {
 340  882
                     String prefix = namespace.getPrefix();
 341  882
                     if ( ! prefixes.contains( prefix ) ) {
 342  666
                         prefixes.add( prefix );
 343  666
                         nsList.add( namespace.asXPathResult( element ) );
 344  
                     }
 345  
                 }
 346  
             }
 347  
         }
 348  378
         nsList.add( Namespace.XML_NAMESPACE.asXPathResult( element ) );
 349  378
         return nsList.iterator();
 350  
     }
 351  
 
 352  
     public Object getDocumentNode(Object contextNode)
 353  
     {
 354  1578
         if ( contextNode instanceof Document ) 
 355  
         {
 356  1170
             return contextNode;
 357  
         }
 358  408
         else if ( contextNode instanceof Node ) 
 359  
         {
 360  408
             Node node = (Node) contextNode;
 361  408
             return node.getDocument();
 362  
         }
 363  0
         return null;
 364  
     }
 365  
 
 366  
     /** Returns a parsed form of the given xpath string, which will be suitable
 367  
      *  for queries on DOM4J documents.
 368  
      */
 369  
     public XPath parseXPath (String xpath) throws SAXPathException
 370  
     {
 371  42
         return new Dom4jXPath(xpath);
 372  
     }
 373  
 
 374  
     public Object getParentNode(Object contextNode)
 375  
     {
 376  150834
         if ( contextNode instanceof Node ) 
 377  
         {
 378  150834
             Node node = (Node) contextNode;
 379  150834
             Object answer = node.getParent();
 380  150834
             if ( answer == null ) 
 381  
             {
 382  58992
                 answer = node.getDocument();
 383  58992
                 if (answer == contextNode) {
 384  29388
                     return null;
 385  
                 }
 386  
             }
 387  121446
             return answer;            
 388  
         }
 389  0
         return null;
 390  
     }
 391  
 
 392  
     public String getTextStringValue(Object obj)
 393  
     {
 394  66
         return getNodeStringValue( (Node) obj );
 395  
     }
 396  
 
 397  
     public String getElementStringValue(Object obj)
 398  
     {
 399  780
         return getNodeStringValue( (Node) obj );
 400  
     }
 401  
 
 402  
     public String getAttributeStringValue(Object obj)
 403  
     {
 404  1722
         return getNodeStringValue( (Node) obj );
 405  
     }
 406  
 
 407  
     private String getNodeStringValue(Node node)
 408  
     {
 409  2568
         return node.getStringValue();
 410  
     }
 411  
 
 412  
     public String getNamespaceStringValue(Object obj)
 413  
     {
 414  0
         Namespace ns = (Namespace) obj;
 415  
 
 416  0
         return ns.getURI();
 417  
     }
 418  
 
 419  
     public String getNamespacePrefix(Object obj)
 420  
     {
 421  702
         Namespace ns = (Namespace) obj;
 422  
 
 423  702
         return ns.getPrefix();
 424  
     }
 425  
 
 426  
     public String getCommentStringValue(Object obj)
 427  
     {
 428  0
         Comment cmt = (Comment) obj;
 429  
 
 430  0
         return cmt.getText();
 431  
     }
 432  
     
 433  
     public String translateNamespacePrefixToUri(String prefix, Object context)
 434  
     {
 435  0
         Element element = null;
 436  0
         if ( context instanceof Element ) 
 437  
         {
 438  0
             element = (Element) context;
 439  
         }
 440  0
         else if ( context instanceof Node )
 441  
         {
 442  0
             Node node = (Node) context;
 443  0
             element = node.getParent();
 444  
         }
 445  0
         if ( element != null )
 446  
         {
 447  0
             Namespace namespace = element.getNamespaceForPrefix( prefix );
 448  
 
 449  0
             if ( namespace != null ) 
 450  
             {
 451  0
                 return namespace.getURI();
 452  
             }
 453  
         }
 454  0
         return null;
 455  
     }
 456  
     
 457  
     public short getNodeType(Object node) 
 458  
     {
 459  150
         if ( node instanceof Node )
 460  
         {
 461  150
             return ((Node) node).getNodeType();
 462  
         }
 463  0
         return 0;
 464  
     }
 465  
     
 466  
     public Object getDocument(String uri) throws FunctionCallException
 467  
     {
 468  
         try
 469  
         {
 470  402
             return getSAXReader().read( uri );
 471  
         }
 472  0
         catch (DocumentException e)
 473  
         {
 474  0
             throw new FunctionCallException("Failed to parse document for URI: " + uri, e);
 475  
         }
 476  
     }
 477  
 
 478  
     public String getProcessingInstructionTarget(Object obj)
 479  
     {
 480  36
         ProcessingInstruction pi = (ProcessingInstruction) obj;
 481  
 
 482  36
         return pi.getTarget();
 483  
     }
 484  
 
 485  
     public String getProcessingInstructionData(Object obj)
 486  
     {
 487  18
         ProcessingInstruction pi = (ProcessingInstruction) obj;
 488  
 
 489  18
         return pi.getText();
 490  
     }
 491  
     
 492  
     // Properties
 493  
     //-------------------------------------------------------------------------    
 494  
     public SAXReader getSAXReader()
 495  
     {
 496  402
         if ( reader == null ) 
 497  
         {
 498  396
             reader = new SAXReader();
 499  396
             reader.setMergeAdjacentText( true );
 500  
         }
 501  402
         return reader;
 502  
     }
 503  
     
 504  
     public void setSAXReader(SAXReader reader)
 505  
     {
 506  0
         this.reader = reader;
 507  0
     }
 508  
     
 509  
 }