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