/*********************************************************************
*	All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*	システム名		：eo顧客基幹システム
*	モジュール名	：JKKNrikemtSvkeiShokaiCC
*	ソースファイル名：JKKNrikemtSvkeiShokaiCC.java
*	作成者			：FJ
*	日付			：2024年07月30日
*＜機能概要＞
*	現サービス情報照会の共通コンポーネント
*＜修正履歴＞
*	バージョン	修正日		修正者		修正内容
*	v71.00.00	2024/07/30	FJ			新規作成
*	v71.00.01	2024/08/06	FJ)舘山		IT1-2024-0000025_PLCモデムの判定条件変更他
*	v71.00.02	2024/08/09	FJ)舘山		IT1-2024-0000026_メッシュWiFiが優先されない
*	v71.00.03	2024/08/22	FJ)舘山		IT1-2024-0000031_乗り換え元を変更しても機器送付先住所が更新されない
*	v71.00.04	2024/08/30	FJ)舘山		IT1-2024-0000034_対象外のサービス契約番号が乗り換え元で返却された
*	v72.00.00	2024/08/19	FJ)吉川		ANK-4577-00-00_eo光ネット「シンプルプラン」追加対応(Step2)
**********************************************************************/
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.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 eo.common.constant.JPCModelConstant;
import eo.common.util.JKKStringUtil;
import eo.ejb.cbs.cbsmsg.EKK0081B004CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK0081B004CBSMsg1List;
import eo.ejb.cbs.cbsmsg.EKK0081B011CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK0081B011CBSMsg1List;
import eo.ejb.cbs.cbsmsg.EKK0081B519CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK0081B519CBSMsg1List;
import eo.ejb.cbs.cbsmsg.EKK0241B001CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK0241B001CBSMsg1List;
import eo.ejb.cbs.cbsmsg.EKK0251A010CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK0251A010CBSMsg1List;
import eo.ejb.cbs.cbsmsg.EKK0341B002CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK0341B002CBSMsg1List;
import eo.ejb.cbs.cbsmsg.EKK1681B001CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK1681B001CBSMsg1List;
import eo.ejb.cbs.cbsmsg.EKK2091B001CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK2091B001CBSMsg1List;
import eo.ejb.cbs.cbsmsg.EKK2811B010CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK2811B010CBSMsg1List;
import eo.ejb.cbs.cbsmsg.EKU0081B020CBSMsg;
import eo.ejb.cbs.cbsmsg.EKU0081B020CBSMsg1List;
import eo.ejb.cbs.cbsmsg.EKU0281A010CBSMsg;
import eo.ejb.cbs.cbsmsg.EKU0281A010CBSMsg1List;
import eo.ejb.cbs.cbsmsg.EZM0321A010CBSMsg;
import eo.ejb.cbs.cbsmsg.EZM0321A010CBSMsg1List;
import eo.ejb.cbs.cbsmsg.EZM0411A010CBSMsg;
import eo.ejb.cbs.cbsmsg.EZM0411A010CBSMsg1List;

/**
 * 乗り換え元サービス契約照会の共通コンポーネントです。<p>
 * <br>
 * @author 富士通
 *
 */
public class JKKNrikemtSvkeiShokaiCC extends AbstractCommonComponent
{
	/** サービスIF テンプレート一覧*/
	private static final String TEMPLATE_ID_EKK0081B519 = "EKK0081B519";
	private static final String TEMPLATE_ID_EKK0081B004 = "EKK0081B004";
	private static final String TEMPLATE_ID_EKK0081B011 = "EKK0081B011";
	private static final String TEMPLATE_ID_EKU0081B020 = "EKU0081B020";
	private static final String TEMPLATE_ID_EKK1681B001 = "EKK1681B001";
	private static final String TEMPLATE_ID_EKK2091B001 = "EKK2091B001";
	private static final String TEMPLATE_ID_EKK0341B002 = "EKK0341B002";
	private static final String TEMPLATE_ID_EZM0411A010 = "EZM0411A010";
	private static final String TEMPLATE_ID_EKK2811B010 = "EKK2811B010";
	private static final String TEMPLATE_ID_EZM0321A010 = "EZM0321A010";
	private static final String TEMPLATE_ID_EKU0281A010 = "EKU0281A010";
	private static final String TEMPLATE_ID_EKK0251A010 = "EKK0251A010";
	private static final String TEMPLATE_ID_EKK0241B001 = "EKK0241B001";
	// ----------
	// エラー定数
	// ----------
	/** エラーコード */
	public static final String ERROR_CODE = "errCode";
	/** エラーメッセージ */
	public static final String ERROR_MESSAGE = "errMessage";
	/** リターンメッセージ取得キー */
	private static final String RETURN_MESSAGE_STRING = "RETURN_MESSAGE_";
	/** リターンメッセージの書式指定文字列 */
	private static final String RETURN_MESSAGE_FORMAT = "%1$04d";
	/** エラー項目接尾辞 */
	private static final String ERRITEM_SUFFIX = "_err";

	/** 処理対象外する契約ステータス（サービスおよび機器） */
	private static final List<String> EXCLUDE_STAT_LIST = Arrays.asList(new String[]{"910","920"}); 
	
	/** 除外する料金グループ（同一回線のネット以外のサービス） */
	private static final List<String> EXCLUDE_PRC_GRP_CD_LIST = Arrays.asList(new String[]{"10","11","12","13"}); 
	
	/** 有効な異動予約状態コードリスト */
	private static final List<String> ACCEPT_IDO_RSV_STAT = Arrays.asList(new String[]{"00","03"});
	
	/** シンプルプランの料金コースリスト */
	private static final List<String> SIMPLE_PLAN_PCRS_LIST = Arrays.asList(new String[]{"A97","A99"});
	
	/** メッシュ判定用業務パラメータキー */
	private static final String ZM_WORK_PARAM_KK_MESHWIFI_PCRS_CD = "KK_MESHWIFI_PCRS_CD";

	/** 設備流用区分 */
// ▽▽▽ IT1-2024-0000025 Modify START
//	private static final String SETUBI_RUYO_KBN = "setubi_ruyo_kbn";
	private static final String EQUIP_RYUYO_KBN = "equip_ryuyo_kbn";
// △△△ IT1-2024-0000025 Modify END
		
	/********************************************************************
	 * 乗り換え登録不可能な異動予約の一覧
	 * 異動区分、異動予約詳細コードの組み合わせで定義すること
	 * "*"はどのコードでも可
	 *******************************************************************/
	private static final String[][] DENY_IDO_RSV_LIST = {
		{"00005", "007"},	// 解約
		{"00006", "007"},	// 撤去(解約)
		{"00009", "003"},	// コース変更
		{"00019", "*"},		// 住所変更・登録
		{"00020", "*"},		// 住所変更・確定
		{"00024", "005"},	// 休止受付
		{"00031", "016"},	// オプション解約
		{"00031", "018"},	// サブオプション解約
// ▽▽▽ IT1-2024-0000034 ADD START
		{"00003", "016"},	// オプション解約(オプション引継)
// △△△ IT1-2024-0000034 ADD END 
	};
	
