/*********************************************************************
*	All Rights reserved,Copyright c Fujitsu, 2011
**********************************************************************
*＜プログラム内容＞
*	システム名		：プロジェクト共通
*	モジュール名	：JACejbDateChecker
*	ソースファイル名：JACejbDateChecker.java
*	作成者			：富士通
*	日付			：2011年06月15日
*＜機能概要＞
*	日付判定に関する共通処理を行うクラスです。
*＜修正履歴＞
*	バージョン	修正日		修正者		修正内容
*	v1.00.00	2011/06/15	富士通		新規作成
*
**********************************************************************/
package eo.ejb.common.itemrelation;

import java.text.ParseException;

import com.fujitsu.futurity.model.base.CAANMsg;
import com.fujitsu.futurity.model.base.CAANRuntimeException;
import com.fujitsu.futurity.model.ejb.common.fw.AgentDispatchContext;

import eo.common.util.JPCDateChecker;
import eo.common.util.JPCUtilCommon;
import eo.ejb.cbs.cbsmsg.EAC0171B010CBSMsg;
import eo.ejb.common.JCCModelCommon;

/**
 * 日付判定に関する共通処理を行うクラスです。
 * <br>
 * @author 富士通
 */
public class JACejbDateChecker {
	
	/** 同月包含フラグ ON */
	private static final String INCLUDE_FLG_ON = "1";

	/** 期間単位 年 */
	private static final String KIKAN_YEAR = "0";
	
	/** 期間単位 月 */
	private static final String KIKAN_MONTH = "1";
	
	/** 期間単位 日 */
	private static final String KIKAN_DAY = "2";

	/**
	 * <p>
	 * 過去日判定処理
	 * </p>
	 * 指定された日付が運用日付より過去日か判定を行う。
	 * <br>
	 * @param inMsg 処理対象のメッセージ
	 * @param inContext エージェントディスパッチコンテキスト
	 * @param inItemName 判定対象項目の項目名(英名小文字)
	 * @param inIncludeFlg 同日を含む、含まないの指定('0':含まない、'1':含む)
	 * @return 過去日：true、未来日：false
	 */
	public static boolean isPastDate(CAANMsg inMsg,
			AgentDispatchContext inContext, String inItemName, String inIncludeFlg)
	{
		// 戻り値
		boolean bRtn = false;
		
		// (1) パラメータ「項目名」を元にパラメータ「処理対象メッセージ」から
		//     処理対象項目の値を取得する。
		String sItemValue = inMsg.getString(inItemName);
		
		// (2) システム日付を取得する。
		String sOpeDate;
		try
		{
			sOpeDate = JCCModelCommon.getOpeDate(inMsg, null);
		}
		catch(Exception e)
		{
			throw new CAANRuntimeException(e);
		}
		
		// (3) 共通処理部品「過去日判定処理」メソッドを呼び出す。
		bRtn = JPCDateChecker.isPastDate(sItemValue, sOpeDate, inIncludeFlg);
		
		// (4) (3)の処理結果を戻り値として処理を終了する。
		return bRtn;
	}

	/**
	 * <p>
	 * 未来日判定処理
	 * </p>
	 * 指定された日付が運用日付より未来日か判定を行う。
	 * <br>
	 * @param inMsg 処理対象のメッセージ
	 * @param inContext エージェントディスパッチコンテキスト
	 * @param inItemName 判定対象項目の項目名(英名小文字)
	 * @param inIncludeFlg 同日を含む、含まないの指定('0':含まない、'1':含む)
	 * @return 未来日：true、過去日：false
	 */
	public static boolean isFutureDate(CAANMsg inMsg,
			AgentDispatchContext inContext, String inItemName, String inIncludeFlg)
	{
		// 戻り値
		boolean bRtn = false;
		
		// (1) パラメータ「項目名」を元にパラメータ「処理対象メッセージ」から
		//     処理対象項目の値を取得する。
		String sItemValue = inMsg.getString(inItemName);
		
		// (2) システム日付を取得する。
		String sOpeDate;
		try
		{
			sOpeDate = JCCModelCommon.getOpeDate(inMsg, null);
		}
		catch(Exception e)
		{
			throw new CAANRuntimeException(e);
		}
		
		// (3) 共通処理部品「未来日判定処理」メソッドを呼び出す。
		bRtn = JPCDateChecker.isFutureDate(sItemValue, sOpeDate, inIncludeFlg);
		
		// (4) (3)の処理結果を戻り値として処理を終了する。
		return bRtn;
	}

