/*********************************************************************
*	All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*	システム名		：eo顧客基幹システム
*	モジュール名	：JCKMustStepApiCC
*	ソースファイル名：JCKMustStepApiCC.java
*   作成者          ：富士通
*   日付            ：2023年01月06日
*＜機能概要＞
*	開通前マストステップ実施状況照会・更新の共通コンポーネントクラスです。
*＜修正履歴＞
*	バージョン	修正日		修正者		修正内容
*   v64.00.00   2023/01/06  FJ)張本     【ANK-4316-00-00】ｅｏアプリ対応
**********************************************************************/
package com.fujitsu.futurity.bp.custom.common;

import static com.fujitsu.futurity.bp.custom.common.JCKPmpCommonUtil.callECK0201B030;
import static com.fujitsu.futurity.bp.custom.common.JCKPmpCommonUtil.printDebugLog;
import static com.fujitsu.futurity.bp.custom.common.JCKPmpCommonUtil.scCallRun;
import static com.fujitsu.futurity.bp.custom.common.JCKPmpScParamHenshu.getResultMsgList;
import static com.fujitsu.futurity.bp.custom.common.JCKPmpScParamHenshu.getResultString;
import static com.fujitsu.futurity.bp.custom.common.JCKPmpScParamHenshu.isSuccess;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.fujitsu.futurity.bp.x21.bpm.ServiceComponentRequestInvoker;
import com.fujitsu.futurity.bp.x21.bpm.db.SessionHandle;
import com.fujitsu.futurity.bp.x21.bpm.exception.RequestParameterException;
import com.fujitsu.futurity.bp.x21.bpm.parameter.IRequestParameterReadWrite;
import com.fujitsu.futurity.bp.x21.cc.exception.CCException;
import com.fujitsu.futurity.bp.x21.cc.exception.SCCallException;
import com.fujitsu.futurity.bp.x21.sc.exception.SCException;
import com.fujitsu.futurity.common.x01.sc.ErrorInfoMapKeys;
import com.fujitsu.futurity.common.x01.sc.SCControlMapKeys;
import com.fujitsu.futurity.model.base.CAANMsg;
import com.fujitsu.futurity.model.common.check.HalfCharCheck;
import com.fujitsu.futurity.model.common.check.LengthCheck;

import eo.common.constant.JKKStrConst;
import eo.common.constant.JPCModelConstant;
import eo.common.util.JKKStringUtil;
import eo.ejb.cbs.cbsmsg.ECCM011B010CBSMsg;
import eo.ejb.cbs.cbsmsg.ECCM011B010CBSMsg1List;
import eo.ejb.cbs.cbsmsg.ECK0011A010CBSMsg1List;
import eo.ejb.cbs.cbsmsg.ECK0201B030CBSMsg;
import eo.ejb.cbs.cbsmsg.ECK0201B030CBSMsg1List;
import eo.ejb.cbs.cbsmsg.ECK0321B010CBSMsg;
import eo.ejb.cbs.cbsmsg.ECK0321B010CBSMsg1List;
import eo.ejb.cbs.cbsmsg.ECK0321D010CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK0081B557CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK0081B557CBSMsg1List;
import eo.ejb.cbs.cbsmsg.EKK0251A010CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK0491A010CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK0491A010CBSMsg1List;


/**
 * 開通前マストステップ実施状況照会・更新の共通コンポーネントクラスです。
 * <br>
 * @author FJ
 */
public class JCKMustStepApiCC extends JCKEoAplCtrlBaseCC
{
	/** CCパラメータ：SYSID */
	private static final String REQ_SYSID = "sysid";
	/** CCパラメータ：変換後SYSID */
	private static final String REQ_CHG_SYSID = "_sysid";
	/** CCパラメータ：回線内訳番号 */
	private static final String REQ_ACCESS_ITEM_NUMBER = "accessItemNumber";
	/** CCパラメータ：照会更新区分 */
	private static final String REQ_MODE = "mode";

	/** CCパラメータ：マストステップ一覧 */
	private static final String REQ_MUSTSTEP_LIST = "muststepList";
	/** CCパラメータ：マストステップ種別 */
	private static final String REQ_MUSTSTEP_CATEGORY = "muststepCategory";
	/** CCパラメータ：表示フラグ */
	private static final String REQ_DISPLAYED_FLG = "displayedFlg";
	/** CCパラメータ：更新完了フラグ */
	private static final String RES_UPDATE_COMPLETEFLG = "updateCompleteFlg";

	/** CCパラメータ：ボディ情報 */
	public static final String BODY_INFO = "BODY_INFO";
	/** CCパラメータ：エラー情報 */
	public static final String ERROR_INFO = "ERROR_INFO";
	/** CCパラメータ：エラーコード */
	public static final String ERROR_CODE = "errorCode";
	/** CCパラメータ：エラーメッセージ */
	public static final String ERROR_MESSAGE = "errorMessage";

	/** テンプレートID：サービス契約回線内訳一意照会 */
	private static final String TEMPLATE_ID_EKK0251A010 = "EKK0251A010";
	/** テンプレートID：請求契約一意照会 */
	private static final String TEMPLATE_ID_EKK0491A010 = "EKK0491A010";
	/** テンプレートID：マストステップ実施状況一覧照会 */
	private static final String TEMPLATE_ID_ECK0321B010 = "ECK0321B010";
	/** テンプレートID：マストステップ実施状況登録 */
	private static final String TEMPLATE_ID_ECK0321D010 = "ECK0321D010";
	

	/** 作業用マップのキー：運用日 */
	private static final String WORK_KEY_OPEDATE = "opeDate";
	/** 作業用マップのキー：お客様一意照会明細 */
	private static final String WORK_KEY_ECK0011A010CBSMSGLIST = "ECK0011A010CBSMsg1List";
	/** 作業用マップのキー：マストステップ種別一覧照会明細 */
	private static final String WORK_KEY_ECCM011B010CBSMSGLIST = "ECCM011B010CBSMsg1List";
	/** 作業用マップのキー：マストステップ実施状況一覧照会明細 */
	private static final String WORK_KEY_ECK0321B010CBSMSGLIST = "ECK0321B010CBSMsg1List";

