/*******************************************************************************
*	All Rights reserved,Copyright (c) K-Opticom
********************************************************************************
*＜プログラム内容＞
*	システム名		：eo顧客基幹システム
*	モジュール名	：JECNA0170001TPMA
*	ソースファイル名：JECNA0170001TPMA.java
*	作成者			：FJ）吉田
*	日付			：2023年08月01日
*＜機能概要＞
*	CNIFE047_契約一覧情報取得です。
*＜修正履歴＞
*	バージョン	修正日		修正者		修正内容
*	v65.00.00	2023/08/01	FJ）吉田	【ANK-4346-00-00】【eo定期】CCMG再構築対応
********************************************************************************/
package eo.ejb.cbs.mainproc;

import java.net.HttpURLConnection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.databind.JsonNode;
import com.fujitsu.futurity.model.base.CAANMsg;
import com.fujitsu.futurity.model.common.JCMAPLConstMgr;
import com.fujitsu.futurity.model.ejb.common.JSYejbLog;
import com.fujitsu.futurity.model.ejb.common.StatusCodes;
import com.fujitsu.futurity.model.ejb.common.fw.AgentDispatchContext;
import com.fujitsu.futurity.model.ejb.common.fw.TemplateMainHandler;

import eo.common.constant.JCKStrConst;
import eo.common.util.JCNStringUtil;
import eo.ejb.cbs.cbsmsg.ECNA0170001CBSMsg;
import eo.ejb.cbs.cbsmsg.ECNA0170001CBSMsg1List;
import eo.ejb.cbs.cbsmsg.ECNA0170001CBSMsg2List;
import eo.ejb.cbs.cbsmsg.ECNA0170001CBSMsg3List;
import eo.ejb.cbs.cbsmsg.ECNA0170001CBSMsg4List;
import eo.ejb.cbs.cbsmsg.ECNA0170001CBSMsg5List;
import eo.ejb.cbs.cbsmsg.ECNA0170001CBSMsg6List;
import eo.ejb.common.JCNCtrlCcmgConnectInfoImpl;


/**
 *  契約一覧情報取得（CCMG）独自処理部品です。
 * <br>
 * @author FJ
 *
 */
public class JECNA0170001TPMA implements TemplateMainHandler
{
	/** エラーフラグ(EA：設定値取得エラー) */
	private static final String EA_ERR_FLAG = "EA";
	
	/** エラーフラグ(EB：応答コードエラー) */
	private static final String EB_ERR_FLAG = "EB";
	
	/** エラーフラグ(EC：実行時エラー) */
	private static final String EC_ERR_FLAG = "EC";
	
	/** APIID */
	private static final String APIID = "CNIFE047";
	
	/** 接続モード取得キー */
	private static final String CCMG_MODE_KEY = "CCMG_CNIFE047_CONNECTION_MODE";
	
	/** CCMGの接続URL取得キー */
	private static final String CCMG_API_URL = "CCMG_CNIFE047_URL";
	
	/** CCMGの接続メソッド取得キー */
	private static final String CCMG_METHOD = "CCMG_CNIFE047_METHOD";
	
	/** CCMGのリクエストタイムアウト時間取得キー */
	private static final String CCMG_API_TIMEOUT = "CCMG_CNIFE047_TIMEOUT";
	
	/** CCMGのリトライ回数取得キー */
	private static final String CCMG_API_RETRY_CNT = "CCMG_CNIFE047_RETRYCOUNT";
	
	/** CCMGのリトライ間隔取得キー */
	private static final String CCMG_API_RETRY_INTERVAL = "CCMG_CNIFE047_RETRYINTERVAL";
	
	/** XML_PATH */
	protected static final String CCMG_CONNECTION_MODE_TEST_DIR = "CCMG_CONNECTION_MODE_TEST_DIR";
	
	/** 応答コードOK */
	private static final String CODE_OK = "00000";
	
	/** 【パラメータ一覧】  */
	/** ダミーURL */
	private static final String DUMMY_URL = "DUMMY";
	
	/** エラーコード */
	private static final String ERR_CD = "err_cd";
	
	/** 接続先（本番） */
	private static final String MODE_0 = "0";
	
