/*
 * $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.CharArrayWriter;
import java.io.Writer;
import java.io.IOException;
import java.util.Vector;

import org.w3c.dom.*;

import org.xml.sax.AttributeList;
import org.xml.sax.Attributes;
//import org.xml.sax.Attr;

// Should move to use the xerces sax2 Attribute impl
import org.apache.xerces.tree.AttributeListEx;


/**
 * Class representing an XML attribute list.
 *
 * <P> This couples slightly with the Sun XML parser, in that it optionally
 * uses an extended SAX 1.0 API to see if an attribute was specified in the
 * document or was instead defaulted by attribute processing.
 *
 * @author David Brownell
 * @version $Revision$
 */
final
class AttributeSet implements NamedNodeMap, XmlWritable
{
    private boolean	readonly;
    private Vector	list;
    private ElementNode	nameScope;
        
    /* Constructs an attribute list, with associated name scope. */
    // package private
    AttributeSet (ElementNode nameScope)
    {
	list = new Vector (5);
	this.nameScope = nameScope;
    }

    /*
     * Constructs a copy of an attribute list, for use in cloning.
     * name scopes are set separately.
     */
    // package private
    AttributeSet (AttributeSet original, boolean deep)
    {
	int		size = original.getLength ();

	list = new Vector (size);
	for (int i = 0; i < size; i++) {
	    Node	node = original.item (i);

	    if (!(node instanceof AttributeNode))
		throw new IllegalArgumentException (((NodeBase)node).
						getMessage ("A-003"));
	    node = node.cloneNode (deep);

	    // temporarily undo binding to element ... it's rebound
	    // by the caller
	    ((AttributeNode)node).setNameScope (null);
	    list.addElement (node);
	}
    }

    // package private
    AttributeSet (AttributeList source)
    throws DOMException
    {
	int			len = source.getLength ();
	AttributeListEx		ex = null;

	list = new Vector (len);
	if (source instanceof AttributeListEx)
	    ex = (AttributeListEx) source;

	for (int i = 0; i < len; i++) {
	    list.addElement (new AttributeNode (
		    source.getName (i),
		    source.getValue (i),
		    ex == null	// remember if it was specified
			? true
			: ex.isSpecified (i),
		    ex == null	// remember any default value
			? null
			: ex.getDefault (i)
		    ));
	}
	list.trimToSize ();
    }

    /**
     * <b>DOM2:</b> Create DOM NamedNodeMap from SAX2 Attributes object
     */
    AttributeSet(Attributes source) throws DOMException {
	int			len = source.getLength();
	AttributeListEx		ex = null;

	list = new Vector(len);
	if (source instanceof AttributeListEx) { // XXX fix this
	    ex = (AttributeListEx) source;
        }

	for (int i = 0; i < len; i++) {
            // Translate "" of SAX2 to null.  See DOM2 spec under Node
            // namespaceURI
            String uri = source.getURI(i);
            if (uri.equals("")) {
                uri = null;
            }

            AttributeNode attrNode =
                new AttributeNode(uri,
                                  source.getQName(i),
                                  source.getValue(i),
                                  ex == null	// remember if it was specified
                                  ? true
                                  : ex.isSpecified(i),
                                  ex == null	// remember any default value
                                  ? null
                                  : ex.getDefault(i));
	    list.addElement(attrNode);
	}
	list.trimToSize();
    }

    // package private
    void trimToSize () { list.trimToSize (); }

    // package private
    public void setReadonly ()
    {
	readonly = true;
	for (int i = 0; i < list.size (); i++)
	    ((AttributeNode)list.elementAt (i)).setReadonly (true);
    }

    public boolean isReadonly () {
    	if (readonly)
	    return true;
	for (int i = 0; i < list.size (); i++) {
	    if (((AttributeNode)list.elementAt (i)).isReadonly ()) {
	   	return true; 
	    }
	}
	return false;
    }

    // package private
    void setNameScope (ElementNode e)
    {
	if (e != null && nameScope != null)
	    throw new IllegalStateException (e.getMessage ("A-004"));
	nameScope = e;

	// need to bind the attributes to this element
	int	length = list.size ();

	for (int i = 0; i < length; i++) {
	    AttributeNode	node;

	    node = (AttributeNode) list.elementAt (i);
	    node.setNameScope (null);
	    node.setNameScope (e);
	}
    }

    // package private
    ElementNode getNameScope ()
    {
	return nameScope;
    }


    // package private
    String getValue (String name)
    {
	Attr	attr = (Attr) getNamedItem (name);

	if (attr == null)
	    return "";
	else
	    return attr.getValue ();
    }

    public Node getNamedItem (String name)
    {
	int	length = list.size ();
	Node	value;

	for (int i = 0; i < length; i++) {
	    value = item (i);
	    if (value.getNodeName ().equals (name))
		return value;
	}
	return null;
    }

    /**
     * <b>DOM2:</b>
     */
    public Node getNamedItemNS(String namespaceURI, String localName) {
	for (int i = 0; i < list.size(); i++) {
	    Node value = item(i);
            String iLocalName = value.getLocalName();
	    if (iLocalName != null && iLocalName.equals(localName)) {
                String iNamespaceURI = value.getNamespaceURI();
                if (iNamespaceURI != null
                    && iNamespaceURI.equals(namespaceURI)) {
                    return value;
                }
            }
	}
	return null;
    }