	/** 
	 * サービス契約回線内訳転送項目  
	 **/
	private static final String[] TRANFER_ITEM_EKK0251A010 = {
		 EKK0251A010CBSMsg1List.KAISEN_PLACE_TELNO 		// 回線場所電話番号	KAISEN_PLACE_TELNO
		,EKK0251A010CBSMsg1List.KAISEN_PLACE_AD_CD		// 回線場所住所コード	KAISEN_PLACE_AD_CD
		,EKK0251A010CBSMsg1List.KAISEN_PLACE_PCD		// 回線場所郵便番号	KAISEN_PLACE_PCD
		,EKK0251A010CBSMsg1List.KAISEN_PLACE_STATE_NM	// 回線場所都道府県名	KAISEN_PLACE_STATE_NM
		,EKK0251A010CBSMsg1List.KAISEN_PLACE_CITY_NM	// 回線場所市区町村名	KAISEN_PLACE_CITY_NM
		,EKK0251A010CBSMsg1List.KAISEN_PLACE_OAZTSU_NM	// 回線場所大字通称名	KAISEN_PLACE_OAZTSU_NM
		,EKK0251A010CBSMsg1List.KAISEN_PLACE_AZCHO_NM	// 回線場所字丁目名	KAISEN_PLACE_AZCHO_NM
		,EKK0251A010CBSMsg1List.KAISEN_PLACE_BNCHIGO	// 回線場所番地号	KAISEN_PLACE_BNCHIGO
		,EKK0251A010CBSMsg1List.KAISEN_PLACE_ADRTTM		// 回線場所住所補記・建物名	KAISEN_PLACE_ADRTTM
		,EKK0251A010CBSMsg1List.KAISEN_PLACE_ADRRM		// 回線場所住所補記・部屋番号	KAISEN_PLACE_ADRRM
		,EKK0251A010CBSMsg1List.KAISEN_PLACE_RENBAN		// 回線場所連番
		,EKK0251A010CBSMsg1List.ROZETT_STC_STAT_CD		// ローゼット設置状態コード	ROZETT_STC_STAT_CD
// ▽▽▽ IT1-2024-0000025 ADD START
		,EKK0251A010CBSMsg1List.AD_FORM_CD				// 住所形態コード AD_FORM_CD
// △△△ IT1-2024-0000025 ADD END
// ▽▽▽ IT1-2024-0000031 ADD START
		,EKK0251A010CBSMsg1List.KODATE_KCKU_FLR_CNT_CD	// 戸建建築階数コード
		,EKK0251A010CBSMsg1List.SHUGJ_NYUKYO_FLR_CNT_CD	// 集合住宅入居階数コード
// △△△ IT1-2024-0000031 ADD END
	};
	
	/** PON種別コード(1:E-PON/2:GE-PON/3:10GE-PON) */
	private static final String PON_SBT_CD = "pon_sbt_cd";

	/** 親機種別コード(01:o-ADS/02:E-PON/03:GE-PON/04:10G-EPON) */
	private static final String OYA_KIKI_SBT_CD = "oya_kiki_sbt_cd";
	
	/** ルータ種類(0:無し/1:BBR/2:多機能/3:HGW) */
	private static final String ROUTER_TYPE = "router_type";

	/** ルータ速度(10/20/30) */
	private static final String ROUTER_SPEED = "router_speed";

	/** ローゼット設置状態コード(0:未設置/1:設置済) */
	private static final String ROZETT_STC_STAT_CD = "rozett_stc_stat_cd";
	
	/** 有線／無線 (1:有線 2:無線 3:選択なし) */
	private static final String YUSEN_MUSEN = "yusen_musen";
	
	/** PLC(1:メッシュWiFi/2:中継器/3:なし) */
	private static final String PLC = "plc";
	
	/**
	 * 設備流用パターン判定テーブル
	 * <br>
	 * *は全てに一致
	 * -------------------------------------------------------------------
	 * PON種別, 親機器種別, ルータ種類, ルータ速度, ローゼット化, 設備流用パターンコード
	 **/
	private static final String[][] EQUIP_RYUYO_JG_TBL = {
// ANK-4577-00-00 MOD START
//		{"3", 	"04", 	"3", 	"*", 	"*", 	"2"},
		{"3", 	"04", 	"3", 	"*", 	"*", 	"1"},
// ANK-4577-00-00 MOD END
		{"3", 	"04", 	"2", 	"30", 	"*",	"1"},
		{"3", 	"04", 	"0", 	"*", 	"*",	"1"},
		{"3", 	"04", 	"*", 	"*", 	"*",	"2"},
		{"2", 	"04", 	"*", 	"*", 	"*",	"2"},
		{"2", 	"03", 	"*", 	"*", 	"*",	"3"},
// ▽▽▽ IT1-2024-0000025 Modify START
//		{"1", 	"03", 	"*", 	"*", 	"*",	"3"},
		{"1", 	"02", 	"*", 	"*", 	"*",	"3"},
// △△△ IT1-2024-0000025 Modify END
	};
	
	/**
	 * コンストラクタ
	 */
	public JKKNrikemtSvkeiShokaiCC()
	{
	}
	
