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