blob: ebaab3b715dd369bf5880e30d38d0ccb2b73112c [file] [log] [blame]
/*
* @(#)$Id$
*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Xalan" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation and was
* originally based on software copyright (c) 2001, Sun
* Microsystems., http://www.sun.com. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
* @author Jacek Ambroziak
* @author Morten Jorgensen
* @author Erwin Bolwidt <ejb@klomp.org>
*
*/
package org.apache.xalan.xsltc.dom;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.apache.xalan.xsltc.DOM;
import org.apache.xalan.xsltc.StripFilter;
import org.apache.xalan.xsltc.NodeIterator;
import org.apache.xalan.xsltc.TransletOutputHandler;
import org.apache.xalan.xsltc.TransletException;
import org.apache.xalan.xsltc.runtime.Hashtable;
import org.apache.xalan.xsltc.runtime.BasisLibrary;
public final class MultiDOM implements DOM {
private static final int NO_TYPE = DOM.FIRST_TYPE - 2;
private static final int INITIAL_SIZE = 4;
private static final int CLR = 0x00FFFFFF;
private static final int SET = 0xFF000000;
private DOM[] _adapters;
private int _free;
private int _size;
private Hashtable _documents = new Hashtable();
private final class AxisIterator implements NodeIterator {
// constitutive data
private final int _axis;
private final int _type;
// implementation mechanism
private NodeIterator _source;
private int _mask;
public AxisIterator(final int axis, final int type) {
_axis = axis;
_type = type;
}
public int next() {
if (_source == null) return(END);
if (_mask == 0) return _source.next();
final int node = _source.next();
return node != END ? (node | _mask) : END;
}
public void setRestartable(boolean flag) {
_source.setRestartable(flag);
}
public NodeIterator setStartNode(final int node) {
_mask = node & SET;
int dom = node >>> 24;
// consider caching these
if ((_type == NO_TYPE) || (_type == DOM.ELEMENT)) {
_source = _adapters[dom].getAxisIterator(_axis);
}
else if (_axis == Axis.CHILD) {
_source = _adapters[dom].getTypedChildren(_type);
}
else {
_source = _adapters[dom].getTypedAxisIterator(_axis,_type);
}
_source.setStartNode(node & CLR);
return this;
}
public NodeIterator reset() {
if (_source != null) _source.reset();
return this;
}
public int getLast() {
return _source.getLast();
}
public int getPosition() {
return _source.getPosition();
}
public boolean isReverse() {
if (_source == null)
return(false);
else
return _source.isReverse();
}
public void setMark() {
_source.setMark();
}
public void gotoMark() {
_source.gotoMark();
}
public NodeIterator cloneIterator() {
final AxisIterator clone = new AxisIterator(_axis, _type);
clone._source = _source.cloneIterator();
clone._mask = _mask;
return clone;
}
} // end of AxisIterator
/**************************************************************
* This is a specialised iterator for predicates comparing node or
* attribute values to variable or parameter values.
*/
private final class NodeValueIterator extends NodeIteratorBase {
private NodeIterator _source;
private String _value;
private boolean _op;
private final boolean _isReverse;
private int _returnType = RETURN_PARENT;
public NodeValueIterator(NodeIterator source, int returnType,
String value, boolean op) {
_source = source;
_returnType = returnType;
_value = value;
_op = op;
_isReverse = source.isReverse();
}
public boolean isReverse() {
return _isReverse;
}
public NodeIterator cloneIterator() {
try {
NodeValueIterator clone = (NodeValueIterator)super.clone();
clone._source = _source.cloneIterator();
clone.setRestartable(false);
return clone.reset();
}
catch (CloneNotSupportedException e) {
BasisLibrary.runTimeError(BasisLibrary.ITERATOR_CLONE_ERR,
e.toString());
return null;
}
}
public void setRestartable(boolean isRestartable) {
_isRestartable = isRestartable;
_source.setRestartable(isRestartable);
}
public NodeIterator reset() {
_source.reset();
return resetPosition();
}
public int next() {
int node;
while ((node = _source.next()) != END) {
String val = getNodeValue(node);
if (_value.equals(val) == _op) {
if (_returnType == RETURN_CURRENT)
return returnNode(node);
else
return returnNode(getParent(node));
}
}
return END;
}
public NodeIterator setStartNode(int node) {
if (_isRestartable) {
_source.setStartNode(_startNode = node);
return resetPosition();
}
return this;
}
public void setMark() {
_source.setMark();
}
public void gotoMark() {
_source.gotoMark();
}
}
public MultiDOM(DOM main) {
_size = INITIAL_SIZE;
_free = 1;
_adapters = new DOM[INITIAL_SIZE];
_adapters[0] = main;
}
public int nextMask() {
return(_free << 24);
}
public void setupMapping(String[] names, String[] namespaces) {
// This method only has a function in DOM adapters
}
public int addDOMAdapter(DOM dom) {
// Add the DOM adapter to the array of DOMs
final int domNo = _free++;
if (domNo == _size) {
final DOMAdapter[] newArray = new DOMAdapter[_size *= 2];
System.arraycopy(_adapters, 0, newArray, 0, domNo);
_adapters = newArray;
}
_adapters[domNo] = dom;
// Store reference to document (URI) in hashtable
String uri = dom.getDocumentURI(0);
_documents.put(uri,new Integer(domNo));
return domNo << 24;
}
public int getDocumentMask(String uri) {
Integer domIdx = (Integer)_documents.get(uri);
if (domIdx == null)
return(-1);
else
return((domIdx.intValue() << 24));
}
/** returns singleton iterator containg the document root */
public NodeIterator getIterator() {
// main source document @ 0
return _adapters[0].getIterator();
}
public String getStringValue() {
return _adapters[0].getStringValue();
}
public String getTreeString() {
return _adapters[0].getTreeString();
}
public NodeIterator getChildren(final int node) {
return (node & SET) == 0
? _adapters[0].getChildren(node)
: getAxisIterator(Axis.CHILD).setStartNode(node);
}
public NodeIterator getTypedChildren(final int type) {
return new AxisIterator(Axis.CHILD, type);
}
public NodeIterator getAxisIterator(final int axis) {
return new AxisIterator(axis, NO_TYPE);
}
public NodeIterator getTypedAxisIterator(final int axis, final int type) {
return new AxisIterator(axis, type);
}
public NodeIterator getNthDescendant(int node, int n, boolean includeself) {
return _adapters[node>>>24].getNthDescendant(node & CLR,n,includeself);
}
public NodeIterator getNodeValueIterator(NodeIterator iterator, int type,
String value, boolean op) {
return(new NodeValueIterator(iterator, type, value, op));
}
public NodeIterator getNamespaceAxisIterator(final int axis, final int ns) {
NodeIterator iterator = _adapters[0].getNamespaceAxisIterator(axis,ns);
return(iterator);
}
public NodeIterator orderNodes(NodeIterator source, int node) {
return _adapters[node>>>24].orderNodes(source, node & CLR);
}
public int getType(final int node) {
return _adapters[node>>>24].getType(node & CLR);
}
public int getNamespaceType(final int node) {
return _adapters[node>>>24].getNamespaceType(node & CLR);
}
public int getParent(final int node) {
return _adapters[node>>>24].getParent(node & CLR) | node&SET;
}
public int getTypedPosition(int type, int node) {
return _adapters[node>>>24].getTypedPosition(type, node&CLR);
}
public int getTypedLast(int type, int node) {
return _adapters[node>>>24].getTypedLast(type, node&CLR);
}
public int getAttributeNode(final int type, final int el) {
return _adapters[el>>>24].getAttributeNode(type, el&CLR) | el&SET;
}
public String getNodeName(final int node) {
return _adapters[node>>>24].getNodeName(node & CLR);
}
public String getNamespaceName(final int node) {
return _adapters[node>>>24].getNamespaceName(node & CLR);
}
public String getNodeValue(final int node) {
return _adapters[node>>>24].getNodeValue(node & CLR);
}
public void copy(final int node, TransletOutputHandler handler)
throws TransletException {
_adapters[node>>>24].copy(node & CLR, handler);
}
public void copy(NodeIterator nodes, TransletOutputHandler handler)
throws TransletException {
int node;
while ((node = nodes.next()) != DOM.NULL) {
_adapters[node>>>24].copy(node & CLR, handler);
}
}
public String shallowCopy(final int node, TransletOutputHandler handler)
throws TransletException {
return _adapters[node>>>24].shallowCopy(node & CLR, handler);
}
public boolean lessThan(final int node1, final int node2) {
final int dom1 = node1>>>24;
final int dom2 = node2>>>24;
return dom1 == dom2
? _adapters[dom1].lessThan(node1 & CLR, node2 & CLR)
: dom1 < dom2;
}
public void characters(final int textNode, TransletOutputHandler handler)
throws TransletException {
_adapters[textNode>>>24].characters(textNode & CLR, handler);
}
public void setFilter(StripFilter filter) {
for (int dom=0; dom<_free; dom++) {
_adapters[dom].setFilter(filter);
}
}
public Node makeNode(int index) {
return _adapters[index>>>24].makeNode(index & CLR);
}
public Node makeNode(NodeIterator iter) {
// TODO: gather nodes from all DOMs ?
return _adapters[0].makeNode(iter);
}
public NodeList makeNodeList(int index) {
return _adapters[index>>>24].makeNodeList(index & CLR);
}
public NodeList makeNodeList(NodeIterator iter) {
// TODO: gather nodes from all DOMs ?
return _adapters[0].makeNodeList(iter);
}
public String getLanguage(int node) {
return _adapters[node>>>24].getLanguage(node & CLR);
}
public int getSize() {
int size = 0;
for (int i=0; i<_size; i++)
size += _adapters[i].getSize();
return(size);
}
public String getDocumentURI(int node) {
return _adapters[node>>>24].getDocumentURI(0);
}
public boolean isElement(final int node) {
return(_adapters[node>>>24].isElement(node & CLR));
}
public boolean isAttribute(final int node) {
return(_adapters[node>>>24].isAttribute(node & CLR));
}
public String lookupNamespace(int node, String prefix)
throws TransletException
{
return _adapters[node>>>24].lookupNamespace(node, prefix);
}
}