001/*
002 * Copyright (c) 2009 The openGion Project.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
013 * either express or implied. See the License for the specific language
014 * governing permissions and limitations under the License.
015 */
016package org.opengion.fukurou.util;
017
018import java.io.File;
019import java.io.FileFilter;
020import java.util.List;
021import java.util.ArrayList;
022import java.util.Calendar;
023import java.util.StringTokenizer;
024
025import java.util.regex.Pattern;
026import java.util.regex.Matcher;
027
028/**
029 * HybsFileFilter.java は、複数の FileFilter を順次実行する フィルタクラスです。
030 *
031 * FileFilter インターフェースを継承し、File クラスの listFiles(FileFilter) メソッドに
032 * 渡すことができます。
033 * Filterに設定された複数のフィルタすべてを満たす場合の時のみ、accept(File pathname)
034 * メソッドは、true を返します。
035 *
036 * この実装は同期化されません。
037 *
038 * @version  4.0
039 * @author   Kazuhiko Hasegawa
040 * @since    JDK5.0,
041 */
042public final class HybsFileFilter implements FileFilter {
043        private final List<FileFilter> list = new ArrayList<FileFilter>();
044        private final boolean isUseDIR ;
045
046        /**
047         * 引数に、ディレクトリの判定を行うかどうかを指定するコンストラクタです。
048         * ここで、true を指定すると、ファイル、ディレクトリの両方に対して
049         * 処理を実施します。
050         * ディレクトリの判定の場合、acceptメソッドで、false が返ると
051         * それ以下の処理も実行されません。
052         *
053         * @og.rev 5.1.2.0 (2010/01/01) 引数つきコンストラクタ追加
054         *
055         * @param       useDIR  判定をディレクトリでも行うかどうか
056         */
057        public HybsFileFilter( final boolean useDIR ) {
058                super();
059                isUseDIR = useDIR;
060        }
061
062        /**
063         * 指定された抽象パス名がパス名リストに含まれる必要がある場合、スルー(選択)されます。
064         * ここでの判定ロジックでは、ファイルについてのみ処理します。
065         * ディレクトリは、常に、true を返します。
066         */
067        public HybsFileFilter() {
068                this( false );
069        }
070
071        /**
072         * 指定された抽象パス名がパス名リストに含まれる必要がある場合、スルー(選択)されます。
073         * ここでの判定ロジックでは、ファイルについてのみ処理します。
074         * ディレクトリは、常に、true を返します。
075         *
076         * @param       pathname        ファイルオブジェクト
077         *
078         * @return      パス名リストに含まれるかどうか
079         * @see java.io.FileFilter#accept(File)
080         */
081        public boolean accept( final File pathname ) {
082                if( pathname != null && (pathname.isFile() || isUseDIR) ) {     // 5.1.2.0 (2010/01/01)
083                        int size = list.size();
084                        for( int i=0; i<size; i++ ) {
085                                FileFilter filter = list.get(i);
086                                if( !filter.accept( pathname ) ) {
087                                        return false;
088                                }
089                        }
090                }
091                return true;
092        }
093
094        /**
095         * 外部指定フィルタ: 内部判定条件に、フィルタを追加します。
096         * 引数が null の場合は、追加しません。
097         *
098         * @param    filter 外部指定フィルタ
099         */
100        public void addFileFilter( final FileFilter filter ) {
101                if( filter != null ) { list.add( filter ); }
102        }
103
104        /**
105         * 内部判定フィルタ: 指定された接頭辞で始まる場合、スルー(選択)されます。
106         * 引数が null の場合は、追加しません。
107         * 引数に、'|' 区切り文字で複数設定した場合は、OR 判断(どれかが一致)します。
108         *
109         * @param    prefix 接頭辞
110         * @see java.lang.String#startsWith(String)
111         */
112        public void startsWith( final String prefix ) {
113                startsWith( prefix, false );    // 反転しない
114        }
115
116        /**
117         * 内部判定フィルタ: 指定された接頭辞で始まる場合、スルー(選択)されます。
118         * 引数が null の場合は、追加しません。
119         * 引数に、'|' 区切り文字で複数設定した場合は、OR 判断(どれかが一致)します。
120         * reverse = true に設定すると、結果を反転させます。
121         *
122         * @og.rev 5.1.2.0 (2010/01/01) reverse属性の追加
123         *
124         * @param    prefix             接頭辞
125         * @param    reverse    true:結果を反転する
126         * @see java.lang.String#startsWith(String)
127         */
128        public void startsWith( final String prefix,final boolean reverse ) {
129                if( prefix != null ) {
130                        list.add( new StartsWithFilter( prefix,reverse ) );
131                }
132        }
133
134        /**
135         * 指定された接頭辞で始まる場合に選択される FileFilter インターフェースの実装内部クラスです。
136         * 引数に、'|' 区切り文字で複数設定した場合は、OR 判断(どれかが一致)します。
137         *
138         * @og.rev 5.1.2.0 (2010/01/01) '|' 区切り文字で複数設定処理の追加、reverse属性の追加
139         *
140         * @version  4.0
141         * @author   Kazuhiko Hasegawa
142         * @since    JDK5.0,
143         */
144        private static class StartsWithFilter implements FileFilter {
145                private final String[] pfix ;
146                private final int      cnt  ;
147                private final boolean  rvse ;
148
149                /**
150                 * 接頭辞フィルターオブジェクトを作成します。
151                 *
152                 * @param       desc    true:昇順 / false:降順
153                 * @param       reverse true:結果を反転する
154                 */
155                StartsWithFilter( final String prefix,final boolean reverse ) {
156                        rvse = reverse;
157
158                        StringTokenizer token = new StringTokenizer( prefix, "|" );
159                        cnt = token.countTokens();
160
161                        pfix = new String[cnt];
162
163                        for( int i=0; i<cnt; i++ ) {
164                                pfix[i] = token.nextToken();
165                        }
166                }
167
168                /**
169                 * FileFilter インターフェースの accept( File ) メソッド
170                 *
171                 * @param       pathname        ファイルオブジェクト
172                 * @return      true:処理対象 / false:処理非対象
173                 * @see java.io.FileFilter#accept( File )
174                 */
175                public boolean accept( final File pathname ) {
176                        for( int i=0; i<cnt; i++ ) {
177                                if( pathname.getName().startsWith( pfix[i] ) ) {
178                                        return !rvse;
179                                }
180                        }
181                        return rvse;
182                }
183        }
184
185        /**
186         * 内部判定フィルタ: 指定された接頭辞で終わる場合、スルー(選択)されます。
187         * 引数が null の場合は、追加しません。
188         * 引数に、'|' 区切り文字で複数設定した場合は、OR 判断(どれかが一致)します。
189         *
190         * @param    suffix 接尾辞
191         * @see java.lang.String#endsWith(String)
192         */
193        public void endsWith( final String suffix ) {
194                endsWith( suffix, false );      // 反転しない
195        }
196
197        /**
198         * 内部判定フィルタ: 指定された接頭辞で終わる場合、スルー(選択)されます。
199         * 引数が null の場合は、追加しません。
200         * 引数に、'|' 区切り文字で複数設定した場合は、OR 判断(どれかが一致)します。
201         * reverse = true に設定すると、結果を反転させます。
202         *
203         * @og.rev 5.1.2.0 (2010/01/01) reverse属性の追加
204         *
205         * @param       suffix  接尾辞
206         * @param       reverse true:結果を反転する
207         * @see java.lang.String#endsWith(String)
208         */
209        public void endsWith( final String suffix,final boolean reverse ) {
210                if( suffix != null ) {
211                        list.add( new EndsWithFilter( suffix,reverse ) );
212                }
213        }
214
215        /**
216         * 指定された接頭辞で終わる場合に選択される FileFilter インターフェースの実装内部クラスです。
217         * 引数に、'|' 区切り文字で複数設定した場合は、OR 判断(どれかが一致)します。
218         *
219         * @og.rev 5.1.2.0 (2010/01/01) '|' 区切り文字で複数設定処理の追加、reverse属性の追加
220         *
221         * @version  4.0
222         * @author   Kazuhiko Hasegawa
223         * @since    JDK5.0,
224         */
225        private static class EndsWithFilter implements FileFilter {
226                private final String[] sfix ;
227                private final int      cnt  ;
228                private final boolean  rvse ;
229
230                /**
231                 * 接頭辞フィルターオブジェクトを作成します。
232                 *
233                 * @param       desc    true:昇順 / false:降順
234                 * @param       reverse true:結果を反転する
235                 */
236                EndsWithFilter( final String suffix,final boolean reverse ) {
237                        rvse = reverse;
238
239                        StringTokenizer token = new StringTokenizer( suffix, "|" );
240                        cnt = token.countTokens();
241
242                        sfix = new String[cnt];
243
244                        for( int i=0; i<cnt; i++ ) {
245                                sfix[i] = token.nextToken();
246                        }
247                }
248
249                /**
250                 * FileFilter インターフェースの accept( File ) メソッド
251                 *
252                 * @param       pathname        ファイルオブジェクト
253                 * @return      true:処理対象 / false:処理非対象
254                 * @see java.io.FileFilter#accept( File )
255                 */
256                public boolean accept( final File pathname ) {
257                        for( int i=0; i<cnt; i++ ) {
258                                if( pathname.getName().endsWith( sfix[i] ) ) {
259                                        return !rvse;
260                                }
261                        }
262                        return rvse;
263                }
264        }
265
266        /**
267         * 内部判定フィルタ: 指定された文字列がファイル名に含まれる場合、スルー(選択)されます。
268         * 引数が null の場合は、追加しません。
269         * 引数に、'|' 区切り文字で複数設定した場合は、OR 判断(どれかが一致)します。
270         *
271         * @param    str 指定の部分文字列
272         */
273        public void instr( final String str ) {
274                instr( str, false );    // 反転しない
275        }
276
277        /**
278         * 内部判定フィルタ: 指定された文字列がファイル名に含まれる場合、スルー(選択)されます。
279         * 引数が null の場合は、追加しません。
280         * 引数に、'|' 区切り文字で複数設定した場合は、OR 判断(どれかが一致)します。
281         * reverse = true に設定すると、結果を反転させます。
282         *
283         * @og.rev 5.1.2.0 (2010/01/01) reverse属性の追加
284         *
285         * @param       str     指定の部分文字列
286         * @param       reverse 結果を反転させるかどうか(true:反転)
287         */
288        public void instr( final String str,final boolean reverse ) {
289                if( str != null ) {
290                        list.add( new InstrFilter( str,reverse ) );
291                }
292        }
293
294        /**
295         * 指定された文字列がファイル名に含まれる場合に選択される FileFilter インターフェースの実装内部クラスです。
296         * 引数に、'|' 区切り文字で複数設定した場合は、OR 判断(どれかが一致)します。
297         *
298         * @og.rev 5.1.2.0 (2010/01/01) '|' 区切り文字で複数設定処理の追加、reverse属性の追加
299         *
300         * @version  4.0
301         * @author   Kazuhiko Hasegawa
302         * @since    JDK5.0,
303         */
304        private static class InstrFilter implements FileFilter {
305                private final String[] instr ;
306                private final int      cnt  ;
307                private final boolean  rvse ;
308
309                /**
310                 * 文字列包含フィルターオブジェクトを作成します。
311                 *
312                 * @param       desc    true:昇順 / false:降順
313                 * @param reverse       true:結果を反転する
314                 */
315                InstrFilter( final String str,final boolean reverse ) {
316                        rvse = reverse;
317
318                        StringTokenizer token = new StringTokenizer( str, "|" );
319                        cnt = token.countTokens();
320
321                        instr = new String[cnt];
322
323                        for( int i=0; i<cnt; i++ ) {
324                                instr[i] = token.nextToken();
325                        }
326                }
327
328                /**
329                 * FileFilter インターフェースの accept( File ) メソッド
330                 *
331                 * @param       pathname        ファイルオブジェクト
332                 * @return      true:処理対象 / false:処理非対象
333                 * @see java.io.FileFilter#accept( File )
334                 */
335                public boolean accept( final File pathname ) {
336                        for( int i=0; i<cnt; i++ ) {
337                                if( pathname.getName().indexOf( instr[i] ) >= 0 ) {
338                                        return !rvse;
339                                }
340                        }
341                        return rvse;
342                }
343        }
344
345        /**
346         * 内部判定フィルタ: ファイル名が一致する場合、スルー(選択)されます。
347         * 大文字小文字は区別しません。
348         * 引数が null の場合は、追加しません。
349         * 引数に、'|' 区切り文字で複数設定した場合は、OR 判断(どれかが一致)します。
350         *
351         * @param    str ファイル名文字列
352         */
353        public void fileEquals( final String str ) {
354                fileEquals( str, false );       // 反転しない
355        }
356
357        /**
358         * 内部判定フィルタ: ファイル名が一致する場合、スルー(選択)されます。
359         * 大文字小文字は区別しません。
360         * 引数が null の場合は、追加しません。
361         * 引数に、'|' 区切り文字で複数設定した場合は、OR 判断(どれかが一致)します。
362         * reverse = true に設定すると、結果を反転させます。
363         *
364         * @og.rev 5.1.2.0 (2010/01/01) reverse属性の追加
365         *
366         * @param    str ファイル名文字列
367         * @param    reverse    true:結果を反転する
368         */
369        public void fileEquals( final String str,final boolean reverse ) {
370                if( str != null ) {
371                        list.add( new EqualsFilter( str,reverse ) );
372                }
373        }
374
375        /**
376         * ファイル名が一致する場合に選択される FileFilter インターフェースの実装内部クラスです。
377         * 引数に、'|' 区切り文字で複数設定した場合は、OR 判断(どれかが一致)します。
378         *
379         * @og.rev 5.1.2.0 (2010/01/01) '|' 区切り文字で複数設定処理の追加、reverse属性の追加
380         *
381         * @version  4.0
382         * @author   Kazuhiko Hasegawa
383         * @since    JDK5.0,
384         */
385        private static class EqualsFilter implements FileFilter {
386                private final String[] eqstr ;
387                private final int      cnt  ;
388                private final boolean  rvse ;
389
390                /**
391                 * ファイル名一致フィルターオブジェクトを作成します。
392                 *
393                 * @param       desc    true:昇順 / false:降順
394                 * @param reverse       true:結果を反転する
395                 */
396                EqualsFilter( final String str,final boolean reverse ) {
397                        rvse = reverse;
398
399                        StringTokenizer token = new StringTokenizer( str, "|" );
400                        cnt = token.countTokens();
401
402                        eqstr = new String[cnt];
403
404                        for( int i=0; i<cnt; i++ ) {
405                                eqstr[i] = token.nextToken();
406                        }
407                }
408
409                /**
410                 * FileFilter インターフェースの accept( File ) メソッド
411                 *
412                 * @param       pathname        ファイルオブジェクト
413                 * @return      true:処理対象 / false:処理非対象
414                 * @see java.io.FileFilter#accept( File )
415                 */
416                public boolean accept( final File pathname ) {
417                        for( int i=0; i<cnt; i++ ) {
418                                if( pathname.getName().equalsIgnoreCase( eqstr[i] ) ) {
419                                        return !rvse;
420                                }
421                        }
422                        return rvse;
423                }
424        }
425
426        /**
427         * 内部判定フィルタ: ファイル名が、指定された
428         * <a href="/java/api14/api/java/util/regex/Pattern.html#sum">正規表現</a>
429         * と一致する場合、スルー(選択)されます
430         * 大文字小文字は区別しません。
431         * Pattern.compile( str,Pattern.CASE_INSENSITIVE ) ;
432         * pattern.matcher( pathname.getName() ).find() == true と同じ結果が得られます。
433         * 引数が null の場合は、追加しません。
434         *
435         * @param    str ファイル名文字列(正規表現)
436         * @see java.util.regex.Pattern#compile(String,int)
437         * @see java.util.regex.Matcher#find()
438         */
439        public void matches( final String str ) {
440                matches( str, false );  // 反転しない
441        }
442
443        /**
444         * 内部判定フィルタ: ファイル名が、指定された
445         * <a href="/java/api14/api/java/util/regex/Pattern.html#sum">正規表現</a>
446         * と一致する場合、スルー(選択)されます
447         * 大文字小文字は区別しません。
448         * Pattern.compile( str,Pattern.CASE_INSENSITIVE ) ;
449         * pattern.matcher( pathname.getName() ).find() == true と同じ結果が得られます。
450         * 引数が null の場合は、追加しません。
451         * reverse = true に設定すると、結果を反転させます。
452         *
453         * @og.rev 5.1.2.0 (2010/01/01) reverse属性の追加
454         *
455         * @param    str ファイル名文字列(正規表現)
456         * @param    reverse    true:結果を反転する
457         * @see java.util.regex.Pattern#compile(String,int)
458         * @see java.util.regex.Matcher#find()
459         */
460        public void matches( final String str,final boolean reverse ) {
461                if( str != null ) {
462                        list.add( new MatchesFilter( str,reverse ) );
463                }
464        }
465
466        /**
467         * ファイル名が、指定された正規表現と一致する場合に選択される FileFilter インターフェースの実装内部クラスです。
468         *
469         * @og.rev 5.1.2.0 (2010/01/01) reverse属性の追加
470         *
471         * @version  4.0
472         * @author   Kazuhiko Hasegawa
473         * @since    JDK5.0,
474         */
475        private static class MatchesFilter implements FileFilter {
476                private final Pattern pattern ;
477                private final boolean  rvse ;
478
479                /**
480                 * 正規表現一致フィルターオブジェクトを作成します。
481                 *
482                 * @param       desc    true:昇順 / false:降順
483                 * @param reverse       true:結果を反転する
484                 */
485                MatchesFilter( final String str,final boolean reverse ) {
486                        pattern = Pattern.compile( str,Pattern.CASE_INSENSITIVE );
487                        rvse = reverse;
488                }
489
490                /**
491                 * FileFilter インターフェースの accept( File ) メソッド
492                 *
493                 * @param       pathname        ファイルオブジェクト
494                 * @return      true:処理対象 / false:処理非対象
495                 * @see java.io.FileFilter#accept( File )
496                 */
497                public boolean accept( final File pathname ) {
498                        Matcher match = pattern.matcher( pathname.getName() );
499                        if( match.find() ) { return !rvse; }
500                        else { return rvse; }
501                }
502        }
503
504        /**
505         * 内部判定フィルタ: 指定のタイムスタンプ以後に変更されている場合、スルー(選択)されます。
506         * ディレクトリは、ここの判定では無視します。(必ず true を返します)
507         * 日付けの指定に、YYYYMMDD 形式の 8文字数字文字列以外に、
508         * TODAY や YESTERDAY なども使用できます。
509         * TODAY は、実行日の 00:00:00 を基準時刻とし、YESTERDAY は、その前日になります。
510         * 引数が null の場合は、追加しません。
511         *
512         * @param    modify 時刻を表す long 値(ミリ秒単位)
513         */
514        public void lastModified( final String modify ) {
515                if( modify != null ) {
516                        list.add( new ModifyFileFilter( modify ) );
517                }
518        }
519
520        /**
521         * 共通処理:単位記号の付与されたバイト文字列から、long値であるバイトを求めます。
522         * 現時点では、K , KB , M , MB , G , GB のみ単位指定可能です。
523         * それぞれ、元の値に対して、1024倍されます。
524         *
525         * 処理が正常に出来ない場合は、-1L を返します。
526         *
527         * @og.rev 5.7.4.3 (2014/03/28) 新規追加
528         *
529         * @param       slen 単位記号付きバイト値
530         * @return      longに換算したバイト値
531         */
532        private long getByteSize( final String slen ) {
533                if( slen == null ) { return -1L; }
534
535                String buf  = slen;
536                int    size = buf.length();
537
538                // 'B' は、単位換算に関係ない為、あれば削除します。
539                if( size > 0 && 'B' == buf.charAt( size-1 ) ) {
540                        buf = buf.substring( 0,size-1 );                        // 'B' が削除された文字列
541                        size--;
542                }
543
544                long rtn = -1L;
545
546                long tani = -1L;                                                                // 変換されたかどうかの判定も兼ねる。
547                if( size > 0 ) {
548                        char ch = buf.charAt( size-1 );                         // 'K' , 'M' , 'G' のチェック
549                        switch( ch ) {
550                                case 'K' : tani=1024L; break;
551                                case 'M' : tani=1024L * 1024L ; break;
552                                case 'G' : tani=1024L * 1024L * 1024L ; break;
553                                default  : break;
554                        }
555                        if( tani > 0L ) {       // つまり、単位換算が行われた場合。
556                                buf = buf.substring( 0,size-1 );                // 'K','M','G' が削除された文字列
557                                size--;                                                                 // ここで空文字列になる可能性がある。
558                        }
559                        else {
560                                tani = 1L;              // 単位換算がない場合は、1倍。
561                        }
562                }
563
564                if( size > 0 ) {
565                        // 先の単位換算で、1L(=1倍)を設定して、if を無くしたが、long の掛け算なので、なんとなく抵抗がある。
566                        rtn = tani * Long.parseLong( buf );                     // buf はすでに数字だけになっているハズ。
567                }
568
569                return rtn ;
570        }
571
572        /**
573         * 内部判定フィルタ: 指定の大きさより大きいファイルの場合、スルー(選択)されます。
574         *
575         * 指定はバイト単位ですが、**KB , **MB , **GB などの単位を付ける事も可能です。
576         * 現時点では、K , KB , M , MB , G , GB のみ指定可能です。
577         *
578         * @og.rev 5.7.4.3 (2014/03/28) isLarger,isSmaller属性を文字列に変更
579         *
580         * @param       slen    ファイルの大きさ(バイト単位)。同値を含む
581         */
582        public void isLarger( final String slen ) {
583                long len = getByteSize( slen );
584
585                if( len >= 0L ) {
586                        list.add( new IsLargerFilter( len ) );
587                }
588        }
589
590        /**
591         * 指定の大きさより大きいファイルの場合に選択される FileFilter インターフェースの実装内部クラスです。
592         *
593         * @version  4.0
594         * @author   Kazuhiko Hasegawa
595         * @since    JDK5.0,
596         */
597        private static class IsLargerFilter implements FileFilter {
598                private final long size ;
599
600                /**
601                 * 大きいファイルフィルターオブジェクトを作成します。
602                 *
603                 * @og.rev 5.7.4.3 (2014/03/28) isLarger,isSmaller属性をlongに変更
604                 *
605                 * @param       len     ファイルの大きさ(バイト単位)。同値を含む
606                 */
607                IsLargerFilter( final long len ) {
608                        size = len ;
609                }
610
611                /**
612                 * FileFilter インターフェースの accept( File ) メソッド
613                 *
614                 * @param       pathname        ファイルオブジェクト
615                 * @return      true:処理対象 / false:処理非対象
616                 * @see java.io.FileFilter#accept( File )
617                 */
618                public boolean accept( final File pathname ) {
619                        return pathname.length() >= size;
620                }
621        }
622
623        /**
624         * 内部判定フィルタ: 指定の大きさより小さいファイルの場合、スルー(選択)されます。
625         * 引数が 0以下(マイナス) の場合は、追加しません。
626         *
627         * @og.rev 5.7.4.3 (2014/03/28) isLarger,isSmaller属性を文字列に変更
628         *
629         * @param    slen ファイルの大きさ(バイト単位)。同値を含まない。
630         */
631        public void isSmaller( final String slen ) {
632                long len = getByteSize( slen );
633
634                if( len >= 0L ) {
635                        list.add( new IsSmallerFilter( len ) );
636                }
637        }
638
639        /**
640         * 指定の大きさより小さいファイルの場合選択される FileFilter インターフェースの実装内部クラスです。
641         *
642         * @version  4.0
643         * @author   Kazuhiko Hasegawa
644         * @since    JDK5.0,
645         */
646        private static class IsSmallerFilter implements FileFilter {
647                private final long size ;
648
649                /**
650                 * 小さいファイルフィルターオブジェクトを作成します。
651                 *
652                 * @og.rev 5.7.4.3 (2014/03/28) isLarger,isSmaller属性をlongに変更
653                 *
654                 * @param    len ファイルの大きさ(バイト単位)。同値を含まない。
655                 */
656                IsSmallerFilter( final long len ) {
657                        size = len ;
658                }
659
660                /**
661                 * FileFilter インターフェースの accept( File ) メソッド
662                 *
663                 * @param       pathname        ファイルオブジェクト
664                 * @return      true:処理対象 / false:処理非対象
665                 * @see java.io.FileFilter#accept( File )
666                 */
667                public boolean accept( final File pathname ) {
668                        return pathname.length() < size;
669                }
670        }
671
672        /**
673         * 内部判定フィルタ: ファイルが hidden の場合、スルー(選択)されます。
674         * 引数がtrueの場合は、hiddenファイルのみを選択します。
675         * falseの場合は、hiddenファイル以外を選択します。(つまり hiddenファイルをブロックします。)
676         * hidden をブロックしたい場合は、false を設定し、すべて選択したい場合は、filter設定をしない事になります。
677         * 引数が null の場合は、追加しません。
678         *
679         * @og.rev 5.7.5.0 (2014/04/04) 新規追加
680         *
681         * @param       flag [true:/false]
682         */
683        public void isHidden( final String flag ) {
684                isHidden( flag, false );                                // 反転しない
685        }
686
687        /**
688         * 内部判定フィルタ: ファイルが hidden の場合、スルー(選択)されます。
689         * 引数がtrueの場合は、hiddenファイルのみを選択します。
690         * falseの場合は、hiddenファイル以外を選択します。(つまり hiddenファイルをブロックします。)
691         * hidden をブロックしたい場合は、false を設定し、すべて選択したい場合は、filter設定をしない事になります。
692         * reverse = true に設定すると、結果を反転させます。
693         *
694         * @og.rev 5.7.5.0 (2014/04/04) 新規追加
695         *
696         * @param       flag [true:/false]
697         * @param       reverse true:結果を反転する
698         */
699        public void isHidden( final String flag,final boolean reverse ) {
700                if( flag != null ) {
701                        list.add( new IsHiddenFilter( flag,reverse ) );
702                }
703        }
704
705        /**
706         * ファイルが hidden の場合に選択される FileFilter インターフェースの実装内部クラスです。
707         * 引数がtrueの場合は、hiddenファイルのみを選択します。
708         * falseの場合は、hiddenファイル以外を選択します。(つまり hiddenファイルをブロックします。)
709         * hidden をブロックしたい場合は、false を設定し、すべて選択したい場合は、filter設定をしない事になります。
710         *
711         * @og.rev 5.7.5.0 (2014/04/04) 新規追加
712         *
713         * @version  6.0
714         * @author   Kazuhiko Hasegawa
715         * @since    JDK6.0,
716         */
717        private static class IsHiddenFilter implements FileFilter {
718                private final boolean  flg  ;
719                private final boolean  rvse ;
720
721                /**
722                 * hiddenフィルターオブジェクトを作成します。
723                 *
724                 * @param       flag    true:hiddenのみ / false:
725                 * @param       reverse true:結果を反転する
726                 */
727                IsHiddenFilter( final String flag,final boolean reverse ) {
728                        flg  = Boolean.parseBoolean( flag );
729                        rvse = reverse;
730                }
731
732                /**
733                 * FileFilter インターフェースの accept( File ) メソッド
734                 *
735                 * @param       pathname        ファイルオブジェクト
736                 * @return      true:処理対象 / false:処理非対象
737                 * @see java.io.FileFilter#accept( File )
738                 */
739                public boolean accept( final File pathname ) {
740                        return (pathname.isHidden()  ^  !flg) ^ rvse ;
741                                //  isHidden()          flg             !flg    rvse    ⇒ 結果
742                                // ======================================================
743                                //      true(hidden)    true    false   false   ⇒ true   選択
744                                //      true(hidden)    false   true    false   ⇒ false 除外
745                                //      false(normal)   true    false   false   ⇒ false 除外
746                                //      false(normal)   false   true    false   ⇒ true   選択
747
748                                //      true(hidden)    true    false   true    ⇒ false 除外
749                                //      true(hidden)    false   true    true    ⇒ true   選択
750                                //      false(normal)   true    false   true    ⇒ true   選択
751                                //      false(normal)   false   true    true    ⇒ false 除外
752                }
753        }
754
755        /**
756         * このオブジェクトの文字列表現を返します。
757         * 基本的にデバッグ目的に使用します。
758         *
759         * @return このクラスの文字列表現
760         */
761        @Override
762        public String toString() {
763                StringBuilder buf = new StringBuilder();
764                int size = list.size();
765                for( int i=0; i<size; i++ ) {
766                        buf.append( "no[" ).append( i ).append( "]=" );
767                        buf.append( list.get(i) ).append( "\n" );
768                }
769
770                return buf.toString();
771        }
772}
773
774/**
775 * ModifyFileFilter.java は、最終変更日付けのフィルタークラスです。
776 *
777 * FileFilter インターフェースを継承し、コンストラクタで指定の日付けよりも
778 * 最終変更日付け が新しいファイルを、選択します。
779 * このクラスでは、ディレクトリは、変更日付けに無関係に選択します。
780 *
781 * 日付けの指定に、YYYYMMDD 形式の 8文字数字文字列以外に、TODAY や YESTERDAY なども使用できます。
782 * TODAY は、実行日の 00:00:00 を基準時刻とし、YESTERDAY は、その前日になります。
783 * バッチ処理等で、前日分の再編成や、先月分を再編成する場合に、実日付けを指定せずに
784 * 使用できます。
785 *
786 * この実装は同期化されません。
787 *
788 * @version  4.0
789 * @author   Kazuhiko Hasegawa
790 * @since    JDK5.0,
791 */
792class ModifyFileFilter implements FileFilter {
793        private final long modify ;
794
795        /**
796         * コンストラクター
797         *
798         * 日付けの指定方法には、実日付け(YYYYMMDD形式 例:20040323)と
799         * 仮想日付け(TODAY,YESTERDAY など)が指定できます。
800         *
801         *     YYYYMMDD   YYYYMMDD形式の指定日の 00:00:00 を基準時刻
802         *     TODAY      実行日の 00:00:00 を基準時刻
803         *     YESTERDAY  実行日前日の 00:00:00 を基準時刻
804         *     LAST_WEEK  実行日の先週(7日前) 00:00:00 を基準時刻
805         *     MONTH      実行月の 1日 00:00:00 を基準時刻
806         *     LAST_MONTH 実行前月の 同日 00:00:00 を基準時刻
807         *     LAST_YEAR  実行前年の 同月同日 00:00:00 を基準時刻
808         *
809         * @og.rev 5.3.5.0 (2011/05/01) 「時」のクリアミスの修正
810         *
811         * @param value 指定日付け
812         */
813        public ModifyFileFilter( final String value ) {
814                if( value != null ) {
815                        Calendar cal = Calendar.getInstance();
816
817                        cal.set( Calendar.HOUR_OF_DAY, 0 );             // 5.3.5.0 (2011/05/01) 時間の解決規則が適用されるため、「時」だけは、setメソッドで 0 にセットする。
818                        cal.clear( Calendar.MINUTE );
819                        cal.clear( Calendar.SECOND );
820                        cal.clear( Calendar.MILLISECOND );
821
822                        if( "YESTERDAY".equalsIgnoreCase( value ) ) {
823                                cal.add( Calendar.DATE, -1 );
824                        }
825                        else if( "LAST_WEEK".equalsIgnoreCase( value ) ) {
826                                cal.add( Calendar.DATE, -7 );
827                        }
828                        else if( "MONTH".equalsIgnoreCase( value ) ) {
829                                cal.set( Calendar.DATE, 1 );
830                        }
831                        else if( "LAST_MONTH".equalsIgnoreCase( value ) ) {
832                                cal.add( Calendar.MONTH, -1 );
833                        }
834                        else if( "LAST_YEAR".equalsIgnoreCase( value ) ) {
835                                cal.add( Calendar.YEAR, -1 );
836                        }
837                        else if( value.length() == 8 ) {
838                                cal.set( Integer.parseInt( value.substring( 0,4 ) ) ,
839                                                 Integer.parseInt( value.substring( 4,6 ) ) - 1,
840                                                 Integer.parseInt( value.substring( 6,8 ) ) );
841                        }
842                        else if( ! "TODAY".equalsIgnoreCase( value ) ) {
843                                String errMsg = "ModifyFileFilter Error! modify Format [" + value + "]\n"
844                                                 + "日付けの指定方法には、実日付け(YYYYMMDD形式 例:20040323)と \n"
845                                                 + "仮想日付け(TODAY,YESTERDAY など)が指定できます。\n"
846                                                 + "    YYYYMMDD   YYYYMMDD形式の指定日の 00:00:00 を基準時刻 \n"
847                                                 + "    TODAY      実行日の 00:00:00 を基準時刻 \n"
848                                                 + "    YESTERDAY  実行日前日の 00:00:00 を基準時刻 \n"
849                                                 + "    LAST_WEEK  実行日の先週(7日前) 00:00:00 を基準時刻 \n"
850                                                 + "    MONTH      実行月の 1日 00:00:00 を基準時刻 \n"
851                                                 + "    LAST_MONTH 実行前月の 同日 00:00:00 を基準時刻 \n"
852                                                 + "    LAST_YEAR  実行前年の 同月同日 00:00:00 を基準時刻 \n" ;
853                                throw new RuntimeException( errMsg );
854                        }
855                        modify = cal.getTimeInMillis() ;
856                }
857                else {
858                        throw new RuntimeException( "ModifyFileFilter Error! modify valus is not null" );
859                }
860        }
861
862        /**
863         * FileFilter インターフェースの accept( File ) メソッド
864         *
865         * @param       file    ファイルオブジェクト
866         *
867         * @return      true:処理対象 / false:処理非対象
868         * @see java.io.FileFilter#accept( File )
869         */
870        public boolean accept( final File file ) {
871                return file.isDirectory() || file.lastModified() >= modify ;
872        }
873}