001/*
002 * Copyright (C) 2007 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.Beta;
022import com.google.common.annotations.GwtCompatible;
023import com.google.j2objc.annotations.WeakOuter;
024
025import java.io.Serializable;
026import java.util.Collection;
027import java.util.Comparator;
028import java.util.Iterator;
029import java.util.LinkedHashMap;
030import java.util.List;
031import java.util.Map;
032import java.util.Map.Entry;
033import java.util.Set;
034import java.util.SortedSet;
035
036import javax.annotation.Nullable;
037
038/**
039 * Factory and utilities pertaining to the {@code MapConstraint} interface.
040 *
041 * @see Constraints
042 * @author Mike Bostock
043 * @since 3.0
044 * @deprecated Use {@link Preconditions} for basic checks. In place of
045 *     constrained maps, we encourage you to check your preconditions
046 *     explicitly instead of leaving that work to the map implementation.
047 *     For the specific case of rejecting null, consider {@link ImmutableMap}.
048 *     This class is scheduled for removal in Guava 20.0.
049 */
050@Beta
051@GwtCompatible
052@Deprecated
053public final class MapConstraints {
054  private MapConstraints() {}
055
056  /**
057   * Returns a constraint that verifies that neither the key nor the value is
058   * null. If either is null, a {@link NullPointerException} is thrown.
059   */
060  public static MapConstraint<Object, Object> notNull() {
061    return NotNullMapConstraint.INSTANCE;
062  }
063
064  // enum singleton pattern
065  private enum NotNullMapConstraint implements MapConstraint<Object, Object> {
066    INSTANCE;
067
068    @Override
069    public void checkKeyValue(Object key, Object value) {
070      checkNotNull(key);
071      checkNotNull(value);
072    }
073
074    @Override
075    public String toString() {
076      return "Not null";
077    }
078  }
079
080  /**
081   * Returns a constrained view of the specified map, using the specified
082   * constraint. Any operations that add new mappings will call the provided
083   * constraint. However, this method does not verify that existing mappings
084   * satisfy the constraint.
085   *
086   * <p>The returned map is not serializable.
087   *
088   * @param map the map to constrain
089   * @param constraint the constraint that validates added entries
090   * @return a constrained view of the specified map
091   */
092  public static <K, V> Map<K, V> constrainedMap(
093      Map<K, V> map, MapConstraint<? super K, ? super V> constraint) {
094    return new ConstrainedMap<K, V>(map, constraint);
095  }
096
097  /**
098   * Returns a constrained view of the specified multimap, using the specified
099   * constraint. Any operations that add new mappings will call the provided
100   * constraint. However, this method does not verify that existing mappings
101   * satisfy the constraint.
102   *
103   * <p>Note that the generated multimap's {@link Multimap#removeAll} and
104   * {@link Multimap#replaceValues} methods return collections that are not
105   * constrained.
106   *
107   * <p>The returned multimap is not serializable.
108   *
109   * @param multimap the multimap to constrain
110   * @param constraint the constraint that validates added entries
111   * @return a constrained view of the multimap
112   */
113  public static <K, V> Multimap<K, V> constrainedMultimap(
114      Multimap<K, V> multimap, MapConstraint<? super K, ? super V> constraint) {
115    return new ConstrainedMultimap<K, V>(multimap, constraint);
116  }
117
118  /**
119   * Returns a constrained view of the specified list multimap, using the
120   * specified constraint. Any operations that add new mappings will call the
121   * provided constraint. However, this method does not verify that existing
122   * mappings satisfy the constraint.
123   *
124   * <p>Note that the generated multimap's {@link Multimap#removeAll} and
125   * {@link Multimap#replaceValues} methods return collections that are not
126   * constrained.
127   *
128   * <p>The returned multimap is not serializable.
129   *
130   * @param multimap the multimap to constrain
131   * @param constraint the constraint that validates added entries
132   * @return a constrained view of the specified multimap
133   */
134  public static <K, V> ListMultimap<K, V> constrainedListMultimap(
135      ListMultimap<K, V> multimap, MapConstraint<? super K, ? super V> constraint) {
136    return new ConstrainedListMultimap<K, V>(multimap, constraint);
137  }
138
139  /**
140   * Returns a constrained view of the specified set multimap, using the
141   * specified constraint. Any operations that add new mappings will call the
142   * provided constraint. However, this method does not verify that existing
143   * mappings satisfy the constraint.
144   *
145   * <p>Note that the generated multimap's {@link Multimap#removeAll} and
146   * {@link Multimap#replaceValues} methods return collections that are not
147   * constrained.
148   * <p>The returned multimap is not serializable.
149   *
150   * @param multimap the multimap to constrain
151   * @param constraint the constraint that validates added entries
152   * @return a constrained view of the specified multimap
153   */
154  public static <K, V> SetMultimap<K, V> constrainedSetMultimap(
155      SetMultimap<K, V> multimap, MapConstraint<? super K, ? super V> constraint) {
156    return new ConstrainedSetMultimap<K, V>(multimap, constraint);
157  }
158
159  /**
160   * Returns a constrained view of the specified sorted-set multimap, using the
161   * specified constraint. Any operations that add new mappings will call the
162   * provided constraint. However, this method does not verify that existing
163   * mappings satisfy the constraint.
164   *
165   * <p>Note that the generated multimap's {@link Multimap#removeAll} and
166   * {@link Multimap#replaceValues} methods return collections that are not
167   * constrained.
168   * <p>The returned multimap is not serializable.
169   *
170   * @param multimap the multimap to constrain
171   * @param constraint the constraint that validates added entries
172   * @return a constrained view of the specified multimap
173   */
174  public static <K, V> SortedSetMultimap<K, V> constrainedSortedSetMultimap(
175      SortedSetMultimap<K, V> multimap, MapConstraint<? super K, ? super V> constraint) {
176    return new ConstrainedSortedSetMultimap<K, V>(multimap, constraint);
177  }
178
179  /**
180   * Returns a constrained view of the specified entry, using the specified
181   * constraint. The {@link Entry#setValue} operation will be verified with the
182   * constraint.
183   *
184   * @param entry the entry to constrain
185   * @param constraint the constraint for the entry
186   * @return a constrained view of the specified entry
187   */
188  private static <K, V> Entry<K, V> constrainedEntry(
189      final Entry<K, V> entry, final MapConstraint<? super K, ? super V> constraint) {
190    checkNotNull(entry);
191    checkNotNull(constraint);
192    return new ForwardingMapEntry<K, V>() {
193      @Override
194      protected Entry<K, V> delegate() {
195        return entry;
196      }
197
198      @Override
199      public V setValue(V value) {
200        constraint.checkKeyValue(getKey(), value);
201        return entry.setValue(value);
202      }
203    };
204  }
205
206  /**
207   * Returns a constrained view of the specified {@code asMap} entry, using the
208   * specified constraint. The {@link Entry#setValue} operation will be verified
209   * with the constraint, and the collection returned by {@link Entry#getValue}
210   * will be similarly constrained.
211   *
212   * @param entry the {@code asMap} entry to constrain
213   * @param constraint the constraint for the entry
214   * @return a constrained view of the specified entry
215   */
216  private static <K, V> Entry<K, Collection<V>> constrainedAsMapEntry(
217      final Entry<K, Collection<V>> entry, final MapConstraint<? super K, ? super V> constraint) {
218    checkNotNull(entry);
219    checkNotNull(constraint);
220    return new ForwardingMapEntry<K, Collection<V>>() {
221      @Override
222      protected Entry<K, Collection<V>> delegate() {
223        return entry;
224      }
225
226      @Override
227      public Collection<V> getValue() {
228        return Constraints.constrainedTypePreservingCollection(
229            entry.getValue(),
230            new Constraint<V>() {
231              @Override
232              public V checkElement(V value) {
233                constraint.checkKeyValue(getKey(), value);
234                return value;
235              }
236            });
237      }
238    };
239  }
240
241  /**
242   * Returns a constrained view of the specified set of {@code asMap} entries,
243   * using the specified constraint. The {@link Entry#setValue} operation will
244   * be verified with the constraint, and the collection returned by {@link
245   * Entry#getValue} will be similarly constrained. The {@code add} and {@code
246   * addAll} operations simply forward to the underlying set, which throws an
247   * {@link UnsupportedOperationException} per the multimap specification.
248   *
249   * @param entries the entries to constrain
250   * @param constraint the constraint for the entries
251   * @return a constrained view of the entries
252   */
253  private static <K, V> Set<Entry<K, Collection<V>>> constrainedAsMapEntries(
254      Set<Entry<K, Collection<V>>> entries, MapConstraint<? super K, ? super V> constraint) {
255    return new ConstrainedAsMapEntries<K, V>(entries, constraint);
256  }
257
258  /**
259   * Returns a constrained view of the specified collection (or set) of entries,
260   * using the specified constraint. The {@link Entry#setValue} operation will
261   * be verified with the constraint, along with add operations on the returned
262   * collection. The {@code add} and {@code addAll} operations simply forward to
263   * the underlying collection, which throws an {@link
264   * UnsupportedOperationException} per the map and multimap specification.
265   *
266   * @param entries the entries to constrain
267   * @param constraint the constraint for the entries
268   * @return a constrained view of the specified entries
269   */
270  private static <K, V> Collection<Entry<K, V>> constrainedEntries(
271      Collection<Entry<K, V>> entries, MapConstraint<? super K, ? super V> constraint) {
272    if (entries instanceof Set) {
273      return constrainedEntrySet((Set<Entry<K, V>>) entries, constraint);
274    }
275    return new ConstrainedEntries<K, V>(entries, constraint);
276  }
277
278  /**
279   * Returns a constrained view of the specified set of entries, using the
280   * specified constraint. The {@link Entry#setValue} operation will be verified
281   * with the constraint, along with add operations on the returned set. The
282   * {@code add} and {@code addAll} operations simply forward to the underlying
283   * set, which throws an {@link UnsupportedOperationException} per the map and
284   * multimap specification.
285   *
286   * <p>The returned multimap is not serializable.
287   *
288   * @param entries the entries to constrain
289   * @param constraint the constraint for the entries
290   * @return a constrained view of the specified entries
291   */
292  private static <K, V> Set<Entry<K, V>> constrainedEntrySet(
293      Set<Entry<K, V>> entries, MapConstraint<? super K, ? super V> constraint) {
294    return new ConstrainedEntrySet<K, V>(entries, constraint);
295  }
296
297  /** @see MapConstraints#constrainedMap */
298  static class ConstrainedMap<K, V> extends ForwardingMap<K, V> {
299    private final Map<K, V> delegate;
300    final MapConstraint<? super K, ? super V> constraint;
301    private transient Set<Entry<K, V>> entrySet;
302
303    ConstrainedMap(Map<K, V> delegate, MapConstraint<? super K, ? super V> constraint) {
304      this.delegate = checkNotNull(delegate);
305      this.constraint = checkNotNull(constraint);
306    }
307
308    @Override
309    protected Map<K, V> delegate() {
310      return delegate;
311    }
312
313    @Override
314    public Set<Entry<K, V>> entrySet() {
315      Set<Entry<K, V>> result = entrySet;
316      if (result == null) {
317        entrySet = result = constrainedEntrySet(delegate.entrySet(), constraint);
318      }
319      return result;
320    }
321
322    @Override
323    public V put(K key, V value) {
324      constraint.checkKeyValue(key, value);
325      return delegate.put(key, value);
326    }
327
328    @Override
329    public void putAll(Map<? extends K, ? extends V> map) {
330      delegate.putAll(checkMap(map, constraint));
331    }
332  }
333
334  /**
335   * Returns a constrained view of the specified bimap, using the specified
336   * constraint. Any operations that modify the bimap will have the associated
337   * keys and values verified with the constraint.
338   *
339   * <p>The returned bimap is not serializable.
340   *
341   * @param map the bimap to constrain
342   * @param constraint the constraint that validates added entries
343   * @return a constrained view of the specified bimap
344   */
345  public static <K, V> BiMap<K, V> constrainedBiMap(
346      BiMap<K, V> map, MapConstraint<? super K, ? super V> constraint) {
347    return new ConstrainedBiMap<K, V>(map, null, constraint);
348  }
349
350  /** @see MapConstraints#constrainedBiMap */
351  private static class ConstrainedBiMap<K, V> extends ConstrainedMap<K, V> implements BiMap<K, V> {
352    /*
353     * We could switch to racy single-check lazy init and remove volatile, but
354     * there's a downside. That's because this field is also written in the
355     * constructor. Without volatile, the constructor's write of the existing
356     * inverse BiMap could occur after inverse()'s read of the field's initial
357     * null value, leading inverse() to overwrite the existing inverse with a
358     * doubly indirect version. This wouldn't be catastrophic, but it's
359     * something to keep in mind if we make the change.
360     *
361     * Note that UnmodifiableBiMap *does* use racy single-check lazy init.
362     * TODO(cpovirk): pick one and standardize
363     */
364    volatile BiMap<V, K> inverse;
365
366    ConstrainedBiMap(
367        BiMap<K, V> delegate,
368        @Nullable BiMap<V, K> inverse,
369        MapConstraint<? super K, ? super V> constraint) {
370      super(delegate, constraint);
371      this.inverse = inverse;
372    }
373
374    @Override
375    protected BiMap<K, V> delegate() {
376      return (BiMap<K, V>) super.delegate();
377    }
378
379    @Override
380    public V forcePut(K key, V value) {
381      constraint.checkKeyValue(key, value);
382      return delegate().forcePut(key, value);
383    }
384
385    @Override
386    public BiMap<V, K> inverse() {
387      if (inverse == null) {
388        inverse = new ConstrainedBiMap<V, K>(
389            delegate().inverse(), this, new InverseConstraint<V, K>(constraint));
390      }
391      return inverse;
392    }
393
394    @Override
395    public Set<V> values() {
396      return delegate().values();
397    }
398  }
399
400  /** @see MapConstraints#constrainedBiMap */
401  private static class InverseConstraint<K, V> implements MapConstraint<K, V> {
402    final MapConstraint<? super V, ? super K> constraint;
403
404    public InverseConstraint(MapConstraint<? super V, ? super K> constraint) {
405      this.constraint = checkNotNull(constraint);
406    }
407
408    @Override
409    public void checkKeyValue(K key, V value) {
410      constraint.checkKeyValue(value, key);
411    }
412  }
413
414  /** @see MapConstraints#constrainedMultimap */
415  private static class ConstrainedMultimap<K, V> extends ForwardingMultimap<K, V>
416      implements Serializable {
417    final MapConstraint<? super K, ? super V> constraint;
418    final Multimap<K, V> delegate;
419
420    transient Collection<Entry<K, V>> entries;
421
422    transient Map<K, Collection<V>> asMap;
423
424    public ConstrainedMultimap(
425        Multimap<K, V> delegate, MapConstraint<? super K, ? super V> constraint) {
426      this.delegate = checkNotNull(delegate);
427      this.constraint = checkNotNull(constraint);
428    }
429
430    @Override
431    protected Multimap<K, V> delegate() {
432      return delegate;
433    }
434
435    @Override
436    public Map<K, Collection<V>> asMap() {
437      Map<K, Collection<V>> result = asMap;
438      if (result == null) {
439        final Map<K, Collection<V>> asMapDelegate = delegate.asMap();
440
441        @WeakOuter
442        class AsMap extends ForwardingMap<K, Collection<V>> {
443          Set<Entry<K, Collection<V>>> entrySet;
444          Collection<Collection<V>> values;
445
446          @Override
447          protected Map<K, Collection<V>> delegate() {
448            return asMapDelegate;
449          }
450
451          @Override
452          public Set<Entry<K, Collection<V>>> entrySet() {
453            Set<Entry<K, Collection<V>>> result = entrySet;
454            if (result == null) {
455              entrySet = result = constrainedAsMapEntries(asMapDelegate.entrySet(), constraint);
456            }
457            return result;
458          }
459
460          @SuppressWarnings("unchecked")
461          @Override
462          public Collection<V> get(Object key) {
463            try {
464              Collection<V> collection = ConstrainedMultimap.this.get((K) key);
465              return collection.isEmpty() ? null : collection;
466            } catch (ClassCastException e) {
467              return null; // key wasn't a K
468            }
469          }
470
471          @Override
472          public Collection<Collection<V>> values() {
473            Collection<Collection<V>> result = values;
474            if (result == null) {
475              values = result = new ConstrainedAsMapValues<K, V>(delegate().values(), entrySet());
476            }
477            return result;
478          }
479
480          @Override
481          public boolean containsValue(Object o) {
482            return values().contains(o);
483          }
484        }
485        asMap = result = new AsMap();
486      }
487      return result;
488    }
489
490    @Override
491    public Collection<Entry<K, V>> entries() {
492      Collection<Entry<K, V>> result = entries;
493      if (result == null) {
494        entries = result = constrainedEntries(delegate.entries(), constraint);
495      }
496      return result;
497    }
498
499    @Override
500    public Collection<V> get(final K key) {
501      return Constraints.constrainedTypePreservingCollection(
502          delegate.get(key),
503          new Constraint<V>() {
504            @Override
505            public V checkElement(V value) {
506              constraint.checkKeyValue(key, value);
507              return value;
508            }
509          });
510    }
511
512    @Override
513    public boolean put(K key, V value) {
514      constraint.checkKeyValue(key, value);
515      return delegate.put(key, value);
516    }
517
518    @Override
519    public boolean putAll(K key, Iterable<? extends V> values) {
520      return delegate.putAll(key, checkValues(key, values, constraint));
521    }
522
523    @Override
524    public boolean putAll(Multimap<? extends K, ? extends V> multimap) {
525      boolean changed = false;
526      for (Entry<? extends K, ? extends V> entry : multimap.entries()) {
527        changed |= put(entry.getKey(), entry.getValue());
528      }
529      return changed;
530    }
531
532    @Override
533    public Collection<V> replaceValues(K key, Iterable<? extends V> values) {
534      return delegate.replaceValues(key, checkValues(key, values, constraint));
535    }
536  }
537
538  /** @see ConstrainedMultimap#asMap */
539  private static class ConstrainedAsMapValues<K, V> extends ForwardingCollection<Collection<V>> {
540    final Collection<Collection<V>> delegate;
541    final Set<Entry<K, Collection<V>>> entrySet;
542
543    /**
544     * @param entrySet map entries, linking each key with its corresponding
545     *     values, that already enforce the constraint
546     */
547    ConstrainedAsMapValues(
548        Collection<Collection<V>> delegate, Set<Entry<K, Collection<V>>> entrySet) {
549      this.delegate = delegate;
550      this.entrySet = entrySet;
551    }
552
553    @Override
554    protected Collection<Collection<V>> delegate() {
555      return delegate;
556    }
557
558    @Override
559    public Iterator<Collection<V>> iterator() {
560      final Iterator<Entry<K, Collection<V>>> iterator = entrySet.iterator();
561      return new Iterator<Collection<V>>() {
562        @Override
563        public boolean hasNext() {
564          return iterator.hasNext();
565        }
566
567        @Override
568        public Collection<V> next() {
569          return iterator.next().getValue();
570        }
571
572        @Override
573        public void remove() {
574          iterator.remove();
575        }
576      };
577    }
578
579    @Override
580    public Object[] toArray() {
581      return standardToArray();
582    }
583
584    @Override
585    public <T> T[] toArray(T[] array) {
586      return standardToArray(array);
587    }
588
589    @Override
590    public boolean contains(Object o) {
591      return standardContains(o);
592    }
593
594    @Override
595    public boolean containsAll(Collection<?> c) {
596      return standardContainsAll(c);
597    }
598
599    @Override
600    public boolean remove(Object o) {
601      return standardRemove(o);
602    }
603
604    @Override
605    public boolean removeAll(Collection<?> c) {
606      return standardRemoveAll(c);
607    }
608
609    @Override
610    public boolean retainAll(Collection<?> c) {
611      return standardRetainAll(c);
612    }
613  }
614
615  /** @see MapConstraints#constrainedEntries */
616  private static class ConstrainedEntries<K, V> extends ForwardingCollection<Entry<K, V>> {
617    final MapConstraint<? super K, ? super V> constraint;
618    final Collection<Entry<K, V>> entries;
619
620    ConstrainedEntries(
621        Collection<Entry<K, V>> entries, MapConstraint<? super K, ? super V> constraint) {
622      this.entries = entries;
623      this.constraint = constraint;
624    }
625
626    @Override
627    protected Collection<Entry<K, V>> delegate() {
628      return entries;
629    }
630
631    @Override
632    public Iterator<Entry<K, V>> iterator() {
633      return new TransformedIterator<Entry<K, V>, Entry<K, V>>(entries.iterator()) {
634        @Override
635        Entry<K, V> transform(Entry<K, V> from) {
636          return constrainedEntry(from, constraint);
637        }
638      };
639    }
640
641    // See Collections.CheckedMap.CheckedEntrySet for details on attacks.
642
643    @Override
644    public Object[] toArray() {
645      return standardToArray();
646    }
647
648    @Override
649    public <T> T[] toArray(T[] array) {
650      return standardToArray(array);
651    }
652
653    @Override
654    public boolean contains(Object o) {
655      return Maps.containsEntryImpl(delegate(), o);
656    }
657
658    @Override
659    public boolean containsAll(Collection<?> c) {
660      return standardContainsAll(c);
661    }
662
663    @Override
664    public boolean remove(Object o) {
665      return Maps.removeEntryImpl(delegate(), o);
666    }
667
668    @Override
669    public boolean removeAll(Collection<?> c) {
670      return standardRemoveAll(c);
671    }
672
673    @Override
674    public boolean retainAll(Collection<?> c) {
675      return standardRetainAll(c);
676    }
677  }
678
679  /** @see MapConstraints#constrainedEntrySet */
680  static class ConstrainedEntrySet<K, V> extends ConstrainedEntries<K, V>
681      implements Set<Entry<K, V>> {
682    ConstrainedEntrySet(Set<Entry<K, V>> entries, MapConstraint<? super K, ? super V> constraint) {
683      super(entries, constraint);
684    }
685
686    // See Collections.CheckedMap.CheckedEntrySet for details on attacks.
687
688    @Override
689    public boolean equals(@Nullable Object object) {
690      return Sets.equalsImpl(this, object);
691    }
692
693    @Override
694    public int hashCode() {
695      return Sets.hashCodeImpl(this);
696    }
697  }
698
699  /** @see MapConstraints#constrainedAsMapEntries */
700  static class ConstrainedAsMapEntries<K, V> extends ForwardingSet<Entry<K, Collection<V>>> {
701    private final MapConstraint<? super K, ? super V> constraint;
702    private final Set<Entry<K, Collection<V>>> entries;
703
704    ConstrainedAsMapEntries(
705        Set<Entry<K, Collection<V>>> entries, MapConstraint<? super K, ? super V> constraint) {
706      this.entries = entries;
707      this.constraint = constraint;
708    }
709
710    @Override
711    protected Set<Entry<K, Collection<V>>> delegate() {
712      return entries;
713    }
714
715    @Override
716    public Iterator<Entry<K, Collection<V>>> iterator() {
717      return new TransformedIterator<Entry<K, Collection<V>>, Entry<K, Collection<V>>>(
718          entries.iterator()) {
719        @Override
720        Entry<K, Collection<V>> transform(Entry<K, Collection<V>> from) {
721          return constrainedAsMapEntry(from, constraint);
722        }
723      };
724    }
725
726    // See Collections.CheckedMap.CheckedEntrySet for details on attacks.
727
728    @Override
729    public Object[] toArray() {
730      return standardToArray();
731    }
732
733    @Override
734    public <T> T[] toArray(T[] array) {
735      return standardToArray(array);
736    }
737
738    @Override
739    public boolean contains(Object o) {
740      return Maps.containsEntryImpl(delegate(), o);
741    }
742
743    @Override
744    public boolean containsAll(Collection<?> c) {
745      return standardContainsAll(c);
746    }
747
748    @Override
749    public boolean equals(@Nullable Object object) {
750      return standardEquals(object);
751    }
752
753    @Override
754    public int hashCode() {
755      return standardHashCode();
756    }
757
758    @Override
759    public boolean remove(Object o) {
760      return Maps.removeEntryImpl(delegate(), o);
761    }
762
763    @Override
764    public boolean removeAll(Collection<?> c) {
765      return standardRemoveAll(c);
766    }
767
768    @Override
769    public boolean retainAll(Collection<?> c) {
770      return standardRetainAll(c);
771    }
772  }
773
774  private static class ConstrainedListMultimap<K, V> extends ConstrainedMultimap<K, V>
775      implements ListMultimap<K, V> {
776    ConstrainedListMultimap(
777        ListMultimap<K, V> delegate, MapConstraint<? super K, ? super V> constraint) {
778      super(delegate, constraint);
779    }
780
781    @Override
782    public List<V> get(K key) {
783      return (List<V>) super.get(key);
784    }
785
786    @Override
787    public List<V> removeAll(Object key) {
788      return (List<V>) super.removeAll(key);
789    }
790
791    @Override
792    public List<V> replaceValues(K key, Iterable<? extends V> values) {
793      return (List<V>) super.replaceValues(key, values);
794    }
795  }
796
797  private static class ConstrainedSetMultimap<K, V> extends ConstrainedMultimap<K, V>
798      implements SetMultimap<K, V> {
799    ConstrainedSetMultimap(
800        SetMultimap<K, V> delegate, MapConstraint<? super K, ? super V> constraint) {
801      super(delegate, constraint);
802    }
803
804    @Override
805    public Set<V> get(K key) {
806      return (Set<V>) super.get(key);
807    }
808
809    @Override
810    public Set<Map.Entry<K, V>> entries() {
811      return (Set<Map.Entry<K, V>>) super.entries();
812    }
813
814    @Override
815    public Set<V> removeAll(Object key) {
816      return (Set<V>) super.removeAll(key);
817    }
818
819    @Override
820    public Set<V> replaceValues(K key, Iterable<? extends V> values) {
821      return (Set<V>) super.replaceValues(key, values);
822    }
823  }
824
825  private static class ConstrainedSortedSetMultimap<K, V> extends ConstrainedSetMultimap<K, V>
826      implements SortedSetMultimap<K, V> {
827    ConstrainedSortedSetMultimap(
828        SortedSetMultimap<K, V> delegate, MapConstraint<? super K, ? super V> constraint) {
829      super(delegate, constraint);
830    }
831
832    @Override
833    public SortedSet<V> get(K key) {
834      return (SortedSet<V>) super.get(key);
835    }
836
837    @Override
838    public SortedSet<V> removeAll(Object key) {
839      return (SortedSet<V>) super.removeAll(key);
840    }
841
842    @Override
843    public SortedSet<V> replaceValues(K key, Iterable<? extends V> values) {
844      return (SortedSet<V>) super.replaceValues(key, values);
845    }
846
847    @Override
848    public Comparator<? super V> valueComparator() {
849      return ((SortedSetMultimap<K, V>) delegate()).valueComparator();
850    }
851  }
852
853  private static <K, V> Collection<V> checkValues(
854      K key, Iterable<? extends V> values, MapConstraint<? super K, ? super V> constraint) {
855    Collection<V> copy = Lists.newArrayList(values);
856    for (V value : copy) {
857      constraint.checkKeyValue(key, value);
858    }
859    return copy;
860  }
861
862  private static <K, V> Map<K, V> checkMap(
863      Map<? extends K, ? extends V> map, MapConstraint<? super K, ? super V> constraint) {
864    Map<K, V> copy = new LinkedHashMap<K, V>(map);
865    for (Entry<K, V> entry : copy.entrySet()) {
866      constraint.checkKeyValue(entry.getKey(), entry.getValue());
867    }
868    return copy;
869  }
870}