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