    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one or more
    003 * contributor license agreements.  See the NOTICE file distributed with
    004 * this work for additional information regarding copyright ownership.
    005 * The ASF licenses this file to You under the Apache License, Version 2.0
    006 * (the "License"); you may not use this file except in compliance with
    007 * the License.  You may obtain a copy of the License at
    008 *
    009 *      http://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 * Unless required by applicable law or agreed to in writing, software
    012 * distributed under the License is distributed on an "AS IS" BASIS,
    013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 * See the License for the specific language governing permissions and
    015 * limitations under the License.
    016 */
    017package org.apache.commons.collections4.keyvalue;
    018
    019import java.util.Map;
    020import java.util.Objects;
    021
    022import org.apache.commons.collections4.KeyValue;
    023
    024/**
    025 * A mutable {@code KeyValue} pair that does not implement
    026 * {@link java.util.Map.Entry Map.Entry}.
    027 * <p>
    028 * Note that a {@code DefaultKeyValue} instance may not contain
    029 * itself as a key or value.
    030 * </p>
    031 *
    032 * @param <K> the type of keys
    033 * @param <V> the type of values
    034 * @since 3.0
    035 */
    036public class DefaultKeyValue<K, V> extends AbstractKeyValue<K, V> {
    037
    038    /**
    039     * Constructs a new pair with a null key and null value.
    040     */
    041    public DefaultKeyValue() {
    042        super(null, null);
    043    }
    044
    045    /**
    046     * Constructs a new pair with the specified key and given value.
    047     *
    048     * @param key  the key for the entry, may be null
    049     * @param value  the value for the entry, may be null
    050     */
    051    public DefaultKeyValue(final K key, final V value) {
    052        super(key, value);
    053    }
    054
    055    /**
    056     * Constructs a new pair from the specified {@code KeyValue}.
    057     *
    058     * @param pair  the pair to copy, must not be null
    059     * @throws NullPointerException if the entry is null
    060     */
    061    public DefaultKeyValue(final KeyValue<? extends K, ? extends V> pair) {
    062        super(pair.getKey(), pair.getValue());
    063    }
    064
    065    /**
    066     * Constructs a new pair from the specified {@code Map.Entry}.
    067     *
    068     * @param entry  the entry to copy, must not be null
    069     * @throws NullPointerException if the entry is null
    070     */
    071    public DefaultKeyValue(final Map.Entry<? extends K, ? extends V> entry) {
    072        super(entry.getKey(), entry.getValue());
    073    }
    074
    075    /**
    076     * Compares this {@code Map.Entry} with another {@code Map.Entry}.
    077     * <p>
    078     * Returns true if the compared object is also a {@code DefaultKeyValue},
    079     * and its key and value are equal to this object's key and value.
    080     *
    081     * @param obj  the object to compare to
    082     * @return true if equal key and value
    083     */
    084    @Override
    085    public boolean equals(final Object obj) {
    086        if (obj == this) {
    087            return true;
    088        }
    089        if (!(obj instanceof DefaultKeyValue)) {
    090            return false;
    091        }
    092
    093        final DefaultKeyValue<?, ?> other = (DefaultKeyValue<?, ?>) obj;
    094        return
    095            Objects.equals(getKey(), other.getKey()) &&
    096            Objects.equals(getValue(), other.getValue());
    097    }
    098
    099    /**
    100     * Gets a hashCode compatible with the equals method.
    101     * <p>
    102     * Implemented per API documentation of {@link java.util.Map.Entry#hashCode()},
    103     * however subclasses may override this.
    104     *
    105     * @return a suitable hash code
    106     */
    107    @Override
    108    public int hashCode() {
    109        return (getKey() == null ? 0 : getKey().hashCode()) ^
    110               (getValue() == null ? 0 : getValue().hashCode());
    111    }
    112
    113    /**
    114     * Sets the key.
    115     *
    116     * @param key  the new key
    117     * @return the old key
    118     * @throws IllegalArgumentException if key is this object
    119     */
    120    @Override
    121    public K setKey(final K key) {
    122        if (key == this) {
    123            throw new IllegalArgumentException("DefaultKeyValue may not contain itself as a key.");
    124        }
    125
    126        return super.setKey(key);
    127    }
    128
    129    /**
    130     * Sets the value.
    131     *
    132     * @return the old value of the value
    133     * @param value the new value
    134     * @throws IllegalArgumentException if value is this object
    135     */
    136    @Override
    137    public V setValue(final V value) {
    138        if (value == this) {
    139            throw new IllegalArgumentException("DefaultKeyValue may not contain itself as a value.");
    140        }
    141
    142        return super.setValue(value);
    143    }
    144
    145    /**
    146     * Returns a new {@code Map.Entry} object with key and value from this pair.
    147     *
    148     * @return a MapEntry instance
    149     */
    150    public Map.Entry<K, V> toMapEntry() {
    151        return new DefaultMapEntry<>(this);
    152    }
    153
    154}