/*********************************************************************
 * All Rights reserved,Copyright (c) K-Opticom, 2011
 **********************************************************************
 *＜プログラム内容＞
 *   システム名      ：eo顧客基幹システム
 *   モジュール名    ：JKKOpSvcKeiDslClCC
 *   ソースファイル名：JKKOpSvcKeiDslClCC.java
 *   作成者          ：富士通
 *   日付            ：2020年08月20日
 *＜機能概要＞
 *   オプションサービス契約解約取消部品
 *＜修正履歴＞
 *   バージョン  修正日       修正者      修正内容
 *   v50.00.00    2020/08/20   FJ）中原    新規作成【IT1-2020-0000046】多機能ルータ出荷後の番号回復であんしん発着信OPがサービス提供中にならなかった
 *   v50.00.01    2020/08/24   FJ)舘山     IT2-2020-0000014_横並び対応
 *   v71.00.00    2024/05/13   FJ)舘山    【#84334】HGW瑕疵内障害
 **********************************************************************/
package com.fujitsu.futurity.bp.custom.common;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import com.fujitsu.futurity.bp.custom.constant.JKKSvcConst;
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.IRequestParameterReadOnly;
import com.fujitsu.futurity.bp.x21.bpm.parameter.IRequestParameterReadWrite;
import com.fujitsu.futurity.bp.x21.cc.AbstractCommonComponent;
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.JCMConstants;
import com.fujitsu.futurity.common.x01.sc.SCControlMapKeys;
import com.fujitsu.futurity.mapping.bp.common.TemplateErrorUtil;
import com.fujitsu.futurity.model.base.CAANMsg;
import com.fujitsu.futurity.model.common.JCMAPLConstMgr;

import eo.common.constant.JKKStrConst;
import eo.common.constant.JPCModelConstant;
import eo.common.util.JKKCommonUtil;
import eo.ejb.cbs.cbsmsg.EDK0011B090CBSMsg;
import eo.ejb.cbs.cbsmsg.EDK0011B090CBSMsg1List;
import eo.ejb.cbs.cbsmsg.EKK0081A010CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK0341B002CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK0341B002CBSMsg1List;
import eo.ejb.cbs.cbsmsg.EKK0351C310CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK0371C040CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK0431C040CBSMsg;


/**
 * オプションサービス契約解約取消部品
 * <p>
 * <br>
 * オプションサービス契約解約取消時に呼び出される <br>
 * @author 富士通
 */
@SuppressWarnings("unchecked")
public class JKKOpSvcKeiDslClCC extends AbstractCommonComponent
{
	
	/** ----- 作業用クラスフィールド ----- **/
	private String oPE_DATE = "";
	
	/** ----- リクエストパラメータ定数 ----- **/
	/** サービス契約番号 **/
	private static final String SVC_KEI_NO = "svc_kei_no";
	
	/** 異動区分 **/
	private static final String IDO_DIV = "ido_div";

	/**************************************************************************/
	/** スキーマID定数                                                       **/
	/**************************************************************************/
	/** オプションサービス契約解約取消                   **/
	private static final String TEMPLATE_ID_EKK0351C310 = "EKK0431C040";
	/** サービス契約一意照会                             **/
	private static final String TEMPLATE_ID_EKK0081A010 = "EKK0081A010";
	/** 機器提供サービス契約一覧照会（サービス契約番号） **/
	private static final String TEMPLATE_ID_EKK0341B002 = "EKK0341B002";
	/** オプションサービス契約＜電話＞開始               **/
	private static final String TEMPLATE_ID_EKK0371C040 = "EKK0371C040";
	/** 契約機器配送対象物品一覧照会         **/
	private static final String TEMPLATE_ID_EDK0011B090 = "EDK0011B090";


	private static final Object[][] CONTENTS_LIST =
	{
		{TEMPLATE_ID_EKK0351C310, new EKK0431C040CBSMsg().getContents()},
		{TEMPLATE_ID_EKK0081A010, new EKK0081A010CBSMsg().getContents()},
		{TEMPLATE_ID_EKK0341B002, new EKK0341B002CBSMsg().getContents()},
		{TEMPLATE_ID_EKK0371C040, new EKK0371C040CBSMsg().getContents()},
		{TEMPLATE_ID_EDK0011B090, new EDK0011B090CBSMsg().getContents()},
	};

	/** ----- コード値定数 ----- **/
	/** 排他制御用更新日時 */
	private static final String EX_UPD_DTM = "ex_upd_dtm";

	/** エラーメッセージ */
	private static final String ERR_MSG = "INVALID_RETURN_MESSAGE";
	
	private static final boolean OUTPUT_LIST = true;
	private static final boolean OUTPUT_MSG  = false;
	private static final String ALLDATA_EKK0341B002 = "ALLDATA_EKK0341B002";

	/**
	 *　オプションサービス契約解約取消部品
	 * @param handle セッションマネージャなどを持ったハンドル
	 * @param param モデルグループ、コントロールマップを含むパラメータオブジェクト
	 * @param fixedText ユーザ任意文字列
	 * @return 業務データ取得・書込用I/F
	 * @throws Throwable
	 */
	public IRequestParameterReadWrite execute(SessionHandle handle, IRequestParameterReadWrite param, String fixedText) throws Throwable
	{
		
		HashMap<String, Object> requestParam = null;
		int statusCode = 0;
		
		//作業日の取得
		oPE_DATE = JCCBPCommon.getOpeDate(null);

		//リクエストパラメータの取得
		requestParam = analyzeRequestParam(param);
	
		//メイン処理開始
		statusCode = mainProc(
				handle, 
				param, 
				requestParam, 
				fixedText);
	
		if(statusCode != 0)
		{
			throw new CCException("", new SCCallException("", String.valueOf(statusCode), statusCode));
		}
		
		//リターンコードの設定
		param.setControlMapData(SCControlMapKeys.RETURN_CODE, String.valueOf(statusCode));
		
		//処理終了
		return param;
		
	}
	
