/*********************************************************************
 * All Rights reserved,Copyright (c) K-Opticom
 **********************************************************************
 *＜プログラム内容＞
 *   システム名      ：eo顧客基幹システム
 *   モジュール名    ：JCNCtrlCcmgConnectInfoImpl
 *   ソースファイル名：JCNCtrlCcmgConnectInfoImpl.java
 *   作成者          ：富士通
 *   日付            ：2023年10月05日
 *＜機能概要＞
 *   ＣＣＭＧ連携接続処理部品です。
 *＜修正履歴＞
 *   バージョン  修正日       修正者      修正内容
 *   v65.00.00	2023/10/04	 FJ) 吉田	 【ANK-4346-00-00】【eo定期】CCMG再構築対応
 *   v65.00.01	2023/02/17	 FJ) 渋谷	 【ST-2024-0000004】【eo定期】CCMG再構築対応
 *   v65.00.02	2024/03/12	 FJ) 吉田あ	 【ANK-4346-16-00】【eo定期】CCMG再構築対応
 *   v65.00.03	2024/03/15	 FJ) 吉田あ	 【ANK-4346-16-01】【eo定期】CCMG再構築対応
 *   v65.00.04	2024/03/18	 FJ) 吉田あ	 【ANK-4346-16-02】【eo定期】CCMG再構築対応
 *   v65.00.05	2024/03/21	 FJ) 吉田	 【ANK-4346-00-00】【eo定期】CCMG再構築対応
 *   v65.00.06	2024/03/18	 FJ) 吉田あ	 #84485 mineoの照査処理でNullPointerExceptionが出力される
 *   v71.00.00	2024/06/20	 FJ）田中	 【ANK-4612-00-00】【随時-24-0204】コネクションタイムアウト値の変更対応
 *   v73.00.00	2024/12/17	 FJ）渋谷	 【ANK-4570-00-00】コンテンツ新規同時申込み時契約仕様見直し対応
 *   v74.00.00	2025/02/05	 FJ）渋谷	 【#86481】キャンペーンコードが設定されない
 **********************************************************************/
package eo.ejb.common;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;

import org.apache.commons.httpclient.HostConfiguration;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.PutMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.fasterxml.jackson.databind.ObjectMapper;

import com.fujitsu.futurity.model.base.CAANMsg;
import com.fujitsu.futurity.model.common.JCMAPLConstMgr;
import com.fujitsu.futurity.model.ejb.common.JSYejbLog;

import com.fasterxml.jackson.databind.JsonNode;

import eo.common.util.JCHStringUtil;
import eo.common.util.JCNStringUtil;


public class JCNCtrlCcmgConnectInfoImpl{
	
	/** 接続情報 */
	public static final String CONNECTINFO = "connectInfo";
	/** 接続情報 接続モード */
	public static final String CONNECTINFO_CONNECTMODE = "connectMode";
	/** 接続情報 接続URL */
	public static final String CONNECTINFO_URL = "URL";
	/** 接続情報 接続APIID */
	public static final String CONNECTINFO_APIID = "APIID";
	/** 接続情報 接続メソッド */
	public static final String CONNECTINFO_CONNECTMETHOD = "connectMethod";
	/** 接続情報 タイムアウト時間 */
	public static final String CONNECTINFO_TIMEOUT = "timeout";
	/** 接続情報 リトライカウント */
	public static final String CONNECTINFO_RETRYCOUNT = "retryCount";
	/** 接続情報 リトライインターバル */
	public static final String CONNECTINFO_RETRYINTERVAL = "retryInterval";
	
	/** リクエスト情報 */
	public static final String REQINFO = "reqInfo";
	/** リクエスト情報 body */
	public static final String REQINFO_BODY = "body";
	
	/** 接続結果 */
	public static final String CONNECTRESULT = "connectResult";
	/** 接続結果 httpstats */
	public static final String CONNECTRESULT_HTTPSTATUS = "httpStatus";
	
	/** レスポンス情報 */
	public static final String RESINFO = "resInfo";
	/** レスポンス情報 body */
	public static final String RESINFO_BODY = "body";
	
	/** ＣＣＭＧ接続モード（本番） */
	private static final String CCMG_SYSTEM = "0";
	
	/** ＣＣＭＧ接続モード（スタブ） */
	private static final String CCMG_STUB = "1";
	
	/** APLConst：ＣＣＭＧアクセストークン */
	private static final String CCMG_ACCESSTOKEN = "CCMG_ACCESSTOKEN";
	
	/** APLConst：ＣＣＭＧテストディレクトリ */
	private static final String CCMG_CONNECTION_MODE_TEST_DIR = "CCMG_CONNECTION_MODE_TEST_DIR";
	
	// ANK-4612-00-00 ADD START
	/** APLConst：コネクションタイムアウト時間 */
	private static final String CCMG_COMMON_CONNECT_TIMEOUT = "CCMG_COMMON_CONNECT_TIMEOUT";
	// ANK-4612-00-00 ADD END
	
	/** スタブ利用時のスタブファイル名を指定 */
	private static final Map<String, String> STUB_FILE_MAP = new HashMap<String, String>();

	/** スタブ利用時のHTTPステータスを指定 */
	private static final Map<String, String> STUB_HTTPSTAT_MAP = new HashMap<String, String>();
	
	/** スタブ利用時でのファイル取得時の実行結果を指定 */
	private static final Map<String, String> NOT_EXITS_FILE_RESULT_MAP = new HashMap<String, String>();

	/** スタブ利用時でのファイル取得時のHTTPステータスを指定 */
	private static final Map<String, String> NOT_EXITS_FILE_HTTPSTAT_MAP = new HashMap<String, String>();

	/**
	 * HTTPヘッダ Conten-TYPE（値）
	 */
	protected static final String CONTENT_TYPE_VALUE = "application/json";
	
