/*
 * Duo class.
 *
 * Copyright (C) 2007 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.io.Serializable;

/**
 * 二つのオブジェクトの組を表すクラス。
 * <br>
 * それぞれの値の設定や取得を行うメソッドを用意している。
 *
 * @author  佐藤隆之. 
 * @version $Revision: 1.1.1.1 $, $Date: 2010-10-16 00:03:44 $
 */
public class Duo<F, S> implements Serializable
{
  /* シリアル番号。 */
  static final long serialVersionUID = -3793037288866678719L;

  /** 第1オブジェクト。 */
  private F value1_ ;

  /** 第2オブジェクト。 */
  private S value2_ ;

  /**
   * デフォルトコンストラクタ。
   * <br>
   * 二つのオブジェクトの値は、ともにヌルに設定される。
   */
  public Duo()
  {}

  /**
   * 二つのオブジェクトの値を引数にとるコンストラクタ。
   * <br>
   * 引数がヌルの場合は、そのままヌルを設定する。
   *
   * @param  first  第一オブジェクト。
   * @param  second 第二オブジェクト。
   */
  public Duo(F first, S second)
  {
    set(first, second);
  }

  /**
   * 二つのオブジェクトの値を設定する。
   * <br>
   * 引数がヌルの場合は、そのままヌルを設定する。
   *
   * @param  first  第一オブジェクト。
   * @param  second 第二オブジェクト。
   */
  public void set(F first, S second)
  {
    setFirst(first);
    setSecond(second);
  }

  /**
   * 第一オブジェクトを設定する。
   * <br>
   * 引数がヌルの場合は、そのままヌルを設定する。
   *
   * @param  first 第一オブジェクト。
   */
  public void setFirst(F first)
  {
    value1_ = first;
  }

  /**
   * 第一オブジェクトを取得する。
   *
   * @return 第一オブジェクト。
   */
  public F getFirst()
  {
    return value1_;
  }

  /**
   * 第二オブジェクトを設定する。
   * <br>
   * 引数がヌルの場合は、そのままヌルを設定する。
   *
   * @param  second 第二オブジェクト。
   */
  public void setSecond(S second)
  {
    value2_ = second;
  }

  /**
   * 第二オブジェクトを取得する。
   *
   * @return 第二オブジェクト。
   */
  public S getSecond()
  {
    return value2_;
  }

  /**
   * 指定されたオブジェクトと内容が等しいかどうかを比較する。
   * <br>
   * 引数が<code>Duo</code>オブジェクトの場合は、それぞれの第一オブジェクト
   * 及び第二オブジェクトを比較して、共に等しい場合は<tt>true</tt>を、
   * そうでなければ<tt>false</tt>を返す。
   * 引数がヌルの場合は<code>Duo</code>オブジェクトでない場合は<tt>false</tt>
   * を返す。
   *
   * @param  obj 比較するオブジェクト。
   * @return オブジェクトの内容が等しい場合は<tt>true</tt>を返す。
   */
  public boolean equals(Object obj)
  {
    if (obj == null || !(obj instanceof Duo))
      return false;

    Duo another = Duo.class.cast(obj);

    if (getFirst() == null) {
      if (another.getFirst() != null)
        return false;
    }
    else if (! getFirst().equals(another.getFirst())) {
      return false;
    }

    if (getSecond() == null) {
      if (another.getSecond() != null)
        return false;
    }
    else if (! getSecond().equals(another.getSecond())) {
      return false;
    }

    return true;
  }

  /**
   * ハッシュコードを取得する。
   *
   * @return ハッシュコード。
   */
  public int hashCode()
  {
    int v1 = (getFirst()  == null) ? 0 : getFirst().hashCode();
    int v2 = (getSecond() == null) ? 0 : getSecond().hashCode();
    return (v1 + v2);
  }
}
