/*********************************************************************
* All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*   システム名      ：eo顧客基幹システム
*   モジュール名    ：JKKInitialCostShokaiUtil
*   ソースファイル名：JKKInitialCostShokaiUtil.java
*   作成者          ：富士通
*   日付            ：2013年01月15日
*＜機能概要＞
*   初期費用一覧照会部品です。
*＜修正履歴＞
*   バージョン  修正日       修正者      修正内容
*   v1.00.00    2013/01/15   FJ          新規作成 ANK-1276-00-00
*
**********************************************************************/
package com.fujitsu.futurity.bp.custom.common;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

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 eo.common.constant.JKKFamiilyPackConst;
import eo.common.constant.JPCModelConstant;
import eo.ejb.cbs.cbsmsg.EKK0721A010CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK0721A010CBSMsg1List;
import eo.ejb.cbs.cbsmsg.EKK1021C011CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK1021C012CBSMsg;

/**
 * 初期費用一覧照会部品です。
 * <br>
 * @author 富士通
 */
@SuppressWarnings("unchecked")
public class JKKInitialCostShokaiUtil extends JKKBaseUtil
{

	/* ■□ 事務手数料判定SC ■□ */
	/** 初期費用一覧照会 事務手数料判定 テンプレートID*/
	private static final String TEMPLATE_ID_JIMU = "EKK1021C011";
	/** テンプレートID(事務手数料判定明細) */
	private static final String TEMPLATE_ID_JIMU_DETAIL = EKK1021C011CBSMsg.EKK1021C011CBSMSG1LIST;
	/** IN項目リスト(事務手数料判定) */
	private static final List<String> IN_COLUMN_LIST_JIMU =
			Arrays.asList(EKK1021C011CBSMsg.IDO_DIV, EKK1021C011CBSMsg.MSKM_PRC_GRP_CD, EKK1021C011CBSMsg.NET_DOJI_MSKM_UM,
					EKK1021C011CBSMsg.MSKM_PCRS_CD, EKK1021C011CBSMsg.KOJI_UM, EKK1021C011CBSMsg.OP_SVC_CD, EKK1021C011CBSMsg.WRIB_SVC_CD,
					EKK1021C011CBSMsg.ID_TCHISHO_CMS_UM, EKK1021C011CBSMsg.IDO_RSN_CD);
	/** 関連チェックエラー項目(事務手数料判定) */
	private static final String ERROR_COLUMN_JIMU = EKK1021C011CBSMsg.IDO_DIV_ERR;

	/* ■□ 工事費判定SC ■□ */
	/** 初期費用一覧照会 工事費判定 テンプレートID*/
	private static final String TEMPLATE_ID_KOJI = "EKK1021C012";
	/** テンプレートID(工事費判定明細) */
	private static final String TEMPLATE_ID_KOJI_DETAIL = EKK1021C012CBSMsg.EKK1021C012CBSMSG1LIST;
	/** IN項目リスト(工事費判定) */
	private static final List<String> IN_COLUMN_LIST_KOJI =
			Arrays.asList(EKK1021C012CBSMsg.IDO_DIV, EKK1021C012CBSMsg.MSKM_PRC_GRP_CD, EKK1021C012CBSMsg.BUNDLE_UM, EKK1021C012CBSMsg.TK_KIBO_EQUIP);
	/** 関連チェックエラー項目(工事費判定) */
	private static final String ERROR_COLUMN_KOJI = EKK1021C012CBSMsg.IDO_DIV_ERR;

	/* ■□ 一時支払料金一意照会SC ■□ */
	/** 初期費用一覧照会 一時支払料金一意照会 テンプレートID*/
	private static final String TEMPLATE_ID_ICHIJI = "EKK0721A010";
	/** テンプレートID(一時支払料金一意照会明細) */
	private static final String TEMPLATE_ID_ICHIJI_DETAIL = EKK0721A010CBSMsg.EKK0721A010CBSMSG1LIST;
	/** IN項目リスト(一時支払料金一意照会) */
	private static final List<String> IN_COLUMN_LIST_ICHIJI = Arrays.asList(EKK0721A010CBSMsg.KEY_TMP_PAY_PRC_NO);
	/** 関連チェックエラー項目(一時支払料金一意照会) */
	private static final String ERROR_COLUMN_ICHIJI = EKK0721A010CBSMsg.KEY_TMP_PAY_PRC_NO_ERR;

