/*********************************************************************
*	All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*	システム名		：eo顧客基幹システム
*	モジュール名	：JKKejbNumberPartsBase
*	ソースファイル名：JKKejbNumberPartsBase.java
*	作成者			：富士通
*	日付			：2011年03月14日
*＜機能概要＞
*	採番部品のスーパークラス
*＜修正履歴＞
*	バージョン	修正日		修正者		修正内容
*	v1.00.00	2011/03/14	富士通		新規作成
*	v5.00.00	2013/06/11	FJ)寺園		SG1-2013-0000006
*	v5.00.01	2013/08/23	FJ)沖田		OM-2013-0000743
*   v5.00.02    2013/09/30  FJ)寺本     OM-2013-0002754
**********************************************************************/

package eo.ejb.common.edit;

import java.security.SecureRandom;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;

import com.fujitsu.futurity.common.JCMConstants;
import com.fujitsu.futurity.model.base.CAANException;
import com.fujitsu.futurity.model.base.CAANMsg;
import com.fujitsu.futurity.model.base.CAANProperties;
import com.fujitsu.futurity.model.base.CAANRuntimeException;
import com.fujitsu.futurity.model.ejb.common.fw.AgentDispatchContext;

import eo.ejb.cbm.entity.ZM0161ETMsg;
import eo.ejb.cbm.entity.ZM0161LE;
import eo.ejb.common.JCCModelCommon;
import eo.ejb.common.JPCModelCommon;

/**
 * <p>
 * 採番部品のスーパークラスです。<br>
 * 採番部品を作成する場合は、本クラスを継承して実装してください。
 * </p>
 * @author 富士通
 */
public class JKKejbNumberPartsBase
{
	/**
	 * 英字・記号のマッピング配列
	 */
	private static final HashMap<String, String> MAPPING = new HashMap<String, String>();

	/**
	 * チェックデジット算出処理27用重み配列
	 */
	private static final String[] WAIT_27 = {"2", "3", "4", "5", "6", "7"};
	
	/** チェックデジット（0） */
	private static final String DIGIT_ZERO = "0";

	/** 乱数発生桁数（10桁） */
	private static final int RANDOM_LENGTH = 10;
	
	/** 乱数発生桁数（8桁） */
	private static final int RANDOM_LENGTH_EIGHT = 8;

	/** 変換モードA */
	private static final String CHANGE_MODE_A = "A";

	/** 変換モードB */
	private static final String CHANGE_MODE_B = "B";

	/** 変換配列 */
	private static final HashMap<String, String> CHANGE_DATA = new HashMap<String, String>();

	static
	{
		// 英字・記号のマッピング配列設定
		MAPPING.put("@", "0");
		MAPPING.put("a", "1");
		MAPPING.put("b", "2");
		MAPPING.put("c", "3");
		MAPPING.put("d", "4");
		MAPPING.put("e", "5");
		MAPPING.put("f", "6");
		MAPPING.put("g", "7");
		MAPPING.put("h", "8");
		MAPPING.put("i", "9");
		MAPPING.put("j", "0");
		MAPPING.put("k", "1");
		MAPPING.put("l", "2");
		MAPPING.put("m", "3");
		MAPPING.put("n", "4");
		MAPPING.put("o", "5");
		MAPPING.put("p", "0");
		MAPPING.put("q", "1");
		MAPPING.put("r", "2");
		MAPPING.put("s", "3");
		MAPPING.put("t", "4");
		MAPPING.put("u", "5");
		MAPPING.put("v", "6");
		MAPPING.put("w", "7");
		MAPPING.put("x", "8");
		MAPPING.put("y", "9");
		MAPPING.put("z", "0");
		MAPPING.put("A", "1");
		MAPPING.put("B", "2");
		MAPPING.put("C", "3");
		MAPPING.put("D", "4");
		MAPPING.put("E", "5");
		MAPPING.put("F", "6");
		MAPPING.put("G", "7");
		MAPPING.put("H", "8");
		MAPPING.put("I", "9");
		MAPPING.put("J", "0");
		MAPPING.put("K", "1");
		MAPPING.put("L", "2");
		MAPPING.put("M", "3");
		MAPPING.put("N", "4");
		MAPPING.put("O", "5");
		MAPPING.put("P", "0");
		MAPPING.put("Q", "1");
		MAPPING.put("R", "2");
		MAPPING.put("S", "3");
		MAPPING.put("T", "4");
		MAPPING.put("U", "5");
		MAPPING.put("V", "6");
		MAPPING.put("W", "7");
		MAPPING.put("X", "8");
		MAPPING.put("Y", "9");
		MAPPING.put("Z", "0");
		// 変換配列設定
		CHANGE_DATA.put("0", "KMNPQRSTUV");
		CHANGE_DATA.put("1", "PQRSTUVWXY");
		CHANGE_DATA.put("2", "TUVWXYZABC");
		CHANGE_DATA.put("3", "IJKMNPQRST");
		CHANGE_DATA.put("4", "CDEFGHIJKM");
		CHANGE_DATA.put("5", "MNPQRSTUVW");
		CHANGE_DATA.put("6", "ABCDEFGHIJ");
		CHANGE_DATA.put("7", "STUVWXYZAB");
		CHANGE_DATA.put("8", "HIJKMNPQRS");
		CHANGE_DATA.put("9", "NPQRSTUVWX");
	}

