/*********************************************************************
 * All Right reserved,Copyright (c) Fujitsu, 2011
 **********************************************************************
 *＜プログラム内容＞
 *   システム名      ：eo顧客基幹システム
 *   モジュール名    ：割引サービス解約/キャンセル画面ビューロジック
 *   ソースファイル名：KKW01031SFLogic.java
 *   作成者          ：富士通
 *   日付            ：2011年05月11日
 *＜機能概要＞
 *   割引サービス解約/キャンセル画面のビューロジック。
 *＜修正履歴＞
 *   バージョン  修正日       修正者      修正内容
 *   v1.00.00    2011/05/11   富士通      新規作成
 *   v3.01.00    2012/05/29   FJ          【IT1-2012-0000572】
 *
 **********************************************************************/

package eo.web.webview.KKW01031SF;

import java.util.ArrayList;
import java.util.HashMap;

import com.fujitsu.futurity.common.JSYwebLog;
import com.fujitsu.futurity.web.x31.X31CVector;
import com.fujitsu.futurity.web.x31.X31CWebConst;
import com.fujitsu.futurity.web.x31.X31SDataBeanAccess;
import com.fujitsu.futurity.web.x31.X31SDataBeanAccessArray;

import eo.common.util.JCCFrameworkException;
import eo.web.webview.JCCWebBusinessLogic;
import eo.web.webview.CommonInfoCF.CommonInfoCFConst;
import eo.web.webview.KKW01031SF.KKW01031SFConst.FunctionCode;
import eo.web.webview.KKW01031SF.KKW01031SFConst.Screen;
import eo.web.webview.KKW01031SF.KKW01031SFConst.Service;
import eo.web.webview.common.JCCWebCommon;
import eo.web.webview.common.JKKCommonConst;
import eo.web.webview.common.JKKScreenConst;

/**
 * <dd>クラス名：KKW01031SFLogic <dd>クラス説明：割引サービス契約の解約／キャンセルを行う。 <dd>備考：なし。
 * 
 * @author 富士通
 */
@SuppressWarnings("serial")
public class KKW01031SFLogic extends JCCWebBusinessLogic {

	/**
	 * <dd>メソッド名：初期表示処理 <dd>メソッド説明：確認画面の初期表示を行う。 <dd>備考：なし。
	 * 
	 * @return true
	 */

