/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.artima.lookup.util; import java.util.Map; import java.util.Set; import java.util.AbstractMap; import java.io.Serializable; /** * An implementation of the <code>java.util.Map.Entry</code> interface that has * a serialized form consistent in all virtual machines. <code>ConsistentMapEntry</code> * instances are unmodifiable. The <code>setValue</code> mutator method * throws <code>UnsupportedOperationException</code>. This class permits <code>null</code> * for values and keys. * * <p> * Although instances of this class are unmodifiable, they are not necessarily * immutable. If a client retrieves a mutable object (either a key or value) contained in a * <code>ConsistentMapEntry</code> and mutates that object, the client in effect * mutates the state of the <code>ConsistentMapEntry</code>. In this case, the * serialized form of the <code>ConsistentMapEntry</code> will most likely also * have been mutated. A <code>ConsistentMapEntry</code> that contains only immutable * objects will maintain a consistent serialized form indefinitely. But a * <code>ConsistentMapEntry</code> that contains mutable objects will maintain a * consistent serialized form only so long as the mutable objects are not * mutated. * * @author Bill Venners */ final class ConsistentMapEntry implements Map.Entry, Serializable { private static final long serialVersionUID = -8633627011729114409L; /** * @serial An <code>Object</code> key, or <code>null</code> */ private Object key; /** * @serial An <code>Object</code> value, or <code>null</code> */ private Object value; /** * Constructs a new <code>ConsistentMapEntry</code> with passed * <code>key</code> and <code>value</code>. <code>null</code> is * allowed in either (or both) parameters. * * @param key the key (<code>null</code> key is OK) * @param value the value (<code>null</code> value is OK) associated with the key */ public ConsistentMapEntry(Object key, Object value) { this.key = key; this.value = value; } /** * Returns the key. * * @return the key. */ public Object getKey() { return key; } /** * Returns the value. * * @return the value. */ public Object getValue() { return value; } /** * Replaces the value corresponding to this entry with the specified value. Because * all instances of this class are unmodifiable, this method always throws * <code>UnsupportedOperationException</code>. * * @throw UnsupportedOperationException always */ public Object setValue(Object value) { throw new UnsupportedOperationException(); } /** * Compares the specified object (the <CODE>Object</CODE> passed * in <CODE>o</CODE>) with this <CODE>ConsistentMapEntry</CODE> * object for equality. Returns true if the specified object * is not <code>null</code>, if the specified object's class is * <CODE>ConsistentMapEntry</CODE>, if the keys of this object and * the specified object are either both <code>null</code> or semantically * equal, and the values of this object and the specified object are either * both <code>null</code> or semantically equal. * * @param o the object to compare against * @return <code>true</code> if the objects are the semantically equal, * <code>false</code> otherwise. */ public boolean equals(Object o) { if (o == null) { return false; } if (o == this) { return true; } // TODO: ASK JOSH SHOULD EQUALS CHECK FOR INSTANCEOF OR EXACT CLASS? if (o.getClass() != ConsistentMapEntry.class) { return false; } ConsistentMapEntry unmod = (ConsistentMapEntry) o; boolean keysEqual = equalsOrNull(key, unmod.key); boolean valsEqual = equalsOrNull(value, unmod.value); return keysEqual && valsEqual; } private static boolean equalsOrNull(Object o1, Object o2) { return (o1 == null ? o2 == null : o1.equals(o2)); } /** * Returns the hash code value for this <CODE>ConsistentMapEntry</CODE> object. * * @return the hashcode for this object */ public int hashCode() { int keyHash = (key == null ? 0 : key.hashCode()); int valueHash = (value == null ? 0 : value.hashCode()); return keyHash ^ valueHash; } }