/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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.
 */
/*
 * $Id$
 */

package org.apache.xalan.xsltc.dom;

import org.apache.xalan.xsltc.DOM;
import org.apache.xalan.xsltc.StripFilter;
import org.apache.xml.serializer.SerializationHandler;
import org.apache.xalan.xsltc.TransletException;
import org.apache.xalan.xsltc.runtime.BasisLibrary;
import org.apache.xalan.xsltc.runtime.Hashtable;
import org.apache.xml.dtm.DTM;
import org.apache.xml.dtm.Axis;
import org.apache.xml.dtm.DTMAxisIterator;
import org.apache.xml.dtm.DTMManager;
import org.apache.xml.dtm.ref.DTMAxisIteratorBase;
import org.apache.xml.dtm.ref.DTMDefaultBase;
import org.apache.xml.utils.SuballocatedIntVector;

import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * @author Jacek Ambroziak
 * @author Morten Jorgensen
 * @author Erwin Bolwidt <ejb@klomp.org>
 */
public final class MultiDOM implements DOM {

    private static final int NO_TYPE = DOM.FIRST_TYPE - 2;
    private static final int INITIAL_SIZE = 4;
    
    private DOM[] _adapters;
    private DOMAdapter _main;
    private DTMManager _dtmManager;
    private int _free;
    private int _size;

    private Hashtable _documents = new Hashtable();

    private final class AxisIterator extends DTMAxisIteratorBase {
        // constitutive data
        private final int _axis;
        private final int _type;
        // implementation mechanism
        private DTMAxisIterator _source;
        private int _dtmId = -1;

        public AxisIterator(final int axis, final int type) {
            _axis = axis;
            _type = type;
        }

        public int next() {
            if (_source == null) {
                return(END);
            }
            return _source.next();
        }


        public void setRestartable(boolean flag) {
            if (_source != null) {
                _source.setRestartable(flag);
            }
        }

        public DTMAxisIterator setStartNode(final int node) {
            if (node == DTM.NULL) {
                return this;
            }

            int dom = node >>> DTMManager.IDENT_DTM_NODE_BITS;

            // Get a new source first time and when mask changes
            if (_source == null || _dtmId != dom) {
                if (_type == NO_TYPE) {
                    _source = _adapters[dom].getAxisIterator(_axis);
                } else if (_axis == Axis.CHILD) {
                    _source = _adapters[dom].getTypedChildren(_type);
                } else {
                    _source = _adapters[dom].getTypedAxisIterator(_axis, _type);
                }
            }

            _dtmId = dom;
            _source.setStartNode(node);
            return this;
        }

        public DTMAxisIterator reset() {
            if (_source != null) {
                _source.reset();
            }
            return this;
        }
    
        public int getLast() {
            if (_source != null) {
                return _source.getLast();
            }
            else {
                return END;
            }
        }

        public int getPosition() {
            if (_source != null) {
                return _source.getPosition();
            }
            else {
                return END;
            }
        }
    
        public boolean isReverse() {
            return Axis.isReverse(_axis);
        }
    
        public void setMark() {
            if (_source != null) {
                _source.setMark();
            }
        }
    
        public void gotoMark() {
            if (_source != null) {
                _source.gotoMark();
            }
        }
    
