/*********************************************************************
* All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*   システム名      ：eo顧客基幹システム
*   モジュール名    ：JKKBaseUtil
*   ソースファイル名：JKKBaseUtil.java
*   作成者          ：富士通
*   日付            ：2011年08月23日
*＜機能概要＞
*   顧客契約基底部品
*＜修正履歴＞
*   バージョン  修正日      修正者     修正内容
*   v1.00.00    2013/01/15  FJ          新規作成 ANK-1276-00-00
*   
**********************************************************************/
package com.fujitsu.futurity.bp.custom.common;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

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.ErrorLevel;
import com.fujitsu.futurity.bp.x21.bpm.parameter.IRequestParameterReadWrite;
import com.fujitsu.futurity.bp.x21.bpm.parameter.StatusArea;
import com.fujitsu.futurity.bp.x21.bpm.parameter.StatusInfo;
import com.fujitsu.futurity.bp.x21.cc.exception.CCException;
import com.fujitsu.futurity.bp.x21.cc.exception.SCCallException;
import com.fujitsu.futurity.bp.x21.values.OUTBREAK_AREA;
import com.fujitsu.futurity.common.JCMConstants;
import com.fujitsu.futurity.common.x01.sc.ErrorInfoMapKeys;
import com.fujitsu.futurity.common.x01.sc.SCControlMapKeys;
import com.fujitsu.futurity.mapping.bp.common.TemplateErrorUtil;
import com.fujitsu.futurity.model.base.CAANMsg;
import com.fujitsu.futurity.model.common.JCMAPLConstMgr;

import eo.common.constant.JPCModelConstant;

/**
 * 顧客契約基底部品
 * 
 * <br>
 * @author 富士通
 */
@SuppressWarnings("unchecked")
public class JKKBaseUtil
{
	/** テンポラリテンプレート領域キー識別子 */
	protected static final String TEMP_TEMPLATE_PRIFIX = "TEMP_TEMPLATE_";
	/** テンポラリテンプレート領域キー識別子区切文字 */
	protected static final String TEMP_TEMPLATE_PRIFIX_SEP = "_";
	/** 空文字 */
	protected static final String BLANK = "";
	/** リターンコード(正常)  */
	protected static final int RETURN_CODE_NORMAL = 0;
	/** SC呼出制御キー(検索エラーなし) */
	protected static final String IGNORE_SEARCH_ERR = "ignore_search_err";
	/** 検索処理パターン(一括) */
	protected static final String SEARCH_TYPE_IKT = "1";

	/** リターンメッセージ */
	private static final String RETURN_MESSAGE_STRING = "RETURN_MESSAGE_";
	/** リターンメッセージ形式 */
	private static final String RETURN_MESSAGE_FORMAT = "%1$04d";
	/** エラーフラグ(関連チェック) */
	private static final String ERROR_FLG_RELATION = "EA";
	/** ステータス(正常)  */
	private static final int STATUS_NORMAL = 0;
	/** ステータス(システムエラー) */
	private static final int STATUS_SYSTEM_ERROR = 9000;

	/** CBSパッケージ */
	private static final String CBS_PACKAGE = "eo.ejb.cbs.cbsmsg.";
	/** CBS識別子 */
	private static final String CBS_PREFIX = "CBSMsg";
	/** 更新系サービスIF識別子 */
	private static final String[] UPDATE_SC_PREFIX = { "C", "D", "E" };
	/** 一時領域マップキー番号初期値 */
	private static final String TEMP_START_NUM = "1";

	/** エラーメッセージ：該当データなし */
	private static final String CC_ERR_MSG_NO_DATA_FOUND = "該当データなしエラー";

	/** 月初 */
	private static final String START_DAY = "01";
	
	/**
	 * サービスコンポーネント実行後に、IRequestParameterReadWriteにエラー情報をマッピングする
	 * 
	 * @param param リクエストパラメータ
	 * @param templates テンプレート
	 * @param returnCode リターンコード
	 * @return リクエストパラメータ管理クラス
	 * @throws RequestParameterException
	 */
	public static final IRequestParameterReadWrite editErrorInfo(IRequestParameterReadWrite param, CAANMsg[] templates, int returnCode)
			throws RequestParameterException
	{
		setErrorInfo(param, templates[0], returnCode);
		return param;
	}

