/*
このファイルの中身は、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 jp.co.ntt.lms.xmo.LoRelation.LoRelationClient;
import jp.co.ntt.lms.xmo.util.DebugLog;
import jp.co.ntt.lms.xmo.DataAccess;

/**
 * 完結要件を扱うクラスです。<BR>
 * @author XXX
 * @version 0.0.0.1
 */
public class Conclusion implements ConclusionMessage{

	// インスタンス変数
	/** 完結要件条件式を保持します */
	private String mstrConclusion;
	/** ユーザIDを保持します */
	private String mstrUserID;
	/** LOIDを保持します */
	private String mstrLoID;
	/** データアクセスオブジェクトを保持します。*/
	private DataAccess mobjDataAccess;
	/** パース結果を保持します */
	private DecideConclusion objDecide = null;

	// コンストラクタ
	/**
	 * 完結要件条件式を指定します。<BR>
	 * 完結要件条件式の構文チェックのみを行いたい場合はこのコンストラクタを呼んでください。
	 * @param strConclusion 完結要件条件式
	 */
	public Conclusion( String strConclusion ) {
		mstrConclusion = strConclusion;
	}

	/**
	 * 完結要件条件式および、LOIDを指定します。<BR>
	 * 完結要件の構文チェックおよび、LOIDチェックを行う場合はこのコンストラクタを呼んでください。
	 * @param strConclusion 完結要件条件式
	 * @param strLoID LOID
	 */
	public Conclusion( String strConclusion, String strLoID ) {
		mstrConclusion = strConclusion;
		mstrLoID = strLoID;
	}

	/**
	 * 完結要件条件式、ユーザID、LOIDを指定します。<BR>
	 * パースを行って、完結要件を満たしているかチェックしたい場合はこのコンストラクタを呼んでください。
	 * @param strConclusion 完結要件条件式
	 * @param strUserID ユーザID
	 * @param strLoID LOID
	 * @param objDataAccess データアクセスオブジェクト
	 */
	public Conclusion( String strConclusion, String strUserID, String strLoID, DataAccess objDataAccess ) {
		mstrConclusion = strConclusion;
		mstrUserID = strUserID;
		mstrLoID = strLoID;
		mobjDataAccess = objDataAccess;
	}

	// 外部メソッド
	/**
	 * 完結要件条件式を解析します。
	 * @exception ConclusionParseException 完結要件条件式の構文に誤りがある場合
	 * @exception ConclusionException 解析中に実行時例外が生じた場合
	 */
	public void parse()
		throws ConclusionParseException,ConclusionException
	{
		if ( mstrConclusion == null || mstrConclusion.equals("") ){
			throw new ConclusionParseException( ConclusionEnv.getMessage( INPUT_EMPTY_ERR ) );
		}
		ConclusionData objCd = new ConclusionData( mstrConclusion, mstrUserID, mobjDataAccess );
		ConclusionNode objCn = new ConclusionNode( objCd );
		objCn.parse();
		objDecide = (DecideConclusion)objCn;
	}

	/**
	 * 完結要件条件式の妥当性チェックを行います。<BR>
	 * 以下のようなチェックを行い誤りがある場合は、ConclusionParseExceptionをスローします。<BR>
	 * <PRE>
	 *       ①　構文チェック　正しい構文でかかれているかチェック
	 *       ②　LOIDチェック　コンストラクタで、LOIDが指定されている場合、
	 *                         指定されたLOIDの兄弟ID、子IDのみが使用されていることをチェックします。
	 * </PRE>
	 * @exception ConclusionParseException 完結要件条件式の構文に誤りがある場合
	 * @exception ConclusionException 解析中に実行時例外が生じた場合
	 */
	public void check(boolean bInsMode)
		throws ConclusionParseException,ConclusionException
	{
		try
		{
			if ( mstrConclusion == null || mstrConclusion.equals("") ){
				throw new ConclusionParseException( ConclusionEnv.getMessage( INPUT_EMPTY_ERR ) );
			}
			ConclusionData objCd = new ConclusionData( mstrConclusion, mstrUserID, mobjDataAccess );
			ConclusionNode objCn = new ConclusionNode( objCd );
			objCn.parse();
			objDecide = (DecideConclusion)objCn;

			//LOIDチェック
			if ( mstrLoID != null ){
				Vector vecConclusion = objDecide.getLoIDList();
				if ( vecConclusion.size() == 0 ){
					throw new ConclusionParseException( ConclusionEnv.getMessage( LOID_LIST_NONE ) );
				}
				Vector vecCheck = getChildList( mstrLoID );//子LOIDを取得
				if ( vecCheck.containsAll( vecConclusion ) != true ){
					DebugLog.write( this.getClass(), vecCheck, DebugLog.ROW );
					DebugLog.write( this.getClass(), vecConclusion, DebugLog.ROW );
					throw new ConclusionParseException( ConclusionEnv.getMessage( LOID_CHECK_ERR ) );
				}
			}
		}
		catch( ConclusionParseException pe)
		{
			DebugLog.write( this.getClass(), pe, DebugLog.ROW );
			throw pe;
		}
		catch( ConclusionException ce)
		{
			DebugLog.write( this.getClass(), ce, DebugLog.ROW );
			throw ce;
		}
	}

