001    /*
002     * Copyright (C) 2008 The Guava Authors
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     */
016    
017    package com.google.common.collect;
018    
019    import static com.google.common.base.Preconditions.checkNotNull;
020    
021    import com.google.common.annotations.Beta;
022    import com.google.common.annotations.GwtCompatible;
023    import com.google.common.annotations.GwtIncompatible;
024    
025    import java.io.Serializable;
026    import java.util.Arrays;
027    import java.util.Collection;
028    import java.util.Collections;
029    import java.util.Comparator;
030    import java.util.Iterator;
031    import java.util.LinkedHashMap;
032    import java.util.List;
033    import java.util.Map;
034    import java.util.TreeMap;
035    
036    import javax.annotation.Nullable;
037    
038    /**
039     * An immutable {@link Multimap}. Does not permit null keys or values.
040     *
041     * <p>Unlike {@link Multimaps#unmodifiableMultimap(Multimap)}, which is
042     * a <i>view</i> of a separate multimap which can still change, an instance of
043     * {@code ImmutableMultimap} contains its own data and will <i>never</i>
044     * change. {@code ImmutableMultimap} is convenient for
045     * {@code public static final} multimaps ("constant multimaps") and also lets
046     * you easily make a "defensive copy" of a multimap provided to your class by
047     * a caller.
048     *
049     * <p><b>Note</b>: Although this class is not final, it cannot be subclassed as
050     * it has no public or protected constructors. Thus, instances of this class
051     * are guaranteed to be immutable.
052     *
053     * @author Jared Levy
054     * @since 2 (imported from Google Collections Library)
055     */
056    @GwtCompatible(emulated = true)
057    public abstract class ImmutableMultimap<K, V>
058        implements Multimap<K, V>, Serializable {
059    
060      /** Returns an empty multimap. */
061      public static <K, V> ImmutableMultimap<K, V> of() {
062        return ImmutableListMultimap.of();
063      }
064    
065      /**
066       * Returns an immutable multimap containing a single entry.
067       */
068      public static <K, V> ImmutableMultimap<K, V> of(K k1, V v1) {
069        return ImmutableListMultimap.of(k1, v1);
070      }
071    
072      /**
073       * Returns an immutable multimap containing the given entries, in order.
074       */
075      public static <K, V> ImmutableMultimap<K, V> of(K k1, V v1, K k2, V v2) {
076        return ImmutableListMultimap.of(k1, v1, k2, v2);
077      }
078    
079      /**
080       * Returns an immutable multimap containing the given entries, in order.
081       */
082      public static <K, V> ImmutableMultimap<K, V> of(
083          K k1, V v1, K k2, V v2, K k3, V v3) {
084        return ImmutableListMultimap.of(k1, v1, k2, v2, k3, v3);
085      }
086    
087      /**
088       * Returns an immutable multimap containing the given entries, in order.
089       */
090      public static <K, V> ImmutableMultimap<K, V> of(
091          K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
092        return ImmutableListMultimap.of(k1, v1, k2, v2, k3, v3, k4, v4);
093      }
094    
095      /**
096       * Returns an immutable multimap containing the given entries, in order.
097       */
098      public static <K, V> ImmutableMultimap<K, V> of(
099          K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
100        return ImmutableListMultimap.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5);
101      }
102    
103      // looking for of() with > 5 entries? Use the builder instead.
104    
105      /**
106       * Returns a new builder. The generated builder is equivalent to the builder
107       * created by the {@link Builder} constructor.
108       */
109      public static <K, V> Builder<K, V> builder() {
110        return new Builder<K, V>();
111      }
112    
113      /**
114       * Multimap for {@link ImmutableMultimap.Builder} that maintains key and
115       * value orderings, allows duplicate values, and performs better than
116       * {@link LinkedListMultimap}.
117       */
118      private static class BuilderMultimap<K, V> extends AbstractMultimap<K, V> {
119        BuilderMultimap() {
120          super(new LinkedHashMap<K, Collection<V>>());
121        }
122        @Override Collection<V> createCollection() {
123          return Lists.newArrayList();
124        }
125        private static final long serialVersionUID = 0;
126      }
127    
128      /**
129       * Multimap for {@link ImmutableMultimap.Builder} that sorts key and allows
130       * duplicate values,
131       */
132      private static class SortedKeyBuilderMultimap<K, V> 
133          extends AbstractMultimap<K, V> {
134        SortedKeyBuilderMultimap(
135            Comparator<? super K> keyComparator, Multimap<K, V> multimap) {
136          super(new TreeMap<K, Collection<V>>(keyComparator));
137          putAll(multimap);
138        }
139        @Override Collection<V> createCollection() {
140          return Lists.newArrayList();
141        }
142        private static final long serialVersionUID = 0;
143      }
144      
145      /**
146       * A builder for creating immutable multimap instances, especially
147       * {@code public static final} multimaps ("constant multimaps"). Example:
148       * <pre>   {@code
149       *
150       *   static final Multimap<String, Integer> STRING_TO_INTEGER_MULTIMAP =
151       *       new ImmutableMultimap.Builder<String, Integer>()
152       *           .put("one", 1)
153       *           .putAll("several", 1, 2, 3)
154       *           .putAll("many", 1, 2, 3, 4, 5)
155       *           .build();}</pre>
156       *
157       * Builder instances can be reused; it is safe to call {@link #build} multiple
158       * times to build multiple multimaps in series. Each multimap contains the
159       * key-value mappings in the previously created multimaps.
160       *
161       * @since 2 (imported from Google Collections Library)
162       */
163      public static class Builder<K, V> {
164        Multimap<K, V> builderMultimap = new BuilderMultimap<K, V>();
165        Comparator<? super V> valueComparator;
166    
167        /**
168         * Creates a new builder. The returned builder is equivalent to the builder
169         * generated by {@link ImmutableMultimap#builder}.
170         */
171        public Builder() {}
172    
173        /**
174         * Adds a key-value mapping to the built multimap.
175         */
176        public Builder<K, V> put(K key, V value) {
177          builderMultimap.put(checkNotNull(key), checkNotNull(value));
178          return this;
179        }
180    
181        /**
182         * Stores a collection of values with the same key in the built multimap.
183         *
184         * @throws NullPointerException if {@code key}, {@code values}, or any
185         *     element in {@code values} is null. The builder is left in an invalid
186         *     state.
187         */
188        public Builder<K, V> putAll(K key, Iterable<? extends V> values) {
189          Collection<V> valueList = builderMultimap.get(checkNotNull(key));
190          for (V value : values) {
191            valueList.add(checkNotNull(value));
192          }
193          return this;
194        }
195    
196        /**
197         * Stores an array of values with the same key in the built multimap.
198         *
199         * @throws NullPointerException if the key or any value is null. The builder
200         *     is left in an invalid state.
201         */
202        public Builder<K, V> putAll(K key, V... values) {
203          return putAll(key, Arrays.asList(values));
204        }
205    
206        /**
207         * Stores another multimap's entries in the built multimap. The generated
208         * multimap's key and value orderings correspond to the iteration ordering
209         * of the {@code multimap.asMap()} view, with new keys and values following
210         * any existing keys and values.
211         *
212         * @throws NullPointerException if any key or value in {@code multimap} is
213         *     null. The builder is left in an invalid state.
214         */
215        public Builder<K, V> putAll(Multimap<? extends K, ? extends V> multimap) {
216          for (Map.Entry<? extends K, ? extends Collection<? extends V>> entry
217              : multimap.asMap().entrySet()) {
218            putAll(entry.getKey(), entry.getValue());
219          }
220          return this;
221        }
222    
223        /**
224         * Specifies the ordering of the generated multimap's keys.
225         * 
226         * @since 8
227         */
228        @Beta
229        public Builder<K, V> orderKeysBy(Comparator<? super K> keyComparator) {
230          builderMultimap = new SortedKeyBuilderMultimap<K, V>(
231              checkNotNull(keyComparator), builderMultimap);
232          return this;
233        }
234    
235        /**
236         * Specifies the ordering of the generated multimap's values for each key.
237         * 
238         * @since 8
239         */
240        @Beta
241        public Builder<K, V> orderValuesBy(Comparator<? super V> valueComparator) {
242          this.valueComparator = checkNotNull(valueComparator);
243          return this;
244        }
245        
246        /**
247         * Returns a newly-created immutable multimap.
248         */
249        public ImmutableMultimap<K, V> build() {
250          if (valueComparator != null) {
251            for (Collection<V> values : builderMultimap.asMap().values()) {
252               List<V> list = (List <V>) values;
253               Collections.sort(list, valueComparator);
254            }
255          }
256          return copyOf(builderMultimap);
257        }
258      }
259    
260      /**
261       * Returns an immutable multimap containing the same mappings as {@code
262       * multimap}. The generated multimap's key and value orderings correspond to
263       * the iteration ordering of the {@code multimap.asMap()} view.
264       *
265       * <p>Despite the method name, this method attempts to avoid actually copying
266       * the data when it is safe to do so. The exact circumstances under which a
267       * copy will or will not be performed are undocumented and subject to change.
268       *
269       * @throws NullPointerException if any key or value in {@code multimap} is
270       *         null
271       */
272      public static <K, V> ImmutableMultimap<K, V> copyOf(
273          Multimap<? extends K, ? extends V> multimap) {
274        if (multimap instanceof ImmutableMultimap) {
275          @SuppressWarnings("unchecked") // safe since multimap is not writable
276          ImmutableMultimap<K, V> kvMultimap
277              = (ImmutableMultimap<K, V>) multimap;
278          if (!kvMultimap.isPartialView()) {
279            return kvMultimap;
280          }
281        }
282        return ImmutableListMultimap.copyOf(multimap);
283      }
284    
285      final transient ImmutableMap<K, ? extends ImmutableCollection<V>> map;
286      final transient int size;
287    
288      // These constants allow the deserialization code to set final fields. This
289      // holder class makes sure they are not initialized unless an instance is
290      // deserialized.
291      @GwtIncompatible("java serialization is not supported")
292      static class FieldSettersHolder {
293        // Eclipse doesn't like the raw ImmutableMultimap
294        @SuppressWarnings("unchecked")
295        static final Serialization.FieldSetter<ImmutableMultimap>
296            MAP_FIELD_SETTER = Serialization.getFieldSetter(
297            ImmutableMultimap.class, "map");
298        // Eclipse doesn't like the raw ImmutableMultimap
299        @SuppressWarnings("unchecked")
300        static final Serialization.FieldSetter<ImmutableMultimap>
301            SIZE_FIELD_SETTER = Serialization.getFieldSetter(
302            ImmutableMultimap.class, "size");
303      }
304    
305      ImmutableMultimap(ImmutableMap<K, ? extends ImmutableCollection<V>> map,
306          int size) {
307        this.map = map;
308        this.size = size;
309      }
310    
311      // mutators (not supported)
312    
313      /**
314       * Guaranteed to throw an exception and leave the multimap unmodified.
315       *
316       * @throws UnsupportedOperationException always
317       */
318      @Override
319      public ImmutableCollection<V> removeAll(Object key) {
320        throw new UnsupportedOperationException();
321      }
322    
323      /**
324       * Guaranteed to throw an exception and leave the multimap unmodified.
325       *
326       * @throws UnsupportedOperationException always
327       */
328      @Override
329      public ImmutableCollection<V> replaceValues(K key,
330          Iterable<? extends V> values) {
331        throw new UnsupportedOperationException();
332      }
333    
334      /**
335       * Guaranteed to throw an exception and leave the multimap unmodified.
336       *
337       * @throws UnsupportedOperationException always
338       */
339      @Override
340      public void clear() {
341        throw new UnsupportedOperationException();
342      }
343    
344      /**
345       * Returns an immutable collection of the values for the given key.  If no
346       * mappings in the multimap have the provided key, an empty immutable
347       * collection is returned. The values are in the same order as the parameters
348       * used to build this multimap.
349       */
350      @Override
351      public abstract ImmutableCollection<V> get(K key);
352    
353      /**
354       * Guaranteed to throw an exception and leave the multimap unmodified.
355       *
356       * @throws UnsupportedOperationException always
357       */
358      @Override
359      public boolean put(K key, V value) {
360        throw new UnsupportedOperationException();
361      }
362    
363      /**
364       * Guaranteed to throw an exception and leave the multimap unmodified.
365       *
366       * @throws UnsupportedOperationException always
367       */
368      @Override
369      public boolean putAll(K key, Iterable<? extends V> values) {
370        throw new UnsupportedOperationException();
371      }
372    
373      /**
374       * Guaranteed to throw an exception and leave the multimap unmodified.
375       *
376       * @throws UnsupportedOperationException always
377       */
378      @Override
379      public boolean putAll(Multimap<? extends K, ? extends V> multimap) {
380        throw new UnsupportedOperationException();
381      }
382    
383      /**
384       * Guaranteed to throw an exception and leave the multimap unmodified.
385       *
386       * @throws UnsupportedOperationException always
387       */
388      @Override
389      public boolean remove(Object key, Object value) {
390        throw new UnsupportedOperationException();
391      }
392    
393      boolean isPartialView(){
394        return map.isPartialView();
395      }
396    
397      // accessors
398    
399      @Override
400      public boolean containsEntry(@Nullable Object key, @Nullable Object value) {
401        Collection<V> values = map.get(key);
402        return values != null && values.contains(value);
403      }
404    
405      @Override
406      public boolean containsKey(@Nullable Object key) {
407        return map.containsKey(key);
408      }
409    
410      @Override
411      public boolean containsValue(@Nullable Object value) {
412        for (Collection<V> valueCollection : map.values()) {
413          if (valueCollection.contains(value)) {
414            return true;
415          }
416        }
417        return false;
418      }
419    
420      @Override
421      public boolean isEmpty() {
422        return size == 0;
423      }
424    
425      @Override
426      public int size() {
427        return size;
428      }
429    
430      @Override public boolean equals(@Nullable Object object) {
431        if (object instanceof Multimap) {
432          Multimap<?, ?> that = (Multimap<?, ?>) object;
433          return this.map.equals(that.asMap());
434        }
435        return false;
436      }
437    
438      @Override public int hashCode() {
439        return map.hashCode();
440      }
441    
442      @Override public String toString() {
443        return map.toString();
444      }
445    
446      // views
447    
448      /**
449       * Returns an immutable set of the distinct keys in this multimap. These keys
450       * are ordered according to when they first appeared during the construction
451       * of this multimap.
452       */
453      @Override
454      public ImmutableSet<K> keySet() {
455        return map.keySet();
456      }
457    
458      /**
459       * Returns an immutable map that associates each key with its corresponding
460       * values in the multimap.
461       */
462      @Override
463      @SuppressWarnings("unchecked") // a widening cast
464      public ImmutableMap<K, Collection<V>> asMap() {
465        return (ImmutableMap) map;
466      }
467    
468      private transient ImmutableCollection<Map.Entry<K, V>> entries;
469    
470      /**
471       * Returns an immutable collection of all key-value pairs in the multimap. Its
472       * iterator traverses the values for the first key, the values for the second
473       * key, and so on.
474       */
475      @Override
476      public ImmutableCollection<Map.Entry<K, V>> entries() {
477        ImmutableCollection<Map.Entry<K, V>> result = entries;
478        return (result == null)
479            ? (entries = new EntryCollection<K, V>(this)) : result;
480      }
481    
482      private static class EntryCollection<K, V>
483          extends ImmutableCollection<Map.Entry<K, V>> {
484        final ImmutableMultimap<K, V> multimap;
485    
486        EntryCollection(ImmutableMultimap<K, V> multimap) {
487          this.multimap = multimap;
488        }
489    
490        @Override public UnmodifiableIterator<Map.Entry<K, V>> iterator() {
491          final Iterator<? extends Map.Entry<K, ? extends ImmutableCollection<V>>>
492              mapIterator = this.multimap.map.entrySet().iterator();
493    
494          return new UnmodifiableIterator<Map.Entry<K, V>>() {
495            K key;
496            Iterator<V> valueIterator;
497    
498            @Override
499            public boolean hasNext() {
500              return (key != null && valueIterator.hasNext())
501                  || mapIterator.hasNext();
502            }
503    
504            @Override
505            public Map.Entry<K, V> next() {
506              if (key == null || !valueIterator.hasNext()) {
507                Map.Entry<K, ? extends ImmutableCollection<V>> entry
508                    = mapIterator.next();
509                key = entry.getKey();
510                valueIterator = entry.getValue().iterator();
511              }
512              return Maps.immutableEntry(key, valueIterator.next());
513            }
514          };
515        }
516    
517        @Override boolean isPartialView() {
518          return multimap.isPartialView();
519        }
520    
521        @Override
522        public int size() {
523          return multimap.size();
524        }
525    
526        @Override public boolean contains(Object object) {
527          if (object instanceof Map.Entry) {
528            Map.Entry<?, ?> entry = (Map.Entry<?, ?>) object;
529            return multimap.containsEntry(entry.getKey(), entry.getValue());
530          }
531          return false;
532        }
533    
534        private static final long serialVersionUID = 0;
535      }
536    
537      private transient ImmutableMultiset<K> keys;
538    
539      /**
540       * Returns a collection, which may contain duplicates, of all keys. The number
541       * of times a key appears in the returned multiset equals the number of
542       * mappings the key has in the multimap. Duplicate keys appear consecutively
543       * in the multiset's iteration order.
544       */
545      @Override
546      public ImmutableMultiset<K> keys() {
547        ImmutableMultiset<K> result = keys;
548        return (result == null) ? (keys = createKeys()) : result;
549      }
550    
551      private ImmutableMultiset<K> createKeys() {
552        ImmutableMultiset.Builder<K> builder = ImmutableMultiset.builder();
553        for (Map.Entry<K, ? extends ImmutableCollection<V>> entry
554            : map.entrySet()) {
555          builder.addCopies(entry.getKey(), entry.getValue().size());
556        }
557        return builder.build();
558      }
559    
560      private transient ImmutableCollection<V> values;
561    
562      /**
563       * Returns an immutable collection of the values in this multimap. Its
564       * iterator traverses the values for the first key, the values for the second
565       * key, and so on.
566       */
567      @Override
568      public ImmutableCollection<V> values() {
569        ImmutableCollection<V> result = values;
570        return (result == null) ? (values = new Values<V>(this)) : result;
571      }
572    
573      private static class Values<V> extends ImmutableCollection<V> {
574        final ImmutableMultimap<?, V> multimap;
575    
576        Values(ImmutableMultimap<?, V> multimap) {
577          this.multimap = multimap;
578        }
579    
580        @Override public UnmodifiableIterator<V> iterator() {
581          final Iterator<? extends Map.Entry<?, V>> entryIterator
582              = multimap.entries().iterator();
583          return new UnmodifiableIterator<V>() {
584            @Override
585            public boolean hasNext() {
586              return entryIterator.hasNext();
587            }
588            @Override
589            public V next() {
590              return entryIterator.next().getValue();
591            }
592          };
593        }
594    
595        @Override
596        public int size() {
597          return multimap.size();
598        }
599    
600        @Override boolean isPartialView() {
601          return true;
602        }
603    
604        private static final long serialVersionUID = 0;
605      }
606    
607      private static final long serialVersionUID = 0;
608    }