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