	/**
	 * サービス契約(HTなど、日割系)のサービス課金終了日を返します。
	 * 
	 * <br>
	 * @param arg パラメータ
	 * @return サービス課金終了日
	 */
	public static String getSvcChrgEndYmdSvcKeiHt(String arg)
	{
		// 運用日付の前日
		return JKKBPActCommon.addDay(JKKBPActCommon.getOpeDate(null), -1);
	}
	
	/**
	 * オプションサービス契約(TV以外、月額系)のサービス課金終了日を返します。
	 * 
	 * <br>
	 * @param arg パラメータ
	 * @return サービス課金終了日
	 */
	public static String getSvcChrgEndYmdOp(String arg)
	{
		// 運用日付の前日
		return JKKBPActCommon.addDay(JKKBPActCommon.getOpeDate(null), -1);
	}

	/**
	 * オプションサービス契約(TV、月額系)のサービス課金終了日を返します。
	 * 
	 * <br>
	 * @param arg パラメータ
	 * @return サービス課金終了日
	 */
	public static String getSvcChrgEndYmdOpTv(String arg)
	{
		// 運用日付の月末日
		return JKKBPActCommon.getEndOfMonthOnlineDate(null);
	}

	/**
	 * 機器提供サービス契約(レンタル、月額系)のサービス課金終了日を返します。
	 * 
	 * <br>
	 * @param arg パラメータ
	 * @return サービス課金終了日
	 */
	public static String getSvcChrgEndYmdKiki(String arg)
	{
		String opeDate = JKKBPActCommon.getOpeDate(null);

		// 月初の場合
		if (START_DAY.equals(opeDate.substring(6, 8)))
		{
			// 前月の月末日
			return JKKBPActCommon.addDay(opeDate, -1);
		}
		// 月中
		else
		{
			// 運用日付の月末日
			return JKKBPActCommon.getEndOfMonthOnlineDate(null);
		}
	}

	/**
	 * 割引サービス契約(HTなど、日割系)のサービス課金終了日を返します。
	 * 
	 * <br>
	 * @param arg パラメータ
	 * @return サービス課金終了日
	 */
	public static String getSvcChrgEndYmdWribHt(String arg)
	{
		// 運用日付の前日
		return JKKBPActCommon.addDay(JKKBPActCommon.getOpeDate(null), -1);
	}

	/**
	 * チェック処理
	 * 
	 * <br>
	 * @param handle セッションハンドル
	 * @param param リクエストパラメータ
	 * @param fixedText サービスメッセージ
	 * @param templateId テンプレートID
	 * @param templateIdDetail テンプレートID(明細)
	 * @param inColumnList IN項目リスト
	 * @return チェック処理用マップ
	 * @throws Exception 
	 */
	protected static HashMap<String, Object> getInvokeCBS(SessionHandle handle, IRequestParameterReadWrite param, String fixedText,
			String templateId, String templateIdDetail, List<String> inColumnList) throws Exception
	{
		HashMap<String, Object> paramMap = new HashMap<String, Object>();
		// 共通データ設定
		setSCInputCommonData(param, paramMap);
		// テンプレート取得・マップ設定
		setParamMap(paramMap, editInData(param, fixedText, templateId, Arrays.asList(templateIdDetail), inColumnList));

		return paramMap;
	}

	/**
	 * サービスIF実行
	 * 
	 * <br>
	 * @param handle セッションハンドル
	 * @param param リクエストパラメータ
	 * @param fixedText サービスメッセージ
	 * @param templateId テンプレートID
	 * @param templateIdDetail テンプレートID(明細)
	 * @param inColumnList IN項目リスト
	 * @param errorColumn エラー項目
	 * @return リクエストパラメータ管理クラス
	 * @throws Exception
	 */
	protected static IRequestParameterReadWrite executeSC(SessionHandle handle, IRequestParameterReadWrite param, String fixedText,
			String templateId, String templateIdDetail, List<String> inColumnList, String errorColumn) throws Exception
	{
		return executeSC(handle, param, fixedText, templateId, Arrays.asList(templateIdDetail), inColumnList, errorColumn);
	}

