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

//
//	ScormMenuMaker
//	変更履歴
//		2004.02.01	新規作成
//

package jp.co.ntt.lms.lo.scorm;

import java.util.Hashtable;
import java.util.Vector;

import jp.co.ntt.lms.lo.LOException;
import jp.co.ntt.lms.lo.LoPropertyDef;
import jp.co.ntt.lms.lo.MenuMaker;
import jp.co.ntt.lms.xmo.MenuData;
import jp.co.ntt.lms.xmo.util.DebugLog;

/**
 * SCORM LOメニュー作成クラス。
 *
 * @author T.Nishiki
 */
public class ScormMenuMaker implements MenuMaker {

	/**
	 * SCORMLO用メニューを生成します。<br>
	 * @param params パラメータ。<br>
	 * 設定しておくべき値は、参照するメソッドを参考にしてください。
	 * @return メニュー項目情報配列。
	 * @throws LOException 処理中に例外が発生した場合。
	 * @see jp.co.ntt.lms.lo.MenuMaker#makeMenu(java.util.Hashtable)
	 * @see jp.co.ntt.lms.lo.LoEnvironment#getStartLearnServletURL(Hashtable)
	 * @see ScormLoEnv#getLoLogURL(Hashtable)
	 * @see ScormLoEnv#getIndividualLogMenuURL(Hashtable)
	 * @see ScormLoEnv#getInsertMenuURL(Hashtable)
	 * @see ScormLoEnv#getUpdateMenuURL(Hashtable)
	 * @see ScormLoEnv#getDeleteMenuURL(Hashtable)
	 */
	public MenuData[] makeMenu(Hashtable params) throws LOException {

		MenuData[] menuDatum = null;
		try {

			Vector menuDataVector = new Vector();

			// 学習開始メニュー
			if (isAbleToStartLearn(params) == true) {
				menuDataVector.add(makeStartLearnMenu(params));
			}
			if (isAbleToBrowseLog(params) == true) {
				// 学習ログメニュー設定
				menuDataVector.add(makeLoLogMenu(params));
				menuDataVector.add(makeIndividualLogMenu(params));
			}

			// セットアップメニューの組み立て
			String setUp = (String) params.get(LoPropertyDef.SETUP_STATUS);
			if (setUp != null) {
				if (setUp.equals(LoPropertyDef.SETUP_INSERT)) {
					// 登録メニュー設定
					menuDataVector.add(makeInsertMenu(params));
				}
				else if (setUp.equals(LoPropertyDef.SETUP_UPDATE)) {
					// 更新メニュー設定
					menuDataVector.add(makeUpdateMenu(params));
				}
				else if (setUp.equals(LoPropertyDef.SETUP_DELETE)) {
					// 削除メニュー設定
					menuDataVector.add(makeDeleteMenu(params));
				}
			}

			// Vectorをメニューデータ配列型に変換
			menuDatum = new MenuData[menuDataVector.size()];
			menuDataVector.copyInto(menuDatum);

		}
		catch (LOException e) {
			throw e;
		}

		return menuDatum;
	}