	/** API送信 項目名 */
	private static final String[][] CNIFE047_REQ_INFO = new String[][]{
		  {"sysid",								ECNA0170001CBSMsg.SYSID}							// SYSID
		, {"service_id",						ECNA0170001CBSMsg.SERVICE_ID}						// コンテンツサービスID
		, {"contract_no",						ECNA0170001CBSMsg.CONTRACT_NO}						// 契約番号
		, {"contents_id",						ECNA0170001CBSMsg.CONTENTS_ID}						// コンテンツID
		, {"sort",								ECNA0170001CBSMsg.SORT}								// ソート順
		, {"sort_order",						ECNA0170001CBSMsg.SORT_ORDER}						// 昇順/降順
		, {"state",								ECNA0170001CBSMsg.STATE}							// 契約状態フラグ
		, {"contract_start_date_from",			ECNA0170001CBSMsg.CONTRACT_START_DATE_FROM}			// 契約開始日時（開始）
		, {"contract_start_date_to",			ECNA0170001CBSMsg.CONTRACT_START_DATE_TO}			// 契約開始日時（終了）
		, {"contract_end_date_from",			ECNA0170001CBSMsg.CONTRACT_END_DATE_FROM}			// 契約終了日時（開始）
		, {"contract_end_date_to",				ECNA0170001CBSMsg.CONTRACT_END_DATE_TO}				// 契約終了日時（終了）
		, {"contents_state",					ECNA0170001CBSMsg.CONTENTS_STATE}					// コンテンツ状態
		, {"contract_class",					ECNA0170001CBSMsg.CONTRACT_CLASS}					// 契約種別
		, {"uncontinue_flg",					ECNA0170001CBSMsg.UNCONTINUE_FLG}					// 非継続フラグ
		, {"contents_division",					ECNA0170001CBSMsg.CONTENTS_DIVISION}				// コンテンツ区分
		, {"price_flg",							ECNA0170001CBSMsg.PRICE_FLG}						// 料金フラグ
		, {"settlement_way_number",				ECNA0170001CBSMsg.SETTLEMENT_WAY_NUMBER}			// 決済方法番号
		, {"settlement_way_id",					ECNA0170001CBSMsg.SETTLEMENT_WAY_ID}				// 決済方法ID
		, {"latest_entry_contents_division",	ECNA0170001CBSMsg.LATEST_ENTRY_CONTENTS_DIVISION}	// 最新入会コンテンツ区分
		, {"auto_entry_contents_division",		ECNA0170001CBSMsg.AUTO_ENTRY_CONTENTS_DIVISION}		// 自動入会コンテンツ区分
		, {"line_option_service_division",		ECNA0170001CBSMsg.LINE_OPTION_SERVICE_DIVISION}		// 回線オプションサービス区分
		, {"return_contract",					ECNA0170001CBSMsg.RETURN_CONTRACT}					// コンテンツ契約情報要否
		, {"return_charge",						ECNA0170001CBSMsg.RETURN_CHARGE}					// 直近課金情報要否
		, {"return_contract_adds",				ECNA0170001CBSMsg.RETURN_CONTRACT_ADDS}				// 契約付加情報要否
		, {"return_other",						ECNA0170001CBSMsg.RETURN_OTHER}						// その他情報要否
		, {"return_cancelable_flg",				ECNA0170001CBSMsg.RETURN_CANCELABLE_FLG}			// 解約可否フラグ要否
	};
	
	/** API受信 項目名 */
	private static final String[][] CNIFE047_RES_INFO = new String[][]{
		  {ERR_CD,		ECNA0170001CBSMsg.ERR_CD}					// エラーコード
		, {"contracts",	ECNA0170001CBSMsg.ECNA0170001CBSMSG1LIST}	// コンテンツ情報リスト
	};
	/** API受信 項目名(コンテンツ情報リスト) */
	private static final String[][] CNIFE047_RES_LIST1_INFO = new String[][]{
		  {"sysid",					ECNA0170001CBSMsg1List.CONTRACTS_SYSID}			// SYSID
		, {"contract_no",			ECNA0170001CBSMsg1List.CONTRACTS_CONTRACT_NO}	// 契約番号
		, {"contract_start_date",	ECNA0170001CBSMsg1List.CONTRACT_START_DATE}		// 契約開始年月日時
		, {"contract_end_date",		ECNA0170001CBSMsg1List.CONTRACT_END_DATE}		// 契約終了年月日時
		, {"service_id",			ECNA0170001CBSMsg1List.CONTRACTS_SERVICE_ID}	// コンテンツサービスID
		, {"service_name",			ECNA0170001CBSMsg1List.SERVICE_NAME}			// コンテンツサービス名称
		, {"contents_id",			ECNA0170001CBSMsg1List.CONTRACTS_CONTENTS_ID}	// コンテンツID
		, {"contents_name",			ECNA0170001CBSMsg1List.CONTENTS_NAME}			// コンテンツ名称
		, {"contract",				ECNA0170001CBSMsg1List.ECNA0170001CBSMSG2LIST}	// コンテンツ契約情報リスト
		, {"charge",				ECNA0170001CBSMsg1List.ECNA0170001CBSMSG3LIST}	// 直近課金情報リスト
		, {"contract_adds",			ECNA0170001CBSMsg1List.ECNA0170001CBSMSG4LIST}	// 契約付加情報リスト
		, {"other",					ECNA0170001CBSMsg1List.ECNA0170001CBSMSG5LIST}	// その他情報リスト
	};
	