	/**
	 * ＡＰＩＩＤとサービスの対応表をセットする
	 */
	static
	{
		/**
		 * APIIDとスタブファイル名の対応表をセットする
		 */
		STUB_FILE_MAP.put("CNIFE047-1", "CCMG_CNIFE047_SYSID_STUB.json"); 
		STUB_FILE_MAP.put("CNIFE047-2", "CCMG_CNIFE047_CONTKEI_STUB.json"); 
		STUB_FILE_MAP.put("CNIFE047-3", "CCMG_CNIFE047_SVCCD_STUB.json"); 
		STUB_FILE_MAP.put("CNIFE048", "CCMG_CNIFE048_STUB.json"); 
		STUB_FILE_MAP.put("CNIFE049", "CCMG_CNIFE049_STUB.json"); 
		STUB_FILE_MAP.put("CNIFE050", "CCMG_CNIFE050_STUB.json"); 
		STUB_FILE_MAP.put("CNIFE051", "CCMG_CNIFE051_STUB.json"); 
		STUB_FILE_MAP.put("CNIFE052", "CCMG_CNIFE052_STUB.json"); 
		STUB_FILE_MAP.put("CNIFE053", "CCMG_CNIFE053_STUB.json"); 
		STUB_FILE_MAP.put("CNIFE054", "CCMG_CNIFE054_STUB.json"); 
		STUB_FILE_MAP.put("CNIFE055", "CCMG_CNIFE055_STUB.json"); 
		STUB_FILE_MAP.put("CNIFE056", "CCMG_CNIFE056_STUB.json"); 
		STUB_FILE_MAP.put("CNIFE057", "CCMG_CNIFE057_STUB.json"); 
		STUB_FILE_MAP.put("CNIFE058", "CCMG_CNIFE058_STUB.json"); 
		STUB_FILE_MAP.put("CNIFE059", "CCMG_CNIFE059_STUB.json"); 
		STUB_FILE_MAP.put("CKIFE071", "CCMG_CKIFE071_STUB.json"); 

		/**
		 * APIIDとスタブHTTPステータスの対応表をセットする
		 */
		STUB_HTTPSTAT_MAP.put("CNIFE047", "CCMG_CNIFE047_HTTP_STAT_CD"); 
		STUB_HTTPSTAT_MAP.put("CNIFE048", "CCMG_CNIFE048_HTTP_STAT_CD"); 
		STUB_HTTPSTAT_MAP.put("CNIFE049", "CCMG_CNIFE049_HTTP_STAT_CD"); 
		STUB_HTTPSTAT_MAP.put("CNIFE050", "CCMG_CNIFE050_HTTP_STAT_CD"); 
		STUB_HTTPSTAT_MAP.put("CNIFE051", "CCMG_CNIFE051_HTTP_STAT_CD"); 
		STUB_HTTPSTAT_MAP.put("CNIFE052", "CCMG_CNIFE052_HTTP_STAT_CD"); 
		STUB_HTTPSTAT_MAP.put("CNIFE053", "CCMG_CNIFE053_HTTP_STAT_CD"); 
		STUB_HTTPSTAT_MAP.put("CNIFE054", "CCMG_CNIFE054_HTTP_STAT_CD"); 
		STUB_HTTPSTAT_MAP.put("CNIFE055", "CCMG_CNIFE055_HTTP_STAT_CD"); 
		STUB_HTTPSTAT_MAP.put("CNIFE056", "CCMG_CNIFE056_HTTP_STAT_CD"); 
		STUB_HTTPSTAT_MAP.put("CNIFE057", "CCMG_CNIFE057_HTTP_STAT_CD"); 
		STUB_HTTPSTAT_MAP.put("CNIFE058", "CCMG_CNIFE058_HTTP_STAT_CD"); 
		STUB_HTTPSTAT_MAP.put("CNIFE059", "CCMG_CNIFE059_HTTP_STAT_CD"); 
		STUB_HTTPSTAT_MAP.put("CKIFE071", "CCMG_CKIFE071_HTTP_STAT_CD"); 
		
		/**
		 * APIIDとスタブファイルが存在しない場合の実行結果の対比表をセットする。
		 */
		NOT_EXITS_FILE_RESULT_MAP.put("CNIFE047", "{\"err_cd\":\"00000\",\"contracts\":[]}"); 
		NOT_EXITS_FILE_RESULT_MAP.put("CNIFE048", "{\"err_cd\":\"00000\",\"charges\":[]}"); 
		NOT_EXITS_FILE_RESULT_MAP.put("CNIFE049", "?"); 
		NOT_EXITS_FILE_RESULT_MAP.put("CNIFE050", "?"); 
		NOT_EXITS_FILE_RESULT_MAP.put("CNIFE051", "?"); 
		NOT_EXITS_FILE_RESULT_MAP.put("CNIFE052", "?"); 
		NOT_EXITS_FILE_RESULT_MAP.put("CNIFE053", "{\"err_cd\":\"00000\",\"contracts\":[\"sysid\":\"9999999999\"]}"); 
		NOT_EXITS_FILE_RESULT_MAP.put("CNIFE054", ""); 
		NOT_EXITS_FILE_RESULT_MAP.put("CNIFE055", "{\"err_cd\":\"00000\",\"contracts\":[\"sysid\":\"9999999999\"]}"); 
		NOT_EXITS_FILE_RESULT_MAP.put("CNIFE056", "{\"err_cd\":\"00000\",\"contracts\":[]}"); 
		NOT_EXITS_FILE_RESULT_MAP.put("CNIFE057", "{\"err_cd\":\"00000\",\"contracts\":[]}"); 
		NOT_EXITS_FILE_RESULT_MAP.put("CNIFE058", ""); 
		NOT_EXITS_FILE_RESULT_MAP.put("CNIFE059", "{\"err_cd\":\"00000\",\"operation_id\":\"9107ffb3-2457-4dc9-8f20-a12XXXXXXXXX\"}"); 
		NOT_EXITS_FILE_RESULT_MAP.put("CKIFE071", ""); 
		
		/**
		 * APIIDとスタブファイルが存在しない場合のHTTPステータスの対比表をセットする。 
		 */
		NOT_EXITS_FILE_HTTPSTAT_MAP.put("CNIFE047", "200"); 
		NOT_EXITS_FILE_HTTPSTAT_MAP.put("CNIFE048", "200"); 
		NOT_EXITS_FILE_HTTPSTAT_MAP.put("CNIFE049", "?"); 
		NOT_EXITS_FILE_HTTPSTAT_MAP.put("CNIFE050", "?"); 
		NOT_EXITS_FILE_HTTPSTAT_MAP.put("CNIFE051", "?"); 
		NOT_EXITS_FILE_HTTPSTAT_MAP.put("CNIFE052", "?"); 
		NOT_EXITS_FILE_HTTPSTAT_MAP.put("CNIFE053", "200"); 
		NOT_EXITS_FILE_HTTPSTAT_MAP.put("CNIFE054", "204"); 
		NOT_EXITS_FILE_HTTPSTAT_MAP.put("CNIFE055", "200"); 
		NOT_EXITS_FILE_HTTPSTAT_MAP.put("CNIFE056", "200"); 
		NOT_EXITS_FILE_HTTPSTAT_MAP.put("CNIFE057", "201"); 
		NOT_EXITS_FILE_HTTPSTAT_MAP.put("CNIFE058", "204"); 
		NOT_EXITS_FILE_HTTPSTAT_MAP.put("CNIFE059", "200"); 
		NOT_EXITS_FILE_HTTPSTAT_MAP.put("CKIFE071", "204"); 
	}
	
