/*
このファイルの中身は、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.Calendar;
import java.util.Date;
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.xmo.util.XMODate;
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.XmsWarningException;
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 LoLogMaterialUseLogic implements Logic {

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

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

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

	/**
	 * リクエストされた期間_from
	 */
	private String termFrom;

	/**
	 * リクエストされた期間_to
	 */
	private String termTo;

	/**
	 * リクエストされたcsv用期間_from
	 */
	private String csvTermFrom;

	/**
	 * リクエストされたcsv用期間_to
	 */
	private String csvTermTo;

	/**
	 * リクエストされた期間単位
	 */
	private String termUnit;

	/**
	 * リクエストされたカウント単位
	 */
	private String countUnit;

	/**
	 * ログデータ(列)
	 */
	private long[] logData;

	/**
	 * ログデータ(行)
	 */
	private List logDataList;

	/**
	 * 合計行計算用
	 */
	private long[] totalCol;
	/**
	 * 集計結果格納クラス
	 */
	LoLogMaterialUseResult result = new LoLogMaterialUseResult();

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

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

	/**
	 * コンストラクタ。<br>
	 * 
	 * @param strGroupId グループID
	 * @param strLoID LOID
	 * @param subordinate_flg 配下フラグ
	 * @param termFrom 検索期間_from
	 * @param termTo 検索期間_to
	 * @param termUnit 粒度
	 * @param countUnit カウント対象
	 * @exception XmsException
	 */
	public LoLogMaterialUseLogic(
		String strGroupId,
		String strLoID,
		String subordinate_flg,
		String termFrom,
		String termTo,
		String termUnit,
		String countUnit,
		String csvTermFrom,
		String csvTermTo)
		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;
		this.termFrom = termFrom;
		this.termTo = termTo;
		this.termUnit = termUnit;
		this.countUnit = countUnit;
		this.csvTermFrom = csvTermFrom;
		this.csvTermTo = csvTermTo;

	}

	/**
	 * 集計ロジック・メソッド。<br>
	 * ＤＢアクセスの為の条件を取得しログデータを取得します。<br>
	 * グループ/コンテナ・グループ/ＬＯ、及び、配下・直下検索<br>
	 * により発行するＳＱＬが異なります。
	 * 
	 * @param dataAccess DataAccessオブジェクト
	 * @return result ログデータ
		 * @exception XmsException
	 * @see LoLogMaterialUseResult
	 */
	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 GapClinent = new GroupAndPeopleClient();

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

			// 初期表示時
			if (termFrom == null
				&& termTo == null
				&& termUnit == null
				&& countUnit == null) {

				// 初期表示時のパラメータ設定
				initParam();

			} else {
				// 検索ボタン押下時
				// 検索期間 from
				result.setFromDate(termFrom);
				// 検索期間 to
				result.setToDate(termTo);
				// csv用検索期間 from
				result.setCsvFromDate(csvTermFrom);
				// csv用検索期間 to
				result.setCsvToDate(csvTermTo);

			}

			// ＤＢ向けの検索キーワードに変更
			// target   各粒度を示すフィールド値 1,2,5
			// term     ＤＢ向け検索キーワード   year,month,week,date
			// termUnit 年,月,週,日
			String term;
			String countTarget;
			// 検索条件より列数を計算
			int target = 0;
			if ((termUnit != null) && (termUnit.equals("TERM_YEAR") == true)) {
				// 年の場合
				target = Calendar.YEAR;
				term = LoLogConstant.DEF_DBTERM_YEAR;
				result.setTermUnit(LoLogConstant.STR_TERM_YEAR_o);
			} else if (
				(termUnit != null)
					&& (termUnit.equals("TERM_MONTH") == true)) {
				// 月の場合
				target = Calendar.MONTH;
				term = LoLogConstant.DEF_DBTERM_MONTH;
				result.setTermUnit(LoLogConstant.STR_TERM_MONTH_o);
			} else if (
				(termUnit != null) && (termUnit.equals("TERM_WEEK") == true)) {
				// 週の場合
				target = Calendar.DATE;
				term = LoLogConstant.DEF_DBTERM_WEEK;
				result.setTermUnit(LoLogConstant.STR_TERM_WEEK_o);
			} else {
				// 日の場合
				target = Calendar.DATE;
				term = LoLogConstant.DEF_DBTERM_DATE;
				result.setTermUnit(LoLogConstant.STR_TERM_DAY_o);
			}

			// 期間の差分 + 1
			// 指定された２つの日付期間を計算(データ部のカラム数となる)
			int colNum = 0;
			// 粒度が週の場合
			if ((termUnit != null) && (termUnit.equals("TERM_WEEK") == true)) {
				// 指定されたyyyy/MM/dd形式の文字列をその週の先頭（日曜日）の日付に変換
				String strTempFrom = XMODate.moveWeekFirst(termFrom);
				// 指定されたyyyy/MM/dd形式の文字列をその週末（土曜日）の日付に変換
				String strTempTo = XMODate.moveWeekEnd(termTo, "");
				// 粒度が週の場合は7で割る
				colNum = cominc.dateDiff(strTempFrom, strTempTo, target) + 1;
				colNum = colNum / 7;

			} else {
				// 粒度が以外の場合
				colNum = cominc.dateDiff(termFrom, termTo, target) + 1;
			}

			// カウント種別
			// カウント種別がユーザ数の場合
			if ((countUnit != null)
				&& (countUnit.equals("COUNT_USER") == true)) {
				countTarget = LoLogConstant.DEF_DBTARGET_USER;
				result.setCountUnit(LoLogConstant.STR_COUNT_USER_o);
				// カウント種別がアクセス数の場合
			} else {
				countTarget = LoLogConstant.DEF_DBTARGET_ACCESS;
				result.setCountUnit(LoLogConstant.STR_COUNT_ACCESS_o);
			}

			List groupIdList = new ArrayList();

			// 配下フラグのセット。配下フラグがnullであればデフォルトでoff(直下になる)	
			// 直下の場合
			if (subordinate_flg.equals("off")) {
				// 集計対象となる文言(直下のユーザ)の設定

				groupIdList.add(groupId);

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

				groupIdList = GapClinent.getGroupIdList(groupId, groupIdList);

			}

			// ＳＱＬ発行回数を取得
			int logSqlCount = cominc.getSqlCount(groupIdList);

			// 最低１度はループする。
			for (int j = 0; j < logSqlCount; j++) {
				// 指定されたグループ配下のLO利用数を検索する
				result =
					getUseStatusDBAccess(
						groupIdList,
						LoID,
						result.getRealLoId(),
						termFrom,
						termTo,
						term,
						countTarget,
						colNum,
						target,
						dataAccess,
						j);
			}

		} 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>
	 *                          例.
	 * from 現在の年月の1年前	2002/04/01
	 * to   現在の年月			2003/04/30
	 * 粒度						月
	 * カウント対象				ユーザ数
	 * となる。
	 * 
	 */
	private void initParam() {

		// ログ共通用Commonクラスの生成
		 LoLogCommon_inc cominc = new LoLogCommon_inc();
		
		// 期間to初期値
		// 日付型データをyyyy/mm/dd型に変換
		String tmpDate = XMODate.parseYYYYMMDD(new Date());
		// 指定された値で日付を増減
		tmpDate = cominc.addDate(tmpDate, Calendar.MONTH, 1);
		tmpDate = tmpDate.substring(0, 7) + "/01";
		tmpDate = cominc.addDate(tmpDate, Calendar.DATE, -1);
		// 当月末日
		termTo = tmpDate;
		// 前年当月1日
		termFrom =
			cominc.addDate(
				tmpDate.substring(0, 7) + "/01",
				Calendar.YEAR,
				-1);
		// 粒度初期値
		termUnit = LoLogConstant.DEF_TERM_UNIT_o;
		// カウント対象初期値
		countUnit = LoLogConstant.DEF_COUNT_UNIT_o;
	
		// 検索期間 from
		result.setFromDate(termFrom);
		// 検索期間 to
		result.setToDate(termTo);
		// csv用検索期間 from
		result.setCsvFromDate(searchResult.getFromDate());
		// csv用検索期間 to
		result.setCsvToDate(searchResult.getToDate());
	}

	/**
	 * LO利用数取得メソッド(グループ配下)。<BR>
	 * 基本画面で選択されたグループ配下のLo利用数データを<BR>
	 * データベースより取得します。
	 * 
	 * @param lstGroupIdList グループIDリスト
	 * @param strLoID        LOID
	 * @param strRealLoId    リアルLOID
	 * @param strTermFrom    検索期間_from
	 * @param strTermTo      検索期間_to
	 * @param strTerm        粒度
	 * @param strCountTarget カウント対象
	 * @param intColNum      データ部のカラム数
	 * @param intTarget      年月日
	 * @param dataAccess     DAOオブジェクト
	 * @param sqlCounter     SQLのカウント数
	 * @return result        ログデータ
	 * @exception XmsException
	 * @exception XmsException
	 */
	private LoLogMaterialUseResult getUseStatusDBAccess(
		List lstGroupIdList,
		String strLoID,
		String strRealLoId,
		String strTermFrom,
		String strTermTo,
		String strTerm,
		String strCountTarget,
		int intColNum,
		int intTarget,
		DataAccess dataAccess,
		int sqlCounter)
		throws XmsException {

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

		LoLogCommon_inc cominc = new LoLogCommon_inc();

		try {

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

			// タイトル行の取得
			String[] titleItems = getTitle(intColNum, intTarget);

			// 検索条件 from [YYYY/MM/DD]
			String[] searchFrom = new String[intColNum]; 
			// 検索条件 to    [YYYY/MM/DD 23:59:59]
			String[] searchTo = new String[intColNum];

			for (int i = 1; i < titleItems.length - 1; i++) {

				if (strTerm.equals(LoLogConstant.DEF_DBTERM_YEAR)) {
					// 年の場合
					// fromを設定
					searchFrom[i-1] = titleItems[i] + "/01/01";
					// toを設定
					searchTo[i-1] = titleItems[i] + "/" + LoLogConstant.MAX_DATE + LoLogConstant.MAX_TIME;
				
				
				} else if (strTerm.equals(LoLogConstant.DEF_DBTERM_MONTH)) {
					// 月の場合
					// fromを設定
					searchFrom[i-1] = titleItems[i] + "/01";
					// 年月日を取得
					int iYear = Integer.parseInt(titleItems[i].substring(0, 4));
					int iMonth =
					Integer.parseInt(titleItems[i].substring(5, 7)) - 1;
					int iDay = 1;
					// カレンダーに取得した年月日を設定する
					Calendar cal = Calendar.getInstance();
					cal.set(iYear, iMonth, iDay);
					// 設定した月の末日を取得
					int last = cal.getActualMaximum(Calendar.DATE);
					// toを設定
					searchTo[i-1] = titleItems[i] + "/" + last + LoLogConstant.MAX_TIME;
				
				
				} else if (strTerm.equals(LoLogConstant.DEF_DBTERM_WEEK)) {
					// 週の場合
					// fromを設定
					searchFrom[i-1] = titleItems[i].substring(0, 10);
					// toを設定
					searchTo[i-1] = titleItems[i].substring(13, 23) + LoLogConstant.MAX_TIME;
				
				} else if (strTerm.equals(LoLogConstant.DEF_DBTERM_DATE)) {
					// 日の場合
					// fromを設定
					searchFrom[i-1] = titleItems[i];
					// toを設定
					searchTo[i-1] = titleItems[i] + LoLogConstant.MAX_TIME;
				}
			}


			// グループのループ開始サイズ
			int intStart = sqlCounter * 1000;

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

			sbSQL.append("SELECT ");

			for (int i = 0; i < intColNum; i++) {
				if (strCountTarget.equals(LoLogConstant.DEF_DBTARGET_USER)) {
					// カウント対象が｢ユーザ数｣の場合、DISTINCTを付る
					sbSQL.append("    COUNT(DISTINCT(CASE WHEN lgs.study_start_date between ");

					//Oracleの場合
					if(objEnv.getDBType().equals( objEnv.DB_ORACLE )){
						sbSQL.append(LoLogConstant.TO_DATE + "('"  + StringEscapeUtils.escapeSql(searchFrom[i] + LoLogConstant.MIN_TIME) + "','" + LoLogConstant.DEF_DAY_TIME + "')"); 
						sbSQL.append(" AND " + LoLogConstant.TO_DATE + "('" + StringEscapeUtils.escapeSql(searchTo[i]) + "','" + LoLogConstant.DEF_DAY_TIME + "')");
						sbSQL.append("    THEN lgs.UserID END)) AS \"" + StringEscapeUtils.escapeSql(searchFrom[i]) + "\", ");
					//PostgreSQLの場合
					}else if(objEnv.getDBType().equals( objEnv.DB_POSTGRE )){
						sbSQL.append(LoLogConstant.TO_TIMESTAMP + "('"  + StringEscapeUtils.escapeSql(searchFrom[i] + LoLogConstant.MIN_TIME) + "','" + LoLogConstant.DEF_DAY_TIME + "')"); 
						sbSQL.append(" AND " + LoLogConstant.TO_TIMESTAMP + "('" + StringEscapeUtils.escapeSql(searchTo[i]) + "','" + LoLogConstant.DEF_DAY_TIME + "')");
						sbSQL.append("    THEN lgs.UserID END)) AS \"" + StringEscapeUtils.escapeSql(searchFrom[i]) + "\", ");
					//SQLServerの場合
					}else if(objEnv.getDBType().equals( objEnv.DB_SQLSERVER )){
						sbSQL.append("'"  + StringEscapeUtils.escapeSql(searchFrom[i]) + "' AND '" + StringEscapeUtils.escapeSql(searchTo[i]) + "'");
						sbSQL.append("    THEN lgs.UserID END)) AS '" + StringEscapeUtils.escapeSql(searchFrom[i]) + "', ");
					}	
				} else {
					// カウント対象が｢アクセス数｣の場合、DISTINCTを付けない
					sbSQL.append("    COUNT(CASE WHEN lgs.study_start_date between ");

					//Oracleの場合
					if(objEnv.getDBType().equals( objEnv.DB_ORACLE )){
						sbSQL.append(LoLogConstant.TO_DATE + "('"  + StringEscapeUtils.escapeSql(searchFrom[i] + LoLogConstant.MIN_TIME) + "','" + LoLogConstant.DEF_DAY_TIME + "')"); 
						sbSQL.append(" AND " + LoLogConstant.TO_DATE + "('" + StringEscapeUtils.escapeSql(searchTo[i]) + "','" + LoLogConstant.DEF_DAY_TIME + "')");
						sbSQL.append("    THEN lgs.UserID END) AS \"" + StringEscapeUtils.escapeSql(searchFrom[i]) + "\", ");
					//PostgreSQLの場合
					}else if(objEnv.getDBType().equals( objEnv.DB_POSTGRE )){
						sbSQL.append(LoLogConstant.TO_TIMESTAMP + "('"  + StringEscapeUtils.escapeSql(searchFrom[i] + LoLogConstant.MIN_TIME) + "','" + LoLogConstant.DEF_DAY_TIME + "')"); 
						sbSQL.append(" AND " + LoLogConstant.TO_TIMESTAMP + "('" + StringEscapeUtils.escapeSql(searchTo[i]) + "','" + LoLogConstant.DEF_DAY_TIME + "')");
						sbSQL.append("    THEN lgs.UserID END) AS \"" + StringEscapeUtils.escapeSql(searchFrom[i]) + "\", ");
					//SQLServerの場合
					}else if(objEnv.getDBType().equals( objEnv.DB_SQLSERVER )){
						sbSQL.append("'"  + StringEscapeUtils.escapeSql(searchFrom[i]) + "' AND '" + StringEscapeUtils.escapeSql(searchTo[i]) + "'");
						sbSQL.append("    THEN lgs.UserID END) AS '" + StringEscapeUtils.escapeSql(searchFrom[i]) + "', ");
					}	
				}
			}
			// LO名
			sbSQL.append("    l.ChildName AS LoName, ");
			// 外部LOID
			sbSQL.append("    l.ChildForeignID AS LoForeignID, ");
			// LOID
			sbSQL.append("    l.ChildID AS LoID, ");

			// LOタイプ
			//Oracleの場合
			if(objEnv.getDBType().equals( Environment.DB_ORACLE )) {
				sbSQL.append("    l.\"type\" AS Type, ");
			//SQLServerの場合 or PostgreSQLの場合
			}else if(objEnv.getDBType().equals( Environment.DB_SQLSERVER ) || objEnv.getDBType().equals( Environment.DB_POSTGRE )) {
				sbSQL.append("    l.Type AS Type, ");
			}

			// 親コンテナID
			sbSQL.append("    l.ParentID AS ContID, ");
			// 並び順
			sbSQL.append("    l.sort_no AS OrderID ");
			sbSQL.append("FROM ");
			sbSQL.append("  v_LOList l ");
			sbSQL.append("    LEFT OUTER JOIN ");

			//Oracleの場合
			if(objEnv.getDBType().equals( objEnv.DB_ORACLE )){
				sbSQL.append("    (SELECT lgs.UserID,");
				sbSQL.append("            lgs.LOID,");
				sbSQL.append("            lgs.study_start_date");
				sbSQL.append("     FROM   LOLogSession lgs ");
				sbSQL.append("     INNER JOIN ");
				sbSQL.append("            v_UserList p ");
				sbSQL.append("     ON lgs.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(" AND ");
				sbSQL.append(" lgs.study_start_date between " + LoLogConstant.TO_DATE + "('" + StringEscapeUtils.escapeSql(strTermFrom + LoLogConstant.MIN_TIME) + "','" +  LoLogConstant.DEF_DAY_TIME + "') ");
				sbSQL.append(" AND " + LoLogConstant.TO_DATE + "('" + StringEscapeUtils.escapeSql(strTermTo + LoLogConstant.MAX_TIME) + "','" + LoLogConstant.DEF_DAY_TIME + "') ");
				sbSQL.append(" ) lgs ");
               			sbSQL.append(" ON lgs.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) + "'");
				}

				sbSQL.append("GROUP BY ");

			//PostgreSQLの場合
			}else if(objEnv.getDBType().equals( objEnv.DB_POSTGRE )){
				sbSQL.append("    (SELECT lgs.UserID,");
				sbSQL.append("            lgs.LOID,");
				sbSQL.append("            lgs.study_start_date");
				sbSQL.append("     FROM   LOLogSession lgs ");
				sbSQL.append("     INNER JOIN ");
				sbSQL.append("            v_UserList p ");
				sbSQL.append("     ON lgs.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(" AND ");
				sbSQL.append(" lgs.study_start_date between " + LoLogConstant.TO_TIMESTAMP + "('" + StringEscapeUtils.escapeSql(strTermFrom + LoLogConstant.MIN_TIME) + "','" +  LoLogConstant.DEF_DAY_TIME + "') ");
				sbSQL.append(" AND " + LoLogConstant.TO_TIMESTAMP + "('" + StringEscapeUtils.escapeSql(strTermTo + LoLogConstant.MAX_TIME) + "','" + LoLogConstant.DEF_DAY_TIME + "') ");
				sbSQL.append(" ) lgs ");
               			sbSQL.append(" ON lgs.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) + "'");
				}

				sbSQL.append("GROUP BY ");

			//SQLServerの場合
			} else if(objEnv.getDBType().equals( objEnv.DB_SQLSERVER )) {

				sbSQL.append("      LOLogSession lgs ");
				sbSQL.append("        INNER JOIN ");
				sbSQL.append("          v_UserList p ");
				sbSQL.append("        ON ");
				sbSQL.append("          lgs.UserID = p.ChildID ");
				sbSQL.append("    ON ");
				sbSQL.append("      lgs.LOID = l.RealID ");
				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("     AND ");
				if (result.isContainer()) {
					// コンテナ指定時
					sbSQL.append("      l.ParentID = '" + StringEscapeUtils.escapeSql(strLoID) + "'");
				} else {
					// LO指定時
					sbSQL.append("      l.ChildID = '" + StringEscapeUtils.escapeSql(strLoID) + "'");
				}
	
				sbSQL.append(" AND ");
				sbSQL.append(" lgs.study_start_date between '" + StringEscapeUtils.escapeSql(strTermFrom) + "' ");
				sbSQL.append(" AND '" + StringEscapeUtils.escapeSql(strTermTo + LoLogConstant.MAX_TIME) + "' ");
				sbSQL.append("GROUP BY ALL ");
			}

			//Oracleの場合
			if(objEnv.getDBType().equals( Environment.DB_ORACLE )) {
				sbSQL.append("  l.\"type\", ");
			//SQLServerの場合 or PostgreSQLの場合
			}else if(objEnv.getDBType().equals( Environment.DB_SQLSERVER ) || objEnv.getDBType().equals( Environment.DB_POSTGRE )) {
				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 ");

			//Oracleの場合
			if(objEnv.getDBType().equals( Environment.DB_ORACLE )) {
				sbSQL.append("    l.\"type\" <> 0 ");
			//SQLServerの場合 or PostgreSQLの場合
			}else if(objEnv.getDBType().equals( Environment.DB_SQLSERVER ) || objEnv.getDBType().equals( Environment.DB_POSTGRE )) {
				sbSQL.append("    l.Type <> 0 ");
			}

			sbSQL.append("  AND ");
			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 row = 0;
			while (rs.next()) {

				// 行合計
				long totalRow = 0;
				// １レコードの結果データを格納する配列を生成
				logData = new long[intColNum + 1];

				// SQLのループ１回目の場合
				if (sqlCounter == 0) {
					// 初期化
					if (logDataList == null && totalCol == null) {
						// 各レコード毎のデータを格納するリストの生成
						logDataList = new ArrayList();
						// 合計(縦計)の生成
						totalCol = new long[intColNum + 1];
					}
					// LO名とLO外部IDの設定
					String LOName = null;
					String LoForeignID = null;

					//Oracleの場合 OR PostgreSQLの場合
					if(objEnv.getDBType().equals( objEnv.DB_ORACLE ) || objEnv.getDBType().equals( objEnv.DB_POSTGRE )){
						LOName = ChangeEncode.setChar(rs.getString("LoName"));
						LoForeignID = ChangeEncode.setChar(rs.getString("LoForeignID"));
					//SQLServerの場合
					}else if(objEnv.getDBType().equals( objEnv.DB_SQLSERVER )) {
						LOName = cominc.charEncode(rs.getString("LoName"));
						LoForeignID = cominc.charEncode(rs.getString("LoForeignID"));
					}	
					result.addLog(LOName, LoForeignID);

					// 検索条件によりカラムは動的に変化する
					// カラム分ループ 
					for (int col = 0; col < intColNum; col++) {
						// // データベースよりデータを取得
						long lngData  = rs.getLong(searchFrom[col]);
						logData[col] = lngData;
						// データ(行)の集計
						totalRow += lngData;
						// データ(縦計)の集計
						totalCol[col] += lngData;
						// 最終カラム時
						if (col == intColNum - 1) {
							// 行を合計したものを代入
							logData[intColNum] = totalRow;
							// 列の合計を集計したものを代入
							totalCol[intColNum] += totalRow;
						}
					}
					logDataList.add(logData);
				} else {
					// 初期化
					if (totalCol == null) {
						// resultからデータ格納リストを取得
						logDataList = result.getLogDataList();
						// resultから合計行(縦計)の生成
  						totalCol = result.getTotalCol();
					}
					// カラム分ループ 
					for (int col = 0; col < intColNum; col++) {
						// 以前に集計したログデータを取得
						long[] rsltLogData = (long[])result.getLogDataList().get(row);
						
						// データベースよりデータを取得
						long lngData  = rs.getLong(searchFrom[col]);
						logData[col] = rsltLogData[col] + lngData;
						// データ(行)の集計
						totalRow += lngData;
						// カラム(縦)の集計
						totalCol[col] = totalCol[col] + lngData;
						// 最終カラム時
						if (col == intColNum - 1) {
							// 行を合計したものを代入
							logData[intColNum] = rsltLogData[intColNum] + totalRow;
							// 列の合計を集計したものを代入
							totalCol[intColNum] = totalCol[intColNum] + totalRow;
						}
					}
					logDataList.set(row, logData);
				}
				
				row++;
			}
			// 検索結果がない場合XmsWarningExceptionを発生させる
			if (logDataList == null) {
				throw new XmsWarningException("logsumup.w.search.notfound");
			} else {
				// ログデータの設定
				result.setLogDataList(logDataList);
			}
			
			// タイトル行の設定
			result.setTitleItems(titleItems);
			// 合計行の設定
			result.setTotalCol(totalCol);
			totalCol = null;

		} catch (XmsException e) {
			throw e;
		} 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;
	}

	/**
	 * 表示用タイトル取得メソッド<BR>
	 * 検索結果画面に出力する対象となる期間のタイトルを取得します。
	 * 
	 * @param  colNum      タイトルカラム数
	 * @param  target      年月日
	 * @return titleItems  タイトル文字配列
	 * @exception XmsException
	 */
	private String[] getTitle(int colNum, int target) {

		LoLogCommon_inc cominc = new LoLogCommon_inc();

		// タイトル用リスト
		String[] titleItems = new String[colNum + 2];
		// 一行一列目ブランク
		titleItems[0] = LoLogConstant.STR_BLANK_o;

		String nowTitle = termFrom;
		for (int i = 1; i < (colNum + 1); i++) {
			// 週の場合
			if ((termUnit != null) && (termUnit.equals("TERM_WEEK") == true)) {
				String strWeekEndTime = XMODate.moveWeekEnd(nowTitle, termTo);
				titleItems[i] = nowTitle + " 〜 " + strWeekEndTime;
				// 日付を1週間進める
				nowTitle = cominc.addDate(strWeekEndTime, Calendar.DATE, 1);
			} else {
				// 指定された期間で切り捨てる
				titleItems[i] = cominc.cutDate(nowTitle, target);
				nowTitle = cominc.addDate(nowTitle, target, 1);
			}
		}
		// 合計列
		titleItems[colNum + 1] = LoLogConstant.STR_TOTAL_o;
		return titleItems;
	}

}