	/** API受信 項目名(コンテンツ契約情報リスト) */
	private static final String[][] CNIFE047_RES_LIST2_INFO = new String[][]{
		  {"cancel_contract_state",						ECNA0170001CBSMsg2List.CANCEL_CONTRACT_STATE}					// 解約状態フラグ
		, {"continue_count",							ECNA0170001CBSMsg2List.CONTINUE_COUNT}							// 継続回数
		, {"unit_price",								ECNA0170001CBSMsg2List.UNIT_PRICE}								// 単価
		, {"contract_amount",							ECNA0170001CBSMsg2List.CONTRACT_AMOUNT}							// 契約数量
		, {"settlement_way_no",							ECNA0170001CBSMsg2List.SETTLEMENT_WAY_NO}						// 決済方法番号
		, {"settlement_way_id",							ECNA0170001CBSMsg2List.CONTRACT_SETTLEMENT_WAY_ID}				// 決済方法ID
		, {"contents_division",							ECNA0170001CBSMsg2List.CONTRACT_CONTENTS_DIVISION}				// コンテンツ区分
		, {"contract_class",							ECNA0170001CBSMsg2List.CONTRACT_CONTRACT_CLASS}					// 契約種別
		, {"contract_ablecount",						ECNA0170001CBSMsg2List.CONTRACT_ABLECOUNT}						// 契約可能数
		, {"uncontinue_flg",							ECNA0170001CBSMsg2List.CONTRACT_UNCONTINUE_FLG}					// 非継続フラグ
		, {"tax_division",								ECNA0170001CBSMsg2List.TAX_DIVISION}							// 税区分
		, {"price_flg",									ECNA0170001CBSMsg2List.CONTRACT_PRICE_FLG}						// 料金フラグ
		, {"charge_form",								ECNA0170001CBSMsg2List.CHARGE_FORM}								// 課金形態
		, {"age_limit",									ECNA0170001CBSMsg2List.AGE_LIMIT}								// 年齢制限
		, {"contents_state",							ECNA0170001CBSMsg2List.CONTRACT_CONTENTS_STATE}					// コンテンツ状態
		, {"contents_start_date",						ECNA0170001CBSMsg2List.CONTENTS_START_DATE}						// コンテンツ開始日時
		, {"contents_end_date",							ECNA0170001CBSMsg2List.CONTENTS_END_DATE}						// コンテンツ終了日時
		, {"contents_available_period",					ECNA0170001CBSMsg2List.CONTENTS_AVAILABLE_PERIOD}				// コンテンツ有効時間
		, {"usable_user_class",							ECNA0170001CBSMsg2List.USABLE_USER_CLASS}						// 利用可能ユーザ種別
		, {"stockfrom",									ECNA0170001CBSMsg2List.STOCKFROM}								// 仕入先
		, {"contents_notes",							ECNA0170001CBSMsg2List.CONTENTS_NOTES}							// コンテンツ備考
		, {"update_date",								ECNA0170001CBSMsg2List.UPDATE_DATE}								// 更新日時
		, {"collaborate_division",						ECNA0170001CBSMsg2List.COLLABORATE_DIVISION}					// 連携先区分
		, {"master_exist_flg",							ECNA0170001CBSMsg2List.MASTER_EXIST_FLG}						// コンテンツ販売マスタ存在フラグ
		, {"free_months",								ECNA0170001CBSMsg2List.FREE_MONTHS}								// 無料期間
		, {"cancel_charge_flg",							ECNA0170001CBSMsg2List.CANCEL_CHARGE_FLG}						// 解約時有料フラグ
		, {"recontract_free_flg",						ECNA0170001CBSMsg2List.RECONTRACT_FREE_FLG}						// 再契約時Xカ月無料即座適用フラグ
		, {"operation_id",								ECNA0170001CBSMsg2List.OPERATION_ID}							// 処理番号
		, {"contract_start_accept_date",				ECNA0170001CBSMsg2List.CONTRACT_START_ACCEPT_DATE}				// 契約開始受付日時
		, {"contract_start_deemed_date",				ECNA0170001CBSMsg2List.CONTRACT_START_DEEMED_DATE}				// 契約開始扱い日時
		, {"contract_start_schedule_date",				ECNA0170001CBSMsg2List.CONTRACT_START_SCHEDULE_DATE}			// 契約開始予定日時
		, {"contract_start_process_date",				ECNA0170001CBSMsg2List.CONTRACT_START_PROCESS_DATE}				// 契約開始処理日時
		, {"contract_end_accept_date",					ECNA0170001CBSMsg2List.CONTRACT_END_ACCEPT_DATE}				// 契約終了受付日時
		, {"contract_end_deemed_date",					ECNA0170001CBSMsg2List.CONTRACT_END_DEEMED_DATE}				// 契約終了扱い日時
		, {"contract_end_schedule_date",				ECNA0170001CBSMsg2List.CONTRACT_END_SCHEDULE_DATE}				// 契約終了予定日時
		, {"contract_end_process_date",					ECNA0170001CBSMsg2List.CONTRACT_END_PROCESS_DATE}				// 契約終了処理日時
		, {"contract_flg",								ECNA0170001CBSMsg2List.CONTRACT_FLG}							// 契約フラグ
		, {"cancel_schedule",							ECNA0170001CBSMsg2List.CANCEL_SCHEDULE}							// 解約予約区分
		, {"contract_end_schedule_date_contract_no",	ECNA0170001CBSMsg2List.CONTRACT_END_SCHEDULE_DATE_CONTRACT_NO}	// 解約予約日時（契約番号）
		, {"contract_end_schedule_date_sysid",			ECNA0170001CBSMsg2List.CONTRACT_END_SCHEDULE_DATE_SYSID}		// 解約予約日時（SYSID）
	};