	/** CCMG文字コード */
	private static final String CCMG_ENCODING = "UTF-8";
	
	/**
	 * 連携されたパラメータより、本番接続またはスタブ接続を判定し処理結果を返却する。
	 * @param inCBSMsg CAANメッセージ
	 * @throws Exception 
	 */
	public Hashtable<String, Object> ctrlCcmgConnect(CAANMsg inCBSMsg) throws Exception
	{
		// 開始ログ出力を実施。
		JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), "JCNCtrlCcmgConnectInfoImpl#ctrlCcmgConnect start");
		
		// CAANメッセージより「接続情報」「リクエスト情報」を取得
		Object connect = inCBSMsg.getObject(CONNECTINFO);
		Object req = inCBSMsg.getObject(REQINFO);
		
		HashMap<String,Object> connectInfo = (HashMap<String, Object>) connect;
		HashMap<String,Object> reqInfo = (HashMap<String, Object>) req;
		
		// 接続情報を取得する
		// 接続モード
		String connectMode = (String) connectInfo.get(CONNECTINFO_CONNECTMODE);
		// 接続URL
		String url = (String) connectInfo.get(CONNECTINFO_URL);
		// 接続APIID
		String apiId = (String) connectInfo.get(CONNECTINFO_APIID);
		// 接続メソッド
		String connectMethod = (String) connectInfo.get(CONNECTINFO_CONNECTMETHOD);
		// タイムアウト時間
		String timeout = (String) connectInfo.get(CONNECTINFO_TIMEOUT);
		// リトライカウント
		String retryCount = (String) connectInfo.get(CONNECTINFO_RETRYCOUNT);
		// リトライインターバル
		String retryInterval = (String) connectInfo.get(CONNECTINFO_RETRYINTERVAL);
		
		// ANK-4612-00-00 ADD START
		// コネクションタイムアウト時間
		String connectionTimeout = JCCModelCommon.getApplicationConst(CCMG_COMMON_CONNECT_TIMEOUT);
		// ANK-4612-00-00 ADD END
		
		// リクエストを取得する
		Map<String, Object> body = (Map<String, Object>) reqInfo.get(REQINFO_BODY);
		
		// 接続情報をログに出力
		JSYejbLog.println(JSYejbLog.EXECUTION, JCNCtrlCcmgConnectInfoImpl.class , "JCNCtrlCcmgConnectInfoImpl" + apiId + "#接続情報 : " + connectInfo);
		// リクエスト情報をログに出力
		JSYejbLog.println(JSYejbLog.EXECUTION, JCNCtrlCcmgConnectInfoImpl.class , "JCNCtrlCcmgConnectInfoImpl" + apiId + "#リクエスト情報 : " + reqInfo);
		
		// 結果格納用のMAPを用意
		Hashtable<String, Object> resultMap = new Hashtable<String, Object>();
		
		// 接続モード判定
		if (CCMG_SYSTEM.equals(connectMode)) {
			// ANK-4612-00-00 MOD START
//			resultMap = apiConnect(url, apiId, connectMethod, timeout, retryCount, retryInterval, body);
			resultMap = apiConnect(url, apiId, connectMethod, timeout, retryCount, retryInterval, body, connectionTimeout);
			// ANK-4612-00-00 MOD END
		} else if(CCMG_STUB.equals(connectMode)) {
			resultMap = stubConnect(apiId, body);
		}
		
		return resultMap;
	}
	
	/**
	 * モードが本番接続の場合に、CCMG向けにAPIを実行する
	 * 
	 * @param url   接続URL
	 * @param apiid 接続APIID
	 * @param connectMethod 接続メソッド
	 * @param timeout タイムアウト時間
	 * @param retryInterval リトライインターバル
	 * @param body リクエスト情報
	 * @param connectionTimeout コネクションタイムアウト時間
	 * @return 実行結果
	 */
	// ANK-4612-00-00 MOD START
