/*
 * Created on Mar 16, 2005
 */
package org.flexdock.util;

import java.util.Hashtable;
import java.util.Map;

/**
 * @author Christopher Butler
 */
public class TypedHashtable extends Hashtable {
	
    /**
     * Constructs a new, empty <code>TypedHashtable</code> with a default initial capacity (11)
     * and load factor of <code>0.75</code>. 
     */
	public TypedHashtable() {
		super();
	}

    /**
     * Constructs a new, empty <code>TypedHashtable</code> with the specified initial capacity
     * and default load factor of <code>0.75</code>.
     *
     * @param     initialCapacity   the initial capacity of the hashtable.
     * @exception IllegalArgumentException if the initial capacity is less
     *              than zero.
     */
	public TypedHashtable(int initialCapacity) {
		super(initialCapacity);
	}

    /**
     * Constructs a new, empty <code>TypedHashtable</code> with the specified initial 
     * capacity and the specified load factor.
     *
     * @param      initialCapacity   the initial capacity of the hashtable.
     * @param      loadFactor        the load factor of the hashtable.
     * @exception  IllegalArgumentException  if the initial capacity is less
     *             than zero, or if the load factor is nonpositive.
     */
	public TypedHashtable(int initialCapacity, float loadFactor) {
		super(initialCapacity, loadFactor);
	}

    /**
     * Constructs a new <code>TypedHashtable</code> with the same mappings as the given 
     * Map.  The hashtable is created with an initial capacity sufficient to
     * hold the mappings in the given Map and a default load factor of <code>0.75</code>.
     *
     * @param t the map whose mappings are to be placed in this map.
     * @throws NullPointerException if the specified map is null.
     */
	public TypedHashtable(Map t) {
		super(t);
	}
	
	/**
	 * Maps the specified <code>key</code> to the specified boolean <code>value</code> in this 
	 * hashtable.  Since hashtables require <code>Object</code> values, this method will put either
	 * <code>Boolean.TRUE</code> or <code>Boolean.FALSE</code> in the hashtable.  If <code>key</code> is 
	 * <code>null</code> then this method returns with no action taken.
	 * 
	 * @param key the hashtable key.
	 * @param value the boolean value to be mapped to the specified <code>key</code>.
	 * @see Boolean#TRUE
	 * @see Boolean#FALSE
	 * @see #put(Object, Object)
	 */
	public void put(Object key, boolean value) {
		Boolean b = value? Boolean.TRUE: Boolean.FALSE;
		put(key, b);
	}
	
	/**
	 * Maps the specified <code>key</code> to the specified byte <code>value</code> in this 
	 * hashtable.  Since hashtables require <code>Object</code> values, this method will wrap the 
	 * specified byte in a <code>java.lang.Byte</code> before inserting.  If <code>key</code> is 
	 * <code>null</code> then this method returns with no action taken.
	 * 
	 * @param key the hashtable key.
	 * @param value the byte value to be mapped to the specified <code>key</code>.
	 * @see Byte#Byte(byte)
	 * @see #put(Object, Object)
	 */
	public void put(Object key, byte value) {
		put(key, new Byte(value));	
	}
	
	/**
	 * Maps the specified <code>key</code> to the specified short <code>value</code> in this 
	 * hashtable.  Since hashtables require <code>Object</code> values, this method will wrap the 
	 * specified short in a <code>java.lang.Short</code> before inserting.  If <code>key</code> is 
	 * <code>null</code> then this method returns with no action taken.
	 * 
	 * @param key the hashtable key.
	 * @param value the short value to be mapped to the specified <code>key</code>.
	 * @see Short#Short(short)
	 * @see #put(Object, Object)
	 */
	public void put(Object key, short value) {
		put(key, new Short(value));
	}
	
	/**
	 * Maps the specified <code>key</code> to the specified int <code>value</code> in this 
	 * hashtable.  Since hashtables require <code>Object</code> values, this method will wrap the 
	 * specified int in a <code>java.lang.Integer</code> before inserting.  If <code>key</code> is 
	 * <code>null</code> then this method returns with no action taken.
	 * 
	 * @param key the hashtable key.
	 * @param value the int value to be mapped to the specified <code>key</code>.
	 * @see Integer#Integer(int)
	 * @see #put(Object, Object)
	 */
	public void put(Object key, int value) {
		put(key, new Integer(value));
	}
	
