1090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson/*
21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Copyright (C) 2008 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 com.google.common.annotations.GwtCompatible;
20090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
21090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport java.util.Map;
22090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
23090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport javax.annotation.Nullable;
24090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
25090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson/**
26090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * Implementation of {@link ImmutableMap} with exactly one entry.
27090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson *
28090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * @author Jesse Wilson
29090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * @author Kevin Bourrillion
30090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson */
311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert@GwtCompatible(serializable = true, emulated = true)
32090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson@SuppressWarnings("serial") // uses writeReplace(), not default serialization
33090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonfinal class SingletonImmutableMap<K, V> extends ImmutableMap<K, V> {
341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
35090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  final transient K singleKey;
36090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  final transient V singleValue;
37090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
38090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  private transient Entry<K, V> entry;
39090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
40090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  SingletonImmutableMap(K singleKey, V singleValue) {
41090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    this.singleKey = singleKey;
42090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    this.singleValue = singleValue;
43090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
44090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
45090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  SingletonImmutableMap(Entry<K, V> entry) {
461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    this.entry = entry;
471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    this.singleKey = entry.getKey();
481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    this.singleValue = entry.getValue();
49090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
50090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
51090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  private Entry<K, V> entry() {
52090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    Entry<K, V> e = entry;
53090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    return (e == null)
54090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        ? (entry = Maps.immutableEntry(singleKey, singleValue)) : e;
55090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
56090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Override public V get(@Nullable Object key) {
58090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    return singleKey.equals(key) ? singleValue : null;
59090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
60090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Override
62090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  public int size() {
63090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    return 1;
64090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
65090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
66090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  @Override public boolean isEmpty() {
67090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    return false;
68090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
69090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Override public boolean containsKey(@Nullable Object key) {
71090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    return singleKey.equals(key);
72090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
73090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Override public boolean containsValue(@Nullable Object value) {
75090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    return singleValue.equals(value);
76090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
77090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Override boolean isPartialView() {
791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return false;
801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
82090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  private transient ImmutableSet<Entry<K, V>> entrySet;
83090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
84090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  @Override public ImmutableSet<Entry<K, V>> entrySet() {
85090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    ImmutableSet<Entry<K, V>> es = entrySet;
86090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    return (es == null) ? (entrySet = ImmutableSet.of(entry())) : es;
87090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
88090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
89090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  private transient ImmutableSet<K> keySet;
90090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
91090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  @Override public ImmutableSet<K> keySet() {
92090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    ImmutableSet<K> ks = keySet;
93090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    return (ks == null) ? (keySet = ImmutableSet.of(singleKey)) : ks;
94090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
95090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
96090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  private transient ImmutableCollection<V> values;
97090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
98090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  @Override public ImmutableCollection<V> values() {
99090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    ImmutableCollection<V> v = values;
100090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    return (v == null) ? (values = new Values<V>(singleValue)) : v;
101090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
102090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
103090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  @SuppressWarnings("serial") // uses writeReplace(), not default serialization
104090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  private static class Values<V> extends ImmutableCollection<V> {
105090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    final V singleValue;
106090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
107090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    Values(V singleValue) {
108090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      this.singleValue = singleValue;
109090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
110090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
111090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    @Override public boolean contains(Object object) {
112090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      return singleValue.equals(object);
113090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
114090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
115090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    @Override public boolean isEmpty() {
116090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      return false;
117090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
118090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
1191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
120090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    public int size() {
121090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      return 1;
122090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
123090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
124090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    @Override public UnmodifiableIterator<V> iterator() {
125090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      return Iterators.singletonIterator(singleValue);
126090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
1271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override boolean isPartialView() {
1291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return true;
1301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
131090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
132090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
133090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  @Override public boolean equals(@Nullable Object object) {
134090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    if (object == this) {
135090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      return true;
136090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
137090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    if (object instanceof Map) {
138090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      Map<?, ?> that = (Map<?, ?>) object;
139090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      if (that.size() != 1) {
140090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        return false;
141090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      }
142090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      Entry<?, ?> entry = that.entrySet().iterator().next();
143090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      return singleKey.equals(entry.getKey())
144090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson          && singleValue.equals(entry.getValue());
145090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
146090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    return false;
147090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
148090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
149090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  @Override public int hashCode() {
150090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    return singleKey.hashCode() ^ singleValue.hashCode();
151090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
152090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
153090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  @Override public String toString() {
154090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    return new StringBuilder()
155090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        .append('{')
156090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        .append(singleKey.toString())
157090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        .append('=')
158090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        .append(singleValue.toString())
159090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        .append('}')
160090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        .toString();
161090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
162090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson}
163