/*********************************************************************
* All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*   システム名      ：eo顧客基幹システム
*   モジュール名    ：JKKChkMoveKikiCC
*   ソースファイル名：JKKChkMoveKikiCC.java
*   作成者          ：富士通
*   日付            ：2013年03月19日
*＜機能概要＞
*   移動機器チェックCCです。
*＜修正履歴＞
*   バージョン  修正日       修正者      修正内容
*   v5.00.00    2013/03/19   FJ）        新規作成
*
**********************************************************************/
package com.fujitsu.futurity.bp.custom.common;

import java.util.HashMap;
import java.util.Map;

import com.fujitsu.futurity.bp.custom.constant.JKKChkMoveKikiConstCC;
import com.fujitsu.futurity.bp.x21.bpm.ServiceComponentRequestInvoker;
import com.fujitsu.futurity.bp.x21.bpm.db.SessionHandle;
import com.fujitsu.futurity.bp.x21.bpm.exception.RequestParameterException;
import com.fujitsu.futurity.bp.x21.bpm.parameter.IRequestParameterReadWrite;
import com.fujitsu.futurity.bp.x21.cc.AbstractCommonComponent;
import com.fujitsu.futurity.bp.x21.cc.exception.CCException;
import com.fujitsu.futurity.bp.x21.cc.exception.SCCallException;
import com.fujitsu.futurity.common.JCMConstants;
import com.fujitsu.futurity.common.x01.sc.SCControlMapKeys;
import com.fujitsu.futurity.model.base.CAANMsg;

import eo.common.constant.JKKStrConst;
import eo.ejb.cbs.cbsmsg.EKK0341B011CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK0341B011CBSMsg1List;
import eo.ejb.cbs.cbsmsg.EKK2091A010CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK2091A010CBSMsg1List;
import eo.ejb.cbs.cbsmsg.EKK2101B001CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK2101B001CBSMsg1List;
import eo.ejb.cbs.cbsmsg.EKK2101B002CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK2101B002CBSMsg1List;
import eo.ejb.cbs.cbsmsg.EKU0081B020CBSMsg;
import eo.ejb.cbs.cbsmsg.EKU0081B020CBSMsg1List;
import eo.ejb.cbs.cbsmsg.EKU0141B010CBSMsg;
import eo.ejb.cbs.cbsmsg.EKU0141B010CBSMsg1List;

/**
 * 移動機器チェックCCです。<p>
 * <br>
 * @author FJ
 */
public class JKKChkMoveKikiCC extends AbstractCommonComponent
{
	/** エラーメッセージ */
	private static final String ERR_MSG = "INVALID_RETURN_MESSAGE";

	/** エラーメッセージ：パラメータ設定不正 */
	private static final String ERR_MSG_PARAM = "リクエストパラメータに誤りがあります。";

	/** サービスインタフェース呼び出しで使用するマッパー群 */
	private JKKChkMoveKikiMapperCC mapper = null;

	/** SC呼び出し部品 */
	ServiceComponentRequestInvoker scCall = null;

	/**
	 * 移動機器チェックの初期処理です。
	 * <br>
	 * @param param モデルグループ、コントロールマップを含むパラメータオブジェクト
	 * @param fixedText ユーザ任意文字列
	 * @throws Throwable 
	 */
	private void init(IRequestParameterReadWrite param, String fixedText)
	throws Throwable
	{
		// マッパーの初期化
		if (null == this.mapper)
		{
			this.mapper = new JKKChkMoveKikiMapperCC();
		}

		// SC呼び出し部品のインスタンス生成（引数にはログに出力するクラス名を渡す。空文字を設定した場合はログに出力されない。
		if (null == this.scCall)
		{
			this.scCall = new ServiceComponentRequestInvoker();
		}

		// ユーザ定義領域作成
		createUserData(param, fixedText);

		// リターンコードに正常を設定
		param.setControlMapData(SCControlMapKeys.RETURN_CODE, JCMConstants.RET_NORMAL);
	}