	/**
	 * 乗り換え元リスト作成
	 * <br>
	 * @param handle
	 * @param param
	 * @param fixedText
	 * @return
	 * @throws Throwable
	 */
	@SuppressWarnings("unchecked")
	public IRequestParameterReadWrite createNrkemtList(SessionHandle handle,
			IRequestParameterReadWrite param, String fixedText) throws Throwable
	{
		// 呼び出し元のパラメータを取得
		HashMap<String, Object> paramMap = (HashMap<String, Object>)param.getData(fixedText);

		// 検索条件を取得
		String keySysid = (String)paramMap.get("key_sysid");
		boolean fromSimple = "0".equals(paramMap.get("simple_plan"));
		
		// SC呼び出し部品のインスタンス生成
		ServiceComponentRequestInvoker scCall = new ServiceComponentRequestInvoker();
		
		// サービス契約一覧照会　EKK0081B004
		Object[][] ekk0081b004In =
		{
			 {EKK0081B004CBSMsg.TEMPLATEID, 		TEMPLATE_ID_EKK0081B004}		// テンプレートＩＤ
			,{EKK0081B004CBSMsg.DISPLAY_NUM, 		"1000"}							// 表示件数
			,{EKK0081B004CBSMsg.DISPLAY_PAGE_NUM, 	"1"}							// 表示ページ数
			,{EKK0081B004CBSMsg.MAX_SEARCH_NUM, 	"1000"}							// 最大件数
			,{EKK0081B004CBSMsg.FUNC_CODE, 			JPCModelConstant.FUNC_CD_1}		// 機能コード
			,{EKK0081B004CBSMsg.KEY_SYSID, 			keySysid}						// ＫＥＹ＿ＳＹＳＩＤ
			,{EKK0081B004CBSMsg.KEY_PRC_GRP_CD, 	"02"}							// ＫＥＹ＿料金グループコード
		};
		
		// 取得データをリストに追加
		ArrayList<HashMap<String, Object>> list = new ArrayList<HashMap<String, Object>>();
		
		// サービスIF実行
		CAANMsg[] ekk0081b004MsgList = callSC(handle, scCall, param, fixedText, ekk0081b004In)
				.getCAANMsgList(EKK0081B004CBSMsg.EKK0081B004CBSMSG1LIST);

		if ( ekk0081b004MsgList != null && ekk0081b004MsgList.length > 0 )
		{
			// 使用済の乗り換え元を検索
			ArrayList<String> usedNrkemtList = getUsedNrkemtList(handle, param, fixedText, scCall, keySysid);
			// 
			for (CAANMsg msg : ekk0081b004MsgList)
			{
				// 解約・キャンセル済は除外
				String svcKeiStat = msg.getString(EKK0081B004CBSMsg1List.SVC_KEI_STAT);
				if (EXCLUDE_STAT_LIST.contains(svcKeiStat))
				{
					continue;
				}
				
				//
				// 提供中であること。
				// 検索対象がシンプル／シンプル以外であること
				// 既に乗り換えで利用されていないこと（このチェック方法は問題あり）
				//
				if ("100".equals(svcKeiStat) && 
						SIMPLE_PLAN_PCRS_LIST.contains(msg.getString(EKK0081B004CBSMsg1List.PCRS_CD)) == fromSimple && 
						!usedNrkemtList.contains(msg.getString(EKK0081B004CBSMsg1List.SVC_KEI_NO)))
				{
					HashMap<String, Object> svcInfoMap = new HashMap<String, Object>();
					svcInfoMap.put(EKK0081B004CBSMsg1List.SVC_KEI_NO, msg.getString(EKK0081B004CBSMsg1List.SVC_KEI_NO));
					svcInfoMap.put(EKK0081B004CBSMsg1List.SVC_KEI_KAISEN_UCWK_NO, msg.getString(EKK0081B004CBSMsg1List.SVC_KEI_KAISEN_UCWK_NO));
					svcInfoMap.put(EKK0081B004CBSMsg1List.PCRS_CD, msg.getString(EKK0081B004CBSMsg1List.PCRS_CD));
					
					// 乗り換え可否をチェックする
					if (checkNrkemtKH(handle, param, fixedText, scCall, svcInfoMap))
					{
						// マップに登録
						list.add(svcInfoMap);
					}
				}
			}
		}
	
		// 返却情報を返す。
		paramMap.put("KK0081_NRKEMT_List", list);
		
		return param;
	}
	
	/**
	 * 乗り換え元情報取得
	 * <br>
	 * @param handle
	 * @param param
	 * @param fixedText
	 * @return
	 * @throws Throwable
	 */
	@SuppressWarnings("unchecked")
	public IRequestParameterReadWrite getNrkemtInfo(SessionHandle handle,
			IRequestParameterReadWrite param, String fixedText) throws Throwable
	{
		// 呼び出し元のパラメータを取得
		HashMap<String, Object> paramMap = (HashMap<String, Object>)param.getData(fixedText);
		HashMap<String, Object> inMap = new HashMap<String, Object>();
		HashMap<String, Object> outMap = new HashMap<String, Object>();

		// SC呼び出し部品のインスタンス生成
		ServiceComponentRequestInvoker scCall = new ServiceComponentRequestInvoker();

		// 検索条件を取得
		inMap.put("svc_kei_no", paramMap.get("key_svc_kei_no"));
		inMap.put("svc_kei_kaisen_ucwk_no", paramMap.get("key_svc_kei_kaisen_ucwk_no"));
		
		if (JKKStringUtil.isNullEmpty(inMap.get("svc_kei_kaisen_ucwk_no")))
		{
			// サービス契約から内訳番号を検索する EKK0241B001
			CAANMsg ekk0241b001 = getEKK0241B001(handle, param, fixedText, scCall, inMap);
			if (ekk0241b001 != null)
			{
				inMap.put("svc_kei_kaisen_ucwk_no", ekk0241b001.getString(EKK0241B001CBSMsg1List.SVC_KEI_KAISEN_UCWK_NO));
			}
		}
		
		// 利用場所を取得
		outMap = getUsePlaceAd(handle, param, fixedText, scCall, inMap, outMap);
		
		// 工事案件番号を取得
		CAANMsg eku0081b020cbsmsg = getEKU0081B020(handle, param, fixedText, scCall, inMap);
		if (eku0081b020cbsmsg != null && "200".equals(eku0081b020cbsmsg.getString(EKU0081B020CBSMsg1List.KOJIAK_STAT)))
		{
			// 工事案件番号を設定
			outMap.put(EKU0081B020CBSMsg1List.KOJIAK_NO, eku0081b020cbsmsg.getString(EKU0081B020CBSMsg1List.KOJIAK_NO));
		}

		// 機器情報の取得
		outMap = getDeviceInfo(handle, param, fixedText, scCall, inMap, outMap);
		
		// 設備流用有無の判定
// ▽▽▽ IT1-2024-0000025 Modify START
//		outMap.put(SETUBI_RUYO_KBN, getSetubiRuyoKbn(outMap));
		outMap.put(EQUIP_RYUYO_KBN, getSetubiRuyoKbn(outMap));
// △△△ IT1-2024-0000025 Modify END
		
		// 乗り換え元情報を返却
		ArrayList<HashMap<String, Object>> list = new ArrayList<HashMap<String, Object>>();
		list.add(outMap);
		paramMap.put("KK0081_NRKEMT_INFO_List", list);
		
		return param;
	}
	