	/**
	 * <p>
	 * 拡張過去日判定処理
	 * </p>
	 * 指定された日付が運用日付の数日（数ヶ月、数年）前後より過去日か判定を行う。
	 * <br>
	 * @param inMsg 処理対象のメッセージ
	 * @param inContext エージェントディスパッチコンテキスト
	 * @param inItemName 判定対象項目の項目名(英名小文字)
	 * @param inIncludeFlg 同日を含む、含まないの指定('0':含まない、'1':含む)
	 * @param inKikan 期間単位 0:年単位、1：月単位、2：日単位
	 * @param inKikanNum 期間単位と合わせて、基準日を設定する
	 * @return 過去日：true、未来日：false
	 */
	public static boolean isPastDateEx(CAANMsg inMsg,
			AgentDispatchContext inContext, String inItemName, String inIncludeFlg,
			String inKikan, int inKikanNum)
	{
		// 戻り値
		boolean bRtn = false;
		
		// (1) パラメータ「項目名」を元にパラメータ「処理対象メッセージ」から
		//     処理対象項目の値を取得する。
		String sItemValue = inMsg.getString(inItemName);
		
		// (2) システム日付を取得する。
		String sOpeDate;
		try
		{
			sOpeDate = JCCModelCommon.getOpeDate(inMsg, null);
		}
		catch(Exception e)
		{
			throw new CAANRuntimeException(e);
		}
		
		// (3) 期間単位でシステム日付に期間数を加算する。
		String sBaseDate = addDate(sOpeDate, inKikan, inKikanNum);
		
		// (4) 共通処理部品「過去日判定処理」メソッドを呼び出す。
		bRtn = JPCDateChecker.isPastDate(sItemValue, sBaseDate, inIncludeFlg);
		
		// (5) (4)の処理結果を戻り値として処理を終了する。
		return bRtn;
	}

	/**
	 * <p>
	 * 拡張未来日判定処理
	 * </p>
	 * 指定された日付が運用日付の数日（数ヶ月、数年）前後より過去日か判定を行う。
	 * <br>
	 * @param inMsg 処理対象のメッセージ
	 * @param inContext エージェントディスパッチコンテキスト
	 * @param inItemName 判定対象項目の項目名(英名小文字)
	 * @param inIncludeFlg 同日を含む、含まないの指定('0':含まない、'1':含む)
	 * @param inKikan 期間単位 0:年単位、1：月単位、2：日単位
	 * @param inKikanNum 期間単位と合わせて、基準日を設定する
	 * @return 未来日：true、過去日：false
	 */
	public static boolean isFutureDateEx(CAANMsg inMsg,
			AgentDispatchContext inContext, String inItemName, String inIncludeFlg,
			String inKikan, int inKikanNum)
	{
		// 戻り値
		boolean bRtn = false;
		
		// (1) パラメータ「項目名」を元にパラメータ「処理対象メッセージ」から
		//     処理対象項目の値を取得する。
		String sItemValue = inMsg.getString(inItemName);
		
		// (2) システム日付を取得する。
		String sOpeDate;
		try
		{
			sOpeDate = JCCModelCommon.getOpeDate(inMsg, null);
		}
		catch(Exception e)
		{
			throw new CAANRuntimeException(e);
		}
		
		// (3) 期間単位でシステム日付に期間数を加算する。
		String sBaseDate = addDate(sOpeDate, inKikan, inKikanNum);
		
		// (4) 共通処理部品「未来日判定処理」メソッドを呼び出す。
		bRtn = JPCDateChecker.isFutureDate(sItemValue, sBaseDate, inIncludeFlg);
		
		// (5) (4)の処理結果を戻り値として処理を終了する。
		return bRtn;
	}

