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;
020
021import org.apache.commons.collections4.KeyValue;
022
023/**
024 * A mutable <code>KeyValue</code> pair that does not implement
025 * {@link java.util.Map.Entry Map.Entry}.
026 * <p>
027 * Note that a <code>DefaultKeyValue</code> instance may not contain
028 * itself as a key or value.
029 *
030 * @since 3.0
031 * @version $Id: DefaultKeyValue.html 972421 2015-11-14 20:00:04Z tn $
032 */
033public class DefaultKeyValue<K, V> extends AbstractKeyValue<K, V> {
034
035    /**
036     * Constructs a new pair with a null key and null value.
037     */
038    public DefaultKeyValue() {
039        super(null, null);
040    }
041
042    /**
043     * Constructs a new pair with the specified key and given value.
044     *
045     * @param key  the key for the entry, may be null
046     * @param value  the value for the entry, may be null
047     */
048    public DefaultKeyValue(final K key, final V value) {
049        super(key, value);
050    }
051
052    /**
053     * Constructs a new pair from the specified <code>KeyValue</code>.
054     *
055     * @param pair  the pair to copy, must not be null
056     * @throws NullPointerException if the entry is null
057     */
058    public DefaultKeyValue(final KeyValue<? extends K, ? extends V> pair) {
059        super(pair.getKey(), pair.getValue());
060    }
061
062    /**
063     * Constructs a new pair from the specified <code>Map.Entry</code>.
064     *
065     * @param entry  the entry to copy, must not be null
066     * @throws NullPointerException if the entry is null
067     */
068    public DefaultKeyValue(final Map.Entry<? extends K, ? extends V> entry) {
069        super(entry.getKey(), entry.getValue());
070    }
071
072    //-----------------------------------------------------------------------
073    /**
074     * Sets the key.
075     *
076     * @param key  the new key
077     * @return the old key
078     * @throws IllegalArgumentException if key is this object
079     */
080    @Override
081    public K setKey(final K key) {
082        if (key == this) {
083            throw new IllegalArgumentException("DefaultKeyValue may not contain itself as a key.");
084        }
085
086        return super.setKey(key);
087    }
088
089    /**
090     * Sets the value.
091     *
092     * @return the old value of the value
093     * @param value the new value
094     * @throws IllegalArgumentException if value is this object
095     */
096    @Override
097    public V setValue(final V value) {
098        if (value == this) {
099            throw new IllegalArgumentException("DefaultKeyValue may not contain itself as a value.");
100        }
101
102        return super.setValue(value);
103    }
104
105    //-----------------------------------------------------------------------
106    /**
107     * Returns a new <code>Map.Entry</code> object with key and value from this pair.
108     *
109     * @return a MapEntry instance
110     */
111    public Map.Entry<K, V> toMapEntry() {
112        return new DefaultMapEntry<K, V>(this);
113    }
114
115    //-----------------------------------------------------------------------
116    /**
117     * Compares this <code>Map.Entry</code> with another <code>Map.Entry</code>.
118     * <p>
119     * Returns true if the compared object is also a <code>DefaultKeyValue</code>,
120     * and its key and value are equal to this object's key and value.
121     *
122     * @param obj  the object to compare to
123     * @return true if equal key and value
124     */
125    @Override
126    public boolean equals(final Object obj) {
127        if (obj == this) {
128            return true;
129        }
130        if (obj instanceof DefaultKeyValue == false) {
131            return false;
132        }
133
134        final DefaultKeyValue<?, ?> other = (DefaultKeyValue<?, ?>) obj;
135        return
136            (getKey() == null ? other.getKey() == null : getKey().equals(other.getKey())) &&
137            (getValue() == null ? other.getValue() == null : getValue().equals(other.getValue()));
138    }
139
140    /**
141     * Gets a hashCode compatible with the equals method.
142     * <p>
143     * Implemented per API documentation of {@link java.util.Map.Entry#hashCode()},
144     * however subclasses may override this.
145     *
146     * @return a suitable hash code
147     */
148    @Override
149    public int hashCode() {
150        return (getKey() == null ? 0 : getKey().hashCode()) ^
151               (getValue() == null ? 0 : getValue().hashCode());
152    }
153
154}