	/**
	 * サービスIF実行
	 * <br>
	 * @param handle セッションハンドル
	 * @param param リクエストパラメータ
	 * @param fixedText サービスメッセージ
	 * @param templateId テンプレートID
	 * @param templateIdDetailList テンプレートID(明細)リスト
	 * @param inColumnList
	 * @param errorColumn エラー項目
	 * @return リクエストパラメータ管理クラス
	 * @throws Exception
	 */
	protected static IRequestParameterReadWrite executeSC(SessionHandle handle, IRequestParameterReadWrite param, String fixedText,
			String templateId, List<String> templateIdDetailList, List<String> inColumnList, String errorColumn) throws Exception
	{
		ServiceComponentRequestInvoker scCall = new ServiceComponentRequestInvoker();
		HashMap<String, Object> paramMap = new HashMap<String, Object>();
		setSCInputCommonData(param, paramMap);
		Map<?, ?> result = null;

		// 上りマッピング
		setParamMap(paramMap, editInData(param, fixedText, templateId, templateIdDetailList, inColumnList));

		// SC呼び出し
		result = scCall.run(paramMap, handle);

		// 下りマッピング
		editOutData(result, param, fixedText, templateId, templateIdDetailList, errorColumn);

		if (getStatus(param, templateId) >= JPCModelConstant.SINGLEDATA_ERR || getReturnCode(param) >= JPCModelConstant.SINGLEDATA_ERR)
		{
			// ステータスが単項目エラー以上であれば例外をスロー
			throw new SCCallException(String.valueOf(param.getControlMapData(SCControlMapKeys.RETURN_MESSAGE)), String.valueOf(getReturnCode(param)),
					getStatus(param, templateId));
		}
		return param;
	}

	/**
	 * 機能コード設定
	 * <br>
	 * @param param リクエストパラメータ
	 * @param fixedText サービスメッセージ
	 * @param funcCode 機能コード
	 * @throws RequestParameterException
	 */
	protected static void setFuncCode(IRequestParameterReadWrite param, String fixedText, String funcCode) throws RequestParameterException
	{
		// ユーザデータに機能コードを設定
		((HashMap<String, String>)param.getData(fixedText)).put(JCMConstants.FUNC_CODE_KEY, funcCode);
	}

	/**
	 * 機能コード取得
	 * <br>
	 * @param param リクエストパラメータ
	 * @param fixedText サービスメッセージ
	 * @return 機能コード
	 * @throws RequestParameterException
	 */
	protected static String getFuncCode(IRequestParameterReadWrite param, String fixedText) throws RequestParameterException
	{
		// 機能コード
		return (String)((HashMap)param.getData(fixedText)).get(JCMConstants.FUNC_CODE_KEY);
	}

	/**
	 * 一時領域のテンプレート値取得
	 * 
	 * <br>
	 * @param dataMap ユーザデータ
	 * @param parentKey テンプレート取得キー
	 * @param columnKey 項目キー
	 * @return 一時領域のテンプレート値
	 */
	protected static String getTemplateValue(HashMap dataMap, String parentKey, String columnKey)
	{
		HashMap parentTemplate = (HashMap)dataMap.get(parentKey);

		return (String)parentTemplate.get(columnKey);
	}

	/**
	 * 一時領域のテンプレート値取得(明細部)
	 * 
	 * <br>
	 * @param dataMap ユーザデータ
	 * @param parentKey テンプレート取得キー
	 * @param listKey  テンプレート取得キー(明細部)
	 * @param columnKey 項目キー
	 * @param index 配列番号
	 * @return 一時領域のテンプレート値(明細部)
	 */
	protected static String getTemplateListValue(HashMap dataMap, String parentKey, String listKey, String columnKey, int index)
	{
		return (String)getTemplateListMap(dataMap, parentKey, listKey, index).get(columnKey);
	}

