/*********************************************************************
*  All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*	システム名			：eo顧客基幹システム
*	モジュール名		：JBSbatKKHapiepMmbAddAimaiEoidCreate
*	ソースファイル名	：JBSbatKKHapiepMmbAddAimaiEoidCreate.java
*	作成者				：富士通　
*	作成日				：2012年07月19日
*＜機能概要＞
*　はぴｅポイント会員登録部品です。
*＜修正履歴＞
*	バージョン	修正日		修正者		修正内容
*	v4.00.00	2013/04/25   富士通		新規作成
*********************************************************************/
package eo.business.service;

import java.util.ArrayList;

import eo.business.common.JBSbatBusinessService;
import eo.business.common.JBSbatKKConst;
import eo.business.util.file.JBSbatKKIFM040;
import eo.business.util.file.JBSbatKKIFM464;
import eo.framework.application.JBSbatBusinessException;
import eo.framework.db.JBSbatSQLAccess;
import eo.framework.item.JBSbatCommonDBInterface;
import eo.framework.item.JBSbatCommonItem;
import eo.framework.item.JBSbatOutputItem;
import eo.framework.item.JBSbatServiceInterfaceMap;
import eo.framework.util.JBSbatStringUtil;

/**
* はぴｅポイント契約審査データのeoIDについて、あいまい検索用のeoIDを生成する.
*<BR>
* @author 富士通
*/
public class JBSbatKKHapiepMmbAddAimaiEoidCreate extends JBSbatBusinessService
{
	/**▼▼▼▼▼▼ツールから生成した宣言です 開始▼▼▼▼▼▼*/
	/** テーブル(システムパラメータ管理)*/
	private static final String D_TBL_NAME_ZM_M_SYS_PARAM_KNRI = "ZM_M_SYS_PARAM_KNRI";

	/** テーブルアクセスクラス(システムパラメータ管理)*/
	private JBSbatSQLAccess db_ZM_M_SYS_PARAM_KNRI = null;
	/**▲▲▲▲▲▲ツールから生成した宣言です 終了▲▲▲▲▲▲*/

	/** エラーメッセージ：引数不正 */
	private final static String ERR_MSG_ILLEGAL_ITEM_EO_ID = "eoIDを指定してください。";

	/** 検索キーセット 区切り文字 */
	private final static String SEARCH_KEY_SET_DELM = " ";

	/** 初期eoID判定用 */
	private final static String INITIAL_EO_ID = "51";

	/** システムパラメータ分類コード */
	private static final String SYS_PARAM_BUNRUI_CD = "KK_EOID_LIKE_SEARCH";

	/** システムパラメータID */
	private static final String SYS_PARAM_ID_1 = "EOID_LIKE_GROUP_1";	

	/** システムパラメータID */
	private static final String SYS_PARAM_ID_2 = "EOID_LIKE_GROUP_2";	

	/** 検索キーセット１ */
	private String keySet1 = "";

	/** 検索キーセット２ */
	private String keySet2 = "";

	/** 生成済みeoIDリスト */
	private ArrayList<String> createEoidList = null;

