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     */
017    package org.apache.commons.collections.keyvalue;
018    
019    import java.util.Map;
020    
021    import org.apache.commons.collections.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 Commons Collections 3.0
031     * @version $Revision: 646777 $ $Date: 2008-04-10 13:33:15 +0100 (Thu, 10 Apr 2008) $
032     * 
033     * @author James Strachan
034     * @author Michael A. Smith
035     * @author Neil O'Toole
036     * @author Stephen Colebourne
037     */
038    public class DefaultKeyValue extends AbstractKeyValue {
039    
040        /**
041         * Constructs a new pair with a null key and null value.
042         */
043        public DefaultKeyValue() {
044            super(null, null);
045        }
046    
047        /**
048         * Constructs a new pair with the specified key and given value.
049         *
050         * @param key  the key for the entry, may be null
051         * @param value  the value for the entry, may be null
052         */
053        public DefaultKeyValue(final Object key, final Object value) {
054            super(key, value);
055        }
056    
057        /**
058         * Constructs a new pair from the specified <code>KeyValue</code>.
059         *
060         * @param pair  the pair to copy, must not be null
061         * @throws NullPointerException if the entry is null
062         */
063        public DefaultKeyValue(final KeyValue pair) {
064            super(pair.getKey(), pair.getValue());
065        }
066    
067        /**
068         * Constructs a new pair from the specified <code>Map.Entry</code>.
069         *
070         * @param entry  the entry to copy, must not be null
071         * @throws NullPointerException if the entry is null
072         */
073        public DefaultKeyValue(final Map.Entry entry) {
074            super(entry.getKey(), entry.getValue());
075        }
076    
077        //-----------------------------------------------------------------------
078        /**
079         * Sets the key.
080         *
081         * @param key  the new key
082         * @return the old key
083         * @throws IllegalArgumentException if key is this object
084         */
085        public Object setKey(final Object key) {
086            if (key == this) {
087                throw new IllegalArgumentException("DefaultKeyValue may not contain itself as a key.");
088            }
089    
090            final Object old = this.key;
091            this.key = key;
092            return old;
093        }
094    
095        /** 
096         * Sets the value.
097         *
098         * @return the old value of the value
099         * @param value the new value
100         * @throws IllegalArgumentException if value is this object
101         */
102        public Object setValue(final Object value) {
103            if (value == this) {
104                throw new IllegalArgumentException("DefaultKeyValue may not contain itself as a value.");
105            }
106    
107            final Object old = this.value;
108            this.value = value;
109            return old;
110        }
111    
112        //-----------------------------------------------------------------------
113        /**
114         * Returns a new <code>Map.Entry</code> object with key and value from this pair.
115         * 
116         * @return a MapEntry instance
117         */
118        public Map.Entry toMapEntry() {
119            return new DefaultMapEntry(this);
120        }
121    
122        //-----------------------------------------------------------------------
123        /**
124         * Compares this <code>Map.Entry</code> with another <code>Map.Entry</code>.
125         * <p>
126         * Returns true if the compared object is also a <code>DefaultKeyValue</code>,
127         * and its key and value are equal to this object's key and value.
128         * 
129         * @param obj  the object to compare to
130         * @return true if equal key and value
131         */
132        public boolean equals(final Object obj) {
133            if (obj == this) {
134                return true;
135            }
136            if (obj instanceof DefaultKeyValue == false) {
137                return false;
138            }
139    
140            DefaultKeyValue other = (DefaultKeyValue) obj;
141            return 
142                (getKey() == null ? other.getKey() == null : getKey().equals(other.getKey())) &&
143                (getValue() == null ? other.getValue() == null : getValue().equals(other.getValue()));
144        }
145    
146        /**
147         * Gets a hashCode compatible with the equals method.
148         * <p>
149         * Implemented per API documentation of {@link java.util.Map.Entry#hashCode()},
150         * however subclasses may override this.
151         * 
152         * @return a suitable hash code
153         */
154        public int hashCode() {
155            return (getKey() == null ? 0 : getKey().hashCode()) ^
156                   (getValue() == null ? 0 : getValue().hashCode());
157        }
158    
159    }