	/**
	 * 一時領域のテンプレートマップ取得(明細部)
	 * <br>
	 * @param dataMap ユーザデータ
	 * @param parentKey テンプレート取得キー
	 * @param listKey  テンプレート取得キー(明細部)
	 * @param index 配列番号
	 * @return 一時領域のテンプレートマップ
	 */
	protected static HashMap getTemplateListMap(HashMap dataMap, String parentKey, String listKey, int index)
	{
		return getTemplateList(dataMap, parentKey, listKey).get(index);
	}

	/**
	 * 一時領域のテンプレート明細リスト取得
	 * <br>
	 * @param dataMap ユーザデータ
	 * @param parentKey テンプレート取得キー
	 * @param listKey  テンプレート取得キー(明細部)
	 * @return 一時領域のテンプレート明細リスト
	 */
	protected static List<HashMap> getTemplateList(HashMap dataMap, String parentKey, String listKey)
	{
		List<HashMap> list = null;

		HashMap parentTemplate = (HashMap)dataMap.get(parentKey);
		HashMap[] childTemplates = (HashMap[])parentTemplate.get(listKey);
		if (null == childTemplates)
		{
			list = new ArrayList<HashMap>();
		}
		else
		{
			list = Arrays.asList(childTemplates);
		}
		return list;
	}

	/**
	 * 最大のSC実行結果取得キー取得
	 * <br>
	 * @param dataMap ユーザデータ
	 * @param parentBaseKey テンプレート取得キー(通番なし)
	 * @return 最大のSC実行結果取得キー
	 */
	protected static String getMaxTempTempleteKey(HashMap dataMap, String parentBaseKey)
	{
		Set<String> set = dataMap.keySet();
		List<String> list = new ArrayList<String>();

		for (String key : set)
		{
			if (key.startsWith(parentBaseKey))
			{
				list.add(key);
			}
		}

		if (list.isEmpty())
		{
			list.add(parentBaseKey + TEMP_START_NUM);
		}

		Collections.sort(list);
		Collections.reverse(list);

		return list.get(0);
	}

	/**
	 * 一時領域のテンプレート明細存在チェック
	 * <br>
	 * @param dataMap ユーザデータ
	 * @param parentKey テンプレート取得キー
	 * @param listKey  テンプレート取得キー(明細部)
	 * @return true:存在 false:未存在
	 */
	protected static boolean isExistsTemplateDetail(HashMap dataMap, String parentKey, String listKey)
	{
		List<HashMap> list = getTemplateList(dataMap, parentKey, listKey);

		if (null == list || list.isEmpty())
		{
			return false;
		}
		else
		{
			return true;
		}
	}

	/**
	 * 一時領域の一括削除
	 * 
	 * <br>
	 * @param param リクエストパラメータ
	 * @param fixedText サービスメッセージ
	 * @throws RequestParameterException
	 */
	protected static void deleteTempArea(IRequestParameterReadWrite param, String fixedText) throws RequestParameterException
	{
		HashMap<String, Object> dataMap = (HashMap<String, Object>)param.getData(fixedText);
		Set<String> set = dataMap.keySet();

		List<String> setClone = new ArrayList<String>();

		// deep copy
		for (String key : set)
		{
			if (key.startsWith(TEMP_TEMPLATE_PRIFIX))
			{
				setClone.add(key);
			}
		}

		// remove
		for (String key : setClone)
		{
			dataMap.remove(key);
		}
	}

	/**
	 * ユーザーデータの初期化
	 * 
	 * <br>
	 * @param param リクエストパラメータ
	 * @param fixedText サービスメッセージ
	 * @param columnList 項目リスト
	 * @throws RequestParameterException
	 */
	protected static void initData(IRequestParameterReadWrite param, String fixedText, List<String> columnList) throws RequestParameterException
	{
		HashMap<String, Object> dataMap = (HashMap<String, Object>)param.getData(fixedText);

		for (String key : columnList)
		{
			dataMap.remove(key);
		}
	}

