/*
 * Copyright (c) 2009 The openGion Project.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
package org.opengion.fukurou.util;

import java.io.File;
import java.io.FileFilter;
import java.util.List;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.StringTokenizer;

import java.util.regex.Pattern;
import java.util.regex.Matcher;

/**
 * HybsFileFilter.java は、複数の FileFilter を順次実行する フィルタクラスです。
 *
 * FileFilter インターフェースを継承し、File クラスの listFiles(FileFilter) メソッドに
 * 渡すことができます。
 * Filterに設定された複数のフィルタすべてを満たす場合の時のみ、accept(File pathname)
 * メソッドは、true を返します。
 *
 * この実装は同期化されません。
 *
 * @version  4.0
 * @author   Kazuhiko Hasegawa
 * @since    JDK5.0,
 */
public final class HybsFileFilter implements FileFilter {
	private final List<FileFilter> list = new ArrayList<FileFilter>();
	private final boolean isUseDIR ;

	/**
	 * 引数に、ディレクトリの判定を行うかどうかを指定するコンストラクタです。
	 * ここで、true を指定すると、ファイル、ディレクトリの両方に対して
	 * 処理を実施します。
	 * ディレクトリの判定の場合、acceptメソッドで、false が返ると
	 * それ以下の処理も実行されません。
	 *
	 * @og.rev 5.1.2.0 (2010/01/01) 引数つきコンストラクタ追加
	 *
	 * @param    useDIR boolean 判定をディレクトリでも行うかどうか
	 */
	public HybsFileFilter( final boolean useDIR ) {
		super();
		isUseDIR = useDIR;
	}

	/**
	 * 指定された抽象パス名がパス名リストに含まれる必要がある場合、スルー(選択)されます。
	 * ここでの判定ロジックでは、ファイルについてのみ処理します。
	 * ディレクトリは、常に、true を返します。
	 */
	public HybsFileFilter() {
		this( false );
	}

	/**
	 * 指定された抽象パス名がパス名リストに含まれる必要がある場合、スルー(選択)されます。
	 * ここでの判定ロジックでは、ファイルについてのみ処理します。
	 * ディレクトリは、常に、true を返します。
	 *
	 * @param    pathname File ファイルオブジェクト
	 * @see java.io.FileFilter#accept(File)
	 */
	public boolean accept( final File pathname ) {
		if( pathname != null && (pathname.isFile() || isUseDIR) ) {	// 5.1.2.0 (2010/01/01)
			int size = list.size();
			for( int i=0; i<size; i++ ) {
				FileFilter filter = list.get(i);
				if( !filter.accept( pathname ) ) {
					return false;
				}
			}
		}
		return true;
	}

	/**
	 * 外部指定フィルタ： 内部判定条件に、フィルタを追加します。
	 * 引数が null の場合は、追加しません。
	 *
	 * @param    filter 外部指定フィルタ
	 */
	public void addFileFilter( final FileFilter filter ) {
		if( filter != null ) { list.add( filter ); }
	}

	/**
	 * 内部判定フィルタ： 指定された接頭辞で始まる場合、スルー(選択)されます。
	 * 引数が null の場合は、追加しません。
	 * 引数に、'|' 区切り文字で複数設定した場合は、OR 判断(どれかが一致)します。
	 *
	 * @param    prefix 接頭辞
	 * @see java.lang.String#startsWith(String)
	 */
	public void startsWith( final String prefix ) {
		startsWith( prefix, false );	// 反転しない
//		if( prefix != null ) {
//			list.add( new StartsWithFilter( prefix ) );
//		}
	}

	/**
	 * 内部判定フィルタ： 指定された接頭辞で始まる場合、スルー(選択)されます。
	 * 引数が null の場合は、追加しません。
	 * 引数に、'|' 区切り文字で複数設定した場合は、OR 判断(どれかが一致)します。
	 * reverse = true に設定すると、結果を反転させます。
	 *
	 * @og.rev 5.1.2.0 (2010/01/01) reverse属性の追加
	 *
	 * @param    prefix 接頭辞
	 * @param    reverse true の場合、結果を反転する
	 * @see java.lang.String#startsWith(String)
	 */
	public void startsWith( final String prefix,final boolean reverse ) {
		if( prefix != null ) {
			list.add( new StartsWithFilter( prefix,reverse ) );
		}
	}