	/**
	 * Maps the specified <code>key</code> to the specified long <code>value</code> in this 
	 * hashtable.  Since hashtables require <code>Object</code> values, this method will wrap the 
	 * specified long in a <code>java.lang.Long</code> before inserting.  If <code>key</code> is 
	 * <code>null</code> then this method returns with no action taken.
	 * 
	 * @param key the hashtable key.
	 * @param value the long value to be mapped to the specified <code>key</code>.
	 * @see Long#Long(long)
	 * @see #put(Object, Object)
	 */
	public void put(Object key, long value) {
		put(key, new Long(value));
	}
	
	/**
	 * Maps the specified <code>key</code> to the specified float <code>value</code> in this 
	 * hashtable.  Since hashtables require <code>Object</code> values, this method will wrap the 
	 * specified float in a <code>java.lang.Float</code> before inserting.  If <code>key</code> is 
	 * <code>null</code> then this method returns with no action taken.
	 * 
	 * @param key the hashtable key.
	 * @param value the float value to be mapped to the specified <code>key</code>.
	 * @see Float#Float(float)
	 * @see #put(Object, Object)
	 */
	public void put(Object key, float value) {
		put(key, new Float(value));
	}
	
	/**
	 * Maps the specified <code>key</code> to the specified double <code>value</code> in this 
	 * hashtable.  Since hashtables require <code>Object</code> values, this method will wrap the 
	 * specified double in a <code>java.lang.Double</code> before inserting.  If <code>key</code> is 
	 * <code>null</code> then this method returns with no action taken.
	 * 
	 * @param key the hashtable key.
	 * @param value the double value to be mapped to the specified <code>key</code>.
	 * @see Double#Double(double)
	 * @see #put(Object, Object)
	 */
	public void put(Object key, double value) {
		put(key, new Double(value));
	}
	
	/**
	 * Maps the specified <code>key</code> to the specified char <code>value</code> in this 
	 * hashtable.  Since hashtables require <code>Object</code> values, this method will wrap the 
	 * specified char in a <code>java.lang.Character</code> before inserting.  If <code>key</code> is 
	 * <code>null</code> then this method returns with no action taken.
	 * 
	 * @param key the hashtable key.
	 * @param value the char value to be mapped to the specified <code>key</code>.
	 * @see Character#Character(char)
	 * @see #put(Object, Object)
	 */
	public void put(Object key, char value) {
		put(key, new Character(value));
	}
	
    /**
     * Maps the specified <code>key</code> to the specified 
     * <code>value</code> in this hashtable. If the <code>key</code> is <code>null</code>, then this
     * method returns with no action taken.  If the <code>value</code> is <code>null</code>, then
     * this method removes any existing mapping in the hashtable for the specified <code>key</code>
     * by calling <code>remove(Object key)</code>.
     *
     * The value can be retrieved by calling the <code>get(Object key)</code> method 
     * with a key that is equal to the original key. 
     *
     * @param key the hashtable key.
     * @param value the value.
     * @see Object#equals(Object)
     * @see #get(Object)
     * @see Hashtable#remove(java.lang.Object)
     */
	public Object put(Object key, Object value) {
		if(value==null)
			return super.remove(key);
		else
			return super.put(key, value);
	}
	
	
	
	
	
	/**
	 * Returns the boolean value associated with the specified <code>key</code> in this hashtable.
	 * This method attempts to cast the value in this hashtable for the specified <code>key</code> to
	 * a <code>java.lang.Boolean</code> and invoke its <code>booleanValue()</code> method.
	 * If the key does not exist in the hashtable, or it maps to a non-<code>Boolean</code> value, 
	 * then this method returns the specified <code>defaultValue</code>.
	 * 
	 * @param key the hashtable key
	 * @param defaultValue the value to return if a valid boolean cannot be found for the specified key
	 * @return the boolean value associated with the specified <code>key</code> in this hashtable.
	 * @see #put(Object, boolean)
	 * @see #getBoolean(Object)
	 * @see Boolean#booleanValue()
	 */
	public boolean get(Object key, boolean defaultValue) {
		Object obj = get(key);
		return obj instanceof Boolean? defaultValue: ((Boolean)obj).booleanValue();
	}
	
