Coverage Report - org.jaxen.jdom.DocumentNavigator

Classes in this Package Line Coverage Branch Coverage Complexity
DocumentNavigator
67% 
69% 
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.28 2005/04/09 21:56:31 elharo Exp $
 5  
  * $Revision: 1.28 $
 6  
  * $Date: 2005/04/09 21:56:31 $
 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.28 2005/04/09 21:56:31 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  156
 public class DocumentNavigator extends DefaultNavigator implements NamedAccessNavigator
 101  
 {
 102  
     /** Singleton implementation.
 103  
      */
 104  156
     private static class Singleton
 105  
     {
 106  
         /** Singleton instance.
 107  
          */
 108  2
         private static DocumentNavigator instance = new DocumentNavigator();
 109  
     }
 110  
 
 111  
     public static Navigator getInstance()
 112  
     {
 113  13
         return Singleton.instance;
 114  
     }
 115  
 
 116  
     public boolean isElement(Object obj)
 117  
     {
 118  111865
         return obj instanceof Element;
 119  
     }
 120  
 
 121  
     public boolean isComment(Object obj)
 122  
     {
 123  1072
         return obj instanceof Comment;
 124  
     }
 125  
 
 126  
     public boolean isText(Object obj)
 127  
     {
 128  75688
         return ( obj instanceof Text
 129  
                  ||
 130  
                  obj instanceof CDATA );
 131  
     }
 132  
 
 133  
     public boolean isAttribute(Object obj)
 134  
     {
 135  4352
         return obj instanceof Attribute;
 136  
     }
 137  
 
 138  
     public boolean isProcessingInstruction(Object obj)
 139  
     {
 140  1042
         return obj instanceof ProcessingInstruction;
 141  
     }
 142  
 
 143  
     public boolean isDocument(Object obj)
 144  
     {
 145  1400
         return obj instanceof Document;
 146  
     }
 147  
 
 148  
     public boolean isNamespace(Object obj)
 149  
     {
 150  3973
         return obj instanceof Namespace || obj instanceof XPathNamespace;
 151  
     }
 152  
 
 153  
     public String getElementName(Object obj)
 154  
     {
 155  37070
         Element elem = (Element) obj;
 156  
 
 157  37070
         return elem.getName();
 158  
     }
 159  
 
 160  
     public String getElementNamespaceUri(Object obj)
 161  
     {
 162  36839
         Element elem = (Element) obj;
 163  
         
 164  36839
         String uri = elem.getNamespaceURI();
 165  36839
         if ( uri != null && uri.length() == 0 ) 
 166  36811
             return null;
 167  
         else
 168  28
             return uri;
 169  
     }
 170  
 
 171  
     public String getAttributeName(Object obj)
 172  
     {
 173  30
         Attribute attr = (Attribute) obj;
 174  
 
 175  30
         return attr.getName();
 176  
     }
 177  
 
 178  
     public String getAttributeNamespaceUri(Object obj)
 179  
     {
 180  30
         Attribute attr = (Attribute) obj;
 181  
 
 182  30
         String uri = attr.getNamespaceURI();
 183  30
         if ( uri != null && uri.length() == 0 ) 
 184  0
             return null;
 185  
         else
 186  30
             return uri;
 187  
     }
 188  
 
 189  
     public Iterator getChildAxisIterator(Object contextNode)
 190  
     {
 191  116860
         if ( contextNode instanceof Element )
 192  
         {
 193  40629
             return ((Element)contextNode).getContent().iterator();
 194  
         }
 195  76231
         else if ( contextNode instanceof Document )
 196  
         {
 197  179
             return ((Document)contextNode).getContent().iterator();
 198  
         }
 199  
 
 200  76052
         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  2362
         if ( contextNode instanceof Element ) {
 217  934
             Element node = (Element) contextNode;
 218  934
             if (namespaceURI == null) {
 219  925
                 return node.getChildren(localName).iterator();
 220  
             }
 221  9
             return node.getChildren(localName, Namespace.getNamespace(namespacePrefix, namespaceURI)).iterator();
 222  
         }
 223  1428
         if ( contextNode instanceof Document ) {
 224  115
             Document node = (Document) contextNode;
 225  
             
 226  115
             Element el = node.getRootElement();
 227  115
             if (el.getName().equals(localName) == false) {
 228  16
                 return JaxenConstants.EMPTY_ITERATOR;
 229  
             }
 230  99
             if (namespaceURI != null) {
 231  10
                 if (Namespace.getNamespace(namespacePrefix, namespaceURI).equals(el.getNamespace()) == false) {
 232  1
                     return JaxenConstants.EMPTY_ITERATOR;
 233  
                 }
 234  
             }
 235  98
             return new SingleObjectIterator(el);
 236  
         }
 237  
 
 238  1313
         return JaxenConstants.EMPTY_ITERATOR;
 239  
     }
 240  
     
 241  
     public Iterator getNamespaceAxisIterator(Object contextNode)
 242  
     {
 243  105
         if ( ! ( contextNode instanceof Element ) )
 244  
         {
 245  60
             return JaxenConstants.EMPTY_ITERATOR;
 246  
         }
 247  
 
 248  45
         Element elem = (Element) contextNode;
 249  
 
 250  45
         Map nsMap = new HashMap();
 251  
 
 252  45
         Element current = elem;
 253  
 
 254  160
         while ( current != null ) {
 255  
         
 256  115
             Namespace ns = current.getNamespace();
 257  
             
 258  115
             if ( ns != Namespace.NO_NAMESPACE ) {
 259  27
                 if ( !nsMap.containsKey(ns.getPrefix()) )
 260  27
                     nsMap.put( ns.getPrefix(), new XPathNamespace(elem, ns) );
 261  
             }
 262  
         
 263  115
             Iterator additional = current.getAdditionalNamespaces().iterator();
 264  
 
 265  189
             while ( additional.hasNext() ) {
 266  
 
 267  74
                 ns = (Namespace)additional.next();
 268  74
                 if ( !nsMap.containsKey(ns.getPrefix()) )
 269  50
                     nsMap.put( ns.getPrefix(), new XPathNamespace(elem, ns) );
 270  
             }
 271  
 
 272  115
             if (current.getParent() instanceof Element) {
 273  70
                 current = (Element)current.getParent();
 274  
             } else {
 275  45
                 current = null;
 276  
             }
 277  
         }
 278  
 
 279  45
         nsMap.put( "xml", new XPathNamespace(elem, Namespace.XML_NAMESPACE) );
 280  
 
 281  45
         return nsMap.values().iterator();
 282  
     }
 283  
 
 284  
     public Iterator getParentAxisIterator(Object contextNode)
 285  
     {
 286  25126
         Object parent = null;
 287  
 
 288  25126
         if ( contextNode instanceof Document )
 289  
         {
 290  4905
             return JaxenConstants.EMPTY_ITERATOR;
 291  
         }
 292  20221
         else if ( contextNode instanceof Element )
 293  
         {
 294  19755
             parent = ((Element)contextNode).getParent();
 295  
 
 296  19755
             if ( parent == null )
 297  
             {
 298  0
                 if ( ((Element)contextNode).isRootElement() )
 299  
                 {
 300  0
                     parent = ((Element)contextNode).getDocument();
 301  
                 }
 302  
             }
 303  
         }
 304  466
         else if ( contextNode instanceof Attribute )
 305  
         {
 306  74
             parent = ((Attribute)contextNode).getParent();
 307  
         }
 308  392
         else if ( contextNode instanceof XPathNamespace )
 309  
         {
 310  332
             parent = ((XPathNamespace)contextNode).getJDOMElement();
 311  
         }
 312  60
         else if ( contextNode instanceof ProcessingInstruction )
 313  
         {
 314  20
             parent = ((ProcessingInstruction)contextNode).getParent();
 315  
         }
 316  40
         else if ( contextNode instanceof Comment )
 317  
         {
 318  20
             parent = ((Comment)contextNode).getParent();
 319  
         }
 320  20
         else if ( contextNode instanceof Text )
 321  
         {
 322  20
             parent = ((Text)contextNode).getParent();
 323  
         }
 324  
         
 325  20221
         if ( parent != null )
 326  
         {
 327  20221
             return new SingleObjectIterator( parent );
 328  
         }
 329  
 
 330  0
         return JaxenConstants.EMPTY_ITERATOR;
 331  
     }
 332  
 
 333  
     public Iterator getAttributeAxisIterator(Object contextNode)
 334  
     {
 335  51
         if ( ! ( contextNode instanceof Element ) )
 336  
         {
 337  0
             return JaxenConstants.EMPTY_ITERATOR;
 338  
         }
 339  
 
 340  51
         Element elem = (Element) contextNode;
 341  
 
 342  51
         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  594
         if ( contextNode instanceof Element ) {
 359  548
             Element node = (Element) contextNode;
 360  548
             Namespace namespace = (namespaceURI == null ? Namespace.NO_NAMESPACE : 
 361  
                                     Namespace.getNamespace(namespacePrefix, namespaceURI));
 362  548
             Attribute attr = node.getAttribute(localName, namespace);
 363  548
             if (attr != null) {
 364  317
                 return new SingleObjectIterator(attr);
 365  
             }
 366  
         }
 367  277
         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  7
         return new JDOMXPath(xpath);
 376  
     }
 377  
 
 378  
     public Object getDocumentNode(Object contextNode)
 379  
     {
 380  264
         if ( contextNode instanceof Document )
 381  
         {
 382  195
             return contextNode;
 383  
         }
 384  
 
 385  69
         Element elem = (Element) contextNode;
 386  
 
 387  69
         return elem.getDocument();
 388  
     }
 389  
 
 390  
     public String getElementQName(Object obj)
 391  
     {
 392  26
         Element elem = (Element) obj;
 393  
 
 394  26
         String prefix = elem.getNamespacePrefix();
 395  
 
 396  26
         if ( prefix == null || prefix.length() == 0 )
 397  
         {
 398  26
             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  117
         if (obj instanceof Namespace) {
 435  
 
 436  0
             Namespace ns = (Namespace) obj;
 437  0
             return ns.getPrefix();
 438  
         } else {
 439  
 
 440  117
             XPathNamespace ns = (XPathNamespace) obj;
 441  117
             return ns.getJDOMNamespace().getPrefix();
 442  
         }
 443  
     }
 444  
 
 445  
     public String getTextStringValue(Object obj)
 446  
     {
 447  144
         if ( obj instanceof Text )
 448  
         {
 449  144
             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  287
         Attribute attr = (Attribute) obj;
 463  
 
 464  287
         return attr.getValue();
 465  
     }
 466  
 
 467  
     public String getElementStringValue(Object obj)
 468  
     {
 469  0
         Element elem = (Element) obj;
 470  
 
 471  0
         StringBuffer buf = new StringBuffer();
 472  
 
 473  0
         List     content     = elem.getContent();
 474  0
         Iterator contentIter = content.iterator();
 475  0
         Object   each        = null;
 476  
 
 477  0
         while ( contentIter.hasNext() )
 478  
         {
 479  0
             each = contentIter.next();
 480  
 
 481  0
             if ( each instanceof Text )
 482  
             {
 483  0
                 buf.append( ((Text)each).getText() );
 484  
             }
 485  0
             else if ( each instanceof CDATA )
 486  
             {
 487  0
                 buf.append( ((CDATA)each).getText() );
 488  
             }
 489  0
             else if ( each instanceof Element )
 490  
             {
 491  0
                 buf.append( getElementStringValue( each ) );
 492  
             }
 493  
         }
 494  
 
 495  0
         return buf.toString();
 496  
     }
 497  
 
 498  
     public String getProcessingInstructionTarget(Object obj)
 499  
     {
 500  6
         ProcessingInstruction pi = (ProcessingInstruction) obj;
 501  
 
 502  6
         return pi.getTarget();
 503  
     }
 504  
 
 505  
     public String getProcessingInstructionData(Object obj)
 506  
     {
 507  3
         ProcessingInstruction pi = (ProcessingInstruction) obj;
 508  
 
 509  3
         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  4
             SAXBuilder builder = new SAXBuilder();
 564  
             
 565  4
             return builder.build( url );
 566  
         }
 567  0
         catch (Exception e)
 568  
         {
 569  0
             throw new FunctionCallException( e.getMessage() );
 570  
         }
 571  
     }
 572  
 }