	/**
	 * 検索エラーなし設定
	 * 
	 * <br>
	 * @param param リクエストパラメータ
	 * @param fixedText サービスメッセージ
	 * @throws RequestParameterException
	 */
	protected static void ignoreSearchError(IRequestParameterReadWrite param, String fixedText) throws RequestParameterException
	{
		HashMap<String, Object> dataMap = (HashMap<String, Object>)param.getData(fixedText);

		dataMap.put(IGNORE_SEARCH_ERR, null);
	}

	/**
	 * 関連チェックエラー情報設定
	 * 
	 * <br>
	 * @param param リクエストパラメータ
	 * @param templateId テンプレートID
	 * @param errColumn エラー項目
	 * @param fixedText サービスメッセージ
	 * @throws RequestParameterException 
	 */
	protected static void setRelationErrorInfo(IRequestParameterReadWrite param, String templateId, String errColumn, String fixedText)
			throws RequestParameterException
	{
		// 関連チェックエラー
		String formatStatus = String.format(RETURN_MESSAGE_FORMAT, JPCModelConstant.RELATION_ERR);
		String message = JCMAPLConstMgr.getString(RETURN_MESSAGE_STRING + formatStatus);
		param.setControlMapData(SCControlMapKeys.RETURN_CODE, String.format(RETURN_MESSAGE_FORMAT, RETURN_CODE_NORMAL));
		param.setControlMapData(SCControlMapKeys.RETURN_MESSAGE, message);

		// エラー情報のリストを取得
		ArrayList<Object> errList = (ArrayList<Object>)param.getControlMapData(SCControlMapKeys.ERROR_INFO);
		if (errList == null)
		{
			errList = new ArrayList<Object>();
		}

		// コントロールマップに設定
		HashMap<String, Object> errorMap = new HashMap<String, Object>();
		HashMap<String, String> errorMapChild = new HashMap<String, String>();

		errorMap.put(ErrorInfoMapKeys.RETURN_CODE, RETURN_CODE_NORMAL);
		errorMap.put(ErrorInfoMapKeys.TEMPLATE_ID, templateId);
		errorMap.put(ErrorInfoMapKeys.STATUS, JPCModelConstant.RELATION_ERR);

		errorMapChild.put(errColumn, ERROR_FLG_RELATION);
		errorMap.put(ErrorInfoMapKeys.ITEM_CHECK_ERRORS, errorMapChild);

		errList.add(errorMap);

		param.setControlMapData(SCControlMapKeys.ERROR_INFO, errList);

		// ステータスエリア編集
		StatusArea sa = param.getStatusArea();
		StatusInfo si = new StatusInfo(ErrorLevel.EL888, OUTBREAK_AREA.CC);
		sa.setCurrent(si);

		// ユーザ情報設定
		HashMap<String, String> inMap = (HashMap<String, String>)param.getData(fixedText);
		inMap.put(errColumn, ERROR_FLG_RELATION);
	}

	/**
	 * マップのコピー
	 * 
	 * <br>
	 * @param dest 先のマップ
	 * @param org 元のマップ
	 */
	protected static void copyProperties(HashMap<String, Object> dest, HashMap<String, Object> org)
	{
		Set<String> keySet = org.keySet();

		for (String key : keySet)
		{
			dest.put(key, org.get(key));
		}
	}