	/**
	 * メイン処理
	 * @param handle セッションマネージャなどを持ったハンドル
	 * @param param モデルグループ、コントロールマップを含むパラメータオブジェクト
	 * @param requestParam リクエストパラメータ
	 * @param fixedText ユーザ任意文字列
	 * @return SIF呼び出し時のリターンコード
	 * @throws Throwable
	 */
	public int mainProc(
			SessionHandle handle, 
			IRequestParameterReadWrite param, 
			HashMap<String, Object> requestParam,
			String fixedText
	) throws Throwable
	{
		HashMap<String, Object> wkResultHash = null;

		int statusCode = 0;
		String svcKeiStat     = "";			// サービス契約ステータス
		String opSvcCd  = "";				// オプションサービスコード

		wkResultHash = new HashMap<String, Object>();
		
		/*************************************************************************************/
		/** オプションサービス契約解約取消                                                  **/
		/*************************************************************************************/
		statusCode = callEKK0351C310SC(param, handle, wkResultHash, requestParam);
		// 失敗していたらステータスコードを返却する
		if(statusCode != 0)
		{
			return statusCode;
		}
		// 排他制御用の更新日時を更新
		if (wkResultHash != null)
		{
			setSvKeiUpdDtm(requestParam, wkResultHash, TEMPLATE_ID_EKK0351C310);
		}
		/*************************************************************************************/
		/** サービス契約一意照会                                                            **/
		/*************************************************************************************/
		statusCode = callEKK0081A010SC(param, handle, requestParam, wkResultHash);

		// 失敗していたらステータスコードを返却する
		if (statusCode != 0)
		{
			return statusCode;
		}

		// サービス契約ステータスを取得
		Map<String, Object> svcKeiInfo = (Map<String, Object>)wkResultHash.get(TEMPLATE_ID_EKK0081A010);
		svcKeiStat = (String)svcKeiInfo.get("svc_kei_stat");

		// オプションサービスコード
		opSvcCd = (String)requestParam.get("op_svc_cd");

		// あんしん発着信サービスの場合、回復時にサービス提供中にする処理を追加
		// 親契約のステータスはサービス提供中以上で以下の処理を実施
		if ( JKKStrConst.OP_SVC_CD_ANSN_HCS_SVC.equals(opSvcCd) && JKKSvcConst.SVC_KEI_STAT_030.compareTo(svcKeiStat) < 0)
		{
			/*************************************************************************************/
			/** 機器提供サービス契約一覧照会（サービス契約番号）                                **/
			/*************************************************************************************/
			statusCode = callEKK0341B002SC(param, handle, requestParam, wkResultHash);

			// 失敗していたらステータスコードを返却する
			if(statusCode != 0)
			{
				return statusCode;
			}

			
			// 多機能ルータの含んだリストを取得
			CAANMsg[] kk0341b002CbsMsg1List = (CAANMsg[])wkResultHash.get(ALLDATA_EKK0341B002);
			

			// オプション開始可能かどうかチェックする
			if (isEnabledStartOption(handle, param, requestParam, kk0341b002CbsMsg1List)){
				/*************************************************************************************/
				/** オプションサービス契約＜電話＞開始                                              **/
				/*************************************************************************************/
				statusCode = callEKK0371C040SC(param, handle, requestParam, wkResultHash);

				// 失敗していたらステータスコードを返却する
				if (statusCode != 0)
				{
					return statusCode;
				}

				// 排他制御用の更新日時を更新
				if (wkResultHash != null)
				{
					setSvKeiUpdDtm(requestParam, wkResultHash, TEMPLATE_ID_EKK0371C040);
				}
			}
		}

		return statusCode;
	}



	
	/**
	 * リクエストパラメータの取得
	 * @param param モデルグループ、コントロールマップを含むパラメータオブジェクト
	 * @return リクエストパラメータのHash
	 * @throws RequestParameterException 例外時にスローされます
	 */
	private HashMap<String, Object> analyzeRequestParam(IRequestParameterReadWrite param) 
	throws RequestParameterException
	{
		
		HashMap<String, Object> paramData = null;

		//データの受け取り
		paramData = (HashMap<String, Object>)param.getData("KKSV0194136CC");

		return paramData;
		
	}


