/*********************************************************************
*	All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*	システム名		：eo顧客基幹システム
*	モジュール名	：JKKCmpMalwareBlockingApiCC
*	ソースファイル名：JKKCmpMalwareBlockingApiCC.java
*	作成者			：FJ)後藤
*	日付			：2020年3月25日
*＜機能概要＞
*	マルウェアブロッキング情報照会・更新(CMP)の共通コンポーネントクラスです。
*＜修正履歴＞
*	バージョン	修正日		修正者		修正内容
*   v49.00.00   2020/03/25   FJ)後藤   【ANK-3834-00-00】マルウェアブロッキング
*   v49.00.01	2020/04/20   FJ)舘山   【ANK-3834-00-00】マルウェアブロッキング
**********************************************************************/
package com.fujitsu.futurity.bp.custom.common;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;

import com.fujitsu.futurity.bp.custom.constant.JKKHakkoSODConstCC;
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.AbstractCommonComponent;
import com.fujitsu.futurity.bp.x21.cc.exception.CCException;
import com.fujitsu.futurity.bp.x21.cc.exception.SCCallException;
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 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.EKK0011D020CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK0011D020CBSMsg1List;
import eo.ejb.cbs.cbsmsg.EKK0021C060CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK0081A010CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK0081A010CBSMsg1List;
import eo.ejb.cbs.cbsmsg.EKK0091A010CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK0091A010CBSMsg1List;
import eo.ejb.cbs.cbsmsg.EKK0091C040CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK1091D010CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK1091D010CBSMsg1List;

/**
 * マルウェアブロッキング情報照会・更新(CMP)の共通コンポーネントクラスです。
 * <br>
 * @author FJ
 */
public class JKKCmpMalwareBlockingApiCC extends AbstractCommonComponent 
{
	/** テンプレートID　"EKK0081A010" */
	private static final String TEMPLATE_ID_EKK0081A010 = "EKK0081A010";
	/** テンプレートID　"EKK0091A010" */
	private static final String TEMPLATE_ID_EKK0091A010 = "EKK0091A010";
	/** テンプレートID　"EKK0091C040" */
	private static final String TEMPLATE_ID_EKK0091C040 = "EKK0091C040";
	/** テンプレートID　"EKK1091D010" */
	private static final String TEMPLATE_ID_EKK1091D010 = "EKK1091D010";
	/** テンプレートID　"EKK0011D020" */
	private static final String TEMPLATE_ID_EKK0011D020 = "EKK0011D020";
	/** テンプレートID　"EKK0021C060" */
	private static final String TEMPLATE_ID_EKK0021C060 = "EKK0021C060";
	
	/** CCパラメータ：サービス契約番号 */
	private static final String SVC_KEI_NO = "svc_kei_no";
	/** CCパラメータ：処理区分 */
	private static final String PROCESSING_TYPE = "processing_type";
	/** CCパラメータ：変更後ブロッキング設定 */
	private static final String REVISED_BLOCKING = "revised_blocking";

	/** 処理区分：参照 */
	private static final String PROCESSING_TYPE_REFERENCE = "1";
	/** 処理区分：更新 */
	private static final String PROCESSING_TYPE_UPDATE = "2";
	
	/**変更後ブロッキング設定；ブロッキングあり*/
	private static final String BLOCKING = "1";
	/**変更後ブロッキング設定：ブロッキングなし*/
	private static final String NON_BLOCKING = "2";
	
	/** CCパラメータ：エラー情報 */
	private static final String ERROR_INFO = "ERROR_INFO";
	/** CCパラメータ：エラーコード */
	private static final String ERROR_CODE = "errCode";
	/** CCパラメータ：エラーメッセージ */
	private static final String ERROR_MESSAGE = "errMessage";
	
	/** 空白 */
	private static final String EMPTY = "";

	/** 結果を設定するキー文字列*/
	private static final String RESULT_KEY = "result";
	
	/** ブロッキング状態を設定するキー文字列*/
	private static final String BLOCKING_VALUE_KEY = "blocking";

	/** 正常終了*/
	private static final String NORMAL_END = "0";

	/** マルウェアブロッキング無フラグ（ON）*/
	private static final String MALWARE_BLOCKING_NON_FLG_ON = "1";
	
	/** 更新時の異動区分 */
	private static final String UPDATE_IDO_DIV = "00033";
	
	/** 進捗ステータス */
	private static final String UPDATE_PRG_STATE = "1001";
	