	/**
	 * 初期処理
	 * @param JBSbatCommonItem commonItem　バッチ共通パラメータ電文
	 * @throws Exception
	 */
	public void initial(JBSbatCommonItem commonItem) throws Exception
	{
	/**▼▼▼▼▼▼業務サービスの初期処理を記述してください。▼▼▼▼▼▼*/
		/**▼▼▼▼▼▼ツールから生成した初期化のソースです 開始▼▼▼▼▼▼*/
		// 共通パラメータを設定します
		super.setCommonInfo(commonItem);

		// DBアクセスクラスを生成します
		db_ZM_M_SYS_PARAM_KNRI = new JBSbatSQLAccess(commonItem, D_TBL_NAME_ZM_M_SYS_PARAM_KNRI);
		/**▲▲▲▲▲▲ツールから生成した初期化のソースです 終了▲▲▲▲▲▲*/

		// システムパラメータ管理の設定値
		Object[] prm = new Object[]{SYS_PARAM_BUNRUI_CD, SYS_PARAM_ID_1};
		JBSbatCommonDBInterface ret = executeZM_M_SYS_PARAM_KNRI_PKSELECT(prm);
		if (ret == null)
		{
			// システムパラメータ管理から取得できない場合はエラーとする
			throw new JBSbatBusinessException("EKKB0130CE", new String[] {"システムパラメータ設定値"});
		}
		keySet1 = ret.getString("SYS_PARAM_SETTE_VALUE_1");
		prm = new Object[]{SYS_PARAM_BUNRUI_CD, SYS_PARAM_ID_2};
		ret = executeZM_M_SYS_PARAM_KNRI_PKSELECT(prm);
		if (ret == null)
		{
			// システムパラメータ管理から取得できない場合はエラーとする
			throw new JBSbatBusinessException("EKKB0130CE", new String[] {"システムパラメータ設定値"});
		}
		keySet2 = ret.getString("SYS_PARAM_SETTE_VALUE_1");
		
		// 生成済みeoIDリストを生成
		createEoidList = new ArrayList<String>();

	/**▲▲▲▲▲▲業務サービスの初期処理を記述してください。▲▲▲▲▲▲*/
	}

	/**
	 * 主処理
	 * @param inMap　入力電文
	 * @return JBSbatOutputItem　出力情報
	 * @throws Exception
	 */
	public JBSbatOutputItem execute(JBSbatServiceInterfaceMap inMap) throws Exception
	{
	/**▼▼▼▼▼▼業務サービスの主処理を記述してください。▼▼▼▼▼▼*/
		super.logPrint.printDebugLog("execute() start");
		super.logPrint.printDebugLog("ファイルデータ＝" + inMap.getMap().toString());
		
		// ダミーレコードの場合
		String trgtMon = inMap.getString(JBSbatKKIFM040.TRGT_MON);
		if (JBSbatKKConst.HAPIEK_JDG_REQ_DUMMY.equals(trgtMon))
		{
			// 終了
			super.logPrint.printDebugLog("execute() ダミーレコード");
			super.logPrint.printDebugLog("execute() end");
			return null;
		}

		String eoID = JBSbatStringUtil.Rtrim(inMap.getString(JBSbatKKIFM040.EO_ID));
		
		// 入力ファイルから読込んだeoIDについて、生成処理が行われている場合には処理を抜ける
		if(createEoidList.contains(eoID))
		{
			return null;
		}
		else
		{
			createEoidList.add(eoID);
		}
		
		ArrayList<String> eoIDArrayList = new ArrayList<String>();
		if(eoID == null || "".equals(eoID.trim()))
		{
			throw new IllegalArgumentException(ERR_MSG_ILLEGAL_ITEM_EO_ID);
		}
		// 検索キーセット１での結果
		ArrayList<String> cond1 = createEoID(keySet1, eoID);
		for (String conditionKey : cond1)
		{
			// １つづつ取り出し、検索キーセット２での変換を行う。
			eoIDArrayList.addAll(createEoID(keySet2, conditionKey));
		}
		
		// ファイル記載内容保持
		JBSbatOutputItem outputItem = new JBSbatOutputItem();
		for(String aimaiEoid : eoIDArrayList)
		{
			JBSbatServiceInterfaceMap outmap = new JBSbatServiceInterfaceMap();
			
			// 入力ファイルのeoIDを出力
			outmap.setString(JBSbatKKIFM464.EOID, eoID);
			// 生成したeoIDをファイルに出力
			outmap.setString(JBSbatKKIFM464.AIMAI_EOID, aimaiEoid);
			// 
			if(eoID.startsWith(INITIAL_EO_ID))
			{
				// 初期EOIDの場合には"1"を設定
				outmap.setString(JBSbatKKIFM464.EOID_DIV, "1");
			}
			else
			{
				// 初期EOIDでない場合には"0"を設定
				outmap.setString(JBSbatKKIFM464.EOID_DIV, "0");
			}
			//出力フラグを設定
			outmap.setOutFlg(true);
			//出力共通電文に入出力インターフェースを設定する。
			outputItem.addOutMapList(outmap);
		}

		super.logPrint.printDebugLog("execute() end");
		return outputItem;
	/**▲▲▲▲▲▲業務サービスの主処理を記述してください。▲▲▲▲▲▲*/
	}

