/*********************************************************************
*	All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*	システム名		：eo顧客基幹システム
*	モジュール名	：JKKejbRuleBase
*	ソースファイル名：JKKejbRuleBase.java
*	作成者			：富士通
*	日付			：2011年7月7日
*＜機能概要＞
*	顧客契約相関ルール部品のスーパークラス
*＜修正履歴＞
*	バージョン	修正日		修正者		修正内容
*	v1.00.00	2011/07/07	FJ)			新規作成
*
**********************************************************************/

package eo.ejb.common.rule;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import com.fujitsu.futurity.common.JCMConstants;
import com.fujitsu.futurity.model.base.CAANCreateException;
import com.fujitsu.futurity.model.base.CAANFinderException;
import com.fujitsu.futurity.model.base.CAANMsg;
import com.fujitsu.futurity.model.base.CAANRemoveException;
import com.fujitsu.futurity.model.base.CAANRuntimeException;
import com.fujitsu.futurity.model.ejb.common.JSYejbSokanRuleEngineAccessor;
import com.fujitsu.futurity.model.ejb.common.fw.TemplateSQLEntity;
import com.fujitsu.futurity.rule.common.JRuleXMLHandler;
import com.fujitsu.futurity.rule.xml.compare.JRuleXMLPattern;

/**
 * <p>
 * 顧客契約相関ルール部品のスーパークラスです。
 * </p>
 * @author 富士通
 */
public abstract class JKKejbRuleBase extends TemplateSQLEntity
{

	/** ルールエンジン実行用ハンドラ */
	private JRuleXMLHandler handle = null;

	/** ルールエンジンインターフェイスMap */
	private HashMap<String, Object> ruleMap = null;

	/** ルールエンジン実行結果List */
	private List<ArrayList<HashMap<String, Object>>> rsltList = null;

	/** ルールエンジン実行結果参照回数 */
	private int rsltCount = 0;

	/** スキーマ名 */
	private String schemaName = null;

	/** スキーマ定義情報 */
	private Object[][] schemaContents = null;

	/** テーブル名 */
	private String tableName = null;

	/** 相関ルール自動適用要否(要) */
	public static final String AUTO_APLY_ON = "1";

	/** 相関ルール自動適用要否(否) */
	public static final String AUTO_APLY_OFF = "0";

	/** スキーマ定義情報の取得メソッド名 */
	private static final String GET_CONTENTS = "getContents";

	/** スキーマテーブル名の取得メソッド名 */
	private static final String GET_TABLE = "getTableName";

	/** 登録年月日時分秒 */
	private static final String ADD_DTM = "ADD_DTM";

	/** 登録オペレータアカウント */
	private static final String ADD_OPEACNT = "ADD_OPEACNT";

	/** 更新年月日時分秒 */
	private static final String UPD_DTM = "UPD_DTM";

	/** 更新オペレータアカウント */
	private static final String UPD_OPEACNT = "UPD_OPEACNT";

	/** 削除年月日時分秒 */
	private static final String DEL_DTM = "DEL_DTM";

	/** 削除オペレータアカウント */
	private static final String DEL_OPEACNT = "DEL_OPEACNT";

	/** 無効フラグ */
	private static final String MK_FLG = "MK_FLG";

	/** 無効フラグ：有効 */
	private static final String MK_FLG_YK = "0";

	/** 無効フラグ：無効 */
	private static final String MK_FLG_MK = "1";

	/** 更新系サービスインターフェイス共通部項目定義 */
	private static final String[] CMN_HEADER_KMK = {
		JCMConstants.TEMPLATE_ID_KEY,		// サービスIF_ID
		JCMConstants.IDENTIFY_CD_KEY,		// 識別コード
		JCMConstants.STATUS_INT_KEY,		// ステータス
		JCMConstants.OPERATOR_ID_KEY,		// オペレータ_ID
		JCMConstants.OPERATE_DATE_KEY,		// 運用日付
		JCMConstants.OPERATE_DATETIME_KEY,	// 運用日時
		JCMConstants.ACCESS_GRP_KEY,		// 権限制御用項目
		JCMConstants.FUNC_CODE_KEY,			// 機能コード
	};

	/**
	 * <p>
	 * JKKejbRuleBaseクラスのインスタンスを生成します。
	 * </p>
	 */
	protected JKKejbRuleBase()
	{
		createRuleEngine(getRuleId());
		this.ruleMap = new HashMap<String, Object>();
	}

	/**
	 * <p>
	 * JKKejbRuleBaseクラスのインスタンスを生成します。
	 * </p>
	 * @param ruleId ルールID
	 */
	protected JKKejbRuleBase(String ruleId)
	{
		createRuleEngine(ruleId);
		this.ruleMap = new HashMap<String, Object>();
	}

