/*********************************************************************
*	All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*	システム名		：eo顧客基幹システム
*	モジュール名	：JKKAddKeishaInfoEdenCC
*	ソースファイル名：JKKAddKeishaInfoEdenCC.java
*	作成者			：FJ)藤本
*	日付			：2017年09月26日
*＜機能概要＞
*	契約者情報登録(eden)の共通コンポーネントクラスです。
*＜修正履歴＞
*	バージョン	修正日		修正者		修正内容
*   v34.00.00   2017/09/26   FJ) 藤本  【ANK-3210-00-00】【eo電気】電気単独対応（STEP3）
*   v34.01.00   2017/10/25   FJ) 藤本  【IT1-2017-0000126】住所存在チェックのエラーがレスポンスに設定されない
*
**********************************************************************/
package com.fujitsu.futurity.bp.custom.common;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
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.AbstractCommonComponent;
import com.fujitsu.futurity.bp.x21.cc.exception.CCException;
import com.fujitsu.futurity.common.JCMConstants;
import com.fujitsu.futurity.common.x01.sc.ErrorInfoMapKeys;
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.JCKStrConst;
import eo.common.constant.JKKStrConst;
import eo.common.constant.JPCModelConstant;
import eo.common.util.JKKStringUtil;
import eo.ejb.cbs.cbsmsg.ECK0021D010CBSMsg;
import eo.ejb.cbs.cbsmsg.ECK0031D010CBSMsg;
import eo.ejb.cbs.cbsmsg.ECK0031D010CBSMsg1List;
import eo.ejb.cbs.cbsmsg.ECK0141B002CBSMsg;
import eo.ejb.cbs.cbsmsg.ECK0141B002CBSMsg1List;
import eo.ejb.cbs.cbsmsg.ECK0141D010CBSMsg;
import eo.ejb.cbs.cbsmsg.ECK0201D010CBSMsg;


/**
 * 契約者情報登録(eden)の共通コンポーネントクラスです。
 * <br>
 * @author FJ
 */
public class JKKAddKeishaInfoEdenCC extends AbstractCommonComponent
{
	/** テンプレートID：お客様＜個人＞登録 */
	private static final String TEMPLATE_ID_ECK0021D010 = "ECK0021D010";
	/** テンプレートID：お客様＜法人＞登録 */
	private static final String TEMPLATE_ID_ECK0031D010 = "ECK0031D010";
	/** テンプレートID：連絡先登録 */
	private static final String TEMPLATE_ID_ECK0201D010 = "ECK0201D010";
	/** テンプレートID：オプトインメール一覧照会 */
	private static final String TEMPLATE_ID_ECK0141B002 = "ECK0141B002";
	/** テンプレートID：オプトインメール受信設定登録 */
	private static final String TEMPLATE_ID_ECK0141D010 = "ECK0141D010";

	/** リターンメッセージ取得キー */
	private static final String RETURN_MESSAGE_STRING = "RETURN_MESSAGE_";
	/** リターンメッセージの書式指定文字列 */
	private static final String RETURN_MESSAGE_FORMAT = "%1$04d";
	/** リターンコード(正常)  */
	private static final int RETURN_CODE_NORMAL = 0;
	/** エラー項目接尾辞 */
	private static final String ERRITEM_SUFFIX = "_err";

	/** サービスコンポーネントエラー発生時のエラー文字列 */
	private static final String SC_ERROR_STRING = "サービスコンポーネントエラー";

	/** エラー固定文字列：E1 */
	private static final String E1_ERR = "E1";
	/** エラー固定文字列：E2 */
	private static final String E2_ERR = "E2";
	/** エラー固定文字列：E3 */
	private static final String E3_ERR = "E3";
	/** エラー固定文字列：E4 */
	private static final String E4_ERR = "E4";
	/** エラー固定文字列：E5 */
	private static final String E5_ERR = "E5";
	/** エラー固定文字列：E6 */
	private static final String E6_ERR = "E6";
	/** エラー固定文字列：EA */
	private static final String EA_ERR = "EA";
	/** ワーニング固定文字列：WA */
	private static final String WA_WAR = "WA";
	/** ワーニング固定文字列：WB */
	private static final String WB_WAR = "WB";

	/** 作業用マップのキー：運用日 */
	private static final String WORK_MAP_KEY_OPEDATE = "opeDate";
	/** 作業用マップのキー：更新年月日時分秒(お客様) */
	private static final String WORK_MAP_KEY_UPD_DTM_CUST = "updDtmCust";
	/** 作業用マップのキー：SYSID */
	private static final String WORK_MAP_KEY_SYSID = "sysid";

	/** 契約者住所チェックレベル：最下層チェック無 */
	private static final String KEISHA_AD_CHK_LV_NO_LOWEST = "2";

	/** オプトインメール番号：セキュリティーに関するお知らせ */
	private static final String OPTINM_NO_SECINFO = "104";
	/** オプトインメール番号：プロバイダサービスに関するお知らせ */
	private static final String OPTINM_NO_PVSVINFO = "105";
	/** オプトインメール番号：新サービスのご案内 */
	private static final String OPTINM_NO_NEWSVINFO = "106";
	/** オプトインメール番号：お得な情報、サービス、キャンペーンに関するお知らせ */
	private static final String OPTINM_NO_SVCPINFO = "107";

	/** コード値リスト：契約者タイプコード(1：個人／2：法人／3：保守用／4：自社利用) */
	private static final String[] KEISHA_TYPE_CD_LIST = {"1", "2", "3", "4"};
	/** コード値リスト：お客様性別コード(1：男性／2：女性／3：不明) */
	private static final String[] CUST_SEX_CD_LIST = {"1", "2", "3"};
	/** コード値リスト：契約者住所手動入力フラグ(0：手動入力でない／1：手動入力である) */
	private static final String[] KEISHA_AD_MAN_INPUT_FLG_LIST = {"0", "1"};
	/** コード値リスト：連絡手段コード(null：なし／01：ＦＡＸ／02：電子メール／03：ＦＡＸまたは電子メール／04：代理人／05：遠隔サポート条件あり／99：その他) */
	private static final String[] RRK_WAY_CD_LIST = {"01", "02", "03", "04", "05", "99"};
	/** コード値リスト：会員種別コード(00：非eo会員) */
	private static final String[] MEMBER_SBT_CD_LIST = {"00"};
	/** コード値リスト：内販外販コード(001：外販／002：内販) */
	private static final String[] NAIHAN_GAIHAN_CD_LIST = {"001", "002"};
	/** コード値リスト：関電G個人情報取扱同意有無(null：未聴取／1：有／0：無) */
	private static final String[] KEPG_KJNIF_TRAT_DOI_UM_LIST = {"1", "0"};
	/** コード値リスト：関電G個人情報提供不可フラグ(null：未聴取／1：提供不可／0：提供可) */
	private static final String[] KEPG_KJNIFT_FFG_LIST = {"1", "0"};
	/** コード値リスト：法人格種別コード(00：指定なし／01：株式会社／02：有限会社／03：合資会社／04：合名会社／05：社団法人／06：財団法人／07：医療法人／08：宗教法人／09：学校法人／10：社会福祉法人／11：相互会社／12：連合会／13：共済組合／14：協同組合／15：生命保険／16：海上火災保険／17：火災海上保険／18：健康保険組合／19：国民健康保険組合／20：国民健康保険団体連合会／21：厚生年金基金／22：社会保険診療報酬支払基金／23：生活協同組合／24：食糧販売協同組合／25：農業協同組合／26：経済農業協同組合連合会／27：共済農業協同組合連合会／28：漁業協同組合／29：漁業協同組合連合会／30：公共職業安定所／31：労働組合／32：特定非営利活動法人) */
	private static final String[] HOJIN_SBT_CD_LIST = {"00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32"};
	/** コード値リスト：法人格前後指定コード(0：前／1：後／2：なし) */
	private static final String[] HOJIN_ZENGO_SHITEI_CD_LIST = {"0", "1", "2"};
	/** コード値リスト：業種コード(201：農林水産鉱業／202：建設業／203：製造業／204：電気・ガス業／205：運輸・通信業／206：卸売・小売・飲食業／207：金融・保険・不動産業／208：サービス業／209：官公庁／210：医療／211：その他業種) */
	private static final String[] GSHU_CD_LIST = {"201", "202", "203", "204", "205", "206", "207", "208", "209", "210", "211"};
	/** コード値リスト：セキュリティに関するお知らせ希望有無(1：有／0：無) */
	private static final String[] SECINFO_JSNST_UM_LIST = {"1", "0"};
	/** コード値リスト：プロバイダサービスに関するお知らせ希望有無(1：有／0：無) */
	private static final String[] PVSVINFO_JSNST_UM_LIST = {"1", "0"};
	/** コード値リスト：新サービスのご案内希望有無(1：有／0：無) */
	private static final String[] NEWSVINFO_JSNST_UM_LIST = {"1", "0"};
	/** コード値リスト：お得な情報、サービス、キャンペーンに関するお知らせ希望有無(1：有／0：無) */
	private static final String[] SVCPINFO_JSNST_UM_LIST = {"1", "0"};