	/**
	 * 機器提供サービス契約一覧照会（サービス契約番号）SIFを呼び出し
	 * @param param リクエストパラメータ
	 * @param handle セッションハンドル
	 * @param inHash 条件用Hash
	 * @param resultHash 結果のハッシュ
	 * @return サービスインターフェースのリターンコード
	 * @throws RequestParameterException, SCException 例外時にスローされます
	 */
	private int callEKK0341B002SC(
			IRequestParameterReadWrite param,
			SessionHandle handle,
			HashMap<String, Object> inHash,
			HashMap<String, Object> resultHash)
			throws RequestParameterException, SCException
	{
		
		HashMap<String, Object> sIFRequest = null;
		CAANMsg[] resultMsgs = null;
		CAANMsg template = null;
		ServiceComponentRequestInvoker scCall = null;
		Map<?, ?> sIFResult = null;
		int status = 0;

		//サービスIF共通の情報を設定
		sIFRequest = editInMsgCmn(param);
		
		//EKK0341B002への呼び出しパラメータ設定
		template = new CAANMsg(EKK0341B002CBSMsg.class.getName());
		mappingEKK0341B002InMsg(template, inHash);
		editBasicCmn(param, template);
		
		//リクエスト用クラスの設定
		sIFRequest.put(JCMConstants.TEMPLATE_LIST_KEY, new CAANMsg[]{template});

		//SC呼び出しクラスの生成
		scCall = new ServiceComponentRequestInvoker();
		
		//SIFの呼び出し
		sIFResult = scCall.run(sIFRequest, handle);

		//結果の取得
		resultMsgs = (CAANMsg[])sIFResult.get(JCMConstants.TEMPLATE_LIST_KEY);
		
		//ステータスコードの取得
		status = template.getInt(JCMConstants.STATUS_INT_KEY);
		
		//ステータスが0以外はエラーとなっている
		if(status == 0)
		{
			// マップに全レコードを登録する
			resultHash.put(
					ALLDATA_EKK0341B002, 
					resultMsgs[0].getMsgData().get(EKK0341B002CBSMsg.EKK0341B002CBSMSG1LIST));
			
			
		}

		return status;
		
	}
	
	/**
	 * templateに対してEKK0341B002の条件に関する部分を設定する
	 * @param template 条件の設定先
	 * @param inHash 設定条件
	 * @param requestParam アプリ固有のパラメータ
	 */
	private void mappingEKK0341B002InMsg(CAANMsg template, HashMap<String, Object> inHash)
	{

		//まずは全条件のNullマッピング
		fillCAANMSGNullMapping(template, new EKK0341B002CBSMsg().getContents());
		
		//テンプレートID(SIFのID)
		template.set(EKK0341B002CBSMsg.TEMPLATEID, TEMPLATE_ID_EKK0341B002);

		//機能コード--回線対象サービス契約結合,カレント,契約変更中取得
		template.set(EKK0341B002CBSMsg.FUNC_CODE, "12");

		//ＫＥＹ＿サービス契約番号
		template.set(EKK0341B002CBSMsg.KEY_SVC_KEI_NO, inHash.get(SVC_KEI_NO));

		//ＫＥＹ＿機器提供サービスコード
		template.setNull(EKK0341B002CBSMsg.KEY_KKTK_SVC_CD);

		//ＫＥＹ＿機器提供サービス契約番号
		template.setNull(EKK0341B002CBSMsg.KEY_KKTK_SVC_KEI_NO);

		//ＫＥＹ＿ソート区分
		template.setNull(EKK0341B002CBSMsg.KEY_SORT_KBN);

	}
	

	/**
	 * @param requestParam
	 * @param wkResultHash
	 * @param templateId
	 */
	private void setSvKeiUpdDtm(Map<String, Object> requestParam, Map<String, Object> wkResultHash, String templateId)
	{
		String updDtm = getUpdDtm(wkResultHash, templateId);
		if (updDtm != null && !"".equals(updDtm))
		{
			requestParam.put(EX_UPD_DTM, updDtm);
		}
	}


	/**
	 * @param obj
	 * @param key
	 * @return
	 */
	private String getUpdDtm(Map<String, Object> obj, String key)
	{
		Map<String, Object> map = (HashMap<String, Object>)obj.get(key);
		return (String)map.get("upd_dtm");
	}