	/**
	 * 上りマッピング処理
	 * <br>
	 * @param param リクエストパラメータ
	 * @param fixedText サービスメッセージ
	 * @param templateId テンプレートID
	 * @param templateIdDetailList テンプレートID(明細)リスト
	 * @param inColumnList IN項目リスト
	 * @return テンプレート
	 * @throws Exception
	 */
	private static CAANMsg editInData(IRequestParameterReadWrite param, String fixedText, String templateId, List<String> templateIdDetailList,
			List<String> inColumnList) throws Exception
	{
		// ユーザデータ情報
		HashMap<String, Object> inMap = (HashMap<String, Object>)param.getData(fixedText);

		// テンプレートクラス名
		String templateClassName = CBS_PACKAGE + templateId + CBS_PREFIX;

		// ●テンプレート共通項目設定
		// テンプレート作成
		CAANMsg template = new CAANMsg(templateClassName);

		// ユーザデータの未設定項目初期化
		// initFields(template.getSchema().getSchemaKeySet(), inMap);

		// テンプレートID
		template.set(JCMConstants.TEMPLATE_ID_KEY, templateId);

		// 機能コード
		template.set(JCMConstants.FUNC_CODE_KEY, inMap.get(JCMConstants.FUNC_CODE_KEY));

		// オペレータID
		Object operatorId = param.getControlMapData(SCControlMapKeys.OPERATOR_ID);
		template.set(JCMConstants.OPERATOR_ID_KEY, operatorId);

		// 運用日付
		Object operateDate = param.getControlMapData(SCControlMapKeys.OPE_DATE);
		template.set(JCMConstants.OPERATE_DATE_KEY, operateDate);

		// 運用日時
		Object operateDateTime = param.getControlMapData(SCControlMapKeys.OPE_TIME);
		template.set(JCMConstants.OPERATE_DATETIME_KEY, operateDateTime);

		// ●業務データの設定
		// ヘッダ部
		for (String key : inColumnList)
		{
			if (BLANK.equals(inMap.get(key)))
			{
				template.setNull(key);
			}
			else
			{
				template.set(key, inMap.get(key));
			}

		}

		// 明細部(更新系SIFのみ)
		if (isUpdateTemplete(templateId))
		{
			for (String templateIdDetail : templateIdDetailList)
			{
				ArrayList<HashMap<String, String>> inList = (ArrayList<HashMap<String, String>>)inMap.get(templateIdDetail);
				if (inList == null)
				{
					// 明細部なしの場合は後続処理なし
					continue;
				}

				CAANMsg[] templateArray = template.getCAANMsgList(templateIdDetail);

				if (templateArray == null)
				{
					templateArray = new CAANMsg[inList.size()];
				}

				int cnt = 0;
				for (HashMap<String, String> childMap : inList)
				{
					CAANMsg childTemplate = templateArray[cnt];
					if (childTemplate == null)
					{
						childTemplate = new CAANMsg(CBS_PACKAGE + templateIdDetail);
					}

					Set<String> childMapKeySet = childMap.keySet();

					for (String key : childMapKeySet)
					{
						if (BLANK.equals(childMap.get(key)))
						{
							childTemplate.setNull(key);
						}
						else
						{
							childTemplate.set(key, childMap.get(key));
						}
					}
					templateArray[cnt] = childTemplate;
					cnt++;
				}
				template.set(templateIdDetail, templateArray);
			}
		}
		return template;
	}

