/*
このファイルの中身は、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 新規作成 A.Shimoma
//
package jp.co.ntt.lms.xms.logsumup;

import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.StringEscapeUtils;

import jp.co.ntt.lms.xmo.DataAccess;
import jp.co.ntt.lms.xmo.Environment;
import jp.co.ntt.lms.xmo.GroupAndPeople.GroupAndPeopleClient;
import jp.co.ntt.lms.xmo.util.ChangeEncode;
import jp.co.ntt.lms.xms.framework.XmsException;
import jp.co.ntt.lms.xms.framework.XmsInnerException;
import jp.co.ntt.lms.xms.framework.XmsSystemException;
import jp.co.ntt.lms.xms.framework.base.Logic;
import jp.co.ntt.lms.xms.framework.base.LogicResult;
import jp.co.ntt.lms.xmo.util.DebugLog;

/**
 * ＬＯ別合格状況一覧結果フレーム用ロジック・クラス。<br>
 * 
 * @author shimoma
 */
public class LoLogMaterialPassLogic implements Logic {

	/**
	 * リクエストされたグループID
	 */
	private String groupId;

	/**
	 * リクエストされたLoID
	 */
	private String LoID;

	/**
	 * リクエストされた配下フラグ
	 */
	private String subordinate_flg;

	/**
	 * 集計結果格納クラス
	 */
	LoLogMaterialPassResult result = new LoLogMaterialPassResult();

	/**
	 * 共通データ・クラス
	 */
	LoLogSearchResult searchResult;

	/**
	 * コンストラクタ。<br>
	 */
	public LoLogMaterialPassLogic() {
	}

	/**
	 * コンストラクタ。<br>
	 * 
	 * @param strGroupId       グループID
	 * @param LoID             LOID
	 * @param subordinate_flg  配下フラグ
	 * @exception XmsException
	 */
	public LoLogMaterialPassLogic(
		String strGroupId,
		String strLoID,
		String subordinate_flg)
		throws XmsException {

		// パラメータチェック
		if (strGroupId == null || strLoID == null || subordinate_flg == null) {
			throw new XmsInnerException("parameter is null.");
		}

		this.groupId = strGroupId;
		this.LoID = strLoID;
		this.subordinate_flg = subordinate_flg;

	}

	/**
	 * 集計ロジック・メソッド。<br>
	 * グループ・ＬＯ情報を取得し、その情報を元に<br>、
	 * 直下及び配下の合格状況ログデータを取得し集計します。<br>
	 * 
	 * @param     dataAccess DataAccessオブジェクト
	 * @return    result ログデータ
	 * @exception XmsException
	 * @see        LoLogMaterialPassResult
	 */
	public LogicResult doLogic(DataAccess dataAccess) throws XmsException {

		// パラメータチェック
		if (dataAccess == null) {
			throw new XmsInnerException("parameter is null.");
		}

		// ログ共通用Commonクラスの生成
		LoLogCommon_inc cominc = new LoLogCommon_inc();

		try {

			GroupAndPeopleClient GapClient = new GroupAndPeopleClient();

			List groupIdList = new ArrayList();

			// LoLogResultCommonより共通データを取得する。
			getResultCommonData();

			// 配下フラグのセット。配下フラグがnullであればデフォルトでoff(直下になる)
			// 直下の場合
			if (subordinate_flg.equals("off")) {

				groupIdList.add(groupId);

				// 配下の場合
			} else {
				// groupId配下のグループIDを取得
				// グループが1000以上の場合は複数回ループ

				groupIdList = GapClient.getGroupIdList(groupId, groupIdList);

			}

			// ＳＱＬ発行回数を取得
			int logSqlCount = cominc.getSqlCount(groupIdList);
			// グループ直下・配下、コンテナ・LO指定に関わらず同じメソッドをコールする
			// 最低１度はループする。
			for (int i = 0; i < logSqlCount; i++) {
				// グループ配下のログ集計
				result =
					getPassStatusDBAccess(
						groupIdList,
						LoID,
						result.getRealLoId(),
						dataAccess,
						i);
			}

		} catch (XmsException e) {
			throw e;
		} catch (Exception e) {
			throw new XmsSystemException(e);
		}

		return result;
	}