	/** 表示フラグ：表示不要 */
	private static final String DISPLAYED_FLG_0 = "0";
	/** 表示フラグ：表示要 */
	private static final String DISPLAYED_FLG_1 = "1";
	/** 照会更新区分：照会 */
	private static final String MODE_1 = "1";
	/** 照会更新区分：更新 */
	private static final String MODE_2 = "2";
	/** 更新完了区分：更新完了 */
	private static final String UPDATE_COMPLETEFLG_1 = "1";

	/**マストステップ種別：001 */
	private static final String MUSTSTEP_SBT_001 = "001";
	/**マストステップ種別：002 */
	private static final String MUSTSTEP_SBT_002 = "002";
	/**マストステップ種別：003 */
	private static final String MUSTSTEP_SBT_003 = "003";
	/**マストステップ種別：004 */
	private static final String MUSTSTEP_SBT_004 = "004";
	/**マストステップ種別：005 */
	private static final String MUSTSTEP_SBT_005 = "005";
	/**マストステップ種別：006 */
	private static final String MUSTSTEP_SBT_006 = "006";

	/** 照査解約：照査NG */
	static final String SHOSA_DSL_FIN_CD_2 = "2";

	/** 関連チェックでエラー発生 */
	public static final int RELATION_ERR = 1100;

	/**
	 *マストステップ実施状況の照会・更新を行う。
	 * <br>
	 * @param handle セッションハンドル
	 * @param param リクエストパラメータ
	 * @param fixedText ユーザ定義文字列
	 * @return リクエストパラメータ
	 * @throws Throwable 例外が発生した場合
	 */
	@SuppressWarnings("unchecked")
	public IRequestParameterReadWrite execute(SessionHandle handle, IRequestParameterReadWrite param, String fixedText)
	throws Throwable
	{
		// eoIDログイン後表示判定情報照会CCマップ
		Map<String, Object> ccMsg = (Map<String, Object>)param.getData(fixedText);
		// 作業用マップ
		Map<String, Object> work = new HashMap<String, Object>();

		try
		{
			// 運用日
			work.put(WORK_KEY_OPEDATE, JPCBPCommon.getOpeDate(null));
			// 単項目チェック
			if (!checkUnitParam(ccMsg, work))
			{
				param.setControlMapData(SCControlMapKeys.RETURN_CODE, JKKStrConst.RETURN_CD_5000);
				return param;
			}

			// 関連チェック
			if (!checkParameter(handle, param, fixedText, ccMsg, work))
			{
				param.setControlMapData(SCControlMapKeys.RETURN_CODE, JKKStrConst.RETURN_CD_5000);
				return param;
			}

			// 照会更新区分＝照会
			if(MODE_1.equals(ccMsg.get(REQ_MODE)))
			{
				// マストステップ取得処理
				searchMuststepInfo(handle, param, fixedText, ccMsg, work);
			}
			// 照会更新区分＝更新
			if(MODE_2.equals(ccMsg.get(REQ_MODE)))
			{
				// マストステップ登録処理
				addMuststepInfo(handle, param, fixedText, ccMsg, work);
			}

			// 正常終了
			param.setControlMapData(SCControlMapKeys.RETURN_CODE, JKKStrConst.RETURN_CD_0000);
			param.setControlMapData(SCControlMapKeys.RETURN_MESSAGE, null);
		}
		catch (SCCallException se)
		{
			// 関連チェックエラーの場合
			if (RELATION_ERR == se.getStatusCD() && isErrorField(param, TEMPLATE_ID_ECK0321D010, ECK0321D010CBSMsg.SYSID_ERR))
			{
				// データ更新で排他エラーの場合
				setResponse(ccMsg, JKKStrConst.RETURN_CD_2002, "登録内容が更新されています");
				param.setControlMapData(SCControlMapKeys.RETURN_CODE, JKKStrConst.RETURN_CD_5000);
			}
			else
			{
				// システムエラー
				setResponse(ccMsg, JKKStrConst.RETURN_CD_3001, "");
				param.setControlMapData(SCControlMapKeys.RETURN_CODE, JKKStrConst.RETURN_CD_5000);
			}
			throw se;
		}
		catch(Exception e)
		{
			// システムエラー
			setResponse(ccMsg, JKKStrConst.RETURN_CD_3001, "");
			param.setControlMapData(SCControlMapKeys.RETURN_CODE, JKKStrConst.RETURN_CD_5000);
			throw new CCException(JKKStrConst.RETURN_CD_3001, new Exception());
		}
		catch (Throwable throwable)
		{
			// システムエラー
			setResponse(ccMsg, JKKStrConst.RETURN_CD_3001, "");
			param.setControlMapData(SCControlMapKeys.RETURN_CODE, JKKStrConst.RETURN_CD_5000);
			throw new CCException(JKKStrConst.RETURN_CD_3001, new Exception());
		}

		return param;
	}