	/* ■□ XML関連 ■□ */
	/** 属性名 */
	private static final String QUERY_ATTR_NAME = "id";
	/** フロント用初期費用取得パラメータ定義ファイルパス取得キー */
	private static final String KEY_FUSERVICE_FILE_PATH = "FUSERVICE_INITIAL_COST_FILE_PATH";
	/** フロント用初期費用取得パラメータ定義ファイル */
	private static final String FUSERVICE_FILE_PATH = JCCBPCommon.getApplicationConst(KEY_FUSERVICE_FILE_PATH);
	/** ルートタグ */
	private static final String ROOT_TAG_NAME = "SERVICE";
	/** パスのセパレータ */
	private static final String SEP = "/";

	/** 初期費用取得検索キー (事務手数料/異動区分) */
	private static final String QUERY_JIM_IDO_DIV = "JIM_FEE/IDO_DIV";
	/** 初期費用取得検索キー (事務手数料/申込料金グループコード) */
	private static final String QUERY_JIM_MSKM_PRC_GRP_CD = "JIM_FEE/MSKM_PRC_GRP_CD";
	/** 初期費用取得検索キー (事務手数料/ネット同時申込有無) */
	private static final String QUERY_JIM_NET_DOJI_MSKM_UM = "JIM_FEE/NET_DOJI_MSKM_UM";
	/** 初期費用取得検索キー (事務手数料/申込料金コースコード) */
	private static final String QUERY_JIM_MSKM_PCRS_CD = "JIM_FEE/MSKM_PCRS_CD";
	/** 初期費用取得検索キー (事務手数料/工事有無) */
	private static final String QUERY_JIM_KOJI_UM = "JIM_FEE/KOJI_UM";
	/** 初期費用取得検索キー (事務手数料/オプションサービスコード) */
	private static final String QUERY_JIM_OP_SVC_CD = "JIM_FEE/OP_SVC_CD";
	/** 初期費用取得検索キー (事務手数料/割引サービスコード) */
	private static final String QUERY_JIM_WRIB_SVC_CD = "JIM_FEE/WRIB_SVC_CD";
	/** 初期費用取得検索キー (事務手数料/ID通知書手数料有無) */
	private static final String QUERY_JIM_ID_TCHISHO_CMS_UM = "JIM_FEE/ID_TCHISHO_CMS_UM";
	/** 初期費用取得検索キー (事務手数料/異動理由コード) */
	private static final String QUERY_JIM_IDO_RSN_CD = "JIM_FEE/IDO_RSN_CD";

	/** 初期費用取得検索キー(工事費/異動区分) */
	private static final String QUERY_KOJI_IDO_DIV = "KOJI_FEE/IDO_DIV";
	/** 初期費用取得検索キー(工事費/申込料金グループコード) */
	private static final String QUERY_KOJI_MSKM_PRC_GRP_CD = "KOJI_FEE/MSKM_PRC_GRP_CD";
	/** 初期費用取得検索キー(工事費/バンドル有無) */
	private static final String QUERY_KOJI_BUNDLE_UM = "KOJI_FEE/BUNDLE_UM";
	/** 初期費用取得検索キー(工事費/撤去希望設備) */
	private static final String QUERY_KOJI_TK_KIBO_EQUIP = "KOJI_FEE/TK_KIBO_EQUIP";

