/*
 * Copyright 2003-2006 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.swing;

import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Enumeration;
import java.util.Hashtable;

/*
 * Private storage mechanism for Action key-value pairs.
 * In most cases this will be an array of alternating
 * key-value pairs.  As it grows larger it is scaled
 * up to a Hashtable.
 * <p>
 * This does no synchronization, if you need thread safety synchronize on
 * another object before calling this.
 *
 * @author Georges Saab
 * @author Scott Violet
 */
class ArrayTable implements Cloneable {
    // Our field for storage
    private Object table = null;
    private static final int ARRAY_BOUNDARY = 8;


    /**
     * Writes the passed in ArrayTable to the passed in ObjectOutputStream.
     * The data is saved as an integer indicating how many key/value
     * pairs are being archived, followed by the the key/value pairs. If
     * <code>table</code> is null, 0 will be written to <code>s</code>.
     * <p>
     * This is a convenience method that ActionMap/InputMap and
     * AbstractAction use to avoid having the same code in each class.
     */
    static void writeArrayTable(ObjectOutputStream s, ArrayTable table) throws IOException {
        Object keys[];

        if (table == null || (keys = table.getKeys(null)) == null) {
            s.writeInt(0);
        }
        else {
            // Determine how many keys have Serializable values, when
            // done all non-null values in keys identify the Serializable
            // values.
            int validCount = 0;

            for (int counter = 0; counter < keys.length; counter++) {
                Object key = keys[counter];

                /* include in Serialization when both keys and values are Serializable */
                if (    (key instanceof Serializable
                         && table.get(key) instanceof Serializable)
                             ||
                         /* include these only so that we get the appropriate exception below */
                        (key instanceof ClientPropertyKey
                         && ((ClientPropertyKey)key).getReportValueNotSerializable())) {

                    validCount++;
                } else {
                    keys[counter] = null;
                }
            }
            // Write ou the Serializable key/value pairs.
            s.writeInt(validCount);
            if (validCount > 0) {
                for (int counter = 0; counter < keys.length; counter++) {
                    if (keys[counter] != null) {
                        s.writeObject(keys[counter]);
                        s.writeObject(table.get(keys[counter]));
                        if (--validCount == 0) {
                            break;
                        }
                    }
                }
            }
        }
    }


    /*
     * Put the key-value pair into storage
     */
    public void put(Object key, Object value){
        if (table==null) {
            table = new Object[] {key, value};
        } else {
            int size = size();
            if (size < ARRAY_BOUNDARY) {              // We are an array
                if (containsKey(key)) {
                    Object[] tmp = (Object[])table;
                    for (int i = 0; i<tmp.length-1; i+=2) {
                        if (tmp[i].equals(key)) {
                            tmp[i+1]=value;
                            break;
                        }
                    }
                } else {
                    Object[] array = (Object[])table;
                    int i = array.length;
                    Object[] tmp = new Object[i+2];
                    System.arraycopy(array, 0, tmp, 0, i);

                    tmp[i] = key;
                    tmp[i+1] = value;
                    table = tmp;
                }
            } else {                 // We are a hashtable
                if ((size==ARRAY_BOUNDARY) && isArray()) {
                    grow();
                }
                ((Hashtable)table).put(key, value);
            }
        }
    }

    /*
     * Gets the value for key
     */
    public Object get(Object key) {
        Object value = null;
        if (table !=null) {
            if (isArray()) {
                Object[] array = (Object[])table;
                for (int i = 0; i<array.length-1; i+=2) {
                    if (array[i].equals(key)) {
                        value = array[i+1];
                        break;
                    }
                }
            } else {
                value = ((Hashtable)table).get(key);
            }
        }
        return value;
    }

    /*
     * Returns the number of pairs in storage
     */
    public int size() {
        int size;
        if (table==null)
            return 0;
        if (isArray()) {
            size = ((Object[])table).length/2;
        } else {
            size = ((Hashtable)table).size();
        }
        return size;
    }

