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.Entry;
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     * <p>In addition to methods defined by {@link Multimap}, an {@link #inverse}
054     * method is also supported.
055     *
056     * <p>See the Guava User Guide article on <a href=
057     * "http://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained">
058     * immutable collections</a>.
059     *
060     * @author Jared Levy
061     * @since 2.0 (imported from Google Collections Library)
062     */
063    @GwtCompatible(emulated = true)
064    // TODO(user): If BiMultimap graduates from labs, this class should implement it.
065    public abstract class ImmutableMultimap<K, V>
066        implements Multimap<K, V>, 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 AbstractMultimap<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       * Multimap for {@link ImmutableMultimap.Builder} that sorts key and allows
138       * duplicate values,
139       */
140      private static class SortedKeyBuilderMultimap<K, V>
141          extends AbstractMultimap<K, V> {
142        SortedKeyBuilderMultimap(
143            Comparator<? super K> keyComparator, Multimap<K, V> multimap) {
144          super(new TreeMap<K, Collection<V>>(keyComparator));
145          putAll(multimap);
146        }
147        @Override Collection<V> createCollection() {
148          return Lists.newArrayList();
149        }
150        private static final long serialVersionUID = 0;
151      }
152    
153      /**
154       * A builder for creating immutable multimap instances, especially
155       * {@code public static final} multimaps ("constant multimaps"). Example:
156       * <pre>   {@code
157       *
158       *   static final Multimap<String, Integer> STRING_TO_INTEGER_MULTIMAP =
159       *       new ImmutableMultimap.Builder<String, Integer>()
160       *           .put("one", 1)
161       *           .putAll("several", 1, 2, 3)
162       *           .putAll("many", 1, 2, 3, 4, 5)
163       *           .build();}</pre>
164       *
165       * Builder instances can be reused; it is safe to call {@link #build} multiple
166       * times to build multiple multimaps in series. Each multimap contains the
167       * key-value mappings in the previously created multimaps.
168       *
169       * @since 2.0 (imported from Google Collections Library)
170       */
171      public static class Builder<K, V> {
172        Multimap<K, V> builderMultimap = new BuilderMultimap<K, V>();
173        Comparator<? super V> valueComparator;
174    
175        /**
176         * Creates a new builder. The returned builder is equivalent to the builder
177         * generated by {@link ImmutableMultimap#builder}.
178         */
179        public Builder() {}
180    
181        /**
182         * Adds a key-value mapping to the built multimap.
183         */
184        public Builder<K, V> put(K key, V value) {
185          builderMultimap.put(checkNotNull(key), checkNotNull(value));
186          return this;
187        }
188    
189        /**
190         * Adds an entry to the built multimap.
191         *
192         * @since 11.0
193         */
194        public Builder<K, V> put(Entry<? extends K, ? extends V> entry) {
195          builderMultimap.put(
196              checkNotNull(entry.getKey()), checkNotNull(entry.getValue()));
197          return this;
198        }
199    
200        /**
201         * Stores a collection of values with the same key in the built multimap.
202         *
203         * @throws NullPointerException if {@code key}, {@code values}, or any
204         *     element in {@code values} is null. The builder is left in an invalid
205         *     state.
206         */
207        public Builder<K, V> putAll(K key, Iterable<? extends V> values) {
208          Collection<V> valueList = builderMultimap.get(checkNotNull(key));
209          for (V value : values) {
210            valueList.add(checkNotNull(value));
211          }
212          return this;
213        }
214    
215        /**
216         * Stores an array of values with the same key in the built multimap.
217         *
218         * @throws NullPointerException if the key or any value is null. The builder
219         *     is left in an invalid state.
220         */
221        public Builder<K, V> putAll(K key, V... values) {
222          return putAll(key, Arrays.asList(values));
223        }
224    
225        /**
226         * Stores another multimap's entries in the built multimap. The generated
227         * multimap's key and value orderings correspond to the iteration ordering
228         * of the {@code multimap.asMap()} view, with new keys and values following
229         * any existing keys and values.
230         *
231         * @throws NullPointerException if any key or value in {@code multimap} is
232         *     null. The builder is left in an invalid state.
233         */
234        public Builder<K, V> putAll(Multimap<? extends K, ? extends V> multimap) {
235          for (Entry<? extends K, ? extends Collection<? extends V>> entry
236              : multimap.asMap().entrySet()) {
237            putAll(entry.getKey(), entry.getValue());
238          }
239          return this;
240        }
241    
242        /**
243         * Specifies the ordering of the generated multimap's keys.
244         *
245         * @since 8.0
246         */
247        @Beta
248        public Builder<K, V> orderKeysBy(Comparator<? super K> keyComparator) {
249          builderMultimap = new SortedKeyBuilderMultimap<K, V>(
250              checkNotNull(keyComparator), builderMultimap);
251          return this;
252        }
253    
254        /**
255         * Specifies the ordering of the generated multimap's values for each key.
256         *
257         * @since 8.0
258         */
259        @Beta
260        public Builder<K, V> orderValuesBy(Comparator<? super V> valueComparator) {
261          this.valueComparator = checkNotNull(valueComparator);
262          return this;
263        }
264    
265        /**
266         * Returns a newly-created immutable multimap.
267         */
268        public ImmutableMultimap<K, V> build() {
269          if (valueComparator != null) {
270            for (Collection<V> values : builderMultimap.asMap().values()) {
271              List<V> list = (List <V>) values;
272              Collections.sort(list, valueComparator);
273            }
274          }
275          return copyOf(builderMultimap);
276        }
277      }
278    
279      /**
280       * Returns an immutable multimap containing the same mappings as {@code
281       * multimap}. The generated multimap's key and value orderings correspond to
282       * the iteration ordering of the {@code multimap.asMap()} view.
283       *
284       * <p>Despite the method name, this method attempts to avoid actually copying
285       * the data when it is safe to do so. The exact circumstances under which a
286       * copy will or will not be performed are undocumented and subject to change.
287       *
288       * @throws NullPointerException if any key or value in {@code multimap} is
289       *         null
290       */
291      public static <K, V> ImmutableMultimap<K, V> copyOf(
292          Multimap<? extends K, ? extends V> multimap) {
293        if (multimap instanceof ImmutableMultimap) {
294          @SuppressWarnings("unchecked") // safe since multimap is not writable
295          ImmutableMultimap<K, V> kvMultimap
296              = (ImmutableMultimap<K, V>) multimap;
297          if (!kvMultimap.isPartialView()) {
298            return kvMultimap;
299          }
300        }
301        return ImmutableListMultimap.copyOf(multimap);
302      }
303    
304      final transient ImmutableMap<K, ? extends ImmutableCollection<V>> map;
305      final transient int size;
306    
307      // These constants allow the deserialization code to set final fields. This
308      // holder class makes sure they are not initialized unless an instance is
309      // deserialized.
310      @GwtIncompatible("java serialization is not supported")
311      static class FieldSettersHolder {
312        static final Serialization.FieldSetter<ImmutableMultimap>
313            MAP_FIELD_SETTER = Serialization.getFieldSetter(
314            ImmutableMultimap.class, "map");
315        static final Serialization.FieldSetter<ImmutableMultimap>
316            SIZE_FIELD_SETTER = Serialization.getFieldSetter(
317            ImmutableMultimap.class, "size");
318      }
319    
320      ImmutableMultimap(ImmutableMap<K, ? extends ImmutableCollection<V>> map,
321          int size) {
322        this.map = map;
323        this.size = size;
324      }
325    
326      // mutators (not supported)
327    
328      /**
329       * Guaranteed to throw an exception and leave the multimap unmodified.
330       *
331       * @throws UnsupportedOperationException always
332       */
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       */
343      @Override
344      public ImmutableCollection<V> replaceValues(K key,
345          Iterable<? extends V> values) {
346        throw new UnsupportedOperationException();
347      }
348    
349      /**
350       * Guaranteed to throw an exception and leave the multimap unmodified.
351       *
352       * @throws UnsupportedOperationException always
353       */
354      @Override
355      public void clear() {
356        throw new UnsupportedOperationException();
357      }
358    
359      /**
360       * Returns an immutable collection of the values for the given key.  If no
361       * mappings in the multimap have the provided key, an empty immutable
362       * collection is returned. The values are in the same order as the parameters
363       * used to build this multimap.
364       */
365      @Override
366      public abstract ImmutableCollection<V> get(K key);
367    
368      /**
369       * Returns an immutable multimap which is the inverse of this one. For every
370       * key-value mapping in the original, the result will have a mapping with
371       * key and value reversed.
372       *
373       * @since 11
374       */
375      @Beta
376      public abstract ImmutableMultimap<V, K> inverse();
377    
378      /**
379       * Guaranteed to throw an exception and leave the multimap unmodified.
380       *
381       * @throws UnsupportedOperationException always
382       */
383      @Override
384      public boolean put(K key, V value) {
385        throw new UnsupportedOperationException();
386      }
387    
388      /**
389       * Guaranteed to throw an exception and leave the multimap unmodified.
390       *
391       * @throws UnsupportedOperationException always
392       */
393      @Override
394      public boolean putAll(K key, Iterable<? extends V> values) {
395        throw new UnsupportedOperationException();
396      }
397    
398      /**
399       * Guaranteed to throw an exception and leave the multimap unmodified.
400       *
401       * @throws UnsupportedOperationException always
402       */
403      @Override
404      public boolean putAll(Multimap<? extends K, ? extends V> multimap) {
405        throw new UnsupportedOperationException();
406      }
407    
408      /**
409       * Guaranteed to throw an exception and leave the multimap unmodified.
410       *
411       * @throws UnsupportedOperationException always
412       */
413      @Override
414      public boolean remove(Object key, Object value) {
415        throw new UnsupportedOperationException();
416      }
417    
418      boolean isPartialView(){
419        return map.isPartialView();
420      }
421    
422      // accessors
423    
424      @Override
425      public boolean containsEntry(@Nullable Object key, @Nullable Object value) {
426        Collection<V> values = map.get(key);
427        return values != null && values.contains(value);
428      }
429    
430      @Override
431      public boolean containsKey(@Nullable Object key) {
432        return map.containsKey(key);
433      }
434    
435      @Override
436      public boolean containsValue(@Nullable Object value) {
437        for (Collection<V> valueCollection : map.values()) {
438          if (valueCollection.contains(value)) {
439            return true;
440          }
441        }
442        return false;
443      }
444    
445      @Override
446      public boolean isEmpty() {
447        return size == 0;
448      }
449    
450      @Override
451      public int size() {
452        return size;
453      }
454    
455      @Override public boolean equals(@Nullable Object object) {
456        if (object instanceof Multimap) {
457          Multimap<?, ?> that = (Multimap<?, ?>) object;
458          return this.map.equals(that.asMap());
459        }
460        return false;
461      }
462    
463      @Override public int hashCode() {
464        return map.hashCode();
465      }
466    
467      @Override public String toString() {
468        return map.toString();
469      }
470    
471      // views
472    
473      /**
474       * Returns an immutable set of the distinct keys in this multimap. These keys
475       * are ordered according to when they first appeared during the construction
476       * of this multimap.
477       */
478      @Override
479      public ImmutableSet<K> keySet() {
480        return map.keySet();
481      }
482    
483      /**
484       * Returns an immutable map that associates each key with its corresponding
485       * values in the multimap.
486       */
487      @Override
488      @SuppressWarnings("unchecked") // a widening cast
489      public ImmutableMap<K, Collection<V>> asMap() {
490        return (ImmutableMap) map;
491      }
492    
493      private transient ImmutableCollection<Entry<K, V>> entries;
494    
495      /**
496       * Returns an immutable collection of all key-value pairs in the multimap. Its
497       * iterator traverses the values for the first key, the values for the second
498       * key, and so on.
499       */
500      @Override
501      public ImmutableCollection<Entry<K, V>> entries() {
502        ImmutableCollection<Entry<K, V>> result = entries;
503        return (result == null)
504            ? (entries = new EntryCollection<K, V>(this)) : result;
505      }
506    
507      private static class EntryCollection<K, V>
508          extends ImmutableCollection<Entry<K, V>> {
509        final ImmutableMultimap<K, V> multimap;
510    
511        EntryCollection(ImmutableMultimap<K, V> multimap) {
512          this.multimap = multimap;
513        }
514    
515        @Override public UnmodifiableIterator<Entry<K, V>> iterator() {
516          final Iterator<? extends Entry<K, ? extends ImmutableCollection<V>>>
517              mapIterator = this.multimap.map.entrySet().iterator();
518    
519          return new UnmodifiableIterator<Entry<K, V>>() {
520            K key;
521            Iterator<V> valueIterator;
522    
523            @Override
524            public boolean hasNext() {
525              return (key != null && valueIterator.hasNext())
526                  || mapIterator.hasNext();
527            }
528    
529            @Override
530            public Entry<K, V> next() {
531              if (key == null || !valueIterator.hasNext()) {
532                Entry<K, ? extends ImmutableCollection<V>> entry
533                    = mapIterator.next();
534                key = entry.getKey();
535                valueIterator = entry.getValue().iterator();
536              }
537              return Maps.immutableEntry(key, valueIterator.next());
538            }
539          };
540        }
541    
542        @Override boolean isPartialView() {
543          return multimap.isPartialView();
544        }
545    
546        @Override
547        public int size() {
548          return multimap.size();
549        }
550    
551        @Override 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 transient ImmutableMultiset<K> keys;
563    
564      /**
565       * Returns a collection, which may contain duplicates, of all keys. The number
566       * of times a key appears in the returned multiset equals the number of
567       * mappings the key has in the multimap. Duplicate keys appear consecutively
568       * in the multiset's iteration order.
569       */
570      @Override
571      public ImmutableMultiset<K> keys() {
572        ImmutableMultiset<K> result = keys;
573        return (result == null) ? (keys = createKeys()) : result;
574      }
575    
576      private ImmutableMultiset<K> createKeys() {
577        ImmutableMultiset.Builder<K> builder = ImmutableMultiset.builder();
578        for (Entry<K, ? extends ImmutableCollection<V>> entry
579            : map.entrySet()) {
580          builder.addCopies(entry.getKey(), entry.getValue().size());
581        }
582        return builder.build();
583      }
584    
585      private transient ImmutableCollection<V> values;
586    
587      /**
588       * Returns an immutable collection of the values in this multimap. Its
589       * iterator traverses the values for the first key, the values for the second
590       * key, and so on.
591       */
592      @Override
593      public ImmutableCollection<V> values() {
594        ImmutableCollection<V> result = values;
595        return (result == null) ? (values = new Values<V>(this)) : result;
596      }
597    
598      private static class Values<V> extends ImmutableCollection<V> {
599        final ImmutableMultimap<?, V> multimap;
600    
601        Values(ImmutableMultimap<?, V> multimap) {
602          this.multimap = multimap;
603        }
604    
605        @Override public UnmodifiableIterator<V> iterator() {
606          return Maps.valueIterator(multimap.entries().iterator());
607        }
608    
609        @Override
610        public int size() {
611          return multimap.size();
612        }
613    
614        @Override boolean isPartialView() {
615          return true;
616        }
617    
618        private static final long serialVersionUID = 0;
619      }
620    
621      private static final long serialVersionUID = 0;
622    }