/*******************************************************************************
*	All Rights reserved,Copyright (c) K-Opticom
********************************************************************************
*＜プログラム内容＞
*	システム名		：eo顧客基幹システム
*	モジュール名	：JEKK0081C011TPMA
*	ソースファイル名：JEKK0081C011TPMA.java
*	作成者			：富士通
*	日付			：2011年10月25日
*＜機能概要＞
*	サービス契約番号採番の副次処理を呼び出す部品
*＜修正履歴＞
*	バージョン	修正日		修正者		修正内容
*	v1.00.00	2011/10/25	富士通		新規作成
*
********************************************************************************/

package eo.ejb.cbs.mainproc;

import java.sql.SQLException;
import java.util.HashMap;

import com.fujitsu.futurity.model.base.CAANMsg;
import com.fujitsu.futurity.model.ejb.common.JSYejbLog;
import com.fujitsu.futurity.model.ejb.common.fw.AgentDispatchContext;
import com.fujitsu.futurity.model.ejb.common.fw.TemplateMainHandler;

import eo.common.util.JCCFrameworkException;
import eo.ejb.cbs.cbsmsg.EKK0081C011CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK0081C011CBSMsg1List;
import eo.ejb.common.edit.JKKejbKK0081NumberParts;


/**
 * <p>
 * サービス契約番号採番の顧客独自処理部品クラスです。
 * </p>
 * @author 富士通
 */
public class JEKK0081C011TPMA implements TemplateMainHandler
{
	/** サービス契約番号採番区分（サービス契約番号／PWD共に採番） */
	private static final String SVC_KEI_KBN_BOTH = "00";

	/** サービス契約番号採番区分（サービス契約番号のみを採番） */
	private static final String SVC_KEI_KBN_ID = "01";

	/** サービス契約番号採番区分（サービス契約番号PWDのみを採番） */
	private static final String SVC_KEI_KBN_PWD = "02";

	/** サービス契約番号採番区分既定用MAP */
	private static final HashMap<String, String> SVC_MAP = new HashMap<String, String>();

	static
	{
		SVC_MAP.put(SVC_KEI_KBN_BOTH, SVC_KEI_KBN_BOTH);
		SVC_MAP.put(SVC_KEI_KBN_ID, SVC_KEI_KBN_ID);
		SVC_MAP.put(SVC_KEI_KBN_PWD, SVC_KEI_KBN_PWD);
	}

	/** 完了コード（正常終了） */
	private static final String FIN_CD_OK = "00";

	/** 完了コード（パラメータエラー） */
	private static final String FIN_CD_ERR_PARAM = "91";

	/** 完了コード（採番エラー） */
	private static final String FIN_CD_ERR_SAIBAN = "92";

	/** 完了コード（システムエラー） */
	private static final String FIN_CD_ERR_SYSTEM = "93";

	/** 詳細コード（正常終了） */
	private static final String DTL_CD_OK = "00000";

	/** 詳細コード（パラメータ指定不正） */
	private static final String DTL_CD_PARAM_ERR = "91002";

	/** 詳細コード（サービス契約番号枯渇(シーケンス枯渇)） */
	private static final String DTL_CD_ID_SEQ_OVER = "92001";

	/** 詳細コード（サービス契約番号PWD枯渇(シーケンス枯渇)） */
	private static final String DTL_CD_PWD_SEQ_OVER = "92002";

//	/** 詳細コード（チェックデジットエラー） */
//	private static final String DTL_CD_CHK_DIGI_ERR = "92003";
//
	/** ORACLEエラーコード（シーケンスエラー） */
	private static final String ORACLE_ERR_SEQ = "08004";

	
	/**
	 * <p>
	 * サービス契約番号採番の副次処理部品の呼び出しを行います。
	 * </p>
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	*/
	public void invoke(CAANMsg inCBSMsg, AgentDispatchContext inContext)
	{
		// 開始ログ出力
		JSYejbLog.println(JSYejbLog.DEBUG, getClass(), "call:JEKK0081C011TPMA#invoke");

		// 採番処理を行う
		execNumberParts(inCBSMsg, inContext);

		// 終了ログ出力
		JSYejbLog.println(JSYejbLog.DEBUG, getClass(), "end:JEKK0081C011TPMA#invoke");
	}
	
