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