	/** API受信 項目名(直近課金情報リスト) */
	private static final String[][] CNIFE047_RES_LIST3_INFO = new String[][]{
		  {"target_date",					ECNA0170001CBSMsg3List.TARGET_DATE}					// 対象年月
		, {"settlement_way_no",				ECNA0170001CBSMsg3List.CHARGE_SETTLEMENT_WAY_NO}	// 決済方法番号
		, {"settlement_way_id",				ECNA0170001CBSMsg3List.CHARGE_SETTLEMENT_WAY_ID}	// 決済方法ID
		, {"campaign_id",					ECNA0170001CBSMsg3List.CAMPAIGN_ID}					// キャンペーンID
		, {"campaign_name",					ECNA0170001CBSMsg3List.CAMPAIGN_NAME}				// キャンペーン名称
		, {"campaign_target",				ECNA0170001CBSMsg3List.CAMPAIGN_TARGET}				// キャンペーン対象
		, {"campaign_form",					ECNA0170001CBSMsg3List.CAMPAIGN_FORM}				// キャンペーン形態
		, {"discount",						ECNA0170001CBSMsg3List.DISCOUNT}					// 割引
		, {"nochange",						ECNA0170001CBSMsg3List.NOCHANGE}					// 一律
		, {"campaign_apply_ablecount",		ECNA0170001CBSMsg3List.CAMPAIGN_APPLY_ABLECOUNT}	// キャンペーン適用可能数
		, {"campaign_apply_release_flg",	ECNA0170001CBSMsg3List.CAMPAIGN_APPLY_RELEASE_FLG}	// キャンペーン適用解除フラグ
		, {"contract_amount",				ECNA0170001CBSMsg3List.CHARGE_CONTRACT_AMOUNT}		// 契約数量
		, {"tax_rates",						ECNA0170001CBSMsg3List.TAX_RATES}					// 税率
		, {"charge_amount",					ECNA0170001CBSMsg3List.CHARGE_AMOUNT}				// 課金額
		, {"charge_flg",					ECNA0170001CBSMsg3List.CHARGE_FLG}					// 課金フラグ
		, {"campaign_text_screen",			ECNA0170001CBSMsg3List.CAMPAIGN_TEXT_SCREEN}		// キャンペーン文言（画面用）
		, {"campaign_cd_type",				ECNA0170001CBSMsg3List.CAMPAIGN_CD_TYPE}			// キャンペーンコード種別
		, {"campaign_cd",					ECNA0170001CBSMsg3List.CAMPAIGN_CD}					// キャンペーンコード
		, {"regular_unit_price",			ECNA0170001CBSMsg3List.REGULAR_UNIT_PRICE}			// 単価（税込）
		, {"regular_charge_amount",			ECNA0170001CBSMsg3List.REGULAR_CHARGE_AMOUNT}		// 料金（税込）
		, {"campaign_apply_flg",			ECNA0170001CBSMsg3List.CAMPAIGN_APPLY_FLG}			// キャンペーン適用有無フラグ
		, {"campaign_unit_price",			ECNA0170001CBSMsg3List.CAMPAIGN_UNIT_PRICE}			// キャンペーン適用単価（税込）
		, {"campaign_charge_amount",		ECNA0170001CBSMsg3List.CAMPAIGN_CHARGE_AMOUNT}		// キャンペーン適用料金（税込）
		, {"correction",					ECNA0170001CBSMsg3List.ECNA0170001CBSMSG6LIST}		// 直近課金訂正情報
	};

	/** API受信 項目名(契約付加情報リスト) */
	private static final String[][] CNIFE047_RES_LIST4_INFO = new String[][]{
		  {"item_name",	ECNA0170001CBSMsg4List.ITEM_NAME}	// 項目名
		, {"disp_name",	ECNA0170001CBSMsg4List.DISP_NAME}	// 表示名
		, {"value",		ECNA0170001CBSMsg4List.VALUE}		// 値
	};
	
	/** API受信 項目名(その他情報リスト) */
	private static final String[][] CNIFE047_RES_LIST5_INFO = new String[][]{
		  {"auto_entry_contents_division",	ECNA0170001CBSMsg5List.OTHER_AUTO_ENTRY_CONTENTS_DIVISION}	// 自動入会コンテンツ区分
		, {"line_option_service_division",	ECNA0170001CBSMsg5List.OTHER_LINE_OPTION_SERVICE_DIVISION}	// 回線オプションサービス区分
		, {"settlement_way_changeable_flg",	ECNA0170001CBSMsg5List.SETTLEMENT_WAY_CHANGEABLE_FLG}		// 決済方法変更可否フラグ
		, {"cancelable_flg",				ECNA0170001CBSMsg5List.CANCELABLE_FLG}						// 解約可否フラグ
		, {"representation_contents_id",	ECNA0170001CBSMsg5List.REPRESENTATION_CONTENTS_ID}			// 代表コンテンツID
	};
	
