    001    /*
    002     * Copyright (C) 2008 The Guava Authors
    003     *
    004     * Licensed under the Apache License, Version 2.0 (the "License");
    005     * you may not use this file except in compliance with the License.
    006     * You may obtain a copy of the License at
    007     *
    008     * http://www.apache.org/licenses/LICENSE-2.0
    009     *
    010     * Unless required by applicable law or agreed to in writing, software
    011     * distributed under the License is distributed on an "AS IS" BASIS,
    012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    013     * See the License for the specific language governing permissions and
    014     * limitations under the License.
    015     */
    016
    017    package com.google.common.collect;
    018
    019    import com.google.common.annotations.GwtCompatible;
    020
    021    import java.util.Map;
    022
    023    import javax.annotation.Nullable;
    024
    025    /**
    026     * An immutable {@link BiMap} with reliable user-specified iteration order. Does
    027     * not permit null keys or values. An {@code ImmutableBiMap} and its inverse
    028     * have the same iteration ordering.
    029     *
    030     * <p>An instance of {@code ImmutableBiMap} contains its own data and will
    031     * <i>never</i> change. {@code ImmutableBiMap} is convenient for
    032     * {@code public static final} maps ("constant maps") and also lets you easily
    033     * make a "defensive copy" of a bimap provided to your class by a caller.
    034     *
    035     * <p><b>Note:</b> Although this class is not final, it cannot be subclassed as
    036     * it has no public or protected constructors. Thus, instances of this class are
    037     * guaranteed to be immutable.
    038     *
    039     * @author Jared Levy
    040     * @since 2.0 (imported from Google Collections Library)
    041     */
    042    @GwtCompatible(serializable = true, emulated = true)
    043    public abstract class ImmutableBiMap<K, V> extends ImmutableMap<K, V>
    044        implements BiMap<K, V> {
    045
    046      /**
    047       * Returns the empty bimap.
    048       */
    049      // Casting to any type is safe because the set will never hold any elements.
    050      @SuppressWarnings("unchecked")
    051      public static <K, V> ImmutableBiMap<K, V> of() {
    052        return (ImmutableBiMap<K, V>) EmptyImmutableBiMap.INSTANCE;
    053      }
    054
    055      /**
    056       * Returns an immutable bimap containing a single entry.
    057       */
    058      public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1) {
    059        return new RegularImmutableBiMap<K, V>(ImmutableMap.of(k1, v1));
    060      }
    061
    062      /**
    063       * Returns an immutable map containing the given entries, in order.
    064       *
    065       * @throws IllegalArgumentException if duplicate keys or values are added
    066       */
    067      public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1, K k2, V v2) {
    068        return new RegularImmutableBiMap<K, V>(ImmutableMap.of(k1, v1, k2, v2));
    069      }
    070
    071      /**
    072       * Returns an immutable map containing the given entries, in order.
    073       *
    074       * @throws IllegalArgumentException if duplicate keys or values are added
    075       */
    076      public static <K, V> ImmutableBiMap<K, V> of(
    077          K k1, V v1, K k2, V v2, K k3, V v3) {
    078        return new RegularImmutableBiMap<K, V>(ImmutableMap.of(
    079            k1, v1, k2, v2, k3, v3));
    080      }
    081
    082      /**
    083       * Returns an immutable map containing the given entries, in order.
    084       *
    085       * @throws IllegalArgumentException if duplicate keys or values are added
    086       */
    087      public static <K, V> ImmutableBiMap<K, V> of(
    088          K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
    089        return new RegularImmutableBiMap<K, V>(ImmutableMap.of(
    090            k1, v1, k2, v2, k3, v3, k4, v4));
    091      }
    092
    093      /**
    094       * Returns an immutable map containing the given entries, in order.
    095       *
    096       * @throws IllegalArgumentException if duplicate keys or values are added
    097       */
    098      public static <K, V> ImmutableBiMap<K, V> of(
    099          K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
    100        return new RegularImmutableBiMap<K, V>(ImmutableMap.of(
    101            k1, v1, k2, v2, k3, v3, k4, v4, k5, v5));
    102      }
    103
    104      // looking for of() with > 5 entries? Use the builder instead.
    105
    106      /**
    107       * Returns a new builder. The generated builder is equivalent to the builder
    108       * created by the {@link Builder} constructor.
    109       */
    110      public static <K, V> Builder<K, V> builder() {
    111        return new Builder<K, V>();
    112      }
    113
    114      /**
    115       * A builder for creating immutable bimap instances, especially {@code public
    116       * static final} bimaps ("constant bimaps"). Example: <pre>   {@code
    117       *
    118       *   static final ImmutableBiMap<String, Integer> WORD_TO_INT =
    119       *       new ImmutableBiMap.Builder<String, Integer>()
    120       *           .put("one", 1)
    121       *           .put("two", 2)
    122       *           .put("three", 3)
    123       *           .build();}</pre>
    124       *
    125       * For <i>small</i> immutable bimaps, the {@code ImmutableBiMap.of()} methods
    126       * are even more convenient.
    127       *
    128       * <p>Builder instances can be reused - it is safe to call {@link #build}
    129       * multiple times to build multiple bimaps in series. Each bimap is a superset
    130       * of the bimaps created before it.
    131       *
    132       * @since 2.0 (imported from Google Collections Library)
    133       */
    134      public static final class Builder<K, V> extends ImmutableMap.Builder<K, V> {
    135
    136        /**
    137         * Creates a new builder. The returned builder is equivalent to the builder
    138         * generated by {@link ImmutableBiMap#builder}.
    139         */
    140        public Builder() {}
    141
    142        /**
    143         * Associates {@code key} with {@code value} in the built bimap. Duplicate
    144         * keys or values are not allowed, and will cause {@link #build} to fail.
    145         */
    146        @Override public Builder<K, V> put(K key, V value) {
    147          super.put(key, value);
    148          return this;
    149        }
    150
    151        /**
    152         * Associates all of the given map's keys and values in the built bimap.
    153         * Duplicate keys or values are not allowed, and will cause {@link #build}
    154         * to fail.
    155         *
    156         * @throws NullPointerException if any key or value in {@code map} is null
    157         */
    158        @Override public Builder<K, V> putAll(Map<? extends K, ? extends V> map) {
    159          super.putAll(map);
    160          return this;
    161        }
    162
    163        /**
    164         * Returns a newly-created immutable bimap.
    165         *
    166         * @throws IllegalArgumentException if duplicate keys or values were added
    167         */
    168        @Override public ImmutableBiMap<K, V> build() {
    169          ImmutableMap<K, V> map = super.build();
    170          if (map.isEmpty()) {
    171            return of();
    172          }
    173          return new RegularImmutableBiMap<K, V>(map);
    174        }
    175      }
    176
    177      /**
    178       * Returns an immutable bimap containing the same entries as {@code map}. If
    179       * {@code map} somehow contains entries with duplicate keys (for example, if
    180       * it is a {@code SortedMap} whose comparator is not <i>consistent with
    181       * equals</i>), the results of this method are undefined.
    182       *
    183       * <p>Despite the method name, this method attempts to avoid actually copying
    184       * the data when it is safe to do so. The exact circumstances under which a
    185       * copy will or will not be performed are undocumented and subject to change.
    186       *
    187       * @throws IllegalArgumentException if two keys have the same value
    188       * @throws NullPointerException if any key or value in {@code map} is null
    189       */
    190      public static <K, V> ImmutableBiMap<K, V> copyOf(
    191          Map<? extends K, ? extends V> map) {
    192        if (map instanceof ImmutableBiMap) {
    193          @SuppressWarnings("unchecked") // safe since map is not writable
    194          ImmutableBiMap<K, V> bimap = (ImmutableBiMap<K, V>) map;
    195          // TODO(user): if we need to make a copy of a BiMap because the
    196          // forward map is a view, don't make a copy of the non-view delegate map
    197          if (!bimap.isPartialView()) {
    198            return bimap;
    199          }
    200        }
    201
    202        if (map.isEmpty()) {
    203          return of();
    204        }
    205
    206        ImmutableMap<K, V> immutableMap = ImmutableMap.copyOf(map);
    207        return new RegularImmutableBiMap<K, V>(immutableMap);
    208      }
    209
    210      ImmutableBiMap() {}
    211
    212      abstract ImmutableMap<K, V> delegate();
    213
    214      /**
    215       * {@inheritDoc}
    216       *
    217       * <p>The inverse of an {@code ImmutableBiMap} is another
    218       * {@code ImmutableBiMap}.
    219       */
    220      @Override
    221      public abstract ImmutableBiMap<V, K> inverse();
    222
    223      @Override public boolean containsKey(@Nullable Object key) {
    224        return delegate().containsKey(key);
    225      }
    226
    227      @Override public boolean containsValue(@Nullable Object value) {
    228        return inverse().containsKey(value);
    229      }
    230
    231      @Override ImmutableSet<Entry<K, V>> createEntrySet() {
    232        return delegate().entrySet();
    233      }
    234
    235      @Override public V get(@Nullable Object key) {
    236        return delegate().get(key);
    237      }
    238
    239      @Override public ImmutableSet<K> keySet() {
    240        return delegate().keySet();
    241      }
    242
    243      /**
    244       * Returns an immutable set of the values in this map. The values are in the
    245       * same order as the parameters used to build this map.
    246       */
    247      @Override public ImmutableSet<V> values() {
    248        return inverse().keySet();
    249      }
    250
    251      /**
    252       * Guaranteed to throw an exception and leave the bimap unmodified.
    253       *
    254       * @throws UnsupportedOperationException always
    255       */
    256      @Override
    257      public V forcePut(K key, V value) {
    258        throw new UnsupportedOperationException();
    259      }
    260
    261      @Override public boolean isEmpty() {
    262        return delegate().isEmpty();
    263      }
    264
    265      @Override
    266      public int size() {
    267        return delegate().size();
    268      }
    269
    270      @Override public boolean equals(@Nullable Object object) {
    271        return object == this || delegate().equals(object);
    272      }
    273
    274      @Override public int hashCode() {
    275        return delegate().hashCode();
    276      }
    277
    278      @Override public String toString() {
    279        return delegate().toString();
    280      }
    281
    282      /**
    283       * Serialized type for all ImmutableBiMap instances. It captures the logical
    284       * contents and they are reconstructed using public factory methods. This
    285       * ensures that the implementation types remain as implementation details.
    286       *
    287       * Since the bimap is immutable, ImmutableBiMap doesn't require special logic
    288       * for keeping the bimap and its inverse in sync during serialization, the way
    289       * AbstractBiMap does.
    290       */
    291      private static class SerializedForm extends ImmutableMap.SerializedForm {
    292        SerializedForm(ImmutableBiMap<?, ?> bimap) {
    293          super(bimap);
    294        }
    295        @Override Object readResolve() {
    296          Builder<Object, Object> builder = new Builder<Object, Object>();
    297          return createMap(builder);
    298        }
    299        private static final long serialVersionUID = 0;
    300      }
    301
    302      @Override Object writeReplace() {
    303        return new SerializedForm(this);
    304      }
    305    }