	/** 変換配列 (顧客)*/
	private static final HashMap<String, String> CK_CHANGE_DATA = new HashMap<String, String>();
	
	static
	{
		CK_CHANGE_DATA.put("0", "3");
		CK_CHANGE_DATA.put("1", "4");
		CK_CHANGE_DATA.put("2", "5");
		CK_CHANGE_DATA.put("6", "7");
		CK_CHANGE_DATA.put("9", "8");
		CK_CHANGE_DATA.put("l", "m");
		CK_CHANGE_DATA.put("L", "M");
		CK_CHANGE_DATA.put("o", "p");
		CK_CHANGE_DATA.put("O", "P");
		CK_CHANGE_DATA.put("z", "a");
		CK_CHANGE_DATA.put("Z", "A");
		CK_CHANGE_DATA.put("q", "r");
		CK_CHANGE_DATA.put("Q", "R");
		CK_CHANGE_DATA.put("b", "c");
		CK_CHANGE_DATA.put("B", "C");
		CK_CHANGE_DATA.put("i", "j");
		CK_CHANGE_DATA.put("I", "J");
	}
		
	
	/**
	* <p>
	* 機能コードがチェックのみの実行モードか判定します。<br>
	* 制約上、奇数は実行モード、偶数はチェックモードとして扱います。
	* </p>
	* @param inMsg 処理対象のCBSMsg
	* @return チェックモードの場合はtrue
	*/
	protected boolean isFuncMode(CAANMsg inMsg)
	{
		String func = inMsg.getString(JCMConstants.FUNC_CODE_KEY);
		int in = Integer.parseInt(func);
		boolean ret = (in % 2) == 0;
		return ret;
	}

	/**
	 * <p>
	 * チェックデジット算出処理21。<br>
	 * </p>
	 * @param targetNo チェックデジット算出対象の番号
	 * @return 算出されたチェックデジット
	 */
	public String getCheckDigit21(String targetNo)
	{
		int total = 0;

		// 下位の桁から1桁ずつ処理を行う
		for (int i = 0; i < targetNo.length(); i++)
		{
			// 算出対象の番号に含まれる、英字・記号を数値に置換
			String strSub = String.valueOf(targetNo.charAt(i));

			if (MAPPING.containsKey(strSub))
			{
				strSub = MAPPING.get(strSub);
			}

			int one = Integer.valueOf(strSub);

			// 「1 * 10^偶数」の位の数値に、2の重みを付与する
			if ((targetNo.length() - i) % 2 == 1)
			{
				one = one * 2;
			}

			// 重みを掛けた数値の1の位と10の位をそれぞれ合計に加算する
			total = total + (one / 10);
			total = total + (one % 10);

		}

		// 合計値の1の位を10から減算した値の1の位をチェックデジットとして返却する
		total = 10 - (total % 10);

		return String.valueOf(total % 10);
	}