	/**
	 * 指定された接頭辞で始まる場合に選択される FileFilter インターフェースの実装内部クラスです。
	 * 引数に、'|' 区切り文字で複数設定した場合は、OR 判断(どれかが一致)します。
	 *
	 * @og.rev 5.1.2.0 (2010/01/01) '|' 区切り文字で複数設定処理の追加、reverse属性の追加
	 *
	 * @version  4.0
	 * @author   Kazuhiko Hasegawa
	 * @since    JDK5.0,
	 */
	private static class StartsWithFilter implements FileFilter {
//		private final String pfix ;
		private final String[] pfix ;
		private final int      cnt  ;
		private final boolean  rvse ;

		/**
		 * 接頭辞フィルターオブジェクトを作成します。
		 *
		 * @param desc boolean true:昇順 / false:降順
		 * @param reverse true の場合、結果を反転する
		 */
		StartsWithFilter( final String prefix,final boolean reverse ) {
//			pfix = prefix;
			rvse = reverse;

			StringTokenizer token = new StringTokenizer( prefix, "|" );
			cnt = token.countTokens();

			pfix = new String[cnt];

			for( int i=0; i<cnt; i++ ) {
				pfix[i] = token.nextToken();
			}
		}

		/**
		 * FileFilter インターフェースの accept( File ) メソッド
		 *
		 * @param pathname File ファイルオブジェクト
		 * @return boolean	true:処理対象 / false:処理非対象
		 * @see java.io.FileFilter#accept( File )
		 */
		public boolean accept( final File pathname ) {
//			return pathname.getName().startsWith( pfix );

			for( int i=0; i<cnt; i++ ) {
				if( pathname.getName().startsWith( pfix[i] ) ) {
					return !rvse;
				}
			}
			return rvse;
		}
	}

	/**
	 * 内部判定フィルタ： 指定された接頭辞で終わる場合、スルー(選択)されます。
	 * 引数が null の場合は、追加しません。
	 * 引数に、'|' 区切り文字で複数設定した場合は、OR 判断(どれかが一致)します。
	 *
	 * @param    suffix 接尾辞
	 * @see java.lang.String#endsWith(String)
	 */
	public void endsWith( final String suffix ) {
		endsWith( suffix, false );	// 反転しない
//		if( suffix != null ) {
//			list.add( new EndsWithFilter( suffix ) );
//		}
	}

	/**
	 * 内部判定フィルタ： 指定された接頭辞で終わる場合、スルー(選択)されます。
	 * 引数が null の場合は、追加しません。
	 * 引数に、'|' 区切り文字で複数設定した場合は、OR 判断(どれかが一致)します。
	 * reverse = true に設定すると、結果を反転させます。
	 *
	 * @og.rev 5.1.2.0 (2010/01/01) reverse属性の追加
	 *
	 * @param    suffix 接尾辞
	 * @param    reverse true の場合、結果を反転する
	 * @see java.lang.String#endsWith(String)
	 */
	public void endsWith( final String suffix,final boolean reverse ) {
		if( suffix != null ) {
			list.add( new EndsWithFilter( suffix,reverse ) );
		}
	}

	/**
	 * 指定された接頭辞で終わる場合に選択される FileFilter インターフェースの実装内部クラスです。
	 * 引数に、'|' 区切り文字で複数設定した場合は、OR 判断(どれかが一致)します。
	 *
	 * @og.rev 5.1.2.0 (2010/01/01) '|' 区切り文字で複数設定処理の追加、reverse属性の追加
	 *
	 * @version  4.0
	 * @author   Kazuhiko Hasegawa
	 * @since    JDK5.0,
	 */
	private static class EndsWithFilter implements FileFilter {
//		private final String sfix ;
		private final String[] sfix ;
		private final int      cnt  ;
		private final boolean  rvse ;

