/*********************************************************************
* All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*   システム名      ：eo顧客基幹システム
*   モジュール名    ：JCN050InfoRefUpdCC
*   ソースファイル名：JCN050InfoRefUpdCC.java
*   作成者          ：富士通
*   日付            ：2013年02月06日
*＜機能概要＞
*  ０５０情報参照更新処理を行います。
*＜修正履歴＞
*   バージョン  修正日       修正者      修正内容
*   v5.00.00    2013/02/06   FJ)圓山     新規作成
*   v5.00.01    2013/06/05   FJ)木村     ANK-1539-00-00_無効化APIの複数回実行許容対策
*   v8.00.01    2013/12/17   FJ)味岡     ANK-1585-00-00_LC複数契約化に伴う仕様変更対応
*   v8.00.02    2014/02/10   FJ)高川     ANK-1585-01-00_L2-MVNO LC複数契約化 案件内部仕様変更
*
**********************************************************************/

package com.fujitsu.futurity.bp.custom.common;

import static eo.common.constant.JCNStrConst.*;
import static com.fujitsu.futurity.bp.custom.common.JCNDslCommonUtil.*;
import static com.fujitsu.futurity.bp.custom.common.JCNDslScParamHenshu.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.fujitsu.futurity.bp.custom.constant.CNSV0046_CNSV0046OP_CNSV004601CC;
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.IRequestParameterReadOnly;
import com.fujitsu.futurity.bp.x21.bpm.parameter.IRequestParameterReadWrite;
import com.fujitsu.futurity.bp.x21.cc.AbstractCommonComponent;
import com.fujitsu.futurity.bp.x21.cc.ICommonComponent;
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.JCNStrConst;
import eo.common.constant.JPCModelConstant;
import eo.ejb.cbs.cbsmsg.ECN0331A001CBSMsg;
import eo.ejb.cbs.cbsmsg.ECN0331A001CBSMsg1List;
import eo.ejb.cbs.cbsmsg.ECN0331C004CBSMsg;
import eo.ejb.cbs.cbsmsg.EZM0111B070CBSMsg;
import eo.ejb.cbs.cbsmsg.EZM0111B070CBSMsg1List;
import eo.ejb.cbs.cbsmsg.EZM0111C010CBSMsg;

import eo.ejb.cbs.cbsmsg.ECNA0080001CBSMsg;
import eo.ejb.common.JPCModelCommon;

/**
 * ０５０情報参照更新処理を行います。
 * <BR>
 * @ author 富士通
 *
 */
public class JCN050InfoRefUpdCC extends AbstractCommonComponent implements ICommonComponent
{

	// **************************************************************
	// クラス変数
	// **************************************************************
	String tranDiv = "";
	String inputContKeiNo = "";
	
	// **************************************************************
	// 定数
	// **************************************************************
	/** 共通コンポーネント名 */
	public static String ccName = "JCN050InfoRefUpdCC";
	
	// ------------------------------------------
	// 処理区分 
	// ------------------------------------------
	/** 処理区分：参照 */
	private static final String TRAN_DIV_SANSHO = "1";
	
	/** 処理区分：パスワード更新 */
	private static final String TRAN_DIV_PWD_UP = "2";
	
	/** 処理区分：050番号無効化 */
	private static final String  TRAN_DIV_MUKOUKA = "3";
	
	// ------------------------------------------
	// サービスマップ項目
	// ------------------------------------------
	/** サービスマップ項目名：SYSID */
	private static final String SVMAP_SYSID = "SYSID";

	/** サービスマップ項目名：コンテンツ契約番号 */
	private static final String SVMAP_CONT_KEI_NO = "CONT_KEI_NO";

	/** サービスマップ項目名：処理区分 */
	private static final String SVMAP_TRAN_DIV = "TRAN_DIV";
	
	// ------------------------------------------
	// コンテンツ契約内訳
	// ------------------------------------------
	/** コンテンツ契約内訳ステータス（解約済） */
	private static final String SVC_KEI_STAT_KAIYAKUZUMI = "910";
	
	// ------------------------------------------
	// テンプレートID
	// ------------------------------------------
	/** テンプレートID：コンテンツ契約050情報参照更新SC */
	private static final String TEMPLATE_CONT_KEI_050DATA_SELUPD = "ECNA0080001";
	
	/** テンプレートID：コンテンツ契約050電話番号内訳一意照会 */
	private static final String TEMPLATE_CONT_KEI_050TEL_UCHIWAKE1_SHOW = "ECN0331A001";
	
	/** テンプレートID：コンテンツ契約050電話番号内訳内容変更 */
	private static final String TEMPLATE_CONT_KEI_050TEL_UCHIWAKE_UPD = "ECN0331C004";
	
	/** テンプレートID：050番号エイジング一覧照会 */
	private static final String TEMPLATE_050TEL_AGING_ICHIRAN = "EZM0111B070";
	
	/** テンプレートID：エイジング対象使用終了 */
	private static final String TEMPLATE_AGING_USE_END = "EZM0111C010";

	// ------------------------------------------
	// 050アプリSIPユーザーパスワード発行処理
	// ------------------------------------------
	/** 乱数発生桁数（10桁） */
	private static final int RANDOM_LENGTH = 10;
	