	/** 初期費用マッピング情報(事務手数料) */
	private static final String[][] QUERY_JIM_FEE =
			{ { QUERY_JIM_IDO_DIV, EKK1021C011CBSMsg.IDO_DIV }, { QUERY_JIM_MSKM_PRC_GRP_CD, EKK1021C011CBSMsg.MSKM_PRC_GRP_CD },
					{ QUERY_JIM_NET_DOJI_MSKM_UM, EKK1021C011CBSMsg.NET_DOJI_MSKM_UM }, { QUERY_JIM_MSKM_PCRS_CD, EKK1021C011CBSMsg.MSKM_PCRS_CD },
					{ QUERY_JIM_KOJI_UM, EKK1021C011CBSMsg.KOJI_UM }, { QUERY_JIM_OP_SVC_CD, EKK1021C011CBSMsg.OP_SVC_CD },
					{ QUERY_JIM_WRIB_SVC_CD, EKK1021C011CBSMsg.WRIB_SVC_CD }, { QUERY_JIM_ID_TCHISHO_CMS_UM, EKK1021C011CBSMsg.ID_TCHISHO_CMS_UM },
					{ QUERY_JIM_IDO_RSN_CD, EKK1021C011CBSMsg.IDO_RSN_CD } };

	/** 初期費用マッピング情報(工事費) */
	private static final String[][] QUERY_KOJI_FEE =
			{ { QUERY_KOJI_IDO_DIV, EKK1021C012CBSMsg.IDO_DIV }, { QUERY_KOJI_MSKM_PRC_GRP_CD, EKK1021C012CBSMsg.MSKM_PRC_GRP_CD },
					{ QUERY_KOJI_BUNDLE_UM, EKK1021C012CBSMsg.BUNDLE_UM }, { QUERY_KOJI_TK_KIBO_EQUIP, EKK1021C012CBSMsg.TK_KIBO_EQUIP } };

	/** OUT項目:事務手数料情報 */
	private static final String OUT_PARAM_JM_INFO = "jm_fee_info";
	/** OUT項目:工事費情報 */
	private static final String OUT_PARAM_KJ_INFO = "kj_fee_info";
	
