/*
 * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
 */
/*
 * 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: KeyIndex.java,v 1.6 2006/06/19 19:49:02 spericas Exp $
 */

package com.sun.org.apache.xalan.internal.xsltc.dom;

import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.DOMEnhancedForDTM;
import com.sun.org.apache.xalan.internal.xsltc.runtime.BasisLibrary;
import com.sun.org.apache.xalan.internal.xsltc.util.IntegerArray;
import com.sun.org.apache.xml.internal.dtm.Axis;
import com.sun.org.apache.xml.internal.dtm.DTM;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.dtm.ref.DTMAxisIteratorBase;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;

/**
 * Stores mappings of key values or IDs to DTM nodes.
 * <em>Use of an instance of this class as a {@link DTMAxisIterator} is
 * <b>deprecated.</b></em>
 * @author Morten Jorgensen
 * @author Santiago Pericas-Geertsen
 */
public class KeyIndex extends DTMAxisIteratorBase {

    /**
     * A mapping between values and nodesets for the current document.  Used
     * only while building keys.
     */
    private Map<String, IntegerArray> _index;

    /**
     * The document node currently being processed.  Used only while building
     * keys.
     */
    private int _currentDocumentNode = DTM.NULL;

    /**
     * A mapping from a document node to the mapping between values and nodesets
     */
    private Map<Integer, Map> _rootToIndexMap = new HashMap<>();

    /**
     * The node set associated to the current value passed
     * to lookupKey();
     */
    private IntegerArray _nodes = null;

    /**
     * The XSLTC DOM object if this KeyIndex is being used to implement the
     * id() function.
     */
    private DOM        _dom;

    private DOMEnhancedForDTM    _enhancedDOM;

    /**
     * Store position after call to setMark()
     */
    private int _markedPosition = 0;

    public KeyIndex(int dummy) {
    }

    public void setRestartable(boolean flag) {
    }

    /**
     * Adds a node to the node list for a given value. Nodes will
     * always be added in document order.
     */
    public void add(String value, int node, int rootNode) {
        if (_currentDocumentNode != rootNode) {
            _currentDocumentNode = rootNode;
            _index = new HashMap<>();
            _rootToIndexMap.put(rootNode, _index);
        }

        IntegerArray nodes = _index.get(value);

        if (nodes == null) {
             nodes = new IntegerArray();
            _index.put(value, nodes);
            nodes.add(node);

        // Because nodes are added in document order,
        // duplicates can be eliminated easily at this stage.
        } else if (node != nodes.at(nodes.cardinality() - 1)) {
            nodes.add(node);
        }
    }

    /**
     * Merge the current value's nodeset set by lookupKey() with _nodes.
     * @deprecated
     */
    public void merge(KeyIndex other) {
        if (other == null) return;

        if (other._nodes != null) {
            if (_nodes == null) {
                _nodes = (IntegerArray)other._nodes.clone();
            }
            else {
                _nodes.merge(other._nodes);
            }
        }
    }

    /**
     * This method must be called by the code generated by the id() function
     * prior to returning the node iterator. The lookup code for key() and
     * id() differ in the way the lookup value can be whitespace separated
     * list of tokens for the id() function, but a single string for the
     * key() function.
     * @deprecated
     */
    public void lookupId(Object value) {
        // Clear _nodes array
        _nodes = null;

        final StringTokenizer values = new StringTokenizer((String) value,
                                                           " \n\t");
        while (values.hasMoreElements()) {
            final String token = (String) values.nextElement();
            IntegerArray nodes = _index.get(token);

            if (nodes == null && _enhancedDOM != null
                && _enhancedDOM.hasDOMSource()) {
                nodes = getDOMNodeById(token);
            }

            if (nodes == null) continue;

            if (_nodes == null) {
                 nodes = (IntegerArray)nodes.clone();
                _nodes = nodes;
            }
            else {
                _nodes.merge(nodes);
            }
        }
    }