	/**
	 * 移動機器チェック処理を行います。<br>
	 * 指定されたサービス契約番号に、住所変更に伴う移動機器が存在するかどうかを出力パラメータに設定します。
	 * <br>
	 * @param handle セッションマネージャなどを持ったハンドル
	 * @param param モデルグループ、コントロールマップを含むパラメータオブジェクト
	 * @param fixedText ユーザ任意文字列
	 * @return 業務データ取得・書込用I/F
	 * @throws Throwable 
	 */
	@SuppressWarnings("unchecked")
	public IRequestParameterReadWrite chkMoveKiki(SessionHandle handle, IRequestParameterReadWrite param, String fixedText)
	throws Throwable
	{
		// 初期処理
		init(param, fixedText);

		// リクエストパラメータの取得処理
		HashMap<String, Object> trgtData = (HashMap<String, Object>)param.getData(fixedText);

		// 移動機器有無に「無」を設定（初期値）
		trgtData.put(JKKChkMoveKikiConstCC.MOVE_KIKI_UM, JKKStrConst.CD_DIV_UM_NASHI);

		// 入力パラメータチェック処理
		String errMsg = chkInput(handle, param, trgtData);
		if (null != errMsg && !errMsg.isEmpty())
		{
			// チェックエラー
			throw new CCException(errMsg, new Exception());
		}

		// サービス契約番号
		String svcKeiNo = (String)trgtData.get(JKKChkMoveKikiConstCC.SVC_KEI_NO);

		// 住所変更明細一覧照会（変更前識別番号）
		CAANMsg[] msgEKK2101B002List = searchAdchgDtlListBySkbtNo(handle, param, fixedText, svcKeiNo);

		// 照会結果が0件の場合
		if (null == msgEKK2101B002List || msgEKK2101B002List.length == 0)
		{
			// 移動機器有無は「無」
			return param;
		}

		// 住所変更番号
		String adchgNo = msgEKK2101B002List[0].getString(EKK2101B002CBSMsg1List.ADCHG_NO);
		// 変更後識別番号(移転先サービス契約番号)
		String itensSvcKeiNo = msgEKK2101B002List[0].getString(EKK2101B001CBSMsg1List.CHAF_SKBT_NO);

		// 移転先サービス契約番号が設定されていない場合
		if (null == itensSvcKeiNo || itensSvcKeiNo.isEmpty())
		{
			// 移動機器有無は「無」
			return param;
		}

		// 住所変更明細一覧照会
		CAANMsg[] msgEKK2101B001List = searchAdchgDtlList(handle, param, fixedText, adchgNo);

		// 照会結果が0件の場合
		if (null == msgEKK2101B001List || msgEKK2101B001List.length == 0)
		{
			// 移動機器有無は「無」
			return param;
		}

		// 住所変更一意照会
		CAANMsg[] msgEKK2091A010List = searchAdchgList(handle, param, fixedText, adchgNo);

		// 照会結果が0件の場合
		if (null == msgEKK2091A010List || msgEKK2091A010List.length == 0)
		{
			// 移動機器有無は「無」
			return param;
		}

		// 移転先サービス契約回線内訳番号
		String itensSvcKeiKaisenUcwkNo = msgEKK2091A010List[0].getString(EKK2091A010CBSMsg1List.ITENS_SVKEI_KISUW_NO);

		// サービス契約_工事案件一覧照会(基本工事取得)
		CAANMsg[] msgEKU0081B020List = searchSvkeiKojiakList(handle, param, fixedText, itensSvcKeiNo, itensSvcKeiKaisenUcwkNo);

		// 照会結果が0件の場合
		if (null == msgEKU0081B020List || msgEKU0081B020List.length == 0)
		{
			// 移動機器有無は「無」
			return param;
		}

		// 移転先工事の工事案件番号
		String itensKojiakNo = "";
		// 住所変更明細一覧照会結果から移転先サービス契約に紐付く工事案件番号を取得する
		ADCHG_DTL_LOOP : for (CAANMsg msgEKK2101B001 : msgEKK2101B001List)
		{
			// 変更後識別番号(工事案件番号)
			String kojiakNo = msgEKK2101B001.getString(EKK2101B001CBSMsg1List.CHAF_SKBT_NO);

			for (CAANMsg msgEKU0081B020 : msgEKU0081B020List)
			{
				// 移転先サービス契約番号から取得したサービス契約_工事案件一覧照会結果の工事案件番号と一致する場合
				if (null != kojiakNo && kojiakNo.equals(msgEKU0081B020.getString(EKU0081B020CBSMsg1List.KOJIAK_NO)))
				{
					// 移転先工事の工事案件番号として保持
					itensKojiakNo = kojiakNo;
					break ADCHG_DTL_LOOP;
				}
			}
		}

		// IT1-2013-0000660 住変中の解約時に「工事案件番号は必ず入力してください」のエラーが発生 2013/03/27 START
		if (null == itensKojiakNo || itensKojiakNo.isEmpty())
		{
			// 移動機器有無は「無」
			return param;
		}
		// IT1-2013-0000660 住変中の解約時に「工事案件番号は必ず入力してください」のエラーが発生 2013/03/27 END

		// 工事案件対象宅内機器一覧照会
		CAANMsg[] msgEKU0141B010List = searchKjakTgTkkiki(handle, param, fixedText, itensKojiakNo);

		// 照会結果が0件の場合
		if (null == msgEKU0141B010List || msgEKU0141B010List.length == 0)
		{
			// 移動機器有無は「無」
			return param;
		}

		// 解約済以外機器提供サービス契約一覧照会（サービス契約番号）
		CAANMsg[] msgEKK0341B011List = searchKktkSvcKeiNotDslZm(handle, param, fixedText, svcKeiNo);

		// 照会結果が0件の場合
		if (null == msgEKK0341B011List || msgEKK0341B011List.length == 0)
		{
			// 移動機器有無は「無」
			return param;
		}

		// 工事案件対象宅内機器一覧照会の件数分ループ
		KJAK_TG_TKKIKI_LOOP : for (int i = 0; i < msgEKU0141B010List.length; i++)
		{
			String taknkikiIdoCd = msgEKU0141B010List[i].getString(EKU0141B010CBSMsg1List.TAKNKIKI_IDO_CD);
			String kktkSvcKeiNo = msgEKU0141B010List[i].getString(EKU0141B010CBSMsg1List.KKTK_SVC_KEI_NO);
			// 宅内機器異動コードが「移動」の場合
			if (JKKStrConst.CD00562_MOVE.equals(taknkikiIdoCd) && null != kktkSvcKeiNo)
			{
				// 解約済以外機器提供サービス契約一覧照会の件数分ループ
				for (int j = 0; j < msgEKK0341B011List.length; j++)
				{
					String kktkSvcKeiNo2 = msgEKK0341B011List[j].getString(EKK0341B011CBSMsg1List.KKTK_SVC_KEI_NO);
					// 機器提供サービス契約番号が一致した場合
					if (kktkSvcKeiNo.equals(kktkSvcKeiNo2))
					{
						// 移動機器有無は「有」
						trgtData.put(JKKChkMoveKikiConstCC.MOVE_KIKI_UM, JKKStrConst.CD_DIV_UM_ARI);
						break KJAK_TG_TKKIKI_LOOP;
					}
				}
			}
		}

		return param;
	}

