1/*
2 * Copyright (C) 2009 Google Inc.
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 java.util.concurrent;
18
19import java.util.AbstractMap;
20import java.util.Collections;
21import java.util.Enumeration;
22import java.util.HashMap;
23import java.util.Map;
24import java.util.Set;
25
26/**
27 * Minimal emulation of {@link java.util.concurrent.ConcurrentHashMap}.
28 * Note that javascript intepreter is <a
29 * href="http://code.google.com/docreader/#p=google-web-toolkit-doc-1-5&t=DevGuideJavaCompatibility">
30 * single-threaded</a>, it is essentially a {@link java.util.HashMap},
31 * implementing the new methods introduced by {@link ConcurrentMap}.
32 *
33 * @author Hayward Chan
34 */
35public class ConcurrentHashMap<K, V>
36    extends AbstractMap<K, V> implements ConcurrentMap<K, V> {
37
38  private final Map<K, V> backingMap;
39
40  public ConcurrentHashMap() {
41    this.backingMap = new HashMap<K, V>();
42  }
43
44  public ConcurrentHashMap(int initialCapacity) {
45    this.backingMap = new HashMap<K, V>(initialCapacity);
46  }
47
48  public ConcurrentHashMap(int initialCapacity, float loadFactor) {
49    this.backingMap = new HashMap<K, V>(initialCapacity, loadFactor);
50  }
51
52  public ConcurrentHashMap(Map<? extends K, ? extends V> t) {
53    this.backingMap = new HashMap<K, V>(t);
54  }
55
56  public V putIfAbsent(K key, V value) {
57    if (!containsKey(key)) {
58      return put(key, value);
59    } else {
60      return get(key);
61    }
62  }
63
64  public boolean remove(Object key, Object value) {
65    if (containsKey(key) && get(key).equals(value)) {
66      remove(key);
67      return true;
68    } else {
69      return false;
70    }
71  }
72
73  public boolean replace(K key, V oldValue, V newValue) {
74    if (oldValue == null || newValue == null) {
75      throw new NullPointerException();
76    } else if (containsKey(key) && get(key).equals(oldValue)) {
77      put(key, newValue);
78      return true;
79    } else {
80      return false;
81    }
82  }
83
84  public V replace(K key, V value) {
85    if (value == null) {
86      throw new NullPointerException();
87    } else if (containsKey(key)) {
88      return put(key, value);
89    } else {
90      return null;
91    }
92  }
93
94  @Override public boolean containsKey(Object key) {
95    if (key == null) {
96      throw new NullPointerException();
97    }
98    return backingMap.containsKey(key);
99  }
100
101  @Override public V get(Object key) {
102    if (key == null) {
103      throw new NullPointerException();
104    }
105    return backingMap.get(key);
106  }
107
108  @Override public V put(K key, V value) {
109    if (key == null || value == null) {
110      throw new NullPointerException();
111    }
112    return backingMap.put(key, value);
113  }
114
115  @Override public boolean containsValue(Object value) {
116    if (value == null) {
117      throw new NullPointerException();
118    }
119    return backingMap.containsValue(value);
120  }
121
122  @Override public V remove(Object key) {
123    if (key == null) {
124      throw new NullPointerException();
125    }
126    return backingMap.remove(key);
127  }
128
129  @Override public Set<Entry<K, V>> entrySet() {
130    return backingMap.entrySet();
131  }
132
133  public boolean contains(Object value) {
134    return containsValue(value);
135  }
136
137  public Enumeration<V> elements() {
138    return Collections.enumeration(values());
139  }
140
141  public Enumeration<K> keys() {
142    return Collections.enumeration(keySet());
143  }
144}
145