/*******************************************************************************
*	All Rights reserved,Copyright (c) K-Opticom
********************************************************************************
*＜プログラム内容＞
*	システム名		：eo顧客基幹システム
*	モジュール名	：JEKK0081C015TPMA
*	ソースファイル名：JEKK0081C015TPMA.java
*	作成者			：富士通
*	日付			：2011年10月25日
*＜機能概要＞
*	整理番号番号採番の副次処理を呼び出す部品
*＜修正履歴＞
*	バージョン	修正日		修正者		修正内容
*	v1.00.00	2012/02/17	富士通		新規作成
*
********************************************************************************/

package eo.ejb.cbs.mainproc;

import java.util.ArrayList;

import com.fujitsu.futurity.model.base.CAANMsg;
import com.fujitsu.futurity.model.base.CAANRuntimeException;
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.ejb.cbs.cbsmsg.EKK0081C015CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK0081C015CBSMsg1List;
import eo.ejb.common.edit.JKKejbKK0081NumberParts;


/**
 * <p>
 * 整理番号採番の顧客独自処理部品クラスです。
 * </p>
 * @author 富士通
 */
public class JEKK0081C015TPMA implements TemplateMainHandler
{

	/** 完了コード（正常終了） */
	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_REQUIRED = "91001";
	
	/** 詳細コード（パラメータ指定不正） */
	private static final String DTL_CD_PARAM_ERR = "91002";

	/** 詳細コード（整理番号枯渇(連番枯渇)） */
	private static final String DTL_CD_ID_SEQ_OVER = "92001";
	
	/**
	 * <p>
	 * 整理番号採番の副次処理部品の呼び出しを行います。
	 * </p>
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	*/
	public void invoke(CAANMsg inCBSMsg, AgentDispatchContext inContext)
	{
		// 開始ログ出力
		JSYejbLog.println(JSYejbLog.DEBUG, getClass(), "call:JEKK0081C015TPMA#invoke");

		// 採番処理を行う
		execNumberParts(inCBSMsg, inContext);

		// 終了ログ出力
		JSYejbLog.println(JSYejbLog.DEBUG, getClass(), "end:JEKK0081C015TPMA#invoke");
	}
	
	/**
	 * 採番処理を行う。
	 * 
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 */
	private void execNumberParts(CAANMsg inCBSMsg, AgentDispatchContext inContext)
	{
		// パラメータのチェックを行う
		if (!isParamCheck(inCBSMsg, inContext))
		{
			// パラメータが不正の場合は処理を終了する
			// 採番数を設定する
			inCBSMsg.set(EKK0081C015CBSMsg.OUT_NP_NUM, "0");
			return;
		}

		// 採番数の取得
		int npNum = inCBSMsg.getStringAsInt(EKK0081C015CBSMsg.NP_NUM);
		// 初期eoID下10桁を取得
		String shk_eoid = inCBSMsg.getString(EKK0081C015CBSMsg.SHK_EOID).substring(2);

		// 整理番号枯渇用フラグ
		boolean kokatsu_err = true;
	
		try 
		{
			// サービス契約採番部品クラス
			JKKejbKK0081NumberParts numPartsKK0081 = new JKKejbKK0081NumberParts();

			// 整理番号最大値取得処理の呼び出し
			String maxSeiriNo =  numPartsKK0081.getMaxSeiriNo(inCBSMsg, inContext, shk_eoid);
			
			// 採番した整理番号格納用リスト
			ArrayList<String> seiriNoList = new ArrayList<String>();
	
			// 指定された採番数分処理を行う
			for (int i = 0; i < npNum; i++)
			{
				
				// 整理番号格納用
				String seiriNo = null;
				
				// 整理番号取得処理呼び出し
				seiriNo = numPartsKK0081.getSeiriNo(inCBSMsg, inContext, shk_eoid, maxSeiriNo, i + 1);
	
				// 既に整理番号最大値が"9999" or 加算された値が"10000"になった場合は採番出来たところまでを返却し、完了＆詳細コードも返却する
				if (seiriNo == null)
				{
					// 整理番号枯渇フラグにtrueを設定
					kokatsu_err = false;
					// 処理終了
					break;
				}
				
				// 採番できた整理番号をリストに保持する
				seiriNoList.add(seiriNo);
			}
			
			// 結果設定用メッセージの設定
			CAANMsg[] outMsg1 = new CAANMsg[seiriNoList.size()];
	
			// 取得できた整理番号の数分繰り返す
			for (int x = 0; x < seiriNoList.size(); x++)
			{
				// 採番した値の設定
				outMsg1[x] = new CAANMsg(EKK0081C015CBSMsg1List.class.getName());
				outMsg1[x].set(EKK0081C015CBSMsg1List.SEIRI_NO, seiriNoList.get(x));
			}
	
			// 結果をリストに設定する
			inCBSMsg.set(EKK0081C015CBSMsg.EKK0081C015CBSMSG1LIST, outMsg1);
	
			// 採番数を設定する
			inCBSMsg.set(EKK0081C015CBSMsg.OUT_NP_NUM, String.valueOf(outMsg1.length));
	
			// falseの場合は整理番号枯渇、trueの場合は正常終了
			if(!kokatsu_err) {
				// 完了コード：採番エラー、詳細コード：整理番号枯渇
				setCdToMsg(inCBSMsg, FIN_CD_ERR_SAIBAN, DTL_CD_ID_SEQ_OVER);
			} else {
				// 処理が正常に終了した場合、コードを設定する
				// 完了コード：正常終了、詳細コード：正常終了
				setCdToMsg(inCBSMsg, FIN_CD_OK, DTL_CD_OK);
			}
		}
		catch (CAANRuntimeException e1)
		{
			// Exception発生時は、既定の処理を行いnullを返却する
			execExceptionID(inCBSMsg, inContext, e1);

			// Exception発生時は無条件に採番数に0を設定する
			// 採番数を設定する
			inCBSMsg.set(EKK0081C015CBSMsg.OUT_NP_NUM, "0");
			return;
		}		

	}