	/**
	 * 入力パラメータのチェックを行います。
	 * <br>
	 * @param handle セッションマネージャなどを持ったハンドル
	 * @param param モデルグループ、コントロールマップを含むパラメータオブジェクト
	 * @param trgtData 対象データ
	 * @return エラーメッセージ
	 */
	@SuppressWarnings("unchecked")
	private String chkInput(SessionHandle handle, IRequestParameterReadWrite param, HashMap trgtData)
	{
		// 必須チェック
		String svcKeiNo = (String)trgtData.get(JKKChkMoveKikiConstCC.SVC_KEI_NO);
		if (null == svcKeiNo || svcKeiNo.isEmpty())
		{
			return ERR_MSG_PARAM + "サービス契約番号が設定されていません。";
		}

		// チェックOK
		return "";
	}

	/**
	 * 住所変更明細一覧照会（変更前識別番号）サービスインターフェースを呼び出します。
	 * <br>
	 * @param handle セッションマネージャなどを持ったハンドル
	 * @param param モデルグループ、コントロールマップを含むパラメータオブジェクト
	 * @param fixedText ユーザ任意文字列
	 * @param svcKeiNo サービス契約番号
	 * @return 住所変更明細一覧照会（変更前識別番号）結果
	 * @throws Throwable 例外が発生した場合
	 */
	private CAANMsg[] searchAdchgDtlListBySkbtNo(SessionHandle handle, IRequestParameterReadWrite param, String fixedText, String svcKeiNo)
	throws Throwable
	{
		// 上りマッピング処理
		HashMap<String, Object> inMap = this.mapper.editInMsgEKK2101B002(param, svcKeiNo);
		// サービスインターフェース呼び出し
		CAANMsg rsltMsg = callSvcInter(handle, param, fixedText, inMap, new EKK2101B002CBSMsg().getContents());

		return rsltMsg.getCAANMsgList(EKK2101B002CBSMsg.EKK2101B002CBSMSG1LIST);
	}

