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 }