	/**
	 * <p>
	 * 過去月判定処理
	 * </p>
	 * 指定された日付が運用日付より過去月か判定を行う。
	 * <br>
	 * @param inMsg 処理対象のメッセージ
	 * @param inContext エージェントディスパッチコンテキスト
	 * @param inItemName 判定対象項目の項目名(英名小文字)
	 * @param inIncludeFlg 同月を含む、含まないの指定('0':含まない、'1':含む)
	 * @return 過去月：true、未来月：false
	 */
	public static boolean isPastMonth(CAANMsg inMsg,
			AgentDispatchContext inContext, String inItemName, String inIncludeFlg)
	{
		// 戻り値
		boolean bRtn = false;
		
		
		// (1) パラメータ「項目名」を元にパラメータ「処理対象メッセージ」から
		//     処理対象項目の値を取得する。
		String sItemValue = inMsg.getString(inItemName);
		
		// (2) システム日付をYYYYMMDDの書式で取得し、日付を"01"に編集する。
		String sOpeDate;
		try
		{
			sOpeDate = inMsg.getString(EAC0171B010CBSMsg.OPERATEDATETIME).substring(0, 6);
		}
		catch(Exception e)
		{
			throw new CAANRuntimeException(e);
		}
		String sFirstOpeDate = getStartOfMonth(sOpeDate);
		
		// (3) (1)で取得した値の日付を"01"に編集する。
		String sFirstTargetDate = getStartOfMonth(sItemValue);
		
		// (4) 共通処理部品「月差算出処理」メソッドを呼び出す。
		int iSubtract = JPCUtilCommon.subtractMonth(sFirstTargetDate,
				sFirstOpeDate);
		
		// (5) (4)で取得した値をもとに戻り値を判定する。
		if (iSubtract < 0)
		{
			// 月差が0より小さい場合はチェックOK
			bRtn = true;
		}
		else if (iSubtract > 0)
		{
			// 月差が0より大きい場合はチェックNG
			bRtn = false;
		}
		else
		{
			// 月差が無い場合は同月包含フラグで判定する
			if (INCLUDE_FLG_ON.equals(inIncludeFlg))
			{
				// 同月包含フラグが含むの場合はチェックOK
				bRtn = true;
			}
			else
			{
				// 同月包含フラグが含まないの場合はチェックNG
				bRtn = false;
			}
		}
		
		return bRtn;
	}
	
	/**
	 * <p>
	 * 未来月判定処理
	 * </p>
	 * 指定された日付が運用日付より未来月か判定を行う。
	 * <br>
	 * @param inMsg 処理対象のメッセージ
	 * @param inContext エージェントディスパッチコンテキスト
	 * @param inItemName 判定対象項目の項目名(英名小文字)
	 * @param inIncludeFlg 同月を含む、含まないの指定('0':含まない、'1':含む)
	 * @return 未来月：true、過去月：false
	 */
	public static boolean isFutureMonth(CAANMsg inMsg,
			AgentDispatchContext inContext, String inItemName, String inIncludeFlg)
	{
		// 戻り値
		boolean bRtn = false;
		
		// (1) パラメータ「項目名」を元にパラメータ「処理対象メッセージ」から
		//     処理対象項目の値を取得する。
		String sItemValue = inMsg.getString(inItemName);
		
		// (2) システム日付をYYYYMMDDの書式で取得し、日付を"01"に編集する。
		String sOpeDate;
		try
		{
			sOpeDate = inMsg.getString(EAC0171B010CBSMsg.OPERATEDATETIME).substring(0, 8);
		}
		catch(Exception e)
		{
			throw new CAANRuntimeException(e);
		}
		String sFirstOpeDate = getStartOfMonth(sOpeDate);
		
		// (3) (1)で取得した値の日付を"01"に編集する。
		String sFirstTargetDate = getStartOfMonth(sItemValue);
		
		// (4) 共通処理部品「月差算出処理」メソッドを呼び出す。
		int iSubtract = JPCUtilCommon.subtractMonth(sFirstTargetDate,
				sFirstOpeDate);
		
		// (5) (4)で取得した値をもとに戻り値を判定する。
		if (iSubtract < 0)
		{
			// 月差が0より小さい場合はチェックNG
			bRtn = false;
		}
		else if (iSubtract > 0)
		{
			// 月差が0より大きい場合はチェックOK
			bRtn = true;
		}
		else
		{
			// 月差が無い場合は同月包含フラグで判定する
			if (INCLUDE_FLG_ON.equals(inIncludeFlg))
			{
				// 同月包含フラグが含むの場合はチェックOK
				bRtn = true;
			}
			else
			{
				// 同月包含フラグが含まないの場合はチェックNG
				bRtn = false;
			}
		}
		
		return bRtn;
	}
	