	/**
	 * <pre>
	 * サービスコンポーネント実行後に、IRequestParameterReadWriteに必要なデータをマッピングする
	 * 
	 * </pre>
	 * @param msgList CAANMsgクラス
	 * @param param 業務データ取得・書込用I/F
	 * @param fixedText ユーザ任意文字列
	 * @return 業務データ取得・書込用I/F
	 * @throws Throwable
	 */
	public IRequestParameterReadWrite editResultRP(
			Map<?, ?> msgList,
			IRequestParameterReadWrite param) 
			throws Throwable 
	{

		// SCからの戻り値からCAANMsgを取得する。
		CAANMsg[] templates = (CAANMsg[])msgList.get(JCMConstants.TEMPLATE_LIST_KEY);
		CAANMsg template = templates[0];

		// リターンコード取得
		Integer returnCode = (Integer)msgList.get(JCMConstants.RET_CD_INT_KEY);

		// テンプレートID、ステータス取得
		String templateId = template.getString(JCMConstants.TEMPLATE_ID_KEY);
		int templateStatus = template.getInt(JCMConstants.STATUS_INT_KEY);
		
		if (returnCode.intValue() != 0)
		{
			templateStatus = 9000;
		}
		if (JCMAPLConstMgr.getString("RETURN_MESSAGE_"
				+ String.format("%1$04d", templateStatus)) == null)
		{
			templateStatus = 0;
		}

		int bpStatus = 0;
		Object obj = param.getControlMapData(SCControlMapKeys.RETURN_CODE);
		if (obj == null)
		{
			bpStatus = -1;
		}
		else
		{
			bpStatus = Integer.parseInt((String)param.getControlMapData(SCControlMapKeys.RETURN_CODE));
		}

		if (templateStatus > bpStatus)
		{
			// BPにサービスコンポーネントのステータスを設定する。
			String formatStatus = String.format("%1$04d", templateStatus);
			String message = JCMAPLConstMgr.getString("RETURN_MESSAGE_"
					+ formatStatus);
			param.setControlMapData(SCControlMapKeys.RETURN_CODE, formatStatus);
			param.setControlMapData(SCControlMapKeys.RETURN_MESSAGE, message);
		}

		/* ユーザデータ情報 */
		HashMap inMap = (HashMap)param.getData("KKSV0194136CC");

		// ユーザデータ情報にエラー情報をマッピング
		// 項目の配列を取得
		Object[][] contents = getContents(templateId);
		// エラーIDをマッピング
		mappingErrId(inMap, template, contents);
		
		// 明細に対するマッピング処理
		// ※明細1のみ対応
		String msg1ListId = templateId + "CBSMsg1List";
		CAANMsg[] templateArray = template.getCAANMsgList(msg1ListId);
		if (templateArray != null)
		{
			ArrayList inList = (ArrayList)inMap.get(msg1ListId);
			if (inList == null)
			{
				inList = new ArrayList();
				inMap.put(msg1ListId, inList);
			}
			
			for (int i = 0; i < templateArray.length; i++)
			{
				if (i >= inList.size())
				{
					inList.add(new HashMap());
				}
			
				HashMap childMap = (HashMap)inList.get(i);
				CAANMsg childTemplate = templateArray[i];
				
				Object[][] msg1ListContents = getContents(msg1ListId);
				
				mappingErrId(childMap, childTemplate, msg1ListContents);
			}
		}
		
		//エラー情報のマップを取得
		ArrayList<Object> errList = (ArrayList<Object>)param.getControlMapData(SCControlMapKeys.ERROR_INFO);
		if(errList == null)
		{
			errList = new ArrayList<Object>();
		}
		
		// コントロールマップに設定
		param.setControlMapData(SCControlMapKeys.ERROR_INFO, TemplateErrorUtil.getErrorInfo(msgList, errList));

		return param;
	}
	
	/**
	 * 各S/IFのエラーIDをマッピングする
	 * 
	 * @param inMap 入力マップ
	 * @param template サービスIFマップ
	 * @param contents サービスIFの項目配列
	 */
	private void mappingErrId(
			HashMap inMap,
			CAANMsg template,
			Object[][] contents)
	{
		for(int i = 0 ; contents != null && i < contents.length ; i++)
		{
			String element = null;
			element = (String)contents[i][0];
			if (element.indexOf("_err") > 0)
			{
				if (!template.isNull(element))
				{
					if (!inMap.containsKey(element))
					{
						inMap.put(element, template.getString(element));
					}
				}
			}
		}
	}
	

	/**************************************************************************/
	/** サービス-I/F実行共通処理領域                                         **/
	/**************************************************************************/
	private int callSCCmn(
			IRequestParameterReadWrite param,
			SessionHandle handle,
			HashMap<String, Object> resultHash,
			CAANMsg template,
			HashMap<String, Object> sIFRequest,
			String templateId,
			String msg1ListKey,
			boolean listFlg
	) throws Throwable
	{
		ServiceComponentRequestInvoker scCall     = null;
		CAANMsg[]                      resultMsgs = null;
		Map<?, ?>                      sIFResult  = null;

		int status = 0;

		editBasicCmn(param, template);

		// リクエスト用クラスの設定
		sIFRequest.put(JCMConstants.TEMPLATE_LIST_KEY, new CAANMsg[]{template});

		// SC呼び出しクラスの生成
		scCall = new ServiceComponentRequestInvoker();

		// SIFの呼び出し
		sIFResult = scCall.run(sIFRequest, handle);

		// エラーマッピング処理
		editResultRP(sIFResult, param);
		errChk(sIFResult);

		// 結果の取得
		resultMsgs = (CAANMsg[])sIFResult.get(JCMConstants.TEMPLATE_LIST_KEY);

		// ステータスコードの取得
		status = template.getInt(JCMConstants.STATUS_INT_KEY);

		// ステータスが0以外はエラーとなっている
		if(status == 0)
		{
			if (listFlg)
			{
				resultHash.put(templateId, mappingOutMsgList(resultMsgs, msg1ListKey));
			}
			else
			{
				resultHash.put(templateId, mappingOutMsg(resultMsgs));
			}
		}

		return status;
	}

	/**
	 * サービスI/F実行用の共通部を設定します<br>
	 * <br>
	 * @param	param	(I) 業務データ取得用I/F
	 * @return			オプションサービス契約作成数
	 * @throws	RequestParameterException
	 */
	private HashMap<String, Object> editInMsgCmn(IRequestParameterReadOnly param) 
	throws RequestParameterException
	{
		HashMap<String, Object> paramMap = new HashMap<String, Object>();

		// 電文ID
		paramMap.put(JCMConstants.TRANZACTION_ID_KEY,    param.getTelegramID());
		// ユースケースID
		paramMap.put(JCMConstants.USECASE_ID_KEY,        param.getUsecaseID());
		// オペレーションID
		paramMap.put(JCMConstants.OPERATION_ID_KEY,      param.getOperationID());
		// サービス呼び出し区分
		paramMap.put(JCMConstants.CALL_TYPE_KEY,         param.getCallType());
		// 依頼先ホスト名
		paramMap.put(JCMConstants.CLIENT_HOST_NAME_KEY,  param.getControlMapData(SCControlMapKeys.REQ_HOSTNAME));
		// 依頼元IPアドレス
		paramMap.put(JCMConstants.CLIENT_IP_ADDRESS_KEY, param.getControlMapData(SCControlMapKeys.REQ_HOSTIP));
		// 依頼元画面ID
		paramMap.put(JCMConstants.INVOKE_GAMEN_ID_KEY,   param.getControlMapData(SCControlMapKeys.REQ_VIEWID));
		// オペレータID
		paramMap.put(JCMConstants.OPERATOR_ID_KEY,       param.getControlMapData(SCControlMapKeys.OPERATOR_ID));

		return paramMap;
	}

