blob: bc2d7c9ad73e35f852b3bac5af3e9dc457abdf2d [file] [log] [blame]
/* Copyright 2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.xmlbeans.impl.xpath.jaxen;
import org.jaxen.XPath;
import org.jaxen.Navigator;
import org.jaxen.DefaultNavigator;
import org.jaxen.FunctionCallException;
import org.jaxen.UnsupportedAxisException;
//import org.jaxen.NamedAccessNavigator;
import org.jaxen.util.AncestorAxisIterator;
import org.jaxen.util.FollowingSiblingAxisIterator;
import org.jaxen.util.PrecedingSiblingAxisIterator;
import org.jaxen.util.FollowingAxisIterator;
import org.jaxen.util.PrecedingAxisIterator;
import org.jaxen.util.SelfAxisIterator;
import org.jaxen.util.DescendantOrSelfAxisIterator;
import org.jaxen.util.AncestorOrSelfAxisIterator;
import org.jaxen.util.SingleObjectIterator;
import org.jaxen.util.DescendantAxisIterator;
import org.jaxen.saxpath.SAXPathException;
import org.apache.xmlbeans.XmlCursor;
import javax.xml.namespace.QName;
import java.util.Iterator;
/**
* Author: Cezar Andrei (cezar.andrei at bea.com)
* Date: Oct 10, 2003
*/
public class XBeansNavigator
extends DefaultNavigator
// implements NamedAccessNavigator
{
private XmlCursor _xc;
private XBeansNavigator()
{}
/** Retrieve an instance of this <code>DocumentNavigator</code>.
*/
public static Navigator getInstance()
{
return new XBeansNavigator();
}
static class JaxenNode
extends XmlCursor.XmlBookmark
{
public String toString()
{
XmlCursor xc = this.createCursor();
return "{Node:" + xc.currentTokenType().toString() + " " + xc.toString() + "}";
}
}
//
// DefaultNavigator implementation
//
/** Retrieve the namespace URI of the given element node.
*
* @param element The context element node.
*
* @return The namespace URI of the element node.
*/
public String getElementNamespaceUri(Object element)
{
((JaxenNode)element).toBookmark(_xc);
return _xc.getName().getNamespaceURI();
}
/** Retrieve the name of the given element node.
*
* @param element The context element node.
*
* @return The name of the element node.
*/
public String getElementName(Object element)
{
((JaxenNode)element).toBookmark(_xc);
return _xc.getName().getLocalPart();
}
/** Retrieve the QName of the given element node.
*
* @param element The context element node.
*
* @return The QName of the element node.
*/
public String getElementQName(Object element)
{
((JaxenNode)element).toBookmark(_xc);
String prefix = _xc.getName().getPrefix();
return ( !"".equals(prefix) ? prefix + ":" : "" ) + _xc.getName().getLocalPart();
}
/** Retrieve the namespace URI of the given attribute node.
*
* @param attr The context attribute node.
*
* @return The namespace URI of the attribute node.
*/
public String getAttributeNamespaceUri(Object attr)
{
((JaxenNode)attr).toBookmark(_xc);
return _xc.getName().getNamespaceURI();
}
/** Retrieve the name of the given attribute node.
*
* @param attr The context attribute node.
*
* @return The name of the attribute node.
*/
public String getAttributeName(Object attr)
{
((JaxenNode)attr).toBookmark(_xc);
return _xc.getName().getLocalPart();
}
/** Retrieve the QName of the given attribute node.
*
* @param attr The context attribute node.
*
* @return The QName of the attribute node.
*/
public String getAttributeQName(Object attr)
{
((JaxenNode)attr).toBookmark(_xc);
String uri = _xc.getName().getNamespaceURI();
String prefix = _xc.prefixForNamespace(uri);
return ( !"".equals(prefix) ? prefix + ":" : "" ) + _xc.getName().getLocalPart();
}
/** Returns whether the given object is a document node. A document node
* is the node that is selected by the xpath expression <code>/</code>.
*
* @param object The object to test.
*
* @return <code>true</code> if the object is a document node,
* else <code>false</code>
*/
public boolean isDocument(Object object)
{
((JaxenNode)object).toBookmark(_xc);
return _xc.isStartdoc();
}
/** Returns whether the given object is an element node.
*
* @param object The object to test.
*
* @return <code>true</code> if the object is an element node,
* else <code>false</code>
*/
public boolean isElement(Object object)
{
((JaxenNode)object).toBookmark(_xc);
return _xc.isStart();
}
/** Returns whether the given object is an attribute node.
*
* @param object The object to test.
*
* @return <code>true</code> if the object is an attribute node,
* else <code>false</code>
*/
public boolean isAttribute(Object object)
{
((JaxenNode)object).toBookmark(_xc);
return _xc.isAttr();
}
/** Returns whether the given object is a namespace node.
*
* @param object The object to test.
*
* @return <code>true</code> if the object is a namespace node,
* else <code>false</code>
*/
public boolean isNamespace(Object object)
{
((JaxenNode)object).toBookmark(_xc);
return _xc.isNamespace();
}
/** Returns whether the given object is a comment node.
*
* @param object The object to test.
*
* @return <code>true</code> if the object is a comment node,
* else <code>false</code>
*/
public boolean isComment(Object object)
{
((JaxenNode)object).toBookmark(_xc);
return _xc.isComment();
}
/** Returns whether the given object is a text node.
*
* @param object The object to test.
*
* @return <code>true</code> if the object is a text node,
* else <code>false</code>
*/
public boolean isText(Object object)
{
((JaxenNode)object).toBookmark(_xc);
return _xc.isText();
}
/** Returns whether the given object is a processing-instruction node.
*
* @param object The object to test.
*
* @return <code>true</code> if the object is a processing-instruction node,
* else <code>false</code>
*/
public boolean isProcessingInstruction(Object object)
{
((JaxenNode)object).toBookmark(_xc);
return _xc.isProcinst();
}
/** Retrieve the string-value of a comment node.
*
* @param comment The comment node.
*
* @return The string-value of the node.
*/
public String getCommentStringValue(Object comment)
{
((JaxenNode)comment).toBookmark(_xc);
return _xc.getTextValue();
}
/** Retrieve the string-value of an element node.
*
* @param element The comment node.
*
* @return The string-value of the node.
*/
public String getElementStringValue(Object element)
{
((JaxenNode)element).toBookmark(_xc);
return _xc.getTextValue();
}
/** Retrieve the string-value of an attribute node.
*
* @param attr The attribute node.
*
* @return The string-value of the node.
*/
public String getAttributeStringValue(Object attr)
{
((JaxenNode)attr).toBookmark(_xc);
return _xc.getTextValue();
}
/** Retrieve the string-value of a namespace node.
*
* @param ns The namespace node.
*
* @return The string-value of the node.
*/
public String getNamespaceStringValue(Object ns)
{
((JaxenNode)ns).toBookmark(_xc);
return _xc.getName().getNamespaceURI();
}
/** Retrieve the string-value of a text node.
*
* @param txt The text node.
*
* @return The string-value of the node.
*/
public String getTextStringValue(Object txt)
{
((JaxenNode)txt).toBookmark(_xc);
return _xc.getTextValue();
}
/** Retrieve the namespace prefix of a namespace node.
*
* @param ns The namespace node.
*
* @return The prefix associated with the node.
*/
public String getNamespacePrefix(Object ns)
{
((JaxenNode)ns).toBookmark(_xc);
return _xc.getName().getLocalPart();
}
/** Returns a parsed form of the given xpath string, which will be suitable
* for queries on documents that use the same navigator as this one.
*
* @see org.jaxen.XPath
*
* @param xpath The xpath expression.
*
* @return A new XPath expression object.
*
* @throws org.jaxen.saxpath.SAXPathException If an error occurs while parsing the
* xpath expression.
*/
public XPath parseXPath(String xpath)
throws SAXPathException
{
return new XBeansXPath(xpath);
}
//
// Overwritten methods
//
public static class ChildIterator implements Iterator
{
private JaxenNode _nextNode = null;
private XmlCursor _xc = null;
ChildIterator(XmlCursor xc)
{
_xc = xc;
XmlCursor.TokenType tk = _xc.toFirstContentToken(); //not including atts and ns-es
if (tk.isFinish())
_nextNode = null;
else
_nextNode = getBookmarkInThisPlace(_xc);
}
public boolean hasNext()
{
if (_nextNode == null)
return false;
return true;
}
public Object next()
{
if (_nextNode == null)
return null;
JaxenNode res = _nextNode;
res.toBookmark(_xc);
if (_xc.currentTokenType() == XmlCursor.TokenType.START)
{
_xc.toEndToken();
}
if (_xc.toNextToken().isFinish())
_nextNode = null;
else
_nextNode = getBookmarkInThisPlace(_xc);
return res;
}
public void remove() { throw new RuntimeException("optional method not implemented"); }
}
public Iterator getChildAxisIterator(Object contextNode) throws UnsupportedAxisException
{
((JaxenNode)contextNode).toBookmark(_xc);
return new ChildIterator(_xc);
}
public Iterator getDescendantAxisIterator(Object contextNode) throws UnsupportedAxisException
{
return new DescendantAxisIterator( contextNode, this );
/*
((JaxenNode)contextNode).toBookmark(_xc);
return new DescendantIterator(_xc);
*/
}
public Iterator getParentAxisIterator(Object contextNode) throws UnsupportedAxisException
{
((JaxenNode)contextNode).toBookmark(_xc);
if (_xc.toParent())
return new SingleObjectIterator(getBookmarkInThisPlace(_xc));
else
return null;
}
public Iterator getAncestorAxisIterator(Object contextNode) throws UnsupportedAxisException
{
return new AncestorAxisIterator( contextNode, this );
}
public Iterator getFollowingSiblingAxisIterator(Object contextNode) throws UnsupportedAxisException
{
return new FollowingSiblingAxisIterator( contextNode, this );
}
public Iterator getPrecedingSiblingAxisIterator(Object contextNode) throws UnsupportedAxisException
{
return new PrecedingSiblingAxisIterator( contextNode, this );
}
public Iterator getFollowingAxisIterator(Object contextNode) throws UnsupportedAxisException
{
return new FollowingAxisIterator( contextNode, this );
}
public Iterator getPrecedingAxisIterator(Object contextNode) throws UnsupportedAxisException
{
return new PrecedingAxisIterator( contextNode, this );
}
public static class AttributeIterator implements Iterator
{
private JaxenNode _nextNode = null;
private XmlCursor _xc = null;
AttributeIterator(XmlCursor xc)
{
_xc = xc;
if (!_xc.toFirstAttribute())
_nextNode = null;
else
_nextNode = getBookmarkInThisPlace(_xc);
}
public boolean hasNext()
{
if (_nextNode == null)
return false;
return true;
}
public Object next()
{
if (_nextNode == null)
return null;
JaxenNode res = _nextNode;
res.toBookmark(_xc);
if (!_xc.toNextAttribute())
_nextNode = null;
else
_nextNode = getBookmarkInThisPlace(_xc);
return res;
}
public void remove() { throw new RuntimeException("optional method not implemented"); }
}
public Iterator getAttributeAxisIterator(Object contextNode) throws UnsupportedAxisException
{
((JaxenNode)contextNode).toBookmark(_xc);
return new AttributeIterator(_xc);
}
public static class NamespaceIterator implements Iterator
{
private JaxenNode _nextNode = null;
private XmlCursor _xc = null;
NamespaceIterator(XmlCursor xc)
{
_xc = xc;
while (true)
{
XmlCursor.TokenType tk = _xc.toNextToken();
if (tk == XmlCursor.TokenType.ATTR)
continue;
if (tk == XmlCursor.TokenType.NAMESPACE)
{
_nextNode = getBookmarkInThisPlace(_xc);
break;
}
_nextNode = null;
return;
}
}
public boolean hasNext()
{
if (_nextNode == null)
return false;
return true;
}
public Object next()
{
if (_nextNode == null)
return null;
JaxenNode res = _nextNode;
res.toBookmark(_xc);
if (_xc.toNextToken().isNamespace())
_nextNode = getBookmarkInThisPlace(_xc);
else
_nextNode = null;
return res;
}
public void remove() { throw new RuntimeException("optional method not implemented"); }
}
public Iterator getNamespaceAxisIterator(Object contextNode) throws UnsupportedAxisException
{
((JaxenNode)contextNode).toBookmark(_xc);
return new NamespaceIterator(_xc);
}
public Iterator getSelfAxisIterator(Object contextNode) throws UnsupportedAxisException
{
return new SelfAxisIterator( contextNode );
}
public static class DescendantOrSelfAxisItr implements Iterator
{
private JaxenNode _nextNode = null;
private XmlCursor _xc = null;
DescendantOrSelfAxisItr(XmlCursor xc)
{
_xc = xc;
XmlCursor.TokenType tk = _xc.toFirstContentToken(); //not including atts and ns-es
if (tk.isFinish())
_nextNode = null;
else
_nextNode = getBookmarkInThisPlace(_xc);
}
public boolean hasNext()
{
if (_nextNode == null)
return false;
return true;
}
public Object next()
{
if (_nextNode == null)
return null;
JaxenNode res = _nextNode;
res.toBookmark(_xc);
if (_xc.currentTokenType() == XmlCursor.TokenType.START)
{
_xc.toEndToken();
}
if (_xc.toNextToken().isFinish())
_nextNode = null;
else
_nextNode = getBookmarkInThisPlace(_xc);
return res;
}
public void remove() { throw new RuntimeException("optional method not implemented"); }
}
public Iterator getDescendantOrSelfAxisIterator(Object contextNode) throws UnsupportedAxisException
{
return new DescendantOrSelfAxisIterator( contextNode, this );
//((JaxenNode)contextNode).toBookmark(_xc);
//return new DescendantOrSelfAxisIterator(_xc);
}
public Iterator getAncestorOrSelfAxisIterator(Object contextNode) throws UnsupportedAxisException
{
return new AncestorOrSelfAxisIterator( contextNode, this );
//((JaxenNode)contextNode).toBookmark(_xc);
//return new AncestorOrSelfAxisIterator(_xc);
}
public Object getDocumentNode(Object contextNode)
{
((JaxenNode)contextNode).toBookmark(_xc);
_xc.toStartDoc();
return getBookmarkInThisPlace(_xc);
}
public String translateNamespacePrefixToUri(String prefix, Object element)
{
((JaxenNode)element).toBookmark(_xc);
return _xc.namespaceForPrefix(prefix);
}
public String getProcessingInstructionTarget(Object obj)
{
((JaxenNode)obj).toBookmark(_xc);
return _xc.getTextValue();
}
public String getProcessingInstructionData(Object obj)
{
((JaxenNode)obj).toBookmark(_xc);
return _xc.getTextValue();
}
public Object getDocument(String url) throws FunctionCallException
{
return null;
}
/**
* Default implementation that can not find elements. Override in subclass
* if subclass does know about attribute types.
*
* @param object a node from the document in which to look for the
* id
* @param elementId id to look for
*
* @return null
*/
public Object getElementById(Object object, String elementId)
{
return null;
}
public static class NamedChildIterator implements Iterator
{
private JaxenNode _nextNode = null;
private QName _qname;
private XmlCursor _xc = null;
NamedChildIterator(XmlCursor xc, String localName, String namespaceURI)
{
_xc = xc;
_qname = new QName( (namespaceURI==null ? "" : namespaceURI), localName);
if (!_xc.toFirstChild())
{
_nextNode = null;
return;
}
if (!(_xc.currentTokenType()==XmlCursor.TokenType.START &&
_xc.getName().equals(_qname)
))
{
if (!_xc.toNextSibling(_qname))
{
_nextNode = null;
return;
}
}
_nextNode = getBookmarkInThisPlace(_xc);
}
public boolean hasNext()
{
if (_nextNode == null)
return false;
return true;
}
public Object next()
{
if (_nextNode == null)
return null;
JaxenNode res = _nextNode;
res.toBookmark(_xc);
if (!_xc.toNextSibling(_qname))
_nextNode = null;
else
_nextNode = getBookmarkInThisPlace(_xc);
return res;
}
public void remove() { throw new RuntimeException("optional method not implemented"); }
}
public Iterator getChildAxisIterator(
Object contextNode,
String localName, String namespacePrefix, String namespaceURI)
throws UnsupportedAxisException
{
((JaxenNode)contextNode).toBookmark(_xc);
return new NamedChildIterator(_xc, localName, namespaceURI);
}
public static class NamedAttributeIterator implements Iterator
{
private JaxenNode _nextNode = null;
private QName _qname;
private XmlCursor _xc;
NamedAttributeIterator(XmlCursor xc, String local, String uri)
{
_xc = xc;
_qname = new QName(( uri==null ? "" : uri), local);
XmlCursor.TokenType tk = _xc.toNextToken();
if (tk!=XmlCursor.TokenType.ATTR)
{
_nextNode = null;
return;
}
if ( _xc.getName().equals(_qname) )
{
_nextNode = getBookmarkInThisPlace(_xc);
return;
}
_nextNode = move(_xc);
return;
}
public boolean hasNext()
{
if (_nextNode == null)
return false;
return true;
}
public Object next()
{
if (_nextNode == null)
return null;
JaxenNode res = _nextNode;
res.toBookmark(_xc);
_nextNode = move(_xc);
return res;
}
private JaxenNode move(XmlCursor xc)
{
if (xc.currentTokenType() != XmlCursor.TokenType.ATTR )
{
return null;
}
while(xc.toNextToken()==XmlCursor.TokenType.ATTR)
{
if ( xc.getName().equals(_qname) )
{
return getBookmarkInThisPlace(xc);
}
}
return null;
}
public void remove() { throw new RuntimeException("optional method not implemented"); }
}
public Iterator getAttributeAxisIterator(
Object contextNode,
String localName, String namespacePrefix, String namespaceURI)
throws UnsupportedAxisException
{
((JaxenNode)contextNode).toBookmark(_xc);
return new NamedAttributeIterator(_xc, localName, namespaceURI);
}
static JaxenNode getBookmarkInThisPlace(XmlCursor xc)
{
JaxenNode rez = (JaxenNode)xc.getBookmark(JaxenNode.class);
if (rez==null)
{
rez = new JaxenNode();
xc.setBookmark(rez);
}
return rez;
}
XmlCursor getCursor()
{
return _xc;
}
void setCursor(XmlCursor xc)
{
this._xc = xc;
}
}