	/**
	 * 共通データ取得メソッド。<BR>
	 * LoLogResultCommonクラスにて各画面で共通に取得するデータを取得し<BR>
	 * LoLogSearchResultクラスに保持します。
	 * 保持した結果を各業務で使用するResultクラスへ詰め変えます。
	 * 
	 * @exception XmsException
	 */
	private void getResultCommonData() throws XmsException {

		// ログ画面共通データ取得クラスの生成
		LoLogResultCommon resultCommon =
			new LoLogResultCommon(subordinate_flg, groupId, LoID);

		// LoLogSearchResultにグループ・LO情報を設定
		searchResult = resultCommon.getLoLogSearchResult();

		// LoLogSearchResultからLoLogMaterialPassResultへ詰め替え
		// グループIDの設定
		result.setGroupId(searchResult.getGroupOrUserId());
		// グループ名の設定
		result.setGroupName(searchResult.getGroupOrUserName());
		// グループ外部ID
		result.setForeignId(searchResult.getForeignId());
		// LoIdの設定
		result.setLoID(searchResult.getLoID());
		// LO名の設定
		result.setLoName(searchResult.getLoName());
		// LO外部IDの設定
		result.setLoForeignId(searchResult.getLoForeignId());
		// LOタイプの設定
		result.setLoType(searchResult.getLoType());
		// リアルLOIDの設定
		result.setRealLoId(searchResult.getRealLOID());
		// 集計対象となる文言(直下または配下のユーザ)の設定
		result.setCondidateTotalMassage(
			searchResult.getCondidateTotalMassage());
		// LOTYPEがコンテナかＬＯどうかを設定
		result.setContainer(searchResult.isContainer());
		result.setMateriall(searchResult.isMateriall());
		// ユーザ数をセット
		result.setUserCount(searchResult.getUserCount());

	}