//	private static Hashtable<String, Object> apiConnect(String url, String apiid, String connectMethod, String timeout, String retryCount, String retryInterval, Map<String, Object> body) throws Exception
	private static Hashtable<String, Object> apiConnect(String url, String apiid, String connectMethod, String timeout, String retryCount, String retryInterval, Map<String, Object> body, String connectionTimeout) throws Exception
	// ANK-4612-00-00 MOD END
	{
		// アクセストークンを取得
		String acecssToken = JCMAPLConstMgr.getString(CCMG_ACCESSTOKEN);
		
		// #86481 DEL START
//		// 実行するAPI・接続URL・リクエスト情報をログ出力
//		JSYejbLog.println(JSYejbLog.EXECUTION, JCNCtrlCcmgConnectInfoImpl.class , ("JCNCtrlCcmgConnectInfoImpl 実行URL=" + url + " 実行APIID= " + apiid + "リクエスト情報=" +body 
//				).replaceAll("\\s+", " "));
		// #86481 DEL END
		
		// CCMGへ接続を行う
		// ANK-4612-00-00 MOD START
//		String result[] = ccmgConnect(url, apiid, connectMethod, timeout, retryCount, retryInterval, body,acecssToken);
		String result[] = ccmgConnect(url, apiid, connectMethod, timeout, retryCount, retryInterval, body, acecssToken, connectionTimeout);
		// ANK-4612-00-00 MOD END
		
		// 接続結果を取得
		String httpstat = result[0];
		String response = result[1];
		
		// 結果設定用
		Hashtable<String, Object> resultMap = new Hashtable<String, Object>();
		// 接続結果設定用
		Map<String, Object> connectResult = new HashMap<String, Object>();
		// レスポンス情報設定用
		Map<String, Object> resInfo = new HashMap<String, Object>();
		
		// 返却情報を作成
		ObjectMapper mapper = new ObjectMapper();
		JsonNode root = mapper.readTree(response);
		
		// 処理結果を格納
		// 接続結果
		connectResult.put(CONNECTRESULT_HTTPSTATUS, httpstat);
		// 実行結果
		resInfo.put(RESINFO_BODY, root);
		
		// レスポンス返却用に格納
		resultMap.put(CONNECTRESULT, connectResult);
		resultMap.put(RESINFO, resInfo);
		
		// ANK-4346-16-00 DEL START	
		// 処理結果をログ出力
//		JSYejbLog.println(JSYejbLog.EXECUTION, JCNCtrlCcmgConnectInfoImpl.class , ("json連携結果 HttpStatus=" 
//				+ connectResult.get(CONNECTRESULT_HTTPSTATUS)).replaceAll("\\s+", " "));
//		JSYejbLog.println(JSYejbLog.EXECUTION, JCNCtrlCcmgConnectInfoImpl.class , ("json連携結果 response=" + 
//				resInfo.toString()).replaceAll("\\s+", " "));
		// ANK-4346-16-00 DEL END
		
		// 接続情報をログに出力
		JSYejbLog.println(JSYejbLog.EXECUTION, JCNCtrlCcmgConnectInfoImpl.class , "JCNCtrlCcmgConnectInfoImpl" + apiid + "#レスポンス情報 : " + resultMap);
		return resultMap;
	}
	
	/**
	 * CCMGへHTTP接続を実施する。
	 * 
	 * @param url   接続URL
	 * @param apiid 接続APIID
	 * @param connectMethod 接続メソッド
	 * @param send_timeout タイムアウト時間
	 * @param send_retryCount リトライ回数
	 * @param send_retryInterval リトライインターバル
	 * @param body リクエスト情報
	 * @param acecssToken アクセストークン
	 * @return 実行結果
	 */
	// ANK-4612-00-00 MOD START
