/*
 * $Id$
 *
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 2000 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 "Crimson" 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) 1999, Sun Microsystems, Inc., 
 * http://www.sun.com.  For more information on the Apache Software 
 * Foundation, please see <http://www.apache.org/>.
 */

package org.apache.xerces.tree;


import java.io.IOException;
import java.io.Writer;

import org.xml.sax.SAXException;

import org.w3c.dom.*;


/**
 * This adds an implementation of "parent of" relationships to the NodeBase
 * class.  It implements operations for maintaining a set of children,
 * providing indexed access to them, and writing them them out as text.
 *
 * <P> The NodeList it implements to describe its children is "live", as
 * required by DOM.  That means that indexed accesses by applications must
 * handle cases associated with unstable indices and lengths.  Indices
 * should not be stored if they can be invalidated by changes, including
 * changes made by other threads.
 *
 * @author David Brownell
 * @version $Revision$
 */
// not public ... javadoc looks a bit odd (hidden base class)
// but it's only subclassable within this package anyway
abstract class ParentNode
    extends NodeBase
    implements XmlReadable
{
    private NodeBase		children [];
    private int			length;

    /**
     * Builds a ParentNode, which can have children that are
     * subclasses of NodeBase.
     */
    // package private
    ParentNode () { }

    /**
     * Called to minimize space utilization.  Affects only
     * this node; children must be individually trimmed.
     */
    public void trimToSize ()
    {
	if (length == 0)
	    children = null;
        else if (children.length != length) {
	    NodeBase	temp [] = new NodeBase [length];

            System.arraycopy (children, 0, temp, 0, length);
	    children = temp;
	}
    }

    // package private
    void reduceWaste ()
    {
	if (children == null)
	    return;

	//
	// Arbitrary -- rather than paying trimToSize() costs
	// on most elements, we routinely accept some waste but
	// do try to reduce egregious waste.  Interacts with
	// the array allocation done in appendChild.
	//
	if ((children.length - length) > 6)
            trimToSize ();
    }


    /**
     * Writes each of the child nodes.  For element nodes, this adds
     * whitespace to indent non-text children (it prettyprints) unless
     * the <em>xml:space='preserve'</em> attribute applies, or the
     * write context disables prettyprinting.
     *
     * @param context describes how the children should be printed
     */
    public void writeChildrenXml (XmlWriteContext context) throws IOException
    {
	if (children == null)
	    return;

	int	oldIndent = 0;
	boolean	preserve = true;
	boolean	pureText = true;

	if (getNodeType () == ELEMENT_NODE) {
	    preserve = "preserve".equals (
		    getInheritedAttribute ("xml:space"));
	    oldIndent = context.getIndentLevel ();
	}

	try {
	    if (!preserve)
		context.setIndentLevel (oldIndent + 2);
	    for (int i = 0; i < length; i++) {
		if (!preserve && children [i].getNodeType () != TEXT_NODE) {
		    context.printIndent ();
		    pureText = false;
		}
		children [i].writeXml (context);
	    }
	} finally {
	    if (!preserve) {
		context.setIndentLevel (oldIndent);
		if (!pureText)
		    context.printIndent ();		// for ETag
	    }
	}
    }

    /**
     * Subclasses may override this method, which is called shortly after
     * the object type is known and before any children are processed.
     * For elements, attributes are known and may be modified; since
     * parent context is available, inherited attributes can be seen.
     *
     * <P> The default implementation does nothing.
     *
     * @param context provides location and error reporting data
     */
    public void startParse (ParseContext context)
    throws SAXException
    {
	// nothing
    }

    /**
     * Subclasses may override this method, which is called after each
     * child (text, element, processing instruction) is fully parsed.
     * Subclassers may substitute, discard, reorder, modify, or otherwise
     * process the child.  For example, elements which correspond to object
     * properties may be stored in that way, rather than appended.  The
     * <em>startParse</em> method has always been called before this.
     *
     * <P> The default implementation does nothing.
     *
     * @param child the child which has just been completely parsed;
     *	it is already a child of this node.
     * @param context provides location and error reporting data
     */
    public void doneChild (NodeEx child, ParseContext context)
    throws SAXException
    {
    }

    /**
     * Subclasses may override this method, which is called shortly after
     * the object is fully parsed.  The <em>startParse</em> method has
     * always been called before this, and doneChild will have been called
     * for each child.
     *
     * <P> The default implementation does nothing.
     *
     * @param context provides location and error reporting data
     */
    public void doneParse (ParseContext context)
    throws SAXException
    {
	// nothing
    }


    // package private -- overridden in implementation classes
    abstract void checkChildType (int type)
    throws DOMException;

    // DOM support


    /**
     * <b>DOM:</b>  Returns true if there are children to this node.
     */
    final public boolean hasChildNodes ()
    {
	return length > 0;
    }

    /**
     * <b>DOM:</b>  Returns the first child of this node, else null if there
     * are no children.
     */
    final public Node getFirstChild ()
    {
	if (length == 0)
	    return null;
	return children [0];
    }
    
    /**
     * <b>DOM:</b>  Returns the last child of this node, else null if there
     * are no children.
     */
    final public Node getLastChild ()
    {
	if (length == 0)
	    return null;
	return children [length - 1];
    }

    /** <b>DOM:</b>  Returns the number of children */
    final public int getLength ()
    {
	return length;
    }

    /** <b>DOM:</b>  Returns the Nth child, or null */
    final public Node item (int i)
    {
	if (length == 0 || i >= length)
	    return null;
	try {
	    return children [i];
	} catch (ArrayIndexOutOfBoundsException e) {
	    return null;
	}
    }

    // groups all the "wrong document/implementation" checks
    private NodeBase checkDocument (Node newChild)
    throws DOMException
    {
	if (newChild == null)
	    throw new DomEx (DomEx.HIERARCHY_REQUEST_ERR);

	// check for wrong implementation
	if (!(newChild instanceof NodeBase))
	    throw new DomEx (DomEx.WRONG_DOCUMENT_ERR);

	Document	owner = newChild.getOwnerDocument ();
	XmlDocument	myOwner = ownerDocument;
	NodeBase	child = (NodeBase) newChild;

	// bizarre DOM special case for document
	if (myOwner == null && this instanceof XmlDocument)
	    myOwner = (XmlDocument) this;

	// check for wrong document
	if (owner != null && owner != myOwner)
	    throw new DomEx (DomEx.WRONG_DOCUMENT_ERR);
	
	// permit "unowned" NodeBase children to be added,
	// e.g. if someone constructs an ElementNode directly
	if (owner == null) {
	    child.setOwnerDocument (myOwner);
	}

        if (child.hasChildNodes ()) {
    	    for (int i = 0; true; i++) {
	        Node	node = child.item (i);
	        if (node == null)
		    break;
	        if (node.getOwnerDocument () == null)
	    	    ((NodeBase)node).setOwnerDocument (myOwner);
	        else if (node.getOwnerDocument () != myOwner)
		    throw new DomEx (DomEx.WRONG_DOCUMENT_ERR);
	    }
        }

	return child;
    }

    // makes sure that child isn't an ancestor of this
    private void checkNotAncestor (Node newChild) throws DOMException
    {
	// text, etc ...
	if (!newChild.hasChildNodes ())
	    return;

	Node	ancestor = this;

	while (ancestor != null) {
	    if (newChild == ancestor)
		throw new DomEx (DomEx.HIERARCHY_REQUEST_ERR);
	    ancestor = ancestor.getParentNode ();
	}
    }

    // update mutation count 
    private void mutated ()
    {
	XmlDocument doc = ownerDocument;

	if (doc == null && this instanceof XmlDocument)
	    doc = (XmlDocument) this;
	if (doc != null)
	    doc.mutationCount++;
    }

    //
    // When fragments are appended/inserted/replaced, their entire
    // contents get moved and the fragment becomes empty.
    //
    private void consumeFragment (Node fragment, Node before)
    throws DOMException
    {
	ParentNode	frag = (ParentNode) fragment;
	Node		temp;

	// don't start insertions we can't complete
	for (int i = 0; (temp = frag.item (i)) != null; i++) {
	    checkNotAncestor (temp);
	    checkChildType (temp.getNodeType ());
	}

	while ((temp = frag.item (0)) != null) 
	    insertBefore (temp, before);
    }

    /**
     * <b>DOM:</b>  Appends the child to the set of this node's children.
     * The new child must belong to this document.  
     * 
     * @param newChild the new child to be appended
     */
    public Node appendChild (Node newChild)
    throws DOMException
    {
	NodeBase	child;

	if (readonly)
	    throw new DomEx (DomEx.NO_MODIFICATION_ALLOWED_ERR);
	child = checkDocument (newChild);

	if (newChild.getNodeType () == DOCUMENT_FRAGMENT_NODE) {
	    consumeFragment (newChild, null);
	    return newChild;
	}

	checkNotAncestor (newChild);
	checkChildType (child.getNodeType ());

	// this is the only place this vector needs allocating,
	// though it may also need to be grown in insertBefore.
	// most elements have very few children
	if (children == null)
	    children = new NodeBase [3];
	else if (children.length == length) {
	    NodeBase temp [] = new NodeBase [length * 2];
            System.arraycopy (children, 0, temp, 0, length);
	    children = temp;
	}

	child.setParentNode (this, length);
	children [length++] = child;
	mutated ();
	return child;
    }


    /**
     * <b>DOM:</b>  Inserts the new child before the specified child,
     * which if null indicates appending the new child to the
     * current set of children.  The new child must belong to
     * this particular document.
     *
     * @param newChild the new child to be inserted
     * @param refChild node before which newChild is to be inserted
     */
    public Node insertBefore (Node newChild, Node refChild)
    throws DOMException
    {
	NodeBase	child;

	if (readonly)
	    throw new DomEx (DomEx.NO_MODIFICATION_ALLOWED_ERR);
	if (refChild == null) 
	    return appendChild (newChild);
	if (length == 0)
	    throw new DomEx (DomEx.NOT_FOUND_ERR);

	child = checkDocument (newChild);

	if (newChild.getNodeType () == DOCUMENT_FRAGMENT_NODE) {
	    consumeFragment (newChild, refChild);
	    return newChild;
	}

	checkNotAncestor (newChild);
	checkChildType (newChild.getNodeType ());

	// grow array if needed
	if (children.length == length) {
	    NodeBase temp [] = new NodeBase [length * 2];
            System.arraycopy (children, 0, temp, 0, length);
	    children = temp;
	}

	for (int i = 0; i < length; i++) {
	    if (children [i] != refChild)
		continue;
	    child.setParentNode (this, i);
            System.arraycopy (children, i, children, i + 1, length - i);
	    children [i] = child;
	    length++;
	    mutated ();
	    return newChild;
	}

	throw new DomEx (DomEx.NOT_FOUND_ERR);
    }

    /**
     * <b>DOM:</b>  Replaces the specified child with the new node,
     * returning the original child or throwing an exception.
     * The new child must belong to this particular document.
     *
     * @param newChild the new child to be inserted
     * @param refChild node which is to be replaced
     */
    public Node replaceChild (Node newChild, Node refChild)
    throws DOMException
    {
	NodeBase	child;

	if (readonly)
	    throw new DomEx (DomEx.NO_MODIFICATION_ALLOWED_ERR);
	if (newChild == null || refChild == null)
	    throw new DomEx (DomEx.HIERARCHY_REQUEST_ERR);
	if (children == null)
	    throw new DomEx (DomEx.NOT_FOUND_ERR);

	child = checkDocument (newChild);

	if (newChild.getNodeType () == DOCUMENT_FRAGMENT_NODE) {
	    consumeFragment (newChild, refChild);
	    return removeChild (refChild);
	}

	checkNotAncestor (newChild);
	checkChildType (newChild.getNodeType ());

	for (int i = 0; i < length; i++) {
	    if (children [i] != refChild)
		continue;
	    child.setParentNode (this, i);
	    children [i] = child;
	    ((NodeBase) refChild).setParentNode (null, -1);
	    mutated ();
	    return refChild;
	}
	throw new DomEx (DomEx.NOT_FOUND_ERR);
    }


    /**
     * <b>DOM:</b>  removes child if present, returning argument.
     *
     * @param oldChild the node which is to be removed
     */
    public Node removeChild (Node oldChild)
    throws DOMException
    {
	NodeBase	child;

	if (readonly)
	    throw new DomEx (DomEx.NO_MODIFICATION_ALLOWED_ERR);
	if (!(oldChild instanceof NodeBase))
	    throw new DomEx (DomEx.NOT_FOUND_ERR);
	child = (NodeBase) oldChild;
	for (int i = 0; i < length; i++) {
	    if (children [i] != child)
		continue;
	    if ((i + 1) != length)
		System.arraycopy (children, i + 1, children, i,
		    (length - 1) - i);
	    length--;
	    children [length] = null;
	    child.setParentNode (null, -1);
	    mutated ();
	    return oldChild;
	}
	throw new DomEx (DomEx.NOT_FOUND_ERR);
    }


    /**
     * <b>DOM:</b>  Returns a "live" list view of the elements below this
     * one which have the specified tag name.  Because this is "live", this
     * API is dangerous -- indices are not stable in the face of most tree
     * updates.  Use a TreeWalker instead.
     *
     * @param tagname the tag name to show; or "*" for all elements.
     * @return list of such elements
     */
    public NodeList getElementsByTagName (String tagname)
    {
	if ("*".equals (tagname))
	    tagname = null;
	return new TagList (tagname); 
    }

    /**
     * @since DOM Level 2
     */
    public NodeList getElementsByTagNameNS(String namespaceURI,
                                           String localName) {
	if ("*".equals(namespaceURI)) {
	    namespaceURI = null;
        }
	if ("*".equals(localName)) {
	    localName = null;
        }
	return new TagListNS(namespaceURI, localName); 
    }

    //
    // Slightly optimized to track document mutation count.  For now
    // we assume that a 32 bit counter won't wrap around, and that
    // there's no point in caching list length.
    //
    class TagList implements NodeList {
	protected String        tag;

	protected int		lastMutationCount;
	protected int		lastIndex;
	protected TreeWalker	lastWalker;

	protected int getLastMutationCount() {
	    XmlDocument doc = (XmlDocument) getOwnerDocument ();
	    return (doc == null) ? 0 : doc.mutationCount;
	}

	TagList (String tag) { this.tag = tag; }

	public Node	item (int i)
	{
	    if (i < 0)
		return null;

	    int temp = getLastMutationCount ();

	    // Can we try to reuse the last walker?
	    if (lastWalker != null) {
		if (i < lastIndex || temp != lastMutationCount)
		    lastWalker = null;
	    }

	    // if not, get a new one ...
	    if (lastWalker == null) {
		lastWalker = new TreeWalker (ParentNode.this);
		lastIndex = -1;
		lastMutationCount = temp;
	    }

	    if (i == lastIndex)
		return lastWalker.getCurrent ();

	    Node	node = null;

	    while (i > lastIndex
		    && (node = lastWalker.getNextElement (tag)) != null)
		lastIndex++;
	    return node;
	}

	public int	getLength ()
	{
	    TreeWalker	walker = new TreeWalker (ParentNode.this);
	    Node	node = null;
	    int		retval;

	    for (retval = 0;
		    (node = walker.getNextElement (tag)) != null;
		    retval++)
		continue;
	    return retval;
	}
    }

    // Namespace version
    // XXX Ugly: much code in common with superclass
    class TagListNS extends TagList {
	private String		namespaceURI;

	TagListNS(String namespaceURI, String tag) {
            super(tag);
            this.namespaceURI = namespaceURI;
        }

	public Node item(int i)	{
	    if (i < 0) {
		return null;
            }

	    int temp = getLastMutationCount();

	    // Can we try to reuse the last walker?
	    if (lastWalker != null) {
		if (i < lastIndex || temp != lastMutationCount) {
		    lastWalker = null;
                }
	    }

	    // if not, get a new one ...
	    if (lastWalker == null) {
		lastWalker = new TreeWalker(ParentNode.this);
		lastIndex = -1;
		lastMutationCount = temp;
	    }

	    if (i == lastIndex) {
		return lastWalker.getCurrent();
            }

	    Node node = null;

	    while (i > lastIndex
                   && (node = lastWalker.getNextElement(namespaceURI, tag))
                   != null) {
		lastIndex++;
            }
	    return node;
	}

	public int getLength() {
	    TreeWalker walker = new TreeWalker(ParentNode.this);
            int count;
	    for (count = 0; walker.getNextElement(namespaceURI, tag) != null;
                 count++) {
                // noop
            }
	    return count;
	}
    }


    /**
     * Returns the index of the node in the list of children, such
     * that <em>item()</em> will return that child.
     *
     * @param maybeChild the node which may be a child of this one
     * @return the index of the node in the set of children, or
     *	else -1 if that node is not a child
     */
    final public int getIndexOf (Node maybeChild)
    {
	for (int i = 0; i < length; i++)
	    if (children [i] == maybeChild)
		return i;
	return -1;
    }


    /**
     * @since DOM Level 2
     * In DOM2, normalize() was generalized and got moved to Node.
     *
     * XXX Comments below are old:
     * <b>DOM2:</b> Merges all adjacent Text nodes in the tree rooted by this
     * element.  Avoid using this on large blocks of text not separated
     * by markup such as elements or processing instructions, since it
     * can require arbitrarily large blocks of contiguous memory.
     *
     * <P> As a compatible extension to DOM, this normalizes treatment
     * of whitespace except when the <em>xml:space='preserve'</em>
     * attribute value applies to a node.  All whitespace is normalized
     * to one space.  This ensures that text which is pretty-printed and
     * then reread (and normalized) retains the same content. </P>
     */
    public void normalize() {
	boolean	preserve = false;
	boolean	knowPreserve = false;

	if (readonly) {
	    throw new DomEx (DomEx.NO_MODIFICATION_ALLOWED_ERR);
        }

	for (int i = 0; true; i++) {
            Node node = item(i);
	    if (node == null) {
		break;
            }
	    switch (node.getNodeType()) {
            case ELEMENT_NODE:
		((Element)node).normalize ();
		continue;
                // case CDATA_SECTION_NODE:
            case TEXT_NODE: {
                Node node2 = item(i + 1);
                if (node2 == null || node2.getNodeType() != TEXT_NODE) {
                    // See if xml:space='preserve' is set...
                    if (!knowPreserve) {
                        preserve = "preserve".equals(
                            getInheritedAttribute("xml:space"));
                        knowPreserve = true;
                    }

                    // ... and if not, normalize whitespace
                    if (!preserve) {
                        char[] buf = ((TextNode)node).data;

                        // XXX this isn't supposed to happen
                        if (buf == null || buf.length == 0) {
                            removeChild(node);
                            i--;
                            continue;
                        }

                        int current = removeWhiteSpaces(buf);

                        // compact if it shrank
                        if (current != buf.length) {
                            char[] tmp = new char[current];
                            System.arraycopy(buf, 0, tmp, 0, current);
                            ((TextNode)node).data = tmp;
                        }
                    }
                    continue;
                }
		    
                ((TextNode) node).joinNextText();
                i--;
                continue;
            }
            default:
		continue;
	    }
	}
    }

    /*
     * removes white leading, trailing and extra white spaces from the buffer.
     * returns the size of the new buf after the white spaces are removed.
     */
    public int removeWhiteSpaces(char[] buf) {
        int current = 0;
        int j = 0;

        // copy to beginning, normalizing whitespace
        // (including leading, trailing) to one space
        while (j < buf.length) {
            boolean sawSpace = false;
            char c = buf[j++];

            if (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
                c = ' ';
                sawSpace = true;
            }
            buf[current++] = c;
            if (sawSpace) {
                while (j < buf.length) {
                    c = buf[j];
                    if (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
                        j++;
                        continue;
                    } else {
                        break;
                    }
                }
            }
        }
        return current;
    }
}