	/**
	 * 完結要件を満たしているかを返します。
	 * @return boolean true: 満たしている false: 満たしていない
	 * @exception ConclusionException 完結要件条件式がパースされていないときなど
	 */
	public boolean isConcluded()
		throws ConclusionException
	{
		return objDecide.isConcluded();
	}

	/**
	 * 完結要件条件式で使用されているLOIDの一覧を取得します
	 * @return String[] LOID一覧
	 * @exception ConclusionParseException 完結要件条件式の構文に誤りがある場合
	 * @exception ConclusionException 解析中に実行時例外が生じた場合
	 */
	public String[] getLoIDList()
		throws ConclusionParseException,ConclusionException
	{
		if ( objDecide == null ){
			parse();
		}
		Vector vecTemp = objDecide.getLoIDList();
		if ( vecTemp.size() == 0 ){
			return new String[0];
		}
		else{
			String[] result = new String[vecTemp.size()];
			vecTemp.copyInto( result );
			return result;
		}
	}

	/**
	 * 完結要件に指定されたLOIDが使用されているかどうかを調べます。
	 * @param strLoID 比較対照LOID
	 * @return boolean true:使用されている false: 使用されていない
	 * @exception ConclusionParseException 完結要件条件式の構文に誤りがある場合
	 * @exception ConclusionException 解析中に実行時例外が生じた場合
	 */
	public boolean isUsedLoID( String strLoID )
		throws ConclusionParseException,ConclusionException
	{
		if ( objDecide == null ){
			parse();
		}
		Vector vecTemp = objDecide.getLoIDList();
		return vecTemp.contains( strLoID );
	}



	/**
	 * LOIDから親LOIDを取得するメソッドです。
	 * @exception ConclusionException 伝搬例外
	 */
	private String getParentID(String strLoID)
		throws ConclusionException
	{
		String strParentID = null;
		try {
			LoRelationClient objLoRelation = new LoRelationClient();
			// 検索条件に子LOIDを指定します
			objLoRelation.setWhereChildID( strLoID );
			// 検索処理
			if( !objLoRelation.select() ) {
				// 検索に失敗した場合
				throw new ConclusionException( objLoRelation.getMessage() );
			}

			// 検索結果を取得
			if( objLoRelation.next() ) {
				strParentID = objLoRelation.getParentID();
			}
		}
		catch(ConclusionException pe) {
			throw pe;
		}
		catch(Exception ex) {
			DebugLog.write( this.getClass(), ex, DebugLog.HIGHT );
			throw new ConclusionException(ex.getMessage());
		}
		return strParentID;
	}

	/**
	 * 指定されたLOIDの子IDリストを取得します。
	 * @param strParentID 親ID
	 * @return Vector 子IDリスト
	 * @exception ConclusionException 伝搬例外
	 */
	private Vector getChildList(String strParentID)
		throws ConclusionException
	{
		Vector vecChildList = new Vector();
		try {
			LoRelationClient objLoRelation = new LoRelationClient();
			// 検索条件に親LOIDを指定します
			objLoRelation.setWhereParentID( strParentID );
			// 検索処理
			if( !objLoRelation.select() ) {
				// 検索に失敗した場合
				throw new ConclusionException( objLoRelation.getMessage() );
			}

			// 検索結果を取得
			while( objLoRelation.next() ) {
				String strChildID = objLoRelation.getChildID();
				vecChildList.add( objLoRelation.getChildID() );
			}
		}
		catch(ConclusionException pe) {
			throw pe;
		}
		catch(Exception ex) {
			DebugLog.write( this.getClass(), ex, DebugLog.HIGHT );
			throw new ConclusionException(ex.getMessage());
		}
		return vecChildList;
	}

}