    /**
     * Return an IntegerArray for the DOM Node which has the given id.
     *
     * @param id The id
     * @return A IntegerArray representing the Node whose id is the given value.
     */
    public IntegerArray getDOMNodeById(String id) {
        IntegerArray nodes = null;

        if (_enhancedDOM != null) {
            int ident = _enhancedDOM.getElementById(id);

            if (ident != DTM.NULL) {
                Integer root = new Integer(_enhancedDOM.getDocument());
                Map<String, IntegerArray> index = _rootToIndexMap.get(root);

                if (index == null) {
                    index = new HashMap<>();
                    _rootToIndexMap.put(root, index);
                } else {
                    nodes = index.get(id);
                }

                if (nodes == null) {
                    nodes = new IntegerArray();
                    index.put(id, nodes);
                }

                nodes.add(_enhancedDOM.getNodeHandle(ident));
            }
        }

        return nodes;
    }

    /**
     * <p>This method must be called by the code generated by the key() function
     * prior to returning the node iterator.</p>
     * <p><em>Use of an instance of this class as a {@link DTMAxisIterator} is
     * <b>deprecated.</b></em></p>
     * @deprecated
     */
    public void lookupKey(Object value) {
        IntegerArray nodes = _index.get(value);
        _nodes = (nodes != null) ? (IntegerArray) nodes.clone() : null;
        _position = 0;
    }

    /**
     * <p>Callers should not call next() after it returns END.</p>
     * <p><em>Use of an instance of this class as a {@link DTMAxisIterator} is
     * <b>deprecated.</b></em></p>
     * @deprecated
     */
    public int next() {
        if (_nodes == null) return DTMAxisIterator.END;

        return (_position < _nodes.cardinality()) ?
            _dom.getNodeHandle(_nodes.at(_position++)) : DTMAxisIterator.END;
    }

    /**
     * Given a context node and the argument to the XPath <code>id</code>
     * function, checks whether the context node is in the set of nodes that
     * results from that reference to the <code>id</code> function.  This is
     * used in the implementation of <code>id</code> patterns.
     *
     * @param node The context node
     * @param value The argument to the <code>id</code> function
     * @return <code>1</code> if the context node is in the set of nodes
     *         returned by the reference to the <code>id</code> function;
     *         <code>0</code>, otherwise
     */
    public int containsID(int node, Object value) {
        final String string = (String)value;
        int rootHandle = _dom.getAxisIterator(Axis.ROOT)
                                 .setStartNode(node).next();

        // Get the mapping table for the document containing the context node
        Map<String, IntegerArray> index =
            _rootToIndexMap.get(rootHandle);

        // Split argument to id function into XML whitespace separated tokens
        final StringTokenizer values = new StringTokenizer(string, " \n\t");

        while (values.hasMoreElements()) {
            final String token = (String) values.nextElement();
            IntegerArray nodes = null;

            if (index != null) {
                nodes = index.get(token);
            }

            // If input was from W3C DOM, use DOM's getElementById to do
            // the look-up.
            if (nodes == null && _enhancedDOM != null
                && _enhancedDOM.hasDOMSource()) {
                nodes = getDOMNodeById(token);
            }

            // Did we find the context node in the set of nodes?
            if (nodes != null && nodes.indexOf(node) >= 0) {
                return 1;
            }
        }

        // Didn't find the context node in the set of nodes returned by id
        return 0;
    }

    /**
     * <p>Given a context node and the second argument to the XSLT
     * <code>key</code> function, checks whether the context node is in the
     * set of nodes that results from that reference to the <code>key</code>
     * function.  This is used in the implementation of key patterns.</p>
     * <p>This particular {@link KeyIndex} object is the result evaluating the
     * first argument to the <code>key</code> function, so it's not taken into
     * any further account.</p>
     *
     * @param node The context node
     * @param value The second argument to the <code>key</code> function
     * @return <code>1</code> if and only if the context node is in the set of
     *         nodes returned by the reference to the <code>key</code> function;
     *         <code>0</code>, otherwise
     */
    public int containsKey(int node, Object value) {
        int rootHandle = _dom.getAxisIterator(Axis.ROOT)
                                 .setStartNode(node).next();

        // Get the mapping table for the document containing the context node
        Map<String,IntegerArray> index =
                    _rootToIndexMap.get(new Integer(rootHandle));

        // Check whether the context node is present in the set of nodes
        // returned by the key function
        if (index != null) {
            final IntegerArray nodes = index.get(value);
            return (nodes != null && nodes.indexOf(node) >= 0) ? 1 : 0;
        }

        // The particular key name identifies no nodes in this document
        return 0;
    }

