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