	/**
	 * メニュー項目「学習開始」の情報を生成します。
	 * @param params パラメータ。<br>
	 * 以下の値が設定されていることを期待しています。<br>
	 * <table border="1">
	 * 	<tr>
	 * 		<th>キー</th>
	 * 		<th>値</th>
	 * 	</tr>
	 * 	<tr>
	 * 		<td>LoPropertyDef.REAL_LOID</td>
	 * 		<td>学習する教材のRealLOID</td>
	 * 	</tr>
	 * </table><br><br>
	 * @return メニュー項目「学習開始」の情報。
	 * @throws LOException 情報取得中に例外が発生した場合。
	 * @see jp.co.ntt.lms.lo.LoEnvironment#getStartLearnServletURL(Hashtable)
	 */
	private MenuData makeStartLearnMenu(Hashtable params) throws LOException {
		////////////////////////////////////////////////////////////////////////
		// メソッド開始ログ
		DebugLog.write(
			getClass(),
			"HEAD makeStartLearnMenu(" + params + ")",
			DebugLog.ROW);
		////////////////////////////////////////////////////////////////////////
		// パラメータ追加
		// =====================================================================
		// 教材の情報を取得し、パラメータに追加する。
		putLoInfo(params);
		// セッションIDの設定（RealLOIDがセッションID）
		String loID = null;
		loID = (String) params.get(LoPropertyDef.REAL_LOID);
		if (loID != null) {
			params.put(LoPropertyDef.SESSIONID, loID);
		}
		////////////////////////////////////////////////////////////////////////
		// 設定ファイルより、学習開始のURLを取得し、メニュー項目を生成する。
		ScormLoEnv scormEnv = new ScormLoEnv();
		String learnURL = scormEnv.getStartLearnServletURL(params);
		MenuData menuData =
			new MenuData(
				learnURL,
				ScormLoConstant.MENU_LABEL_START_LEARN,
				MenuData.DEFAULT_MENU,
				MenuData.STUDENT_MENU);
		//EDIT START 学習ウィンドウ名指定でOpenするように変更します 2006/3/9 NTT-R MNM 
		//menuData.setTargetWindow(ScormLoConstant.WINDOW_TARGET_BLANK);	// ウィンドウ表示方法を別ウィンドウに設定します。
		menuData.setTargetWindow(ScormLoConstant.WINDOW_TARGET_LEARN);
		// EDIT END 2006/3/9 NTT-R MNM
		////////////////////////////////////////////////////////////////////////
		// メソッド終了ログ
		DebugLog.write(
			getClass(),
			"TAIL makeStartLearnMenu(" + params + ")" + " return " + menuData,
			DebugLog.ROW);
		return menuData;
	}

	/**
	 * メニュー項目「学習ログ」の情報を生成します。
	 * @param params パラメータ。<br>
	 * @return メニュー項目「学習ログ」の情報。
	 * @throws LOException 情報取得中に例外が発生した場合。
	 * @see ScormLoEnv#getLoLogURL(Hashtable)
	 */
	private MenuData makeLoLogMenu(Hashtable params) throws LOException {
		////////////////////////////////////////////////////////////////////////
		// メソッド開始ログ
		DebugLog.write(
			getClass(),
			"HEAD makeLoLogMenu(" + params + ")",
			DebugLog.ROW);
		////////////////////////////////////////////////////////////////////////
		// 設定ファイルより、個別ログのURLを取得し、メニュー項目を生成する。
		ScormLoEnv scormEnv = new ScormLoEnv();
		String logMenuURL = scormEnv.getLoLogURL(params);
		MenuData menuData =
			new MenuData(
				logMenuURL,
				ScormLoConstant.MENU_LABEL_LO_LOG,
				MenuData.DEFAULT_MENU,
				MenuData.ALL_MENU);
		// ウィンドウ表示方法を別ウィンドウに設定します。
		menuData.setTargetWindow(ScormLoConstant.WINDOW_TARGET_BLANK);
		
		////////////////////////////////////////////////////////////////////////
		// メソッド終了ログ
		DebugLog.write(
			getClass(),
			"TAIL makeLoLogMenu(" + params + ")" + " return " + menuData,
			DebugLog.ROW);
		return menuData;
	}

	/**
	 * メニュー項目「個別ログ」の情報を生成します。
	 * @param params パラメータ。<br>
	 * @return メニュー項目「個別ログ」の情報。
	 * @throws LOException 情報取得中に例外が発生した場合。
	 * @see ScormLoEnv#getIndividualLogMenuURL(Hashtable)
	 */
	private MenuData makeIndividualLogMenu(Hashtable params)
		throws LOException {
		// メソッド開始ログ
		DebugLog.write(
			getClass(),
			"HEAD makeIndividualLogMenu(" + params + ")",
			DebugLog.ROW);

		// 設定ファイルより、個別ログのURLを取得し、メニュー項目を生成する。
		ScormLoEnv scormEnv = new ScormLoEnv();
		String logMenuURL = scormEnv.getIndividualLogMenuURL(params);
		MenuData menuData =
			new MenuData(
				logMenuURL,
				ScormLoConstant.MENU_LABEL_INDIVIDUAL_LOG,
				MenuData.DEFAULT_MENU,
				MenuData.ALL_MENU);

		// ウィンドウ表示方法を別ウィンドウに設定します。
		menuData.setTargetWindow(ScormLoConstant.WINDOW_TARGET_BLANK);

		// メソッド終了ログ
		DebugLog.write(
			getClass(),
			"TAIL makeIndividualLogMenu("
				+ params
				+ ")"
				+ " return "
				+ menuData,
			DebugLog.ROW);
		return menuData;
	}

