View Javadoc

    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 public class DocumentNavigator extends org.jaxen.DefaultNavigator
    102 {
    103     public boolean isAttribute(Object o) {
    104         return o instanceof Attribute;
    105     }
    106
    107     public boolean isComment(Object o) {
    108         return o instanceof Comment;
    109     }
    110
    111     public boolean isDocument(Object o) {
    112         return o instanceof Document;
    113     }
    114
    115     public boolean isElement(Object o) {
    116         return o instanceof Element;
    117     }
    118
    119     public boolean isNamespace(Object o) {
    120         return o instanceof XPathNamespace;
    121     }
    122
    123     public boolean isProcessingInstruction(Object o) {
    124         return o instanceof ProcessingInstruction;
    125     }
    126
    127     public boolean isText(Object o) {
    128         return o instanceof Text;
    129     }
    130
    131     //
    132
    133     public String getAttributeName(Object o) {
    134         return (isAttribute(o) ? ((Attribute)o).getLocalName() : null);
    135     }
    136
    137     public String getAttributeNamespaceUri(Object o) {
    138         return (isAttribute(o) ? ((Attribute)o).getNamespaceURI() : null);
    139     }
    140
    141     public String getAttributeQName(Object o) {
    142         return (isAttribute(o) ? ((Attribute)o).getQualifiedName() : null);
    143     }
    144
    145     public String getAttributeStringValue(Object o) {
    146         return (isAttribute(o) ? ((Attribute)o).getValue() : null);
    147     }
    148
    149     //
    150
    151     public String getCommentStringValue(Object o) {
    152         return (isComment(o) ? ((Comment)o).getValue() : null);
    153     }
    154
    155     public String getElementName(Object o) {
    156         return (isElement(o) ? ((Element)o).getLocalName() : null);
    157     }
    158
    159     public String getElementNamespaceUri(Object o) {
    160         return (isElement(o) ? ((Element)o).getNamespaceURI() : null);
    161     }
    162
    163     public String getElementQName(Object o) {
    164         return (isElement(o) ? ((Element)o).getQualifiedName() : null);
    165     }
    166
    167     public String getElementStringValue(Object o) {
    168         return (o instanceof Node ? ((Node)o).getValue() : null);
    169     }
    170
    171     //
    172
    173     public String getNamespacePrefix(Object o) {
    174         if (isElement(o)) {
    175             return ((Element)o).getNamespacePrefix();
    176         } else if (isAttribute(o)) {
    177             return ((Attribute)o).getNamespacePrefix();
    178         } else if (o instanceof XPathNamespace) {
    179             return ((XPathNamespace)o).getNamespacePrefix();
    180         }
    181         return null;
    182     }
    183
    184     public String getNamespaceStringValue(Object o) {
    185         if (isElement(o)) {
    186             return ((Element)o).getNamespaceURI();
    187         } else if (isAttribute(o)) {
    188             return ((Attribute)o).getNamespaceURI();
    189         } else if (o instanceof XPathNamespace) {
    190             return ((XPathNamespace)o).getNamespaceURI();
    191         }
    192         return null;
    193     }
    194
    195     //
    196
    197     public String getTextStringValue(Object o) {
    198         return (o instanceof Text ? ((Text)o).getValue() : null);
    199     }
    200
    201     //
    202
    203     public Object getDocument(String s) throws FunctionCallException {
    204         try {
    205             return new Builder(new NodeFactory()).build(s);
    206         } catch (Exception pe) {
    207             throw new FunctionCallException(pe);
    208         }
    209     }
    210
    211     public Object getDocumentNode(Object o) {
    212         ParentNode parent = null;
    213         if (o instanceof ParentNode) {
    214             parent = (ParentNode)o;
    215         } else if (o instanceof Node) {
    216             parent = ((Node)o).getParent();
    217         }
    218         return parent.getDocument();
    219     }
    220
    221     //
    222
    223     private abstract static class IndexIterator implements Iterator {
    224         private Object o = null;
    225         private int pos = 0, end = -1;
    226         public IndexIterator(Object o, int pos, int end) {
    227             this.o = o;
    228             this.pos = pos;
    229             this.end = end;
    230         }
    231         public boolean hasNext() {
    232             return pos < end;
    233         }
    234         public abstract Object get(Object o, int i);
    235
    236         public Object next() {
    237             return get(o, pos++);
    238         }
    239
    240         public void remove() {
    241             throw new UnsupportedOperationException();
    242         }
    243     }
    244
    245     //
    246
    247     public Iterator getAttributeAxisIterator(Object o) {
    248         if (isElement(o)) {
    249             return new IndexIterator(o, 0, ((Element)o).getAttributeCount()) {
    250                 public Object get(Object o, int i) {
    251                     return ((Element)o).getAttribute(i);
    252                 }
    253             };
    254         }
    255         return JaxenConstants.EMPTY_ITERATOR;
    256     }
    257
    258     public Iterator getChildAxisIterator(Object o) {
    259         if (isElement(o) || (o instanceof Document)) {
    260             return new IndexIterator(o, 0, ((ParentNode)o).getChildCount()) {
    261                 public Object get(Object o, int i) {
    262                     return ((ParentNode)o).getChild(i);
    263                 }
    264             };
    265         }
    266         return JaxenConstants.EMPTY_ITERATOR;
    267     }
    268
    269     //
    270
    271     public Iterator getParentAxisIterator(Object o) {
    272         Object parent = null;
    273         if (o instanceof Node) {
    274             parent = ((Node)o).getParent();
    275         } else if (isNamespace(o)) {
    276             parent = ((XPathNamespace)o).getElement();
    277         }
    278         return (parent != null ? new SingleObjectIterator(parent) : null);
    279     }
    280
    281     public Object getParentNode(Object o)  {
    282         return (o instanceof Node ? ((Node)o).getParent() : null);
    283     }
    284
    285     //
    286
    287     public Iterator getPrecedingAxisIterator(Object o) throws UnsupportedAxisException {
    288         return super.getPrecedingAxisIterator(o);
    289     }
    290
    291     public Iterator getPrecedingSiblingAxisIterator(Object o) throws UnsupportedAxisException {
    292         return super.getPrecedingSiblingAxisIterator(o);
    293     }
    294
    295     //
    296
    297     public String getProcessingInstructionData(Object o) {
    298         return (o instanceof ProcessingInstruction ? ((ProcessingInstruction)o).getValue() : null);
    299     }
    300
    301     public String getProcessingInstructionTarget(Object o) {
    302         return (o instanceof ProcessingInstruction ? ((ProcessingInstruction)o).getTarget() : null);
    303     }
    304
    305     //
    306
    307     public String translateNamespacePrefixToUri(String s, Object o) {
    308         Element element = null;
    309         if (o instanceof Element) {
    310             element = (Element) o;
    311         } else if (o instanceof ParentNode) {
    312         }
    313         else if (o instanceof Node) {
    314             element = (Element)((Node)o).getParent();
    315         }
    316         else if (o instanceof XPathNamespace)
    317         {
    318             element = ((XPathNamespace)o).getElement();
    319         }
    320         if (element != null) {
    321             return element.getNamespaceURI(s);
    322         }
    323         return null;
    324     }
    325
    326     //
    327
    328     public XPath parseXPath(String s) throws SAXPathException {
    329         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     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         {
    347             element = elt;
    348             this.uri = uri;
    349             this.prefix = prefix;
    350         }
    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             return element;
    359         }
    360
    361         public String getNamespaceURI()
    362         {
    363             return uri;
    364         }
    365
    366         public String getNamespacePrefix()
    367         {
    368             return prefix;
    369         }
    370
    371         public String toString()
    372         {
    373             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         if (uri != null && uri.length() > 0 && (! map.containsKey(prefix))) {
    384             map.put(prefix, new XPathNamespace(elt, uri, prefix));
    385             return true;
    386         }
    387         return false;
    388     }
    389
    390     public Iterator getNamespaceAxisIterator(Object o)
    391     {
    392         if (! isElement(o)) {
    393             return JaxenConstants.EMPTY_ITERATOR;
    394         }
    395         Map nsMap = new HashMap();
    396         Element elt = (Element)o;
    397         ParentNode parent = elt;
    398
    399         while (parent instanceof Element) {
    400             elt = (Element)parent;
    401             String uri    = elt.getNamespaceURI();
    402             String prefix = elt.getNamespacePrefix();
    403             addNamespaceForElement(elt, uri, prefix, nsMap);
    404             int count = elt.getNamespaceDeclarationCount();
    405             for (int i = 0; i < count; i++) {
    406                 prefix = elt.getNamespacePrefix(i);
    407                 uri    = elt.getNamespaceURI(prefix);
    408                 addNamespaceForElement(elt, uri, prefix, nsMap);
    409             }
    410             parent = elt.getParent();
    411         }
    412         addNamespaceForElement(elt, "http://www.w3.org/XML/1998/namespace", "xml", nsMap);
    413
    414         return nsMap.values().iterator();
    415     }
    416 }