//	private static String[] ccmgConnect(String url, String apiid, String connectMethod, String send_timeout, String send_retryCount, String send_retryInterval, 
//			Map<String, Object> body, String acecssToken) throws Exception
	private static String[] ccmgConnect(String url, String apiid, String connectMethod, String send_timeout, String send_retryCount, String send_retryInterval, 
			Map<String, Object> body, String acecssToken, String send_connectionTimeout) throws Exception
	// ANK-4612-00-00 MOD END
	{
		JSYejbLog.println(JSYejbLog.EXECUTION, JCNCtrlCcmgConnectInfoImpl.class , ("JCNCtrlCcmgConnectInfoImpl#ccmgConnect start"));
		// レスポンス(レスポンスボディ)
		String resultText = "";

		// HttpClientを生成
		HttpClient client = new HttpClient();
		// HttpConnectionManagerParamsを生成
		HttpConnectionManagerParams clientParams = client.getHttpConnectionManager().getParams();
		// HttpMethodParamsを生成
		HttpMethodParams methodParams = new HttpMethodParams();

		// 送信用の情報を作成
		String proxyHost   = null;
		Integer proxyPort  = null;
		
		Long timeout       = new Long(send_timeout);
		int retryCnt       = Integer.parseInt(send_retryCount);
		int retryInterval  = Integer.parseInt(send_retryInterval);
		String methodType  = connectMethod;	// メソッドの設定
		String encoding    = CCMG_ENCODING;	// 文字コードの設定(UTF-8)
		
		// ANK-4612-00-00 ADD START
		Long connectionTimeout = new Long(send_connectionTimeout);
		// ANK-4612-00-00 ADD END
		
		// プロキシの設定
		if ((proxyHost != null) && (!"".equals(proxyHost)))
		{
			HostConfiguration hostConfig = client.getHostConfiguration();
			hostConfig.setProxy(proxyHost, proxyPort);
		}

		// タイムアウトの設定
		if (timeout != null)
		{
			clientParams.setSoTimeout(timeout.intValue());
		}

		// ANK-4612-00-00 ADD START
		// コネクションタイムアウトの設定
		if (connectionTimeout != null)
		{
			clientParams.setConnectionTimeout(connectionTimeout.intValue());
		}
		// ANK-4612-00-00 ADD END
		
		// 文字コードの設定
		if (encoding != null)
		{
			methodParams.setContentCharset(encoding);
		}

		Iterator<?> it = body.keySet().iterator();

		// リクエストメソッドの生成
		PostMethod postMethod = null;
		GetMethod getMethod = null;
		PutMethod putMethod = null;
		
		// メソッドごとにリクエストパラメータを作成
		if ("post".equals(methodType.toLowerCase()))
		{
			// リクエストデータのセット
			postMethod = new PostMethod(url);
			// ヘッダにアクセストークンをセット
			postMethod.setRequestHeader("Authorization","Bearer"+" "+acecssToken);

			//while (it.hasNext())
			//{
			//	String paramName = (String) it.next();
			//	String paramValue = (String) body.get(paramName);
			//	postMethod.setParameter(paramName, paramValue);
			//}

			String reqData = "";
			// リクエストのBODY情報を作成する。
			if ("CNIFE058".equals(apiid)) {
				reqData = makeJsonRecParamDirect(body, apiid);
			}
			else
			{
				reqData = makeJsonRecParam(body);
			}
			postMethod.setParams(methodParams);

			StringRequestEntity requestEntity = new StringRequestEntity(
					reqData,
					CONTENT_TYPE_VALUE,
					"UTF-8"
					);
			postMethod.setRequestEntity(requestEntity);
			// #86481 ADD START
			// 実行するAPI・接続URL・リクエスト情報をログ出力
			JSYejbLog.println(JSYejbLog.EXECUTION, JCNCtrlCcmgConnectInfoImpl.class , ("JCNCtrlCcmgConnectInfoImpl 実行URL=" + url + " 実行APIID= " + apiid + "リクエスト情報=" + reqData 
					).replaceAll("\\s+", " "));
			// #86481 ADD END
		}
		else if ("get".equals(methodType.toLowerCase()))
		{
			// #86481 ADD START
			// 実行するAPI・接続URL・リクエスト情報をログ出力
			JSYejbLog.println(JSYejbLog.EXECUTION, JCNCtrlCcmgConnectInfoImpl.class , ("JCNCtrlCcmgConnectInfoImpl 実行URL=" + url + " 実行APIID= " + apiid + "リクエスト情報=" + body 
					).replaceAll("\\s+", " "));
			// #86481 ADD END
			// リクエストデータのセット
			StringBuffer queryStringSb = new StringBuffer();
			
			while (it.hasNext())
			{
				String paramName = (String) it.next();
				String paramValue = (String) body.get(paramName);
				if (queryStringSb.length() > 0)
				{
					queryStringSb.append("&");
				}
				queryStringSb.append(paramName + "=" + paramValue);
			}
			if (queryStringSb.length() > 0)
			{
				url = url + "?" + queryStringSb.toString();
			}
			getMethod = new GetMethod(url);
			// ヘッダにアクセストークンをセット
			getMethod.setRequestHeader("Authorization","Bearer"+" "+acecssToken);
		}
		else if ("put".equals(methodType.toLowerCase()))
		{
			// リクエストデータのセット
			//StringBuffer queryStringSb = new StringBuffer();
			
			//while (it.hasNext())
			//{
			//	String paramName = (String) it.next();
			//	String paramValue = (String) body.get(paramName);
			//	if (queryStringSb.length() > 0)
			//	{
			//		queryStringSb.append("&");
			//	}
			//	queryStringSb.append(paramName + "=" + paramValue);
			//}
			//if (queryStringSb.length() > 0)
			//{
			//	url = url + "?" + queryStringSb.toString();
			//}

			putMethod = new PutMethod(url);
			// ヘッダにアクセストークンをセット
			putMethod.setRequestHeader("Authorization","Bearer"+" "+acecssToken);
			
			// リクエストのBODY情報を作成する。
			String reqData = "";
			// リクエストのBODY情報を作成する。
			if ("CNIFE056".equals(apiid)) {
				reqData = makeJsonRecParamDirect(body, apiid);
			}
			else
			{
				reqData = makeJsonRecParam(body);
			}

			putMethod.setParams(methodParams);

			StringRequestEntity requestEntity = new StringRequestEntity(
					reqData,
					CONTENT_TYPE_VALUE,
					"UTF-8"
					);
			putMethod.setRequestEntity(requestEntity);
			// #86481 ADD START
			// 実行するAPI・接続URL・リクエスト情報をログ出力
			JSYejbLog.println(JSYejbLog.EXECUTION, JCNCtrlCcmgConnectInfoImpl.class , ("JCNCtrlCcmgConnectInfoImpl 実行URL=" + url + " 実行APIID= " + apiid + "リクエスト情報=" + reqData 
					).replaceAll("\\s+", " "));
			// #86481 ADD END
		}
		
		int httpStatus = 500;
		Exception ex = null;

		// リクエストデータの送信とリトライ
		int reqCnt = retryCnt + 1;
		for (int i = 0; i < reqCnt; i++)
		{
			ex = null;

			try
			{
				JSYejbLog.println(JSYejbLog.EXECUTION, JCNCtrlCcmgConnectInfoImpl.class , ("JCNCtrlCcmgConnectInfoImpl#ccmgConnect 接続開始"));
				if (postMethod != null)
				{
					httpStatus = client.executeMethod(postMethod);
					resultText = postMethod.getResponseBodyAsString();
				}
				if (getMethod != null)
				{
					httpStatus = client.executeMethod(getMethod);
					resultText = getMethod.getResponseBodyAsString();
				}
				if (putMethod != null)
				{
					httpStatus = client.executeMethod(putMethod);
					resultText = putMethod.getResponseBodyAsString();
				}
				JSYejbLog.println(JSYejbLog.EXECUTION, JCNCtrlCcmgConnectInfoImpl.class , ("JCNCtrlCcmgConnectInfoImpl#ccmgConnect 接続終了"));
			}
			catch (HttpException e)
			{
				ex = e;
				JSYejbLog.println(JSYejbLog.EXECUTION, JCNCtrlCcmgConnectInfoImpl.class , ("JCNCtrlCcmgConnectInfoImpl#ccmgConnect 異常検知：パターン１"));
			}
			catch (IOException e)
			{
				ex = e;
				JSYejbLog.println(JSYejbLog.EXECUTION, JCNCtrlCcmgConnectInfoImpl.class , ("JCNCtrlCcmgConnectInfoImpl#ccmgConnect 異常検知：パターン２"));
			}
			catch (Exception e)
			{
				ex = e;
				JSYejbLog.println(JSYejbLog.EXECUTION, JCNCtrlCcmgConnectInfoImpl.class , ("JCNCtrlCcmgConnectInfoImpl#ccmgConnect 異常検知：パターン３"));
			}

			// 失敗時はリトライ回数の上限までリトライ
			if (((ex != null)) && (i < retryCnt))
			{
				try
				{
					JSYejbLog.println(JSYejbLog.EXECUTION, JCNCtrlCcmgConnectInfoImpl.class , ("[EKB9930-CE]コンテンツ管理システムへの連携に失敗しました。"));
					Thread.sleep(retryInterval);
				}
				catch (InterruptedException e)
				{
					// 割り込み要求による例外は無視
				}
				continue;
			}

			break;
		}

		// コネクション解放
		if (postMethod != null)
		{
			postMethod.releaseConnection();
			postMethod = null;
		}
		if (getMethod != null)
		{
			getMethod.releaseConnection();
			getMethod = null;
		}
		if (putMethod != null)
		{
			putMethod.releaseConnection();
			putMethod = null;
		}
		
//		// #84485 DEL START
//		// ANK-4346-16-00 ADD START
//		// 処理結果をログ出力
//		JSYejbLog.println(JSYejbLog.EXECUTION, JCNCtrlCcmgConnectInfoImpl.class , ("json連携結果 HttpStatus=" 
//				+ new Integer(httpStatus).toString().replaceAll("\\s+", " ")));
//		JSYejbLog.println(JSYejbLog.EXECUTION, JCNCtrlCcmgConnectInfoImpl.class , ("json連携結果 response=" + 
//				resultText.toString()).replaceAll("\\s+", " "));
//		// ANK-4346-16-00 ADD END
//		// #84485 DEL END
		
		// ST-2024-0000004 ADD SATRT
		// レスポンスBodyがnull、または空の場合
		if(JCNStringUtil.isNullEmpty(resultText))
		{
			// 空のBodyを生成する
			resultText = "{}";
		}
		// ST-2024-0000004 ADD END
		
		// #84485 ADD START
		// 処理結果をログ出力
		JSYejbLog.println(JSYejbLog.EXECUTION, JCNCtrlCcmgConnectInfoImpl.class , ("json連携結果 HttpStatus=" 
				+ new Integer(httpStatus).toString().replaceAll("\\s+", " ")));
		JSYejbLog.println(JSYejbLog.EXECUTION, JCNCtrlCcmgConnectInfoImpl.class , ("json連携結果 response=" + 
				resultText).replaceAll("\\s+", " "));
		// #84485 ADD END
		
		JSYejbLog.println(JSYejbLog.EXECUTION, JCNCtrlCcmgConnectInfoImpl.class , ("JCNCtrlCcmgConnectInfoImpl#ccmgConnect end"));
		
		return new String[] { new Integer(httpStatus).toString(), resultText };
	}
	
	/**
	 * モードがスタブ接続の場合に、疑似的にAPIを実行する
	 * 
	 * @param apiid 接続APIID
	 * @param body リクエスト情報
	 * @return 実行結果
	 */
	private static Hashtable<String, Object> stubConnect(String apiid,Map<String, Object> body) throws Exception
	{
		JSYejbLog.println(JSYejbLog.EXECUTION, JCNCtrlCcmgConnectInfoImpl.class , ("JCNCtrlCcmgConnectInfoImpl 実行APIID= " + apiid + "リクエスト情報=" +body 
		).replaceAll("\\s+", " "));
		
		// 結果設定用
		Hashtable<String, Object> resultMap = new Hashtable<String, Object>();
		// 接続結果設定用
		Map<String, Object> connectResult = new HashMap<String, Object>();
		// レスポンス情報設定用
		Map<String, Object> resInfo = new HashMap<String, Object>();
		
		// スタブファイル名を取得
		String filenm = "";
		// スタブHTTPステータス取得コードを取得
		String httpstatcd = STUB_HTTPSTAT_MAP.get(apiid);
		// スタブHTTPステータスを取得
		String httpstat = JCMAPLConstMgr.getString(httpstatcd);
		// スタブファイル格納パスを取得
		String dir_pass = JCMAPLConstMgr.getString(CCMG_CONNECTION_MODE_TEST_DIR) + "/";

		Boolean sysid_um = false;
		Boolean contract_no_um = false;
		Boolean service_id_um = false;
		
		String sysid = "";
		String contract_no = "";
		String service_id = "";
		
		// ANK-4346-16-00 MOD START
//		String stub_response = null;
		String stub_response = "";
		// ANK-4346-16-00 MOD END
		Boolean sonzai_um = false;
		
		
		if ("CNIFE047".equals(apiid)) {
			// パラメータ.BODYよりファイル判定キー情報を取得する
			sysid_um = body.containsKey("sysid");
			contract_no_um = body.containsKey("contract_no");
			service_id_um = body.containsKey("service_id");
			
			if (sysid_um) {
				sysid = nullToBlank((String) body.get("sysid"));
			}
			
			if (contract_no_um) {
				contract_no = nullToBlank((String) body.get("contract_no"));
			}
			
			if (service_id_um) {
				service_id = nullToBlank((String) body.get("service_id"));
			}
			// スタブファイル名を取得
			if(!isNullBlank(contract_no)) {
				filenm = STUB_FILE_MAP.get(apiid+"-2");
			} else if(!isNullBlank(service_id)) {
				filenm = STUB_FILE_MAP.get(apiid+"-3");
			} else if (!isNullBlank(sysid)) {
				filenm = STUB_FILE_MAP.get(apiid+"-1");
			}
		} else {
			// スタブファイル名を取得
			filenm = STUB_FILE_MAP.get(apiid);
		}
		
		// スタブファイルフルパスを取得
		String full_pass = dir_pass + filenm;
		
		 // スタブファイル読込
		File file = new File(full_pass);
		if(!file.exists()){
			// ファイル読込に失敗した場合、
			// 実行結果およびHTTPステータスを取得
			String gizi_result = NOT_EXITS_FILE_RESULT_MAP.get(apiid);
			String gizi_httpstat = NOT_EXITS_FILE_HTTPSTAT_MAP.get(apiid);
			// apiidがCNIFE059の場合XXXXXXXXXをランダムな数字9桁に置換
			if ("CNIFE059".equals(apiid)) {
				// ランダムな9桁数字を取得
				String random9 = getRandTrnNo();
				gizi_result = gizi_result.replace("XXXXXXXXX", random9);
			}
			
			// 処理結果を格納
			// 接続結果
			connectResult.put(CONNECTRESULT_HTTPSTATUS, gizi_httpstat);
			// 実行結果
			ObjectMapper mapper = new ObjectMapper();
			JsonNode root = mapper.readTree(gizi_result);
			
			resInfo.put(RESINFO_BODY, root);
			
		} else {
			// 該当ファイルが存在する場合、
			
			if ("CNIFE047".equals(apiid) ||
					// ANK-4570-00-00 ADD START
					"CNIFE057".equals(apiid) ||
					// ANK-4570-00-00 ADD AND
						"CNIFE048".equals(apiid)) {
				// CNIFE047またはCNIFE048またはCNIFE057の場合、
				
				// ファイル読込用にインスタンスを生成
				BufferedReader br = new BufferedReader(new FileReader(file));
				// 1行目読込
				String line = br.readLine();
				
				// 1行目のキー情報およびレスポンス情報を切り分ける
				String[] response = line.split("@@");
				
				String search_key = null;
				
				if ("CNIFE047".equals(apiid)) {
					// CNIFE047の場合、
					
					// 利用するスタブファイル毎に検索キーを設定
					if (filenm.equals("CCMG_CNIFE047_SYSID_STUB.json")) {
						search_key = sysid;
					} else if(filenm.equals("CCMG_CNIFE047_CONTKEI_STUB.json")) {
						search_key = contract_no;
					} else if(filenm.equals("CCMG_CNIFE047_SVCCD_STUB.json")) {
						// ANK-4346-00-00 v65.00.05 MOD START
//						search_key = service_id;
						search_key = sysid + service_id;
						// ANK-4346-00-00 v65.00.05 MOD END
					}
				} else if("CNIFE048".equals(apiid)) {
					// CNIFE048の場合、
					
					// パラメータ.BODYより「SYSID」「対象年月」「ページ番号」を取得
					sysid = nullToBlank((String) body.get("sysid"));
					String tgtYm = nullToBlank((String) body.get("target_date"));
					String page_number = nullToBlank((String) body.get("page"));
					
					// 検索キーを設定
					search_key = sysid + tgtYm + page_number;
				}
				// ANK-4570-00-00 ADD START
				 else if("CNIFE057".equals(apiid)) {
					 // CNIFE057の場合、
				
					// パラメータ.BODYより「SYSID」を取得
					sysid = nullToBlank((String) body.get("sysid"));
					
					// パラメータ.BODYより「サービスID」を取得
					service_id = nullToBlank((String) body.get("service_id"));
					
					// 検索キーを設定
					search_key = sysid + service_id;
				}
				// ANK-4570-00-00 ADD END
				
				while(line != null) {
					response = line.split("@@");
					
					// 検索キーと一致するデータを取得する
					if(response[0].equals(search_key)) {
						stub_response = response[1];
						sonzai_um = true;
						
						// 検索対象が存在した場合は、処理を抜ける
						break;
					}
					// 次の行を読込み
					line = br.readLine();
				}
				
			}
			
			// JsonNodeインスタンスを作成
			ObjectMapper mapper = new ObjectMapper();
			JsonNode root = null;
			
			// ANK-4346-16-01 DEL START
			// ANK-4346-16-00 ADD START
			// 処理結果をログ出力
//			JSYejbLog.println(JSYejbLog.EXECUTION, JCNCtrlCcmgConnectInfoImpl.class , ("json連携結果 HttpStatus=" 
//					+ new Integer(httpstat).toString().replaceAll("\\s+", " ")));
//			JSYejbLog.println(JSYejbLog.EXECUTION, JCNCtrlCcmgConnectInfoImpl.class , ("json連携結果 response=" + 
//					stub_response.toString()).replaceAll("\\s+", " "));
			// ANK-4346-16-00 ADD END
			// ANK-4346-16-01 DEL END
			
			if ("CNIFE047".equals(apiid) ||
					// ANK-4570-00-00 ADD START
					"CNIFE057".equals(apiid) ||
					// ANK-4570-00-00 ADD END
						"CNIFE048".equals(apiid)) {
				// CNIFE047またはCNIFE048またはCNIFE057の場合、
				
				// ANK-4346-16-01 ADD START
				// 処理結果をログ出力
				JSYejbLog.println(JSYejbLog.EXECUTION, JCNCtrlCcmgConnectInfoImpl.class , ("json連携結果 HttpStatus=" 
						+ new Integer(httpstat).toString().replaceAll("\\s+", " ")));
				JSYejbLog.println(JSYejbLog.EXECUTION, JCNCtrlCcmgConnectInfoImpl.class , ("json連携結果 response=" + 
						stub_response.toString()).replaceAll("\\s+", " "));
				// ANK-4346-16-01 ADD END
				
				if (sonzai_um) {
					// 検索対象存在有無フラグが"true"の場合、
					root = mapper.readTree(stub_response);
				} else {
					// 検索対象存在有無フラグが"false"の場合、
					if ("CNIFE047".equals(apiid)) {
						root = mapper.readTree("{\"err_cd\":\"00000\",\"contracts\":[]}");
					} else if("CNIFE048".equals(apiid)) {
						root = mapper.readTree("{\"err_cd\":\"00000\",\"charges\":[]}");
					}
					// ANK-4570-00-00 ADD START
					else if("CNIFE057".equals(apiid))
					{
						root = mapper.readTree("{\"err_cd\":\"00000\",\"contractable_contents\":[]}");
					}
					// ANK-4570-00-00 ADD END
				}
			} else {
				// ANK-4346-00-00 MOD START
//				root = mapper.readTree(file);
				// ファイル読込用にインスタンスを生成
				BufferedReader br = new BufferedReader(new FileReader(file));
				// 1行目読込
				// ANK-4346-16-02 MOD START
//				String line = br.readLine();
				String line = JCNStringUtil.nullToBlank(br.readLine());
				// ANK-4346-16-02 MOD END
				
				// ANK-4346-16-01 ADD START
				// 処理結果をログ出力
				JSYejbLog.println(JSYejbLog.EXECUTION, JCNCtrlCcmgConnectInfoImpl.class , ("json連携結果 HttpStatus=" 
						+ new Integer(httpstat).toString().replaceAll("\\s+", " ")));
				JSYejbLog.println(JSYejbLog.EXECUTION, JCNCtrlCcmgConnectInfoImpl.class , ("json連携結果 response=" + 
						line.toString()).replaceAll("\\s+", " "));
				// ANK-4346-16-01 ADD END
				
				if(JCNStringUtil.isNullBlank(line))
				{
					root = mapper.readTree("{}");
				}
				else
				{
					root = mapper.readTree(file);
				}
				// ANK-4346-00-00 MOD END

				
			}
			
			// 処理結果を格納
			// 接続結果
			connectResult.put(CONNECTRESULT_HTTPSTATUS, httpstat);
			// 実行結果
			resInfo.put(RESINFO_BODY, root);
		}
		
		// レスポンス返却用に格納
		resultMap.put(CONNECTRESULT, connectResult);
		resultMap.put(RESINFO, resInfo);
		
		// ANK-4346-16-00 DEL AND
		// 処理結果をログ出力
//		JSYejbLog.println(JSYejbLog.EXECUTION, JCNCtrlCcmgConnectInfoImpl.class , ("json連携結果 HttpStatus=" 
//				+ connectResult.get(CONNECTRESULT_HTTPSTATUS)).replaceAll("\\s+", " "));
//		JSYejbLog.println(JSYejbLog.EXECUTION, JCNCtrlCcmgConnectInfoImpl.class , ("json連携結果 response=" + 
//				resInfo.toString()).replaceAll("\\s+", " "));
		// ANK-4346-16-00 DEL END
		// 接続情報をログに出力
		JSYejbLog.println(JSYejbLog.EXECUTION, JCNCtrlCcmgConnectInfoImpl.class , "JCNCtrlCcmgConnectInfoImpl" + apiid + "#レスポンス情報 : " + resultMap);
		return resultMap;
	}
	
	/**
	 * 処理番号用の9桁のランダムな数値を返却
	 * @return String value ランダムな9桁数値文字列
	 */
	private static String getRandTrnNo() {
		Random r = new Random();
		String value = String.valueOf(r.nextInt(899999999) + 1000000);
		
		return value;
	}
	
	/**
	 * null又は空文字の場合、trueを返却する
	 * 
	 * @param str 検査対象文字列
	 * @return true:null、又は空文字／false:左記以外
	 */
	public static boolean isNullBlank(String str)
	{
		if (null == str || "".equals(str))
		{
			return true;
		}
		return false;
	}
	
	/**
	 * nullを空文字に置き換え
	 * 
	 * @param str 置き換え対象文字列
	 * @return
	 */
	public static String nullToBlank(String str)
	{
		if (str == null)
		{
			return "";
		}
		return str;
	}

	/**
	 * JSON形式のパラメータ作成処理
	 * <br>
	 * @param body 		リクエスト情報

	 * @return 作成したJSON形式のリクエストパラメータを返却する。
	 */
	protected static String makeJsonRecParam(Map<String, Object> body)
	{
		JSONObject json1kaisoMap = new JSONObject();
		Iterator<?> it = body.keySet().iterator();
		try
		{
			//JSON形式のリクエストパラメータを作成する。
			while (it.hasNext())
			{
				String paramName = (String) it.next();
				String paramValue = (String) body.get(paramName);
				json1kaisoMap.put(paramName, paramValue); 
			}
		}
		catch (JSONException e)
		{
			e.printStackTrace();
		}
		return json1kaisoMap.toString();
	}

	/**
	 * JSON形式のパラメータ作成処理
	 * (リクエストデータをそのままマッピングします。)
	 * <br>
	 * @param body 		リクエスト情報

	 * @return 作成したJSON形式のリクエストパラメータを返却する。
	 */
	@SuppressWarnings("unchecked")
	protected static String makeJsonRecParamDirect(Map<String, Object> body, String apiId)
	{

		String list_name = "";
		// #86481 MOD START
//		String list_item_name = "";
		ArrayList<String> list_item_name = new ArrayList();
		// #86481 MOD END
		if ("CNIFE058".equals(apiId)) {
			list_name = "contents";
			// #86481 DEL START
//			list_item_name = "contents_id";
			// #86481 DEL END
			// #86481 ADD START
			list_item_name.add("contents_id");
			list_item_name.add("campaign_cd");
			// #86481 ADD END
		}
		else if ("CNIFE056".equals(apiId)) {
			list_name = "cancel";
			// #86481 MOD START
//			list_item_name = "contract_no";
			list_item_name.add("contract_no");
			// #86481 MOD END
		}
		JSONObject json1kaisoMap = new JSONObject();
		// コンテンツ情報リスト 
		JSONObject contentsInfo = new JSONObject();
		Iterator<?> it = body.keySet().iterator();
		try
		{
			//JSON形式のリクエストパラメータを作成する。
			while (it.hasNext())
			{
				String paramName = (String) it.next();
				if (list_name.equals(paramName)) {
					ArrayList dataList = (ArrayList)body.get(paramName);
					for(int i = 0; i < dataList.size(); i++){
						HashMap<String, Object> list = (HashMap<String, Object>)dataList.get(i);
						// #86481 ADD START
						for(int k = 0; k < list_item_name.size(); k++)
						{
						// #86481 ADD END
							// #86481 MOD START
//							contentsInfo.put(list_item_name, list.get(list_item_name));
							contentsInfo.put(list_item_name.get(k), list.get(list_item_name.get(k)));
							// #86481 MOD END
						// #86481 ADD START
						}
						// #86481 ADD END
					}

					JSONArray json2kaisoMap = new JSONArray();
					json2kaisoMap.put(contentsInfo);
					
					json1kaisoMap.put(paramName, json2kaisoMap);
				}
				else 
				{
					String paramValue = (String) body.get(paramName);
					json1kaisoMap.put(paramName, paramValue);
				}
			}
		}
		catch (JSONException e)
		{
			e.printStackTrace();
		}
		return json1kaisoMap.toString();
	}
}