    /**
     * <p>Resets the iterator to the last start node.</p>
     * <p><em>Use of an instance of this class as a {@link DTMAxisIterator} is
     * <b>deprecated.</b></em></p>
     * @deprecated
     */
    public DTMAxisIterator reset() {
        _position = 0;
        return this;
    }

    /**
     * <p>Returns the number of elements in this iterator.</p>
     * <p><em>Use of an instance of this class as a {@link DTMAxisIterator} is
     * <b>deprecated.</b></em></p>
     * @deprecated
     */
    public int getLast() {
        return (_nodes == null) ? 0 : _nodes.cardinality();
    }

    /**
     * <p>Returns the position of the current node in the set.</p>
     * <p><em>Use of an instance of this class as a {@link DTMAxisIterator} is
     * <b>deprecated.</b></em></p>
     * @deprecated
     */
    public int getPosition() {
        return _position;
    }

    /**
     * <p>Remembers the current node for the next call to gotoMark().</p>
     * <p><em>Use of an instance of this class as a {@link DTMAxisIterator} is
     * <b>deprecated.</b></em></p>
     * @deprecated
     */
    public void setMark() {
        _markedPosition = _position;
    }

    /**
     * <p>Restores the current node remembered by setMark().</p>
     * <p><em>Use of an instance of this class as a {@link DTMAxisIterator} is
     * <b>deprecated.</b></em></p>
     * @deprecated
     */
    public void gotoMark() {
        _position = _markedPosition;
    }

    /**
     * <p>Set start to END should 'close' the iterator,
     * i.e. subsequent call to next() should return END.</p>
     * <p><em>Use of an instance of this class as a {@link DTMAxisIterator} is
     * <b>deprecated.</b></em></p>
     * @deprecated
     */
    public DTMAxisIterator setStartNode(int start) {
        if (start == DTMAxisIterator.END) {
            _nodes = null;
        }
        else if (_nodes != null) {
            _position = 0;
        }
        return (DTMAxisIterator) this;
    }

    /**
     * <p>Get start to END should 'close' the iterator,
     * i.e. subsequent call to next() should return END.</p>
     * <p><em>Use of an instance of this class as a {@link DTMAxisIterator} is
     * <b>deprecated.</b></em></p>
     * @deprecated
     */
    public int getStartNode() {
        return 0;
    }

    /**
     * <p>True if this iterator has a reversed axis.</p>
     * <p><em>Use of an instance of this class as a {@link DTMAxisIterator} is
     * <b>deprecated.</b></em></p>
     * @deprecated
     */
    public boolean isReverse() {
        return(false);
    }

    /**
     * <p>Returns a deep copy of this iterator.</p>
     * <p><em>Use of an instance of this class as a {@link DTMAxisIterator} is
     * <b>deprecated.</b></em></p>
     * @deprecated
     */
    public DTMAxisIterator cloneIterator() {
        KeyIndex other = new KeyIndex(0);
        other._index = _index;
        other._rootToIndexMap = _rootToIndexMap;
        other._nodes = _nodes;
        other._position = _position;
        return (DTMAxisIterator) other;
    }

    public void setDom(DOM dom, int node) {
        _dom = dom;

        // If a MultiDOM, ensure _enhancedDOM is correctly set
        // so that getElementById() works in lookupNodes below
        if (dom instanceof MultiDOM) {
            dom = ((MultiDOM) dom).getDTM(node);
        }

        if (dom instanceof DOMEnhancedForDTM) {
            _enhancedDOM = (DOMEnhancedForDTM)dom;
        }
        else if (dom instanceof DOMAdapter) {
            DOM idom = ((DOMAdapter)dom).getDOMImpl();
            if (idom instanceof DOMEnhancedForDTM) {
                _enhancedDOM = (DOMEnhancedForDTM)idom;
            }
        }
    }

    /**
     * Create a {@link KeyIndexIterator} that iterates over the nodes that
     * result from a reference to the XSLT <code>key</code> function or
     * XPath <code>id</code> function.
     *
     * @param keyValue A string or iterator representing the key values or id
     *                 references
     * @param isKeyCall A <code>boolean</code> indicating whether the iterator
     *                 is being created for a reference <code>key</code> or
     *                 <code>id</code>
     */
    public KeyIndexIterator getKeyIndexIterator(Object keyValue,
                                                boolean isKeyCall) {
        if (keyValue instanceof DTMAxisIterator) {
            return getKeyIndexIterator((DTMAxisIterator) keyValue, isKeyCall);
        } else {
            return getKeyIndexIterator(BasisLibrary.stringF(keyValue, _dom),
                                       isKeyCall);
        }
    }