	/**
	 * 単項目チェック
	 * @param ccMsg CCマップ
	 * @param work 作業用マップ
	 * @return チェックの判定
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	private boolean checkUnitParam(Map<String, Object> ccMsg, Map<String, Object> work)
	throws Exception
	{
		// エラーリスト
		List<Map<String, String>> errList = new ArrayList<Map<String, String>>();
		Map<String, Object> bodyMap = new HashMap<String, Object>();
		String itemName = null;
		String itemValue = null;

		// 回線内訳番号
		itemName = REQ_ACCESS_ITEM_NUMBER;
		itemValue = (String)ccMsg.get(itemName);
		// 半角英数字1 12桁
		checkUnitEnNumber1(errList, itemName, itemValue, 12, true);

		// 照会更新区分
		itemName = REQ_MODE;
		itemValue = (String)ccMsg.get(itemName);
		// 半角数字1 1桁
		checkUnitNumber1(errList, itemName, itemValue, 1, true);

		// マストステップリスト
		if (!JKKStringUtil.isNullEmpty(ccMsg.get(REQ_MUSTSTEP_LIST)))
		{
			List<Map<String, Object>> muststepList = (List<Map<String, Object>>)ccMsg.get(REQ_MUSTSTEP_LIST);

			for (Map<String, Object> muststep : muststepList)
			{
				// マストステップ種別
				itemName = REQ_MUSTSTEP_CATEGORY;
				itemValue = (String)muststep.get(itemName);
				// 半角数字1 3桁
				checkUnitNumber1(errList, itemName, itemValue, 3, false);

				// 表示フラグ
				itemName = REQ_DISPLAYED_FLG;
				itemValue = (String)muststep.get(itemName);
				// 半角数字1 1桁
				checkUnitNumber1(errList, itemName, itemValue, 1, false);
			}
		}

		// SYSID
		itemName = getReqSysid(ccMsg);
		itemValue = (String)ccMsg.get(itemName);

		if (!JKKStringUtil.isNullBlank(itemName))
		{
			// 半角英数字1 12桁
			checkUnitEnNumber1(errList, itemName, itemValue, 10, false);
		}

		// エラーが存在する場合
		if (errList.size() > 0)
		{
			// SYSID
			setMapString(bodyMap, REQ_SYSID, (String)ccMsg.get(REQ_SYSID));
			// 回線内訳番号
			setMapString(bodyMap, REQ_ACCESS_ITEM_NUMBER, (String)ccMsg.get(REQ_ACCESS_ITEM_NUMBER));
			// マストステップ
			setMapObject(bodyMap, REQ_MUSTSTEP_LIST, ccMsg.get(REQ_MUSTSTEP_LIST));

			// ボディ部の設定
			ccMsg.put(BODY_INFO, bodyMap);

			ccMsg.put(ERROR_INFO, errList);
			return false;
		}
		
		return true;

	}

	/**
	 * 関連チェックを行います。<br>
	 * ※後続処理に必要な情報の取得も行う。
	 * <br>
	 * @param handle セッションハンドル
	 * @param param リクエストパラメータ
	 * @param fixedText ユーザ定義文字列
	 * @param ccMsg 開通前マストステップ実施状況照会・更新CCマップ
	 * @param work 作業用マップ
	 * @return チェックエラーの場合はfalse、チェックOKの場合はtrue
	 * @throws Throwable 例外が発生した場合
	 */
	@SuppressWarnings("unchecked")
	private boolean checkParameter(SessionHandle handle, IRequestParameterReadWrite param, String fixedText,
			Map<String, Object> ccMsg, Map<String, Object> work)
	throws Throwable
	{

		// SC呼び出し部品のインスタンス生成
		ServiceComponentRequestInvoker scCall = new ServiceComponentRequestInvoker();

		// マストステップ種別
		Object[][] eccm011b010In =
		{
			{ECCM011B010CBSMsg.TEMPLATEID, "ECCM011B010"}
			// 機能コード
			, {ECCM011B010CBSMsg.FUNC_CODE, JPCModelConstant.FUNC_CD_1}
			// ＫＥＹ＿スキーマID
			, {ECCM011B010CBSMsg.SCHIMA_ID, "CK0311"}
			// ＫＥＹ＿要求カラムNO
			, {ECCM011B010CBSMsg.YOUKYU_COLUM_NO, "0"}
		};
		// サービスIF実行
		CAANMsg[] eccm011b010MsgList = callSC(handle, scCall, param, fixedText, eccm011b010In)
				.getCAANMsgList(ECCM011B010CBSMsg.ECCM011B010CBSMSG1LIST);

		// マストステップ種別が取得できない場合
		if (eccm011b010MsgList == null || eccm011b010MsgList.length == 0)
		{
			// 関連チェックエラー
			setResponse(ccMsg, JKKStrConst.RETURN_CD_3001, "");
			return false;
		}

		// SYSID
		String itemName = getReqSysid(ccMsg);
		String itemValue = (String)ccMsg.get(itemName);
		if (JKKStringUtil.isNullBlank(itemValue))
		{
			// 関連チェックエラー
			setResponse(ccMsg, JKKStrConst.RETURN_CD_1005, REQ_SYSID + JKKStrConst.COLON);
			return false;
		}

		// 照会更新区分　コード値チェック
		itemName = REQ_MODE;
		itemValue = (String)ccMsg.get(itemName);
		if (!Arrays.asList(MODE_1, MODE_2).contains(itemValue))
		{
			// 関連チェックエラー
			setResponse(ccMsg, JKKStrConst.RETURN_CD_1004, itemName + JKKStrConst.COLON + itemValue);
			return false;
		}

		// 照会更新区分が更新の場合
		if (MODE_2.equals(ccMsg.get(REQ_MODE)))
		{
			// マストステップリスト　整合性チェック
			itemName = REQ_MUSTSTEP_LIST;
			if (JKKStringUtil.isNullEmpty(ccMsg.get(itemName)))
			{
				// 関連チェックエラー
				setResponse(ccMsg, JKKStrConst.RETURN_CD_1005, itemName + JKKStrConst.COLON);
				return false;
			}

			List<Map<String, Object>> muststepList = (List<Map<String, Object>>)ccMsg.get(REQ_MUSTSTEP_LIST);
			for (Map<String, Object> muststep : muststepList)
			{
				// マストステップ種別　整合性チェック
				itemName = REQ_MUSTSTEP_CATEGORY;
				itemValue = (String)muststep.get(itemName);
				if (JKKStringUtil.isNullBlank(itemValue))
				{
					// 関連チェックエラー
					setResponse(ccMsg, JKKStrConst.RETURN_CD_1005, itemName + JKKStrConst.COLON);
					return false;
				}
				// マストステップ種別　コード値チェック
				boolean isMastStepSbt = false;
				for (CAANMsg caanMsg : eccm011b010MsgList)
				{
					if (itemValue.equals(caanMsg.getString(ECCM011B010CBSMsg1List.RECORD)))
					{
						isMastStepSbt = true;
					}
				}
				if (!isMastStepSbt)
				{
					// 関連チェックエラー
					setResponse(ccMsg, JKKStrConst.RETURN_CD_1004, itemName + JKKStrConst.COLON + itemValue);
					return false;
				}

				// 表示フラグ　整合性チェック
				itemName = REQ_DISPLAYED_FLG;
				itemValue = (String)muststep.get(itemName);
				if (JKKStringUtil.isNullBlank(itemValue))
				{
					// 関連チェックエラー
					setResponse(ccMsg, JKKStrConst.RETURN_CD_1005, itemName + JKKStrConst.COLON);
					return false;
				}
				// 表示フラグ　コード値チェック
				else if (!Arrays.asList(DISPLAYED_FLG_0).contains(itemValue))
				{
					// 関連チェックエラー
					setResponse(ccMsg, JKKStrConst.RETURN_CD_1004, itemName + JKKStrConst.COLON + itemValue);
					return false;
				}
			}
		}

		// 運用日
		String opeDate = (String)work.get(WORK_KEY_OPEDATE);

		// 関連チェック(SYSID存在チェック)
		// お客様一意照会
		CAANMsg[] eck0011a010MsgList = callECK0011A010SC(handle, param, fixedText, (String)ccMsg.get(getReqSysid(ccMsg)), opeDate);

		// SYSIDが取得できない場合
		if (eck0011a010MsgList == null || eck0011a010MsgList.length == 0)
		{
			// SYSID存在チェックエラー
			setResponse(ccMsg, JKKStrConst.RETURN_CD_2001, "回線が見つかりません");
			return false;
		}

		// 関連チェック(サービス契約回線内訳番号存在チェック)
		// サービス契約回線内訳一意照会
		Object[][] ekk0251a010In =
		{
			{EKK0251A010CBSMsg.TEMPLATEID, TEMPLATE_ID_EKK0251A010}
			// 機能コード
			, {EKK0251A010CBSMsg.FUNC_CODE, JPCModelConstant.FUNC_CD_2}
			// ＫＥＹ＿サービス契約回線内訳番号
			, {EKK0251A010CBSMsg.KEY_SVC_KEI_KAISEN_UCWK_NO, (String)ccMsg.get(REQ_ACCESS_ITEM_NUMBER)}
		};
		// サービスIF実行
		CAANMsg[] ekk0251a010MsgList = callSC(handle, scCall, param, fixedText, ekk0251a010In)
				.getCAANMsgList(EKK0251A010CBSMsg.EKK0251A010CBSMSG1LIST);

		// 回線が取得できない場合
		if (ekk0251a010MsgList == null || ekk0251a010MsgList.length == 0)
		{
			// 回線内訳番号存在チェックエラー
			setResponse(ccMsg, JKKStrConst.RETURN_CD_2001, "回線が見つかりません");
			return false;
		}

		// マストステップ実施状況一覧照会
		Object[][] eck032b010In =
		{
			{ECK0321B010CBSMsg.TEMPLATEID, TEMPLATE_ID_ECK0321B010}
			// 機能コード
			, {ECK0321B010CBSMsg.FUNC_CODE, JPCModelConstant.FUNC_CD_1}
			// ＫＥＹ＿SYSID
			, {ECK0321B010CBSMsg.KEY_SYSID, (String)ccMsg.get(getReqSysid(ccMsg))}
			// ＫＥＹ＿サービス契約回線内訳番号
			, {ECK0321B010CBSMsg.KEY_SVC_KEI_KAISEN_UCWK_NO, (String)ccMsg.get(REQ_ACCESS_ITEM_NUMBER)}
		};
		// サービスIF実行
		CAANMsg[] eck0321b010MsgList = callSC(handle, scCall, param, fixedText, eck032b010In)
				.getCAANMsgList(ECK0321B010CBSMsg.ECK0321B010CBSMSG1LIST);

		// お客様一意照会明細を作業用マップに設定
		work.put(WORK_KEY_ECK0011A010CBSMSGLIST, eck0011a010MsgList);
		// マストステップ種別一覧照会明細を作業用マップに設定
		work.put(WORK_KEY_ECCM011B010CBSMSGLIST, eccm011b010MsgList);
		// マストステップ実施状況一覧照会明細を作業用マップに設定
		work.put(WORK_KEY_ECK0321B010CBSMSGLIST, eck0321b010MsgList);

		return true;
	}

