/*
 * reserved comment block
 * DO NOT REMOVE OR ALTER!
 */
/*
 * Copyright 2000-2002,2004 The Apache Software Foundation.
 *
 * Licensed 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.
 */

package com.sun.org.apache.xerces.internal.dom;

import java.util.ArrayList;
import java.util.List;

import org.w3c.dom.DOMException;
import org.w3c.dom.Node;

/**
 * AttributeMap inherits from NamedNodeMapImpl and extends it to deal with the
 * specifics of storing attributes. These are:
 * <ul>
 *  <li>managing ownership of attribute nodes
 *  <li>managing default attributes
 *  <li>firing mutation events
 * </ul>
 * <p>
 * This class doesn't directly support mutation events, however, it notifies
 * the document when mutations are performed so that the document class do so.
 *
 * @xerces.internal
 *
 * @version $Id: AttributeMap.java,v 1.7 2010-11-01 04:39:37 joehw Exp $
 */
public class AttributeMap extends NamedNodeMapImpl {

    /** Serialization version. */
    static final long serialVersionUID = 8872606282138665383L;

    //
    // Constructors
    //

    /** Constructs a named node map. */
    protected AttributeMap(ElementImpl ownerNode, NamedNodeMapImpl defaults) {
        super(ownerNode);
        if (defaults != null) {
            // initialize map with the defaults
            cloneContent(defaults);
            if (nodes != null) {
                hasDefaults(true);
            }
        }
    }