	/**
	 * 乗り換え元の対象かどうかを可否で返す。
	 * <br>
	 * @param inMap
	 * @return true:可 false:否
	 */
	private boolean checkNrkemtKH(
			SessionHandle handle,
			IRequestParameterReadWrite param,  
			String fixedText,
			ServiceComponentRequestInvoker scCall,
			HashMap<String, Object> inMap) throws Throwable
	{
		
		// 同一回線にネット単独であることを確認
		CAANMsg[] ekk0081b011cbs1msgList = getEKK0081B011(handle, param, fixedText, scCall, inMap);
		for (CAANMsg ekk0081b011cbs1msg : ekk0081b011cbs1msgList)
		{
			if (EXCLUDE_STAT_LIST.contains(ekk0081b011cbs1msg.getString(EKK0081B011CBSMsg1List.SVC_KEI_STAT)))
			{
				continue;
			}
			if (EXCLUDE_PRC_GRP_CD_LIST.contains(ekk0081b011cbs1msg.getString(EKK0081B011CBSMsg1List.PRC_GRP_CD)))
			{
				return false;
			}
		}
		
		// 住所変更中の判定 EKK2091B001
		CAANMsg ekk2091b001cbs1msg = getgetEKK2091B001(handle, param, fixedText, scCall, inMap);
		if (ekk2091b001cbs1msg != null && "001".equals(ekk2091b001cbs1msg.getString(EKK2091B001CBSMsg1List.ADCHG_STAT)))
		{
			return false;
		}
		
		// 工事案件番号の取得	EKU0081B020
		// 仕掛中の工事が取得できた場合、エラー
		CAANMsg eku0081b020cbs1msg = getEKU0081B020(handle, param, fixedText, scCall, inMap);
		if (eku0081b020cbs1msg == null || !"200".equals(eku0081b020cbs1msg.getString(EKU0081B020CBSMsg1List.KOJIAK_STAT)))
		{
			// 仕掛中の工事がある場合、乗換対象外
			return false;
		}
		
		// 異動の取得 EKK1681B001
		CAANMsg[] ekk1681b001CbsMsg1List =  getEKK1681B001(handle, param, fixedText, scCall, inMap);
		for (CAANMsg ekk1681b001cbsmsg : ekk1681b001CbsMsg1List)
		{
			// 異動区分、異動予約詳細の組み合わせでチェック
			if (ACCEPT_IDO_RSV_STAT.contains(ekk1681b001cbsmsg.getString(EKK1681B001CBSMsg1List.IDO_RSV_STAT_CD))
					&& checkIdoRsv(ekk1681b001cbsmsg.getString(EKK1681B001CBSMsg1List.IDO_DIV), 
							ekk1681b001cbsmsg.getString(EKK1681B001CBSMsg1List.IDO_RSV_DTL_CD)))
			{
				return false;
			}
		}
		
		return true;
	}
	
	/**
	 * 設備流用区分を返す
	 * <br>
	 * @param param
	 * @return
	 */
	private String getSetubiRuyoKbn(HashMap<String, Object> param)
	{
		
		for (String[] item : EQUIP_RYUYO_JG_TBL)
		{
			if (
				(item[0].equals("*") || item[0].equals(param.get(PON_SBT_CD))) && 		// ONU
				(item[1].equals("*") || item[1].equals(param.get(OYA_KIKI_SBT_CD))) &&		// OLT
				(item[2].equals("*") || item[2].equals(param.get(ROUTER_TYPE))) &&		// ルータタイプ
				(item[3].equals("*") || item[3].equals(param.get(ROUTER_SPEED))) &&		// ルータ速度
				(item[4].equals("*") || item[4].equals(param.get(ROZETT_STC_STAT_CD))) 	// ローゼット化設置状態コード
				)
			{
				return item[5];
			}
		}
// ▽▽▽ IT1-2024-0000025 Modify START
// 一致しない場合は、「工事有り（宅内調査あり）」を返す様に変更する
//		return "";
		return "3";
// △△△ IT1-2024-0000025 Modify END
	}
	
	/**
	 * 利用場所関連情報を取得
	 * <br>
	 * @param handle
	 * @param param
	 * @param fixedText
	 * @param scCall
	 * @param inMap
	 * @param outMap
	 * @throws Throwable
	 */
	private HashMap<String, Object> getUsePlaceAd(
		SessionHandle handle,
		IRequestParameterReadWrite param,  
		String fixedText,
		ServiceComponentRequestInvoker scCall,
		HashMap<String, Object> inMap, 
		HashMap<String, Object> outMap) throws Throwable
	{
		
		// 利用場所の取得
		CAANMsg ekk0251a010cbsmsg =  getEKK0251A010(handle, param, fixedText, scCall, inMap);
		if (ekk0251a010cbsmsg != null)
		{
			transfer(outMap, ekk0251a010cbsmsg, TRANFER_ITEM_EKK0251A010);
		}
		
		// 申込収容位置空き情報
		CAANMsg eku0281a010cbsmsg =  getEKU0281A010(handle, param, fixedText, scCall, inMap);
		if (eku0281a010cbsmsg != null)
		{
			outMap.put(OYA_KIKI_SBT_CD, eku0281a010cbsmsg.getString(EKU0281A010CBSMsg1List.OYA_KIKI_SBT_CD));
		}
		
		return outMap;
	}
	
	/**
	 * 指定項目を転送する。
	 * <br>
	 * @param outMap
	 * @param message
	 * @param tranItems
	 */
	private void transfer(HashMap<String, Object> outMap, CAANMsg message, String[] tranItems)
	{
		for (String item : tranItems)
		{
			outMap.put(item, message.getString(item));
		}
	}
	