		/**
		 * 接頭辞フィルターオブジェクトを作成します。
		 *
		 * @param desc boolean true:昇順 / false:降順
		 * @param reverse true の場合、結果を反転する
		 */
		EndsWithFilter( String suffix,final boolean reverse ) {
//			sfix = suffix;
			rvse = reverse;

			StringTokenizer token = new StringTokenizer( suffix, "|" );
			cnt = token.countTokens();

			sfix = new String[cnt];

			for( int i=0; i<cnt; i++ ) {
				sfix[i] = token.nextToken();
			}
		}

		/**
		 * FileFilter インターフェースの accept( File ) メソッド
		 *
		 * @param pathname File ファイルオブジェクト
		 * @return boolean	true:処理対象 / false:処理非対象
		 * @see java.io.FileFilter#accept( File )
		 */
		public boolean accept( final File pathname ) {
//			return pathname.getName().endsWith( sfix );

			for( int i=0; i<cnt; i++ ) {
				if( pathname.getName().endsWith( sfix[i] ) ) {
					return !rvse;
				}
			}
			return rvse;
		}
	}

	/**
	 * 内部判定フィルタ： 指定された文字列がファイル名に含まれる場合、スルー(選択)されます。
	 * 引数が null の場合は、追加しません。
	 * 引数に、'|' 区切り文字で複数設定した場合は、OR 判断(どれかが一致)します。
	 *
	 * @param    str 指定の部分文字列
	 */
	public void instr( final String str ) {
		instr( str, false );	// 反転しない
//		if( str != null ) {
//			list.add( new InstrFilter( str ) );
//		}
	}

	/**
	 * 内部判定フィルタ： 指定された文字列がファイル名に含まれる場合、スルー(選択)されます。
	 * 引数が null の場合は、追加しません。
	 * 引数に、'|' 区切り文字で複数設定した場合は、OR 判断(どれかが一致)します。
	 * reverse = true に設定すると、結果を反転させます。
	 *
	 * @og.rev 5.1.2.0 (2010/01/01) reverse属性の追加
	 *
	 * @param    str String 指定の部分文字列
	 * @param    reverse boolean 結果を反転させるかどうか(true：反転)
	 */
	public void instr( final String str,final boolean reverse ) {
		if( str != null ) {
			list.add( new InstrFilter( str,reverse ) );
		}
	}

	/**
	 * 指定された文字列がファイル名に含まれる場合に選択される FileFilter インターフェースの実装内部クラスです。
	 * 引数に、'|' 区切り文字で複数設定した場合は、OR 判断(どれかが一致)します。
	 *
	 * @og.rev 5.1.2.0 (2010/01/01) '|' 区切り文字で複数設定処理の追加、reverse属性の追加
	 *
	 * @version  4.0
	 * @author   Kazuhiko Hasegawa
	 * @since    JDK5.0,
	 */
	private static class InstrFilter implements FileFilter {
//		private final String instr ;
		private final String[] instr ;
		private final int      cnt  ;
		private final boolean  rvse ;

		/**
		 * 文字列包含フィルターオブジェクトを作成します。
		 *
		 * @param desc boolean true:昇順 / false:降順
		 * @param reverse true の場合、結果を反転する
		 */
		InstrFilter( String str,final boolean reverse ) {
//			instr = str;
			rvse = reverse;

			StringTokenizer token = new StringTokenizer( str, "|" );
			cnt = token.countTokens();

			instr = new String[cnt];

			for( int i=0; i<cnt; i++ ) {
				instr[i] = token.nextToken();
			}
		}

		/**
		 * FileFilter インターフェースの accept( File ) メソッド
		 *
		 * @param pathname File ファイルオブジェクト
		 * @return boolean	true:処理対象 / false:処理非対象
		 * @see java.io.FileFilter#accept( File )
		 */
		public boolean accept( final File pathname ) {
//			return ( pathname.getName().indexOf( instr ) >= 0 );

			for( int i=0; i<cnt; i++ ) {
				if( pathname.getName().indexOf( instr[i] ) >= 0 ) {
					return !rvse;
				}
			}
			return rvse;
		}
	}