	/**
	 * <p>
	 * 処理対象のCBSMsgを取得します。
	 * </p>
	 * @return 処理対象のCBSMsg
	 */
	protected abstract CAANMsg getCBSMsg();

	/**
	 * <p>
	 * ルールIDを取得します。
	 * </p>
	 * @return ルールID
	 */
	protected abstract String getRuleId();

	/**
	 * <p>
	 * ルールエンジンを複数条件モードで実行するか設定します。
	 * </p>
	 * @return 複数条件モードで実行する場合はtrue
	 */
	protected abstract boolean isMultiMode();

	/**
	 * <p>
	 * スキーマ名を取得します。
	 * </p>
	 * @return スキーマ名
	 */
	protected String getSchemaName()
	{
		return this.schemaName;
	}

	/**
	 * <p>
	 * スキーマの定義情報を取得します。
	 * </p>
	 * @return スキーマの定義情報
	 */
	protected Object[][] getSchemaContents()
	{
		return this.schemaContents;
	}

	/**
	 * <p>
	 * スキーマのテーブル名を取得します。
	 * </p>
	 * @return スキーマのテーブル名
	 */
	protected String getTableName()
	{
		return this.tableName;
	}

	/**
	 * <p>
	 * ルールエンジンハンドラを生成します。
	 * </p>
	 * @param ruleId ルールID
	 */
	private void createRuleEngine(String ruleId)
	{
		int modeType = JRuleXMLPattern.SINGLE_MODE_TYPE;

		if (isMultiMode())
		{
			modeType = JRuleXMLPattern.MULTI_MODE_TYPE;
		}

		this.handle = JSYejbSokanRuleEngineAccessor.createSokanRuleEngine(ruleId, modeType);
	}

	/**
	 * <p>
	 * スキーマの定義情報を設定します。
	 * </p>
	 * @param inMsg 実行するメッセージ
	 */
	private void setSchemaContents(CAANMsg inMsg)
	{
		if (inMsg.getSchemaName().equals(this.schemaName))
		{
			return;
		}

		try
		{
			// 実行メッセージのスキーマ名からETMsgのインスタンスを生成
			Class<?>[] methodParam = null;
			Class<?> cls = Class.forName(inMsg.getSchemaName());
			Object instance = cls.newInstance();
			Method methodContents = cls.getMethod(GET_CONTENTS, methodParam);
			Method methodTable = cls.getMethod(GET_TABLE, methodParam);

			// 抽象メソッドの戻り値を設定
			Object[] invokeParam = null;
			this.schemaName = inMsg.getSchemaName();
			this.schemaContents = (Object[][])methodContents.invoke(instance, invokeParam);
			this.tableName = (String)methodTable.invoke(instance, invokeParam);
		}
		catch (Exception e)
		{
			throw new CAANRuntimeException(e);
		}
	}

	/**
	 * <p>
	 * ルールエンジンのチェックを実行します。
	 * </p>
	 */
	protected void execRuleEngine()
	{
		// ルールエンジンのチェック実行
		this.rsltList = this.handle.getCheckResultArray(this.ruleMap);
		this.rsltCount = 0;
	}

	/**
	 * <p>
	 * 次のルールエンジン実行結果Mapが存在するか判定します。
	 * </p>
	 * @return 次のルールエンジン実行結果Mapが存在する場合はtrue、存在しない場合はfalse
	 */
	protected boolean hasNext()
	{
		if (this.rsltList == null)
		{
			return false;
		}

		if (null == this.rsltList.get(0))
		{
			return false;
		}

		if (this.rsltCount >= this.rsltList.get(0).size())
		{
			return false;
		}

		return true;
	}

	/**
	 * <p>
	 * ルールエンジン実行結果をリスト形式で取得します。
	 * </p>
	 * @return ルールエンジン実行結果のリスト
	 */
	protected ArrayList<HashMap<String, Object>> getResultList()
	{
		return this.rsltList.get(0);
	}

	/**
	 * <p>
	 * ルールエンジン実行結果を取得します。
	 * </p>
	 * @return ルールエンジン実行結果のMap
	 */
	protected HashMap<String, Object> getResultMap()
	{
		return this.rsltList.get(0).get(this.rsltCount++);
	}

	/**
	 * <p>
	 * 指定されたキー名でルールエンジンインターフェイスMapに値を設定します。
	 * </p>
	 * @param key ルールエンジンインターフェイスMapに設定するキー名
	 * @param value ルールエンジンインターフェイスMapに設定する値
	 */
	protected void set(String key, Object value)
	{
		this.ruleMap.put(key, value);
	}

