/*
 * Copyright (c) 2009 The openGion Project.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
package org.opengion.fukurou.util;

/**
 * HybsEntry.java は、内部に final 定義された文字列の、key と value を持つ、値クラスです。
 *
 * 全変数は、public final 宣言されており、外部より取得できますが、設定できません。
 * このクラスは、コンストラクタで設定されたキーと設定値を変える事が出来ません。
 * よって、デフォルトコンストラクタを持たないため、java.io.Serializable インターフェースは
 * 持ちません。また、内部の値を変更できない為、clone() をする必要がないため、
 * java.lang.Cloneable インターフェースも実装していません。
 * HybsEntry オブジェクトの同一性を確保するには、equals( Object ) と、hashCode() メソッドを
 * オーバーライドしておく必要があります。同一性の条件は、key と value が、ともに
 * String.equals の関係を持てば、成立することとします。
 *
 * @version  4.0
 * @author	 Kazuhiko Hasegawa
 * @since    JDK5.0,
 */
public final class HybsEntry implements Comparable<HybsEntry> {	// 4.3.3.6 (2008/11/15) Generics警告対応
	/** 内部のキー情報	*/
	private final String key ;
	/** 内部のバリュー情報	*/
	private final String value ;
	/** 内部のコメント情報	*/
	private final String comment ;	// 4.0.0 (2005/01/31) 追加

	// 4.0.0 (2005/01/31) private 化
	private final int hCode ;
	//	private static final ValueComparator valueComp = new ValueComparator();

	/**
	 * コンストラクタ
	 * 内部変数への値の設定は、このコンストラクターで行われます。
	 * key への null セットは認められません。value へは、セットできます。
	 * コメントは、ゼロ文字列("") で、初期化されます。
	 *
	 * @param key	キー
	 * @param value	値
	 * @throws IllegalArgumentException key に null がセットされた場合
	 */
	public HybsEntry( final String key,final String value ) {
		this( key,value,"" );
	}

	/**
	 * コンストラクタ
	 * 内部変数への値の設定は、このコンストラクターで行われます。
	 * key への null セットは認められません。value へは、セットできます。
	 *
	 * @param key	キー
	 * @param value 値
	 * @param comment コメント
	 * @throws IllegalArgumentException key に null がセットされた場合
	 */
	public HybsEntry( final String key,final String value,final String comment ) {
		if( key == null ) {
			final String errMsg = "key への null セットは認められません。" ;
			throw new IllegalArgumentException( errMsg );
		}

		this.key	= key;
		this.value	= value;
		this.comment = comment;
		hCode		= ( key + ',' + value + '.' + comment ).hashCode();
	}

	/**
	 * エントリに対応するキーを返します。
	 *
	 * @return	エントリに対応するキー
	 */
	public String getKey() { return key; }

	/**
	 * エントリに対応する値を返します。
	 *
	 * @return	エントリに対応する値
	 */
	public String getValue() { return value; }

	/**
	 * エントリに対応するコメントを返します。
	 *
	 * @return エントリに対応するコメント
	 */
	public String getComment() { return comment; }

	/**
	 * HybsEntry の設定されている値を変更します。
	 * これは、設定値を変更した新しい HybsEntry を作成して返します。
	 * なお、value が、内部の値と等しい時(equals が成立する時)自分自身を返します。
	 *
	 * @param newValue 新しい値
	 *
	 * @return エントリー HybsEntry
	 * @og.rtnNotNull
	 */
	public HybsEntry getValue( final String newValue ) {
		// 6.4.1.1 (2016/01/16) PMD refactoring. A method should have only one exit point, and that should be the last statement in the method
		return	( newValue == null && value == null ) ||
				( newValue != null && newValue.equals( value ) )
					? this
					: new HybsEntry( key,newValue,comment );
	}

	/**
	 * 自然比較メソッド
	 * インタフェース Comparable の 実装です。
	 * HybsEntryの順序は、key の順序であらわされます。
	 * 同一keyの場合は，value の順番になります。
	 *
	 * @param   other 比較対象のObject
	 *
	 * @return  このオブジェクトが指定されたオブジェクトより小さい場合は負の整数、等しい場合はゼロ、大きい場合は正の整数
	 * @throws ClassCastException 指定されたオブジェクトがキャストできない場合。
	 */
	@Override
	public int compareTo( final HybsEntry other ) {		// 4.3.3.6 (2008/11/15) Generics警告対応
		int comp = key.compareTo( other.key );

		if( comp == 0 ) {
			// 6.4.1.1 (2016/01/16) PMD refactoring. Avoid if (x != y) ..; else ..;
			comp = value == null
					? other.value == null ? 0 : -1					// value が null 同士で、一致って ???
					: value.compareTo( other.value );

			if( comp == 0 ) {
				comp = comment.compareTo( other.comment );
			}
		}
		return comp ;
	}

