Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/javax/swing/ArrayTable.java
38829 views
/*1* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/24package javax.swing;2526import java.io.IOException;27import java.io.ObjectOutputStream;28import java.io.Serializable;29import java.util.Enumeration;30import java.util.Hashtable;3132/*33* Private storage mechanism for Action key-value pairs.34* In most cases this will be an array of alternating35* key-value pairs. As it grows larger it is scaled36* up to a Hashtable.37* <p>38* This does no synchronization, if you need thread safety synchronize on39* another object before calling this.40*41* @author Georges Saab42* @author Scott Violet43*/44class ArrayTable implements Cloneable {45// Our field for storage46private Object table = null;47private static final int ARRAY_BOUNDARY = 8;484950/**51* Writes the passed in ArrayTable to the passed in ObjectOutputStream.52* The data is saved as an integer indicating how many key/value53* pairs are being archived, followed by the the key/value pairs. If54* <code>table</code> is null, 0 will be written to <code>s</code>.55* <p>56* This is a convenience method that ActionMap/InputMap and57* AbstractAction use to avoid having the same code in each class.58*/59static void writeArrayTable(ObjectOutputStream s, ArrayTable table) throws IOException {60Object keys[];6162if (table == null || (keys = table.getKeys(null)) == null) {63s.writeInt(0);64}65else {66// Determine how many keys have Serializable values, when67// done all non-null values in keys identify the Serializable68// values.69int validCount = 0;7071for (int counter = 0; counter < keys.length; counter++) {72Object key = keys[counter];7374/* include in Serialization when both keys and values are Serializable */75if ( (key instanceof Serializable76&& table.get(key) instanceof Serializable)77||78/* include these only so that we get the appropriate exception below */79(key instanceof ClientPropertyKey80&& ((ClientPropertyKey)key).getReportValueNotSerializable())) {8182validCount++;83} else {84keys[counter] = null;85}86}87// Write ou the Serializable key/value pairs.88s.writeInt(validCount);89if (validCount > 0) {90for (Object key : keys) {91if (key != null) {92s.writeObject(key);93s.writeObject(table.get(key));94if (--validCount == 0) {95break;96}97}98}99}100}101}102103104/*105* Put the key-value pair into storage106*/107public void put(Object key, Object value){108if (table==null) {109table = new Object[] {key, value};110} else {111int size = size();112if (size < ARRAY_BOUNDARY) { // We are an array113if (containsKey(key)) {114Object[] tmp = (Object[])table;115for (int i = 0; i<tmp.length-1; i+=2) {116if (tmp[i].equals(key)) {117tmp[i+1]=value;118break;119}120}121} else {122Object[] array = (Object[])table;123int i = array.length;124Object[] tmp = new Object[i+2];125System.arraycopy(array, 0, tmp, 0, i);126127tmp[i] = key;128tmp[i+1] = value;129table = tmp;130}131} else { // We are a hashtable132if ((size==ARRAY_BOUNDARY) && isArray()) {133grow();134}135((Hashtable<Object,Object>)table).put(key, value);136}137}138}139140/*141* Gets the value for key142*/143public Object get(Object key) {144Object value = null;145if (table !=null) {146if (isArray()) {147Object[] array = (Object[])table;148for (int i = 0; i<array.length-1; i+=2) {149if (array[i].equals(key)) {150value = array[i+1];151break;152}153}154} else {155value = ((Hashtable)table).get(key);156}157}158return value;159}160161/*162* Returns the number of pairs in storage163*/164public int size() {165int size;166if (table==null)167return 0;168if (isArray()) {169size = ((Object[])table).length/2;170} else {171size = ((Hashtable)table).size();172}173return size;174}175176/*177* Returns true if we have a value for the key178*/179public boolean containsKey(Object key) {180boolean contains = false;181if (table !=null) {182if (isArray()) {183Object[] array = (Object[])table;184for (int i = 0; i<array.length-1; i+=2) {185if (array[i].equals(key)) {186contains = true;187break;188}189}190} else {191contains = ((Hashtable)table).containsKey(key);192}193}194return contains;195}196197/*198* Removes the key and its value199* Returns the value for the pair removed200*/201public Object remove(Object key){202Object value = null;203if (key==null) {204return null;205}206if (table !=null) {207if (isArray()){208// Is key on the list?209int index = -1;210Object[] array = (Object[])table;211for (int i = array.length-2; i>=0; i-=2) {212if (array[i].equals(key)) {213index = i;214value = array[i+1];215break;216}217}218219// If so, remove it220if (index != -1) {221Object[] tmp = new Object[array.length-2];222// Copy the list up to index223System.arraycopy(array, 0, tmp, 0, index);224// Copy from two past the index, up to225// the end of tmp (which is two elements226// shorter than the old list)227if (index < tmp.length)228System.arraycopy(array, index+2, tmp, index,229tmp.length - index);230// set the listener array to the new array or null231table = (tmp.length == 0) ? null : tmp;232}233} else {234value = ((Hashtable)table).remove(key);235}236if (size()==ARRAY_BOUNDARY - 1 && !isArray()) {237shrink();238}239}240return value;241}242243/**244* Removes all the mappings.245*/246public void clear() {247table = null;248}249250/*251* Returns a clone of the <code>ArrayTable</code>.252*/253public Object clone() {254ArrayTable newArrayTable = new ArrayTable();255if (isArray()) {256Object[] array = (Object[])table;257for (int i = 0 ;i < array.length-1 ; i+=2) {258newArrayTable.put(array[i], array[i+1]);259}260} else {261Hashtable<?,?> tmp = (Hashtable)table;262Enumeration<?> keys = tmp.keys();263while (keys.hasMoreElements()) {264Object o = keys.nextElement();265newArrayTable.put(o,tmp.get(o));266}267}268return newArrayTable;269}270271/**272* Returns the keys of the table, or <code>null</code> if there273* are currently no bindings.274* @param keys array of keys275* @return an array of bindings276*/277public Object[] getKeys(Object[] keys) {278if (table == null) {279return null;280}281if (isArray()) {282Object[] array = (Object[])table;283if (keys == null) {284keys = new Object[array.length / 2];285}286for (int i = 0, index = 0 ;i < array.length-1 ; i+=2,287index++) {288keys[index] = array[i];289}290} else {291Hashtable<?,?> tmp = (Hashtable)table;292Enumeration<?> enum_ = tmp.keys();293int counter = tmp.size();294if (keys == null) {295keys = new Object[counter];296}297while (counter > 0) {298keys[--counter] = enum_.nextElement();299}300}301return keys;302}303304/*305* Returns true if the current storage mechanism is306* an array of alternating key-value pairs.307*/308private boolean isArray(){309return (table instanceof Object[]);310}311312/*313* Grows the storage from an array to a hashtable.314*/315private void grow() {316Object[] array = (Object[])table;317Hashtable<Object, Object> tmp = new Hashtable<Object, Object>(array.length/2);318for (int i = 0; i<array.length; i+=2) {319tmp.put(array[i], array[i+1]);320}321table = tmp;322}323324/*325* Shrinks the storage from a hashtable to an array.326*/327private void shrink() {328Hashtable<?,?> tmp = (Hashtable)table;329Object[] array = new Object[tmp.size()*2];330Enumeration<?> keys = tmp.keys();331int j = 0;332333while (keys.hasMoreElements()) {334Object o = keys.nextElement();335array[j] = o;336array[j+1] = tmp.get(o);337j+=2;338}339table = array;340}341}342343344