	/**
	 * 内部判定フィルタ： ファイル名が一致する場合、スルー(選択)されます。
	 * 大文字小文字は区別しません。
	 * 引数が null の場合は、追加しません。
	 * 引数に、'|' 区切り文字で複数設定した場合は、OR 判断(どれかが一致)します。
	 *
	 * @param    str ファイル名文字列
	 */
	public void fileEquals( final String str ) {
		fileEquals( str, false );	// 反転しない
//		if( str != null ) {
//			list.add( new EqualsFilter( str ) );
//		}
	}

	/**
	 * 内部判定フィルタ： ファイル名が一致する場合、スルー(選択)されます。
	 * 大文字小文字は区別しません。
	 * 引数が null の場合は、追加しません。
	 * 引数に、'|' 区切り文字で複数設定した場合は、OR 判断(どれかが一致)します。
	 * reverse = true に設定すると、結果を反転させます。
	 *
	 * @og.rev 5.1.2.0 (2010/01/01) reverse属性の追加
	 *
	 * @param    str ファイル名文字列
	 * @param    reverse true の場合、結果を反転する
	 */
	public void fileEquals( final String str,final boolean reverse ) {
		if( str != null ) {
			list.add( new EqualsFilter( str,reverse ) );
		}
	}

	/**
	 * ファイル名が一致する場合に選択される FileFilter インターフェースの実装内部クラスです。
	 * 引数に、'|' 区切り文字で複数設定した場合は、OR 判断(どれかが一致)します。
	 *
	 * @og.rev 5.1.2.0 (2010/01/01) '|' 区切り文字で複数設定処理の追加、reverse属性の追加
	 *
	 * @version  4.0
	 * @author   Kazuhiko Hasegawa
	 * @since    JDK5.0,
	 */
	private static class EqualsFilter implements FileFilter {
//		private final String eqstr ;
		private final String[] eqstr ;
		private final int      cnt  ;
		private final boolean  rvse ;

		/**
		 * ファイル名一致フィルターオブジェクトを作成します。
		 *
		 * @param desc boolean true:昇順 / false:降順
		 * @param reverse true の場合、結果を反転する
		 */
		EqualsFilter( String str,final boolean reverse ) {
//			eqstr = str;
			rvse = reverse;

			StringTokenizer token = new StringTokenizer( str, "|" );
			cnt = token.countTokens();

			eqstr = new String[cnt];

			for( int i=0; i<cnt; i++ ) {
				eqstr[i] = token.nextToken();
			}
		}

		/**
		 * FileFilter インターフェースの accept( File ) メソッド
		 *
		 * @param pathname File ファイルオブジェクト
		 * @return boolean	true:処理対象 / false:処理非対象
		 * @see java.io.FileFilter#accept( File )
		 */
		public boolean accept( final File pathname ) {
//			return pathname.getName().equalsIgnoreCase( eqstr );

			for( int i=0; i<cnt; i++ ) {
				if( pathname.getName().equalsIgnoreCase( eqstr[i] ) ) {
					return !rvse;
				}
			}
			return rvse;
		}
	}

	/**
	 * 内部判定フィルタ： ファイル名が、指定された
	 * <a href="/java/api14/api/java/util/regex/Pattern.html#sum">正規表現</a>
	 * と一致する場合、スルー(選択)されます
	 * 大文字小文字は区別しません。
	 * Pattern.compile( str,Pattern.CASE_INSENSITIVE ) ;
	 * pattern.matcher( pathname.getName() ).find() == true と同じ結果が得られます。
	 * 引数が null の場合は、追加しません。
	 *
	 * @param    str ファイル名文字列(正規表現)
	 * @see java.util.regex.Pattern#compile(String,int)
	 * @see java.util.regex.Matcher#find()
	 */
	public void matches( final String str ) {
		matches( str, false );	// 反転しない
//		if( str != null ) {
//			list.add( new MatchesFilter( str ) );
//		}
	}