	/**
	 * Returns the byte value associated with the specified <code>key</code> in this hashtable.
	 * This method attempts to cast the value in this hashtable for the specified <code>key</code> to
	 * a <code>java.lang.Byte</code> and invoke its <code>byteValue()</code> method.
	 * If the key does not exist in the hashtable, or it maps to a non-<code>Byte</code> value, 
	 * then this method returns the specified <code>defaultValue</code>.
	 * 
	 * @param key the hashtable key
	 * @param defaultValue the value to return if a valid byte cannot be found for the specified key
	 * @return the byte value associated with the specified <code>key</code> in this hashtable.
	 * @see #put(Object, byte)
	 * @see #getByte(Object)
	 * @see Byte#byteValue()
	 */
	public byte get(Object key, byte defaultValue) {
		Object obj = get(key);
		return obj instanceof Byte? defaultValue: ((Byte)obj).byteValue();	
	}
	
	/**
	 * Returns the short value associated with the specified <code>key</code> in this hashtable.
	 * This method attempts to cast the value in this hashtable for the specified <code>key</code> to
	 * a <code>java.lang.Short</code> and invoke its <code>shortValue()</code> method.
	 * If the key does not exist in the hashtable, or it maps to a non-<code>Short</code> value, 
	 * then this method returns the specified <code>defaultValue</code>.
	 * 
	 * @param key the hashtable key
	 * @param defaultValue the value to return if a valid short cannot be found for the specified key
	 * @return the short value associated with the specified <code>key</code> in this hashtable.
	 * @see #put(Object, short)
	 * @see #getShort(Object)
	 * @see Short#shortValue()
	 */
	public short get(Object key, short defaultValue) {
		Object obj = get(key);
		return obj instanceof Short? defaultValue: ((Short)obj).shortValue();
	}
	
	/**
	 * Returns the int value associated with the specified <code>key</code> in this hashtable.
	 * This method attempts to cast the value in this hashtable for the specified <code>key</code> to
	 * a <code>java.lang.Integer</code> and invoke its <code>intValue()</code> method.
	 * If the key does not exist in the hashtable, or it maps to a non-<code>Integer</code> value, 
	 * then this method returns the specified <code>defaultValue</code>.
	 * 
	 * @param key the hashtable key
	 * @param defaultValue the value to return if a valid int cannot be found for the specified key
	 * @return the int value associated with the specified <code>key</code> in this hashtable.
	 * @see #put(Object, int)
	 * @see #getInt(Object)
	 * @see Integer#intValue()
	 */
	public int get(Object key, int defaultValue) {
		Object obj = get(key);
		return obj instanceof Integer? defaultValue: ((Integer)obj).intValue();
	}
	
	/**
	 * Returns the long value associated with the specified <code>key</code> in this hashtable.
	 * This method attempts to cast the value in this hashtable for the specified <code>key</code> to
	 * a <code>java.lang.Long</code> and invoke its <code>longValue()</code> method.
	 * If the key does not exist in the hashtable, or it maps to a non-<code>Long</code> value, 
	 * then this method returns the specified <code>defaultValue</code>.
	 * 
	 * @param key the hashtable key
	 * @param defaultValue the value to return if a valid long cannot be found for the specified key
	 * @return the long value associated with the specified <code>key</code> in this hashtable.
	 * @see #put(Object, long)
	 * @see #getLong(Object)
	 * @see Long#longValue()
	 */
	public long get(Object key, long defaultValue) {
		Object obj = get(key);
		return obj instanceof Long? defaultValue: ((Long)obj).longValue();
	}
	
	/**
	 * Returns the float value associated with the specified <code>key</code> in this hashtable.
	 * This method attempts to cast the value in this hashtable for the specified <code>key</code> to
	 * a <code>java.lang.Float</code> and invoke its <code>floatValue()</code> method.
	 * If the key does not exist in the hashtable, or it maps to a non-<code>Float</code> value, 
	 * then this method returns the specified <code>defaultValue</code>.
	 * 
	 * @param key the hashtable key
	 * @param defaultValue the value to return if a valid float cannot be found for the specified key
	 * @return the float value associated with the specified <code>key</code> in this hashtable.
	 * @see #put(Object, float)
	 * @see #getFloat(Object)
	 * @see Float#floatValue()
	 */
	public float get(Object key, float defaultValue) {
		Object obj = get(key);
		return obj instanceof Float? defaultValue: ((Float)obj).floatValue();
	}
	