	/**
	 * 初期費用一覧取得処理です。<br>
	 * 
	 * <br>
	 * @param handle セッションハンドル
	 * @param param リクエストパラメータ
	 * @param fixedText サービスメッセージ
	 * @return リクエストパラメータ管理クラス
	 * @throws Exception 例外
	 */
	public IRequestParameterReadWrite getResultData(SessionHandle handle, IRequestParameterReadWrite param, String fixedText) throws Exception
	{
		// ●サービスID取得
		String serviceId = null;
		if (((HashMap)param.getData(fixedText)).containsKey(JKKFamiilyPackConst.INITIAL_COST_KEY))
		{
			serviceId = (String)((HashMap)param.getData(fixedText)).get(JKKFamiilyPackConst.INITIAL_COST_KEY);
		}
		else
		{
			serviceId = param.getUsecaseID();
		}

		// サービスIDがない場合は処理を終了する
		if (null == serviceId || serviceId.length() == 0)
		{
			return param;
		}

		// 初期費用格納用マップ生成
		HashMap resMap = new HashMap();

		// ●フロント用共通関連チェック定義ファイル情報取得
		HashMap<String, String> xmlMap = getFUFeeParamDefinition(serviceId);
		if (null == xmlMap || 0 == xmlMap.size())
		{
			// 検索結果格納マップをリクエストパラメータ.ユーザデータに設定し返却する
			resMap.put(TEMPLATE_ID_ICHIJI_DETAIL, null);
			param.setData(fixedText, resMap);
			return param;
		}

		// 初期費用格納用リスト
		ArrayList resList = new ArrayList();

		// サービスIF実行結果リスト(事務手数料判定、工事費判定)
		ArrayList<HashMap> result = new ArrayList<HashMap>();

		// ユーザデータ取得
		HashMap dataMap = (HashMap)param.getData(fixedText);
		dataMap.remove(TEMPLATE_ID_JIMU_DETAIL);
		dataMap.remove(TEMPLATE_ID_KOJI_DETAIL);
		dataMap.remove(TEMPLATE_ID_ICHIJI_DETAIL);

		if (isExistsMapValue(xmlMap, QUERY_JIM_FEE))
		{
			// ●事務手数料判定 サービスIF実行
			// 上りマッピング
			setInMapJimuSearch(param, fixedText, xmlMap);
			// サービスIF実行
			executeSC(handle, param, fixedText, TEMPLATE_ID_JIMU, TEMPLATE_ID_JIMU_DETAIL, IN_COLUMN_LIST_JIMU, ERROR_COLUMN_JIMU);
			// 実行結果をサービスIF実行結果リストに保存
			dataMap = (HashMap)param.getData(fixedText);
			ArrayList<HashMap> resultList = setResultList(dataMap, TEMPLATE_ID_JIMU_DETAIL);
			result.addAll(resultList);
			resMap.put(OUT_PARAM_JM_INFO, resultList.get(0));
		}

		if (isExistsMapValue(xmlMap, QUERY_KOJI_FEE))
		{
			// ●工事費判定 サービスIF実行
			// 上りマッピング
			setInMapKojiSearch(param, fixedText, xmlMap);

			// サービスIF実行
			executeSC(handle, param, fixedText, TEMPLATE_ID_KOJI, TEMPLATE_ID_KOJI_DETAIL, IN_COLUMN_LIST_KOJI, ERROR_COLUMN_KOJI);
			
			// 実行結果をサービスIF実行結果リストに保存
			dataMap = (HashMap)param.getData(fixedText);
			ArrayList<HashMap> resultList = setResultList(dataMap, TEMPLATE_ID_KOJI_DETAIL);
			result.addAll(resultList);
			resMap.put(OUT_PARAM_KJ_INFO, resultList.get(0));
		}

		// 事務手数料判定サービスI/Fの取得件数＋工事費判定サービスI/Fの取得件数分、処理を繰り返す
		for (int i = 0; i < result.size(); i++)
		{
			// 一時支払料金番号が設定されているか判定
			String keyTppn = null;
			if ((String)result.get(i).get(EKK0721A010CBSMsg1List.TMP_PAY_PRC_NO) != null)
			{
				// 事務手数料判定.一時支払料金番号、または、工事費判定.一時支払料金番号を設定
				keyTppn = (String)result.get(i).get(EKK0721A010CBSMsg1List.TMP_PAY_PRC_NO);
			}
			else
			{
				// 設定されていない場合、一時支払料金一意照会のサービスIFを実行しない
				continue;
			}

			// ●一時支払料金一意照会 サービスIF実行
			// 上りマッピング
			setInMapIchijiSearch(param, fixedText, keyTppn);
			// サービスIF実行
			executeSC(handle, param, fixedText, TEMPLATE_ID_ICHIJI, TEMPLATE_ID_ICHIJI_DETAIL, IN_COLUMN_LIST_ICHIJI, ERROR_COLUMN_ICHIJI);
			// 下りマッピング
			dataMap = setResultIchijiMapping((HashMap)param.getData(fixedText));

			// 初期費用リストに一時支払い料金情報を設定
			resList.addAll(setResultList(dataMap, TEMPLATE_ID_ICHIJI_DETAIL));
		}

		// 一時支払い料金情報がない場合、初期費用リストにNULLを設定
		if (resList.size() == 0)
		{
			resList = null;
		}

		// 検索結果格納マップをリクエストパラメータ.ユーザデータに設定し返却する
		resMap.put(TEMPLATE_ID_ICHIJI_DETAIL, resList);
		param.setData(fixedText, resMap);

		return param;
	}

	/**
	 * 初期費用一覧取得チェック処理です。
	 * 
	 * <br>
	 * @param handle セッションハンドル
	 * @param param リクエストパラメータ
	 * @param fixedText サービスメッセージ
	 * @return チェック処理用マップ
	 * @throws Exception 
	 */
	public HashMap<String, Object> getInvokeCBS(SessionHandle handle, IRequestParameterReadWrite param, String fixedText) throws Exception
	{
		return null;
	}