	/** 最大桁数(文字数)：お客様名 */
	private static final int MAX_SIZE_CUST_NM = 45;
	/** 最大桁数(文字数)：お客様カナ名 */
	private static final int MAX_SIZE_CUST_KANA = 45;

	/**
	 * 契約者情報を登録します。
	 * <br>
	 * @param handle セッションハンドル
	 * @param param リクエストパラメータ
	 * @param fixedText ユーザ定義文字列
	 * @return リクエストパラメータ
	 * @throws Throwable 例外が発生した場合
	 */
	public IRequestParameterReadWrite addKeisha(SessionHandle handle, 
													IRequestParameterReadWrite param, 
													String fixedText) throws Throwable
	{
		// 契約者情報登録マップ
		Map<String, Object> ccMsg = (Map<String, Object>)param.getData(fixedText);

		// 単項目チェック
		checkSingleItem(param, ccMsg);
		// リターンコードチェック
		checkReturnCode(param);

		// 単関連チェック
		checkItemRelation(param, ccMsg);
		// リターンコードチェック
		checkReturnCode(param);

		// 作業用マップ
		Map<String, String> work = new HashMap<String, String>();
		// 運用日
		work.put(WORK_MAP_KEY_OPEDATE, JPCBPCommon.getOpeDate(null));

		// お客様登録
		addCust(handle, param, fixedText, ccMsg, work);

		// 連絡先登録
		addRrks(handle, param, fixedText, ccMsg, work);

		// レスポンス項目設定
		setResponse(ccMsg, work);

		return param;
	}

	/**
	 * BPチェック用パラメータ作成します。<br />
	 * @param handle セッションハンドル
	 * @param param リクエストパラメータ
	 * @param fixedText ユーザ定義文字列
	 * @return BPチェック用パラメータ
	 */
	public HashMap<?, ?> getInvokeCBS(SessionHandle handle, IRequestParameterReadWrite param, String fixedText)
	{
		// BPチェックはスキップする
		return JCKPmpScParamHenshu.createBpNotCheckParam();
	}

	/**
	 * ＢＰチェック結果を編集します。<br />
	 * @param param リクエストパラメータ
	 * @param caanMsgs サービスインターフェイス用のパラメータ配列
	 * @param returnCode リターンコード
	 * @return リクエストパラメータ
	 * @throws Throwable 例外が発生した場合
	 */
	public IRequestParameterReadWrite editErrorInfo(IRequestParameterReadWrite param, CAANMsg[] caanMsgs, Integer returnCode) throws Throwable
	{
		return JCKPmpScParamHenshu.editErrorInfo(param, caanMsgs, returnCode);
	}