	public boolean actionInit() throws Exception {
		// DataBeanログ出力
		JSYwebLog.println(JSYwebLog.DataBean_Dump, getClass(), dumpDatabean(), null, null, null);

		// 跨り関係のない画面からの遷移にあたって
		// 跨り関係のない画面および自画面が設定した受け渡し情報をSFBeanに設定。
		JCCWebCommon.getScreenInfo(this);
		// サービスフォームBeanのデータBeanアクセスクラスを取得。
		X31SDataBeanAccess bean = super.getServiceFormBean();
		// 引継ぎリストからSYSID,サービス契約番号,異動区分,異動理由コード,申込番号を転記
		X31SDataBeanAccessArray custKeiHktgiListArray = Mover.getBeanArray(
				bean, KKW01031SFConst.CUST_KEI_HKTGI_LIST);
		X31SDataBeanAccess custKeiHktgiList = custKeiHktgiListArray
				.getDataBean(0);
		//SYSIDを転記
		String sysid = Mover.getString(custKeiHktgiList,
				KKW01031SFConst.SYSID_01);
		Mover.setString(bean, KKW01031SFConst.SYSID, sysid);
		//サービス契約番号を転記
		String svcKeiNo = Mover.getString(custKeiHktgiList,
				KKW01031SFConst.SVC_KEI_NO_01);
		Mover.setString(bean, KKW01031SFConst.SVC_KEI_NO, svcKeiNo);
		//異動区分を転記
		String idoDiv = Mover.getString(custKeiHktgiList,
				KKW01031SFConst.IDO_DIV_01);
		Mover.setString(bean, KKW01031SFConst.IDO_DIV, idoDiv);
		//異動理由コードを転記
		String[] idoRsnCd = Mover.getStringArray(custKeiHktgiList,
				KKW01031SFConst.IDO_RSN_CD_01);
		Mover.setStringArray(bean, KKW01031SFConst.IDO_RSN_CD, idoRsnCd);
		// ++++++++++++++ 2012/05/29 v3.01.00 追加開始 ++++++++++++++++ //
		//異動理由メモを転記
		String idoRsnMemo = Mover.getString(custKeiHktgiList, KKW01031SFConst.IDO_RSN_MEMO_01);
		Mover.setString(bean, KKW01031SFConst.IDO_RSN_MEMO, idoRsnMemo);
		// ++++++++++++++ 2012/05/29 v3.01.00 追加終了 ++++++++++++++++ //
		//申込番号を転記
		String mskmNo = Mover.getString(custKeiHktgiList,
				KKW01031SFConst.MSKM_NO_01);
		Mover.setString(bean, KKW01031SFConst.MSKM_NO, mskmNo);
		
		// サービス呼び出し
		Service.KKSV0239.invokeAndApplySFBean(this, bean, FunctionCode.READ_FULL.getCode());

		//SFBean書き出し
		BeanMap beanMap=Mover.getBeanMapFromDataBean(bean, KKW01031SFConst.SFBEAN);

		
		//申込年月日の解決
		//申込年月日=運用日としておく
		String mskmYmd=JCCWebCommon.getOpeDate(this, null);
		beanMap.put(KKW01031SFConst.MSKM_YMD,mskmYmd );
		//申込年月日(年,月,日)の解決
		String mskmYmdYear=mskmYmd.substring(0, 4);
		String mskmYmdMon=mskmYmd.substring(4, 6);
		String mskmYmdDay=mskmYmd.substring(6, 8);
		
		beanMap.put(KKW01031SFConst.MSKM_YMD_YEAR,mskmYmdYear );
		beanMap.put(KKW01031SFConst.MSKM_YMD_MON,mskmYmdMon );
		beanMap.put(KKW01031SFConst.MSKM_YMD_DAY,mskmYmdDay );
		
		// ++++++++++++++ 2012/05/29 v3.01.00 追加開始 ++++++++++++++++ //
		//異動理由メモを転記
		beanMap.put(KKW01031SFConst.OPE_DATE, mskmYmd );
		// ++++++++++++++ 2012/05/29 v3.01.00 追加終了 ++++++++++++++++ //

		//SFBean書き戻し
		Mover.setBeanMapToDataBean(beanMap, bean);
		
		//画面名設定
		X31SDataBeanAccess commoninfoBean = super.getCommonInfoBean();
		commoninfoBean.sendMessageString(CommonInfoCFConst.NEXT_SCREEN_NAME, X31CWebConst.DATABEAN_SET_VALUE, JKKScreenConst.SCREEN_NAME_KKW01031);

		///// メッセージ表示処理 /////
		String[] messages = {"割引サービス契約の解約"};
		JCCWebCommon.setMessageInfo(this, "EKB0370--I", messages);
		String[] messages2 = {"割引サービス契約のキャンセル"};
		JCCWebCommon.setMessageInfo(this, "EKB0370--I", messages2);
		
		// DataBeanログ出力
		JSYwebLog.println(JSYwebLog.DataBean_Dump, getClass(), dumpDatabean(), null, null, null);
		return true;
	}

	
	/**
	 * <dd>メソッド名：確定ボタン押下 <dd>メソッド説明：確認画面の確定ボタン押下時処理を行う。 <dd>備考：なし。
	 * 
	 * @return true
	 */

	public boolean actionFix() throws Exception {
		// DataBeanログ出力
		JSYwebLog.println(JSYwebLog.DataBean_Dump, getClass(), dumpDatabean(), null, null, null);

		/* サービスを呼び出し、削除対象となる割引のチェック、登録を行い
		 * 問題なければ完了画面へ遷移 */
		// サービスフォームBeanのデータBeanアクセスクラスを取得。
		X31SDataBeanAccess bean = super.getServiceFormBean();
		BeanMap beanMap=Mover.getBeanMapFromDataBean(bean, KKW01031SFConst.SFBEAN);
		//申込年月日を転記
		String mskmYmdYear=(String)beanMap.take(KKW01031SFConst.MSKM_YMD_YEAR);
		String mskmYmdMon=(String)beanMap.take(KKW01031SFConst.MSKM_YMD_MON);
		String mskmYmdDay=(String)beanMap.take(KKW01031SFConst.MSKM_YMD_DAY);
		String mskmYmd=mskmYmdYear+mskmYmdMon+mskmYmdDay;
		beanMap.pair(KKW01031SFConst.MSKM_YMD, mskmYmd);
		// 更新されたキャンペーン一覧をSFBeanへ書き戻し
		Mover.setBeanMapToDataBean(beanMap, bean);
		// サービス呼び出し
		Service.KKSV0240.invokeAndApplySFBean(this, bean, FunctionCode.CHECK_AND_CHANGE.getCode());
		moveToNextSameScreen(Screen.KKW01032);
		
		///// メッセージ表示処理 /////
		String[] messages1 = {"割引サービス契約の解約"};
		JCCWebCommon.setMessageInfo(this, "EKB4390--I", messages1);
		String[] messages2 = {"割引サービス契約のキャンセル"};
		JCCWebCommon.setMessageInfo(this, "EKB4390--I", messages2);
		
		// DataBeanログ出力
		JSYwebLog.println(JSYwebLog.DataBean_Dump, getClass(), dumpDatabean(), null, null, null);
		return true;
	}

