/*******************************************************************************
 *	All Rights reserved,Copyright (c) K-Opticom
 ********************************************************************************
 *＜プログラム内容＞
 *	システム名		：eo顧客基幹システム
 *	モジュール名	：JKKejbExclusiveProcKK0011
 *	ソースファイル名：JKKejbExclusiveProcKK0011.java
 *	作成者			：富士通
 *	日付			：2011年11月25日
 *＜機能概要＞
 *	申込を起点とするルートの排他処理部品。
 *＜修正履歴＞
 *	バージョン	修正日		修正者		修正内容
 *	ｖ1.00.00	2011/11/25	富士通		新規作成
 *  v10.00.00   2014/07/14  FJ）北谷　　ANK-2135-00-00
 ********************************************************************************/

package eo.ejb.common.db;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;

import com.fujitsu.futurity.model.base.CAANMsg;
import com.fujitsu.futurity.model.base.CAANRuntimeException;
import com.fujitsu.futurity.model.ejb.common.JSYejbDBAccess;
import com.fujitsu.futurity.model.ejb.common.JSYejbLog;

import eo.ejb.cbm.entity.KK0011ETMsg;

/**
 * <p>
 * 申込を起点とするルートの排他処理部品です。
 * </p>
 * @author 富士通
 *
 */
public class JKKejbExclusiveProcKK0011
{
	/** データ取得結果設定項目名（プライマリキー） */
	private static final String SET_PRIMARY = "SET_PRIMARY";

	/** データ取得結果設定項目名（更新年月日時分秒） */
	private static final String SET_UPD_DTM = "SET_UPD_DTM";
	
	/** 申込取得項目（申込番号） */
	private static final String MSKM_NO = "MSKM_NO";
	
	/** 申込取得項目（世代登録年月日時分秒） */
	private static final String GENE_ADD_DTM = "GENE_ADD_DTM";

	/** 申込取得項目（更新年月日時分秒） */
	private static final String UPD_DTM = "UPD_DTM";