	/**
	 * このオブジェクトと他のオブジェクトが等しいかどうかを示します。
	 * インタフェース Comparable の 実装に関連して、再定義しています。
	 * HybsEntryは、key が等しく、かつ valueが同一の場合に、
	 * 等しいと判断されます。
	 *
	 * @param   object 比較対象の参照オブジェクト
	 *
	 * @return	引数に指定されたオブジェクトとこのオブジェクトが等しい場合は true、そうでない場合は false
	 */
	@Override
	public boolean equals( final Object object ) {
		if( object instanceof HybsEntry ) {
			final HybsEntry other = (HybsEntry)object;
			return  key.equals( other.key ) 
					&& value != null && value.equals( other.value ) ;
		}
		return false ;
	}

	/**
	 * オブジェクトのハッシュコード値を返します。
	 * このメソッドは、java.util.Hashtable によって提供されるような
	 * ハッシュテーブルで使用するために用意されています。
	 * equals( Object ) メソッドをオーバーライトした場合は、hashCode() メソッドも
	 * 必ず 記述する必要があります。
	 * ここでは、key と value の合成した文字列のハッシュコード値を返します。
	 *
	 * @return  このオブジェクトのハッシュコード値
	 *
	 */
	@Override
	public int hashCode() {
		return hCode ;
	}

	/**
	 * オブジェクトの識別子として，詳細なユーザー情報を返します。
	 *
	 * @return  詳細なユーザー情報
	 * @og.rtnNotNull
	 */
	@Override
	public String toString() {
		return "key=[" + key + "],value=[" + value + "],comment=[" + comment + "]" ;
	}

	/**
	 * 設定値の順序を表す Comparator を返します。
	 * HybsEntryクラス自身は、key の順番で自然順序付けを行う、Comparable インターフェースを
	 * 実装しています。しかし、設定値でソートする場合は、この
	 * Comparator インターフェースを実装した内部クラスを使用することで、
	 * 対応出来ます。
	 *
	 * @return  設定値の順序を表す Comparator
	 */
	//	public Comparator getValueComparator() {
	//		return valueComp ;
	//	}

	/**
	 * オブジェクトの識別子として，詳細なユーザー情報を返します。
	 *
	 * @return  詳細なユーザー情報
	 */
	//	private static class ValueComparator implements Comparator {
	//		/**
	//		 * value の順序付けのために 2 つの引数を比較します。
	//		 * 最初の引数が 2 番目の引数より小さい場合は負の整数、両方が等しい場合は 0、
	//		 * 最初の引数が 2 番目の引数より大きい場合は正の整数を返します。
	//		 *
	//		 * @param   o1 Object 比較対象の最初のオブジェクト
	//		 * @param   o2 Objectb比較対象の 2 番目のオブジェクト
	//		 * @return  最初の引数が 2 番目の引数より小さい場合は負の整数、両方が等しい場合は 0、最初の引数が 2 番目の引数より大きい場合は正の整数
	//		 * @throws  ClassCastException - 引数の型がこのコンパレータによる比較を妨げる場合
	//		 */
	//		public int compare(Object o1, Object o2) {
	//			HybsEntry e1 = (HybsEntry)o1 ;		// キャスト失敗で、ClassCastException
	//			HybsEntry e2 = (HybsEntry)o2 ;		// キャスト失敗で、ClassCastException
	//
	//			int comp = 0;
	//			if( e1 == null && e2 == null ) { comp = 0; }
	//			else if( e1 == null && e2 != null ) { comp = -1; }
	//			else if( e1 != null && e2 == null ) { comp = 1;  }
	//			else if( e1 != null && e2 != null ) {
	//				if( e1.value == null && e2.value == null ) { comp = 0; }
	//				else if( e1.value == null && e2.value != null ) { comp = -1; }
	//				else if( e1.value != null && e2.value == null ) { comp = 1; }
	//				else {
	//					comp = e1.value.compareTo( e2.value );
	//				}
	//			}
	//			return comp ;
	//		}
	//	}
}