        public DTMAxisIterator cloneIterator() {
            final AxisIterator clone = new AxisIterator(_axis, _type);
            if (_source != null) {
                clone._source = _source.cloneIterator();
            }
            clone._dtmId = _dtmId;
            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 DTMAxisIteratorBase {

        private DTMAxisIterator _source;
        private String _value;
        private boolean _op;
        private final boolean _isReverse;
        private int _returnType = RETURN_PARENT;

        public NodeValueIterator(DTMAxisIterator source, int returnType,
                                 String value, boolean op) {
            _source = source;
            _returnType = returnType;
            _value = value;
            _op = op;
            _isReverse = source.isReverse();
        }

        public boolean isReverse() {
            return _isReverse;
        }
    
        public DTMAxisIterator 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 DTMAxisIterator reset() {
            _source.reset();
            return resetPosition();
        }

        public int next() {

            int node;
            while ((node = _source.next()) != END) {
                String val = getStringValueX(node);
                if (_value.equals(val) == _op) {
                    if (_returnType == RETURN_CURRENT)
                        return returnNode(node);
                    else
                        return returnNode(getParent(node));
                }
            }
            return END;
        }

        public DTMAxisIterator 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];
        DOMAdapter adapter = (DOMAdapter)main;
        _adapters[0] = adapter;
        _main = adapter;
        DOM dom = adapter.getDOMImpl();
        if (dom instanceof DTMDefaultBase) {
            _dtmManager = ((DTMDefaultBase)dom).getManager();
        }

        // %HZ% %REVISIT% Is this the right thing to do here?  In the old
        // %HZ% %REVISIT% version, the main document did not get added through
        // %HZ% %REVISIT% a call to addDOMAdapter, which meant it couldn't be
        // %HZ% %REVISIT% found by a call to getDocumentMask.  The problem is
        // %HZ% %REVISIT% TransformerHandler is typically constructed with a
        // %HZ% %REVISIT% system ID equal to the stylesheet's URI; with SAX
        // %HZ% %REVISIT% input, it ends up giving that URI to the document.
        // %HZ% %REVISIT% Then, any references to document('') are resolved
        // %HZ% %REVISIT% using the stylesheet's URI.
        // %HZ% %REVISIT% MultiDOM.getDocumentMask is called to verify that
        // %HZ% %REVISIT% a document associated with that URI has not been
        // %HZ% %REVISIT% encountered, and that method ends up returning the
        // %HZ% %REVISIT% mask of the main document, when what we really what
        // %HZ% %REVISIT% is to read the stylesheet itself!
        addDOMAdapter(adapter, false);
    }

    public int nextMask() {
        return _free;
    }

    public void setupMapping(String[] names, String[] uris, int[] types, String[] namespaces) {
        // This method only has a function in DOM adapters
    }

    public int addDOMAdapter(DOMAdapter adapter) {
        return addDOMAdapter(adapter, true);
    }

    private int addDOMAdapter(DOMAdapter adapter, boolean indexByURI) {
        // Add the DOM adapter to the array of DOMs
        DOM dom = adapter.getDOMImpl();
        
        int domNo = 1;
        int dtmSize = 1;
        SuballocatedIntVector dtmIds = null;
        if (dom instanceof DTMDefaultBase) {
            DTMDefaultBase dtmdb = (DTMDefaultBase)dom;
            dtmIds = dtmdb.getDTMIDs();
            dtmSize = dtmIds.size();
            domNo = dtmIds.elementAt(dtmSize-1) >>> DTMManager.IDENT_DTM_NODE_BITS;
        }
        else if (dom instanceof SimpleResultTreeImpl) {
            SimpleResultTreeImpl simpleRTF = (SimpleResultTreeImpl)dom;
            domNo = simpleRTF.getDocument() >>> DTMManager.IDENT_DTM_NODE_BITS;
        }
                  
        if (domNo >= _size) {
            int oldSize = _size;
            do {
            	_size *= 2;
            } while (_size <= domNo);
            
            final DOMAdapter[] newArray = new DOMAdapter[_size];
            System.arraycopy(_adapters, 0, newArray, 0, oldSize);
            _adapters = newArray;
        }
        
        _free = domNo + 1;
        
        if (dtmSize == 1) {
            _adapters[domNo] = adapter;
        }
        else if (dtmIds != null) {
            int domPos = 0;
            for (int i = dtmSize - 1; i >= 0; i--) {
                domPos = dtmIds.elementAt(i) >>> DTMManager.IDENT_DTM_NODE_BITS;
                _adapters[domPos] = adapter;
            }
            domNo = domPos;
        }

        // Store reference to document (URI) in hashtable
        if (indexByURI) {
            String uri = adapter.getDocumentURI(0);
            _documents.put(uri, new Integer(domNo));
        }
        
        // If the dom is an AdaptiveResultTreeImpl, we need to create a
        // DOMAdapter around its nested dom object (if it is non-null) and
        // add the DOMAdapter to the list.
        if (dom instanceof AdaptiveResultTreeImpl) {
            AdaptiveResultTreeImpl adaptiveRTF = (AdaptiveResultTreeImpl)dom;
            DOM nestedDom = adaptiveRTF.getNestedDOM();
            if (nestedDom != null) {
                DOMAdapter newAdapter = new DOMAdapter(nestedDom, 
                                                       adapter.getNamesArray(),
                                                       adapter.getUrisArray(),
                                                       adapter.getTypesArray(),
                                                       adapter.getNamespaceArray());
                addDOMAdapter(newAdapter);  
            } 
        }
        
        return domNo;
    }
        