	/**
	 * 更新系インターフェイス使用時の処理を行います（申込番号指定）。
	 * レコードのロック、タイムスタンプの実施、ロック対象レコードの更新を行います。
	 * @param inETMsg 処理内で使用する項目を保持しているメッセージ
	 * @param key 申込番号
	 * @param updDtmBf タイムスタンプチェック用更新年月日時分秒（更新前）
	 * @param funcCd 機能コード
	 * @return ロック失敗の場合、タイムスタンプ不一致の場合はfalseを返却する。
	 */
	public boolean isExProcMskmNo(CAANMsg inETMsg, String key, String updDtmBf, String funcCd)
	{
		JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), "call:JKKejbExclusiveProcKK0011#isExProcMskmNo");

		// 申込番号が設定されていない場合はtrueを返却する
		if (null == key)
		{
			return true;
		}

		// 更新年月日時分秒（更新前）が設定されていない場合はtrueを返却する
		if (null == updDtmBf)
		{
			return true;
		}

		// データ設定用MAP
		HashMap<String, ArrayList<String>> retMap = new HashMap<String, ArrayList<String>>();

		// レコードロック、データ取得の実行
		try 
		{
			retMap = execSQLForLockMskmNo(inETMsg, key);
		}
		catch (CAANRuntimeException ce)
		{
			// レコードロックに失敗した場合はfalseを返却する
			return false;
		}

		// 取得結果からそれぞれのリストを取り出す
		ArrayList<String> keyArray = retMap.get(SET_PRIMARY);
		ArrayList<String> updArray = retMap.get(SET_UPD_DTM);

		// データが取得できなかった場合はtrueを返却する
		if(keyArray.size() < 1)
		{
			return true;
		}

		// 共通処理のインスタンスを生成
		JKKejbExclusiveProcCommon epc = new JKKejbExclusiveProcCommon();

		// タイムスタンプチェックを行い、チェックエラーの場合はfalseを返却する。
		if (!epc.isTimeStampCheck(updArray, updDtmBf))
		{
			return false;
		}

		// 機能コードが実行モードの場合はロック対象レコード更新処理を行う
		if (!epc.isFuncMode(funcCd))
		{
			epc.updateKK0011(inETMsg, keyArray);
		}

		return true;
	}

	/**
	 * 照会系インターフェイス使用時の処理を行います（申込番号指定）。
	 * 指定されたキーに紐付く親テーブルを各ルートから検索し、
	 * その中で最大の更新年月日時分秒を取得します。
	 * @param inMsg 処理対象のメッセージ
	 * @param key 申込番号
	 * @return 指定したキーに紐付く最終更新年月日時分秒。
	 */
	public String getLastUpdDtmMskmNo(CAANMsg inMsg, String key)
	{
		JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), "call:JKKejbExclusiveProcKK0011#getLastUpdDtmMskmNo");
		JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), "call:JKKejbExclusiveProcKK0011#key=" + key);

		// 最終更新年月日候補レコードの取得
		HashMap<String, ArrayList<String>> retMap = execSQLForSelectMskmNo(inMsg, key);

		// 取得結果から更新年月日時分秒のリストを取り出す
		ArrayList<String> updArray = retMap.get(SET_UPD_DTM);

		// データが取得できなかった場合はnullを返却する
		if(updArray.size() < 1)
		{
			return null;
		}

		// 最終更新年月日時分秒を取得する
		String maxUpdDtm = new JKKejbExclusiveProcCommon().getLastUpdDtm(updArray);

		return maxUpdDtm;
	}

	/**
	 * 申込番号に紐付く
	 * 各ルートから導き出される親契約のロックとデータの取得を行います。
	 * @param inMsg バインド変数に設定するための情報を保持しているメッセージ
	 * @param key 申込番号
	 * @return 実行結果を保持したリスト
	 * 			┣申込番号
	 * 			┣世代登録年月日時分秒 
	 * 			┗更新年月日時分秒
	 */
	private HashMap<String, ArrayList<String>> execSQLForLockMskmNo(CAANMsg inMsg, String key)
	{
		// データベースアクセス機能インスタンスを生成
		JSYejbDBAccess jsydba = new JSYejbDBAccess(KK0011ETMsg.getTableName());

		try
		{
			// 初期化処理を行う
			jsydba.initialize();

			// プリコンパイルするSQL文を設定（レコードロック、データ取得用SQL文）
			jsydba.prepareStatement(new JKKejbExclusiveProcCommon().creSQLForLock(creSQLMskmNo()));

			// バインド変数リストの取得
			ArrayList<String> strBind = creBindMskmNo(inMsg, key);

			// パラメータの設定
			for (int i = 0; i < strBind.size(); i++)
			{
				jsydba.setParam(strBind.get(i));
			}

			// PreparedStatementオブジェクトのSQLクエリを実行
			jsydba.executeQuery();

			// 結果設定用ArrayList
			ArrayList<String> setKey = new ArrayList<String>();
			ArrayList<String> setUpd = new ArrayList<String>();

			// 取得結果をメッセージキャリアに格納
			while (jsydba.next())
			{
				// ArrayListに取得結果を設定
				StringBuffer primary = new StringBuffer();
				primary.append(jsydba.getString(MSKM_NO));
				primary.append(",");
				primary.append(jsydba.getString(GENE_ADD_DTM));
				
				setKey.add(primary.toString());
				setUpd.add(jsydba.getString(UPD_DTM));
			}

			// 返却用HashMap
			HashMap<String, ArrayList<String>> retMap = new HashMap<String, ArrayList<String>>();

			// 設定したArrayListをHashMapに格納
			retMap.put(SET_PRIMARY, setKey);
			retMap.put(SET_UPD_DTM, setUpd);

			return retMap;
		}
		catch(SQLException se)
		{
			throw new CAANRuntimeException(se);
		}
		finally
		{
			// リソースの開放処理を行う
			jsydba.terminal();
		}
	}

	/**
	 * 申込番号に紐付く
	 * 各ルートから導き出される親契約のデータの取得を行います。
	 * @param inMsg バインド変数に設定するための情報を保持しているメッセージ
	 * @param key 申込番号
	 * @return 実行結果を保持したリスト
	 * 			┣申込番号
	 * 			┣世代登録年月日時分秒 
	 * 			┗更新年月日時分秒
	 */
	private HashMap<String, ArrayList<String>> execSQLForSelectMskmNo(CAANMsg inMsg, String key)
	{
		// データベースアクセス機能インスタンスを生成
		JSYejbDBAccess jsydba = new JSYejbDBAccess(KK0011ETMsg.getTableName());

		try
		{
			// 初期化処理を行う
			jsydba.initialize();

			// プリコンパイルするSQL文を設定（データ取得用SQL文）
			jsydba.prepareStatement(creSQLMskmNo());

			// バインド変数リストの取得
			ArrayList<String> strBind = creBindMskmNo(inMsg, key);

			// パラメータの設定
			for (int i = 0; i < strBind.size(); i++)
			{
				jsydba.setParam(strBind.get(i));
			}

			// PreparedStatementオブジェクトのSQLクエリを実行
			jsydba.executeQuery();

			// 結果設定用ArrayList
			ArrayList<String> setKey = new ArrayList<String>();
			ArrayList<String> setUpd = new ArrayList<String>();

			// 取得結果をメッセージキャリアに格納
			while (jsydba.next())
			{
				// ArrayListに取得結果を設定
				StringBuffer primary = new StringBuffer();
				primary.append(jsydba.getString(MSKM_NO));
				primary.append(",");
				primary.append(jsydba.getString(GENE_ADD_DTM));
				
				setKey.add(primary.toString());
				setUpd.add(jsydba.getString(UPD_DTM));
			}

			// 返却用HashMap
			HashMap<String, ArrayList<String>> retMap = new HashMap<String, ArrayList<String>>();

			// 設定したArrayListをHashMapに格納
			retMap.put(SET_PRIMARY, setKey);
			retMap.put(SET_UPD_DTM, setUpd);

			return retMap;
		}
		catch(SQLException se)
		{
			throw new CAANRuntimeException(se);
		}
		finally
		{
			// リソースの開放処理を行う
			jsydba.terminal();
		}
	}

	/**
	 * 申込番号に紐付く、各ルートから親契約を取得するためのSQL文を作成します。
	 * @return データ取得用のSQL文。
	 */
	private String creSQLMskmNo()
	{
		StringBuffer buff = new StringBuffer();

		buff.append(" SELECT ");
		buff.append(" TABLE_01.MSKM_NO, ");
		buff.append(" TABLE_01.GENE_ADD_DTM, ");
		buff.append(" TABLE_01.UPD_DTM ");
		buff.append(" FROM ");
		buff.append(" KK_T_MSKM TABLE_01 ");
		buff.append(" WHERE ");
		buff.append(" TABLE_01.MSKM_NO = ? AND ");
		buff.append(" (TABLE_01.MSKM_NO, TABLE_01.UPD_DTM || TABLE_01.GENE_ADD_DTM) = ( ");
		buff.append(" SELECT ");
		buff.append(" TABLE_02.MSKM_NO, MAX(TABLE_02.UPD_DTM || TABLE_02.GENE_ADD_DTM) AS TABLE_03 ");
		buff.append(" FROM ");
		buff.append(" KK_T_MSKM TABLE_02 ");
		buff.append(" WHERE  ");
		buff.append(" TABLE_02.MSKM_NO = TABLE_01.MSKM_NO ");
		buff.append(" GROUP BY TABLE_02.MSKM_NO ");
		buff.append(" ) ");

		return buff.toString();
	}

	/**
	 * 申込番号指定時のSQL文に設定するためのバインド変数リストの作成を行います。
	 * @param inMsg バインド変数に設定するための情報を保持しているメッセージ
	 * @param key 申込番号
	 * @return SQLに設定するためのバインド変数のリスト。
	 */
	private ArrayList<String> creBindMskmNo(CAANMsg inMsg, String key)
	{
		ArrayList<String> retList = new ArrayList<String>();

		// バインド変数の設定
		retList.add(key);

		return retList;
	}
	
	
	// ANK-2135-00-00 2014/07/11 add start
	/**
	 * 更新系インターフェイス使用時の処理を行います（申込明細番号指定）。
	 * レコードのロック、タイムスタンプの実施、ロック対象レコードの更新を行います。
	 * @param inETMsg 処理内で使用する項目を保持しているメッセージ
	 * @param key 申込明細番号
	 * @param updDtmBf タイムスタンプチェック用更新年月日時分秒（更新前）
	 * @param funcCd 機能コード
	 * @return ロック失敗の場合、タイムスタンプ不一致の場合はfalseを返却する。
	 */
	public boolean isExProcMskmDtlNo(CAANMsg inETMsg, String key, String updDtmBf, String funcCd)
	{
		JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), "call:JKKejbExclusiveProcKK0011#isExProcMskmDtlNo");

		// 申込明細番号が設定されていない場合はtrueを返却する
		if (null == key)
		{
			return true;
		}

		// 更新年月日時分秒（更新前）が設定されていない場合はtrueを返却する
		if (null == updDtmBf)
		{
			return true;
		}

		// データ設定用MAP
		HashMap<String, ArrayList<String>> retMap = new HashMap<String, ArrayList<String>>();

		// レコードロック、データ取得の実行
		try 
		{
			retMap = execSQLForLockMskmDtlNo(inETMsg, key);
		}
		catch (CAANRuntimeException ce)
		{
			// レコードロックに失敗した場合はfalseを返却する
			return false;
		}

		// 取得結果からそれぞれのリストを取り出す
		ArrayList<String> keyArray = retMap.get(SET_PRIMARY);
		ArrayList<String> updArray = retMap.get(SET_UPD_DTM);

		// データが取得できなかった場合はtrueを返却する
		if(keyArray.size() < 1)
		{
			return true;
		}

		// 共通処理のインスタンスを生成
		JKKejbExclusiveProcCommon epc = new JKKejbExclusiveProcCommon();

		// タイムスタンプチェックを行い、チェックエラーの場合はfalseを返却する。
		if (!epc.isTimeStampCheck(updArray, updDtmBf))
		{
			return false;
		}

		// 機能コードが実行モードの場合はロック対象レコード更新処理を行う
		if (!epc.isFuncMode(funcCd))
		{
			epc.updateKK0011(inETMsg, keyArray);
		}

		return true;
	}

	/**
	 * 照会系インターフェイス使用時の処理を行います（申込明細番号指定）。
	 * 指定されたキーに紐付く親テーブルを各ルートから検索し、
	 * その中で最大の更新年月日時分秒を取得します。
	 * @param inMsg 処理対象のメッセージ
	 * @param key 申込明細番号
	 * @return 指定したキーに紐付く最終更新年月日時分秒。
	 */
	public String getLastUpdDtmMskmDtlNo(CAANMsg inMsg, String key)
	{
		JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), "call:JKKejbExclusiveProcKK0011#getLastUpdDtmMskmDtlNo");
		JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), "call:JKKejbExclusiveProcKK0011#key=" + key);

		// 最終更新年月日候補レコードの取得
		HashMap<String, ArrayList<String>> retMap = execSQLForSelectMskmDtlNo(inMsg, key);

		// 取得結果から更新年月日時分秒のリストを取り出す
		ArrayList<String> updArray = retMap.get(SET_UPD_DTM);

		// データが取得できなかった場合はnullを返却する
		if(updArray.size() < 1)
		{
			return null;
		}

		// 最終更新年月日時分秒を取得する
		String maxUpdDtm = new JKKejbExclusiveProcCommon().getLastUpdDtm(updArray);

		return maxUpdDtm;
	}

	/**
	 * 申込明細番号に紐付く
	 * 各ルートから導き出される親契約のロックとデータの取得を行います。
	 * @param inMsg バインド変数に設定するための情報を保持しているメッセージ
	 * @param key 申込明細番号
	 * @return 実行結果を保持したリスト
	 * 			┣申込明細番号
	 * 			┣世代登録年月日時分秒 
	 * 			┗更新年月日時分秒
	 */
	private HashMap<String, ArrayList<String>> execSQLForLockMskmDtlNo(CAANMsg inMsg, String key)
	{
		// データベースアクセス機能インスタンスを生成
		JSYejbDBAccess jsydba = new JSYejbDBAccess(KK0011ETMsg.getTableName());

		try
		{
			// 初期化処理を行う
			jsydba.initialize();

			// プリコンパイルするSQL文を設定（レコードロック、データ取得用SQL文）
			jsydba.prepareStatement(new JKKejbExclusiveProcCommon().creSQLForLock(creSQLMskmDtlNo()));

			// バインド変数リストの取得
			ArrayList<String> strBind = creBindMskmDtlNo(inMsg, key);

			// パラメータの設定
			for (int i = 0; i < strBind.size(); i++)
			{
				jsydba.setParam(strBind.get(i));
			}

			// PreparedStatementオブジェクトのSQLクエリを実行
			jsydba.executeQuery();

			// 結果設定用ArrayList
			ArrayList<String> setKey = new ArrayList<String>();
			ArrayList<String> setUpd = new ArrayList<String>();

			// 取得結果をメッセージキャリアに格納
			while (jsydba.next())
			{
				// ArrayListに取得結果を設定
				StringBuffer primary = new StringBuffer();
				primary.append(jsydba.getString(MSKM_NO));
				primary.append(",");
				primary.append(jsydba.getString(GENE_ADD_DTM));
				
				setKey.add(primary.toString());
				setUpd.add(jsydba.getString(UPD_DTM));
			}

			// 返却用HashMap
			HashMap<String, ArrayList<String>> retMap = new HashMap<String, ArrayList<String>>();

			// 設定したArrayListをHashMapに格納
			retMap.put(SET_PRIMARY, setKey);
			retMap.put(SET_UPD_DTM, setUpd);

			return retMap;
		}
		catch(SQLException se)
		{
			throw new CAANRuntimeException(se);
		}
		finally
		{
			// リソースの開放処理を行う
			jsydba.terminal();
		}
	}

	/**
	 * 申込明細番号に紐付く
	 * 各ルートから導き出される親契約のデータの取得を行います。
	 * @param inMsg バインド変数に設定するための情報を保持しているメッセージ
	 * @param key 申込明細番号
	 * @return 実行結果を保持したリスト
	 * 			┣申込明細番号
	 * 			┣世代登録年月日時分秒 
	 * 			┗更新年月日時分秒
	 */
	private HashMap<String, ArrayList<String>> execSQLForSelectMskmDtlNo(CAANMsg inMsg, String key)
	{
		// データベースアクセス機能インスタンスを生成
		JSYejbDBAccess jsydba = new JSYejbDBAccess(KK0011ETMsg.getTableName());

		try
		{
			// 初期化処理を行う
			jsydba.initialize();

			// プリコンパイルするSQL文を設定（データ取得用SQL文）
			jsydba.prepareStatement(creSQLMskmDtlNo());

			// バインド変数リストの取得
			ArrayList<String> strBind = creBindMskmDtlNo(inMsg, key);

			// パラメータの設定
			for (int i = 0; i < strBind.size(); i++)
			{
				jsydba.setParam(strBind.get(i));
			}

			// PreparedStatementオブジェクトのSQLクエリを実行
			jsydba.executeQuery();

			// 結果設定用ArrayList
			ArrayList<String> setKey = new ArrayList<String>();
			ArrayList<String> setUpd = new ArrayList<String>();

			// 取得結果をメッセージキャリアに格納
			while (jsydba.next())
			{
				// ArrayListに取得結果を設定
				StringBuffer primary = new StringBuffer();
				primary.append(jsydba.getString(MSKM_NO));
				primary.append(",");
				primary.append(jsydba.getString(GENE_ADD_DTM));
				
				setKey.add(primary.toString());
				setUpd.add(jsydba.getString(UPD_DTM));
			}

			// 返却用HashMap
			HashMap<String, ArrayList<String>> retMap = new HashMap<String, ArrayList<String>>();

			// 設定したArrayListをHashMapに格納
			retMap.put(SET_PRIMARY, setKey);
			retMap.put(SET_UPD_DTM, setUpd);

			return retMap;
		}
		catch(SQLException se)
		{
			throw new CAANRuntimeException(se);
		}
		finally
		{
			// リソースの開放処理を行う
			jsydba.terminal();
		}
	}

	/**
	 * 申込明細番号に紐付く、各ルートから親契約を取得するためのSQL文を作成します。
	 * @return データ取得用のSQL文。
	 */
	private String creSQLMskmDtlNo()
	{
		StringBuffer buff = new StringBuffer();

		buff.append("  SELECT ");
		buff.append("  TABLE_01.MSKM_NO, ");
		buff.append("  TABLE_01.GENE_ADD_DTM, ");
		buff.append("  TABLE_01.UPD_DTM ");
		buff.append(" FROM ");
		buff.append("  KK_T_MSKM TABLE_01, KK_T_MSKM_DTL TABLE_02 ");
		buff.append(" WHERE ");
		buff.append("  TABLE_01.MSKM_NO = TABLE_02.MSKM_NO ");
		buff.append("  AND TABLE_02.MSKM_DTL_NO = ?");
		buff.append("  AND (TABLE_01.MSKM_NO, TABLE_01.UPD_DTM || TABLE_01.GENE_ADD_DTM) = ( ");
		buff.append("   SELECT ");
		buff.append("    TABLE_03.MSKM_NO, MAX(TABLE_03.UPD_DTM || TABLE_03.GENE_ADD_DTM) AS TABLE_04 ");
		buff.append("   FROM ");
		buff.append("    KK_T_MSKM TABLE_03 ");
		buff.append("   WHERE  ");
		buff.append("    TABLE_03.MSKM_NO = TABLE_01.MSKM_NO ");
		buff.append("   GROUP BY TABLE_03.MSKM_NO ");
		buff.append("  ) ");
		buff.append("  AND (TABLE_02.MSKM_DTL_NO, TABLE_02.UPD_DTM || TABLE_02.GENE_ADD_DTM) = ( ");
		buff.append("   SELECT ");
		buff.append("    TABLE_05.MSKM_DTL_NO, MAX(TABLE_05.UPD_DTM || TABLE_05.GENE_ADD_DTM) AS TABLE_06 ");
		buff.append("   FROM ");
		buff.append("    KK_T_MSKM_DTL TABLE_05 ");
		buff.append("   WHERE  ");
		buff.append("    TABLE_05.MSKM_DTL_NO = TABLE_02.MSKM_DTL_NO ");
		buff.append("   GROUP BY TABLE_05.MSKM_DTL_NO ");
		buff.append("  ) ");

		return buff.toString();
	}

	/**
	 * 申込明細番号指定時のSQL文に設定するためのバインド変数リストの作成を行います。
	 * @param inMsg バインド変数に設定するための情報を保持しているメッセージ
	 * @param key 申込明細番号
	 * @return SQLに設定するためのバインド変数のリスト。
	 */
	private ArrayList<String> creBindMskmDtlNo(CAANMsg inMsg, String key)
	{
		ArrayList<String> retList = new ArrayList<String>();

		// バインド変数の設定
		retList.add(key);

		return retList;
	}
	// ANK-2135-00-00 2014/07/11 add end

}