	/**
	 * 入力パラメータのチェックを行います。
	 * 
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @return 入力パラメータが正常な場合true。不正な場合false。
	 * 			（不正：未入力、規定値以外の入力値）
	 */
	private boolean isParamCheck(CAANMsg inCBSMsg, AgentDispatchContext inContext)
	{
		// 初期ｅｏＩＤが設定されていない場合、コードを設定してfalseを返却する
		// 完了コード：パラメータエラー、詳細コード：必須パラメータなし
		if (inCBSMsg.isNull(EKK0081C015CBSMsg.SHK_EOID))
		{
			setCdToMsg(inCBSMsg, FIN_CD_ERR_PARAM, DTL_CD_PARAM_REQUIRED);
			return false;
		}

		// 採番数が設定されていない場合、コードを設定してfalseを返却する
		// 完了コード：パラメータエラー、詳細コード：必須パラメータなし
		if (inCBSMsg.isNull(EKK0081C015CBSMsg.NP_NUM))
		{
			setCdToMsg(inCBSMsg, FIN_CD_ERR_PARAM, DTL_CD_PARAM_REQUIRED);
			return false;
		}

		// 初期ｅｏＩＤが12桁以外の場合、コードを設定してfalseを返却する
		// 完了コード：パラメータエラー、詳細コード：パラメータ指定不正
		if (inCBSMsg.getString(EKK0081C015CBSMsg.SHK_EOID).length() != 12)
		{
			setCdToMsg(inCBSMsg, FIN_CD_ERR_PARAM, DTL_CD_PARAM_ERR);
			return false;
		}
		
		// 採番数が1桁〜4桁以外の場合、コードを設定してfalseを返却する
		// 完了コード：パラメータエラー、詳細コード：パラメータ指定不正
		if (!(inCBSMsg.getString(EKK0081C015CBSMsg.NP_NUM).length() > 0 && inCBSMsg.getString(EKK0081C015CBSMsg.NP_NUM).length() < 5))
		{
			setCdToMsg(inCBSMsg, FIN_CD_ERR_PARAM, DTL_CD_PARAM_ERR);
			return false;
		}

		// 初期ｅｏＩＤが半角英数字以外の場合、コードを設定してfalseを返却する
		// 完了コード：パラメータエラー、詳細コード：パラメータ指定不正
		if (!inCBSMsg.getString(EKK0081C015CBSMsg.SHK_EOID).matches("[a-zA-Z0-9]+"))
		{
			setCdToMsg(inCBSMsg, FIN_CD_ERR_PARAM, DTL_CD_PARAM_ERR);
			return false;
		}

		// 採番数が半角数字以外の場合、コードを設定してfalseを返却する
		// 完了コード：パラメータエラー、詳細コード：パラメータ指定不正
		if (!inCBSMsg.getString(EKK0081C015CBSMsg.NP_NUM).matches("[0-9]+"))
		{
			setCdToMsg(inCBSMsg, FIN_CD_ERR_PARAM, DTL_CD_PARAM_ERR);
			return false;
		}
		
		// 採番数が"0"の場合、コードを設定してfalseを返却する
		// 完了コード：パラメータエラー、詳細コード：パラメータ指定不正
		if (inCBSMsg.getString(EKK0081C015CBSMsg.NP_NUM).equals("0"))
		{
			setCdToMsg(inCBSMsg, FIN_CD_ERR_PARAM, DTL_CD_PARAM_ERR);
			return false;
		}
		
		return true;
	}

	/**
	 * 整理番号採番でException発生時の処理を行います。
	 * 
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @param e1 発生したException
	 */
	private void execExceptionID(CAANMsg inCBSMsg, AgentDispatchContext inContext, Exception e1)
	{
		
		// Exceptionの内容を取得
		String exp = e1.toString();
		
		// 対象のException内にSQLExceptionがあるかを判定する
		if (exp.indexOf("SQLException") != -1)
		{
			// ORACLEエラーコードの取得
			String sqlErrCd = exp.substring(exp.indexOf("ORA-") + 4, 87);

			// ORACLEエラーコードを設定して処理を終了する
			// 完了コード：採番エラー、詳細コード：ORACLEエラーコード
			setCdToMsg(inCBSMsg, FIN_CD_ERR_SYSTEM, sqlErrCd);
			return;					
		}

		// 対象のExceptionがSQLException以外の場合、コードを設定して処理を終了する
		// 完了コード：システムエラー、詳細コード：なし
		setCdToMsg(inCBSMsg, FIN_CD_ERR_SYSTEM, null);
		return;
	}

	/**
	 * 指定された完了コード、詳細コードをメッセージに設定する処理です。
	 * 
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param finCd 完了コード
	 * @param dtlCd 詳細コード
	 */
	private void setCdToMsg(CAANMsg inCBSMsg, String finCd, String dtlCd)
	{
		inCBSMsg.set(EKK0081C015CBSMsg.FIN_CD, finCd);
		inCBSMsg.set(EKK0081C015CBSMsg.DTL_CD, dtlCd);
	}

}
