Coverage Report - org.jaxen.jdom.DocumentNavigator

Classes in this File Line Coverage Branch Coverage Complexity
DocumentNavigator
74% 
77% 
3.312

 1  
 package org.jaxen.jdom;
 2  
 
 3  
 /*
 4  
  * $Header: /home/projects/jaxen/scm/jaxen/src/java/main/org/jaxen/jdom/DocumentNavigator.java,v 1.29 2005/06/28 13:44:46 elharo Exp $
 5  
  * $Revision: 1.29 $
 6  
  * $Date: 2005/06/28 13:44:46 $
 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.29 2005/06/28 13:44:46 elharo Exp $
 62  
 */
 63  
 
 64  
 import java.util.HashMap;
 65  
 import java.util.Iterator;
 66  
 import java.util.List;
 67  
 import java.util.Map;
 68  
 
 69  
 import org.jaxen.DefaultNavigator;
 70  
 import org.jaxen.FunctionCallException;
 71  
 import org.jaxen.NamedAccessNavigator;
 72  
 import org.jaxen.Navigator;
 73  
 import org.jaxen.XPath;
 74  
 import org.jaxen.JaxenConstants;
 75  
 import org.jaxen.saxpath.SAXPathException;
 76  
 import org.jaxen.util.SingleObjectIterator;
 77  
 import org.jdom.Attribute;
 78  
 import org.jdom.CDATA;
 79  
 import org.jdom.Comment;
 80  
 import org.jdom.Document;
 81  
 import org.jdom.Element;
 82  
 import org.jdom.Namespace;
 83  
 import org.jdom.ProcessingInstruction;
 84  
 import org.jdom.Text;
 85  
 import org.jdom.input.SAXBuilder;
 86  
 
 87  
 /** 
 88  
  * Interface for navigating around the JDOM object model.
 89  
  *
 90  
  * <p>
 91  
  * This class is not intended for direct usage, but is
 92  
  * used by the Jaxen engine during evaluation.
 93  
  * </p>
 94  
  *
 95  
  * @see XPath
 96  
  *
 97  
  * @author <a href="mailto:bob@werken.com">bob mcwhirter</a>
 98  
  * @author Stephen Colebourne
 99  
  */
 100  1656
 public class DocumentNavigator extends DefaultNavigator implements NamedAccessNavigator
 101  
 {
 102  
     /** Singleton implementation.
 103  
      */
 104  1656
     private static class Singleton
 105  
     {
 106  
         /** Singleton instance.
 107  
          */
 108  6
         private static DocumentNavigator instance = new DocumentNavigator();
 109  
     }
 110  
 
 111  
     public static Navigator getInstance()
 112  
     {
 113  42
         return Singleton.instance;
 114  
     }
 115  
 
 116  
     public boolean isElement(Object obj)
 117  
     {
 118  671406
         return obj instanceof Element;
 119  
     }
 120  
 
 121  
     public boolean isComment(Object obj)
 122  
     {
 123  6660
         return obj instanceof Comment;
 124  
     }
 125  
 
 126  
     public boolean isText(Object obj)
 127  
     {
 128  453492
         return ( obj instanceof Text
 129  
                  ||
 130  
                  obj instanceof CDATA );
 131  
     }
 132  
 
 133  
     public boolean isAttribute(Object obj)
 134  
     {
 135  26208
         return obj instanceof Attribute;
 136  
     }
 137  
 
 138  
     public boolean isProcessingInstruction(Object obj)
 139  
     {
 140  6480
         return obj instanceof ProcessingInstruction;
 141  
     }
 142  
 
 143  
     public boolean isDocument(Object obj)
 144  
     {
 145  7056
         return obj instanceof Document;
 146  
     }
 147  
 
 148  
     public boolean isNamespace(Object obj)
 149  
     {
 150  23904
         return obj instanceof Namespace || obj instanceof XPathNamespace;
 151  
     }
 152  
 
 153  
     public String getElementName(Object obj)
 154  
     {
 155  222408
         Element elem = (Element) obj;
 156  
 
 157  222408
         return elem.getName();
 158  
     }
 159  
 
 160  
     public String getElementNamespaceUri(Object obj)
 161  
     {
 162  221022
         Element elem = (Element) obj;
 163  
         
 164  221022
         String uri = elem.getNamespaceURI();
 165  221022
         if ( uri != null && uri.length() == 0 ) 
 166  220866
             return null;
 167  
         else
 168  156
             return uri;
 169  
     }
 170  
 
 171  
     public String getAttributeName(Object obj)
 172  
     {
 173  180
         Attribute attr = (Attribute) obj;
 174  
 
 175  180
         return attr.getName();
 176  
     }
 177  
 
 178  
     public String getAttributeNamespaceUri(Object obj)
 179  
     {
 180  180
         Attribute attr = (Attribute) obj;
 181  
 
 182  180
         String uri = attr.getNamespaceURI();
 183  180
         if ( uri != null && uri.length() == 0 ) 
 184  0
             return null;
 185  
         else
 186  180
             return uri;
 187  
     }
 188  
 
 189  
     public Iterator getChildAxisIterator(Object contextNode)
 190  
     {
 191  699594
         if ( contextNode instanceof Element )
 192  
         {
 193  242958
             return ((Element)contextNode).getContent().iterator();
 194  
         }
 195  456636
         else if ( contextNode instanceof Document )
 196  
         {
 197  1062
             return ((Document)contextNode).getContent().iterator();
 198  
         }
 199  
 
 200  455574
         return JaxenConstants.EMPTY_ITERATOR;
 201  
     }
 202  
 
 203  
     /**
 204  
      * Retrieves an <code>Iterator</code> over the child elements that
 205  
      * match the supplied name.
 206  
      *
 207  
      * @param contextNode  the origin context node
 208  
      * @param localName  the local name of the children to return, always present
 209  
      * @param namespacePrefix  the prefix of the namespace of the children to return
 210  
      * @param namespaceURI  the uri of the namespace of the children to return
 211  
      * @return an Iterator that traverses the named children, or null if none
 212  
      */
 213  
     public Iterator getChildAxisIterator(
 214  
             Object contextNode, String localName, String namespacePrefix, String namespaceURI) {
 215  
 
 216  14118
         if ( contextNode instanceof Element ) {
 217  5580
             Element node = (Element) contextNode;
 218  5580
             if (namespaceURI == null) {
 219  5526
                 return node.getChildren(localName).iterator();
 220  
             }
 221  54
             return node.getChildren(localName, Namespace.getNamespace(namespacePrefix, namespaceURI)).iterator();
 222  
         }
 223  8538
         if ( contextNode instanceof Document ) {
 224  678
             Document node = (Document) contextNode;
 225  
             
 226  678
             Element el = node.getRootElement();
 227  678
             if (el.getName().equals(localName) == false) {
 228  90
                 return JaxenConstants.EMPTY_ITERATOR;
 229  
             }
 230  588
             if (namespaceURI != null) {
 231  60
                 if (Namespace.getNamespace(namespacePrefix, namespaceURI).equals(el.getNamespace()) == false) {
 232  6
                     return JaxenConstants.EMPTY_ITERATOR;
 233  
                 }
 234  
             }
 235  582
             return new SingleObjectIterator(el);
 236  
         }
 237  
 
 238  7860
         return JaxenConstants.EMPTY_ITERATOR;
 239  
     }
 240  
     
 241  
     public Iterator getNamespaceAxisIterator(Object contextNode)
 242  
     {
 243  750
         if ( ! ( contextNode instanceof Element ) )
 244  
         {
 245  438
             return JaxenConstants.EMPTY_ITERATOR;
 246  
         }
 247  
 
 248  312
         Element elem = (Element) contextNode;
 249  
 
 250  312
         Map nsMap = new HashMap();
 251  
 
 252  312
         Element current = elem;
 253  
 
 254  1134
         while ( current != null ) {
 255  
         
 256  822
             Namespace ns = current.getNamespace();
 257  
             
 258  822
             if ( ns != Namespace.NO_NAMESPACE ) {
 259  180
                 if ( !nsMap.containsKey(ns.getPrefix()) )
 260  180
                     nsMap.put( ns.getPrefix(), new XPathNamespace(elem, ns) );
 261  
             }
 262  
         
 263  822
             Iterator additional = current.getAdditionalNamespaces().iterator();
 264  
 
 265  1362
             while ( additional.hasNext() ) {
 266  
 
 267  540
                 ns = (Namespace)additional.next();
 268  540
                 if ( !nsMap.containsKey(ns.getPrefix()) )
 269  360
                     nsMap.put( ns.getPrefix(), new XPathNamespace(elem, ns) );
 270  
             }
 271  
 
 272  822
             if (current.getParent() instanceof Element) {
 273  510
                 current = (Element)current.getParent();
 274  
             } else {
 275  312
                 current = null;
 276  
             }
 277  
         }
 278  
 
 279  312
         nsMap.put( "xml", new XPathNamespace(elem, Namespace.XML_NAMESPACE) );
 280  
 
 281  312
         return nsMap.values().iterator();
 282  
     }
 283  
 
 284  
     public Iterator getParentAxisIterator(Object contextNode)
 285  
     {
 286  150444
         Object parent = null;
 287  
 
 288  150444
         if ( contextNode instanceof Document )
 289  
         {
 290  29358
             return JaxenConstants.EMPTY_ITERATOR;
 291  
         }
 292  121086
         else if ( contextNode instanceof Element )
 293  
         {
 294  118338
             parent = ((Element)contextNode).getParent();
 295  
 
 296  118338
             if ( parent == null )
 297  
             {
 298  0
                 if ( ((Element)contextNode).isRootElement() )
 299  
                 {
 300  0
                     parent = ((Element)contextNode).getDocument();
 301  
                 }
 302  
             }
 303  
         }
 304  2748
         else if ( contextNode instanceof Attribute )
 305  
         {
 306  444
             parent = ((Attribute)contextNode).getParent();
 307  
         }
 308  2304
         else if ( contextNode instanceof XPathNamespace )
 309  
         {
 310  1944
             parent = ((XPathNamespace)contextNode).getJDOMElement();
 311  
         }
 312  360
         else if ( contextNode instanceof ProcessingInstruction )
 313  
         {
 314  120
             parent = ((ProcessingInstruction)contextNode).getParent();
 315  
         }
 316  240
         else if ( contextNode instanceof Comment )
 317  
         {
 318  120
             parent = ((Comment)contextNode).getParent();
 319  
         }
 320  120
         else if ( contextNode instanceof Text )
 321  
         {
 322  120
             parent = ((Text)contextNode).getParent();
 323  
         }
 324  
         
 325  121086
         if ( parent != null )
 326  
         {
 327  121086
             return new SingleObjectIterator( parent );
 328  
         }
 329  
 
 330  0
         return JaxenConstants.EMPTY_ITERATOR;
 331  
     }
 332  
 
 333  
     public Iterator getAttributeAxisIterator(Object contextNode)
 334  
     {
 335  306
         if ( ! ( contextNode instanceof Element ) )
 336  
         {
 337  0
             return JaxenConstants.EMPTY_ITERATOR;
 338  
         }
 339  
 
 340  306
         Element elem = (Element) contextNode;
 341  
 
 342  306
         return elem.getAttributes().iterator();
 343  
     }
 344  
 
 345  
     /**
 346  
      * Retrieves an <code>Iterator</code> over the attribute elements that
 347  
      * match the supplied name.
 348  
      *
 349  
      * @param contextNode  the origin context node
 350  
      * @param localName  the local name of the attributes to return, always present
 351  
      * @param namespacePrefix  the prefix of the namespace of the attributes to return
 352  
      * @param namespaceURI  the URI of the namespace of the attributes to return
 353  
      * @return an Iterator that traverses the named attributes, not null
 354  
      */
 355  
     public Iterator getAttributeAxisIterator(
 356  
             Object contextNode, String localName, String namespacePrefix, String namespaceURI) {
 357  
 
 358  3564
         if ( contextNode instanceof Element ) {
 359  3288
             Element node = (Element) contextNode;
 360  3288
             Namespace namespace = (namespaceURI == null ? Namespace.NO_NAMESPACE : 
 361  
                                     Namespace.getNamespace(namespacePrefix, namespaceURI));
 362  3288
             Attribute attr = node.getAttribute(localName, namespace);
 363  3288
             if (attr != null) {
 364  1902
                 return new SingleObjectIterator(attr);
 365  
             }
 366  
         }
 367  1662
         return JaxenConstants.EMPTY_ITERATOR;
 368  
     }
 369  
 
 370  
     /** Returns a parsed form of the given XPath string, which will be suitable
 371  
      *  for queries on JDOM documents.
 372  
      */
 373  
     public XPath parseXPath (String xpath) throws SAXPathException
 374  
     {
 375  42
         return new JDOMXPath(xpath);
 376  
     }
 377  
 
 378  
     public Object getDocumentNode(Object contextNode)
 379  
     {
 380  1554
         if ( contextNode instanceof Document )
 381  
         {
 382  1146
             return contextNode;
 383  
         }
 384  
 
 385  408
         Element elem = (Element) contextNode;
 386  
 
 387  408
         return elem.getDocument();
 388  
     }
 389  
 
 390  
     public String getElementQName(Object obj)
 391  
     {
 392  156
         Element elem = (Element) obj;
 393  
 
 394  156
         String prefix = elem.getNamespacePrefix();
 395  
 
 396  156
         if ( prefix == null || prefix.length() == 0 )
 397  
         {
 398  156
             return elem.getName();
 399  
         }
 400  
 
 401  0
         return prefix + ":" + elem.getName();
 402  
     }
 403  
 
 404  
     public String getAttributeQName(Object obj)
 405  
     {
 406  0
         Attribute attr = (Attribute) obj;
 407  
 
 408  0
         String prefix = attr.getNamespacePrefix();
 409  
 
 410  0
         if ( prefix == null || "".equals( prefix ) )
 411  
         {
 412  0
             return attr.getName();
 413  
         }
 414  
 
 415  0
         return prefix + ":" + attr.getName();
 416  
     }
 417  
 
 418  
     public String getNamespaceStringValue(Object obj)
 419  
     {
 420  0
         if (obj instanceof Namespace) {
 421  
 
 422  0
             Namespace ns = (Namespace) obj;
 423  0
             return ns.getURI();
 424  
         } else {
 425  
 
 426  0
             XPathNamespace ns = (XPathNamespace) obj;
 427  0
             return ns.getJDOMNamespace().getURI();
 428  
         }
 429  
         
 430  
     }
 431  
 
 432  
     public String getNamespacePrefix(Object obj)
 433  
     {
 434  702
         if (obj instanceof Namespace) {
 435  
 
 436  0
             Namespace ns = (Namespace) obj;
 437  0
             return ns.getPrefix();
 438  
         } else {
 439  
 
 440  702
             XPathNamespace ns = (XPathNamespace) obj;
 441  702
             return ns.getJDOMNamespace().getPrefix();
 442  
         }
 443  
     }
 444  
 
 445  
     public String getTextStringValue(Object obj)
 446  
     {
 447  66
         if ( obj instanceof Text )
 448  
         {
 449  66
             return ((Text)obj).getText();
 450  
         }
 451  
 
 452  0
         if ( obj instanceof CDATA )
 453  
         {
 454  0
             return ((CDATA)obj).getText();
 455  
         }
 456  
 
 457  0
         return "";
 458  
     }
 459  
 
 460  
     public String getAttributeStringValue(Object obj)
 461  
     {
 462  1722
         Attribute attr = (Attribute) obj;
 463  
 
 464  1722
         return attr.getValue();
 465  
     }
 466  
 
 467  
     public String getElementStringValue(Object obj)
 468  
     {
 469  828
         Element elem = (Element) obj;
 470  
 
 471  828
         StringBuffer buf = new StringBuffer();
 472  
 
 473  828
         List     content     = elem.getContent();
 474  828
         Iterator contentIter = content.iterator();
 475  828
         Object   each        = null;
 476  
 
 477  1680
         while ( contentIter.hasNext() )
 478  
         {
 479  852
             each = contentIter.next();
 480  
 
 481  852
             if ( each instanceof Text )
 482  
             {
 483  798
                 buf.append( ((Text)each).getText() );
 484  
             }
 485  54
             else if ( each instanceof CDATA )
 486  
             {
 487  0
                 buf.append( ((CDATA)each).getText() );
 488  
             }
 489  54
             else if ( each instanceof Element )
 490  
             {
 491  54
                 buf.append( getElementStringValue( each ) );
 492  
             }
 493  
         }
 494  
 
 495  828
         return buf.toString();
 496  
     }
 497  
 
 498  
     public String getProcessingInstructionTarget(Object obj)
 499  
     {
 500  36
         ProcessingInstruction pi = (ProcessingInstruction) obj;
 501  
 
 502  36
         return pi.getTarget();
 503  
     }
 504  
 
 505  
     public String getProcessingInstructionData(Object obj)
 506  
     {
 507  18
         ProcessingInstruction pi = (ProcessingInstruction) obj;
 508  
 
 509  18
         return pi.getData();
 510  
     }
 511  
 
 512  
     public String getCommentStringValue(Object obj)
 513  
     {
 514  0
         Comment cmt = (Comment) obj;
 515  
 
 516  0
         return cmt.getText();
 517  
     }
 518  
 
 519  
     public String translateNamespacePrefixToUri(String prefix, Object context)
 520  
     {
 521  0
         Element element = null;
 522  0
         if ( context instanceof Element ) 
 523  
         {
 524  0
             element = (Element) context;
 525  
         }
 526  0
         else if ( context instanceof Text )
 527  
         {
 528  0
             element = (Element)((Text)context).getParent();
 529  
         }
 530  0
         else if ( context instanceof Attribute )
 531  
         {
 532  0
             element = ((Attribute)context).getParent();
 533  
         }
 534  0
         else if ( context instanceof XPathNamespace )
 535  
         {
 536  0
             element = ((XPathNamespace)context).getJDOMElement();
 537  
         }
 538  0
         else if ( context instanceof Comment )
 539  
         {
 540  0
             element = (Element)((Comment)context).getParent();
 541  
         }
 542  0
         else if ( context instanceof ProcessingInstruction )
 543  
         {
 544  0
             element = (Element)((ProcessingInstruction)context).getParent();
 545  
         }
 546  
 
 547  0
         if ( element != null )
 548  
         {
 549  0
             Namespace namespace = element.getNamespace( prefix );
 550  
 
 551  0
             if ( namespace != null ) 
 552  
             {
 553  0
                 return namespace.getURI();
 554  
             }
 555  
         }
 556  0
         return null;
 557  
     }
 558  
 
 559  
     public Object getDocument(String url) throws FunctionCallException
 560  
     {
 561  
         try
 562  
         {
 563  396
             SAXBuilder builder = new SAXBuilder();
 564  
             
 565  396
             return builder.build( url );
 566  
         }
 567  0
         catch (Exception e)
 568  
         {
 569  0
             throw new FunctionCallException( e.getMessage() );
 570  
         }
 571  
     }
 572  
 }