001/* 002 * ModeShape (http://www.modeshape.org) 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.modeshape.common.collection; 017 018import java.util.AbstractCollection; 019import java.util.AbstractMap; 020import java.util.AbstractSet; 021import java.util.ArrayList; 022import java.util.Collection; 023import java.util.Collections; 024import java.util.Comparator; 025import java.util.ConcurrentModificationException; 026import java.util.Iterator; 027import java.util.List; 028import java.util.ListIterator; 029import java.util.Map; 030import java.util.Map.Entry; 031import java.util.Optional; 032import java.util.Set; 033import java.util.SortedMap; 034import java.util.SortedSet; 035 036/** 037 * A {@link Multimap} implementation that uses an {@link ArrayList} to store the values associated with a key. This implementation 038 * allows duplicates. 039 * 040 * @param <K> the key type 041 * @param <V> the value type 042 */ 043public abstract class AbstractMultimap<K, V> implements Multimap<K, V> { 044 045 private final Map<K, Collection<V>> data; 046 private int totalSize; 047 private transient Set<K> keysView; 048 private transient Map<K, Collection<V>> mapView; 049 private transient Collection<V> valuesCollection; 050 private transient Collection<Map.Entry<K, V>> entriesCollection; 051 052 protected AbstractMultimap( Map<K, Collection<V>> entries ) { 053 assert entries != null; 054 this.data = entries; 055 } 056 057 protected Map<K, Collection<V>> rawData() { 058 return data; 059 } 060 061 protected abstract Collection<V> createCollection(); 062 063 protected abstract Collection<V> createUnmodifiableEmptyCollection(); 064 065 protected Collection<V> createUnmodifiable( Collection<V> original ) { 066 if (original instanceof List<?>) { 067 return Collections.unmodifiableList((List<V>) original); 068 } 069 if (original instanceof Set<?>) { 070 return Collections.unmodifiableSet((Set<V>) original); 071 } 072 return Collections.unmodifiableCollection(original); 073 } 074 075 @Override 076 public int size() { 077 return totalSize; 078 } 079 080 void incrementSize( int n ) { 081 totalSize += n; 082 } 083 084 void decrementSize( int n ) { 085 totalSize -= n; 086 assert totalSize >= 0; 087 } 088 089 @Override 090 public boolean isEmpty() { 091 return totalSize == 0; 092 } 093 094 @Override 095 public boolean containsKey( K key ) { 096 return data.containsKey(key); 097 } 098 099 @Override 100 public boolean containsValue( Object value ) { 101 return data.values().stream().anyMatch(c -> c.contains(value)); 102 } 103 104 @Override 105 public boolean containsEntry( Object key, 106 Object value ) { 107 Collection<V> values = data.get(key); 108 return values != null && values.contains(value); 109 } 110 111 @Override 112 public Collection<V> get( K key ) { 113 Collection<V> collection = data.get(key); 114 if (collection == null) { 115 collection = createCollection(); 116 } 117 return wrapCollection(key, collection); 118 } 119 120 @Override 121 public boolean put( K key, 122 V value ) { 123 if (getOrCreateCollection(key).add(value)) { 124 incrementSize(1); 125 return true; 126 } 127 return false; 128 } 129 130 protected Collection<V> getOrCreateCollection( K key ) { 131 return data.computeIfAbsent(key, k -> createCollection()); 132 } 133 134 @Override 135 public boolean remove( K key, 136 V value ) { 137 Collection<V> values = data.get(key); 138 if (values == null) return false; 139 140 if (!values.remove(value)) return false; 141 decrementSize(1); 142 if (values.isEmpty()) { 143 data.remove(key); 144 } 145 return true; 146 } 147 148 @Override 149 public Collection<V> removeAll( K key ) { 150 Collection<V> values = data.remove(key); 151 if (values == null) return createUnmodifiableEmptyCollection(); 152 Collection<V> copy = createCollection(); 153 copy.addAll(values); 154 decrementSize(values.size()); 155 values.clear(); 156 return createUnmodifiable(copy); 157 } 158 159 protected boolean removeAllValuesForKey( Object key ) { 160 Collection<V> values = data.remove(key); 161 if (values == null) return false; 162 decrementSize(values.size()); 163 values.clear(); 164 return true; 165 } 166 167 @Override 168 public int hashCode() { 169 return data.hashCode(); 170 } 171 172 @Override 173 public boolean equals( Object obj ) { 174 if (obj == this) return true; 175 return data.equals(obj); 176 } 177 178 @Override 179 public String toString() { 180 return data.toString(); 181 } 182 183 @Override 184 public Set<K> keySet() { 185 if (keysView == null) keysView = wrapKeySet(); 186 return keysView; 187 } 188 189 @Override 190 public void clear() { 191 totalSize = 0; 192 data.clear(); 193 } 194 195 @Override 196 public Map<K, Collection<V>> asMap() { 197 if (mapView == null) mapView = wrapMap(data); 198 return mapView; 199 } 200 201 /** 202 * Return an iterator over all entries in this multimap. 203 * 204 * @return the entry iterator; never null 205 */ 206 protected Iterator<Map.Entry<K, V>> createEntryIterator() { 207 return new EntryIterator(); 208 } 209 210 protected Collection<V> wrapCollection( K key, 211 Collection<V> values ) { 212 if (values instanceof List) { 213 return wrapList(key, (List<V>)values); 214 } 215 return new WrappedCollection(key, values); 216 } 217 218 protected List<V> wrapList( K key, 219 List<V> values ) { 220 return new WrappedList(key, values); 221 } 222 223 protected Map<K, Collection<V>> wrapMap( Map<K, Collection<V>> map ) { 224 return new WrappedMap(map); 225 } 226 227 protected Set<K> wrapKeySet() { 228 if (data instanceof SortedMap) { 229 return new WrappedSortedKeySet((SortedMap<K, Collection<V>>)data); 230 } 231 return new WrappedKeySet(data); 232 } 233 234 @Override 235 public Collection<V> values() { 236 if (valuesCollection == null) valuesCollection = new ValuesCollection(); 237 return valuesCollection; 238 } 239 240 protected final class ValuesCollection extends AbstractCollection<V> { 241 @Override 242 public int size() { 243 return AbstractMultimap.this.size(); 244 } 245 246 @Override 247 public Iterator<V> iterator() { 248 return new ValueIterator(); 249 } 250 251 @Override 252 public void clear() { 253 AbstractMultimap.this.clear(); 254 } 255 256 @Override 257 public boolean contains( Object o ) { 258 return AbstractMultimap.this.containsValue(o); 259 } 260 } 261 262 protected final class ValueIterator implements Iterator<V> { 263 private final Iterator<Map.Entry<K, V>> entryIterator = createEntryIterator(); 264 265 @Override 266 public boolean hasNext() { 267 return entryIterator.hasNext(); 268 } 269 270 @Override 271 public V next() { 272 return entryIterator.next().getValue(); 273 } 274 275 @Override 276 public void remove() { 277 entryIterator.remove(); 278 } 279 } 280 281 @Override 282 public Collection<Entry<K, V>> entries() { 283 if (entriesCollection == null) entriesCollection = new EntriesCollection(); 284 return entriesCollection; 285 } 286 287 protected final class EntryIterator implements Iterator<Map.Entry<K, V>> { 288 private final Iterator<Map.Entry<K, Collection<V>>> iter; 289 protected K currentKey; 290 protected Collection<V> currentValues; 291 protected Iterator<V> currentValuesIterator; 292 293 EntryIterator() { 294 iter = rawData().entrySet().iterator(); 295 if (iter.hasNext()) { 296 nextKey(); 297 } else { 298 currentValuesIterator = new EmptyIterator<>(); 299 } 300 } 301 302 protected void nextKey() { 303 Map.Entry<K, Collection<V>> entry = iter.next(); 304 currentKey = entry.getKey(); 305 currentValues = entry.getValue(); 306 currentValuesIterator = currentValues.iterator(); 307 } 308 309 @Override 310 public boolean hasNext() { 311 return iter.hasNext() || currentValuesIterator.hasNext(); 312 } 313 314 @Override 315 public Entry<K, V> next() { 316 if (!currentValuesIterator.hasNext()) { 317 nextKey(); 318 } 319 return new ImmutableMapEntry<>(currentKey, currentValuesIterator.next()); 320 } 321 322 @SuppressWarnings( "synthetic-access" ) 323 @Override 324 public void remove() { 325 currentValuesIterator.remove(); 326 if (currentValues.isEmpty()) { 327 iter.remove(); 328 } 329 --totalSize; 330 } 331 } 332 333 protected final class EntriesCollection extends AbstractCollection<Map.Entry<K, V>> { 334 @Override 335 public int size() { 336 return AbstractMultimap.this.size(); 337 } 338 339 @Override 340 public Iterator<Map.Entry<K, V>> iterator() { 341 return new EntryIterator(); 342 } 343 344 @Override 345 public void clear() { 346 AbstractMultimap.this.clear(); 347 } 348 349 @Override 350 public boolean contains( Object o ) { 351 if (!(o instanceof Map.Entry)) return false; 352 Map.Entry<?, ?> that = (Map.Entry<?, ?>)o; 353 return AbstractMultimap.this.containsEntry(that.getKey(), that.getValue()); 354 } 355 } 356 357 protected class WrappedCollection implements Collection<V> { 358 private final K key; 359 private Collection<V> delegate; 360 361 protected WrappedCollection( K key, 362 Collection<V> values ) { 363 this.key = key; 364 this.delegate = values; 365 } 366 367 public K getKey() { 368 return key; 369 } 370 371 protected Collection<V> delegate() { 372 if (delegate == null || delegate.isEmpty()) { 373 // Fetch the actual values from the multimap's raw data ... 374 Collection<V> rawValues = rawData().get(key); 375 if (rawValues != null) { 376 // Always use the raw values ... 377 delegate = rawValues; 378 } 379 } 380 return delegate; 381 } 382 383 protected final void removeIfEmpty() { 384 if (delegate != null && delegate.isEmpty()) { 385 AbstractMultimap.this.removeAll(key); 386 delegate = null; 387 } 388 } 389 390 protected final void addToMap() { 391 rawData().put(key, delegate); 392 } 393 394 @Override 395 public int size() { 396 Collection<V> d = delegate(); 397 return d == null ? 0 : d.size(); 398 } 399 400 @Override 401 public boolean isEmpty() { 402 Collection<V> d = delegate(); 403 return d == null || d.isEmpty(); 404 } 405 406 @Override 407 public boolean contains( Object o ) { 408 Collection<V> d = delegate(); 409 return d != null && d.contains(o); 410 } 411 412 @Override 413 public Iterator<V> iterator() { 414 return new DelegateIterator(); 415 } 416 417 @Override 418 public Object[] toArray() { 419 // The size of the values (and thus the multimap) cannot be changed via the resulting array, so no need to wrap ... 420 return delegate().toArray(); 421 } 422 423 @Override 424 public <T> T[] toArray( T[] a ) { 425 // The size of the values (and thus the multimap) cannot be changed via the resulting array, so no need to wrap ... 426 return delegate().toArray(a); 427 } 428 429 @Override 430 public boolean add( V e ) { 431 boolean wasEmpty = isEmpty(); 432 try { 433 return AbstractMultimap.this.put(key, e); 434 } finally { 435 if (wasEmpty) { 436 delegate(); 437 } 438 } 439 } 440 441 @Override 442 public boolean remove( Object o ) { 443 Collection<V> d = delegate(); 444 if (d == null || !d.remove(o)) return false; 445 decrementSize(1); 446 removeIfEmpty(); 447 return true; 448 } 449 450 @Override 451 public boolean containsAll( Collection<?> c ) { 452 return delegate().containsAll(c); 453 } 454 455 @Override 456 public boolean addAll( Collection<? extends V> c ) { 457 if (c.isEmpty()) return false; 458 if (isEmpty()) getOrCreateCollection(key); 459 Collection<V> d = delegate(); 460 int sizeBefore = d.size(); 461 if (!d.addAll(c)) return false; 462 incrementSize(d.size() - sizeBefore); 463 return true; 464 } 465 466 @Override 467 public boolean removeAll( Collection<?> c ) { 468 if (c.isEmpty() || isEmpty()) { 469 return false; 470 } 471 Collection<V> d = delegate(); 472 int sizeBefore = d.size(); 473 if (!d.removeAll(c)) return false; 474 incrementSize(d.size() - sizeBefore); // will be negative 475 removeIfEmpty(); 476 return true; 477 } 478 479 @Override 480 public boolean retainAll( Collection<?> c ) { 481 if (isEmpty()) { 482 return false; 483 } 484 Collection<V> d = delegate(); 485 int sizeBefore = d.size(); 486 if (!d.retainAll(c)) return false; 487 int diff = d.size() - sizeBefore; 488 incrementSize(diff); // will change correctly if diff is negative 489 return true; 490 } 491 492 @Override 493 public void clear() { 494 if (isEmpty()) return; 495 Collection<V> d = delegate(); 496 int sizeBefore = d.size(); 497 d.clear(); 498 decrementSize(sizeBefore); 499 removeIfEmpty(); 500 } 501 502 @Override 503 public int hashCode() { 504 return isEmpty() ? Collections.EMPTY_SET.hashCode() : delegate().hashCode(); 505 } 506 507 @Override 508 public boolean equals( Object obj ) { 509 return obj == this 510 || Optional.ofNullable(delegate()).orElseGet(AbstractMultimap.this::createUnmodifiableEmptyCollection).equals(obj); 511 } 512 513 @Override 514 public String toString() { 515 return delegate().toString(); 516 } 517 518 protected class DelegateIterator implements Iterator<V> { 519 private final Iterator<V> iterator; 520 private Collection<V> source; 521 522 protected DelegateIterator() { 523 source = delegate(); 524 iterator = source instanceof List ? ((List<V>)source).listIterator() : source.iterator(); 525 } 526 527 protected DelegateIterator( int index ) { 528 this.source = delegate(); 529 iterator = source instanceof List ? ((List<V>)source).listIterator(index) : source.iterator(); 530 } 531 532 protected Iterator<V> iterator() { 533 if (source != delegate()) { 534 throw new ConcurrentModificationException(); 535 } 536 return iterator; 537 } 538 539 @Override 540 public boolean hasNext() { 541 return iterator().hasNext(); 542 } 543 544 @Override 545 public V next() { 546 return iterator.next(); 547 } 548 549 @Override 550 public void remove() { 551 iterator.remove(); 552 decrementSize(1); 553 removeIfEmpty(); 554 if (isEmpty()) { 555 source = null; 556 } 557 } 558 } 559 } 560 561 protected class WrappedList extends WrappedCollection implements List<V> { 562 563 protected WrappedList( K key, 564 Collection<V> values ) { 565 super(key, values); 566 } 567 568 @Override 569 protected List<V> delegate() { 570 return (List<V>)super.delegate(); 571 } 572 573 @Override 574 public boolean addAll( int index, 575 Collection<? extends V> c ) { 576 if (c.isEmpty()) return false; 577 List<V> delegate = delegate(); 578 int sizeBefore = delegate.size(); 579 if (!delegate.addAll(index, c)) return false; 580 incrementSize(delegate.size() - sizeBefore); 581 if (sizeBefore == 0) addToMap(); 582 return true; 583 } 584 585 @Override 586 public V get( int index ) { 587 return delegate().get(index); 588 } 589 590 @Override 591 public V set( int index, 592 V element ) { 593 return delegate().set(index, element); 594 } 595 596 @Override 597 public void add( int index, 598 V element ) { 599 List<V> values = delegate(); 600 boolean wasEmpty = values.isEmpty(); 601 values.add(index, element); 602 incrementSize(1); 603 if (wasEmpty) addToMap(); 604 } 605 606 @Override 607 public V remove( int index ) { 608 V removed = delegate().remove(index); 609 decrementSize(1); 610 removeIfEmpty(); 611 return removed; 612 } 613 614 @Override 615 public int indexOf( Object o ) { 616 return delegate().indexOf(o); 617 } 618 619 @Override 620 public int lastIndexOf( Object o ) { 621 return delegate().lastIndexOf(o); 622 } 623 624 @Override 625 public ListIterator<V> listIterator() { 626 return new DelegateListIterator(); 627 } 628 629 @Override 630 public ListIterator<V> listIterator( int index ) { 631 return new DelegateListIterator(index); 632 } 633 634 @Override 635 public List<V> subList( int fromIndex, 636 int toIndex ) { 637 List<V> valueSublist = delegate().subList(fromIndex, toIndex); 638 return wrapList(getKey(), valueSublist); 639 } 640 641 /** 642 * {@inheritDoc} 643 * 644 * @see org.modeshape.common.collection.AbstractMultimap.WrappedCollection#hashCode() 645 */ 646 @Override 647 public int hashCode() { 648 return isEmpty() ? Collections.EMPTY_LIST.hashCode() : delegate().hashCode(); 649 } 650 651 protected class DelegateListIterator extends DelegateIterator implements ListIterator<V> { 652 653 protected DelegateListIterator() { 654 super(); 655 } 656 657 protected DelegateListIterator( int index ) { 658 super(index); 659 } 660 661 @Override 662 protected ListIterator<V> iterator() { 663 return (ListIterator<V>)super.iterator(); 664 } 665 666 @Override 667 public boolean hasPrevious() { 668 return iterator().hasPrevious(); 669 } 670 671 @Override 672 public void add( V e ) { 673 iterator().add(e); 674 incrementSize(1); 675 676 } 677 678 @Override 679 public int nextIndex() { 680 return iterator().nextIndex(); 681 } 682 683 @Override 684 public V previous() { 685 return iterator().previous(); 686 } 687 688 @Override 689 public int previousIndex() { 690 return iterator().previousIndex(); 691 } 692 693 @Override 694 public void set( V e ) { 695 iterator().set(e); 696 } 697 } 698 } 699 700 protected class WrappedMap extends AbstractMap<K, Collection<V>> { 701 702 private transient Set<Map.Entry<K, Collection<V>>> entries; 703 private Map<K, Collection<V>> delegate; 704 705 protected WrappedMap( Map<K, Collection<V>> wrapped ) { 706 this.delegate = wrapped; 707 } 708 709 @Override 710 public Set<Map.Entry<K, Collection<V>>> entrySet() { 711 if (entries == null) entries = new WrappedEntrySet(); 712 return entries; 713 } 714 715 protected Map<K, Collection<V>> delegate() { 716 return delegate; 717 } 718 719 @Override 720 public int hashCode() { 721 return delegate.hashCode(); 722 } 723 724 @Override 725 public boolean equals( Object o ) { 726 if (o == this) return true; 727 return delegate.equals(o); 728 } 729 730 @Override 731 public String toString() { 732 return delegate.toString(); 733 } 734 735 @SuppressWarnings( "unchecked" ) 736 @Override 737 public Collection<V> get( Object key ) { 738 return AbstractMultimap.this.get((K)key); 739 } 740 741 @Override 742 public Collection<V> remove( Object key ) { 743 Collection<V> values = rawData().remove(key); 744 if (values != null) { 745 // Now create a copy of the data, since someone might be holding a reference to the existing values ... 746 Collection<V> copy = createCollection(); 747 copy.addAll(values); 748 decrementSize(values.size()); 749 values.clear(); // in case anyone is holding onto this collection ... 750 values = copy; 751 } 752 return values; // may be null 753 } 754 755 protected class WrappedEntrySet extends AbstractSet<Map.Entry<K, Collection<V>>> { 756 757 @Override 758 public Iterator<Map.Entry<K, Collection<V>>> iterator() { 759 return new WrappedMapEntryIterator(); 760 } 761 762 @Override 763 public int size() { 764 return delegate().size(); 765 } 766 767 @Override 768 public boolean contains( Object o ) { 769 // Faster if we do this directly against the delegate ... 770 return delegate().entrySet().contains(o); 771 } 772 773 @Override 774 public boolean remove( Object o ) { 775 if (!contains(o)) return false; 776 // Faster if we do this directly against the delegate ... 777 Map.Entry<?, ?> entry = (Map.Entry<?, ?>)o; 778 removeAllValuesForKey(entry.getKey()); 779 return true; 780 } 781 } 782 783 protected class WrappedMapEntryIterator implements Iterator<Map.Entry<K, Collection<V>>> { 784 private final Iterator<Map.Entry<K, Collection<V>>> delegateIterator = delegate().entrySet().iterator(); 785 private Collection<V> currentValues = null; 786 787 @Override 788 public boolean hasNext() { 789 return delegateIterator.hasNext(); 790 } 791 792 @Override 793 public Map.Entry<K, Collection<V>> next() { 794 Map.Entry<K, Collection<V>> currentEntry = delegateIterator.next(); 795 currentValues = currentEntry.getValue(); 796 K key = currentEntry.getKey(); 797 return new ImmutableMapEntry<>(key, wrapCollection(key, currentValues)); 798 } 799 800 @Override 801 public void remove() { 802 // Remove the current value collection ... 803 delegateIterator.remove(); 804 // Update the total size of the multimap ... 805 decrementSize(currentValues.size()); 806 // and clear the values ... 807 currentValues.clear(); 808 } 809 } 810 } 811 812 protected class WrappedKeySet extends AbstractSet<K> { 813 814 private final Map<K, Collection<V>> delegate; 815 816 protected WrappedKeySet( Map<K, Collection<V>> wrapped ) { 817 this.delegate = wrapped; 818 } 819 820 @Override 821 public int size() { 822 return this.delegate.size(); 823 } 824 825 @Override 826 public boolean remove( Object o ) { 827 return removeAllValuesForKey(o); 828 } 829 830 @Override 831 public boolean contains( Object o ) { 832 return this.delegate.containsKey(o); 833 } 834 835 @Override 836 public boolean containsAll( Collection<?> c ) { 837 return this.delegate.keySet().containsAll(c); 838 } 839 840 @SuppressWarnings( "synthetic-access" ) 841 @Override 842 public void clear() { 843 this.delegate.clear(); 844 totalSize = 0; 845 } 846 847 @Override 848 public Iterator<K> iterator() { 849 final Map<K, Collection<V>> delegate = this.delegate; 850 return new Iterator<K>() { 851 private final Iterator<Map.Entry<K, Collection<V>>> entryIter = delegate.entrySet().iterator(); 852 private Map.Entry<K, Collection<V>> currentEntry; 853 854 @Override 855 public boolean hasNext() { 856 return entryIter.hasNext(); 857 } 858 859 @Override 860 public K next() { 861 currentEntry = entryIter.next(); 862 return currentEntry.getKey(); 863 } 864 865 @Override 866 public void remove() { 867 entryIter.remove(); 868 Collection<V> values = currentEntry.getValue(); 869 decrementSize(values.size()); 870 values.clear(); 871 } 872 }; 873 } 874 } 875 876 protected class WrappedSortedKeySet extends WrappedKeySet implements SortedSet<K> { 877 878 private SortedMap<K, Collection<V>> sortedDelegate; 879 880 protected WrappedSortedKeySet( SortedMap<K, Collection<V>> wrapped ) { 881 super(wrapped); 882 sortedDelegate = wrapped; 883 } 884 885 @Override 886 public Comparator<? super K> comparator() { 887 return sortedDelegate.comparator(); 888 } 889 890 @Override 891 public SortedSet<K> subSet( K fromElement, 892 K toElement ) { 893 return new WrappedSortedKeySet(sortedDelegate.subMap(fromElement, toElement)); 894 } 895 896 @Override 897 public SortedSet<K> headSet( K toElement ) { 898 return new WrappedSortedKeySet(sortedDelegate.headMap(toElement)); 899 } 900 901 @Override 902 public SortedSet<K> tailSet( K fromElement ) { 903 return new WrappedSortedKeySet(sortedDelegate.tailMap(fromElement)); 904 } 905 906 @Override 907 public K first() { 908 return sortedDelegate.firstKey(); 909 } 910 911 @Override 912 public K last() { 913 return sortedDelegate.lastKey(); 914 } 915 } 916 917}