	/**
	 * 業務サービス終了処理
	 * @throws Exception
	 */
	public void terminal() throws Exception
	{
	/**▼▼▼▼▼▼業務サービスの終了処理を記述してください。▼▼▼▼▼▼*/
		/**▼▼▼▼▼▼ツールから生成した終了処理のソースです 開始▼▼▼▼▼▼*/
		// DBアクセスクラスをクローズします
		db_ZM_M_SYS_PARAM_KNRI.close();
		/**▲▲▲▲▲▲ツールから生成した終了処理のソースです 終了▲▲▲▲▲▲*/
	/**▲▲▲▲▲▲業務サービスの終了処理を記述してください。▲▲▲▲▲▲*/
	}

	/**▼▼▼▼▼▼ツールから生成したメソッドです 開始▼▼▼▼▼▼*/
	/**
	 * PK(ＰＫ　検索)でDBアクセスを行います。<br>
	 * <p>
	 * <b>処理フロー</b><br>
	 * <pre>
	 * 1.引数で条件マップを作ります。<br>
	 *
	 * 2.DBアクセスを実行します。<br>
	 * 
	 * 3.メソッドの呼び出し方です。<br>
	 *		引数:
	 *		whereParam:PK項目の(項目、値)を(key、value)として,格納された配列です。PK項目は以下に説明します。
	 *		 	SYS_PARAM_BUNRUI_CD
	 *		 	SYS_PARAM_ID
	 * </pre>
	 * <p>
	 * @param whereParam 条件項目の値。
	 * @return JBSbatCommonDBInterface 検索の結果。
	 * @throws Exception 業務サービス内で発生した例外全般。
	 */
	private JBSbatCommonDBInterface executeZM_M_SYS_PARAM_KNRI_PKSELECT(Object[] whereParam) throws Exception
	{
		// 条件のマップを作成します
		JBSbatCommonDBInterface whereMap = new JBSbatCommonDBInterface();
		whereMap.setValue("SYS_PARAM_BUNRUI_CD", whereParam[0]);
		whereMap.setValue("SYS_PARAM_ID", whereParam[1]);

		// DBアクセスを実行します
		return db_ZM_M_SYS_PARAM_KNRI.selectByPrimaryKeys(whereMap);
	}
	/**▲▲▲▲▲▲ツールから生成したメソッドです 終了▲▲▲▲▲▲*/

	/**
	 * 指定されたeoIDをもとに、あいまい検索用eoIDを生成して返却します.
	 * <BR>
	 * @param key_set 編集対象となる検索キーセット
	 * @param eo_id 検索条件となるeoID
	 * @return String 検索キーセットにあうSQL文の条件文を返します。
	 */
	private static ArrayList<String> createEoID(String key_set1, String eo_id)
	{
		// 検索キーセット
		String[] keySetArray = null;
		// 検索条件 eoIDリスト
		ArrayList<String> eoIDArrayList = null;
		//eoID
		String eoIDtoLower = null;
		
		//(2) eoIDをすべて小文字へ変換する。
		eoIDtoLower = eo_id.toLowerCase();
		//(3) 検索キーセットの設定有無の判定。
		if(key_set1 != null && !"".equals(key_set1.trim()))
		{
			// 1-1. 検索キーセットの分割を行う。
			keySetArray = key_set1.split(SEARCH_KEY_SET_DELM);
			// 1-2. eoIDをすべて小文字に変換し、SQL文作成用のArrayListを作成する。
			eoIDArrayList = getEoIDArray(new StringBuffer(eoIDtoLower), keySetArray);
		}
		else
		{
			// 2-1. 検索キーセットが無い場合、指定されたeoIDそのままが検索条件とする。
			eoIDArrayList = new ArrayList<String>();
			eoIDArrayList.add(eoIDtoLower);
		}
		
		return eoIDArrayList;
	}