	/**
	 * 上りマッピングの項目設定(事務手数料判定)です。
	 * 
	 * <br>
	 * @param param リクエストパラメータ
	 * @param fixedText サービスメッセージ
	 * @param xmlMap XMLマップ情報
	 * @throws RequestParameterException
	 */
	private void setInMapJimuSearch(IRequestParameterReadWrite param, String fixedText, HashMap<String, String> xmlMap)
			throws RequestParameterException
	{
		// 機能コード設定(1:事務手数料判定結果取得)
		setFuncCode(param, fixedText, JPCModelConstant.FUNC_CD_1);

		// ユーザデータ取得
		HashMap inMap = (HashMap)param.getData(fixedText);
		for (int i = 0; i < QUERY_JIM_FEE.length; i++)
		{
			String value = xmlMap.get(QUERY_JIM_FEE[i][0]);
			if (!isNullOrEmpty(value))
			{
				inMap.put(QUERY_JIM_FEE[i][1], value);
			}
		}
	}

	/**
	 * 上りマッピングの項目設定(工事費判定)です。
	 * 
	 * <br>
	 * @param param リクエストパラメータ
	 * @param fixedText サービスメッセージ
	 * @param xmlMap XMLマップ情報
	 * @throws RequestParameterException
	 */
	private void setInMapKojiSearch(IRequestParameterReadWrite param, String fixedText, HashMap<String, String> xmlMap)
			throws RequestParameterException
	{
		// 機能コード設定(1:現工事費判定結果取得)
		setFuncCode(param, fixedText, JPCModelConstant.FUNC_CD_1);

		// ユーザデータ取得
		HashMap inMap = (HashMap)param.getData(fixedText);
		for (int i = 0; i < QUERY_KOJI_FEE.length; i++)
		{
			String value = xmlMap.get(QUERY_KOJI_FEE[i][0]);
			if (!isNullOrEmpty(value))
			{
				inMap.put(QUERY_KOJI_FEE[i][1], value);
			}
		}
	}

	/**
	 * 上りマッピングの項目設定(一時支払料金一意照会)です。
	 * 
	 * <br>
	 * @param param リクエストパラメータ
	 * @param fixedText サービスメッセージ
	 * @param keyTppn 一時支払料金番号
	 * @throws RequestParameterException
	 */
	private void setInMapIchijiSearch(IRequestParameterReadWrite param, String fixedText, String keyTppn) throws RequestParameterException
	{
		// 機能コード設定(1:一時支払料金一意照会)
		setFuncCode(param, fixedText, JPCModelConstant.FUNC_CD_1);

		// ユーザデータ取得
		HashMap inMap = (HashMap)param.getData(fixedText);
		inMap.put(EKK0721A010CBSMsg.KEY_TMP_PAY_PRC_NO, keyTppn);
	}

	/**
	 * 下りマッピングの項目設定(一時支払料金一意照会)です。
	 * 
	 * <br>
	 * @param inMap
	 * @return 下りマッピングの結果
	 * @throws RequestParameterException
	 */
	private HashMap setResultIchijiMapping(HashMap inMap) throws RequestParameterException
	{
		// 返却マップ
		HashMap resMap = new HashMap();
		// 返却リスト
		ArrayList resList = new ArrayList();
		// 一時リスト
		ArrayList childList = (ArrayList)(inMap.get(TEMPLATE_ID_ICHIJI_DETAIL));

		// マッピング
		for (int i = 0; i < childList.size(); i++)
		{
			HashMap childMap = (HashMap)childList.get(i);
			HashMap childResMap = new HashMap();
			childResMap.put(EKK0721A010CBSMsg1List.TMP_PAY_PRC_NM, (String)childMap.get(EKK0721A010CBSMsg1List.TMP_PAY_PRC_NM));
			childResMap.put(EKK0721A010CBSMsg1List.TMP_PAY_PRC_AMNT, (String)childMap.get(EKK0721A010CBSMsg1List.TMP_PAY_PRC_AMNT));
			resList.add(childResMap);
		}
		resMap.put(TEMPLATE_ID_ICHIJI_DETAIL, resList);
		return resMap;
	}