	/**
	 * マルウェアブロッキング照会・更新のメイン処理
	 * @param handle ハンドル
	 * @param param パラメータ
	 * @param fixedText パラメータ取得文字
	 * @return 処理結果を設定したパラメータ
	 * @throws Throwable
	 */
	@SuppressWarnings("unchecked")
	public IRequestParameterReadWrite malwareBlockingMain(SessionHandle handle, IRequestParameterReadWrite param, String fixedText)
	throws Throwable
	{
		// マルウェアブロッキング情報照会・更新(CMP)CCマップ
		Map<String, Object> ccMsg = (Map<String, Object>)param.getData(fixedText);
		String processingType = (String) ccMsg.get(PROCESSING_TYPE);

		// 単項目チェック（エラーが発生した場合、エラーリストに返却値が登録される。）
		List<Map<String, String>> errList = getErrOfUnitParam(handle, param, fixedText, ccMsg, processingType);
		if (errList.size() > 0) 
		{
			ccMsg.put(ERROR_INFO, errList);
			param.setControlMapData(SCControlMapKeys.RETURN_CODE, JKKStrConst.RETURN_CD_5000);
			return param;
		}
		
		try {
			// パラメータのサービス契約番号からサービス契約を取得
			CAANMsg ekk0081a010 = getEKK0081A010(handle, param, fixedText);
			
			// 取得したサービス契約の値が対象かどうかを判定する。（エラーリストが登録されている場合はエラー）
			errList = getErrOfSvcKei(ekk0081a010, processingType);
			if (errList.size() > 0)
			{
				// サービス契約存在チェックエラー（番号不正もしくは、状態不正）
				ccMsg.put(ERROR_INFO, errList);
				param.setControlMapData(SCControlMapKeys.RETURN_CODE, JKKStrConst.RETURN_CD_5000);
				return param;
			}
			
			// パラメータのサービス契約番号からサービス契約<eo光ネット>を取得
			CAANMsg ekk0091a010 = getEKK0091A010( handle,  param,  fixedText);
			if (ekk0091a010 == null)
			{
				// 基本的のレコードが返却されないことはない。
				// もしサブタイプのレコードが取得できない場合、サービス契約番号のエラーとして返却する。
				errList = new ArrayList<Map<String, String>>();
				errList.add(getReqErrInfMap(SVC_KEI_NO));
				ccMsg.put(ERROR_INFO, errList);
				param.setControlMapData(SCControlMapKeys.RETURN_CODE, JKKStrConst.RETURN_CD_5000);
				return param;
			}
	
			// ブロッキング状態（カレント）
			String currentBlocking = null;
	
			// 更新 or 参照チェック
			if (StringUtils.equals(PROCESSING_TYPE_REFERENCE, processingType)) {
				// サービス契約<eo光ネット>の値を返却値に変換する
				if (MALWARE_BLOCKING_NON_FLG_ON.equals(ekk0091a010.getString(EKK0091A010CBSMsg1List.MALWARE_BLOCKING_NON_FLG)))
				{
					currentBlocking = NON_BLOCKING;		// ブロッキング無
				}
				else
				{
					currentBlocking = BLOCKING;			// "1"以外は、全てデフォルトと判断する。
				}
			} else if (StringUtils.equals(PROCESSING_TYPE_UPDATE, processingType)) {
				// マルウェアブロッキング無フラグを更新する。
				updateMalwareBlockingInfo( handle,  param,  fixedText, ekk0081a010, ekk0091a010);
				// 更新した結果をカレントの値として返却する。
				currentBlocking = (String)ccMsg.get(REVISED_BLOCKING);
			}
				
			// 返却値作成
			HashMap<String, Object> resMap = new HashMap<String, Object>();
			resMap.put(RESULT_KEY, NORMAL_END);		// ここまで処理された場合、正常終了として返却
			resMap.put(BLOCKING_VALUE_KEY, currentBlocking);
			param.setData(fixedText, resMap);		// 返却マップを入れ替える。返却値に余分なデータを渡さない
		}
		// サービスインターフェース呼び出しでエラーが発生した場合
		catch (SCCallException scCallEx) {
			// システムエラーを設定する
			param.setControlMapData(SCControlMapKeys.RETURN_CODE, JKKStrConst.RETURN_CD_9000);
			param.setControlMapData(SCControlMapKeys.RETURN_MESSAGE, JKKStrConst.RETURN_MESSAGE_SYSTEM_ERROR);
			throw new CCException("", scCallEx);
		}
		return param;
	}
	
	/**
	 * 単項目チェックを行い、エラーがある場合リストにエラーを登録して返却する。
	 * <br>
	 * @param handle ハンドル
	 * @param param パラメータ
	 * @param fixedText パラメータ取得文字
	 * @param ccMsg パラメータを保持するマップ
	 * @param processingType 処理区分
	 * @return エラーリスト
	 * @throws Throwable
	 */
	private List<Map<String, String>> getErrOfUnitParam(SessionHandle handle, IRequestParameterReadWrite param, String fixedText,
			Map<String, Object> ccMsg, String processingType) throws Throwable {
		// エラーリスト
		List<Map<String, String>> errList = new ArrayList<Map<String, String>>();

		String itemName = null;
		String itemValue = null;
		
		// サービス契約番号
		itemName = SVC_KEI_NO;
		itemValue = (String)ccMsg.get(itemName);
		// 必須チェック
		if ( JKKStringUtil.isNullBlank(itemValue) )
		{
			// 必須チェックエラー
			errList.add(getReqErrInfMap(itemName));
		}
		else if (!HalfCharCheck.isEnNumber1Check(itemValue))
		{
			// 属性チェックエラー
			errList.add(getFormErrInfMap(itemName));
		}
		else if (!LengthCheck.isLength1Check(itemValue, 10))
		{
			// 桁数チェックエラー
			errList.add(getLenErrInfMap(itemName));
		}
		
		// 処理区分
		itemName = PROCESSING_TYPE;
		itemValue = (String)ccMsg.get(itemName);

		// 必須チェック
		if ( JKKStringUtil.isNullBlank(itemValue) )
		{
			// 必須チェックエラー
			errList.add(getReqErrInfMap(itemName));
		}
		else if (!HalfCharCheck.isNumber1Check(itemValue))
		{
			// 属性チェックエラー
			errList.add(getFormErrInfMap(itemName));
		}
		else if (!LengthCheck.isLength1Check(itemValue, 1))
		{
			// 桁数チェックエラー
			errList.add(getLenErrInfMap(itemName));
		}
		else if (!(PROCESSING_TYPE_REFERENCE.equals(itemValue) || PROCESSING_TYPE_UPDATE.equals(itemValue)))
		{
			// 設定値がエラーの場合、属性チェックエラーとして返却
			errList.add(getFormErrInfMap(itemName));
		}

		// 変更後ブロッキング設定
		itemName = REVISED_BLOCKING;
		itemValue = (String)ccMsg.get(itemName);

		// 必須チェック(更新時のみ)
		if ( JKKStringUtil.isNullBlank(itemValue) && PROCESSING_TYPE_UPDATE.equals(processingType))
		{
			// 必須チェックエラー
			errList.add(getReqErrInfMap(itemName));
		}
		else if (!HalfCharCheck.isNumber1Check(itemValue))
		{
			// 属性チェックエラー
			errList.add(getFormErrInfMap(itemName));
		}
		else if (!LengthCheck.isLength1Check(itemValue, 1) && !JKKStringUtil.isNullBlank(itemValue))
		{
			// 桁数チェックエラー
			errList.add(getLenErrInfMap(itemName));
		}
		else if (!(BLOCKING.equals(itemValue) || NON_BLOCKING.equals(itemValue)) && !JKKStringUtil.isNullBlank(itemValue))
		{
			// 設定値がエラーの場合、属性チェックエラーとして返却
			errList.add(getFormErrInfMap(itemName));
		}

		return errList;
	}
	