	/**
	 * 単項目チェック（半角英数字1）を行います。<br>
	 * @param errList
	 * @param itemName
	 * @param itemValue
	 * @param len
	 * @param req
	 */
	private void checkUnitEnNumber1(List<Map<String, String>> errList, String itemName, String itemValue, int len, boolean req)
	{
		// 必須チェック
		if (itemValue == null || "".equals(itemValue))
		{
			if (req)
			{
				// 必須チェックエラー
				errList.add(getReqErrInfMap(itemName));
			}
		}
		else if (!HalfCharCheck.isEnNumber1Check(itemValue))
		{
			// 属性チェックエラー
			errList.add(getFormErrInfMap(itemName, itemValue));
		}
		else if (!LengthCheck.isLength1Check(itemValue, len))
		{
			// 桁数チェックエラー
			errList.add(getLenErrInfMap(itemName, itemValue));
		}
	}

	/**
	 * 単項目チェック（半角数字1）を行います。<br>
	 * @param errList
	 * @param itemName
	 * @param itemValue
	 * @param len
	 * @param req
	 */
	private void checkUnitNumber1(List<Map<String, String>> errList, String itemName, String itemValue, int len, boolean req)
	{
		// 必須チェック
		if (itemValue == null || "".equals(itemValue))
		{
			if (req)
			{
				// 必須チェックエラー
				errList.add(getReqErrInfMap(itemName));
			}
		}
		else if (!HalfCharCheck.isNumber1Check(itemValue))
		{
			// 属性チェックエラー
			errList.add(getFormErrInfMap(itemName, itemValue));
		}
		else if (!LengthCheck.isLength1Check(itemValue, len))
		{
			// 桁数チェックエラー
			errList.add(getLenErrInfMap(itemName, itemValue));
		}
	}

	/**
	 * リクエストパラメタよりSYSIDを取得します<br>
	 * @param ccMsg
	 * @return
	 */
	private String getReqSysid(Map<String, Object> ccMsg)
	{
		if (!JKKStringUtil.isNullEmpty(ccMsg.get(REQ_CHG_SYSID)))
		{
			return REQ_CHG_SYSID;
		}
		else if (!JKKStringUtil.isNullEmpty(ccMsg.get(REQ_SYSID)))
		{
			return REQ_SYSID;
		}
		return null;
	}

