/*
このファイルの中身は、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.text.NumberFormat;
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.xms.framework.XmsException;
import jp.co.ntt.lms.xms.framework.XmsSystemException;
import jp.co.ntt.lms.xms.framework.XmsWarningException;
import jp.co.ntt.lms.xms.framework.base.Logic;
import jp.co.ntt.lms.xms.framework.base.LogicResult;

/**
 * 学習状況(共通[ユーザ一覧/LO一覧])ログ取得共通クラス
 * 
 * <pre>
 * ユーザ一覧/LO一覧共通のインターフェースを提供する
 * 
 *  
 * 
 * </pre>
 * 
 * @author ishizaki
 * 
 */
public abstract class LoLogLearnStatusLogic implements Logic {
	/** 検索条件 */
	private LoLogLearnStatusParam reference;
	/** アクション[グループ/コンテナ.グループ/教材.ユーザ/コンテナ.ユーザ/教材 */
	private int action;
	/** LoId */
	private String loId;
	/** LOIDリスト*/
	private List loIdList;
	/** グループリスト */
	private List groupIdList;
	/** ユーザID */
	private String userId;
	/** ユーザが所属しているグループ*/
	private String belonggroupid;

	/** 総ユーザ人数 */
	protected int userCount;
	/** 総LO数 */
	protected int loCount;
	/**メニュー画面からの画面表示であるか */
	protected boolean isFirst;

	/**
	 * コンストラクタ
	 * @param action 		選択の仕方(グループ/コンテナ,グループ/教材,ユーザ/コンテナ,ユーザ/教材)
	 * @param loId 			LOID	
	 * @param loIdList 		LOIDのリスト(コンテナ指定の場合そのLOIDのリスト
	 * @param userId 		ユーザＩＤ
	 * @param geroupIdList	グループIDのリスト(グループが選ばれた場合グループの下のリスト)
	 * @param userCount 	グループの下にいるユーザの人数
	 * @param loCount  	 	コンテナの下にあるLOの数
	 *
	 * @exception XmsException
	 */
	public LoLogLearnStatusLogic(
		LoLogLearnStatusParam param,
		int action,
		String realLoId,
		List loIdList,
		String userId,
		List groupIdList,
		int userCount,
		int loCount)
		throws XmsException {
		try {
			this.reference = param; 			//検索条件
			this.userId = userId;				//ユーザID
			this.groupIdList = groupIdList; 	//グループＩＤリスト
			this.action = action; 				//action
			this.loId = realLoId; 				//realLoId
			this.loIdList = loIdList;			//LOID
			this.userCount = userCount;		//ユーザ人数
			this.loCount = loCount;			//loの数
			this.belonggroupid = reference.getBelonggroupid();	//ユーザの場合ユーザが所属しているグループ

			//メニューからきたかどうか判定
			if(param.getMenu()== null){
				//メニュー画面からきた
				this.isFirst= true;
			}else{
				//メニュー画面からきてない
				this.isFirst= false;
			}
		} catch (Exception e) {
			throw new XmsSystemException(e);
		}
	}