	/**
	 * 単項目チェックを行います。
	 * <br>
	 * @param param リクエストパラメータ
	 * @param ccMsg 契約者情報登録マップ
	 * @throws Throwable 例外が発生した場合
	 */
	private void checkSingleItem(IRequestParameterReadWrite param, Map<String, Object> ccMsg)
	throws Throwable
	{
		// チェック結果
		boolean isError = false;
		List<Object> errList = new ArrayList<Object>();
		Map<String, Object> errorMap = new HashMap<String, Object>();
		Map<String, String> errorMapChild = new HashMap<String, String>();

		// 契約者タイプコードの必須チェック
		if (checkNotNull(ccMsg, errorMapChild, "keisha_type_cd"))
		{
			isError = true;
		}
		// 契約者住所コードの必須チェック
		if (checkNotNull(ccMsg, errorMapChild, "keisha_ad_cd"))
		{
			isError = true;
		}
		// 契約者郵便番号の必須チェック
		if (checkNotNull(ccMsg, errorMapChild, "keisha_pcd"))
		{
			isError = true;
		}
		// 契約者番地号の必須チェック
		if (checkNotNull(ccMsg, errorMapChild, "keisha_bnchigo"))
		{
			isError = true;
		}
		// 契約者住所手動入力フラグの必須チェック
		if (checkNotNull(ccMsg, errorMapChild, "keisha_ad_man_input_flg"))
		{
			isError = true;
		}
		// 契約者電話番号の必須チェック
		if (checkNotNull(ccMsg, errorMapChild, "keisha_telno"))
		{
			isError = true;
		}

		// 契約者タイプコードのコード値不整合チェック
		if (checkCode(ccMsg, errorMapChild, "keisha_type_cd", KEISHA_TYPE_CD_LIST))
		{
			isError = true;
		}
		// お客様性別コードのコード値不整合チェック
		if (checkCode(ccMsg, errorMapChild, "cust_sex_cd", CUST_SEX_CD_LIST))
		{
			isError = true;
		}
		// 契約者住所手動入力フラグのコード値不整合チェック
		if (checkCode(ccMsg, errorMapChild, "keisha_ad_man_input_flg", KEISHA_AD_MAN_INPUT_FLG_LIST))
		{
			isError = true;
		}
		// 連絡手段コードのコード値不整合チェック
		if (checkCode(ccMsg, errorMapChild, "rrk_way_cd", RRK_WAY_CD_LIST))
		{
			isError = true;
		}
		// 会員種別コードのコード値不整合チェック
		if (checkCode(ccMsg, errorMapChild, "member_sbt_cd", MEMBER_SBT_CD_LIST))
		{
			isError = true;
		}
		// 内販外販コードのコード値不整合チェック
		if (checkCode(ccMsg, errorMapChild, "naihan_gaihan_cd", NAIHAN_GAIHAN_CD_LIST))
		{
			isError = true;
		}
		// 関電G個人情報取扱同意有無のコード値不整合チェック
		if (checkCode(ccMsg, errorMapChild, "kepg_kjnif_trat_doi_um", KEPG_KJNIF_TRAT_DOI_UM_LIST))
		{
			isError = true;
		}
		// 関電G個人情報提供不可フラグのコード値不整合チェック
		if (checkCode(ccMsg, errorMapChild, "kepg_kjnift_ffg", KEPG_KJNIFT_FFG_LIST))
		{
			isError = true;
		}
		// 法人格種別コードのコード値不整合チェック
		if (checkCode(ccMsg, errorMapChild, "hojin_sbt_cd", HOJIN_SBT_CD_LIST))
		{
			isError = true;
		}
		// 法人格前後指定コードのコード値不整合チェック
		if (checkCode(ccMsg, errorMapChild, "hojin_zengo_shitei_cd", HOJIN_ZENGO_SHITEI_CD_LIST))
		{
			isError = true;
		}
		// 業種コードのコード値不整合チェック
		if (checkCode(ccMsg, errorMapChild, "gshu_cd", GSHU_CD_LIST))
		{
			isError = true;
		}
		// セキュリティに関するお知らせ希望有無のコード値不整合チェック
		if (checkCode(ccMsg, errorMapChild, "secinfo_jsnst_um", SECINFO_JSNST_UM_LIST))
		{
			isError = true;
		}
		// プロバイダサービスに関するお知らせ希望有無のコード値不整合チェック
		if (checkCode(ccMsg, errorMapChild, "pvsvinfo_jsnst_um", PVSVINFO_JSNST_UM_LIST))
		{
			isError = true;
		}
		// 新サービスのご案内希望有無のコード値不整合チェック
		if (checkCode(ccMsg, errorMapChild, "newsvinfo_jsnst_um", NEWSVINFO_JSNST_UM_LIST))
		{
			isError = true;
		}
		// お得な情報、サービス、キャンペーンに関するお知らせ希望有無のコード値不整合チェック
		if (checkCode(ccMsg, errorMapChild, "svcpinfo_jsnst_um", SVCPINFO_JSNST_UM_LIST))
		{
			isError = true;
		}

		// お客様名の桁数チェック
		if (checkSize(ccMsg, errorMapChild, "cust_nm", MAX_SIZE_CUST_NM))
		{
			isError = true;
		}
		// お客様カナ名の桁数チェック
		if (checkSize(ccMsg, errorMapChild, "cust_kana", MAX_SIZE_CUST_KANA))
		{
			isError = true;
		}

		// エラーが存在する場合はエラー値を設定
		if (isError)
		{
			String formatStatus = String.format(RETURN_MESSAGE_FORMAT, JPCModelConstant.SINGLEDATA_ERR);
			String message = JCMAPLConstMgr.getString(RETURN_MESSAGE_STRING + formatStatus);
			param.setControlMapData(SCControlMapKeys.RETURN_CODE, formatStatus);
			param.setControlMapData(SCControlMapKeys.RETURN_MESSAGE, message);

			errorMap.put(ErrorInfoMapKeys.RETURN_CODE, RETURN_CODE_NORMAL);
			errorMap.put(ErrorInfoMapKeys.TEMPLATE_ID, "JKKAddKeishaInfoEdenCC");
			errorMap.put(ErrorInfoMapKeys.STATUS, JPCModelConstant.SINGLEDATA_ERR);
			errorMap.put(ErrorInfoMapKeys.ITEM_CHECK_ERRORS, errorMapChild);
			errList.add(errorMap);

			param.setControlMapData(SCControlMapKeys.ERROR_INFO, errList);
		}
	}

	
	/**
	 * 単関連チェックを行います。
	 * <br>
	 * @param param リクエストパラメータ
	 * @param ccMsg 契約者情報登録マップ
	 * @throws Throwable 例外が発生した場合
	 */
	private void checkItemRelation(IRequestParameterReadWrite param, Map<String, Object> ccMsg)
	throws Throwable
	{
		// チェック結果
		boolean isError = false;
		List<Object> errList = new ArrayList<Object>();
		Map<String, Object> errorMap = new HashMap<String, Object>();
		Map<String, String> errorMapChild = new HashMap<String, String>();

		// お客様が個人の場合
		if (isCustKojin(ccMsg))
		{
			// お客様名の必須チェック
			if (checkNotNull(ccMsg, errorMapChild, "cust_nm"))
			{
				isError = true;
			}
			// お客様カナ名の必須チェック
			if (checkNotNull(ccMsg, errorMapChild, "cust_kana"))
			{
				isError = true;
			}
			// お客様性別コードの必須チェック
			if (checkNotNull(ccMsg, errorMapChild, "cust_sex_cd"))
			{
				isError = true;
			}
			// お客様生年月日の必須チェック
			if (checkNotNull(ccMsg, errorMapChild, "cust_birthd"))
			{
				isError = true;
			}
		}
		else
		{
			// 法人格種別コードの必須チェック
			if (checkNotNull(ccMsg, errorMapChild, "hojin_sbt_cd"))
			{
				isError = true;
			}
			// 法人格前後指定コードの必須チェック
			if (checkNotNull(ccMsg, errorMapChild, "hojin_zengo_shitei_cd"))
			{
				isError = true;
			}
			// 会社名の必須チェック
			if (checkNotNull(ccMsg, errorMapChild, "comp_nm"))
			{
				isError = true;
			}
			// 会社カナ名の必須チェック
			if (checkNotNull(ccMsg, errorMapChild, "comp_kana"))
			{
				isError = true;
			}
		}

		// 内販外販コードが「内販」の場合
		if (JKKStrConst.CD00682_002.equals((String)ccMsg.get("naihan_gaihan_cd")))
		{
			// 内販企業識別コードの必須チェック
			if (checkNotNull(ccMsg, errorMapChild, "naihan_comp_skbt_cd"))
			{
				isError = true;
			}
		}

		// 関電G個人情報取扱同意有無が「有」の場合
		if (JKKStrConst.CD_DIV_UM_ARI.equals((String)ccMsg.get("kepg_kjnif_trat_doi_um")))
		{
			// 関電G個人情報取扱同意年月日の必須チェック
			if (checkNotNull(ccMsg, errorMapChild, "kepg_kjnif_trat_doi_ymd"))
			{
				isError = true;
			}
			// 関電G個人情報提供不可フラグの必須チェック ※「null:未聴取」は連携されない想定
			if (checkNotNull(ccMsg, errorMapChild, "kepg_kjnift_ffg"))
			{
				isError = true;
			}
			// 関電G個人情報提供不可フラグ変更年月日の必須チェック
			if (checkNotNull(ccMsg, errorMapChild, "kepg_kjnift_ffg_chg_ymd"))
			{
				isError = true;
			}
		}

		// 法人格相関チェック
		// 法人格前後指定コードが「なし」の場合
		if (JKKStrConst.HOJIN_ZENGO_SHITEI_CD_NON.equals((String)ccMsg.get("hojin_zengo_shitei_cd")))
		{
			// 法人格種別コード"が「指定なし」以外の場合
			if (!JKKStrConst.HOJIN_SBT_CD_BLANK.equals((String)ccMsg.get("hojin_sbt_cd")))
			{
				ccMsg.put("hojin_sbt_cd_err", E6_ERR);
				errorMapChild.put("hojin_sbt_cd_err", E6_ERR);
				isError = true;
			}
		}

		// エラーが存在する場合はエラー値を設定
		if (isError)
		{
			String formatStatus = String.format(RETURN_MESSAGE_FORMAT, JPCModelConstant.ITEM_RELATION_ERR);
			String message = JCMAPLConstMgr.getString(RETURN_MESSAGE_STRING + formatStatus);
			param.setControlMapData(SCControlMapKeys.RETURN_CODE, formatStatus);
			param.setControlMapData(SCControlMapKeys.RETURN_MESSAGE, message);

			errorMap.put(ErrorInfoMapKeys.RETURN_CODE, RETURN_CODE_NORMAL);
			errorMap.put(ErrorInfoMapKeys.TEMPLATE_ID, "JKKAddKeishaInfoEdenCC");
			errorMap.put(ErrorInfoMapKeys.STATUS, JPCModelConstant.ITEM_RELATION_ERR);
			errorMap.put(ErrorInfoMapKeys.ITEM_CHECK_ERRORS, errorMapChild);
			errList.add(errorMap);

			param.setControlMapData(SCControlMapKeys.ERROR_INFO, errList);
		}
	}

	/**
	 * 必須チェックを行い、エラーの場合はエラー情報を設定します。
	 * <br>
	 * @param ccMsg 契約者情報登録マップ
	 * @param errorMapChild 項目チェックエラー情報
	 * @param itemNm 項目名
	 * @return 必須チェックエラーの場合はtrue、そうでない場合はfalse
	 */
	private boolean checkNotNull(Map<String, Object> ccMsg, Map<String, String> errorMapChild, String itemNm)
	{
		if (JKKStringUtil.isNullBlank((String)ccMsg.get(itemNm)))
		{
			// エラーを設定
			ccMsg.put(itemNm + ERRITEM_SUFFIX, E1_ERR);
			errorMapChild.put(itemNm + ERRITEM_SUFFIX, E1_ERR);
			return true;
		}

		return false;
	}

	/**
	 * コード値チェックを行い、エラーの場合はエラー情報を設定します。
	 * <br>
	 * @param ccMsg 契約者情報登録マップ
	 * @param errorMapChild 項目チェックエラー情報
	 * @param itemNm 項目名
	 * @param codeList コード値リスト
	 * @return コード値チェックエラーの場合はtrue、そうでない場合はfalse
	 */
	private boolean checkCode(Map<String, Object> ccMsg, Map<String, String> errorMapChild, String itemNm, String[] codeList)
	{
		String code = (String)ccMsg.get(itemNm);
		if (!JKKStringUtil.isNullBlank(code) && !Arrays.asList(codeList).contains(code))
		{
			// エラーを設定
			ccMsg.put(itemNm + ERRITEM_SUFFIX, E4_ERR);
			errorMapChild.put(itemNm + ERRITEM_SUFFIX, E4_ERR);
			return true;
		}

		return false;
	}

	/**
	 * 桁数チェックを行い、エラーの場合はエラー情報を設定します。
	 * <br>
	 * @param ccMsg 契約者情報登録マップ
	 * @param errorMapChild 項目チェックエラー情報
	 * @param itemNm 項目名
	 * @param maxSize 最大バイト数
	 * @return 桁数チェックエラーの場合はtrue、そうでない場合はfalse
	 */
	private boolean checkSize(Map<String, Object> ccMsg, Map<String, String> errorMapChild, String itemNm, int maxSize)
	{
		String val = (String)ccMsg.get(itemNm);
		if (!JKKStringUtil.isNullBlank(val) && maxSize < val.length())
		{
			// エラーを設定
			ccMsg.put(itemNm + ERRITEM_SUFFIX, E3_ERR);
			errorMapChild.put(itemNm + ERRITEM_SUFFIX, E3_ERR);
			return true;
		}

		return false;
	}

