/*
このファイルの中身は、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一覧)ログ取得クラス
// 
//
//	変更履歴
//	2004.01.08 新規作成		ishizaki 
//

package jp.co.ntt.lms.xms.logsumup;

import java.sql.ResultSet;
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.Assignments.AssignmentsClient;
import jp.co.ntt.lms.xmo.util.ChangeEncode;
import jp.co.ntt.lms.xmo.util.XMODate;
import jp.co.ntt.lms.xms.common.util.StringUtil;
import jp.co.ntt.lms.xms.framework.XmsException;
import jp.co.ntt.lms.xms.framework.XmsSystemException;
import jp.co.ntt.lms.xmo.util.DebugLog;

/**
 * 学習状況(ログ一覧)ログ取得クラス
 * 
 * <pre>
 * 	LO一覧では次の形式で取得項目をわけます
 * 
 * グループが選ばれた時は 学習開始日時,最終アクセス日時, 総アクセス回数（回）,累積滞在時間（分）,完了者数(%),合格者数(%)
 * ユーザが選ばれた時は 学習開始日時,最終アクセス日時,総アクセス回数（回）, 累積滞在時間（分）, 最新得点(%), 最高得点(%),完了,合格
 * 
 * 
 * </pre>
 * 
 * @author ishizaki
 * 
 */
public class LoLogLearnMaterialStatusLogic extends LoLogLearnStatusLogic {

	/**
	 * コンストラクタ検索条件を設定する
	 * Constructor for LoLogLearnUserStatusLogic.
	 * @param action 		選択の仕方(グループ/コンテナ,グループ/教材,ユーザ/コンテナ,ユーザ/教材)
	 * @param loId 			LOID	
	 * @param loIdList 		LOIDのリスト(コンテナ指定の場合そのLOIDのリスト
	 * @param userId 		ユーザＩＤ
	 * @param geroupIdList	グループIDのリスト(グループが選ばれた場合グループの下のリスト)
	 * @param userCount 	グループの下にいるユーザの人数
	 * @param loCount  	 	コンテナの下にあるLOの数
	 *
	 * @exception XmsException
	 */
	public LoLogLearnMaterialStatusLogic(
		LoLogLearnStatusParam param,
		int action,
		String realLoId,
		List loIdList,
		String userId,
		List groupIdList,
		int userCount,
		int loCount)
		throws XmsException {
		super(
			param,
			action,
			realLoId,
			loIdList,
			userId,
			groupIdList,
			userCount,
			loCount);
	}

	//---------------------------------- LoLogLearnStatusLogicのabstractメソッド実装メソッドstart ------
	/**
	 * アサイン情報を取得しLoLogResultに反映させる.
	 * 
	 * @param result 学習状況LogResultオブジェクト
	 * @param subordinateFlg 直下配下フラグ
	 * @return アサイン情報反映後のLoLogLearnStatusResult
	 * @see jp.co.ntt.lms.xms.logsumup.LoLogLearnStatusLogic#doAssain(LoLogLearnStatusResult, LoLogLearnStatusParam)
	 */
	public LoLogLearnStatusResult doAssain(
		LoLogLearnStatusResult result,
		String subordinateFlg)
		throws XmsException {
		try {
			//////////////////////////////////////////////////
			//アサイン情報取得用パラメータの作成
			/////////////////////////////////////////////////
			String userId = null; //ユーザＩＤ
			String groupId = null; //グループID
			String loId = getLoId(); //loId
			int type = 0; //直下のLO(1)のLO地震は(0)

			switch (getAction()) {
				//グループ/コンテナまたはグループ/教材
				case LoLogConstant.LOG_SELECT_G_C :
				case LoLogConstant.LOG_SELECT_G_M :
					return result;

				//ユーザ/コンテナ
				case LoLogConstant.LOG_SELECT_U_C :
					userId = getUserId(); //ユーザIDの設定
					groupId = getBelonggroupid(); //所属グループIDを設定
					type = 1;	//直下		
					break;		
				//ユーザ/教材
				case LoLogConstant.LOG_SELECT_U_M :
					userId = getUserId(); //ユーザIDの設定
					groupId = getBelonggroupid(); //所属グループIDを設定
					type = 0;	//教材自身
					break;

				default :
					break;
			}

			//アサイン情報の取得
			AssignmentsClient client = new AssignmentsClient();
			client.getAssignInfo(userId, groupId, loId, type, subordinateFlg);

			result.beforeFirst(); //カーソルを一行へ
			//アサインがあるかないか判断しLogResultに設定する
			int index = 0;
			while (result.next()) {
				String sub_userId = getUserId();
				String strLoID = result.getId();

				if (client.isAssign(sub_userId, strLoID)) {
					//アサイン有り
					result.setAssain(index, "1");
				} else {
					//アサイン無し
					result.setAssain(index, "0");
				}
				index++;
			}
			return result;
		} catch (XmsException e) {
			throw e;
		} catch (Exception e) {
			throw new XmsSystemException(e);
		}

	}


