Coverage Report - org.jaxen.xom.DocumentNavigator

Classes in this File Line Coverage Branch Coverage Complexity
DocumentNavigator
74% 
69% 
1.8

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