	/**
	 * 明細リスト内を検索します。
	 * 
	 * <br>
	 * @param dataMap
	 * @param listNm
	 * @return 検索結果リスト
	 */
	private ArrayList<HashMap> setResultList(HashMap dataMap, String listNm)
	{
		// 結果格納用リスト
		ArrayList<HashMap> resultList = new ArrayList<HashMap>();
		// リスト内検索
		ArrayList childList = (ArrayList)dataMap.get(listNm);
		if (childList != null)
		{
			for (int j = 0; j < childList.size(); j++)
			{
				HashMap childMap = (HashMap)childList.get(j);
				resultList.add(childMap);
			}
		}
		return resultList;
	}

	/**
	 * フロント用初期費用取得パラメータ定義ファイル取得処理
	 * 
	 * <br>
	 * @param usecaseID サービスID
	 * @return XML情報
	 * @throws ParserConfigurationException
	 * @throws SAXException
	 * @throws IOException
	 */
	private HashMap<String, String> getFUFeeParamDefinition(String usecaseID) throws ParserConfigurationException, SAXException, IOException
	{
		DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
		Document doc = builder.parse(new File(FUSERVICE_FILE_PATH));
		Element root = doc.getDocumentElement();
		NodeList svcList = root.getElementsByTagName(ROOT_TAG_NAME);
		HashMap<String, String> map = null;
		for (int i = 0; i < svcList.getLength(); i++)
		{
			Element svcElement = (Element)svcList.item(i);
			if (usecaseID.equals(svcElement.getAttribute(QUERY_ATTR_NAME)))
			{
				map = new HashMap<String, String>();
				getNodeValeInfo(svcElement, map, null);
				break;
			}
		}
		return map;
	}

	/**
	 * ノード情報取得処理
	 * 
	 * <br>
	 * @param node 対象ノード
	 * @param map XML情報格納
	 * @param key 検索キー
	 */
	private void getNodeValeInfo(Node node, HashMap<String, String> map, String key)
	{
		for (Node ch = node.getFirstChild(); ch != null; ch = ch.getNextSibling())
		{
			if (ch.getNodeType() == Node.ELEMENT_NODE)
			{
				getNodeValeInfo(ch, map, ch.getNodeName());
			}
			else if (ch.getNodeType() == Node.TEXT_NODE && 0 != ch.getNodeValue().trim().length())
			{
				String searchKey = getParentNodePath(ch);
				String value = ch.getNodeValue();
				map.put(searchKey, value);
			}
		}
	}

	/**
	 * ノードパス情報取得処理
	 * 
	 * <br>
	 * @param args 対象ノード
	 * @return 指定ルートからの現在のターゲットへのパス
	 */
	private String getParentNodePath(Node args)
	{
		String nodeName = null;
		Node ch = args;
		while (true)
		{
			if (null == ch.getParentNode())
			{
				break;
			}
			String nowNodeName = ch.getParentNode().getNodeName();
			if (ROOT_TAG_NAME.equals(nowNodeName))
			{
				break;
			}
			nodeName = (null == nodeName ? nowNodeName : nowNodeName + SEP + nodeName);
			ch = ch.getParentNode();
		}
		return nodeName;
	}

	/**
	 * null又は空文字かをチェックします。
	 * 
	 * <br>
	 * @param str 文字列
	 * @return true:null又は空文字、false:左記以外
	 */
	private static boolean isNullOrEmpty(String str)
	{
		return null == str || str.length() == 0;
	}

	/**
	 * Map情報に値が存在するかチェックします。
	 * 
	 * <br>
	 * @param map Map情報
	 * @param keyArray マップキー情報
	 * @return true:Map情報に値が存在する、false:左記以外
	 */
	private static boolean isExistsMapValue(HashMap<String, String> map, String[][] keyArray)
	{
		for (int i = 0; i < keyArray.length; i++)
		{
			String key = keyArray[i][0];
			if (isNullOrEmpty(map.get(key)))
			{
				return true;
			}
		}
		return false;
	}
}
