001
014
015 package com.liferay.portal.kernel.util;
016
017 import com.liferay.portal.kernel.memory.EqualityWeakReference;
018 import com.liferay.portal.kernel.memory.FinalizeAction;
019 import com.liferay.portal.kernel.memory.FinalizeManager;
020
021 import java.io.Serializable;
022
023 import java.lang.ref.Reference;
024
025 import java.util.AbstractCollection;
026 import java.util.AbstractSet;
027 import java.util.ArrayList;
028 import java.util.Collection;
029 import java.util.Iterator;
030 import java.util.List;
031 import java.util.Map;
032 import java.util.Set;
033 import java.util.concurrent.ConcurrentHashMap;
034 import java.util.concurrent.ConcurrentMap;
035
036
039 public class WeakValueConcurrentHashMap<K, V>
040 implements ConcurrentMap<K, V>, Serializable {
041
042 public WeakValueConcurrentHashMap() {
043 _map = new ConcurrentHashMap<K, Reference<V>>();
044 }
045
046 public WeakValueConcurrentHashMap(int initialCapacity) {
047 _map = new ConcurrentHashMap<K, Reference<V>>(initialCapacity);
048 }
049
050 public WeakValueConcurrentHashMap(
051 int initialCapacity, float loadFactor, int concurrencyLevel) {
052 _map = new ConcurrentHashMap<K, Reference<V>>(
053 initialCapacity, loadFactor, concurrencyLevel);
054 }
055
056 public WeakValueConcurrentHashMap(Map<? extends K, ? extends V> map) {
057 _map = new ConcurrentHashMap<K, Reference<V>>();
058
059 putAll(map);
060 }
061
062 public void clear() {
063 _map.clear();
064 }
065
066 public boolean containsKey(Object key) {
067 return _map.containsKey(key);
068 }
069
070 public boolean containsValue(Object value) {
071 return _map.containsValue(new EqualityWeakReference<V>((V)value));
072 }
073
074 public Set<Entry<K, V>> entrySet() {
075 if (_entrySet == null) {
076 _entrySet = new UnwrapEntrySet();
077 }
078
079 return _entrySet;
080 }
081
082 public V get(Object key) {
083 Reference<V> valueReference = _map.get(key);
084
085 if (valueReference != null) {
086 return valueReference.get();
087 }
088
089 return null;
090 }
091
092 public boolean isEmpty() {
093 return _map.isEmpty();
094 }
095
096 public Set<K> keySet() {
097 return _map.keySet();
098 }
099
100 public V put(K key, V value) {
101 Reference<V> valueReference = wrapValue(key, value);
102
103 valueReference = _map.putIfAbsent(key, valueReference);
104
105 if (valueReference != null) {
106 return valueReference.get();
107 }
108
109 return null;
110 }
111
112 public final void putAll(Map<? extends K, ? extends V> map) {
113 for (Map.Entry<? extends K, ? extends V> entry : map.entrySet()) {
114 K key = entry.getKey();
115 V value = entry.getValue();
116
117 Reference<V> valueReference = wrapValue(key, value);
118
119 _map.put(key, valueReference);
120 }
121 }
122
123 public V putIfAbsent(K key, V value) {
124 Reference<V> valueReference = wrapValue(key, value);
125
126 valueReference = _map.putIfAbsent(key, valueReference);
127
128 if (valueReference != null) {
129 return valueReference.get();
130 }
131
132 return null;
133 }
134
135 public V remove(Object key) {
136 Reference<V> valueReference = _map.remove(key);
137
138 if (valueReference != null) {
139 return valueReference.get();
140 }
141
142 return null;
143 }
144
145 public boolean remove(Object key, Object value) {
146 Reference<V> valueReference = wrapValue(key, value);
147
148 return _map.remove(key, valueReference);
149 }
150
151 public V replace(K key, V value) {
152 Reference<V> valueReference = wrapValue(key, value);
153
154 valueReference = _map.replace(key, valueReference);
155
156 if (valueReference != null) {
157 return valueReference.get();
158 }
159
160 return null;
161 }
162
163 public boolean replace(K key, V oldValue, V newValue) {
164 Reference<V> oldValueReference = wrapValue(key, oldValue);
165 Reference<V> newValueReference = wrapValue(key, newValue);
166
167 return _map.replace(key, oldValueReference, newValueReference);
168 }
169
170 public int size() {
171 return _map.size();
172 }
173
174 public Collection<V> values() {
175 if (_values == null) {
176 _values = new UnwrapValues();
177 }
178 return _values;
179 }
180
181 protected Reference<V> wrapValue(Object key, Object value) {
182 return FinalizeManager.register(
183 (V)value, new RemoveEntryFinalizeAction((K) key));
184 }
185
186 private transient Set<Map.Entry<K, V>> _entrySet;
187 private final ConcurrentMap<K, Reference<V>> _map;
188 private transient Collection<V> _values;
189
190 private class RemoveEntryFinalizeAction implements FinalizeAction {
191
192 public RemoveEntryFinalizeAction(K key) {
193 _key = key;
194 }
195
196 public void doFinalize() {
197 remove(_key);
198 }
199
200 private final K _key;
201
202 }
203
204 private class UnwrapEntry implements Map.Entry<K, V> {
205
206 public UnwrapEntry(Entry<K, Reference<V>> entry) {
207 _entry = entry;
208 }
209
210 public K getKey() {
211 return _entry.getKey();
212 }
213
214 public V getValue() {
215 Reference<V> valueReference = _entry.getValue();
216
217 if (valueReference != null) {
218 return valueReference.get();
219 }
220
221 return null;
222 }
223
224 public V setValue(V value) {
225 return WeakValueConcurrentHashMap.this.put(_entry.getKey(), value);
226 }
227
228 private Map.Entry<K, Reference<V>> _entry;
229
230 }
231
232 private class UnwrapEntryIterator implements Iterator<Map.Entry<K, V>> {
233
234 public UnwrapEntryIterator() {
235 _iterator = _map.entrySet().iterator();
236 }
237
238 public boolean hasNext() {
239 return _iterator.hasNext();
240 }
241
242 public Entry<K, V> next() {
243 return new UnwrapEntry(_iterator.next());
244 }
245
246 public void remove() {
247 _iterator.remove();
248 }
249
250 private Iterator<Map.Entry<K, Reference<V>>> _iterator;
251
252 }
253
254 private class UnwrapEntrySet extends AbstractSet<Map.Entry<K, V>> {
255
256 @Override
257 public void clear() {
258 WeakValueConcurrentHashMap.this.clear();
259 }
260
261 @Override
262 public boolean contains(Object obj) {
263 if (!(obj instanceof Map.Entry<?, ?>)) {
264 return false;
265 }
266
267 Map.Entry<K, V> entry = (Map.Entry<K, V>)obj;
268
269 V value = WeakValueConcurrentHashMap.this.get(entry.getKey());
270
271 if ((value != null) && value.equals(entry.getValue())) {
272 return true;
273 }
274 else {
275 return false;
276 }
277 }
278
279 @Override
280 public Iterator<Map.Entry<K, V>> iterator() {
281 return new UnwrapEntryIterator();
282 }
283
284 @Override
285 public boolean remove(Object obj) {
286 if (!(obj instanceof Map.Entry<?, ?>)) {
287 return false;
288 }
289
290 Map.Entry<K, V> entry = (Map.Entry<K, V>)obj;
291
292 return WeakValueConcurrentHashMap.this.remove(
293 entry.getKey(), entry.getValue());
294 }
295
296 @Override
297 public int size() {
298 return WeakValueConcurrentHashMap.this.size();
299 }
300
301 @Override
302 public Object[] toArray() {
303 List<Map.Entry<K, V>> list = new ArrayList<Map.Entry<K, V>>(size());
304
305 Iterator<Map.Entry<K, V>> iterator = iterator();
306
307 while (iterator.hasNext()) {
308 list.add(iterator.next());
309 }
310
311 return list.toArray();
312 }
313
314 @Override
315 public <T> T[] toArray(T[] array) {
316 List<Map.Entry<K, V>> list = new ArrayList<Map.Entry<K, V>>(size());
317
318 Iterator<Map.Entry<K, V>> iterator = iterator();
319
320 while (iterator.hasNext()) {
321 list.add(iterator.next());
322 }
323
324 return list.toArray(array);
325 }
326
327 }
328
329 private class UnwrapValueIterator implements Iterator<V> {
330
331 public UnwrapValueIterator() {
332 _iterator = _map.values().iterator();
333 }
334
335 public boolean hasNext() {
336 return _iterator.hasNext();
337 }
338
339 public V next() {
340 Reference<V> valueReference = _iterator.next();
341
342 if (valueReference != null) {
343 return valueReference.get();
344 }
345
346 return null;
347 }
348
349 public void remove() {
350 _iterator.remove();
351 }
352
353 private Iterator<Reference<V>> _iterator;
354
355 }
356
357 private class UnwrapValues extends AbstractCollection<V> {
358
359 @Override
360 public void clear() {
361 WeakValueConcurrentHashMap.this.clear();
362 }
363
364 @Override
365 public boolean contains(Object obj) {
366 return WeakValueConcurrentHashMap.this.containsValue(obj);
367 }
368
369 @Override
370 public Iterator<V> iterator() {
371 return new UnwrapValueIterator();
372 }
373
374 @Override
375 public int size() {
376 return WeakValueConcurrentHashMap.this.size();
377 }
378
379 @Override
380 public Object[] toArray() {
381 List<V> list = new ArrayList<V>();
382
383 Iterator<V> iterator = iterator();
384
385 while (iterator.hasNext()) {
386 list.add(iterator.next());
387 }
388
389 return list.toArray();
390 }
391
392 @Override
393 public <T> T[] toArray(T[] a) {
394 List<V> list = new ArrayList<V>();
395
396 Iterator<V> iterator = iterator();
397
398 while (iterator.hasNext()) {
399 list.add(iterator.next());
400 }
401
402 return list.toArray(a);
403 }
404
405 }
406
407 }