Coverage Report - org.jaxen.xom.DocumentNavigator
 
Classes in this File Line Coverage Branch Coverage Complexity
DocumentNavigator
71%
67/94
69%
24/35
1.8
DocumentNavigator$1
100%
2/2
N/A
1.8
DocumentNavigator$2
100%
2/2
N/A
1.8
DocumentNavigator$IndexIterator
90%
9/10
100%
1/1
1.8
DocumentNavigator$XPathNamespace
78%
7/9
N/A
1.8
 
 1  
 /*
 2  
  * $Header$
 3  
  * $Revision: 1156 $
 4  
  * $Date: 2006-06-03 13:04:05 -0700 (Sat, 03 Jun 2006) $
 5  
  *
 6  
  * ====================================================================
 7  
  *
 8  
  * Copyright 2000-2003 bob mcwhirter & James Strachan.
 9  
  * All rights reserved.
 10  
  *
 11  
  *
 12  
  * Redistribution and use in source and binary forms, with or without
 13  
  * modification, are permitted provided that the following conditions are
 14  
  * met:
 15  
  * 
 16  
  *   * Redistributions of source code must retain the above copyright
 17  
  *     notice, this list of conditions and the following disclaimer.
 18  
  * 
 19  
  *   * Redistributions in binary form must reproduce the above copyright
 20  
  *     notice, this list of conditions and the following disclaimer in the
 21  
  *     documentation and/or other materials provided with the distribution.
 22  
  * 
 23  
  *   * Neither the name of the Jaxen Project nor the names of its
 24  
  *     contributors may be used to endorse or promote products derived 
 25  
  *     from this software without specific prior written permission.
 26  
  * 
 27  
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 28  
  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 29  
  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 30  
  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
 31  
  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 32  
  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 33  
  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 34  
  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 35  
  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 36  
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 37  
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 38  
  *
 39  
  * ====================================================================
 40  
  * This software consists of voluntary contributions made by many
 41  
  * individuals on behalf of the Jaxen Project and was originally
 42  
  * created by bob mcwhirter <bob@werken.com> and
 43  
  * James Strachan <jstrachan@apache.org>.  For more information on the
 44  
  * Jaxen Project, please see <http://www.jaxen.org/>.
 45  
  *
 46  
  * $Id: DocumentNavigator.java 1156 2006-06-03 20:04:05Z elharo $
 47  
  */
 48  
 
 49  
 
 50  
 package org.jaxen.xom;
 51  
 
 52  
 
 53  
 import nu.xom.Attribute;
 54  
 import nu.xom.Comment;
 55  
 import nu.xom.Document;
 56  
 import nu.xom.Element;
 57  
 import nu.xom.ProcessingInstruction;
 58  
 import nu.xom.Text;
 59  
 import nu.xom.Node;
 60  
 import nu.xom.Builder;
 61  
 import nu.xom.NodeFactory;
 62  
 import nu.xom.ParentNode;
 63  
 
 64  
 import org.jaxen.XPath;
 65  
 import org.jaxen.UnsupportedAxisException;
 66  
 import org.jaxen.FunctionCallException;
 67  
 import org.jaxen.BaseXPath;
 68  
 import org.jaxen.JaxenConstants;
 69  
 import org.jaxen.util.SingleObjectIterator;
 70  
 
 71  
 import org.jaxen.saxpath.SAXPathException;
 72  
 
 73  
 import java.util.Iterator;
 74  
 import java.util.HashMap;
 75  
 import java.util.Map;
 76  
 
 77  
 /**
 78  
  * Interface for navigating around the XOM object model.
 79  
  *
 80  
  * <p>
 81  
  * This class is not intended for direct usage, but is
 82  
  * used by the Jaxen engine during evaluation.
 83  
  * </p>
 84  
  *
 85  
  * @see XPath
 86  
  *
 87  
  */
 88  1465
 public class DocumentNavigator extends org.jaxen.DefaultNavigator
 89  
 {
 90  
     /**
 91  
      * 
 92  
      */
 93  
     private static final long serialVersionUID = 3159311338575942877L;
 94  
 
 95  
     public boolean isAttribute(Object o) {
 96  32905
         return o instanceof Attribute;
 97  
     }
 98  
 
 99  
     public boolean isComment(Object o) {
 100  5615
         return o instanceof Comment;
 101  
     }
 102  
 
 103  
     public boolean isDocument(Object o) {
 104  6110
         return o instanceof Document;
 105  
     }
 106  
 
 107  
     public boolean isElement(Object o) {
 108  1594289
         return o instanceof Element;
 109  
     }
 110  
 
 111  
     public boolean isNamespace(Object o) {
 112  22280
         return o instanceof XPathNamespace;
 113  
     }
 114  
 
 115  
     public boolean isProcessingInstruction(Object o) {
 116  5465
         return o instanceof ProcessingInstruction;
 117  
     }
 118  
 
 119  
     public boolean isText(Object o) {
 120  399071
         return o instanceof Text;
 121  
     }
 122  
 
 123  
     //
 124  
     
 125  
     public String getAttributeName(Object o) {
 126  2275
         return (isAttribute(o) ? ((Attribute)o).getLocalName() : null);
 127  
     }
 128  
 
 129  
     public String getAttributeNamespaceUri(Object o) {
 130  2275
         return (isAttribute(o) ? ((Attribute)o).getNamespaceURI() : null);
 131  
     }
 132  
 
 133  
     public String getAttributeQName(Object o) {
 134  0
         return (isAttribute(o) ? ((Attribute)o).getQualifiedName() : null);
 135  
     }
 136  
 
 137  
     public String getAttributeStringValue(Object o) {
 138  1435
         return (isAttribute(o) ? ((Attribute)o).getValue() : null);
 139  
     }
 140  
 
 141  
     //
 142  
     
 143  
     public String getCommentStringValue(Object o) {
 144  0
         return (isComment(o) ? ((Comment)o).getValue() : null);
 145  
     }
 146  
 
 147  
     public String getElementName(Object o) {
 148  200341
         return (isElement(o) ? ((Element)o).getLocalName() : null);
 149  
     }
 150  
 
 151  
     public String getElementNamespaceUri(Object o) {
 152  199186
         return (isElement(o) ? ((Element)o).getNamespaceURI() : null);
 153  
     }
 154  
 
 155  
     public String getElementQName(Object o) {
 156  130
         return (isElement(o) ? ((Element)o).getQualifiedName() : null);
 157  
     }
 158  
 
 159  
     public String getElementStringValue(Object o) {
 160  645
         return (o instanceof Node ? ((Node)o).getValue() : null);
 161  
     }
 162  
 
 163  
     //
 164  
     
 165  
     public String getNamespacePrefix(Object o) {
 166  585
         if (isElement(o)) {
 167  0
             return ((Element)o).getNamespacePrefix();
 168  585
         } else if (isAttribute(o)) {
 169  0
             return ((Attribute)o).getNamespacePrefix();
 170  585
         } else if (o instanceof XPathNamespace) {
 171  585
             return ((XPathNamespace)o).getNamespacePrefix();
 172  
         }
 173  0
         return null;
 174  
     }
 175  
 
 176  
     public String getNamespaceStringValue(Object o) {
 177  0
         if (isElement(o)) {
 178  0
             return ((Element)o).getNamespaceURI();
 179  0
         } else if (isAttribute(o)) {
 180  0
             return ((Attribute)o).getNamespaceURI();
 181  0
         } else if (o instanceof XPathNamespace) {
 182  0
             return ((XPathNamespace)o).getNamespaceURI();
 183  
         }
 184  0
         return null;
 185  
     }
 186  
 
 187  
     //
 188  
     
 189  
     public String getTextStringValue(Object o) {
 190  60
         return (o instanceof Text ? ((Text)o).getValue() : null);
 191  
     }
 192  
     
 193  
     //
 194  
 
 195  
     public Object getDocument(String s) throws FunctionCallException {
 196  
         try {
 197  340
             return new Builder(new NodeFactory()).build(s);
 198  0
         } catch (Exception pe) {
 199  0
             throw new FunctionCallException(pe);
 200  
         }
 201  
     }
 202  
 
 203  
     public Object getDocumentNode(Object o) {
 204  1310
         ParentNode parent = null;
 205  1310
         if (o instanceof ParentNode) {
 206  1310
             parent = (ParentNode)o;
 207  0
         } else if (o instanceof Node) {
 208  0
             parent = ((Node)o).getParent();
 209  
         }
 210  1310
         return parent.getDocument();
 211  
     }
 212  
 
 213  
     //
 214  
     
 215  
     private abstract static class IndexIterator implements Iterator {
 216  211385
         private Object o = null;
 217  211385
         private int pos = 0, end = -1;
 218  211385
         public IndexIterator(Object o, int pos, int end) {
 219  211385
             this.o = o;
 220  211385
             this.pos = pos;
 221  211385
             this.end = end;
 222  211385
         }
 223  
         public boolean hasNext() {
 224  1761547
             return pos < end;
 225  
         }
 226  
         public abstract Object get(Object o, int i); 
 227  
         
 228  
         public Object next() {
 229  990897
             return get(o, pos++);
 230  
         }
 231  
 
 232  
         public void remove() {
 233  0
             throw new UnsupportedOperationException();
 234  
         }
 235  
     }
 236  
     
 237  
     //
 238  
     
 239  
     public Iterator getAttributeAxisIterator(Object o) {
 240  3225
         if (isElement(o)) {
 241  2995
             return new IndexIterator(o, 0, ((Element)o).getAttributeCount()) {
 242  2995
                 public Object get(Object o, int i) {
 243  2275
                     return ((Element)o).getAttribute(i);
 244  
                 }
 245  
             };
 246  
         }
 247  230
         return JaxenConstants.EMPTY_ITERATOR;
 248  
     }
 249  
 
 250  
     public Iterator getChildAxisIterator(Object o) {
 251  594585
         if (isElement(o) || (o instanceof Document)) {
 252  208390
             return new IndexIterator(o, 0, ((ParentNode)o).getChildCount()) {
 253  208390
                 public Object get(Object o, int i) {
 254  988622
                     return ((ParentNode)o).getChild(i);
 255  
                 }
 256  
             };
 257  
         }
 258  386195
         return JaxenConstants.EMPTY_ITERATOR;
 259  
     }
 260  
 
 261  
     //
 262  
 
 263  
     public Iterator getParentAxisIterator(Object o) {
 264  70
         Object parent = null;
 265  70
         if (o instanceof Node) {
 266  60
             parent = ((Node)o).getParent();
 267  10
         } else if (isNamespace(o)) {
 268  10
             parent = ((XPathNamespace)o).getElement();
 269  
         }
 270  70
         return (parent != null ? new SingleObjectIterator(parent) : null);
 271  
     }
 272  
 
 273  
     public Object getParentNode(Object o)  {
 274  120515
         return (o instanceof Node ? ((Node)o).getParent() : null);
 275  
     }
 276  
 
 277  
     //
 278  
 
 279  
     public Iterator getPrecedingAxisIterator(Object o) throws UnsupportedAxisException {
 280  90
         return super.getPrecedingAxisIterator(o);
 281  
     }
 282  
 
 283  
     public Iterator getPrecedingSiblingAxisIterator(Object o) throws UnsupportedAxisException {
 284  55
         return super.getPrecedingSiblingAxisIterator(o);
 285  
     }
 286  
     
 287  
     //
 288  
 
 289  
     public String getProcessingInstructionData(Object o) {
 290  15
         return (o instanceof ProcessingInstruction ? ((ProcessingInstruction)o).getValue() : null);
 291  
     }
 292  
 
 293  
     public String getProcessingInstructionTarget(Object o) {
 294  30
         return (o instanceof ProcessingInstruction ? ((ProcessingInstruction)o).getTarget() : null);
 295  
     }
 296  
 
 297  
     //
 298  
 
 299  
     public String translateNamespacePrefixToUri(String s, Object o) {
 300  0
         Element element = null;
 301  0
         if (o instanceof Element) {
 302  0
             element = (Element) o;
 303  0
         } else if (o instanceof ParentNode) {
 304  
         }
 305  0
         else if (o instanceof Node) {
 306  0
             element = (Element)((Node)o).getParent();
 307  
         }
 308  0
         else if (o instanceof XPathNamespace)
 309  
         {
 310  0
             element = ((XPathNamespace)o).getElement();
 311  
         }
 312  0
         if (element != null) {
 313  0
             return element.getNamespaceURI(s);
 314  
         }
 315  0
         return null;
 316  
     }
 317  
 
 318  
     //
 319  
     
 320  
     public XPath parseXPath(String s) throws SAXPathException {
 321  35
         return new BaseXPath(s, this);
 322  
     }
 323  
 
 324  
     //
 325  
     
 326  
     /** Wrapper for XOM namespace nodes to give them a parent,
 327  
      * as required by the XPath data model.
 328  
      *
 329  
      *  @author Erwin Bolwidt
 330  
      */
 331  1465
     private static class XPathNamespace
 332  
     {
 333  
         private Element element;
 334  
 
 335  
         private String uri, prefix;
 336  
 
 337  
         public XPathNamespace(Element elt, String uri, String prefix)
 338  710
         {
 339  710
             element = elt;
 340  710
             this.uri = uri;
 341  710
             this.prefix = prefix;
 342  710
         }
 343  
 
 344  
         /** Returns the XOM element from which this namespace node has been 
 345  
          *  retrieved. The result may be null when the namespace node has not yet
 346  
          *  been assigned to an element.
 347  
          */
 348  
         public Element getElement()
 349  
         {
 350  10
             return element;
 351  
         }
 352  
 
 353  
         public String getNamespaceURI()
 354  
         {
 355  0
             return uri;
 356  
         }
 357  
 
 358  
         public String getNamespacePrefix()
 359  
         {
 360  585
             return prefix;
 361  
         }
 362  
 
 363  
         public String toString()
 364  
         {
 365  0
             return ( "[xmlns:" + prefix + "=\"" +
 366  
                     uri + "\", element=" +
 367  
                     element.getLocalName() + "]" );
 368  
         }
 369  
     }
 370  
 
 371  
     //
 372  
     
 373  
     private boolean addNamespaceForElement(Element elt, String uri, String prefix, Map map)
 374  
     {
 375  2080
         if (uri != null && uri.length() > 0 && (! map.containsKey(prefix))) {
 376  710
             map.put(prefix, new XPathNamespace(elt, uri, prefix));
 377  710
             return true;
 378  
         }
 379  1370
         return false;
 380  
     }
 381  
     
 382  
     public Iterator getNamespaceAxisIterator(Object o)
 383  
     {
 384  625
         if (! isElement(o)) {
 385  365
             return JaxenConstants.EMPTY_ITERATOR;
 386  
         }
 387  260
         Map nsMap = new HashMap();
 388  260
         Element elt = (Element)o;
 389  260
         ParentNode parent = elt;
 390  
         
 391  945
         while (parent instanceof Element) {
 392  685
             elt = (Element)parent;
 393  685
             String uri    = elt.getNamespaceURI();
 394  685
             String prefix = elt.getNamespacePrefix();
 395  685
             addNamespaceForElement(elt, uri, prefix, nsMap);
 396  685
             int count = elt.getNamespaceDeclarationCount();
 397  1820
             for (int i = 0; i < count; i++) {
 398  1135
                 prefix = elt.getNamespacePrefix(i);
 399  1135
                 uri    = elt.getNamespaceURI(prefix);
 400  1135
                 addNamespaceForElement(elt, uri, prefix, nsMap);
 401  
             }
 402  685
             parent = elt.getParent();
 403  685
         }
 404  260
         addNamespaceForElement(elt, "http://www.w3.org/XML/1998/namespace", "xml", nsMap);
 405  
 
 406  260
         return nsMap.values().iterator();
 407  
     }
 408  
 }