/*
このファイルの中身は、NTT オープンソースライセンス　バージョン 1.0（「本
契約」という）の適用を受けます。
本契約を遵守しない限り、このファイルを使用してはなりません。
本契約のコピーは、次のＵＲＬから入手できます。
【配布サイトのURL】 http://www.oss.ecl.ntt.co.jp/lms/

本契約に基づき頒布されるソフトウェアは、現状のまま、明示又は黙示のあらゆ
る種類の保証なしで、頒布されます。本契約に基づく権利及び制限を律する特定
の文言については、本契約を参照してください。

「オリジナルコード」は、 NTT Cyber Space Laboratories Code です。 
「オリジナルコード」の「初期開発者」は、日本電信電話株式会社です。  
日本電信電話株式会社により創作された部分は、Copyright (C) 2004 
日本電信電話株式会社 です。
全ての権利が留保されます。 
「コントリビュータ」：_____________________________________ 


The contents of this file are subject to the NTT Opensource License
Version 1.0 (the License); you may not use this file except in
compliance with the License. You may obtain a copy of the License at
【配布サイトのURL】 http://www.oss.ecl.ntt.co.jp/lms/

Software distributed under the License is distributed on an AS IS
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
License for the specific language governing rights and limitations
under the License.

The Original Code is NTT Cyber Space Laboratories Code .

The Initial Developer of the Original Code is NIPPON TELEGRAPH AND 
TELEPHONE CORPORATION.
Portions created by the NIPPON TELEGRAPH AND TELEPHONE CORPORATION 
are Copyright (C) 2004 NIPPON TELEGRAPH AND TELEPHONE CORPORATION. 
All Rights Reserved.

Contributor(s) ______________________________________.
*/

//
//	完結判定末端クラス
//			変更履歴
//				2004.01.08	新規作成	中山雅文
//
package jp.co.ntt.lms.Common.status.conclusion;

import java.util.Vector;
import java.sql.SQLException;

import jp.co.ntt.lms.xmo.DataAccess;
import jp.co.ntt.lms.lo.LoLogDataAccess;
import jp.co.ntt.lms.xmo.util.DebugLog;
import jp.co.ntt.lms.xmo.Lo.LoDataAccess;

/**
 * 完結判定末端クラスです。<BR>
 * このクラスで実装されている、isConcludedメソッドから実際にLoLogテーブルへ
 * アクセスを行い、要件を満たしているかどうかを判断します。
 * @author 二條智文
 * @version 0.0.0.1
 */
class ConclusionPrimitive implements DecideConclusion,ConclusionMessage {


	/** 完結要件文字列を保持します */
	private ConclusionData mobjConclusionData;

	/** LOIDを保持します */
	private String mstrLoID;

	/** 完結条件ステータスを保持します */
	private char mchaStatus;

	/** 関係演算子タイプを保持します */
	private int mintRelationType = EQUAL_TYPE;


	/** 合格(passed)文字です。 */
	private static final char STATUS_PASSED = 'p';

	/** 修了(completed)文字です。 */
	private static final char STATUS_COMPLETED = 'c';

	/** 不合格、未修了、未学習(failed)文字です。*/
	private static final char STATUS_FAILED = 'f';

	/** 未閲覧(Not Attempt)文字です。*/
	private static final char STATUS_NOT_ATTEMPT = 'n';

	/** 未習得(Incomplete)文字です。*/
	private static final char STATUS_INCOMPLETE = 'i';

	/** 閲覧済(Browsed)文字です。*/
	private static final char STATUS_BROWSED = 'b';

	/** 関係演算子の "=" をあらわします */
	private static final int EQUAL_TYPE = 1;

	/** 関係演算子の "!=" をあらまします */
	private static final int NOT_EQUAL_TYPE = 2;

	/** !=を定義します。 */
	private static final String NOT_EQUAL_STRING = "!=";

	/** =を定義します。 */
	private static final String EQUAL_STRING = "=";

	/**
	 * コンストラクタです。<BR>
	 * パースする完結要件情報を格納したデータオブジェクトを指定します。
	 * @param objConclusionData
	 */
	public ConclusionPrimitive( ConclusionData objConclusionData ) {
		mobjConclusionData = objConclusionData;
	}