	/**
	 * <p>
	 * 拡張過去月判定処理
	 * </p>
	 * 指定された日付が運用日付の数ヶ月（数年）前後より過去月か判定を行う。
	 * <br>
	 * @param inMsg 処理対象のメッセージ
	 * @param inContext エージェントディスパッチコンテキスト
	 * @param inItemName 判定対象項目の項目名(英名小文字)
	 * @param inIncludeFlg 同月を含む、含まないの指定('0':含まない、'1':含む)
	 * @param inKikan 期間単位 0:年単位、1：月単位
	 * @param inKikanNum 期間単位と合わせて、基準日を設定する
	 * @return 過去月：true、未来月：false
	 */
	public static boolean isPastMonthEx(CAANMsg inMsg,
			AgentDispatchContext inContext, String inItemName, String inIncludeFlg,
			String inKikan, int inKikanNum)
	{
		// 戻り値
		boolean bRtn = false;
		
		// (1) パラメータ「項目名」を元にパラメータ「処理対象メッセージ」から
		//     処理対象項目の値を取得する。
		String sItemValue = inMsg.getString(inItemName);
		
		// (2) システム日付をYYYYMMDDの書式で取得する。
		String sOpeDate;
		try
		{
			sOpeDate = inMsg.getString(EAC0171B010CBSMsg.OPERATEDATETIME).substring(0, 8);
		}
		catch(Exception e)
		{
			throw new CAANRuntimeException(e);
		}
		
		// (3) 期間単位でシステム日付に期間数を加算し、日付を"01"に編集する。
		String sBaseDate = addDate(sOpeDate, inKikan, inKikanNum);
		String sFirstBaseDate = getStartOfMonth(sBaseDate);
		
		// (4) (1)で取得した値の日付を"01"に編集する。
		String sFirstTargetDate = getStartOfMonth(sItemValue);
		
		// (5) 共通処理部品「月差算出処理」メソッドを呼び出す。
		int iSubtract = JPCUtilCommon.subtractMonth(sFirstTargetDate,
				sFirstBaseDate);
		
		// (6) (5)で取得した値をもとに戻り値を判定する。
		if (iSubtract < 0)
		{
			// 月差が0より小さい場合はチェックOK
			bRtn = true;
		}
		else if (iSubtract > 0)
		{
			// 月差が0より大きい場合はチェックNG
			bRtn = false;
		}
		else
		{
			// 月差が無い場合は同月包含フラグで判定する
			if (INCLUDE_FLG_ON.equals(inIncludeFlg))
			{
				// 同月包含フラグが含むの場合はチェックOK
				bRtn = true;
			}
			else
			{
				// 同月包含フラグが含まないの場合はチェックNG
				bRtn = false;
			}
		}
		
		return bRtn;
	}
	