	/** API受信 項目名(直近課金訂正情報) */
	private static final String[][] CNIFE047_RES_LIST6_INFO = new String[][]{
		  {"corrected_division",	ECNA0170001CBSMsg6List.CORRECTED_DIVISION}	// 訂正区分
		, {"discount_amount",		ECNA0170001CBSMsg6List.DISCOUNT_AMOUNT}		// 値引額
		, {"corrected_notes",		ECNA0170001CBSMsg6List.CORRECTED_NOTES}		// 訂正記事
	};
	
	/**
	 * 契約一覧情報取得（CCMG）を行います。
	 * 
	 * @param inCBSMsg  契約一覧情報取得（CCMG）メッセージ
	 * @param inContext AgentDispatchContext
	 */
	public static void call_CNIFE047(CAANMsg inCBSMsg, AgentDispatchContext inContext)
	{
		// 開始ログ出力を実施。
		JSYejbLog.println(JSYejbLog.DEBUG, JECNA0170001TPMA.class, "JECNA0170001TPMA#call_CNIFE047 start");
		
		Hashtable<String, Object> response = new Hashtable<String, Object>();
		
		/*  接続先などの判定に使用
		 *  0： 本番・検証、1: 開発
		 */
		String mode = JCMAPLConstMgr.getString(CCMG_MODE_KEY);
		// アプリケーションプロパティ設定チェック
		if(isNullBlank(mode))
		{
			// ステータス設定（設定値取得エラー）
			inCBSMsg.set(ECNA0170001CBSMsg.STATUS, StatusCodes.RELATION_ERR);
			inCBSMsg.set(ECNA0170001CBSMsg.SYSID_ERR, EA_ERR_FLAG);
			inCBSMsg.set(ECNA0170001CBSMsg.ECNA0170001CBSMSG1LIST, new CAANMsg[0]);
			return;
		}
		
		// eo顧客 ⇒ CCMGへの送信先URLを設定
		String strUrl = "";
		
		if (MODE_0.equals(mode))
		{
			// 本番・検証：propertiesに設定された値を使用
			strUrl = JCMAPLConstMgr.getString(CCMG_API_URL);
		}
		else
		{
			// 開発：設定しない
			strUrl = DUMMY_URL;
		}
		
		// API名称
		String apiid = APIID;
		// 接続メソッド
		String method = JCMAPLConstMgr.getString(CCMG_METHOD);
		// タイムアウト時間
		String strConnectTimeout = JCMAPLConstMgr.getString(CCMG_API_TIMEOUT);
		// リトライ回数
		String strRetryCount = JCMAPLConstMgr.getString(CCMG_API_RETRY_CNT);
		// リトライインターバル
		String strRetryInterval = JCMAPLConstMgr.getString(CCMG_API_RETRY_INTERVAL);
		
		// アプリケーションプロパティ設定チェック
		if(isNullBlank(strUrl)
				|| isNullBlank(strConnectTimeout)
				|| isNullBlank(strRetryCount)
				|| isNullBlank(strRetryInterval))
		{
			// ステータス設定（設定値取得エラー）
			inCBSMsg.set(ECNA0170001CBSMsg.STATUS, StatusCodes.RELATION_ERR);
			inCBSMsg.set(ECNA0170001CBSMsg.SERVICE_ID_ERR, EA_ERR_FLAG);
			inCBSMsg.set(ECNA0170001CBSMsg.ECNA0170001CBSMSG1LIST, new CAANMsg[0]);
			return;
		}
		JSYejbLog.println(JSYejbLog.EXECUTION, JECNA0170001TPMA.class , "JECNA0170001TPMA#URL=" + strUrl + apiid);
		
		Hashtable<String, Object> jsonResult = new Hashtable<String, Object>();
		try
		{
			/*
			 * 送信パラメータ作成
			 */
			CAANMsg paramMap = requestParamMake(inCBSMsg, apiid, mode, strUrl, method, strConnectTimeout, strRetryCount, strRetryInterval);
			JSYejbLog.println(JSYejbLog.EXECUTION, JECNA0170001TPMA.class , "JECNA0170001TPMA#request postParameter=" + paramMap);
			
			// コマンド発行部品のインスタンスを取得
			response = new JCNCtrlCcmgConnectInfoImpl().ctrlCcmgConnect(paramMap);
			
			// 接続結果
			Map<String, Object> connectResult = (Map<String, Object>) response.get(JCNCtrlCcmgConnectInfoImpl.CONNECTRESULT);
			// レスポンス情報
			Map<String, Object> resInfo = (Map<String, Object>) response.get(JCNCtrlCcmgConnectInfoImpl.RESINFO);
			JsonNode resBodyNode = (JsonNode)resInfo.get(JCNCtrlCcmgConnectInfoImpl.RESINFO_BODY);
			jsonResult = read(resBodyNode);
			
			// body情報マッピング
			// 連携実行結果判定
			if(isNormal(response))
			{
				// ステータス設定（0:正常終了）
				inCBSMsg.set(ECNA0170001CBSMsg.STATUS, StatusCodes.NORMAL_END);
			}
			else
			{
				// ステータス設定（応答コードエラー）
				inCBSMsg.set(ECNA0170001CBSMsg.STATUS, StatusCodes.RELATION_ERR);
				inCBSMsg.set(ECNA0170001CBSMsg.SYSID_ERR, EB_ERR_FLAG);
			}
			
		}
		catch (Exception e)
		{
			printErrorLog(e);
			// ステータス設定（実行時エラー）
			inCBSMsg.set(ECNA0170001CBSMsg.STATUS, StatusCodes.RELATION_ERR);
			inCBSMsg.set(ECNA0170001CBSMsg.SYSID_ERR, EC_ERR_FLAG);
			inCBSMsg.set(ECNA0170001CBSMsg.ECNA0170001CBSMSG1LIST, new CAANMsg[0]);
			return;
		}
		
		// JSONレスポンス
		editOutMsg(inCBSMsg, jsonResult);
		
		// 終了ログ出力を実施。
		JSYejbLog.println(JSYejbLog.DEBUG, JECNA0170001TPMA.class, "JECNA0170001TPMA#call_CNIFE047 end");
	}
	