	/** 変換配列 */
	private static final HashMap<String, String> CHANGE_DATA = new HashMap<String, String>();
	static
	{
		// 変換配列設定
		CHANGE_DATA.put("0", "kmnpqrstuv");
		CHANGE_DATA.put("1", "pqrstuvwxy");
		CHANGE_DATA.put("2", "tuvwxyzabc");
		CHANGE_DATA.put("3", "ijkmnpqrst");
		CHANGE_DATA.put("4", "cdefghijkm");
		CHANGE_DATA.put("5", "mnpqrstuvw");
		CHANGE_DATA.put("6", "abcdefghij");
		CHANGE_DATA.put("7", "stuvwxyzab");
		CHANGE_DATA.put("8", "hijkmnpqrs");
		CHANGE_DATA.put("9", "npqrstuvwx");
	}
	
	
	/**
	 * ０５０情報参照更新メイン処理を行います。
	 * <BR>
	 * @param handle セッションハンドル	
	 * @param param リクエストパラメータ
	 * @param fixedText サービスメッセージ
	 * @return リクエストパラメータ
	 * @throws Throwable
	 */
	@SuppressWarnings("unchecked")
	public IRequestParameterReadWrite execute050InfoRefUpd(SessionHandle handle, IRequestParameterReadWrite param, String fixedText) throws Throwable
	{
		// 入力パラメータ格納
		HashMap<String, Object> ccParam = (HashMap<String, Object>)param.getData(ccName);

		// 処理区分
		tranDiv = (String)ccParam.get(SVMAP_TRAN_DIV);
		
		// リターンコード初期化
		String rtnCd = DSL_NORMAL_END;

		// **************************************************
		// 内部で使用する変数の初期化
		// **************************************************
		String aplSetteStatCd = "";
		String telNo = "";
		String aplSipUserId = "";
		String aplSipUserPwd = "";
		String contUcwkStatusCd = "";
		String tanmt_use_model_sbt = "";
		
		// 返却パラメータ格納用マップ生成
		Map userResult = new HashMap();
		
		// コンテンツ契約内訳情報保持、格納用List
		List dataList = new ArrayList();

		// **************************************************
		// コンテンツ契約050情報参照更新SCの実行
		// **************************************************
		rtnCd = callInfoRefUpdSc(handle, param, ccParam);
		
		// リターンコードが00以外の場合はそのまま呼び出し元へ返却
		if (!JCNStrConst.API_RETURN_CD_00.equals(rtnCd))
		{
			editReturnValue(userResult, rtnCd, dataList);
			setResultUserData(param, ccName, userResult);
			return param;
		}
		
		// **************************************************
		// コンテンツ契約050電話番号内訳一意照会SCの実行
		// **************************************************
		// SC戻り値格納用Mapの初期化
		Map<?, ?> inMap = null;
		
		// パラメータのコンテンツ契約番号(カンマ区切り)を分割する
		inputContKeiNo = (String)ccParam.get(SVMAP_CONT_KEI_NO);
		String contKeiNo[] = inputContKeiNo.split(JCNStrConst.S_SEP_CAM);
		
		// 分割分の要素数分SCを実行、データ格納する
		for(int i = 0; i < contKeiNo.length; i++)
		{
			// SC実行
			Map<?, ?> result = callGetUcwkSc(handle, param, ccParam, contKeiNo[i]);
			
			// 処理結果の判定を行う。
			if (result == null)
			{
				// コンテンツ契約内訳データなしの場合は「50:該当050電話番号無しエラー」を設定
				rtnCd = JCNStrConst.API_RETURN_CD_50;
				editReturnValue(userResult, rtnCd, dataList);
				setResultUserData(param, ccName, userResult);
				return param;
			}
			else
			{
				rtnCd = getECN0331A001returnCd(result);
				if (!JCNStrConst.API_RETURN_CD_00.equals(rtnCd))
				{
					// リターンコードが00以外の場合は呼び出し元へ返却
					editReturnValue(userResult, rtnCd, dataList);
					setResultUserData(param, ccName, userResult);
					return param;
				}
			}
			
			// 戻り値から値を取得する。
			inMap = getResultMsgList(result, ECN0331A001CBSMsg.ECN0331A001CBSMSG1LIST)[0].getHashMap(); 
			
			// コンテンツ契約内訳レコード格納用Map
			Map recMap = new HashMap(); 
			
			// ------------------
			// 返却値の編集
			// ------------------
			aplSetteStatCd = (String)inMap.get(ECN0331A001CBSMsg1List.N_050APL_SETTE_STAT_CD);
			telNo = (String)inMap.get(ECN0331A001CBSMsg1List.N_050_TELNO);
			aplSipUserId = (String)inMap.get(ECN0331A001CBSMsg1List.N_050APL_SIP_USER_ID);
			aplSipUserPwd = (String)inMap.get(ECN0331A001CBSMsg1List.N_050APL_SIP_USER_PWD);
			contUcwkStatusCd = (String)inMap.get(ECN0331A001CBSMsg1List.CONT_KEI_UCWK_STAT);
			tanmt_use_model_sbt = JCNBPCommon.n_050apl_use_model_sbt_set((String)inMap.get(ECN0331A001CBSMsg1List.TANMT_USE_ENV_INFO));
			
			recMap.put(CNSV0046_CNSV0046OP_CNSV004601CC.N_050APL_SETTE_STAT_CD, aplSetteStatCd);
			recMap.put(CNSV0046_CNSV0046OP_CNSV004601CC.CONT_KEI_NO, contKeiNo[i]);
			recMap.put(CNSV0046_CNSV0046OP_CNSV004601CC.N_050_TELNO, telNo);
			recMap.put(CNSV0046_CNSV0046OP_CNSV004601CC.N_050APL_SIP_USER_ID, aplSipUserId);
			recMap.put(CNSV0046_CNSV0046OP_CNSV004601CC.N_050APL_SIP_USER_PWD, aplSipUserPwd);
			recMap.put(CNSV0046_CNSV0046OP_CNSV004601CC.CONT_KEI_UCWK_STAT, contUcwkStatusCd);
			recMap.put(CNSV0046_CNSV0046OP_CNSV004601CC.TANMT_DSP_MODEL_SBT, tanmt_use_model_sbt);
			dataList.add(recMap);
			
			// 処理区分が「無効化」且つ、コンテンツ契約内訳ステータスが解約済みの場合は、参照モードに読み替えて動作する。
			// ただし、リターンコードはこの切り替え動作が判別できるように専用の値を設定する。
			if(TRAN_DIV_MUKOUKA.equals(tranDiv) && SVC_KEI_STAT_KAIYAKUZUMI.equals(contUcwkStatusCd)){
				tranDiv = TRAN_DIV_SANSHO;
				rtnCd = "01";
			}
		}
		
		// **************************************************
		// SIPユーザIDパスワードの払い出し処理
		// **************************************************
		// 処理区分が[パスワード更新]の場合、パスワード採番処理
		if (TRAN_DIV_PWD_UP.equals(tranDiv))
		{
			// パスワード採番処理
			aplSipUserPwd = getPwd();
		}
		
		// **************************************************
		// コンテンツ契約050電話番号内訳内容変更
		// **************************************************
		// 処理区分が[参照]以外の場合は、コンテンツ契約内訳を編集し登録
		if (!TRAN_DIV_SANSHO.equals(tranDiv))
		{	
			// コンテンツ契約050電話番号内訳内容変更
			rtnCd = callUpdUcwkSc(handle, param, inMap, aplSipUserPwd);
			
			if (!JCNStrConst.API_RETURN_CD_00.equals(rtnCd))
			{
				// リターンコードが00以外の場合は呼び出し元へ返却
				editReturnValue(userResult, rtnCd, dataList);
				setResultUserData(param, ccName, userResult);
				return param;
			}
			
			// コンテンツ契約内訳内容変更が完了した時点で、設定したSIPユーザIDパスワードを返却値としてセット
			Map tempMap = new HashMap();
			tempMap = (Map)dataList.get(0);	// List格納の1つ目をListとして取得
			
			if(tempMap != null)
			{
				// 取得したListがNullでなければ払出したSIPユーザIDパスワードをセット
				tempMap.put(CNSV0046_CNSV0046OP_CNSV004601CC.N_050APL_SIP_USER_PWD, aplSipUserPwd);
				dataList.set(0, tempMap);		// dataListにtemplistを再格納
			}
		}

		// **************************************************
		// エイジングの更新
		// **************************************************
		// 処理区分が「050番号無効化」の場合は、以下の要領でエイジングを更新
		if (TRAN_DIV_MUKOUKA.equals(tranDiv))
		{
			// **********************************************
			// 050番号エイジング一覧照会SCの実行
			// **********************************************
			int status = 0;
			Map<?, ?> agingResult = callGetAgingSc(handle, param, inMap);
			
			// リターンコード、ステータス、検索エラーフラグの内容を見て処理結果の判定を行う。
			rtnCd = agingResult.get(JCMConstants.RET_CD_INT_KEY).toString();
			status = resultChkScStatus(agingResult);
			String errFlg = getResultString(agingResult, EZM0111B070CBSMsg.SEARCH_ERR_FLG);
			if (!("0".equals(rtnCd) && 0 == status) || JPCModelConstant.SEARCH_ERR_FLG_ZERO.equals(errFlg)) 
			{
				// リターンコードが0以外 or ステータスが0以外 or エラーフラグが1ならエラー
				printErrorLog("050番号エイジング一覧照会SCにてエラーが発生しました。" + "(KEY:N_050_TELNO=" + telNo
						+ " returnCd:" + rtnCd + " status:" + status + " errFlg:" + errFlg + ")");
				rtnCd = JCNStrConst.API_RETURN_CD_99;
			}
			else 
			{
				rtnCd = JCNStrConst.API_RETURN_CD_00;
			}
			
			if (!JCNStrConst.API_RETURN_CD_00.equals(rtnCd))
			{
				// リターンコードが00以外の場合は呼び出し元へ返却
				// Exception発生させてロールバック
				SCCallException scCallEx = new SCCallException("INVALID_RETURN_MESSAGE", rtnCd, status);
				throw scCallEx;
			}
			
			
			// **********************************************
			// エイジング対象使用終了SCの実行
			// **********************************************
			// 戻り値から値を取得する。
			Map<?, ?> agingInMap = getResultMsgList(agingResult, EZM0111B070CBSMsg.EZM0111B070CBSMSG1LIST)[0].getHashMap(); 
			
			agingResult = callUpdAgingSc(handle, param, agingInMap);
			
			// リターンコード、ステータスの内容を見て処理結果の判定を行う。
			status = resultChkScStatus(agingResult);
			if (!("0".equals(agingResult.get(JCMConstants.RET_CD_INT_KEY).toString()) && 0 == status)) 
			{
				printErrorLog("050番号エイジング一覧照会SCにてエラーが発生しました。" + "(KEY:N_050_TELNO=" + telNo + ")");
				rtnCd = JCNStrConst.API_RETURN_CD_99;
			}
			else 
			{
				rtnCd = JCNStrConst.API_RETURN_CD_00;
			}
			
			if (!JCNStrConst.API_RETURN_CD_00.equals(rtnCd))
			{
				// リターンコードが00以外の場合は呼び出し元へ返却
				// Exception発生させてロールバック
				SCCallException scCallEx = new SCCallException("INVALID_RETURN_MESSAGE", rtnCd, status);
				throw scCallEx;
			}
			
		}
		
		// 呼び出し元へ返却
		editReturnValue(userResult, rtnCd, dataList);
		setResultUserData(param, ccName, userResult);
		return param;
	}
	