	/**
	 * <p>
	 * チェックデジット算出処理27。<br>
	 * </p>
	 * @param targetNo チェックデジット算出対象の番号
	 * @return 算出されたチェックデジット
	 */
	public String getCheckDigit27(String targetNo)
	{
		// 算出対象の番号を、ローカル変数に格納する
		String tempNo = targetNo;

		int total = 0;

		// 上位の桁から1桁ずつ処理を行う
		for (int i = 0; i < tempNo.length(); i++)
		{
			int one = Integer.valueOf(String.valueOf(tempNo.charAt(i)));

			// 上位の桁から順に、2,3,4,5,6,7,2,・・・の重みを付与し、合計値に加算する
			total = total + (one * Integer.parseInt(WAIT_27[i % 6]));
		}

		// 合計値の11の剰余を求める
		total = total % 11;

		// 剰余が0、または1の場合は0をチェックデジットとして返却する
		if (total == 0 || total == 1)
		{
			return DIGIT_ZERO;
		}

		// 上記条件以外の場合は11から剰余を減算した結果をチェックデジットとして返却する
		total = 11 - total;

		return String.valueOf(total);
	}

	/**
	 * <p>
	 * パスワード採番処理。<br>
	 * </p>
	 * @return 採番した番号
	 */
	public String getPwd()
	{
		// 乱数を発生
		String random = JPCModelCommon.getRandomNumber(RANDOM_LENGTH);

		// 変換処理
		StringBuffer pwd = new StringBuffer();

		// (1)乱数の9桁目,10桁目を元に英小文字変換処理を呼び出す
		pwd.append(toAlphabetLower(random.substring(8, 9), random.substring(9, 10)));
		// (2)乱数の1桁目,10桁目の加算値の下1桁目を設定する
		pwd.append(toNumLastDigit(random.substring(0, 1), random.substring(9, 10)));
		// (3)乱数の3桁目,4桁目を元に英小文字変換処理を呼び出す
		pwd.append(toAlphabetLower(random.substring(2, 3), random.substring(3, 4)));
		// (4)乱数の9桁目を設定する
		pwd.append(random.substring(8, 9));
		// (5)乱数の8桁目を設定する
		pwd.append(random.substring(7, 8));
		// (6)乱数の5桁目,6桁目を元に英小文字変換処理を呼び出す
		pwd.append(toAlphabetLower(random.substring(4, 5), random.substring(5, 6)));
		// (7)乱数の2桁目,4桁目の加算値の下1桁目を設定する
		pwd.append(toNumLastDigit(random.substring(1, 2), random.substring(3, 4)));
		// (8)乱数の7桁目,8桁目を元に英小文字変換処理を呼び出す
		pwd.append(toAlphabetLower(random.substring(6, 7), random.substring(7, 8)));

		// パスワードとして返却する
		return pwd.toString();
	}

	/**
	 * <p>
	 * ADSL認証パスワード採番処理。<br>
	 * @return 採番した番号
	 * </p>
	 */
	public String getAdslPwd()
	{
		
		// 乱数を発生。
		String random = JPCModelCommon.getRandomNumber(RANDOM_LENGTH_EIGHT);
		
		// 変換処理
		StringBuffer pwd = new StringBuffer();
		
		// (1)乱数の7桁目,8桁目を元に英小文字変換処理を呼び出す。
		pwd.append(toAlphabetLower(random.substring(6, 7), random.substring(7, 8)));
		// (2)乱数の乱数の8桁目を設定する。
		pwd.append(random.substring(7, 8));
		// (3)乱数の1桁目,2桁目を元に英小文字変換処理を呼び出す。
		pwd.append(toAlphabetLower(random.substring(0, 1), random.substring(1, 2)));
		// (4)乱数の7桁目を設定する。
		pwd.append(random.substring(6, 7));
		// (5)乱数の6桁目を設定する。
		pwd.append(random.substring(5, 6));
		// (6)乱数の3桁目,4桁目を元に英小文字変換処理を呼び出す。
		pwd.append(toAlphabetLower(random.substring(2, 3), random.substring(3, 4)));
		// (7)乱数の2桁目を設定する。
		pwd.append(random.substring(1, 2));
		// (8)乱数の5桁目,6桁目を元に英小文字変換処理を呼び出す。
		pwd.append(toAlphabetLower(random.substring(4, 5), random.substring(5, 6)));
		
		// パスワードとして返却する
		return pwd.toString();
		
	}
	
	/**
	 * <p>
	 * 顧客側のパスワード採番処理。<br>
	 * </p>
	 * @return 採番した番号
	 */
	public String getPwdCk()
	{
		// 変換処理
		StringBuffer pwd = null;

		do
		{
			// 初期化
			pwd = new StringBuffer();

			// 乱数を発生
			String random = JPCModelCommon.getRandomChar(RANDOM_LENGTH_EIGHT);

			for (int i = 0; i < random.length(); i++)
			{

				// 算出対象の番号に含まれる、英字・記号を数値に置換
				String strSub = String.valueOf(random.charAt(i));

				if (CK_CHANGE_DATA.containsKey(strSub))
				{
					strSub = CK_CHANGE_DATA.get(strSub);
				}

				pwd.append(strSub);
			}
		}
		// 採番された値が全て数字の場合はやり直し
		while (isNumChk(pwd.toString()));

		return pwd.toString();
	}
	