    /**
     * Create a {@link KeyIndexIterator} that iterates over the nodes that
     * result from a reference to the XSLT <code>key</code> function or
     * XPath <code>id</code> function.
     *
     * @param keyValue A string representing the key values or id
     *                 references
     * @param isKeyCall A <code>boolean</code> indicating whether the iterator
     *                 is being created for a reference <code>key</code> or
     *                 <code>id</code>
     */
    public KeyIndexIterator getKeyIndexIterator(String keyValue,
                                                boolean isKeyCall) {
        return new KeyIndexIterator(keyValue, isKeyCall);
    }

    /**
     * Create a {@link KeyIndexIterator} that iterates over the nodes that
     * result from a reference to the XSLT <code>key</code> function or
     * XPath <code>id</code> function.
     *
     * @param keyValue An iterator representing the key values or id
     *                 references
     * @param isKeyCall A <code>boolean</code> indicating whether the iterator
     *                 is being created for a reference <code>key</code> or
     *                 <code>id</code>
     */
    public KeyIndexIterator getKeyIndexIterator(DTMAxisIterator keyValue,
                                                boolean isKeyCall) {
        return new KeyIndexIterator(keyValue, isKeyCall);
    }

    /**
     * Used to represent an empty node set.
     */
    final private static IntegerArray EMPTY_NODES = new IntegerArray(0);


    /**
     * An iterator representing the result of a reference to either the
     * XSLT <code>key</code> function or the XPath <code>id</code> function.
     */
    public class KeyIndexIterator extends MultiValuedNodeHeapIterator {

        /**
         * <p>A reference to the <code>key</code> function that only has one
         * key value or to the <code>id</code> function that has only one string
         * argument can be optimized to ignore the multi-valued heap.  This
         * field will be <code>null</code> otherwise.
         */
        private IntegerArray _nodes;

        /**
         * <p>This field contains the iterator representing a node set key value
         * argument to the <code>key</code> function or a node set argument
         * to the <code>id</code> function.</p>
         *
         * <p>Exactly one of this field and {@link #_keyValue} must be
         * <code>null</code>.</p>
         */
        private DTMAxisIterator _keyValueIterator;

        /**
         * <p>This field contains the iterator representing a non-node-set key
         * value argument to the <code>key</code> function or a non-node-set
         * argument to the <code>id</code> function.</p>
         *
         * <p>Exactly one of this field and {@link #_keyValueIterator} must be
         * <code>null</code>.</p>
         */
        private String _keyValue;

        /**
         * Indicates whether this object represents the result of a reference
         * to the <code>key</code> function (<code>true</code>) or the
         * <code>id</code> function (<code>false</code>).
         */
        private boolean _isKeyIterator;