	/**
	 * コンテンツ契約050情報参照更新SCを実行します。
	 * <BR>
	 * @param handle セッションハンドル
	 * @param param リクエストパラメータ
	 * @param ccPam CCパラメータ
	 * @return 処理結果
	 */
	private String callInfoRefUpdSc(SessionHandle handle, IRequestParameterReadWrite param ,Map<String, Object> ccParam) throws Throwable
	{
		// **************************************************
		// コンテンツ契約050情報参照更新SCの実行。
		// **************************************************
		 
		// リターンコード初期化
		String rtnCd = JCNStrConst.API_RETURN_CD_00;
		String templateId = TEMPLATE_CONT_KEI_050DATA_SELUPD;
		Map<Object, Object> paramIf = new HashMap<Object, Object>();
		
		// 入力SYSID
		paramIf.put(ECNA0080001CBSMsg.IN_SYS_ID , (String)ccParam.get(SVMAP_SYSID));
		
		// コンテンツ契約番号
		paramIf.put(ECNA0080001CBSMsg.CONT_KEI_NO, (String)ccParam.get(SVMAP_CONT_KEI_NO));
		
		// 処理区分
		paramIf.put(ECNA0080001CBSMsg.TRAN_DIV, (String)ccParam.get(SVMAP_TRAN_DIV));
		
		// SC呼出用パラメータ作成
		HashMap<String, Object> paramMap = createScParam(param, templateId, ECNA0080001CBSMsg.class , paramIf, "1");

		// SC呼出実行
		ServiceComponentRequestInvoker scCall = new ServiceComponentRequestInvoker();
		Map<?, ?> result = scCall.run(paramMap, handle);

		// 結果取得
		rtnCd = result.get(JCMConstants.RET_CD_INT_KEY).toString();
		int status = resultChkScStatus(result);
		
		// リターンコード、ステータスの内容を見て処理結果の判定を行う。
		if (!("0".equals(rtnCd) && 0 == status)) 
		{
			// リターンコード、ステータスが0でない場合、「エラーコード」を「結果コード」に変換
			rtnCd = this.rtnCdEdit(result);
		}
		else
		{
			rtnCd = JCNStrConst.API_RETURN_CD_00;
		}
		
		return rtnCd;
	}
	