	/**
	 * 文字列の値が全て数字か否かチェックする
	 * <p>
	 * </p>
	 * @param value チェックする文字列
	 * @return true：全て数字　false：全て数字でない
	 */
	private boolean isNumChk(String value)
	{
		// 文字列の文字数分繰り返す
		char[] valAry = value.toCharArray();

		int numCnt = 0;
		int engCnt = 0;

		for (int i = 0; i < valAry.length; i++)
		{
			// 一文字取得する
			char target = valAry[i];

			// ０〜９の場合
			if (String.valueOf(target).matches("[0-9]"))
			{
				numCnt++;
			}

			// A〜Zの場合
			if (String.valueOf(target).matches("[a-z]"))
			{
				engCnt++;
			}
			
			// A〜Zの場合
			if (String.valueOf(target).matches("[A-Z]"))
			{
				engCnt++;
			}

		}

		// 文字列の文字数と数字または英字の数が同一の場合
		if (value.length() == numCnt || value.length() == engCnt)
		{
			// 文字列が全て数字もしくは英字となるのでtrueを返却
			return true;
		}
		// 混在のため、false
		return false;
	}

	/**
	 * <p>
	 * 英大文字変換処理。<br>
	 * </p>
	 * @param str1 変換元データの１桁目
	 * @param str2 変換元データの２桁目
	 * @return 変換した英字
	 */
	protected String toAlphabetUpper(String str1, String str2)
	{
		// 変換モードAにて英字変換処理を呼び出す
		return toAlphabet(str1, str2, CHANGE_MODE_A);
	}

	/**
	 * <p>
	 * 英小文字変換処理。<br>
	 * </p>
	 * @param str1 変換元データの１桁目
	 * @param str2 変換元データの２桁目
	 * @return 変換した英字
	 */
	protected String toAlphabetLower(String str1, String str2)
	{
		// 変換モードBにて英字変換処理を呼び出す
		return toAlphabet(str1, str2, CHANGE_MODE_B);
	}

	/**
	 * <p>
	 * 英字変換処理。<br>
	 * </p>
	 * @param str1 変換元データの１桁目
	 * @param str2 変換元データの２桁目
	 * @param mode 変換モード
	 * @return 変換した英字
	 */
	private String toAlphabet(String str1, String str2, String mode)
	{
		// 変換元データの１桁目から、英字変換対象行を取得
		String chgStr = CHANGE_DATA.get(str1);
		// 変換元データの２桁目から、変換した英字を取得
		chgStr = chgStr.substring(Integer.valueOf(str2), Integer.valueOf(str2) + 1);

		if (CHANGE_MODE_A.equals(mode))
		{
			// 変換モードAのとき、そのまま返却
			return chgStr;
		}
		// 英字を小文字に変換して返却
		return chgStr.toLowerCase();
	}

	/**
	 * <p>
	 * 指定した変換表により、英字変換を行います。<br>
	 * </p>
	 * @param str1 変換元データの１桁目
	 * @param str2 変換元データの２桁目
	 * @param changeList 変換表
	 * @return 変換した英字
	 */
	protected String toAlphabetTarget(String str1, String str2, HashMap<String, String> changeList)
	{
		// 変換元データの１桁目から、英字変換対象行を取得
		String chgStr = changeList.get(str1);

		// 変換元データの２桁目から、変換した英字を取得
		chgStr = chgStr.substring(Integer.valueOf(str2), Integer.valueOf(str2) + 1);

		return chgStr;
	}

	/**
	 * <p>
	 * 数字下一桁変換処理。<br>
	 * </p>
	 * @param str1 変換元データの１桁目
	 * @param str2 変換元データの２桁目
	 * @return 変換した数字
	 */
	protected String toNumLastDigit(String str1, String str2)
	{
		// 変換元データの１桁目と変換元データの２桁目を加算
		int total = Integer.valueOf(str1) + Integer.valueOf(str2);

		String totalStr = String.valueOf(total);

		if (totalStr.length() == 1)
		{
			// 加算値が１桁の数字のとき、そのまま返却
			return totalStr;
		}
		// 下一桁を返却
		return totalStr.substring(1, 2);
	}
	