	/**
	 * <dd>メソッド名：一覧照会へボタン押下 <dd>メソッド説明：確認画面の修正ボタン押下時処理及び完了画面の一覧照会へボタン押下時処理を行う。 <dd>備考：なし。
	 * 
	 * @return true
	 */

	public boolean actionReturnToIcrn() throws Exception {
		// DataBeanログ出力
		JSYwebLog.println(JSYwebLog.DataBean_Dump, getClass(), dumpDatabean(), null, null, null);
		//画面遷移
		backToNextOtherScreen();
		// DataBeanログ出力
		JSYwebLog.println(JSYwebLog.DataBean_Dump, getClass(), dumpDatabean(), null, null, null);
		return true;
	}
	
	/**
	 * <dd>メソッド名：お客様一覧照会へボタン押下 <dd>メソッド説明：完了画面のお客様一覧照会へボタン押下時処理を行う。 <dd>備考：なし。
	 * 
	 * @return true
	 */

	public boolean actionReturnToCustIcrn() throws Exception {
		// DataBeanログ出力
		JSYwebLog.println(JSYwebLog.DataBean_Dump, getClass(), dumpDatabean(), null, null, null);
		//画面遷移
		moveToNextOtherScreen(Screen.CKW00101);
		// DataBeanログ出力
		JSYwebLog.println(JSYwebLog.DataBean_Dump, getClass(), dumpDatabean(), null, null, null);
		return true;
	}



	private void moveToNextSameScreen(String nextScreenId, String nextScreenNm) 
	{
		// 遷移先情報の設定
		X31SDataBeanAccess commoninfoBean = super.getCommonInfoBean();
		commoninfoBean.sendMessageString(CommonInfoCFConst.NEXT_SCREEN_ID, X31CWebConst.DATABEAN_SET_VALUE, nextScreenId);
		commoninfoBean.sendMessageString(CommonInfoCFConst.NEXT_SCREEN_NAME, X31CWebConst.DATABEAN_SET_VALUE, nextScreenNm);
	}

	private void moveToNextSameScreen(Screen next) 
	{
		moveToNextSameScreen(next.getScreenId(), next.getScreenName());
	}

	private void moveToNextOtherScreen(String nextScreenId) 
	{
		// 遷移先情報の設定
		X31SDataBeanAccess commoninfoBean = super.getCommonInfoBean();
		commoninfoBean.sendMessageString(CommonInfoCFConst.NEXT_SCREEN_ID, X31CWebConst.DATABEAN_SET_VALUE, nextScreenId);
	}

	private void moveToNextOtherScreen(Screen next) 
	{
		moveToNextOtherScreen(next.getScreenId());
	}


	private void backToNextOtherScreen() 
	{
		// 遷移先情報の設定
		X31SDataBeanAccess commoninfoBean = super.getCommonInfoBean();
		commoninfoBean.sendMessageString(CommonInfoCFConst.NEXT_SCREEN_ID, X31CWebConst.DATABEAN_SET_VALUE, JCCWebCommon
				.getScreenId(this));
	}
	
}

@SuppressWarnings("serial")
class BeanMap extends HashMap<String, Object>
{
	static final int DEFAULT_HASH_SIZE=50;

	public BeanMap(HashMap<String, Object> beanMap)
	{
		super(beanMap);
	}

	public BeanMap()
	{
		super(DEFAULT_HASH_SIZE);
	}

	public BeanMap pair(String item, Object value)
	{
		super.put(item, value);
		return this;
	}

	public Object take(String item)
	{
		return super.get(item);
	}
}

class Mover
{