	/**
	 * 条件部の共通する項目の設定<br>
	 * <br>
	 * @param	param		リクエストパラメータ
	 * @param	template	条件の設定先
	 * @throws	RequestParameterException
	 */
	public void editBasicCmn(IRequestParameterReadOnly param, CAANMsg template)
	throws RequestParameterException
	{
		// オペレータID
		Object operatorId = param.getControlMapData(SCControlMapKeys.OPERATOR_ID);
		template.set(JCMConstants.OPERATOR_ID_KEY, operatorId);

		// 運用日付
		Object operateDate = param.getControlMapData(SCControlMapKeys.OPE_DATE);
		template.set(JCMConstants.OPERATE_DATE_KEY, operateDate);

		// 運用日時
		Object operateDateTime = param.getControlMapData(SCControlMapKeys.OPE_TIME);
		template.set(JCMConstants.OPERATE_DATETIME_KEY, operateDateTime);
	}

	/**
	 * 持ちうるフィールドにNullマッピングで埋める<br>
	 * <br>
	 * @param	msg			対象クラス
	 * @param	contents	対応クラスのフィールド列挙
	 */
	private void fillCAANMSGNullMapping(CAANMsg msg, Object[][] contents)
	{
		// 要素ごとのループ
		for(int i = 0 ; i < contents.length ; i++)
		{
			Object element = null;

			// キーに該当する箇所の取得
			element = contents[i][0];

			// Nullでマッピング
			msg.setNull((String)element);
		}
	}

	/**
	 * 結果をHashとして抽出する<br>
	 * <br>
	 * @param	resultMsgs	テンプレートリスト
	 * @param	msg1ListKey	
	 * @return				結果部分
	 */
	private HashMap<String, Object> mappingOutMsgList(CAANMsg[] resultMsgs, String msg1ListKey)
	{
		HashMap<String, Object> retHash = null;
		CAANMsg                 msg     = null;
		CAANMsg[]               msgList = null;

		// 結果の抽出
		msg = resultMsgs[0];

		// 結果の取得
		msgList = (CAANMsg[])msg.getMsgData().get(msg1ListKey);
		retHash = msgList[0].getMsgData();

		return retHash;
	}

	/**
	 * 結果をHashとして抽出する<br>
	 * <br>
	 * @param	resultMsgs	テンプレートリスト
	 * @param	msg1ListKey	
	 * @return				結果部分
	 */
	private HashMap<String, Object> mappingOutMsg(CAANMsg[] resultMsgs)
	{
		HashMap<String, Object> retHash = null;
		CAANMsg                 msg     = null;

		// 結果の抽出
		msg = resultMsgs[0];

		// 結果の取得
		retHash = msg.getMsgData();

		return retHash;
	}

	/**
	 * 各S/IFが保持する項目の配列を取得する<br>
	 * <br>
	 * @param	templateId	サービスIF_ID
	 * @return				項目の配列
	 */
	private Object[][] getContents(String templateId)
	{
		Object[][] contents = null;

		for (int i = 0; i < CONTENTS_LIST.length; i++)
		{
			if (((String)CONTENTS_LIST[i][0]).equals(templateId))
			{
				contents = (Object[][])CONTENTS_LIST[i][1];
				break;
			}
		}

		return contents;
	}

	/**
	 * エラーチェック処理
	 * 
	 * @param msgList サービスインタフェース実行結果
	 * return void
	 * @throws SCCallException 
	 */
	private void errChk(Map<?, ?> msgList) 
	throws SCCallException
	{
		CAANMsg[] templates = (CAANMsg[])msgList.get(JCMConstants.TEMPLATE_LIST_KEY);
		CAANMsg template = templates[0];

		// リターンコード取得
		int returnCode = (Integer)msgList.get(JCMConstants.RET_CD_INT_KEY);

		// ステータス
		int templateStatus = template.getInt(JCMConstants.STATUS_INT_KEY);

		if ((0 != returnCode) || (0 != templateStatus))
		{
			throw new SCCallException(ERR_MSG, String.valueOf(returnCode), templateStatus);
		}
	}

	/**
	 * EKK0081A010_サービス契約一意照会<br>
	 * <br>
	 * @param	param		リクエストパラメータ
	 * @param	handle		セッションハンドル
	 * @param	inHash		条件用Hash
	 * @param	resultHash	結果のハッシュ
	 * @return				サービスインターフェースのリターンコード
	 */
	private int callEKK0081A010SC(
			IRequestParameterReadWrite param,
			SessionHandle handle,
			HashMap<String, Object> inHash,
			HashMap<String, Object> resultHash
	) throws Throwable
	{
		HashMap<String, Object> sIFRequest = null;
		CAANMsg                 template   = null;

		int status = 0;

		// サービスIF共通の情報を設定
		sIFRequest = editInMsgCmn(param);

		// EKK0081A010への呼び出しパラメータ設定
		template = new CAANMsg(EKK0081A010CBSMsg.class.getName());
		mappingEKK0081A010InMsg(template, inHash);

		status = callSCCmn(
				param,
				handle,
				resultHash,
				template,
				sIFRequest,
				TEMPLATE_ID_EKK0081A010,
				EKK0081A010CBSMsg.EKK0081A010CBSMSG1LIST,
				OUTPUT_LIST
		);


		return status;
	}