	/**
	 * マストステップ登録処理を行います。<br>
	 * <br>
	 * @param handle セッションハンドル
	 * @param param リクエストパラメータ
	 * @param fixedText ユーザ定義文字列
	 * @param ccMsg 開通前マストステップ実施状況照会・更新CCマップ
	 * @param work 作業用マップ
	 * @throws Throwable 例外が発生した場合
	 */
	@SuppressWarnings("unchecked")
	private void addMuststepInfo(SessionHandle handle, IRequestParameterReadWrite param, String fixedText,
			Map<String, Object> ccMsg, Map<String, Object> work)
	throws Throwable
	{

		// エラーリスト
		List<Map<String, String>> errList = new ArrayList<Map<String, String>>();
		Map<String, Object> bodyMap = new HashMap<String, Object>();
		Map<String, String> errMap = new HashMap<String, String>();

		// SYSID
		String sysid = (String)ccMsg.get(getReqSysid(ccMsg));
		// サービス契約回線内訳番号
		String svkeiKaisenUcwkNo = (String)ccMsg.get(REQ_ACCESS_ITEM_NUMBER);

		List<Map<String, Object>> muststepList = (List<Map<String, Object>>)ccMsg.get(REQ_MUSTSTEP_LIST);

		// マストステップ種別を登録
		for (Map<String, Object> muststep : muststepList)
		{
			String sbtCd = (String)muststep.get(REQ_MUSTSTEP_CATEGORY);
			// マストステップ種別登録
			addMuststep(handle, param, fixedText, sysid, svkeiKaisenUcwkNo, sbtCd);
		}

		// エラーコード
		errMap.put(ERROR_CODE, "");
		// エラーメッセージ
		errMap.put(ERROR_MESSAGE, "");
		errList.add(errMap);
		ccMsg.put(ERROR_INFO, errList);

		// SYSID
		setMapString(bodyMap, REQ_SYSID, (String)ccMsg.get(REQ_SYSID));
		// 回線内訳番号
		setMapString(bodyMap, REQ_ACCESS_ITEM_NUMBER, (String)ccMsg.get(REQ_ACCESS_ITEM_NUMBER));
		// 更新完了
		bodyMap.put(RES_UPDATE_COMPLETEFLG, UPDATE_COMPLETEFLG_1);

		ccMsg.put(BODY_INFO, bodyMap);
	}

	/**
	 * マストステップ取得処理を行います。<br>
	 * <br>
	 * @param handle セッションハンドル
	 * @param param リクエストパラメータ
	 * @param fixedText ユーザ定義文字列
	 * @param ccMsg 開通前マストステップ実施状況照会・更新CCマップ
	 * @param work 作業用マップ
	 * @throws Throwable 例外が発生した場合
	 */
	private void searchMuststepInfo(SessionHandle handle, IRequestParameterReadWrite param, String fixedText,
			Map<String, Object> ccMsg, Map<String, Object> work)
	throws Throwable
	{

		// エラーリスト
		List<Map<String, String>> errList = new ArrayList<Map<String, String>>();
		Map<String, Object> bodyMap = new HashMap<String, Object>();
		Map<String, String> errMap = new HashMap<String, String>();

		// SYSID
		String sysid = (String)ccMsg.get(getReqSysid(ccMsg));
		// サービス契約回線内訳番号
		String svkeiKaisenUcwkNo = (String)ccMsg.get(REQ_ACCESS_ITEM_NUMBER);

		// マストステップリストの取得
		getMuststep(handle, param, fixedText, bodyMap, work, sysid, svkeiKaisenUcwkNo);

		// エラーコード
		errMap.put(ERROR_CODE, "");
		// エラーメッセージ
		errMap.put(ERROR_MESSAGE, "");
		errList.add(errMap);
		ccMsg.put(ERROR_INFO, errList);

		// SYSID
		setMapString(bodyMap, REQ_SYSID, (String)ccMsg.get(REQ_SYSID));
		// 回線内訳番号
		setMapString(bodyMap, REQ_ACCESS_ITEM_NUMBER, (String)ccMsg.get(REQ_ACCESS_ITEM_NUMBER));

		ccMsg.put(BODY_INFO, bodyMap);

		return;
	}

	/**
	 * マストステップリストの取得 <br>
	 * @param handle セッションハンドル
	 * @param param リクエストパラメータ
	 * @param fixedText ユーザ定義文字列
	 * @param bodyMap BODYマップ
	 * @param workMap 作業用マップ
	 * @param sysid SYSID
	 * @param svkeiKaisenUcwkNo サービス契約回線内訳番号
	 * @throws Throwable
	 */
	private void getMuststep(
			SessionHandle handle
			,IRequestParameterReadWrite param
			,String fixedText
			,Map<String, Object> bodyMap
			,Map<String, Object> workMap
			,String sysid
			,String svkeiKaisenUcwkNo)
			throws Throwable
	{

		// サービスIF結果取得(EKK0081B557)
		CAANMsg[] workEKK0081B557 = getEKK0081B557CAANMsg(handle, param, sysid, svkeiKaisenUcwkNo);
		// 作業用マップに設定
		workMap.put(WORK_KEY_EKK0081B557CBSMSGLIST, workEKK0081B557);

		List<Map<String, String>> muststepList = new ArrayList<Map<String, String>>();
		Map<String, String> muststepMap = new HashMap<String, String>();

		// マストステップ種別一覧照会明細
		CAANMsg[] eccm011b010MsgList = ((CAANMsg[])workMap.get(WORK_KEY_ECCM011B010CBSMSGLIST));
		// マストステップ種別を判定
		for (CAANMsg caanMsg : eccm011b010MsgList)
		{
			// マストステップ種別
			String muststepSbtCd = caanMsg.getString(ECCM011B010CBSMsg1List.RECORD);
			// マストステップの判定
			if (judgeMuststep(handle, param, fixedText, workMap, sysid, svkeiKaisenUcwkNo, muststepSbtCd))
			{
				muststepMap = new HashMap<String, String>();
				// マストステップ種別
				muststepMap.put(REQ_MUSTSTEP_CATEGORY, muststepSbtCd);
				// 表示要
				muststepMap.put(REQ_DISPLAYED_FLG, DISPLAYED_FLG_1);
				// マストステップリスト追加
				muststepList.add(muststepMap);
			}
		}

		bodyMap.put(REQ_MUSTSTEP_LIST, muststepList);

	}