	/**
	 * コンテンツ契約050電話番号内訳一意照会SCを実行します。
	 * <BR>
	 * @param handle セッションハンドル
	 * @param param リクエストパラメータ
	 * @param ccParam CCパラメータ
	 * @param CCパラメータより分割後のコンテンツ契約番号
	 * @return 処理結果
	 */
	private Map<?, ?> callGetUcwkSc(SessionHandle handle, IRequestParameterReadWrite param, Map<String, Object> ccParam, String contKeiNo) throws Throwable
	{
		// **************************************************
		// 上りマッピング
		// **************************************************
		String templateId = TEMPLATE_CONT_KEI_050TEL_UCHIWAKE1_SHOW;;
		Map<Object, Object> paramIf = new HashMap<Object, Object>();
		
		// KEY_SYSID
		paramIf.put(ECN0331A001CBSMsg.KEY_SYSID, (String)ccParam.get(SVMAP_SYSID));
		
		// KEY_コンテンツ契約番号
		paramIf.put(ECN0331A001CBSMsg.KEY_CONT_KEI_NO, contKeiNo);

		// SC呼出用パラメータ作成
		HashMap<String, Object> paramMap = createScParam(param, templateId, ECN0331A001CBSMsg.class ,paramIf, "1");

		// **************************************************
		// SC呼出実行                                     
		// **************************************************
		ServiceComponentRequestInvoker scCall = new ServiceComponentRequestInvoker();
		Map<?, ?> result = scCall.run(paramMap, handle);
		return result;
	}
	
	/**
	 * コンテンツ契約050電話番号内訳一意照会SCの処理結果を判定します。
	 * <BR>
	 * @param result コンテンツ契約050電話番号内訳一意照会SCの戻り値
	 * @return 処理結果
	 */
	private String getECN0331A001returnCd(Map<?, ?> result)
	{
		// 結果取得
		String rtnCd = result.get(JCMConstants.RET_CD_INT_KEY).toString();
		int status = resultChkScStatus(result);
		
		// 検索エラーフラグの取得
		CAANMsg[] templates = (CAANMsg[])result.get(JCMConstants.TEMPLATE_LIST_KEY);
		CAANMsg msg = templates[0];
		String serchErrFlg = msg.getString(ECN0331A001CBSMsg.SEARCH_ERR_FLG);
		
		// 該当データなしの場合は「52」該当契約番号なし
		if ("1".equals(serchErrFlg))
		{
			return JCNStrConst.API_RETURN_CD_50;
		}
		
		CAANMsg[] cbsMsgList = getResultMsgList(result, ECN0331A001CBSMsg.ECN0331A001CBSMSG1LIST); 
		
		if (!("0".equals(rtnCd) && 0 == status) || cbsMsgList.length == 0) 
		{
			printErrorLog("コンテンツ契約050電話番号内訳一意照会SCにてエラーが発生しました。");
			return JCNStrConst.API_RETURN_CD_99;			
		}
		else
		{
			rtnCd = JCNStrConst.API_RETURN_CD_00;
		}
		
		return rtnCd;
	}
	