	//---- ログ出力共通インターフェース-------------------------------------------
	/**
	 * ログ集計格納オブジェクトを返却する.
	 *
	 * @param dataAccess データアクセス
	 * @return ログ集計クラス
	 * @exception XmsException
	 * @see jp.co.ntt.lms.xms.framework.base.Logic#doLogic(DataAccess)
	 */
	public LogicResult doLogic(DataAccess dataAccess) throws XmsException {
		try{
			LoLogLearnStatusResult result = new LoLogLearnStatusResult();

			String sql = null;
			
			/////////////////////////////////////////////////////////////////////
			//SQLの取得 各選択の仕方によってSQLを決め、LoLogResultを取得する
			/////////////////////////////////////////////////////////////////////
			//ユーザが選択された場合
			if (groupIdList.size() == 0) {
				if (belonggroupid.length() == 0) {
					GroupAndPeopleClient objGandP = new GroupAndPeopleClient();
					// 子IDを元に親IDを取得する
					objGandP.setWhereChildID(userId);
					// 検索処理
					if( !objGandP.select() ) {
						throw new XmsSystemException(objGandP.getMessage());
					}

					// 検索がうまくいったら検索結果から親IDを取得する
					// グループは親をひとつしか持たないため、ループは一回
					if( objGandP.next() ) {
						this.belonggroupid = objGandP.getParentID();
					}					
				}

				switch (action) {
					//ユーザ/コンテナ
					case LoLogConstant.LOG_SELECT_U_C :
						//コンテナの下にLOがなにもなかったら
						if (this.loIdList == null || this.loIdList.size() == 0) {
							//検索結果はありません
							throw new XmsWarningException("logsumup.w.search.notfound");
						}
						sql = getUserContainerSql(userId, loId, belonggroupid);
						break;

					//ユーザ/教材
					case LoLogConstant.LOG_SELECT_U_M :
						sql = getUserMateriallSql(userId, loId, belonggroupid);
						break;

					default :
						break;
				}
				//LoLogResutlの取得
				result = getLog(result, dataAccess, sql, 0);

			//グループ選択された場合
			} else {
				//グループの下に人がいなかったら
				if (this.userCount == 0) {
					//検索結果はありません
					throw new XmsWarningException("logsumup.w.search.notfound");
				}

				// グループの数からSQLのIN句となる文字列が格納されたリストを取得
				// リストのサイズ分のSQLが発行される
				//IN句は1000件までなので1000件対応
				LoLogCommon_inc common = new LoLogCommon_inc();
				List inGroupList = common.getGroupInSql(groupIdList);

				for (int i = 0; i < inGroupList.size(); i++) {
					//SQLの取得
					switch (action) {
						//グループ/コンテナ
						case LoLogConstant.LOG_SELECT_G_C :
							//コンテナの下にLOがなにもなかったら
							if (this.loIdList == null
								|| this.loIdList.size() == 0) {
								//検索結果はありません
								throw new XmsWarningException("logsumup.w.search.notfound");
							}
							sql = getGroupContainerSql((String) inGroupList.get(i),loId);
							break;
							//グループ/教材
						case LoLogConstant.LOG_SELECT_G_M :
							sql = getGroupMateriallSql((String) inGroupList.get(i),loId);
							break;

						default :
							break;
					}
					//LoLogResutlの取得
					result = getLog(result, dataAccess, sql, i);
				}
			}
			// 検索結果がない場合検索結果はありません
			if ( result.size() == 0 ) {
				throw new XmsWarningException("logsumup.w.search.notfound");	
			}
			//アサイン情報を反映させLoLogResultを返却
			return doAssain(result,reference.getSubordinateFlg());

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

	//---------------- 以下派生クラスで実装 start--------------------------------------------------------//
	/**
	 * アサイン情報を取得しLoLogResultに反映させる.
	 * 
	 * @param result 学習状況LogResultオブジェクト
	 * @param subordinateFlg 直下配下フラグ
	 * @return アサイン情報反映後のLoLogLearnStatusResult
	 */
	public abstract LoLogLearnStatusResult doAssain(LoLogLearnStatusResult result,String subordinateFlg)throws XmsException;


	/****
	 * ログデータの取得を行う
	 * 
	 * @param log ログ結果格納クラス
	 * @param dataAccess データアクセスクラス
	 * @param sql 実行するSQL
	 * @param SQLのIN句が1000を越える場合のgetLog実行が何回目であるか
	 */
	public abstract LoLogLearnStatusResult getLog(
		LoLogLearnStatusResult result,
		DataAccess dataAccess,
		String sql,
		int sqlCount)
		throws XmsException;

	/***
	 * グループ/コンテナを選択した場合のSQL文を返却する.
	 * 
	 * @param inGroup グループIDのIN句 IN(グループID,グループID,グループID,......)
	 * @param loId    コンテナのloId
	 * @return グループ/コンテナを選択した場合のSQL文
	 * @exception XmsException
	 */
	public abstract String getGroupContainerSql(String inGroupId, String loId)
		throws XmsException;

	/**
	 * グループ/教材を選択した場合の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 abstract String getGroupMateriallSql(String inGroupId, String loId)
		throws XmsException;

	/**
	 * 
	 * ユーザ/コンテナを選択した場合のSQL文を取得する.
	 * 
	 * @param userId ユーザID
	 * @param loId   コンテナのloId
	 * @param belonggroupid ユーザが所属しているグループID
	 * @return ユーザ/コンテナを選択した場合のSQL文
	 * @exception XmsException
	 */
	public abstract String getUserContainerSql(String userId, String loId,String belonggroupid)
		throws XmsException;

	/**
	 * ユーザ/教材を選択した場合のSQL文を返却する
	 * 
	 * 
	 * @param userId ユーザID
	 * @param loId   教材のloId
	 * @param belonggroupid ユーザが所属しているグループID
	 * @return 教材/コンテナを選択した場合のSQL文
	 * @exception XmsException
	 */
	public abstract String getUserMateriallSql(String userId, String loId,String belonggroupid)
		throws XmsException;
	//---------------- 以下派生クラスで実装 end--------------------------------------------------------//

	/**
	 * グルーピング条件指定（検索条件に設定されたSQL条件文を取得する).
	 * 
	 * <pre>
	 * 学習開始日 以降以前
	 * 最終アクセス日時 以降以前
	 * 総アクセス回数 以上以下
	 * 累積滞在時間（分）以上以下
	 * 完了LO数(%) 以上以下
	 * 合格LO数(%) 以上以下
	 * 最新得点(%) 以上以下
	 * 最高得点(%) 以上以下
	 * 完了者数(%) 以上以下
	 * 合格者数(%) 以上以下
	 * 完了
	 * 合格
	 * </pre>
	 * 
	 * @return グルーピング条件指定（検索条件に設定されたSQL条件文を取得する)
	 * @exception XmsException
	 */
	public String getGroupingSql() throws XmsException {
		StringBuffer sql = new StringBuffer();
		ArrayList list = new ArrayList();


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

			//学習開始日(date_start)
			{
				String condition = reference.getDateStartCondition();
				String value = reference.getDateStart();
				//条件が設定されている
				if (value != null && !value.equals("")) {
					StringBuffer buffer = new StringBuffer();

					//Oracleの場合 OR PostgreSQLの場合
					if(objEnv.getDBType().equals( objEnv.DB_ORACLE ) || objEnv.getDBType().equals( objEnv.DB_POSTGRE )){
						buffer.append(" MIN(lg.study_start_date) between ");
						buffer.append(getDateMinForOracle(value, condition));
						buffer.append(" AND ");
						buffer.append(getDateMaxForOracle(value, condition));
					//SQLServerの場合
					} else if(objEnv.getDBType().equals( objEnv.DB_SQLSERVER )) {
						buffer.append(" MIN(lg.study_start_date) between '");
						buffer.append(getDateMin(value, condition));
						buffer.append("' AND '");
						buffer.append(getDateMax(value, condition));
						buffer.append("'");
					}
					list.add(buffer.toString());

				}
			}
			//最終アクセス日時(date_last)
			{
				String condition = reference.getDateLastCondition();
				//select以上/以下
				String value = reference.getDateLast(); 
				//条件が設定されている
				if (value != null && !value.equals("")) {
					StringBuffer buffer = new StringBuffer();
					//Oracleの場合 OR PostgreSQLの場合
					if(objEnv.getDBType().equals( objEnv.DB_ORACLE ) || objEnv.getDBType().equals( objEnv.DB_POSTGRE )){
						buffer.append(" MAX(lg.last_access) between ");
						buffer.append(getDateMinForOracle(value, condition));
						buffer.append(" AND ");
						buffer.append(getDateMaxForOracle(value, condition));
					//SQLSERVER
					} else if(objEnv.getDBType().equals( objEnv.DB_SQLSERVER )) {
						buffer.append(" MAX(lg.last_access) between '");
						buffer.append(getDateMin(value, condition));
						buffer.append("' AND '");
						buffer.append(getDateMax(value, condition));
						//最終アクセス日時 以降 〜 以前
						buffer.append("'");
					}
					list.add(buffer.toString());

				}
			}

			//総アクセス回数(total_access)
			{
				String condition = reference.getTotalAccessCondition();
				//select以上/以下
				String value = reference.getTotalAccess(); //
				//条件が設定されている
				if (value != null && !value.equals("")) {
					StringBuffer buffer = new StringBuffer();
					buffer.append(" SUM(lg.Access_cnt) >= ");
					buffer.append(getCountMin(value, condition));
					buffer.append(" AND SUM(lg.Access_cnt) <= ");
					buffer.append(getCountMax(value, condition));
					list.add(buffer.toString());

				}
			}

			//累積滞在時間(total_learn_time)					
			{
				String condition = reference.getTotalLearnTimeCondition();
				//select以上/以下
				String value = reference.getTotalLearnTime(); //
				//条件が設定されている
				if (value != null && !value.equals("")) {
					StringBuffer buffer = new StringBuffer();
					buffer.append(" SUM(lg.residanceTime) >= ");
					buffer.append(getMSMin(value, condition));
					buffer.append("  AND SUM(lg.residanceTime) <= ");
					buffer.append(getMSMax(value, condition));
					//累積滞在時間 以上 〜 以下
					list.add(buffer.toString());
				}
			}
			
			//完了LO数(mat_complete)
			{
				String condition = reference.getMatCompleteCondition();
				//select以上/以下
				String value = reference.getMatComplete(); //
				//条件が設定されている
				if (value != null && !value.equals("")) {
					StringBuffer buffer = new StringBuffer();

					//Oracleの場合 OR PostgreSQLの場合
					if(objEnv.getDBType().equals( objEnv.DB_ORACLE ) || objEnv.getDBType().equals( objEnv.DB_POSTGRE )){
						buffer.append(" ROUND((COUNT(DISTINCT(CASE WHEN lg.study_end_date IS NOT NULL THEN '1' || l.ChildID END)) * 100 / ");				
					//SQLServerの場合
					} else if(objEnv.getDBType().equals( objEnv.DB_SQLSERVER )) {
						buffer.append(" ROUND((COUNT(DISTINCT(CASE WHEN lg.study_end_date IS NOT NULL THEN '1' + l.ChildID END)) * 100 / ");
					}
					buffer.append(loCount);
					buffer.append(" ),0) >= ");
					buffer.append(getPercentMin(value, condition));
					buffer.append(" AND ");

					//Oracleの場合 OR PostgreSQLの場合
					if(objEnv.getDBType().equals( objEnv.DB_ORACLE ) || objEnv.getDBType().equals( objEnv.DB_POSTGRE )){
						buffer.append(" ROUND((COUNT(DISTINCT(CASE WHEN lg.study_end_date IS NOT NULL THEN '1' || l.ChildID END)) * 100 / ");
					//SQLServerの場合
					} else if(objEnv.getDBType().equals( objEnv.DB_SQLSERVER )) {
						buffer.append(" ROUND((COUNT(DISTINCT(CASE WHEN lg.study_end_date IS NOT NULL THEN '1' + l.ChildID END)) * 100 / ");
					}				
					buffer.append(loCount);
					buffer.append(" ),0) <= ");
					buffer.append(getPercentMax(value, condition));
					list.add(buffer.toString());
				}
			}

			//合格ＬＯ数(mat_pass)					
			{
				String condition = reference.getMatPassCondition();
				//select以上/以下
				String value = reference.getMatPass(); //
				//条件が設定されている
				if (value != null && !value.equals("")) {
					StringBuffer buffer = new StringBuffer();

					//Oracleの場合 OR PostgreSQLの場合
					if(objEnv.getDBType().equals( objEnv.DB_ORACLE ) || objEnv.getDBType().equals( objEnv.DB_POSTGRE )){
						buffer.append(" ROUND((COUNT(DISTINCT(CASE WHEN lg.passday IS NOT NULL THEN '1' || l.ChildID END)) * 100 / ");
					//SQLServerの場合
					} else if(objEnv.getDBType().equals( objEnv.DB_SQLSERVER )) {
						buffer.append(" ROUND((COUNT(DISTINCT(CASE WHEN lg.passday IS NOT NULL THEN '1' + l.ChildID END)) * 100 / ");	
					}			
					buffer.append(loCount);
					buffer.append(" ),0) >= ");
					buffer.append(getPercentMin(value, condition));
					buffer.append(" AND ");

					//Oracleの場合 OR PostgreSQLの場合
					if(objEnv.getDBType().equals( objEnv.DB_ORACLE ) || objEnv.getDBType().equals( objEnv.DB_POSTGRE )){
						buffer.append(" ROUND((COUNT(DISTINCT(CASE WHEN lg.passday IS NOT NULL THEN '1' || l.ChildID END)) * 100 / ");				
					//SQLServerの場合
					} else if(objEnv.getDBType().equals( objEnv.DB_SQLSERVER )) {
						buffer.append(" ROUND((COUNT(DISTINCT(CASE WHEN lg.passday IS NOT NULL THEN '1' + l.ChildID END)) * 100 / ");
					}
					buffer.append(loCount);
					buffer.append("),0) <= ");
					buffer.append(getPercentMax(value, condition));
					list.add(buffer.toString());
				}
			}

			//最新得点(mat_newest_score)					
			{
				String condition = reference.getMatNewestScoreCondition();
				//select以上/以下
				String value = reference.getMatNewestScore(); //
				//条件が設定されている
				if (value != null && !value.equals("")) {
					StringBuffer buffer = new StringBuffer();
					//buffer.append(
					//	" ROUND(MAX(lg.execise_point) * 100/(CASE WHEN MAX(lg.fullScore) = 0 THEN NULL ELSE MAX(lg.fullScore) END),0)  >= ");

					//PostgreSQLの場合
					if(objEnv.getDBType().equals( objEnv.DB_POSTGRE )) {
						buffer.append(" CASE WHEN ROUND(TO_NUMBER(MAX(lg.execise_point) * 100/(CASE WHEN MAX(lg.fullScore) = 0 THEN NULL ELSE MAX(lg.fullScore) END),'99999999D9'),0) IS NULL ");
						buffer.append(" THEN 0 ELSE ROUND(TO_NUMBER(MAX(lg.execise_point) * 100/(CASE WHEN MAX(lg.fullScore) = 0 THEN NULL ELSE MAX(lg.fullScore) END),'99999999D9'),0) END >= ");
						buffer.append(getPercentMin(value, condition));
						buffer.append(" AND ");
						//buffer.append(
						//	"ROUND(MAX(lg.execise_point) * 100/(CASE WHEN MAX(lg.fullScore) = 0 THEN NULL ELSE MAX(lg.fullScore) END),0)  <= ");
						buffer.append(" CASE WHEN ROUND(TO_NUMBER(MAX(lg.execise_point) * 100/(CASE WHEN MAX(lg.fullScore) = 0 THEN NULL ELSE MAX(lg.fullScore) END),'99999999D9'),0) IS NULL ");
						buffer.append(" THEN 0 ELSE ROUND(TO_NUMBER(MAX(lg.execise_point) * 100/(CASE WHEN MAX(lg.fullScore) = 0 THEN NULL ELSE MAX(lg.fullScore) END),'9999999D9'),0) END <= ");
						buffer.append(getPercentMax(value, condition));
					//Oracleの場合 OR SQLServerの場合
					} else if (objEnv.getDBType().equals( objEnv.DB_ORACLE ) || objEnv.getDBType().equals( objEnv.DB_SQLSERVER )) {
						buffer.append(" CASE WHEN ROUND(MAX(lg.execise_point) * 100/(CASE WHEN MAX(lg.fullScore) = 0 THEN NULL ELSE MAX(lg.fullScore) END),0) IS NULL ");
						buffer.append(" THEN 0 ELSE ROUND(MAX(lg.execise_point) * 100/(CASE WHEN MAX(lg.fullScore) = 0 THEN NULL ELSE MAX(lg.fullScore) END),0) END >= ");
						buffer.append(getPercentMin(value, condition));
						buffer.append(" AND ");
						//buffer.append(
						//	"ROUND(MAX(lg.execise_point) * 100/(CASE WHEN MAX(lg.fullScore) = 0 THEN NULL ELSE MAX(lg.fullScore) END),0)  <= ");
						buffer.append(" CASE WHEN ROUND(MAX(lg.execise_point) * 100/(CASE WHEN MAX(lg.fullScore) = 0 THEN NULL ELSE MAX(lg.fullScore) END),0) IS NULL ");
						buffer.append(" THEN 0 ELSE ROUND(MAX(lg.execise_point) * 100/(CASE WHEN MAX(lg.fullScore) = 0 THEN NULL ELSE MAX(lg.fullScore) END),0) END <= ");
						buffer.append(getPercentMax(value, condition));						
					}
					list.add(buffer.toString());
				}
			}
			//最高得点(mat_high_score)					
			{
				String condition = reference.getMatHighScoreCondition();
				//select以上/以下
				String value = reference.getMatHighScore(); //
				//条件が設定されている
				if (value != null && !value.equals("")) {
					StringBuffer buffer = new StringBuffer();

					//PostgreSQLの場合
					if(objEnv.getDBType().equals( objEnv.DB_POSTGRE )) {					
						buffer.append(" CASE WHEN ROUND(TO_NUMBER(MAX(lg.highScore) * 100/(CASE WHEN MAX(lg.fullScore) = 0 THEN NULL ELSE MAX(lg.fullScore) END),'99999999D9'),0) IS NULL ");
						buffer.append(" THEN 0 ELSE ROUND(TO_NUMBER(MAX(lg.highScore) * 100/(CASE WHEN MAX(lg.fullScore) = 0 THEN NULL ELSE MAX(lg.fullScore) END),'99999999D9'),0) END >= ");
						buffer.append(getPercentMin(value, condition));
						buffer.append(" AND ");
						buffer.append(" CASE WHEN ROUND(TO_NUMBER(MAX(lg.highScore) * 100/(CASE WHEN MAX(lg.fullScore) = 0 THEN NULL ELSE MAX(lg.fullScore) END),'99999999D9'),0) IS NULL ");
						buffer.append(" THEN 0 ELSE ROUND(TO_NUMBER(MAX(lg.highScore) * 100/(CASE WHEN MAX(lg.fullScore) = 0 THEN NULL ELSE MAX(lg.fullScore) END),'99999999D9'),0) END <= ");
						buffer.append(getPercentMax(value, condition));
					//Oracleの場合 OR SQLServerの場合
					} else if (objEnv.getDBType().equals( objEnv.DB_ORACLE ) || objEnv.getDBType().equals( objEnv.DB_SQLSERVER )) {
						buffer.append(" CASE WHEN ROUND(MAX(lg.highScore) * 100/(CASE WHEN MAX(lg.fullScore) = 0 THEN NULL ELSE MAX(lg.fullScore) END),0) IS NULL ");
						buffer.append(" THEN 0 ELSE ROUND(MAX(lg.highScore) * 100/(CASE WHEN MAX(lg.fullScore) = 0 THEN NULL ELSE MAX(lg.fullScore) END),0) END >= ");
						buffer.append(getPercentMin(value, condition));
						buffer.append(" AND ");
						buffer.append(" CASE WHEN ROUND(MAX(lg.highScore) * 100/(CASE WHEN MAX(lg.fullScore) = 0 THEN NULL ELSE MAX(lg.fullScore) END),0) IS NULL ");
						buffer.append(" THEN 0 ELSE ROUND(MAX(lg.highScore) * 100/(CASE WHEN MAX(lg.fullScore) = 0 THEN NULL ELSE MAX(lg.fullScore) END),0) END <= ");
						buffer.append(getPercentMax(value, condition));						
					}
					list.add(buffer.toString());
				}
			}

			//完了者数(user_complete_condition)							
			{
				String condition = reference.getUserCompleteCondition();
				//select以上/以下
				String value = reference.getUserComplete(); 
				//条件が設定されている
				if (value != null && !value.equals("")) {
					StringBuffer buffer = new StringBuffer();
					buffer.append(
					" ROUND((COUNT(lg.study_end_date) * 100 / ");
					buffer.append(userCount);
					buffer.append(" ),0) >= ");
					buffer.append(getPercentMin(value, condition));
					buffer.append(" AND ");
					buffer.append(
					" ROUND((COUNT(lg.study_end_date) * 100 / ");
					buffer.append(userCount);
					buffer.append(" ),0) <= ");
					buffer.append(getPercentMax(value, condition));
					list.add(buffer.toString());
				}

			}

			//合格者数(user_pass)							
			{
				String condition = reference.getUserPassCondition();
				//select以上/以下
				String value = reference.getUserPass(); //
				//条件が設定されている
				if (value != null && !value.equals("")) {
					StringBuffer buffer = new StringBuffer();
					buffer.append(
					" ROUND((COUNT(lg.passday) * 100 / ");
					buffer.append(userCount);
					buffer.append(" ),0) >= ");
					buffer.append(getPercentMin(value, condition));
					buffer.append(" AND ");
					buffer.append(
					" ROUND((COUNT(lg.passday) * 100 / ");
					buffer.append(userCount);
					buffer.append(" ),0) <= ");
					buffer.append(getPercentMax(value, condition));
					list.add(buffer.toString());
				}
			}

			//完了(complete_condition)
			String completeCondition = reference.getCompleteCondition();
			//合格(pass_condition)					
			String passCondition = reference.getPassCondition();

			if (completeCondition == null || completeCondition.equals("")) {
				//条件指定なしなのでなにもしない
			} else if (
				completeCondition.equals(
					LoLogConstant.DEF_COMPLETE_PASS_RES_o)) {
				//完了ステータス 「完了」
				StringBuffer buffer = new StringBuffer();
				//Oracleの場合 OR PostgreSQLの場合
				if(objEnv.getDBType().equals( objEnv.DB_ORACLE ) || objEnv.getDBType().equals( objEnv.DB_POSTGRE )){
					buffer.append(" MAX(CASE WHEN lg.study_end_date IS NOT NULL THEN '1' || l.ChildID END) IS NOT NULL  ");
				//SQLServerの場合
				} else if(objEnv.getDBType().equals( objEnv.DB_SQLSERVER )) {
					buffer.append(" MAX(CASE WHEN lg.study_end_date IS NOT NULL THEN '1' + l.ChildID END) IS NOT NULL  ");
				}				
				list.add(buffer.toString());

			} else {
				//完了ステータス 「未完了」	
				StringBuffer buffer = new StringBuffer();

				//Oracleの場合 OR PostgreSQLの場合
				if(objEnv.getDBType().equals( objEnv.DB_ORACLE ) || objEnv.getDBType().equals( objEnv.DB_POSTGRE )){
					buffer.append(" MAX(CASE WHEN lg.study_end_date IS NOT NULL THEN '1' || l.ChildID END) IS NULL  ");
				//SQLServerの場合
				} else if(objEnv.getDBType().equals( objEnv.DB_SQLSERVER )) {
					buffer.append(" MAX(CASE WHEN lg.study_end_date IS NOT NULL THEN '1' + l.ChildID END) IS NULL  ");
				}					
				list.add(buffer.toString());
			}
			if (passCondition == null || passCondition.equals("")) {
				//条件指定なしなのでなにもしない
			} else if (
				passCondition.equals(LoLogConstant.DEF_PASS_PASS_RES_o)) {
				//合格ステータス 「合格」
				StringBuffer buffer = new StringBuffer();

				//Oracleの場合 OR PostgreSQLの場合
				if(objEnv.getDBType().equals( objEnv.DB_ORACLE ) || objEnv.getDBType().equals( objEnv.DB_POSTGRE )){
					buffer.append(" MAX(CASE WHEN lg.passday IS NOT NULL THEN '1' || l.ChildID END) IS NOT NULL  ");
				//SQLServerの場合
				} else if(objEnv.getDBType().equals( objEnv.DB_SQLSERVER )) {
					buffer.append(" MAX(CASE WHEN lg.passday IS NOT NULL THEN '1' + l.ChildID END) IS NOT NULL  ");
				}
				list.add(buffer.toString());

			} else {
				//合格ステータス 「未合格」
				StringBuffer buffer = new StringBuffer();

				//Oracleの場合 OR PostgreSQLの場合
				if(objEnv.getDBType().equals( objEnv.DB_ORACLE ) || objEnv.getDBType().equals( objEnv.DB_POSTGRE )){
					buffer.append(" MAX(CASE WHEN lg.passday IS NOT NULL THEN '1' || l.ChildID END) IS NULL  ");
				//SQLServerの場合
				} else if(objEnv.getDBType().equals( objEnv.DB_SQLSERVER )) {
					buffer.append(" MAX(CASE WHEN lg.passday IS NOT NULL THEN '1' + l.ChildID END) IS NULL  ");
				}
				list.add(buffer.toString());
			}

			//グルーピングSQLの作成
			for(int i=0;i<list.size();i++){
				sql.append(" AND ");						
				sql.append(list.get(i));
			}

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

	}

	/**
	 * LoLogがないレコードと検索条件にあてはまったレコードを表示するしないの判定を行う.
	 * 
	 * @return falseの場合 検索条件にあてはまったレコードのみ表示,true 検索条件にあてはまったレコード+LoLogレコードがないレコードも表示
	 * @exception XmsException
	 * 
	 *
	 */
	public boolean isAllDisp() throws XmsException {
		try {
			//学習開始日(date_start)
			{
				//以前以降にかかわらず条件が設定されていれば表示しない
				String value = reference.getDateStart();
				if (value != null && !value.equals("")) {
					return false;
				}
			}
			//最終アクセス日時(date_last)
			{
				//以前以降にかかわらず条件が設定されていれば表示しない
				String value = reference.getDateLast(); //
				if (value != null && !value.equals("")) {
					return false;
				}

			}

			//総アクセス回数(total_access)
			{
				//指定なしは表示
				//1以上表示しない
				//0以上表示する
				//n以下表示する
				//0を含まず以下（この条件はありえない)			
				String condition = reference.getTotalAccessCondition();
				//select以上/以下
				String value = reference.getTotalAccess(); //
				if (value != null && !value.equals("")) {
					int intval = Integer.parseInt(value);
					if (intval >= 1 && condition.equals("0")) {
						return false;
					}

				}
			}

			//累積滞在時間(total_learn_time)					
			{
				//指定なしは表示
				//1以上表示しない
				//0以上表示する
				//n以下表示する
				//0を含まず以下（この条件はありえない)			
				String condition = reference.getTotalLearnTimeCondition();
				//select以上/以下
				String value = reference.getTotalLearnTime(); //
				if (value != null && !value.equals("")) {
					int intval = Integer.parseInt(value);
					if (intval >= 1 && condition.equals("0")) {
						return false;
					}

				}
			}
			//完了LO数(mat_complete)
			{
				//指定なしは表示
				//1以上表示しない
				//0以上表示する
				//n以下表示する
				//0を含まず以下（この条件はありえない)			

				String condition = reference.getMatCompleteCondition();
				//select以上/以下
				String value = reference.getMatComplete(); //
				if (value != null && !value.equals("")) {
					int intval = Integer.parseInt(value);
					if (intval >= 1 && condition.equals("0")) {
						return false;
					}

				}
			}
			//合格ＬＯ数(mat_pass)					
			{
				//指定なしは表示
				//1以上表示しない
				//0以上表示する
				//n以下表示する
				//0を含まず以下（この条件はありえない)			

				String condition = reference.getMatPassCondition();
				//select以上/以下
				String value = reference.getMatPass(); //
				if (value != null && !value.equals("")) {
					int intval = Integer.parseInt(value);
					if (intval >= 1 && condition.equals("0")) {
						return false;
					}

				}
			}
			//最新得点(mat_newest_score)					
			{
				//指定なしは表示
				//1以上表示しない
				//0以上表示する
				//n以下表示する
				//0を含まず以下（この条件はありえない)			

				String condition = reference.getMatNewestScoreCondition();
				//select以上/以下
				String value = reference.getMatNewestScore(); //
				if (value != null && !value.equals("")) {
					int intval = Integer.parseInt(value);
					if (intval >= 1 && condition.equals("0")) {
						return false;
					}

				}
			}
			//最高得点(mat_high_score)					
			{
				//指定なしは表示
				//1以上表示しない
				//0以上表示する
				//n以下表示する
				//0を含まず以下（この条件はありえない)			

				String condition = reference.getMatHighScoreCondition();
				//select以上/以下
				String value = reference.getMatHighScore(); //
				if (value != null && !value.equals("")) {
					int intval = Integer.parseInt(value);
					if (intval >= 1 && condition.equals("0")) {
						return false;
					}

				}
			}

			//完了者数(user_complete_condition)							
			{
				//指定なしは表示
				//1以上表示しない
				//0以上表示する
				//n以下表示する
				//0を含まず以下（この条件はありえない)			

				String condition = reference.getUserCompleteCondition();
				//select以上/以下
				String value = reference.getUserComplete(); //
				if (value != null && !value.equals("")) {
					int intval = Integer.parseInt(value);
					if (intval >= 1 && condition.equals("0")) {
						return false;
					}

				}
			}

			//合格者数(user_pass)							
			{
				//指定なしは表示
				//1以上表示しない
				//0以上表示する
				//n以下表示する
				//0を含まず以下（この条件はありえない)			

				String condition = reference.getUserPassCondition();
				//select以上/以下
				String value = reference.getUserPass(); //
				if (value != null && !value.equals("")) {
					int intval = Integer.parseInt(value);
					if (intval >= 1 && condition.equals("0")) {
						return false;
					}

				}
			}

			{
				//完了(complete_condition)
				String value = reference.getCompleteCondition();
				//完了指定
				if (value != null && value.equals(LoLogConstant.DEF_COMPLETE_PASS_RES_o)) {
					return false;
				}
			} 

			{
				//合格
				//合格(pass_condition)					
				String value = reference.getPassCondition();
				//完了指定
				if (value != null && value.equals(LoLogConstant.DEF_PASS_PASS_RES_o)) {
					return false;
				}
			} 

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

	/**
	 * 日付最小日付の取得.
	 * 
	 * @param value チェックする文字列
	 * @param condition 以前か以降か[0以降,1以前]
	 * @return valueが設定されていない場合、決められた最小日付を返却
	 * @exception XmsException
	 * 
	 */
	private String getDateMin(String value, String condition)
		throws XmsException {
		try {
			if (value != null
				&& !value.equals("")
				&& condition != null
				&& condition.equals("0")) {
				return value;
			} else {
				return LoLogConstant.DEF_DATE_MIN_o;
			}
		} catch (Exception e) {
			throw new XmsSystemException(e);
		}
	}

	/**
	 * 日付最大日付の取得.
	 *
	 * @param value チェックする文字列
	 * @param condition 以前か以降か[0以降,1以前]
	 * @return valueが設定されていない場合、決められた最大日付を返却
	 * @exception XmsException
	 * 
	 */
	private String getDateMax(String value, String condition)
		throws XmsException {
		try {
			if (value != null
				&& !value.equals("")
				&& condition != null
				&& condition.equals("1")) {
				return value + LoLogConstant.MAX_TIME;
			} else {
				return LoLogConstant.DEF_DATE_MAX_o;
			}
		} catch (Exception e) {
			throw new XmsSystemException(e);
		}
	}

	/**
	 * 日付最小日付の取得(オラクルDB用).
	 * 
	 * @param value チェックする文字列
	 * @param condition 以前か以降か[0以降,1以前]
	 * @return valueが設定されていない場合、決められた最小日付を返却
	 * @exception XmsException
	 * 
	 */
	private String getDateMinForOracle(String value, String condition)
		throws XmsException {
		try {
			if ((value != null
				&& !value.equals("")
				&& condition != null
				&& condition.equals("0")) == false) {

				value = LoLogConstant.DEF_DATE_MIN_o;
			}								

			return changeToDate(value + LoLogConstant.MIN_TIME);			

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

	/**
	 * 日付最大日付の取得(オラクルDB用).
	 *
	 * @param value チェックする文字列
	 * @param condition 以前か以降か[0以降,1以前]
	 * @return valueが設定されていない場合、決められた最大日付を返却
	 * @exception XmsException
	 * 
	 */
	private String getDateMaxForOracle(String value, String condition)
		throws XmsException {
		try {
			if ((value != null
				&& !value.equals("")
				&& condition != null
				&& condition.equals("1")) == false) {
				
				value = LoLogConstant.DEF_DATE_MAX_o;
			}

			return changeToDate(value + LoLogConstant.MAX_TIME);	

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

	/**
	 * 日付フォーマット変換メソッド(オラクルDB用).
	 *
	 * @param value チェックする文字列
	 * @return to_dateを使用し『YYYY/MM/DD HH24:MI:SS』の形で返却
	 * @exception XmsException
	 * 
	 */
	private String changeToDate(String value)
		throws XmsException,Exception {

		StringBuffer sbufResult = new StringBuffer(); 
		
		Environment objEnv = new Environment();
		//PostgreSQLの場合
		if(objEnv.getDBType().equals( objEnv.DB_POSTGRE )){
			sbufResult.append(LoLogConstant.TO_TIMESTAMP + "('" + StringEscapeUtils.escapeSql(value) + "',");
		} else {
			sbufResult.append(LoLogConstant.TO_DATE + "('" + StringEscapeUtils.escapeSql(value) + "',");
		}
		sbufResult.append("'" + LoLogConstant.DEF_DAY_TIME + "')");
	
		return sbufResult.toString();

	}
	/**
	 * 回数最小値の取得.
	 * 
	 * @param value チェックする文字列
	 * @param condition 以下か以上か[0以上,1以下]
	 * @return valueが設定されていない場合、決められた最小値を返却
	 * @exception XmsException
	 */
	private String getCountMin(String value, String condition)
		throws XmsException {
		try {
			if (value != null
				&& !value.equals("")
				&& condition != null
				&& condition.equals("0")) {
				NumberFormat.getInstance().parse(value);
				return value;
			} else {
				return LoLogConstant.DEF_COUNT_MIN_o;
			}
		} catch (Exception e) {
			throw new XmsSystemException(e);
		}
	}

	/**
	 * 回数最大値の取得.
	 * @param value チェックする文字列
	 * @param condition 以下か以上か[0以上,1以下]
	 * @return valueが設定されていない場合、決められた最大値を返却
	 * @exception XmsException
	 */
	private String getCountMax(String value, String condition)
		throws XmsException {
		try {
			if (value != null
				&& !value.equals("")
				&& condition != null
				&& condition.equals("1")) {
				NumberFormat.getInstance().parse(value);
				return value;
			} else {
				return LoLogConstant.DEF_COUNT_MAX_o;
			}
		} catch (Exception e) {
			throw new XmsSystemException(e);
		}
	}

	/**
	 * ミリ最小値の取得.
	 * @param value チェックする文字列
	 * @param condition 以下か以上か[0以上,1以下]
	 * @return valueが設定されていない場合、決められた最小値を返却
	 * @exception XmsException
	 */
	private String getMSMin(String value, String condition)
		throws XmsException {
		try {
			if (value != null
				&& !value.equals("")
				&& condition != null
				&& condition.equals("0")) {
				long min = Long.parseLong(value);
				min = min * 60000;
				return String.valueOf(min);
			} else {
				return LoLogConstant.DEF_MS_MIN_o;
			}
		} catch (Exception e) {
			throw new XmsSystemException(e);
		}
	}

	/**
	 * ミリ最大値の取得.
	 * @param value チェックする文字列
	 * @param condition 以下か以上か[0以上,1以下]
	 * @return valueが設定されていない場合、決められた最大値を返却
	 * @exception XmsException
	 */
	private String getMSMax(String value, String condition)
		throws XmsException {
		try {
			if (value != null
				&& !value.equals("")
				&& condition != null
				&& condition.equals("1")) {
				long min = Long.parseLong(value);
				min = min * 60000;
				return String.valueOf(min);
			} else {
				return LoLogConstant.DEF_MS_MAX_o;
			}
		} catch (Exception e) {
			throw new XmsSystemException(e);
		}
	}

	/**
	 * 数最小値の取得.
	 * @param value チェックする文字列
	 * @param condition 以下か以上か[0以上,1以下]
	 * @return valueが設定されていない場合、決められた最小値を返却
	 * @exception XmsException
	 */
	private String getPercentMin(String value, String condition)
		throws XmsException {
		try {
			if (value != null
				&& !value.equals("")
				&& condition != null
				&& condition.equals("0")) {
				NumberFormat.getInstance().parse(value);
				return value;
			} else {
				return LoLogConstant.DEF_PERCENT_MIN_o;
			}
		} catch (Exception e) {
			throw new XmsSystemException(e);
		}
	}

	/**
	 * 数最大値の取得.
	 * @param value チェックする文字列
	 * @param condition 以下か以上か[0以上,1以下]
	 * @return valueが設定されていない場合、決められた最大値を返却
	 * @exception XmsException
	 */
	private String getPercentMax(String value, String condition)
		throws XmsException {
		try {
			if (value != null
				&& !value.equals("")
				&& condition != null
				&& condition.equals("1")) {
				NumberFormat.getInstance().parse(value);
				return value;
			} else {
				return LoLogConstant.DEF_PERCENT_MAX_o;
			}
		} catch (Exception e) {
			throw new XmsSystemException(e);
		}
	}


	/**
	 * Returns the action.
	 * @return int
	 */
	public int getAction() {
		return action;
	}

	/**
	 * Returns the groupIdList.
	 * @return List
	 */
	public List getGroupIdList() {
		return groupIdList;
	}

	/**
	 * Returns the isFirst.
	 * @return boolean
	 */
	public boolean isFirst() {
		return isFirst;
	}

	/**
	 * Returns the loCount.
	 * @return int
	 */
	public int getLoCount() {
		return loCount;
	}

	/**
	 * Returns the loId.
	 * @return String
	 */
	public String getLoId() {
		return loId;
	}

	/**
	 * Returns the loIdList.
	 * @return List
	 */
	public List getLoIdList() {
		return loIdList;
	}

	/**
	 * Returns the reference.
	 * @return LoLogLearnStatusParam
	 */
	public LoLogLearnStatusParam getReference() {
		return reference;
	}

	/**
	 * Returns the userCount.
	 * @return int
	 */
	public int getUserCount() {
		return userCount;
	}

	/**
	 * Returns the userId.
	 * @return String
	 */
	public String getUserId() {
		return userId;
	}

	/**
	 * Sets the action.
	 * @param action The action to set
	 */
	public void setAction(int action) {
		this.action = action;
	}

	/**
	 * Sets the groupIdList.
	 * @param groupIdList The groupIdList to set
	 */
	public void setGroupIdList(List groupIdList) {
		this.groupIdList = groupIdList;
	}

	/**
	 * Sets the isFirst.
	 * @param isFirst The isFirst to set
	 */
	public void setIsFirst(boolean isFirst) {
		this.isFirst = isFirst;
	}

	/**
	 * Sets the loCount.
	 * @param loCount The loCount to set
	 */
	public void setLoCount(int loCount) {
		this.loCount = loCount;
	}

	/**
	 * Sets the loId.
	 * @param loId The loId to set
	 */
	public void setLoId(String loId) {
		this.loId = loId;
	}

	/**
	 * Sets the loIdList.
	 * @param loIdList The loIdList to set
	 */
	public void setLoIdList(List loIdList) {
		this.loIdList = loIdList;
	}

	/**
	 * Sets the reference.
	 * @param reference The reference to set
	 */
	public void setReference(LoLogLearnStatusParam reference) {
		this.reference = reference;
	}

	/**
	 * Sets the userCount.
	 * @param userCount The userCount to set
	 */
	public void setUserCount(int userCount) {
		this.userCount = userCount;
	}

	/**
	 * Sets the userId.
	 * @param userId The userId to set
	 */
	public void setUserId(String userId) {
		this.userId = userId;
	}

	/**
	 * Returns the belonggroupid.
	 * @return String
	 */
	public String getBelonggroupid() {
		return belonggroupid;
	}

	/**
	 * Sets the belonggroupid.
	 * @param belonggroupid The belonggroupid to set
	 */
	public void setBelonggroupid(String belonggroupid) {
		this.belonggroupid = belonggroupid;
	}

}
