10888a09821a98ac0680fad765217302858e70fa4Paul Duffin/*
20888a09821a98ac0680fad765217302858e70fa4Paul Duffin * Copyright (C) 2009 The Guava Authors
30888a09821a98ac0680fad765217302858e70fa4Paul Duffin *
40888a09821a98ac0680fad765217302858e70fa4Paul Duffin * Licensed under the Apache License, Version 2.0 (the "License");
50888a09821a98ac0680fad765217302858e70fa4Paul Duffin * you may not use this file except in compliance with the License.
60888a09821a98ac0680fad765217302858e70fa4Paul Duffin * You may obtain a copy of the License at
70888a09821a98ac0680fad765217302858e70fa4Paul Duffin *
80888a09821a98ac0680fad765217302858e70fa4Paul Duffin * http://www.apache.org/licenses/LICENSE-2.0
90888a09821a98ac0680fad765217302858e70fa4Paul Duffin *
100888a09821a98ac0680fad765217302858e70fa4Paul Duffin * Unless required by applicable law or agreed to in writing, software
110888a09821a98ac0680fad765217302858e70fa4Paul Duffin * distributed under the License is distributed on an "AS IS" BASIS,
120888a09821a98ac0680fad765217302858e70fa4Paul Duffin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130888a09821a98ac0680fad765217302858e70fa4Paul Duffin * See the License for the specific language governing permissions and
140888a09821a98ac0680fad765217302858e70fa4Paul Duffin * limitations under the License.
150888a09821a98ac0680fad765217302858e70fa4Paul Duffin */
160888a09821a98ac0680fad765217302858e70fa4Paul Duffin
170888a09821a98ac0680fad765217302858e70fa4Paul Duffinpackage com.google.common.collect;
180888a09821a98ac0680fad765217302858e70fa4Paul Duffin
190888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport static com.google.common.base.Preconditions.checkNotNull;
200888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport static com.google.common.collect.CollectPreconditions.checkEntryNotNull;
210888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport static com.google.common.collect.Iterables.getOnlyElement;
220888a09821a98ac0680fad765217302858e70fa4Paul Duffin
230888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport java.io.Serializable;
240888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport java.util.Collections;
250888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport java.util.EnumMap;
260888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport java.util.Iterator;
270888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport java.util.List;
280888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport java.util.Map;
290888a09821a98ac0680fad765217302858e70fa4Paul Duffin
300888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport javax.annotation.Nullable;
310888a09821a98ac0680fad765217302858e70fa4Paul Duffin
320888a09821a98ac0680fad765217302858e70fa4Paul Duffin/**
330888a09821a98ac0680fad765217302858e70fa4Paul Duffin * GWT emulation of {@link ImmutableMap}.  For non sorted maps, it is a thin
340888a09821a98ac0680fad765217302858e70fa4Paul Duffin * wrapper around {@link java.util.Collections#emptyMap()}, {@link
350888a09821a98ac0680fad765217302858e70fa4Paul Duffin * Collections#singletonMap(Object, Object)} and {@link java.util.LinkedHashMap}
360888a09821a98ac0680fad765217302858e70fa4Paul Duffin * for empty, singleton and regular maps respectively.  For sorted maps, it's
370888a09821a98ac0680fad765217302858e70fa4Paul Duffin * a thin wrapper around {@link java.util.TreeMap}.
380888a09821a98ac0680fad765217302858e70fa4Paul Duffin *
390888a09821a98ac0680fad765217302858e70fa4Paul Duffin * @see ImmutableSortedMap
400888a09821a98ac0680fad765217302858e70fa4Paul Duffin *
410888a09821a98ac0680fad765217302858e70fa4Paul Duffin * @author Hayward Chan
420888a09821a98ac0680fad765217302858e70fa4Paul Duffin */
430888a09821a98ac0680fad765217302858e70fa4Paul Duffinpublic abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
440888a09821a98ac0680fad765217302858e70fa4Paul Duffin
450888a09821a98ac0680fad765217302858e70fa4Paul Duffin  ImmutableMap() {}
460888a09821a98ac0680fad765217302858e70fa4Paul Duffin
470888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public static <K, V> ImmutableMap<K, V> of() {
480888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return ImmutableBiMap.of();
490888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
500888a09821a98ac0680fad765217302858e70fa4Paul Duffin
510888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public static <K, V> ImmutableMap<K, V> of(K k1, V v1) {
520888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return ImmutableBiMap.of(k1, v1);
530888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
540888a09821a98ac0680fad765217302858e70fa4Paul Duffin
550888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public static <K, V> ImmutableMap<K, V> of(K k1, V v1, K k2, V v2) {
560888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return new RegularImmutableMap<K, V>(entryOf(k1, v1), entryOf(k2, v2));
570888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
580888a09821a98ac0680fad765217302858e70fa4Paul Duffin
590888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public static <K, V> ImmutableMap<K, V> of(
600888a09821a98ac0680fad765217302858e70fa4Paul Duffin      K k1, V v1, K k2, V v2, K k3, V v3) {
610888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return new RegularImmutableMap<K, V>(
620888a09821a98ac0680fad765217302858e70fa4Paul Duffin        entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3));
630888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
640888a09821a98ac0680fad765217302858e70fa4Paul Duffin
650888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public static <K, V> ImmutableMap<K, V> of(
660888a09821a98ac0680fad765217302858e70fa4Paul Duffin      K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
670888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return new RegularImmutableMap<K, V>(
680888a09821a98ac0680fad765217302858e70fa4Paul Duffin        entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3), entryOf(k4, v4));
690888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
700888a09821a98ac0680fad765217302858e70fa4Paul Duffin
710888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public static <K, V> ImmutableMap<K, V> of(
720888a09821a98ac0680fad765217302858e70fa4Paul Duffin      K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
730888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return new RegularImmutableMap<K, V>(entryOf(k1, v1),
740888a09821a98ac0680fad765217302858e70fa4Paul Duffin        entryOf(k2, v2), entryOf(k3, v3), entryOf(k4, v4), entryOf(k5, v5));
750888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
760888a09821a98ac0680fad765217302858e70fa4Paul Duffin
770888a09821a98ac0680fad765217302858e70fa4Paul Duffin  // looking for of() with > 5 entries? Use the builder instead.
780888a09821a98ac0680fad765217302858e70fa4Paul Duffin
790888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public static <K, V> Builder<K, V> builder() {
800888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return new Builder<K, V>();
810888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
820888a09821a98ac0680fad765217302858e70fa4Paul Duffin
830888a09821a98ac0680fad765217302858e70fa4Paul Duffin  static <K, V> Entry<K, V> entryOf(K key, V value) {
840888a09821a98ac0680fad765217302858e70fa4Paul Duffin    checkEntryNotNull(key, value);
850888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return Maps.immutableEntry(key, value);
860888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
870888a09821a98ac0680fad765217302858e70fa4Paul Duffin
880888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public static class Builder<K, V> {
890888a09821a98ac0680fad765217302858e70fa4Paul Duffin    final List<Entry<K, V>> entries = Lists.newArrayList();
900888a09821a98ac0680fad765217302858e70fa4Paul Duffin
910888a09821a98ac0680fad765217302858e70fa4Paul Duffin    public Builder() {}
920888a09821a98ac0680fad765217302858e70fa4Paul Duffin
930888a09821a98ac0680fad765217302858e70fa4Paul Duffin    public Builder<K, V> put(K key, V value) {
940888a09821a98ac0680fad765217302858e70fa4Paul Duffin      entries.add(entryOf(key, value));
950888a09821a98ac0680fad765217302858e70fa4Paul Duffin      return this;
960888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
970888a09821a98ac0680fad765217302858e70fa4Paul Duffin
980888a09821a98ac0680fad765217302858e70fa4Paul Duffin    public Builder<K, V> put(Entry<? extends K, ? extends V> entry) {
990888a09821a98ac0680fad765217302858e70fa4Paul Duffin      if (entry instanceof ImmutableEntry) {
1000888a09821a98ac0680fad765217302858e70fa4Paul Duffin        checkNotNull(entry.getKey());
1010888a09821a98ac0680fad765217302858e70fa4Paul Duffin        checkNotNull(entry.getValue());
1020888a09821a98ac0680fad765217302858e70fa4Paul Duffin        @SuppressWarnings("unchecked") // all supported methods are covariant
1030888a09821a98ac0680fad765217302858e70fa4Paul Duffin        Entry<K, V> immutableEntry = (Entry<K, V>) entry;
1040888a09821a98ac0680fad765217302858e70fa4Paul Duffin        entries.add(immutableEntry);
1050888a09821a98ac0680fad765217302858e70fa4Paul Duffin      } else {
1060888a09821a98ac0680fad765217302858e70fa4Paul Duffin        entries.add(entryOf((K) entry.getKey(), (V) entry.getValue()));
1070888a09821a98ac0680fad765217302858e70fa4Paul Duffin      }
1080888a09821a98ac0680fad765217302858e70fa4Paul Duffin      return this;
1090888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
1100888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1110888a09821a98ac0680fad765217302858e70fa4Paul Duffin    public Builder<K, V> putAll(Map<? extends K, ? extends V> map) {
1120888a09821a98ac0680fad765217302858e70fa4Paul Duffin      for (Entry<? extends K, ? extends V> entry : map.entrySet()) {
1130888a09821a98ac0680fad765217302858e70fa4Paul Duffin        put(entry.getKey(), entry.getValue());
1140888a09821a98ac0680fad765217302858e70fa4Paul Duffin      }
1150888a09821a98ac0680fad765217302858e70fa4Paul Duffin      return this;
1160888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
1170888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1180888a09821a98ac0680fad765217302858e70fa4Paul Duffin    public ImmutableMap<K, V> build() {
1190888a09821a98ac0680fad765217302858e70fa4Paul Duffin      return fromEntryList(entries);
1200888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
1210888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1220888a09821a98ac0680fad765217302858e70fa4Paul Duffin    private static <K, V> ImmutableMap<K, V> fromEntryList(
1230888a09821a98ac0680fad765217302858e70fa4Paul Duffin        List<Entry<K, V>> entries) {
1240888a09821a98ac0680fad765217302858e70fa4Paul Duffin      int size = entries.size();
1250888a09821a98ac0680fad765217302858e70fa4Paul Duffin      switch (size) {
1260888a09821a98ac0680fad765217302858e70fa4Paul Duffin        case 0:
1270888a09821a98ac0680fad765217302858e70fa4Paul Duffin          return of();
1280888a09821a98ac0680fad765217302858e70fa4Paul Duffin        case 1:
1290888a09821a98ac0680fad765217302858e70fa4Paul Duffin          Entry<K, V> entry = getOnlyElement(entries);
1300888a09821a98ac0680fad765217302858e70fa4Paul Duffin          return of(entry.getKey(), entry.getValue());
1310888a09821a98ac0680fad765217302858e70fa4Paul Duffin        default:
1320888a09821a98ac0680fad765217302858e70fa4Paul Duffin          @SuppressWarnings("unchecked")
1330888a09821a98ac0680fad765217302858e70fa4Paul Duffin          Entry<K, V>[] entryArray
1340888a09821a98ac0680fad765217302858e70fa4Paul Duffin              = entries.toArray(new Entry[entries.size()]);
1350888a09821a98ac0680fad765217302858e70fa4Paul Duffin          return new RegularImmutableMap<K, V>(entryArray);
1360888a09821a98ac0680fad765217302858e70fa4Paul Duffin      }
1370888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
1380888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
1390888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1400888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public static <K, V> ImmutableMap<K, V> copyOf(
1410888a09821a98ac0680fad765217302858e70fa4Paul Duffin      Map<? extends K, ? extends V> map) {
1420888a09821a98ac0680fad765217302858e70fa4Paul Duffin    if ((map instanceof ImmutableMap) && !(map instanceof ImmutableSortedMap)) {
1430888a09821a98ac0680fad765217302858e70fa4Paul Duffin      @SuppressWarnings("unchecked") // safe since map is not writable
1440888a09821a98ac0680fad765217302858e70fa4Paul Duffin      ImmutableMap<K, V> kvMap = (ImmutableMap<K, V>) map;
1450888a09821a98ac0680fad765217302858e70fa4Paul Duffin      return kvMap;
1460888a09821a98ac0680fad765217302858e70fa4Paul Duffin    } else if (map instanceof EnumMap) {
1470888a09821a98ac0680fad765217302858e70fa4Paul Duffin      EnumMap<?, ?> enumMap = (EnumMap<?, ?>) map;
1480888a09821a98ac0680fad765217302858e70fa4Paul Duffin      for (Map.Entry<?, ?> entry : enumMap.entrySet()) {
1490888a09821a98ac0680fad765217302858e70fa4Paul Duffin        checkNotNull(entry.getKey());
1500888a09821a98ac0680fad765217302858e70fa4Paul Duffin        checkNotNull(entry.getValue());
1510888a09821a98ac0680fad765217302858e70fa4Paul Duffin      }
1520888a09821a98ac0680fad765217302858e70fa4Paul Duffin      @SuppressWarnings("unchecked")
1530888a09821a98ac0680fad765217302858e70fa4Paul Duffin      // immutable collections are safe for covariant casts
1540888a09821a98ac0680fad765217302858e70fa4Paul Duffin      ImmutableMap<K, V> result = ImmutableEnumMap.asImmutable(new EnumMap(enumMap));
1550888a09821a98ac0680fad765217302858e70fa4Paul Duffin      return result;
1560888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
1570888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1580888a09821a98ac0680fad765217302858e70fa4Paul Duffin    int size = map.size();
1590888a09821a98ac0680fad765217302858e70fa4Paul Duffin    switch (size) {
1600888a09821a98ac0680fad765217302858e70fa4Paul Duffin      case 0:
1610888a09821a98ac0680fad765217302858e70fa4Paul Duffin        return of();
1620888a09821a98ac0680fad765217302858e70fa4Paul Duffin      case 1:
1630888a09821a98ac0680fad765217302858e70fa4Paul Duffin        Entry<? extends K, ? extends V> entry
1640888a09821a98ac0680fad765217302858e70fa4Paul Duffin            = getOnlyElement(map.entrySet());
1650888a09821a98ac0680fad765217302858e70fa4Paul Duffin        return ImmutableMap.<K, V>of(entry.getKey(), entry.getValue());
1660888a09821a98ac0680fad765217302858e70fa4Paul Duffin      default:
1670888a09821a98ac0680fad765217302858e70fa4Paul Duffin        Map<K, V> orderPreservingCopy = Maps.newLinkedHashMap();
1680888a09821a98ac0680fad765217302858e70fa4Paul Duffin        for (Entry<? extends K, ? extends V> e : map.entrySet()) {
1690888a09821a98ac0680fad765217302858e70fa4Paul Duffin          orderPreservingCopy.put(
1700888a09821a98ac0680fad765217302858e70fa4Paul Duffin              checkNotNull(e.getKey()), checkNotNull(e.getValue()));
1710888a09821a98ac0680fad765217302858e70fa4Paul Duffin        }
1720888a09821a98ac0680fad765217302858e70fa4Paul Duffin        return new RegularImmutableMap<K, V>(orderPreservingCopy);
1730888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
1740888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
1750888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1760888a09821a98ac0680fad765217302858e70fa4Paul Duffin  abstract boolean isPartialView();
1770888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1780888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public final V put(K k, V v) {
1790888a09821a98ac0680fad765217302858e70fa4Paul Duffin    throw new UnsupportedOperationException();
1800888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
1810888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1820888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public final V remove(Object o) {
1830888a09821a98ac0680fad765217302858e70fa4Paul Duffin    throw new UnsupportedOperationException();
1840888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
1850888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1860888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public final void putAll(Map<? extends K, ? extends V> map) {
1870888a09821a98ac0680fad765217302858e70fa4Paul Duffin    throw new UnsupportedOperationException();
1880888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
1890888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1900888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public final void clear() {
1910888a09821a98ac0680fad765217302858e70fa4Paul Duffin    throw new UnsupportedOperationException();
1920888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
1930888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1940888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Override
1950888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public boolean isEmpty() {
1960888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return size() == 0;
1970888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
1980888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1990888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Override
2000888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public boolean containsKey(@Nullable Object key) {
2010888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return get(key) != null;
2020888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
2030888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2040888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Override
2050888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public boolean containsValue(@Nullable Object value) {
2060888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return values().contains(value);
2070888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
2080888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2090888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private transient ImmutableSet<Entry<K, V>> cachedEntrySet = null;
2100888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2110888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public final ImmutableSet<Entry<K, V>> entrySet() {
2120888a09821a98ac0680fad765217302858e70fa4Paul Duffin    if (cachedEntrySet != null) {
2130888a09821a98ac0680fad765217302858e70fa4Paul Duffin      return cachedEntrySet;
2140888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
2150888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return cachedEntrySet = createEntrySet();
2160888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
2170888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2180888a09821a98ac0680fad765217302858e70fa4Paul Duffin  abstract ImmutableSet<Entry<K, V>> createEntrySet();
2190888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2200888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private transient ImmutableSet<K> cachedKeySet = null;
2210888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2220888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public ImmutableSet<K> keySet() {
2230888a09821a98ac0680fad765217302858e70fa4Paul Duffin    if (cachedKeySet != null) {
2240888a09821a98ac0680fad765217302858e70fa4Paul Duffin      return cachedKeySet;
2250888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
2260888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return cachedKeySet = createKeySet();
2270888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
2280888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2290888a09821a98ac0680fad765217302858e70fa4Paul Duffin  ImmutableSet<K> createKeySet() {
2300888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return new ImmutableMapKeySet<K, V>(this);
2310888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
2320888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2330888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private transient ImmutableCollection<V> cachedValues = null;
2340888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2350888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public ImmutableCollection<V> values() {
2360888a09821a98ac0680fad765217302858e70fa4Paul Duffin    if (cachedValues != null) {
2370888a09821a98ac0680fad765217302858e70fa4Paul Duffin      return cachedValues;
2380888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
2390888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return cachedValues = createValues();
2400888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
2410888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2420888a09821a98ac0680fad765217302858e70fa4Paul Duffin  // esnickell is editing here
2430888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2440888a09821a98ac0680fad765217302858e70fa4Paul Duffin  // cached so that this.multimapView().inverse() only computes inverse once
2450888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private transient ImmutableSetMultimap<K, V> multimapView;
2460888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2470888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public ImmutableSetMultimap<K, V> asMultimap() {
2480888a09821a98ac0680fad765217302858e70fa4Paul Duffin    ImmutableSetMultimap<K, V> result = multimapView;
2490888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return (result == null) ? (multimapView = createMultimapView()) : result;
2500888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
2510888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2520888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private ImmutableSetMultimap<K, V> createMultimapView() {
2530888a09821a98ac0680fad765217302858e70fa4Paul Duffin    ImmutableMap<K, ImmutableSet<V>> map = viewValuesAsImmutableSet();
2540888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return new ImmutableSetMultimap<K, V>(map, map.size(), null);
2550888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
2560888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2570888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private ImmutableMap<K, ImmutableSet<V>> viewValuesAsImmutableSet() {
2580888a09821a98ac0680fad765217302858e70fa4Paul Duffin    final Map<K, V> outer = this;
2590888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return new ImmutableMap<K, ImmutableSet<V>>() {
2600888a09821a98ac0680fad765217302858e70fa4Paul Duffin      @Override
2610888a09821a98ac0680fad765217302858e70fa4Paul Duffin      public int size() {
2620888a09821a98ac0680fad765217302858e70fa4Paul Duffin        return outer.size();
2630888a09821a98ac0680fad765217302858e70fa4Paul Duffin      }
2640888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2650888a09821a98ac0680fad765217302858e70fa4Paul Duffin      @Override
2660888a09821a98ac0680fad765217302858e70fa4Paul Duffin      public ImmutableSet<V> get(@Nullable Object key) {
2670888a09821a98ac0680fad765217302858e70fa4Paul Duffin        V outerValue = outer.get(key);
2680888a09821a98ac0680fad765217302858e70fa4Paul Duffin        return outerValue == null ? null : ImmutableSet.of(outerValue);
2690888a09821a98ac0680fad765217302858e70fa4Paul Duffin      }
2700888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2710888a09821a98ac0680fad765217302858e70fa4Paul Duffin      @Override
2720888a09821a98ac0680fad765217302858e70fa4Paul Duffin      ImmutableSet<Entry<K, ImmutableSet<V>>> createEntrySet() {
2730888a09821a98ac0680fad765217302858e70fa4Paul Duffin        return new ImmutableSet<Entry<K, ImmutableSet<V>>>() {
2740888a09821a98ac0680fad765217302858e70fa4Paul Duffin          @Override
2750888a09821a98ac0680fad765217302858e70fa4Paul Duffin          public UnmodifiableIterator<Entry<K, ImmutableSet<V>>> iterator() {
2760888a09821a98ac0680fad765217302858e70fa4Paul Duffin            final Iterator<Entry<K,V>> outerEntryIterator = outer.entrySet().iterator();
2770888a09821a98ac0680fad765217302858e70fa4Paul Duffin            return new UnmodifiableIterator<Entry<K, ImmutableSet<V>>>() {
2780888a09821a98ac0680fad765217302858e70fa4Paul Duffin              @Override
2790888a09821a98ac0680fad765217302858e70fa4Paul Duffin              public boolean hasNext() {
2800888a09821a98ac0680fad765217302858e70fa4Paul Duffin                return outerEntryIterator.hasNext();
2810888a09821a98ac0680fad765217302858e70fa4Paul Duffin              }
2820888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2830888a09821a98ac0680fad765217302858e70fa4Paul Duffin              @Override
2840888a09821a98ac0680fad765217302858e70fa4Paul Duffin              public Entry<K, ImmutableSet<V>> next() {
2850888a09821a98ac0680fad765217302858e70fa4Paul Duffin                final Entry<K, V> outerEntry = outerEntryIterator.next();
2860888a09821a98ac0680fad765217302858e70fa4Paul Duffin                return new AbstractMapEntry<K, ImmutableSet<V>>() {
2870888a09821a98ac0680fad765217302858e70fa4Paul Duffin                  @Override
2880888a09821a98ac0680fad765217302858e70fa4Paul Duffin                  public K getKey() {
2890888a09821a98ac0680fad765217302858e70fa4Paul Duffin                    return outerEntry.getKey();
2900888a09821a98ac0680fad765217302858e70fa4Paul Duffin                  }
2910888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2920888a09821a98ac0680fad765217302858e70fa4Paul Duffin                  @Override
2930888a09821a98ac0680fad765217302858e70fa4Paul Duffin                  public ImmutableSet<V> getValue() {
2940888a09821a98ac0680fad765217302858e70fa4Paul Duffin                    return ImmutableSet.of(outerEntry.getValue());
2950888a09821a98ac0680fad765217302858e70fa4Paul Duffin                  }
2960888a09821a98ac0680fad765217302858e70fa4Paul Duffin                };
2970888a09821a98ac0680fad765217302858e70fa4Paul Duffin              }
2980888a09821a98ac0680fad765217302858e70fa4Paul Duffin            };
2990888a09821a98ac0680fad765217302858e70fa4Paul Duffin          }
3000888a09821a98ac0680fad765217302858e70fa4Paul Duffin
3010888a09821a98ac0680fad765217302858e70fa4Paul Duffin          @Override
3020888a09821a98ac0680fad765217302858e70fa4Paul Duffin          boolean isPartialView() {
3030888a09821a98ac0680fad765217302858e70fa4Paul Duffin            return false;
3040888a09821a98ac0680fad765217302858e70fa4Paul Duffin          }
3050888a09821a98ac0680fad765217302858e70fa4Paul Duffin
3060888a09821a98ac0680fad765217302858e70fa4Paul Duffin          @Override
3070888a09821a98ac0680fad765217302858e70fa4Paul Duffin          public int size() {
3080888a09821a98ac0680fad765217302858e70fa4Paul Duffin            return outer.size();
3090888a09821a98ac0680fad765217302858e70fa4Paul Duffin          }
3100888a09821a98ac0680fad765217302858e70fa4Paul Duffin        };
3110888a09821a98ac0680fad765217302858e70fa4Paul Duffin      }
3120888a09821a98ac0680fad765217302858e70fa4Paul Duffin
3130888a09821a98ac0680fad765217302858e70fa4Paul Duffin      @Override
3140888a09821a98ac0680fad765217302858e70fa4Paul Duffin      boolean isPartialView() {
3150888a09821a98ac0680fad765217302858e70fa4Paul Duffin        return false;
3160888a09821a98ac0680fad765217302858e70fa4Paul Duffin      }
3170888a09821a98ac0680fad765217302858e70fa4Paul Duffin    };
3180888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
3190888a09821a98ac0680fad765217302858e70fa4Paul Duffin
3200888a09821a98ac0680fad765217302858e70fa4Paul Duffin  ImmutableCollection<V> createValues() {
3210888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return new ImmutableMapValues<K, V>(this);
3220888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
3230888a09821a98ac0680fad765217302858e70fa4Paul Duffin
3240888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Override public boolean equals(@Nullable Object object) {
3250888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return Maps.equalsImpl(this, object);
3260888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
3270888a09821a98ac0680fad765217302858e70fa4Paul Duffin
3280888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Override public int hashCode() {
3290888a09821a98ac0680fad765217302858e70fa4Paul Duffin    // not caching hash code since it could change if map values are mutable
3300888a09821a98ac0680fad765217302858e70fa4Paul Duffin    // in a way that modifies their hash codes
3310888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return entrySet().hashCode();
3320888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
3330888a09821a98ac0680fad765217302858e70fa4Paul Duffin
3340888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Override public String toString() {
3350888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return Maps.toStringImpl(this);
3360888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
3370888a09821a98ac0680fad765217302858e70fa4Paul Duffin}
338