	/**
	 * コンテンツ契約050電話番号内訳内容変更SCを実行します。
	 * <BR>
	 * @param handle セッションハンドル
	 * @param param リクエストパラメータ
	 * @param inMap パラメータ
	 * @param aplSipUserPwd パスワード
	 * @return 処理結果
	 */
	private String callUpdUcwkSc(SessionHandle handle, IRequestParameterReadWrite param ,Map<?,?> inMap, String aplSipUserPwd) throws Throwable
	{
		// リターンコード初期化
		String rtnCd = JCNStrConst.API_RETURN_CD_00;

		// **************************************************
		// 上りマッピング
		// **************************************************
		String templateId = TEMPLATE_CONT_KEI_050TEL_UCHIWAKE_UPD;
		Map<Object, Object> paramIf = new HashMap<Object, Object>();
		String mapKey = "";

		// コンテンツ契約内訳番号
		mapKey = ECN0331C004CBSMsg.CONT_KEI_UCWK_NO;
		paramIf.put(mapKey, (String)inMap.get(mapKey));

		// コンテンツ契約内訳ステータス
		mapKey = ECN0331C004CBSMsg.CONT_KEI_UCWK_STAT;
		paramIf.put(mapKey, (String)inMap.get(mapKey));
		if (TRAN_DIV_MUKOUKA.equals(tranDiv))
		{
			// 処理区分が[050番号無効化]の場合、コンテンツ契約内訳ステータス に「解約済」を設定
			paramIf.put(mapKey, SVC_KEI_STAT_KAIYAKUZUMI);
		} 
		
		// コンテンツ契約番号
		mapKey = ECN0331C004CBSMsg.CONT_KEI_NO;
		paramIf.put(mapKey, (String)inMap.get(mapKey));
		String contKeiNo = (String)inMap.get(mapKey);
		
		// SYSID
		mapKey = ECN0331C004CBSMsg.SYSID;
		paramIf.put(mapKey, (String)inMap.get(mapKey));
		
		// ０５０電話番号
		mapKey = ECN0331C004CBSMsg.N_050_TELNO;
		paramIf.put(mapKey, (String)inMap.get(mapKey));
		
		// ０５０アプリＳＩＰユーザーＩＤ
		mapKey = ECN0331C004CBSMsg.N_050APL_SIP_USER_ID;
		paramIf.put(mapKey, (String)inMap.get(mapKey));
		
		// ０５０アプリＳＩＰユーザーＩＤパスワード
		mapKey = ECN0331C004CBSMsg.N_050APL_SIP_USER_PWD;
		paramIf.put(mapKey, (String)inMap.get(mapKey));
		if (TRAN_DIV_PWD_UP.equals(tranDiv))
		{
			// 処理区分が[パスワード更新]の場合、パスワード設定
			paramIf.put(mapKey, aplSipUserPwd);
		}
		
		// ０５０アプリ設定状態コード
		mapKey = ECN0331C004CBSMsg.N_050APL_SETTE_STAT_CD;
		paramIf.put(mapKey, (String)inMap.get(mapKey));
		
		// ０５０アプリ払出依頼コード
		mapKey = ECN0331C004CBSMsg.N_050APL_HRADSI_REQ_CD;
		paramIf.put(mapKey, (String)inMap.get(mapKey));
		
		// ０５０電話番号払出種別コード
		mapKey = ECN0331C004CBSMsg.N_050_TELNO_HRADSI_SBT_CD;
		paramIf.put(mapKey, (String)inMap.get(mapKey));
		
		// サービス開始年月日時分秒
		mapKey = ECN0331C004CBSMsg.SVC_STA_DTM;
		paramIf.put(mapKey, (String)inMap.get(mapKey));
		
		// サービス終了年月日時分秒
		mapKey = ECN0331C004CBSMsg.SVC_END_DTM;
		paramIf.put(mapKey, (String)inMap.get(mapKey));
		if (TRAN_DIV_MUKOUKA.equals(tranDiv))
		{
			// 処理区分が[050番号無効化]の場合、オンライン運用日付を設定
			paramIf.put(mapKey, JCCBPCommon.getOpeDateTimeStamp( null));
		} 
		
		// ０５０アプリ本人確認用電話番号
		mapKey = ECN0331C004CBSMsg.N_050APL_HNIN_CFM_TELNO;
		paramIf.put(mapKey, (String)inMap.get(mapKey));
		
		// ０５０アプリ本人確認用電話番号取得年月日
		mapKey = ECN0331C004CBSMsg.N_050APL_HNCFM_TLN_STYMD;
		paramIf.put(mapKey, (String)inMap.get(mapKey));
		
		// 利用端末環境情報
		mapKey = ECN0331C004CBSMsg.TANMT_USE_ENV_INFO;
		paramIf.put(mapKey, (String)inMap.get(mapKey));
		
		// 利用端末環境情報取得年月日
		mapKey = ECN0331C004CBSMsg.TANMT_USE_ENV_INFO_STYMD;
		paramIf.put(mapKey, (String)inMap.get(mapKey));

		// 削除年月日時分秒
		mapKey = ECN0331C004CBSMsg.DEL_DTM;
		paramIf.put(mapKey, (String)inMap.get(mapKey));
		
		// 削除オペレータアカウント
		mapKey = ECN0331C004CBSMsg.DEL_OPEACNT;
		paramIf.put(mapKey, (String)inMap.get(mapKey));
		
		// 無効フラグ
		mapKey = ECN0331C004CBSMsg.MK_FLG;
		paramIf.put(mapKey, (String)inMap.get(mapKey));
		
		// SC呼出用パラメータ作成
		HashMap<String, Object> paramMap = createScParam(param, templateId, ECN0331C004CBSMsg.class, paramIf, "1");

		// SC呼出実行
		ServiceComponentRequestInvoker scCall = new ServiceComponentRequestInvoker();
		Map<?, ?> result = scCall.run(paramMap, handle);

		// 結果取得
		rtnCd = result.get(JCMConstants.RET_CD_INT_KEY).toString();
		int status = resultChkScStatus(result);
		
		// リターンコード、ステータスの内容を見て処理結果の判定を行う。
		if (!("0".equals(rtnCd) && 0 == status)) 
		{
			printErrorLog("コンテンツ契約050電話番号内訳内容変更SCにてエラーが発生しました。" 
							+ "(KEY:CONT_KEI_NO=" + contKeiNo + ")");
			return JCNStrConst.API_RETURN_CD_99;
		}
		else
		{
			rtnCd = JCNStrConst.API_RETURN_CD_00;
		}
		
		return rtnCd;
	}	
	