	/**
	 * お客様情報を登録します。
	 * <br>
	 * @param handle セッションハンドル
	 * @param param リクエストパラメータ
	 * @param fixedText ユーザ定義文字列
	 * @param ccMsg 契約者情報登録マップ
	 * @param work 作業用マップ
	 * @throws Throwable 例外が発生した場合
	 */
	private void addCust(SessionHandle handle, IRequestParameterReadWrite param, String fixedText, Map<String, Object> ccMsg,
			Map<String, String> work)
	throws Throwable
	{
		// お客様登録情報
		CAANMsg custAddMsg = null;
		// 登録されたSYSID
		String sysid = "";
		// 更新年月日時分秒
		String updDtm = "";

		// SC呼び出し部品のインスタンス生成
		ServiceComponentRequestInvoker scCall = new ServiceComponentRequestInvoker();

		// お客様が個人の場合
		if (isCustKojin(ccMsg))
		{
			// お客様＜個人＞登録の上りマッピング
			Object[][] eck0021d010In =
			{
				{ECK0021D010CBSMsg.TEMPLATEID, TEMPLATE_ID_ECK0021D010}
				// 機能コード
				,{ECK0021D010CBSMsg.FUNC_CODE, (String)ccMsg.get("func_code")}
				// 契約者タイプコード
				,{ECK0021D010CBSMsg.KEISHA_TYPE_CD, (String)ccMsg.get("keisha_type_cd")}
				// お客様名
				,{ECK0021D010CBSMsg.CUST_NM, (String)ccMsg.get("cust_nm")}
				// お客様カナ名
				,{ECK0021D010CBSMsg.CUST_KANA, (String)ccMsg.get("cust_kana")}
				// お客様性別コード
				,{ECK0021D010CBSMsg.CUST_SEX_CD, (String)ccMsg.get("cust_sex_cd")}
				// お客様生年月日
				,{ECK0021D010CBSMsg.CUST_BIRTHD, (String)ccMsg.get("cust_birthd")}
				// 契約者住所コード
				,{ECK0021D010CBSMsg.KEISHA_AD_CD, (String)ccMsg.get("keisha_ad_cd")}
				// 契約者郵便番号
				,{ECK0021D010CBSMsg.KEISHA_PCD, (String)ccMsg.get("keisha_pcd")}
				// 契約者都道府県名
				,{ECK0021D010CBSMsg.KEISHA_STATE_NM, (String)ccMsg.get("keisha_state_nm")}
				// 契約者市区町村名
				,{ECK0021D010CBSMsg.KEISHA_CITY_NM, (String)ccMsg.get("keisha_city_nm")}
				// 契約者大字通称名
				,{ECK0021D010CBSMsg.KEISHA_OAZTSU_NM, (String)ccMsg.get("keisha_oaztsu_nm")}
				// 契約者字丁目名
				,{ECK0021D010CBSMsg.KEISHA_AZCHO_NM, (String)ccMsg.get("keisha_azcho_nm")}
				// 契約者番地号
				,{ECK0021D010CBSMsg.KEISHA_BNCHIGO, (String)ccMsg.get("keisha_bnchigo")}
				// 契約者住所補記・建物名
				,{ECK0021D010CBSMsg.KEISHA_ADRTTM, (String)ccMsg.get("keisha_adrttm")}
				// 契約者住所補記・部屋番号
				,{ECK0021D010CBSMsg.KEISHA_ADRRM, (String)ccMsg.get("keisha_adrrm")}
				// 契約者電話番号
				,{ECK0021D010CBSMsg.KEISHA_TELNO, (String)ccMsg.get("keisha_telno")}
				// 連絡手段コード
				,{ECK0021D010CBSMsg.RRK_WAY_CD, (String)ccMsg.get("rrk_way_cd")}
				// 連絡手段補記
				,{ECK0021D010CBSMsg.RRK_WAY_HOKI, (String)ccMsg.get("rrk_way_hoki")}
				// 会員種別コード
				,{ECK0021D010CBSMsg.MEMBER_SBT_CD, (String)ccMsg.get("member_sbt_cd")}
				// 内販外販コード
				,{ECK0021D010CBSMsg.NAIHAN_GAIHAN_CD, (String)ccMsg.get("naihan_gaihan_cd")}
				// 内販企業識別コード
				,{ECK0021D010CBSMsg.NAIHAN_COMP_SKBT_CD, (String)ccMsg.get("naihan_comp_skbt_cd")}
				// 会員ISP決済状態コード (0：通常)
				,{ECK0021D010CBSMsg.MMB_ISP_KSSAI_STAT_CD, JCKStrConst.CD00870_TUJYO}
				// 契約者住所手動入力フラグ
				,{ECK0021D010CBSMsg.KEISHA_AD_MAN_INPUT_FLG, (String)ccMsg.get("keisha_ad_man_input_flg")}
				// 契約者住所チェックレベル (2：最下層チェック無)
				,{ECK0021D010CBSMsg.KEISHA_AD_CHK_LV, KEISHA_AD_CHK_LV_NO_LOWEST}
				// 関電G個人情報取扱同意有無
				,{ECK0021D010CBSMsg.KEPG_KJNIF_TRAT_DOI_UM, (String)ccMsg.get("kepg_kjnif_trat_doi_um")}
				// 関電G個人情報取扱同意年月日
				,{ECK0021D010CBSMsg.KEPG_KJNIF_TRAT_DOI_YMD, (String)ccMsg.get("kepg_kjnif_trat_doi_ymd")}
				// 関電G個人情報提供不可フラグ
				,{ECK0021D010CBSMsg.KEPG_KJNIFT_FFG, (String)ccMsg.get("kepg_kjnift_ffg")}
				// 関電G個人情報提供不可フラグ変更年月日
				,{ECK0021D010CBSMsg.KEPG_KJNIFT_FFG_CHG_YMD, (String)ccMsg.get("kepg_kjnift_ffg_chg_ymd")}
			};

			// サービスIF実行
			custAddMsg = callSC(handle, scCall, param, fixedText, eck0021d010In);

			// 登録されたSYSIDを取得
			sysid = custAddMsg.getString(ECK0021D010CBSMsg.SYSID_O);
			// 更新年月日時分秒
			updDtm = custAddMsg.getString(ECK0021D010CBSMsg.UPD_DTM);
		}
		// お客様が個人以外の場合
		else
		{
			// 法人連絡先明細の作成
			CAANMsg childTemplate = new CAANMsg(ECK0031D010CBSMsg1List.class.getName());
			// 連絡先コード (01：契約者)
			childTemplate.set(ECK0031D010CBSMsg1List.RRKS_CD, JCKStrConst.CD00268_KEISHA);
			// 法人連絡先名
			childTemplate.set(ECK0031D010CBSMsg1List.HJRRKS_NM, (String)ccMsg.get("hjrrks_nm"));
			// 法人連絡先担当者名
			childTemplate.set(ECK0031D010CBSMsg1List.HJRRKS_TNTSHA_NM, (String)ccMsg.get("hjrrks_tntsha_nm"));
			// 法人連絡先担当者カナ名
			childTemplate.set(ECK0031D010CBSMsg1List.HJRRKS_TNTSHA_KANA, (String)ccMsg.get("hjrrks_tntsha_kana"));
			// 法人連絡先担当者所属部署名
			childTemplate.set(ECK0031D010CBSMsg1List.HJRRKS_TNTSHA_SHOZKBSHO_NM, (String)ccMsg.get("hjrrks_tntsha_shozkbsho_nm"));

			// 法人連絡先明細
			CAANMsg[] eck0031d010Msg1List = new CAANMsg[]{childTemplate};

			// お客様＜法人＞登録の上りマッピング
			Object[][] eck0031d010In =
			{
				{ECK0031D010CBSMsg.TEMPLATEID, TEMPLATE_ID_ECK0031D010}
				// 機能コード
				,{ECK0031D010CBSMsg.FUNC_CODE, (String)ccMsg.get("func_code")}
				// 契約者タイプコード
				,{ECK0031D010CBSMsg.KEISHA_TYPE_CD, (String)ccMsg.get("keisha_type_cd")}
				// お客様名
				,{ECK0031D010CBSMsg.CUST_NM, (String)ccMsg.get("cust_nm")}
				// お客様カナ名
				,{ECK0031D010CBSMsg.CUST_KANA, (String)ccMsg.get("cust_kana")}
				// お客様性別コード
				,{ECK0031D010CBSMsg.CUST_SEX_CD, (String)ccMsg.get("cust_sex_cd")}
				// お客様生年月日
				,{ECK0031D010CBSMsg.CUST_BIRTHD, (String)ccMsg.get("cust_birthd")}
				// 契約者住所コード
				,{ECK0031D010CBSMsg.KEISHA_AD_CD, (String)ccMsg.get("keisha_ad_cd")}
				// 契約者郵便番号
				,{ECK0031D010CBSMsg.KEISHA_PCD, (String)ccMsg.get("keisha_pcd")}
				// 契約者都道府県名
				,{ECK0031D010CBSMsg.KEISHA_STATE_NM, (String)ccMsg.get("keisha_state_nm")}
				// 契約者市区町村名
				,{ECK0031D010CBSMsg.KEISHA_CITY_NM, (String)ccMsg.get("keisha_city_nm")}
				// 契約者大字通称名
				,{ECK0031D010CBSMsg.KEISHA_OAZTSU_NM, (String)ccMsg.get("keisha_oaztsu_nm")}
				// 契約者字丁目名
				,{ECK0031D010CBSMsg.KEISHA_AZCHO_NM, (String)ccMsg.get("keisha_azcho_nm")}
				// 契約者番地号
				,{ECK0031D010CBSMsg.KEISHA_BNCHIGO, (String)ccMsg.get("keisha_bnchigo")}
				// 契約者住所補記・建物名
				,{ECK0031D010CBSMsg.KEISHA_ADRTTM, (String)ccMsg.get("keisha_adrttm")}
				// 契約者住所補記・部屋番号
				,{ECK0031D010CBSMsg.KEISHA_ADRRM, (String)ccMsg.get("keisha_adrrm")}
				// 契約者電話番号
				,{ECK0031D010CBSMsg.KEISHA_TELNO, (String)ccMsg.get("keisha_telno")}
				// 連絡手段コード
				,{ECK0031D010CBSMsg.RRK_WAY_CD, (String)ccMsg.get("rrk_way_cd")}
				// 連絡手段補記
				,{ECK0031D010CBSMsg.RRK_WAY_HOKI, (String)ccMsg.get("rrk_way_hoki")}
				// 会員種別コード
				,{ECK0031D010CBSMsg.MEMBER_SBT_CD, (String)ccMsg.get("member_sbt_cd")}
				// 内販外販コード
				,{ECK0031D010CBSMsg.NAIHAN_GAIHAN_CD, (String)ccMsg.get("naihan_gaihan_cd")}
				// 内販企業識別コード
				,{ECK0031D010CBSMsg.NAIHAN_COMP_SKBT_CD, (String)ccMsg.get("naihan_comp_skbt_cd")}
				// 会員ISP決済状態コード (0：通常)
				,{ECK0031D010CBSMsg.MMB_ISP_KSSAI_STAT_CD, JCKStrConst.CD00870_TUJYO}
				// 法人格種別コード
				,{ECK0031D010CBSMsg.HOJIN_SBT_CD, (String)ccMsg.get("hojin_sbt_cd")}
				// 法人格前後指定コード
				,{ECK0031D010CBSMsg.HOJIN_ZENGO_SHITEI_CD, (String)ccMsg.get("hojin_zengo_shitei_cd")}
				// 会社名
				,{ECK0031D010CBSMsg.COMP_NM, (String)ccMsg.get("comp_nm")}
				// 会社カナ名
				,{ECK0031D010CBSMsg.COMP_KANA, (String)ccMsg.get("comp_kana")}
				// 業種コード
				,{ECK0031D010CBSMsg.GSHU_CD, (String)ccMsg.get("gshu_cd")}
				// 法人連絡先明細
				,{ECK0031D010CBSMsg.ECK0031D010CBSMSG1LIST, eck0031d010Msg1List}
				// 契約者住所手動入力フラグ
				,{ECK0031D010CBSMsg.KEISHA_AD_MAN_INPUT_FLG, (String)ccMsg.get("keisha_ad_man_input_flg")}
				// 契約者住所チェックレベル (2：最下層チェック無)
				,{ECK0031D010CBSMsg.KEISHA_AD_CHK_LV, KEISHA_AD_CHK_LV_NO_LOWEST}
				// 代表者名
				,{ECK0031D010CBSMsg.DIHYSHA_NM, (String)ccMsg.get("dihysha_nm")}
				// 代表者カナ名
				,{ECK0031D010CBSMsg.DIHYSHA_KANA, (String)ccMsg.get("dihysha_kana")}
				// 関電G個人情報取扱同意有無
				,{ECK0031D010CBSMsg.KEPG_KJNIF_TRAT_DOI_UM, (String)ccMsg.get("kepg_kjnif_trat_doi_um")}
				// 関電G個人情報取扱同意年月日
				,{ECK0031D010CBSMsg.KEPG_KJNIF_TRAT_DOI_YMD, (String)ccMsg.get("kepg_kjnif_trat_doi_ymd")}
				// 関電G個人情報提供不可フラグ
				,{ECK0031D010CBSMsg.KEPG_KJNIFT_FFG, (String)ccMsg.get("kepg_kjnift_ffg")}
				// 関電G個人情報提供不可フラグ変更年月日
				,{ECK0031D010CBSMsg.KEPG_KJNIFT_FFG_CHG_YMD, (String)ccMsg.get("kepg_kjnift_ffg_chg_ymd")}
			};

			// サービスIF実行
			custAddMsg = callSC(handle, scCall, param, fixedText, eck0031d010In);

			// 登録されたSYSIDを取得
			sysid = custAddMsg.getString(ECK0031D010CBSMsg.SYSID);
			// 更新年月日時分秒
			updDtm = custAddMsg.getString(ECK0031D010CBSMsg.UPD_DTM);
		}

		// 契約者住所コード相関チェック
		checkKeishaAdRelation(param, ccMsg, custAddMsg);
		// 住所存在チェック
		checkAdExist(param, ccMsg, custAddMsg);
		// 二重登録チェック（非eo会員）
		checkDuplicate(param, ccMsg, custAddMsg);
		// 不良顧客チェック
		checkHuryoCust(param, ccMsg, custAddMsg);
		// リターンコードチェック
		checkReturnCode(param);

		// 作業用マップに設定
		work.put(WORK_MAP_KEY_SYSID, sysid);
		work.put(WORK_MAP_KEY_UPD_DTM_CUST, updDtm);
	}