	/**
	 * templateに対してEKK0081A010の条件に関する部分を設定する<br>
	 * <br>
	 * @param	template	条件の設定先
	 * @param	inHash		設定条件
	 */
	private void mappingEKK0081A010InMsg(CAANMsg template, HashMap<String, Object> inHash)
	{
		// まずは全条件のNullマッピング
		fillCAANMSGNullMapping(template, new EKK0081A010CBSMsg().getContents());

		// テンプレートID(SIFのID)
		template.set(EKK0081A010CBSMsg.TEMPLATEID, TEMPLATE_ID_EKK0081A010);

		// 機能コード--サービス契約一意照会(ここだけはカレント)
		template.set(EKK0081A010CBSMsg.FUNC_CODE,        JPCModelConstant.FUNC_CD_2);
		// ＫＥＹ＿サービス契約番号
		template.set(EKK0081A010CBSMsg.KEY_SVC_KEI_NO,   inHash.get(SVC_KEI_NO));
		// ＫＥＹ＿予約適用年月日
		template.set(EKK0081A010CBSMsg.KEY_RSV_APLY_YMD, oPE_DATE);
		// ＫＥＹ＿世代登録年月日時分（形だけの設定）
		template.set(EKK0081A010CBSMsg.KEY_GENE_ADD_DTM, oPE_DATE + "000000000");
	}

	/**
	 * EKK0371C040_オプションサービス契約＜電話＞開始<br>
	 * <br>
	 * @param	param					リクエストパラメータ
	 * @param	handle					セッションハンドル
	 * @param	inHash					条件用Hash
	 * @param	resultHash				結果のハッシュ
	 * @return							サービスインターフェースのリターンコード
	 * @throws Throwable 
	 */
	private int callEKK0371C040SC(
			IRequestParameterReadWrite param,
			SessionHandle handle,
			HashMap<String, Object> inHash,
			HashMap<String, Object> resultHash
	) throws Throwable
	{
		HashMap<String, Object> sIFRequest = null;
		CAANMsg                 template   = null;

		int status = 0;

		// サービスIF共通の情報を設定
		sIFRequest = editInMsgCmn(param);

		// EKK0371C040への呼び出しパラメータ設定
		template = new CAANMsg(EKK0371C040CBSMsg.class.getName());
		mappingEKK0371C040InMsg(template, inHash, resultHash);

		status = callSCCmn(
				param,
				handle,
				resultHash,
				template,
				sIFRequest,
				TEMPLATE_ID_EKK0371C040,
				null,
				OUTPUT_MSG
		);

		return status;
	}

	/**
	 * templateに対してEKK0371C040の条件に関する部分を設定する<br>
	 * <br>
	 * @param	template				条件の設定先
	 * @param	inHash					設定条件
	 * @param	resultHash				結果のハッシュ
	 */
	private void mappingEKK0371C040InMsg(
			CAANMsg template, 
			HashMap<String, Object> inHash ,
			HashMap<String, Object> resultHash
	)
	{
		// まずは全条件のNullマッピング
		fillCAANMSGNullMapping(template, new EKK0371C040CBSMsg().getContents());

		// テンプレートID(SIFのID)
		template.set(EKK0371C040CBSMsg.TEMPLATEID, TEMPLATE_ID_EKK0371C040);

		// 機能コード
		template.set(EKK0371C040CBSMsg.FUNC_CODE,     JPCModelConstant.FUNC_CD_1);
		// オプションサービス契約番号
		template.set(EKK0371C040CBSMsg.OP_SVC_KEI_NO, inHash.get(EKK0371C040CBSMsg.OP_SVC_KEI_NO));
		// 異動区分
		template.set(EKK0371C040CBSMsg.IDO_DIV,       inHash.get(IDO_DIV));
		// 更新年月日時分秒（更新前）
		template.set(EKK0371C040CBSMsg.UPD_DTM_BF,    inHash.get(EX_UPD_DTM));
	}

	/**
	 * EKK0351C310_オプションサービス契約解約取消 <br>
	 * <br>
	 * @param	param		リクエストパラメータ
	 * @param	handle		セッションハンドル
	 * @param	resultHash	結果のハッシュ
	 * @param	requestParam	リクエストパラメータ
	 * @return				サービスインターフェースのリターンコード
	 * @throws	Throwable	例外時にスローされます。
	 */
	private int callEKK0351C310SC(
			IRequestParameterReadWrite param,
			SessionHandle handle,
			HashMap<String, Object> resultHash,
			HashMap<String, Object> requestParam
	) throws Throwable
	{
		HashMap<String, Object> sIFRequest = null;
		CAANMsg                 template   = null;

		int status;

		// サービスIF共通の情報を設定
		sIFRequest = editInMsgCmn(param);

		// EKK0351C310への呼び出しパラメータ設定
		template = new CAANMsg(EKK0351C310CBSMsg.class.getName());
		mappinEKK0351C310SCInMsg(template, param, requestParam);

		status = callSCCmn(
				param,
				handle,
				resultHash,
				template,
				sIFRequest,
				TEMPLATE_ID_EKK0351C310,
				null,
				OUTPUT_MSG
		);

		return status;
	}