	/**
	 * シード値を使用してランダムな数字の文字列を生成します。
	 * <br>
	 * @param arg0 生成する文字数
	 * @param arg1 シード値
	 * @return String 生成された文字列
	 */
	protected String getRandomNumberSeed(int arg0, long arg1) 
	{
		if (0 >= arg0) 
		{
			throw new IllegalArgumentException("引数の文字数[" + arg0 + "]" + "は不正です。");
		}

		SecureRandom random = new SecureRandom();

		StringBuffer ret = new StringBuffer();

		random.setSeed(arg1);

		for (int i = 0; i < arg0; i++) 
		{
			ret.append((char)(48 + random.nextInt(10)));
		}

		return ret.toString();
	}

	/**
	 * <p>
	 * Oracleシーケンス増分値の変更を行います。
	 * </p>
	 * @param seqName Oracleシーケンス名
	 * @param incVal シーケンスの増分値
	 * @throws SQLException Oracleシーケンス増分値の変更で例外が発生した場合 
	 */
	protected void alterSeq(String seqName, int incVal) throws SQLException
	{
		Connection con = null;
		PreparedStatement pstmt = null;

		try
		{
			con = getConnection();

			StringBuffer sql = new StringBuffer();
			sql.append("CALL CCPL0003 ('ALTER SEQUENCE ");
			sql.append(seqName);
			sql.append(" INCREMENT BY ");
			sql.append(incVal);
			sql.append("')");
			
			pstmt = con.prepareStatement(sql.toString());
			pstmt.execute();
		}
		catch (SQLException sqle)
		{
			sqle.printStackTrace();
			throw sqle;
		}
		catch (Exception e)
		{
			e.printStackTrace();
			throw new CAANRuntimeException(e);
		}
		finally
		{
			if (pstmt != null)
			{
				pstmt.close();
			}
			
			if (con != null)
			{
				con.close();
			}
		}
	}
 	
	/**
	 * コネクション取得処理です。
	 * <br>
	 * @return コネクション
	 * @throws Throwable 
	 */
 	private static Connection getConnection() throws Exception
 	{	
 		Connection cnct = null;
 		Context initialCtx = null;
 		try 
 		{
			CAANProperties dbInfo = new CAANProperties();
			dbInfo.load("CAANDBInfo.properties");
			String dsName = dbInfo.getString("ContainerDataSourceName_" + 0);
			initialCtx = new InitialContext();
			DataSource dataSource = (DataSource)initialCtx.lookup("jdbc/" + dsName);
			cnct = dataSource.getConnection();
 		}
		finally
		{
			if(initialCtx != null)
			{
				initialCtx.close();
			}
		}
 		
 		return cnct;
 	}

	/**
	 * <p>
	 * 引数の採番値の忌み数字の存在有無をチェックし、存在する場合は対象外処理を行います。
	 * </p>
	 * @param inMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @param seq チェック対象の採番値
	 * @param seqName シーケンス定義名
	 * @param prefix 接頭語文字列
	 * @param seqLength 桁数
	 * @return 忌み数字対象外処理後の採番値
	 */
	protected String chkNgWord(CAANMsg inMsg, AgentDispatchContext inContext, String seq, String seqName, String prefix, int seqLength)
	{
		//返却用変数
		String retStr = seq;

		//NGワードマスタから忌み数字一覧取得
		ArrayList<String> ngWordList = getNgWord(inMsg, inContext);

		boolean chkFlg = true;
		while (chkFlg)
		{

			//NGワードの数字が引数文字列に存在するかどうかをチェック
			int searchIndex = getNgWordIndex(retStr, ngWordList);

			if (searchIndex > 0)
			{
				//NGワードが文字列に存在したら、値の増分処理を行う。
				retStr = createNewNumber(retStr, searchIndex, seqName, prefix, seqLength);
			}
			else
			{
				//NGワードがなくなったら繰り返し処理終了
				chkFlg = false;
			}

		}

		return retStr;
	}