	/**
	 * マストステップの判定 <br>
	 * @param bodyMap BODYマップ
	 * @param workMap 作業用マップ
	 * @param sysid SYSID
	 * @param svkeiKaisenUcwkNo サービス契約回線内訳番号
	 * @param muststepSbt マストステップ種別
	 * @throws Throwable
	 */
	private boolean judgeMuststep(
			SessionHandle handle
			,IRequestParameterReadWrite param
			,String fixedText
			,Map<String, Object> work
			,String sysid
			,String svkeiKaisenUcwkNo
			,String muststepSbt)
			throws Throwable
	{

		// 作業用マップに設定
		CAANMsg[] workEKK0081B557 = (CAANMsg[])work.get(WORK_KEY_EKK0081B557CBSMSGLIST);
		// お客様一意照会明細
		CAANMsg eck0011a010Msg = ((CAANMsg[])work.get(WORK_KEY_ECK0011A010CBSMSGLIST))[0];

		// 卸事業者の取得
		String orsJgsCd = eck0011a010Msg.getString(ECK0011A010CBSMsg1List.ORSJGS_CD);

		// ウェルカム画面
		if (MUSTSTEP_SBT_001.equals(muststepSbt))
		{
			// マストステップ実施状況が未登録
			if (existsMuststep(muststepSbt, work))
			{
				// あれば表示不要
				return false;
			}
			// 以外は表示要
			return true;
		}

		// 申込内容の確認
		// 契約内容の確認
		if (MUSTSTEP_SBT_002.equals(muststepSbt) || MUSTSTEP_SBT_003.equals(muststepSbt))
		{
			// マストステップ実施状況が未登録
			if (existsMuststep(muststepSbt, work))
			{
				// あれば表示不要
				return false;
			}
			// eo光パートナー会員ではないこと
			if (!JKKStringUtil.isNullBlank(orsJgsCd))
			{
				// 表示不要
				return false;
			}
			// 以外はサービス契約で判定
		}

		// 連絡用メールアドレス・受信設定の登録
		if (MUSTSTEP_SBT_005.equals(muststepSbt))
		{
			// マストステップ実施状況が未登録
			if (existsMuststep(muststepSbt, work))
			{
				// あれば表示不要
				return false;
			}
			// 連絡用メールアドレス(コンテンツ)が未登録であること
			Map<?, ?> result = callECK0201B030(handle, param, JPCModelConstant.FUNC_CD_2, sysid, null);
			if (isSuccess(result))
			{
				String rrksMlad = getResultString(result, ECK0201B030CBSMsg.ECK0201B030CBSMSG1LIST + "[0]." + ECK0201B030CBSMsg1List.MLAD);
				if (!JKKStringUtil.isNullBlank(rrksMlad))
				{
					// あれば表示不要
					return false;
				}
			}
			// 以外は表示要
			return true;
		}
		// コンテンツ利用開始
		if (MUSTSTEP_SBT_006.equals(muststepSbt))
		{
			// マストステップ実施状況が未登録
			if (existsMuststep(muststepSbt, work))
			{
				// あれば表示不要
				return false;
			}
			// 連絡用メールアドレス(コンテンツ)が登録済みであること
			Map<?, ?> result = callECK0201B030(handle, param, JPCModelConstant.FUNC_CD_2, sysid, null);
			if (isSuccess(result))
			{
				String rrksMlad = getResultString(result, ECK0201B030CBSMsg.ECK0201B030CBSMSG1LIST + "[0]." + ECK0201B030CBSMsg1List.MLAD);
				if (JKKStringUtil.isNullBlank(rrksMlad))
				{
					// なければ表示不要
					return false;
				}
			}
			// 以外はサービス契約で判定
		}

		if (workEKK0081B557 == null || workEKK0081B557.length == 0)
		{
			// なければ表示不要
			return false;
		}

		boolean isContMkmInfStcd01 = false;
		String sekyKeiNo = "";
		for (CAANMsg caanMsg : workEKK0081B557)
		{
			// 照査NGチェック
			if (!SHOSA_DSL_FIN_CD_2.equals(caanMsg.getString(EKK0081B557CBSMsg1List.SHOSA_DSL_FIN_CD)))
			{
				// 対象サービス判定
				if (judgeTgSvc(caanMsg.getString(EKK0081B557CBSMsg1List.SVC_CD), caanMsg.getString(EKK0081B557CBSMsg1List.PRC_GRP_CD), caanMsg
						.getString(EKK0081B557CBSMsg1List.PCRS_CD)))
				{
					// 申込内容の確認
					if (MUSTSTEP_SBT_002.equals(muststepSbt))
					{
						// "010"(受付済)の契約がある
						if (Arrays.asList(JKKStrConst.CD00037_UK_ZM).contains(caanMsg.getString(EKK0081B557CBSMsg1List.SVC_KEI_STAT)))
						{
							// 表示要
							return true;
						}
					}
					// 契約内容の確認
					if (MUSTSTEP_SBT_003.equals(muststepSbt))
					{
						// "020"(照査済(照査OKのみ)) or "030"(締結済)の契約がある
						if (Arrays.asList(JKKStrConst.CD00037_SHOSA_ZUMI, JKKStrConst.CD00037_CNC_ZM).contains(
								caanMsg.getString(EKK0081B557CBSMsg1List.SVC_KEI_STAT)))
						{
							// 表示要
							return true;
						}
					}
					// コンテンツ利用開始
					if (MUSTSTEP_SBT_006.equals(muststepSbt))
					{
						if (!isContMkmInfStcd01)
						{
							// 開始未登録の同時申込コンテンツがある
							isContMkmInfStcd01 =
									judgeContMkmInfStcd01(handle, param, fixedText, caanMsg.getString(EKK0081B557CBSMsg1List.MSKM_DTL_NO), sysid);
							if (!isContMkmInfStcd01)
							{
								// なければ表示不要
								return false;
							}
						}
						// "020"(照査済(照査OKのみ)) or "030"(締結済)の契約がある
						if (Arrays.asList(JKKStrConst.CD00037_SHOSA_ZUMI, JKKStrConst.CD00037_CNC_ZM).contains(
								caanMsg.getString(EKK0081B557CBSMsg1List.SVC_KEI_STAT)))
						{
							// 表示要
							return true;
						}
					}
				}
				// 支払方法の登録
				if (MUSTSTEP_SBT_004.equals(muststepSbt))
				{
					// 回線内に請求契約番号が1つのみ
					if (!JKKStringUtil.isNullBlank(sekyKeiNo) && !sekyKeiNo.equals(caanMsg.getString(EKK0081B557CBSMsg1List.SEIKY_KEI_NO)))
					{
						// 表示不要
						return false;
					}
					sekyKeiNo = caanMsg.getString(EKK0081B557CBSMsg1List.SEIKY_KEI_NO);
				}
			}
		}

		// 支払方法の登録
		if (MUSTSTEP_SBT_004.equals(muststepSbt))
		{
			if(!JKKStringUtil.isNullBlank(sekyKeiNo))
			{
				// 支払方法が窓口払い
				if (JKKStrConst.SEIKY_WAY_CD_MADOGUCHI.equals(getSeikyWayCd(handle, param, fixedText, sekyKeiNo)))
				{
					// 表示要
					return true;
				}
			}
		}

		// 表示不要
		return false;
	}