	/**
	 * エラーログ出力
	 * @param e 発生した例外
	 * @param params 指示書パラメータ(1〜50)
	 * @param errTitle エラータイトル
	 * @param sjishoNo 指示書番号
	 * @param sjishoNaiyoSeq 指示書内容枝番
	 */
	static private void printErrorLog(Exception e)
	{
		StringBuffer sb = new StringBuffer();
		sb.append(e.getMessage()+ "\n");
		sb.append(e.getClass().getName()+ "\n");
		StackTraceElement[] steAll = e.getStackTrace();
		for (StackTraceElement ste : steAll) {
			sb.append("	at " + ste.getClassName() + "." + ste.getMethodName() + "(" + ste.getFileName() + ":" + ste.getLineNumber()+")"+ "\n");
		}
		JSYejbLog.println(JSYejbLog.ERROR, JECNA0170001TPMA.class, sb.toString());
	}
	
	/**
	 * 連携実行結果判定
	 */
	private static boolean isNormal(Map<String, Object> response) 
	{
		if(response==null)
		{
			return false;
		}
		
		Map<String, Object> connectResult = (HashMap<String, Object>)response.get(JCNCtrlCcmgConnectInfoImpl.CONNECTRESULT);
		// HTTPステータスを取得
		String httpStat = (String) connectResult.get(JCNCtrlCcmgConnectInfoImpl.CONNECTRESULT_HTTPSTATUS);
		
		// HTTPステータスをログ出力
		JSYejbLog.println(JSYejbLog.EXECUTION, JECNA0170001TPMA.class, "JECNA0170001TPMA#http_status=" + httpStat );
		
		// HTTPステータス確認
		if( !Integer.toString(HttpURLConnection.HTTP_OK).equals(httpStat) )
		{
			return false;
		}
		
		Map<String, Object> resInfo = (Map<String, Object>)response.get(JCNCtrlCcmgConnectInfoImpl.RESINFO);
		JsonNode body = (JsonNode)resInfo.get(JCNCtrlCcmgConnectInfoImpl.RESINFO_BODY);
		
		String errCd = body.get(ERR_CD).asText();
		
		// エラーコードがbody部にあるので確認
		// 応答コード（00000:正常）の確認
		if (!CODE_OK.equals(errCd))
		{
			return false;
		}
		
		// ここまで来たら正常終了
		return true;
	}

	/**
	 * 契約一覧情報取得（CCMG）に対して送信するリクエストパラメータを作成する。
	 * @param inCBSMsg CAANメッセージ
	 * @param apiId APIID
	 * @param mode 処理区分
	 * @param strUrl URL
	 * @param method メソッド
	 * @param strConnectTimeout コネクションタイムアウト
	 * @param strRetryCount リトライ回数
	 * @param strRetryInterval リトライインターバル
	 * @return リクエストパラメータを返却する。
	 */
	private static CAANMsg requestParamMake(CAANMsg inCBSMsg, String apiId, String mode, String strUrl, String method,
						String strConnectTimeout, String strRetryCount, String strRetryInterval)
	{
		// リクエストパラメータ作成
		CAANMsg paramMap = new CAANMsg();
		
		// リクエストパラメータヘッダー部作成
		Map<String, Object> paramConnectinfo = new HashMap<String, Object>();
		
		paramConnectinfo.put(JCNCtrlCcmgConnectInfoImpl.CONNECTINFO_CONNECTMODE, mode);
		paramConnectinfo.put(JCNCtrlCcmgConnectInfoImpl.CONNECTINFO_URL, strUrl);
		paramConnectinfo.put(JCNCtrlCcmgConnectInfoImpl.CONNECTINFO_APIID, apiId);
		paramConnectinfo.put(JCNCtrlCcmgConnectInfoImpl.CONNECTINFO_CONNECTMETHOD, method);
		paramConnectinfo.put(JCNCtrlCcmgConnectInfoImpl.CONNECTINFO_TIMEOUT, strConnectTimeout);
		paramConnectinfo.put(JCNCtrlCcmgConnectInfoImpl.CONNECTINFO_RETRYCOUNT, strRetryCount);
		paramConnectinfo.put(JCNCtrlCcmgConnectInfoImpl.CONNECTINFO_RETRYINTERVAL, strRetryInterval);
		
		// リクエストパラメータボディ部作成
		Map<String, Object> paramReqInfo = new HashMap<String, Object>();
		Map<String, Object> paramBody = new HashMap<String, Object>();
		
		for(String[] item : CNIFE047_REQ_INFO)
		{
			String itemName = item[0];
			String itemValue = inCBSMsg.getString(item[1]);
			
			if( !isNullBlank(itemValue) )
			{
				paramBody.put(itemName, itemValue);
			}
		}
		paramReqInfo.put(JCNCtrlCcmgConnectInfoImpl.REQINFO_BODY, paramBody);
		
		
		// ------------------------------------
		// リストをデータマップに設定する
		// ------------------------------------
		paramMap.setPrivate(JCNCtrlCcmgConnectInfoImpl.CONNECTINFO, paramConnectinfo);
		paramMap.setPrivate(JCNCtrlCcmgConnectInfoImpl.REQINFO, paramReqInfo);
		
		return paramMap;
	}
	