	/**
	 * 内部判定フィルタ： ファイル名が、指定された
	 * <a href="/java/api14/api/java/util/regex/Pattern.html#sum">正規表現</a>
	 * と一致する場合、スルー(選択)されます
	 * 大文字小文字は区別しません。
	 * Pattern.compile( str,Pattern.CASE_INSENSITIVE ) ;
	 * pattern.matcher( pathname.getName() ).find() == true と同じ結果が得られます。
	 * 引数が null の場合は、追加しません。
	 * reverse = true に設定すると、結果を反転させます。
	 *
	 * @og.rev 5.1.2.0 (2010/01/01) reverse属性の追加
	 *
	 * @param    str ファイル名文字列(正規表現)
	 * @param    reverse true の場合、結果を反転する
	 * @see java.util.regex.Pattern#compile(String,int)
	 * @see java.util.regex.Matcher#find()
	 */
	public void matches( final String str,final boolean reverse ) {
		if( str != null ) {
			list.add( new MatchesFilter( str,reverse ) );
		}
	}

	/**
	 * ファイル名が、指定された正規表現と一致する場合に選択される FileFilter インターフェースの実装内部クラスです。
	 *
	 * @og.rev 5.1.2.0 (2010/01/01) reverse属性の追加
	 *
	 * @version  4.0
	 * @author   Kazuhiko Hasegawa
	 * @since    JDK5.0,
	 */
	private static class MatchesFilter implements FileFilter {
		private final Pattern pattern ;
		private final boolean  rvse ;

		/**
		 * 正規表現一致フィルターオブジェクトを作成します。
		 *
		 * @param desc boolean true:昇順 / false:降順
		 * @param reverse true の場合、結果を反転する
		 */
		MatchesFilter( final String str,final boolean reverse ) {
			pattern = Pattern.compile( str,Pattern.CASE_INSENSITIVE );
			rvse = reverse;
		}

		/**
		 * FileFilter インターフェースの accept( File ) メソッド
		 *
		 * @param pathname File ファイルオブジェクト
		 * @return boolean	true:処理対象 / false:処理非対象
		 * @see java.io.FileFilter#accept( File )
		 */
		public boolean accept( final File pathname ) {
			Matcher match = pattern.matcher( pathname.getName() );
//			return match.find() ;
			if( match.find() ) { return !rvse; }
			else { return rvse; }
		}
	}

	/**
	 * 内部判定フィルタ： ファイル名が、指定された
	 * <a href="/java/api14/api/java/util/regex/Pattern.html#sum">正規表現</a>
	 * と一致しない場合、スルー(選択)されます。
	 * 大文字小文字は区別しません。
	 * Pattern.compile( str,Pattern.CASE_INSENSITIVE ) ;
	 * pattern.matcher( pathname.getName() ).find() == false と同じ結果が得られます。
	 * 引数が null の場合は、追加しません。
	 *
	 * @param    str ファイル名文字列(正規表現) とマッチしない
	 * @see java.util.regex.Pattern#compile(String,int)
	 * @see java.util.regex.Matcher#find()
	 */
//	public void unMatches( final String str ) {
//		if( str != null ) {
//			list.add( new UnMatchesFilter( str ) );
//		}
//	}

	/**
	 * ファイル名が、指定された正規表現と一致しない場合に選択される FileFilter インターフェースの実装内部クラスです。
	 *
	 * @version  4.0
	 * @author   Kazuhiko Hasegawa
	 * @since    JDK5.0,
	 */
//	private static class UnMatchesFilter implements FileFilter {
//		private final Pattern pattern ;
//
//		/**
//		 * 正規表現不一致フィルターオブジェクトを作成します。
//		 *
//		 * @param desc boolean true:昇順 / false:降順
//		 */
//		UnMatchesFilter( String str ) {
//			pattern = Pattern.compile( str,Pattern.CASE_INSENSITIVE );
//		}
//
//		/**
//		 * FileFilter インターフェースの accept( File ) メソッド
//		 *
//		 * @param pathname File ファイルオブジェクト
//		 * @return boolean	true:処理対象 / false:処理非対象
//		 * @see java.io.FileFilter#accept( File )
//		 */
//		public boolean accept( final File pathname ) {
//			Matcher match = pattern.matcher( pathname.getName() );
//			return ! match.find() ;
//		}
//	}