    public int getDocumentMask(String uri) {
        Integer domIdx = (Integer)_documents.get(uri);
        if (domIdx == null) {
            return(-1);
        } else {
            return domIdx.intValue();
        }
    }
    
    public DOM getDOMAdapter(String uri) {
        Integer domIdx = (Integer)_documents.get(uri);
        if (domIdx == null) {
            return(null);
        } else {
            return(_adapters[domIdx.intValue()]);
        }
    }
    
    public int getDocument() 
    {
        return _main.getDocument();
    }

    public DTMManager getDTMManager() {
    	return _dtmManager;
    }

    /** 
      * Returns singleton iterator containing the document root 
      */
    public DTMAxisIterator getIterator() {
        // main source document @ 0
        return _main.getIterator();
    }
    
    public String getStringValue() {
        return _main.getStringValue();
    }
    
    public DTMAxisIterator getChildren(final int node) {
        return _adapters[getDTMId(node)].getChildren(node);
    }
    
    public DTMAxisIterator getTypedChildren(final int type) {
        return new AxisIterator(Axis.CHILD, type);
    }
    
    public DTMAxisIterator getAxisIterator(final int axis) {
        return new AxisIterator(axis, NO_TYPE);
    }
    
    public DTMAxisIterator getTypedAxisIterator(final int axis, final int type)
    {
        return new AxisIterator(axis, type);
    }

    public DTMAxisIterator getNthDescendant(int node, int n,
                                            boolean includeself)
    {
        return _adapters[getDTMId(node)].getNthDescendant(node, n, includeself);
    }

    public DTMAxisIterator getNodeValueIterator(DTMAxisIterator iterator,
                                                int type, String value,
                                                boolean op)
    {
        return(new NodeValueIterator(iterator, type, value, op));
    }

    public DTMAxisIterator getNamespaceAxisIterator(final int axis,
                                                    final int ns)
    {
        DTMAxisIterator iterator = _main.getNamespaceAxisIterator(axis, ns);
        return(iterator);        
    }

    public DTMAxisIterator orderNodes(DTMAxisIterator source, int node) {
        return _adapters[getDTMId(node)].orderNodes(source, node);
    }

    public int getExpandedTypeID(final int node) {
    	if (node != DTM.NULL) {
            return _adapters[node >>> DTMManager.IDENT_DTM_NODE_BITS].getExpandedTypeID(node);
    	}
    	else {
    	    return DTM.NULL;
    	}
    }

    public int getNamespaceType(final int node) {
        return _adapters[getDTMId(node)].getNamespaceType(node);
    }
    
    public int getNSType(int node)
   {
        return _adapters[getDTMId(node)].getNSType(node);
   }
    
    public int getParent(final int node) {
        if (node == DTM.NULL) {
            return DTM.NULL;
        }
        return _adapters[node >>> DTMManager.IDENT_DTM_NODE_BITS].getParent(node);
    }
    
    public int getAttributeNode(final int type, final int el) {
        if (el == DTM.NULL) {
            return DTM.NULL;
        }
        return _adapters[el >>> DTMManager.IDENT_DTM_NODE_BITS].getAttributeNode(type, el);
    }
    
    public String getNodeName(final int node) {
        if (node == DTM.NULL) {
            return "";
        }
        return _adapters[node >>> DTMManager.IDENT_DTM_NODE_BITS].getNodeName(node);
    }
    
    public String getNodeNameX(final int node) {
        if (node == DTM.NULL) {
            return "";
        }
        return _adapters[node >>> DTMManager.IDENT_DTM_NODE_BITS].getNodeNameX(node);
    }

    public String getNamespaceName(final int node) {
        if (node == DTM.NULL) {
            return "";
        }
        return _adapters[node >>> DTMManager.IDENT_DTM_NODE_BITS].getNamespaceName(node);
    }
    
    public String getStringValueX(final int node) {
        if (node == DTM.NULL) {
            return "";
        }
        return _adapters[node >>> DTMManager.IDENT_DTM_NODE_BITS].getStringValueX(node);
    }
    
    public void copy(final int node, SerializationHandler handler)
        throws TransletException
    {
        if (node != DTM.NULL) {
            _adapters[node >>> DTMManager.IDENT_DTM_NODE_BITS].copy(node, handler);
        }
    }
    
    public void copy(DTMAxisIterator nodes, SerializationHandler handler)
            throws TransletException
    {
        int node;
        while ((node = nodes.next()) != DTM.NULL) {
            _adapters[node >>> DTMManager.IDENT_DTM_NODE_BITS].copy(node, handler);
        }
    }