    /*
     * Returns true if we have a value for the key
     */
    public boolean containsKey(Object key) {
        boolean contains = false;
        if (table !=null) {
            if (isArray()) {
                Object[] array = (Object[])table;
                for (int i = 0; i<array.length-1; i+=2) {
                    if (array[i].equals(key)) {
                        contains = true;
                        break;
                    }
                }
            } else {
                contains = ((Hashtable)table).containsKey(key);
            }
        }
        return contains;
    }

    /*
     * Removes the key and its value
     * Returns the value for the pair removed
     */
    public Object remove(Object key){
        Object value = null;
        if (key==null) {
            return null;
        }
        if (table !=null) {
            if (isArray()){
                // Is key on the list?
                int index = -1;
                Object[] array = (Object[])table;
                for (int i = array.length-2; i>=0; i-=2) {
                    if (array[i].equals(key)) {
                        index = i;
                        value = array[i+1];
                        break;
                    }
                }

                // If so,  remove it
                if (index != -1) {
                    Object[] tmp = new Object[array.length-2];
                    // Copy the list up to index
                    System.arraycopy(array, 0, tmp, 0, index);
                    // Copy from two past the index, up to
                    // the end of tmp (which is two elements
                    // shorter than the old list)
                    if (index < tmp.length)
                        System.arraycopy(array, index+2, tmp, index,
                                         tmp.length - index);
                    // set the listener array to the new array or null
                    table = (tmp.length == 0) ? null : tmp;
                }
            } else {
                value = ((Hashtable)table).remove(key);
            }
            if (size()==ARRAY_BOUNDARY - 1 && !isArray()) {
                shrink();
            }
        }
        return value;
    }

    /**
     * Removes all the mappings.
     */
    public void clear() {
        table = null;
    }

    /*
     * Returns a clone of the <code>ArrayTable</code>.
     */
    public Object clone() {
        ArrayTable newArrayTable = new ArrayTable();
        if (isArray()) {
            Object[] array = (Object[])table;
            for (int i = 0 ;i < array.length-1 ; i+=2) {
                newArrayTable.put(array[i], array[i+1]);
            }
        } else {
            Hashtable tmp = (Hashtable)table;
            Enumeration keys = tmp.keys();
            while (keys.hasMoreElements()) {
                Object o = keys.nextElement();
                newArrayTable.put(o,tmp.get(o));
            }
        }
        return newArrayTable;
    }

    /**
     * Returns the keys of the table, or <code>null</code> if there
     * are currently no bindings.
     * @param keys  array of keys
     * @return an array of bindings
     */
    public Object[] getKeys(Object[] keys) {
        if (table == null) {
            return null;
        }
        if (isArray()) {
            Object[] array = (Object[])table;
            if (keys == null) {
                keys = new Object[array.length / 2];
            }
            for (int i = 0, index = 0 ;i < array.length-1 ; i+=2,
                     index++) {
                keys[index] = array[i];
            }
        } else {
            Hashtable tmp = (Hashtable)table;
            Enumeration enum_ = tmp.keys();
            int counter = tmp.size();
            if (keys == null) {
                keys = new Object[counter];
            }
            while (counter > 0) {
                keys[--counter] = enum_.nextElement();
            }
        }
        return keys;
    }

    /*
     * Returns true if the current storage mechanism is
     * an array of alternating key-value pairs.
     */
    private boolean isArray(){
        return (table instanceof Object[]);
    }

    /*
     * Grows the storage from an array to a hashtable.
     */
    private void grow() {
        Object[] array = (Object[])table;
        Hashtable tmp = new Hashtable(array.length/2);
        for (int i = 0; i<array.length; i+=2) {
            tmp.put(array[i], array[i+1]);
        }
        table = tmp;
    }

    /*
     * Shrinks the storage from a hashtable to an array.
     */
    private void shrink() {
        Hashtable tmp = (Hashtable)table;
        Object[] array = new Object[tmp.size()*2];
        Enumeration keys = tmp.keys();
        int j = 0;

        while (keys.hasMoreElements()) {
            Object o = keys.nextElement();
            array[j] = o;
            array[j+1] = tmp.get(o);
            j+=2;
        }
        table = array;
    }
}