	enum ValueType
	{
		NULL(null), ARRAY_LIST(ArrayList.class), STRING(String.class), LONG(Long.class), BOOLEAN(Boolean.class), STRINGS(
				String[].class), LONGS(Long[].class), BOOLEANS(Boolean[].class), ;

		Class<?> type;

		private ValueType(Class<?> type)
		{
			this.type = type;
		}

		public boolean isMatch(Object value)
		{
			if (null == value)
			{
				return (this.equals(NULL));
			}
			if (this.equals(NULL))
			{
				return false;
			}
			else
			{
				return this.type.isInstance(value);
			}
		}

		static public ValueType resolve(Object value)
		{
			ValueType[] types = ValueType.values();
			for (ValueType type : types)
			{
				if (type.isMatch(value))
				{
					return type;
				}
			}
			return ValueType.NULL;
		}
	}

	enum StructureType
	{
		NULL(null), DATABEAN(Object[].class), STRING(String.class), LONG(Long.class), BOOLEAN(Boolean.class), STRINGS(
				String[].class), LONGS(Long[].class), BOOLEANS(Boolean[].class), ;

		Class<?> type;

		private StructureType(Class<?> type)
		{
			this.type = type;
		}

		public boolean isMatch(Object value)
		{
			if (null == value)
			{
				return (this.equals(NULL));
			}
			if (this.equals(NULL))
			{
				return false;
			}
			if (value instanceof Class<?>)
			{
				return this.type.equals(value);
			}
			else
			{
				return this.type.equals(value.getClass());
			}
		}

		static public StructureType resolve(Object value)
		{
			StructureType[] types = StructureType.values();
			for (StructureType type : types)
			{
				if (type.isMatch(value))
				{
					return type;
				}
			}
			return StructureType.NULL;
		}
	}

	public static void setString(X31SDataBeanAccess bean, String item, String value)
	{
		bean.sendMessageString(item, X31CWebConst.DATABEAN_SET_VALUE, value);
	}

	public static void setLong(X31SDataBeanAccess bean, String item, Long value)
	{
		bean.sendMessageLong(item, X31CWebConst.DATABEAN_SET_VALUE, value);
	}

	public static void setBoolean(X31SDataBeanAccess bean, String item, Boolean value)
	{
		bean.sendMessageBoolean(item, X31CWebConst.DATABEAN_SET_VALUE, value);
	}

	public static void setStringArrayAt(X31SDataBeanAccess bean, String item, int index, String value)
	{
		bean.sendMessageString(item, X31CWebConst.DATABEAN_SET_VALUE, index, value);
	}

	public static void setLongAt(X31SDataBeanAccess bean, String item, int index, Long value)
	{
		bean.sendMessageLong(item, X31CWebConst.DATABEAN_SET_VALUE, index, value);
	}

	public static void setBooleanAt(X31SDataBeanAccess bean, String item, int index, Boolean value)
	{
		bean.sendMessageBoolean(item, X31CWebConst.DATABEAN_SET_VALUE, index, value);
	}

	public static void setStringArray(X31SDataBeanAccess bean, String item, String[] values)
	{
		X31CVector<String> vector = new X31CVector<String>();
		for (String value : values)
		{
			vector.add(value);
		}
		bean.sendMessageStringArray(item, X31CWebConst.DATABEAN_SET_DEF_VALUE, vector);
	}

	public static void setLongArray(X31SDataBeanAccess bean, String item, Long[] values)
	{
		X31CVector<Long> vector = new X31CVector<Long>();
		for (Long value : values)
		{
			vector.add(value);
		}
		bean.sendMessageLongArray(item, X31CWebConst.DATABEAN_SET_DEF_VALUE, vector);
	}

	public static void setBooleanArray(X31SDataBeanAccess bean, String item, Boolean[] values)
	{
		X31CVector<Boolean> vector = new X31CVector<Boolean>();
		for (Boolean value : values)
		{
			vector.add(value);
		}
		bean.sendMessageBooleanArray(item, X31CWebConst.DATABEAN_SET_DEF_VALUE, vector);
	}

	public static void clearBeanArray(X31SDataBeanAccess bean, String item)
	{
		X31SDataBeanAccessArray beanArray = bean.getDataBeanArray(item);
		beanArray.clearArray();
	}

	public static X31SDataBeanAccessArray getBeanArray(X31SDataBeanAccess bean, String item)
	{
		return bean.getDataBeanArray(item);
	}