	/**
	 * 下りマッピング処理
	 * <br>
	 * @param msgList　
	 * @param msgList 検索結果
	 * @param param リクエストパラメータ
	 * @param fixedText サービスメッセージ
	 * @param templateId テンプレートID
	 * @param templateIdDetailList テンプレートID(明細)リスト
	 * @param errorColumn エラー項目
	 * @throws Exception
	 */
	private static void editOutData(Map<?, ?> msgList, IRequestParameterReadWrite param, String fixedText, String templateId,
			List<String> templateIdDetailList, String errorColumn) throws Exception
	{
		// SCからの戻り値からCAANMsgを取得する。
		CAANMsg[] templates = (CAANMsg[])msgList.get(JCMConstants.TEMPLATE_LIST_KEY);
		CAANMsg parentTemplate = templates[0];

		// リターンコード取得
		int returnCode = (Integer)msgList.get(JCMConstants.RET_CD_INT_KEY);
		// ステータス取得
		int status = (Integer)parentTemplate.getMsgData().get(JCMConstants.STATUS_INT_KEY);

		/* 業務データ設定 */
		HashMap<String, Object> dataMap = (HashMap<String, Object>)param.getData(fixedText);
		if (null == dataMap)
		{
			dataMap = new HashMap<String, Object>();
		}

		// 後続SC呼び出しへ引き継ぐ為、テンプレートを退避
		setTempTemplate(dataMap, parentTemplate, TEMP_TEMPLATE_PRIFIX + templateId);

		// ヘッダ部設定
		HashMap<String, Object> parentTempleteMap = parentTemplate.getMsgData();
		// 下りマッピング項目を全て抽出
		Set<String> parentTempleteMapKeys = parentTempleteMap.keySet();

		for (String key : parentTempleteMapKeys)
		{
			Object obj = parentTempleteMap.get(key);
			if (obj instanceof String)
			{
				dataMap.put(key, (String)obj);
			}
		}

		for (String templateIdDetail : templateIdDetailList)
		{
			// 明細取得
			CAANMsg[] detailArray = parentTemplate.getCAANMsgList(templateIdDetail);
			if (JPCModelConstant.NORMAL_END == returnCode && JPCModelConstant.NORMAL_END == status)
			{
				// データなし
				if (detailArray == null || 0 == detailArray.length)
				{
					// 更新系SCの場合は独自に関連チェックエラーは起こさない
					if (!isUpdateTemplete(templateId))
					{
						// 検索失敗エラーなし設定されていない場合
						if (!dataMap.containsKey(IGNORE_SEARCH_ERR))
						{
							// 検索エラーなしキー削除
							dataMap.remove(IGNORE_SEARCH_ERR);
							// 例外スロー(該当データなし)
							throw new CCException(CC_ERR_MSG_NO_DATA_FOUND, new Exception());
						}
					}
				}
				else
				{
					// 検索結果設定
					List<CAANMsg> detailList = Arrays.asList(detailArray);
					List<HashMap<String, String>> resultList = new ArrayList<HashMap<String, String>>();

					for (CAANMsg detail : detailList)
					{
						HashMap<String, String> innerMap = new HashMap<String, String>();
						HashMap<String, Object> detailMap = detail.getMsgData();
						// 下りマッピング項目を全て抽出
						Set<String> detailKeySet = detailMap.keySet();

						for (String key : detailKeySet)
						{
							Object obj = detailMap.get(key);
							if (obj instanceof String)
							{
								if (detail.isNull(key))
								{
									innerMap.put(key, BLANK);
								}
								else
								{
									innerMap.put(key, detail.getString(key));
								}
							}
						}
						resultList.add(innerMap);
					}

					// 検索結果マップの設定
					dataMap.put(templateIdDetail, resultList);
					param.setData(fixedText, dataMap);
				}
			}
		}
		// 検索エラーなしキー削除
		dataMap.remove(IGNORE_SEARCH_ERR);

		// エラー情報の設定
		setErrorInfo(param, parentTemplate, (Integer)returnCode);

		// エラー情報のマップを取得
		ArrayList<Object> errList = (ArrayList<Object>)param.getControlMapData(SCControlMapKeys.ERROR_INFO);
		if (errList == null)
		{
			errList = new ArrayList<Object>();
		}

		// コントロールマップに設定
		param.setControlMapData(SCControlMapKeys.ERROR_INFO, TemplateErrorUtil.getErrorInfo(msgList, errList));

	}

	/**
	 * 一時領域へのテンプレート設定
	 * 
	 * <br>
	 * @param dataMap ユーザデータ
	 * @param template テンプレート
	 * @param key キー
	 */
	private static void setTempTemplate(HashMap<String, Object> dataMap, CAANMsg template, String key)
	{
		int cnt = 1;

		while (true)
		{
			String putKey = key + TEMP_TEMPLATE_PRIFIX_SEP + String.valueOf(cnt);
			if (!dataMap.containsKey(putKey))
			{
				dataMap.put(putKey, template.getHashMap());
				break;
			}
			cnt++;
		}
	}