	/**
	 * 連絡先情報を登録します。
	 * <br>
	 * @param handle セッションハンドル
	 * @param param リクエストパラメータ
	 * @param fixedText ユーザ定義文字列
	 * @param ccMsg 契約者情報登録マップ
	 * @param work 作業用マップ
	 * @throws Throwable 例外が発生した場合
	 */
	private void addRrks(SessionHandle handle, IRequestParameterReadWrite param, String fixedText, Map<String, Object> ccMsg,
			Map<String, String> work)
	throws Throwable
	{
		// 登録されたSYSID
		String sysid = work.get(WORK_MAP_KEY_SYSID);
		// 更新年月日時分秒
		String updDtm = work.get(WORK_MAP_KEY_UPD_DTM_CUST);

		// 連絡先コード
		String rrksCd = "";
		// お客様が個人以外の場合
		if (!isCustKojin(ccMsg))
		{
			// 01：契約者
			rrksCd = JCKStrConst.CD00268_KEISHA;
		}

		// SC呼び出し部品のインスタンス生成
		ServiceComponentRequestInvoker scCall = new ServiceComponentRequestInvoker();

		// 契約者連絡先内線番号の登録
		String keishaRrksNisnno = (String)ccMsg.get("keisha_rrks_nisnno");
		if (!JKKStringUtil.isNullBlank(keishaRrksNisnno))
		{
			// 連絡先登録の上りマッピング
			Object[][] eck0201d010In =
			{
				{ECK0201D010CBSMsg.TEMPLATEID, TEMPLATE_ID_ECK0201D010}
				// 機能コード
				,{ECK0201D010CBSMsg.FUNC_CODE, (String)ccMsg.get("func_code")}
				// SYSID
				,{ECK0201D010CBSMsg.SYSID, sysid}
				// 連絡先コード
				,{ECK0201D010CBSMsg.RRKS_CD, rrksCd}
				// 連絡方法コード (004：内線番号)
				,{ECK0201D010CBSMsg.RRK_WAY_CD, JCKStrConst.CD00790_NISNNO}
				// 連絡先種別コード (3：勤務先)
				,{ECK0201D010CBSMsg.RRKS_SBT_CD, JCKStrConst.CD00254_OFFC}
				// 連絡先分類コード (0：回線系連絡先)
				,{ECK0201D010CBSMsg.RRKS_BUNRUI_CD, JCKStrConst.CD00871_KAISEN}
				// 内線番号
				,{ECK0201D010CBSMsg.NISNNO, keishaRrksNisnno}
				// 更新年月日時分秒(更新前)
				,{ECK0201D010CBSMsg.UPD_DTM_BF, updDtm}
			};

			// サービスIF実行
			CAANMsg eck0201d010Msg = callSC(handle, scCall, param, fixedText, eck0201d010In);
			if (!JKKStringUtil.isNullBlank(eck0201d010Msg.getString(ECK0201D010CBSMsg.NISNNO_ERR)))
			{
				// 内線番号エラーを設定
				ccMsg.put("keisha_rrks_nisnno_err", eck0201d010Msg.getString(ECK0201D010CBSMsg.NISNNO_ERR));
			}
			// リターンコードチェック
			checkReturnCode(param);

			// 更新年月日時分秒
			updDtm = eck0201d010Msg.getString(ECK0201D010CBSMsg.UPD_DTM);
		}

		// 契約者連絡先電話番号の登録
		String keishaRrksTelno = (String)ccMsg.get("keisha_rrks_telno");
		if (!JKKStringUtil.isNullBlank(keishaRrksTelno))
		{
			// 連絡先登録の上りマッピング
			Object[][] eck0201d010In =
			{
				{ECK0201D010CBSMsg.TEMPLATEID, TEMPLATE_ID_ECK0201D010}
				// 機能コード
				,{ECK0201D010CBSMsg.FUNC_CODE, (String)ccMsg.get("func_code")}
				// SYSID
				,{ECK0201D010CBSMsg.SYSID, sysid}
				// 連絡先コード
				,{ECK0201D010CBSMsg.RRKS_CD, rrksCd}
				// 連絡方法コード (003：電話番号)
				,{ECK0201D010CBSMsg.RRK_WAY_CD, JCKStrConst.CD00790_TELNO}
				// 連絡先種別コード (5：その他)
				,{ECK0201D010CBSMsg.RRKS_SBT_CD, JCKStrConst.CD00254_OTHER}
				// 連絡先分類コード (0：回線系連絡先)
				,{ECK0201D010CBSMsg.RRKS_BUNRUI_CD, JCKStrConst.CD00871_KAISEN}
				// 電話番号
				,{ECK0201D010CBSMsg.TELNO, keishaRrksTelno}
				// 更新年月日時分秒(更新前)
				,{ECK0201D010CBSMsg.UPD_DTM_BF, updDtm}
			};

			// サービスIF実行
			CAANMsg eck0201d010Msg = callSC(handle, scCall, param, fixedText, eck0201d010In);
			if (!JKKStringUtil.isNullBlank(eck0201d010Msg.getString(ECK0201D010CBSMsg.TELNO_ERR)))
			{
				// 電話番号エラーを設定
				ccMsg.put("keisha_rrks_telno_err", eck0201d010Msg.getString(ECK0201D010CBSMsg.TELNO_ERR));
			}
			// リターンコードチェック
			checkReturnCode(param);

			// 更新年月日時分秒
			updDtm = eck0201d010Msg.getString(ECK0201D010CBSMsg.UPD_DTM);
		}

		// 契約者連絡先携帯電話番号の登録
		String keishaRrksKtaiTelno = (String)ccMsg.get("keisha_rrks_ktai_telno");
		if (!JKKStringUtil.isNullBlank(keishaRrksKtaiTelno))
		{
			// 連絡先登録の上りマッピング
			Object[][] eck0201d010In =
			{
				{ECK0201D010CBSMsg.TEMPLATEID, TEMPLATE_ID_ECK0201D010}
				// 機能コード
				,{ECK0201D010CBSMsg.FUNC_CODE, (String)ccMsg.get("func_code")}
				// SYSID
				,{ECK0201D010CBSMsg.SYSID, sysid}
				// 連絡先コード
				,{ECK0201D010CBSMsg.RRKS_CD, rrksCd}
				// 連絡方法コード (003：電話番号)
				,{ECK0201D010CBSMsg.RRK_WAY_CD, JCKStrConst.CD00790_TELNO}
				// 連絡先種別コード (2：携帯)
				,{ECK0201D010CBSMsg.RRKS_SBT_CD, JCKStrConst.CD00254_KTAI}
				// 連絡先分類コード (0：回線系連絡先)
				,{ECK0201D010CBSMsg.RRKS_BUNRUI_CD, JCKStrConst.CD00871_KAISEN}
				// 電話番号
				,{ECK0201D010CBSMsg.TELNO, keishaRrksKtaiTelno}
				// 更新年月日時分秒(更新前)
				,{ECK0201D010CBSMsg.UPD_DTM_BF, updDtm}
			};

			// サービスIF実行
			CAANMsg eck0201d010Msg = callSC(handle, scCall, param, fixedText, eck0201d010In);
			if (!JKKStringUtil.isNullBlank(eck0201d010Msg.getString(ECK0201D010CBSMsg.TELNO_ERR)))
			{
				// 電話番号エラーを設定
				ccMsg.put("keisha_rrks_ktai_telno_err", eck0201d010Msg.getString(ECK0201D010CBSMsg.TELNO_ERR));
			}
			// リターンコードチェック
			checkReturnCode(param);

			// 更新年月日時分秒
			updDtm = eck0201d010Msg.getString(ECK0201D010CBSMsg.UPD_DTM);
		}

		// 契約者連絡先メールアドレスの登録
		String keishaRrksMlad = (String)ccMsg.get("keisha_rrks_mlad");
		if (!JKKStringUtil.isNullBlank(keishaRrksMlad))
		{
			// 連絡先登録の上りマッピング
			Object[][] eck0201d010In =
			{
				{ECK0201D010CBSMsg.TEMPLATEID, TEMPLATE_ID_ECK0201D010}
				// 機能コード
				,{ECK0201D010CBSMsg.FUNC_CODE, (String)ccMsg.get("func_code")}
				// SYSID
				,{ECK0201D010CBSMsg.SYSID, sysid}
				// 連絡先コード
				,{ECK0201D010CBSMsg.RRKS_CD, rrksCd}
				// 連絡方法コード (001：メールアドレス)
				,{ECK0201D010CBSMsg.RRK_WAY_CD, JCKStrConst.CD00790_MLAD}
				// 連絡先種別コード (5：その他)
				,{ECK0201D010CBSMsg.RRKS_SBT_CD, JCKStrConst.CD00254_OTHER}
				// 連絡先分類コード (0：回線系連絡先)
				,{ECK0201D010CBSMsg.RRKS_BUNRUI_CD, JCKStrConst.CD00871_KAISEN}
				// メールアドレス
				,{ECK0201D010CBSMsg.MLAD, keishaRrksMlad}
				// 更新年月日時分秒(更新前)
				,{ECK0201D010CBSMsg.UPD_DTM_BF, updDtm}
			};

			// サービスIF実行
			CAANMsg eck0201d010Msg = callSC(handle, scCall, param, fixedText, eck0201d010In);
			if (!JKKStringUtil.isNullBlank(eck0201d010Msg.getString(ECK0201D010CBSMsg.MLAD_ERR)))
			{
				// メールアドレスエラーを設定
				ccMsg.put("keisha_rrks_mlad_err", eck0201d010Msg.getString(ECK0201D010CBSMsg.MLAD_ERR));
			}
			// リターンコードチェック
			checkReturnCode(param);

			// 更新年月日時分秒
			updDtm = eck0201d010Msg.getString(ECK0201D010CBSMsg.UPD_DTM);
		}

		// 契約者連絡先メールアドレス２の登録
		String keishaRrksMlad2 = (String)ccMsg.get("keisha_rrks_mlad2");
		if (!JKKStringUtil.isNullBlank(keishaRrksMlad2))
		{
			// 連絡先登録の上りマッピング
			Object[][] eck0201d010In =
			{
				{ECK0201D010CBSMsg.TEMPLATEID, TEMPLATE_ID_ECK0201D010}
				// 機能コード
				,{ECK0201D010CBSMsg.FUNC_CODE, (String)ccMsg.get("func_code")}
				// SYSID
				,{ECK0201D010CBSMsg.SYSID, sysid}
				// 連絡先コード
				,{ECK0201D010CBSMsg.RRKS_CD, rrksCd}
				// 連絡方法コード (001：メールアドレス)
				,{ECK0201D010CBSMsg.RRK_WAY_CD, JCKStrConst.CD00790_MLAD}
				// 連絡先種別コード (1：自宅)
				,{ECK0201D010CBSMsg.RRKS_SBT_CD, JCKStrConst.CD00254_HOME}
				// 連絡先分類コード (1：コンテンツ系連絡先)
				,{ECK0201D010CBSMsg.RRKS_BUNRUI_CD, JCKStrConst.CD00871_CONT}
				// メールアドレス
				,{ECK0201D010CBSMsg.MLAD, keishaRrksMlad2}
				// 更新年月日時分秒(更新前)
				,{ECK0201D010CBSMsg.UPD_DTM_BF, updDtm}
			};

			// サービスIF実行
			CAANMsg eck0201d010Msg = callSC(handle, scCall, param, fixedText, eck0201d010In);
			if (!JKKStringUtil.isNullBlank(eck0201d010Msg.getString(ECK0201D010CBSMsg.MLAD_ERR)))
			{
				// メールアドレスエラーを設定
				ccMsg.put("keisha_rrks_mlad2_err", eck0201d010Msg.getString(ECK0201D010CBSMsg.MLAD_ERR));
			}
			// リターンコードチェック
			checkReturnCode(param);

			// 更新年月日時分秒
			updDtm = eck0201d010Msg.getString(ECK0201D010CBSMsg.UPD_DTM);

			// 作業用マップに設定
			work.put(WORK_MAP_KEY_UPD_DTM_CUST, updDtm);

			// オプトインメール受信設定登録
			addOptinmRcvSet(handle, param, fixedText, ccMsg, work, keishaRrksMlad2);
		}

		// 作業用マップに設定
		work.put(WORK_MAP_KEY_UPD_DTM_CUST, updDtm);
	}

