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}