	/**
	 * レスポンス項目を設定します。
	 * <br>
	 * @param ccMsg 開通前マストステップ実施状況照会・更新CCマップ
	 * @param returnCode リターンコード
	 * @param returnMessage リターンメッセージ
	 */
	private void setResponse(Map<String, Object> ccMsg, String errCode, String errMessage)
	throws Exception
	{
		// エラーリスト
		List<Map<String, String>> errList = new ArrayList<Map<String, String>>();

		Map<String, Object> bodyMap = new HashMap<String, Object>();
		Map<String, String> errMap = new HashMap<String, String>();

		// SYSID
		setMapString(bodyMap, REQ_SYSID, (String)ccMsg.get(REQ_SYSID));
		// 回線内訳番号
		setMapString(bodyMap, REQ_ACCESS_ITEM_NUMBER, (String)ccMsg.get(REQ_ACCESS_ITEM_NUMBER));
		// マストステップ
		setMapObject(bodyMap, REQ_MUSTSTEP_LIST, ccMsg.get(REQ_MUSTSTEP_LIST));
		// ボディ部の設定
		ccMsg.put(BODY_INFO, bodyMap);

		// エラーコード
		errMap.put(ERROR_CODE, errCode);
		// エラーメッセージ
		errMap.put(ERROR_MESSAGE, errMessage);
		errList.add(errMap);
		ccMsg.put(ERROR_INFO, errList);

	}

	/**
	 * 単項目チェックの必須エラーマップ作成メソッドです。
	 * 
	 * @param itemName 項目名
	 * @return returnMap
	 */
	private Map<String, String> getReqErrInfMap(String itemName)
	{
		Map<String, String> returnMap = new HashMap<String, String>();

		returnMap.put(ERROR_CODE, JKKStrConst.RETURN_CD_1001);
		returnMap.put(ERROR_MESSAGE, itemName + JKKStrConst.COLON);

		return returnMap;
	}

	/**
	 * 単項目チェックの属性エラーマップ作成メソッドです。
	 * 
	 * @param itemName 項目名
	 * @param itemValue 項目値
	 * @return returnMap
	 */
	private Map<String, String> getFormErrInfMap(String itemName, String itemValue)
	{
		Map<String, String> returnMap = new HashMap<String, String>();

		returnMap.put(ERROR_CODE, JKKStrConst.RETURN_CD_1002);
		returnMap.put(ERROR_MESSAGE, itemName + JKKStrConst.COLON + itemValue);

		return returnMap;
	}
	
	/**
	 * 単項目チェックの桁数エラーマップ作成メソッドです。
	 * 
	 * @param itemName 項目名
	 * @param itemValue 項目値
	 * @return returnMap
	 */
	private Map<String, String> getLenErrInfMap(String itemName, String itemValue)
	{
		Map<String, String> returnMap = new HashMap<String, String>();
		
		returnMap.put(ERROR_CODE, JKKStrConst.RETURN_CD_1003);
		returnMap.put(ERROR_MESSAGE, itemName + JKKStrConst.COLON + itemValue);

		return returnMap;
	}

	/**
	 * <br>
	 * @param handle セッションハンドル
	 * @param scCall サービスコンポーネントリクエスト
	 * @param param リクエストパラメータ
	 * @param sysid SYSID
	 * @param svkeiKaisenUcwkNo サービス契約回線内訳番号
	 * @return CAANMsg[]
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	private CAANMsg[] getEKK0081B557CAANMsg(SessionHandle handle, IRequestParameterReadWrite param, String sysid, String svkeiKaisenUcwkNo) throws Exception
	{
		// 機能コード：１
		Map result = callEKK0081B557(handle, param, JPCModelConstant.FUNC_CD_1, sysid, svkeiKaisenUcwkNo);
		CAANMsg[] workEKK0081B557 = null;
		if (isSuccess(result))
		{
			workEKK0081B557 = getResultMsgList(result, EKK0081B557CBSMsg.EKK0081B557CBSMSG1LIST);
		}

		return workEKK0081B557;
	}

	/**
	 * サービス契約一覧照会(SYSID)5呼出。<br />
	 * @param handle セッションハンドル
	 * @param param リクエストパラメータ
	 * @param funcCd 機能コード
	 * @param sysid SYSID
	 * @param svkeiKaisenUcwkNo サービス契約回線内訳番号
	 * @return ＳＣ実行結果
	 * @throws RequestParameterException 
	 * @throws SCException 
	 */
	private static Map<?, ?> callEKK0081B557(SessionHandle handle, IRequestParameterReadWrite param, String funcCd, String sysid, String svkeiKaisenUcwkNo)
			throws RequestParameterException, SCException
	{
		//*****************************************************************
		// サービス契約一覧照会(SYSID)5への上りマッピング
		//*****************************************************************
		Map<Object, Object> inMap = new HashMap<Object, Object>();
		inMap.put(EKK0081B557CBSMsg.FUNC_CODE, funcCd);
		inMap.put(EKK0081B557CBSMsg.KEY_SYSID, sysid);
		inMap.put(EKK0081B557CBSMsg.KEY_SVC_KEI_KAISEN_UCWK_NO, svkeiKaisenUcwkNo);
		HashMap<String, Object> paramMap = JCKBPCommon.createScParamForSearch(param, EKK0081B557CBSMsg.class , inMap, funcCd);

		//***************************************************
		// ＳＣ呼出実行
		//***************************************************
		printDebugLog("サービス契約一覧照会(SYSID)5呼び出し開始");
		Map<?, ?> result = scCallRun(param, handle, paramMap);
		printDebugLog("サービス契約一覧照会(SYSID)5呼び出し完了" + result);

		return result;
	}

