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

//
//	LO SmartForce教材 サーバクラス
//			変更履歴
//				2004.01.08	新規作成	五木田　泰史
//
package jp.co.ntt.lms.lo.SmartForce;

import jp.co.ntt.lms.lo.*;
import jp.co.ntt.lms.xmo.util.*;

import jp.co.ntt.lms.xmo.Lo.MaterialData;
import jp.co.ntt.lms.xmo.MenuData;
import jp.co.ntt.lms.xmo.MessageData;
import jp.co.ntt.lms.xmo.People.PeopleClient;
import jp.co.ntt.lms.xmo.Lo.LoClient;

import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.RMISecurityManager;
import java.util.*;
import java.sql.*;

import org.apache.commons.lang.StringEscapeUtils;

/**
 * LO SmartForce教材 サーバクラスです。<BR>
 * 上位にLoServerクラスを持ち、LoTopとLoPropertyDefを実装します。
 *
 * @author Y.Gokita
 * @version 0.0.0.1 2004/01/08
 */
public class SmartForceLo extends LoServer
	implements LoTop, SmartForceLoPropertyDef
{
	//////////////////////////////////////////////////////////////////
	// 変数定義
	//////////////////////////////////////////////////////////////////
	DBAccess mobjDba;

	//////////////////////////////////////////////////////////////////
	// メソッド名定義
	//////////////////////////////////////////////////////////////////
	/**
	 * コンストラクタです。
	 */
	public SmartForceLo() throws RemoteException
	{
		// リモートオブジェクトをエクスポートする
		// java.rmi.server.UnicastRemoteObject の
		// 引数なしのコンストラクタを呼び出す
		super();
		// 各共通インターフェース生成
		mobjLearnManagerIF         = new SmartForceLearnManager();
		mobjMenuMakerIF            = new SmartForceMenuMaker();
		mobjSetupIF                = new SmartForceSetup();
	}

	/**
	 * 教材一覧を返します
	 *
	 * @param Hathtable パラメータ
	 * @return Vector 教材一覧
	 */
	public Vector getMaterialList(Hashtable htbParam)
	{
		Vector vecLoMaterialList = new Vector();
		Vector vecRet            = new Vector();
		MessageData objMd        = null;
		MaterialData[] objRet    = null;
		String strCourseID       = "";
		String strCourseTitle    = "";
		String strCourseVersion  = "";
		try
		{
			// DBAccessクラス生成
			mobjDba                = new DBAccess();
			// DBAccessプロパティ設定処理
			SmartForceLoEnv objEnv = new SmartForceLoEnv();
			mobjDba.setDriver(objEnv.getDBDriver());
			mobjDba.setConStr(objEnv.getDBConStr());
			mobjDba.setUser(objEnv.getDBUser());
			mobjDba.setPass(objEnv.getDBPass());
			Vector vecList         = new Vector();
			vecList                = getCourseList();
			objRet                 = new MaterialData[vecList.size()];
			for(int i = 0; i < vecList.size(); i++)
			{
				String[] strList    = new String[vecList.size()];
				strList             = (String[])vecList.get(i);
				strCourseID         = getItem(strList, 0);			// 教材ID取得
				strCourseVersion    = getItem(strList, 1);			// 教材バージョン
				strCourseTitle      = getItem(strList, 2);			// 教材名
				MaterialData objMat = new MaterialData();
				objMat.setMaterialID(strCourseID);
				objMat.setVersion(strCourseVersion);
				objMat.setTitle(strCourseTitle);
				objRet[i]           = objMat;
			}
			mobjDba.commit();
		}
		catch(LOException le)
		{
			try
			{
				if(mobjDba != null)
				{
					mobjDba.rollback();
				}
			}
			catch(Exception e)
			{
				DebugLog.write(this.getClass(), e.getMessage(), DebugLog.HIGHT);
			}
			DebugLog.write(this.getClass(), le.getMessage(), DebugLog.HIGHT);
			objMd = createSystemErrMessage(le.getMessage());
		}
		catch(Exception e)
		{
			try
			{
				if(mobjDba != null)
				{
					mobjDba.rollback();
				}
			}
			catch(Exception ne)
			{
				DebugLog.write(this.getClass(), ne.getMessage(), DebugLog.HIGHT);
			}
			DebugLog.write(this.getClass(), e.getMessage(), DebugLog.HIGHT);
			objMd = createSystemErrMessage(e.getMessage());
		}
		vecRet.add(objMd);
		vecRet.add(objRet);
		return vecRet;
	}

	/**
	 * 教材情報レコードリスト取得処理
	 * <PRE>
	 * 処理内容：教材情報テーブルの内容を取得する。
	 *           教材IDから教材情報を取得する。
	 * </PRE>
	 * @param String 教材ID
	 * @return Vector 教材情報データリスト
	 **/
	private Vector getCourseList()
			throws LOException
	{
		// 戻り値初期化
		Vector vecRet       = new Vector();

		try
		{
			// Select, Update, Insert, Deleteを設定
			mobjDba.setCommand(DBAccess.CMD_SELECT);
			// 項目名("*"等)を設定
			mobjDba.setItem(DBAccess.ITEM_ALL);
			// テーブル名を設定
			mobjDba.setTableName("course_info");
			// Execute実行
			vecRet = mobjDba.execute();
		}
		catch(Exception ex)
		{
			throw new LOException("教材情報テーブルからデータ取得失敗");
		}
		return vecRet;
	}

	/**
	 * 指定項目値取得処理
	 * <PRE>
	 * 処理内容：1レコードから指定項目を取得する。
	 * </PRE>
	 *
	 * @param String[] 1レコード
	 * @return String 指定項目値
	 **/
	private String getItem(String[] strList, int intIndex)
	{
		String strRet = "";
		int i         = 0;
		for(i = 0; i < strList.length; i++)
		{
			if(i == intIndex)
			{
				strRet = strList[intIndex];
			}
		}
		return strRet;
	}

	/**
	 * メソッドリストを返します
	 * @param htbParam パラメータ
	 * @return Vector メッセージデータとメソッドリスト
	 */
	public Vector getMethodList(Hashtable htbParam)
	{
		// @pending ここに処理を記述します
		Vector vecRet     = new Vector();
		Object objRet     = null;
		MessageData objMd = null;
		vecRet.add(objMd);
		vecRet.add(objRet);
		return vecRet;
	}

	/**
	 * デフォルトメニューURLを返します
	 * @param htbParam パラメータ
	 * @return Vector メッセージデータとデフォルトメニュー情報
	 */
	public Vector getDefaultMenu(Hashtable htbParam)
	{
		// @pending ここに処理を記述します
		Vector vecRet     = new Vector();
		Object objRet     = null;
		MessageData objMd = null;
		vecRet.add(objMd);
		vecRet.add(objRet);
		return vecRet;
	}

	/**
	 * 各Loに登録されているメソッドを起動します
	 * @param strMehodName 起動するメソッド名
	 * @param objParams 起動するメソッドのパラメータ
	 * @return Vector メッセージデータと実行結果
	 */
	public Vector execute(String strMethodName, Hashtable htbParams)
	{
		Vector vecRet     = new Vector();
		MessageData objMd = null;
		Object objRet     = null;
		vecRet.add(objMd);
		vecRet.add(objRet);
		return vecRet;
	}

	/**
	 * データ取得処理
	 *
	 * @param Hashtable パラメータリスト
	 * @return Vector メッセージデータと実行結果データ
	 */
	public Vector getData(Hashtable htbParam)
	{
		Vector vecRet     = new Vector();
		MessageData objMd = null;
		Object objRet     = null;
		try
		{
			DebugLog.write(this.getClass(), "getData()", DebugLog.ROW);
			SmartForceLoDataAccess objDataAccess = new SmartForceLoDataAccess();
			objRet = objDataAccess.getData(htbParam);
		}
		catch(LOException le)
		{
			// メッセージデータオブジェクトが取得できない場合は
			// システムエラーメッセージオブジェクトを生成
			objMd = createSystemErrMessage(le.getMessage());
		}
		vecRet.add(objMd);
		vecRet.add(objRet);
		return vecRet;
	}

	/**
	 * 個別ログの取得を行います
	 * <PRE>
	 *   LoIDリストから教材IDリストを取得する。
	 *   SmartForce個別ログレコードリストを取得する。
	 * </PRE>
	 * @param htbParam パラメータ
	 * @return Vector メッセージデータと個別ログレコードリスト
	 */
	public Vector getIndividualLog( Hashtable htbParam )
	{
		Vector vecRet     = new Vector();
		MessageData objMd = null;
		try
		{
			// LoIDリストから教材IDリストを取得する
			setSmartForceLoData(htbParam);

			String[] strUserIDList     = (String[])htbParam.get(USER_LIST);		// ユーザIDリストを取得
			String[] strMaterialIDList = (String[])htbParam.get(MAT_LIST);		// 教材IDリストを取得

			// SmartForceテーブルから指定されたUserIDとLOIDでログを取得
			SmartForceLoILogControl objSlc = new SmartForceLoILogControl();
			CourseUnitLogRecord[] objCurList = objSlc.convert(strUserIDList,
																strMaterialIDList);
			if(objCurList == null)
			{
				return vecRet;
			}
			
			// 内部ID→学習者名置換処理
			StringBuffer strWhereSQL = new StringBuffer();
			String strStudentWhere   = makeIDWhere(strUserIDList);
			strWhereSQL.append("user_id IN (");
			strWhereSQL.append(strStudentWhere);
			strWhereSQL.append(")");
			String strWhere = strWhereSQL.toString();
			convertUserID(objCurList, strWhere);
			
			vecRet.add(objCurList);
		}
		catch(LOException le)
		{
			// エラーメッセージオブジェクトを生成
			objMd = createSystemErrMessage(le.getMessage());
		}
		vecRet.add(0, objMd);
		return vecRet;
	}

	/**
	 * スマートフォース教材詳細情報を設定します
	 * @param Hashtable パラメータ
	 * @exception LOException Lo独自の例外エラー
	 */
	private void setSmartForceLoData(Hashtable htbParam)
		throws LOException
	{
		// Dataアクセスクラスを使用して、詳細情報を取得する
		SmartForceLoDataAccess objDataAccess = new SmartForceLoDataAccess();

		// コンディションキー作成と設定
		String[] strLoIDList                 = (String[])htbParam.get(LOID_LIST);
		String strConditionKey               = makeConditionKey(strLoIDList);
		htbParam.put("condition_key", strConditionKey);

		// LoIDからLo詳細情報取得
		SmartForceLoData[] objData           = objDataAccess.getData(htbParam);
		String[] strMaterialIDList           = new String[objData.length];
		for(int i = 0; i < objData.length; i++)
		{
			// 必要な項目を設定
			strMaterialIDList[i] = objData[i].getCourseCode();
		}
		// 教材IDリストの設定
		htbParam.put(MAT_LIST, strMaterialIDList);
	}

	/**
	 * 文字列リストからコンディションキーを作成します。
	 * @param String[] 文字列リスト
	 * @return String コンディションキー(Where句)
	 * @exception LOException Lo独自の例外エラー
	 */
	private String makeConditionKey(String[] strList)
		throws LOException
	{
		String strKey       = LOID;
		StringBuffer strBuf = new StringBuffer();
		String strRealLOID = "";
		for(int i = 0; i < strList.length; i++)
		{
			strBuf.append( " WHERE " );
			strBuf.append(strKey);
			strBuf.append("='");
			strBuf.append(StringEscapeUtils.escapeSql(strList[i]));
			strBuf.append("' ");
		}
		DebugLog.write(this.getClass(), "ConditionKey : [" + strBuf.toString() + "]", DebugLog.ROW);
		return(strBuf.toString());
	}

	/**
	 * 内部IDを学習者名に変換します。
	 * @param CourseUnitLogRecord[] 教材ユニットレコードリスト
	 * @param String コンディションキー
	 */
	private void convertUserID(CourseUnitLogRecord[] objCulr, String strConditionKey)
	{
		// 内部IDから学習者レコードを取得する
		Vector vecUserNameList = new Vector();
		try
		{
			vecUserNameList = makeUserNameList(strConditionKey);
		}
		catch(Exception e)
		{
			// ユーザ名が取得できない場合、内部IDで表示する
		}
		for(int i = 0; i < objCulr.length; i++)
		{
			String strUserID = objCulr[i].getUserID();
			for(int j = 0; j < vecUserNameList.size(); j++)
			{
				String[] strUserData = (String[])vecUserNameList.get(j);
				String strTempUserID = strUserData[0];
				if(strUserID != null && strUserID.equals(strTempUserID))
				{
					// ユーザIDをユーザ名に置換
					objCulr[i].setUserID(strUserData[1]);
					break;
				}
			}
		}
	}
	
	/**
	 * IDリストからWhere文を作成する
	 * @param String[] IDリスト
	 * @return String IDWhere句
	 */
	private String makeIDWhere(String[] strIDList)
	{
		String strRet = "";
		StringBuffer strIDWhere = new StringBuffer();
		int intIndex = 0;
		while(intIndex < strIDList.length)
		{
			strIDWhere.append("'");
			strIDWhere.append(StringEscapeUtils.escapeSql(strIDList[intIndex++]));
			strIDWhere.append("'");
			strIDWhere.append(",");
				
		}
		// 最後の","を削除します
		strIDWhere.deleteCharAt(strIDWhere.length() - 1);
		strRet = strIDWhere.toString();
		return strRet;
	}

	/**
	 * ユーザーIDとユーザー名のリストを作成します
	 * @param String ユーザーIDのWhere句
	 * @return Vector ユーザーIDとユーザー名のリスト
	 */
	private Vector makeUserNameList(String strUserConditionKey)
		throws Exception
	{
		// ユーザー名リスト作成
		Vector vecUserNameList = new Vector();
		PeopleClient objPc     = new PeopleClient();
		objPc.setCondition(strUserConditionKey);
		if(!objPc.select())
		{
			// エラー処理
			DebugLog.write(this.getClass(), "学習者名変換失敗", DebugLog.HIGHT);
		}
		else
		{
			while(objPc.next())
			{
				String[] strUserNameList = new String[2];
				strUserNameList[0]       = objPc.getUserID();
				strUserNameList[1]       = objPc.getUserName();
				vecUserNameList.add(strUserNameList);
			}
		}
		return vecUserNameList;
	}

}

