//===========================================================================
// package
//===========================================================================
package jp.gr.java_conf.bugslife.util;

//===========================================================================
// import
//===========================================================================

/**
 *<PRE>
 * アサーションクラス
 *
 * Cのassrt関数を模したクラス。第１引数がfalseの場合異常終了する。
 * デバッグ用に内部の論理矛盾を検出するために使用する。
 * static methodの集合体なのでインスタンス化する必要はない
 *
 * 今回、使う用途として、
 * ○引数チェック
 * ○あり得ない状態
 * 等につかう。
 *
 * 使用例
 * 例）取得したオブジェクトがnullかチェック
 * Assert.check(obj != null,"xxx is null");
 *
 * 使い方
 * 
 * 第１引数は条件で、第２引数にメッセージを渡せる仕様になっている。
 *
 *
 *</PRE>
 * @version	0.1, 2000/11/30
 * @author	鰐川 正寛
 */
//===========================================================================
// version	0.0, 2000/11/30	新規作成
// version	0.0, 2001/06/12	notNull, argumentの追加(末廣)
//===========================================================================
public class Assert
{
//===========================================================================
// attributes
//===========================================================================
	/**
	 * アサートフラグ
	 *
	 */ 
	public static boolean bASSERT = true;
//===========================================================================
// methods
//===========================================================================
	/**
	 *
	 *	内部エラーアサーション
	 *
	 * @param	cond	アサーションコンディション
	 * @exception	InternalError
	 */ 
	public static final void check(boolean cond)
	{
		//コンディションが偽か
		if (cond == false) {
			String s = "assertion!";
			//例外を発生してもいいか？
			if (bASSERT) {
				throw (new InternalError(s));
			} else {
				//警告のメッセージだけログに出し、異常終了はしない
				//※単体テスト用にログに出す代わりにコンソールに出す
				System.out.println(s);
			}
		}
	}
	/**
	 *
	 *	内部エラーアサーション
	 *
	 * @param	cond	アサーションコンディション
	 * @param	msg		アサーションメッセージ
	 * @exception	InternalError
	 */ 
	public static final void check(boolean cond, String msg)
	{
		//コンディションが偽か
		if (cond == false) {
			String s = msg;
			//例外を発生してもいいか？
			if (bASSERT) {
				throw (new InternalError(s));
			} else {
				//警告のメッセージだけログに出し、異常終了はしない
				//※単体テスト用にログに出す代わりにコンソールに出す
				System.out.println(s);
			}
		}
	}

	/**
	 *
	 *	2重チェックアサーション
	 *
	 * @param	preCond	プリアサーションコンディション
	 * @param	cond	アサーションコンディション
	 * @exception	InternalError
	 */ 
	public static final void checkCond(boolean preCond, boolean cond)
	{
		//プリコンディションが真か
		if (preCond) {
			//コンディションが偽か
			if (cond == false) {
				String s = "assertion!";
				//例外を発生してもいいか？
				if (bASSERT) {
					throw (new InternalError(s));
				} else {
					//警告のメッセージだけログに出し、異常終了はしない
					//※単体テスト用にログに出す代わりにコンソールに出す
					System.out.println(s);
				}
			}
		}
	}
	/**
	 *
	 *	2重チェックアサーション
	 *
	 * @param	preCond	プリアサーションコンディション
	 * @param	cond	アサーションコンディション
	 * @param	msg		アサーションメッセージ
	 * @exception	InternalError
	 */ 
	public static final void checkCond(boolean preCond, boolean cond, String msg)
	{
		//プリコンディションが真か
		if (preCond) {
			//コンディションが偽か
			if (cond == false) {
				String s = msg;
				//例外を発生してもいいか？
				if (bASSERT) {
					throw (new InternalError(s));
				} else {
					//警告のメッセージだけログに出し、異常終了はしない
					//※単体テスト用にログに出す代わりにコンソールに出す
					System.out.println(s);
				}
			}
		}
	}

	/**
	 *
	 * オブジェクトチェックアサーション
	 *
	 * @param	var		オブジェクト
	 * @exception		IllegalStateException
	 */
	public static final void notNull(Object var)
	{
		if (var == null) {
			String s = "assertion!";
			//例外を発生してもいいか？
			if (bASSERT) {
				throw (new IllegalStateException(s));
			} else {
				//警告のメッセージだけログに出し、異常終了はしない
				//※単体テスト用にログに出す代わりにコンソールに出す
				System.out.println(s);
			}
		}
	}
	/**
	 *
	 * オブジェクトチェックアサーション
	 *
	 * @param	var		オブジェクト
	 * @param	msg		アサーションメッセージ
	 * @exception	IllegalStateException
	 */
	public static final void notNull(Object var, String msg)
	{
		if (var == null) {
			String s = msg;
			//例外を発生してもいいか？
			if (bASSERT) {
				throw (new IllegalStateException(s));
			} else {
				//警告のメッセージだけログに出し、異常終了はしない
				//※単体テスト用にログに出す代わりにコンソールに出す
				System.out.println(s);
			}
		}
	}