	/**
	 * templateに対してEKK0351C310の入力項目を設定する<br>
	 * <br>
	 * @param	template		条件の設定先
	 * @param	param			リクエストパラメータ
	 * @param	svcKeiNo		サービス契約番号
	 * @throws	RequestParameterException 
	 */
	private void mappinEKK0351C310SCInMsg(
			CAANMsg template,
			IRequestParameterReadWrite param,
			HashMap<String, Object> requestParam
	) throws RequestParameterException
	{
		// まずは全条件のNullマッピング
		fillCAANMSGNullMapping(template, new EKK0351C310CBSMsg().getContents());

		// テンプレートID(SIFのID)
		template.set(EKK0351C310CBSMsg.TEMPLATEID, TEMPLATE_ID_EKK0351C310);

		// 機能コード
		template.set(EKK0351C310CBSMsg.FUNC_CODE,      JPCModelConstant.FUNC_CD_1);
		// オプションサービス契約番号
		template.set(EKK0351C310CBSMsg.OP_SVC_KEI_NO, (String)requestParam.get("op_svc_kei_no"));
		// 申込明細番号
		template.set(EKK0351C310CBSMsg.MSKM_DTL_NO,  (String)requestParam.get("mskm_dtl_no"));
		// 異動区分
		template.set(EKK0351C310CBSMsg.IDO_DIV, (String)requestParam.get("ido_div"));
		// 更新年月日時分秒（更新前）
		template.set(EKK0351C310CBSMsg.UPD_DTM_BF,  (String)requestParam.get("upd_dtm_bf"));
	}

	/**
	 * オプションが開始可能かどうか返す
	 * <br>
	 * @param handle
	 * @param param
	 * @param requestParam
	 * @param ekk0341b002Cbs1MsgList
	 * @param kk0341b504
	 */
	private boolean isEnabledStartOption(
			SessionHandle handle, 
			IRequestParameterReadWrite param, 
			HashMap<String, Object> requestParam,
			CAANMsg[] ekk0341b002Cbs1MsgList) throws Throwable
	{
		String kktkSvcKeiNo = null;
		String kktkStat = null;
		if (ekk0341b002Cbs1MsgList != null && ekk0341b002Cbs1MsgList.length > 0)
		{
			// 機器リストには有効な多機能ルータしか存在しない。
			for(CAANMsg ekk0341b002 : ekk0341b002Cbs1MsgList)
			{
				String kkSvcCd = ekk0341b002.getString(EKK0341B002CBSMsg1List.KKTK_SVC_CD);
				
// ▽▽▽ #84334 ADD START
//				if (JKKStrConst.KKTK_SVC_CD_TAKINORT.equals(kkSvcCd))	// 多機能ルータ
				if (JKKStrConst.KKTK_SVC_CD_TAKINORT.equals(kkSvcCd) || JKKStrConst.KKTK_SVC_CD_HGW.equals(kkSvcCd))	// 多機能ルータ or HGW
// ▲▲▲ #84334 ADD END
				{
// ▽▽▽ #84334 ADD START
					// 取得済のステータスの方が進んでいれば、上書きしない
					if (kktkStat != null && kktkStat.compareTo(ekk0341b002.getString(EKK0341B002CBSMsg1List.KKTK_SVC_KEI_STAT)) > 0) 
					{
						continue;
					}
// ▲▲▲ #84334 ADD END
					kktkSvcKeiNo = ekk0341b002.getString(EKK0341B002CBSMsg1List.KKTK_SVC_KEI_NO);
					kktkStat = ekk0341b002.getString(EKK0341B002CBSMsg1List.KKTK_SVC_KEI_STAT);
				}
			}
		}
		
		
		// 機器のステータスをチェック
		if ( kktkStat != null && kktkSvcKeiNo != null )
		{
			if (JKKStrConst.CD00056_STAT_TEIKYO_CHU.equals(kktkStat) || 
				JKKStrConst.CD00056_STAT_KEI_KYUSHI_CHU.equals(kktkStat) ||
				JKKStrConst.CD00056_STAT_KEI_TEISHI_CHU.equals(kktkStat)
				)
			{
				// 機器のステータスが提供中であれば、工事完了もしくは配送完了しているため開始はさせる
				return true;
			}
			else
			{
				// 機器のレコードが取得できるいる場合は、配送状態を確認する
				// 型番／製番が入っているかでも確認可能かもしれないが、
				// 工事会社配送かどうかを判定する必要があるので仕方がない
				if (kktkSvcKeiNo != null && kktkSvcKeiNo.length() > 0)
				{
					HashMap<String, Object> wkResultHash = new HashMap<String, Object>();
					/*************************************************************************************/
					/** 契約機器配送対象物品一覧照会                                                    **/
					/*************************************************************************************/
					int statusCode = callEDK0011B090SC(param,handle,requestParam, wkResultHash, kktkSvcKeiNo);
					// 失敗していたらステータスコードを返却する
					if(statusCode != 0)
					{
						throw new CCException("", new SCCallException("", String.valueOf(statusCode), statusCode));
					}
					// 開始の条件は、配送完了済で工事会社配送以外
					ArrayList<HashMap<String, Object>> edk0011B090List = (ArrayList<HashMap<String, Object>>)wkResultHash.get(TEMPLATE_ID_EDK0011B090);
					
					for (HashMap<String, Object> ekk0011b090 : edk0011B090List)
					{
						// 配送済かつ、工事会社配送ではない（工事案件番号がNULL）
						if (JKKStrConst.HAISO_STAT_KANRYOU_ZM.equals(ekk0011b090.get(EDK0011B090CBSMsg1List.HAISO_STAT)) &&
// ▽▽▽ IT2-2020-0000014 Modify START
//							JKKCommonUtil.isNull(ekk0011b090.get(EDK0011B090CBSMsg1List.HISOS_KOCOMP_CD))
							JKKCommonUtil.isNull(ekk0011b090.get(EDK0011B090CBSMsg1List.KOJIAK_NO))
// △△△ IT2-2020-0000014 Modify END
							)
						{
							// 機器変更番号は見ない。（そもそも契約変更中の場合は、ステータスが提供中の為見なくて良い）
							return true;
						}
					}
				}
			}
		}
		else
		{
			// 本来は機器提供SV契約番号が取得できないことはない。（申込時点で機器が存在することは確認済の為）
			// デッドロジックになるかもしれないが、エラーとはしない。CCエラーにしておく
			throw new CCException("", new IllegalArgumentException("Not Found R0."));
		}
		return false;
	}