	/**
	 * Returns the double value associated with the specified <code>key</code> in this hashtable.
	 * This method attempts to cast the value in this hashtable for the specified <code>key</code> to
	 * a <code>java.lang.Double</code> and invoke its <code>doubleValue()</code> method.
	 * If the key does not exist in the hashtable, or it maps to a non-<code>Double</code> value, 
	 * then this method returns the specified <code>defaultValue</code>.
	 * 
	 * @param key the hashtable key
	 * @param defaultValue the value to return if a valid double cannot be found for the specified key
	 * @return the double value associated with the specified <code>key</code> in this hashtable.
	 * @see #put(Object, double)
	 * @see #getDouble(Object)
	 * @see Double#doubleValue()
	 */
	public double get(Object key, double defaultValue) {
		Object obj = get(key);
		return obj instanceof Double? defaultValue: ((Double)obj).doubleValue();
	}
	
	/**
	 * Returns the char value associated with the specified <code>key</code> in this hashtable.
	 * This method attempts to cast the value in this hashtable for the specified <code>key</code> to
	 * a <code>java.lang.Character</code> and invoke its <code>charValue()</code> method.
	 * If the key does not exist in the hashtable, or it maps to a non-<code>Character</code> value, 
	 * then this method returns the specified <code>defaultValue</code>.
	 * 
	 * @param key the hashtable key
	 * @param defaultValue the value to return if a valid char cannot be found for the specified key
	 * @return the char value associated with the specified <code>key</code> in this hashtable.
	 * @see #put(Object, char)
	 * @see #getChar(Object)
	 * @see Character#charValue()
	 */
	public char get(Object key, char defaultValue) {
		Object obj = get(key);
		return obj instanceof Character? defaultValue: ((Character)obj).charValue();
	}
	
	
	/**
	 * Retrieves the value to which the specified key is mapped in this hashtable and casts to a 
	 * <code>java.lang.String</code> before returning.  If the specified <code>key</code> maps to an
	 * object type other than a <code>String</code> value, then this method throws a 
	 * <code>ClassCastException</code>.
	 * 
     * @param   key a key in the hashtable.
     * @return  the <code>String</code> value to which the key is mapped in this hashtable;
     * <code>null</code> if the key is not mapped to any value in this hashtable.
     * @throws  NullPointerException  if the key is <code>null</code>.
     * @throws ClassCastException if the returns value is not a <code>String</code>
     * @see #put(Object, Object)
	 */
	public String getString(Object key) {
		return (String)get(key);
	}	
	
	/**
	 * Retrieves the value to which the specified key is mapped in this hashtable and casts to a 
	 * <code>java.lang.Boolean</code> before returning.  If the specified <code>key</code> maps to an
	 * object type other than a <code>Boolean</code> value, then this method throws a 
	 * <code>ClassCastException</code>.
	 * 
     * @param   key a key in the hashtable.
     * @return  the <code>Boolean</code> value to which the key is mapped in this hashtable;
     * <code>null</code> if the key is not mapped to any value in this hashtable.
     * @throws  NullPointerException  if the key is <code>null</code>.
     * @throws ClassCastException if the returns value is not a <code>Boolean</code>
     * @see #put(Object, Object)
	 */
	public Boolean getBoolean(Object key) {
		return (Boolean)get(key);
	}
	
	/**
	 * Retrieves the value to which the specified key is mapped in this hashtable and casts to a 
	 * <code>java.lang.Byte</code> before returning.  If the specified <code>key</code> maps to an
	 * object type other than a <code>Byte</code> value, then this method throws a 
	 * <code>ClassCastException</code>.
	 * 
     * @param   key a key in the hashtable.
     * @return  the <code>Byte</code> value to which the key is mapped in this hashtable;
     * <code>null</code> if the key is not mapped to any value in this hashtable.
     * @throws  NullPointerException  if the key is <code>null</code>.
     * @throws ClassCastException if the returns value is not a <code>Byte</code>
     * @see #put(Object, Object)
	 */
	public Byte getByte(Object key) {
		return (Byte)get(key);
	}
	
