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.hayabusa.taglib; 017 018import org.opengion.hayabusa.common.HybsSystem; 019import org.opengion.hayabusa.common.HybsSystemException; 020import org.opengion.hayabusa.db.DBTableModel; 021import org.opengion.fukurou.util.ErrorMessage; 022import org.opengion.fukurou.util.FileUtil; 023import org.opengion.fukurou.util.ToString; // 6.1.1.0 (2015/01/17) 024import org.opengion.fukurou.util.ArraySet; // 6.4.3.4 (2016/03/11) 025 026import static org.opengion.fukurou.util.StringUtil.nval ; 027import static org.opengion.fukurou.system.HybsConst.BR; // 6.1.0.0 (2014/12/26) refactoring 028 029import java.util.Locale ; 030import java.util.Set ; 031import java.util.TreeSet ; 032import java.util.Comparator ; 033import java.io.File ; 034import java.io.Serializable; 035import java.io.IOException ; // 7.0.5.0 (2019/09/13) 036 037/** 038 * ファイル検索リストを元に、action に基づいた処理を行うタグです。 039 * command="ENTRY" 時のみ処理を行います。 040 * 041 * fileQuery などで検索したファイル一覧のDBTableModel を元に、ファイルの 042 * コピー(COPY)、移動(MOVE,MODIFY)、削除(DELETE)などの処理を行います。 043 * 処理を行うオリジナルファイルは、PARENT,NAME というカラムでなければなりません。 044 * このカラム名は、fileQuery の検索時には、必ず作成されるカラムです。 045 * また、各アクションに対応するターゲットファイルは、TO_PARENT,TO_NAME という 046 * カラムで指定するか、targetDir 属性を利用してフォルダを指定します。 047 * TO_PARENT(先フォルダ)と、TO_NAME(先ファイル名)は、処理に応じて、必要なカラムが 048 * あれば、自動的に処理します。 049 * つまり、TO_PARENT のみの場合は、ファイル名はオリジナルのまま、フォルダのみ変更します。 050 * 逆に、TO_NAME の場合は、フォルダはそのままで、ファイル名のみ指定します。 051 * 両方同時に指定することも可能です。 052 * targetDir 属性で指定する場合は、TO_PARENT のみに同じ値を設定した場合と同じになります。 053 * この属性を指定すると、TO_PARENT は無視されます。(TO_NAME は有効です。) 054 * COPY、MOVE(,MODIFY) の場合は、指定のフォルダに一括処理可能です。 055 * COPY、MOVE(,MODIFY) などの処理で、ターゲットフォルダが存在しないときに、作成するか、エラーにするかは 056 * createDir属性 で指定できます。初期値は、(true:作成する) です。 057 * これは、COPY先やMOVE(,MODIFY)先が存在している前提のシステムで、不要な箇所に間違ってフォルダを 058 * 自動作成されると困る場合に、(false:作成しない) とすれば、間違いに気づく確率が上がります。 059 * 060 * ※ このタグは、Transaction タグの対象ではありません。 061 * 062 * @og.formSample 063 * ●body:なし 064 * ●形式: 065 * ・<og:fileUpdate 066 * action = "COPY|MOVE|MODIFY|DELETE" アクション属性(必須) 067 * command = "[ENTRY]" ENTRY 時のみ実行します(初期値:ENTRY) 068 * targetDir = "[指定フォルダ]" ターゲットとなるフォルダ 069 * createDir = "[true/false]" ターゲットとなるフォルダがなければ作成する(true)かどうか(初期値:true) 070 * tableId = [HybsSystem.TBL_MDL_KEY] DBTableModel を取り出すキー 071 * outMessage = "[true/false]" 検索結果のメッセージを表示する(true)かどうかを指定(初期値:true) 072 * displayMsg = "MSG0040"; 処理結果を表示します(初期値:「 件登録しました。」) 073 * selectedAll = "[false/true]" データを全件選択済みとして処理する(true)かどうか指定(初期値:false) 074 * keepTimeStamp = "[false/true]" COPY,親違いMOVE(,MODIFY)の時にオリジナルのタイムスタンプを使用するかどうか(初期値:false) 075 * /> 076 * 077 * [action属性(必須)] 078 * COPY オリジナルファイルを、ターゲット(TO_PARENT,TO_NAMEで指定)にコピーします。 079 * MOVE オリジナルファイルを、ターゲットに移動(COPY+DELETE)/名称変更(RENAME)します。 080 * MODIFY (MOVE と同じ。エンジンの command を利用するための簡易action) 081 * DELETE オリジナルファイルを削除します(ターゲット(TO_PARENT,TO_NAME)は、関係しません)。 082 * 083 * ●Tag定義: 084 * <og:fileUpdate 085 * action ○【TAG】アクション[COPY|MOVE|MODIFY|DELETE]をセットします(必須)。 086 * command 【TAG】コマンド[ENTRY]をセットします(初期値:ENTRY) 087 * targetDir 【TAG】ターゲットとなるフォルダを指定します 088 * createDir 【TAG】ターゲットとなるフォルダがなければ、作成するかどうかを指定します(初期値:true) 089 * tableId 【TAG】(通常は使いません)結果のDBTableModelを、sessionに登録するときのキーを指定します 090 * scope 【TAG】キャッシュする場合のスコープ[request/page/session/application]を指定します(初期値:session) 091 * outMessage 【TAG】検索結果のメッセージを表示する/しない[true/false]を指定します(初期値:true) 092 * displayMsg 【TAG】処理結果を画面上に表示するメッセージリソースIDを指定します(初期値:MSG0040[ 件登録しました]) 093 * selectedAll 【TAG】データを全件選択済みとして処理するかどうか[true/false]を指定します(初期値:false) 094 * keepTimeStamp 【TAG】オリジナルのタイムスタンプを利用するかどうかを指定します(初期値:false) 095 * inPath 【TAG】入力共通パスを指定します(PARENTフォルダの共通部分、COPY/MOVE時にtargetDirと置換されます) 6.8.0.0 (2017/06/02)。 096 * useTimeView 【TAG】処理時間を表示する TimeView を表示するかどうかを指定します 097 * (初期値:VIEW_USE_TIMEBAR[={@og.value SystemData#VIEW_USE_TIMEBAR}])。 098 * useSLabel 【TAG】7.0.7.0 (2019/12/13) エラーメッセージにSLABELを利用するかどうか[true/false]を指定します(初期値:false) 099 * caseKey 【TAG】このタグ自体を利用するかどうかの条件キーを指定します(初期値:null) 100 * caseVal 【TAG】このタグ自体を利用するかどうかの条件値を指定します(初期値:null) 101 * caseNN 【TAG】指定の値が、null/ゼロ文字列 でない場合(Not Null=NN)は、このタグは使用されます(初期値:判定しない) 102 * caseNull 【TAG】指定の値が、null/ゼロ文字列 の場合は、このタグは使用されます(初期値:判定しない) 103 * caseIf 【TAG】指定の値が、true/TRUE文字列の場合は、このタグは使用されます(初期値:判定しない) 104 * debug 【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false) 105 * /> 106 * 107 * ●使用例 108 * ・<og:fileUpdate command="{@command}" action="COPY" /> 109 * TO_PARENT または、 TO_NAME(両方指定も可)による行単位 COPY 処理 110 * fileQuery の useUpdateClm="true" を設定し、検索結果に、TO_PARENT、 TO_NAMEカラムを追加します。 111 * TO_PARENT または、 TO_NAME は、columnSet などで値をセットしておきます。 112 * 113 * ・<og:fileUpdate command="{@command}" action="MODIFY" targetDir="AAA_DIR" /> 114 * fileQuery の検索結果を、AAA_DIR フォルダに移動します。 115 * ファイル名は、そのままオリジナルの値が使用されます。 116 * 117 * @og.rev 5.3.4.0 (2011/04/01) 新規追加 118 * @og.group ファイル出力 119 * 120 * @version 4.0 121 * @author Kazuhiko Hasegawa 122 * @since JDK5.0, 123 */ 124public class FileUpdateTag extends CommonTagSupport { 125 /** このプログラムのVERSION文字列を設定します。 {@value} */ 126 private static final String VERSION = "7.0.7.0 (2019/12/13)" ; 127 private static final long serialVersionUID = 707020191213L ; 128 129 /** command 引数に渡す事の出来る コマンド 登録{@value} */ 130 public static final String CMD_ENTRY = "ENTRY" ; 131 /** command 引数に渡す事の出来る コマンド リスト */ 132 // 6.4.3.4 (2016/03/11) String配列 から、Setに置き換えます。 133 private static final Set<String> COMMAND_SET = new ArraySet<>( CMD_ENTRY ); 134 135 /** エラーメッセージID {@value} */ 136 private static final String ERR_MSG_ID = HybsSystem.ERR_MSG_KEY; // 6.4.1.1 (2016/01/16) errMsgId → ERR_MSG_ID refactoring 137 138 /** action 引数に渡す事の出来る アクションコマンド COPY {@value} */ 139 public static final String ACT_COPY = "COPY" ; 140 /** action 引数に渡す事の出来る アクションコマンド MOVE {@value} */ 141 public static final String ACT_MOVE = "MOVE" ; 142 /** action 引数に渡す事の出来る アクションコマンド MODIFY {@value} */ 143 public static final String ACT_MODIFY = "MODIFY" ; 144 /** action 引数に渡す事の出来る アクションコマンド DELETE {@value} */ 145 public static final String ACT_DELETE = "DELETE" ; 146 // 6.4.3.4 (2016/03/11) String配列 から、Setに置き換えます。 147 private static final Set<String> ACTION_SET = new ArraySet<>( ACT_COPY , ACT_MOVE , ACT_MODIFY , ACT_DELETE ); 148 149 private String action ; 150 private String targetDir ; // ターゲットとなるフォルダ 151 private boolean createDir = true; // ターゲットとなるフォルダがなければ、作成するかどうか(true:作成する) 152 153 private String inPath ; // 6.8.0.0 (2017/06/02) 入力共通パスを指定します。 154 155 private String tableId = HybsSystem.TBL_MDL_KEY; 156 private String command = CMD_ENTRY; 157 private boolean outMessage = true; 158 private String displayMsg = "MSG0040"; // 件登録しました。 159 private boolean selectedAll ; 160 private boolean keepTimeStamp; // オリジナルのタイムスタンプを利用する場合、true 161 162 private transient DBTableModel table ; 163 private transient ErrorMessage errMessage ; 164 private int executeCount = -1; // 処理件数 165 private int errCode = ErrorMessage.OK; 166 private boolean useTimeView = HybsSystem.sysBool( "VIEW_USE_TIMEBAR" ); // 6.3.6.0 (2015/08/16) 167 private boolean useSLabel ; // 7.0.7.0 (2019/12/13) エラーメッセージにSLABELを利用するかどうか[true/false]を指定します(初期値:false) 168 169 /** 170 * デフォルトコンストラクター 171 * 172 * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor. 173 */ 174 public FileUpdateTag() { super(); } // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。 175 176 /** 177 * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。 178 * 179 * @og.rev 6.4.4.1 (2016/03/18) 意味のない、StringBuilderだったので、廃止します。 180 * @og.rev 6.9.9.0 (2018/08/20) 「ERR0041:検索処理中に割り込みの検索要求がありました」エラーを、標準のErrorMessageに追加するようにします。 181 * @og.rev 7.0.7.0 (2019/12/13) useSLabel 属性を追加。 182 * 183 * @return 後続処理の指示 184 */ 185 @Override 186 public int doEndTag() { 187 debugPrint(); 188 // 5.2.2.0 (2010/11/01) caseKey 、caseVal 属性対応 189 if( !useTag() ) { return EVAL_PAGE ; } 190 191 final long dyStart = System.currentTimeMillis(); 192 193 table = (DBTableModel)getObject( tableId ); 194 195 String label = ""; // 4.0.0 (2005/11/30) 検索しなかった場合。 196 if( table != null && table.getRowCount() > 0 && check( command, COMMAND_SET ) ) { 197 startQueryTransaction( tableId ); 198 199 execute(); // 実際の処理を実行します。 200 201 setRequestAttribute( "DB.COUNT" , String.valueOf( executeCount ) ); 202 setRequestAttribute( "DB.ERR_CODE", String.valueOf( errCode ) ); 203 204 // 6.9.9.0 (2018/08/20) 「ERR0041:検索処理中に割り込みの検索要求がありました」エラーを、標準のErrorMessageに追加するようにします。 205 if( ! commitTableObject( tableId, table ) ) { 206 if( errMessage == null ) { errMessage = new ErrorMessage( "FileUpdateTag Query Error!" ); } 207 // ERR0041:検索処理中に割り込みの検索要求がありました。処理されません。 208 errMessage.addMessage( 0,ErrorMessage.NG,"ERR0041" ); 209 errCode = ErrorMessage.NG; 210 } 211 212// final String err = TaglibUtil.makeHTMLErrorTable( errMessage,getResource() ); 213 final String err = TaglibUtil.makeHTMLErrorTable( errMessage,getResource(),useSLabel ); // 7.0.7.0 (2019/12/13) 214 if( err != null && err.length() > 0 ) { 215 label = err ; // 6.4.4.1 (2016/03/18) 216 setSessionAttribute( ERR_MSG_ID,errMessage ); 217 } 218 219// // 6.9.9.0 (2018/08/20) 「ERR0041:検索処理中に割り込みの検索要求がありました」エラーを、標準のErrorMessageに追加するようにします。 220// if( table != null && ! commitTableObject( tableId, table ) ) { 221// jspPrint( "FileUpdateTag Query処理が割り込まれました。DBTableModel は登録しません。" ); 222// return SKIP_PAGE ; 223// } 224 } 225 226 jspPrint( label ); 227 228 // 実行件数の表示 229 // 4.0.0 (2005/11/30) 出力順の変更。一番最初に出力します。 230 if( displayMsg != null && displayMsg.length() > 0 ) { 231 final String status = executeCount + getResource().getLabel( displayMsg ) ; 232 jspPrint( status + BR ); 233 } 234 235 if( useTimeView ) { // 6.3.6.0 (2015/08/16) 236 // 3.5.4.7 (2004/02/06) 237 final long dyTime = System.currentTimeMillis()-dyStart; 238 jspPrint( "<div id=\"queryTime\" value=\"" + (dyTime) + "\"></div>" ); // 3.5.6.3 (2004/07/12) 239 } 240 return EVAL_PAGE ; 241 } 242 243 /** 244 * タグリブオブジェクトをリリースします。 245 * キャッシュされて再利用されるので、フィールドの初期設定を行います。 246 * 247 * @og.rev 6.8.0.0 (2017/06/02) 入力共通パス(inPath)を指定します。 248 * @og.rev 7.0.7.0 (2019/12/13) useSLabel 属性を追加。 249 */ 250 @Override 251 protected void release2() { 252 super.release2(); 253 tableId = HybsSystem.TBL_MDL_KEY; 254 command = CMD_ENTRY; 255 action = null; 256 targetDir = null; // ターゲットとなるフォルダ 257 createDir = true; // ターゲットとなるフォルダがなければ、作成するかどうか(true:作成する) 258 outMessage = true; 259 displayMsg = "MSG0040"; // 件登録しました。 260 selectedAll = false; 261 keepTimeStamp = false; // オリジナルのタイムスタンプを利用する場合、true 262 table = null; 263 errMessage = null; 264 executeCount= -1; // 処理件数 265 errCode = ErrorMessage.OK; 266 useTimeView = HybsSystem.sysBool( "VIEW_USE_TIMEBAR" ); // 6.3.6.0 (2015/08/16) 267 inPath = null; // 6.8.0.0 (2017/06/02) 入力共通パスを指定します。 268 useSLabel = false; // 7.0.7.0 (2019/12/13) エラーメッセージにSLABELを利用するかどうか[true/false]を指定します(初期値:false) 269 } 270 271 /** 272 * 処理を実行します。 273 * 274 * @og.rev 6.8.0.0 (2017/06/02) 入力共通パス(inPath)を指定します。 275 */ 276 private void execute() { 277 final int[] rowNo = getParameterRows(); 278 if( rowNo.length > 0 ) { 279 280 final FromToFiles fromToFiles = new FromToFiles( table , targetDir , createDir , inPath ); // 6.8.0.0 (2017/06/02) 入力共通パス(inPath)を指定 281 282 if( ACT_COPY.equalsIgnoreCase( action ) ) { 283 actionCOPY( rowNo,fromToFiles ); 284 } 285 // ACT_MODIFY は、エンジンの command で使うため、便利 286 else if( ACT_MOVE.equalsIgnoreCase( action ) || ACT_MODIFY.equalsIgnoreCase( action ) ) { 287 actionMOVE( rowNo,fromToFiles ); 288 } 289 else if( ACT_DELETE.equalsIgnoreCase( action ) ) { 290 actionDELETE( rowNo,fromToFiles ); 291 } 292 } 293 } 294 295 /** 296 * COPY アクションを実行します。 297 * 298 * @og.rev 5.6.5.2 (2013/06/21) From側がファイルの場合のみ処理します。 299 * 300 * @param rowNo 処理を実施する行番号 301 * @param fromToFiles FromFile,ToFileをまとめた補助クラス 302 * @throws HybsSystemException 処理中に何らかのエラーが発生した場合 303 */ 304 private void actionCOPY( final int[] rowNo , final FromToFiles fromToFiles ) { 305 File fromFile = null ; 306 File toFile = null ; 307 308 executeCount = 0 ; // 開始前に初期化しておく。 309 final int rowCount = rowNo.length ; 310 for( int i=0; i<rowCount; i++ ) { 311 final File[] files = fromToFiles.makeFromToFile( rowNo[i] ); // FromFile,ToFile 312 fromFile = files[0]; 313 toFile = files[1]; 314 315 // 5.6.5.2 (2013/06/21) From側がファイルの場合のみ処理します。 316 if( fromFile.isFile() && !FileUtil.copy( fromFile,toFile,keepTimeStamp ) ) { 317 final String errMsg = "アクション=[" + action + "]中にエラーが発生しました。" + CR 318 + "From=[" + fromFile + "],To=[" + toFile + "]" + CR; 319 // 6.0.2.5 (2014/10/31) refactoring 320 if( errMessage == null ) { errMessage = new ErrorMessage( "FileUpdateTag Error" ); } 321 errMessage.addMessage( rowNo[i]+1,ErrorMessage.NG,"actionCOPY",errMsg ); 322 } 323 executeCount++ ; 324 } 325 } 326 327 /** 328 * MOVE アクションを実行します。 329 * 330 * @og.rev 5.5.2.4 (2012/05/16) メソッドの戻り値の設定 331 * @og.rev 5.6.5.2 (2013/06/21) From側がファイルの場合のみ処理します。 332 * 333 * @param rowNo 処理を実施する行番号 334 * @param fromToFiles FromFile,ToFileをまとめた補助クラス 335 * @throws HybsSystemException 処理中に何らかのエラーが発生した場合 336 */ 337 private void actionMOVE( final int[] rowNo , final FromToFiles fromToFiles ) { 338 File fromFile = null ; 339 File toFile = null ; 340 341 executeCount = 0 ; // 開始前に初期化しておく。 342 final int rowCount = rowNo.length ; 343 for( int i=0; i<rowCount; i++ ) { 344 final File[] files = fromToFiles.makeFromToFile( rowNo[i] ); // FromFile,ToFile 345 fromFile = files[0]; 346 toFile = files[1]; 347 348 if( fromToFiles.lastParentEquals() ) { // FromDirとToDirが同じなので、RENAMEできる。 349 if( !fromFile.renameTo( toFile ) ) { 350 final String errMsg = "アクション=[" + action + "]中にエラーが発生しました。" + CR 351 + "同一親フォルダのため、RENAME処理を行っています。" + CR 352 + "From=[" + fromFile + "],To=[" + toFile + "]" + CR; 353 // 6.0.2.5 (2014/10/31) refactoring 354 if( errMessage == null ) { errMessage = new ErrorMessage( "FileUpdateTag Error" ); } 355 errMessage.addMessage( rowNo[i]+1,ErrorMessage.NG,"actionMOVE",errMsg ); 356 } 357 } 358 // 5.6.5.2 (2013/06/21) From側がファイルの場合のみ処理します。 359 else if( fromFile.isFile() ) { // FromDirとToDirが異なるので、COPY + DELETE する。 360 if( !FileUtil.copy( fromFile,toFile,keepTimeStamp ) ) { 361 final String errMsg = "アクション=[" + action + "]中にエラーが発生しました。" + CR 362 + "移動前のCOPY処理を行っていました。" + CR 363 + "From=[" + fromFile + "],To=[" + toFile + "]" + CR; 364 // 6.0.2.5 (2014/10/31) refactoring 365 if( errMessage == null ) { errMessage = new ErrorMessage( "FileUpdateTag Error" ); } 366 errMessage.addMessage( rowNo[i]+1,ErrorMessage.NG,"actionMOVE",errMsg ); 367 } 368 369 if( !fromFile.delete() ) { 370 String errMsg = "アクション=[" + action + "]中にエラーが発生しました。" + CR 371 + "移動後のオリジナルファイルの削除処理を行っていました。" + CR 372 + "From=[" + fromFile + "],To=[" + toFile + "]" + CR; 373 // 5.5.2.4 (2012/05/16) メソッドの戻り値の設定 374 if( !toFile.delete() ) { 375 errMsg = errMsg + "toFile も削除に失敗しました。" + CR; 376 } 377 378 // 6.0.2.5 (2014/10/31) refactoring 379 if( errMessage == null ) { errMessage = new ErrorMessage( "FileUpdateTag Error" ); } 380 errMessage.addMessage( rowNo[i]+1,ErrorMessage.NG,"actionMOVE",errMsg ); 381 } 382 } 383 executeCount++ ; 384 } 385 } 386 387 /** 388 * DELETE アクションを実行します。 389 * 390 * この処理では、リストにフォルダが含まれている場合も削除します。 391 * 通常、フォルダの削除は、その要素(内部)にファイル等が存在しない場合のみ 392 * 行いますが、検索リストから削除する順番によっては、フォルダもファイルも 393 * 削除対象になる場合があります。そこで、まず。ファイルだけ削除し、フォルダは、 394 * あとで削除するように処理を行います。 395 * 396 * @og.rev 5.6.5.2 (2013/06/21) フォルダも削除対象にします。 397 * 398 * @param rowNo 処理を実施する行番号 399 * @param fromToFiles FromFile,ToFileをまとめた補助クラス 400 * @throws HybsSystemException 処理中に何らかのエラーが発生した場合 401 */ 402 private void actionDELETE( final int[] rowNo , final FromToFiles fromToFiles ) { 403 File fromFile = null; 404 405 // 5.6.5.2 (2013/06/21) フォルダを削除する為の、退避 406 final Set<File> dirSet = new TreeSet<>( new FileNameLengthComparator() ); // ファイルの文字数順に並べたSet 407 408 executeCount = 0 ; // 開始前に初期化しておく。 409 final int rowCount = rowNo.length ; 410 for( int i=0; i<rowCount; i++ ) { 411 fromFile = fromToFiles.makeFromOnly( rowNo[i] ); // FromFile 412 413 // 5.6.5.2 (2013/06/21) まず、ファイルを削除します。 414 if( fromFile.isFile() ) { 415 if( !fromFile.delete() ) { 416 final String errMsg = "アクション=[" + action + "]中にエラーが発生しました。" + CR 417 + "From=[" + fromFile + "]" + CR; 418 // 6.0.2.5 (2014/10/31) refactoring 419 if( errMessage == null ) { errMessage = new ErrorMessage( "FileUpdateTag Error" ); } 420 errMessage.addMessage( rowNo[i]+1,ErrorMessage.NG,"actionDELETE",errMsg ); 421 } 422 } 423 else { 424 // 5.6.5.2 (2013/06/21) フォルダの場合は、アドレスの桁数をキーにソートしておきます。 425 dirSet.add( fromFile ); 426 } 427 executeCount++ ; 428 } 429 430 // 5.6.5.2 (2013/06/21) フォルダの削除は、アドレスの桁数の大きい順(階層の深い順)に削除します。 431 for( final File file : dirSet ) { 432 if( !file.delete() ) { 433 final String errMsg = "アクション=[" + action + "]中にエラーが発生しました。" + CR 434 + "From(Dir)=[" + file + "]" + CR; 435 // 6.0.2.5 (2014/10/31) refactoring 436 if( errMessage == null ) { errMessage = new ErrorMessage( "FileUpdateTag Error" ); } 437 errMessage.addMessage(-1,ErrorMessage.NG,"actionDELETE",errMsg ); 438 } 439 } 440 } 441 442 /** 443 * ファイルの名称の長さ順(長い順)に比較する、Comparator インターフェースの実装クラス 444 * 445 * ここでの大小比較は、ファイル名の文字数が、大きい方が、小さいとみなされます。 446 * つまり階層が深いので、先に処理する必要があるという事を意味します。 447 * 処理としては、f1 != null && f2 != null で、len1 = f1.getAbsolutePath().length() と len2 = f2.getAbsolutePath().length() を比較し 448 * len1 > len2 ⇒ 負 , len1 < len2 ⇒ 正 , len1 == len2 ⇒ 0 を返します。 449 * 具体的には、return ( len2 - len1 ); です。 450 * 451 * 注: このコンパレータは equals と一貫性のない順序付けを課します。 452 * 453 * @og.rev 5.6.5.2 (2013/06/21) 新規追加 454 * 455 */ 456 private static final class FileNameLengthComparator implements Comparator<File> , Serializable { 457 private static final long serialVersionUID = 565220130621L ; // 5.6.5.2 (2013/06/21) 458 /** 459 * 順序付けのために 2つの引数を比較します。 460 * 461 * ここでの大小比較は、ファイル名の文字数が、大きい方が、小さいとみなされます。 462 * 具体的には、return ( len2 - len1 ); です。 463 * 464 * @param f1 比較対象の1番目のオブジェクト 465 * @param f2 比較対象の2番目のオブジェクト 466 * @return 最初の引数が2番目の引数より小さい場合は負の整数、両方が等しい場合は 0、最初の引数が 2番目の引数より大きい場合は正の整数 467 */ 468 public int compare( final File f1 , final File f2 ) { 469 if( f1 == null || f2 == null ) { 470 final String errMsg = "引数のFileにnullが含まれています。file1=[" + f1 + "] , file2=[" + f2 + "]" ; 471 throw new IllegalArgumentException( errMsg ); 472 } 473 474 final int len1 = f1.getAbsolutePath().length(); 475 final int len2 = f2.getAbsolutePath().length(); 476 477 return len2 - len1 ; 478 } 479 } 480 481 /** 482 * 表示データの HybsSystem.ROW_SEL_KEY を元に、選ばれた 行を処理の対象とします。 483 * 484 * @return 選択行の配列 485 * @og.rtnNotNull 486 */ 487 @Override 488 protected int[] getParameterRows() { 489 final int[] rowNo ; 490 if( selectedAll ) { 491 final int rowCnt = table.getRowCount(); 492 rowNo = new int[ rowCnt ]; 493 for( int i=0; i<rowCnt; i++ ) { 494 rowNo[i] = i; 495 } 496 } else { 497 rowNo = super.getParameterRows(); 498 } 499 return rowNo ; 500 } 501 502 /** 503 * 【TAG】アクション[COPY|MOVE|MODIFY|DELETE]をセットします。 504 * 505 * @og.tag 506 * アクションは、ファイルをコピー(COPY)したり、移動(MOVE,MODIFY)したり、削除(DELETE)する 507 * などの操作を指定する必須属性です。 508 * 509 * <table class="plain"> 510 * <caption>action属性(必須)のキーワード</caption> 511 * <tr><th>action</th><th>名称</th><th>機能</th></tr> 512 * <tr><td>COPY </td><td>コピー</td><td>オリジナルファイルを、ターゲット(TO_PARENT,TO_NAMEで指定)にコピーします。</td></tr> 513 * <tr><td>MOVE </td><td>移動 </td><td>オリジナルファイルを、ターゲットに移動(COPY+DELETE)/名称変更(RENAME)します。</td></tr> 514 * <tr><td>MODIFY</td><td>移動 </td><td>(MOVE と同じ。エンジンの command を利用するための簡易action)</td></tr> 515 * <tr><td>DELETE</td><td>削除 </td><td>オリジナルファイルを、削除します。(フォルダ、ファイルに関わらず)</td></tr> 516 * </table> 517 * 518 * @og.rev 6.3.4.0 (2015/08/01) Arrays.toString から String.join に置き換え。 519 * @og.rev 6.4.3.4 (2016/03/11) String配列 から、Setに置き換えます。 520 * 521 * @param act アクション (public static final 宣言されている文字列) 522 * @see <a href="../../../../constant-values.html#org.opengion.hayabusa.taglib.FileUpdateTag.ACT_COPY">アクション定数</a> 523 */ 524 public void setAction( final String act ) { 525 action = nval( getRequestParameter( act ),action ); 526 527 if( action != null && !check( action, ACTION_SET ) ) { 528 final String errMsg = "指定のアクションは実行できません。アクションエラー" + CR 529 + "action=[" + action + "] " + CR 530 + "actionList=" + String.join( ", " , ACTION_SET ) ; 531 throw new HybsSystemException( errMsg ); 532 } 533 } 534 535 /** 536 * 【TAG】ターゲットとなるフォルダを指定します(初期値:null)。 537 * 538 * @og.tag 539 * targetDir 属性を利用する場合は、引数のファイル、またはフォルダが指定されたことに 540 * なります。COPY、MOVE(,MODIFY) の場合は、targetDir 属性にフォルダを指定することで一括処理可能です。 541 * 指定先のフォルダが存在しない場合は、createDir属性の値により処理が異なります。 542 * createDir="true"(初期値)で、ターゲットフォルダが存在しない場合は、自動作成します。 543 * 544 * @param dir ターゲットとなるフォルダ 545 * @see #setCreateDir( String ) 546 */ 547 public void setTargetDir( final String dir ) { 548 targetDir = nval( getRequestParameter( dir ),targetDir ); 549 } 550 551 /** 552 * 【TAG】ターゲットとなるフォルダがなければ、作成するかどうかを指定します(初期値:true)。 553 * 554 * @og.tag 555 * COPY,MOVE(,MODIFY) などの処理で、ターゲットフォルダが存在しないときに、作成するか、エラーにするかを 556 * createDir属性 で指定できます。 557 * これは、COPY先やMOVE(,MODIFY)先が存在している前提のシステムで、不要な箇所に間違ってフォルダを 558 * 自動作成されると困る場合に、false:作成しない とすれば、間違いに気づく確率が上がります。 559 * 初期値は true:作成する です。 560 * 561 * @param flag フォルダ作成可否 [true:作成する/false:作成しない] 562 */ 563 public void setCreateDir( final String flag ) { 564 createDir = nval( getRequestParameter( flag ),createDir ); 565 } 566 567 /** 568 * 【TAG】(通常は使いません)結果のDBTableModelを、sessionに登録するときのキーを指定します 569 * (初期値:HybsSystem#TBL_MDL_KEY[={@og.value HybsSystem#TBL_MDL_KEY}])。 570 * 571 * @og.tag 572 * 検索結果より、DBTableModelオブジェクトを作成します。これを、下流のviewタグ等に 573 * 渡す場合に、通常は、session を利用します。その場合の登録キーです。 574 * query タグを同時に実行して、結果を求める場合、同一メモリに配置される為、 575 * この tableId 属性を利用して、メモリ空間を分けます。 576 * (初期値:HybsSystem#TBL_MDL_KEY[={@og.value HybsSystem#TBL_MDL_KEY}])。 577 * 578 * @param id テーブルID (sessionに登録する時のID) 579 */ 580 public void setTableId( final String id ) { 581 tableId = nval( getRequestParameter( id ),tableId ); 582 } 583 584 /** 585 * 【TAG】コマンド (ENTRY)をセットします(初期値:ENTRY)。 586 * 587 * @og.tag 588 * このタグは、command="ENTRY" でのみ実行されます。 589 * コマンドは,HTMLから(get/post)指定されますので,CMD_xxx で設定される 590 * フィールド定数値のいづれかを、指定できます。 591 * 初期値は、ENTRY なので、何も指定しなければ、実行されます。 592 * 593 * @param cmd コマンド (public static final 宣言されている文字列) 594 * @see <a href="../../../../constant-values.html#org.opengion.hayabusa.taglib.FileUpdateTag.CMD_ENTRY">コマンド定数</a> 595 */ 596 public void setCommand( final String cmd ) { 597 final String cmd2 = getRequestParameter( cmd ); 598 if( cmd2 != null && cmd2.length() >= 0 ) { command = cmd2.toUpperCase(Locale.JAPAN); } 599 } 600 601 /** 602 * 【TAG】検索結果のメッセージを表示する/しない[true/false]を指定します(初期値:true)。 603 * 604 * @og.tag 605 * 初期値は、表示する:true です。 606 * 607 * @param flag メッセージ表示可否 [true:表示する/それ以外:含めない] 608 */ 609 public void setOutMessage( final String flag ) { 610 outMessage = nval( getRequestParameter( flag ),outMessage ); 611 } 612 613 /** 614 * 【TAG】処理結果を画面上に表示するメッセージリソースIDを指定します(初期値:MSG0040[ 件登録しました])。 615 * 616 * @og.tag 617 * ここでは、検索結果の件数や登録された件数をまず出力し、 618 * その次に、ここで指定したメッセージをリソースから取得して表示します。 619 * 表示させたくない場合は, displayMsg = "" をセットしてください。 620 * displayMsg の初期値は、MSG0040[ 件登録しました]です。 621 * 622 * @param id 処理結果表示メッセージID 623 */ 624 public void setDisplayMsg( final String id ) { 625 final String ids = getRequestParameter( id ); 626 if( ids != null ) { displayMsg = ids; } 627 } 628 629 /** 630 * 【TAG】データを全件選択済みとして処理するかどうか[true/false]を指定します(初期値:false)。 631 * 632 * @og.tag 633 * 全てのデータを選択済みデータとして扱って処理します。 634 * 全件処理する場合に、(true/false)を指定します。 635 * 初期値は false です。 636 * 637 * @param all 全件選択済み指定 [true:全件選択済み/false:通常] 638 */ 639 public void setSelectedAll( final String all ) { 640 selectedAll = nval( getRequestParameter( all ),selectedAll ); 641 } 642 643 /** 644 * 【TAG】オリジナルのタイムスタンプを利用するかどうかを指定します(初期値:false)。 645 * 646 * @og.tag 647 * COPYや親違いMOVE(,MODIFY)の時に、オリジナルのタイムスタンプをそのままコピー先のファイルにも 648 * 適用するかどうかを指定します。 649 * タイムスタンプを初期化されたくない場合に、true に設定します。 650 * 初期値は 利用しない:false です。 651 * 652 * @param flag タイムスタンプ利用 [true:する/false:しない] 653 */ 654 public void setKeepTimeStamp( final String flag ) { 655 keepTimeStamp = nval( getRequestParameter( flag ),keepTimeStamp ); 656 } 657 658 /** 659 * 【TAG】処理時間を表示する TimeView を表示するかどうか[true:する/false:しない]を指定します 660 * (初期値:VIEW_USE_TIMEBAR[={@og.value SystemData#VIEW_USE_TIMEBAR}])。 661 * 662 * @og.tag 663 * true に設定すると、処理時間を表示するバーイメージが表示されます。 664 * これは、DB検索、APサーバー処理、画面表示の各処理時間をバーイメージで 665 * 表示させる機能です。処理時間の目安になります。 666 * (初期値:VIEW_USE_TIMEBAR[={@og.value SystemData#VIEW_USE_TIMEBAR}])。 667 * 668 * @og.rev 6.3.6.0 (2015/08/16) useTimeView の初期値を、VIEW_USE_TIMEBAR にする。 669 * 670 * @param flag 処理時間を表示 [true:する/false:しない] 671 */ 672 public void setUseTimeView( final String flag ) { 673 useTimeView = nval( getRequestParameter( flag ),useTimeView ); 674 } 675 676 /** 677 * 【TAG】入力共通パスを指定します。 678 * 679 * @og.tag 680 * 通常、fileQueryタグ等で、検索した結果は、PARENT,NAME というカラムにセットされます。 681 * この、fileQueryのfrom属性に、検索を開始するディレクトリを指定し、multi="true"で、 682 * 多段階展開 した場合、この、from属性に指定したパスを、inPath にセットすることで、 683 * 以下の階層フォルダそのままに、targetDir にCOPY または、MOVE することが出来ます。 684 * 逆に、指定しない場合は、フォルダ階層無しで、COPY,MOVE されます。 685 * 686 * @og.rev 6.8.0.0 (2017/06/02) 入力共通パスを指定します。 687 * @og.rev 7.0.5.0 (2019/09/13) inPath のパスは、正規パス名から作成。 688 * 689 * @param path 入力共通パス 690 */ 691 public void setInPath( final String path ) { 692 inPath = nval( getRequestParameter( path ),inPath ); 693 694 // 7.0.5.0 (2019/09/13) inPath のパスは、正規パス名から作成。 695 if( inPath != null ) { 696 try { 697 inPath = new File(inPath).getCanonicalPath(); 698 } 699 catch( final IOException ex ) { 700 final String errMsg = "inPathの正式なファイル名の取得に失敗しました。[" + inPath + "]" 701 + CR + ex.getMessage(); 702 throw new HybsSystemException( errMsg,ex ); 703 } 704 } 705 } 706 707 /** 708 * 【TAG】エラーメッセージにSLABELを利用するかどうか[true/false]を指定します(初期値:false)。 709 * 710 * @og.tag 711 * 通常のエラーメッセージは、ラベル(長)が使われますが、これをラベル(短)を使いたい場合に、true にセットします。 712 * ここでのラベル(短)は、タグ修飾なしの、ラベル(短)です。 713 * 標準はfalse:利用しない=ラベル(長)です。 714 * true/false以外を指定した場合はfalse扱いとします。 715 * 716 * ラベルリソースの概要説明があれば表示しますが、useSLabel="true" 時は、概要説明を表示しません。 717 * 718 * @og.rev 7.0.7.0 (2019/12/13) 新規追加 719 * 720 * @param prm SLABEL利用 [true:利用する/false:利用しない] 721 */ 722 public void setUseSLabel( final String prm ) { 723 useSLabel = nval( getRequestParameter( prm ),useSLabel ); 724 } 725 726 /** 727 * DBTableModel から、FromFile,ToFile を作成するための処理をまとめた補助クラスです。 728 * 729 * ここでは、オリジナルファイルやターゲットファイルを作成するための処理のみを集めています。 730 * メソッドにすると、ローカル変数を多く管理するか、多数の引数渡しを繰り返すことになるため、 731 * このローカルクラスに処理と、値を格納します。 732 * 733 */ 734 private static final class FromToFiles { 735 private final DBTableModel table ; 736 737 private final int PARENT ; 738 private final int NAME ; 739 private final int TO_PARENT ; 740 private final int TO_NAME ; 741 742 private final File toDir ; 743 private final boolean createDir; // ターゲットとなるフォルダがなければ、作成するかどうか(true:作成する) 744 private final int inPathCnt ; // 6.8.0.0 (2017/06/02) 入力共通パスの文字数 745 746 private boolean equalParent ; // 最後に実行された処理で、親フォルダが同一の場合は、true 747 748 /** 749 * 引数指定のコンストラクター 750 * 751 * 必要なパラメータを渡して、オブジェクトを構築します。 752 * 入力共通パス(inPath)は、COPY/MOVE時にtargetDirと置換されます。 753 * 754 * @og.rev 6.8.0.0 (2017/06/02) 入力共通パス(inPath)を指定します。 755 * 756 * @param table 一覧が格納されているDBTableModel 757 * @param targetDir ターゲットとなるフォルダ 758 * @param createDir フォルダ作成可否 [true:作成する/false:作成しない] 759 * @param inPath 入力共通パス 760 */ 761 public FromToFiles( final DBTableModel table , final String targetDir , final boolean createDir , final String inPath ) { 762 this.table = table; 763 this.createDir = createDir ; 764 toDir = mkDirs( targetDir,createDir ); // targetDir が指定されていない場合は、null 765 // 7.0.5.0 (2019/09/13) inPath のパスの文字数も、正規パス名から作成。 766 inPathCnt = inPath == null ? 0 : inPath.length() ; // 6.8.0.0 (2017/06/02) 入力共通パスの文字数 767 768 // "PARENT","NAME","TO_PARENT","TO_NAME" のカラム名のDBTableModelのカラム番号。存在しない場合は、-1 769 PARENT = table.getColumnNo( "PARENT" , false ); 770 NAME = table.getColumnNo( "NAME" , false ); 771 TO_PARENT = table.getColumnNo( "TO_PARENT", false ); 772 TO_NAME = table.getColumnNo( "TO_NAME" , false ); 773 } 774 775 /** 776 * 行番号より、対応するオリジナルファイル(FromFile)を返します。 777 * 778 * ここでは、TO_PARENT や TO_NAME は、判定する必要がないため、makeFromToFile( int ) の 779 * 一部のみで処理が終了できます。 780 * 1.FromDir は、PARENT 列の値から作成する。 781 * 2.FromFileは、FromDir + NAME列の値から作成する。 782 * 783 * 配列返しの関係で、メソッド(および内部処理)を分けています。 784 * 785 * @param rowNo カラムNo 786 * @return オリジナルファイル(FromFile) 787 * @og.rtnNotNull 788 * @see #makeFromToFile( int ) 789 */ 790 public File makeFromOnly( final int rowNo ) { 791 final String[] value = table.getValues( rowNo ); 792 final File fromDir = mkDirs( value[PARENT],createDir ); 793 794 return new File( fromDir, value[NAME] ) ; 795 } 796 797 /** 798 * 行番号より、対応するオリジナルファイル(FromFile)とターゲットファイル(ToFile)を配列に格納して返します。 799 * 800 * ここでは、TO_PARENT や TO_NAME は、存在するかどうか不明なので、以下の手順で作成します。 801 * 1.FromDir は、PARENT 列の値から作成する。 802 * 2.FromFileは、FromDir + NAME列の値から作成する。 803 * 3.toDir は、 804 * A.targetDir が有れば、それを使う。 805 * B.なければ、TO_PARENT 列の値から作成する。 806 * C.TO_PARENT 列がないか、値が未設定の場合は、FromDir をそのまま使う。 807 * 4.toFile は、 808 * A.toDir + TO_NAME 列の値から作成する。 809 * B.TO_NAME 列がないか、値が未設定の場合は、toDir + NAME列の値から作成する。 810 * 返り値は、new File[] { formFile , toFile }; とする。 811 * 812 * @og.rev 6.8.0.0 (2017/06/02) 入力共通パス(inPath)を指定します。 813 * 814 * @param rowNo カラムNo 815 * @return ファイル配列(0:オリジナルファイル 1:ターゲットファイル) 816 * @og.rtnNotNull 817 */ 818 public File[] makeFromToFile( final int rowNo ) { 819 final String[] value = table.getValues( rowNo ); 820 final File fromDir = mkDirs( value[PARENT],createDir ); 821 final File formFile = new File( fromDir, value[NAME] ); 822 File tempToDir = toDir; 823 824 equalParent = false; // 最後に実行された処理で、親フォルダが同一かどうかのフラグをリセットする。 825 if( tempToDir == null ) { 826 if( TO_PARENT >= 0 && nval( value[TO_PARENT],null ) != null ) { 827 tempToDir = mkDirs( value[TO_PARENT],createDir ); 828 } 829 else { 830 tempToDir = fromDir; 831 equalParent = true; // 最後に実行された処理で、親フォルダが同一の場合は、true 832 } 833 } 834 // 6.8.0.0 (2017/06/02) toDirが指定され、かつ、入力共通パスの文字数(inPathCnt)が指定された場合。 835 else if( inPathCnt > 0 ) { 836 if( TO_PARENT >= 0 && nval( value[TO_PARENT],null ) != null ) { 837 final String prntVal = toDir.getAbsolutePath() + value[TO_PARENT].substring( inPathCnt ); 838 tempToDir = mkDirs( prntVal,createDir ); 839 } 840 else { 841 final String prntVal = toDir.getAbsolutePath() + value[PARENT].substring( inPathCnt ); 842 tempToDir = mkDirs( prntVal,createDir ); 843 } 844 } 845 846 File toFile = null; 847 if( TO_NAME >= 0 && nval(value[TO_NAME],null) != null ) { 848 toFile = new File( tempToDir, value[TO_NAME] ); 849 } 850 else { 851 toFile = new File( tempToDir, value[NAME] ); 852 } 853 854 return new File[] { formFile , toFile }; 855 } 856 857 /** 858 * 最後に実行された処理で、親フォルダが同一かどうかを返します(同一の場合は、true)。 859 * 860 * makeFromToFile( int ) が処理されたときの、FromDir と toDir が同一であれば、true を、 861 * 異なる場合は、false を返します。 862 * ここでの結果は、厳密な同一判定ではなく、処理的に、同一かどうかを判定しています。 863 * つまり、toDir に FromDir をセットする(3.Cのケース)場合に、true を内部変数にセットします。 864 * この判定値は、ファイルの移動処理で、異なる親フォルダの場合は、COPY & DELETE しなければ 865 * なりませんが、同一親フォルダの場合は、RENAME で済む という処理負荷の軽減が目的です。 866 * よって、結果的に、PARENT と TO_PARENT が同じとか、PARENT と targetDir が同じでも 867 * ここでのフラグは、false が返されます。 868 * 869 * @return 最後に実行された処理で、親フォルダが同一の場合は、true 870 * @see #makeFromToFile( int ) 871 */ 872 public boolean lastParentEquals() { 873 return equalParent ; 874 } 875 876 // /** 877 // * カラム名配列(String[])より、対応するカラムNo配列(int[])を作成します。 878 // * 879 // * ここでは、TO_PARENT や TO_NAME は、存在するかどうか不明なので、 880 // * EXCEPTION にせず、配列番号に、-1 を返すようにしています。 881 // * 882 // * @param table 一覧が格納されているDBTableModel 883 // * @param nameArray カラム名配列 884 // * @return カラムNo配列(カラム名が存在しない場合は、-1) 885 // */ 886 // private int[] getTableColumnNo( final DBTableModel table ,final String[] nameArray ) { 887 // int[] clmNo = new int[ nameArray.length ]; 888 // for( int i=0; i<clmNo.length; i++ ) { 889 // clmNo[i] = table.getColumnNo( nameArray[i] , false ); // カラム名が存在しない場合は、-1 を返す。 890 // } 891 // return clmNo; 892 // } 893 894 /** 895 * フォルダを作成します。 896 * 897 * フォルダが存在しない場合は、途中階層をすべて作成します。 898 * 899 * @og.rev 7.0.5.0 (2019/09/13) target のパスも、正規パス名から作成。 900 * 901 * @param fname フォルダ名 902 * @param createDir フォルダ作成可否 [true:作成する/false:作成しない] 903 * @return フォルダを表すファイルオブジェクト。引数が null の場合は、null を返します。 904 * @throws HybsSystemException ファイルか、存在しない場合に、createDir=false か、mkdirs() が false の場合 905 */ 906 private File mkDirs( final String fname , final boolean createDir ) { 907 File target = null; 908 if( fname != null ) { 909 // 7.0.5.0 (2019/09/13) target のパスも、正規パス名から作成。 910// target = new File( fname ); 911 try { 912 target = new File( fname ).getCanonicalFile(); 913 if( target.exists() ) { // 存在する 914 if( target.isFile() ) { 915 final String errMsg = "ターゲットに、ファイル名は指定できません。" + CR 916 + "ターゲット=[" + fname + "]" + CR; 917 throw new HybsSystemException( errMsg ); 918 } 919 } 920 else { // 存在しない 921 // 存在しないのに、作成しない 922 if( !createDir ) { 923 final String errMsg = "ターゲットが存在しません。 " + CR 924 + "ターゲット=[" + fname + "]" + CR; 925 throw new HybsSystemException( errMsg ); 926 } 927 // 作成できない 928 if( !target.mkdirs() ) { 929 final String errMsg = "ターゲットを自動作成使用としましたが、作成できませんでした。" + CR 930 + "ターゲット=[" + fname + "]" + CR; 931 throw new HybsSystemException( errMsg ); 932 } 933 } 934 } 935 catch( final IOException ex ) { 936 final String errMsg = "File#getCanonicalFile() で、正式パス名を求めることができませんでした。" + CR 937 + ex.getMessage() 938 + "ターゲット=[" + fname + "]" + CR; 939 throw new HybsSystemException( errMsg,ex ); 940 } 941 } 942 return target; 943 } 944 } 945 946 /** 947 * このオブジェクトの文字列表現を返します。 948 * 基本的にデバッグ目的に使用します。 949 * 950 * @return このクラスの文字列表現 951 * @og.rtnNotNull 952 */ 953 @Override 954 public String toString() { 955 return ToString.title( this.getClass().getName() ) 956 .println( "VERSION" ,VERSION ) 957 .println( "action" ,action ) 958 .println( "command" ,command ) 959 .println( "targetDir" ,targetDir ) 960 .println( "createDir" ,createDir ) 961 .println( "tableId" ,tableId ) 962 .println( "outMessage" ,outMessage ) 963 .println( "displayMsg" ,displayMsg ) 964 .println( "selectedAll" ,selectedAll ) 965 .println( "keepTimeStamp" ,keepTimeStamp ) 966 .fixForm().toString() ; 967 } 968}