	public static String getString(X31SDataBeanAccess bean, String item)
	{
		return bean.sendMessageString(item, X31CWebConst.DATABEAN_GET_VALUE);
	}

	public static Long getLong(X31SDataBeanAccess bean, String item)
	{
		return bean.sendMessageLong(item, X31CWebConst.DATABEAN_GET_VALUE);
	}

	public static Boolean getBoolean(X31SDataBeanAccess bean, String item)
	{
		return bean.sendMessageBoolean(item, X31CWebConst.DATABEAN_GET_VALUE);
	}

	public static String getStringAt(X31SDataBeanAccess bean, String item, int index)
	{
		return bean.sendMessageString(item, X31CWebConst.DATABEAN_GET_VALUE, index);
	}

	public static Long getLongAt(X31SDataBeanAccess bean, String item, int index)
	{
		return bean.sendMessageLong(item, X31CWebConst.DATABEAN_GET_VALUE, index);
	}

	public static Boolean getBooleanAt(X31SDataBeanAccess bean, String item, int index)
	{
		return bean.sendMessageBoolean(item, X31CWebConst.DATABEAN_GET_VALUE, index);
	}

	public static int getArrayCount(X31SDataBeanAccess bean, String item)
	{
		Integer count = (Integer)bean.sendMessage(item, X31CWebConst.DATABEAN_GET_COUNT);
		return count.intValue();
	}

	public static String[] getStringArray(X31SDataBeanAccess bean, String item)
	{
		int count = getArrayCount(bean, item);
		ArrayList<String> result = new ArrayList<String>(count);
		for (int i = 0; i < count; i++)
		{
			String element = getStringAt(bean, item, i);
			result.add(element);
		}
		return (String[])result.toArray(new String[0]);
	}

	public static Long[] getLongArray(X31SDataBeanAccess bean, String item)
	{
		int count = getArrayCount(bean, item);
		ArrayList<Long> result = new ArrayList<Long>(count);
		for (int i = 0; i < count; i++)
		{
			Long element = getLongAt(bean, item, i);
			result.add(element);
		}
		return (Long[])result.toArray(new Long[0]);
	}

	public static Boolean[] getBooleanArray(X31SDataBeanAccess bean, String item)
	{
		int count = getArrayCount(bean, item);
		ArrayList<Boolean> result = new ArrayList<Boolean>(count);
		for (int i = 0; i < count; i++)
		{
			Boolean element = getBooleanAt(bean, item, i);
			result.add(element);
		}
		return (Boolean[])result.toArray(new Boolean[0]);
	}

	public static X31SDataBeanAccess createBeanFromArray(X31SDataBeanAccessArray beanArray)
	{
		return beanArray.addDataBean();
	}

	public static BeanMap getBeanMapFromDataBean(X31SDataBeanAccess bean, Object[] structure)
	{
		BeanMap result = new BeanMap();
		for (Object node : structure)
		{
			Object[] pair = (Object[])node;
			String item = (String)pair[0];
			Object value = pair[1];

			StructureType type = StructureType.resolve(value);

			switch (type)
			{
			case DATABEAN:
			{
				X31SDataBeanAccessArray beanArray = Mover.getBeanArray(bean, item);
				ArrayList<BeanMap> content = getBeanMapListFromDataBeanArray(beanArray, (Object[])value);
				result.pair(item, content);
			}
				break;
			case STRING:
			{
				String content = Mover.getString(bean, item);
				result.pair(item, content);
			}
				break;
			case LONG:
			{
				Long content = Mover.getLong(bean, item);
				result.pair(item, content);
			}
				break;
			case BOOLEAN:
			{
				Boolean content = Mover.getBoolean(bean, item);
				result.pair(item, content);
			}
				break;
			case STRINGS:
			{
				String[] content = Mover.getStringArray(bean, item);
				result.pair(item, content);
			}
				break;
			case LONGS:
			{
				Long[] content = Mover.getLongArray(bean, item);
				result.pair(item, content);
			}
				break;
			case BOOLEANS:
			{
				Boolean[] content = Mover.getBooleanArray(bean, item);
				result.pair(item, content);
			}
				break;

			default:
				break;
			}
		}
		return result;
	}

