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