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.db; 017 018import org.opengion.fukurou.system.HybsConst ; // 6.1.0.0 (2014/12/26) 019import org.opengion.fukurou.util.ErrorMessage; 020import org.opengion.fukurou.db.Transaction; 021import org.opengion.hayabusa.common.HybsSystemException; 022import org.opengion.hayabusa.resource.ResourceManager; 023import org.opengion.hayabusa.html.ViewMarker; // 8.0.0.0 (2021/09/30) 024 025import java.util.Locale; 026import java.util.Map; 027import java.util.LinkedHashMap ; 028import java.util.concurrent.ConcurrentMap; // 6.4.3.3 (2016/03/04) 029import java.util.concurrent.ConcurrentHashMap; // 6.4.3.1 (2016/02/12) refactoring 030import java.util.Collections; // 6.4.3.1 (2016/02/12) refactoring 031 032/** 033 * AbstractTableFilter は、TableUpda インターフェースを継承した、DBTableModel 処理用の 034 * Abstract実装クラスです。 035 * 036 * @og.rev 5.5.2.6 (2012/05/25) protected変数をprivateに変更。インターフェースにメソッド追加 037 * @og.rev 6.4.1.1 (2016/01/16) keysMap を、サブクラスから設定させるように変更。 038 * 039 * @version 0.9.0 2000/10/17 040 * @author Kazuhiko Hasegawa 041 * @since JDK1.1, 042 */ 043public abstract class AbstractTableFilter implements TableFilter { 044 /** システムの改行コードを設定します。*/ 045 protected static final String CR = HybsConst.CR; // 6.1.0.0 (2014/12/26) refactoring 046 /** StringBilderなどの初期値を設定します。 {@value} */ 047 protected static final int BUFFER_MIDDLE = HybsConst.BUFFER_MIDDLE; // 6.1.0.0 (2014/12/26) refactoring 048 049 // 5.5.2.6 (2012/05/25) protected変数をprivateに変更。インターフェースにメソッド追加 050 private DBTableModel table ; 051 private String modifyType ; 052 private int[] rowNo ; 053 private boolean useDebug ; // 6.0.2.5 (2014/10/31) refactoring メソッドと同じなので名称変更 054 private Transaction tran ; // 5.1.9.0 (2010/08/01) 追加 055 private String sql ; // 4.2.4.0 (2008/06/23) 056 private String dbid ; // 4.2.4.0 (2008/06/23) 057 private ResourceManager resource ; // 4.3.7.4 (2009/07/01) 058 private ViewMarker viewMarker ; // 8.0.0.0 (2021/09/30) 059 060 private int errCode = ErrorMessage.OK; 061 private ErrorMessage errMessage ; 062 063 /** 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。 */ 064 private final ConcurrentMap<String,String> keyValMap = new ConcurrentHashMap<>(); 065 066 /** 7.4.0.1 (2021/04/16) 値を返すための変数 */ 067 private final ConcurrentMap<String,String> rtnValMap = new ConcurrentHashMap<>(); 068 069 // 5.6.6.0 (2013/07/05) keys の整合性チェックを行います。 070 // 6.4.1.1 (2016/01/16) keysMap を、サブクラスから設定させるように変更 071 /** 6.4.3.1 (2016/02/12) Collections.synchronizedMap で同期処理を行います。 */ 072 private final Map<String,String> keysMap = Collections.synchronizedMap( new LinkedHashMap<>() ) ; 073 074 // 6.0.2.3 (2014/10/10) plugin.table.TableFilter_XXXX から移動 075 /** XML宣言定数 */ 076 protected static final String XML_START_TAG = "<?xml version='1.0' encoding='UTF-8'?>" + CR + "<ROWSET tableName='xxx'>"; 077 /** ROWSET 終了TAG {@value} */ 078 protected static final String XML_END_TAG = "</ROWSET>"; 079 /** EXEC_SQL 開始TAG {@value} */ 080 protected static final String EXEC_START_TAG= "<EXEC_SQL>"; 081 /** EXEC_SQL exists="0" 開始TAG {@value} */ 082 protected static final String EXEC_EXISTS_0_TAG= "<EXEC_SQL exists=\"0\">"; // 8.1.0.3 (2022/01/21) 083 /** EXEC_SQL 終了TAG {@value} */ 084 protected static final String EXEC_END_TAG = "</EXEC_SQL>"; 085 086 // 6.0.2.3 (2014/10/10) isXml で、CR + EXEC_END_TAG のキャッシュを作成します。 087 /** XML形式かどうか */ 088 protected boolean isXml ; // 6.0.2.3 (2014/10/10) 089 /** exists判定に使用するSQL文 */ 090 protected String execExistsSQL; // 8.1.0.3 (2022/01/21) 091 /** 終了タグ */ 092 protected String execEndTag ; // 6.0.2.3 (2014/10/10) 093 094 /** 095 * デフォルトコンストラクター 096 * 097 * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor. 098 */ 099 protected AbstractTableFilter() { super(); } // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。 100 101 /** 102 * keys の整合性チェックを行うための初期設定を行います。 103 * サブクラスのコンストラクタ内で、設定するようにしてください。 104 * 105 * @og.rev 6.4.1.1 (2016/01/16) keys の整合性チェック対応 106 * @og.rev 6.4.3.1 (2016/02/12) ConcurrentMap 系は、key,val ともに not null 制限です。 107 * 108 * @param key 整合性チェックを行うための keysMap に設定するキー 109 * @param cmnt 整合性チェックを行うための キー の説明 110 */ 111 protected void initSet( final String key , final String cmnt ) { 112 if( key != null && cmnt != null ) { 113 keysMap.put( key , cmnt ); 114 } 115 } 116 117 /** 118 * DBTableModel をセットします。 119 * 120 * @param table DBTableModelオブジェクト 121 */ 122 public void setDBTableModel( final DBTableModel table ) { 123 this.table = table; 124 } 125 126 /** 127 * DBTableModel を取得します。 128 * 129 * @og.rev 5.5.2.6 (2012/05/25) インターフェースにgetterメソッド追加 130 * 131 * @return 内部のDBTableModel 132 */ 133 public DBTableModel getDBTableModel() { 134 return table; 135 } 136 137 /** 138 * データ処理の方法(A:追加 C:更新 D:削除)を指定します。 139 * 140 * 通常は、DBTableModel に自動設定されている modifyType を元に、データ処理方法を 141 * 選別します。(A:追加 C:更新 D:削除) 142 * この場合、行単位で modifyType の値を取得して判別する必要がありますが、一般には 143 * 処理対象は、全件おなじ modifyType である可能性が高いです。 144 * また、selectedAll などで強制的に全件処理対象とする場合は、modifyType に値が 145 * 設定さていません。その様な場合に外部より modifyType を指定します。 146 * 初期値は、自動判定 です。 147 * 148 * @og.rev 5.5.2.6 (2012/05/25) 廃止 149 * 150 * @param type データ処理の方法(A:追加 C:更新 D:削除) 151 */ 152 public void setModifyType( final String type ) { 153 modifyType = type; 154 } 155 156 /** 157 * データ処理の方法(A:追加 C:更新 D:削除)を取得します。 158 * 159 * 初期値は、自動判定 です。 160 * 161 * @og.rev 5.5.2.6 (2012/05/25) インターフェースにgetterメソッド追加 162 * 163 * @return データ処理の方法(A:追加 C:更新 D:削除) 164 */ 165 public String getModifyType() { 166 return modifyType ; 167 } 168 169 /** 170 * キーと値のペアの変数配列を受け取ります。 171 * 172 * ここでは、この方式以外に、パラメーターMapを受け取る方法もあります。 173 * この受け取る時に、キーを大文字化します。TableFilter の keys は、 174 * 大文字のみで定義しておくことで、HTMLやWindows世代の曖昧な表記方法に 175 * 対応しています。(unixやxmlのような厳格な方が好きですけど) 176 * 177 * keys,vals とパラメーターMapを同時に指定した場合は、両方とも有効です。 178 * ただし、キーが重複した場合は、不定と考えてください。 179 * 180 * @og.rev 5.6.6.0 (2013/07/05) keys の整合性チェックを行います。 181 * 182 * @param keys キー配列 183 * @param vals 値配列 184 * @see #setParamMap( ConcurrentMap ) 185 */ 186 public void setKeysVals( final String[] keys,final String[] vals ) { 187 if( keys != null && vals != null ) { 188 for( int i=0; i<keys.length; i++ ) { 189 // 5.6.6.0 (2013/07/05) 共通のセッターメソッド経由で登録します。 190 setKeyVal( keys[i],vals[i] ); 191 } 192 } 193 } 194 195 /** 196 * キーと値のペアを受け取り、内部の keyValMap マップに追加します。 197 * 198 * キーか値のどちらかが null の場合は、何もしません。つまり、val に 199 * null をセットすることはできません。 200 * 201 * このメソッドは、setKeysVals( String[] ,String[] ) メソッドと、 202 * setParamMap( Map<String,String> ) メソッドの両方から、使用します。 203 * 処理を行うに当たり、下記の処理を行います。 204 * 1.キーを大文字化します。 205 * 2.各クラスの keys と整合性チェックを行います。 206 * 207 * ただし、setKeysVals と setParamMap の登録順は、不定と考えてください。 208 * 両方に同じキーを指定すると、どちらの値がセットされたかは、不定です。 209 * 210 * @og.rev 5.6.6.0 (2013/07/05) keys の整合性チェックを行います。 211 * @og.rev 6.4.3.4 (2016/03/12) Map#forEach で対応する。 212 * @og.rev 6.7.9.1 (2017/05/19) keysMap が、空の場合も、keyValMap に登録する。(initSet 未登録時) 213 * @og.rev 7.0.1.0 (2018/10/15) XHTML → HTML5 対応(空要素の、"/>" 止めを、">" に変更します)。 214 * @og.rev 8.0.0.0 (2021/09/30) brタグを止めてを、preタグに変更します。 215 * 216 * @param key キー文字列(null の場合は、処理しない) 217 * @param val 値文字列(null の場合は、処理しない) 218 * @see #setKeysVals( String[] ,String[] ) 219 * @see #setParamMap( ConcurrentMap ) 220 */ 221 private void setKeyVal( final String key,final String val ) { 222 // key か val かどちらかが null の場合は、処理を行わない。 223 if( key == null || val == null ) { return; } 224 225 final String upKey = key.toUpperCase(Locale.JAPAN); 226 227 // 6.7.9.1 (2017/05/19) keysMap が、空の場合も、keyValMap に登録する。(initSet 未登録時) 228 if( keysMap.isEmpty() || keysMap.containsKey( upKey ) ) { // keysMap は、各サブクラスで定義 229 keyValMap.put( upKey,val ); 230 } 231 else { 232// final String BR = "<br />" + CR ; 233// final String BR = "<br>" + CR ; // 7.0.1.0 (2018/10/15) 234 final String BR = CR ; // 8.0.0.0 (2021/09/30) 235 final StringBuilder errMsg = new StringBuilder( BUFFER_MIDDLE ); 236 // 6.0.2.5 (2014/10/31) char を append する。 237// errMsg.append( BR ) 238 errMsg.append( "<pre>" ).append( BR ) 239 .append( "指定のキーは、この tableFilter では、使用できません。" ).append( BR ) 240 .append( " class=[" ).append( getClass().getName() ).append( ']' ).append( BR ) 241 .append( " key =[" ).append( key ).append( ']' ).append( BR ) 242 .append( " ======== usage keys ======== " ).append( BR ) ; 243 // 6.4.3.4 (2016/03/12) Map#forEach で対応する。 244 keysMap.forEach( (k,v) -> { errMsg.append( ' ' ).append( k ).append( ':' ).append( v ).append( BR ); } ); 245 errMsg.append( " ============================ " ).append( BR ).append( "</pre>" ); 246 247 throw new HybsSystemException( errMsg.toString() ); 248 } 249 } 250 251 /** 252 * 選択された行番号の配列をセットします。 253 * 254 * 表示データの HybsSystem.ROW_SELECTED_KEY を元に、選ばれた 行を 255 * 処理の対象とします。 256 * 257 * @param rowNoTmp 行番号配列(可変長引数) 258 */ 259 public void setParameterRows( final int... rowNoTmp ) { 260 if( rowNoTmp != null && rowNoTmp.length > 0 ) { // 6.1.1.0 (2015/01/17) 可変長引数でもnullは来る。 261 final int size = rowNoTmp.length ; 262 rowNo = new int[size]; 263 System.arraycopy( rowNoTmp,0,rowNo,0,size ); 264 } 265 } 266 267 /** 268 * 選択された行番号の配列を取得します。 269 * 270 * 表示データの HybsSystem.ROW_SEL_KEY を元に、選ばれた 行を 271 * 処理の対象とします。 272 * 273 * @og.rev 5.5.2.6 (2012/05/25) インターフェースにgetterメソッド追加 274 * @og.rev 6.0.2.5 (2014/10/31) null ではなく、サイズ0の配列を返すように変更。 275 * 276 * @return 行番号の配列(選ばれていない場合は、サイズ0の配列を返す) 277 * @og.rtnNotNull 278 */ 279 public int[] getParameterRows() { 280 // 6.4.1.1 (2016/01/16) PMD refactoring. Avoid if (x != y) ..; else ..; 281 return rowNo == null ? new int[0] : rowNo.clone() ; 282 } 283 284 /** 285 * アクセスログ取得の為,Transactionオブジェクトを設定します。 286 * 287 * @og.rev 5.1.9.0 (2010/08/01) Transaction 対応(新規追加) 288 * 289 * @param tran Transactionオブジェクト 290 */ 291 public void setTransaction( final Transaction tran ) { 292 this.tran = tran; 293 } 294 295 /** 296 * アクセスログ取得の為,Transactionオブジェクトを取得します。 297 * 298 * @og.rev 5.1.9.0 (2010/08/01) Transaction 対応(新規追加) 299 * @og.rev 5.5.2.6 (2012/05/25) インターフェースにgetterメソッド追加 300 * 301 * @return Transactionオブジェクト 302 */ 303 public Transaction getTransaction() { 304 return tran; 305 } 306 307 /** 308 * DBIDを指定します。 309 * 310 * @og.rev 4.2.4.0 (2008/06/23) 新規追加 311 * 312 * @param dbid 接続先ID 313 */ 314 public void setDbid( final String dbid ) { 315 this.dbid = dbid; 316 } 317 318 /** 319 * DBIDを取得します。 320 * 321 * @og.rev 4.2.4.0 (2008/06/23) 新規追加 322 * @og.rev 5.5.2.6 (2012/05/25) インターフェースにgetterメソッド追加 323 * 324 * @return DBID(接続先情報) 325 */ 326 public String getDbid() { 327 return dbid; 328 } 329 330 /** 331 * ボディー部分のSQLを指定します。 332 * 333 * @og.rev 4.2.4.0 (2008/06/23) 新規追加 334 * 335 * @param sql ボディー部分のSQL 336 */ 337 public void setSql( final String sql ) { 338 this.sql = sql; 339 } 340 341 /** 342 * ボディー部分のSQLを取得します。 343 * 344 * @og.rev 4.2.4.0 (2008/06/23) 新規追加 345 * @og.rev 5.5.2.6 (2012/05/25) インターフェースにgetterメソッド追加 346 * 347 * @return ボディー部分のSQL 348 */ 349 public String getSql() { 350 return sql; 351 } 352 353 /** 354 * パラメーターMapを指定します。 355 * 356 * keys,vals と パラメーターMapを同時に指定した場合は、両方とも有効です。 357 * ただし、キーが重複した場合は、不定と考えてください。 358 * 359 * この受け取る時に、キーを大文字化します。TableFilter の keys は、 360 * 大文字のみで定義しておくことで、HTMLやWindows世代の曖昧な表記方法に 361 * 対応しています。(unixやxmlのような厳格な方が好きですけど) 362 * 363 * @og.rev 5.6.5.2 (2013/06/21) 新規追加 364 * @og.rev 5.6.6.0 (2013/07/05) keys の整合性チェックを行います。 365 * @og.rev 6.4.3.3 (2016/03/04) ConcurrentHashMap を受け取ることを明確にするため、I/FをConcurrentMapに変更します。 366 * 367 * @param paramMap パラメーターMap 368 * @see #setKeysVals( String[] ,String[] ) 369 */ 370 public void setParamMap( final ConcurrentMap<String,String> paramMap ) { 371 // 6.4.3.3 (2016/03/04) Map#forEach に変更 372 if( paramMap != null ) { 373 paramMap.forEach( (k,v) -> setKeyVal( k,v ) ); 374 } 375 } 376 377 /** 378 * リソースオブジェクトを指定します。 379 * 380 * @og.rev 4.3.7.4 (2009/07/01) 新規追加 381 * 382 * @param resource リソースオブジェクト 383 */ 384 public void setResource( final ResourceManager resource ) { 385 this.resource = resource; 386 } 387 388 /** 389 * リソースオブジェクトを取得します。 390 * 391 * @og.rev 4.3.7.4 (2009/07/01) 新規追加 392 * @og.rev 5.5.2.6 (2012/05/25) インターフェースにgetterメソッド追加 393 * 394 * @return リソースオブジェクト 395 */ 396 public ResourceManager getResource() { 397 return resource; 398 } 399 400 /** 401 * viewMarkerオブジェクトを指定します。 402 * 403 * @og.rev 8.0.0.0 (2021/09/30) viewMarker追加 404 * 405 * @param marker viewMarkerオブジェクト 406 */ 407 public void setViewMarker( final ViewMarker marker ) { 408 viewMarker = marker; 409 } 410 411 /** 412 * viewMarkerオブジェクトを取得します。 413 * 414 * @og.rev 8.0.0.0 (2021/09/30) viewMarker追加 415 * 416 * @return viewMarkerオブジェクト 417 */ 418 public ViewMarker getViewMarker() { 419 return viewMarker; 420 } 421 422 /** 423 * 値を返すためのMapを返します。 424 * 425 * Mapそのものを返しますので、中身の書き換えは行わないでください。 426 * 427 * @og.rev 7.4.0.1 (2021/04/16) 値を返すための変数 428 * 429 * @return Mapオブジェクト 430 */ 431 public Map<String,String> getReturnMap() { 432 return rtnValMap; 433 } 434 435 /** 436 * デバッグ情報を出力するかどうか[true:する/false:しない]を指定します。 437 * true でデバッグ情報を表示します。 438 * 439 * @param flag デバッグ出力するか [true:する/false:しない] 440 */ 441 public void setDebug( final boolean flag ) { 442 useDebug = flag; // 6.0.2.5 (2014/10/31) refactoring メソッドと同じなので名称変更 443 } 444 445 /** 446 * デバッグ情報を出力するかどうか[true:する/false:しない]を取得します。 447 * true でデバッグ情報を表示します。 448 * 449 * @og.rev 5.5.2.6 (2012/05/25) インターフェースにgetterメソッド追加 450 * 451 * @return デバッグ出力 [true:する/false:しない] 452 */ 453 public boolean isDebug() { 454 return useDebug ; // 6.0.2.5 (2014/10/31) refactoring メソッドと同じなので名称変更 455 } 456 457 /** 458 * エラーコード を取得します。 459 * エラーコード は、ErrorMessage クラスで規定されているコードです。 460 * 461 * @return エラーコード 462 */ 463 public int getErrorCode() { 464 return errCode; 465 } 466 467 /** 468 * エラーメッセージオブジェクト を取得します。 469 * 470 * @return エラーメッセージオブジェクト 471 */ 472 public ErrorMessage getErrorMessage() { 473 return errMessage; 474 } 475 476 /** 477 * タイトルとエラーコードを指定して、エラーメッセージオブジェクト を作成します。 478 * すでに、作成済みの場合は、作成済みのオブジェクトを、まだ、未作成の場合は、 479 * 新規に作成します。 480 * 481 * @param title タイトル 482 * @param code エラーコード 483 * 484 * @return エラーメッセージオブジェクト 485 */ 486 protected ErrorMessage makeErrorMessage( final String title,final int code ) { 487 if( errMessage == null ) { 488 errMessage = new ErrorMessage( title ); 489 } 490 if( errCode < code ) { errCode = code; } 491 return errMessage; 492 } 493 494 /** 495 * カラム名配列(String[])より、対応するカラムNo配列(int[])を作成します。 496 * 497 * @param nameArray カラム名配列 498 * 499 * @return カラムNo配列(可変長引数) 500 */ 501 protected int[] getTableColumnNo( final String... nameArray ) { 502 int[] clmNo = new int[nameArray.length]; 503 for( int i=0; i<clmNo.length; i++ ) { 504 clmNo[i] = table.getColumnNo( nameArray[i] ); 505 } 506 return clmNo; 507 } 508 509 /** 510 * 設定されたパラメータキーに対する値を取得します。 511 * 引数、および、パラメータが null の場合は、 null を返します。 512 * 513 * @og.rev 6.4.3.3 (2016/03/04) ConcurrentHashMap の not null制限のチェック追加 514 * 515 * @param key パラメータキー 516 * 517 * @return パラメータ値 518 */ 519 protected String getValue( final String key ) { 520 return key == null ? null : keyValMap.get( key ); 521 } 522 523 /** 524 * フィルターからtaglibのリクエスト変数に値を書き戻したい場合に、key と val をセットします。 525 * 引数、および、パラメータが null の場合は、何もしません。 526 * 527 * @og.rev 7.4.0.1 (2021/04/16) 値を返すための変数セット 528 * 529 * @param key 戻しキー 530 * @param val 戻し値 531 */ 532 protected void setValue( final String key ,final String val ) { 533 if( key != null && val != null ) { 534 rtnValMap.put( key,val ); 535 } 536 } 537 538 /** 539 * keyValMapに持っているキーの配列を取得します。 540 * これは、サブクラスで、initSet(String,String) を行わない場合、keys には 541 * 値を自由に設定できます。 542 * その値を取り出すためです。 543 * 544 * @og.rev 6.7.9.1 (2017/05/19) 新規追加 545 * 546 * @return キー値の配列(keyValMapに持っているキー) 547 */ 548 protected String[] getKeys() { 549 return keyValMap.keySet().toArray( new String[keyValMap.size()] ); 550 } 551}