151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/*
22c87ad3a45cecf9e344487cad1abfdebe79f2c7cNarayan Kamath * Copyright (C) 2014 The Android Open Source Project
351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it
751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as
851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation.  Oracle designates this
951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided
1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code.
1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT
1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that
1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code).
1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version
1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation,
2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any
2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions.
2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipackage java.util;
2851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Map.Entry;
3051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
3151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/**
3251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * A specialized {@link Map} implementation for use with enum type keys.  All
3351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * of the keys in an enum map must come from a single enum type that is
3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * specified, explicitly or implicitly, when the map is created.  Enum maps
3551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * are represented internally as arrays.  This representation is extremely
3651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * compact and efficient.
3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
3851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>Enum maps are maintained in the <i>natural order</i> of their keys
3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * (the order in which the enum constants are declared).  This is reflected
4051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * in the iterators returned by the collections views ({@link #keySet()},
4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * {@link #entrySet()}, and {@link #values()}).
4251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
4351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>Iterators returned by the collection views are <i>weakly consistent</i>:
4451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * they will never throw {@link ConcurrentModificationException} and they may
4551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or may not show the effects of any modifications to the map that occur while
4651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the iteration is in progress.
4751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>Null keys are not permitted.  Attempts to insert a null key will
4951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * throw {@link NullPointerException}.  Attempts to test for the
5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * presence of a null key or to remove one will, however, function properly.
5151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Null values are permitted.
5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
5351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <P>Like most collection implementations <tt>EnumMap</tt> is not
5451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * synchronized. If multiple threads access an enum map concurrently, and at
5551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * least one of the threads modifies the map, it should be synchronized
5651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * externally.  This is typically accomplished by synchronizing on some
5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * object that naturally encapsulates the enum map.  If no such object exists,
5851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the map should be "wrapped" using the {@link Collections#synchronizedMap}
5951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * method.  This is best done at creation time, to prevent accidental
6051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * unsynchronized access:
6151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
6251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <pre>
6351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     Map&lt;EnumKey, V&gt; m
6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         = Collections.synchronizedMap(new EnumMap&lt;EnumKey, V&gt;(...));
6551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </pre>
6651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>Implementation note: All basic operations execute in constant time.
6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * They are likely (though not guaranteed) to be faster than their
6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * {@link HashMap} counterparts.
7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>This class is a member of the
72d2449bb576ad1e3a3877364e5e1ae28625f69e35Yi Kong * <a href="{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/collections/index.html">
7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Java Collections Framework</a>.
7451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
7551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @author Josh Bloch
7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see EnumSet
7751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since 1.5
7851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
7951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipublic class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V>
8051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    implements java.io.Serializable, Cloneable
8151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski{
8251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
8351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The <tt>Class</tt> object for the enum type of all the keys of this map.
8451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
8551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @serial
8651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
8751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private final Class<K> keyType;
8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
8951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
9051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * All of the values comprising K.  (Cached for performance.)
9151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
9251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private transient K[] keyUniverse;
9351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
9451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
9551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Array representation of this map.  The ith element is the value
9651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * to which universe[i] is currently mapped, or null if it isn't
9751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * mapped to anything, or NULL if it's mapped to null.
9851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
9951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private transient Object[] vals;
10051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The number of mappings in this map.
10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
10451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private transient int size = 0;
10551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
10651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Distinguished non-null value for representing null values.
10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
10951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static final Object NULL = new Object() {
11051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public int hashCode() {
11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return 0;
11251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
11351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
11451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public String toString() {
11551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return "java.util.EnumMap.NULL";
11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    };
11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private Object maskNull(Object value) {
12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return (value == null ? NULL : value);
12151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private V unmaskNull(Object value) {
12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return (V) (value == NULL ? null : value);
12551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
12651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static final Enum[] ZERO_LENGTH_ENUM_ARRAY = new Enum[0];
12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
12951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
13051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Creates an empty enum map with the specified key type.
13151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
13251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param keyType the class object of the key type for this enum map
13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws NullPointerException if <tt>keyType</tt> is null
13451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
13551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public EnumMap(Class<K> keyType) {
13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this.keyType = keyType;
13751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        keyUniverse = getKeyUniverse(keyType);
13851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        vals = new Object[keyUniverse.length];
13951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
14251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Creates an enum map with the same key type as the specified enum
14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * map, initially containing the same mappings (if any).
14451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
14551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param m the enum map from which to initialize this enum map
14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws NullPointerException if <tt>m</tt> is null
14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public EnumMap(EnumMap<K, ? extends V> m) {
14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        keyType = m.keyType;
15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        keyUniverse = m.keyUniverse;
15151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        vals = m.vals.clone();
15251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        size = m.size;
15351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
15651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Creates an enum map initialized from the specified map.  If the
15751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * specified map is an <tt>EnumMap</tt> instance, this constructor behaves
15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * identically to {@link #EnumMap(EnumMap)}.  Otherwise, the specified map
15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * must contain at least one mapping (in order to determine the new
16051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * enum map's key type).
16151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param m the map from which to initialize this enum map
16351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws IllegalArgumentException if <tt>m</tt> is not an
16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     <tt>EnumMap</tt> instance and contains no mappings
16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws NullPointerException if <tt>m</tt> is null
16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public EnumMap(Map<K, ? extends V> m) {
16851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (m instanceof EnumMap) {
16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            EnumMap<K, ? extends V> em = (EnumMap<K, ? extends V>) m;
17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            keyType = em.keyType;
17151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            keyUniverse = em.keyUniverse;
17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            vals = em.vals.clone();
17351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            size = em.size;
17451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else {
17551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (m.isEmpty())
17651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new IllegalArgumentException("Specified map is empty");
17751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            keyType = m.keySet().iterator().next().getDeclaringClass();
17851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            keyUniverse = getKeyUniverse(keyType);
17951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            vals = new Object[keyUniverse.length];
18051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            putAll(m);
18151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
18251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
18351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
18451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // Query Operations
18551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
18651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
18751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns the number of key-value mappings in this map.
18851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
18951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return the number of key-value mappings in this map
19051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
19151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public int size() {
19251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return size;
19351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
19451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
19551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
19651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns <tt>true</tt> if this map maps one or more keys to the
19751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * specified value.
19851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
19951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param value the value whose presence in this map is to be tested
20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return <tt>true</tt> if this map maps one or more keys to this value
20151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
20251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public boolean containsValue(Object value) {
20351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        value = maskNull(value);
20451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
20551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        for (Object val : vals)
20651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (value.equals(val))
20751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return true;
20851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
20951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return false;
21051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
21151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
21251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
21351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns <tt>true</tt> if this map contains a mapping for the specified
21451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * key.
21551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
21651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param key the key whose presence in this map is to be tested
21751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return <tt>true</tt> if this map contains a mapping for the specified
21851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *            key
21951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
22051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public boolean containsKey(Object key) {
22151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return isValidKey(key) && vals[((Enum)key).ordinal()] != null;
22251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
22351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
22451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private boolean containsMapping(Object key, Object value) {
22551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return isValidKey(key) &&
22651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            maskNull(value).equals(vals[((Enum)key).ordinal()]);
22751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
22851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
22951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
23051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns the value to which the specified key is mapped,
23151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * or {@code null} if this map contains no mapping for the key.
23251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
23351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>More formally, if this map contains a mapping from a key
23451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * {@code k} to a value {@code v} such that {@code (key == k)},
23551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * then this method returns {@code v}; otherwise it returns
23651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * {@code null}.  (There can be at most one such mapping.)
23751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
23851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>A return value of {@code null} does not <i>necessarily</i>
23951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * indicate that the map contains no mapping for the key; it's also
24051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * possible that the map explicitly maps the key to {@code null}.
24151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The {@link #containsKey containsKey} operation may be used to
24251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * distinguish these two cases.
24351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
24451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public V get(Object key) {
24551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return (isValidKey(key) ?
24651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                unmaskNull(vals[((Enum)key).ordinal()]) : null);
24751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
24851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
24951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // Modification Operations
25051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
25151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
25251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Associates the specified value with the specified key in this map.
25351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * If the map previously contained a mapping for this key, the old
25451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * value is replaced.
25551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
25651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param key the key with which the specified value is to be associated
25751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param value the value to be associated with the specified key
25851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
25951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return the previous value associated with specified key, or
26051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     <tt>null</tt> if there was no mapping for key.  (A <tt>null</tt>
26151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     return can also indicate that the map previously associated
26251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     <tt>null</tt> with the specified key.)
26351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws NullPointerException if the specified key is null
26451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
26551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public V put(K key, V value) {
26651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        typeCheck(key);
26751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
26851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int index = key.ordinal();
26951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Object oldValue = vals[index];
27051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        vals[index] = maskNull(value);
27151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (oldValue == null)
27251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            size++;
27351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return unmaskNull(oldValue);
27451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
27551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
27651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
27751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Removes the mapping for this key from this map if present.
27851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
27951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param key the key whose mapping is to be removed from the map
28051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return the previous value associated with specified key, or
28151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     <tt>null</tt> if there was no entry for key.  (A <tt>null</tt>
28251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     return can also indicate that the map previously associated
28351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     <tt>null</tt> with the specified key.)
28451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
28551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public V remove(Object key) {
28651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (!isValidKey(key))
28751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
28851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int index = ((Enum)key).ordinal();
28951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Object oldValue = vals[index];
29051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        vals[index] = null;
29151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (oldValue != null)
29251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            size--;
29351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return unmaskNull(oldValue);
29451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
29551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
29651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private boolean removeMapping(Object key, Object value) {
29751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (!isValidKey(key))
29851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return false;
29951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int index = ((Enum)key).ordinal();
30051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (maskNull(value).equals(vals[index])) {
30151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            vals[index] = null;
30251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            size--;
30351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return true;
30451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
30551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return false;
30651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
30751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
30851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
30951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns true if key is of the proper type to be a key in this
31051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * enum map.
31151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
31251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private boolean isValidKey(Object key) {
31351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (key == null)
31451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return false;
31551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
31651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Cheaper than instanceof Enum followed by getDeclaringClass
31751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Class keyClass = key.getClass();
31851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return keyClass == keyType || keyClass.getSuperclass() == keyType;
31951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
32051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
32151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // Bulk Operations
32251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
32351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
32451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Copies all of the mappings from the specified map to this map.
32551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * These mappings will replace any mappings that this map had for
32651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * any of the keys currently in the specified map.
32751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
32851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param m the mappings to be stored in this map
32951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws NullPointerException the specified map is null, or if
33051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     one or more keys in the specified map are null
33151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
33251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void putAll(Map<? extends K, ? extends V> m) {
33351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (m instanceof EnumMap) {
33451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            EnumMap<? extends K, ? extends V> em =
33551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                (EnumMap<? extends K, ? extends V>)m;
33651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (em.keyType != keyType) {
33751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (em.isEmpty())
33851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return;
33951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new ClassCastException(em.keyType + " != " + keyType);
34051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
34151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
34251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            for (int i = 0; i < keyUniverse.length; i++) {
34351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                Object emValue = em.vals[i];
34451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (emValue != null) {
34551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (vals[i] == null)
34651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        size++;
34751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    vals[i] = emValue;
34851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
34951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
35051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else {
35151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            super.putAll(m);
35251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
35351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
35451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
35551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
35651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Removes all mappings from this map.
35751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
35851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void clear() {
35951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Arrays.fill(vals, null);
36051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        size = 0;
36151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
36251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
36351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // Views
36451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
36551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
36651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This field is initialized to contain an instance of the entry set
36751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * view the first time this view is requested.  The view is stateless,
36851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * so there's no reason to create more than one.
36951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
37051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private transient Set<Map.Entry<K,V>> entrySet = null;
37151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
37251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
37351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns a {@link Set} view of the keys contained in this map.
37451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The returned set obeys the general contract outlined in
37551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * {@link Map#keySet()}.  The set's iterator will return the keys
37651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * in their natural order (the order in which the enum constants
37751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * are declared).
37851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
37951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return a set view of the keys contained in this enum map
38051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
38151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public Set<K> keySet() {
38251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Set<K> ks = keySet;
38351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (ks != null)
38451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return ks;
38551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        else
38651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return keySet = new KeySet();
38751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
38851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
38951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private class KeySet extends AbstractSet<K> {
39051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public Iterator<K> iterator() {
39151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return new KeyIterator();
39251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
39351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public int size() {
39451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return size;
39551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
39651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public boolean contains(Object o) {
39751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return containsKey(o);
39851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
39951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public boolean remove(Object o) {
40051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int oldSize = size;
40151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            EnumMap.this.remove(o);
40251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return size != oldSize;
40351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
40451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public void clear() {
40551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            EnumMap.this.clear();
40651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
40751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
40851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
40951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
41051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns a {@link Collection} view of the values contained in this map.
41151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The returned collection obeys the general contract outlined in
41251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * {@link Map#values()}.  The collection's iterator will return the
41351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * values in the order their corresponding keys appear in map,
41451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * which is their natural order (the order in which the enum constants
41551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * are declared).
41651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
41751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return a collection view of the values contained in this map
41851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
41951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public Collection<V> values() {
42051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Collection<V> vs = values;
42151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (vs != null)
42251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return vs;
42351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        else
42451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return values = new Values();
42551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
42651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
42751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private class Values extends AbstractCollection<V> {
42851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public Iterator<V> iterator() {
42951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return new ValueIterator();
43051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
43151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public int size() {
43251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return size;
43351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
43451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public boolean contains(Object o) {
43551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return containsValue(o);
43651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
43751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public boolean remove(Object o) {
43851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            o = maskNull(o);
43951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
44051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            for (int i = 0; i < vals.length; i++) {
44151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (o.equals(vals[i])) {
44251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    vals[i] = null;
44351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    size--;
44451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return true;
44551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
44651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
44751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return false;
44851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
44951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public void clear() {
45051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            EnumMap.this.clear();
45151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
45251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
45351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
45451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
45551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns a {@link Set} view of the mappings contained in this map.
45651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The returned set obeys the general contract outlined in
45751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * {@link Map#keySet()}.  The set's iterator will return the
45851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * mappings in the order their keys appear in map, which is their
45951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * natural order (the order in which the enum constants are declared).
46051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
46151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return a set view of the mappings contained in this enum map
46251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
46351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public Set<Map.Entry<K,V>> entrySet() {
46451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Set<Map.Entry<K,V>> es = entrySet;
46551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (es != null)
46651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return es;
46751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        else
46851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return entrySet = new EntrySet();
46951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
47051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
47151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private class EntrySet extends AbstractSet<Map.Entry<K,V>> {
47251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public Iterator<Map.Entry<K,V>> iterator() {
47351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return new EntryIterator();
47451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
47551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
47651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public boolean contains(Object o) {
47751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (!(o instanceof Map.Entry))
47851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return false;
47951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            Map.Entry entry = (Map.Entry)o;
48051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return containsMapping(entry.getKey(), entry.getValue());
48151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
48251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public boolean remove(Object o) {
48351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (!(o instanceof Map.Entry))
48451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return false;
48551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            Map.Entry entry = (Map.Entry)o;
48651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return removeMapping(entry.getKey(), entry.getValue());
48751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
48851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public int size() {
48951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return size;
49051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
49151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public void clear() {
49251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            EnumMap.this.clear();
49351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
49451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public Object[] toArray() {
49551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return fillEntryArray(new Object[size]);
49651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
49751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        @SuppressWarnings("unchecked")
49851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public <T> T[] toArray(T[] a) {
49951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int size = size();
50051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (a.length < size)
50151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                a = (T[])java.lang.reflect.Array
50251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    .newInstance(a.getClass().getComponentType(), size);
50351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (a.length > size)
50451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                a[size] = null;
50551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return (T[]) fillEntryArray(a);
50651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
50751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private Object[] fillEntryArray(Object[] a) {
50851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int j = 0;
50951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            for (int i = 0; i < vals.length; i++)
51051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (vals[i] != null)
51151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    a[j++] = new AbstractMap.SimpleEntry<>(
51251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        keyUniverse[i], unmaskNull(vals[i]));
51351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return a;
51451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
51551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
51651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
51751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private abstract class EnumMapIterator<T> implements Iterator<T> {
51851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Lower bound on index of next element to return
51951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int index = 0;
52051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
52151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Index of last returned element, or -1 if none
52251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int lastReturnedIndex = -1;
52351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
52451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public boolean hasNext() {
52551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            while (index < vals.length && vals[index] == null)
52651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                index++;
52751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return index != vals.length;
52851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
52951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
53051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public void remove() {
53151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            checkLastReturnedIndex();
53251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
53351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (vals[lastReturnedIndex] != null) {
53451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                vals[lastReturnedIndex] = null;
53551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                size--;
53651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
53751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            lastReturnedIndex = -1;
53851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
53951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
54051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private void checkLastReturnedIndex() {
54151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (lastReturnedIndex < 0)
54251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new IllegalStateException();
54351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
54451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
54551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
54651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private class KeyIterator extends EnumMapIterator<K> {
54751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public K next() {
54851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (!hasNext())
54951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new NoSuchElementException();
55051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            lastReturnedIndex = index++;
55151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return keyUniverse[lastReturnedIndex];
55251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
55351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
55451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
55551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private class ValueIterator extends EnumMapIterator<V> {
55651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public V next() {
55751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (!hasNext())
55851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new NoSuchElementException();
55951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            lastReturnedIndex = index++;
56051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return unmaskNull(vals[lastReturnedIndex]);
56151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
56251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
56351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
56451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private class EntryIterator extends EnumMapIterator<Map.Entry<K,V>> {
56551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private Entry lastReturnedEntry = null;
56651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
56751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public Map.Entry<K,V> next() {
56851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (!hasNext())
56951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new NoSuchElementException();
57051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            lastReturnedEntry = new Entry(index++);
57151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return lastReturnedEntry;
57251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
57351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
57451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public void remove() {
57551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            lastReturnedIndex =
57651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                ((null == lastReturnedEntry) ? -1 : lastReturnedEntry.index);
57751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            super.remove();
57851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            lastReturnedEntry.index = lastReturnedIndex;
57951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            lastReturnedEntry = null;
58051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
58151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
58251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private class Entry implements Map.Entry<K,V> {
58351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            private int index;
58451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
58551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            private Entry(int index) {
58651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                this.index = index;
58751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
58851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
58951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            public K getKey() {
59051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                checkIndexForEntryUse();
59151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return keyUniverse[index];
59251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
59351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
59451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            public V getValue() {
59551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                checkIndexForEntryUse();
59651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return unmaskNull(vals[index]);
59751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
59851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
59951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            public V setValue(V value) {
60051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                checkIndexForEntryUse();
60151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                V oldValue = unmaskNull(vals[index]);
60251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                vals[index] = maskNull(value);
60351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return oldValue;
60451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
60551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
60651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            public boolean equals(Object o) {
60751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (index < 0)
60851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return o == this;
60951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
61051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (!(o instanceof Map.Entry))
61151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return false;
61251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
61351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                Map.Entry e = (Map.Entry)o;
61451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                V ourValue = unmaskNull(vals[index]);
61551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                Object hisValue = e.getValue();
61651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return (e.getKey() == keyUniverse[index] &&
61751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        (ourValue == hisValue ||
61851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                         (ourValue != null && ourValue.equals(hisValue))));
61951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
62051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
62151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            public int hashCode() {
62251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (index < 0)
62351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return super.hashCode();
62451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
62551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return entryHashCode(index);
62651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
62751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
62851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            public String toString() {
62951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (index < 0)
63051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return super.toString();
63151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
63251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return keyUniverse[index] + "="
63351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    + unmaskNull(vals[index]);
63451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
63551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
63651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            private void checkIndexForEntryUse() {
63751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (index < 0)
63851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    throw new IllegalStateException("Entry was removed");
63951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
64051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
64151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
64251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
64351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // Comparison and hashing
64451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
64551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
64651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Compares the specified object with this map for equality.  Returns
64751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <tt>true</tt> if the given object is also a map and the two maps
64851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * represent the same mappings, as specified in the {@link
64951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Map#equals(Object)} contract.
65051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
65151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param o the object to be compared for equality with this map
65251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return <tt>true</tt> if the specified object is equal to this map
65351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
65451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public boolean equals(Object o) {
65551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (this == o)
65651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return true;
65751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (o instanceof EnumMap)
65851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return equals((EnumMap)o);
65951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (!(o instanceof Map))
66051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return false;
66151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
66251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Map<K,V> m = (Map<K,V>)o;
66351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (size != m.size())
66451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return false;
66551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
66651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        for (int i = 0; i < keyUniverse.length; i++) {
66751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (null != vals[i]) {
66851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                K key = keyUniverse[i];
66951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                V value = unmaskNull(vals[i]);
67051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (null == value) {
67151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (!((null == m.get(key)) && m.containsKey(key)))
67251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                       return false;
67351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } else {
67451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                   if (!value.equals(m.get(key)))
67551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                      return false;
67651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
67751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
67851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
67951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
68051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return true;
68151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
68251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
68351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private boolean equals(EnumMap em) {
68451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (em.keyType != keyType)
68551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return size == 0 && em.size == 0;
68651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
68751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Key types match, compare each value
68851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        for (int i = 0; i < keyUniverse.length; i++) {
68951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            Object ourValue =    vals[i];
69051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            Object hisValue = em.vals[i];
69151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (hisValue != ourValue &&
69251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                (hisValue == null || !hisValue.equals(ourValue)))
69351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return false;
69451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
69551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return true;
69651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
69751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
69851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
69951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns the hash code value for this map.  The hash code of a map is
70051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * defined to be the sum of the hash codes of each entry in the map.
70151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
70251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public int hashCode() {
70351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int h = 0;
70451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
70551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        for (int i = 0; i < keyUniverse.length; i++) {
70651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (null != vals[i]) {
70751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                h += entryHashCode(i);
70851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
70951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
71051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
71151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return h;
71251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
71351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
71451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private int entryHashCode(int index) {
71551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return (keyUniverse[index].hashCode() ^ vals[index].hashCode());
71651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
71751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
71851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
71951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns a shallow copy of this enum map.  (The values themselves
72051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * are not cloned.
72151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
72251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return a shallow copy of this enum map
72351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
72451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public EnumMap<K, V> clone() {
72551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        EnumMap<K, V> result = null;
72651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
72751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            result = (EnumMap<K, V>) super.clone();
72851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch(CloneNotSupportedException e) {
72951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new AssertionError();
73051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
73151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        result.vals = result.vals.clone();
73251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        result.entrySet = null;
73351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return result;
73451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
73551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
73651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
73751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Throws an exception if e is not of the correct type for this enum set.
73851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
73951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private void typeCheck(K key) {
74051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Class keyClass = key.getClass();
74151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (keyClass != keyType && keyClass.getSuperclass() != keyType)
74251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new ClassCastException(keyClass + " != " + keyType);
74351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
74451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
74551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
74651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns all of the values comprising K.
74751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The result is uncloned, cached, and shared by all callers.
74851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
74951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static <K extends Enum<K>> K[] getKeyUniverse(Class<K> keyType) {
750983b2c6ff9ea6d35adf7ab6398dccf870b7e180aPiotr Jastrzebski        // Android-changed: Use JavaLangAccess directly instead of going through
751983b2c6ff9ea6d35adf7ab6398dccf870b7e180aPiotr Jastrzebski        // SharedSecrets.
752983b2c6ff9ea6d35adf7ab6398dccf870b7e180aPiotr Jastrzebski        return JavaLangAccess.getEnumConstantsShared(keyType);
75351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
75451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
75551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static final long serialVersionUID = 458661240069192865L;
75651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
75751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
75851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Save the state of the <tt>EnumMap</tt> instance to a stream (i.e.,
75951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * serialize it).
76051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
76151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @serialData The <i>size</i> of the enum map (the number of key-value
76251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *             mappings) is emitted (int), followed by the key (Object)
76351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *             and value (Object) for each key-value mapping represented
76451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *             by the enum map.
76551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
76651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private void writeObject(java.io.ObjectOutputStream s)
76751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws java.io.IOException
76851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
76951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Write out the key type and any hidden stuff
77051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        s.defaultWriteObject();
77151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
77251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Write out size (number of Mappings)
77351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        s.writeInt(size);
77451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
77551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Write out keys and values (alternating)
77651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int entriesToBeWritten = size;
77751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        for (int i = 0; entriesToBeWritten > 0; i++) {
77851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (null != vals[i]) {
77951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                s.writeObject(keyUniverse[i]);
78051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                s.writeObject(unmaskNull(vals[i]));
78151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                entriesToBeWritten--;
78251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
78351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
78451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
78551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
78651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
78751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Reconstitute the <tt>EnumMap</tt> instance from a stream (i.e.,
78851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * deserialize it).
78951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
79051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private void readObject(java.io.ObjectInputStream s)
79151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws java.io.IOException, ClassNotFoundException
79251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
79351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Read in the key type and any hidden stuff
79451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        s.defaultReadObject();
79551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
79651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        keyUniverse = getKeyUniverse(keyType);
79751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        vals = new Object[keyUniverse.length];
79851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
79951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Read in size (number of Mappings)
80051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int size = s.readInt();
80151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
80251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Read the keys and values, and put the mappings in the HashMap
80351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        for (int i = 0; i < size; i++) {
80451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            K key = (K) s.readObject();
80551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            V value = (V) s.readObject();
80651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            put(key, value);
80751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
80851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
80951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
810