	/**
	 * 内部判定フィルタ： 指定のタイムスタンプ以後に変更されている場合、スルー(選択)されます。
	 * ディレクトリは、ここの判定では無視します。（必ず true を返します）
	 * 日付けの指定に、YYYYMMDD 形式の ８文字数字文字列以外に、
	 * TODAY や YESTERDAY なども使用できます。
	 * TODAY は、実行日の 00:00:00 を基準時刻とし、YESTERDAY は、その前日になります。
	 * 引数が null の場合は、追加しません。
	 *
	 * @param    modify 時刻を表す long 値(ミリ秒単位)
	 */
	public void lastModified( final String modify ) {
		if( modify != null ) {
			list.add( new ModifyFileFilter( modify ) );
		}
	}

	/**
	 * 内部判定フィルタ： 指定の大きさより大きいファイルの場合、スルー(選択)されます。
	 * 引数が 0以下(マイナス) の場合は、追加しません。
	 *
	 * @param  len  int ファイルの大きさ(Kバイト単位)。同値を含む
	 */
	public void isLarger( final int len ) {
		if( len >= 0 ) {
			list.add( new IsLargerFilter( len ) );
		}
	}

	/**
	 * 指定の大きさより大きいファイルの場合に選択される FileFilter インターフェースの実装内部クラスです。
	 *
	 * @version  4.0
	 * @author   Kazuhiko Hasegawa
	 * @since    JDK5.0,
	 */
	private static class IsLargerFilter implements FileFilter {
		private final long size ;

		/**
		 * 大きいファイルフィルターオブジェクトを作成します。
		 *
		 * @param desc boolean true:昇順 / false:降順
		 */
		IsLargerFilter( int len ) {
			size = len ;
		}

		/**
		 * FileFilter インターフェースの accept( File ) メソッド
		 *
		 * @param pathname File ファイルオブジェクト
		 * @return boolean	true:処理対象 / false:処理非対象
		 * @see java.io.FileFilter#accept( File )
		 */
		public boolean accept( final File pathname ) {
			return pathname.length() >= size;
		}
	}

	/**
	 * 内部判定フィルタ： 指定の大きさより小さいファイルの場合、スルー(選択)されます。
	 * 引数が 0以下(マイナス) の場合は、追加しません。
	 *
	 * @param    len ファイルの大きさ(Kバイト単位)。同値を含まない。
	 */
	public void isSmaller( final int len ) {
		if( len >= 0 ) {
			list.add( new IsSmallerFilter( len ) );
		}
	}

	/**
	 * 指定の大きさより小さいファイルの場合選択される FileFilter インターフェースの実装内部クラスです。
	 *
	 * @version  4.0
	 * @author   Kazuhiko Hasegawa
	 * @since    JDK5.0,
	 */
	private static class IsSmallerFilter implements FileFilter {
		private final long size ;

		/**
		 * 小さいファイルフィルターオブジェクトを作成します。
		 *
		 * @param desc boolean true:昇順 / false:降順
		 */
		IsSmallerFilter( int len ) {
			size = len ;
		}

		/**
		 * FileFilter インターフェースの accept( File ) メソッド
		 *
		 * @param pathname File ファイルオブジェクト
		 * @return boolean	true:処理対象 / false:処理非対象
		 * @see java.io.FileFilter#accept( File )
		 */
		public boolean accept( final File pathname ) {
			return pathname.length() < size;
		}
	}

	/**
	 * このオブジェクトの文字列表現を返します。
	 * 基本的にデバッグ目的に使用します。
	 *
	 * @return このクラスの文字列表現
	 */
	public String toString() {
		StringBuilder buf = new StringBuilder();
		int size = list.size();
		for( int i=0; i<size; i++ ) {
			buf.append( "no[" ).append( i ).append( "]=" );
			buf.append( list.get(i) ).append( "\n" );
		}

		return buf.toString();
	}
}

/**
 * ModifyFileFilter.java は、最終変更日付けのフィルタークラスです。
 *
 * FileFilter インターフェースを継承し、コンストラクタで指定の日付けよりも
 * 最終変更日付け が新しいファイルを、選択します。
 * このクラスでは、ディレクトリは、変更日付けに無関係に選択します。
 *
 * 日付けの指定に、YYYYMMDD 形式の ８文字数字文字列以外に、TODAY や YESTERDAY なども使用できます。
 * TODAY は、実行日の 00:00:00 を基準時刻とし、YESTERDAY は、その前日になります。
 * バッチ処理等で、前日分の再編成や、先月分を再編成する場合に、実日付けを指定せずに
 * 使用できます。
 *
 * この実装は同期化されません。
 *
 * @version  4.0
 * @author   Kazuhiko Hasegawa
 * @since    JDK5.0,
 */