	/**
	 *
	 *	引数チェックアサーション
	 *
	 * @param	cond	アサーションコンディション
	 * @exception	IllegalArgumentException
	 */ 
	public static final void argument(boolean cond)
	{
		//コンディションが偽か
		if (cond == false) {
			String s = "assertion!";
			//例外を発生してもいいか？
			if (bASSERT) {
				throw (new IllegalArgumentException());
			} else {
				//警告のメッセージだけログに出し、異常終了はしない
				//※単体テスト用にログに出す代わりにコンソールに出す
				System.out.println(s);
			}
		}
	}
	/**
	 *
	 *	引数チェックアサーション
	 *
	 * @param	cond	アサーションコンディション
	 * @param	msg		アサーションメッセージ
	 * @exception	IllegalArgumentException
	 */ 
	public static final void argument(boolean cond, String msg)
	{
		//コンディションが偽か
		if (cond == false) {
			String s = msg;
			//例外を発生してもいいか？
			if (bASSERT) {
				throw (new IllegalArgumentException());
			} else {
				//警告のメッセージだけログに出し、異常終了はしない
				//※単体テスト用にログに出す代わりにコンソールに出す
				System.out.println(s);
			}
		}
	}
	/**
	 * クラス名の取得
	 *
	 * @return	クラス名
	 */
	private String getClassName()
	{
		return ((Assert)this).getClass().getName();
	}

	/**
	 *
	 *	テストメイン
	 *
	 */ 
	public static void main(String[] args)
	{
		//テスト開始
		System.out.println("----------Assert class Unit Test start!");
		
		//
		// デバッグモード時のテスト
		//
/* ------------------------
		System.out.println("<debug mode test>");
		//bDEBUG = true;
		runUnitTest();
 ------------------------ */
		//
		// リリースモード時のテスト
		//
		System.out.println("<release mode test>");
		//bDEBUG = false;
		runUnitTest1();
		runUnitTest2();
		runUnitTest3();
		runUnitTest4();

		//テスト終了
		System.out.println("----------Assert class Unit Test done!");
	}
	
	/**
	 *
	 *	checkのテスト
	 *
	 */ 
	public static void runUnitTest1()
	{
		System.out.println("<check test>");

		//メッセージ無しパターン
		
		//cond = falseの場合
		System.out.println("[check]cond = false");
		Assert.check(false);
		//cond = trueの場合
		System.out.println("[check]cond = true");
		Assert.check(true);
		
		//メッセージ渡しのパターン
		
		//cond = falseの場合
		System.out.println("[check]cond = false, messege ");
		Assert.check(false, "this is assert test");
		//cond = trueの場合
		System.out.println("[check]cond = true, messege ");
		Assert.check(true, "this is assert test");
		
	}
	/**
	 *
	 *	checkCondのテスト
	 *
	 */ 
	public static void runUnitTest2()
	{
		System.out.println("<checkCond test>");

		//メッセージ無しパターン
		
		//preCond = false, cond = falseの場合
		System.out.println("[checkCond]preCond = false, cond = false");
		Assert.checkCond(false, false);
		//preCond = false, cond = trueの場合
		System.out.println("[checkCond]preCond = false, cond = true");
		Assert.checkCond(false, true);
		//preCond = true, cond = falseの場合
		System.out.println("[checkCond]preCond = true, cond = false");
		Assert.checkCond(true, false);
		//preCond = true, cond = trueの場合
		System.out.println("[checkCond]preCond = true, cond = true");
		Assert.checkCond(true, true);
		
		//メッセージ渡しのパターン
		
		//cond = falseの場合
		//preCond = false, cond = falseの場合
		System.out.println("[checkCond]preCond = false, cond = false, messege ");
		Assert.checkCond(false, false, "this is checkCond test");
		//preCond = false, cond = trueの場合
		System.out.println("[checkCond]preCond = false, cond = true, messege ");
		Assert.checkCond(false, true, "this is checkCond test");
		//preCond = true, cond = falseの場合
		System.out.println("[checkCond]preCond = true, cond = false, messege ");
		Assert.checkCond(true, false, "this is checkCond test");
		//preCond = true, cond = trueの場合
		System.out.println("[checkCond]preCond = true, cond = true, messege ");
		Assert.checkCond(true, true, "this is checkCond test");
		
	}
	/**
	 *
	 *	notNullのテスト
	 *
	 */ 
	public static void runUnitTest3()
	{
		System.out.println("<notNull test>");

		//メッセージ無しパターン
		Object var = null;
		
		//var = nullの場合
		System.out.println("[notNull]var = false");
		Assert.notNull(var);
		//var != nullの場合
		System.out.println("[notNull]var = true");
		var = new Object();
		Assert.notNull(var);
		
		//メッセージ渡しのパターン
		
		//var = nullの場合
		System.out.println("[notNull]var = false, messege ");
		var = null;
		Assert.notNull(var, "this is notNull test");
		//var != nullの場合
		System.out.println("[notNull]var = true, messege ");
		var = new Object();
		Assert.notNull(var, "this is notNull test");
		
	}
	/**
	 *
	 *	argumentのテスト
	 *
	 */ 
	public static void runUnitTest4()
	{
		System.out.println("<argument test>");

		//メッセージ無しパターン
		
		//cond = falseの場合
		System.out.println("[argument]cond = false");
		Assert.argument(false);
		//cond = trueの場合
		System.out.println("[argument]cond = true");
		Assert.argument(true);
		
		//メッセージ渡しのパターン
		
		//cond = falseの場合
		System.out.println("[argument]cond = false, messege ");
		Assert.argument(false, "this is argument test");
		//cond = trueの場合
		System.out.println("[argument]cond = true, messege ");
		Assert.argument(true, "this is argument test");
		
	}
}
