1090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson/* 21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Copyright (C) 2007 The Guava Authors 3090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * 4090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * Licensed under the Apache License, Version 2.0 (the "License"); 5090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * you may not use this file except in compliance with the License. 6090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * You may obtain a copy of the License at 7090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * 8090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * http://www.apache.org/licenses/LICENSE-2.0 9090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * 10090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * Unless required by applicable law or agreed to in writing, software 11090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS, 12090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * See the License for the specific language governing permissions and 14090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * limitations under the License. 15090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson */ 16090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 17090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonpackage com.google.common.collect; 18090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 19090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport static com.google.common.base.Preconditions.checkArgument; 20090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.annotations.GwtCompatible; 221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 23090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport java.util.EnumMap; 24090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport java.util.Map; 25090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 26090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson/** 27090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * A {@code BiMap} backed by two {@code EnumMap} instances. Null keys and values 28090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * are not permitted. An {@code EnumBiMap} and its inverse are both 29090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * serializable. 30090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * 31090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * @author Mike Bostock 321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @since 2.0 (imported from Google Collections Library) 33090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson */ 341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert@GwtCompatible(emulated = true) 35090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonpublic final class EnumBiMap<K extends Enum<K>, V extends Enum<V>> 36090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson extends AbstractBiMap<K, V> { 37090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private transient Class<K> keyType; 38090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private transient Class<V> valueType; 39090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 40090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson /** 41090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * Returns a new, empty {@code EnumBiMap} using the specified key and value 42090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * types. 43090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * 44090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * @param keyType the key type 45090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * @param valueType the value type 46090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson */ 47090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson public static <K extends Enum<K>, V extends Enum<V>> EnumBiMap<K, V> 48090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson create(Class<K> keyType, Class<V> valueType) { 49090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return new EnumBiMap<K, V>(keyType, valueType); 50090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 51090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 52090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson /** 53090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * Returns a new bimap with the same mappings as the specified map. If the 54090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * specified map is an {@code EnumBiMap}, the new bimap has the same types as 55090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * the provided map. Otherwise, the specified map must contain at least one 56090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * mapping, in order to determine the key and value types. 57090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * 58090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * @param map the map whose mappings are to be placed in this map 59090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * @throws IllegalArgumentException if map is not an {@code EnumBiMap} 60090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * instance and contains no mappings 61090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson */ 62090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson public static <K extends Enum<K>, V extends Enum<V>> EnumBiMap<K, V> 63090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson create(Map<K, V> map) { 64090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson EnumBiMap<K, V> bimap = create(inferKeyType(map), inferValueType(map)); 65090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson bimap.putAll(map); 66090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return bimap; 67090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 68090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 69090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private EnumBiMap(Class<K> keyType, Class<V> valueType) { 701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert super(WellBehavedMap.wrap(new EnumMap<K, V>(keyType)), 711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert WellBehavedMap.wrap(new EnumMap<V, K>(valueType))); 72090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson this.keyType = keyType; 73090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson this.valueType = valueType; 74090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 75090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 76090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson static <K extends Enum<K>> Class<K> inferKeyType(Map<K, ?> map) { 77090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson if (map instanceof EnumBiMap) { 78090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return ((EnumBiMap<K, ?>) map).keyType(); 79090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 80090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson if (map instanceof EnumHashBiMap) { 81090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return ((EnumHashBiMap<K, ?>) map).keyType(); 82090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 83090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson checkArgument(!map.isEmpty()); 84090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return map.keySet().iterator().next().getDeclaringClass(); 85090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 86090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 87090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private static <V extends Enum<V>> Class<V> inferValueType(Map<?, V> map) { 88090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson if (map instanceof EnumBiMap) { 89090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return ((EnumBiMap<?, V>) map).valueType; 90090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 91090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson checkArgument(!map.isEmpty()); 92090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return map.values().iterator().next().getDeclaringClass(); 93090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 94090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 95090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson /** Returns the associated key type. */ 96090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson public Class<K> keyType() { 97090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return keyType; 98090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 99090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 100090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson /** Returns the associated value type. */ 101090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson public Class<V> valueType() { 102090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return valueType; 103090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 104090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson} 1051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 106