	/**
	 * 機器情報を取得
	 * <br>
	 * @param handle
	 * @param param
	 * @param fixedText
	 * @param scCall
	 * @param inMap
	 * @param outMap
	 * @throws Throwable
	 */
	private HashMap<String, Object> getDeviceInfo(
			SessionHandle handle,
			IRequestParameterReadWrite param,  
			String fixedText,
			ServiceComponentRequestInvoker scCall,
			HashMap<String, Object> inMap, 
			HashMap<String, Object> outMap) throws Throwable
	{
		// 業務パラメータからメッシュ用判定の料金コースコードを取得
		String meshPcrsCd = getWorkParamValue(handle, param, fixedText, scCall, ZM_WORK_PARAM_KK_MESHWIFI_PCRS_CD);
		
		// ルータは無しで初期化
		outMap.put(ROUTER_TYPE, "0");
		outMap.put(YUSEN_MUSEN, "3");
		outMap.put(PLC, "3");

		// 機器の取得 EKK0341B002
		CAANMsg[] ekk0341b002CbsMsg1List =  getEKK0341B002(handle, param, fixedText, scCall, inMap);
		for (CAANMsg ekk0341b00cbsmsg : ekk0341b002CbsMsg1List)
		{
			// 機器のステータスで対象外を削除
			if (EXCLUDE_STAT_LIST.contains(ekk0341b00cbsmsg.getString(EKK0341B002CBSMsg1List.KKTK_SVC_KEI_STAT)))
			{
				continue;
			}
			String kktkSvcCd = ekk0341b00cbsmsg.getString(EKK0341B002CBSMsg1List.KKTK_SVC_CD);
			if ("C015".equals(kktkSvcCd))
			{
				// 中継器／メッシュWiFiの判定
				if (meshPcrsCd.equals(ekk0341b00cbsmsg.getString(EKK0341B002CBSMsg1List.PCRS_CD)))
				{
					// メッシュ
					outMap.put(PLC, "1");	// メッシュを設定
				}
// ▽▽▽ IT1-2024-0000025 Modify Start
// PLCモデムが中継器と誤判定される為、PLCモデム以外を追加
//				else 
// ▽▽▽ IT1-2024-0000026 Modify START
// メッシュと中継器の両方が存在する場合、メッシュを優先する様に変更(PLC_TYPEが初期値の場合、値を上書きする）
//				else if (!"C26".equals(ekk0341b00cbsmsg.getString(EKK0341B002CBSMsg1List.PCRS_CD)))
				else if (!"C26".equals(ekk0341b00cbsmsg.getString(EKK0341B002CBSMsg1List.PCRS_CD)) && "3".equals(outMap.get(PLC)))
// △△△ IT1-2024-0000026 Modify END
// △△△ IT1-2024-0000025 Modify END
				{
					// 中継器
					outMap.put(PLC, "2");	// 中継器を設定
				}
			}
			else if ("C012".equals(kktkSvcCd) || "C014".equals(kktkSvcCd) || "C024".equals(kktkSvcCd) || "C025".equals(kktkSvcCd))
			{
				CAANMsg zm0411a010 = null;
				
				// 型式が入っていない場合、とりあえずマスタは検索しない。
				if (!JKKStringUtil.isNullBlank(ekk0341b00cbsmsg.getString(EKK0341B002CBSMsg1List.TAKNKIKI_MODEL_CD)))
				{
					// 型式を取得 EZM0411A010
					zm0411a010 = getEZM0411A010(handle, param, fixedText, scCall, ekk0341b00cbsmsg.getString(EKK0341B002CBSMsg1List.TAKNKIKI_MODEL_CD));
				}
				if ("C012".equals(kktkSvcCd))	// ONU
				{
					// PON種別を取得
					outMap.put(PON_SBT_CD, getValue(zm0411a010, EZM0411A010CBSMsg1List.PON_SBT_CD, "2"));
				}
				else if ("C014".equals(kktkSvcCd))	// BBR
				{
					// 有料無料コード
					if ("1".equals(getValue(zm0411a010, EZM0411A010CBSMsg1List.YRYO_MRYO_CD, "")))
					{
						// 無線ルータ
						outMap.put(YUSEN_MUSEN, "1");
					}
					else
					{
						// 有線ルータ
						outMap.put(YUSEN_MUSEN, "2");
					}
					
					// ルーター速度種別コード
					outMap.put(ROUTER_SPEED, getValue(zm0411a010, EZM0411A010CBSMsg1List.ROUTER_SPEED_SBT_CD, "10"));
					outMap.put(ROUTER_TYPE, "1");
				}
				else  // 多機能・HGW
				{
					// HGW・多機能ルータの場合
					// 機器OP対象機器の場合、機器OPを取得 EKK2811B010
					CAANMsg[] ekk281b010cbsmsgList = getEKK2811B010(handle, param, fixedText, scCall, ekk0341b00cbsmsg.getString(EKK0341B002CBSMsg1List.KKTK_SVC_KEI_NO));
					for (CAANMsg msg : ekk281b010cbsmsgList)
					{
						if (EXCLUDE_STAT_LIST.contains(msg.getString(EKK2811B010CBSMsg1List.KKOP_SVC_KEI_STAT)))
						{
							continue;
						}
						if ("G01".equals(msg.getString(EKK2811B010CBSMsg1List.KKOP_SVC_CD)))
						{
							if ("G01".equals(msg.getString(EKK2811B010CBSMsg1List.PCRS_CD)))
							{
								// 有線ルータ
								outMap.put(YUSEN_MUSEN, "2");
							}
							else if ("G02".equals(msg.getString(EKK2811B010CBSMsg1List.PCRS_CD)))
							{
								// 無線ルータ
								outMap.put(YUSEN_MUSEN, "1");
							}
						}
					}
					
					// HGWの場合はPON種別は10G-PON
					if ("C025".equals(kktkSvcCd))
					{
						// PON種別
						outMap.put(PON_SBT_CD, getValue(zm0411a010, EZM0411A010CBSMsg1List.PON_SBT_CD, "3"));
						// ルーター速度種別コード
						outMap.put(ROUTER_SPEED, getValue(zm0411a010, EZM0411A010CBSMsg1List.ROUTER_SPEED_SBT_CD, "30"));
						//
						outMap.put(ROUTER_TYPE, "3");
					}
					else
					{
						// ルーター速度種別コード
						outMap.put(ROUTER_SPEED, getValue(zm0411a010, EZM0411A010CBSMsg1List.ROUTER_SPEED_SBT_CD, "20"));
						outMap.put(ROUTER_TYPE, "2");
					}
				}
			}
		}
		
		return outMap;
	}
	
	/**
	 * 値を取得
	 * <br>
	 * @param msg
	 * @param key
	 * @param defultValue
	 * @return
	 */
	private String getValue(CAANMsg msg, String key, String defultValue)
	{
		if (msg == null)
		{
			return defultValue;
		}
		return msg.getString(key);
	}
	
	/**
	 * 異動予約チェック
	 * <br>
	 * @param idoDiv	異動区分
	 * @param idoRsvDtlCd	異動予約詳細コード
	 * @return false:なし true:チェックエラー
	 */
	private boolean checkIdoRsv(String idoDiv, String idoRsvDtlCd)
	{
		for (String[] item : DENY_IDO_RSV_LIST)
		{
			if (item[0].equals("*") || item[0].equals(idoDiv))
			{
				if (item[1].equals("*") || item[1].equals(idoRsvDtlCd))
				{
					return true;
				}
			}
		}
		return false;
	}
	
	/**
	 * 使用済の乗り換え元サービス契約番号取得
	 * <br>
	 * @param handle
	 * @param param
	 * @param fixedText
	 * @param scCall
	 * @param keySysid
	 * @return
	 * @throws Throwable
	 */
	private ArrayList<String> getUsedNrkemtList(
			SessionHandle handle,
			IRequestParameterReadWrite param,  
			String fixedText,
			ServiceComponentRequestInvoker scCall,
			String keySysid) throws Throwable
	{
		ArrayList<String> list = new ArrayList<String>();
		
		CAANMsg[] ekk0081b519cbs1list = getEKK0081B519(handle, param, fixedText, scCall, keySysid);
		for (CAANMsg msg : ekk0081b519cbs1list)
		{
// ▽▽▽ IT1-2024-0000025 Modify START
//			if (EXCLUDE_STAT_LIST.equals(msg.getString(EKK0081B519CBSMsg1List.SVC_KEI_STAT)))
			if (EXCLUDE_STAT_LIST.contains(msg.getString(EKK0081B519CBSMsg1List.SVC_KEI_STAT)))
// △△△ IT1-2024-0000025 Modify END
			{
				continue;
			}
			String nrkemtSvkeiNo = msg.getString(EKK0081B519CBSMsg1List.NRKEMT_SVKEI_NO);
			if (!JKKStringUtil.isNullBlank(nrkemtSvkeiNo))
			{
				list.add(nrkemtSvkeiNo);
			}
		}
		
		return list;
	}
	