	/**
	 * 契約機器配送対象物品一覧照会SIFを呼び出し
	 * @param param リクエストパラメータ
	 * @param handle セッションハンドル
	 * @param inHash 条件用Hash
	 * @param resultHash 結果のハッシュ
	 * @return サービスインターフェースのリターンコード
	 * @throws RequestParameterException, SCException 例外時にスローされます
	 */
	private int callEDK0011B090SC(
			IRequestParameterReadWrite param,
			SessionHandle handle,
			HashMap<String, Object> inHash,
			HashMap<String, Object> resultHash,
			String kktkSvcCdTakinoR)
			throws RequestParameterException, SCException
	{
		
		HashMap<String, Object> sIFRequest = null;
		CAANMsg[] resultMsgs = null;
		CAANMsg template = null;
		ServiceComponentRequestInvoker scCall = null;
		Map<?, ?> sIFResult = null;
		int status = 0;

		//サービスIF共通の情報を設定
		sIFRequest = editInMsgCmn(param);
		
		//EDK0011B090への呼び出しパラメータ設定
		template = new CAANMsg(EDK0011B090CBSMsg.class.getName());
		mappingEDK0011B090InMsg(template, kktkSvcCdTakinoR);
		editBasicCmn(param, template);
		
		//リクエスト用クラスの設定
		sIFRequest.put(JCMConstants.TEMPLATE_LIST_KEY, new CAANMsg[]{template});

		//SC呼び出しクラスの生成
		scCall = new ServiceComponentRequestInvoker();
		
		//SIFの呼び出し
		sIFResult = scCall.run(sIFRequest, handle);

		//結果の取得
		resultMsgs = (CAANMsg[])sIFResult.get(JCMConstants.TEMPLATE_LIST_KEY);
		
		//ステータスコードの取得
		status = template.getInt(JCMConstants.STATUS_INT_KEY);
		
		//ステータスが0以外はエラーとなっている
		if(status == 0)
		{

			resultHash.put(
					TEMPLATE_ID_EDK0011B090, 
					mappingEDK0011B090SCOutMsg(resultMsgs));
			
		}

		return status;
		
	}
	
	/**
	 * templateに対してEDK0011B090の条件に関する部分を設定する
	 * @param template 条件の設定先
	 * @param inHash 設定条件
	 * @param kktkSvcKeiNo アプリ固有のパラメータ
	 */
	private void mappingEDK0011B090InMsg(CAANMsg template, String kktkSvcKeiNo)
	{

		//まずは全条件のNullマッピング
		fillCAANMSGNullMapping(template, new EDK0011B090CBSMsg().getContents());
		
		//テンプレートID(SIFのID)
		template.set(EDK0011B090CBSMsg.TEMPLATEID, TEMPLATE_ID_EDK0011B090);

		//機能コード--契約機器配送対象物品一覧照会

		template.set(EDK0011B090CBSMsg.FUNC_CODE, JPCModelConstant.FUNC_CD_1);

		//ＫＥＹ＿ＫＥＹ＿機器提供サービス契約番号
		template.set(EDK0011B090CBSMsg.KEY_KKTK_SVC_KEI_NO, kktkSvcKeiNo);
	}
	
	/**
	 * 契約機器配送対象物品一覧照会の結果をHashとして抽出する
	 * @param resultMsgs EDK0011B090のテンプレートリスト
	 * @return EDK0011B090の結果部分
	 */
	private ArrayList<HashMap<String, Object>> mappingEDK0011B090SCOutMsg(CAANMsg[] resultMsgs)
	{
		ArrayList<HashMap<String, Object>> retList = new ArrayList<HashMap<String, Object>>();
		CAANMsg msg = null;
		CAANMsg[] msgList = null;
		
		//結果の抽出
		msg = resultMsgs[0];
		
		//結果の取得
		msgList = 
			(CAANMsg[])msg.getMsgData().get(EDK0011B090CBSMsg.EDK0011B090CBSMSG1LIST);
		for (int i=0; i<msgList.length; i++)
		{
			HashMap<String, Object> retHash = msgList[0].getMsgData();
			retList.add(retHash);
		}
		
		return retList;
	}	

}