	/**
	 * 請求方法の取得 <br>
	 * @param handle セッションハンドル
	 * @param param リクエストパラメータ
	 * @param fixedText ユーザ定義文字列
	 * @param sekyKeiNo 請求契約番号
	 * @return 請求方法
	 */
	private String getSeikyWayCd(SessionHandle handle, IRequestParameterReadWrite param, String fixedText, String sekyKeiNo) throws Throwable
	{
		// SC呼び出し部品のインスタンス生成
		ServiceComponentRequestInvoker scCall = new ServiceComponentRequestInvoker();

		// 請求契約一意照会
		Object[][] ekk0491a010In =
		{
			{EKK0491A010CBSMsg.TEMPLATEID, TEMPLATE_ID_EKK0491A010}
			// 機能コード
			, {EKK0491A010CBSMsg.FUNC_CODE, JPCModelConstant.FUNC_CD_2}
			// ＫＥＹ＿請求契約番号
			, {EKK0491A010CBSMsg.KEY_SEIKY_KEI_NO, sekyKeiNo}
			// ＫＥＹ＿請求契約番号
			, {EKK0491A010CBSMsg.KEY_RSV_APLY_YMD, JPCBPCommon.getOpeDate(null)}
		};
		// サービスIF実行
		CAANMsg[] ekk0491a010MsgList = callSC(handle, scCall, param, fixedText, ekk0491a010In)
				.getCAANMsgList(EKK0491A010CBSMsg.EKK0491A010CBSMSG1LIST);
	
		// 取得できない場合
		if (ekk0491a010MsgList != null)
		{
			for (CAANMsg caanMsg : ekk0491a010MsgList)
			{
				return caanMsg.getString(EKK0491A010CBSMsg1List.SEIKY_WAY_CD);
			}
		}
		return null;
	}

	/**
	 * マストステップ実施状況の取得 <br>
	 * @param muststepSbt マストステップ種別
	 * @param workMap 作業用マップ
	 * @return 表示不要
	 * @throws Throwable
	 */
	private boolean existsMuststep(String muststepSbt, Map<String, Object> work) throws Throwable
	{
		CAANMsg[] eck0321b010MsgList = (CAANMsg[])work.get(WORK_KEY_ECK0321B010CBSMSGLIST);

		if (eck0321b010MsgList != null)
		{
			for (CAANMsg cbsMsg : eck0321b010MsgList)
			{
				if (muststepSbt.equals(cbsMsg.getString(ECK0321B010CBSMsg1List.MSTSTEP_SBT_CD)))
				{
					return true;
				}
			}
		}

		return false;

	}

	/**
	 * マストステップ実施状況の登録 <br>
	 * @param handle セッションハンドル
	 * @param param リクエストパラメータ
	 * @param fixedText ユーザ定義文字列
	 * @param sysid SYSID
	 * @param svkeiKaisenUcwkNo サービス契約回線内訳番号
	 * @param muststepSbt マストステップ種別
	 * @return ＳＣ実行結果
	 */
	private void addMuststep(SessionHandle handle, IRequestParameterReadWrite param, String fixedText, String sysid, String svkeiKaisenUcwkNo, String muststepSbt) throws Throwable
	{
		// SC呼び出し部品のインスタンス生成
		ServiceComponentRequestInvoker scCall = new ServiceComponentRequestInvoker();

		// マストステップ実施状況登録
		String[][] eck0321d010 = {{ECK0321D010CBSMsg.TEMPLATEID, TEMPLATE_ID_ECK0321D010},
									{ECK0321D010CBSMsg.FUNC_CODE, JPCModelConstant.FUNC_CD_1},
									{ECK0321D010CBSMsg.SYSID, sysid},
									{ECK0321D010CBSMsg.SVC_KEI_KAISEN_UCWK_NO, svkeiKaisenUcwkNo},
									{ECK0321D010CBSMsg.MSTSTEP_SBT_CD, muststepSbt}};

		callSC(handle, scCall, param, fixedText, eck0321d010);
	}

	/**
	 * 項目エラー判定。<br />
	 * <pre>指定された項目のエラー情報がリクエストパラメータに存在するかどうかを調べる。</pre>
	 * @param param リクエストパラメータ
	 * @param templateId テンプレートID
	 * @param errFieldName エラーフィールド名 例) sysid_err
	 * @return true:エラーあり、false:エラーなし
	 * @throws RequestParameterException
	 */
	@SuppressWarnings("unchecked")
	private static boolean isErrorField(IRequestParameterReadWrite param, String templateId, String errFieldName) throws RequestParameterException
	{
		ArrayList<Object> errList = (ArrayList<Object>)param.getControlMapData(SCControlMapKeys.ERROR_INFO);
		for (Object errObj : errList)
		{
			Map errorInfoMap = (Map)errObj;
			if (templateId.equals(errorInfoMap.get(ErrorInfoMapKeys.TEMPLATE_ID)))
			{
				Map itemCheckErrorMap = (Map)errorInfoMap.get(ErrorInfoMapKeys.ITEM_CHECK_ERRORS);

				if (itemCheckErrorMap.containsKey(errFieldName))
				{
					return true;
				}
			}
		}
		return false;
	}
}