	/**
	 * 050番号エイジング一覧照会SCを実行します。
	 * <BR>
	 * @param handle セッションハンドル
	 * @param param リクエストパラメータ
	 * @param inMap パラメータ
	 * @return 処理結果
	 */
	private Map<?, ?> callGetAgingSc(SessionHandle handle, IRequestParameterReadWrite param, Map<?, ?> inMap) throws Throwable
	{

		// **************************************************
		// 上りマッピング
		// **************************************************
		String templateId = TEMPLATE_050TEL_AGING_ICHIRAN;
		Map<Object, Object> paramIf = new HashMap<Object, Object>();
		
		// 050電話番号(コンテンツ契約050電話番号内訳内容変更で取得した値)
		paramIf.put(EZM0111B070CBSMsg.KEY_N_050_TELNO, (String)inMap.get(ECN0331C004CBSMsg.N_050_TELNO));

		// エイジング種別コード(電話番号(050IP電話アプリ))
		paramIf.put(EZM0111B070CBSMsg.KEY_AGING_SBT_CD, JCNStrConst.CD00412_050TELNO);

		// SC呼出用パラメータ作成
		HashMap<String, Object> paramMap = createScParam(param, templateId, EZM0111B070CBSMsg.class ,paramIf, "1");

		// **************************************************
		// SC呼出実行                                     
		// **************************************************
		ServiceComponentRequestInvoker scCall = new ServiceComponentRequestInvoker();
		Map<?, ?> result = scCall.run(paramMap, handle);
		
		return result;
	}	
	
	/**
	 * エイジング対象使用終了SCを実行します。
	 * <BR>
	 * @param handle セッションハンドル
	 * @param param リクエストパラメータ
	 * @param inMap パラメータ
	 * @param telNo 050電話番号
	 * @return 処理結果
	 */
	private Map<?, ?> callUpdAgingSc(SessionHandle handle, IRequestParameterReadWrite param, Map<?, ?> inMap) throws Throwable
	{

		// **************************************************
		// 上りマッピング
		// **************************************************
		String templateId = TEMPLATE_AGING_USE_END;;
		Map<Object, Object> paramIf = new HashMap<Object, Object>();
		
		// エイジング番号
		paramIf.put(EZM0111C010CBSMsg.AGING_NO, (String)inMap.get(EZM0111B070CBSMsg1List.AGING_NO));

		// エイジング種別コード
		paramIf.put(EZM0111C010CBSMsg.AGING_SBT_CD, (String)inMap.get(EZM0111B070CBSMsg1List.AGING_SBT_CD));

		// エイジング対象値
		paramIf.put(EZM0111C010CBSMsg.AGING_TG_VALUE, (String)inMap.get(EZM0111B070CBSMsg1List.AGING_TG_VALUE));
		
		// 更新前最終年月日時分秒
		paramIf.put(EZM0111C010CBSMsg.LAST_UPD_DTM_BF, (String)inMap.get(EZM0111B070CBSMsg1List.UPD_DTM));
		
		// SC呼出用パラメータ作成
		HashMap<String, Object> paramMap = createScParam(param, templateId, EZM0111C010CBSMsg.class ,paramIf, "1");

		// **************************************************
		// SC呼出実行                                     
		// **************************************************
		ServiceComponentRequestInvoker scCall = new ServiceComponentRequestInvoker();
		Map<?, ?> result = scCall.run(paramMap, handle);
		
		return result;
	}