	/**
	 * 入力されたサービス契約の情報が処理対象かどうかをチェックし、エラーの場合はリストにエラーを登録して返却する。
	 * @param ekk0081a010	サービス契約<eo光ネット>
	 * @param processingType	処理区分
	 * @return エラーリスト
	 * @throws Exception
	 */
	private List<Map<String, String>> getErrOfSvcKei(CAANMsg ekk0081a010, String processingType)
	throws Exception
	{
		// エラーリスト
		List<Map<String, String>> errList = new ArrayList<Map<String, String>>();

		// 取得件数が0件の場合、業務エラーを設定する
		if (ekk0081a010 == null)
		{
			
			// 業務エラー設定
			errList.add(getExistErrInfMap(SVC_KEI_NO));
		}
		else
		{
			// 料金グループコードチェック(02, 03, 04以外の場合にエラー)
			String prcGrpCd = nullToStr(ekk0081a010.getString(EKK0081A010CBSMsg1List.PRC_GRP_CD));
			if (!JKKStrConst.CD00133_02.equals(prcGrpCd) && !JKKStrConst.CD00133_03.equals(prcGrpCd) 
					&& !JKKStrConst.CD00133_04.equalsIgnoreCase(prcGrpCd)) {
				
				// 業務エラー設定
				errList.add(getExistErrInfMap(SVC_KEI_NO));
			}
			// 更新の場合のみサービス契約ステータスチェックを実施する
			else if (StringUtils.equals(PROCESSING_TYPE_UPDATE, processingType)) {
				String svcKeiStat = nullToStr(ekk0081a010.getString(EKK0081A010CBSMsg1List.SVC_KEI_STAT));
				if (JKKStrConst.CD00037_UK_ZM.equals(svcKeiStat) || JKKStrConst.CD00037_DSL_ZM.equals(svcKeiStat) 
						|| JKKStrConst.CD00037_CANCEL_ZM.equals(svcKeiStat)) {
					
					// 業務エラー設定
					errList.add(getExistErrInfMap(SVC_KEI_NO));
				}
			}
			
		}
		return errList;
	}
	
