001
014
015 package com.liferay.portal.kernel.concurrent;
016
017 import com.liferay.portal.kernel.util.Validator;
018
019 import java.io.Serializable;
020
021 import java.util.AbstractCollection;
022 import java.util.AbstractMap;
023 import java.util.AbstractSet;
024 import java.util.Collection;
025 import java.util.Iterator;
026 import java.util.Map;
027 import java.util.Set;
028 import java.util.concurrent.ConcurrentMap;
029
030
033 public abstract class ConcurrentMapperHashMap<K, IK, V, IV>
034 extends AbstractMap<K, V> implements ConcurrentMap<K, V>, Serializable {
035
036 @Override
037 public void clear() {
038 innerConcurrentMap.clear();
039 }
040
041 @Override
042 public boolean containsKey(Object key) {
043 if (key == null) {
044 throw new NullPointerException("Key is null");
045 }
046
047 return innerConcurrentMap.containsKey(mapKeyForQuery((K)key));
048 }
049
050 @Override
051 public boolean containsValue(Object value) {
052 if (value == null) {
053 throw new NullPointerException("Value is null");
054 }
055
056 return innerConcurrentMap.containsValue(mapValueForQuery((V)value));
057 }
058
059 @Override
060 public Set<Entry<K, V>> entrySet() {
061 if (entrySet == null) {
062 entrySet = new UnwrapEntrySet();
063 }
064
065 return entrySet;
066 }
067
068 @Override
069 public V get(Object key) {
070 if (key == null) {
071 throw new NullPointerException("Key is null");
072 }
073
074 IV innerValue = innerConcurrentMap.get(mapKeyForQuery((K)key));
075
076 if (innerValue == null) {
077 return null;
078 }
079
080 return unmapValueForQuery(innerValue);
081 }
082
083 @Override
084 public boolean isEmpty() {
085 return innerConcurrentMap.isEmpty();
086 }
087
088 @Override
089 public Set<K> keySet() {
090 if (keySet == null) {
091 keySet = new UnwrapKeySet();
092 }
093
094 return keySet;
095 }
096
097 @Override
098 public V put(K key, V value) {
099 if (key == null) {
100 throw new NullPointerException("Key is null");
101 }
102
103 if (value == null) {
104 throw new NullPointerException("Value is null");
105 }
106
107 IK innerKey = mapKey(key);
108
109 IV oldInnerValue = innerConcurrentMap.put(
110 innerKey, mapValue(key, value));
111
112 if (oldInnerValue == null) {
113 return null;
114 }
115
116 unmapKey(innerKey);
117
118 return unmapValue(oldInnerValue);
119 }
120
121 @Override
122 public void putAll(Map<? extends K, ? extends V> map) {
123 for (Map.Entry<? extends K, ? extends V> entry : map.entrySet()) {
124 put(entry.getKey(), entry.getValue());
125 }
126 }
127
128 @Override
129 public V putIfAbsent(K key, V value) {
130 if (key == null) {
131 throw new NullPointerException("Key is null");
132 }
133
134 if (value == null) {
135 throw new NullPointerException("Value is null");
136 }
137
138 IK innerKey = mapKey(key);
139 IV innerValue = mapValue(key, value);
140
141 IV previousInnerValue = innerConcurrentMap.putIfAbsent(
142 innerKey, innerValue);
143
144 if (previousInnerValue == null) {
145 return null;
146 }
147
148 unmapKey(innerKey);
149 unmapValue(innerValue);
150
151 return unmapValueForQuery(previousInnerValue);
152 }
153
154 @Override
155 public V remove(Object key) {
156 if (key == null) {
157 throw new NullPointerException("Key is null");
158 }
159
160 IK innerKey = mapKeyForQuery((K)key);
161
162 IV innerValue = innerConcurrentMap.remove(innerKey);
163
164 if (innerValue == null) {
165 return null;
166 }
167
168 return unmapValue(innerValue);
169 }
170
171 @Override
172 public boolean remove(Object key, Object value) {
173 if (key == null) {
174 throw new NullPointerException("Key is null");
175 }
176
177 if (value == null) {
178 throw new NullPointerException("Value is null");
179 }
180
181 IK innerKey = mapKeyForQuery((K)key);
182 IV innerValue = mapValueForQuery((V)value);
183
184 IV previousInnerValue = innerConcurrentMap.get(innerKey);
185
186 if (!innerValue.equals(previousInnerValue) ||
187 !innerConcurrentMap.remove(innerKey, previousInnerValue)) {
188
189 return false;
190 }
191
192 unmapValue(previousInnerValue);
193
194 return true;
195 }
196
197 @Override
198 public V replace(K key, V value) {
199 if (key == null) {
200 throw new NullPointerException("Key is null");
201 }
202
203 if (value == null) {
204 throw new NullPointerException("Value is null");
205 }
206
207 IV newInnerValue = mapValue(key, value);
208
209 IV oldInnerValue = innerConcurrentMap.replace(
210 mapKeyForQuery(key), newInnerValue);
211
212 if (oldInnerValue == null) {
213 unmapValue(newInnerValue);
214
215 return null;
216 }
217
218 return unmapValue(oldInnerValue);
219 }
220
221 @Override
222 public boolean replace(K key, V oldValue, V newValue) {
223 if (key == null) {
224 throw new NullPointerException("Key is null");
225 }
226
227 if (oldValue == null) {
228 throw new NullPointerException("Old value is null");
229 }
230
231 if (newValue == null) {
232 throw new NullPointerException("New value is null");
233 }
234
235 IK innerKey = mapKeyForQuery(key);
236
237 IV newInnerValue = mapValue(key, newValue);
238
239 IV oldInnerValue = innerConcurrentMap.get(innerKey);
240
241 if ((oldInnerValue == null) ||
242 !oldValue.equals(unmapValueForQuery(oldInnerValue))) {
243
244 unmapValue(newInnerValue);
245
246 return false;
247 }
248
249 if (innerConcurrentMap.replace(
250 innerKey, oldInnerValue, newInnerValue)) {
251
252 unmapValue(oldInnerValue);
253
254 return true;
255 }
256
257 unmapValue(newInnerValue);
258
259 return false;
260 }
261
262 @Override
263 public int size() {
264 return innerConcurrentMap.size();
265 }
266
267 @Override
268 public Collection<V> values() {
269 if (values == null) {
270 values = new UnwrapValues();
271 }
272
273 return values;
274 }
275
276 protected ConcurrentMapperHashMap(
277 ConcurrentMap<IK, IV> innerConcurrentMap) {
278
279 this.innerConcurrentMap = innerConcurrentMap;
280 }
281
282 protected abstract IK mapKey(K key);
283
284 protected abstract IK mapKeyForQuery(K key);
285
286 protected abstract IV mapValue(K key, V value);
287
288 protected abstract IV mapValueForQuery(V value);
289
290 protected abstract K unmapKey(IK key);
291
292 protected abstract K unmapKeyForQuery(IK key);
293
294 protected abstract V unmapValue(IV value);
295
296 protected abstract V unmapValueForQuery(IV value);
297
298 protected transient Set<Map.Entry<K, V>> entrySet;
299 protected final ConcurrentMap<IK, IV> innerConcurrentMap;
300 protected transient Set<K> keySet;
301 protected transient Collection<V> values;
302
303 private static final long serialVersionUID = 1L;
304
305 private class UnwrapEntry implements Map.Entry<K, V> {
306
307 public UnwrapEntry(Entry<IK, IV> innerEntry) {
308 _innerEntry = innerEntry;
309 }
310
311 @Override
312 public boolean equals(Object obj) {
313 if (this == obj) {
314 return true;
315 }
316
317 if (!(obj instanceof Map.Entry)) {
318 return false;
319 }
320
321 Map.Entry<K, V> entry = (Map.Entry<K, V>)obj;
322
323 if (Validator.equals(getKey(), entry.getKey()) &&
324 Validator.equals(getValue(), entry.getValue())) {
325
326 return true;
327 }
328
329 return false;
330 }
331
332 @Override
333 public K getKey() {
334 return unmapKeyForQuery(_innerEntry.getKey());
335 }
336
337 @Override
338 public V getValue() {
339 return unmapValueForQuery(_innerEntry.getValue());
340 }
341
342 @Override
343 public int hashCode() {
344 return _innerEntry.hashCode();
345 }
346
347 @Override
348 public V setValue(V value) {
349 K key = getKey();
350
351 V v = unmapValueForQuery(
352 _innerEntry.setValue(mapValueForQuery(value)));
353
354 ConcurrentMapperHashMap.this.put(key, value);
355
356 return v;
357 }
358
359 private final Entry<IK, IV> _innerEntry;
360
361 }
362
363 private class UnwrapEntryIterator implements Iterator<Map.Entry<K, V>> {
364
365 public UnwrapEntryIterator() {
366 Set<Entry<IK, IV>> entrySet = innerConcurrentMap.entrySet();
367
368 _iterator = entrySet.iterator();
369 }
370
371 @Override
372 public boolean hasNext() {
373 return _iterator.hasNext();
374 }
375
376 @Override
377 public Entry<K, V> next() {
378 return new UnwrapEntry(_iterator.next());
379 }
380
381 @Override
382 public void remove() {
383 _iterator.remove();
384 }
385
386 private final Iterator<Map.Entry<IK, IV>> _iterator;
387
388 }
389
390 private class UnwrapEntrySet extends AbstractSet<Map.Entry<K, V>> {
391
392 @Override
393 public void clear() {
394 ConcurrentMapperHashMap.this.clear();
395 }
396
397 @Override
398 public boolean contains(Object obj) {
399 if (!(obj instanceof Map.Entry<?, ?>)) {
400 return false;
401 }
402
403 Map.Entry<K, V> entry = (Map.Entry<K, V>)obj;
404
405 V value = ConcurrentMapperHashMap.this.get(entry.getKey());
406
407 if ((value != null) && value.equals(entry.getValue())) {
408 return true;
409 }
410 else {
411 return false;
412 }
413 }
414
415 @Override
416 public boolean isEmpty() {
417 return ConcurrentMapperHashMap.this.isEmpty();
418 }
419
420 @Override
421 public Iterator<Map.Entry<K, V>> iterator() {
422 return new UnwrapEntryIterator();
423 }
424
425 @Override
426 public boolean remove(Object obj) {
427 if (!(obj instanceof Map.Entry<?, ?>)) {
428 return false;
429 }
430
431 Map.Entry<K, V> entry = (Map.Entry<K, V>)obj;
432
433 return ConcurrentMapperHashMap.this.remove(
434 entry.getKey(), entry.getValue());
435 }
436
437 @Override
438 public int size() {
439 return ConcurrentMapperHashMap.this.size();
440 }
441
442 }
443
444 private class UnwrapKeyIterator implements Iterator<K> {
445
446 public UnwrapKeyIterator() {
447 Set<IK> keySet = innerConcurrentMap.keySet();
448
449 _iterator = keySet.iterator();
450 }
451
452 @Override
453 public boolean hasNext() {
454 return _iterator.hasNext();
455 }
456
457 @Override
458 public K next() {
459 return unmapKeyForQuery(_iterator.next());
460 }
461
462 @Override
463 public void remove() {
464 _iterator.remove();
465 }
466
467 private final Iterator<IK> _iterator;
468
469 }
470
471 private class UnwrapKeySet extends AbstractSet<K> {
472
473 @Override
474 public void clear() {
475 ConcurrentMapperHashMap.this.clear();
476 }
477
478 @Override
479 public boolean contains(Object o) {
480 return ConcurrentMapperHashMap.this.containsKey(o);
481 }
482
483 @Override
484 public boolean isEmpty() {
485 return ConcurrentMapperHashMap.this.isEmpty();
486 }
487
488 @Override
489 public Iterator<K> iterator() {
490 return new UnwrapKeyIterator();
491 }
492
493 @Override
494 public boolean remove(Object o) {
495 if (ConcurrentMapperHashMap.this.remove(o) != null) {
496 return true;
497 }
498
499 return false;
500 }
501
502 @Override
503 public int size() {
504 return ConcurrentMapperHashMap.this.size();
505 }
506
507 }
508
509 private class UnwrapValueIterator implements Iterator<V> {
510
511 public UnwrapValueIterator() {
512 Collection<IV> values = innerConcurrentMap.values();
513
514 _iterator = values.iterator();
515 }
516
517 @Override
518 public boolean hasNext() {
519 return _iterator.hasNext();
520 }
521
522 @Override
523 public V next() {
524 return unmapValueForQuery(_iterator.next());
525 }
526
527 @Override
528 public void remove() {
529 _iterator.remove();
530 }
531
532 private final Iterator<IV> _iterator;
533
534 }
535
536 private class UnwrapValues extends AbstractCollection<V> {
537
538 @Override
539 public void clear() {
540 ConcurrentMapperHashMap.this.clear();
541 }
542
543 @Override
544 public boolean contains(Object obj) {
545 return ConcurrentMapperHashMap.this.containsValue(obj);
546 }
547
548 @Override
549 public boolean isEmpty() {
550 return ConcurrentMapperHashMap.this.isEmpty();
551 }
552
553 @Override
554 public Iterator<V> iterator() {
555 return new UnwrapValueIterator();
556 }
557
558 @Override
559 public int size() {
560 return ConcurrentMapperHashMap.this.size();
561 }
562
563 }
564
565 }