	/**
	 * SC呼出用のパラメータを作成します。
	 * <BR>
	 * @param param リクエストパラメータ
	 * @param templateId テンプレートID
	 * @param cbsMsgClass CBSMsgクラス
	 * @param param4serviceIf サービスインターフェイス用パラメータ
	 * @param funcCode 機能コード
	 * @return SC呼出用パラメータ
	 * @throws RequestParameterException
	 */
	@SuppressWarnings("unchecked")
	private static HashMap<String, Object> createScParam(IRequestParameterReadOnly param,
			String templateId, Class<?> cbsMsgClass , Map param4serviceIf, String funcCode) throws RequestParameterException
	{
		// 受け取ったリクエストパラメータを元に、ＳＣ呼出用の上りマップを生成
		HashMap<String, Object> paramMap = new HashMap<String, Object>();

		CAANMsg[] templates = new CAANMsg[1];
		CAANMsg template = new CAANMsg(cbsMsgClass.getName());

		// **********************************************
		// 【取得元：電文ヘッダ(ヘッダ)】
		// **********************************************
		// 電文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());

		// **********************************************
		// 【取得元：ユーザエリア(コントロールマップ)】
		// **********************************************
		// 依頼先ホスト名
		Object clientHostName = param.getControlMapData(SCControlMapKeys.REQ_HOSTNAME);
		paramMap.put(JCMConstants.CLIENT_HOST_NAME_KEY, clientHostName);

		// 依頼元IPアドレス
		Object clientIPAddress = param.getControlMapData(SCControlMapKeys.REQ_HOSTIP);
		paramMap.put(JCMConstants.CLIENT_IP_ADDRESS_KEY, clientIPAddress);

		// 依頼元画面ID
		Object clientViewId = param.getControlMapData(SCControlMapKeys.REQ_VIEWID);
		paramMap.put(JCMConstants.INVOKE_GAMEN_ID_KEY, clientViewId);

		// オペレータID
		Object operatorId = param.getControlMapData(SCControlMapKeys.OPERATOR_ID);
		paramMap.put(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);

		// **********************************************
		// 【取得元：ユーザデータ
		// **********************************************

		// テンプレートIDのセット
		paramMap.put(JCMConstants.TEMPLATE_ID_KEY, templateId);
		template.set(JCMConstants.TEMPLATE_ID_KEY, templateId);
		template.set(JCMConstants.FUNC_CODE_KEY, funcCode);
		
		setNullOtherColumn(cbsMsgClass, param4serviceIf);
		
		// 入力パラメータのセット
		template.setMsgDataOfAll((HashMap)param4serviceIf);
		templates[0] = template;

		paramMap.put("templates", templates);

		return paramMap;
	}
	