	/****
	 * LO一覧のデータの取得を行う.
	 * 
	 * SQLでIN句が1000を越える場合は引数logの末尾にデータが追加される<BR>
	 * 
	 * 
	 * その他<br>
	 * デバックモード10でSQLの中身をデバック
	 * 
	 * 
	 * @param log ログ結果格納クラス
	 * @param dataAccess データアクセスクラス
	 * @param sql 実行するSQL
	 * @param SQLのIN句が1000を越える場合のgetLog実行が何回目であるか
	 * @see jp.co.ntt.lms.xms.logsumup.LoLogLearnStatusLogic#getLog(DataAccess, String)
	 */
	public LoLogLearnStatusResult getLog(
		LoLogLearnStatusResult log,
		DataAccess dataAccess,
		String sql,
		int sqlCount)
		throws XmsException {

		ResultSet rs = null;
		LoLogCommon_inc common = new LoLogCommon_inc();

		String dateStart = null;				//学習開始日時
		String dateLast = null;				//最終アクセス日時
		String totalAccess = null;				//総アクセス回数
		String totalLearnTime = null;			//累積滞在時間
		String matComplete = null;				//完了LO数
		String matPass = null;					//合格LO数
		String matNewestScore = null;			//最新得点
		String matHighScore = null;			//最高得点
		String completeCondition = null;		//完了
		String passCondition = null;			//合格
		String userCompleteCondition = null;	//完了者数
		String userPass = null;				//合格者数
		String id = null;						//ユーザまたはLOのＩＤ
		String name = null;					//ユーザまたはLOの名称
		String affiliationGroup = null;		//ユーザの所属するグループのパス
		String groupForeinId = null;			//ユーザの所属するグループの外部ＩＤ
		String foreinId = null;				//ユーザまたはＬＯの外部ＩＤ
		String fullScore = null;				//総得点
		String matCompletePercent = null;		//完了LO数パーセント
		String matPassPercent = null;			//合格LO数パーセント
		String userCompleteConditionPercent = null;	//完了者数パーセント
		String userPassPercent = null;			//合格者数パーセント
		String totalLoCount = null;			//総LO数
		String totalUserCount = null;			//総ユーザ数
		String newScorePercent = null;			//最新得点パーセント
		String highScorePercent = null;		//最高得点パーセント
		String assain = null;					//アサイン
		String groupId = null;					//グループID

		try {
			//SQLの中身をデバック
			DebugLog.write(this.getClass(),sql,DebugLog.ROW );

			rs = dataAccess.executeQuery(sql);

			//XMS.iniファイルロードクラスのインスタンス
			Environment objEnv = new Environment();

			int count = 0;
			while (rs.next()) {

				//LOIDの取得
				id = ChangeEncode.setChar(rs.getString("LoID"));
				//Oracleの場合 OR PostgreSQLの場合
				if(objEnv.getDBType().equals( objEnv.DB_ORACLE ) || objEnv.getDBType().equals( objEnv.DB_POSTGRE )){
					// 外部LOID
					foreinId = ChangeEncode.setChar(rs.getString("LoForeignID"));
					// LO名の取得
					name = ChangeEncode.setChar(rs.getString("LoName"));
					// 所属コンテナ名
					affiliationGroup = ChangeEncode.setChar(rs.getString("ContName"));
					// 外部コンテナID
					groupForeinId = ChangeEncode.setChar(rs.getString("ContForeignID"));
				//SQLServerの場合
				}else if(objEnv.getDBType().equals( objEnv.DB_SQLSERVER )){
					// 外部LOID
					foreinId = common.charEncode(rs.getString("LoForeignID"));
					// LO名の取得
					name = common.charEncode(rs.getString("LoName"));
					// 所属コンテナ名
					affiliationGroup = common.charEncode(rs.getString("ContName"));
					// 外部コンテナID
					groupForeinId =	common.charEncode(rs.getString("ContForeignID"));
				}

				//学習開始日
				dateStart = XMODate.parseTime(rs.getTimestamp("StartDate"));
				//最終アクセス日時
				dateLast = XMODate.parseTime(rs.getTimestamp("LastDate"));
				//最終アクセス回数
				totalAccess = ChangeEncode.setChar(rs.getString("AccessCount"));
				//累積滞在時間
				totalLearnTime =
					ChangeEncode.setChar(rs.getString("LearnTime"));

				//完了者数
				userCompleteCondition =
					ChangeEncode.setChar(rs.getString("CompleteCount"));
				//合格者数
				userPass = ChangeEncode.setChar(rs.getString("PassCount"));

				// 完了者数パーセント
				userCompleteConditionPercent =
					String.valueOf(rs.getLong("CompleteCountRate"));
				//合格者数パーセント
				userPassPercent = String.valueOf(rs.getLong("PassCountRate"));

				// 最新得点
				matNewestScore =
					ChangeEncode.setChar(
						String.valueOf(rs.getLong("ExecisePoint")));
				//最高得点
				matHighScore =
					ChangeEncode.setChar(
						String.valueOf(rs.getLong("HighScore")));

				//最新得点パーセント
				newScorePercent =
					String.valueOf(rs.getLong("ExecisePointRate"));
				//最高得点パーセント
				highScorePercent = String.valueOf(rs.getLong("HighScoreRate"));

				//総得点
				fullScore =
					ChangeEncode.setChar(
						String.valueOf(rs.getLong("FullScore")));

				//完了
				completeCondition =
					ChangeEncode.setChar(rs.getString("IsComplete"));

				//合格
				passCondition = ChangeEncode.setChar(rs.getString("IsPass"));

				totalUserCount = Integer.toString(userCount);

				int action = getAction();
				// ログデータのマージ集計処理
				if ((action == LoLogConstant.LOG_SELECT_G_C
					|| action == LoLogConstant.LOG_SELECT_G_M)
					&& sqlCount != 0) {
					log.doSumLogResult(
						dateStart,
						dateLast,
						totalAccess,
						totalLearnTime,
						userCompleteCondition,
						userPass,
						count);
				} else {

					//LogResultに値をセット
					log.addLog(
						dateStart,
						dateLast,
						totalAccess,
						totalLearnTime,
						matComplete,
						matPass,
						matNewestScore,
						matHighScore,
						completeCondition,
						passCondition,
						userCompleteCondition,
						userPass,
						id,
						name,
						affiliationGroup,
						groupForeinId,
						foreinId,
						fullScore,
						matCompletePercent,
						matPassPercent,
						userCompleteConditionPercent,
						userPassPercent,
						totalLoCount,
						totalUserCount,
						newScorePercent,
						highScorePercent,
						assain,
						groupId);
				}
				count++;
			}

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

	/**
	 * グループ/コンテナを選択した場合のSQL文を返却する.
	 * 
	 * @param inGroup グループIDのIN句 IN(グループID,グループID,グループID,......)
	 * @param loId    コンテナのloId
	 * @return グループ/コンテナを選択した場合のSQL文
	 * @exception XmsException
	 * @see jp.co.ntt.lms.xms.logsumup.LoLogLearnStatusLogic#getGroupContainerSql(String inGroup,String loId)
	 */
	public String getGroupContainerSql(String inGroup, String loId)
		throws XmsException {
		try {
			//XMS.iniファイルロードクラスのインスタンス
			Environment objEnv = new Environment();
			StringBuffer sql = new StringBuffer();
			
			sql.append(getSelectSql());	//select SQL
			sql.append(" WHERE ");

			//コンテナを指定
			sql.append(" l.ParentID = '" + StringEscapeUtils.escapeSql(loId) + "'");
			sql.append(" ) L ");
		
			// ネストした内側のselect SQL
			// ユーザ選択時は引数として(グループID,ユーザID)となる。
			// 引数の数を合わせたいのであえて第2引数をnullとしている。
			sql.append(getInnerSql(inGroup, null));
			
			//Oracleの場合 OR PostgreSQLの場合
			if(objEnv.getDBType().equals( objEnv.DB_ORACLE ) || objEnv.getDBType().equals( objEnv.DB_POSTGRE )){
				sql.append(" WHERE ");

				sql.append(" ( ");
				//グループIDを指定 IN('GR000001','GR000002',.....)
				sql.append(" p.ParentID ");
				sql.append(inGroup);
				//メニューからではくnullプラス条件に一致
				if (this.isFirst == false && this.isAllDisp()) {
					sql.append(" OR ");
					sql.append(" p.ParentID IS NULL ");
				}

				sql.append(" ) ");

				//コンテナを指定
				sql.append(" AND ");
				sql.append("    l.ParentID = '" + StringEscapeUtils.escapeSql(loId) + "'");
				//GROUP BY
				sql.append(" GROUP BY ");
			//SQLServerの場合
			}else if(objEnv.getDBType().equals( objEnv.DB_SQLSERVER )){
				//コンテナを指定
				sql.append(" AND ");
				sql.append(" l.ParentID = '" + StringEscapeUtils.escapeSql(loId) + "'");
				sql.append(" WHERE ");

				//グループIDを指定 IN('GR000001','GR000002',.....)
				sql.append(" p.ParentID ");
				sql.append(inGroup);

				//コンテナを指定
				sql.append(" AND ");
				sql.append("    l.ParentID = '" + StringEscapeUtils.escapeSql(loId) + "'");
				//GROUP BY
				sql.append(" GROUP BY ALL ");
			}	

			sql.append(
				" l.ParentForeignID,l.ParentID,l.ParentName, l.ChildName, l.ChildForeignID, l.ChildID ");
			
			//コンテナを指定
			sql.append(" HAVING ");
			sql.append("    l.ParentID = '" + StringEscapeUtils.escapeSql(loId) + "'");

			// グルーピング条件を定義する
			sql.append(super.getGroupingSql());
			//メニューからではくnullプラス条件に一致
			if (this.isFirst == false && this.isAllDisp()) {
				sql.append(" OR ");
				sql.append(" MIN(lg.study_start_date) IS NULL ");
			}

			sql.append("	) R ");
			sql.append("ON ");
			sql.append("	L.LoID = R.LoID ");
			sql.append("ORDER BY L.OrderID ");

			return sql.toString();
		} catch (Exception e) {
			throw new XmsSystemException(e);
		}
	}

	/**
	 * グループ/教材を選択した場合のSQL文を取得する.
	 * 
	 * @param inGroup グループIDのIN句 IN(グループID,グループID,グループID,......)
	 * @param loId    教材のloId
	 * @return グループ/コンテナを選択した場合のSQL文
	 * @exception XmsException
	 * @see jp.co.ntt.lms.xms.logsumup.LoLogLearnStatusLogic#getGroupMateriallSql()
	 */
	public String getGroupMateriallSql(String inGroup, String loId)
		throws XmsException {
		try {
			//XMS.iniファイルロードクラスのインスタンス
			Environment objEnv = new Environment();

			StringBuffer sql = new StringBuffer();
			//select SQL
			sql.append(getSelectSql());
			sql.append(" WHERE ");

			//ＬＯ指定
			sql.append(" l.ChildID = '" + StringEscapeUtils.escapeSql(loId) + "'");
			sql.append(" ) L ");

			// ユーザ選択時は引数として(グループID,ユーザID)となる。
			// 引数の数を合わせたいのであえて第2引数をnullとしている。
			sql.append(getInnerSql(inGroup, null));

			//Oracleの場合 OR PostgreSQLの場合
			if(objEnv.getDBType().equals( objEnv.DB_ORACLE ) || objEnv.getDBType().equals( objEnv.DB_POSTGRE )){
				sql.append(" WHERE ");
				sql.append(" ( ");

				//グループIDの作成--------------------------
				sql.append(" p.ParentID ");
				sql.append(inGroup);
				//グループIDの作成ここまで------------------
				//メニューからではくnullプラス条件に一致
				if (this.isFirst == false && this.isAllDisp()) {
					sql.append(" OR ");
					sql.append(" p.ParentID IS NULL ");
				}

				sql.append(" ) ");

				sql.append(" AND ");
				sql.append("    l.ChildID= '" + StringEscapeUtils.escapeSql(loId) + "'");

				sql.append(" GROUP BY ");

				//SQLServerの場合
			}else if(objEnv.getDBType().equals( objEnv.DB_SQLSERVER )){
				sql.append(" AND ");
				sql.append(" l.ChildID = '" + StringEscapeUtils.escapeSql(loId) + "'");

				sql.append(" WHERE ");

				//グループIDの作成--------------------------
				sql.append(" p.ParentID ");
				sql.append(inGroup);
				//グループIDの作成ここまで------------------

				sql.append(" AND ");
				sql.append("    l.ChildID= '" + StringEscapeUtils.escapeSql(loId) + "'");

				sql.append(" GROUP BY ALL ");
			}	

			sql.append(
				" l.ParentForeignID,l.ParentID,l.ParentName, l.ChildName, l.ChildForeignID, l.ChildID ");
			sql.append(" HAVING ");
			sql.append(" l.ChildID = '" + StringEscapeUtils.escapeSql(loId) + "'");
			// グルーピング条件を定義する
			sql.append(super.getGroupingSql());
			if (this.isFirst == false && this.isAllDisp()) {
				sql.append(" OR ");
				sql.append(" MIN(lg.study_start_date) IS NULL ");
			}
			sql.append("	) R ");
			sql.append("ON ");
			sql.append("	L.LoID = R.LoID ");
			sql.append("ORDER BY L.OrderID ");

			return sql.toString();

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

	/**
	 * 
	 * ユーザ/コンテナを選択した場合のSQL文を取得する.
	 * 
	 * @param userId ユーザID
	 * @param loId   コンテナのloId
	 * @param belonggroupid ユーザが所属しているグループID
	 * @return ユーザ/コンテナを選択した場合のSQL文
	 * @exception XmsException
	 * @see jp.co.ntt.lms.xms.logsumup.LoLogLearnStatusLogic#getUserContainerSql()
	 */
	public String getUserContainerSql(String userId, String loId,String belonggroupid)
		throws XmsException {
		try {
			//XMS.iniファイルロードクラスのインスタンス
			Environment objEnv = new Environment();

			StringBuffer sql = new StringBuffer();
			//select SQL
			sql.append(getSelectSql());
			sql.append(" WHERE ");

			//コンテナ指定
			sql.append(" l.ParentID = '" + StringEscapeUtils.escapeSql(loId) + "'");
			sql.append(" ) L ");

			sql.append(getInnerSql(belonggroupid, userId));

			//Oracleの場合 OR PostgreSQLの場合
			if(objEnv.getDBType().equals( objEnv.DB_ORACLE ) || objEnv.getDBType().equals( objEnv.DB_POSTGRE )){
				sql.append(" WHERE ");
				sql.append(" ( ");
				sql.append(" p.ChildID = '" + StringEscapeUtils.escapeSql(userId) + "'");
				// 所属グループ
// 学習者の場合（所属グループIDが送信されてこない場合）条件に含めない
				if ( StringUtil.isNullString(belonggroupid) == false ) {
					sql.append(" AND ");
					sql.append("    p.ParentID = '" + StringEscapeUtils.escapeSql(belonggroupid) + "'");
				}
				//メニューからではくnullプラス条件に一致
				if (this.isFirst == false && this.isAllDisp()) {
					sql.append(" OR ");
					sql.append(" p.ParentID IS NULL ");
				}

				sql.append(" ) ");

				sql.append(" AND ");
				sql.append("    l.ParentID = '" + StringEscapeUtils.escapeSql(loId) + "'");

				sql.append(" GROUP BY ");
				//SQLServerの場合
			}else if(objEnv.getDBType().equals( objEnv.DB_SQLSERVER )){
				sql.append(" WHERE ");

				sql.append(" p.ChildID = '" + StringEscapeUtils.escapeSql(userId) + "'");
				// 所属グループ
// 学習者の場合（所属グループIDが送信されてこない場合）条件に含めない
				if ( StringUtil.isNullString(belonggroupid) == false ) {
					sql.append(" AND ");
					sql.append("    p.ParentID = '" + StringEscapeUtils.escapeSql(belonggroupid) + "'");
				}

				sql.append(" AND ");
				sql.append("    l.ParentID = '" + StringEscapeUtils.escapeSql(loId) + "'");

				sql.append(" GROUP BY ALL ");
			}

			sql.append(" l.ParentForeignID,l.ParentID,l.ParentName, ");
			sql.append(" l.ChildName, l.ChildForeignID, l.ChildID ");
			sql.append(" HAVING ");
			sql.append(" l.ParentID = '" + StringEscapeUtils.escapeSql(loId) + "'");
			// グルーピング条件を定義する
			sql.append(super.getGroupingSql());
			if (this.isFirst == false && this.isAllDisp()) {
				sql.append(" OR ");
				sql.append(" MIN(lg.study_start_date) IS NULL ");
			}
			sql.append("	) R ");
			sql.append("ON ");
			sql.append("	L.LoID = R.LoID ");
			sql.append("ORDER BY L.OrderID ");

			return sql.toString();
		} catch (XmsException e) {
			throw e;
		} catch (Exception e) {
			throw new XmsSystemException(e);
		}
	}

	/**
	 * ユーザ/教材を選択した場合のSQL文を返却する
	 * 
	 * 
	 * @param userId ユーザID
	 * @param loId   教材のloId
	 * @param belonggroupid ユーザが所属しているグループID
	 * @return 教材/コンテナを選択した場合のSQL文
	 * @exception XmsException
	 * 
	 * @see jp.co.ntt.lms.xms.logsumup.LoLogLearnStatusLogic#getUserMateriallSql()
	 */
	public String getUserMateriallSql(String userId, String loId,String belonggroupid)
		throws XmsException {
		try {

			//XMS.iniファイルロードクラスのインスタンス
			Environment objEnv = new Environment();

			StringBuffer sql = new StringBuffer();
			//select SQL
			sql.append(getSelectSql());
			sql.append(" WHERE ");

			//ＬＯ指定
			sql.append(" l.ChildID = '" + StringEscapeUtils.escapeSql(loId) + "'");
			sql.append(" ) L ");

			sql.append(getInnerSql(belonggroupid, userId));

			//Oracleの場合 OR PostgreSQLの場合
			if(objEnv.getDBType().equals( objEnv.DB_ORACLE ) || objEnv.getDBType().equals( objEnv.DB_POSTGRE )){
				sql.append(" WHERE ");
				sql.append(" ( ");
				sql.append(" p.ChildID = '" + StringEscapeUtils.escapeSql(userId) + "'");
				// 所属グループ
// 学習者の場合（所属グループIDが送信されてこない場合）条件に含めない
				if ( StringUtil.isNullString(belonggroupid) == false ) {
					sql.append(" AND ");
					sql.append(" p.ParentID = '" + StringEscapeUtils.escapeSql(belonggroupid) + "'");
				}
				//メニューからではくnullプラス条件に一致
				if (this.isFirst == false && this.isAllDisp()) {
					sql.append(" OR ");
					sql.append(" p.ParentID IS NULL ");
				}
				sql.append(" ) ");
				sql.append(" AND ");
				sql.append("    l.ChildID= '" + StringEscapeUtils.escapeSql(loId) + "'");

				sql.append(" GROUP BY ");
			//SQLServerの場合
			}else if(objEnv.getDBType().equals( objEnv.DB_SQLSERVER )){
				sql.append(" WHERE ");

				sql.append(" p.ChildID = '" + StringEscapeUtils.escapeSql(userId) + "'");
				
				// 所属グループ
				// クライアントから送信されてきたときのみ条件にする
				if (StringUtil.isNullString(belonggroupid) == false) {
					sql.append(" AND p.ParentID = '" + StringEscapeUtils.escapeSql(belonggroupid) + "'");
				}
				
				sql.append(" AND ");
				sql.append("    l.ChildID= '" + StringEscapeUtils.escapeSql(loId) + "'");

				sql.append(" GROUP BY ALL ");
			}
			sql.append(" l.ParentForeignID,l.ParentID,l.ParentName, ");
			sql.append(" l.ChildName, l.ChildForeignID, l.ChildID ");
			sql.append(" HAVING ");
			sql.append(" l.ChildID = '" + StringEscapeUtils.escapeSql(loId) + "'");
			// グルーピング条件を定義する
			sql.append(super.getGroupingSql());
			if (this.isFirst == false && this.isAllDisp()) {
				sql.append(" OR ");
				sql.append(" MIN(lg.study_start_date) IS NULL ");
			}
			sql.append("	) R ");
			sql.append("ON ");
			sql.append("	L.LoID = R.LoID ");
			sql.append("ORDER BY L.OrderID ");

			return sql.toString();
		} catch (XmsException e) {
			throw e;
		} catch (Exception e) {
			throw new XmsSystemException(e);
		}
	}

	//---------------------------------- LoLogLearnStatusLogicのabstractメソッド実装メソッドend ------

	/**
	 * ネストしたSQLの内側のSELECT文を返却する.
	 *
	 * @param groupId グループID
	 *                 基本画面でグループ選択した場合とユーザ選択した場合により形式が異なる。
	 *                 グループ選択時は選択したグループIDまたはそのグループ配下のグループID。
	 *                 ユーザ選択時は選択したユーザの所属するグループID。
	 *                 例.グループ選択時 : IN (GRxxxxxx,･･･) ユーザ選択時 : GRxxxxxx(所属)
	 *                 となる。 
	 * @param userId  ユーザID
	 *                 基本画面でグループ選択した場合とユーザ選択した場合により形式が異なる。
	 *                 グループ選択時はnull。ユーザ選択時は選択したユーザIDとなる。
	 * @return ネストしたSQLの内側のSELECT文
	 * @exception XmsException
	 */
	private String getInnerSql(String groupId, String userId) throws XmsException {
		try {
			StringBuffer sql = new StringBuffer();

			if (super.isFirst) {
				// 全件表示する
				sql.append(" LEFT OUTER JOIN ");
			} else {
				// 全件表示しない
				sql.append(" INNER JOIN ");
			}

			sql.append(" ( ");
			sql.append(" SELECT ");
			sql.append(" l.ChildName AS LoName, "); // LO名 
			sql.append(" l.ChildForeignID AS LoForeignID, ");
			// 外部LOID 
			sql.append(" l.ParentName AS ContName, "); // 所属コンテナ 
			sql.append(" l.ParentForeignID AS ContForeignID, ");
			// 外部コンテナID 
			sql.append(" MIN(lg.study_start_date) AS StartDate, ");
			// 学習開始日時 
			sql.append(" MAX(lg.last_access) AS LastDate, ");
			// 最終アクセス日時 
			sql.append(" SUM(lg.Access_cnt) AS AccessCount, ");
			// 総アクセス回数 
			sql.append(" COUNT(lg.study_end_date) AS CompleteCount, ");
			// 完了LO数 
			sql.append(" COUNT(lg.passday) AS PassCount, ");
			// 累積滞在時間（分） 
			sql.append(" SUM(lg.residanceTime) AS LearnTime, ");
			// 合格LO数 
			sql.append(" MAX(lg.execise_point) AS ExecisePoint, ");
			// 最新得点 
			sql.append(" MAX(lg.highScore) AS HighScore, "); // 最高得点 
			sql.append(" MAX(lg.fullScore) AS FullScore, "); // 満点 
			sql.append(" (CASE WHEN MAX(lg.study_end_date) IS NOT NULL " +
				"THEN '1' ELSE '0' END) AS IsComplete, ");
			// 完了ステータス 
			sql.append(" (CASE WHEN MAX(lg.passday) IS NOT NULL " +
				"THEN '1' ELSE '0' END) AS IsPass, ");
			// 合格ステータス 
			sql.append(" l.ChildID AS LoID, "); // LOID 
			sql.append(" l.ParentID AS ContID "); // コンテナID 
			sql.append(" FROM ");
			sql.append(" v_LoList  l ");
			sql.append(" LEFT OUTER JOIN ");
			sql.append(" LOLog  lg ");
			sql.append(" INNER JOIN ");
			// グループ選択時
			if (userId == null) {
				sql.append(" (select * from v_UserList ");
				sql.append(" where parentid " + groupId + ") p "); 
			// ユーザ選択時
			} else if(userId.equals("PE000000")) {
				sql.append(" (select * from ");
				sql.append(" (select * from v_UserList ");
				sql.append(" union all ");
				sql.append(" select null AS ParentID, null AS ParentName, null AS ParentForeignID, ");
				sql.append(" pl.user_id AS ChildID, pl.user_name AS ChildName, ");
				sql.append(" pl.foreignID AS ChildForeignID, 0 AS sort_no ");
				sql.append(" from People pl ");
				sql.append(" where pl.user_id = 'PE000000') pu ");
				sql.append(" where pu.childid = '" + StringEscapeUtils.escapeSql(userId) + "') p ");
			} else {
				sql.append(" (select * from v_UserList ");
				sql.append(" where parentid = '" + StringEscapeUtils.escapeSql(groupId) + "' and childid = '" + StringEscapeUtils.escapeSql(userId) + "') p "); 
			}
			sql.append(" ON ");
			sql.append(" lg.UserID = p.ChildID ");
			sql.append(" ON ");
			sql.append(" l.RealID = lg.LOID ");

			return sql.toString();
		} catch (Exception e) {
			throw new XmsSystemException(e);
		}
	}

	/**
	 * ネストしたSQL文の外側のSQLを返却する.
	 *
	 * @return ネストしたSQL文
	 * @exception XmsException
	 *
	 */
	private String getSelectSql() throws XmsException {
		try {
			StringBuffer sql = new StringBuffer();
			Environment objEnv=new Environment();

			sql.append(" SELECT ");

			sql.append(" L.LoName AS LoName, "); // LO名
			sql.append(" L.LoForeignID AS LoForeignID, "); // 外部LOID 
			sql.append(" L.ContName AS ContName, "); // 所属コンテナ
			sql.append(" L.ContForeignID AS ContForeignID, "); // 外部コンテナID
			sql.append(" StartDate, "); // 学習開始日時
			sql.append(" LastDate, "); // 最終アクセス日時
			sql.append(" AccessCount, "); // 総アクセス回数
			sql.append(" CompleteCount, "); // 完了者数
			sql.append(" R.CompleteCount * 100 / " + userCount);
			sql.append(" AS CompleteCountRate, "); // 完了者数(%)
			sql.append(" PassCount, "); // 合格者数
			sql.append(" R.PassCount * 100 / " + userCount);
			sql.append(" AS PassCountRate, "); // 合格者数(%)
			sql.append(" LearnTime, "); // 累積滞在時間（分
			sql.append(" ExecisePoint, "); // 最新得点

			//SQLServerの場合 OR Oracleの場合
			if(objEnv.getDBType().equals( objEnv.DB_SQLSERVER ) || objEnv.getDBType().equals( objEnv.DB_ORACLE )){
				sql.append(" CAST(ROUND(R.ExecisePoint * 100 / (CASE WHEN FullScore = 0 THEN NULL ELSE FullScore END),0) as int) AS ExecisePointRate, ");
				// 最新得点（%） 
				sql.append(" HighScore, "); // 最高得点 
				sql.append(" CAST(ROUND(R.HighScore * 100 / (CASE WHEN FullScore = 0 THEN NULL ELSE FullScore END),0) as int) AS HighScoreRate, ");
				// 最高得点(%）
			//PostgreSQLの場合
			}else if(objEnv.getDBType().equals( objEnv.DB_POSTGRE )){
				sql.append(" CAST(ROUND(to_number(R.ExecisePoint * 100 / (CASE WHEN FullScore = 0 THEN NULL ELSE FullScore END),'99999999D9'),0) AS INT) AS ExecisePointRate, ");
				// 最新得点（%） 
				sql.append(" HighScore, "); // 最高得点 
				sql.append(" CAST(ROUND(to_number(R.HighScore * 100 / (CASE WHEN FullScore = 0 THEN NULL ELSE FullScore END),'99999999D9'),0) as int) AS HighScoreRate, ");
				// 最高得点(%）
			}

			sql.append(" FullScore, "); // 満点 
			sql.append(" IsComplete, "); // 完了ステータス 
			sql.append(" IsPass, "); // 合格ステータス 
			sql.append(" L.LoID AS LoID, "); // LOID 
			sql.append(" L.ContID AS ContID "); // コンテナID 
			sql.append(" FROM ");
			sql.append(" ( ");
			sql.append(" SELECT ");
			sql.append(" l.ChildName AS LoName, "); // LO名 
			sql.append(" l.ChildForeignID AS LoForeignID, ");
			// 外部LOID 
			sql.append(" l.ParentName AS ContName, "); // 所属コンテナ 
			sql.append(" l.ParentForeignID AS ContForeignID, ");
			// 外部コンテナID 
			sql.append(" l.ChildID AS LoID, "); // LOID 
			sql.append(" l.ParentID AS ContID, "); // コンテナID 
			sql.append(" l.sort_no AS OrderID "); // 並び順 
			sql.append(" FROM ");
			sql.append(" v_LoList  l ");

			DebugLog.write( this.getClass(), sql.toString(), DebugLog.ROW );
			return sql.toString();

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