	/**
	 * レスポンス電文を設定します。
	 */
	private static void editOutMsg(CAANMsg inCBSMsg, Hashtable<String, Object> response)
	{
		if (response != null)
		{
			for( String[] item : CNIFE047_RES_INFO )
			{
				String itemName = item[1];
				Object itemValue = response.get(item[0]);
				
				if(itemValue == null)
				{
					inCBSMsg.setNull(itemName);
				}
				else if(itemName.equals(ECNA0170001CBSMsg.ECNA0170001CBSMSG1LIST) )
				{
					List<CAANMsg> msg1List = new ArrayList<CAANMsg>();
					
					List<Map<String, Object>> list1 = (List<Map<String, Object>>) itemValue;
					for( Map<String, Object> record1 : list1)
					{
						CAANMsg msg1 = new CAANMsg(ECNA0170001CBSMsg1List.class.getName());
						
						for( String[] item1 : CNIFE047_RES_LIST1_INFO )
						{
							String itemName1 = item1[1];
							Object itemValue1 = record1.get(item1[0]);
							
							if(itemValue1 == null)
							{
								msg1.setNull(itemName);
							}
							else if(itemName1.equals(ECNA0170001CBSMsg1List.ECNA0170001CBSMSG2LIST) )
							{
								List<CAANMsg> msg2List = new ArrayList<CAANMsg>();
								
								Map<String, Object> record2 = (Map<String, Object>) itemValue1;
								
								CAANMsg msg2 = new CAANMsg(ECNA0170001CBSMsg2List.class.getName());
								
								for( String[] item2 : CNIFE047_RES_LIST2_INFO )
								{
									String itemName2 = item2[1];
									Object itemValue2 = record2.get(item2[0]);
									if(itemValue2 == null)
									{
										msg2.setNull(itemName2);
									}
									else if("usable_user_class".equals(itemName2))
									{
										// usable_user_class:利用可能ユーザ種別はリストで来るためカンマ区切りにする。
										List<String> contentsAvailablePeriodList = (List<String>)itemValue2;
										String str = "";
										for(String contentsAvailablePeriod : contentsAvailablePeriodList)
										{
											if(!"".equals(str))
											{
												str += ",";
											}
											str += contentsAvailablePeriod;
										}
										msg2.set(itemName2, str);
									}
									else{
										msg2.set(itemName2, (String) itemValue2);
									}
								}
								msg2List.add(msg2);
								
								msg1.set(itemName1, msg2List.toArray(new CAANMsg[msg2List.size()]));
							}
							else if(itemName1.equals(ECNA0170001CBSMsg1List.ECNA0170001CBSMSG3LIST) )
							{
								List<CAANMsg> msg3List = new ArrayList<CAANMsg>();
								
								Map<String, Object> record3 = (Map<String, Object>) itemValue1;
								
								CAANMsg msg3 = new CAANMsg(ECNA0170001CBSMsg3List.class.getName());
								
								for( String[] item3 : CNIFE047_RES_LIST3_INFO )
								{
									String itemName3 = item3[1];
									Object itemValue3 = record3.get(item3[0]);
									
									if(itemValue3 == null)
									{
										msg3.setNull(itemName);
									}
									else if(itemName3.equals(ECNA0170001CBSMsg3List.ECNA0170001CBSMSG6LIST) )
									{
										List<CAANMsg> msg6List = new ArrayList<CAANMsg>();
										
										Map<String, Object> record6 = (Map<String, Object>) itemValue3;
										
										CAANMsg msg6 = new CAANMsg(ECNA0170001CBSMsg6List.class.getName());
										
										for( String[] item6 : CNIFE047_RES_LIST6_INFO )
										{
											String itemName6 = item6[1];
											Object itemValue6 = record6.get(item6[0]);
											
											msg6.set(itemName6, (String) itemValue6);
										}
										msg6List.add(msg6);
										
										msg3.set(itemName3, msg6List.toArray(new CAANMsg[msg6List.size()]));
									}
									else
									{
										msg3.set(itemName3, (String) itemValue3);
									}
								}
								msg3List.add(msg3);
								
								msg1.set(itemName1, msg3List.toArray(new CAANMsg[msg3List.size()]));
							}
							else if( itemValue1 != null && itemName1.equals(ECNA0170001CBSMsg1List.ECNA0170001CBSMSG4LIST) )
							{
								List<CAANMsg> msg4List = new ArrayList<CAANMsg>();
								
								List<Map<String, Object>> list4 = (List<Map<String, Object>>) itemValue1;
								for( Map<String, Object> record4 : list4)
								{
									CAANMsg msg4 = new CAANMsg(ECNA0170001CBSMsg4List.class.getName());
									
									for( String[] item4 : CNIFE047_RES_LIST4_INFO )
									{
										String itemName4 = item4[1];
										Object itemValue4 = record4.get(item4[0]);
										msg4.set(itemName4, (String) itemValue4);
									}
									msg4List.add(msg4);
								}
								
								msg1.set(itemName1, msg4List.toArray(new CAANMsg[msg4List.size()]));
							}
							else if( itemValue1 != null && itemName1.equals(ECNA0170001CBSMsg1List.ECNA0170001CBSMSG5LIST) )
							{
								List<CAANMsg> msg5List = new ArrayList<CAANMsg>();
								
								Map<String, Object> record5 = (Map<String, Object>) itemValue1;
								
								CAANMsg msg5 = new CAANMsg(ECNA0170001CBSMsg5List.class.getName());
								
								for( String[] item5 : CNIFE047_RES_LIST5_INFO )
								{
									String itemName5 = item5[1];
									Object itemValue5 = record5.get(item5[0]);
									msg5.set(itemName5, (String) itemValue5);
								}
								msg5List.add(msg5);
								
								msg1.set(itemName1, msg5List.toArray(new CAANMsg[msg5List.size()]));
							}
							else
							{
								msg1.set(itemName1, (String) itemValue1);
							}
						}
						msg1List.add(msg1);
					}
					
					inCBSMsg.set(itemName, msg1List.toArray(new CAANMsg[msg1List.size()]));
				}
				else
				{
					inCBSMsg.set(itemName, (String) itemValue);
				}
			}
		}
	}
	