    /**
     * Adds an attribute using its nodeName attribute.
     * @see org.w3c.dom.NamedNodeMap#setNamedItem
     * @return If the new Node replaces an existing node the replaced Node is
     *      returned, otherwise null is returned.
     * @param arg
     *      An Attr node to store in this map.
     * @exception org.w3c.dom.DOMException The exception description.
     */
    public Node setNamedItem(Node arg)
    throws DOMException {

        boolean errCheck = ownerNode.ownerDocument().errorChecking;
        if (errCheck) {
            if (isReadOnly()) {
                String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
                throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
            }
            if (arg.getOwnerDocument() != ownerNode.ownerDocument()) {
                String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null);
                throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, msg);
            }
            if (arg.getNodeType() != Node.ATTRIBUTE_NODE) {
                String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "HIERARCHY_REQUEST_ERR", null);
                throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, msg);
            }
        }
        AttrImpl argn = (AttrImpl)arg;

        if (argn.isOwned()){
            if (errCheck && argn.getOwnerElement() != ownerNode) {
                String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INUSE_ATTRIBUTE_ERR", null);
                throw new DOMException(DOMException.INUSE_ATTRIBUTE_ERR, msg);
            }
            // replacing an Attribute with itself does nothing
            return arg;
        }


        // set owner
        argn.ownerNode = ownerNode;
        argn.isOwned(true);

        int i = findNamePoint(argn.getNodeName(),0);
        AttrImpl previous = null;
        if (i >= 0) {
            previous = (AttrImpl) nodes.get(i);
            nodes.set(i, arg);
            previous.ownerNode = ownerNode.ownerDocument();
            previous.isOwned(false);
            // make sure it won't be mistaken with defaults in case it's reused
            previous.isSpecified(true);
        } else {
            i = -1 - i; // Insert point (may be end of list)
            if (null == nodes) {
                nodes = new ArrayList(5);
            }
            nodes.add(i, arg);
        }

        // notify document
        ownerNode.ownerDocument().setAttrNode(argn, previous);

        // If the new attribute is not normalized,
        // the owning element is inherently not normalized.
        if (!argn.isNormalized()) {
            ownerNode.isNormalized(false);
        }
        return previous;

    } // setNamedItem(Node):Node

    /**
     * Adds an attribute using its namespaceURI and localName.
     * @see org.w3c.dom.NamedNodeMap#setNamedItem
     * @return If the new Node replaces an existing node the replaced Node is
     *      returned, otherwise null is returned.
     * @param arg A node to store in a named node map.
     */
    public Node setNamedItemNS(Node arg)
    throws DOMException {

        boolean errCheck = ownerNode.ownerDocument().errorChecking;
        if (errCheck) {
            if (isReadOnly()) {
                String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
                throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
            }
            if(arg.getOwnerDocument() != ownerNode.ownerDocument()) {
                String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null);
                throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, msg);
            }
            if (arg.getNodeType() != Node.ATTRIBUTE_NODE) {
                String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "HIERARCHY_REQUEST_ERR", null);
                throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, msg);
            }
        }
        AttrImpl argn = (AttrImpl)arg;

        if (argn.isOwned()){
            if (errCheck && argn.getOwnerElement() != ownerNode) {
                String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INUSE_ATTRIBUTE_ERR", null);
                throw new DOMException(DOMException.INUSE_ATTRIBUTE_ERR, msg);
            }
            // replacing an Attribute with itself does nothing
            return arg;
        }

        // set owner
        argn.ownerNode = ownerNode;
        argn.isOwned(true);

        int i = findNamePoint(argn.getNamespaceURI(), argn.getLocalName());
        AttrImpl previous = null;
        if (i >= 0) {
            previous = (AttrImpl) nodes.get(i);
            nodes.set(i, arg);
            previous.ownerNode = ownerNode.ownerDocument();
            previous.isOwned(false);
            // make sure it won't be mistaken with defaults in case it's reused
            previous.isSpecified(true);
        } else {
            // If we can't find by namespaceURI, localName, then we find by
            // nodeName so we know where to insert.
            i = findNamePoint(arg.getNodeName(),0);
            if (i >=0) {
                previous = (AttrImpl) nodes.get(i);
                nodes.add(i, arg);
            } else {
                i = -1 - i; // Insert point (may be end of list)
                if (null == nodes) {
                    nodes = new ArrayList(5);
                }
                nodes.add(i, arg);
            }
        }
        //      changed(true);

        // notify document
        ownerNode.ownerDocument().setAttrNode(argn, previous);

        // If the new attribute is not normalized,
        // the owning element is inherently not normalized.
        if (!argn.isNormalized()) {
            ownerNode.isNormalized(false);
        }
        return previous;

    } // setNamedItemNS(Node):Node

    /**
     * Removes an attribute specified by name.
     * @param name
     *      The name of a node to remove. If the
     *      removed attribute is known to have a default value, an
     *      attribute immediately appears containing the default value
     *      as well as the corresponding namespace URI, local name,
     *      and prefix when applicable.
     * @return The node removed from the map if a node with such a name exists.
     * @throws              NOT_FOUND_ERR: Raised if there is no node named
     *                      name in the map.
     */
    /***/
    public Node removeNamedItem(String name)
        throws DOMException {
        return internalRemoveNamedItem(name, true);
    }

    /**
     * Same as removeNamedItem except that it simply returns null if the
     * specified name is not found.
     */
    Node safeRemoveNamedItem(String name) {
        return internalRemoveNamedItem(name, false);
    }


    /**
     * NON-DOM: Remove the node object
     *
     * NOTE: Specifically removes THIS NODE -- not the node with this
     * name, nor the node with these contents. If node does not belong to
     * this named node map, we throw a DOMException.
     *
     * @param item       The node to remove
     * @param addDefault true -- magically add default attribute
     * @return Removed node
     * @exception DOMException
     */
    protected Node removeItem(Node item, boolean addDefault)
        throws DOMException {

        int index = -1;
        if (nodes != null) {
            final int size = nodes.size();
            for (int i = 0; i < size; ++i) {
                if (nodes.get(i) == item) {
                    index = i;
                    break;
                }
            }
        }
        if (index < 0) {
            String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR", null);
            throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
        }

        return remove((AttrImpl)item, index, addDefault);
    }

    /**
     * Internal removeNamedItem method allowing to specify whether an exception
     * must be thrown if the specified name is not found.
     */
    final protected Node internalRemoveNamedItem(String name, boolean raiseEx){
        if (isReadOnly()) {
                String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
                throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
        }
        int i = findNamePoint(name,0);
        if (i < 0) {
            if (raiseEx) {
                String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR", null);
                throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
            } else {
                return null;
            }
        }

        return remove((AttrImpl)nodes.get(i), i, true);

    } // internalRemoveNamedItem(String,boolean):Node

    private final Node remove(AttrImpl attr, int index,
                              boolean addDefault) {

        CoreDocumentImpl ownerDocument = ownerNode.ownerDocument();
        String name = attr.getNodeName();
        if (attr.isIdAttribute()) {
            ownerDocument.removeIdentifier(attr.getValue());
        }

        if (hasDefaults() && addDefault) {
            // If there's a default, add it instead
            NamedNodeMapImpl defaults =
                ((ElementImpl) ownerNode).getDefaultAttributes();

            Node d;
            if (defaults != null &&
                (d = defaults.getNamedItem(name)) != null &&
                findNamePoint(name, index+1) < 0) {
                    NodeImpl clone = (NodeImpl)d.cloneNode(true);
                    if (d.getLocalName() !=null){
                            // we must rely on the name to find a default attribute
                            // ("test:attr"), but while copying it from the DOCTYPE
                            // we should not loose namespace URI that was assigned
                            // to the attribute in the instance document.
                            ((AttrNSImpl)clone).namespaceURI = attr.getNamespaceURI();
                    }
                    clone.ownerNode = ownerNode;
                    clone.isOwned(true);
                    clone.isSpecified(false);

                    nodes.set(index, clone);
                    if (attr.isIdAttribute()) {
                        ownerDocument.putIdentifier(clone.getNodeValue(),
                                                (ElementImpl)ownerNode);
                    }
            } else {
                nodes.remove(index);
            }
        } else {
            nodes.remove(index);
        }

        //        changed(true);

        // remove reference to owner
        attr.ownerNode = ownerDocument;
        attr.isOwned(false);

        // make sure it won't be mistaken with defaults in case it's
        // reused
        attr.isSpecified(true);
        attr.isIdAttribute(false);

        // notify document
        ownerDocument.removedAttrNode(attr, ownerNode, name);

        return attr;
    }

    /**
     * Introduced in DOM Level 2. <p>
     * Removes an attribute specified by local name and namespace URI.
     * @param namespaceURI
     *                      The namespace URI of the node to remove.
     *                      When it is null or an empty string, this
     *                      method behaves like removeNamedItem.
     * @param name          The local name of the node to remove. If the
     *                      removed attribute is known to have a default
     *                      value, an attribute immediately appears
     *                      containing the default value.
     * @return Node         The node removed from the map if a node with such
     *                      a local name and namespace URI exists.
     * @throws              NOT_FOUND_ERR: Raised if there is no node named
     *                      name in the map.
     */
    public Node removeNamedItemNS(String namespaceURI, String name)
        throws DOMException {
        return internalRemoveNamedItemNS(namespaceURI, name, true);
    }

    /**
     * Same as removeNamedItem except that it simply returns null if the
     * specified local name and namespace URI is not found.
     */
    Node safeRemoveNamedItemNS(String namespaceURI, String name) {
        return internalRemoveNamedItemNS(namespaceURI, name, false);
    }

    /**
     * Internal removeNamedItemNS method allowing to specify whether an
     * exception must be thrown if the specified local name and namespace URI
     * is not found.
     */
    final protected Node internalRemoveNamedItemNS(String namespaceURI,
            String name,
            boolean raiseEx) {

        CoreDocumentImpl ownerDocument = ownerNode.ownerDocument();
        if (ownerDocument.errorChecking && isReadOnly()) {
            String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
            throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
        }
        int i = findNamePoint(namespaceURI, name);
        if (i < 0) {
            if (raiseEx) {
                String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR", null);
                throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
            } else {
                return null;
            }
        }

        AttrImpl n = (AttrImpl)nodes.get(i);

        if (n.isIdAttribute()) {
            ownerDocument.removeIdentifier(n.getValue());
        }
        // If there's a default, add it instead
        String nodeName = n.getNodeName();
        if (hasDefaults()) {
            NamedNodeMapImpl defaults = ((ElementImpl) ownerNode).getDefaultAttributes();
            Node d;
            if (defaults != null
                    && (d = defaults.getNamedItem(nodeName)) != null)
            {
                int j = findNamePoint(nodeName,0);
                if (j>=0 && findNamePoint(nodeName, j+1) < 0) {
                    NodeImpl clone = (NodeImpl)d.cloneNode(true);
                    clone.ownerNode = ownerNode;
                    if (d.getLocalName() != null) {
                        // we must rely on the name to find a default attribute
                        // ("test:attr"), but while copying it from the DOCTYPE
                        // we should not loose namespace URI that was assigned
                        // to the attribute in the instance document.
                        ((AttrNSImpl)clone).namespaceURI = namespaceURI;
                    }
                    clone.isOwned(true);
                    clone.isSpecified(false);
                    nodes.set(i, clone);
                    if (clone.isIdAttribute()) {
                        ownerDocument.putIdentifier(clone.getNodeValue(),
                                (ElementImpl)ownerNode);
                    }
                } else {
                    nodes.remove(i);
                }
            } else {
                nodes.remove(i);
            }
        } else {
            nodes.remove(i);
        }

        //        changed(true);

        // remove reference to owner
        n.ownerNode = ownerDocument;
        n.isOwned(false);
        // make sure it won't be mistaken with defaults in case it's
        // reused
        n.isSpecified(true);
        // update id table if needed
        n.isIdAttribute(false);

        // notify document
        ownerDocument.removedAttrNode(n, ownerNode, name);

        return n;

    } // internalRemoveNamedItemNS(String,String,boolean):Node

    //
    // Public methods
    //

    /**
     * Cloning a NamedNodeMap is a DEEP OPERATION; it always clones
     * all the nodes contained in the map.
     */

    public NamedNodeMapImpl cloneMap(NodeImpl ownerNode) {
        AttributeMap newmap =
            new AttributeMap((ElementImpl) ownerNode, null);
        newmap.hasDefaults(hasDefaults());
        newmap.cloneContent(this);
        return newmap;
    } // cloneMap():AttributeMap

    /**
     * Override parent's method to set the ownerNode correctly
     */
    protected void cloneContent(NamedNodeMapImpl srcmap) {
        List srcnodes = srcmap.nodes;
        if (srcnodes != null) {
            int size = srcnodes.size();
            if (size != 0) {
                if (nodes == null) {
                    nodes = new ArrayList(size);
                }
                else {
                    nodes.clear();
                }
                for (int i = 0; i < size; ++i) {
                    NodeImpl n = (NodeImpl) srcnodes.get(i);
                    NodeImpl clone = (NodeImpl) n.cloneNode(true);
                    clone.isSpecified(n.isSpecified());
                    nodes.add(clone);
                    clone.ownerNode = ownerNode;
                    clone.isOwned(true);
                }
            }
        }
    } // cloneContent():AttributeMap


    /**
     * Move specified attributes from the given map to this one
     */
    void moveSpecifiedAttributes(AttributeMap srcmap) {
        int nsize = (srcmap.nodes != null) ? srcmap.nodes.size() : 0;
        for (int i = nsize - 1; i >= 0; i--) {
            AttrImpl attr = (AttrImpl) srcmap.nodes.get(i);
            if (attr.isSpecified()) {
                srcmap.remove(attr, i, false);
                if (attr.getLocalName() != null) {
                    setNamedItem(attr);
                }
                else {
                    setNamedItemNS(attr);
                }
            }
        }
    } // moveSpecifiedAttributes(AttributeMap):void


    /**
     * Get this AttributeMap in sync with the given "defaults" map.
     * @param defaults The default attributes map to sync with.
     */
    protected void reconcileDefaults(NamedNodeMapImpl defaults) {

        // remove any existing default
        int nsize = (nodes != null) ? nodes.size() : 0;
        for (int i = nsize - 1; i >= 0; --i) {
            AttrImpl attr = (AttrImpl) nodes.get(i);
            if (!attr.isSpecified()) {
                remove(attr, i, false);
            }
        }
        // add the new defaults
        if (defaults == null) {
            return;
        }
        if (nodes == null || nodes.size() == 0) {
            cloneContent(defaults);
        }
        else {
            int dsize = defaults.nodes.size();
            for (int n = 0; n < dsize; ++n) {
                AttrImpl d = (AttrImpl) defaults.nodes.get(n);
                int i = findNamePoint(d.getNodeName(), 0);
                if (i < 0) {
                        i = -1 - i;
                    NodeImpl clone = (NodeImpl) d.cloneNode(true);
                    clone.ownerNode = ownerNode;
                    clone.isOwned(true);
                    clone.isSpecified(false);
                        nodes.add(i, clone);
                }
            }
        }

    } // reconcileDefaults()

    protected final int addItem (Node arg) {

        final AttrImpl argn = (AttrImpl) arg;

        // set owner
        argn.ownerNode = ownerNode;
        argn.isOwned(true);

        int i = findNamePoint(argn.getNamespaceURI(), argn.getLocalName());
        if (i >= 0) {
            nodes.set(i, arg);
        }
        else {
            // If we can't find by namespaceURI, localName, then we find by
            // nodeName so we know where to insert.
            i = findNamePoint(argn.getNodeName(),0);
            if (i >= 0) {
                nodes.add(i, arg);
            }
            else {
                i = -1 - i; // Insert point (may be end of list)
                if (null == nodes) {
                    nodes = new ArrayList(5);
                }
                nodes.add(i, arg);
            }
        }

        // notify document
        ownerNode.ownerDocument().setAttrNode(argn, null);
        return i;
    }

} // class AttributeMap
