package finiteAutomata;

import java.util.Map;
/**
 * A key-value pair such that the key cannot be 
 * modified.  Associations are used by the Hashtable class.  
 * 
 * Adapted from code in "Java Structures: Data Structures in Java 
 * for the Principled Programmer", 2nd edition, Duane A. Bailey, 
 * 2003 (McGraw-Hill Publishers), p.14.
 * 
 * @author Barbara Wahl
 * @version Fall 2007
*/
public class Association implements Map.Entry
{
	// ** DATA FIELDS **
	/**
	 * the key
	 */
	protected Object theKey;
	
	/**
	 * the value
	 */
	protected Object theValue;
	
	/**
	 * 2-parameter constructor.
	 * @param key Object to store as the key
	 * @param value Object to store as the value
	 * @pre key is not null
	 * @post creates an Association with the given key and value
	 */
	public Association(Object key, Object value)
	{
		Assert.pre(key != null, "key is not null");
		theKey = key;
		theValue = value;
	}
	
	/**
	 * 1-parameter constructor.
	 * @param key Object to store as the key
	 * @pre key is not null
	 * @post creates an Association with the given key and a null value
	 */
	public Association(Object key)
	{
		this(key,null);
	}
	
	/**
	 * Returns the key.
	 * @return Object theKey
	 */
	public Object getKey()
	{
		return theKey;
	}
	
	/**
	 * Returns the value.
	 * @return Object theValue (may be null)
	 */
	public Object getValue()
	{
		return theValue;
	}
	
	/**
	 * Converts this Association to a String for pretty-printing.
	 * @return String representation of this Association as an ordered pair
	 * (inserts "null" in place of theValue.toString() if the value is null)
	 */
	public String toString()
	{
		if(theValue!=null)
			return "(" + theKey.toString() + "," + 
				theValue.toString() + ")";
		else
			return "(" + theKey.toString() + ",null)";
	}
	
	/**
	 * Sets the value of this Association to the given Object.
	 * @param value Object to store as the new value
	 * @return (Object) the old value of this Association
	 */
	public Object setValue(Object value)
	{
		Object oldValue = theValue;
		theValue = value;
		return oldValue;
	}
	
	/**
	 * Tests whether this Association and the given Association have
	 * equal keys.
	 * @param other Association to compare with this 
	 * @return true iff the two keys are equal, according to the 
	 * appropriate equals method
	 * @pre other is a non-null Association
	 */
	public boolean equals(Object other)
	{
		Assert.pre(other != null, "other is not null");
		Object otherKey = ((Association)other).getKey();
		return this.theKey.equals(otherKey);
	}
	
	// ** TEST METHOD **
	public static void main(String[] args)
	{
		// create an array of 5 Associations
		Association[] pair = new Association[5];
		pair[0] = new Association("zero",new Integer(0));
		pair[1] = new Association("one",new Integer(1));
		pair[2] = new Association("two",new Integer(2));
		pair[3] = new Association("two",new Integer(12));
		pair[4] = new Association("noValue"); // value is null
		
		// test the methods toString and equals
		for(int i=0; i<5; i++)
			System.out.println("pair["+i+"] = " + pair[i]);
		System.out.println("pair[0] == pair[1] is " + 
				pair[0].equals(pair[1]));
		System.out.println("pair[2] == pair[3] is " + 
				pair[2].equals(pair[3]));
	}
}