	/**
	 * 入力パラメータ値の指定がない項目にnullをセットします。
	 * <BR>
	 * @param cbsMsgClass CBSMsgクラス
	 * @param param4serviceIf サービスインターフェイス用パラメータ
	 */
	@SuppressWarnings("unchecked")
	public static void setNullOtherColumn(Class<?> cbsMsgClass, Map param4serviceIf) 
	{
		try 
		{
			java.lang.reflect.Field fieldContents = cbsMsgClass.getDeclaredField("CONTENTS");
			fieldContents.setAccessible(true);
			Object[][] contents = (Object[][])fieldContents.get(cbsMsgClass);

			// サービスインターフェイスの列情報を取得
			Map<String, String> colInfo = new HashMap<String, String>();
			for (int i = 0; i < contents.length; i++) 
			{
				Object[] obj = contents[i]; 
				colInfo.put(obj[0].toString(), obj[1].toString()); 
			}

			// エラーフィールド(項目末尾が"_err"の項目)の定義されている項目を入力項目と見なし
			// 当該フィールドについて、パラメータ値の指定がない場合は項nullをセットする
			for (int i = 0; i < contents.length; i++) 
			{
				Object[] obj = contents[i];
				String errFieldName = obj[0].toString(); 
				if (errFieldName.matches(".*_err$"))
				{
					String fieldName = errFieldName.replaceAll("_err$", ""); 
					String colDataType = colInfo.get(fieldName);
					if (("String".equals(colDataType))||("Long".equals(colDataType))) 
					{
						// 指定がない項目にnullをセット
						if (!param4serviceIf.containsKey(fieldName))
						{
							param4serviceIf.put(fieldName, null); 
						}
					}
				}
			}
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}	
	
	/**
	 * SC処理結果(ステータス)を取得します。
	 * <BR>
	 * @param result オブジェクト名
	 */
	private int resultChkScStatus(Map<?, ?> result)
	{
		CAANMsg[] templates = (CAANMsg[]) result.get(JCMConstants.TEMPLATE_LIST_KEY);
		CAANMsg msg = templates[0];
		return msg.getInt(JCMConstants.STATUS_INT_KEY);
	}
	
	/**
	 * 返却値を編集します。
	 * <BR>
	 * @param userResult 返却用Map
	 * @param returnCode 戻りコード
	 * @param aplSetteStatCd 050アプリ設定状態コード(配列形式)
	 * @param telNo 050電話番号(配列形式)
	 * @param aplSipUserId 050アプリSIPユーザID(配列形式)
	 * @param aplSipUserPwd 050アプリSIPユーザパスワード(配列形式)
	 */
	@SuppressWarnings("unchecked")
	private void editReturnValue(Map userResult, String returnCode, List dataList)
	{
		
		userResult.put(CNSV0046_CNSV0046OP_CNSV004601CC.RETURN_CODE, returnCode);

		// 戻りコードが00または01の場合のみ、戻りコード以外の返却値を設定する
		if (JCNStrConst.API_RETURN_CD_00.equals(returnCode) || "01".equals(returnCode))
		{
			userResult.put(CNSV0046_CNSV0046OP_CNSV004601CC.CONT_KEI_UCWK_LIST, dataList);
		}
	}
	
	/**
	 * リターンコードを設定します。
	 * <BR>
	 * @param map サービスIF処理結果
	 * @return rtnCd リターンコード
	 */
	private String rtnCdEdit(Map<?, ?> result)
	{
		String rtnCd = "";
		CAANMsg[] templates = (CAANMsg[]) result.get(JCMConstants.TEMPLATE_LIST_KEY);
		CAANMsg msg = templates[0];
		
		// エラー項目の抽出
		String sysIdErr = msg.getString(ECNA0080001CBSMsg.IN_SYS_ID_ERR);
		String contKeiNoErr = msg.getString(ECNA0080001CBSMsg.CONT_KEI_NO_ERR);
		String trainDivErr = msg.getString(ECNA0080001CBSMsg.TRAN_DIV_ERR);
		
		// SYSIDエラーチェック
		if (!isNullOrBlank(sysIdErr))
		{
			if ("E1".equals(sysIdErr))
			{
				return JCNStrConst.API_RETURN_CD_10;
			}
			if ("E2".equals(sysIdErr))
			{
				return JCNStrConst.API_RETURN_CD_12;
			}
			if ("E4".equals(sysIdErr))
			{
				return JCNStrConst.API_RETURN_CD_12;
			}
			if ("E3".equals(sysIdErr))
			{
				return JCNStrConst.API_RETURN_CD_11;
			}
			if ("EA".equals(sysIdErr))
			{
				return JCNStrConst.API_RETURN_CD_51;
			}
			if ("EB".equals(sysIdErr))
			{
				return JCNStrConst.API_RETURN_CD_50;
			}
		}
		
		// コンテンツ契約番号エラーチェック
		if (!isNullOrBlank(contKeiNoErr))
		{
			if ("E1".equals(contKeiNoErr))
			{
				return JCNStrConst.API_RETURN_CD_13;
			}
			if ("E3".equals(contKeiNoErr))
			{
				return JCNStrConst.API_RETURN_CD_14;
			}
			if ("E2".equals(contKeiNoErr))
			{
				return JCNStrConst.API_RETURN_CD_15;
			}
			if ("E4".equals(contKeiNoErr))
			{
				return JCNStrConst.API_RETURN_CD_15;
			}
			if ("EA".equals(contKeiNoErr))
			{
				return JCNStrConst.API_RETURN_CD_52;
			}
			if ("EB".equals(contKeiNoErr))
			{
				return JCNStrConst.API_RETURN_CD_50;
			}
		}
		
		// 処理区分エラーチェック
		if (!isNullOrBlank(trainDivErr))
		{
			if ("E1".equals(trainDivErr))
			{
				return JCNStrConst.API_RETURN_CD_16;
			}
			if ("E3".equals(trainDivErr))
			{
				return JCNStrConst.API_RETURN_CD_17;
			}
			if ("E2".equals(trainDivErr))
			{
				return JCNStrConst.API_RETURN_CD_18;
			}
			if ("E4".equals(trainDivErr))
			{
				return JCNStrConst.API_RETURN_CD_18;
			}
			if ("EA".equals(trainDivErr))
			{
				return JCNStrConst.API_RETURN_CD_52;
			}
		}
		
		return rtnCd;
	}	
		
	/**
     * null、空文字判定を行います。
	 * <BR>
     * @param strCheck 対象文字列
     * @return true :対象文字列がnullもしくは空文字、false:それ以外
     */
	private static boolean isNullOrBlank(String strCheck) 
	{
		// 対象文字列が対象文字列がnullもしくは空文字の場合、trueを返す
		return strCheck == null || S_BLANK.equals(strCheck);
	}	

	/**
	 * パスワード採番処理を行います。
	 * <BR>
	 * @return 採番した番号
	 */
	public String getPwd()
	{
		// 乱数を発生
		String random = JPCModelCommon.getRandomNumber(RANDOM_LENGTH);

		// 変換処理
		StringBuffer pwd = new StringBuffer();

		// (1)乱数の9桁目,10桁目を元に英小文字変換処理を呼び出す
		pwd.append(toAlphabetLower(random.substring(8, 9), random.substring(9, 10)));
		
		// (2)乱数の1桁目,10桁目の加算値の下1桁目を設定する
		pwd.append(toNumLastDigit(random.substring(0, 1), random.substring(9, 10)));
		
		// (3)乱数の3桁目,4桁目を元に英小文字変換処理を呼び出す
		pwd.append(toAlphabetLower(random.substring(2, 3), random.substring(3, 4)));
		
		// (4)乱数の9桁目を設定する
		pwd.append(random.substring(8, 9));
		
		// (5)乱数の8桁目を設定する
		pwd.append(random.substring(7, 8));
		
		// (6)乱数の5桁目,6桁目を元に英小文字変換処理を呼び出す
		pwd.append(toAlphabetLower(random.substring(4, 5), random.substring(5, 6)));
		
		// (7)乱数の2桁目,4桁目の加算値の下1桁目を設定する
		pwd.append(toNumLastDigit(random.substring(1, 2), random.substring(3, 4)));
		
		// (8)乱数の7桁目,8桁目を元に英小文字変換処理を呼び出す
		pwd.append(toAlphabetLower(random.substring(6, 7), random.substring(7, 8)));

		// パスワードとして返却する
		return pwd.toString();
	}	
	
	/**
	 * パスワード採番処理：変換元データから1文字の英小文字を取得して返します。
	 * <BR>
	 * @param str1 変換元データの１桁目
	 * @param str2 変換元データの２桁目
	 * @return 取得した英字
	 */
	private String toAlphabetLower(String str1, String str2)
	{
		// 変換元データの１桁目から、英字変換対象行を取得
		String chgStr = CHANGE_DATA.get(str1);

		// 変換元データの２桁目から、変換した英字を取得して返す
		return chgStr.substring(Integer.valueOf(str2), Integer.valueOf(str2) + 1);
	}
	
	/**
	 * <p>
	 * パスワード採番処理：数字を加算し、下１桁の値を返します。<br>
	 * </p>
	 * @param str1 変換元データの１桁目
	 * @param str2 変換元データの２桁目
	 * @return 変換した数字
	 */
	private String toNumLastDigit(String str1, String str2)
	{
		// 変換元データの１桁目と変換元データの２桁目を加算
		int total = Integer.valueOf(str1) + Integer.valueOf(str2);
		String totalStr = String.valueOf(total);

		if (totalStr.length() == 1)
		{
			// 加算値が１桁の数字のとき、そのまま返却
			return totalStr;
		}
		// 下一桁を返却
		return totalStr.substring(1, 2);
	}	
}