        /**
         * Represents the DTM nodes retrieved for one key value or one string
         * argument to <code>id</code> for use as one heap node in a
         * {@link MultiValuedNodeHeapIterator}.
         */
        protected class KeyIndexHeapNode
                extends MultiValuedNodeHeapIterator.HeapNode
        {
            /**
             * {@link IntegerArray} of DTM nodes retrieved for one key value.
             * Must contain no duplicates and be stored in document order.
             */
            private IntegerArray _nodes;

            /**
             * Position in {@link #_nodes} array of next node to return from
             * this heap node.
             */
            private int _position = 0;

            /**
             * Marked position.  Used by {@link #setMark()} and
             * {@link #gotoMark()}
             */
            private int _markPosition = -1;

            /**
             * Create a heap node representing DTM nodes retrieved for one
             * key value in a reference to the <code>key</code> function
             * or string argument to the <code>id</code> function.
             */
            KeyIndexHeapNode(IntegerArray nodes) {
                _nodes = nodes;
            }

            /**
             * Advance to the next node represented by this {@link HeapNode}
             *
             * @return the next DTM node.
             */
            public int step() {
                if (_position < _nodes.cardinality()) {
                    _node = _nodes.at(_position);
                    _position++;
                } else {
                    _node = DTMAxisIterator.END;
                }

                return _node;
            }

            /**
             * Creates a deep copy of this {@link HeapNode}.  The clone is not
             * reset from the current position of the original.
             *
             * @return the cloned heap node
             */
            public HeapNode cloneHeapNode() {
                KeyIndexHeapNode clone =
                        (KeyIndexHeapNode) super.cloneHeapNode();

                clone._nodes = _nodes;
                clone._position = _position;
                clone._markPosition = _markPosition;

                return clone;
            }

            /**
             * Remembers the current node for the next call to
             * {@link #gotoMark()}.
             */
            public void setMark() {
                _markPosition = _position;
            }

            /**
             * Restores the current node remembered by {@link #setMark()}.
             */
            public void gotoMark() {
                _position = _markPosition;
            }

            /**
             * Performs a comparison of the two heap nodes
             *
             * @param heapNode the heap node against which to compare
             * @return <code>true</code> if and only if the current node for
             *         this heap node is before the current node of the
             *         argument heap node in document order.
             */
            public boolean isLessThan(HeapNode heapNode) {
                return _node < heapNode._node;
            }

            /**
             * <p>Sets context with respect to which this heap node is
             * evaluated.</p>
             * <p>This has no real effect on this kind of heap node.  Instead,
             * the {@link KeyIndexIterator#setStartNode(int)} method should
             * create new instances of this class to represent the effect of
             * changing the context.</p>
             */
            public HeapNode setStartNode(int node) {
                return this;
            }

            /**
             * Reset the heap node back to its beginning.
             */
            public HeapNode reset() {
                _position = 0;
                return this;
            }
        }

        /**
         * Constructor used when the argument to <code>key</code> or
         * <code>id</code> is not a node set.
         *
         * @param keyValue the argument to <code>key</code> or <code>id</code>
         *                 cast to a <code>String</code>
         * @param isKeyIterator indicates whether the constructed iterator
         *                represents a reference to <code>key</code> or
         *                <code>id</code>.
         */
        KeyIndexIterator(String keyValue, boolean isKeyIterator) {
            _isKeyIterator = isKeyIterator;
            _keyValue = keyValue;
        }

        /**
         * Constructor used when the argument to <code>key</code> or
         * <code>id</code> is a node set.
         *
         * @param keyValues the argument to <code>key</code> or <code>id</code>
         * @param isKeyIterator indicates whether the constructed iterator
         *                represents a reference to <code>key</code> or
         *                <code>id</code>.
         */
        KeyIndexIterator(DTMAxisIterator keyValues, boolean isKeyIterator) {
            _keyValueIterator = keyValues;
            _isKeyIterator = isKeyIterator;
        }

        /**
         * Retrieve nodes for a particular key value or a particular id
         * argument value.
         *
         * @param root The root node of the document containing the context node
         * @param keyValue The key value of id string argument value
         * @return an {@link IntegerArray} of the resulting nodes
         */
        protected IntegerArray lookupNodes(int root, String keyValue) {
            IntegerArray result = null;

            // Get mapping from key values/IDs to DTM nodes for this document
            Map<String, IntegerArray> index = _rootToIndexMap.get(root);

            if (!_isKeyIterator) {
                // For id function, tokenize argument as whitespace separated
                // list of values and look up nodes identified by each ID.
                final StringTokenizer values =
                        new StringTokenizer(keyValue, " \n\t");

                while (values.hasMoreElements()) {
                    final String token = (String) values.nextElement();
                    IntegerArray nodes = null;

                    // Does the ID map to any node in the document?
                    if (index != null) {
                        nodes = index.get(token);
                    }

                    // If input was from W3C DOM, use DOM's getElementById to do
                    // the look-up.
                    if (nodes == null && _enhancedDOM != null
                            && _enhancedDOM.hasDOMSource()) {
                        nodes = getDOMNodeById(token);
                    }

                    // If we found any nodes, merge them into the cumulative
                    // result
                    if (nodes != null) {
                        if (result == null) {
                            result = (IntegerArray)nodes.clone();
                        } else {
                            result.merge(nodes);
                        }
                    }
                }
            } else if (index != null) {
                // For key function, map key value to nodes
                result = index.get(keyValue);
            }

            return result;
        }