	/**
	 * オプトインメール受信設定に登録します。
	 * <br>
	 * @param handle セッションハンドル
	 * @param param リクエストパラメータ
	 * @param fixedText ユーザ定義文字列
	 * @param ccMsg 契約者情報登録マップ
	 * @param work 作業用マップ
	 * @param mlad メールアドレス
	 * @throws Throwable 例外が発生した場合
	 */
	private void addOptinmRcvSet(SessionHandle handle, IRequestParameterReadWrite param, String fixedText, Map<String, Object> ccMsg,
			Map<String, String> work, String mlad)
	throws Throwable
	{
		// 登録されたSYSID
		String sysid = work.get(WORK_MAP_KEY_SYSID);
		// 更新年月日時分秒
		String updDtm = work.get(WORK_MAP_KEY_UPD_DTM_CUST);

		// SC呼び出し部品のインスタンス生成
		ServiceComponentRequestInvoker scCall = new ServiceComponentRequestInvoker();

		// オプトインメール一覧照会の上りマッピング
		Object[][] eck0141b002In =
		{
			{ECK0141B002CBSMsg.TEMPLATEID, TEMPLATE_ID_ECK0141B002}
			// 機能コード："2"(オプトインメール一覧照会（非公開含む）)
			,{ECK0141B002CBSMsg.FUNC_CODE, JPCModelConstant.FUNC_CD_2}
			// ＫＥＹ＿運用年月日
			,{ECK0141B002CBSMsg.KEY_OPE_YMD, work.get(WORK_MAP_KEY_OPEDATE)}
		};

		// サービスIF実行
		CAANMsg[] optinmList = callSC(handle, scCall, param, fixedText, eck0141b002In).getCAANMsgList(ECK0141B002CBSMsg.ECK0141B002CBSMSG1LIST);
		// リターンコードチェック
		checkReturnCode(param);

		for (int i = 0; i < optinmList.length; i++)
		{
			// オプトインメール番号
			String optinmNo = optinmList[i].getString(ECK0141B002CBSMsg1List.OPTINM_NO);

			// 受信区分
			String rcvDiv = "";
			// 「セキュリティに関するお知らせ希望有無」が設定されている場合
			if (OPTINM_NO_SECINFO.equals(optinmNo) && !JKKStringUtil.isNullBlank((String)ccMsg.get("secinfo_jsnst_um")))
			{
				rcvDiv = (String)ccMsg.get("secinfo_jsnst_um");
			}
			// 「プロバイダサービスに関するお知らせ希望有無」が設定されている場合
			else if (OPTINM_NO_PVSVINFO.equals(optinmNo) && !JKKStringUtil.isNullBlank((String)ccMsg.get("pvsvinfo_jsnst_um")))
			{
				rcvDiv = (String)ccMsg.get("pvsvinfo_jsnst_um");
			}
			// 「新サービスのご案内希望有無」が設定されている場合
			else if (OPTINM_NO_NEWSVINFO.equals(optinmNo) && !JKKStringUtil.isNullBlank((String)ccMsg.get("newsvinfo_jsnst_um")))
			{
				rcvDiv = (String)ccMsg.get("newsvinfo_jsnst_um");
			}
			// 「お得な情報、サービス、キャンペーンに関するお知らせ希望有無」が設定されている場合
			else if (OPTINM_NO_SVCPINFO.equals(optinmNo) && !JKKStringUtil.isNullBlank((String)ccMsg.get("svcpinfo_jsnst_um")))
			{
				rcvDiv = (String)ccMsg.get("svcpinfo_jsnst_um");
			}
			// 上記以外
			else
			{
				// オプトインメール.初期値フラグを設定
				rcvDiv = optinmList[i].getString(ECK0141B002CBSMsg1List.SHK_VALUE_FLG);
			}

			// オプトインメール受信設定登録の上りマッピング
			Object[][] eck0141d010In =
			{
				{ECK0141D010CBSMsg.TEMPLATEID, TEMPLATE_ID_ECK0141D010}
				// 機能コード
				,{ECK0141D010CBSMsg.FUNC_CODE, (String)ccMsg.get("func_code")}
				// オプトインメール番号
				,{ECK0141D010CBSMsg.OPTINM_NO, optinmNo}
				// SYSID
				,{ECK0141D010CBSMsg.SYSID, sysid}
				// メールアドレス
				,{ECK0141D010CBSMsg.MLAD, mlad}
				// 受信区分
				,{ECK0141D010CBSMsg.RCV_DIV, rcvDiv}
				// 受信設定年月日
				,{ECK0141D010CBSMsg.RCV_SETTE_YMD, work.get(WORK_MAP_KEY_OPEDATE)}
				// 更新年月日時分秒(更新前)
				,{ECK0141D010CBSMsg.UPD_DTM_BF, updDtm}
			};

			// サービスIF実行
			CAANMsg eck0141d010Msg = callSC(handle, scCall, param, fixedText, eck0141d010In);
			// リターンコードチェック
			checkReturnCode(param);

			// 更新年月日時分秒
			updDtm = eck0141d010Msg.getString(ECK0141D010CBSMsg.UPD_DTM);
		}

		// 作業用マップに設定
		work.put(WORK_MAP_KEY_UPD_DTM_CUST, updDtm);
	}

