/*
 * (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 TXNodeList class is used to represent collections of Node 
 * objects which need to be accessed by name, ordinal, etc. 
 * For example, the Parent class uses TXNodeList to organize and access 
 * its Child Nodes.
 *
 * @version 1.1
 * @author TAMURA Kent &lt;kent@trl.ibm.co.jp&gt;
 * @see com.ibm.xml.parser.Parent
 */
class TXNodeList implements java.io.Serializable {

            Vector      nodes   =   new Vector();

    /**
     * Returns the number of Nodes in this TXNodeList.
     * @return      The number of Nodes in this TXNodeList.
     */
    public int getLength() {
        return this.nodes.size();
    }

    /**
     * Returns a NodeIterator containing all Nodes in the TXNodeList.
     * 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.
     * @return      A NodeIterator containing the Nodes in this list.
     * @see org.w3c.dom.NodeIterator
     * @see #elements
     */
    public NodeIterator getIterator() {
        return new VectorNodeIterator(this.nodes);
    }

    /**
     * Returns an enumeration of the Nodes of this TXNodeList.
     * @return      An enumeration of the Nodes of this list.
     * @see java.util.Enumeration
     * @see #getIterator
     */
    public java.util.Enumeration elements() {
        return this.nodes.elements();
    }

    /**
     * Returns the Node at the specified index.
     * @param      index   0-based index into this list.
     * @return     The Node at the specified index.
     * @exception  NoSuchNodeException  Thrown if an invalid index is specified.
     * @see #indexOf
     */
    public Child item(int index) throws NoSuchNodeException {
        if (index < 0 || this.nodes.size() <= index)
            throw new NoSuchNodeException();
        return (Child)this.nodes.elementAt(index);
    }

    /**
     * Searches for the first occurence of the specified Node, testing 
     * for equality using the Vector <code>equals</code> method. 
     * @param   node   Node to search for in this list.
     * @return  The 0-based index of the first occurrence of a matching Node in this list, or -1 if no matching Node.
     * @see     java.lang.Object#equals(java.lang.Object)
     * @see     #item
     */
    public int indexOf(Node node) {
        return this.nodes.indexOf(node);
    }

    /**
     * Replaces the Node at the specified index with <var>newNode</var>. 
     * @param   index       0-based index of the Node to replace.
     * @param   newNode     The new Node to replace at the specified index.
     * @see #insert      
     * @see #remove      
     * @exception  NoSuchNodeException  Thrown if an invalid index is specified.
     */
    public void replace(int index, Node newNode) throws NoSuchNodeException {
        if (index < 0 || this.nodes.size() <= index)  throw new NoSuchNodeException();
        Child oldChild = item(index);
        Child prev = (Child)oldChild.getPreviousSibling();
        Child next = (Child)oldChild.getNextSibling();
        this.nodes.setElementAt(newNode, index);
        Child newChild = (Child)newNode;
        newChild.setPreviousSibling(prev);
        if (null != prev)  prev.setNextSibling(newChild);
        newChild.setNextSibling(next);
        if (null != next)  next.setPreviousSibling(newChild);
    }

    /**
     * Inserts a new Node at the specified index.
     * @param   index       0-based index of where to insert <var>newNode</var>.
     * @param   newNode     The new Node to insert at the specified index.
     * @see #replace     
     * @see #remove
     * @see #addElement
     * @exception  NoSuchNodeException  Thrown if an invalid index is specified.
     */
    public void insert(int index, Node newNode) throws NoSuchNodeException {
        if (index < 0 || index > this.nodes.size())  throw new NoSuchNodeException();
        Child prev = 0 < index ? (Child)this.nodes.elementAt(index-1) : null;
        Child next = this.nodes.size() > index ? (Child)this.nodes.elementAt(index) : null;
        this.nodes.insertElementAt(newNode, index);
        Child child = (Child)newNode;
        child.setPreviousSibling(prev);
        if (null != prev)  prev.setNextSibling(child);
        child.setNextSibling(next);
        if (null != next)  next.setPreviousSibling(child);
    }

    /**
     * Removes a Node at the specified index.
     * @param   index       0-based index of where to remove a Node.
     * @return              The Node removed at the specified index.
     * @see #replace     
     * @see #insert      
     * @exception  NoSuchNodeException  Thrown if an invalid index is specified.
     */
    public Node remove(int index) throws NoSuchNodeException {
        if (index < 0 || this.nodes.size() <= index)  throw new NoSuchNodeException();
        Child old = (Child)this.nodes.elementAt(index);
        Child prev = (Child)old.getPreviousSibling();
        Child next = (Child)old.getNextSibling();
        this.nodes.removeElementAt(index);
        old.setParent(null);
        old.setPreviousSibling(null);
        old.setNextSibling(null);
        if (null != prev)  prev.setNextSibling(next);
        if (null != next)  next.setPreviousSibling(prev);
        return old;
    }

    /**
     * Inserts a new Node at the end of this NodeList.
     * @param   newNode     The new Node to insert at the end.
     * @see #insert
     * @see #replace     
     * @see #remove
     */
    public void addElement(Child newNode) {
        insert(this.nodes.size(), newNode);
    }

    /**
     * Increases the capacity of this TXNodeList, if necessary, to ensure 
     * that it can hold at least the number of Nodes specified by 
     * the minimum capacity argument. 
     * @param   minCapacity   The desired minimum capacity.
     */
    public void ensureCapacity(int minCapacity) {
        this.nodes.ensureCapacity(minCapacity);
    }
}
