/*
 * Copyright 1999-2004 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */


package javax.naming.directory;

import java.util.Hashtable;
import java.util.Enumeration;

import javax.naming.NamingException;
import javax.naming.NamingEnumeration;

/**
  * This class provides a basic implementation
  * of the Attributes interface.
  *<p>
  * BasicAttributes is either case-sensitive or case-insensitive (case-ignore).
  * This property is determined at the time the BasicAttributes constructor
  * is called.
  * In a case-insensitive BasicAttributes, the case of its attribute identifiers
  * is ignored when searching for an attribute, or adding attributes.
  * In a case-sensitive BasicAttributes, the case is significant.
  *<p>
  * When the BasicAttributes class needs to create an Attribute, it
  * uses BasicAttribute. There is no other dependency on BasicAttribute.
  *<p>
  * Note that updates to BasicAttributes (such as adding or removing an attribute)
  * does not affect the corresponding representation in the directory.
  * Updates to the directory can only be effected
  * using operations in the DirContext interface.
  *<p>
  * A BasicAttributes instance is not synchronized against concurrent
  * multithreaded access. Multiple threads trying to access and modify
  * a single BasicAttributes instance should lock the object.
  *
  * @author Rosanna Lee
  * @author Scott Seligman
  *
  * @see DirContext#getAttributes
  * @see DirContext#modifyAttributes
  * @see DirContext#bind
  * @see DirContext#rebind
  * @see DirContext#createSubcontext
  * @see DirContext#search
  * @since 1.3
  */

public class BasicAttributes implements Attributes {
    /**
     * Indicates whether case of attribute ids is ignored.
     * @serial
     */
    private boolean ignoreCase = false;

    // The 'key' in attrs is stored in the 'right case'.
    // If ignoreCase is true, key is aways lowercase.
    // If ignoreCase is false, key is stored as supplied by put().
    // %%% Not declared "private" due to bug 4064984.
    transient Hashtable attrs = new Hashtable(11);

    /**
      * Constructs a new instance of Attributes.
      * The character case of attribute identifiers
      * is significant when subsequently retrieving or adding attributes.
      */
    public BasicAttributes() {
    }

    /**
      * Constructs a new instance of Attributes.
      * If <code>ignoreCase</code> is true, the character case of attribute
      * identifiers is ignored; otherwise the case is significant.
      * @param ignoreCase true means this attribute set will ignore
      *                   the case of its attribute identifiers
      *                   when retrieving or adding attributes;
      *                   false means case is respected.
      */
    public BasicAttributes(boolean ignoreCase) {
        this.ignoreCase = ignoreCase;
    }

    /**
      * Constructs a new instance of Attributes with one attribute.
      * The attribute specified by attrID and val are added to the newly
      * created attribute.
      * The character case of attribute identifiers
      * is significant when subsequently retrieving or adding attributes.
      * @param attrID   non-null The id of the attribute to add.
      * @param val The value of the attribute to add. If null, a null
      *        value is added to the attribute.
      */
    public BasicAttributes(String attrID, Object val) {
        this();
        this.put(new BasicAttribute(attrID, val));
    }

    /**
      * Constructs a new instance of Attributes with one attribute.
      * The attribute specified by attrID and val are added to the newly
      * created attribute.
      * If <code>ignoreCase</code> is true, the character case of attribute
      * identifiers is ignored; otherwise the case is significant.
      * @param attrID   non-null The id of the attribute to add.
      *           If this attribute set ignores the character
      *           case of its attribute ids, the case of attrID
      *           is ignored.
      * @param val The value of the attribute to add. If null, a null
      *        value is added to the attribute.
      * @param ignoreCase true means this attribute set will ignore
      *                   the case of its attribute identifiers
      *                   when retrieving or adding attributes;
      *                   false means case is respected.
      */
    public BasicAttributes(String attrID, Object val, boolean ignoreCase) {
        this(ignoreCase);
        this.put(new BasicAttribute(attrID, val));
    }

    public Object clone() {
        BasicAttributes attrset;
        try {
            attrset = (BasicAttributes)super.clone();
        } catch (CloneNotSupportedException e) {
            attrset = new BasicAttributes(ignoreCase);
        }
        attrset.attrs = (Hashtable)attrs.clone();
        return attrset;
    }

    public boolean isCaseIgnored() {
        return ignoreCase;
    }

    public int size() {
        return attrs.size();
    }

    public Attribute get(String attrID) {
        Attribute attr = (Attribute) attrs.get(
                ignoreCase ? attrID.toLowerCase() : attrID);
        return (attr);
    }

    public NamingEnumeration<Attribute> getAll() {
        return new AttrEnumImpl();
    }

    public NamingEnumeration<String> getIDs() {
        return new IDEnumImpl();
    }

    public Attribute put(String attrID, Object val) {
        return this.put(new BasicAttribute(attrID, val));
    }

    public Attribute put(Attribute attr) {
        String id = attr.getID();
        if (ignoreCase) {
            id = id.toLowerCase();
        }
        return (Attribute)attrs.put(id, attr);
    }

    public Attribute remove(String attrID) {
        String id = (ignoreCase ? attrID.toLowerCase() : attrID);
        return (Attribute)attrs.remove(id);
    }