	/**
	 * 採番処理を行う。
	 * 
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 */
	public void execNumberParts(CAANMsg inCBSMsg, AgentDispatchContext inContext)
	{
		// パラメータのチェックを行う
		if (!isParamCheck(inCBSMsg, inContext))
		{
			// パラメータが不正の場合は処理を終了する
			return;
		}

		// 採番数の取得
		int npNum = inCBSMsg.getStringAsInt(EKK0081C011CBSMsg.NP_NUM);

		// 結果設定用メッセージの設定
		CAANMsg[] outMsg1 = new CAANMsg[npNum];
		
		// 指定された採番数分処理を行う
		for (int i = 0; i < npNum; i++)
		{
			// サービス契約番号用変数の設定
			String svcKeiNo = null;

			// サービス契約番号採番区分が、「サービス契約番号／PWD共に採番」または「サービス契約番号のみを採番」の場合のみ採番を行う
			if (SVC_KEI_KBN_BOTH.equals(inCBSMsg.getString(EKK0081C011CBSMsg.SVC_KEI_NO_KBN))
					|| SVC_KEI_KBN_ID.equals(inCBSMsg.getString(EKK0081C011CBSMsg.SVC_KEI_NO_KBN)))
			{
				// サービス契約番号の採番
				svcKeiNo = getSvcKeiNo(inCBSMsg, inContext);

				// 採番された値がnullだった場合は処理を終了する
				if (svcKeiNo == null)
				{
					return;
				}
			}

			// サービス契約番号ＰＷＤ用変数の設定
			String svcKeiPwd = null;

			// サービス契約番号採番区分が、「サービス契約番号／PWD共に採番」または「サービス契約番号PWDのみを採番」の場合のみ採番を行う
			if (SVC_KEI_KBN_BOTH.equals(inCBSMsg.getString(EKK0081C011CBSMsg.SVC_KEI_NO_KBN))
					|| SVC_KEI_KBN_PWD.equals(inCBSMsg.getString(EKK0081C011CBSMsg.SVC_KEI_NO_KBN)))
			{
				// サービス契約番号ＰＷＤの採番
				svcKeiPwd = getShkDfltPwd(inCBSMsg, inContext);
	
				// 採番された値がnullだった場合は処理を終了する
				if (svcKeiPwd == null)
				{
					return;
				}
			}
			
			// 採番した値の設定
			outMsg1[i] = new CAANMsg(EKK0081C011CBSMsg1List.class.getName());
			outMsg1[i].set(EKK0081C011CBSMsg1List.SVC_KEI_NO, svcKeiNo);
			outMsg1[i].set(EKK0081C011CBSMsg1List.SVC_KEI_NO_PWD, svcKeiPwd);
		}

		// 結果をリストに設定する
		inCBSMsg.set(EKK0081C011CBSMsg.EKK0081C011CBSMSG1LIST, outMsg1);

		// 処理が正常に終了した場合、コードを設定する
		// 完了コード：正常終了、詳細コード：正常終了
		setCdToMsg(inCBSMsg, FIN_CD_OK, DTL_CD_OK);
	}

	/**
	 * 入力パラメータのチェックを行います。
	 * 
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @return 入力パラメータが正常な場合true。不正な場合false。
	 * 			（不正：未入力、規定値以外の入力値）
	 */
	public boolean isParamCheck(CAANMsg inCBSMsg, AgentDispatchContext inContext)
	{
		// サービス契約番号採番区分が設定されていない場合、コードを設定してfalseを返却する
		// 完了コード：パラメータエラー、詳細コード：必須パラメータなし
		if (inCBSMsg.isNull(EKK0081C011CBSMsg.SVC_KEI_NO_KBN))
		{
			setCdToMsg(inCBSMsg, FIN_CD_ERR_PARAM, DTL_CD_PARAM_ERR);
			return false;
		}

		// 採番数が設定されていない場合、コードを設定してfalseを返却する
		// 完了コード：パラメータエラー、詳細コード：必須パラメータなし
		if (inCBSMsg.isNull(EKK0081C011CBSMsg.NP_NUM))
		{
			setCdToMsg(inCBSMsg, FIN_CD_ERR_PARAM, DTL_CD_PARAM_ERR);
			return false;
		}

		// サービス契約番号採番区分が既定された値以外の場合、コードを設定してfalseを返却する
		// 完了コード：パラメータエラー、詳細コード：パラメータ指定不正
		if (!SVC_MAP.containsKey(inCBSMsg.getString(EKK0081C011CBSMsg.SVC_KEI_NO_KBN)))
		{
			setCdToMsg(inCBSMsg, FIN_CD_ERR_PARAM, DTL_CD_PARAM_ERR);
			return false;
		}

		return true;
	}

	/**
	 * サービス契約番号の採番を行います。
	 * 
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @return 採番されたサービス契約番号（採番部品でエラーが発生した場合はnull）。
	 */
	public String getSvcKeiNo(CAANMsg inCBSMsg, AgentDispatchContext inContext)
	{
		// サービス契約採番部品クラス
		JKKejbKK0081NumberParts numPartsKK0081 = new JKKejbKK0081NumberParts();

		try 
		{
			// サービス契約番号採番処理の呼び出し
			HashMap<String, Object> rsltMap = (HashMap<String, Object>)numPartsKK0081.getSvcKeiNoSingle(inCBSMsg, inContext);
			if (null != rsltMap)
			{
				String svcKeiNo = (String)rsltMap.get("svc_kei_no");
				String finCd = (String)rsltMap.get("fin_cd");
				String dtlCd = (String)rsltMap.get("dtl_cd");
				if (null != svcKeiNo && !"".equals(svcKeiNo))
				{
					return svcKeiNo;
				}
				else
				{
					setCdToMsg(inCBSMsg, finCd, dtlCd);
				}
			}

			return null;
		}
		catch (JCCFrameworkException e1)
		{
			// Exception発生時は、既定の処理を行いnullを返却する
			execExceptionID(inCBSMsg, inContext, e1);
			return null;
		}
	}

