11d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/*
21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Copyright (C) 2007 The Guava Authors
31d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
41d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Licensed under the Apache License, Version 2.0 (the "License");
51d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * you may not use this file except in compliance with the License.
61d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * You may obtain a copy of the License at
71d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
81d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * http://www.apache.org/licenses/LICENSE-2.0
91d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Unless required by applicable law or agreed to in writing, software
111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * distributed under the License is distributed on an "AS IS" BASIS,
121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * See the License for the specific language governing permissions and
141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * limitations under the License.
151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpackage com.google.common.collect;
181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.base.Preconditions.checkNotNull;
201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.annotations.Beta;
221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.annotations.GwtCompatible;
231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Collection;
251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Comparator;
261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Iterator;
271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.LinkedHashMap;
281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.List;
291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Map;
301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Map.Entry;
311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Set;
321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.SortedSet;
331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport javax.annotation.Nullable;
351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/**
371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Factory and utilities pertaining to the {@code MapConstraint} interface.
381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @see Constraints
401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Mike Bostock
411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @since 3.0
421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert@Beta
441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert@GwtCompatible
451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpublic final class MapConstraints {
461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private MapConstraints() {}
471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns a constraint that verifies that neither the key nor the value is
501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * null. If either is null, a {@link NullPointerException} is thrown.
511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static MapConstraint<Object, Object> notNull() {
531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return NotNullMapConstraint.INSTANCE;
541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  // enum singleton pattern
571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private enum NotNullMapConstraint implements MapConstraint<Object, Object> {
581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    INSTANCE;
591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void checkKeyValue(Object key, Object value) {
621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      checkNotNull(key);
631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      checkNotNull(value);
641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public String toString() {
671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return "Not null";
681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns a constrained view of the specified map, using the specified
731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * constraint. Any operations that add new mappings will call the provided
741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * constraint. However, this method does not verify that existing mappings
751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * satisfy the constraint.
761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>The returned map is not serializable.
781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param map the map to constrain
801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param constraint the constraint that validates added entries
811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return a constrained view of the specified map
821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static <K, V> Map<K, V> constrainedMap(
841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Map<K, V> map, MapConstraint<? super K, ? super V> constraint) {
851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return new ConstrainedMap<K, V>(map, constraint);
861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns a constrained view of the specified multimap, using the specified
901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * constraint. Any operations that add new mappings will call the provided
911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * constraint. However, this method does not verify that existing mappings
921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * satisfy the constraint.
931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>Note that the generated multimap's {@link Multimap#removeAll} and
951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * {@link Multimap#replaceValues} methods return collections that are not
961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * constrained.
971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>The returned multimap is not serializable.
991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param multimap the multimap to constrain
1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param constraint the constraint that validates added entries
1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return a constrained view of the multimap
1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static <K, V> Multimap<K, V> constrainedMultimap(
1051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Multimap<K, V> multimap, MapConstraint<? super K, ? super V> constraint) {
1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return new ConstrainedMultimap<K, V>(multimap, constraint);
1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns a constrained view of the specified list multimap, using the
1111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * specified constraint. Any operations that add new mappings will call the
1121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * provided constraint. However, this method does not verify that existing
1131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * mappings satisfy the constraint.
1141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
1151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>Note that the generated multimap's {@link Multimap#removeAll} and
1161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * {@link Multimap#replaceValues} methods return collections that are not
1171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * constrained.
1181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
1191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>The returned multimap is not serializable.
1201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
1211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param multimap the multimap to constrain
1221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param constraint the constraint that validates added entries
1231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return a constrained view of the specified multimap
1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static <K, V> ListMultimap<K, V> constrainedListMultimap(
1261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      ListMultimap<K, V> multimap,
1271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      MapConstraint<? super K, ? super V> constraint) {
1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return new ConstrainedListMultimap<K, V>(multimap, constraint);
1291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns a constrained view of the specified set multimap, using the
1331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * specified constraint. Any operations that add new mappings will call the
1341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * provided constraint. However, this method does not verify that existing
1351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * mappings satisfy the constraint.
1361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
1371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>Note that the generated multimap's {@link Multimap#removeAll} and
1381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * {@link Multimap#replaceValues} methods return collections that are not
1391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * constrained.
1401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>The returned multimap is not serializable.
1411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
1421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param multimap the multimap to constrain
1431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param constraint the constraint that validates added entries
1441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return a constrained view of the specified multimap
1451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static <K, V> SetMultimap<K, V> constrainedSetMultimap(
1471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      SetMultimap<K, V> multimap,
1481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      MapConstraint<? super K, ? super V> constraint) {
1491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return new ConstrainedSetMultimap<K, V>(multimap, constraint);
1501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns a constrained view of the specified sorted-set multimap, using the
1541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * specified constraint. Any operations that add new mappings will call the
1551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * provided constraint. However, this method does not verify that existing
1561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * mappings satisfy the constraint.
1571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
1581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>Note that the generated multimap's {@link Multimap#removeAll} and
1591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * {@link Multimap#replaceValues} methods return collections that are not
1601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * constrained.
1611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>The returned multimap is not serializable.
1621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
1631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param multimap the multimap to constrain
1641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param constraint the constraint that validates added entries
1651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return a constrained view of the specified multimap
1661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static <K, V> SortedSetMultimap<K, V> constrainedSortedSetMultimap(
1681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      SortedSetMultimap<K, V> multimap,
1691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      MapConstraint<? super K, ? super V> constraint) {
1701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return new ConstrainedSortedSetMultimap<K, V>(multimap, constraint);
1711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns a constrained view of the specified entry, using the specified
1751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * constraint. The {@link Entry#setValue} operation will be verified with the
1761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * constraint.
1771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
1781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param entry the entry to constrain
1791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param constraint the constraint for the entry
1801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return a constrained view of the specified entry
1811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static <K, V> Entry<K, V> constrainedEntry(
1831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      final Entry<K, V> entry,
1841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      final MapConstraint<? super K, ? super V> constraint) {
1851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    checkNotNull(entry);
1861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    checkNotNull(constraint);
1871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return new ForwardingMapEntry<K, V>() {
1881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override protected Entry<K, V> delegate() {
1891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return entry;
1901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
1911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override public V setValue(V value) {
1921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        constraint.checkKeyValue(getKey(), value);
1931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return entry.setValue(value);
1941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
1951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    };
1961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns a constrained view of the specified {@code asMap} entry, using the
2001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * specified constraint. The {@link Entry#setValue} operation will be verified
2011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * with the constraint, and the collection returned by {@link Entry#getValue}
2021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * will be similarly constrained.
2031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
2041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param entry the {@code asMap} entry to constrain
2051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param constraint the constraint for the entry
2061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return a constrained view of the specified entry
2071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
2081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static <K, V> Entry<K, Collection<V>> constrainedAsMapEntry(
2091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      final Entry<K, Collection<V>> entry,
2101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      final MapConstraint<? super K, ? super V> constraint) {
2111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    checkNotNull(entry);
2121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    checkNotNull(constraint);
2131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return new ForwardingMapEntry<K, Collection<V>>() {
2141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override protected Entry<K, Collection<V>> delegate() {
2151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return entry;
2161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
2171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override public Collection<V> getValue() {
2181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return Constraints.constrainedTypePreservingCollection(
2191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            entry.getValue(), new Constraint<V>() {
2201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          @Override
2211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          public V checkElement(V value) {
2221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            constraint.checkKeyValue(getKey(), value);
2231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            return value;
2241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
2251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        });
2261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
2271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    };
2281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
2311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns a constrained view of the specified set of {@code asMap} entries,
2321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * using the specified constraint. The {@link Entry#setValue} operation will
2331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * be verified with the constraint, and the collection returned by {@link
2341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Entry#getValue} will be similarly constrained. The {@code add} and {@code
2351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * addAll} operations simply forward to the underlying set, which throws an
2361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * {@link UnsupportedOperationException} per the multimap specification.
2371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
2381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param entries the entries to constrain
2391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param constraint the constraint for the entries
2401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return a constrained view of the entries
2411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
2421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static <K, V> Set<Entry<K, Collection<V>>> constrainedAsMapEntries(
2431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Set<Entry<K, Collection<V>>> entries,
2441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      MapConstraint<? super K, ? super V> constraint) {
2451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return new ConstrainedAsMapEntries<K, V>(entries, constraint);
2461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
2491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns a constrained view of the specified collection (or set) of entries,
2501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * using the specified constraint. The {@link Entry#setValue} operation will
2511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * be verified with the constraint, along with add operations on the returned
2521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * collection. The {@code add} and {@code addAll} operations simply forward to
2531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * the underlying collection, which throws an {@link
2541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * UnsupportedOperationException} per the map and multimap specification.
2551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
2561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param entries the entries to constrain
2571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param constraint the constraint for the entries
2581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return a constrained view of the specified entries
2591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
2601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static <K, V> Collection<Entry<K, V>> constrainedEntries(
2611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Collection<Entry<K, V>> entries,
2621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      MapConstraint<? super K, ? super V> constraint) {
2631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (entries instanceof Set) {
2641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return constrainedEntrySet((Set<Entry<K, V>>) entries, constraint);
2651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return new ConstrainedEntries<K, V>(entries, constraint);
2671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
2701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns a constrained view of the specified set of entries, using the
2711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * specified constraint. The {@link Entry#setValue} operation will be verified
2721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * with the constraint, along with add operations on the returned set. The
2731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * {@code add} and {@code addAll} operations simply forward to the underlying
2741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * set, which throws an {@link UnsupportedOperationException} per the map and
2751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * multimap specification.
2761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
2771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>The returned multimap is not serializable.
2781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
2791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param entries the entries to constrain
2801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param constraint the constraint for the entries
2811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return a constrained view of the specified entries
2821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
2831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static <K, V> Set<Entry<K, V>> constrainedEntrySet(
2841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Set<Entry<K, V>> entries,
2851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      MapConstraint<? super K, ? super V> constraint) {
2861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return new ConstrainedEntrySet<K, V>(entries, constraint);
2871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /** @see MapConstraints#constrainedMap */
2901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static class ConstrainedMap<K, V> extends ForwardingMap<K, V> {
2911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private final Map<K, V> delegate;
2921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final MapConstraint<? super K, ? super V> constraint;
2931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private transient Set<Entry<K, V>> entrySet;
2941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ConstrainedMap(
2961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        Map<K, V> delegate, MapConstraint<? super K, ? super V> constraint) {
2971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.delegate = checkNotNull(delegate);
2981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.constraint = checkNotNull(constraint);
2991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override protected Map<K, V> delegate() {
3011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return delegate;
3021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public Set<Entry<K, V>> entrySet() {
3041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Set<Entry<K, V>> result = entrySet;
3051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (result == null) {
3061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        entrySet = result =
3071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            constrainedEntrySet(delegate.entrySet(), constraint);
3081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
3091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return result;
3101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public V put(K key, V value) {
3121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      constraint.checkKeyValue(key, value);
3131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return delegate.put(key, value);
3141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public void putAll(Map<? extends K, ? extends V> map) {
3161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      delegate.putAll(checkMap(map, constraint));
3171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
3211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns a constrained view of the specified bimap, using the specified
3221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * constraint. Any operations that modify the bimap will have the associated
3231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * keys and values verified with the constraint.
3241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
3251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>The returned bimap is not serializable.
3261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
3271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param map the bimap to constrain
3281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param constraint the constraint that validates added entries
3291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return a constrained view of the specified bimap
3301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
3311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static <K, V> BiMap<K, V> constrainedBiMap(
3321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      BiMap<K, V> map, MapConstraint<? super K, ? super V> constraint) {
3331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return new ConstrainedBiMap<K, V>(map, null, constraint);
3341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /** @see MapConstraints#constrainedBiMap */
3371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static class ConstrainedBiMap<K, V> extends ConstrainedMap<K, V>
3381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      implements BiMap<K, V> {
3391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /*
3401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * We could switch to racy single-check lazy init and remove volatile, but
3411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * there's a downside. That's because this field is also written in the
3421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * constructor. Without volatile, the constructor's write of the existing
3431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * inverse BiMap could occur after inverse()'s read of the field's initial
3441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * null value, leading inverse() to overwrite the existing inverse with a
3451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * doubly indirect version. This wouldn't be catastrophic, but it's
3461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * something to keep in mind if we make the change.
3471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     *
3481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Note that UnmodifiableBiMap *does* use racy single-check lazy init.
3491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * TODO(cpovirk): pick one and standardize
3501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
3511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    volatile BiMap<V, K> inverse;
3521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ConstrainedBiMap(BiMap<K, V> delegate, @Nullable BiMap<V, K> inverse,
3541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        MapConstraint<? super K, ? super V> constraint) {
3551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      super(delegate, constraint);
3561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.inverse = inverse;
3571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override protected BiMap<K, V> delegate() {
3601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return (BiMap<K, V>) super.delegate();
3611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
3641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public V forcePut(K key, V value) {
3651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      constraint.checkKeyValue(key, value);
3661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return delegate().forcePut(key, value);
3671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
3701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public BiMap<V, K> inverse() {
3711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (inverse == null) {
3721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        inverse = new ConstrainedBiMap<V, K>(delegate().inverse(), this,
3731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            new InverseConstraint<V, K>(constraint));
3741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
3751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return inverse;
3761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public Set<V> values() {
3791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return delegate().values();
3801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /** @see MapConstraints#constrainedBiMap */
3841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static class InverseConstraint<K, V> implements MapConstraint<K, V> {
3851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final MapConstraint<? super V, ? super K> constraint;
3861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public InverseConstraint(MapConstraint<? super V, ? super K> constraint) {
3881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.constraint = checkNotNull(constraint);
3891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
3911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void checkKeyValue(K key, V value) {
3921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      constraint.checkKeyValue(value, key);
3931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /** @see MapConstraints#constrainedMultimap */
3971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static class ConstrainedMultimap<K, V>
3981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      extends ForwardingMultimap<K, V> {
3991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final MapConstraint<? super K, ? super V> constraint;
4001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final Multimap<K, V> delegate;
4011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    transient Collection<Entry<K, V>> entries;
4021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    transient Map<K, Collection<V>> asMap;
4031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ConstrainedMultimap(Multimap<K, V> delegate,
4051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        MapConstraint<? super K, ? super V> constraint) {
4061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.delegate = checkNotNull(delegate);
4071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.constraint = checkNotNull(constraint);
4081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
4091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override protected Multimap<K, V> delegate() {
4111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return delegate;
4121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
4131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public Map<K, Collection<V>> asMap() {
4151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Map<K, Collection<V>> result = asMap;
4161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (result == null) {
4171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        final Map<K, Collection<V>> asMapDelegate = delegate.asMap();
4181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        asMap = result = new ForwardingMap<K, Collection<V>>() {
4201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          Set<Entry<K, Collection<V>>> entrySet;
4211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          Collection<Collection<V>> values;
4221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          @Override protected Map<K, Collection<V>> delegate() {
4241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            return asMapDelegate;
4251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
4261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          @Override public Set<Entry<K, Collection<V>>> entrySet() {
4281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            Set<Entry<K, Collection<V>>> result = entrySet;
4291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            if (result == null) {
4301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              entrySet = result = constrainedAsMapEntries(
4311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                  asMapDelegate.entrySet(), constraint);
4321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            }
4331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            return result;
4341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
4351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          @SuppressWarnings("unchecked")
4371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          @Override public Collection<V> get(Object key) {
4381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            try {
4391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              Collection<V> collection = ConstrainedMultimap.this.get((K) key);
4401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              return collection.isEmpty() ? null : collection;
4411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            } catch (ClassCastException e) {
4421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              return null; // key wasn't a K
4431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            }
4441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
4451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          @Override public Collection<Collection<V>> values() {
4471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            Collection<Collection<V>> result = values;
4481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            if (result == null) {
4491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              values = result = new ConstrainedAsMapValues<K, V>(
4501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                  delegate().values(), entrySet());
4511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            }
4521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            return result;
4531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
4541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          @Override public boolean containsValue(Object o) {
4561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            return values().contains(o);
4571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
4581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        };
4591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
4601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return result;
4611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
4621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public Collection<Entry<K, V>> entries() {
4641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Collection<Entry<K, V>> result = entries;
4651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (result == null) {
4661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        entries = result = constrainedEntries(delegate.entries(), constraint);
4671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
4681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return result;
4691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
4701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public Collection<V> get(final K key) {
4721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return Constraints.constrainedTypePreservingCollection(
4731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          delegate.get(key), new Constraint<V>() {
4741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        @Override
4751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        public V checkElement(V value) {
4761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          constraint.checkKeyValue(key, value);
4771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return value;
4781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
4791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      });
4801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
4811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public boolean put(K key, V value) {
4831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      constraint.checkKeyValue(key, value);
4841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return delegate.put(key, value);
4851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
4861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public boolean putAll(K key, Iterable<? extends V> values) {
4881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return delegate.putAll(key, checkValues(key, values, constraint));
4891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
4901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public boolean putAll(
4921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        Multimap<? extends K, ? extends V> multimap) {
4931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      boolean changed = false;
4941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      for (Entry<? extends K, ? extends V> entry : multimap.entries()) {
4951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        changed |= put(entry.getKey(), entry.getValue());
4961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
4971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return changed;
4981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
4991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public Collection<V> replaceValues(
5011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        K key, Iterable<? extends V> values) {
5021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return delegate.replaceValues(key, checkValues(key, values, constraint));
5031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
5041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
5051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /** @see ConstrainedMultimap#asMap */
5071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static class ConstrainedAsMapValues<K, V>
5081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      extends ForwardingCollection<Collection<V>> {
5091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final Collection<Collection<V>> delegate;
5101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final Set<Entry<K, Collection<V>>> entrySet;
5111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
5131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * @param entrySet map entries, linking each key with its corresponding
5141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     *     values, that already enforce the constraint
5151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
5161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ConstrainedAsMapValues(Collection<Collection<V>> delegate,
5171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        Set<Entry<K, Collection<V>>> entrySet) {
5181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.delegate = delegate;
5191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.entrySet = entrySet;
5201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
5211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override protected Collection<Collection<V>> delegate() {
5221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return delegate;
5231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
5241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public Iterator<Collection<V>> iterator() {
5261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      final Iterator<Entry<K, Collection<V>>> iterator = entrySet.iterator();
5271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return new Iterator<Collection<V>>() {
5281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        @Override
5291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        public boolean hasNext() {
5301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return iterator.hasNext();
5311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
5321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        @Override
5331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        public Collection<V> next() {
5341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return iterator.next().getValue();
5351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
5361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        @Override
5371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        public void remove() {
5381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          iterator.remove();
5391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
5401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      };
5411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
5421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public Object[] toArray() {
5441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return standardToArray();
5451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
5461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public <T> T[] toArray(T[] array) {
5471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return standardToArray(array);
5481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
5491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public boolean contains(Object o) {
5501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return standardContains(o);
5511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
5521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public boolean containsAll(Collection<?> c) {
5531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return standardContainsAll(c);
5541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
5551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public boolean remove(Object o) {
5561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return standardRemove(o);
5571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
5581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public boolean removeAll(Collection<?> c) {
5591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return standardRemoveAll(c);
5601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
5611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public boolean retainAll(Collection<?> c) {
5621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return standardRetainAll(c);
5631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
5641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
5651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /** @see MapConstraints#constrainedEntries */
5671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static class ConstrainedEntries<K, V>
5681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      extends ForwardingCollection<Entry<K, V>> {
5691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final MapConstraint<? super K, ? super V> constraint;
5701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final Collection<Entry<K, V>> entries;
5711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ConstrainedEntries(Collection<Entry<K, V>> entries,
5731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        MapConstraint<? super K, ? super V> constraint) {
5741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.entries = entries;
5751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.constraint = constraint;
5761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
5771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override protected Collection<Entry<K, V>> delegate() {
5781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return entries;
5791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
5801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public Iterator<Entry<K, V>> iterator() {
5821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      final Iterator<Entry<K, V>> iterator = entries.iterator();
5831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return new ForwardingIterator<Entry<K, V>>() {
5841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        @Override public Entry<K, V> next() {
5851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return constrainedEntry(iterator.next(), constraint);
5861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
5871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        @Override protected Iterator<Entry<K, V>> delegate() {
5881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return iterator;
5891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
5901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      };
5911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
5921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // See Collections.CheckedMap.CheckedEntrySet for details on attacks.
5941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public Object[] toArray() {
5961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return standardToArray();
5971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
5981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public <T> T[] toArray(T[] array) {
5991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return standardToArray(array);
6001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
6011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public boolean contains(Object o) {
6021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return Maps.containsEntryImpl(delegate(), o);
6031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
6041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public boolean containsAll(Collection<?> c) {
6051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return standardContainsAll(c);
6061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
6071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public boolean remove(Object o) {
6081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return Maps.removeEntryImpl(delegate(), o);
6091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
6101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public boolean removeAll(Collection<?> c) {
6111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return standardRemoveAll(c);
6121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
6131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public boolean retainAll(Collection<?> c) {
6141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return standardRetainAll(c);
6151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
6161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
6171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /** @see MapConstraints#constrainedEntrySet */
6191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static class ConstrainedEntrySet<K, V>
6201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      extends ConstrainedEntries<K, V> implements Set<Entry<K, V>> {
6211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ConstrainedEntrySet(Set<Entry<K, V>> entries,
6221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        MapConstraint<? super K, ? super V> constraint) {
6231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      super(entries, constraint);
6241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
6251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // See Collections.CheckedMap.CheckedEntrySet for details on attacks.
6271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public boolean equals(@Nullable Object object) {
6291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return Sets.equalsImpl(this, object);
6301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
6311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public int hashCode() {
6331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return Sets.hashCodeImpl(this);
6341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
6351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
6361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /** @see MapConstraints#constrainedAsMapEntries */
6381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static class ConstrainedAsMapEntries<K, V>
6391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      extends ForwardingSet<Entry<K, Collection<V>>> {
6401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private final MapConstraint<? super K, ? super V> constraint;
6411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private final Set<Entry<K, Collection<V>>> entries;
6421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ConstrainedAsMapEntries(Set<Entry<K, Collection<V>>> entries,
6441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        MapConstraint<? super K, ? super V> constraint) {
6451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.entries = entries;
6461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.constraint = constraint;
6471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
6481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override protected Set<Entry<K, Collection<V>>> delegate() {
6501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return entries;
6511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
6521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public Iterator<Entry<K, Collection<V>>> iterator() {
6541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      final Iterator<Entry<K, Collection<V>>> iterator = entries.iterator();
6551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return new ForwardingIterator<Entry<K, Collection<V>>>() {
6561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        @Override public Entry<K, Collection<V>> next() {
6571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return constrainedAsMapEntry(iterator.next(), constraint);
6581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
6591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        @Override protected Iterator<Entry<K, Collection<V>>> delegate() {
6601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return iterator;
6611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
6621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      };
6631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
6641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // See Collections.CheckedMap.CheckedEntrySet for details on attacks.
6661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public Object[] toArray() {
6681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return standardToArray();
6691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
6701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public <T> T[] toArray(T[] array) {
6721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return standardToArray(array);
6731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
6741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public boolean contains(Object o) {
6761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return Maps.containsEntryImpl(delegate(), o);
6771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
6781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public boolean containsAll(Collection<?> c) {
6801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return standardContainsAll(c);
6811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
6821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public boolean equals(@Nullable Object object) {
6841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return standardEquals(object);
6851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
6861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public int hashCode() {
6881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return standardHashCode();
6891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
6901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public boolean remove(Object o) {
6921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return Maps.removeEntryImpl(delegate(), o);
6931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
6941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public boolean removeAll(Collection<?> c) {
6961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return standardRemoveAll(c);
6971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
6981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public boolean retainAll(Collection<?> c) {
7001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return standardRetainAll(c);
7011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
7021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
7031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static class ConstrainedListMultimap<K, V>
7051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      extends ConstrainedMultimap<K, V> implements ListMultimap<K, V> {
7061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ConstrainedListMultimap(ListMultimap<K, V> delegate,
7071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        MapConstraint<? super K, ? super V> constraint) {
7081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      super(delegate, constraint);
7091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
7101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public List<V> get(K key) {
7111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return (List<V>) super.get(key);
7121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
7131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public List<V> removeAll(Object key) {
7141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return (List<V>) super.removeAll(key);
7151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
7161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public List<V> replaceValues(
7171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        K key, Iterable<? extends V> values) {
7181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return (List<V>) super.replaceValues(key, values);
7191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
7201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
7211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static class ConstrainedSetMultimap<K, V>
7231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      extends ConstrainedMultimap<K, V> implements SetMultimap<K, V> {
7241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ConstrainedSetMultimap(SetMultimap<K, V> delegate,
7251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        MapConstraint<? super K, ? super V> constraint) {
7261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      super(delegate, constraint);
7271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
7281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public Set<V> get(K key) {
7291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return (Set<V>) super.get(key);
7301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
7311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public Set<Map.Entry<K, V>> entries() {
7321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return (Set<Map.Entry<K, V>>) super.entries();
7331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
7341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public Set<V> removeAll(Object key) {
7351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return (Set<V>) super.removeAll(key);
7361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
7371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public Set<V> replaceValues(
7381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        K key, Iterable<? extends V> values) {
7391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return (Set<V>) super.replaceValues(key, values);
7401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
7411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
7421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static class ConstrainedSortedSetMultimap<K, V>
7441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      extends ConstrainedSetMultimap<K, V> implements SortedSetMultimap<K, V> {
7451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ConstrainedSortedSetMultimap(SortedSetMultimap<K, V> delegate,
7461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        MapConstraint<? super K, ? super V> constraint) {
7471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      super(delegate, constraint);
7481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
7491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public SortedSet<V> get(K key) {
7501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return (SortedSet<V>) super.get(key);
7511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
7521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public SortedSet<V> removeAll(Object key) {
7531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return (SortedSet<V>) super.removeAll(key);
7541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
7551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public SortedSet<V> replaceValues(
7561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        K key, Iterable<? extends V> values) {
7571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return (SortedSet<V>) super.replaceValues(key, values);
7581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
7591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
7601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public Comparator<? super V> valueComparator() {
7611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return ((SortedSetMultimap<K, V>) delegate()).valueComparator();
7621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
7631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
7641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static <K, V> Collection<V> checkValues(K key,
7661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Iterable<? extends V> values,
7671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      MapConstraint<? super K, ? super V> constraint) {
7681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Collection<V> copy = Lists.newArrayList(values);
7691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (V value : copy) {
7701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      constraint.checkKeyValue(key, value);
7711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
7721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return copy;
7731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
7741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static <K, V> Map<K, V> checkMap(Map<? extends K, ? extends V> map,
7761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      MapConstraint<? super K, ? super V> constraint) {
7771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Map<K, V> copy = new LinkedHashMap<K, V>(map);
7781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (Entry<K, V> entry : copy.entrySet()) {
7791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      constraint.checkKeyValue(entry.getKey(), entry.getValue());
7801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
7811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return copy;
7821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
7831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
784