/*******************************************************************************
*	All Rights reserved,Copyright (c) K-Opticom
********************************************************************************
*＜プログラム内容＞
*	システム名		：eo顧客基幹システム
*	モジュール名	：JEKK0111C011TPMA
*	ソースファイル名：JEKK0111C012TPMA.java
*	作成者			：EKek0043
*	日付			：2011年10月25日
*＜機能概要＞
*	PPP認証ID採番顧客独自処理部品です。
*＜修正履歴＞
*	バージョン	修正日		修正者		修正内容
*	ｖ1.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.EKK0111C011CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK0111C011CBSMsg1List;
import eo.ejb.common.edit.JKKejbKK0111NumberParts;

/**
 * <p>
 * PPP認証ID採番顧客独自処理部品クラスです。
 * </p>
 * @author 富士通
 */
public class JEKK0111C011TPMA implements TemplateMainHandler
{

	/** PPP認証ID採番区分（PPP認証ID／PWD共に採番） */
	private static final String PPP_NINSHO_KBN_BOTH = "00";

	/** PPP認証ID採番区分（PPP認証IDのみを採番） */
	private static final String PPP_NINSHO_KBN_ID = "01";

	/** PPP認証ID採番区分（PPP認証IDPWDのみを採番） */
	private static final String PPP_NINSHO_KBN_PWD = "02";

	/** PPP認証ID採番区分既定用MAP */
	private static final HashMap<String, String> PPP_MAP = new HashMap<String, String>();

