    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.process;
    017
    018import org.opengion.fukurou.util.Argument;
    019import org.opengion.fukurou.util.HybsFileFilter;
    020import org.opengion.fukurou.util.LogWriter;
    021
    022import java.io.File;
    023import java.util.Map ;
    024import java.util.LinkedHashMap ;
    025import java.util.Stack;
    026
    027/**
    028 * Process_FileSearch は、指定のフォルダ以下のファイルを一覧する、FirstProcess
    029 * インターフェースと、ChainProcess インターフェースの実装クラスです。
    030 *
    031 * 指定の条件に合致するファイルを検索し、LineModel のサブクラスである、
    032 * FileLineModel オブジェクトを作成して、下流に渡します。
    033 * FileLineModel オブジェクトには、ファイル属性(Level,File,Length,Modify)
    034 * が設定されます。
    035 *
    036 * 引数文字列中にスペースを含む場合は、ダブルコーテーション("") で括って下さい。
    037 * 引数文字列の 『=』の前後には、スペースは挟めません。必ず、-key=value の様に
    038 * 繋げてください。
    039 *
    040 * @og.formSample
    041 *  Process_FileSearch -start=d:/ -suffix=jsp
    042 *
    043 *     -start=開始フォルダ         ：検索を開始するフォルダ
    044 *   [ -prefix=接頭辞            ] ：File････,View････,など、指定の接頭辞で始まるファイルを検索
    045 *   [ -unprefix=不接頭辞        ] ：File････,View････,など、指定の接頭辞で始まらないファイルを検索
    046 *   [ -suffix=接尾辞            ] ：.txt,.java,.jsp.... など、指定の接尾辞で終わるファイルを検索
    047 *   [ -unsuffix=不接尾辞        ] ：.txt,.java,.jsp.... など、指定の接尾辞で終わらないファイルを検索
    048 *   [ -instr=部分文字列         ] ：ファイル名と一致する部分文字列を指定
    049 *   [ -uninstr=不部分文字列     ] ：ファイル名と一致しな部分文字列を指定
    050 *   [ -equals=一致              ] ：ファイル名と一致する文字列(大文字小文字は区別しない)を指定
    051 *   [ -notequals=不一致         ] ：ファイル名と一致しない文字列(大文字小文字は区別しない)を指定
    052 *   [ -match=正規表現           ] ：ファイル名と一致する正規表現を指定
    053 *   [ -unmatch=正規表現         ] ：ファイル名と一致しない正規表現を指定
    054 *   [ -modify=YYYYMMDD          ] ：指定日付け以降に変更されたファイルを検索
    055 *             YYYYMMDD   : YYYYMMDD 形式での指定日の 00:00:00 を基準時刻
    056 *             TODAY      : 実行日の 00:00:00 を基準時刻
    057 *             YESTERDAY  : 実行日前日の 00:00:00 を基準時刻
    058 *             LAST_WEEK  : 実行日の先週(7日前) 00:00:00 を基準時刻
    059 *             MONTH      : 実行月の 1日 00:00:00 を基準時刻
    060 *             LAST_MONTH : 実行前月の 同日 00:00:00 を基準時刻
    061 *             LAST_YEAR  : 実行前年の 同月同日 00:00:00 を基準時刻
    062 *   [ -useDIR=[false/true]      ] ：判定をファイルだけでなく、ディレクトリでも行うかどうかを指定(初期値:false)
    063 *   [ -larger=サイズ(Byte)      ] ：ファイルの大きさが指定のバイト数と同じか大きいファイルを検索
    064 *   [ -smaller=サイズ(Byte)     ] ：ファイルの大きさが指定のバイト数より小さいファイルを検索
    065 *   [ -isHidden=[true/false]    ] ：true:HIDDENファイルのみ検索/false:NORMALファイルのみ検索(初期値:null)
    066 *   [ -maxLevel=最大階層数      ] ：ディレクトリの階層を下がる最大数(初期値:256)
    067 *   [ -useLineCnt=行数計算      ] ：ファイルの行数をカウントするかどうかを指定(初期値:false)
    068 *   [ -useMD5=MD5計算値         ] ：ファイルのMD5計算を行うかどうかを指定(初期値:false)
    069 *   [ -useOmitCmnt=[false/true] ] ：コメント部分を削除した行数と文字数計算を行うかどうかを指定(初期値:false)
    070 *   [ -encode=エンコード名      ] ：コメント削除時の文字数計算で利用するファイルのエンコード(初期値:JISAutoDetect)
    071 *   [ -inPath=入力共通パス      ] ：BIKO作成用のファイルパスから削除する部分(文字数のみ)
    072 *   [ -outPath=出力追加パス     ] ：BIKO作成用のファイルパスに追加する部分
    073 *   [ -display=[false/true]     ] ：trueは、検索状況を表示します(初期値:false)
    074 *   [ -debug=[false/true]       ] ：デバッグ情報を標準出力に表示する(true)かしない(false)か(初期値:false[表示しない])
    075 *
    076 * @version  4.0
    077 * @author   Kazuhiko Hasegawa
    078 * @since    JDK5.0,
    079 */
    080public class Process_FileSearch extends AbstractProcess
    081                                                                implements FirstProcess , ChainProcess {
    082
    083        private Stack<FileListStack>      dirs            = null;
    084        private File                    file            = null;
    085        private HybsFileFilter  filter          = null;
    086        private FileLineModel   newData         = null;
    087        private int                             level           = 1;
    088
    089        private String                  startDir        = null;
    090        private int                             maxLevel        = 256;
    091        private int                             inCount         = 0;
    092        private int                             outCount        = 0;
    093        private int                             inPathLen       = 0;            // 4.2.3.0 (2008/05/26) BIKO欄用
    094        private String                  outPath         = null;         // 4.3.1.1 (2008/08/23) BIKO欄用
    095        private boolean                 display         = false;        // 表示しない
    096        private boolean                 debug           = false;        // 5.7.3.0 (2014/02/07) デバッグ情報
    097
    098        private static final Map<String,String> mustProparty   ;          // ［プロパティ］必須チェック用 Map
    099        private static final Map<String,String> usableProparty ;          // ［プロパティ］整合性チェック Map
    100
    101        static {
    102                mustProparty = new LinkedHashMap<String,String>();
    103                mustProparty.put( "start",      "検索を開始するフォルダ(必須)" );
    104
    105                usableProparty = new LinkedHashMap<String,String>();
    106                usableProparty.put( "prefix",   "File････,View････,など、指定の接頭辞で始まるファイルを検索" );
    107                usableProparty.put( "unprefix", "File････,View････,など、指定の接頭辞で始まらないファイルを検索" );
    108                usableProparty.put( "suffix",   ".txt,.java,.jsp.... など、指定の接尾辞で終わるファイルを検索" );
    109                usableProparty.put( "unsuffix", ".txt,.java,.jsp.... など、指定の接尾辞で終わらないファイルを検索" );
    110                usableProparty.put( "instr",    "ファイル名と一致する部分文字列を指定" );
    111                usableProparty.put( "uninstr",  "ファイル名と一致しない部分文字列を指定" );
    112                usableProparty.put( "equals",   "ファイル名と一致する文字列(大文字小文字は区別しない)を指定" );
    113                usableProparty.put( "notequals",        "ファイル名と一致しない文字列(大文字小文字は区別しない)を指定" );
    114                usableProparty.put( "match",    "ファイル名と一致する正規表現を指定" );
    115                usableProparty.put( "unmatch",  "ファイル名と一致しない正規表現を指定" );
    116                usableProparty.put( "modify",   "指定日付け以降に変更されたファイルを検索" +
    117                                        CR + "YYYYMMDD   : YYYYMMDD 形式での指定日の 00:00:00 を基準時刻" +
    118                                        CR + "TODAY      : 実行日の 00:00:00 を基準時刻" +
    119                                        CR + "YESTERDAY  : 実行日前日の 00:00:00 を基準時刻" +
    120                                        CR + "LAST_WEEK  : 実行日の先週(7日前) 00:00:00 を基準時刻" +
    121                                        CR + "MONTH      : 実行月の 1日 00:00:00 を基準時刻" +
    122                                        CR + "LAST_MONTH : 実行前月の 同日 00:00:00 を基準時刻" +
    123                                        CR + "LAST_YEAR  : 実行前年の 同月同日 00:00:00 を基準時刻"
    124                );
    125                usableProparty.put( "useDIR"    ,"判定をファイルだけでなく、ディレクトリでも行うかどうかを指定(初期値:false)" );
    126                usableProparty.put( "larger"    ,"ファイルの大きさが指定のバイト数と同じか大きいファイルを検索" );
    127                usableProparty.put( "smaller"   ,"ファイルの大きさが指定のバイト数より小さいファイルを検索" );
    128                usableProparty.put( "isHidden"  ,"true:HIDDENファイルのみ検索/false:NORMALファイルのみ検索(初期値:null)" );
    129                usableProparty.put( "maxLevel"  ,"ディレクトリの階層を下がる最大数(初期値:256)" );
    130                usableProparty.put( "useLineCnt","ファイルの行数をカウントするかどうかを指定(初期値:false)" );
    131                usableProparty.put( "useMD5"    ,"ファイルのMD5計算を行うかどうかを指定(初期値:false)" );           // 5.7.2.1 (2014/01/17)
    132                usableProparty.put( "useOmitCmnt" ,"コメント部分を削除した行数と文字数計算を行うかどうかを指定(初期値:false)" );                // 5.7.4.0 (2014/03/07)
    133                usableProparty.put( "encode"    ,"コメント削除時の文字数計算で利用するファイルのエンコード(初期値:JISAutoDetect)" );   // 5.7.4.0 (2014/03/07)
    134                usableProparty.put( "inPath"    ,"BIKO作成用のファイルパスから削除する部分(文字数のみ)" );
    135                usableProparty.put( "outPath"   ,"BIKO作成用のファイルパスに追加する部分" );
    136                usableProparty.put( "display"   ,"trueは、検索状況を表示します(初期値:false)" );
    137                usableProparty.put( "debug"             ,"デバッグ情報を標準出力に表示する(true)かしない(false)か" +
    138                                                                                CR + "(初期値:false:表示しない)" );             // 5.7.3.0 (2014/02/07) デバッグ情報
    139        }
    140
    141        /**
    142         * デフォルトコンストラクター。
    143         * このクラスは、動的作成されます。デフォルトコンストラクターで、
    144         * super クラスに対して、必要な初期化を行っておきます。
    145         *
    146         */
    147        public Process_FileSearch() {
    148                super( "org.opengion.fukurou.process.Process_FileSearch",mustProparty,usableProparty );
    149        }
    150
    151        /**
    152         * プロセスの初期化を行います。初めに一度だけ、呼び出されます。
    153         * 初期処理(ファイルオープン、ＤＢオープン等)に使用します。
    154         *
    155         * @og.rev 4.2.2.0 (2008/05/10) 行数カウントの使用有無
    156         * @og.rev 4.3.1.1 (2008/08/23) BIKO 欄にoutPath 属性を追加します。
    157         * @og.rev 5.1.2.0 (2010/01/01) useDIR 属性を追加します。
    158         * @og.rev 5.7.2.1 (2014/01/17) useMD5 属性を追加します。
    159         * @og.rev 5.7.4.0 (2014/03/07) useOmitCmnt,encode 属性を追加します。
    160         * @og.rev 5.7.4.3 (2014/03/28) larger,smaller属性を文字列に変更
    161         * @og.rev 5.7.5.0 (2014/04/04) isHidden属性を追加します。
    162         *
    163         * @param   paramProcess データベースの接続先情報などを持っているオブジェクト
    164         */
    165        public void init( final ParamProcess paramProcess ) {
    166                Argument arg = getArgument();
    167
    168                startDir                = arg.getProparty("start" );
    169
    170                String inPath   = arg.getProparty("inPath");
    171                if( inPath != null ) { inPathLen = inPath.length(); }
    172
    173                String prefix   = arg.getProparty("prefix");
    174                String unprefix = arg.getProparty("unprefix");          // 5.1.2.0 (2010/01/01) 追加
    175                String suffix   = arg.getProparty("suffix");
    176                String unsuffix = arg.getProparty("unsuffix");          // 5.1.2.0 (2010/01/01) 追加
    177                String instr    = arg.getProparty("instr");
    178                String uninstr  = arg.getProparty("uninstr");           // 5.1.2.0 (2010/01/01) 追加
    179                String equals   = arg.getProparty("equals");
    180                String notequals= arg.getProparty("notequals");         // 5.1.2.0 (2010/01/01) 追加
    181                String match    = arg.getProparty("match");
    182                String unmatch  = arg.getProparty("unmatch");
    183                String modify   = arg.getProparty("modify");
    184                String larger   = arg.getProparty("larger");
    185                String smaller  = arg.getProparty("smaller");
    186                String isHidden = arg.getProparty("isHidden");          // 5.7.5.0 (2014/04/04) 追加
    187                maxLevel                = arg.getProparty("maxLevel",maxLevel);
    188                outPath                 = arg.getProparty("outPath");
    189                // 4.2.2.0 (2008/05/10) 行数カウントの使用有無
    190                boolean useLineCnt      = arg.getProparty( "useLineCnt",false );
    191                // 5.7.2.1 (2014/01/17) ファイルのMD5の計算有無
    192                boolean useMD5          = arg.getProparty( "useMD5",false );
    193                // 5.7.4.0 (2014/03/07) コメント部分を削除した行数と文字数計算を行うかどうか
    194                boolean useOmitCmnt     = arg.getProparty( "useOmitCmnt",false );
    195                // 5.7.4.0 (2014/03/07) コメント削除時の文字数計算で利用するファイルのエンコード(初期値:JISAutoDetect)
    196                String encode   = arg.getProparty( "encode" , "JISAutoDetect" );
    197
    198                // 5.1.2.0 (2010/01/01) 判定をディレクトリでも行うかどうか
    199                boolean useDIR = arg.getProparty( "useDIR",false );
    200
    201                display = arg.getProparty("display",display);
    202//              if( display ) { println( startDir ); }                                  // 4.0.0 (2005/01/31)
    203                debug   = arg.getProparty("debug",debug);                               // 5.7.3.0 (2014/02/07) デバッグ情報
    204//              if( debug ) { println( arg.toString() ); }                              // 5.7.3.0 (2014/02/07) デバッグ情報
    205
    206                // 5.1.2.0 (2010/01/01) 反転処理の引数追加
    207                filter = new HybsFileFilter( useDIR );                                  // 5.1.2.0 (2010/01/01) 判定をディレクトリでも行うかどうか
    208                filter.startsWith( prefix   , false);
    209                filter.startsWith( unprefix , true );
    210                filter.endsWith( suffix   , false);
    211                filter.endsWith( unsuffix , true );
    212                filter.instr( instr   , false);
    213                filter.instr( uninstr , true );
    214                filter.fileEquals( equals   , false);
    215                filter.fileEquals( notequals , true );
    216                filter.matches( match   , false);
    217                filter.matches( unmatch , true );
    218//              filter.unMatches( unmatch );                    // 5.1.2.0 (2010/01/01) 反転処理は、matches の 反転引数で対応
    219                filter.lastModified( modify );
    220                // 5.7.4.3 (2014/03/28) larger,smaller属性を文字列に変更
    221//              if( larger  != null ) { filter.isLarger( Integer.parseInt( larger ) ); }
    222//              if( smaller != null ) { filter.isSmaller( Integer.parseInt( smaller ) ); }
    223                filter.isLarger( larger );
    224                filter.isSmaller( smaller );
    225                filter.isHidden( isHidden );                    // 5.7.5.0 (2014/04/04) 追加
    226
    227                File tempFile = new File( startDir );
    228                if( display ) { println( "start=[" + tempFile + "]" ); }                // 5.7.3.0 (2014/02/07)
    229                if( tempFile.isDirectory() ) {
    230                        dirs = new Stack<FileListStack>();
    231                        File[] fileList = tempFile.listFiles( filter );
    232                        dirs.push( new FileListStack( fileList, level ) );
    233                }
    234                else {
    235                        dirs = new Stack<FileListStack>();
    236                        File[] fileList = new File[] { tempFile };
    237                        dirs.push( new FileListStack( fileList, level ) );
    238                }
    239
    240//              newData = new FileLineModel();
    241//              newData = new FileLineModel( useLineCnt );                      // 4.2.2.0 (2008/05/10)
    242//              newData = new FileLineModel( useLineCnt,useMD5 );       // 5.7.2.1 (2014/01/17)
    243                newData = new FileLineModel( useLineCnt,useMD5,useOmitCmnt );   // 5.7.4.0 (2014/03/07)
    244                newData.setEncode( encode );
    245        }
    246
    247        /**
    248         * このデータの処理において、次の処理が出来るかどうかを問い合わせます。
    249         * この呼び出し１回毎に、次のデータを取得する準備を行います。
    250         *
    251         * @og.rev 5.3.8.0 (2011/08/01) 処理中の状態を表示するための println を追加
    252         *
    253         * @return      処理できる:true / 処理できない:false
    254         */
    255        public boolean next() {
    256                while( !dirs.empty() ) {
    257                        FileListStack fStack = dirs.pop();
    258
    259                        level = fStack.getLevel();
    260                        if( level > maxLevel ) { continue; }
    261
    262                        File[] fileList = fStack.getFileList();
    263                        if( fileList == null ) { continue; }
    264
    265                        int address = fStack.getAddress();
    266                        for( ; address < fileList.length; address++ ) {
    267                                inCount++ ;
    268                                if( fileList[address].isDirectory() ) {
    269//                                      if( display ) { println( fileList[address].getAbsolutePath() ); }               // 5.3.8.0 (2011/08/01)
    270                                        if( debug ) { println( "file Add=" + fileList[address].getAbsolutePath() ); }                   // 5.7.3.0 (2014/02/07) デバッグ情報
    271                                        File[] newList = fileList[address].listFiles( filter );
    272                                        dirs.push( new FileListStack( newList,level+1) );
    273                                }
    274                                else {
    275                                        file = fileList[address];
    276                                        if( debug ) { println( "file=" + file ); }                      // 5.7.3.0 (2014/02/07) デバッグ情報
    277                                        fStack.setAddress( address+1 );
    278                                        dirs.push( fStack );
    279                                        return true;
    280                                }
    281                        }
    282                }
    283                return false;
    284        }
    285
    286        /**
    287         * 最初に、 行データである LineModel を作成します
    288         * FirstProcess は、次々と処理をチェインしていく最初の行データを
    289         * 作成して、後続の ChainProcess クラスに処理データを渡します。
    290         *
    291         * @og.rev 4.2.3.0 (2008/05/26) BIKO 欄に展開ファイル名を記述します。
    292         * @og.rev 4.3.1.1 (2008/08/23) BIKO 欄にoutPath 属性を追加します。
    293         *
    294         * @param       rowNo   処理中の行番号
    295         *
    296         * @return      処理変換後のLineModel
    297         */
    298        public LineModel makeLineModel( final int rowNo ) {
    299                outCount++ ;
    300                newData.setFileVals( level,file );
    301
    302                // 4.3.1.1 (2008/08/23)
    303                String biko = null;
    304                // 4.2.3.0 (2008/05/26) BIKO 欄追加
    305                if( inPathLen > 0 ) {
    306                        biko = file.getAbsolutePath().substring( inPathLen );
    307//                      newData.setBiko( biko );
    308                }
    309
    310                if( outPath != null ) {
    311                        if( biko == null ) {
    312                                biko = outPath + file.getName() ;
    313                        }
    314                        else {
    315                                biko = outPath + biko ;
    316                        }
    317                }
    318                if( biko != null ) {
    319                        newData.setBiko( biko );
    320                }
    321
    322                newData.setRowNo( rowNo );
    323
    324//              if( display ) { println( newData.dataLine() ); }                // 5.1.2.0 (2010/01/01) display の条件変更
    325
    326                return newData;
    327        }
    328
    329        /**
    330         * 引数の LineModel を処理するメソッドです。
    331         * 変換処理後の LineModel を返します。
    332         * 後続処理を行わない場合(データのフィルタリングを行う場合)は、
    333         * null データを返します。つまり、null データは、後続処理を行わない
    334         * フラグの代わりにも使用しています。
    335         * なお、変換処理後の LineModel と、オリジナルの LineModel が、
    336         * 同一か、コピー(クローン)かは、各処理メソッド内で決めています。
    337         * ドキュメントに明記されていない場合は、副作用が問題になる場合は、
    338         * 各処理ごとに自分でコピー(クローン)して下さい。
    339         *
    340         * @param       data    オリジナルのLineModel
    341         *
    342         * @return      処理変換後のLineModel
    343         */
    344        public LineModel action( final LineModel data ) {
    345                LineModel rtn = null;
    346
    347                final FileLineModel fileData ;
    348                if( data instanceof FileLineModel ) {
    349                        fileData = (FileLineModel)data ;
    350                }
    351                else {
    352                        String errMsg = "データが FileLineModel オブジェクトではありません。" + CR ;
    353                        throw new RuntimeException( errMsg );
    354                }
    355
    356                if( debug ) { println( "Before:" + data.dataLine() ); }         // 5.1.2.0 (2010/01/01) display の条件変更
    357
    358                File inFile = fileData.getFile() ;
    359                File[] fileList = inFile.listFiles( filter );
    360
    361                if( fileList != null && fileList.length > 0 ) {
    362                        rtn = data;
    363                }
    364
    365                if( display && rtn != null ) { println( rtn.dataLine() ); }             // 5.1.2.0 (2010/01/01) display の条件変更
    366                return rtn ;
    367        }
    368
    369        /**
    370         * プロセスの終了を行います。最後に一度だけ、呼び出されます。
    371         * 終了処理(ファイルクローズ、ＤＢクローズ等)に使用します。
    372         *
    373         * @param   isOK トータルで、OKだったかどうか[true:成功/false:失敗]
    374         */
    375        public void end( final boolean isOK ) {
    376                dirs            = null;
    377                file            = null;
    378                filter          = null;
    379                newData         = null;
    380        }
    381
    382        /**
    383         * プロセスの処理結果のレポート表現を返します。
    384         * 処理プログラム名、入力件数、出力件数などの情報です。
    385         * この文字列をそのまま、標準出力に出すことで、結果レポートと出来るような
    386         * 形式で出してください。
    387         *
    388         * @return   処理結果のレポート
    389         */
    390        public String report() {
    391                String report = "[" + getClass().getName() + "]" + CR
    392                                + TAB + "Start Folder : " + startDir  + CR
    393                                + TAB + "Search Count : " + inCount   + CR
    394                                + TAB + "Output Count : " + outCount ;
    395
    396                return report ;
    397        }
    398
    399        /**
    400         * このクラスの使用方法を返します。
    401         *
    402         * @return      このクラスの使用方法
    403         */
    404        public String usage() {
    405                StringBuilder buf = new StringBuilder();
    406
    407                buf.append( "Process_FileSearch は、指定のフォルダ以下のファイルを一覧する、FirstProcess"     ).append( CR );
    408                buf.append( "インターフェースと、ChainProcess インターフェースの実装クラスです。"                  ).append( CR );
    409                buf.append( CR );
    410                buf.append( "指定の条件に合致するファイルを検索し、ファイル属性(Level,File,Length,Modify)"       ).append( CR );
    411                buf.append( "を元に、LineModelを作成し、下流に渡します。"                                                                        ).append( CR );
    412                buf.append( CR );
    413                buf.append( "引数文字列中に空白を含む場合は、ダブルコーテーション(\"\") で括って下さい。" ).append( CR );
    414                buf.append( "引数文字列の 『=』の前後には、空白は挟めません。必ず、-key=value の様に"                ).append( CR );
    415                buf.append( "繋げてください。"                                                                                                                          ).append( CR );
    416                buf.append( CR );
    417                buf.append( "  -start=開始フォルダ    ：検索を開始するフォルダ"                                                                   ).append( CR );
    418                buf.append( "[ -prefix=接頭辞        ]：File････,View････,などの接頭辞で始まるファイル"                   ).append( CR );
    419                buf.append( "[ -unprefix=不接頭辞    ]：File････,View････,などの接頭辞で始まらないファイル"          ).append( CR );
    420                buf.append( "[ -suffix=接尾辞        ]：.txt,.java,.jsp.... などの接尾辞で終わるファイル"         ).append( CR );
    421                buf.append( "[ -unsuffix=不接尾辞    ]：.txt,.java,.jsp.... などの接尾辞で終わらないファイル"        ).append( CR );
    422                buf.append( "[ -instr=部分文字列     ]：ファイル名と一致する部分文字列"                                      ).append( CR );
    423                buf.append( "[ -uninstr=不部分文字列 ]：ファイル名と一致しな部分文字列"                                                       ).append( CR );
    424                buf.append( "[ -equals=一致          ]：ファイル名と一致する文字列(大文字小文字は区別しない)"       ).append( CR );
    425                buf.append( "[ -notequals=不一致     ]：ファイル名と一致しない文字列(大文字小文字は区別しない)"       ).append( CR );
    426                buf.append( "[ -match=正規表現       ]：ファイル名と一致する正規表現"                                                      ).append( CR );
    427                buf.append( "[ -unmatch=正規表現     ]：ファイル名と一致しない正規表現"                                                     ).append( CR );
    428                buf.append( "[ -modify=YYYYMMDD      ]：指定日付け以降に変更されたファイル"                                               ).append( CR );
    429                buf.append( "          YYYYMMDD   : YYYYMMDD 形式での指定日の 00:00:00 を基準時刻"                           ).append( CR );
    430                buf.append( "          TODAY      : 実行日の 00:00:00 を基準時刻"                                                                ).append( CR );
    431                buf.append( "          YESTERDAY  : 実行日前日の 00:00:00 を基準時刻"                                                      ).append( CR );
    432                buf.append( "          LAST_WEEK  : 実行日の先週(7日前) 00:00:00 を基準時刻"                                 ).append( CR );
    433                buf.append( "          MONTH      : 実行月の 1日 00:00:00 を基準時刻"                                                     ).append( CR );
    434                buf.append( "          LAST_MONTH : 実行前月の 同日 00:00:00 を基準時刻"                                            ).append( CR );
    435                buf.append( "          LAST_YEAR  : 実行前年の 同月同日 00:00:00 を基準時刻"                                  ).append( CR );
    436                buf.append( "[ -useDIR=[false/true]  ]：判定をディレクトリ名も含めて行うかどうか(初期値:false)" ).append( CR );
    437                buf.append( "[ -larger=サイズ(Byte)  ]：大きさが指定のバイト数と同じか大きいファイル"                     ).append( CR );
    438                buf.append( "[ -smaller=サイズ(Byte) ]：大きさが指定のバイト数より小さいファイル"                               ).append( CR );
    439                buf.append( "[ -isHidden=[false/true]]：true:HIDDENのみ検索/false:NORMALのみ検索(初期値:null)"      ).append( CR );
    440                buf.append( "[ -maxLevel=最大階層数  ]：ディレクトリの階層を下がる最大数(初期値:256)"                    ).append( CR );
    441                buf.append( "[ -useLineCnt=行数計算  ]：ファイルの行数をカウントするかどうか(初期値:false)"               ).append( CR );
    442                buf.append( "[ -useMD5=MD5計算値     ]：ファイルのMD5計算を行うかどうかを指定(初期値:false)"    ).append( CR );
    443                buf.append( "[ -inPath=入力共通パス  ]：BIKO作成用のファイルパスから削除する文字列"                               ).append( CR );
    444                buf.append( "[ -outPath=出力追加パス ]：BIKO作成用のファイルパスに追加する文字列"                                ).append( CR );
    445                buf.append( "[ -display=[false/true] ]：trueは、検索状況を表示(初期値:false)"                                        ).append( CR );
    446                buf.append( "[ -debug=[false/true]   ]：trueは、デバッグ状況を表示(初期値:false)"                              ).append( CR );
    447                buf.append( CR ).append( CR );
    448                buf.append( getArgument().usage() ).append( CR );
    449
    450                return buf.toString();
    451        }
    452
    453        /**
    454         * このクラスは、main メソッドから実行できません。
    455         *
    456         * @param       args    コマンド引数配列
    457         */
    458        public static void main( final String[] args ) {
    459                LogWriter.log( new Process_FileSearch().usage() );
    460        }
    461
    462        /**
    463         * このクラスはファイルをスタックを使用して展開する場合の
    464         * 個々の状態を保持する為のクラスです。
    465         *
    466         * @version  4.0
    467         * @author   Kazuhiko Hasegawa
    468         * @since    JDK5.0,
    469         */
    470        private static final class FileListStack {
    471                private int address ;
    472                private final File[] files;
    473                private final int level;
    474
    475                /**
    476                 * コンストラクター
    477                 * 初期値を設定します。
    478                 * ファイルの配列については、コピーせずそのまま内部配列にセットしています。
    479                 *
    480                 * @param files File[] ファイルの配列(ファイルリスト)
    481                 * @param       level   レベル(指定のstartフォルダからの階層数)
    482                 */
    483                FileListStack( final File[] files,final int level ) {
    484                        this.files   = files;
    485                        this.address = 0;
    486                        this.level   = level;
    487                }
    488
    489                /**
    490                 * ファイルリストのアドレスを設定します。
    491                 * スタックから取り出した後、配列を前回の続きからサーチする場合に使用します。
    492                 *
    493                 * @param       address ファイルリストのアドレス
    494                 */
    495                void setAddress( final int address ) {
    496                        this.address = address;
    497                }
    498
    499                /**
    500                 * ファイルリストのアドレスを取り出します。
    501                 *
    502                 * @return      ファイルリストのアドレス
    503                 */
    504                int getAddress() {
    505                        return address;
    506                }
    507
    508                /**
    509                 * ファイルリストを取り出します。
    510                 * ファイルの配列については、コピーせずそのまま内部配列を返しています。
    511                 *
    512                 * @return File[] ファイルリスト
    513                 */
    514                File[] getFileList() {
    515                        return files;
    516                }
    517
    518                /**
    519                 * 階層レベルを取り出します。
    520                 *
    521                 * @return      レベル
    522                 */
    523                int getLevel() {
    524                        return level;
    525                }
    526        }
    527}