	/**
	 * <p>
	 * 登録処理を実行します。
	 * </p>
	 * @param inETMsg 登録するデータが格納されたメッセージ
	 * @return 登録された実行結果のメッセージ
	 */
	protected CAANMsg create(CAANMsg inETMsg)
	{
		try
		{
			setSchemaContents(inETMsg);
			setCommonHeader(inETMsg);

			// スキーマ共通項目の設定
			inETMsg.set(ADD_DTM, inETMsg.getString(JCMConstants.OPERATE_DATETIME_KEY));
			inETMsg.set(ADD_OPEACNT, inETMsg.getString(JCMConstants.OPERATOR_ID_KEY));
			inETMsg.set(UPD_DTM, inETMsg.getString(JCMConstants.OPERATE_DATETIME_KEY));
			inETMsg.set(UPD_OPEACNT, inETMsg.getString(JCMConstants.OPERATOR_ID_KEY));
			inETMsg.set(MK_FLG, MK_FLG_YK);

			return super.create(inETMsg);
		}
		catch (CAANCreateException ce)
		{
			throw new CAANRuntimeException(ce);
		}
	}

	/**
	 * <p>
	 * 更新処理を実行します。
	 * </p>
	 * @param inETMsg 更新するデータが格納されたメッセージ
	 * @return 更新された実行結果のメッセージ
	 */
	protected CAANMsg update(CAANMsg inETMsg)
	{
		try
		{
			setSchemaContents(inETMsg);
			setCommonHeader(inETMsg);

			// スキーマ共通項目の設定
			inETMsg.set(UPD_DTM, inETMsg.getString(JCMConstants.OPERATE_DATETIME_KEY));
			inETMsg.set(UPD_OPEACNT, inETMsg.getString(JCMConstants.OPERATOR_ID_KEY));

			return super.update(inETMsg);
		}
		catch (CAANFinderException ce)
		{
			throw new CAANRuntimeException(ce);
		}
	}

	/**
	 * <p>
	 * 論理削除処理を実行します。
	 * </p>
	 * @param inETMsg 論理削除するデータが格納されたメッセージ
	 * @return 論理削除された実行結果のメッセージ
	 */
	protected CAANMsg invalid(CAANMsg inETMsg)
	{
		try
		{
			setSchemaContents(inETMsg);
			setCommonHeader(inETMsg);

			// スキーマ共通項目の設定
			inETMsg.set(UPD_DTM, inETMsg.getString(JCMConstants.OPERATE_DATETIME_KEY));
			inETMsg.set(UPD_OPEACNT, inETMsg.getString(JCMConstants.OPERATOR_ID_KEY));
			inETMsg.set(DEL_DTM, inETMsg.getString(JCMConstants.OPERATE_DATETIME_KEY));
			inETMsg.set(DEL_OPEACNT, inETMsg.getString(JCMConstants.OPERATOR_ID_KEY));
			inETMsg.set(MK_FLG, MK_FLG_MK);

			return super.update(inETMsg);
		}
		catch (CAANFinderException ce)
		{
			throw new CAANRuntimeException(ce);
		}
	}

	/**
	 * <p>
	 * 削除処理を実行します。
	 * </p>
	 * @param inETMsg 削除するデータが格納されたメッセージ
	 * @return 削除された実行結果のメッセージ
	 */
	protected CAANMsg remove(CAANMsg inETMsg)
	{
		try
		{
			setSchemaContents(inETMsg);
			setCommonHeader(inETMsg);
			return super.remove(inETMsg);
		}
		catch (CAANRemoveException ce)
		{
			throw new CAANRuntimeException(ce);
		}
	}

	/**
	 * <p>
	 * プライマリキーによる検索処理を実行します。
	 * </p>
	 * @param inETMsg 検索キーが格納されたメッセージ
	 * @return 検索結果のメッセージ
	 */
	protected CAANMsg findByPrimaryKey(CAANMsg inETMsg)
	{
		try
		{
			setSchemaContents(inETMsg);
			return super.findByPrimaryKey(inETMsg);
		}
		catch (CAANFinderException ce)
		{
			return null;
		}
	}

	/**
	 * <p>
	 * 共通部項目の設定を行います。
	 * </p>
	 * @param inETMsg 処理対象のETMsg
	 */
	private void setCommonHeader(CAANMsg inETMsg)
	{
		CAANMsg inCBSMsg = getCBSMsg();

		for (String key : CMN_HEADER_KMK)
		{
			inETMsg.set(key, inCBSMsg.getObject(key));
		}
	}

}