	/**
	 * 電文読み込み処理
	 * @param jsonResponse
	 * @return json電文解析結果
	 */
	private static Hashtable<String, Object> read(JsonNode jsonResponse) 
	{
		if (jsonResponse == null)
		{
			return null;
		}
		Hashtable<String, Object> result = analyzeJson(jsonResponse);

		return result;
	}
	
	/**
	 * コマンド送信戻り電文解析処理
	 * @param elem コマンド解析電文rootjson要素
	 * @param rootflag ルートフラグ
	 * @return json解析結果
	 */
	private static Hashtable<String, Object> analyzeJson(JsonNode elem)
	{
		
		Hashtable<String, Object> resultMap = new Hashtable<String, Object>();
		
		Iterator<Map.Entry<String, JsonNode>> fields = elem.fields();
		while(fields.hasNext())
		{
			Map.Entry<String, JsonNode> field = fields.next();
			
			String fieldName = field.getKey();
			JsonNode fieldValue = field.getValue();
			
			
			if(fieldValue.isNull())
			{
				//何もしない
			}
			// Arrayの場合
			else if(fieldValue.isArray())
			{
				ArrayList<Object> Bodynodelist = new ArrayList<Object>();
				Iterator<JsonNode> itr = fieldValue.elements();
				while(itr.hasNext())
				{
					JsonNode node = itr.next();
					if(node.isValueNode())
					{
						Bodynodelist.add(node.textValue());
					}
					else
					{
						Hashtable<String, Object> resultinfo = analyzeJson(node);
						if (resultinfo != null && !resultinfo.isEmpty())
						{
							Bodynodelist.add(resultinfo);
						}
					}
				}
				
				resultMap.put( fieldName, Bodynodelist);
			}
			// 子要素を持つ場合は再帰処理
			else if( fieldValue.isObject() )
			{
				resultMap.put(fieldName, analyzeJson(fieldValue) );
			}
			// 以外は値を設定
			else
			{
				if(fieldValue.isInt())
				{
					resultMap.put(fieldName, fieldValue.bigIntegerValue().toString());
				}
				else if(fieldValue.isTextual())
				{
					resultMap.put(fieldName, fieldValue.textValue());
				}
				else
				{
					//何もしない
				}
			}
		}
		
		return resultMap;
	}
	
	/**
	 * null又は空文字の場合、trueを返却する
	 * 
	 * @param str 検査対象文字列
	 * @return true:null、又は空文字／false:左記以外
	 */
	public static boolean isNullBlank(String str)
	{
		if (str == null || "".equals(str))
		{
			return true;
		}
		return false;
	}
}
