ImmutableBiMap.java revision 1d580d0f6ee4f21eb309ba7b509d2c6d671c4044
1/*
2 * Copyright (C) 2009 The Guava Authors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.google.common.collect;
18
19import java.util.Collections;
20import java.util.Map;
21
22/**
23 * GWT emulation of {@link ImmutableBiMap}.
24 *
25 * @author Hayward Chan
26 */
27public abstract class ImmutableBiMap<K, V> extends ImmutableMap<K,V>
28    implements BiMap<K, V> {
29
30  private static final ImmutableBiMap<Object, Object> EMPTY_IMMUTABLE_BIMAP
31      = new EmptyBiMap();
32
33  // Casting to any type is safe because the set will never hold any elements.
34  @SuppressWarnings("unchecked")
35  public static <K, V> ImmutableBiMap<K, V> of() {
36    return (ImmutableBiMap<K, V>) EMPTY_IMMUTABLE_BIMAP;
37  }
38
39  public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1) {
40    return new RegularImmutableBiMap<K, V>(ImmutableMap.of(k1, v1));
41  }
42
43  public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1, K k2, V v2) {
44    return new RegularImmutableBiMap<K, V>(ImmutableMap.of(k1, v1, k2, v2));
45  }
46
47  public static <K, V> ImmutableBiMap<K, V> of(
48      K k1, V v1, K k2, V v2, K k3, V v3) {
49    return new RegularImmutableBiMap<K, V>(ImmutableMap.of(
50        k1, v1, k2, v2, k3, v3));
51  }
52
53  public static <K, V> ImmutableBiMap<K, V> of(
54      K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
55    return new RegularImmutableBiMap<K, V>(ImmutableMap.of(
56        k1, v1, k2, v2, k3, v3, k4, v4));
57  }
58
59  public static <K, V> ImmutableBiMap<K, V> of(
60      K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
61    return new RegularImmutableBiMap<K, V>(ImmutableMap.of(
62        k1, v1, k2, v2, k3, v3, k4, v4, k5, v5));
63  }
64
65  public static <K, V> Builder<K, V> builder() {
66    return new Builder<K, V>();
67  }
68
69  public static final class Builder<K, V> extends ImmutableMap.Builder<K, V> {
70
71    public Builder() {}
72
73    @Override public Builder<K, V> put(K key, V value) {
74      super.put(key, value);
75      return this;
76    }
77
78    @Override public Builder<K, V> putAll(Map<? extends K, ? extends V> map) {
79      super.putAll(map);
80      return this;
81    }
82
83    @Override public ImmutableBiMap<K, V> build() {
84      ImmutableMap<K, V> map = super.build();
85      if (map.isEmpty()) {
86        return of();
87      }
88      return new RegularImmutableBiMap<K, V>(super.build());
89    }
90  }
91
92  public static <K, V> ImmutableBiMap<K, V> copyOf(
93      Map<? extends K, ? extends V> map) {
94    if (map instanceof ImmutableBiMap) {
95      @SuppressWarnings("unchecked") // safe since map is not writable
96      ImmutableBiMap<K, V> bimap = (ImmutableBiMap<K, V>) map;
97      return bimap;
98    }
99
100    if (map.isEmpty()) {
101      return of();
102    }
103
104    ImmutableMap<K, V> immutableMap = ImmutableMap.copyOf(map);
105    return new RegularImmutableBiMap<K, V>(immutableMap);
106  }
107
108  ImmutableBiMap(Map<K, V> delegate) {
109    super(delegate);
110  }
111
112  public abstract ImmutableBiMap<V, K> inverse();
113
114  @Override public ImmutableSet<V> values() {
115    return inverse().keySet();
116  }
117
118  public final V forcePut(K key, V value) {
119    throw new UnsupportedOperationException();
120  }
121
122  @SuppressWarnings("serial")
123  static class EmptyBiMap extends ImmutableBiMap<Object, Object> {
124    EmptyBiMap() {
125      super(Collections.emptyMap());
126    }
127    @Override public ImmutableBiMap<Object, Object> inverse() {
128      return this;
129    }
130  }
131}
132