	static
	{
		PPP_MAP.put(PPP_NINSHO_KBN_BOTH, PPP_NINSHO_KBN_BOTH);
		PPP_MAP.put(PPP_NINSHO_KBN_ID, PPP_NINSHO_KBN_ID);
		PPP_MAP.put(PPP_NINSHO_KBN_PWD, PPP_NINSHO_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";

	/**
	 * PPP認証ID採番顧客独自処理。
	 * 
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 */
	public void invoke(CAANMsg inCBSMsg, AgentDispatchContext inContext)
	{
		JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), "Call");

		// 採番処理を行う
		execNumberParts(inCBSMsg, inContext);

		JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), "End");
	}

	/**
	 * 採番処理を行う。
	 * 
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 */
	public void execNumberParts(CAANMsg inCBSMsg, AgentDispatchContext inContext)
	{
		// パラメータのチェックを行う
		if (!isParamCheck(inCBSMsg, inContext))
		{
			// パラメータが不正の場合は処理を終了する
			return;
		}

		// 採番数の取得
		int npNum = inCBSMsg.getStringAsInt(EKK0111C011CBSMsg.NP_NUM);

		// 結果設定用メッセージの設定
		CAANMsg[] outMsg1 = new CAANMsg[npNum];
		
		// 指定された採番数分処理を行う
		for (int i = 0; i < npNum; i++)
		{
			// PPP認証ID用変数の設定
			String pppId = null;

			// PPP認証ID採番区分が、「PPP認証ID／PWD共に採番」または「PPP認証IDのみを採番」の場合のみ採番を行う
			if (PPP_NINSHO_KBN_BOTH.equals(inCBSMsg.getString(EKK0111C011CBSMsg.PPP_NINSHO_ID_KBN))
					|| PPP_NINSHO_KBN_ID.equals(inCBSMsg.getString(EKK0111C011CBSMsg.PPP_NINSHO_ID_KBN)))
			{
				// PPP認証IDの採番
				pppId = getPppNinshoId(inCBSMsg, inContext);

				// 採番された値がnullだった場合は処理を終了する
				if (pppId == null)
				{
					return;
				}
			}

			// PPP認証IDパスワード用変数の設定
			String pppPwd = null;

			// PPP認証ID採番区分が、「PPP認証ID／PWD共に採番」または「PPP認証IDPWDのみを採番」の場合のみ採番を行う
			if (PPP_NINSHO_KBN_BOTH.equals(inCBSMsg.getString(EKK0111C011CBSMsg.PPP_NINSHO_ID_KBN))
					|| PPP_NINSHO_KBN_PWD.equals(inCBSMsg.getString(EKK0111C011CBSMsg.PPP_NINSHO_ID_KBN)))
			{
				// PPP認証IDパスワードの採番
				pppPwd = getPppNinshoIdPwd(inCBSMsg, inContext);
	
				// 採番された値がnullだった場合は処理を終了する
				if (pppPwd == null)
				{
					return;
				}
			}
			
			// 採番した値の設定
			outMsg1[i] = new CAANMsg(EKK0111C011CBSMsg1List.class.getName());
			outMsg1[i].set(EKK0111C011CBSMsg1List.PPP_NINSHO_ID, pppId);
			outMsg1[i].set(EKK0111C011CBSMsg1List.PPP_NINSHO_ID_PWD, pppPwd);
		}

		// 結果をリストに設定する
		inCBSMsg.set(EKK0111C011CBSMsg.EKK0111C011CBSMSG1LIST, 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)
	{
		// PPP認証ID採番区分が設定されていない場合、コードを設定してfalseを返却する
		// 完了コード：パラメータエラー、詳細コード：必須パラメータなし
		if (inCBSMsg.isNull(EKK0111C011CBSMsg.PPP_NINSHO_ID_KBN))
		{
			setCdToMsg(inCBSMsg, FIN_CD_ERR_PARAM, DTL_CD_PARAM_ERR);
			return false;
		}

		// 採番数が設定されていない場合、コードを設定してfalseを返却する
		// 完了コード：パラメータエラー、詳細コード：必須パラメータなし
		if (inCBSMsg.isNull(EKK0111C011CBSMsg.NP_NUM))
		{
			setCdToMsg(inCBSMsg, FIN_CD_ERR_PARAM, DTL_CD_PARAM_ERR);
			return false;
		}

		// PPP認証ID採番区分が既定された値以外の場合、コードを設定してfalseを返却する
		// 完了コード：パラメータエラー、詳細コード：パラメータ指定不正
		if (!PPP_MAP.containsKey(inCBSMsg.getString(EKK0111C011CBSMsg.PPP_NINSHO_ID_KBN)))
		{
			setCdToMsg(inCBSMsg, FIN_CD_ERR_PARAM, DTL_CD_PARAM_ERR);
			return false;
		}

		return true;
	}

	/**
	 * PPP認証IDの採番を行います。
	 * 
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @return 採番されたPPP認証ID（採番部品でエラーが発生した場合はnull）。
	 */
	public String getPppNinshoId(CAANMsg inCBSMsg, AgentDispatchContext inContext)
	{
		// サービス契約採番部品クラス
		JKKejbKK0111NumberParts numPartsKK0111 = new JKKejbKK0111NumberParts();

		try 
		{
			// PPP認証ID採番処理の呼び出し
			return String.valueOf(numPartsKK0111.getPppNinshoId(inCBSMsg, inContext));
		}
		catch (JCCFrameworkException e1)
		{
			// Exception発生時は、既定の処理を行いnullを返却する
			execExceptionID(inCBSMsg, inContext, e1);
			return null;
		}
	}

	/**
	 * PPP認証IDパスワードの採番を行います。
	 * 
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @return 採番されたPPP認証IDパスワード（採番部品でエラーが発生した場合はnull）。
	 */
	public String getPppNinshoIdPwd(CAANMsg inCBSMsg, AgentDispatchContext inContext)
	{
		// サービス契約採番部品クラス
		JKKejbKK0111NumberParts numPartsKK0111 = new JKKejbKK0111NumberParts();

		try 
		{
			// PPP認証IDパスワード採番処理の呼び出し
			return String.valueOf(numPartsKK0111.getPppNinshoIdPwd(inCBSMsg, inContext));
		}
		catch (JCCFrameworkException e1)
		{
			// Exception発生時は、既定の処理を行いnullを返却する
			execExceptionPwd(inCBSMsg, inContext, e1);
			return null;
		}
	}

	/**
	 * PPP認証ID採番で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;
	}

	/**
	 * PPP認証IDパスワード採番で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(EKK0111C011CBSMsg.FIN_CD, finCd);
		inCBSMsg.set(EKK0111C011CBSMsg.DTL_CD, dtlCd);
	}

}