	/**
	 * サービス契約一覧照会（SYSID）3
	 * <br>
	 * @param handle
	 * @param param
	 * @param fixedText
	 * @param scCall
	 * @param inMap
	 * @return
	 * @throws Throwable
	 */
	private CAANMsg[] getEKK0081B519(
		SessionHandle handle,
		IRequestParameterReadWrite param,  
		String fixedText,
		ServiceComponentRequestInvoker scCall,
		String keySysid) throws Throwable
	{
		//  EKK0081B519_サービス契約一覧照会（SYSID）3
		Object[][] ekk0081b519In =
		{
			 {EKK0081B519CBSMsg.TEMPLATEID, TEMPLATE_ID_EKK0081B519}			// テンプレートＩＤ
			,{EKK0081B519CBSMsg.FUNC_CODE, 	JPCModelConstant.FUNC_CD_1}			// 機能コード
			,{EKK0081B519CBSMsg.KEY_SYSID, 	keySysid}							// ＫＥＹ＿ＳＹＳＩＤ
		};
		
		// サービスIF実行
		CAANMsg[] ekk0081b519MsgList = callSC(handle, scCall, param, fixedText, ekk0081b519In)
				.getCAANMsgList(EKK0081B519CBSMsg.EKK0081B519CBSMSG1LIST);
		if (ekk0081b519MsgList != null)
		{
			return ekk0081b519MsgList;
		}
		
		return new CAANMsg[0];
	}
	
	/**
	 * 同一利用場所サービス契約一覧照会
	 * <br>
	 * @param handle
	 * @param param
	 * @param fixedText
	 * @param scCall
	 * @param inMap
	 * @return
	 * @throws Throwable
	 */
	private CAANMsg[] getEKK0081B011(
		SessionHandle handle,
		IRequestParameterReadWrite param,  
		String fixedText,
		ServiceComponentRequestInvoker scCall,
		HashMap<String, Object> inMap) throws Throwable
	{
		// EKK0081B011_同一利用場所サービス契約一覧照会
		Object[][] ekk0081b011In =
		{
			 {EKK0081B011CBSMsg.TEMPLATEID, 				TEMPLATE_ID_EKK0081B011}				// テンプレートＩＤ
			,{EKK0081B011CBSMsg.FUNC_CODE, 					JPCModelConstant.FUNC_CD_2}				// 機能コード
			,{EKK0081B011CBSMsg.KEY_SVC_KEI_KAISEN_UCWK_NO, inMap.get("svc_kei_kaisen_ucwk_no")}	// ＫＥＹ＿移転先回線サービス契約番号
		};
		
		// サービスIF実行
		CAANMsg[] ekk0081b011MsgList = callSC(handle, scCall, param, fixedText, ekk0081b011In)
				.getCAANMsgList(EKK0081B011CBSMsg.EKK0081B011CBSMSG1LIST);
		if (ekk0081b011MsgList != null)
		{
			return ekk0081b011MsgList;
		}
		return new CAANMsg[0];
	}
	
	/**
	 * サービス契約回線内訳一覧照会
	 * <br>
	 * @param handle
	 * @param param
	 * @param fixedText
	 * @param scCall
	 * @param inMap
	 * @param outMap
	 * @return
	 * @throws Throwable
	 */
	private CAANMsg getEKK0251A010(
			SessionHandle handle,
			IRequestParameterReadWrite param,  
			String fixedText,
			ServiceComponentRequestInvoker scCall,
			HashMap<String, Object> inMap) throws Throwable
	{
		// EKK0251A010_サービス契約回線内訳一覧照会
		Object[][] ekk0251a010In =
		{
			 {EKK0251A010CBSMsg.TEMPLATEID, 				TEMPLATE_ID_EKK0251A010}				// テンプレートＩＤ
			,{EKK0251A010CBSMsg.FUNC_CODE, 					JPCModelConstant.FUNC_CD_2}				// 機能コード
			,{EKK0251A010CBSMsg.KEY_SVC_KEI_KAISEN_UCWK_NO, inMap.get("svc_kei_kaisen_ucwk_no")}	// ＫＥＹ＿サービス契約回線内訳番号
		};
		
		// サービスIF実行
		CAANMsg[] ekk0251a010MsgList = callSC(handle, scCall, param, fixedText, ekk0251a010In)
											.getCAANMsgList(EKK0251A010CBSMsg.EKK0251A010CBSMSG1LIST);
		
		if (ekk0251a010MsgList != null && ekk0251a010MsgList.length > 0)
		{
			return ekk0251a010MsgList[0];
		}
		return null;		
	}
	
	/**
	 * サービス契約回線内訳一覧照会
	 * <br>
	 * @param handle
	 * @param param
	 * @param fixedText
	 * @param scCall
	 * @param inMap
	 * @param outMap
	 * @return
	 * @throws Throwable
	 */
	private CAANMsg getEKK0241B001(
			SessionHandle handle,
			IRequestParameterReadWrite param,  
			String fixedText,
			ServiceComponentRequestInvoker scCall,
			HashMap<String, Object> inMap) throws Throwable
	{
		// EKK0241B001_サービス契約回線内訳一覧照会
		Object[][] ekk0242b001In =
		{
			 {EKK0241B001CBSMsg.TEMPLATEID, 	TEMPLATE_ID_EKK0241B001}		// テンプレートＩＤ
			,{EKK0241B001CBSMsg.FUNC_CODE, 		JPCModelConstant.FUNC_CD_2}		// 機能コード
			,{EKK0241B001CBSMsg.KEY_SVC_KEI_NO, inMap.get("svc_kei_no")}		// ＫＥＹ＿サービス契約番号
		};
		
		// サービスIF実行
		CAANMsg[] ekk0241b001MsgList = callSC(handle, scCall, param, fixedText, ekk0242b001In)
											.getCAANMsgList(EKK0241B001CBSMsg.EKK0241B001CBSMSG1LIST);
		
		if (ekk0241b001MsgList != null && ekk0241b001MsgList.length > 0)
		{
			return ekk0241b001MsgList[0];
		}
		return null;		
	}