	/**
	 * サービス契約を検索しレコードを返す。
	 * @param handle	ハンドル
	 * @param param		パラメータ
	 * @param fixedText	パラメータ取得文字
	 * @return サービス契約のレコード
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	private CAANMsg getEKK0081A010(SessionHandle handle, IRequestParameterReadWrite param, String fixedText) throws Throwable 
	{
		// サービスIF（EKK0081A010）の実行
		Map<String, Object> ccMsg = (Map<String, Object>)param.getData(fixedText);
		
		// SC呼び出し部品のインスタンス生成（引数にはログに出力するクラス名を渡す。空文字を設定した場合はログに出力されない）
		ServiceComponentRequestInvoker scCall = new ServiceComponentRequestInvoker();
		
		// サービス契約取得の上りマッピング
		Object[][] ekk0081A010In =
		{
			{EKK0081A010CBSMsg.TEMPLATEID, TEMPLATE_ID_EKK0081A010},
			{EKK0081A010CBSMsg.FUNC_CODE, JPCModelConstant.FUNC_CD_2},
			{EKK0081A010CBSMsg.KEY_SVC_KEI_NO, ccMsg.get(SVC_KEI_NO)},
			{EKK0081A010CBSMsg.KEY_RSV_APLY_YMD, JCCBPCommon.getOpeDate(null)}
		};
		
		// サービスIF実行
		CAANMsg ekk0081a010Msg = callSC(handle, scCall, param, fixedText, ekk0081A010In, new EKK0081A010CBSMsg().getContents());
		
		// 実行結果取得
		CAANMsg[] ekk0081a010Msg1List = ekk0081a010Msg.getCAANMsgList(EKK0081A010CBSMsg.EKK0081A010CBSMSG1LIST);
		if (ekk0081a010Msg1List != null && ekk0081a010Msg1List.length > 0)
		{
			return ekk0081a010Msg1List[0];
			
		}
		// サービス契約が存在しない
		return null;
	}

	/**
	 * サービス契約<eo光ネット>を検索しレコードを返す。
	 * @param handle	ハンドル
	 * @param param		パラメータ
	 * @param fixedText	パラメータ取得文字
	 * @return サービス契約<eo光ネット>のレコード
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	private CAANMsg getEKK0091A010(SessionHandle handle, IRequestParameterReadWrite param, String fixedText) throws Throwable 
	{
		// サービスIF（EKK0091A010）の実行
		Map<String, Object> ccMsg = (Map<String, Object>)param.getData(fixedText);
		
		// SC呼び出し部品のインスタンス生成（引数にはログに出力するクラス名を渡す。空文字を設定した場合はログに出力されない）
		ServiceComponentRequestInvoker scCall = new ServiceComponentRequestInvoker();
		
		// サービス契約取得の上りマッピング
		Object[][] ekk0091A010In =
		{
			{EKK0091A010CBSMsg.TEMPLATEID, TEMPLATE_ID_EKK0091A010},
			{EKK0091A010CBSMsg.FUNC_CODE, JPCModelConstant.FUNC_CD_2},
			{EKK0091A010CBSMsg.KEY_SVC_KEI_NO, ccMsg.get(SVC_KEI_NO)},		// サービス契約
		};
		
		// サービスIF実行
		CAANMsg ekk0091a010Msg = callSC(handle, scCall, param, fixedText, ekk0091A010In, new EKK0091A010CBSMsg().getContents());
		
		// 実行結果取得
		CAANMsg[] ekk0091a010Msg1List = ekk0091a010Msg.getCAANMsgList(EKK0091A010CBSMsg.EKK0091A010CBSMSG1LIST);
		if (ekk0091a010Msg1List != null && ekk0091a010Msg1List.length > 0)
		{
			return ekk0091a010Msg1List[0];
			
		}
		// データが壊れていない限りこの返却値は帰らない。
		return null;
	}

	/**
	 * マルウェアブロッキング無フラグを更新し、SODHakkoCCを呼出し後、進捗を登録する。
	 * @param handle	ハンドル
	 * @param param		パラメータ
	 * @param fixedTextパラメータ取得文字
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	private void updateMalwareBlockingInfo(SessionHandle handle, IRequestParameterReadWrite param, String fixedText, CAANMsg ekk0081a010, CAANMsg ekk0091a010) throws Throwable
	{
		Map<String, Object> ccMsg = (Map<String, Object>)param.getData(fixedText);

		// SC呼び出し部品のインスタンス生成（引数にはログに出力するクラス名を渡す。空文字を設定した場合はログに出力されない）
		ServiceComponentRequestInvoker scCall = new ServiceComponentRequestInvoker();

		// 申込明細番号を取得
		String mskmDtlNo = insertMskm(handle, param, fixedText, ekk0081a010.getString(EKK0081A010CBSMsg1List.SYSID));
		if (mskmDtlNo == null)
		{
			// 登録出来ない場合、既存の申込明細番号を引継ぐ？
			mskmDtlNo = ekk0081a010.getString(EKK0081A010CBSMsg1List.MSKM_DTL_NO);
		}
		// マルウェアブロッキング無フラグ
		String malwareBlockingNashiF = null;
		if (NON_BLOCKING.equals(ccMsg.get(REVISED_BLOCKING)))
		{
			malwareBlockingNashiF = MALWARE_BLOCKING_NON_FLG_ON;
		}
		
		// サービスIF（EKK0091C040）の実行（更新処理）
		Object[][] ekk0091C040In =
		{
			{EKK0091C040CBSMsg.TEMPLATEID, 				TEMPLATE_ID_EKK0091C040},
			{EKK0091C040CBSMsg.FUNC_CODE, 				JPCModelConstant.FUNC_CD_1},											// チェック＆登録
			{EKK0091C040CBSMsg.SVC_KEI_NO, 				ekk0081a010.getString(EKK0081A010CBSMsg1List.SVC_KEI_NO)}, 				// サービス契約番号
			{EKK0091C040CBSMsg.MSKM_DTL_NO, 			mskmDtlNo},																// 申込明細番号
			{EKK0091C040CBSMsg.SEIRI_NO, 				ekk0081a010.getString(EKK0081A010CBSMsg1List.SEIRI_NO)},				// 整理番号
			{EKK0091C040CBSMsg.MENKAIHAT_ANKEN_NO, 		ekk0081a010.getString(EKK0081A010CBSMsg1List.MENKAIHAT_ANKEN_NO)},		// 面開発案件番号
			{EKK0091C040CBSMsg.SVC_USE_STA_KIBO_YMD, 	ekk0081a010.getString(EKK0081A010CBSMsg1List.SVC_USE_STA_KIBO_YMD)},	// サービス利用開始希望年月日
			{EKK0091C040CBSMsg.ID_SOKHOSHO_OUTPUT_YH,	ekk0081a010.getString(EKK0081A010CBSMsg1List.ID_SOKHOSHO_OUTPUT_YH)},	// ID速報書出力要否
			{EKK0091C040CBSMsg.SKEKKA_CD, 				ekk0081a010.getString(EKK0081A010CBSMsg1List.SKEKKA_CD)},				// 審査結果コード
			{EKK0091C040CBSMsg.SKEKKA_DTL_CD, 			ekk0081a010.getString(EKK0081A010CBSMsg1List.SKEKKA_DTL_CD)},			// 審査結果詳細コード
			{EKK0091C040CBSMsg.SKEKKA_HOKI_CD, 			ekk0081a010.getString(EKK0081A010CBSMsg1List.SKEKKA_HOKI_CD)},			// 審査結果補記コード
			{EKK0091C040CBSMsg.SKEKKA_SEND_CD,			ekk0081a010.getString(EKK0081A010CBSMsg1List.SKEKKA_SEND_CD)},			// 審査結果送信コード

			{EKK0091C040CBSMsg.PAYWAY_KEIZOKU_FLG, 		ekk0081a010.getString(EKK0081A010CBSMsg1List.PAYWAY_KEIZOKU_FLG)},		//支払い方法継続フラグ
			{EKK0091C040CBSMsg.FTRIAL_KANYU_YMD, 		ekk0081a010.getString(EKK0081A010CBSMsg1List.FTRIAL_KANYU_YMD)},		//試用加入年月日
			{EKK0091C040CBSMsg.FTRIAL_PRD_ENDYMD, 		ekk0081a010.getString(EKK0081A010CBSMsg1List.FTRIAL_PRD_ENDYMD)},		//試用期間終了年月日
			{EKK0091C040CBSMsg.HONKANYU_YMD, 			ekk0081a010.getString(EKK0081A010CBSMsg1List.HONKANYU_YMD)},			//本加入年月日
			{EKK0091C040CBSMsg.HONKANYU_IKO_KIGEN_YMD, 	ekk0081a010.getString(EKK0081A010CBSMsg1List.HONKANYU_IKO_KIGEN_YMD)},	// 本加入移行期限年月日
			{EKK0091C040CBSMsg.LETTER_HASSO_SHIWAKE_DIV, ekk0081a010.getString(EKK0081A010CBSMsg1List.LETTER_HASSO_SHIWAKE_DIV)},	// レター発送仕分区分
			{EKK0091C040CBSMsg.THNX_LETTER_SHS_CD, 		ekk0081a010.getString(EKK0081A010CBSMsg1List.THNX_LETTER_SHS_CD)},		//サンキューレター送付先コード
			{EKK0091C040CBSMsg.WEB_OP_ADD_FAIL_FLG, 	ekk0081a010.getString(EKK0081A010CBSMsg1List.WEB_OP_ADD_FAIL_FLG)},		// WEBオプション追加不可フラグ
			{EKK0091C040CBSMsg.CHMT_HJIN_EO_YKAE_SVKEI_NO, ekk0081a010.getString(EKK0081A010CBSMsg1List.CHMT_HJIN_EO_YKAE_SVKEI_NO)},	// 変更元法人eo読替サービス契約番号
			{EKK0091C040CBSMsg.PNLTY_HASSEI_CD, 		ekk0081a010.getString(EKK0081A010CBSMsg1List.PNLTY_HASSEI_CD)},			// 違約金発生コード

			{EKK0091C040CBSMsg.IDO_DIV, 				UPDATE_IDO_DIV},	// 異動区分
			{EKK0091C040CBSMsg.INTR_CD, 				ekk0081a010.getString(EKK0081A010CBSMsg1List.INTR_CD)},					// 紹介コード
			{EKK0091C040CBSMsg.IDO_NG_STAT_CD, 			ekk0081a010.getString(EKK0081A010CBSMsg1List.IDO_NG_STAT_CD)},			// 異動NG状態コード
			{EKK0091C040CBSMsg.WORK_RRK_BIKO, 			ekk0081a010.getString(EKK0081A010CBSMsg1List.WORK_RRK_BIKO)},			// 業務連絡備考
			{EKK0091C040CBSMsg.AUTO_SHOSA_TRAN_STAT_CD, ekk0081a010.getString(EKK0081A010CBSMsg1List.AUTO_SHOSA_TRAN_STAT_CD)},	// 自動照査処理状態コード
			{EKK0091C040CBSMsg.UPD_DTM_BF, 				ekk0081a010.getString(EKK0081A010CBSMsg1List.LAST_UPD_DTM)},			// 更新年月日時分秒(更新前)

			{EKK0091C040CBSMsg.KOTEI_IP_AD_HKTGI_UM, 	ekk0091a010.getString(EKK0091A010CBSMsg1List.KOTEI_IP_AD_HKTGI_UM)},	// 固定IPアドレス引継ぎ有無
			{EKK0091C040CBSMsg.PC_PACK_UM, 				ekk0091a010.getString(EKK0091A010CBSMsg1List.PC_PACK_UM)},				// PCパック有無
			{EKK0091C040CBSMsg.MALWARE_BLOCKING_NON_FLG, malwareBlockingNashiF},	// マルウェアブロッキング無しフラグ

		};
		// サービスIF実行
		CAANMsg ekk0091c040Msg = callSC(handle, scCall, param, fixedText, ekk0091C040In, new EKK0091C040CBSMsg().getContents());
		
		// 登録後のチェックは特に行わない。
		
		// FTTH認証SOD発行（JKKHakkoSODCC）
		JKKHakkoSODCC sodCC = new JKKHakkoSODCC();
		HashMap<String, Object> workMap = new HashMap<String, Object>();
		ArrayList<Object> targetList = new ArrayList<Object>();
		HashMap<String, Object> sod_map = new HashMap<String, Object>();

		// 処理区分は登録
		workMap.put(JCMConstants.FUNC_CODE_KEY, JPCModelConstant.FUNC_CD_1);

		// 基本情報を設定する
		HashMap<String, Object> sod_kihon_info = new HashMap<String, Object>();
		sod_kihon_info.put("sysid", ekk0081a010.getString(EKK0081A010CBSMsg1List.SYSID)); 	// SYSID
		sod_kihon_info.put(JKKHakkoSODConstCC.INFO_MALWARE_BLOCKING_DIV, "1");				// マルウェアブロッキング

		// 契約情報を設定する
		HashMap<String, Object> svc_kei_info = new HashMap<String, Object>();
		svc_kei_info.put("svc_kei_no", ekk0081a010.getString(EKK0081A010CBSMsg1List.SVC_KEI_NO)); // サービス契約番号

		// 階層の作成
		sod_map.put(JKKHakkoSODConstCC.SOD_KIHON_INFO, sod_kihon_info);
		sod_map.put(JKKHakkoSODConstCC.SVC_KEI_INFO, svc_kei_info);
		targetList.add(sod_map);
		workMap.put(JKKHakkoSODConstCC.TRGT_DATA_LIST, targetList);

		// パラメータに情報を設定する
		String wkFixedText = fixedText + "01";
		param.setData(wkFixedText, workMap);
		// CCの実行
		sodCC.hakkoSOD(handle, param, wkFixedText);
		
		// 進捗を登録する
		String blockingNm = "有";
		if (MALWARE_BLOCKING_NON_FLG_ON.equals(ekk0091a010.getString(EKK0091A010CBSMsg1List.MALWARE_BLOCKING_NON_FLG)))
		{
			blockingNm = "無";
		}
		
		Object[][] ekk1091D010In =
		{
			{EKK0091C040CBSMsg.TEMPLATEID, 	TEMPLATE_ID_EKK1091D010},
			{EKK0091C040CBSMsg.FUNC_CODE, 	JPCModelConstant.FUNC_CD_1},								// チェック＆登録
			{EKK1091D010CBSMsg.MSKM_DTL_NO, mskmDtlNo},													// 申込明細番号
			{EKK1091D010CBSMsg.SVC_KEI_NO, 	ekk0081a010.getString(EKK0081A010CBSMsg1List.SVC_KEI_NO)},	// サービス契約番号
			{EKK1091D010CBSMsg.IDO_DIV, 	UPDATE_IDO_DIV},											// 異動区分
			{EKK1091D010CBSMsg.IDO_DTM, 	JCCBPCommon.getSysDateTimeStamp()},							// 異動年月日時分秒
			{EKK1091D010CBSMsg.PRG_STAT, 	UPDATE_PRG_STATE},											// 進捗ステータス
			{EKK1091D010CBSMsg.PRG_MEMO, 	""},														// 進捗メモ
			{EKK1091D010CBSMsg.PRG_TKJK_1, 	"マルウェア通信遮断(変更前)" + blockingNm},					// 進捗特記事項１
			{EKK1091D010CBSMsg.PRG_TKJK_2, 	""},														// 進捗特記事項２
		};

		// サービスIF実行
		CAANMsg ekk1091d010Msg = callSC(handle, scCall, param, fixedText, ekk1091D010In, new EKK1091D010CBSMsg().getContents());

		// 登録後のチェックは特に行わない。
	}

	/**
	 * 申込を登録し、申込明細番号を返却する。
	 * <br>
	 * @param handle		ハンドル
	 * @param param			パラメータ
	 * @param fixedText		パラメータ取得文字
	 * @param sysid			SYSID
	 * @return 登録した申込の申込明細番号
	 * @throws Throwable
	 */
	@SuppressWarnings("unchecked")
	private String insertMskm(SessionHandle handle, IRequestParameterReadWrite param, String fixedText, String sysid) throws Throwable
	{

		// SC呼び出し部品のインスタンス生成（引数にはログに出力するクラス名を渡す。空文字を設定した場合はログに出力されない）
		ServiceComponentRequestInvoker scCall = new ServiceComponentRequestInvoker();
		
		Object[][] ekk0011d020CBSMsg1ListIn = {				
				{EKK0011D020CBSMsg1List.MKM_UK_SBT_CD, ""},				// 申込内容承認登録明細.申込受付種別コード
				{EKK0011D020CBSMsg1List.MSKMSHO_TRAT_IF_TNTSHA_NM, ""},	// 申込内容承認登録明細.申込書取扱情報担当者名
				{EKK0011D020CBSMsg1List.MSKMSHO_TRAT_IF_TELNO, ""},		// 申込内容承認登録明細.申込書取扱情報電話番号
				{EKK0011D020CBSMsg1List.KEI_HUKA_CD, ""},				// 申込内容承認登録明細.契約付加コード
				{EKK0011D020CBSMsg1List.HNIN_CFM_ATICLE_NM, ""},		// 本人確認書類名
				{EKK0011D020CBSMsg1List.MSKMSHO_NO, ""},				// 申込内容承認登録明細.申込書番号
				{EKK0011D020CBSMsg1List.MSKMSHO_DTL_NO, ""},			// 申込書明細番号
		};
		CAANMsg[] ekk0011d020cbsmsg1list = createCAANMsgList(EKK0011D020CBSMsg1List.class.getName(), ekk0011d020CBSMsg1ListIn);
		Object[][] ekk0011D020In = {
				{EKK0011D020CBSMsg.TEMPLATEID, 					TEMPLATE_ID_EKK0011D020},
				{EKK0011D020CBSMsg.FUNC_CODE, 					JPCModelConstant.FUNC_CD_1},		// チェック＆登録
				{EKK0011D020CBSMsg.SYSID, 						sysid},								// ■ＳＹＳＩＤ
				{EKK0011D020CBSMsg.MSKM_SBT_CD, 				"00027"},							// ■申込種別コード 
				{EKK0011D020CBSMsg.MSKM_UK_DTM, 				JCCBPCommon.getSysDateTimeStamp()},	// ■申込受付年月日時分秒 
				{EKK0011D020CBSMsg.MSKM_YMD, 					JCCBPCommon.getOpeDate(null)},		// ■申込年月日 
				{EKK0011D020CBSMsg.CONSMBSN_MSKM_STAT_SKBT_CD, 	"04"},								// ■コンシューマ営業用申込状態識別コード 
				{EKK0011D020CBSMsg.EKK0011D020CBSMSG1LIST, 		ekk0011d020cbsmsg1list},			// 申込内容承認登録明細
		};
		
		// サービスIF実行
		CAANMsg ekk0011d020Msg = callSC(handle, scCall, param, fixedText, ekk0011D020In, new EKK0011D020CBSMsg().getContents());
		CAANMsg[] ekk0011d020cbsmsg1List = ekk0011d020Msg.getCAANMsgList(EKK0011D020CBSMsg.EKK0011D020CBSMSG1LIST);
		
		if (ekk0011d020cbsmsg1List != null && ekk0011d020cbsmsg1List.length > 0)
		{
		
			// 申込明細照査・後続業務依頼
			Object[][] ekk0021C060In = {
					{EKK0021C060CBSMsg.TEMPLATEID, 	TEMPLATE_ID_EKK0021C060},
					{EKK0021C060CBSMsg.FUNC_CODE, 	JPCModelConstant.FUNC_CD_1},		// チェック＆登録
					{EKK0021C060CBSMsg.MSKM_DTL_NO, ekk0011d020cbsmsg1List[0].getString(EKK0011D020CBSMsg1List.MSKM_DTL_NO)},	// ■申込明細番号
					{EKK0021C060CBSMsg.UPD_DTM_BF, 	ekk0011d020Msg.getString(EKK0011D020CBSMsg.UPD_DTM)},						// ■更新年月日時分秒（更新前） 
					{EKK0021C060CBSMsg.IDO_DIV, 	UPDATE_IDO_DIV},															// ■異動区分 
					{EKK0021C060CBSMsg.KZKWRK_REQYMD, JCCBPCommon.getOpeDate(null)},											// 後続業務依頼年月日
			};
			CAANMsg ekk0021c060Msg = callSC(handle, scCall, param, fixedText, ekk0021C060In, new EKK0021C060CBSMsg().getContents());
		
			return ekk0011d020cbsmsg1List[0].getString(EKK0011D020CBSMsg1List.MSKM_DTL_NO);
		}
		return null;
	}
	