	/**
	 * <p>
	 * 拡張未来月判定処理
	 * </p>
	 * 指定された日付が運用日付の数ヶ月（数年）前後より未来月か判定を行う。
	 * <br>
	 * @param inMsg 処理対象のメッセージ
	 * @param inContext エージェントディスパッチコンテキスト
	 * @param inItemName 判定対象項目の項目名(英名小文字)
	 * @param inIncludeFlg 同月を含む、含まないの指定('0':含まない、'1':含む)
	 * @param inKikan 期間単位 0:年単位、1：月単位
	 * @param inKikanNum 期間単位と合わせて、基準日を設定する
	 * @return 未来月：true、過去月：false
	 */
	public static boolean isFutureMonthEx(CAANMsg inMsg,
			AgentDispatchContext inContext, String inItemName, String inIncludeFlg,
			String inKikan, int inKikanNum)
	{
		// 戻り値
		boolean bRtn = false;
		
		// (1) パラメータ「項目名」を元にパラメータ「処理対象メッセージ」から
		//     処理対象項目の値を取得する。
		String sItemValue = inMsg.getString(inItemName);
		
		// (2) システム日付をYYYYMMDDの書式で取得する。
		String sOpeDate;
		try
		{
			sOpeDate = inMsg.getString(EAC0171B010CBSMsg.OPERATEDATETIME).substring(0, 8);
		}
		catch(Exception e)
		{
			throw new CAANRuntimeException(e);
		}
		
		// (3) 期間単位でシステム日付に期間数を加算し、日付を"01"に編集する。
		String sBaseDate = addDate(sOpeDate, inKikan, inKikanNum);
		String sFirstBaseDate = getStartOfMonth(sBaseDate);
		
		// (4) (1)で取得した値の日付を"01"に編集する。
		String sFirstTargetDate = getStartOfMonth(sItemValue);
		
		// (5) 共通処理部品「月差算出処理」メソッドを呼び出す。
		int iSubtract = JPCUtilCommon.subtractMonth(sFirstTargetDate,
				sFirstBaseDate);
		
		// (6) (5)で取得した値をもとに戻り値を判定する。
		if (iSubtract < 0)
		{
			// 月差が0より小さい場合はチェックNG
			bRtn = false;
		}
		else if (iSubtract > 0)
		{
			// 月差が0より大きい場合はチェックOK
			bRtn = true;
		}
		else
		{
			// 月差が無い場合は同月包含フラグで判定する
			if (INCLUDE_FLG_ON.equals(inIncludeFlg))
			{
				// 同月包含フラグが含むの場合はチェックOK
				bRtn = true;
			}
			else
			{
				// 同月包含フラグが含まないの場合はチェックNG
				bRtn = false;
			}
		}
		
		return bRtn;
	}
	
	/**
	 * <p>
	 * 日付加算処理
	 * </p>
	 * 指定された日付の数日（数ヶ月、数年）前後の日付を取得する。
	 * <br>
	 * @param inTargetDate 加算対象日付
	 * @param inKikan 期間単位 0:年単位、1：月単位、2：日単位
	 * @param inKikanNum 期間数
	 * @return 加算後の日付
	 */
	private static String addDate(String inTargetDate, String inKikan,
			int inKikanNum)
	{
		// 戻り値
		String sRtn = null;
		
		try
		{
			// 期間単位チェック
			if (KIKAN_YEAR.equals(inKikan))
			{
				// 期間単位が年の場合は年の加算を行う
				sRtn = JPCUtilCommon.addYear(inTargetDate, inKikanNum);
			}
			else if (KIKAN_MONTH.equals(inKikan))
			{
				// 期間単位が年の場合は月の加算を行う
				sRtn = JPCUtilCommon.addMonth(inTargetDate, inKikanNum);
			}
			else if (KIKAN_DAY.equals(inKikan))
			{
				// 期間単位が年の場合は日の加算を行う
				sRtn = JPCUtilCommon.addDay(inTargetDate, inKikanNum);
			}
		}
		catch(ParseException e)
		{
			throw new CAANRuntimeException(e);
		}
		
		return sRtn;
	}
	
	/**
	 * <p>
	 * 月初取得処理
	 * </P>
	 * 指定された日付または年月の月初日を取得する
	 * <br>
	 * @param inYmd 年月日または年月
	 * @return 指定日付の月初日付
	 */
	private static String getStartOfMonth(String inYmd)
	{
		// 戻り値
		String sRet = null;
		
		// パラメータチェック
		if (inYmd == null)
		{
			throw new CAANRuntimeException();
		}
		
		// 月初日の編集
		if (inYmd.length() == 8)
		{
			// 年月日の場合、年月に"01"を付加する
			String sYm = inYmd.substring(0, 6);
			sRet = sYm + "01";
		}
		else if (inYmd.length() == 6)
		{
			// 年月の場合、年月に"01"を付加する
			sRet = inYmd + "01";
		}
		
		return sRet;
	}
}