	/**
	 * すべてのeoIDのパターンを含んだ配列を返します。
	 * @param eo_id eoID
	 * @param key_set_array 検索キーセット
	 * @return OR条件で結ぶすべてのeoIDのパターンを含んだ配列
	 */
	private static ArrayList<String> getEoIDArray(StringBuffer eo_id, String[] key_set_array)
	{
		//検索キーセットを含んだeoIDリスト
		ArrayList<String> eoIDArrayList = new ArrayList<String>();
		//eoIDに対するHITした検索キーセットを保持する配列
		int[] eoIDKeySetPoint = new int[eo_id.length()];
		for(int iCnt = 0;iCnt < eoIDKeySetPoint.length;iCnt++)
		{
			eoIDKeySetPoint[iCnt] = -1;
		}
		//検索キーセットに含まれる文字
		String key;
		//検索キーセットに含まれる文字がeoIDの何桁目にHITしたかを示すインデックス
		int hit = 0;
		
		// (1) eoIDに検索キーセットが含まれるか判定する。
		for(int iCnt = 0;iCnt < key_set_array.length;iCnt++)
		{
			for(int iCntkeySet = 0;iCntkeySet < key_set_array[iCnt].length();iCntkeySet++)
			{
				//(2) 検索キーセット 文字列から1文字取り出す。
				key = key_set_array[iCnt].substring(iCntkeySet, iCntkeySet + 1);
				//(3) eoIDに取り出した1文字が含まれるか判定する。
				hit = 0;
				while(hit != -1)
				{
					hit = eo_id.indexOf(key, hit);
					if(hit != -1)
					{
						// 検索キーセット 文字列から取り出した文字列がeoIDに含まれる場合、
						// 検索キーセットの配列番号をeoIDに対するHITした検索キーセットを
						// 保持する配列に格納する。
						eoIDKeySetPoint[hit] = iCnt;
						hit++;
					}
				}
			}
		}
		//(4) 検索キーセットを含んだeoIDの生成
		createEoIDForArrayList(eo_id, 0, eoIDArrayList, eoIDKeySetPoint, key_set_array);
		
		return eoIDArrayList;
	}

	/**
	 * 指定されたeoIDと検索キーセットを比較し、検索キーセットと一致する場合、その文字を検索キーセットのパターン分置き換える。
	 * @param eo_id eoID
	 * @param index_eoid 比較するeoIDの左から位置（桁数）
	 * @param eoid_list すべてのeoIDのパターンを含んだ配列
	 * @param key_set_index eoIDのどの位置でどの検索キーセットにヒットしたか関連付ける配列
	 * @param key_set 検索キーセット
	 */
	private static void createEoIDForArrayList(StringBuffer eo_id, int index_eoid, ArrayList<String> eoid_list, 
																		int[] key_set_index, String[] key_set)
	{
		// (1) インデックスがeoIDの桁数を超えた場合、処理を抜ける
		if(index_eoid >= eo_id.length())
		{
			// インデックスがeoIDの桁数を超えた場合、編集したeoIDをArrayListへ追加し処理を抜ける
			eoid_list.add(eo_id.toString());
			return;
		}
		
		int keySetArrayIndex =key_set_index[index_eoid]; 
		// (2) eoIDのどの位置でどの検索キーセットにヒットしたか関連付ける配列を参照し、置換え処理を行う。
		if(keySetArrayIndex < 0)
		{
			// ・検索キーセットに置き換える必要なしの場合 次の位置を処理するためにインデックスをインクリメントし、自分自身を呼び出す。
			createEoIDForArrayList(eo_id, ++index_eoid, eoid_list, key_set_index, key_set);
		}
		else
		{
			// ・検索キーセットに置き換える必要ありの場合
			for(int iCnt = 0;iCnt < key_set[keySetArrayIndex].length();iCnt++)
			{
				// (a) 検索キーセットに含まれる文字を取り出す。
				String rep = key_set[keySetArrayIndex].substring(iCnt, iCnt+1);
				// (b) eoIDへ反映し、下位の桁の置換え、次の位置を処理するためにインデックスをインクリメントし、自分自身を呼び出す。
				createEoIDForArrayList(eo_id.replace(index_eoid, index_eoid + 1, rep), index_eoid + 1, eoid_list, key_set_index, key_set);
			}
		}
	}
}
