/*
 * Quad 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;

/**
 * 四つのオブジェクトの組を保持するクラス。
 * <p>
 * 四つのオブジェクトの組をフィールド変数として保持し、
 * それぞれの組の設定や取得を行うメソッド、及び各オブジェクトの値の
 * 比較によう等値の判定を行うメソッドを用意している。
 *
 * @author  佐藤隆之. 
 * @version $Revision: 1.1.1.1 $, $Date: 2010-10-16 00:03:44 $
 */
public class Quad<F,S,T,O> implements Serializable
{
  /* シリアル番号。 */
  static final long serialVersionUID = 8340877329259337297L;

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

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

  /** 第3オブジェクト。 */
  private T value3_ ;

  /** 第4オブジェクト。 */
  private O value4_ ;

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

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

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

  /**
   * 第一オブジェクトを設定する。
   * <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>
   * 引数にヌルを設定した場合はそのままヌルを設定する。
   *
   * @param  third 第三オブジェクト。
   */
  public void setThird(T third)
  {
    value3_ = third;
  }

  /**
   * 第三オブジェクトを取得する。
   *
   * @return 第三オブジェクト。
   */
  public T getThird()
  {
    return value3_ ;
  }

  /**
   * 第四オブジェクトを設定する。
   * <br>
   * 引数がヌルの場合はそのままヌルを設定する。
   *
   * @param  fourth 第四オブジェクト。
   */
  public void setFourth(O fourth)
  {
    value4_ = fourth;
  }

  /**
   * 第四オブジェクトを取得する。
   *
   * @return 第四オブジェクト。
   */
  public O getFourth()
  {
    return value4_;
  }

  /**
   * 指定されたオブジェクトと内容が等しいかどうかを比較する。
   * <br>
   * 引数が<code>Quad</code>オブジェクトの場合は、それらのフィールド変数で
   * ある四つのオブジェクトをそれぞれ比較して、全て等しい場合は<tt>true</tt>
   * を、そうでなければ<tt>false</tt>を返す。
   * 引数がヌルまたは<code>Quad</code>オブジェクトでない場合は<tt>false</tt>
   * を返す。
   *
   * @param  obj 比較するオブジェクト。
   * @return オブジェクトの内容が等しい場合は<tt>true</tt>を返す。
   */
  public boolean equals(Object obj)
  {
    if (obj == null || !(obj instanceof Quad))
      return false;

    Quad another = Quad.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;
    }

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

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

    return true;
  }

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