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
017package com.google.common.collect;
018
019import static com.google.common.base.Preconditions.checkNotNull;
020import static com.google.common.collect.CollectPreconditions.checkEntryNotNull;
021
022import com.google.common.annotations.Beta;
023import com.google.common.annotations.GwtCompatible;
024import com.google.common.annotations.GwtIncompatible;
025import com.google.j2objc.annotations.Weak;
026import com.google.j2objc.annotations.WeakOuter;
027
028import java.io.Serializable;
029import java.util.Arrays;
030import java.util.Collection;
031import java.util.Collections;
032import java.util.Comparator;
033import java.util.Iterator;
034import java.util.LinkedHashMap;
035import java.util.List;
036import java.util.Map;
037import java.util.Map.Entry;
038import java.util.Set;
039
040import javax.annotation.Nullable;
041
042/**
043 * A {@link Multimap} whose contents will never change, with many other important properties
044 * detailed at {@link ImmutableCollection}.
045 *
046 * <p><b>Warning:</b> avoid <i>direct</i> usage of {@link ImmutableMultimap} as a type (as with
047 * {@link Multimap} itself). Prefer subtypes such as {@link ImmutableSetMultimap} or {@link
048 * ImmutableListMultimap}, which have well-defined {@link #equals} semantics, thus avoiding a common
049 * source of bugs and confusion.
050 *
051 * <p><b>Note:</b> every {@link ImmutableMultimap} offers an {@link #inverse} view, so there is no
052 * need for a distinct {@code ImmutableBiMultimap} type.
053 *
054 * <a name="iteration"></a>
055 * <p><b>Key-grouped iteration.</b> All view collections follow the same iteration order. In all
056 * current implementations, the iteration order always keeps multiple entries with the same key
057 * together. Any creation method that would customarily respect insertion order (such as {@link
058 * #copyOf(Multimap)}) instead preserves key-grouped order by inserting entries for an existing key
059 * immediately after the last entry having that key.
060 *
061 * <p>See the Guava User Guide article on <a href=
062 * "https://github.com/google/guava/wiki/ImmutableCollectionsExplained">
063 * immutable collections</a>.
064 *
065 * @author Jared Levy
066 * @since 2.0
067 */
068@GwtCompatible(emulated = true)
069public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
070    implements Serializable {
071
072  /** Returns an empty multimap. */
073  public static <K, V> ImmutableMultimap<K, V> of() {
074    return ImmutableListMultimap.of();
075  }
076
077  /**
078   * Returns an immutable multimap containing a single entry.
079   */
080  public static <K, V> ImmutableMultimap<K, V> of(K k1, V v1) {
081    return ImmutableListMultimap.of(k1, v1);
082  }
083
084  /**
085   * Returns an immutable multimap containing the given entries, in order.
086   */
087  public static <K, V> ImmutableMultimap<K, V> of(K k1, V v1, K k2, V v2) {
088    return ImmutableListMultimap.of(k1, v1, k2, v2);
089  }
090
091  /**
092   * Returns an immutable multimap containing the given entries, in the
093   * "key-grouped" insertion order described in the
094   * <a href="#iteration">class documentation</a>.
095   */
096  public static <K, V> ImmutableMultimap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3) {
097    return ImmutableListMultimap.of(k1, v1, k2, v2, k3, v3);
098  }
099
100  /**
101   * Returns an immutable multimap containing the given entries, in the
102   * "key-grouped" insertion order described in the
103   * <a href="#iteration">class documentation</a>.
104   */
105  public static <K, V> ImmutableMultimap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
106    return ImmutableListMultimap.of(k1, v1, k2, v2, k3, v3, k4, v4);
107  }
108
109  /**
110   * Returns an immutable multimap containing the given entries, in the
111   * "key-grouped" insertion order described in the
112   * <a href="#iteration">class documentation</a>.
113   */
114  public static <K, V> ImmutableMultimap<K, V> of(
115      K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
116    return ImmutableListMultimap.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5);
117  }
118
119  // looking for of() with > 5 entries? Use the builder instead.
120
121  /**
122   * Returns a new builder. The generated builder is equivalent to the builder
123   * created by the {@link Builder} constructor.
124   */
125  public static <K, V> Builder<K, V> builder() {
126    return new Builder<K, V>();
127  }
128
129  /**
130   * Multimap for {@link ImmutableMultimap.Builder} that maintains key and
131   * value orderings, allows duplicate values, and performs better than
132   * {@link LinkedListMultimap}.
133   */
134  private static class BuilderMultimap<K, V> extends AbstractMapBasedMultimap<K, V> {
135    BuilderMultimap() {
136      super(new LinkedHashMap<K, Collection<V>>());
137    }
138
139    @Override
140    Collection<V> createCollection() {
141      return Lists.newArrayList();
142    }
143
144    private static final long serialVersionUID = 0;
145  }
146
147  /**
148   * A builder for creating immutable multimap instances, especially
149   * {@code public static final} multimaps ("constant multimaps"). Example:
150   * <pre>   {@code
151   *
152   *   static final Multimap<String, Integer> STRING_TO_INTEGER_MULTIMAP =
153   *       new ImmutableMultimap.Builder<String, Integer>()
154   *           .put("one", 1)
155   *           .putAll("several", 1, 2, 3)
156   *           .putAll("many", 1, 2, 3, 4, 5)
157   *           .build();}</pre>
158   *
159   * <p>Builder instances can be reused; it is safe to call {@link #build} multiple
160   * times to build multiple multimaps in series. Each multimap contains the
161   * key-value mappings in the previously created multimaps.
162   *
163   * @since 2.0
164   */
165  public static class Builder<K, V> {
166    Multimap<K, V> builderMultimap = new BuilderMultimap<K, V>();
167    Comparator<? super K> keyComparator;
168    Comparator<? super V> valueComparator;
169
170    /**
171     * Creates a new builder. The returned builder is equivalent to the builder
172     * generated by {@link ImmutableMultimap#builder}.
173     */
174    public Builder() {}
175
176    /**
177     * Adds a key-value mapping to the built multimap.
178     */
179    public Builder<K, V> put(K key, V value) {
180      checkEntryNotNull(key, value);
181      builderMultimap.put(key, value);
182      return this;
183    }
184
185    /**
186     * Adds an entry to the built multimap.
187     *
188     * @since 11.0
189     */
190    public Builder<K, V> put(Entry<? extends K, ? extends V> entry) {
191      return put(entry.getKey(), entry.getValue());
192    }
193
194    /**
195     * Adds entries to the built multimap.
196     *
197     * @since 19.0
198     */
199    @Beta
200    public Builder<K, V> putAll(Iterable<? extends Entry<? extends K, ? extends V>> entries) {
201      for (Entry<? extends K, ? extends V> entry : entries) {
202        put(entry);
203      }
204      return this;
205    }
206
207    /**
208     * Stores a collection of values with the same key in the built multimap.
209     *
210     * @throws NullPointerException if {@code key}, {@code values}, or any
211     *     element in {@code values} is null. The builder is left in an invalid
212     *     state.
213     */
214    public Builder<K, V> putAll(K key, Iterable<? extends V> values) {
215      if (key == null) {
216        throw new NullPointerException("null key in entry: null=" + Iterables.toString(values));
217      }
218      Collection<V> valueList = builderMultimap.get(key);
219      for (V value : values) {
220        checkEntryNotNull(key, value);
221        valueList.add(value);
222      }
223      return this;
224    }
225
226    /**
227     * Stores an array of values with the same key in the built multimap.
228     *
229     * @throws NullPointerException if the key or any value is null. The builder
230     *     is left in an invalid state.
231     */
232    public Builder<K, V> putAll(K key, V... values) {
233      return putAll(key, Arrays.asList(values));
234    }
235
236    /**
237     * Stores another multimap's entries in the built multimap. The generated
238     * multimap's key and value orderings correspond to the iteration ordering
239     * of the {@code multimap.asMap()} view, with new keys and values following
240     * any existing keys and values.
241     *
242     * @throws NullPointerException if any key or value in {@code multimap} is
243     *     null. The builder is left in an invalid state.
244     */
245    public Builder<K, V> putAll(Multimap<? extends K, ? extends V> multimap) {
246      for (Entry<? extends K, ? extends Collection<? extends V>> entry :
247          multimap.asMap().entrySet()) {
248        putAll(entry.getKey(), entry.getValue());
249      }
250      return this;
251    }
252
253    /**
254     * Specifies the ordering of the generated multimap's keys.
255     *
256     * @since 8.0
257     */
258    public Builder<K, V> orderKeysBy(Comparator<? super K> keyComparator) {
259      this.keyComparator = checkNotNull(keyComparator);
260      return this;
261    }
262
263    /**
264     * Specifies the ordering of the generated multimap's values for each key.
265     *
266     * @since 8.0
267     */
268    public Builder<K, V> orderValuesBy(Comparator<? super V> valueComparator) {
269      this.valueComparator = checkNotNull(valueComparator);
270      return this;
271    }
272
273    /**
274     * Returns a newly-created immutable multimap.
275     */
276    public ImmutableMultimap<K, V> build() {
277      if (valueComparator != null) {
278        for (Collection<V> values : builderMultimap.asMap().values()) {
279          List<V> list = (List<V>) values;
280          Collections.sort(list, valueComparator);
281        }
282      }
283      if (keyComparator != null) {
284        Multimap<K, V> sortedCopy = new BuilderMultimap<K, V>();
285        List<Map.Entry<K, Collection<V>>> entries =
286            Ordering.from(keyComparator)
287                .<K>onKeys()
288                .immutableSortedCopy(builderMultimap.asMap().entrySet());
289        for (Map.Entry<K, Collection<V>> entry : entries) {
290          sortedCopy.putAll(entry.getKey(), entry.getValue());
291        }
292        builderMultimap = sortedCopy;
293      }
294      return copyOf(builderMultimap);
295    }
296  }
297
298  /**
299   * Returns an immutable multimap containing the same mappings as {@code
300   * multimap}, in the "key-grouped" iteration order described in the class
301   * documentation.
302   *
303   * <p>Despite the method name, this method attempts to avoid actually copying
304   * the data when it is safe to do so. The exact circumstances under which a
305   * copy will or will not be performed are undocumented and subject to change.
306   *
307   * @throws NullPointerException if any key or value in {@code multimap} is
308   *         null
309   */
310  public static <K, V> ImmutableMultimap<K, V> copyOf(Multimap<? extends K, ? extends V> multimap) {
311    if (multimap instanceof ImmutableMultimap) {
312      @SuppressWarnings("unchecked") // safe since multimap is not writable
313      ImmutableMultimap<K, V> kvMultimap = (ImmutableMultimap<K, V>) multimap;
314      if (!kvMultimap.isPartialView()) {
315        return kvMultimap;
316      }
317    }
318    return ImmutableListMultimap.copyOf(multimap);
319  }
320
321  /**
322   * Returns an immutable multimap containing the specified entries.  The
323   * returned multimap iterates over keys in the order they were first
324   * encountered in the input, and the values for each key are iterated in the
325   * order they were encountered.
326   *
327   * @throws NullPointerException if any key, value, or entry is null
328   * @since 19.0
329   */
330  @Beta
331  public static <K, V> ImmutableMultimap<K, V> copyOf(
332      Iterable<? extends Entry<? extends K, ? extends V>> entries) {
333    return ImmutableListMultimap.copyOf(entries);
334  }
335
336  final transient ImmutableMap<K, ? extends ImmutableCollection<V>> map;
337  final transient int size;
338
339  // These constants allow the deserialization code to set final fields. This
340  // holder class makes sure they are not initialized unless an instance is
341  // deserialized.
342  @GwtIncompatible("java serialization is not supported")
343  static class FieldSettersHolder {
344    static final Serialization.FieldSetter<ImmutableMultimap> MAP_FIELD_SETTER =
345        Serialization.getFieldSetter(ImmutableMultimap.class, "map");
346    static final Serialization.FieldSetter<ImmutableMultimap> SIZE_FIELD_SETTER =
347        Serialization.getFieldSetter(ImmutableMultimap.class, "size");
348    static final Serialization.FieldSetter<ImmutableSetMultimap> EMPTY_SET_FIELD_SETTER =
349        Serialization.getFieldSetter(ImmutableSetMultimap.class, "emptySet");
350  }
351
352  ImmutableMultimap(ImmutableMap<K, ? extends ImmutableCollection<V>> map, int size) {
353    this.map = map;
354    this.size = size;
355  }
356
357  // mutators (not supported)
358
359  /**
360   * Guaranteed to throw an exception and leave the multimap unmodified.
361   *
362   * @throws UnsupportedOperationException always
363   * @deprecated Unsupported operation.
364   */
365  @Deprecated
366  @Override
367  public ImmutableCollection<V> removeAll(Object key) {
368    throw new UnsupportedOperationException();
369  }
370
371  /**
372   * Guaranteed to throw an exception and leave the multimap unmodified.
373   *
374   * @throws UnsupportedOperationException always
375   * @deprecated Unsupported operation.
376   */
377  @Deprecated
378  @Override
379  public ImmutableCollection<V> replaceValues(K key, Iterable<? extends V> values) {
380    throw new UnsupportedOperationException();
381  }
382
383  /**
384   * Guaranteed to throw an exception and leave the multimap unmodified.
385   *
386   * @throws UnsupportedOperationException always
387   * @deprecated Unsupported operation.
388   */
389  @Deprecated
390  @Override
391  public void clear() {
392    throw new UnsupportedOperationException();
393  }
394
395  /**
396   * Returns an immutable collection of the values for the given key.  If no
397   * mappings in the multimap have the provided key, an empty immutable
398   * collection is returned. The values are in the same order as the parameters
399   * used to build this multimap.
400   */
401  @Override
402  public abstract ImmutableCollection<V> get(K key);
403
404  /**
405   * Returns an immutable multimap which is the inverse of this one. For every
406   * key-value mapping in the original, the result will have a mapping with
407   * key and value reversed.
408   *
409   * @since 11.0
410   */
411  public abstract ImmutableMultimap<V, K> inverse();
412
413  /**
414   * Guaranteed to throw an exception and leave the multimap unmodified.
415   *
416   * @throws UnsupportedOperationException always
417   * @deprecated Unsupported operation.
418   */
419  @Deprecated
420  @Override
421  public boolean put(K key, V value) {
422    throw new UnsupportedOperationException();
423  }
424
425  /**
426   * Guaranteed to throw an exception and leave the multimap unmodified.
427   *
428   * @throws UnsupportedOperationException always
429   * @deprecated Unsupported operation.
430   */
431  @Deprecated
432  @Override
433  public boolean putAll(K key, Iterable<? extends V> values) {
434    throw new UnsupportedOperationException();
435  }
436
437  /**
438   * Guaranteed to throw an exception and leave the multimap unmodified.
439   *
440   * @throws UnsupportedOperationException always
441   * @deprecated Unsupported operation.
442   */
443  @Deprecated
444  @Override
445  public boolean putAll(Multimap<? extends K, ? extends V> multimap) {
446    throw new UnsupportedOperationException();
447  }
448
449  /**
450   * Guaranteed to throw an exception and leave the multimap unmodified.
451   *
452   * @throws UnsupportedOperationException always
453   * @deprecated Unsupported operation.
454   */
455  @Deprecated
456  @Override
457  public boolean remove(Object key, Object value) {
458    throw new UnsupportedOperationException();
459  }
460
461  /**
462   * Returns {@code true} if this immutable multimap's implementation contains references to
463   * user-created objects that aren't accessible via this multimap's methods. This is generally
464   * used to determine whether {@code copyOf} implementations should make an explicit copy to avoid
465   * memory leaks.
466   */
467  boolean isPartialView() {
468    return map.isPartialView();
469  }
470
471  // accessors
472
473  @Override
474  public boolean containsKey(@Nullable Object key) {
475    return map.containsKey(key);
476  }
477
478  @Override
479  public boolean containsValue(@Nullable Object value) {
480    return value != null && super.containsValue(value);
481  }
482
483  @Override
484  public int size() {
485    return size;
486  }
487
488  // views
489
490  /**
491   * Returns an immutable set of the distinct keys in this multimap, in the same
492   * order as they appear in this multimap.
493   */
494  @Override
495  public ImmutableSet<K> keySet() {
496    return map.keySet();
497  }
498
499  /**
500   * Returns an immutable map that associates each key with its corresponding
501   * values in the multimap. Keys and values appear in the same order as in this
502   * multimap.
503   */
504  @Override
505  @SuppressWarnings("unchecked") // a widening cast
506  public ImmutableMap<K, Collection<V>> asMap() {
507    return (ImmutableMap) map;
508  }
509
510  @Override
511  Map<K, Collection<V>> createAsMap() {
512    throw new AssertionError("should never be called");
513  }
514
515  /**
516   * Returns an immutable collection of all key-value pairs in the multimap.
517   */
518  @Override
519  public ImmutableCollection<Entry<K, V>> entries() {
520    return (ImmutableCollection<Entry<K, V>>) super.entries();
521  }
522
523  @Override
524  ImmutableCollection<Entry<K, V>> createEntries() {
525    return new EntryCollection<K, V>(this);
526  }
527
528  private static class EntryCollection<K, V> extends ImmutableCollection<Entry<K, V>> {
529    @Weak final ImmutableMultimap<K, V> multimap;
530
531    EntryCollection(ImmutableMultimap<K, V> multimap) {
532      this.multimap = multimap;
533    }
534
535    @Override
536    public UnmodifiableIterator<Entry<K, V>> iterator() {
537      return multimap.entryIterator();
538    }
539
540    @Override
541    boolean isPartialView() {
542      return multimap.isPartialView();
543    }
544
545    @Override
546    public int size() {
547      return multimap.size();
548    }
549
550    @Override
551    public boolean contains(Object object) {
552      if (object instanceof Entry) {
553        Entry<?, ?> entry = (Entry<?, ?>) object;
554        return multimap.containsEntry(entry.getKey(), entry.getValue());
555      }
556      return false;
557    }
558
559    private static final long serialVersionUID = 0;
560  }
561
562  private abstract class Itr<T> extends UnmodifiableIterator<T> {
563    final Iterator<Entry<K, Collection<V>>> mapIterator = asMap().entrySet().iterator();
564    K key = null;
565    Iterator<V> valueIterator = Iterators.emptyIterator();
566
567    abstract T output(K key, V value);
568
569    @Override
570    public boolean hasNext() {
571      return mapIterator.hasNext() || valueIterator.hasNext();
572    }
573
574    @Override
575    public T next() {
576      if (!valueIterator.hasNext()) {
577        Entry<K, Collection<V>> mapEntry = mapIterator.next();
578        key = mapEntry.getKey();
579        valueIterator = mapEntry.getValue().iterator();
580      }
581      return output(key, valueIterator.next());
582    }
583  }
584
585  @Override
586  UnmodifiableIterator<Entry<K, V>> entryIterator() {
587    return new Itr<Entry<K, V>>() {
588      @Override
589      Entry<K, V> output(K key, V value) {
590        return Maps.immutableEntry(key, value);
591      }
592    };
593  }
594
595  /**
596   * Returns an immutable multiset containing all the keys in this multimap, in
597   * the same order and with the same frequencies as they appear in this
598   * multimap; to get only a single occurrence of each key, use {@link #keySet}.
599   */
600  @Override
601  public ImmutableMultiset<K> keys() {
602    return (ImmutableMultiset<K>) super.keys();
603  }
604
605  @Override
606  ImmutableMultiset<K> createKeys() {
607    return new Keys();
608  }
609
610  @SuppressWarnings("serial") // Uses writeReplace, not default serialization
611  @WeakOuter
612  class Keys extends ImmutableMultiset<K> {
613    @Override
614    public boolean contains(@Nullable Object object) {
615      return containsKey(object);
616    }
617
618    @Override
619    public int count(@Nullable Object element) {
620      Collection<V> values = map.get(element);
621      return (values == null) ? 0 : values.size();
622    }
623
624    @Override
625    public Set<K> elementSet() {
626      return keySet();
627    }
628
629    @Override
630    public int size() {
631      return ImmutableMultimap.this.size();
632    }
633
634    @Override
635    Multiset.Entry<K> getEntry(int index) {
636      Map.Entry<K, ? extends Collection<V>> entry = map.entrySet().asList().get(index);
637      return Multisets.immutableEntry(entry.getKey(), entry.getValue().size());
638    }
639
640    @Override
641    boolean isPartialView() {
642      return true;
643    }
644  }
645
646  /**
647   * Returns an immutable collection of the values in this multimap. Its
648   * iterator traverses the values for the first key, the values for the second
649   * key, and so on.
650   */
651  @Override
652  public ImmutableCollection<V> values() {
653    return (ImmutableCollection<V>) super.values();
654  }
655
656  @Override
657  ImmutableCollection<V> createValues() {
658    return new Values<K, V>(this);
659  }
660
661  @Override
662  UnmodifiableIterator<V> valueIterator() {
663    return new Itr<V>() {
664      @Override
665      V output(K key, V value) {
666        return value;
667      }
668    };
669  }
670
671  private static final class Values<K, V> extends ImmutableCollection<V> {
672    @Weak private final transient ImmutableMultimap<K, V> multimap;
673
674    Values(ImmutableMultimap<K, V> multimap) {
675      this.multimap = multimap;
676    }
677
678    @Override
679    public boolean contains(@Nullable Object object) {
680      return multimap.containsValue(object);
681    }
682
683    @Override
684    public UnmodifiableIterator<V> iterator() {
685      return multimap.valueIterator();
686    }
687
688    @GwtIncompatible("not present in emulated superclass")
689    @Override
690    int copyIntoArray(Object[] dst, int offset) {
691      for (ImmutableCollection<V> valueCollection : multimap.map.values()) {
692        offset = valueCollection.copyIntoArray(dst, offset);
693      }
694      return offset;
695    }
696
697    @Override
698    public int size() {
699      return multimap.size();
700    }
701
702    @Override
703    boolean isPartialView() {
704      return true;
705    }
706
707    private static final long serialVersionUID = 0;
708  }
709
710  private static final long serialVersionUID = 0;
711}