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