	/**
	 * メニュー項目「LO登録」の情報を生成します。
	 * @param params パラメータ。
	 * @return メニュー項目「LO登録」の情報。
	 * @throws LOException 情報取得中に例外が発生した場合。
	 * @see ScormLoEnv#getInsertMenuURL(Hashtable)
	 */
	private MenuData makeInsertMenu(Hashtable params) throws LOException {
		// メソッド開始ログ
		DebugLog.write(
			getClass(),
			"HEAD makeInsertMenu(" + params + ")",
			DebugLog.ROW);

		// 設定ファイルより、LO更新のURLを取得し、メニュー項目を生成する。
		ScormLoEnv scormEnv = new ScormLoEnv();
		String insertMenuURL = scormEnv.getInsertMenuURL(params);
		MenuData menuData =
			new MenuData(
				insertMenuURL,
				ScormLoConstant.MENU_LABEL_LO_INSERT,
				MenuData.INSERT_MENU,
				MenuData.INSTRUCTOR_MENU);

		// メソッド終了ログ
		DebugLog.write(
			getClass(),
			"TAIL makeInsertMenu(" + params + ")" + " return " + menuData,
			DebugLog.ROW);
		return menuData;
	}

	/**
	 * メニュー項目「LO更新」の情報を生成します。
	 * @param params パラメータ。
	 * @return メニュー項目「LO更新」の情報。
	 * @throws LOException 情報取得中に例外が発生した場合。
	 * @see ScormLoEnv#getUpdateMenuURL(Hashtable)
	 */
	private MenuData makeUpdateMenu(Hashtable params) throws LOException {
		// メソッド開始ログ
		DebugLog.write(
			getClass(),
			"HEAD makeUpdateMenu(" + params + ")",
			DebugLog.ROW);

		// 設定ファイルより、LO更新のURLを取得し、メニュー項目を生成する。
		ScormLoEnv scormEnv = new ScormLoEnv();
		String updateMenuURL = scormEnv.getUpdateMenuURL(params);
		MenuData menuData =
			new MenuData(
				updateMenuURL,
				ScormLoConstant.MENU_LABEL_LO_UPDATE,
				MenuData.UPDATE_MENU,
				MenuData.INSTRUCTOR_MENU);

		// メソッド終了ログ
		DebugLog.write(
			getClass(),
			"TAIL makeUpdateMenu(" + params + ")" + " return " + menuData,
			DebugLog.ROW);
		return menuData;
	}

	/**
	 * メニュー項目「LO削除」の情報を生成します。
	 * @param params パラメータ（未使用）。
	 * @return メニュー項目「LO削除」の情報。
	 * @throws LOException 情報取得中に例外が発生した場合。
	 * @see ScormLoEnv#getDeleteMenuURL(Hashtable)
	 */
	private MenuData makeDeleteMenu(Hashtable params) throws LOException {
		// メソッド開始ログ
		DebugLog.write(
			getClass(),
			"HEAD makeDeleteMenu(" + params + ")",
			DebugLog.ROW);
		// 設定ファイルより、LO削除のURLを取得し、メニュー項目を生成する。
		ScormLoEnv scormEnv = new ScormLoEnv();
		String deleteMenuURL = scormEnv.getDeleteMenuURL(params);
		MenuData menuData =
			new MenuData(
				deleteMenuURL,
				ScormLoConstant.MENU_LABEL_LO_DELETE,
				MenuData.DELETE_MENU,
				MenuData.INSTRUCTOR_MENU);

		// メソッド終了ログ
		DebugLog.write(
			getClass(),
			"TAIL makeDeleteMenu(" + params + ") return " + menuData,
			DebugLog.ROW);
		return menuData;
	}