	/**
	 * <p>
	 * 忌み数字対象外処理を行います。
	 * </p>
	 * @param seq 処理対象の採番値
	 * @param searchIndex 忌み数字を検出したindex番号
	 * @param seqName シーケンス定義名
	 * @param prefix 接頭辞文字列
	 * @param seqLength 桁数
	 * @return 忌み数字対象外処理後の採番値
	 */
	private String createNewNumber(String seq, int searchIndex, String seqName, String prefix, int seqLength)
	{
		//index番号から桁シフトの指数を決定
		int keta = seq.length();
		int exNum = keta - searchIndex - 1;

		String strNum = seq.substring(searchIndex + 1);

		//右１桁目だったら初期化(="0")する。
		if ("".equals(strNum))
		{
			strNum = "0";
		}

		//増分値計算
		double incBase = Math.pow(10, exNum);
		int incInt = Double.valueOf(incBase).intValue() - Integer.parseInt(strNum);

		//桁あふれチェック
		//元の採番値から接頭語を除いた数値のみを抽出
		int oldNum = Integer.parseInt(seq.substring(prefix.length()));
		int newNumer = oldNum + incInt;

		//指定桁数をオーバーしたらException
		if (String.valueOf(newNumer).length() > seqLength)
		{
			throw new CAANRuntimeException("忌み数字対象外処理の採番エラーです。指定桁数をオーバーしました。");
		}

		String newSeq = null;

		try
		{
			//増分値を変更
			alterSeq(seqName, incInt);

			//oracleシーケンスで再採番
			newSeq = JCCModelCommon.getFormatedNextSeq(seqName, prefix, seqLength);

		}
		catch (SQLException e1)
		{
			throw new CAANRuntimeException(e1);
		}
		finally
		{
			//増分値を元に戻す
			try{
				alterSeq(seqName, 1);
			}catch (SQLException e2){
				throw new CAANRuntimeException(e2);
			}
		}

		return newSeq;
	}

	/**
	 * <p>
	 * 忌み数字の出現箇所のindex番号を取得します。
	 * </p>
	 * @param seq 処理対象の採番値
	 * @param ngWordList 忌み数字のリスト
	 * @return 忌み数字の出現箇所のindex番号
	 */
	private int getNgWordIndex(String seq, ArrayList<String> ngWordList)
	{

		//NGワードの数字が引数文字列に存在するかどうかをチェック
		int retIndex = -1;
		for (String ngWord : ngWordList)
		{
			int searchIndex = seq.indexOf(ngWord);

			//NGワードが文字列に存在したら、NGワード文字列の最後の文字のindex番号を取得。
			if (searchIndex >= 0)
			{
				//一番小さいindex番号を選んで返却値に設定する
				if (retIndex < 0 || searchIndex < retIndex)
				{
					retIndex = searchIndex + ngWord.length() - 1;
				}
			}
		}

		return retIndex;
	}

	/**
	 * <p>
	 * NGワードマスタから忌み数字のリストを取得します。
	 * </p>
	 * @param inMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @return 忌み数字のリスト
	 */
	private ArrayList<String> getNgWord(CAANMsg inMsg, AgentDispatchContext inContext)
	{
		//NGワードマスタから忌み数字一覧取得
		ArrayList<String> ngWordList = new ArrayList<String>();
		CAANMsg inETMsg = new CAANMsg(ZM0161ETMsg.class.getName());
		inETMsg.set(ZM0161ETMsg.NG_WORD_CD, "30");
		ZM0161LE le = new ZM0161LE();
		CAANMsg[] outETMsgList = null;
		try
		{
			outETMsgList = le.findByCondition(inETMsg);

			for (CAANMsg outETMsg : outETMsgList)
			{

				//適用開始年月日<=運用日<=適用終了年月日であればリストに追加
				String baseDate = (String)JPCModelCommon.getOpeDate(inMsg, inContext, null);
				String sFirstAppliedDate = outETMsg.getString(ZM0161ETMsg.NG_WORD_TSTAYMD);
				String sLastAppliedDate = outETMsg.getString(ZM0161ETMsg.NG_WORD_TENDYMD);

				if (JPCModelCommon.isFutureDate(baseDate, sFirstAppliedDate, "1") && JPCModelCommon.isPastDate(baseDate, sLastAppliedDate, "1"))
				{
					String ngWord = outETMsg.getString(ZM0161ETMsg.NG_WORD);
					ngWordList.add(ngWord);
				}

			}

		}
		catch (CAANException e1)
		{
			new CAANRuntimeException(e1);
		}

		return ngWordList;
	}

}
