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