	/**
	 * 住所変更明細一覧照会サービスインターフェースを呼び出します。
	 * <br>
	 * @param handle セッションマネージャなどを持ったハンドル
	 * @param param モデルグループ、コントロールマップを含むパラメータオブジェクト
	 * @param fixedText ユーザ任意文字列
	 * @param adchgNo 住所変更番号
	 * @return 住所変更明細一覧照会結果
	 * @throws Throwable 例外が発生した場合
	 */
	private CAANMsg[] searchAdchgDtlList(SessionHandle handle, IRequestParameterReadWrite param, String fixedText, String adchgNo)
	throws Throwable
	{
		// 上りマッピング処理
		HashMap<String, Object> inMap = this.mapper.editInMsgEKK2101B001(param, adchgNo);
		// サービスインターフェース呼び出し
		CAANMsg rsltMsg = callSvcInter(handle, param, fixedText, inMap, new EKK2101B001CBSMsg().getContents());

		return rsltMsg.getCAANMsgList(EKK2101B001CBSMsg.EKK2101B001CBSMSG1LIST);
	}

	/**
	 * 住所変更一意照会サービスインターフェースを呼び出します。
	 * <br>
	 * @param handle セッションマネージャなどを持ったハンドル
	 * @param param モデルグループ、コントロールマップを含むパラメータオブジェクト
	 * @param fixedText ユーザ任意文字列
	 * @param adchgNo 住所変更番号
	 * @return 住所変更一覧照会結果
	 * @throws Throwable 例外が発生した場合
	 */
	private CAANMsg[] searchAdchgList(SessionHandle handle, IRequestParameterReadWrite param, String fixedText, String adchgNo)
	throws Throwable
	{
		// 上りマッピング処理
		HashMap<String, Object> inMap = this.mapper.editInMsgEKK2091A010(param, adchgNo);
		// サービスインターフェース呼び出し
		CAANMsg rsltMsg = callSvcInter(handle, param, fixedText, inMap, new EKK2091A010CBSMsg().getContents());

		return rsltMsg.getCAANMsgList(EKK2091A010CBSMsg.EKK2091A010CBSMSG1LIST);
	}

	/**
	 * サービス契約_工事案件一覧照会(基本工事取得)サービスインターフェースを呼び出します。
	 * <br>
	 * @param handle セッションマネージャなどを持ったハンドル
	 * @param param モデルグループ、コントロールマップを含むパラメータオブジェクト
	 * @param fixedText ユーザ任意文字列
	 * @param svcKeiNo サービス契約番号
	 * @param svcKeiKaisenUcwkNo サービス契約回線内訳番号
	 * @return 住所変更一覧照会結果
	 * @throws Throwable 例外が発生した場合
	 */
	private CAANMsg[] searchSvkeiKojiakList(SessionHandle handle, IRequestParameterReadWrite param, String fixedText,
		String svcKeiNo, String svcKeiKaisenUcwkNo)
	throws Throwable
	{
		// 上りマッピング処理
		HashMap<String, Object> inMap = this.mapper.editInMsgEKU0081B020(param, svcKeiNo, svcKeiKaisenUcwkNo);
		// サービスインターフェース呼び出し
		CAANMsg rsltMsg = callSvcInter(handle, param, fixedText, inMap, new EKU0081B020CBSMsg().getContents());

		return rsltMsg.getCAANMsgList(EKU0081B020CBSMsg.EKU0081B020CBSMSG1LIST);
	}

	/**
	 * 工事案件対象宅内機器一覧照会サービスインターフェースを呼び出します。
	 * <br>
	 * @param handle セッションマネージャなどを持ったハンドル
	 * @param param モデルグループ、コントロールマップを含むパラメータオブジェクト
	 * @param fixedText ユーザ任意文字列
	 * @param kojiakNo 工事案件番号
	 * @return 工事案件対象宅内機器一覧照会結果
	 * @throws Throwable 例外が発生した場合
	 */
	private CAANMsg[] searchKjakTgTkkiki(SessionHandle handle, IRequestParameterReadWrite param, String fixedText, String kojiakNo)
	throws Throwable
	{
		// 上りマッピング処理
		HashMap<String, Object> inMap = this.mapper.editInMsgEKU0141B010(param, kojiakNo);
		// サービスインターフェース呼び出し
		CAANMsg rsltMsg = callSvcInter(handle, param, fixedText, inMap, new EKU0141B010CBSMsg().getContents());

		return rsltMsg.getCAANMsgList(EKU0141B010CBSMsg.EKU0141B010CBSMSG1LIST);
	}