	/**
	 * SCORM LOの情報を取得します。<br>
	 * @param params パラメータ。<br>
	 * 以下の値が設定されていることを期待しています。<br>
	 * <table border="1">
	 * 	<tr>
	 * 		<th>キー</th>
	 * 		<th>値</th>
	 * 	</tr>
	 * 	<tr>
	 * 		<td>LoPropertyDef.REAL_LOID</td>
	 * 		<td>学習する教材のRealLOID</td>
	 * 	</tr>
	 * </table><br><br>
	 * また、このメソッド呼出後は以下の値が設定されます。<br>
	 * 	<tr>
	 * 		<th>キー</th>
	 * 		<th>値</th>
	 * 	</tr>
	 * 	<tr>
	 * 		<td>LoPropertyDef.MATLID</td>
	 * 		<td>学習する教材の教材ID</td>
	 * 	</tr>
	 * </table><br><br>
	 *
	 * @throws LOException 情報取得中に例外が発生した場合。
	 */
	private void putLoInfo(Hashtable params) throws LOException {
		// メソッド開始ログ
		DebugLog.write(
			getClass(),
			"HEAD putLoInfo(" + params + ")",
			DebugLog.ROW);

		// Real LOIDを取得して、教材IDを取得する。
		String realLOID = (String) params.get(LoPropertyDef.REAL_LOID);
		if (realLOID == null) {
			throw new LOException("RealLOIDを取得できません。");
		}

		Hashtable condition = new Hashtable();
		condition.put(LoPropertyDef.LOID, realLOID);
		ScormLoDataAccess scormLoDataAccess = new ScormLoDataAccess();
		ScormLoData[] objData = scormLoDataAccess.getLoData(condition);
		// 教材IDを設定
		params.put(LoPropertyDef.MATLID, objData[0].getMaterialID());

		// メソッド終了ログ
		DebugLog.write(
			getClass(),
			"TAIL putLoInfo(" + params + ")",
			DebugLog.ROW);
	}

	/**
	 * 学習開始をメニュー項目として表示させるか否か判定します。
	 * @param params パラメータ。<br>
	 * 以下の値を取得して、判定します。値がない（nullである）でも動作します。<br>
	 * <table border="1">
	 * 	<tr>
	 * 		<th>キー</th>
	 * 		<th>値</th>
	 * 	</tr>
	 * 	<tr>
	 * 		<td>LoPropertyDef.LEARN_AUTH</td>
	 * 		<td>ログイン・ユーザの学習権限の有無</td>
	 * 	</tr>
	 * 	<tr>
	 * 		<td>LoPropertyDef.LEARNER_ASSIGN</td>
	 * 		<td>ログイン・ユーザと対象教材との学習アサイン割当有無</td>
	 * 	</tr>
	 * 	<tr>
	 * 		<td>LoPropertyDef.TARGET_ID</td>
	 * 		<td>ログ取得時のターゲットとなるID設定キー</td>
	 * 	</tr>
	 * 	<tr>
	 * 		<td>LoPropertyDef.USER</td>
	 * 		<td>ユーザID</td>
	 * 	</tr>
	 * 	<tr>
	 * 		<td>LoPropertyDef.PRERE_FLG</td>
	 * 		<td>前提条件フラグ</td>
	 * 	</tr>
	 * </table><br>
	 *
	 * @return 学習開始メニューを表示する場合は、true。
	 *          表示させない場合は、false。
	 */
	private boolean isAbleToStartLearn(Hashtable params) {
		////////////////////////////////////////////////////////////////////////
		// メソッド開始ログ
		DebugLog.write(
			getClass(),
			"HEAD isAbleToStartLearn(" + params + ")",
			DebugLog.ROW);
		////////////////////////////////////////////////////////////////////////
		// パラメータを取得
		// =====================================================================
		// 学習権限情報
		String learnAuth = (String) params.get(LoPropertyDef.LEARN_AUTH);
		// 学習アサイン情報
		String learnerAssign =
			(String) params.get(LoPropertyDef.LEARNER_ASSIGN);
		// ログ取得時のターゲットとなるID設定キー(ユーザID)
		String targetID = (String) params.get(LoPropertyDef.TARGET_ID);
		// ユーザID
		String userID = (String) params.get(LoPropertyDef.USER);
		// 前提条件フラグ
		String prereFlg = (String) params.get(LoPropertyDef.PRERE_FLG);
		// =====================================================================
		// ログ出力
		DebugLog.write(
			getClass(),
			"[" + LoPropertyDef.LEARN_AUTH + "]=" + learnAuth,
			DebugLog.MID);
		DebugLog.write(
			getClass(),
			"[" + LoPropertyDef.LEARNER_ASSIGN + "]=" + learnerAssign,
			DebugLog.MID);
		DebugLog.write(
			getClass(),
			"[" + LoPropertyDef.TARGET_ID + "]=" + targetID,
			DebugLog.MID);
		DebugLog.write(
			getClass(),
			"[" + LoPropertyDef.USER + "]=" + userID,
			DebugLog.MID);
		DebugLog.write(
			getClass(),
			"[" + LoPropertyDef.PRERE_FLG + "]=" + prereFlg,
			DebugLog.MID);
		////////////////////////////////////////////////////////////////////////
		// メニュー表示可否確認
		boolean able = false;
		if (learnAuth != null
			&& learnerAssign != null
			&& targetID != null
			&& (userID != null && userID.equals(targetID))
			&& (prereFlg != null && prereFlg.equals("on"))) {
			able = true;
		}
		DebugLog.write(getClass(), "Start Learn is " + able, DebugLog.MID);
		////////////////////////////////////////////////////////////////////////
		// メソッド終了ログ
		DebugLog.write(
			getClass(),
			"TAIL isAbleToStartLearn(" + params + ")" + " return " + able,
			DebugLog.ROW);
		return able;
	}