	/**
	 * 申込収容位置空き情報一意照会
	 * <br>
	 * @param handle
	 * @param param
	 * @param fixedText
	 * @param scCall
	 * @param inMap
	 * @return
	 * @throws Throwable
	 */
	private CAANMsg getEKU0281A010(
			SessionHandle handle,
			IRequestParameterReadWrite param,  
			String fixedText,
			ServiceComponentRequestInvoker scCall,
			HashMap<String, Object> inMap) throws Throwable
	{
		// EKU0281A010_申込収容位置空き情報一意照会
		Object[][] eku0281a010In =
		{
			 {EKU0281A010CBSMsg.TEMPLATEID, 				TEMPLATE_ID_EKU0281A010}				// テンプレートＩＤ
			,{EKU0281A010CBSMsg.FUNC_CODE, 					JPCModelConstant.FUNC_CD_2}				// 機能コード
			,{EKU0281A010CBSMsg.KEY_SVC_KEI_KAISEN_UCWK_NO, inMap.get("svc_kei_kaisen_ucwk_no")}	// ＫＥＹ＿移転先回線サービス契約番号
		};
		
		
		// サービスIF実行
		CAANMsg[] eku0281a010MsgList = callSC(handle, scCall, param, fixedText, eku0281a010In)
											.getCAANMsgList(EKU0281A010CBSMsg.EKU0281A010CBSMSG1LIST);
		
		if (eku0281a010MsgList != null && eku0281a010MsgList.length > 0)
		{
			return eku0281a010MsgList[0];
		}
		return null;		
	}
	
	/**
	 * 住所変更一覧照会
	 * <br>
	 * @param handle
	 * @param param
	 * @param fixedText
	 * @param scCall
	 * @param inMap
	 * @return
	 * @throws Throwable
	 */
	private CAANMsg getgetEKK2091B001(
			SessionHandle handle,
			IRequestParameterReadWrite param,  
			String fixedText,
			ServiceComponentRequestInvoker scCall,
			HashMap<String, Object> inMap) throws Throwable

	{
		// EKK2091B001_住所変更一覧照会
		Object[][] ekk2091b001In =
		{
			 {EKK2091B001CBSMsg.TEMPLATEID, 				TEMPLATE_ID_EKK2091B001}				// テンプレートＩＤ
			,{EKK2091B001CBSMsg.FUNC_CODE, 					JPCModelConstant.FUNC_CD_1}				// 機能コード
			,{EKK2091B001CBSMsg.KEY_ITNM_SVKEI_KISUW_NO, 	inMap.get("svc_kei_kaisen_ucwk_no")}	// ＫＥＹ＿移転先回線サービス契約番号
		};
		
		
		// サービスIF実行
		CAANMsg[] ekk2091b001MsgList = callSC(handle, scCall, param, fixedText, ekk2091b001In)
											.getCAANMsgList(EKK2091B001CBSMsg.EKK2091B001CBSMSG1LIST);
		
		if (ekk2091b001MsgList != null && ekk2091b001MsgList.length > 0)
		{
			return ekk2091b001MsgList[0];
		}
		return null;
	}

	/**
	 * サービス契約_工事案件一覧照会(基本工事取得)
	 * <br>
	 * @param handle
	 * @param param
	 * @param fixedText
	 * @param scCall
	 * @param inMap
	 * @return
	 * @throws Throwable
	 */
	private CAANMsg getEKU0081B020(
			SessionHandle handle,
			IRequestParameterReadWrite param,  
			String fixedText,
			ServiceComponentRequestInvoker scCall,
			HashMap<String, Object> inMap) throws Throwable
	{
		// EKU0081B020_サービス契約_工事案件一覧照会(基本工事取得)
		Object[][] eku0081b020In =
		{
			 {EKU0081B020CBSMsg.TEMPLATEID, TEMPLATE_ID_EKU0081B020}										// テンプレートＩＤ
			,{EKU0081B020CBSMsg.FUNC_CODE, 	JPCModelConstant.FUNC_CD_2}										// 機能コード
			,{EKU0081B020CBSMsg.KEY_SVC_KEI_NO, 	inMap.get("svc_kei_no")}								// ＫＥＹ＿サービス契約番号
			,{EKU0081B020CBSMsg.KEY_SVC_KEI_KAISEN_UCWK_NO, 	inMap.get("svc_kei_kaisen_ucwk_no")}		// ＫＥＹ＿サービス契約回線内訳番号
		};
		
		
		// サービスIF実行
		CAANMsg[] eku0081b020MsgList = callSC(handle, scCall, param, fixedText, eku0081b020In)
											.getCAANMsgList(EKU0081B020CBSMsg.EKU0081B020CBSMSG1LIST);
		
		if (eku0081b020MsgList != null && eku0081b020MsgList.length > 0)
		{
			return eku0081b020MsgList[0];
		}
		return null;
	}
	
	/**
	 * 異動予約一覧照会
	 * <br>
	 * @param handle
	 * @param param
	 * @param fixedText
	 * @param scCall
	 * @param inMap
	 * @return
	 * @throws Throwable
	 */
	private CAANMsg[] getEKK1681B001(
			SessionHandle handle,
			IRequestParameterReadWrite param,  
			String fixedText,
			ServiceComponentRequestInvoker scCall,
			HashMap<String, Object> inMap) throws Throwable
	{
		// EKK1681B001_異動予約一覧照会
		Object[][] ekk1681b001In =
		{
			 {EKK1681B001CBSMsg.TEMPLATEID, TEMPLATE_ID_EKK1681B001}										// テンプレートＩＤ
			,{EKK1681B001CBSMsg.FUNC_CODE, 	JPCModelConstant.FUNC_CD_2}										// 機能コード
			,{EKK1681B001CBSMsg.KEY_SVC_KEI_NO, 	inMap.get("svc_kei_no")}								// ＫＥＹ＿サービス契約番号
		};
		
		
		// サービスIF実行
		CAANMsg[] ekk1681b001MsgList = callSC(handle, scCall, param, fixedText, ekk1681b001In)
											.getCAANMsgList(EKK1681B001CBSMsg.EKK1681B001CBSMSG1LIST);
		
		if (ekk1681b001MsgList != null)
		{
			return ekk1681b001MsgList;
		}
		return new CAANMsg[0];
	}
	