class ModifyFileFilter implements FileFilter {
	private final long modify ;

	/**
	 * コンストラクター
	 *
	 * 日付けの指定方法には、実日付け（YYYYMMDD形式 例：20040323）と
	 * 仮想日付け（TODAY,YESTERDAY など）が指定できます。
	 *
	 *     YYYYMMDD   YYYYMMDD形式の指定日の 00:00:00 を基準時刻
	 *     TODAY      実行日の 00:00:00 を基準時刻
	 *     YESTERDAY  実行日前日の 00:00:00 を基準時刻
	 *     LAST_WEEK  実行日の先週(7日前) 00:00:00 を基準時刻
	 *     MONTH      実行月の 1日 00:00:00 を基準時刻
	 *     LAST_MONTH 実行前月の 同日 00:00:00 を基準時刻
	 *     LAST_YEAR  実行前年の 同月同日 00:00:00 を基準時刻
	 *
	 * @param value 指定日付け
	 */
	public ModifyFileFilter( final String value ) {
		if( value != null ) {
			Calendar cal = Calendar.getInstance();
			cal.clear( Calendar.HOUR_OF_DAY );
			cal.clear( Calendar.MINUTE );
			cal.clear( Calendar.SECOND );
			cal.clear( Calendar.MILLISECOND );

			if( value.equalsIgnoreCase( "YESTERDAY" ) ) {
				cal.add( Calendar.DATE, -1 );
			}
			else if( value.equalsIgnoreCase( "LAST_WEEK" ) ) {
				cal.add( Calendar.DATE, -7 );
			}
			else if( value.equalsIgnoreCase( "MONTH" ) ) {
				cal.set( Calendar.DATE, 1 );
			}
			else if( value.equalsIgnoreCase( "LAST_MONTH" ) ) {
				cal.add( Calendar.MONTH, -1 );
			}
			else if( value.equalsIgnoreCase( "LAST_YEAR" ) ) {
				cal.add( Calendar.YEAR, -1 );
			}
			else if( value.length() == 8 ) {
				cal.set( Integer.parseInt( value.substring( 0,4 ) ) ,
						 Integer.parseInt( value.substring( 4,6 ) ) - 1,
						 Integer.parseInt( value.substring( 6,8 ) ) );
			}
			else if( ! value.equalsIgnoreCase( "TODAY" ) ) {
				String errMsg = "ModifyFileFilter Error! modify Format [" + value + "]\n"
						 + "日付けの指定方法には、実日付け（YYYYMMDD形式 例：20040323）と \n"
						 + "仮想日付け（TODAY,YESTERDAY など）が指定できます。\n"
						 + "    YYYYMMDD   YYYYMMDD形式の指定日の 00:00:00 を基準時刻 \n"
						 + "    TODAY      実行日の 00:00:00 を基準時刻 \n"
						 + "    YESTERDAY  実行日前日の 00:00:00 を基準時刻 \n"
						 + "    LAST_WEEK  実行日の先週(7日前) 00:00:00 を基準時刻 \n"
						 + "    MONTH      実行月の 1日 00:00:00 を基準時刻 \n"
						 + "    LAST_MONTH 実行前月の 同日 00:00:00 を基準時刻 \n"
						 + "    LAST_YEAR  実行前年の 同月同日 00:00:00 を基準時刻 \n" ;
				throw new RuntimeException( errMsg );
			}
			modify = cal.getTimeInMillis() ;
		}
		else {
			throw new RuntimeException( "ModifyFileFilter Error! modify valus is not null" );
		}
	}

	/**
	 * FileFilter インターフェースの accept( File ) メソッド
	 *
	 * @param file File ファイルオブジェクト
	 * @return boolean	true:処理対象 / false:処理非対象
	 * @see java.io.FileFilter#accept( File )
	 */
	public boolean accept( final File file ) {
		return file.isDirectory() || ( file.lastModified() >= modify ) ;
	}
}
