/*
 * @(#)$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(DOMAdapter 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));
	
	// Store mask in DOMAdapter
	dom.setMultiDOMMask(domNo << 24);
	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);
    }
}