    public String shallowCopy(final int node, SerializationHandler handler)
            throws TransletException
    {
        if (node == DTM.NULL) {
            return "";
        }
        return _adapters[node >>> DTMManager.IDENT_DTM_NODE_BITS].shallowCopy(node, handler);
    }
    
    public boolean lessThan(final int node1, final int node2) {
        if (node1 == DTM.NULL) {
            return true;
        }
        if (node2 == DTM.NULL) {
            return false;
        }
        final int dom1 = getDTMId(node1);
        final int dom2 = getDTMId(node2);
        return dom1 == dom2 ? _adapters[dom1].lessThan(node1, node2)
                            : dom1 < dom2;
    }
    
    public void characters(final int textNode, SerializationHandler handler)
                 throws TransletException
    {
        if (textNode != DTM.NULL) {
            _adapters[textNode >>> DTMManager.IDENT_DTM_NODE_BITS].characters(textNode, handler);
        }
    }

    public void setFilter(StripFilter filter) {
        for (int dom=0; dom<_free; dom++) {
            if (_adapters[dom] != null) {
                _adapters[dom].setFilter(filter);
            }
        }
    }

    public Node makeNode(int index) {
        if (index == DTM.NULL) {
            return null;
        }
        return _adapters[getDTMId(index)].makeNode(index);
    }

    public Node makeNode(DTMAxisIterator iter) {
        // TODO: gather nodes from all DOMs ?
        return _main.makeNode(iter);
    }

    public NodeList makeNodeList(int index) {
        if (index == DTM.NULL) {
            return null;
        }
        return _adapters[getDTMId(index)].makeNodeList(index);
    }

    public NodeList makeNodeList(DTMAxisIterator iter) {
        // TODO: gather nodes from all DOMs ?
        return _main.makeNodeList(iter);
    }

    public String getLanguage(int node) {
        return _adapters[getDTMId(node)].getLanguage(node);
    }

    public int getSize() {
        int size = 0;
        for (int i=0; i<_size; i++) {
            size += _adapters[i].getSize();
        }
        return(size);
    }

    public String getDocumentURI(int node) {
        if (node == DTM.NULL) {
            node = DOM.NULL;
        }
        return _adapters[node >>> DTMManager.IDENT_DTM_NODE_BITS].getDocumentURI(0);
    }

    public boolean isElement(final int node) {
        if (node == DTM.NULL) {
            return false;
        }
        return(_adapters[node >>> DTMManager.IDENT_DTM_NODE_BITS].isElement(node));
    }

    public boolean isAttribute(final int node) {
        if (node == DTM.NULL) {
            return false;
        }
        return(_adapters[node >>> DTMManager.IDENT_DTM_NODE_BITS].isAttribute(node));
    }
    
    public int getDTMId(int nodeHandle)
    {
        if (nodeHandle == DTM.NULL)
            return 0;
        
        int id = nodeHandle >>> DTMManager.IDENT_DTM_NODE_BITS;
        while (id >= 2 && _adapters[id] == _adapters[id-1]) {
            id--;
        }
        return id;
    }
    
    public int getNodeIdent(int nodeHandle)
    {
        return _adapters[nodeHandle >>> DTMManager.IDENT_DTM_NODE_BITS].getNodeIdent(nodeHandle);
    }
    
    public int getNodeHandle(int nodeId)
    {
        return _main.getNodeHandle(nodeId);
    }
    
    public DOM getResultTreeFrag(int initSize, int rtfType)
    {
        return _main.getResultTreeFrag(initSize, rtfType);
    }
    
    public DOM getResultTreeFrag(int initSize, int rtfType, boolean addToManager)
    {
        return _main.getResultTreeFrag(initSize, rtfType, addToManager);
    }
    
    public DOM getMain()
    {
        return _main;
    }
    
    /**
     * Returns a DOMBuilder class wrapped in a SAX adapter.
     */
    public SerializationHandler getOutputDomBuilder()
    {
        return _main.getOutputDomBuilder();
    }

    public String lookupNamespace(int node, String prefix) 
        throws TransletException
    {
        return _main.lookupNamespace(node, prefix);
    }

    // %HZ% Does this method make any sense here???
    public String getUnparsedEntityURI(String entity) {
        return _main.getUnparsedEntityURI(entity);
    }

    // %HZ% Does this method make any sense here???
    public Hashtable getElementsWithIDs() {
        return _main.getElementsWithIDs();
    }
}
