/*
 * (C) Copyright IBM Corp. 1997-1998  All rights reserved.
 *
 * US Government Users Restricted Rights Use, duplication or
 * disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
 *
 * The program is provided "as is" without any warranty express or
 * implied, including the warranty of non-infringement and the implied
 * warranties of merchantibility and fitness for a particular purpose.
 * IBM will not be liable for any damages suffered by you as a result
 * of using the Program. In no event will IBM be liable for any
 * special, indirect or consequential damages or lost profits even if
 * IBM has been advised of the possibility of their occurrence. IBM
 * will not be liable for any third party claims against you.
 */

package com.ibm.xml.parser;

import org.w3c.dom.*;
import java.util.Vector;

/**
 * The VectorNodeIterator class implements the NodeIterator interface as defined by the Document Object Model (DOM).
 * <p>The content of a NodeIterator is "live" in the sense that changes to the children 
 * of the Node object that it was created from will be immediately reflected in the 
 * Nodes returned by the iterator; it is not a static snapshot of the content of the 
 * Node. Similarly, changes made to the Nodes returned by the iterator will be 
 * immediately reflected in the tree, including the set of children of the Node that
 * the NodeIterator was created from.
 *
 * @version 1.1
 * @author TAMURA Kent &lt;kent@trl.ibm.co.jp&gt;
 * @see org.w3c.dom.NodeIterator
 */
class VectorNodeIterator implements NodeIterator {
    /**
     * This is for an empty Iterator.
     */
    static final Vector             emptyVector   = new Vector(0);
    static final VectorNodeIterator emptyIterator = new VectorNodeIterator(null);


            Vector          nodes       = null;
            int             currentPos  = 0;

    /**
     * Constructor.
     * @param nodes        The Nodes to be iterated over.
     */
    public VectorNodeIterator(Vector nodes) {
        this.nodes = null == nodes ? emptyVector : nodes;
    }

    /**
     * Return the number of Nodes in the iterator.
     * <p>This method is defined by DOM.
     * @return          Number of Nodes in the iterator.
     */
    public int getLength() {
        return this.nodes.size();
    }

    /**
     * Return the current position (index) in the iterator.
     * <p>This method is defined by DOM.
     * @return          The current position in the iterator.
     * @see #atFirst
     * @see #atLast
     */
    public int getCurrentPos() {
        return this.currentPos;
    }

    /**
     * Return whether the current position is at the beginning of the iterator.
     * <p>This method is defined by DOM.
     * @return          =true if at current position is 0; otherwise, false.
     * @see #getCurrentPos
     * @see #atLast
     */
    public boolean atFirst() {
        return 0 == this.currentPos;
    }

    /**
     * Return whether the current position is at the end of the iterator.
     * <p>This method is defined by DOM.
     * @return          =true if at current position is =getLength(); otherwise, false.
     * @see #getCurrentPos
     * @see #atLast
     */
    public boolean atLast() {
        return getLength() <= this.currentPos;
    }

    /**
     * Return the next Node in the iterator.
     * <p>This method is defined by DOM.
     * @return          Next sequential Node after the current position, or <var>null</var> if already at the end of the iterator.
     * @see #toPrevNode
     * @see #toFirstNode
     * @see #toLastNode
     * @see #moveTo
     */
    public Node toNextNode() {
        return this.nodes.size() <= this.currentPos ? null : (Node)this.nodes.elementAt(this.currentPos++);
    }

    /**
     * Return the previous Node in the iterator.
     * <p>This method is defined by DOM.
     * @return          Previous sequential Node before the current position, or <var>null</var> if already at the beginning of the iterator.
     * @see #toNextNode
     * @see #toFirstNode
     * @see #toLastNode
     * @see #moveTo
     */
    public Node toPrevNode() {
        return 0 < this.currentPos ? (Node)this.nodes.elementAt(--this.currentPos) : null;
    }

    /**
     * Return the Node at the beginning of the iterator.
     * <p>This method is defined by DOM.
     * @return          First Node in the iterator, or <var>null</var> if no Nodes in the iterator.                
     * @see #toNextNode
     * @see #toPrevNode
     * @see #toLastNode
     * @see #moveTo
     */
    public Node toFirstNode() {
        this.currentPos = 0;
        return 0 == this.nodes.size() ? null : (Node)this.nodes.elementAt(0);
    }

    /**
     * Return the Node at the end of the iterator.
     * <p>This method is defined by DOM.
     * @return          Last Node in the iterator, or <var>null</var> if no Nodes in the iterator.                
     * @see #toNextNode
     * @see #toPrevNode
     * @see #toFirstNode
     * @see #moveTo
     */
    public Node toLastNode() {
        this.currentPos = this.nodes.size();
        return 0 == this.currentPos ? null : (Node)this.nodes.elementAt(this.currentPos-1);
    }

    /**
     * Return the Nth Node in the iterator.
     * <p>This method is defined by DOM.
     * @param   nth     0-based index into the iterator to retrieve the Node.
     * @return          Nth Node in the iterator, or <var>null</var> if no Nodes at the specified index.         
     * @see #toNextNode
     * @see #toPrevNode
     * @see #toFirstNode
     * @see #toLastNode
     */
    public Node moveTo(int nth) {
        this.currentPos = nth;
        return (0 <= nth && nth < this.nodes.size()) ? (Node)this.nodes.elementAt(this.currentPos) : null;
    }

}