	/**
	 * SCインプット共通データ設定処理
	 * <br>
	 * @param param リクエストパラメータ
	 * @param paramMap パラメータマップ
	 * @throws RequestParameterException
	 */
	private static void setSCInputCommonData(IRequestParameterReadWrite param, HashMap<String, Object> paramMap) throws RequestParameterException
	{
		/* SCインプット共通データ */
		// **********************************************
		// 【取得元：電文ヘッダ(ヘッダ)】
		// **********************************************
		// 電文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));

	}

	/**
	 * 単一CAANMsgのマッピング処理
	 * <br>
	 * @param paramMap パラメータマップ
	 * @param template テンプレート
	 * @throws RequestParameterException
	 */
	private static void setParamMap(HashMap<String, Object> paramMap, CAANMsg template) throws RequestParameterException
	{
		CAANMsg[] templates = { template };
		paramMap.put(JCMConstants.TEMPLATE_LIST_KEY, templates);
	}

	/**
	 * エラー情報設定
	 * 
	 * <br>
	 * @param param リクエストパラメータ
	 * @param template　テンプレート
	 * @param returnCode　リターンコード
	 * @throws RequestParameterException
	 */
	private static void setErrorInfo(IRequestParameterReadWrite param, CAANMsg template, int returnCode) throws RequestParameterException
	{

		int templateStatus = template.getInt(JCMConstants.STATUS_INT_KEY);
		if (returnCode != RETURN_CODE_NORMAL)
		{
			templateStatus = STATUS_SYSTEM_ERROR;
		}
		if (JCMAPLConstMgr.getString(RETURN_MESSAGE_STRING + String.format(RETURN_MESSAGE_FORMAT, templateStatus)) == null)
		{
			templateStatus = STATUS_NORMAL;
		}

		int bpStatus = 0;
		Object obj = param.getControlMapData(SCControlMapKeys.RETURN_CODE);
		if (obj == null)
		{
			bpStatus = -1;
		}
		else
		{
			bpStatus = Integer.parseInt((String)param.getControlMapData(SCControlMapKeys.RETURN_CODE));
		}

		if (templateStatus > bpStatus)
		{
			String formatStatus = String.format(RETURN_MESSAGE_FORMAT, templateStatus);
			String message = JCMAPLConstMgr.getString(RETURN_MESSAGE_STRING + formatStatus);
			param.setControlMapData(SCControlMapKeys.RETURN_CODE, String.format(RETURN_MESSAGE_FORMAT, returnCode));
			param.setControlMapData(SCControlMapKeys.RETURN_MESSAGE, message);

			return;
		}

	}

	/**
	 * SCの実行リターンコードの取得
	 * <br>
	 * @param param
	 * @return リターンコード
	 * @throws Exception
	 */
	private static int getReturnCode(IRequestParameterReadWrite param) throws Exception
	{
		return Integer.parseInt((String)param.getControlMapData(SCControlMapKeys.RETURN_CODE));
	}

	/**
	 * SCの実行ステータス取得
	 * 
	 * <br>
	 * @param param リクエストパラメータ
	 * @param templateId テンプレートID
	 * @return ステータス
	 * @throws Exception
	 */
	private static int getStatus(IRequestParameterReadWrite param, String templateId) throws Exception
	{
		int status = STATUS_NORMAL;

		ArrayList<Object> errList = (ArrayList<Object>)param.getControlMapData(SCControlMapKeys.ERROR_INFO);
		for (Object errObj : errList)
		{
			Map<String, String> errMap = (Map<String, String>)errObj;

			if (templateId.equals(errMap.get(ErrorInfoMapKeys.TEMPLATE_ID)))
			{
				status = Integer.parseInt(String.valueOf(errMap.get(ErrorInfoMapKeys.STATUS)));
				break;
			}
		}
		return status;
	}

	/**
	 * 更新系サービスIF判定
	 * <br>
	 * @param templateId
	 * @return true:更新系 false:照会系
	 */
	private static boolean isUpdateTemplete(String templateId)
	{
		List<String> list = Arrays.asList(UPDATE_SC_PREFIX);
		String prefix = templateId.substring(7, 8);

		for (String target : list)
		{
			if (target.equals(prefix))
			{
				return true;
			}
		}
		return false;
	}

}