	public static ArrayList<BeanMap> getBeanMapListFromDataBeanArray(X31SDataBeanAccessArray beanArray, Object[] structure)
	{
		int count = beanArray.getCount().intValue();
		ArrayList<BeanMap> result = new ArrayList<BeanMap>(count);
		for (int i = 0; i < count; i++)
		{
			X31SDataBeanAccess bean = beanArray.getDataBean(i);
			BeanMap content = getBeanMapFromDataBean(bean, structure);
			result.add(content);
		}
		return result;
	}

	@SuppressWarnings("unchecked")
	public static void setBeanMapToDataBean(BeanMap beanMap, X31SDataBeanAccess bean)
	{
		for (String key : beanMap.keySet())
		{
			Object value = beanMap.get(key);
			ValueType type = ValueType.resolve(value);

			switch (type)
			{
			case NULL:
				break;
			case STRING:
				Mover.setString(bean, key, (String)value);
				break;
			case LONG:
				Mover.setLong(bean, key, (Long)value);
				break;
			case BOOLEAN:
				Mover.setBoolean(bean, key, (Boolean)value);
				break;
			case STRINGS:
			{
				X31CVector<String> vec = new X31CVector<String>();
				for (String s : (String[])value)
				{
					vec.add(s);
				}
				bean.sendMessageStringArray(key, X31CWebConst.DATABEAN_SET_DEF_VALUE, vec);
			}
				break;
			case LONGS:
			{
				X31CVector<Long> vec = new X31CVector<Long>();
				for (Long s : (Long[])value)
				{
					vec.add(s);
				}
				bean.sendMessageLongArray(key, X31CWebConst.DATABEAN_SET_DEF_VALUE, vec);
			}
				break;
			case BOOLEANS:
			{
				X31CVector<Boolean> vec = new X31CVector<Boolean>();
				for (Boolean s : (Boolean[])value)
				{
					vec.add(s);
				}
				bean.sendMessageBooleanArray(key, X31CWebConst.DATABEAN_SET_DEF_VALUE, vec);
			}
				break;
			case ARRAY_LIST:
			{
				X31SDataBeanAccessArray subBeanArray = null;
				subBeanArray = bean.getDataBeanArray(key);
				setBeanMapListForDataBeanArray(subBeanArray, (ArrayList<BeanMap>)value);
			}
				break;

			default:
				throw new JCCFrameworkException("JCCWebCommon#getScreenInfoでサポートされていないオブジェクトの型です。");
			}
		}
	}

	public static void setBeanMapListForDataBeanArray(X31SDataBeanAccessArray beanArray, ArrayList<BeanMap> beanMapList)
	{
		beanArray.clearArray();
		for (BeanMap beanMap : beanMapList)
		{
			X31SDataBeanAccess bean = beanArray.addDataBean();
			// 再帰呼び出し
			setBeanMapToDataBean(beanMap, bean);
		}
	}

	public static void addBeanMapForDataBeanArray(X31SDataBeanAccessArray beanArray, BeanMap beanMap)
	{
		X31SDataBeanAccess bean = beanArray.addDataBean();
		setBeanMapToDataBean(beanMap, bean);
	}

}

class Items
{

	interface Transformer<I, O>
	{

		O transform(I input);
	}

	interface Closure<I>
	{

		void execute(I input);
	}

	interface Predicater<I>
	{

		boolean evaluate(I input);
	}

	public static <I, O> ArrayList<O> map(ArrayList<I> in, final Transformer<I, O> transformer)
	{
		final ArrayList<O> result = new ArrayList<O>(in.size());
		each(in, new Closure<I>()
		{

			@Override
			public void execute(I input)
			{
				result.add(transformer.transform(input));
			}
		});
		return result;
	}

	public static <I> void each(ArrayList<I> in, Closure<I> closure)
	{
		for (I item : in)
		{
			closure.execute(item);
		}
	}

	public static <I> ArrayList<I> select(ArrayList<I> in, Predicater<I> predicater)
	{
		ArrayList<I> result = new ArrayList<I>(in.size());
		for (I item : in)
		{
			if (predicater.evaluate(item))
			{
				result.add(item);
			}
		}
		return result;
	}

	public static <I> boolean exist(ArrayList<I> in, Predicater<I> predicater)
	{
		for (I item : in)
		{
			if (predicater.evaluate(item))
			{
				return true;
			}
		}
		return false;
	}

	public static <I> I find(ArrayList<I> in, Predicater<I> predicater)
	{
		for (I item : in)
		{
			if (predicater.evaluate(item))
			{
				return item;
			}
		}
		return null;
	}

}