	/**
	 * 学習ログ参照をメニュー項目として表示させるか否か判定します。
	 * @param params パラメータ。<br>
	 * 以下の値を取得して、判定します。値がない（nullである）でも動作します。<br>
	 * <table border="1">
	 * 	<tr>
	 * 		<th>キー</th>
	 * 		<th>値</th>
	 * 	</tr>
	 * 	<tr>
	 * 		<td>LoPropertyDef.MANAGE_ASSIGN</td>
	 * 		<td>ログイン・ユーザと対象教材との管理アサイン割当有無</td>
	 * 	</tr>
	 * 	<tr>
	 * 		<td>LoPropertyDef.LEARNER_ASSIGN</td>
	 * 		<td>ログイン・ユーザと対象教材との学習アサイン割当有無</td>
	 * 	</tr>
	 * 	<tr>
	 * 		<td>LoPropertyDef.LOG_AUTH</td>
	 * 		<td>ログイン・ユーザのログ参照権限の有無</td>
	 * 	</tr>
	 * </table><br>
	 *
	 * @return ログ参照メニューを表示する場合は、true。
	 *           表示させない場合は、false。
	 */
	private boolean isAbleToBrowseLog(Hashtable params) {
		////////////////////////////////////////////////////////////////////////
		// メソッド開始ログ
		DebugLog.write(
			getClass(),
			"HEAD isAbleToBrowseLog(" + params + ")",
			DebugLog.ROW);
		////////////////////////////////////////////////////////////////////////
		// パラメータを取得
		// =====================================================================
		// 管理アサイン情報
		String manageAssign = (String)params.get(LoPropertyDef.MANAGE_ASSIGN);
		// 学習アサイン情報
		String learnerAssign = (String)params.get(LoPropertyDef.LEARNER_ASSIGN);
		// ログ参照権限の取得
		String logAuth = (String)params.get(LoPropertyDef.LOG_AUTH);
		// =====================================================================
		// ログ出力
		DebugLog.write(
			getClass(),
			"[" + LoPropertyDef.MANAGE_ASSIGN + "]=" + manageAssign,
			DebugLog.MID);
		DebugLog.write(
			getClass(),
			"[" + LoPropertyDef.LEARNER_ASSIGN + "]=" + learnerAssign,
			DebugLog.MID);
		DebugLog.write(
			getClass(),
			"[" + LoPropertyDef.LOG_AUTH + "]=" + logAuth,
			DebugLog.MID);

		////////////////////////////////////////////////////////////////////////
		// メニュー表示可否確認
		boolean able = false;
		if (logAuth != null
			&& (manageAssign != null || learnerAssign != null)) {
			able = true;
		}
		DebugLog.write(getClass(), "Browse Log is " + able, DebugLog.MID);
		////////////////////////////////////////////////////////////////////////
		// メソッド終了ログ
		DebugLog.write(
			getClass(),
			"TAIL isAbleToBrowseLog(" + params + ")" + " return " + able,
			DebugLog.ROW);
		return able;
	}
}