        /**
         * Set context node for the iterator.  This will cause the iterator
         * to reset itself, reevaluate arguments to the function, look up
         * nodes in the input and reinitialize its internal heap.
         *
         * @param node the context node
         * @return A {@link DTMAxisIterator} set to the start of the iteration.
         */
        public DTMAxisIterator setStartNode(int node) {
            _startNode = node;

            // If the arugment to the function is a node set, set the
            // context node on it.
            if (_keyValueIterator != null) {
                _keyValueIterator = _keyValueIterator.setStartNode(node);
            }

            init();

            return super.setStartNode(node);
        }

        /**
         * Get the next node in the iteration.
         *
         * @return The next node handle in the iteration, or END.
         */
        public int next() {
            int nodeHandle;

            // If at most one key value or at most one string argument to id
            // resulted in nodes being returned, use the IntegerArray
            // stored at _nodes directly.  This relies on the fact that the
            // IntegerArray never includes duplicate nodes and is always stored
            // in document order.
            if (_nodes != null) {
                if (_position < _nodes.cardinality()) {
                    nodeHandle = returnNode(_nodes.at(_position));
                } else {
                    nodeHandle = DTMAxisIterator.END;
                }
            } else {
                nodeHandle = super.next();
            }

            return nodeHandle;
        }

        /**
         * Resets the iterator to the last start node.
         *
         * @return A DTMAxisIterator, which may or may not be the same as this
         *         iterator.
         */
        public DTMAxisIterator reset() {
            if (_nodes == null) {
                init();
            } else {
                super.reset();
            }

            return resetPosition();
        }

        /**
         * Evaluate the reference to the <code>key</code> or <code>id</code>
         * function with the context specified by {@link #setStartNode(int)}
         * and set up this iterator to iterate over the DTM nodes that are
         * to be returned.
         */
        protected void init() {
            super.init();
            _position = 0;

            // All nodes retrieved are in the same document
            int rootHandle = _dom.getAxisIterator(Axis.ROOT)
                                      .setStartNode(_startNode).next();

            // Is the argument not a node set?
            if (_keyValueIterator == null) {
                // Look up nodes returned for the single string argument
                _nodes = lookupNodes(rootHandle, _keyValue);

                if (_nodes == null) {
                    _nodes = EMPTY_NODES;
                }
            } else {
                DTMAxisIterator keyValues = _keyValueIterator.reset();
                int retrievedKeyValueIdx = 0;
                boolean foundNodes = false;

                _nodes = null;

                // For each node in the node set argument, get the string value
                // and look up the nodes returned by key or id for that string
                // value.  If at most one string value has nodes associated,
                // the nodes will be stored in _nodes; otherwise, the nodes
                // will be placed in a heap.
                for (int keyValueNode = keyValues.next();
                     keyValueNode != DTMAxisIterator.END;
                     keyValueNode = keyValues.next()) {

                    String keyValue = BasisLibrary.stringF(keyValueNode, _dom);

                    IntegerArray nodes = lookupNodes(rootHandle, keyValue);

                    if (nodes != null) {
                        if (!foundNodes) {
                            _nodes = nodes;
                            foundNodes = true;
                        } else {
                            if (_nodes != null) {
                                addHeapNode(new KeyIndexHeapNode(_nodes));
                                _nodes = null;
                            }
                            addHeapNode(new KeyIndexHeapNode(nodes));
                        }
                    }
                }

                if (!foundNodes) {
                    _nodes = EMPTY_NODES;
                }
            }
        }

        /**
         * Returns the number of nodes in this iterator.
         *
         * @return the number of nodes
         */
        public int getLast() {
            // If nodes are stored in _nodes, take advantage of the fact that
            // there are no duplicates.  Otherwise, fall back to the base heap
            // implementaiton and hope it does a good job with this.
            return (_nodes != null) ? _nodes.cardinality() : super.getLast();
        }

        /**
         * Return the node at the given position.
         *
         * @param position The position
         * @return The node at the given position.
         */
        public int getNodeByPosition(int position) {
            int node = DTMAxisIterator.END;

            // If nodes are stored in _nodes, take advantage of the fact that
            // there are no duplicates and they are stored in document order.
            // Otherwise, fall back to the base heap implementation to do a
            // good job with this.
            if (_nodes != null) {
                if (position > 0) {
                    if (position <= _nodes.cardinality()) {
                        _position = position;
                        node = _nodes.at(position-1);
                    } else {
                        _position = _nodes.cardinality();
                    }
                }
            } else {
                node = super.getNodeByPosition(position);
            }

            return node;
        }
    }
}
