jdk/src/share/classes/javax/swing/ArrayTable.java
changeset 2 90ce3da70b43
child 1301 15e81207e1f2
equal deleted inserted replaced
0:fd16c54261b3 2:90ce3da70b43
       
     1 /*
       
     2  * Copyright 2003-2006 Sun Microsystems, Inc.  All Rights Reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Sun designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Sun in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    23  * have any questions.
       
    24  */
       
    25 package javax.swing;
       
    26 
       
    27 import java.io.IOException;
       
    28 import java.io.ObjectOutputStream;
       
    29 import java.io.Serializable;
       
    30 import java.util.Enumeration;
       
    31 import java.util.Hashtable;
       
    32 
       
    33 /*
       
    34  * Private storage mechanism for Action key-value pairs.
       
    35  * In most cases this will be an array of alternating
       
    36  * key-value pairs.  As it grows larger it is scaled
       
    37  * up to a Hashtable.
       
    38  * <p>
       
    39  * This does no synchronization, if you need thread safety synchronize on
       
    40  * another object before calling this.
       
    41  *
       
    42  * @author Georges Saab
       
    43  * @author Scott Violet
       
    44  */
       
    45 class ArrayTable implements Cloneable {
       
    46     // Our field for storage
       
    47     private Object table = null;
       
    48     private static final int ARRAY_BOUNDARY = 8;
       
    49 
       
    50 
       
    51     /**
       
    52      * Writes the passed in ArrayTable to the passed in ObjectOutputStream.
       
    53      * The data is saved as an integer indicating how many key/value
       
    54      * pairs are being archived, followed by the the key/value pairs. If
       
    55      * <code>table</code> is null, 0 will be written to <code>s</code>.
       
    56      * <p>
       
    57      * This is a convenience method that ActionMap/InputMap and
       
    58      * AbstractAction use to avoid having the same code in each class.
       
    59      */
       
    60     static void writeArrayTable(ObjectOutputStream s, ArrayTable table) throws IOException {
       
    61         Object keys[];
       
    62 
       
    63         if (table == null || (keys = table.getKeys(null)) == null) {
       
    64             s.writeInt(0);
       
    65         }
       
    66         else {
       
    67             // Determine how many keys have Serializable values, when
       
    68             // done all non-null values in keys identify the Serializable
       
    69             // values.
       
    70             int validCount = 0;
       
    71 
       
    72             for (int counter = 0; counter < keys.length; counter++) {
       
    73                 Object key = keys[counter];
       
    74 
       
    75                 /* include in Serialization when both keys and values are Serializable */
       
    76                 if (    (key instanceof Serializable
       
    77                          && table.get(key) instanceof Serializable)
       
    78                              ||
       
    79                          /* include these only so that we get the appropriate exception below */
       
    80                         (key instanceof ClientPropertyKey
       
    81                          && ((ClientPropertyKey)key).getReportValueNotSerializable())) {
       
    82 
       
    83                     validCount++;
       
    84                 } else {
       
    85                     keys[counter] = null;
       
    86                 }
       
    87             }
       
    88             // Write ou the Serializable key/value pairs.
       
    89             s.writeInt(validCount);
       
    90             if (validCount > 0) {
       
    91                 for (int counter = 0; counter < keys.length; counter++) {
       
    92                     if (keys[counter] != null) {
       
    93                         s.writeObject(keys[counter]);
       
    94                         s.writeObject(table.get(keys[counter]));
       
    95                         if (--validCount == 0) {
       
    96                             break;
       
    97                         }
       
    98                     }
       
    99                 }
       
   100             }
       
   101         }
       
   102     }
       
   103 
       
   104 
       
   105     /*
       
   106      * Put the key-value pair into storage
       
   107      */
       
   108     public void put(Object key, Object value){
       
   109         if (table==null) {
       
   110             table = new Object[] {key, value};
       
   111         } else {
       
   112             int size = size();
       
   113             if (size < ARRAY_BOUNDARY) {              // We are an array
       
   114                 if (containsKey(key)) {
       
   115                     Object[] tmp = (Object[])table;
       
   116                     for (int i = 0; i<tmp.length-1; i+=2) {
       
   117                         if (tmp[i].equals(key)) {
       
   118                             tmp[i+1]=value;
       
   119                             break;
       
   120                         }
       
   121                     }
       
   122                 } else {
       
   123                     Object[] array = (Object[])table;
       
   124                     int i = array.length;
       
   125                     Object[] tmp = new Object[i+2];
       
   126                     System.arraycopy(array, 0, tmp, 0, i);
       
   127 
       
   128                     tmp[i] = key;
       
   129                     tmp[i+1] = value;
       
   130                     table = tmp;
       
   131                 }
       
   132             } else {                 // We are a hashtable
       
   133                 if ((size==ARRAY_BOUNDARY) && isArray()) {
       
   134                     grow();
       
   135                 }
       
   136                 ((Hashtable)table).put(key, value);
       
   137             }
       
   138         }
       
   139     }
       
   140 
       
   141     /*
       
   142      * Gets the value for key
       
   143      */
       
   144     public Object get(Object key) {
       
   145         Object value = null;
       
   146         if (table !=null) {
       
   147             if (isArray()) {
       
   148                 Object[] array = (Object[])table;
       
   149                 for (int i = 0; i<array.length-1; i+=2) {
       
   150                     if (array[i].equals(key)) {
       
   151                         value = array[i+1];
       
   152                         break;
       
   153                     }
       
   154                 }
       
   155             } else {
       
   156                 value = ((Hashtable)table).get(key);
       
   157             }
       
   158         }
       
   159         return value;
       
   160     }
       
   161 
       
   162     /*
       
   163      * Returns the number of pairs in storage
       
   164      */
       
   165     public int size() {
       
   166         int size;
       
   167         if (table==null)
       
   168             return 0;
       
   169         if (isArray()) {
       
   170             size = ((Object[])table).length/2;
       
   171         } else {
       
   172             size = ((Hashtable)table).size();
       
   173         }
       
   174         return size;
       
   175     }
       
   176 
       
   177     /*
       
   178      * Returns true if we have a value for the key
       
   179      */
       
   180     public boolean containsKey(Object key) {
       
   181         boolean contains = false;
       
   182         if (table !=null) {
       
   183             if (isArray()) {
       
   184                 Object[] array = (Object[])table;
       
   185                 for (int i = 0; i<array.length-1; i+=2) {
       
   186                     if (array[i].equals(key)) {
       
   187                         contains = true;
       
   188                         break;
       
   189                     }
       
   190                 }
       
   191             } else {
       
   192                 contains = ((Hashtable)table).containsKey(key);
       
   193             }
       
   194         }
       
   195         return contains;
       
   196     }
       
   197 
       
   198     /*
       
   199      * Removes the key and its value
       
   200      * Returns the value for the pair removed
       
   201      */
       
   202     public Object remove(Object key){
       
   203         Object value = null;
       
   204         if (key==null) {
       
   205             return null;
       
   206         }
       
   207         if (table !=null) {
       
   208             if (isArray()){
       
   209                 // Is key on the list?
       
   210                 int index = -1;
       
   211                 Object[] array = (Object[])table;
       
   212                 for (int i = array.length-2; i>=0; i-=2) {
       
   213                     if (array[i].equals(key)) {
       
   214                         index = i;
       
   215                         value = array[i+1];
       
   216                         break;
       
   217                     }
       
   218                 }
       
   219 
       
   220                 // If so,  remove it
       
   221                 if (index != -1) {
       
   222                     Object[] tmp = new Object[array.length-2];
       
   223                     // Copy the list up to index
       
   224                     System.arraycopy(array, 0, tmp, 0, index);
       
   225                     // Copy from two past the index, up to
       
   226                     // the end of tmp (which is two elements
       
   227                     // shorter than the old list)
       
   228                     if (index < tmp.length)
       
   229                         System.arraycopy(array, index+2, tmp, index,
       
   230                                          tmp.length - index);
       
   231                     // set the listener array to the new array or null
       
   232                     table = (tmp.length == 0) ? null : tmp;
       
   233                 }
       
   234             } else {
       
   235                 value = ((Hashtable)table).remove(key);
       
   236             }
       
   237             if (size()==ARRAY_BOUNDARY - 1 && !isArray()) {
       
   238                 shrink();
       
   239             }
       
   240         }
       
   241         return value;
       
   242     }
       
   243 
       
   244     /**
       
   245      * Removes all the mappings.
       
   246      */
       
   247     public void clear() {
       
   248         table = null;
       
   249     }
       
   250 
       
   251     /*
       
   252      * Returns a clone of the <code>ArrayTable</code>.
       
   253      */
       
   254     public Object clone() {
       
   255         ArrayTable newArrayTable = new ArrayTable();
       
   256         if (isArray()) {
       
   257             Object[] array = (Object[])table;
       
   258             for (int i = 0 ;i < array.length-1 ; i+=2) {
       
   259                 newArrayTable.put(array[i], array[i+1]);
       
   260             }
       
   261         } else {
       
   262             Hashtable tmp = (Hashtable)table;
       
   263             Enumeration keys = tmp.keys();
       
   264             while (keys.hasMoreElements()) {
       
   265                 Object o = keys.nextElement();
       
   266                 newArrayTable.put(o,tmp.get(o));
       
   267             }
       
   268         }
       
   269         return newArrayTable;
       
   270     }
       
   271 
       
   272     /**
       
   273      * Returns the keys of the table, or <code>null</code> if there
       
   274      * are currently no bindings.
       
   275      * @param keys  array of keys
       
   276      * @return an array of bindings
       
   277      */
       
   278     public Object[] getKeys(Object[] keys) {
       
   279         if (table == null) {
       
   280             return null;
       
   281         }
       
   282         if (isArray()) {
       
   283             Object[] array = (Object[])table;
       
   284             if (keys == null) {
       
   285                 keys = new Object[array.length / 2];
       
   286             }
       
   287             for (int i = 0, index = 0 ;i < array.length-1 ; i+=2,
       
   288                      index++) {
       
   289                 keys[index] = array[i];
       
   290             }
       
   291         } else {
       
   292             Hashtable tmp = (Hashtable)table;
       
   293             Enumeration enum_ = tmp.keys();
       
   294             int counter = tmp.size();
       
   295             if (keys == null) {
       
   296                 keys = new Object[counter];
       
   297             }
       
   298             while (counter > 0) {
       
   299                 keys[--counter] = enum_.nextElement();
       
   300             }
       
   301         }
       
   302         return keys;
       
   303     }
       
   304 
       
   305     /*
       
   306      * Returns true if the current storage mechanism is
       
   307      * an array of alternating key-value pairs.
       
   308      */
       
   309     private boolean isArray(){
       
   310         return (table instanceof Object[]);
       
   311     }
       
   312 
       
   313     /*
       
   314      * Grows the storage from an array to a hashtable.
       
   315      */
       
   316     private void grow() {
       
   317         Object[] array = (Object[])table;
       
   318         Hashtable tmp = new Hashtable(array.length/2);
       
   319         for (int i = 0; i<array.length; i+=2) {
       
   320             tmp.put(array[i], array[i+1]);
       
   321         }
       
   322         table = tmp;
       
   323     }
       
   324 
       
   325     /*
       
   326      * Shrinks the storage from a hashtable to an array.
       
   327      */
       
   328     private void shrink() {
       
   329         Hashtable tmp = (Hashtable)table;
       
   330         Object[] array = new Object[tmp.size()*2];
       
   331         Enumeration keys = tmp.keys();
       
   332         int j = 0;
       
   333 
       
   334         while (keys.hasMoreElements()) {
       
   335             Object o = keys.nextElement();
       
   336             array[j] = o;
       
   337             array[j+1] = tmp.get(o);
       
   338             j+=2;
       
   339         }
       
   340         table = array;
       
   341     }
       
   342 }