/*
このファイルの中身は、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) ______________________________________.
*/

//
//	Evaluate 管理XMO クライアントクラス
//			変更履歴
//				2004.01.08	新規作成	          五木田　泰史
//
package jp.co.ntt.lms.xmo.Evaluate;

import java.rmi.RemoteException;
import java.util.*;

import org.apache.commons.lang.StringEscapeUtils;

import jp.co.ntt.lms.xmo.*;
import jp.co.ntt.lms.xmo.Lo.*;
import jp.co.ntt.lms.xmo.LoRelation.*;
import jp.co.ntt.lms.xmo.Groups.*;
import jp.co.ntt.lms.xmo.People.*;
import jp.co.ntt.lms.xmo.util.*;

/**
 * Evaluate 管理XMO クライアントクラスです。<BR>
 * このクラスはEvaluate XMO サーバクラスとの接続および、
 * 登録、更新、削除、検索処理に必要なパラメータの設定、検索後の
 * 検索結果の取得メソッドを提供します。<BR>
 * @author Y.Gokita
 * @version 0.0.0.1 2004/01/08
 */
public class EvaluateClient extends XMOBasicClient
	implements EvaluateTable
{

	private static final String CLASS_NAME = "jp.co.ntt.lms.xmo.Evaluate.Evaluate";

	// LOID　をキーにして、リアルLOIDを保持します。
	private Hashtable mhtbLoIDMap = new Hashtable();
	// LOIDリスト
	private Vector mvecLoIDList = new Vector();

	/**
	 * コンストラクタです。<BR>
	 * 親クラスのコンストラクタを呼び出し、接続先サーバクラス名を
	 * 設定します。
	 */
	public EvaluateClient() throws Exception {
		super( CLASS_NAME );
	}

	/**
	 * パラメータにLoIDをセットします
	 */
	public void setLoID( String strLoID ) {
		putData( LOID, strLoID );
	}

	/**
	 * 検索結果の現在のインデックスのLoIDを取得します
	 */
	public String getLoID() {
		EvaluateData objData = (EvaluateData)getResult();
		return objData.getLoID();
	}

	/**
	 * パラメータにユーザーIDをセットします
	 */
	public void setUserID( String strUserID ) {
		putData( USER, strUserID );
	}

	/**
	 * 検索結果から現在のインデックスのグループ名を取得します
	 */
	public String getUserID() {
		EvaluateData objData = (EvaluateData)getResult();
		return objData.getUserID();
	}

	/**
	 * パラメータに評価した日時をセットします
	 */
	public void setScoreDate( String strScoreDate ) {
		putData( SCOREDATE, strScoreDate );
	}

	/**
	 * 検索結果から現在のインデックスの評価した日時を取得します
	 */
	public String getScoreDate() {
		EvaluateData objData = (EvaluateData)getResult();
		return objData.getScoreDate();
	}

	/**
	 * パラメータに得点をセットします
	 */
	public void setScore( String strScore ) {
		putData( SCORE, strScore );
	}

	/**
	 * 検索結果から現在のインデックスの得点を取得します
	 */
	public String getScore() {
		EvaluateData objData = (EvaluateData)getResult();
		return objData.getScore();
	}


	/**
	 * パラメータにコメントをセットします
	 */
	public void setCustomMsgDir( String strCustomMsgDir ) {
		putData( CUSTOM_MSG_DIR, strCustomMsgDir );
	}

	/**
	 * 検索結果から現在のインデックスのコメントを取得します
	 */
	public String getCustomMsgDir() {
		EvaluateData objData = (EvaluateData)getResult();
		return objData.getCustomMsgDir();
	}

	/**
	 * LoIDを検索条件に付与します
	 * デフォルトで"="条件をつけます
	 * @param String LoID
	 */
	public void setWhereLoID( String strLoID ) {
		String strCondition = LOID + SEARCH_EQUALS + "'" + StringEscapeUtils.escapeSql(strLoID) + "' ";
		setCondition( strCondition );
	}

	/**
	 * ユーザーIDを検索条件に付与します
	 * デフォルトで"="条件をつけます
	 * @param String ユーザーID
	 */
	public void setWhereUserID( String strUserID ) {
		String strCondition = USER + SEARCH_EQUALS + "'" + StringEscapeUtils.escapeSql(strUserID) + "' ";
		setCondition( strCondition );
	}

	/**
	 * 得点を検索条件に付与します
	 * デフォルトで"="条件をつけます
	 * @param String 得点
	 */
	public void setWhereScore( String strScore ) {
		String strCondition = SCORE + SEARCH_EQUALS + "'" + StringEscapeUtils.escapeSql(strScore) + "' ";
		setCondition( strCondition );
	}

	/**
	 * コメントを検索条件に付与します
	 * デフォルトで"="条件をつけます
	 * @param strCustomMsgDir コメント
	 */
	public void setWhereCustomMsgDir( String strCustomMsgDir ) {
		String strCondition = CUSTOM_MSG_DIR + SEARCH_EQUALS + "'" + SqlEscape.escape(strCustomMsgDir) + "' ";
		setCondition( strCondition );
	}

	/**
	 * 削除KeyとなるLOIDをセットします
	 * @param String LOID
	 */
	public void setDeleteSelectID( String strLOID ) {
		putData( DELETE_LOID, strLOID );
	}

	/**
	 * 教材名とユーザー名を設定したEvaluateデータリストを作成します
	 * @return Vector MessageデータとEvaluateデータリスト
	 */
	public Vector makeEvaluateDataComp()
	{
		Vector vecRet     = new Vector();
		Vector vecEvc     = new Vector();
		MessageData objMd = null;
		// Evaluateデータリスト取得
		Vector vecEvaluate = new Vector();
		try
		{
			// Where句作成
			StringBuffer strConditionKey = new StringBuffer();
			String strLoID = (String)htParams.get(LOID);
			String[] strLoIDList = expandLo(strLoID);
			for(int i = 0; i < strLoIDList.length; i++)
			{
				// 最初のみ添付
				if(i == 0)
				{
					strConditionKey.append(" LOID in(");
				}
				strConditionKey.append("'");
				strConditionKey.append(StringEscapeUtils.escapeSql(strLoIDList[i]));
				strConditionKey.append("'");
				//最後のみ終了文字を変更
				if(i == strLoIDList.length - 1)
				{
					strConditionKey.append(") ");
				}
				else
				{
					strConditionKey.append(",");
				}
			}
			setCondition(strConditionKey.toString());
			setOrderBy(LOID);													// LoIDの昇順
			if(!select())
			{
				// エラー処理
				objMd = getMessageData();
				DebugLog.write(this.getClass(), objMd.getMessage(), DebugLog.HIGHT);
				vecRet.add(objMd);
				return vecRet;
			}
			else
			{
				while(next())
				{
					EvaluateData objEd = new EvaluateData();
					objEd.setLoID(getLoID());
					objEd.setUserID(getUserID());
					objEd.setScore(getScore());
					objEd.setCustomMsgDir(getCustomMsgDir());

					vecEvaluate.add(objEd);
				}
			}
		}
		catch(Exception e)
		{
			DebugLog.write(this.getClass(), e, DebugLog.HIGHT);
			objMd = new MessageData();
			objMd.setMessage(e.getMessage());
			vecRet.add(objMd);
			return vecRet;
		}
		if(vecEvaluate.size() == 0)
		{
			vecRet.add(objMd);
			vecRet.add(vecEvaluate);
			return vecRet;
		}

		// 各SQL文(ConditionKey)作成
		String strLoConditionKey   = makeLoConditionKey();
		String strUserConditionKey = makeUserConditionKey(vecEvaluate);

		try
		{
			// 各リスト作成
			Hashtable htbTitleList    = makeTitleList(strLoConditionKey);			// 教材名リスト

			vecEvc = makeEvcList(htbTitleList, vecEvaluate);	// 完全評価データリスト

		}
		catch(Exception e)
		{
			e.printStackTrace();
			objMd = new MessageData();
			objMd.setMessage(e.getMessage());
		}
		vecRet.add(objMd);
		vecRet.add(vecEvc);
		return vecRet;
	}

	/**
	 * LoIDのWhere句を作成します
	 * @return String LoIDのWhere句
	 */
	private String makeLoConditionKey()
	{
		// LoIDリストSQL作成
		StringBuffer strLoConditionKey = new StringBuffer();

		for( int i = 0; i < mvecLoIDList.size(); i++ ) {
			String strLoID     = (String)mvecLoIDList.get(i);

			if(strLoID != null && !strLoID.equals(""))
			{
				// 最初のみ添付
				if(i == 0)
				{
					strLoConditionKey.append(" LOID in(");
				}
				strLoConditionKey.append("'");
				strLoConditionKey.append(StringEscapeUtils.escapeSql(strLoID));
				strLoConditionKey.append("'");
				//最後のみ終了文字を変更
				if(i == mvecLoIDList.size() - 1)
				{
					strLoConditionKey.append(") ");
				}
				else
				{
					strLoConditionKey.append(",");
				}
			}
		}
		return strLoConditionKey.toString();
	}

	/**
	 * ユーザーIDのWhere句を作成します
	 * @param Vector 評価データリスト
	 * @return String PeIDのWhere句
	 */
	private String makeUserConditionKey(Vector vecEvaluate)
	{
		// PeIDリストSQL作成とGrIDリストSQL作成
		StringBuffer strUserConditionKey = new StringBuffer();
		for(int i = 0; i < vecEvaluate.size(); i++)
		{
			EvaluateData objEd = (EvaluateData)vecEvaluate.get(i);
			String strUserID   = objEd.getUserID();
			if(strUserID != null && !strUserID.equals(""))
			{
				if(strUserID.indexOf("GR") != 0)
				{
					// 最初のみ添付
					if(i == 0)
					{
						strUserConditionKey.append(" user_id in(");
					}
					strUserConditionKey.append("'");
					strUserConditionKey.append(StringEscapeUtils.escapeSql(strUserID));
					strUserConditionKey.append("'");
					//最後のみ終了文字を変更
					if(i == vecEvaluate.size() - 1)
					{
						strUserConditionKey.append(") ");
					}
					else
					{
						strUserConditionKey.append(",");
					}
				}
				else
				{
				}
			}
		}
		return strUserConditionKey.toString();
	}

	/**
	 * 教材IDと教材名のリストを作成します
	 * @param String LoIDのWhere句
	 * @return Vector 教材IDと教材名のリスト
	 */
	private Hashtable makeTitleList(String strLoConditionKey)
		throws Exception
	{
		Hashtable htbTitleList = new Hashtable();
		// 教材名リスト作成
		LoClient objLc = new LoClient();
		objLc.setCondition(strLoConditionKey);
		if(!objLc.select())
		{
		}
		else
		{
			while(objLc.next())
			{
				String strLoID = objLc.getLoID();
				String strLoTitle = objLc.getLoTytle();

				if( strLoTitle != null ) {
					htbTitleList.put( strLoID, strLoTitle );
				}
			}
		}
		return htbTitleList;
	}

	/**
	 * ユーザーIDとユーザー名のリストを作成します
	 * @param String ユーザーIDのWhere句
	 * @return Vector ユーザーIDとユーザー名のリスト
	 */
	private Vector makeUserNameList(String strUserConditionKey)
		throws Exception
	{
		// ユーザー名リスト作成
		PeopleClient objPc   = new PeopleClient();
		Vector vecUserNameList = new Vector();
		objPc.setCondition(strUserConditionKey);
		if(!objPc.select())
		{
		}
		else
		{
			while(objPc.next())
			{
				String[] strUserNameList = new String[2];
				strUserNameList[0]       = objPc.getUserID();
				strUserNameList[1]       = objPc.getUserName();
				vecUserNameList.add(strUserNameList);
			}
		}
		return vecUserNameList;
	}

	/**
	 * 評価データの完全リストを作成します
	 * @param Vector 教材名リスト
	 * @param Vector 個人名リスト
	 * @param Vector 評価データリスト
	 * @return Vector 評価データの完全リスト
	 */
	private Vector makeEvcList(Hashtable htbTitleList,
							 Vector vecEvaluate)
	{
		// カウンタ変数
		int i = 0;
		int j = 0;

		// 評価データリストをLOID分作成します。
		Hashtable htbEvaluate = new Hashtable();
		int intEvaluateSize = vecEvaluate.size();
		for( i = 0; i < intEvaluateSize; i++ ) {
			EvaluateData objData = (EvaluateData)vecEvaluate.get(i);
			String strLoID = objData.getLoID();
			Vector vecEvaluateTemp = (Vector)htbEvaluate.get(strLoID );
			if( vecEvaluateTemp == null ) {
				vecEvaluateTemp = new Vector();
				htbEvaluate.put( strLoID, vecEvaluateTemp );
			}

			vecEvaluateTemp.add( objData );
		}

		// 戻りVectorを初期化する
		Vector vecRet = new Vector();

		// 評価リストを初期化する
		vecEvaluate = new Vector();

		// 評価を取得するLOIDをLOIDのソート順に並び替える
		Collections.sort( mvecLoIDList );

		// LOID分ループを行い、画面に表示する評価データを作成する
		for(i = 0; i < mvecLoIDList.size(); i++)
		{

			String strLoID     = (String)mvecLoIDList.get(i);
			// LOID からRealLOIDを取得する
			String strRealLoID = (String)mhtbLoIDMap.get( strLoID );
			Vector vecEvaluateTemp = (Vector)htbEvaluate.get(strRealLoID);

			if( vecEvaluateTemp != null ) {

				for( j = 0; j < vecEvaluateTemp.size(); j++ ) {
					EvaluateData objEd = (EvaluateData)vecEvaluateTemp.get(j);

					// 評価データをコピーする
					objEd = objEd.copy();

					// LoIDによるTitle検索処理
					String strTitle = (String)htbTitleList.get(strLoID);
					objEd.setMaterialName(strTitle);
					// リアルLOIDではないLOIDを設定する
					objEd.setLoID( strLoID );
					vecEvaluate.add( objEd );
				}
			}

		}

		// 合計、平均レコード挿入
		String strTempLoID         = "";
		String strTempMaterialName = "";
		int intSumScore            = 0;
		int intAverageScore        = 0;
		int intCount               = 0;
		Vector vecChildList        = new Vector();
		for(i = 0; i < vecEvaluate.size(); i++)
		{
			EvaluateData objEd     = (EvaluateData)vecEvaluate.get(i);
			String strLoID         = objEd.getLoID();
			// 最初のみ実行
			if(strLoID != null && i == 0)
			{
				strTempLoID         = strLoID;
				strTempMaterialName = objEd.getMaterialName();
			}
			if(strLoID != null && strLoID.equals(strTempLoID))
			{
				//評価(1〜5)が設定されていない場合("")は、統計得点に加算、及びCountUpしない。
				if (! objEd.getScore().equals(""))
				{
					int intScore = Integer.parseInt(objEd.getScore());				// 得点設定
					intSumScore += intScore;										// 統計得点に加算
					intCount++;														// Lo数加算
				}
				vecChildList.add(objEd);										// 配下レコードリストに追加

			}
			else if(strLoID != null)
			{
				// 一致しなかった場合
				EvaluateData objSumEd = new EvaluateData();						// 統計レコード作成
				objSumEd.setLoID(strTempLoID);									// 統計LoID設定
				objSumEd.setMaterialName(strTempMaterialName);					// 統計教材名設定
				if( intCount != 0 ) {
					objSumEd.setScore(String.valueOf(intSumScore));					// 統計得点設定
					intAverageScore = intSumScore / intCount;
					objSumEd.setAverageScore(String.valueOf(intAverageScore));		// 統計平均点設定
				}
				objSumEd.setUserName("");										// 統計ユーザー名設定
				objSumEd.setCustomMsgDir("");									// 統計コメント設定
				vecRet.add(objSumEd);											// 完全リストに追加(統計)
				for(j = 0; j < vecChildList.size(); j++)						// 配下のレコード追加
				{
					vecRet.add((EvaluateData)vecChildList.get(j));				// 完全リストに追加(配下)
				}
				vecChildList.removeAllElements();
				// 後処理
				strTempLoID         = strLoID;									// LoID設定
				strTempMaterialName = objEd.getMaterialName();					// 教材名設定
				// 初期化
				intAverageScore     = 0;										// 平均点初期化

				//評価(1〜5)が設定されていない場合("")は、Lo数初期化は0、統計得点初期化は0を設定する
				intCount = 0;													// Lo数初期化
				intSumScore = 0;												// 統計得点初期化
				if (! objEd.getScore().equals(""))
				{
					intCount = 1;
					intSumScore = Integer.parseInt(objEd.getScore());
				}
				vecChildList.add(objEd);										// 配下リスト追加
			}
			else
			{
			}
		}

		if(vecEvaluate.size() > 0)
		{
			// 最終処理
			EvaluateData objSumEd = new EvaluateData();						// 統計レコード作成
			objSumEd.setLoID(strTempLoID);									// 統計LoID設定
			objSumEd.setMaterialName(strTempMaterialName);					// 統計教材名設定
			if( intCount != 0 ) {
				objSumEd.setScore(String.valueOf(intSumScore));					// 統計得点設定
				intAverageScore = intSumScore / intCount;
				objSumEd.setAverageScore(String.valueOf(intAverageScore));		// 統計平均点設定
			}
			objSumEd.setUserName("");										// 統計ユーザー名設定
			objSumEd.setCustomMsgDir("");									// 統計コメント設定
			vecRet.add(objSumEd);											// 完全リストに追加(統計)
			for(j = 0; j < vecChildList.size(); j++)						// 配下のレコード追加
			{
				vecRet.add((EvaluateData)vecChildList.get(j));				// 完全リストに追加(配下)
			}
			vecChildList.removeAllElements();
		}
		return vecRet;
	}

	/**
	 * LoIDリスト取得処理
	 *
	 * @param String LoID
	 * @return String[] LoIDリスト
	 */
	private String[] expandLo(String strLoID)
		throws Exception
	{
		String[] strRet = null;
		Vector vecList = new Vector();
		getLoIDList(strLoID, vecList);
		strRet = new String[vecList.size()];
		for(int i = 0; i < vecList.size(); i++)
		{
			strRet[i] = (String)vecList.get(i);
		}
		return strRet;
	}

	/**
	 * LoIDリスト取得再帰処理
	 *
	 * @param String LoID
	 * @param Vector LoIDリスト
	 * @return void
	 */
	private void getLoIDList(String strLoID, Vector vecList)
		throws Exception
	{
		LoRelationClient objLrc = new LoRelationClient();

		objLrc.setWhereParentID(strLoID);
		if(!objLrc.select())
		{
			DebugLog.write(this.getClass(), "Lo関連取得失敗", DebugLog.ROW);
			return;
		}
		while(objLrc.next())
		{
			String strLoChildID = objLrc.getChildID();
			getLoIDList(strLoChildID, vecList);
		}

		// LOID から RealLOID取得
		String strRealLOID = "";
		LoClient objLoClient = new LoClient();
		if(objLoClient.getRealLOIDFromLOID(strLoID)){
			strRealLOID = objLoClient.getRealLOIDResult();
		}
		else{
			// 検索失敗
			throw new XMOException( objLoClient.getMessageData() );
		}

		// LOIDをキーにしてリアルLOIDを保持する
		mhtbLoIDMap.put( strLoID, strRealLOID);
		// LOIDを保持します。
		mvecLoIDList.add( strLoID );
		// 同じRealLOIDが含まれていない場合のみ追加
		if( !vecList.contains(strRealLOID ) ) {
			vecList.add(strRealLOID);
		}

		return;
	}
}

