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

//
//	WBT教材　学習終了サーブレット
//			変更履歴
//				2004.01.08	新規作成	二條智文

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

// Java API
import java.io.IOException;
import java.rmi.RemoteException;
import java.util.Hashtable;

import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jp.co.ntt.lms.lo.LOException;
import jp.co.ntt.lms.lo.LearnSession;
import jp.co.ntt.lms.lo.LoConstant;
import jp.co.ntt.lms.lo.LoTopClient;
import jp.co.ntt.lms.lo.WBT.Aicc.AiccLogConverter;
import jp.co.ntt.lms.lo.WBT.Aicc.AiccLogErr;
import jp.co.ntt.lms.lo.WBT.Aicc.AiccParseException;
import jp.co.ntt.lms.xmo.Environment;
import jp.co.ntt.lms.xmo.Assignments.AssignmentsClient;
import jp.co.ntt.lms.xmo.util.DebugLog;

import org.xml.sax.SAXException;

/**
 * WBT教材　学習終了サーブレット
 * @version 0.0.0.1 2004.01.08
 * @author T.Nijou
 */
public class WbtLoEndLearnServlet extends HttpServlet
	implements WbtLoPropertyDef
{

	// 読み込みバイト数
	private static final int BYTE_SIZE = 8*1024;

	// 戻りコード定義
	// 正常時コード
	private static final String RES_OK = "00";
	// リトライ要求(01〜09)　現在使用するのは01のみ
	private static final String RES_RETRY = "01";
	// 異常時コード(10〜)　現在使用するのは10のみ
	private static final String RES_NG = "10";

	// 戻りURL定義
	// 正常時戻りURL
	private static final String WBT_CLOSE_URL = "/view/lo/Wbt/WbtClose.vm";
	// ログ書き込みエラー時戻りURL
	private static final String LOG_ERR_URL = "/view/xmo/Com/ComErr.vm";

	/**
	 * 端末からのＧＥＴ要求を処理するメソッド<br>
	 * @param HttpServletRequest	ＨＴＴＰリクエスト
	 * @param HttpServletResponse	ＨＴＴＰレスポンス
	 * @return void
	 * @exception javax.servlet.ServletException	サーブレット例外
	 * @exception java.io.IOException				入出力例外
	 */
	protected void doGet(HttpServletRequest req, HttpServletResponse res)
		throws ServletException, IOException
	{
		this.doRequest( req, res );
	}
	/**
	 * 端末からのＰＯＳＴ要求を処理するメソッド<br>
	 * @param HttpServletRequest	ＨＴＴＰリクエスト
	 * @param HttpServletResponse	ＨＴＴＰレスポンス
	 * @return void
	 * @exception javax.servlet.ServletException	サーブレット例外
	 * @exception java.io.IOException				入出力例外
	 */
	protected void doPost(HttpServletRequest req, HttpServletResponse res)
		throws ServletException, IOException
	{
		this.doRequest( req, res );
	}

	/**
	 * 端末からの要求を処理するメソッド<br>
	 * @param HttpServletRequest	ＨＴＴＰリクエスト
	 * @param HttpServletResponse	ＨＴＴＰレスポンス
	 * @return void
	 */
	protected void doRequest(HttpServletRequest req, HttpServletResponse res)
		throws ServletException, IOException
	{
		DebugLog.write( this.getClass(), "--------------------------------", DebugLog.ROW);
		DebugLog.write( this.getClass(), "WBT学習終了サーブレット", DebugLog.HIGHT);
		DebugLog.write( this.getClass(), "--------------------------------", DebugLog.ROW);
		ServletOutputStream out = null;
		ServletInputStream in = null;
		StringBuffer sbLog = null;

		try{
			out = res.getOutputStream();
			in = req.getInputStream();

			// ストリームからログを取得します
			sbLog = readLog(in);
		}catch( IOException ie ) {
			// 通信エラー処理
			AiccLogErr.write( ie.getMessage() );
			out.print(getReturnParam(RES_RETRY, LOG_ERR_URL));
			return;
		}

		// AiccLogをURLデコードします
		String strLog = java.net.URLDecoder.decode(new String(sbLog), "Windows-31J" );

		DebugLog.write( this.getClass(),strLog, DebugLog.ROW );

		// ログからユーザIDと教材IDを取得します
		String strUserID = null;
		String strMaterialID = null;
		String strSutdyCount = null;
		try {
			String[] strIDInfo = AiccLogConverter.getIDInfo(strLog);
			strUserID = strIDInfo[0];
			strMaterialID = strIDInfo[1];
			strSutdyCount = strIDInfo[2];
			// 0パディングされてくるため、除去する
			strSutdyCount = String.valueOf(Integer.parseInt(strSutdyCount));
		}
		catch( AiccParseException ae ) {
			// ログパース時のエラー処理
			AiccLogErr.write( ae.getMessage() );
			out.print(getReturnParam(RES_NG, LOG_ERR_URL));
			return;
		}
		catch( SAXException se ) {
			// ログパース時のエラー処理
			AiccLogErr.write( se.getMessage() );
			out.print(getReturnParam(RES_NG, LOG_ERR_URL));
			return;
		}
		catch( IOException ie ) {
			// ログパース時のエラー処理
			AiccLogErr.write( ie.getMessage() );
			out.print(getReturnParam(RES_NG, LOG_ERR_URL));
			return;
		}

		try {
			// WBTLOへログを送信します
			sendWbtLog( strLog, strUserID, strMaterialID, strSutdyCount );
		}
		catch( LOException le ) {
			// ログ送信時のエラー処理
			DebugLog.write( this.getClass(), le, DebugLog.HIGHT );
			out.print(getReturnParam(RES_NG, LOG_ERR_URL));
			return;
		}
		catch( RemoteException re ) {
			// RMIエラー処理
			DebugLog.write( this.getClass(), re, DebugLog.HIGHT );
			out.print(getReturnParam(RES_RETRY, LOG_ERR_URL));
			return;
		}

		out.print(getReturnParam(RES_OK, WBT_CLOSE_URL));
		out.flush();
		return;
	}

	/**
	 * ストリームからログを取得します
	 * @param in ストリーム
	 * @return StringBuffer ログ
	 * @exception IOException 読み取り時に例外
	 */
	private StringBuffer readLog( ServletInputStream in )
		throws IOException
	{
		byte buf[] = new byte[BYTE_SIZE];

		// ログの取得を行います
		StringBuffer sbLog = new StringBuffer();
		int n;
		while((n=in.readLine(buf, 0, buf.length))!= -1) {
			sbLog.append( new String(buf, 0, n) );
		}
		return sbLog;
	}

	/**
	 * WBTLOへログを送信します
	 * @param strLog ログ
	 * @param strUserID ユーザID
	 * @param strMaterialID 教材ID
	 * @param strSutdyCount 学習回数
	 */
	private void sendWbtLog( String strLog, String strUserID, String strMaterialID, String strSutdyCount )
		throws LOException, RemoteException
	{
		DebugLog.write( getClass()
			, "sendWbtLog(\"" + strLog + "\""
				+ ", \"" + strMaterialID + "\""
				+ ", \"" + strSutdyCount + "\")"
			, DebugLog.ROW);
		// パラメータ設定
		Hashtable htbParam = new Hashtable();

		// パラメータにユーザIDを設定
		htbParam.put( USER, strUserID );
		// パラメータに教材IDを設定
		htbParam.put( MATLID, strMaterialID );
		// パラメータにログを設定
		htbParam.put( AICC_LOG, strLog );
		// パラメータに学習回数を設定
		htbParam.put( STUDYCOUNT, strSutdyCount );

		// 学習セッションファイル読込み、LOIDとLOタイプとパスワードを取得する
		// LoTypeは固定
		String strLoType = LO_TYPE_WBT;
		// 学習回数のカウントアップロジックの追加
		try {
			// 学習セッションファイルが存在した場合のみ削除
			// 合わせて学習回数のカウントアップ
			LearnSession objLs = new LearnSession();
			objLs.setUserID(strUserID);
			objLs.setSessionID(strMaterialID);
			objLs.setLoType(strLoType);

			if(LearnSession.isExitSession2(strUserID, strMaterialID)){
				// 学習セッションファイルを読み込み、学習対象ＬＯのLOIDを取得
				objLs.load();
				String strTargetLOID = objLs.getTargetLOID();

				// 学習回数のカウントアップ
				AssignmentsClient assignmentsClient = null;
				assignmentsClient = new AssignmentsClient();

				// カウントアップ用メソッドの引数にLOIDが追加されたことによる修正

				DebugLog.write( getClass()
					, "AssignmentsClient#countupStudyCount("
						+ "\"" + strUserID +"\""
						+ ", \""+ strTargetLOID +"\""
						+ ", \"" + LoConstant.LO_TYPE_WBT +"\")"
					, DebugLog.ROW );
				assignmentsClient.countupStudyCount(
						strUserID, strTargetLOID, LoConstant.LO_TYPE_WBT);
			}

			objLs.delete2();

			// サーバ名称の取得
			Environment objEnv = new Environment();
			String strServerName = objEnv.getLoServerName();
			// Loクライアントのインスタンスを生成します
			LoTopClient objLoCli = new LoTopClient(strServerName, strLoType);

			// Loクライアントの学習開始メソッドを実行します。
			// 　   正否（true：正常、false：異常）
			// パラメータの設定
			objLoCli.setParam( htbParam );
			boolean bLearn = objLoCli.endLearn();
			if ( bLearn == false )
			{
				DebugLog.write( this.getClass(), "学習終了確認 = エラー", DebugLog.ROW );

				// 学習終了処理でエラーが生じた場合は例外を投げる
				throw new LOException(objLoCli.getMessageData());
			}
			else
			{
				DebugLog.write( this.getClass(), "学習終了確認 = OK", DebugLog.ROW );
			}
		}
		catch( LOException le ) {
			throw le;
		}
		catch( RemoteException re ) {
			throw re;
		}
		catch( Exception e ) {
			throw new LOException(e.getMessage());
		}
	}

	/**
	 * Server２へ返すパラメータを生成します
	 * @param strRes エラーコード
	 * @param strURL URL
	 * @return String Server2へ返すパラメータ
	 */
	private String getReturnParam( String strRes, String strURL ) {
		String strFullURL = null;
		try {
			Environment objEnv = new Environment();
			String strSystemUrl = objEnv.getSystemURL();
			strFullURL = strRes + strSystemUrl + strURL;
		}
		catch( Exception ex ) {
			// システムURLを取得できなかった場合はログを残し、URLは空で返す。
			DebugLog.write( this.getClass(), ex, DebugLog.HIGHT );
			strFullURL = RES_NG;
		}

		// ログ出力
		DebugLog.write( this.getClass(), "終了パラメータ:: " + strFullURL, DebugLog.HIGHT );
		return strFullURL;
	}

}