	/**
	 * Retrieves the value to which the specified key is mapped in this hashtable and casts to a 
	 * <code>java.lang.Short</code> before returning.  If the specified <code>key</code> maps to an
	 * object type other than a <code>Short</code> value, then this method throws a 
	 * <code>ClassCastException</code>.
	 * 
     * @param   key a key in the hashtable.
     * @return  the <code>Short</code> value to which the key is mapped in this hashtable;
     * <code>null</code> if the key is not mapped to any value in this hashtable.
     * @throws  NullPointerException  if the key is <code>null</code>.
     * @throws ClassCastException if the returns value is not a <code>Short</code>
     * @see #put(Object, Object)
	 */
	public Short getShort(Object key) {
		return (Short)get(key);
	}
	
	/**
	 * Retrieves the value to which the specified key is mapped in this hashtable and casts to a 
	 * <code>java.lang.Integer</code> before returning.  If the specified <code>key</code> maps to an
	 * object type other than a <code>Integer</code> value, then this method throws a 
	 * <code>ClassCastException</code>.
	 * 
     * @param   key a key in the hashtable.
     * @return  the <code>Integer</code> value to which the key is mapped in this hashtable;
     * <code>null</code> if the key is not mapped to any value in this hashtable.
     * @throws  NullPointerException  if the key is <code>null</code>.
     * @throws ClassCastException if the returns value is not a <code>Integer</code>
     * @see #put(Object, Object)
	 */
	public Integer getInt(Object key) {
		return (Integer)get(key);
	}
	
	/**
	 * Retrieves the value to which the specified key is mapped in this hashtable and casts to a 
	 * <code>java.lang.Long</code> before returning.  If the specified <code>key</code> maps to an
	 * object type other than a <code>Long</code> value, then this method throws a 
	 * <code>ClassCastException</code>.
	 * 
     * @param   key a key in the hashtable.
     * @return  the <code>Long</code> value to which the key is mapped in this hashtable;
     * <code>null</code> if the key is not mapped to any value in this hashtable.
     * @throws  NullPointerException  if the key is <code>null</code>.
     * @throws ClassCastException if the returns value is not a <code>Long</code>
     * @see #put(Object, Object)
	 */
	public Long getLong(Object key) {
		return (Long)get(key);
	}
	
	/**
	 * Retrieves the value to which the specified key is mapped in this hashtable and casts to a 
	 * <code>java.lang.Float</code> before returning.  If the specified <code>key</code> maps to an
	 * object type other than a <code>Float</code> value, then this method throws a 
	 * <code>ClassCastException</code>.
	 * 
     * @param   key a key in the hashtable.
     * @return  the <code>Float</code> value to which the key is mapped in this hashtable;
     * <code>null</code> if the key is not mapped to any value in this hashtable.
     * @throws  NullPointerException  if the key is <code>null</code>.
     * @throws ClassCastException if the returns value is not a <code>Float</code>
     * @see #put(Object, Object)
	 */
	public Float getFloat(Object key) {
		return (Float)get(key);
	}
	
	/**
	 * Retrieves the value to which the specified key is mapped in this hashtable and casts to a 
	 * <code>java.lang.Double</code> before returning.  If the specified <code>key</code> maps to an
	 * object type other than a <code>Double</code> value, then this method throws a 
	 * <code>ClassCastException</code>.
	 * 
     * @param   key a key in the hashtable.
     * @return  the <code>Double</code> value to which the key is mapped in this hashtable;
     * <code>null</code> if the key is not mapped to any value in this hashtable.
     * @throws  NullPointerException  if the key is <code>null</code>.
     * @throws ClassCastException if the returns value is not a <code>Double</code>
     * @see #put(Object, Object)
	 */
	public Double getDouble(Object key) {
		return (Double)get(key);
	}
	
	/**
	 * Retrieves the value to which the specified key is mapped in this hashtable and casts to a 
	 * <code>java.lang.Character</code> before returning.  If the specified <code>key</code> maps to an
	 * object type other than a <code>Character</code> value, then this method throws a 
	 * <code>ClassCastException</code>.
	 * 
     * @param   key a key in the hashtable.
     * @return  the <code>Character</code> value to which the key is mapped in this hashtable;
     * <code>null</code> if the key is not mapped to any value in this hashtable.
     * @throws  NullPointerException  if the key is <code>null</code>.
     * @throws ClassCastException if the returns value is not a <code>Character</code>
     * @see #put(Object, Object)
	 */
	public Character getChar(Object key) {
		return (Character)get(key);
	}

}