	/**
	 * 機器提供サービス契約一覧照会（サービス契約番号）
	 * <br>
	 * @param handle
	 * @param param
	 * @param fixedText
	 * @param scCall
	 * @param inMap
	 * @return
	 * @throws Throwable
	 */
	private CAANMsg[] getEKK0341B002(
			SessionHandle handle,
			IRequestParameterReadWrite param,  
			String fixedText,
			ServiceComponentRequestInvoker scCall,
			HashMap<String, Object> inMap) throws Throwable
	{
		// EKK0341B002_機器提供サービス契約一覧照会（サービス契約番号）
		Object[][] ekk0341b002In =
		{
			 {EKK0341B002CBSMsg.TEMPLATEID, TEMPLATE_ID_EKK0341B002}										// テンプレートＩＤ
			,{EKK0341B002CBSMsg.FUNC_CODE, 	JPCModelConstant.FUNC_CD_8}										// 機能コード
			,{EKK0341B002CBSMsg.KEY_SVC_KEI_NO, 	inMap.get("svc_kei_no")}								// ＫＥＹ＿サービス契約番号
		};
		
		
		// サービスIF実行
		CAANMsg[] ekk0341b002MsgList = callSC(handle, scCall, param, fixedText, ekk0341b002In)
											.getCAANMsgList(EKK0341B002CBSMsg.EKK0341B002CBSMSG1LIST);
		
		if (ekk0341b002MsgList != null)
		{
			return ekk0341b002MsgList;
		}
		return new CAANMsg[0];
	}
	
	/**
	 * 宅内機器型式一意照会
	 * <br>
	 * @param handle
	 * @param param
	 * @param fixedText
	 * @param scCall
	 * @param tanknaiModelCd
	 * @return
	 * @throws Throwable
	 */
	private CAANMsg getEZM0411A010(
			SessionHandle handle,
			IRequestParameterReadWrite param,  
			String fixedText,
			ServiceComponentRequestInvoker scCall,
			String tanknaiModelCd) throws Throwable
	{
		
		
		// EZM0411A010_宅内機器型式一意照会
		Object[][] ezm0411a010In =
		{
			 {EZM0411A010CBSMsg.TEMPLATEID, 			TEMPLATE_ID_EZM0411A010}		// テンプレートＩＤ
			,{EZM0411A010CBSMsg.FUNC_CODE, 				JPCModelConstant.FUNC_CD_1}		// 機能コード
			,{EZM0411A010CBSMsg.KEY_TAKNKIKI_MODEL_CD, 	tanknaiModelCd}					// ＫＥＹ＿サービス契約番号
		};
		
		
		// サービスIF実行
		CAANMsg[] ezm0411a010MsgList = callSC(handle, scCall, param, fixedText, ezm0411a010In)
											.getCAANMsgList(EZM0411A010CBSMsg.EZM0411A010CBSMSG1LIST);
		
		if (ezm0411a010MsgList != null && ezm0411a010MsgList.length > 0)
		{
			return ezm0411a010MsgList[0];
		}

		return null;
	}
	
	/**
	 * 機器オプションサービス契約一覧照会（機器提供ＳＶ）
	 * <br>
	 * @param handle
	 * @param param
	 * @param fixedText
	 * @param scCall
	 * @param tanknaiModelCd
	 * @return
	 * @throws Throwable
	 */
	private CAANMsg[] getEKK2811B010(
			SessionHandle handle,
			IRequestParameterReadWrite param,  
			String fixedText,
			ServiceComponentRequestInvoker scCall,
			String kktkSvcKeiNo) throws Throwable
	{
		
		// EKK2811B010_
		Object[][] ekk2811b010In =
		{
			 {EKK2811B010CBSMsg.TEMPLATEID, 			TEMPLATE_ID_EKK2811B010}		// テンプレートＩＤ
			,{EKK2811B010CBSMsg.FUNC_CODE, 				JPCModelConstant.FUNC_CD_1}		// 機能コード
			,{EKK2811B010CBSMsg.KEY_KKTK_SVC_KEI_NO, 	kktkSvcKeiNo}					// ＫＥＹ＿サービス契約番号
		};
		
		
		// サービスIF実行
		CAANMsg[] ekk2811b010MsgList = callSC(handle, scCall, param, fixedText, ekk2811b010In)
											.getCAANMsgList(EKK2811B010CBSMsg.EKK2811B010CBSMSG1LIST);
		
		if (ekk2811b010MsgList != null)
		{
			return ekk2811b010MsgList;
		}
		return new CAANMsg[0];
	}
	
	/**
	 * 業務パラメータ管理一意照会
	 * <br>
	 * @param handle
	 * @param param
	 * @param fixedText
	 * @param scCall
	 * @param workparamKey
	 * @return
	 * @throws Throwable
	 */
	private String getWorkParamValue(
			SessionHandle handle,
			IRequestParameterReadWrite param,  
			String fixedText,
			ServiceComponentRequestInvoker scCall,
			String workparamKey) throws Throwable	
	{
		
		// EZM0321A010_業務パラメータ管理一意照会
		Object[][] ezm0321a010In =
		{
			 {EZM0321A010CBSMsg.TEMPLATEID, 		TEMPLATE_ID_EZM0321A010}		// テンプレートＩＤ
			,{EZM0321A010CBSMsg.FUNC_CODE, 			JPCModelConstant.FUNC_CD_1}		// 機能コード
			,{EZM0321A010CBSMsg.KEY_WORK_PARAM_ID, 	workparamKey}					// ＫＥＹ＿業務パラメータＩＤ
		};
		
		
		// サービスIF実行
		CAANMsg[] ezm0321a010MsgList = callSC(handle, scCall, param, fixedText, ezm0321a010In)
											.getCAANMsgList(EZM0321A010CBSMsg.EZM0321A010CBSMSG1LIST);
		if (ezm0321a010MsgList != null && ezm0321a010MsgList.length > 0)
		{
			return ezm0321a010MsgList[0].getString(EZM0321A010CBSMsg1List.WORK_PARAM_SETTE_VALUE);
		}
		return "";
	}
	
	/**
	 * SC(サービスインターフェイス）を呼び出します。
	 * @param handle セッションハンドル
	 * @param scCall SC呼び出し部品
	 * @param param リクエストパラメータ
	 * @param dataMapKey パラメータキー
	 * @param mappingData マッピングデータ
	 * @return サービスインターフェイス実行結果
	 * @throws Throwable 例外が発生した場合
	 */
	@SuppressWarnings("unchecked")
	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);

		int status = msg.getInt(JCMConstants.STATUS_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));

		// 異常の場合、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] 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 errorCode リターンコード
	 * @param dataMapKey パラメータキー
	 * @return IRequestParameterReadWrite
	 * @throws RequestParameterException リクエストパラメータの操作でエラーが発生した場合
	 */
	@SuppressWarnings("unchecked")
	private IRequestParameterReadWrite editErrorInfoCom(IRequestParameterReadWrite param,
														CAANMsg[] templates, 
														int errorCode,
														String dataMapKey) throws RequestParameterException
	{
		CAANMsg template = templates[0];

		int templateStatus = template.getInt(JCMConstants.STATUS_INT_KEY);
		
		if (0 != errorCode)
		{
			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;
	}
}