    /**
     * Generates the string representation of this attribute set.
     * The string consists of each attribute identifier and the contents
     * of each attribute. The contents of this string is useful
     * for debugging and is not meant to be interpreted programmatically.
     *
     * @return A non-null string listing the contents of this attribute set.
     */
    public String toString() {
        if (attrs.size() == 0) {
            return("No attributes");
        } else {
            return attrs.toString();
        }
    }

    /**
     * Determines whether this <tt>BasicAttributes</tt> is equal to another
     * <tt>Attributes</tt>
     * Two <tt>Attributes</tt> are equal if they are both instances of
     * <tt>Attributes</tt>,
     * treat the case of attribute IDs the same way, and contain the
     * same attributes. Each <tt>Attribute</tt> in this <tt>BasicAttributes</tt>
     * is checked for equality using <tt>Object.equals()</tt>, which may have
     * be overridden by implementations of <tt>Attribute</tt>).
     * If a subclass overrides <tt>equals()</tt>,
     * it should override <tt>hashCode()</tt>
     * as well so that two <tt>Attributes</tt> instances that are equal
     * have the same hash code.
     * @param obj the possibly null object to compare against.
     *
     * @return true If obj is equal to this BasicAttributes.
     * @see #hashCode
     */
    public boolean equals(Object obj) {
        if ((obj != null) && (obj instanceof Attributes)) {
            Attributes target = (Attributes)obj;

            // Check case first
            if (ignoreCase != target.isCaseIgnored()) {
                return false;
            }

            if (size() == target.size()) {
                Attribute their, mine;
                try {
                    NamingEnumeration theirs = target.getAll();
                    while (theirs.hasMore()) {
                        their = (Attribute)theirs.next();
                        mine = get(their.getID());
                        if (!their.equals(mine)) {
                            return false;
                        }
                    }
                } catch (NamingException e) {
                    return false;
                }
                return true;
            }
        }
        return false;
    }

    /**
     * Calculates the hash code of this BasicAttributes.
     *<p>
     * The hash code is computed by adding the hash code of
     * the attributes of this object. If this BasicAttributes
     * ignores case of its attribute IDs, one is added to the hash code.
     * If a subclass overrides <tt>hashCode()</tt>,
     * it should override <tt>equals()</tt>
     * as well so that two <tt>Attributes</tt> instances that are equal
     * have the same hash code.
     *
     * @return an int representing the hash code of this BasicAttributes instance.
     * @see #equals
     */
    public int hashCode() {
        int hash = (ignoreCase ? 1 : 0);
        try {
            NamingEnumeration all = getAll();
            while (all.hasMore()) {
                hash += all.next().hashCode();
            }
        } catch (NamingException e) {}
        return hash;
    }

    /**
     * Overridden to avoid exposing implementation details.
     * @serialData Default field (ignoreCase flag -- a boolean), followed by
     * the number of attributes in the set
     * (an int), and then the individual Attribute objects.
     */
    private void writeObject(java.io.ObjectOutputStream s)
            throws java.io.IOException {
        s.defaultWriteObject(); // write out the ignoreCase flag
        s.writeInt(attrs.size());
        Enumeration attrEnum = attrs.elements();
        while (attrEnum.hasMoreElements()) {
            s.writeObject(attrEnum.nextElement());
        }
    }

    /**
     * Overridden to avoid exposing implementation details.
     */
    private void readObject(java.io.ObjectInputStream s)
            throws java.io.IOException, ClassNotFoundException {
        s.defaultReadObject();  // read in the ignoreCase flag
        int n = s.readInt();    // number of attributes
        attrs = (n >= 1)
            ? new Hashtable(n * 2)
            : new Hashtable(2); // can't have initial size of 0 (grrr...)
        while (--n >= 0) {
            put((Attribute)s.readObject());
        }
    }


class AttrEnumImpl implements NamingEnumeration<Attribute> {

    Enumeration<Attribute> elements;

    public AttrEnumImpl() {
        this.elements = attrs.elements();
    }

    public boolean hasMoreElements() {
        return elements.hasMoreElements();
    }

    public Attribute nextElement() {
        return elements.nextElement();
    }

    public boolean hasMore() throws NamingException {
        return hasMoreElements();
    }

    public Attribute next() throws NamingException {
        return nextElement();
    }

    public void close() throws NamingException {
        elements = null;
    }
}

class IDEnumImpl implements NamingEnumeration<String> {

    Enumeration<Attribute> elements;

    public IDEnumImpl() {
        // Walking through the elements, rather than the keys, gives
        // us attribute IDs that have not been converted to lowercase.
        this.elements = attrs.elements();
    }

    public boolean hasMoreElements() {
        return elements.hasMoreElements();
    }

    public String nextElement() {
        Attribute attr = elements.nextElement();
        return attr.getID();
    }

    public boolean hasMore() throws NamingException {
        return hasMoreElements();
    }

    public String next() throws NamingException {
        return nextElement();
    }

    public void close() throws NamingException {
        elements = null;
    }
}

    /**
     * Use serialVersionUID from JNDI 1.1.1 for interoperability.
     */
    private static final long serialVersionUID = 4980164073184639448L;
}