	/**
	 * レスポンス項目を設定します。
	 * <br>
	 * @param ccMsg 契約者情報登録マップ
	 * @param work 作業用マップ
	 */
	private void setResponse(Map<String, Object> ccMsg, Map<String, String> work)
	{
		// SYSID
		ccMsg.put("sysid", (String)work.get(WORK_MAP_KEY_SYSID));
	}

	/**
	 * お客様が個人かどうかを返します。
	 * <br>
	 * @param ccMsg 契約者情報登録マップ
	 * @return 個人の場合true、個人以外の場合false
	 */
	private boolean isCustKojin(Map<String, Object> ccMsg)
	{
		// 契約者タイプコードが「個人」の場合
		if (JCKStrConst.CD00036_KOJIN.equals((String)ccMsg.get("keisha_type_cd")))
		{
			return true;
		}
		return false;
	}

	/**
	 * 契約者住所コード相関チェックを行います。
	 * <br>
	 * @param param リクエストパラメータ
	 * @param ccMsg 契約者情報登録マップ
	 * @param custAddMsg お客様＜個人＞登録結果、またはお客様＜法人＞登録結果
	 * @throws Exception 例外が発生した場合
	 */
	private void checkKeishaAdRelation(IRequestParameterReadWrite param, Map<String, Object> ccMsg, CAANMsg custAddMsg)
	throws Exception
	{
		// 住所コード相関チェック(契約者)のエラーフラグ
		String adRelationErrFlg = "";
		// お客様が個人の場合
		if (isCustKojin(ccMsg))
		{
			adRelationErrFlg = E1_ERR;
		}
		else
		{
			adRelationErrFlg = E2_ERR;
		}

		// 住所コード相関チェック(契約者)でエラーとなった場合
		if (getReturnCode(param) == JPCModelConstant.ITEM_RELATION_ERR
			&& adRelationErrFlg.equals(custAddMsg.getString("keisha_ad_cd_err")))
		{
			// 契約者住所コード相関チェックエラーを設定
			ccMsg.put("keisha_ad_cd_err", E5_ERR);
			if (adRelationErrFlg.equals(custAddMsg.getString("keisha_state_nm_err")))
			{
				ccMsg.put("keisha_state_nm_err", E5_ERR);
			}
			if (adRelationErrFlg.equals(custAddMsg.getString("keisha_city_nm_err")))
			{
				ccMsg.put("keisha_city_nm_err", E5_ERR);
			}
			if (adRelationErrFlg.equals(custAddMsg.getString("keisha_oaztsu_nm_err")))
			{
				ccMsg.put("keisha_oaztsu_nm_err", E5_ERR);
			}
			if (adRelationErrFlg.equals(custAddMsg.getString("keisha_azcho_nm_err")))
			{
				ccMsg.put("keisha_azcho_nm_err", E5_ERR);
			}
			if (adRelationErrFlg.equals(custAddMsg.getString("keisha_bnchigo_err")))
			{
				ccMsg.put("keisha_bnchigo_err", E5_ERR);
			}
		}
	}