	/**
	 * サービス契約番号ＰＷＤの採番を行います。
	 * 
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @return 採番されたサービス契約番号ＰＷＤ（採番部品でエラーが発生した場合はnull）。
	 */
	public String getShkDfltPwd(CAANMsg inCBSMsg, AgentDispatchContext inContext)
	{
		// サービス契約採番部品クラス
		JKKejbKK0081NumberParts numPartsKK0081 = new JKKejbKK0081NumberParts();

		try 
		{
			// 初期デフォルトパスワード採番処理の呼び出し
			return String.valueOf(numPartsKK0081.getShkDfltPwd(inCBSMsg, inContext));
		}
		catch (JCCFrameworkException e1)
		{
			// Exception発生時は、既定の処理を行いnullを返却する
			execExceptionPwd(inCBSMsg, inContext, e1);
			return null;
		}
	}

	/**
	 * サービス契約番号採番でException発生時の処理を行います。
	 * 
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @param e1 発生したException
	 */
	public void execExceptionID(CAANMsg inCBSMsg, AgentDispatchContext inContext, Exception e1)
	{
		// 対象のException内にSQLExceptionがあるかを判定する
		if (e1.getCause().getCause() instanceof SQLException)
		{
			// ORACLEエラーコードの取得
			String sqlErrCd = e1.getCause().getCause().getMessage().substring(4, 9);

			// ORACLEエラーコードの判定
			if (ORACLE_ERR_SEQ.equals(sqlErrCd))
			{
				// ORACLEエラーコードがシーケンスエラーの場合、コードを設定して処理を終了する
				// 完了コード：採番エラー、詳細コード：サービス契約番号枯渇(シーケンス枯渇)
				setCdToMsg(inCBSMsg, FIN_CD_ERR_SAIBAN, DTL_CD_ID_SEQ_OVER);
				return;	
			}
			else
			{
				// ORACLEエラーコードがシーケンスエラー以外の場合、コードを設定して処理を終了する
				// 完了コード：採番エラー、詳細コード：ORACLEエラーコード
				setCdToMsg(inCBSMsg, FIN_CD_ERR_SAIBAN, sqlErrCd);
				return;					
			}

		}

		// 対象のExceptionがSQLException以外の場合、コードを設定して処理を終了する
		// 完了コード：システムエラー、詳細コード：なし
		setCdToMsg(inCBSMsg, FIN_CD_ERR_SYSTEM, null);
		return;
	}

	/**
	 * サービス契約番号ＰＷＤ採番でException発生時の処理を行います。
	 * 
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @param e1 発生したException
	 */
	public void execExceptionPwd(CAANMsg inCBSMsg, AgentDispatchContext inContext, Exception e1)
	{
		// 対象のException内にSQLExceptionがあるかを判定する
		if (e1.getCause().getCause() instanceof SQLException)
		{
			// ORACLEエラーコードの取得
			String sqlErrCd = e1.getCause().getCause().getMessage().substring(4, 9);

			// ORACLEエラーコードの判定
			if (ORACLE_ERR_SEQ.equals(sqlErrCd))
			{
				// ORACLEエラーコードがシーケンスエラーの場合、コードを設定して処理を終了する
				// 完了コード：採番エラー、詳細コード：サービス契約番号PWD枯渇(シーケンス枯渇)
				setCdToMsg(inCBSMsg, FIN_CD_ERR_SAIBAN, DTL_CD_PWD_SEQ_OVER);
				return;	
			}
			else
			{
				// ORACLEエラーコードがシーケンスエラー以外の場合、コードを設定して処理を終了する
				// 完了コード：採番エラー、詳細コード：ORACLEエラーコード
				setCdToMsg(inCBSMsg, FIN_CD_ERR_SAIBAN, sqlErrCd);
				return;					
			}

		}

		// 対象のExceptionがSQLException以外の場合、コードを設定して処理を終了する
		// 完了コード：システムエラー、詳細コード：なし
		setCdToMsg(inCBSMsg, FIN_CD_ERR_SYSTEM, null);
		return;
	}

	/**
	 * 指定された完了コード、詳細コードをメッセージに設定する処理です。
	 * 
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param finCd 完了コード
	 * @param dtlCd 詳細コード
	 */
	public void setCdToMsg(CAANMsg inCBSMsg, String finCd, String dtlCd)
	{
		inCBSMsg.set(EKK0081C011CBSMsg.FIN_CD, finCd);
		inCBSMsg.set(EKK0081C011CBSMsg.DTL_CD, dtlCd);
	}

}