	/**
	 * 解約済以外機器提供サービス契約一覧照会（サービス契約番号）サービスインターフェースを呼び出します。
	 * <br>
	 * @param handle セッションマネージャなどを持ったハンドル
	 * @param param モデルグループ、コントロールマップを含むパラメータオブジェクト
	 * @param fixedText ユーザ任意文字列
	 * @param svcKeiNo サービス契約番号
	 * @return 工事案件対象宅内機器一覧照会結果
	 * @throws Throwable 例外が発生した場合
	 */
	private CAANMsg[] searchKktkSvcKeiNotDslZm(SessionHandle handle, IRequestParameterReadWrite param, String fixedText, String svcKeiNo)
	throws Throwable
	{
		// 上りマッピング処理
		HashMap<String, Object> inMap = this.mapper.editInMsgEKK0341B011(param, svcKeiNo);
		// サービスインターフェース呼び出し
		CAANMsg rsltMsg = callSvcInter(handle, param, fixedText, inMap, new EKK0341B011CBSMsg().getContents());

		return rsltMsg.getCAANMsgList(EKK0341B011CBSMsg.EKK0341B011CBSMSG1LIST);
	}

	/*
	 * --------------------------------------------------------------------------------------------
	 *  以下共通で使用するUtil系のメソッド ↓↓↓↓↓
	 * --------------------------------------------------------------------------------------------
	 */

	/**
	 * サービスインターフェース呼び出し処理です。
	 * <br>
	 * @param handle セッションマネージャなどを持ったハンドル
	 * @param param モデルグループ、コントロールマップを含むパラメータオブジェクト
	 * @param fixedText ユーザ任意文字列
	 * @param siInMap サービスインターフェースの入力マップ
	 * @param contents サービスインターフェースのテンプレート項目の配列
	 * @return 業務データ
	 * @throws Throwable 
	 */
	private CAANMsg callSvcInter(
			SessionHandle handle,
			IRequestParameterReadWrite param,
			String fixedText,
			HashMap<String, Object> siInMap,
			Object[][] contents)
			throws Throwable
	{
		
		// サービスインターフェースの呼び出し
		Map<?, ?> rsltMap = this.scCall.run(siInMap, handle);
		// エラーマッピング処理
		this.mapper.editResultRP(rsltMap, param, fixedText, contents);
		// エラーチェック処理
		errChk(rsltMap);
		// 業務データ取得処理
		CAANMsg workData = getWorkCAANMsg(rsltMap);

		return workData;
	}

	/**
	 * エラーチェック処理です。
	 * <br>
	 * @param msgList サービスインタフェース実行結果
	 * @throws SCCallException 
	 */
	private void errChk(
			Map<?, ?> msgList) 
			throws SCCallException
	{
		CAANMsg[] templates = (CAANMsg[])msgList.get(JCMConstants.TEMPLATE_LIST_KEY);
		CAANMsg template = templates[0];

		// リターンコード取得
		Integer returnCode = (Integer)msgList.get(JCMConstants.RET_CD_INT_KEY);
		
		// ステータス取得
		int templateStatus = template.getInt(JCMConstants.STATUS_INT_KEY);
		
		if ((0 != returnCode.intValue()) || (0 != templateStatus))
		{
			String errMsg = ERR_MSG;
			throw new SCCallException(errMsg, String.valueOf(returnCode), templateStatus);
		}
	}

	/**
	 * 業務データの取得処理です。
	 * <br>
	 * @param workMapKey 業務データのマップキー
	 * @param rslt SVIFの実行結果データ
	 * @return 業務データ
	 */
	private CAANMsg getWorkCAANMsg(Map<?, ?> rslt)
	{
		CAANMsg[] templates = (CAANMsg[])rslt.get(JCMConstants.TEMPLATE_LIST_KEY);
		CAANMsg parentTemplate = templates[0];

		return parentTemplate;
	}

	/**
	 * ユーザ定義文字列がユーザ情報になければデータを作成します。 <br>
	 * 
	 * @param param 業務データ取得用I/F
	 * @param workMapKey 業務データのマップキー
	 * @return true：作成した　False：存在していたため作成不要
	 * @throws RequestParameterException
	 */
	private boolean createUserData(IRequestParameterReadWrite param, String workMapKey)
			throws RequestParameterException
	{
		if (param.getData(workMapKey) == null)
		{
			param.setData(workMapKey, new HashMap<String, Object>());
			return true;
		}

		return false;
	}
}