	/**
	 * 住所存在チェックを行います。
	 * <br>
	 * @param param リクエストパラメータ
	 * @param ccMsg 契約者情報登録マップ
	 * @param custAddMsg お客様＜個人＞登録結果、またはお客様＜法人＞登録結果
	 * @throws Exception 例外が発生した場合
	 */
	private void checkAdExist(IRequestParameterReadWrite param, Map<String, Object> ccMsg, CAANMsg custAddMsg)
	throws Exception
	{
		// 住所コード相関チェック(契約者)でエラーとなった場合
		// IT1-2017-0000126 MOD START
//		if (getReturnCode(param) == JPCModelConstant.ITEM_RELATION_ERR
		if (getReturnCode(param) == JPCModelConstant.RELATION_ERR
		// IT1-2017-0000126 MOD END
			&& EA_ERR.equals(custAddMsg.getString("keisha_ad_chk_lv_err")))
		{
			// 住所存在チェックエラーを設定
			ccMsg.put("keisha_ad_cd_err", EA_ERR);
		}
	}

	/**
	 * 二重登録チェック（非eo会員）を行います。
	 * <br>
	 * @param param リクエストパラメータ
	 * @param ccMsg 契約者情報登録マップ
	 * @param custAddMsg お客様＜個人＞登録結果、またはお客様＜法人＞登録結果
	 * @throws Exception 例外が発生した場合
	 */
	private void checkDuplicate(IRequestParameterReadWrite param, Map<String, Object> ccMsg, CAANMsg custAddMsg)
	throws Exception
	{
		// 二重登録チェック（非eo会員）のエラー項目
		String duplicateErrItem = "";
		// お客様が個人の場合
		if (isCustKojin(ccMsg))
		{
			duplicateErrItem = "member_sbt_cd";
		}
		else
		{
			duplicateErrItem = "cust_nm";
		}

		// 二重登録チェック（非eo会員）でエラーとなった場合
		if (getReturnCode(param) == JPCModelConstant.RELATION_ERR
			&& WA_WAR.equals(custAddMsg.getString(duplicateErrItem + ERRITEM_SUFFIX)))
		{
			// 二重登録チェック（非eo会員）エラーを設定
			ccMsg.put("member_sbt_cd_err", WA_WAR);
		}
	}

	/**
	 * 不良顧客チェックを行います。
	 * <br>
	 * @param param リクエストパラメータ
	 * @param ccMsg 契約者情報登録マップ
	 * @param custAddMsg お客様＜個人＞登録結果、またはお客様＜法人＞登録結果
	 * @throws Exception 例外が発生した場合
	 */
	private void checkHuryoCust(IRequestParameterReadWrite param, Map<String, Object> ccMsg, CAANMsg custAddMsg)
	throws Exception
	{
		// 不良顧客チェックのエラー項目
		String huryoCustErrItem = "";
		// お客様が個人の場合
		if (isCustKojin(ccMsg))
		{
			huryoCustErrItem = "member_sbt_cd";
		}
		else
		{
			huryoCustErrItem = "cust_nm";
		}

		// 不良顧客チェックでエラーとなった場合
		if (getReturnCode(param) == JPCModelConstant.RELATION_ERR
			&& WB_WAR.equals(custAddMsg.getString(huryoCustErrItem + ERRITEM_SUFFIX)))
		{
			// 不良顧客チェックエラーを設定
			ccMsg.put("member_sbt_cd_err", WB_WAR);
		}
	}

	/**
	 * SC(サービスインターフェイス）を呼び出します。
	 * @param handle セッションハンドル
	 * @param scCall SC呼び出し部品
	 * @param param リクエストパラメータ
	 * @param dataMapKey パラメータキー
	 * @param mappingData マッピングデータ
	 * @return CAANMsg
	 * @throws Throwable 例外が発生した場合
	 */
	private CAANMsg callSC(SessionHandle handle, 
							ServiceComponentRequestInvoker scCall, 
							IRequestParameterReadWrite param, 
							String dataMapKey,
							Object[][] mappingData) 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);

		//エラー情報のマップを取得
		ArrayList<Object> errList = (ArrayList<Object>)param.getControlMapData(SCControlMapKeys.ERROR_INFO);

		if (null == errList)
		{
			errList = new ArrayList<Object>();
		}

		// コントロールマップに設定
		param.setControlMapData(SCControlMapKeys.ERROR_INFO, TemplateErrorUtil.getErrorInfo(result, errList));

		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] instanceof CAANMsg[])
			{
				 template.set((String)mappingData[i][0], (CAANMsg[])mappingData[i][1]);
			}
			else
			{
				if ("".equals(mappingData[i][1]))
				{
					template.setNull((String)mappingData[i][0]);
				}
				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;
	}

	/**
	 * エラー情報を取得します。
	 * @param param リクエストパラメータ
	 * @param templates CAANMsgクラス
	 * @param returnCode リターンコード
	 * @param dataMapKey パラメータキー
	 * @return IRequestParameterReadWrite
	 * @throws RequestParameterException リクエストパラメータの操作でエラーが発生した場合
	 */
	private IRequestParameterReadWrite editErrorInfoCom(IRequestParameterReadWrite param,
														CAANMsg[] templates, 
														int returnCode,
														String dataMapKey) 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 + String.format(RETURN_MESSAGE_FORMAT, 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(RETURN_MESSAGE_FORMAT, templateStatus);
			
			String message = JCMAPLConstMgr.getString(RETURN_MESSAGE_STRING + formatStatus);
			
			param.setControlMapData(SCControlMapKeys.RETURN_CODE, formatStatus);
			
			param.setControlMapData(SCControlMapKeys.RETURN_MESSAGE, message);
		}

		// ユーザデータ情報
		HashMap<String, Object> inMap = (HashMap<String, Object>)param.getData(dataMapKey);

		HashMap map = template.getHashMap();
		Iterator it = map.keySet().iterator();
		while (it.hasNext())
		{
			String key = (String)it.next();
			Object value = map.get(key);
			if (value instanceof HashMap[])
			{
				HashMap[] childMapList = (HashMap[])value;
				for (HashMap childMap : childMapList)
				{
					Iterator childIt = childMap.keySet().iterator();
					while (childIt.hasNext())
					{
						String childKey = (String)childIt.next();
						if (childKey.endsWith(ERRITEM_SUFFIX))
						{
							int keyIdx = childKey.lastIndexOf(ERRITEM_SUFFIX);
							if (inMap.containsKey(childKey.substring(0, keyIdx)))
							{
								inMap.put(childKey, childMap.get(childKey));
							}
						}
					}
				}
			}
			else
			{
				if (key.endsWith(ERRITEM_SUFFIX))
				{
					int keyIdx = key.lastIndexOf(ERRITEM_SUFFIX);
					if (inMap.containsKey(key.substring(0, keyIdx)))
					{
						inMap.put(key, map.get(key));
					}
				}
			}
		}

		return param;
	}

	/**
	 * SCのリターンコードを取得します。
	 * <br>
	 * @param param リクエストパラメータ
	 * @return SCの実行ステータス
	 * @throws Exception 例外が発生した場合
	 */
	private int getReturnCode(IRequestParameterReadWrite param) throws Exception
	{
		return Integer.parseInt((String)param.getControlMapData(SCControlMapKeys.RETURN_CODE));
	}

	/**
	 * SCのリターンコードを判定し、エラーであれば例外を送出します。
	 * @param param リクエストパラメータ
	 * @throws Exception 例外が発生した場合
	 * @throws CCException 単項目エラー以上のエラーが発生した場合
	 */
	private void checkReturnCode(IRequestParameterReadWrite param)
	throws Exception, CCException
	{
		if (getReturnCode(param) >= JPCModelConstant.SINGLEDATA_ERR)
		{
			// ステータスが単項目エラー以上であれば例外をスロー
			throw new CCException(SC_ERROR_STRING, new Exception());
		}
	}

}