	/**
	 * 完結要件を満たしているかどうかチェックします
	 * @boolean true: 満たしている false: 満たしていない
	 * @exception ConclusionException 解析中に実行時例外が生じた場合
	 */
	public boolean isConcluded()
		throws ConclusionException
	{
		if ( mobjConclusionData == null ){
			throw new ConclusionException( ConclusionEnv.getMessage(SYSTEM_ERR) );
		}

		LoLogDataAccess objLoLog = new LoLogDataAccess();
		boolean bPassed = false;
		boolean bCompleted = false;
		boolean bBrowsed = false;
		boolean result = false;
		String strRealLoID = null;

		try{

			LoDataAccess objLoDataAccess = new LoDataAccess();
			strRealLoID = objLoDataAccess.getRealLOID( mstrLoID, mobjConclusionData.getDataAccess() );
			// UserIDとLOIDを元にLOLogテーブルからステータスを取得します。
			boolean[] bStatus = objLoLog.getStatus( mobjConclusionData.getUserID(), strRealLoID,
													mobjConclusionData.getDataAccess() );

			bPassed = bStatus[0];
			bCompleted = bStatus[1];
			bBrowsed = bStatus[2];

		}catch( SQLException e ){
			DebugLog.write( this.getClass(), e, DebugLog.HIGHT );
			throw new ConclusionException( ConclusionEnv.getMessage(DB_ERR) );
		}


		// 完結要件に設定されているステータスごとに処理を振り分ける
		// 合格('p')の場合
		// =p → 合格日付に日付が入っている場合にtrue となる
		// !=p → 合格日付がnullの場合にtrue となる
		if( mchaStatus == STATUS_PASSED ) {
			// 合格ステータスをチェックする
			if( mintRelationType == EQUAL_TYPE ) {
				result = bPassed;
			}
			else {
				result = !bPassed;
			}
		}
		// 完了('c')の場合
		// =c → 完了日付に日付が入っている場合にtrue となる
		// !=c → 完了日付がnullの場合にtrue となる
		else if( mchaStatus == STATUS_COMPLETED ) {
			// 合格ステータスをチェックする
			if( mintRelationType == EQUAL_TYPE ) {
				result = bCompleted;
			}
			else {
				result = !bCompleted;
			}
		}
		// 不合格('f')の場合
		// =f → 合格日付がnullの場合にtrue となる
		// !=f → 合格日付に日付が入っている場合にtrue となる
		else if ( mchaStatus == STATUS_FAILED ) {
			// 不合格・未完了ステータスをチェックする
			if( mintRelationType == EQUAL_TYPE ) {
				result = !bPassed;
			}
			else {
				result = bPassed;
			}
		}
		// 未閲覧('n')の場合
		// =n → 学習開始日付がnullの場合にtrue となる
		// !=n → 学習開始日付に日付が入っている場合にtrue となる
		else if( mchaStatus == STATUS_NOT_ATTEMPT ) {
			// 未閲覧ステータスをチェックする
			if( mintRelationType == EQUAL_TYPE ) {
				result = !bBrowsed;
			} else {
				result = bBrowsed;
			}
		}
		// 未習得('i')の場合
		// =i → 完了日付がnullの場合にtrue となる
		// !=i → 完了日付に日付が入っている場合にtrue となる
		else if( mchaStatus == STATUS_INCOMPLETE ) {
			// 未習得ステータスをチェックする
			if( mintRelationType == EQUAL_TYPE ) {
				result = !bCompleted;
			} else {
				result = bCompleted;
			}
		}
		// 閲覧済('b')の場合
		// =b → 学習開始日付に日付が入っている場合にtrue となる
		// !=b → 学習開始日付がnullの場合にtrue となる
		else if( mchaStatus == STATUS_BROWSED ) {
			// 閲覧済ステータスをチェックする
			if( mintRelationType == EQUAL_TYPE ) {
				result = bBrowsed;
			} else {
				result = !bBrowsed;
			}
		}

		return result;
	}

	/**
	 * 完結要件条件式に使用されているLOIDのリストを取得します。
	 * @return Vector LOIDリスト
	 */
	public Vector getLoIDList() {
		Vector vecReq = new Vector();
		vecReq.add( mstrLoID );
		return vecReq;
	}
	/**
	 * 完結要件文字列を分解します。<BR>
	 * @exception ConclusionParseException パース例外が発生した場合。
	 */
	public void parse()
		throws ConclusionParseException
	{
		if ( mobjConclusionData == null ){
			throw new ConclusionParseException( ConclusionEnv.getMessage(SYSTEM_ERR) );
		}
		int index = 0;
		//スペース、タブ、CR、LF、()を削除する。
		String strConclusion = eraseSPTABCRLF( mobjConclusionData.getConclusion() );

		if ( (index = strConclusion.indexOf( NOT_EQUAL_STRING )) != -1 ){
			mintRelationType = NOT_EQUAL_TYPE;
			parseSentence( strConclusion.substring(0, index),
						strConclusion.substring(index+2, strConclusion.length()) );
		}
		else if ( (index = strConclusion.indexOf( EQUAL_STRING )) != -1 ){
			mintRelationType = EQUAL_TYPE;
			parseSentence( strConclusion.substring(0, index),
						strConclusion.substring(index+1, strConclusion.length()) );
		}
		else{
			throw new ConclusionParseException( ConclusionEnv.getMessage(OPERATOR_NONE) );
		}
		return;
	}

	/**
	 * 解析に不要なコードを削除します。
	 * @param strInput 完結要件文字列
	 * @return 削除後の文字列
	 */
	private String eraseSPTABCRLF(String strInput)
	{

		String strCheck = replace(strInput, ' ');
		strCheck = replace(strCheck, '\t');
		strCheck = replace(strCheck, '\r');
		strCheck = replace(strCheck, '\n');
		return strCheck;
	}

	private String replace(String src, char match) {
		StringBuffer	result = new StringBuffer(src);

		int i = 0;
		while( true ){
			if ( i >= result.length() ){
				break;
			}
			if ( result.charAt(i) == match ){
				result = result.deleteCharAt(i);
				i--;
			}
			i++;
		}
		return result.toString();
	}

	/**
	 * LOIDとステータスをチェックし設定します。
	 * @param String 関係演算子の前の文字列
	 * @param String 関係演算子の後ろの文字列
	 * @exception ConclusionParseException パース例外が発生した場合。
	 */
	private void parseSentence(String strFront, String strBack )
		throws ConclusionParseException
	{
		if (  strBack.length() != 1 ){
			throw new ConclusionParseException( ConclusionEnv.getMessage(STATUS_LENGTH_ERR));
		}

		char cStatus = strBack.charAt( 0 );
		switch( cStatus ){
			case STATUS_PASSED:
			case STATUS_COMPLETED:
			case STATUS_FAILED:
			case STATUS_NOT_ATTEMPT:
			case STATUS_INCOMPLETE:
			case STATUS_BROWSED:
				mchaStatus = cStatus;
				break;
			default:
				throw new ConclusionParseException( ConclusionEnv.getMessage(STATUS_KIND_ERR) );
		}
		mstrLoID = strFront;


	}

}