    public int getLength ()
    {
	return list.size ();
    }

    public Node item (int index)
    {
	if (index < 0 || index >= list.size ())
	    return null;
	return (Node) list.elementAt (index);
    }

    public Node removeNamedItem (String name)
    throws DOMException
    {
	int		length = list.size ();
	Node		value;

	if (readonly)
	    throw new DomEx (DomEx.NO_MODIFICATION_ALLOWED_ERR);
	for (int i = 0; i < length; i++) {
	    value = item (i);
	    if (value.getNodeName ().equals (name)) {
		AttributeNode	att = (AttributeNode) value;

		if (att.getDefaultValue () != null) {
		    att = new AttributeNode (att);
		    att.setOwnerDocument ((XmlDocument)
			    nameScope.getOwnerDocument ());
		    list.setElementAt (att, i);
		} else
		    list.removeElementAt (i);

		att.setNameScope (null);
		return value;
	    }
	}
	throw new DomEx (DomEx.NOT_FOUND_ERR);
    }

    /**
     * <b>DOM2:</b>
     */
    public Node removeNamedItemNS(String namespaceURI, String localName)
        throws DOMException
    {
	if (readonly) {
	    throw new DomEx(DomEx.NO_MODIFICATION_ALLOWED_ERR);
        }

	for (int i = 0; i < list.size(); i++) {
	    Node value = item(i);
            String iLocalName = value.getLocalName();
	    if (iLocalName != null && iLocalName.equals(localName)) {
                String iNamespaceURI = value.getNamespaceURI();
                if (iNamespaceURI != null
                    && iNamespaceURI.equals(namespaceURI)) {
                    AttributeNode attr = (AttributeNode) value;
                    if (attr.getDefaultValue() != null) {
                        attr = new AttributeNode(attr);
                        list.setElementAt(attr, i);
                    } else {
                        list.removeElementAt(i);
                    }
                    return value;
                }
            }
	}
	throw new DomEx(DomEx.NOT_FOUND_ERR);
    }

    public Node setNamedItem (Node value)
    throws DOMException
    {
	AttributeNode	node;

	if (readonly)
	    throw new DomEx (DomEx.NO_MODIFICATION_ALLOWED_ERR);
	if (!(value instanceof AttributeNode)
		|| value.getOwnerDocument ()
			!= nameScope.getOwnerDocument ())
	    throw new DomEx (DomEx.WRONG_DOCUMENT_ERR);
	node = (AttributeNode)value;
	if (node.getNameScope () != null)
	    throw new DomEx (DomEx.INUSE_ATTRIBUTE_ERR);

	int		length = list.size ();
	AttributeNode	oldValue;

	for (int i = 0; i < length; i++) {
	    oldValue = (AttributeNode) item (i);
	    if (oldValue.getNodeName ().equals (value.getNodeName ())) {
	    	if (oldValue.isReadonly ())
	    	    throw new DomEx (DomEx.NO_MODIFICATION_ALLOWED_ERR);
		node.setNameScope (nameScope);
		list.setElementAt (value, i);
		oldValue.setNameScope (null);
		return oldValue;
	    }
	}
	node.setNameScope (nameScope);
	list.addElement (value);
	return null;
    }
    
    /**
     * <b>DOM2:</b>
     * XXX spec allows Element nodes also, but this code assumes Attr nodes
     * only
     */
    public Node setNamedItemNS(Node arg) throws DOMException {
	if (readonly) {
	    throw new DomEx(DomEx.NO_MODIFICATION_ALLOWED_ERR);
        }

	AttributeNode attr = (AttributeNode) arg;
        if (attr.getOwnerElement() != null) {
	    throw new DomEx(DomEx.INUSE_ATTRIBUTE_ERR);
        }

	for (int i = 0; i < list.size(); i++) {
	    AttributeNode oldNode = (AttributeNode) item(i);
            String localName = oldNode.getLocalName();
            String namespaceURI = oldNode.getNamespaceURI();
            if (arg.getLocalName().equals(localName)
                && arg.getNamespaceURI().equals(namespaceURI)) {
                // Found a matching node so replace it
                list.setElementAt(arg, i);
                return oldNode;
            }
	}

        // Append instead of replace
	list.addElement(arg);
	return null;
    }

    /**
     * Writes out the attribute list.  Attributes known to have been
     * derived from the DTD are not (at this time) written out.  Part
     * of writing standalone XML is first ensuring that all attributes
     * are flagged as being specified in the "printed" form (or else
     * are defaulted only in the internal DTD subset).
     */
    public void writeXml (XmlWriteContext context) throws IOException
    {
	Writer		out = context.getWriter ();
	int		length = list.size ();
	AttributeNode	tmp;

	for (int i = 0; i < length; i++) {
	    tmp = (AttributeNode) list.elementAt (i);
	    if (tmp.getSpecified ()) {
		out.write (' ');
		tmp.writeXml (context);
	    }
	}
    }

    /**
     * Does nothing; this type of node has no children.
     */
    public void writeChildrenXml (XmlWriteContext context) throws IOException
    {
    }

    public String toString ()
    {
	try {
	    CharArrayWriter w = new CharArrayWriter ();
	    XmlWriteContext x = new XmlWriteContext (w);
	    writeXml (x);
	    return w.toString ();

	} catch (IOException e) {
	    return super.toString ();
	}
    }
}