	/**
	 * 合格状況取得メソッド。<BR>
	 * 基本画面より選択されたグループ直下・配下及びコンテナ・ＬＯでの<BR>
	 * 合格状況データをデータベースより取得します。
	 * 
	 * @param  lstGroupList 配下全てのグループID
	 * @param  strLoID      LOID
	 * @param  strRealLoId  リアルLOID
	 * @param  dataAccess   DAOオブジェクト
	 * @param  sqlCounter   SQLのカウント数
	 * @return LogicResult  ログデータ
	 * @exception XmsException
	 */
	private LoLogMaterialPassResult getPassStatusDBAccess(
		List lstGroupIdList,
		String strLoID,
		String strRealLoId,
		DataAccess dataAccess,
		int sqlCounter)
		throws XmsException {


		// ログ共通用Commonクラスの生成
		LoLogCommon_inc cominc = new LoLogCommon_inc();

		// ＳＱＬ文を生成するBuffer
		StringBuffer sbSQL = new StringBuffer();
		ResultSet rs = null;
		boolean exceptionFlag = false;

		try {
			//XMS.iniファイルロードクラスのインスタンス
			Environment objEnv = new Environment();
			
			int userCount = Integer.parseInt(result.getUserCount());


			// ループ開始カウント
			int intStart = sqlCounter * 1000;
			// ループ終了カウント
			int intEnd = intStart + 1000;
			// ループ終了カウントよりグループリストサイズの方が小さい場合
			if (lstGroupIdList.size() < intEnd) {
				intEnd = lstGroupIdList.size() - intStart;
			}

			sbSQL.append("SELECT ");
			sbSQL.append("    l.ChildName AS LoName, "); 						// LO名
			sbSQL.append("    l.ChildForeignID AS LoForeignID, "); 				// 外部LOID
			sbSQL.append("    l.ChildID AS LoID, ");  							// LOID
			sbSQL.append("    COUNT(lg.study_start_date) AS StartCount, "); 	// 学習開始数
			sbSQL.append("    COUNT(lg.study_end_date) AS CompleteCount, ");	// 完了数
			sbSQL.append("    COUNT(lg.passday) AS PassCount, ");				// 合格数
			sbSQL.append("    l.Type AS Type, "); 								// LOタイプ
			sbSQL.append("    l.ParentID AS ContID, "); 						// 親コンテナID
			sbSQL.append("    l.sort_no AS OrderID ");							// 並び順
			sbSQL.append("FROM ");
			sbSQL.append("  v_LOList  l ");
			sbSQL.append("    LEFT OUTER JOIN ");
			sbSQL.append(" (SELECT lg1.study_start_date, ");
			sbSQL.append(" lg1.study_end_date, ");
			sbSQL.append(" lg1.passday, ");
			sbSQL.append(" lg1.LOID ");
			sbSQL.append(" FROM ");
			sbSQL.append(" LOLog lg1 ");
			sbSQL.append(" INNER JOIN v_UserList p ");
			sbSQL.append(" ON lg1.UserID = p.ChildID ");
			sbSQL.append(" WHERE ");

			// グループ指定
			sbSQL.append("      p.ParentID IN ");

			// groupIdを ｢,｣ 区切りの文字列にする
			for (int i = intStart; i < intEnd; i++) {
				String tempGroupId = (String) lstGroupIdList.get(i);
				if (i == 0) {
					sbSQL.append("('" + StringEscapeUtils.escapeSql(tempGroupId) + "'");
				} else {
					sbSQL.append(",'" + StringEscapeUtils.escapeSql(tempGroupId) + "'");
				}
			}
			sbSQL.append(")");
			sbSQL.append(") lg ");

			sbSQL.append(" ON lg.LOID = l.RealID ");
			sbSQL.append(" WHERE ");
			if (result.isContainer()) {
				// コンテナ指定時
				sbSQL.append(" l.ParentID = '" + StringEscapeUtils.escapeSql(strLoID) + "'");
			} else {
				// LO指定時
				sbSQL.append(" l.ChildID = '" + StringEscapeUtils.escapeSql(strLoID) + "'");
			}

			//ORACLEの場合 OR POSTGRESQLの場合
			if(objEnv.getDBType().equals( objEnv.DB_ORACLE ) || objEnv.getDBType().equals( objEnv.DB_POSTGRE )){
				sbSQL.append(" GROUP BY ");
			//SQL_SERVERの場合
			} else if(objEnv.getDBType().equals( objEnv.DB_SQLSERVER )) {
				sbSQL.append(" GROUP BY ALL ");
			}

			sbSQL.append("  l.Type, ");
			sbSQL.append("  l.ParentID, ");
			sbSQL.append("  l.ChildName, ");
			sbSQL.append("  l.ChildForeignID, ");
			sbSQL.append("  l.ChildID, ");
			sbSQL.append("  l.sort_no ");
			sbSQL.append("HAVING ");
			if (result.isContainer()) {
				// コンテナ指定時
				sbSQL.append("    l.ParentID = '" + StringEscapeUtils.escapeSql(strLoID) + "'");
			} else {
				// LO指定時
				sbSQL.append("     l.ChildID = '" + StringEscapeUtils.escapeSql(strLoID) + "'");
			}
			sbSQL.append("ORDER BY l.sort_no ");

			DebugLog.write( this.getClass(),sbSQL.toString(), DebugLog.ROW );
			// クエリーの実行
			rs = dataAccess.executeQuery(sbSQL.toString());
			// レコード分ループ
			int rsCount = 0;
			while (rs.next()) {

				// LO名
				String rsLoName = null;

				//ORACLEの場合 OR POSTGRESQLの場合
				if(objEnv.getDBType().equals( objEnv.DB_ORACLE ) || objEnv.getDBType().equals( objEnv.DB_POSTGRE )){
					rsLoName = ChangeEncode.setChar(rs.getString("LoName"));
				//SQL_SERVERの場合
				} else if(objEnv.getDBType().equals( objEnv.DB_SQLSERVER )) {
					rsLoName = cominc.charEncode(rs.getString("LoName"));
				}

				// 未学習
				int rsUnlearn = userCount - rs.getInt("StartCount");
				// 学習開始
				int rsStartStudy = rs.getInt("StartCount");
				// 完了
				int rsComplete = rs.getInt("CompleteCount");
				// 合格
				int rsPass = rs.getInt("PassCount");
				
				// Lo外部ID
				String rsForeignId = null;

				//ORACLEの場合 OR POSTGRESQLの場合
				if(objEnv.getDBType().equals( objEnv.DB_ORACLE ) || objEnv.getDBType().equals( objEnv.DB_POSTGRE )){
					rsForeignId = ChangeEncode.setChar(rs.getString("LoForeignID"));
				//SQL_SERVERの場合
				} else if(objEnv.getDBType().equals( objEnv.DB_SQLSERVER )) {
					rsForeignId = cominc.charEncode(rs.getString("LoForeignID"));
				}

				// SQLのループ１回目の場合
				if (intStart == 0) {
					result.addLog(rsLoName, rsUnlearn, rsStartStudy, rsComplete, rsPass, rsForeignId);

				// SQLのループ２回目以降の場合
				} else {
					// 未学習
					result.unLearnList.set(
						rsCount,
						Integer.toString(
							Integer.parseInt(
								(String) result.unLearnList.get(rsCount))
								+ rsUnlearn));
					// 学習開始
					result.startStudyList.set(
						rsCount,
						Integer.toString(
							Integer.parseInt(
								(String) result.startStudyList.get(rsCount))
								+ rsStartStudy));
					// 完了
					result.completeList.set(
						rsCount,
						Integer.toString(
							Integer.parseInt(
								(String) result.completeList.get(rsCount))
								+ rsComplete));
					// 合格
					result.passList.set(
						rsCount,
						Integer.toString(
							Integer.parseInt((String) result.passList.get(rsCount))
								+ rsPass));
				}

				// 合格状況の各合計を設定
				result.setSum(
					result.getSumUnlearn() + rsUnlearn,
					result.getSumStartStudy() + rsStartStudy,
					result.getSumComplete() + rsComplete,
					result.getSumPass() + rsPass);

				// ループカウンタのカウントアップ
				rsCount++;
			}

		} catch (Exception e) {
			throw new XmsSystemException(e);
		} finally {
			if (rs != null) {
				try {
					rs.close();
				} catch (Exception e) {
					if (exceptionFlag == true) {
						throw new XmsSystemException(e);
					}
				}
				rs = null;
			}
		}

		return result;

	}

}
