/*
 * TypedMap class.
 *
 * Copyright (C) 2011 SATOH Takayuki All Rights Reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
package ts.util;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;
import java.text.DecimalFormat;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.util.Set;
import java.util.HashSet;

/**
 * キーに結びつけられた値オブジェクトを型変換して取得するためのメソッドを備えた
 * マップ・クラス。
 *
 * @author 佐藤隆之
 * @version $Id: TypedMap.java,v 1.4 2011-08-01 15:29:30 tayu Exp $
 */
public class TypedMap<K,V> extends AbstractTypedGetter<K,V> implements Map<K,V>
{
  /** シリアル・バージョン番号。 */
  static final long serialVersionUID = 8641045995393252723L;

  /** キーと値オブジェクトのマッピングを格納する内部マップ。 */
  private final Map<K,V> innerMap = createInnerMap();

  /**
   * デフォルト・コンストラクタ。
   */
  public TypedMap()
  {}

  /**
   * 内部マップを作成する。
   *
   * @return 内部マップ。
   */
  protected Map<K,V> createInnerMap()
  {
    return new HashMap<K,V>();
  }

  /**
   * このマップに格納されている要素の数を取得する。
   *
   * @return このマップに格納されている要素の数。
   */
  @Override
  public int size()
  {
    return this.innerMap.size();
  }

  /**
   * このマップが空かどうかを確認する。
   *
   * @return このマップの要素数がゼロの場合は<tt>true</tt>を返す。
   */
  @Override
  public boolean isEmpty()
  {
    return this.innerMap.isEmpty();
  }

  /**
   * 指定されたキーを持った要素がこのマップに存在するかどうかを確認する。
   * 
   * @param key キー。
   * @return 引数のキーがこのマップに含まれている場合は<tt>true</tt>を返す。
   */
  @Override
  public boolean containsKey(Object key)
  {
    return this.innerMap.containsKey(key);
  }

  /**
   * 指定された値オブジェクトを持った要素がこのマップに存在するかどうかを確認
   * する。
   *
   * @param value 値オブジェクト。
   * @return 引数の値オブジェクトがこのマップに含まれている場合は<tt>true</tt>
   *         を返す。
   */
  @Override
  public boolean containsValue(Object value)
  {
    return this.innerMap.containsValue(value);
  }

  /**
   * 指定されたキーに結びつけられている値オブジェクトを取得する。
   * <br>
   * 結びつけられた値オブジェクトが存在しない場合はヌルを返す。
   *
   * @param key キー。
   * @return 引数のキーに結びつけられている値オブジェクト。
   */
  @Override
  public V get(Object key)
  {
    return this.innerMap.get(key);
  }

  /**
   * 指定されたキーと値オブジェクトの組をこのマップに登録する。
   *
   * @param key キー。
   * @param value 値オブジェクト。
   * @return 引数のキーに以前結びつけられていた値オブジェクト。
   */
  @Override
  public V put(K key, V value)
  {
    return this.innerMap.put(key, value);
  }

  /**
   * 指定されたキーに結びつけられている値オブジェクトを削除する。
   *
   * @param key キー。
   * @return 引数のキーに以前結びつけらｒていた値オブジェクト。
   */
  @Override
  public V remove(Object key)
  {
    return this.innerMap.remove(key);
  }

  /**
   * 指定されたマップの全ての要素をこのマップに追加する。 
   *
   * @param map 追加する要素を格納するマップ。
   */
  @Override
  public void putAll(Map<? extends K, ? extends V> map)
  {
    this.innerMap.putAll(map);
  }

  /**
   * このマップを空にする。
   * <br>
   * このマップの全ての要素を、このマップから削除する。
   */
  @Override
  public void clear()
  {
    this.innerMap.clear();
  }

  /**
   * このマップが格納しているキーの集合を取得する。
   *
   * @return このマップが格納しているキーの集合。
   */
  @Override
  public Set<K> keySet()
  {
    return this.innerMap.keySet();
  }

  /**
   * このマップの全ての要素の値オブジェクトを格納したコレクション・オブジェクト
   * 取得する。
   *
   * @return このマップの全ての要素の値オブジェクトを格納したコレクション・
   *         オブジェクト。
   */
  @Override
  public Collection<V> values()
  {
    return this.innerMap.values();
  }

  /**
   * このマップに格納されている全てのキーと値の組を、{@link java.util.Map.Entry}
   * オブジェクトの集合として取得する。
   *
   * @return このマップの全ての要素を格納した集合。
   */
  @Override
  public Set<Map.Entry<K,V>> entrySet()
  {
    return this.innerMap.entrySet();
  }

  /**
   * 指定されたオブジェクトと内容が等しいかどうかを比較する。
   * <br>
   * 引数のオブジェクトがマップであり、このマップと引数のマップが同じマッピング
   * を持っている場合は<tt>true</tt>を返す。
   * より具体的には、このマップの{@link Map#entrySet()}メソッドの結果と引数の
   * マップの{@link Map#entrySet()}の結果が等しい場合に<tt>true</tt>を返す。
   *
   * @param obj 比較するオブジェクト。
   * @return 引数のオブジェクトがこのマップと内容が等しい場合に<tt>true</tt>。
   */
  @Override
  public boolean equals(Object obj)
  {
    return this.innerMap.equals(obj);
  }

  /**
   * このマップに対するハッシュ・コードを取得する。
   *
   * @return このマップに対するハッシュ・コード。
   */
  @Override
  public int hashCode()
  {
    return this.innerMap.hashCode();
  }
}
