1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.collections4.bidimap;
18
19 import java.util.Collection;
20 import java.util.Iterator;
21 import java.util.Map;
22 import java.util.Objects;
23 import java.util.Set;
24 import java.util.function.Predicate;
25
26 import org.apache.commons.collections4.BidiMap;
27 import org.apache.commons.collections4.MapIterator;
28 import org.apache.commons.collections4.ResettableIterator;
29 import org.apache.commons.collections4.collection.AbstractCollectionDecorator;
30 import org.apache.commons.collections4.iterators.AbstractIteratorDecorator;
31 import org.apache.commons.collections4.keyvalue.AbstractMapEntryDecorator;
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 public abstract class AbstractDualBidiMap<K, V> implements BidiMap<K, V> {
47
48
49
50
51
52
53
54 protected static class BidiMapIterator<K, V> implements MapIterator<K, V>, ResettableIterator<K> {
55
56
57 protected final AbstractDualBidiMap<K, V> parent;
58
59
60 protected Iterator<Map.Entry<K, V>> iterator;
61
62
63 protected Map.Entry<K, V> last;
64
65
66 protected boolean canRemove;
67
68
69
70
71
72 protected BidiMapIterator(final AbstractDualBidiMap<K, V> parent) {
73 this.parent = parent;
74 this.iterator = parent.normalMap.entrySet().iterator();
75 }
76
77 @Override
78 public K getKey() {
79 if (last == null) {
80 throw new IllegalStateException(
81 "Iterator getKey() can only be called after next() and before remove()");
82 }
83 return last.getKey();
84 }
85
86 @Override
87 public V getValue() {
88 if (last == null) {
89 throw new IllegalStateException(
90 "Iterator getValue() can only be called after next() and before remove()");
91 }
92 return last.getValue();
93 }
94
95 @Override
96 public boolean hasNext() {
97 return iterator.hasNext();
98 }
99
100 @Override
101 public K next() {
102 last = iterator.next();
103 canRemove = true;
104 return last.getKey();
105 }
106
107 @Override
108 public void remove() {
109 if (!canRemove) {
110 throw new IllegalStateException("Iterator remove() can only be called once after next()");
111 }
112
113 final V value = last.getValue();
114 iterator.remove();
115 parent.reverseMap.remove(value);
116 last = null;
117 canRemove = false;
118 }
119
120 @Override
121 public void reset() {
122 iterator = parent.normalMap.entrySet().iterator();
123 last = null;
124 canRemove = false;
125 }
126
127 @Override
128 public V setValue(final V value) {
129 if (last == null) {
130 throw new IllegalStateException(
131 "Iterator setValue() can only be called after next() and before remove()");
132 }
133 if (parent.reverseMap.containsKey(value) &&
134 parent.reverseMap.get(value) != last.getKey()) {
135 throw new IllegalArgumentException(
136 "Cannot use setValue() when the object being set is already in the map");
137 }
138 return parent.put(last.getKey(), value);
139 }
140
141 @Override
142 public String toString() {
143 if (last != null) {
144 return "MapIterator[" + getKey() + "=" + getValue() + "]";
145 }
146 return "MapIterator[]";
147 }
148 }
149
150
151
152
153
154
155
156 protected static class EntrySet<K, V> extends View<K, V, Map.Entry<K, V>> implements Set<Map.Entry<K, V>> {
157
158
159 private static final long serialVersionUID = 4040410962603292348L;
160
161
162
163
164
165
166 protected EntrySet(final AbstractDualBidiMap<K, V> parent) {
167 super(parent.normalMap.entrySet(), parent);
168 }
169
170 @Override
171 public Iterator<Map.Entry<K, V>> iterator() {
172 return parent.createEntrySetIterator(super.iterator());
173 }
174
175 @Override
176 public boolean remove(final Object obj) {
177 if (!(obj instanceof Map.Entry)) {
178 return false;
179 }
180 final Map.Entry<?, ?> entry = (Map.Entry<?, ?>) obj;
181 final Object key = entry.getKey();
182 if (parent.containsKey(key)) {
183 final V value = parent.normalMap.get(key);
184 if (Objects.equals(value, entry.getValue())) {
185 parent.normalMap.remove(key);
186 parent.reverseMap.remove(value);
187 return true;
188 }
189 }
190 return false;
191 }
192 }
193
194
195
196
197
198
199
200 protected static class EntrySetIterator<K, V> extends AbstractIteratorDecorator<Map.Entry<K, V>> {
201
202
203 protected final AbstractDualBidiMap<K, V> parent;
204
205
206 protected Map.Entry<K, V> last;
207
208
209 protected boolean canRemove;
210
211
212
213
214
215
216 protected EntrySetIterator(final Iterator<Map.Entry<K, V>> iterator, final AbstractDualBidiMap<K, V> parent) {
217 super(iterator);
218 this.parent = parent;
219 }
220
221 @Override
222 public Map.Entry<K, V> next() {
223 last = new MapEntry<>(super.next(), parent);
224 canRemove = true;
225 return last;
226 }
227
228 @Override
229 public void remove() {
230 if (!canRemove) {
231 throw new IllegalStateException("Iterator remove() can only be called once after next()");
232 }
233
234 final Object value = last.getValue();
235 super.remove();
236 parent.reverseMap.remove(value);
237 last = null;
238 canRemove = false;
239 }
240 }
241
242
243
244
245
246
247 protected static class KeySet<K> extends View<K, Object, K> implements Set<K> {
248
249
250 private static final long serialVersionUID = -7107935777385040694L;
251
252
253
254
255
256
257 @SuppressWarnings("unchecked")
258 protected KeySet(final AbstractDualBidiMap<K, ?> parent) {
259 super(parent.normalMap.keySet(), (AbstractDualBidiMap<K, Object>) parent);
260 }
261
262 @Override
263 public boolean contains(final Object key) {
264 return parent.normalMap.containsKey(key);
265 }
266
267 @Override
268 public Iterator<K> iterator() {
269 return parent.createKeySetIterator(super.iterator());
270 }
271
272 @Override
273 public boolean remove(final Object key) {
274 if (parent.normalMap.containsKey(key)) {
275 final Object value = parent.normalMap.remove(key);
276 parent.reverseMap.remove(value);
277 return true;
278 }
279 return false;
280 }
281 }
282
283
284
285
286
287
288 protected static class KeySetIterator<K> extends AbstractIteratorDecorator<K> {
289
290
291 protected final AbstractDualBidiMap<K, ?> parent;
292
293
294 protected K lastKey;
295
296
297 protected boolean canRemove;
298
299
300
301
302
303
304 protected KeySetIterator(final Iterator<K> iterator, final AbstractDualBidiMap<K, ?> parent) {
305 super(iterator);
306 this.parent = parent;
307 }
308
309 @Override
310 public K next() {
311 lastKey = super.next();
312 canRemove = true;
313 return lastKey;
314 }
315
316 @Override
317 public void remove() {
318 if (!canRemove) {
319 throw new IllegalStateException("Iterator remove() can only be called once after next()");
320 }
321 final Object value = parent.normalMap.get(lastKey);
322 super.remove();
323 parent.reverseMap.remove(value);
324 lastKey = null;
325 canRemove = false;
326 }
327 }
328
329
330
331
332
333
334
335 protected static class MapEntry<K, V> extends AbstractMapEntryDecorator<K, V> {
336
337
338 protected final AbstractDualBidiMap<K, V> parent;
339
340
341
342
343
344
345 protected MapEntry(final Map.Entry<K, V> entry, final AbstractDualBidiMap<K, V> parent) {
346 super(entry);
347 this.parent = parent;
348 }
349
350 @Override
351 public V setValue(final V value) {
352 final K key = getKey();
353 if (parent.reverseMap.containsKey(value) &&
354 parent.reverseMap.get(value) != key) {
355 throw new IllegalArgumentException(
356 "Cannot use setValue() when the object being set is already in the map");
357 }
358 parent.put(key, value);
359 return super.setValue(value);
360 }
361 }
362
363
364
365
366
367
368 protected static class Values<V> extends View<Object, V, V> implements Set<V> {
369
370
371 private static final long serialVersionUID = 4023777119829639864L;
372
373
374
375
376
377
378 @SuppressWarnings("unchecked")
379 protected Values(final AbstractDualBidiMap<?, V> parent) {
380 super(parent.normalMap.values(), (AbstractDualBidiMap<Object, V>) parent);
381 }
382
383 @Override
384 public boolean contains(final Object value) {
385 return parent.reverseMap.containsKey(value);
386 }
387
388 @Override
389 public Iterator<V> iterator() {
390 return parent.createValuesIterator(super.iterator());
391 }
392
393 @Override
394 public boolean remove(final Object value) {
395 if (parent.reverseMap.containsKey(value)) {
396 final Object key = parent.reverseMap.remove(value);
397 parent.normalMap.remove(key);
398 return true;
399 }
400 return false;
401 }
402 }
403
404
405
406
407
408
409 protected static class ValuesIterator<V> extends AbstractIteratorDecorator<V> {
410
411
412 protected final AbstractDualBidiMap<Object, V> parent;
413
414
415 protected V lastValue;
416
417
418 protected boolean canRemove;
419
420
421
422
423
424
425 @SuppressWarnings("unchecked")
426 protected ValuesIterator(final Iterator<V> iterator, final AbstractDualBidiMap<?, V> parent) {
427 super(iterator);
428 this.parent = (AbstractDualBidiMap<Object, V>) parent;
429 }
430
431 @Override
432 public V next() {
433 lastValue = super.next();
434 canRemove = true;
435 return lastValue;
436 }
437
438 @Override
439 public void remove() {
440 if (!canRemove) {
441 throw new IllegalStateException("Iterator remove() can only be called once after next()");
442 }
443 super.remove();
444 parent.reverseMap.remove(lastValue);
445 lastValue = null;
446 canRemove = false;
447 }
448 }
449
450
451
452
453
454
455
456
457 protected abstract static class View<K, V, E> extends AbstractCollectionDecorator<E> {
458
459
460 private static final long serialVersionUID = 4621510560119690639L;
461
462
463 protected final AbstractDualBidiMap<K, V> parent;
464
465
466
467
468
469
470
471 protected View(final Collection<E> coll, final AbstractDualBidiMap<K, V> parent) {
472 super(coll);
473 this.parent = parent;
474 }
475
476 @Override
477 public void clear() {
478 parent.clear();
479 }
480
481 @Override
482 public boolean equals(final Object object) {
483 return object == this || decorated().equals(object);
484 }
485
486 @Override
487 public int hashCode() {
488 return decorated().hashCode();
489 }
490
491 @Override
492 public boolean removeAll(final Collection<?> coll) {
493 if (parent.isEmpty() || coll.isEmpty()) {
494 return false;
495 }
496 boolean modified = false;
497 for (final Object current : coll) {
498 modified |= remove(current);
499 }
500 return modified;
501 }
502
503
504
505
506 @Override
507 public boolean removeIf(final Predicate<? super E> filter) {
508 if (parent.isEmpty() || Objects.isNull(filter)) {
509 return false;
510 }
511 boolean modified = false;
512 final Iterator<?> it = iterator();
513 while (it.hasNext()) {
514 @SuppressWarnings("unchecked")
515 final E e = (E) it.next();
516 if (filter.test(e)) {
517 it.remove();
518 modified = true;
519 }
520 }
521 return modified;
522 }
523
524
525
526
527
528
529
530
531
532
533 @Override
534 public boolean retainAll(final Collection<?> coll) {
535 if (parent.isEmpty()) {
536 return false;
537 }
538 if (coll.isEmpty()) {
539 parent.clear();
540 return true;
541 }
542 boolean modified = false;
543 final Iterator<E> it = iterator();
544 while (it.hasNext()) {
545 if (!coll.contains(it.next())) {
546 it.remove();
547 modified = true;
548 }
549 }
550 return modified;
551 }
552 }
553
554
555
556
557 transient Map<K, V> normalMap;
558
559
560
561
562
563
564 transient Map<V, K> reverseMap;
565
566
567
568
569 transient BidiMap<V, K> inverseBidiMap;
570
571
572
573
574 transient Set<K> keySet;
575
576
577
578
579 transient Set<V> values;
580
581
582
583
584 transient Set<Map.Entry<K, V>> entrySet;
585
586
587
588
589
590
591
592
593 protected AbstractDualBidiMap() {
594 }
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610 protected AbstractDualBidiMap(final Map<K, V> normalMap, final Map<V, K> reverseMap) {
611 this.normalMap = normalMap;
612 this.reverseMap = reverseMap;
613 }
614
615
616
617
618
619
620
621
622
623
624
625 protected AbstractDualBidiMap(final Map<K, V> normalMap, final Map<V, K> reverseMap,
626 final BidiMap<V, K> inverseBidiMap) {
627 this.normalMap = normalMap;
628 this.reverseMap = reverseMap;
629 this.inverseBidiMap = inverseBidiMap;
630 }
631
632 @Override
633 public void clear() {
634 normalMap.clear();
635 reverseMap.clear();
636 }
637
638 @Override
639 public boolean containsKey(final Object key) {
640 return normalMap.containsKey(key);
641 }
642
643 @Override
644 public boolean containsValue(final Object value) {
645 return reverseMap.containsKey(value);
646 }
647
648
649
650
651
652
653
654
655
656 protected abstract BidiMap<V, K> createBidiMap(Map<V, K> normalMap, Map<K, V> reverseMap, BidiMap<K, V> inverseMap);
657
658
659
660
661
662
663
664
665 protected Iterator<Map.Entry<K, V>> createEntrySetIterator(final Iterator<Map.Entry<K, V>> iterator) {
666 return new EntrySetIterator<>(iterator, this);
667 }
668
669
670
671
672
673
674
675
676 protected Iterator<K> createKeySetIterator(final Iterator<K> iterator) {
677 return new KeySetIterator<>(iterator, this);
678 }
679
680
681
682
683
684
685
686
687 protected Iterator<V> createValuesIterator(final Iterator<V> iterator) {
688 return new ValuesIterator<>(iterator, this);
689 }
690
691
692
693
694
695
696
697
698
699
700
701
702
703 @Override
704 public Set<Map.Entry<K, V>> entrySet() {
705 if (entrySet == null) {
706 entrySet = new EntrySet<>(this);
707 }
708 return entrySet;
709 }
710
711 @Override
712 public boolean equals(final Object obj) {
713 return normalMap.equals(obj);
714 }
715
716 @Override
717 public V get(final Object key) {
718 return normalMap.get(key);
719 }
720
721 @Override
722 public K getKey(final Object value) {
723 return reverseMap.get(value);
724 }
725
726 @Override
727 public int hashCode() {
728 return normalMap.hashCode();
729 }
730
731 @Override
732 public BidiMap<V, K> inverseBidiMap() {
733 if (inverseBidiMap == null) {
734 inverseBidiMap = createBidiMap(reverseMap, normalMap, this);
735 }
736 return inverseBidiMap;
737 }
738
739 @Override
740 public boolean isEmpty() {
741 return normalMap.isEmpty();
742 }
743
744
745
746
747
748
749
750
751
752 @Override
753 public Set<K> keySet() {
754 if (keySet == null) {
755 keySet = new KeySet<>(this);
756 }
757 return keySet;
758 }
759
760
761
762
763
764
765
766
767
768 @Override
769 public MapIterator<K, V> mapIterator() {
770 return new BidiMapIterator<>(this);
771 }
772
773 @Override
774 public V put(final K key, final V value) {
775 if (normalMap.containsKey(key)) {
776 reverseMap.remove(normalMap.get(key));
777 }
778 if (reverseMap.containsKey(value)) {
779 normalMap.remove(reverseMap.get(value));
780 }
781 final V obj = normalMap.put(key, value);
782 reverseMap.put(value, key);
783 return obj;
784 }
785
786 @Override
787 public void putAll(final Map<? extends K, ? extends V> map) {
788 for (final Map.Entry<? extends K, ? extends V> entry : map.entrySet()) {
789 put(entry.getKey(), entry.getValue());
790 }
791 }
792
793 @Override
794 public V remove(final Object key) {
795 V value = null;
796 if (normalMap.containsKey(key)) {
797 value = normalMap.remove(key);
798 reverseMap.remove(value);
799 }
800 return value;
801 }
802
803 @Override
804 public K removeValue(final Object value) {
805 K key = null;
806 if (reverseMap.containsKey(value)) {
807 key = reverseMap.remove(value);
808 normalMap.remove(key);
809 }
810 return key;
811 }
812
813 @Override
814 public int size() {
815 return normalMap.size();
816 }
817
818 @Override
819 public String toString() {
820 return normalMap.toString();
821 }
822
823
824
825
826
827
828
829
830 @Override
831 public Set<V> values() {
832 if (values == null) {
833 values = new Values<>(this);
834 }
835 return values;
836 }
837
838 }