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