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