/*********************************************************************
* All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*   システム名      ：eo顧客基幹システム
*   モジュール名    ：JZMejbEoIdSearchKeySetEdit
*   ソースファイル名：JZMejbEoIdSearchKeySetEdit.java
*   作成者          ：富士通
*   日付            ：2012年01月30日
*＜機能概要＞
*   eoIDあいまい検索条件作成部品です。
*＜修正履歴＞
*   バージョン  修正日       修正者      修正内容
*   v3.00       2012/01/30   FJ) 宮前    新規作成
*   v3.00       2012/01/30   FJ) 宮前    【ANK-0024-00-00】eoIDあいまい検索部品追加
*   v19.00.00   2015/10/29   FJ) 金      【OM-2015-0002479】eoIDあいまい検索部品の判定条件修正
*
**********************************************************************/
package eo.ejb.common.edit;

import java.util.ArrayList;

import eo.ejb.common.JZMModelCommon;

/**
 * eoIDあいまい検索検索キーセットに関する編集を行います。
 * <BR>
 * @author FJ
 *
 */
public class JZMejbEoIdSearchKeySetEdit
{

	/** エラーメッセージ：引数不正 */
	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";
	
	/** SQL文 検索条件指定用 eoID */
	private final static String KEY_EO_ID = "LOWER(CK0011.EOID)";
	
	/** SQL文 検索条件指定用 初期eoID */
	private final static String KEY_INIT_EO_ID = "LOWER(CK0011.SHK_EOID)";
	
	/** eoID桁数判定用 */
	private final static int EO_ID_JUDG_LENGTH = 11;
	
	/**
	 * 指定されたeoIDあいまい検索検索キーセットをSQL文の条件文に編集し、返却します。
	 * <BR>
	 * @param key_set 編集対象となる検索キーセット
	 * @param eo_id 検索条件となるeoID
	 * @return String 検索キーセットにあうSQL文の条件文を返します。
	 */
	public static String createSqlCondition(String key_set, String eo_id)
	{
		
		// 検索キーセット
		String[] keySetArray = null;
		
		// 検索条件 eoIDリスト
		ArrayList<String> eoIDArrayList = null;
		
		// eoID
		String eoIDtoLower = null;
		
		// (1) (1)引数チェックを行う。（eoIDのみ）
		if(eo_id == null || "".equals(eo_id.trim()))
		{
			throw new IllegalArgumentException(ERR_MSG_ILLEGAL_ITEM_EO_ID);
		}
		
		// (2) eoIDをすべて小文字へ変換する。
		eoIDtoLower = eo_id.toLowerCase();
		
		// (3) 検索キーセットの設定有無の判定。
		if(key_set != null && !"".equals(key_set.trim()))
		{
			
			// 1-1. 検索キーセットの分割を行う。
			keySetArray = key_set.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);
		}
		
		// (4) eoIDと分割された検索キーセットからSQL文条件を作成する。
		return createSqlCondition(eoIDtoLower, eoIDArrayList);
	}
	
	/**
	 * 検索キーセットを考慮し、OR条件で結ぶすべての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の生成
		createEoIDForSQLArrayList(eo_id, 0, eoIDArrayList, eoIDKeySetPoint, key_set_array);
		
		return eoIDArrayList;
	}
	
	/**
	 * 指定されたeoIDと検索キーセットを比較し、検索キーセットと一致する場合、その文字を検索キーセットのパターン分置き換える。
	 * @param eo_id eoID
	 * @param index_eoid 比較するeoIDの左から位置（桁数）
	 * @param eoid_list OR条件で結ぶすべてのeoIDのパターンを含んだ配列
	 * @param key_set_index eoIDのどの位置でどの検索キーセットにヒットしたか関連付ける配列
	 * @param key_set 検索キーセット
	 */
	private static void createEoIDForSQLArrayList(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)
		{
			
			// ・検索キーセットに置き換える必要なしの場合 次の位置を処理するためにインデックスをインクリメントし、自分自身を呼び出す。
			createEoIDForSQLArrayList(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へ反映し、下位の桁の置換え、次の位置を処理するためにインデックスをインクリメントし、自分自身を呼び出す。
				createEoIDForSQLArrayList(eo_id.replace(index_eoid, index_eoid + 1, rep), index_eoid + 1, eoid_list, key_set_index, key_set);
			}
		}
	}
	
	/**
	 * OR条件で結ぶすべてのeoIDのパターンを含んだ配列からSQL文（条件文）を作成する。
	 * @param eo_id eoID
	 * @param condition_list OR条件で結ぶすべてのeoIDのパターンを含んだ配列
	 * @return SQL文（条件文）
	 */
	private static String createSqlCondition(String eo_id, ArrayList<String> condition_list)
	{
		StringBuffer sql = new StringBuffer();
		String key_item = null;
		String orCondition = "";
		
		// (1) 検索対象項目が初期eoIDかeoIDの判定
		if(eo_id.startsWith(INITIAL_EO_ID))
		{
			
			// ・eoIDが51で始まる場合、初期eoIDを検索条件に指定する。
			key_item = KEY_INIT_EO_ID;
		}
		else
		{
			
			// ・eoIDが51以外で始まる場合、eoIDを検索条件に指定する。
			key_item = KEY_EO_ID;
		}
		
		// (2) SQL文（条件文）の作成を行う。
		for(int iCnt = 0;iCnt < condition_list.size();iCnt++)
		{
			if(iCnt > 0)
			{
				orCondition = " OR ";
			}
			sql.append(orCondition).append("( ").append(editQuery(key_item, condition_list.get(iCnt))).append(" )");
		}
		
		return sql.toString();
	}
	
	/**
	 * eoIDの桁数から完全一致もしくは前方一致かの判定を行い、SQL文（条件文）を作成する。
	 * @param key DB項目名
	 * @param value 検索条件（値）
	 * @return SQL文（条件文）
	 */
	private static String editQuery(String key, String value)
	{
		String editValue = null;
		// ++++++ v19.00.00 DEL START +++++++++	
//		// (1) 完全一致か前方一致かの判定
//		if(value.length() <= EO_ID_JUDG_LENGTH)
//		{
//			
//			// ・上記以外の場合（12桁の場合）、前方一致とする。
//			editValue = key + " LIKE '" + JZMModelCommon.replaceLikeValue(value) + "%' " + JZMModelCommon.ESCAPE_SQL_STRING;
//		}
//		else
//		{
//			
//			// ・検索条件の桁数が11桁以下の場合、完全一致とする。
//			editValue = key + " = '" + value + "'";
//		}
		// ++++++ v19.00.00 DEL END +++++++++
		// ++++++ v19.00.00 ADD START +++++++++
		// 一部一致の検索文を作成する。
		editValue = key + " LIKE '" + JZMModelCommon.replaceLikeValue(value) + "%' " + JZMModelCommon.ESCAPE_SQL_STRING;
		// ++++++ v19.00.00 ADD END +++++++++	
		return editValue;
	}
	
}