	/**
	 * 単項目チェックの必須エラーマップ作成メソッドです。
	 * 
	 * @param itemName 項目名
	 * @return エラーメッセージのマップ
	 */
	private Map<String, String> getExistErrInfMap(String itemName)
	{
		Map<String, String> returnMap = new HashMap<String, String>();
		
		returnMap.put(ERROR_CODE, JKKStrConst.RETURN_CD_2001);
		returnMap.put(ERROR_MESSAGE, "");
		
		return returnMap;
	}

	/**
	 * 単項目チェックの必須エラーマップ作成メソッドです。
	 * 
	 * @param itemName 項目名
	 * @return エラーメッセージのマップ
	 */
	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);
		
		return returnMap;
	}
	
	/**
	 * 単項目チェックの属性エラーマップ作成メソッドです。
	 * 
	 * @param itemName 項目名
	 * @return エラーメッセージのマップ
	 */
	private Map<String, String> getFormErrInfMap(String itemName)
	{
		Map<String, String> returnMap = new HashMap<String, String>();
		
		returnMap.put(ERROR_CODE, JKKStrConst.RETURN_CD_1002);
		returnMap.put(ERROR_MESSAGE, itemName);
		
		return returnMap;
	}
	
	/**
	 * 単項目チェックの桁数エラーマップ作成メソッドです。
	 * 
	 * @param itemName 項目名
	 * @return エラーメッセージのマップ
	 */
	private Map<String, String> getLenErrInfMap(String itemName)
	{
		Map<String, String> returnMap = new HashMap<String, String>();
		
		returnMap.put(ERROR_CODE, JKKStrConst.RETURN_CD_1003);
		returnMap.put(ERROR_MESSAGE, itemName);
		
		return returnMap;
	}
	
	/**
	 * SC(サービスインターフェイス）を呼び出す。
	 * @param handle セッションハンドル
	 * @param scCall SC呼び出し部品
	 * @param param リクエストパラメータ
	 * @param dataMapKey パラメータキー
	 * @param mappingData マッピングデータ
	 * @param contents CAANMsgのコンテンツ
	 * @return CAANMsg
	 * @throws Throwable 例外が発生した場合
	 */
	@SuppressWarnings("unchecked")
	private CAANMsg callSC(SessionHandle handle, ServiceComponentRequestInvoker scCall, IRequestParameterReadWrite param, String dataMapKey,
			Object[][] mappingData, Object[][] contents)
	throws Throwable
	{
		HashMap<String, Object> paramMap = editInMsg(param, mappingData);

		Map<?, ?> result = scCall.run(paramMap, handle);

		CAANMsg[] templates = (CAANMsg[])result.get(JCMConstants.TEMPLATE_LIST_KEY);

		CAANMsg msg = templates[0];

		// リターンコード取得
		Object return_code = result.get(JCMConstants.RET_CD_INT_KEY);

		editErrorInfoCom(param, templates, (Integer)return_code, dataMapKey, mappingData, contents);

		// エラー情報のマップを取得
		ArrayList<Object> errList = (ArrayList<Object>)param.getControlMapData(SCControlMapKeys.ERROR_INFO);
		int status = msg.getInt(JCMConstants.STATUS_INT_KEY);

		if (null == errList)
		{
			errList = new ArrayList<Object>();
		}

		// コントロールマップに設定
		param.setControlMapData(SCControlMapKeys.ERROR_INFO, TemplateErrorUtil.getErrorInfo(result, errList));

		// SCCallExceptionはスローしない
		// 異常の場合、SCCallExceptionを生成してスローする
		if(!("0".equals(return_code.toString()) && 0 == status))
		{
			throw new SCCallException("戻り値不正", return_code.toString(), status);
		}

		return msg;
	}
	
	/**
	 * 共通項目のメッセージを作成します。
	 * @param param リクエストパラメータ
	 * @param mappingData マッピングデータ
	 * @return HashMap<String, Object>
	 * @throws RequestParameterException リクエストパラメータの操作でエラーが発生した場合
	 */
	private HashMap<String, Object> editInMsg(IRequestParameterReadWrite param, Object[][] mappingData) 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));

		String svcIf = (String)mappingData[0][1];

		CAANMsg template = new CAANMsg(String.format("eo.ejb.cbs.cbsmsg.%sCBSMsg", svcIf));

		// オペレータID
		template.set(JCMConstants.OPERATOR_ID_KEY, param.getControlMapData(SCControlMapKeys.OPERATOR_ID));

		// 運用日付
		template.set(JCMConstants.OPERATE_DATE_KEY, param.getControlMapData(SCControlMapKeys.OPE_DATE));

		// 運用日時
		template.set(JCMConstants.OPERATE_DATETIME_KEY, param.getControlMapData(SCControlMapKeys.OPE_TIME));
		
		for (int i = 0; i < mappingData.length; i++)
		{
			if (mappingData[i][1] == null || "".equals(mappingData[i][1]))
			{
				template.setNull((String)mappingData[i][0]);
			}
			else
			{
				if (mappingData[i][1].getClass().isArray())
				{
					template.set((String)mappingData[i][0], (CAANMsg[])mappingData[i][1]);
				}
				else
				{
					template.set((String)mappingData[i][0], mappingData[i][1]);
				}
			}
		}

		CAANMsg[] templates = new CAANMsg[1];

		templates[0] = template;

		paramMap.put(JCMConstants.TEMPLATE_LIST_KEY, templates);

		return paramMap;
	}

	/**
	 * サービスIFのサブリストを作成する。
	 * <br>
	 * @param classNm		サブリストのクラス名
	 * @param mappingData	マッピングデータ
	 * @return CAANMsgの配列
	 */
	private CAANMsg[] createCAANMsgList(String classNm, Object[][] mappingData)
	{
		CAANMsg template = new CAANMsg(classNm);
		for (int i = 0; i < mappingData.length; i++)
		{
			if ("".equals(mappingData[i][1]))
			{
				template.setNull((String)mappingData[i][0]);
			}
			else
			{
				template.set((String)mappingData[i][0], mappingData[i][1]);
			}
		}
		return new CAANMsg[] {template};
	}
	
	/**
	 * エラー情報を取得します。
	 * @param param リクエストパラメータ
	 * @param templates CAANMsgクラス
	 * @param returnCode リターンコード
	 * @param dataMapKey パラメータキー
	 * @param mappingData マッピングデータ
	 * @param contents CAANMsgのコンテンツ
	 * @return IRequestParameterReadWrite
	 * @throws RequestParameterException リクエストパラメータの操作でエラーが発生した場合
	 */
	@SuppressWarnings("unchecked")
	private IRequestParameterReadWrite editErrorInfoCom(IRequestParameterReadWrite param, CAANMsg[] templates, int returnCode, String dataMapKey,
			Object[][] mappingData, Object[][] contents)
	throws RequestParameterException
	{
		CAANMsg template = templates[0];

		int templateStatus = template.getInt(JCMConstants.STATUS_INT_KEY);
		
		if (0 != returnCode)
		{
			templateStatus = 9000;
		}

		if (null == JCMAPLConstMgr.getString("RETURN_MESSAGE_" + String.format("%1$04d", templateStatus)))
		{
			templateStatus = 0;
		}

		int bpStatus = 0;

		Object obj = param.getControlMapData(SCControlMapKeys.RETURN_CODE);
		
		if (null == obj)
		{
			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);
		}

		Map<String, String> inMap = null;

		// ユーザデータ情報
		inMap = (Map<String, String>)param.getData(dataMapKey);

		for (int i = 0; null != contents && i < contents.length ; i++)
		{
			String itemNm = (String)contents[i][0];
			if (itemNm.endsWith("_err"))
			{
				String errCd = (String)template.getString(itemNm);
				if (!JKKStringUtil.isNullBlank(errCd))
				{
					inMap.put(itemNm, errCd);
				}
			}
		}
		return param;
	}
	
	/**
	 * 項目名がnullかチェックする
	 * @param str 項目名
	 * @return 項目名
	 */
	private String nullToStr(String str)
	{
		if(str == null)
		{
			str = EMPTY;
		}
		return str;
	}
}
