Coverage Report - org.jaxen.xom.DocumentNavigator
 
Classes in this File Line Coverage Branch Coverage Complexity
DocumentNavigator
71%
68/96
71%
25/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: /home/projects/jaxen/scm/jaxen/src/java/main/org/jaxen/xom/DocumentNavigator.java,v 1.8 2006/06/03 20:02:50 elharo Exp $
 3  
  * $Revision: 1.8 $
 4  
  * $Date: 2006/06/03 20:02:50 $
 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,v 1.8 2006/06/03 20:02:50 elharo Exp $
 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  586
 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  13162
         return o instanceof Attribute;
 97  
     }
 98  
 
 99  
     public boolean isComment(Object o) {
 100  2246
         return o instanceof Comment;
 101  
     }
 102  
 
 103  
     public boolean isDocument(Object o) {
 104  2444
         return o instanceof Document;
 105  
     }
 106  
 
 107  
     public boolean isElement(Object o) {
 108  637786
         return o instanceof Element;
 109  
     }
 110  
 
 111  
     public boolean isNamespace(Object o) {
 112  8912
         return o instanceof XPathNamespace;
 113  
     }
 114  
 
 115  
     public boolean isProcessingInstruction(Object o) {
 116  2186
         return o instanceof ProcessingInstruction;
 117  
     }
 118  
 
 119  
     public boolean isText(Object o) {
 120  159646
         return o instanceof Text;
 121  
     }
 122  
 
 123  
     //
 124  
     
 125  
     public String getAttributeName(Object o) {
 126  910
         return (isAttribute(o) ? ((Attribute)o).getLocalName() : null);
 127  
     }
 128  
 
 129  
     public String getAttributeNamespaceUri(Object o) {
 130  910
         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  574
         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  80154
         return (isElement(o) ? ((Element)o).getLocalName() : null);
 149  
     }
 150  
 
 151  
     public String getElementNamespaceUri(Object o) {
 152  79692
         return (isElement(o) ? ((Element)o).getNamespaceURI() : null);
 153  
     }
 154  
 
 155  
     public String getElementQName(Object o) {
 156  52
         return (isElement(o) ? ((Element)o).getQualifiedName() : null);
 157  
     }
 158  
 
 159  
     public String getElementStringValue(Object o) {
 160  258
         return (o instanceof Node ? ((Node)o).getValue() : null);
 161  
     }
 162  
 
 163  
     //
 164  
     
 165  
     public String getNamespacePrefix(Object o) {
 166  234
         if (isElement(o)) {
 167  0
             return ((Element)o).getNamespacePrefix();
 168  234
         } else if (isAttribute(o)) {
 169  0
             return ((Attribute)o).getNamespacePrefix();
 170  234
         } else if (o instanceof XPathNamespace) {
 171  234
             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  24
         return (o instanceof Text ? ((Text)o).getValue() : null);
 191  
     }
 192  
     
 193  
     //
 194  
 
 195  
     public Object getDocument(String s) throws FunctionCallException {
 196  
         try {
 197  136
             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  524
         ParentNode parent = null;
 205  524
         if (o instanceof ParentNode) {
 206  524
             parent = (ParentNode)o;
 207  524
         } else if (o instanceof Node) {
 208  0
             parent = ((Node)o).getParent();
 209  
         }
 210  524
         return parent.getDocument();
 211  
     }
 212  
 
 213  
     //
 214  
     
 215  
     private abstract static class IndexIterator implements Iterator {
 216  84554
         private Object o = null;
 217  84554
         private int pos = 0, end = -1;
 218  84554
         public IndexIterator(Object o, int pos, int end) {
 219  84554
             this.o = o;
 220  84554
             this.pos = pos;
 221  84554
             this.end = end;
 222  84554
         }
 223  
         public boolean hasNext() {
 224  704654
             return pos < end;
 225  
         }
 226  
         public abstract Object get(Object o, int i); 
 227  
         
 228  
         public Object next() {
 229  396394
             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  1290
         if (isElement(o)) {
 241  1198
             return new IndexIterator(o, 0, ((Element)o).getAttributeCount()) {
 242  1198
                 public Object get(Object o, int i) {
 243  910
                     return ((Element)o).getAttribute(i);
 244  
                 }
 245  
             };
 246  
         }
 247  92
         return JaxenConstants.EMPTY_ITERATOR;
 248  
     }
 249  
 
 250  
     public Iterator getChildAxisIterator(Object o) {
 251  237834
         if (isElement(o) || (o instanceof Document)) {
 252  83356
             return new IndexIterator(o, 0, ((ParentNode)o).getChildCount()) {
 253  83356
                 public Object get(Object o, int i) {
 254  395484
                     return ((ParentNode)o).getChild(i);
 255  
                 }
 256  
             };
 257  
         }
 258  154478
         return JaxenConstants.EMPTY_ITERATOR;
 259  
     }
 260  
 
 261  
     //
 262  
 
 263  
     public Iterator getParentAxisIterator(Object o) {
 264  28
         Object parent = null;
 265  28
         if (o instanceof Node) {
 266  24
             parent = ((Node)o).getParent();
 267  24
         } else if (isNamespace(o)) {
 268  4
             parent = ((XPathNamespace)o).getElement();
 269  
         }
 270  28
         return (parent != null ? new SingleObjectIterator(parent) : null);
 271  
     }
 272  
 
 273  
     public Object getParentNode(Object o)  {
 274  48206
         return (o instanceof Node ? ((Node)o).getParent() : null);
 275  
     }
 276  
 
 277  
     //
 278  
 
 279  
     public Iterator getPrecedingAxisIterator(Object o) throws UnsupportedAxisException {
 280  36
         return super.getPrecedingAxisIterator(o);
 281  
     }
 282  
 
 283  
     public Iterator getPrecedingSiblingAxisIterator(Object o) throws UnsupportedAxisException {
 284  22
         return super.getPrecedingSiblingAxisIterator(o);
 285  
     }
 286  
     
 287  
     //
 288  
 
 289  
     public String getProcessingInstructionData(Object o) {
 290  6
         return (o instanceof ProcessingInstruction ? ((ProcessingInstruction)o).getValue() : null);
 291  
     }
 292  
 
 293  
     public String getProcessingInstructionTarget(Object o) {
 294  12
         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  0
         }
 305  0
         else if (o instanceof Node) {
 306  0
             element = (Element)((Node)o).getParent();
 307  0
         }
 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  14
         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  586
     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  284
         {
 339  284
             element = elt;
 340  284
             this.uri = uri;
 341  284
             this.prefix = prefix;
 342  284
         }
 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  4
             return element;
 351  
         }
 352  
 
 353  
         public String getNamespaceURI()
 354  
         {
 355  0
             return uri;
 356  
         }
 357  
 
 358  
         public String getNamespacePrefix()
 359  
         {
 360  234
             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  832
         if (uri != null && uri.length() > 0 && (! map.containsKey(prefix))) {
 376  284
             map.put(prefix, new XPathNamespace(elt, uri, prefix));
 377  284
             return true;
 378  
         }
 379  548
         return false;
 380  
     }
 381  
     
 382  
     public Iterator getNamespaceAxisIterator(Object o)
 383  
     {
 384  250
         if (! isElement(o)) {
 385  146
             return JaxenConstants.EMPTY_ITERATOR;
 386  
         }
 387  104
         Map nsMap = new HashMap();
 388  104
         Element elt = (Element)o;
 389  104
         ParentNode parent = elt;
 390  
         
 391  378
         while (parent instanceof Element) {
 392  274
             elt = (Element)parent;
 393  274
             String uri    = elt.getNamespaceURI();
 394  274
             String prefix = elt.getNamespacePrefix();
 395  274
             addNamespaceForElement(elt, uri, prefix, nsMap);
 396  274
             int count = elt.getNamespaceDeclarationCount();
 397  728
             for (int i = 0; i < count; i++) {
 398  454
                 prefix = elt.getNamespacePrefix(i);
 399  454
                 uri    = elt.getNamespaceURI(prefix);
 400  454
                 addNamespaceForElement(elt, uri, prefix, nsMap);
 401  
             }
 402  274
             parent = elt.getParent();
 403  274
         }
 404  104
         addNamespaceForElement(elt, "http://www.w3.org/XML/1998/namespace", "xml", nsMap);
 405  
 
 406  104
         return nsMap.values().iterator();
 407  
     }
 408  
 }