001/* 002 * Copyright (c) 2009 The openGion Project. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 013 * either express or implied. See the License for the specific language 014 * governing permissions and limitations under the License. 015 */ 016package org.opengion.fukurou.business; 017 018import java.sql.Connection; 019import java.sql.ParameterMetaData; 020import java.sql.PreparedStatement; 021import java.sql.ResultSet; 022import java.sql.ResultSetMetaData; 023import java.sql.SQLException; 024import java.util.Map; 025import java.util.HashMap; // 6.4.3.3 (2016/03/04) not null調査が済むまで、元に戻します。 026import java.util.concurrent.ConcurrentMap; // 6.4.3.3 (2016/03/04) 027import java.util.concurrent.ConcurrentHashMap; // 6.4.3.1 (2016/02/12) refactoring 028import java.util.Locale; 029import java.util.Set; 030import java.util.Arrays; 031 032import org.opengion.fukurou.system.OgRuntimeException ; // 6.4.2.0 (2016/01/29) 033import org.opengion.fukurou.db.ConnectionFactory; 034import org.opengion.fukurou.db.DBFunctionName; 035import org.opengion.fukurou.db.DBUtil; 036import org.opengion.fukurou.db.Transaction; 037import org.opengion.fukurou.model.Formatter; 038import org.opengion.fukurou.model.DataModel; // 6.7.9.1 (2017/05/19) 039import org.opengion.fukurou.system.DateSet; // 6.4.2.0 (2016/01/29) 040import org.opengion.fukurou.util.ErrMsg; 041import org.opengion.fukurou.util.ErrorMessage; 042import org.opengion.fukurou.util.HybsLoader; 043import org.opengion.fukurou.util.StringUtil; 044import org.opengion.fukurou.util.SystemParameter; 045import static org.opengion.fukurou.system.HybsConst.CR; // 6.1.0.0 (2014/12/26) refactoring 046import static org.opengion.fukurou.system.HybsConst.BUFFER_MIDDLE; // 6.1.0.0 (2014/12/26) refactoring 047import static org.opengion.fukurou.system.HybsConst.DB_FETCH_SIZE; // 6.9.4.1 (2018/04/09) 048 049/** 050 * 業務ロジックを処理するために必要な共通メソッドの実行を行っている抽象クラスです。 051 * 052 * メインロジックについては、各サブクラスで実装する必要があります。 053 * 054 * @og.rev 5.1.1.0 (2009/12/01) 新規作成 055 * @og.group 業務ロジック 056 * 057 * @version 5.0 058 * @author Hiroki Nakamura 059 * @since JDK1.6, 060 */ 061public abstract class AbstractBizLogic { 062 063 /** エラーメッセージをセットする際に使用します {@value} */ 064 protected static final int OK = ErrorMessage.OK; 065 /** エラーメッセージをセットする際に使用します {@value} */ 066 protected static final int WARNING = ErrorMessage.WARNING; 067 /** エラーメッセージをセットする際に使用します {@value} */ 068 protected static final int NG = ErrorMessage.NG; 069 /** エラーメッセージをセットする際に使用します {@value} */ 070 protected static final int EXCEPTION = ErrorMessage.EXCEPTION; 071 /** エラーメッセージをセットする際に使用します {@value} */ 072 protected static final int ORCL_ERR = ErrorMessage.ORCL_ERR; 073 074// /** 6.9.3.0 (2018/03/26) データ検索時のフェッチサイズ {@value} */ 075// private static final int DB_FETCH_SIZE = 1001 ; 076 077 private Connection conn ; 078 private Transaction tran ; // 5.1.9.0 (2010/08/01) シーケンス対応 079 private String dbid ; // 5.1.9.0 (2010/08/01) シーケンス対応 080 /** データベースファンクション */ 081 protected DBFunctionName dbName ; // 5.1.9.0 (2010/08/01) シーケンス対応 082 private HybsLoader loader ; 083 private String[] keys ; 084 private String[] vals ; 085 /** 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。 */ 086 private final Map<String, String> variableMap = new HashMap<>(); // 6.4.3.3 (2016/03/04) not null調査が済むまで、元に戻します。 087 /** 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。 */ 088 private final ConcurrentMap<String, Formatter> formatMap = new ConcurrentHashMap<>(); 089 /** 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。 */ 090 private final ConcurrentMap<String, SystemParameter> sysParamMap = new ConcurrentHashMap<>(); 091 private final ErrorMessage errMsg = new ErrorMessage(); 092 private String bizRtn ; // 5.1.8.0 (2010/07/01) メソッド名と変数名を分ける。 093 private boolean debugFlag ; // 5.1.8.0 (2010/07/01) メソッド名と変数名を分ける。 094 095 private final StringBuilder debugMsg = new StringBuilder( BUFFER_MIDDLE ); 096 private boolean useParamMetaData ; // 5.3.8.0 (2011/08/01) useParamMetaData を ConnectionFactory経由で取得。(PostgreSQL対応) 097 098 private final ConcurrentMap<String, String> rtnMap = new ConcurrentHashMap<>(); // 6.9.9.0 (2018/08/20) 戻り値を返せるようにします。 099 100 /** 101 * 配列側テーブルモデル 102 * 103 * 配列型テーブルモデル自体は、protected属性であるため、サブクラスから直接参照することができます。 104 * 但し、これは、各業務ロジックで直接参照することを想定したものではなく、BizLogicの 105 * メイン構造を拡張するサブクラスを定義する際に使用することを想定しています。 106 * (この想定がなければ、本来は、package privateにすべきです) 107 * このため、業務ロジックを各実装クラスでは直接参照しないで下さい。 108 * 109 * @og.rev 6.7.9.1 (2017/05/19) protected ArrayTableModel を、private DataModel に変更します。 110 */ 111 private DataModel<String> table ; // 6.7.9.1 (2017/05/19) 112 113 /** 114 * 配列型テーブルモデルの現在の処理行 115 * 116 * 行番号自体は、protected属性であるため、サブクラスから直接参照することができます。 117 * 但し、これは、各業務ロジックで直接参照することを想定したものではなく、BizLogicの 118 * メイン構造を拡張するサブクラスを定義する際に使用することを想定しています。 119 * (この想定がなければ、本来は、package privateにすべきです) 120 * このため、業務ロジックを各実装クラスでは直接参照しないで下さい。 121 * 122 * ※ インデックス(row)とは、このArrayTableModel に持つ vals 配列の行のインデックスです。 123 * よって、オリジナルのDBTableModelの行番号ではありません。 124 */ 125 protected int row = -1; 126 127 /** 128 * デフォルトコンストラクター 129 * 130 * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor. 131 */ 132 protected AbstractBizLogic() { super(); } // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。 133 134 /** 135 * DBのトランザクションオブジェクトを指定します。 136 * 各実装クラスでは、コネクションのcommit,rollbackは行われません。 137 * (全てのDB処理は、1つのトランザクションとして処理されます。) 138 * このため、commit,rollbackは呼び出し元で行う必要があります。 139 * このメソッドは、1度しかセットすることができません。2回以上呼び出しするとエラーになります。 140 * 141 * @og.rev 5.1.9.0 (2010/08/01) 新規作成 142 * @og.rev 5.3.8.0 (2011/08/01) useParamMetaData を ConnectionFactory経由で取得。(PostgreSQL対応) 143 * 144 * @param tr トランザクション 145 */ 146 public void setTransaction( final Transaction tr ) { 147 tran = tr; 148 conn = tran.getConnection( dbid ); 149 useParamMetaData = ConnectionFactory.useParameterMetaData( dbid ); // 5.3.8.0 (2011/08/01) 150 } 151 152 /** 153 * DBのトランザクションオブジェクトを返します。 154 * 155 * (全てのDB処理は、1つのトランザクションとして処理されます。) 156 * 157 * @og.rev 7.4.2.0 (2021/05/14) 外部から指定するTransactionオブジェクト 対応 158 * 159 * @return トランザクション 160 */ 161 public Transaction getTransaction() { 162 return tran; 163 } 164 165 /** 166 * 接続先IDを指定します。 167 * このメソッドは、1度しかセットすることができません。2回以上呼び出しするとエラーになります。 168 * 169 * @og.rev 5.1.9.0 (2010/08/01) 新規作成 170 * 171 * @param id 接続先ID 172 */ 173 /* default */ void setDbid( final String id ) { 174 dbid = id; 175 } 176 177 /** 178 * 業務ロジックのクラスをロードするためのクラスローダーをセットします。 179 * このメソッドは、1度しかセットすることができません。2回以上呼び出しするとエラーになります。 180 * 181 * @og.rev 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 182 * 183 * @param ldr クラスローダー 184 */ 185 /* default */ void setLoader( final HybsLoader ldr ) { 186 if( loader != null ) { 187 // 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 188 final String errMsg = "既にクラスローダーがセットされています。" 189 + " OLD:" + loader 190 + " IN :" + ldr ; 191 throw new OgRuntimeException( errMsg ); 192 } 193 loader = ldr; 194 } 195 196 /** 197 * 配列型テーブルモデルをセットします。 198 * このメソッドは、1度しかセットすることができません。2回以上呼び出しするとエラーになります。 199 * 200 * @og.rev 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 201 * @og.rev 6.7.9.1 (2017/05/19) ArrayTableModel をDataModel に変更。 202 * 203 * @param tbl 配列型テーブルモデル 204 */ 205 /* default */ void setTable( final DataModel<String> tbl ) { 206 if( table != null ) { 207 // 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 208 final String errMsg = "既に配列型テーブルモデルがセットされています。" 209 + " OLD:" + table 210 + " IN :" + tbl ; 211 throw new OgRuntimeException( errMsg ); 212 } 213 table = tbl; 214 } 215 216 /** 217 * 配列型テーブルモデルを取得します。 218 * 219 * @og.rev 6.7.9.1 (2017/05/19) 新規追加 220 * 221 * @return 配列型テーブルモデル 222 */ 223 protected DataModel<String> getTable() { 224 return table ; 225 } 226 227 /** 228 * 固定値のキー配列を指定します。 229 * このメソッドは、1度しかセットすることができません。2回以上呼び出しするとエラーになります。 230 * 231 * @og.rev 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 232 * 233 * @param ks キー配列(可変長引数) 234 */ 235 /* default */ void setKeys( final String... ks ) { 236 if( keys != null ) { 237 // 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 238 final String errMsg = "既に固定値配列(キー)がセットされています。" + CR 239 + " KESY =" + Arrays.toString( keys ) + CR 240 + " in keys=" + Arrays.toString( ks ) ; 241 throw new OgRuntimeException( errMsg ); 242 } 243 if( ks != null && ks.length > 0 ) { keys = ks; } // 6.1.1.0 (2015/01/17) 可変長引数でもnullは来る。 244 } 245 246 /** 247 * 固定値の値配列を指定します。 248 * このメソッドは、1度しかセットすることができません。2回以上呼び出しするとエラーになります。 249 * 250 * @og.rev 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 251 * 252 * @param vs 値配列(可変長引数) 253 */ 254 /* default */ void setVals( final String... vs ) { 255 if( vals != null ) { 256 // 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 257 final String errMsg = "既に固定値配列(値)がセットされています。" + CR 258 + " VALS =" + Arrays.toString( vals ) + CR 259 + " in vals=" + Arrays.toString( vs ) ; 260 throw new OgRuntimeException( errMsg ); 261 } 262 if( vs != null && vs.length > 0 ) { vals = vs; } // 6.1.1.0 (2015/01/17) 可変長引数でもnullは来る。 263 } 264 265 /** 266 * この処理の実行ユーザーIDを指定します。 267 * 268 * @param id 実行ユーザーID(not null) 269 */ 270 /* default */ void setUserId( final String id ) { 271 variableMap.put( "CON.USERID", id); 272 } 273 274 /** 275 * 親(呼び出し)PGIDを指定します。 276 * 277 * @param id 親PGID 278 */ 279 /* default */ void setParentPgId( final String id ) { 280 variableMap.put( "CON.PGPID", id ); 281 } 282 283 /** 284 * デバッグモードにします。 285 */ 286 /* default */ void setDebug() { 287 debugFlag = true; 288 } 289 290 /** 291 * デバッグメッセージを取得します。 292 * 293 * @return デバッグメッセージ 294 * @og.rtnNotNull 295 */ 296 /* default */ String getDebugMsg() { 297 return debugMsg.toString(); 298 } 299 300 /** 301 * 処理を実行します。 302 * 処理の方法は、main()メソッドにより定義されます。 303 * 実装クラスで発生した全ての例外は、Throwableオブジェクトとしてスローされます。 304 * 呼び出し元では、例外を確実にcatchして、commit,rollbackを行ってください。 305 * 306 * @og.rev 5.1.9.0 (2010/08/01) シーケンス対応 307 * 308 * @return 処理が成功したかどうか 309 * @throws Throwable 実行時の全エラーを上位に転送します。 310 */ 311 /* default */ boolean exec() throws Throwable { 312 dbName = DBFunctionName.getDBName( ConnectionFactory.getDBName( dbid ) ); 313 makeParamMap(); 314 init(); 315 316 return main(); 317 } 318 319 /** 320 * 処理のメインロジックの前処理を記述します。 321 * 322 * このメソッド自体は、protected属性であるため、サブクラスから直接参照することができます。 323 * 但し、これは、各業務ロジックで直接参照することを想定したものではなく、BizLogicの 324 * メイン構造を拡張するサブクラスを定義する際に使用することを想定しています。 325 * (この想定がなければ、本来は、package privateにすべきです) 326 * このため、業務ロジックを各実装クラスでは直接参照しないで下さい。 327 */ 328 protected abstract void init(); 329 330 /** 331 * 処理のメインロジックを記述します。 332 * 333 * このメソッド自体は、protected属性であるため、サブクラスから直接参照することができます。 334 * 但し、これは、各業務ロジックで直接参照することを想定したものではなく、BizLogicの 335 * メイン構造を拡張するサブクラスを定義する際に使用することを想定しています。 336 * (この想定がなければ、本来は、package privateにすべきです) 337 * このため、業務ロジックを各実装クラスでは直接参照しないで下さい。 338 * 339 * @return 処理が正常終了したか 340 */ 341 protected abstract boolean main(); 342 343 /** 344 * 結果ステータスを返します。 345 * 346 * @return 結果ステータス 347 */ 348 /* default */ int getKekka() { 349 return errMsg.getKekka(); 350 } 351 352 /** 353 * エラーメッセージオブジェクトを返します。 354 * 355 * @return エラーメッセージ 356 */ 357 /* default */ ErrorMessage getErrMsg() { 358 return errMsg; 359 } 360 361 /** 362 * 業務ロジックの戻り値を返します。 363 * 364 * @return 戻り値 365 */ 366 /* default */ String getReturn() { 367 return bizRtn; 368 } 369 370 /** 371 * 業務ロジックを実行するために、テーブルモデルが外部からセットされる必要があるか 372 * を返します。 373 * 必須である場合、その業務ロジックは、子ロジックとして呼び出すことができません。 374 * これは、子ロジック呼び出し時は、テーブルモデルがセットされないためです。 375 * (このクラスは、テーブルモデルが外部から指定されている必要はありません。) 376 * 377 * このメソッド自体は、protected属性であるため、サブクラスから直接参照することができます。 378 * 但し、これは、各業務ロジックで直接参照することを想定したものではなく、BizLogicの 379 * メイン構造を拡張するサブクラスを定義する際に使用することを想定しています。 380 * (この想定がなければ、本来は、package privateにすべきです) 381 * このため、業務ロジックを各実装クラスでは直接参照しないで下さい。 382 * 383 * @return テーブルモデルが外部からセットされる必要があるかどうか(常にfalse) 384 */ 385 protected boolean isRequireTable() { 386 return false; 387 } 388 389 /** 390 * デバッグモードかどうかを返します。 391 * 392 * @return デバッグモードかどうか 393 */ 394 protected final boolean isDebug() { 395 return debugFlag; 396 } 397 398 /** 399 * デバッグメッセージを追加します。 400 * 401 * @param msg 追加するデバッグメッセージ 402 */ 403 protected final void debug( final String msg ) { 404 debugMsg.append( msg ).append( CR ); 405 } 406 407 /** 408 * 指定されたキーの値を返します。 409 * 410 * @param key キー 411 * 412 * @return 変数値 413 */ 414 protected final String var( final String key ) { 415 return variableMap.get( key ); 416 } 417 418 /** 419 * 指定されたキーの値をint型に変換して返します。 420 * 421 * @og.rev 6.7.9.0 (2017/04/28) nullと isEmpty() も、0 を返します。 422 * 423 * @param key キー 424 * 425 * @return 変数値 426 */ 427 protected final int vari( final String key ) { 428 return str2int( var( key ) ); // 6.7.9.1 (2017/05/19) 429 } 430 431 /** 432 * 指定されたキーの値をdouble型に変換して返します。 433 * 434 * @og.rev 6.7.9.0 (2017/04/28) nullと isEmpty() も、0 を返します。 435 * 436 * @param key キー 437 * 438 * @return 変数値 439 */ 440 protected final double vard( final String key ) { 441 return str2dbl( var( key ) ); // 6.7.9.1 (2017/05/19) 442 } 443 444 /** 445 * パラメーターのキー一覧を配列形式で返します。 446 * このパラメーターは、業務ロジック内でセットされたパラメーターも含まれますのでご注意下さい。 447 * 448 * @return パラメーターのキー配列 449 */ 450 protected final String[] varKeys() { 451 final Set<String> keys = variableMap.keySet(); 452 return keys.toArray( new String[keys.size()] ); 453 } 454 455 /** 456 * 指定されたキーで値を登録します。 457 * パラメーターとしてこの業務ロジックが呼ばれる際の引数となっている場合は、 458 * エラーとなります。 459 * 460 * @og.rev 5.2.1.0 (2010/10/01) チェックのバグを修正 461 * @og.rev 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 462 * 463 * @param key キー 464 * @param val 値 465 */ 466 protected final void set( final String key, final String val ) { 467 // 6.0.2.5 (2014/10/31) 素直に、variableMap で、キー有無を判定する。 468 if( variableMap.containsKey( key ) ) { 469 final String errMsg = "すでに登録済みのキーを定義することはできません。" + CR 470 + " key =" + key + CR 471 + " val =" + val + CR 472 + " 元 =" + variableMap.get( key ) ; 473 throw new OgRuntimeException( errMsg ); 474 } 475 variableMap.put( key, val ); 476 } 477 478 /** 479 * 指定されたキーで値を登録します。 480 * パラメーターとしてこの業務ロジックが呼ばれる際の引数となっている場合は、 481 * エラーとなります。 482 * 483 * @og.rev 5.1.9.0 (2010/08/01) 新規作成 484 * 485 * @param key キー 486 * @param val 値 487 */ 488 protected final void set( final String key, final int val ) { 489 set( key, String.valueOf( val ) ); 490 } 491 492 /** 493 * 指定されたキーで値(double型)を登録します。 494 * パラメーターとしてこの業務ロジックが呼ばれる際の引数となっている場合は、 495 * エラーとなります。 496 * 497 * @og.rev 5.1.9.0 (2010/08/01) 新規作成 498 * 499 * @param key キー 500 * @param val 値 501 */ 502 protected final void set( final String key, final double val ) { 503 set( key, String.valueOf( val ) ); 504 } 505 506 /** 507 * 処理中の行の指定されたキー(カラム名)の値を返します。 508 * 509 * @param key キー 510 * 511 * @return 値 512 */ 513 protected final String line( final String key ) { 514 return line( key, row ); 515 } 516 517 /** 518 * メインの配列型テーブルモデルに対して、行を指定して値を取得します。 519 * 指定された行が範囲を超えている場合は、nullを返します。 520 * 521 * @og.rev 5.1.8.0 (2010/07/01) テーブルに存在しないカラム名を指定した場合に、NullPointerExceptionが発生するバグを修正 522 * @og.rev 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 523 * 524 * @param key キー 525 * @param rw 行番号(インデックス) 526 * 527 * @return 値 528 */ 529 protected final String line( final String key, final int rw ) { 530 if( table == null ) { 531 // 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 532 final String errMsg = "配列型テーブルモデルがセットされていないため、#line( String,int )メソッドはできません。" + CR 533 + " line( " + key + "," + rw + " );" + CR ; 534 throw new OgRuntimeException( errMsg ); 535 } 536 // 6.4.1.1 (2016/01/16) PMD refactoring. A method should have only one exit point, and that should be the last statement in the method 537 538 final int col = table.getColumnNo( key ); 539 540 return col < 0 || rw < 0 || rw >= table.getRowCount() ? null : table.getValue( rw, col ); 541 } 542 543 /** 544 * 処理中の行の指定されたカラム番号の値を返します。 545 * line( String )は、毎回、カラム番号を取得しているため、非効率です。 546 * ただし、一旦カラム名から、カラム番号を取得し、それを使用するのと、 547 * linei(String)や、lined(String) などの直接的なメソッドもないため、 548 * 利用者側でそのあたりの処理を入れる必要があります。 549 * 550 * @og.rev 6.7.9.1 (2017/05/19) 文字列を整数に変換します。 551 * 552 * @param col カラム番号 553 * @return 値 554 */ 555 protected final String line( final int col ) { 556 return line( col, row ); 557 } 558 559 /** 560 * メインの配列型テーブルモデルに対して、行を指定して値を取得します。 561 * 指定された行が範囲を超えている場合は、nullを返します。 562 * 563 * @og.rev 6.7.9.1 (2017/05/19) 文字列を整数に変換します。 564 * 565 * @param col カラム番号 566 * @param rw 行番号(インデックス) 567 * @return 値 568 */ 569 protected final String line( final int col, final int rw ) { 570 if( table == null ) { 571 // 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 572 final String errMsg = "配列型テーブルモデルがセットされていないため、#line( String,int )メソッドはできません。" + CR 573 + " line( " + col + "," + rw + " );" + CR ; 574 throw new OgRuntimeException( errMsg ); 575 } 576 577 return col < 0 || rw < 0 || rw >= table.getRowCount() ? null : table.getValue( rw, col ); 578 } 579 580 /** 581 * 処理中の行の指定されたキー(カラム名)の値をint型に変換して返します。 582 * 583 * @og.rev 6.7.9.0 (2017/04/28) row を使用して、#linei( String,int )を呼びます。 584 * 585 * @param key キー 586 * 587 * @return 値 588 */ 589 protected final int linei( final String key ) { 590 return str2int( line( key, row ) ); // 6.7.9.1 (2017/05/19) 591 } 592 593 /** 594 * メインの配列型テーブルモデルに対して、行を指定して値をint型に変換して返します。 595 * 指定された行が範囲を超えている場合は、nullを返します。 596 * 597 * @og.rev 6.7.9.0 (2017/04/28) nullと isEmpty() も、0 を返します。 598 * 599 * @param key キー 600 * @param rw 行番号(インデックス) 601 * 602 * @return 値 603 */ 604 protected final int linei( final String key, final int rw ) { 605 return str2int( line( key, rw ) ); // 6.7.9.1 (2017/05/19) 606 } 607 608 /** 609 * 処理中の行の指定されたキー(カラム名)の値をdouble型に変換して返します。 610 * 611 * @og.rev 6.7.9.0 (2017/04/28) row を使用して、#lined( String,int )を呼びます。 612 * 613 * @param key キー 614 * 615 * @return 値 616 */ 617 protected final double lined( final String key ) { 618 return str2dbl( line( key, row ) ); // 6.7.9.1 (2017/05/19) 619 } 620 621 /** 622 * メインの配列型テーブルモデルに対して、行を指定して値をdouble型に変換して返します。 623 * 指定された行が範囲を超えている場合は、nullを返します。 624 * 625 * @og.rev 6.7.9.0 (2017/04/28) nullと isEmpty() も、0 を返します。 626 * 627 * @param key キー 628 * @param rw 行番号(インデックス) 629 * 630 * @return 値 631 */ 632 protected final double lined( final String key, final int rw ) { 633 return str2dbl( line( key, rw ) ); // 6.7.9.1 (2017/05/19) 634 } 635 636 /** 637 * 指定のカラム名引数に相当するデータを2重配列で返します。 638 * 639 * @og.rev 6.8.5.0 (2018/01/09) 新規追加 640 * 641 * @param clmNms 値が参照されるカラム名配列(可変長引数) 642 * 643 * @return 指定された名引数に相当するデータの2重配列 644 * @og.rtnNotNull 645 */ 646 protected String[][] getValues( final String... clmNms ) { 647 // 6.9.8.0 (2018/05/28) FindBugs:コンストラクタで初期化されていないフィールドを null チェックなしで null 値を利用している 648 if( table == null ) { 649 final String errMsg = "配列型テーブルモデルがセットされていないため、#getValues( String... )メソッドはできません。" + CR 650 + " clmNms= " + Arrays.toString( clmNms ) + " );" + CR ; 651 throw new OgRuntimeException( errMsg ); 652 } 653 654 return ((ArrayTableModel)table).getValues( clmNms ); 655 } 656 657 /** 658 * 文字列を整数に変換します。 659 * 文字列が、nullか、空文字列の場合は、0 を返します。 660 * 661 * @og.rev 6.7.9.1 (2017/05/19) 文字列を整数に変換します。 662 * 663 * @param val 入力文字列 664 * @return int値 665 */ 666 protected final int str2int( final String val ) { 667 return val == null || val.isEmpty() ? 0 : Integer.parseInt( val ); 668 } 669 670 /** 671 * 文字列をdoubleに変換します。 672 * 文字列が、nullか、空文字列の場合は、0d を返します。 673 * 674 * @og.rev 6.7.9.1 (2017/05/19) 文字列をdoubleに変換します。 675 * 676 * @param val 入力文字列 677 * @return double値 678 */ 679 protected final double str2dbl( final String val ) { 680 return val == null || val.isEmpty() ? 0d : Double.parseDouble( val ); 681 } 682 683 /** 684 * 文字列配列をdouble配列に変換します。 685 * 文字列が、nullか、空文字列の場合は、長さ0の配列を返します。 686 * 687 * @og.rev 6.8.5.0 (2018/01/09) 新規追加 688 * 689 * @param vals double配列に変換する元の文字列配列 690 * @return 指定された文字列配列に対するdoubleに変換された値配列 691 * @og.rtnNotNull 692 */ 693 protected final double[][] str2dblVals( final String[][] vals ) { 694 if( vals == null || vals.length == 0 || vals[0] == null || vals[0].length == 0 ) { 695 return new double[0][0]; 696 } 697 698 final int rowLen = vals.length; 699 final int colLen = vals[0].length; 700 701 final double[][] dbls = new double[rowLen][colLen]; 702 703 for( int row=0; row<rowLen; row++ ) { 704 for( int col=0; col<colLen; col++ ) { 705 dbls[row][col] = str2dbl( vals[row][col] ); 706 } 707 } 708 709 return dbls; 710 } 711 712 /** 713 * テーブルのカラム名の一覧を配列形式で返します。 714 * 715 * @og.rev 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 716 * 717 * @return テーブルのカラム名配列 718 */ 719 protected final String[] lineKeys() { 720 if( table == null ) { 721 // 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 722 final String errMsg = "配列型テーブルモデルがセットされていないため、#lineKeys()メソッドはできません。" ; 723 throw new OgRuntimeException( errMsg ); 724 } 725 else { 726 return table.getNames(); 727 } 728 } 729 730 /** 731 * テーブルにカラムが存在しているかを返します。 732 * 733 * @og.rev 5.2.0.0 (2010/09/01) 734 * @og.rev 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 735 * 736 * @param clm カラム名 737 * 738 * @return 存在している場合true、存在していない場合false 739 */ 740 protected final boolean isLine( final String clm ) { 741 if( table == null ) { 742 // 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 743 final String errMsg = "配列型テーブルモデルがセットされていないため、#isLine( String )メソッドはできません。" + CR 744 + " isLine( " + clm + " );" + CR ; 745 throw new OgRuntimeException( errMsg ); 746 } 747 return table.getColumnNo( clm ) >= 0 ; 748 } 749 750 /** 751 * 業務ロジックの戻り値をセットします。 752 * 753 * @param rtn 戻り値 754 */ 755 protected final void rtn( final String rtn ) { 756 bizRtn = rtn; 757 } 758 759 /** 760 * 子ロジックを実行します。 761 * 実行する子ロジックの呼び出しは、親クラスと同じソースパス、クラスパスで呼び出しされます。 762 * 子ロジックに渡す引数には、{@XXXX}形式及び[XXXX]形式の変数を使用することができます。 763 * また、子ロジックの戻り値は、val("SUB_RETURN")で取得することができます。 764 * 765 * @param subLogicName 子ロジック名 766 * @param key キー(CSV形式) 767 * @param val 値(CSV形式) 768 * 769 * @return 処理が正常終了したか 770 */ 771 protected final boolean call( final String subLogicName, final String key, final String val ) { 772 return call( subLogicName, key, val, row, table ); 773 } 774 775 /** 776 * 子ロジックを実行します。 777 * 実行する子ロジックの呼び出しは、親クラスと同じソースパス、クラスパスで呼び出しされます。 778 * 子ロジックに渡す引数には、{@XXXX}形式及び[XXXX]形式の変数を使用することができます。 779 * この場合の値は、引数で指定された、配列型テーブルモデルの行に対応する値になります。 780 * また、子ロジックの戻り値は、val("RETURN")で取得することができます。 781 * 782 * @og.rev 5.1.9.0 (2010/08/01) シーケンス対応 783 * @og.rev 5.4.1.0 (2011/11/01) 値にカンマが含まれている場合に正しく動作しないバグを修正 784 * @og.rev 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 785 * @og.rev 6.3.9.0 (2015/11/06) コンストラクタで初期化されていないフィールドを null チェックなしで利用している(findbugs) 786 * @og.rev 6.7.9.1 (2017/05/19) ArrayTableModel をDataModel に変更。 787 * 788 * @param subLogicName 子ロジック名 789 * @param key キー(CSV形式) 790 * @param val 値(CSV形式) 791 * @param rw 行番号(インデックス) 792 * @param tbl 配列型テーブルモデル 793 * 794 * @return 処理が正常終了したか 795 */ 796 protected final boolean call( final String subLogicName, final String key, final String val, final int rw, final DataModel<String> tbl ) { 797 // 6.3.9.0 (2015/11/06) コンストラクタで初期化されていないフィールドを null チェックなしで利用している(findbugs) 798 if( loader == null ) { 799 final String errMsg = "#setLoader(HybsLoader)を先に実行しておいてください。" + CR 800 + " subLogicName =" + subLogicName + CR 801 + " key =" + key + CR 802 + " val =" + val + CR 803 + " ArrayTableModel=" + tbl ; 804 throw new OgRuntimeException( errMsg ); 805 } 806 807 final AbstractBizLogic subLogic = (AbstractBizLogic)loader.newInstance( subLogicName ); 808 809 if( subLogic.isRequireTable() ) { 810 // 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 811 final String errMsg = "このクラスは、外部からテーブルモデルをセットする必要があるため、子ロジックとして呼び出すことはできません。" + CR 812 + " [クラス名=" + subLogic.getClass().getName() + "]" + CR 813 + " subLogicName =" + subLogicName 814 + " key =[" + key + "]" 815 + " val =[" + val + "]" + CR ; 816 throw new OgRuntimeException( errMsg ); 817 } 818 819 subLogic.setTransaction( tran ); 820 subLogic.setLoader( loader ); 821 subLogic.setKeys( StringUtil.csv2Array( key ) ); 822 // 5.4.1.0 (2011/11/01) 値にカンマが含まれている場合に正しく動作しないバグを修正 823 String[] vals = StringUtil.csv2Array( val ); 824 for( int i=0; i<vals.length; i++ ) { 825 vals[i] = replaceParam( vals[i], rw, tbl ); 826 } 827 subLogic.setVals( vals ); 828 subLogic.setUserId( variableMap.get( "CON.USERID" ) ); 829 subLogic.setParentPgId( variableMap.get( "CON.PGID" ) ); 830 if( debugFlag ) { 831 subLogic.setDebug(); 832 } 833 834 final boolean rtn; // 6.3.9.0 (2015/11/06) Found 'DU'-anomaly for variable(PMD) 835 try { 836 rtn = subLogic.exec(); 837 } 838 catch( final Throwable th ) { 839 // 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 840 final String errMsg = "子ロジックの呼び出しでエラーが発生しました。" + CR 841 + " subLogicName =" + subLogicName + CR 842 + " key =[" + key + "]" 843 + " val =[" + val + "]" + CR ; 844 throw new OgRuntimeException( errMsg ,th ); 845 } 846 variableMap.put( "RETURN", subLogic.getReturn() ); 847 848 if( debugFlag ) { debug( subLogic.getDebugMsg() ); } 849 850 final ErrMsg[] errs = subLogic.getErrMsg().toArray(); 851 if( errs.length > 0 ) { 852 final ErrorMessage errMsgTmp = new ErrorMessage(); 853 for( int i=0; i<errs.length; i++ ) { 854 errMsgTmp.addMessage( errs[i].copy( rw ) ); 855 } 856 errMsg.append( errMsgTmp ); 857 } 858 859 return rtn; 860 } 861 862 /** 863 * SQLを実行します。 864 * SQL文には、{@XXXX}形式及び[XXXX]形式の変数を使用することができます。 865 * select文を発行した場合、その結果セットは、var(カラム名)で取得することができます。 866 * 2行以上が返された場合でも、1行目のみが登録されます。 867 * また、検索件数、更新件数については、var("SQL_ROWCOUNT")で取得することができます。 868 * 869 * @param sq SQL文字列 870 */ 871 protected final void sql( final String sq ) { 872 sql( sq, row, table ); 873 } 874 875 /** 876 * SQLを実行します。 877 * SQL文には、{@XXXX}形式及び[XXXX]形式の変数を使用することができます。 878 * [XXXX]形式の変数の置き換えには、引数で指定された配列型テーブルモデルの行が使用されます。 879 * select文を発行した場合、その結果セットは、var(カラム名)で取得することができます。 880 * 2行以上が返された場合でも、1行目のみが登録されます。 881 * また、検索件数、更新件数については、var("SQL_ROWCOUNT")で取得することができます。 882 * 883 * @og.rev 6.7.9.1 (2017/05/19) ArrayTableModel をDataModel に変更。 884 * 885 * @param sq SQL文字列 886 * @param rw 行番号(インデックス) 887 * @param tbl 配列型テーブルモデル 888 */ 889 protected final void sql( final String sq, final int rw, final DataModel<String> tbl ) { 890 final DataModel<String> tbl2 = execSQL( sq, rw, tbl ); 891 892 if( tbl2 != null && tbl2.getRowCount() > 0 ) { 893 final String[] names = tbl2.getNames(); 894 final String[] vals = tbl2.getValues( 0 ); 895 for( int i=0; i<names.length; i++ ) { 896 variableMap.put( names[i], vals[i] ); 897 } 898 } 899 } 900 901 /** 902 * シーケンス名よりシーケンスオブジェクトを検索し、次の値を取り出します。 903 * DBに対するシーケンスオブジェクトは予め作成されている必要があります。 904 * 905 * また、MySQLの場合は、シーケンスオブジェクトが実装されていないため、 906 * 内部的には、引数のシーケンス名と同じ名前のテーブルから、Integer型の 907 * "SEQID"という項目名を検索することにより、シーケンスをエミュレートしています。 908 * 909 * @og.rev 5.1.9.0 (2010/08/01) 新規追加 910 * @og.rev 6.3.9.0 (2015/11/06) コンストラクタで初期化されていないフィールドを null チェックなしで利用している(findbugs) 911 * 912 * @param seqName シーケンス名 913 * 914 * @return シーケンス番号 915 * @see org.opengion.fukurou.db.DBFunctionName#getSequence(String,Transaction) 916 */ 917 protected final int seq( final String seqName ) { 918 // 6.3.9.0 (2015/11/06) コンストラクタで初期化されていないフィールドを null チェックなしで利用している(findbugs) 919 if( dbName == null ) { 920 final String errMsg = "#exec()を先に実行しておいてください。" + CR 921 + " seqName =" + seqName ; 922 throw new OgRuntimeException( errMsg ); 923 } 924 925 return dbName.getSequence( seqName, tran ); 926 } 927 928 /** 929 * SQLを実行します。 930 * 931 * @param sq SQL文字列 932 * @param rw 行番号(インデックス) 933 * @param tbl 配列型テーブルモデル 934 * 935 * @og.rev 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 936 * 937 * @return 結果セット(配列型テーブルモデル) 938 * 939 * @og.rev 5.1.2.0 (2010/01/01) setObject に ParameterMetaData の getParameterType を渡す。(PostgreSQL対応) 940 * @og.rev 5.1.8.0 (2010/07/01) column名は大文字化し、項目名の取得は#getColumnLabel()で行う。(PotgreSQL対応&バグ修正) 941 * @og.rev 5.3.8.0 (2011/08/01) useParamMetaData を ConnectionFactory経由で取得。(PostgreSQL対応)、setNull 対応 942 * @og.rev 6.3.9.0 (2015/11/06) コンストラクタで初期化されていないフィールドを null チェックなしで利用している(findbugs) 943 * @og.rev 6.4.2.1 (2016/02/05) try-with-resources 文で記述。 944 * @og.rev 6.7.9.1 (2017/05/19) ArrayTableModel をDataModel に変更。 945 * @og.rev 6.9.3.0 (2018/03/26) ミス修正(検索件数のところを、フェッチ件数を取得していた) 946 * @og.rev 6.9.3.0 (2018/03/26) データ検索時のフェッチサイズを設定。 947 */ 948 private DataModel<String> execSQL( final String sq, final int rw, final DataModel<String> tbl ) { 949 // 6.3.9.0 (2015/11/06) コンストラクタで初期化されていないフィールドを null チェックなしで利用している(findbugs) 950 if( conn == null ) { 951 final String errMsg = "#setTransaction(Transaction)を先に実行しておいてください。" + CR 952 + " sql =" + sq + CR 953 + " ArrayTableModel=" + tbl ; 954 throw new OgRuntimeException( errMsg ); 955 } 956 957 String sql = replaceParam( sq, false ); // [XXXX]の変換はここでは行わない。 958 Formatter format = null ; 959 if( tbl != null && sql.indexOf( '[' ) >= 0 ) { 960 format = getFormatter( sql, tbl ); 961 sql = format.getQueryFormatString(); 962 } 963 964 DataModel<String> tbl2 = null; 965 // 6.4.2.1 (2016/02/05) try-with-resources 文 966 try( PreparedStatement pstmt = conn.prepareStatement( sql ) ) { 967 if( tbl != null && format != null ) { 968 final int[] clmNo = format.getClmNos(); 969 970 // 5.1.2.0 (2010/01/01) setObject に ParameterMetaData の getParameterType を渡す。(PostgreSQL対応) 971 if( useParamMetaData ) { 972 final ParameterMetaData pMeta = pstmt.getParameterMetaData(); 973 for( int i=0; i<clmNo.length; i++ ) { 974 final int type = pMeta.getParameterType( i+1 ); 975 // 5.3.8.0 (2011/08/01) setNull 対応 976 final String val = tbl.getValue( rw, clmNo[i] ); 977 if( val == null || val.isEmpty() ) { 978 pstmt.setNull( i+1, type ); 979 } 980 else { 981 pstmt.setObject( i+1, val, type ); 982 } 983 } 984 } 985 else { 986 for( int i=0; i<clmNo.length; i++ ) { 987 pstmt.setObject( i+1, tbl.getValue( rw, clmNo[i] ) ); 988 } 989 } 990 } 991 final boolean status = pstmt.execute(); 992 // 6.4.2.1 (2016/02/05) try-with-resources 文 993 try( ResultSet result = pstmt.getResultSet() ) { 994 if( status ) { 995 result.setFetchSize( DB_FETCH_SIZE ); // 6.9.3.0 (2018/03/26) データ検索時のフェッチサイズ 996 997 final ResultSetMetaData metaData = result.getMetaData(); 998 final int cols = metaData.getColumnCount(); 999 1000 String[] names = new String[cols]; 1001 for( int i=0; i<cols; i++ ) { 1002 // 5.1.8.0 (2010/07/01) column名は大文字化し、項目名の取得は#getColumnLabel()で行う。(PotgreSQL対応&バグ修正) 1003 names[i] = metaData.getColumnLabel( i+1 ).toUpperCase( Locale.JAPAN ); 1004 } 1005 1006 final String[][] tblVals = DBUtil.resultToArray( result, false ); 1007 tbl2 = new ArrayTableModel( names, tblVals ); 1008 1009// variableMap.put( "SQL_ROWCOUNT", String.valueOf( pstmt.getFetchSize() ) ); 1010 variableMap.put( "SQL_ROWCOUNT", String.valueOf( tbl2.getRowCount() ) ); // 6.9.3.0 (2018/03/26) ミス修正 1011 } 1012 else { 1013 variableMap.put( "SQL_ROWCOUNT", String.valueOf( pstmt.getUpdateCount() ) ); 1014 } 1015 } 1016 } 1017 catch( final SQLException ex ) { // catch は、close() されてから呼ばれます。 1018 // 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 1019 final String errMsg = "配列型テーブルモデルの生成に失敗しました。" + CR 1020 + " sql =" + sql + CR 1021 + " ArrayTableModel=" + tbl ; 1022 throw new OgRuntimeException( errMsg,ex ); 1023 } 1024 return tbl2; 1025 } 1026 1027 /** 1028 * エラーメッセージを追加します。 1029 * エラーメッセージの引数には、{@XXXX}形式及び[XXXX]形式の変数を使用することができます。 1030 * 1031 * @param kekka エラーレベル 1032 * @param id エラーメッセージID 1033 * @param args エラーメッセージパラメーター 1034 */ 1035 protected final void error( final int kekka, final String id, final String... args ) { 1036 error( row, kekka, id, args ); 1037 } 1038 1039 /** 1040 * 行指定でエラーメッセージを追加します。 1041 * エラーメッセージの引数には、{@XXXX}形式及び[XXXX]形式の変数を使用することができます。 1042 * 1043 * @param rw 行番号(インデックス) 1044 * @param kekka エラーレベル 1045 * @param id エラーメッセージID 1046 * @param args エラーメッセージパラメーター 1047 */ 1048 protected final void error( final int rw, final int kekka, final String id, final String... args ) { 1049 errMsg.addMessage( rw, kekka, id, replaceParam( args ) ); 1050 } 1051 1052 /** 1053 * パラメーターの必須チェックを行います。 1054 * キーは、CSV形式で複数指定することができます。 1055 * 1056 * @param cs カラム(CSV形式) 1057 * 1058 * @return エラーが発生した場合はfalse、それ以外はtrue 1059 */ 1060 protected final boolean must( final String cs ) { 1061 if( cs == null || cs.isEmpty() ) { 1062 return true; 1063 } 1064 1065 final String[] clms = StringUtil.csv2Array( cs ); 1066 for( int i=0; i<clms.length; i++ ) { 1067 final String val = variableMap.get( clms[i] ); 1068 if( val == null || val.isEmpty() ) { 1069// error( 2, "ERR0012", "{#" + clms[i] + "}" ); 1070 error( NG, "ERR0012", "{#" + clms[i] + "}" ); // 7.2.9.5 (2020/11/28) 1071 return false ; 1072 } 1073 } 1074 return true; 1075 } 1076 1077 /** 1078 * マスタチェックを行います。 1079 * 1080 * @og.rev 5.6.3.1 (2013/04/05) isErrThrow 引数を追加 1081 * 1082 * @see #exist(String, String, String, String, String, String) 1083 * @param type エラーチェックのタイプ 1084 * @param tblId テーブル名 1085 * @param ns カラム(CSV形式) 1086 * @param vs 値(CSV形式) 1087 * 1088 * @return エラーが発生した場合はfalse、それ以外はtrue 1089 */ 1090 protected final boolean exist( final String type, final String tblId, final String ns, final String vs ) { 1091 return exist( type, tblId, ns, vs, null, null,true ); 1092 } 1093 1094 /** 1095 * マスタチェックを行います。 1096 * 1097 * 引数に指定されたテーブル名、及び条件句を生成するためのカラム、値から 1098 * 件数を取得し、typeに応じて件数チェックを行います。 1099 * (カラム、値には、CSV形式で複数指定することができます) 1100 * type=true 存在する場合true 存在しない場合false 1101 * type=false 存在する場合false 存在しない場合true 1102 * type=one 1件以内 true 2件以上 false 1103 * 1104 * 必須チェックの引数には、{@XXXX}形式及び[XXXX]形式の変数を使用することができます。 1105 * 1106 * また、固定値カラム、値にも条件となるカラム及び値を指定することができますが、 1107 * ここで指定されたカラムは、エラーメッセージ表示時にカラム、値が画面に表示されません。 1108 * 1109 * @og.rev 5.6.3.1 (2013/04/05) isErrThrow 引数を追加 1110 * 1111 * @param type エラーチェックのタイプ 1112 * @param tblId テーブル名 1113 * @param ns カラム(CSV形式) 1114 * @param vs 値(CSV形式) 1115 * @param conNs 固定値カラム(CSV形式) 1116 * @param conVs 固定値(CSV形式) 1117 * 1118 * @return エラーが発生した場合はfalse、それ以外はtrue 1119 */ 1120 protected final boolean exist( final String type, final String tblId 1121 , final String ns, final String vs, final String conNs, final String conVs ) { 1122 return exist( type, tblId, ns, vs, conNs, conVs,true ); 1123 } 1124 1125 /** 1126 * マスタチェックを行います。 1127 * 引数に指定されたテーブル名、及び条件句を生成するためのカラム、値から 1128 * 件数を取得し、typeに応じて件数チェックを行います。 1129 * (カラム、値には、CSV形式で複数指定することができます) 1130 * type=true 存在する場合true 存在しない場合false 1131 * type=false 存在する場合false 存在しない場合true 1132 * type=one 1件以内 true 2件以上 false 1133 * 1134 * 必須チェックの引数には、{@XXXX}形式及び[XXXX]形式の変数を使用することができます。 1135 * 1136 * また、固定値カラム、値にも条件となるカラム及び値を指定することができますが、 1137 * ここで指定されたカラムは、エラーメッセージ表示時にカラム、値が画面に表示されません。 1138 * 1139 * isErrThrow は、エラーが発生した場合に、エラーメッセージ(ErrorMessage)に書き込むかどうかを指定します。 1140 * 基本は、互換性を考慮し、true(書き込む)です。 1141 * false にするケースは、存在チェックを行い、あれば更新、なければ追加 など後続処理を行いたい場合に使います。 1142 * 1143 * @og.rev 5.6.3.1 (2013/04/05) isErrThrow 引数を追加 1144 * @og.rev 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 1145 * @og.rev 6.7.9.1 (2017/05/19) ArrayTableModel をDataModel に変更。 1146 * 1147 * @param type エラーチェックのタイプ 1148 * @param tblId テーブル名 1149 * @param ns カラム(CSV形式) 1150 * @param vs 値(CSV形式) 1151 * @param conNs 固定値カラム(CSV形式) 1152 * @param conVs 固定値(CSV形式) 1153 * @param isErrThrow 判定結果がfalseの場合に、error関数を呼ぶ場合は、true。呼ばない場合は、falseをセットします。 1154 * 1155 * @return エラーが発生した場合はfalse、それ以外はtrue 1156 */ 1157 protected final boolean exist( final String type, final String tblId 1158 , final String ns, final String vs, final String conNs, final String conVs, final boolean isErrThrow ) { 1159 if( ns == null || ns.isEmpty() || vs == null || vs.isEmpty() ) { 1160 // 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 1161 final String errMsg = "カラム又は、値にnullは指定できません。" + CR 1162 + " ns =[" + ns + "]" 1163 + " vs =[" + vs + "]" ; 1164 throw new OgRuntimeException( errMsg ); 1165 } 1166 1167 final String namesStr = ns + ( conNs == null || conNs.isEmpty() ? "" : "," + conNs ); 1168 final String[] namesArr = StringUtil.csv2Array( namesStr ); 1169 final String valsStr = vs + ( conVs == null || conVs.isEmpty() ? "" : "," + conVs ); 1170 final String[] valsArr = StringUtil.csv2Array( valsStr ); 1171 if( namesArr.length != valsArr.length ) { 1172 // 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 1173 final String errMsg = "カラムと値の個数が異なります。" + CR 1174 + " names = [" + namesStr + "]" + CR 1175 + " vals = [" + valsStr + "]"; 1176 throw new OgRuntimeException( errMsg ); 1177 } 1178 1179 final StringBuilder sb = new StringBuilder( BUFFER_MIDDLE ); 1180 sb.append( "select count(*) CNT from " ).append( tblId ); 1181 for( int i=0 ;i<namesArr.length; i++ ) { 1182 if( i==0 ) { sb.append( " where " ); } 1183 else { sb.append( " and " ); } 1184 sb.append( namesArr[i] ).append( " = " ).append( valsArr[i] ); 1185 } 1186 1187 int count = 0; 1188 final DataModel<String> tbl2 = execSQL( sb.toString(), row, table ); // 6.7.9.1 (2017/05/19) 1189 if( tbl2 != null && tbl2.getRowCount() >= 0 ) { 1190 count = Integer.parseInt( tbl2.getValues( 0 )[0] ); // 6.0.2.4 (2014/10/17) メソッド間違い 1191 } 1192 1193 final String repVals = replaceParam( vs ); 1194 if( "true".equalsIgnoreCase( type ) ) { 1195 // ERR0025=データ未登録エラー。キー={0}、値={1} のデータは、存在していません。 1196 if( count <= 0 ) { 1197 if( isErrThrow ) { error( NG, "ERR0025", "{#" + ns + "}", repVals ); } // 5.6.3.1 (2013/04/05) 1198 return false; 1199 } 1200 } 1201 else if( "false".equalsIgnoreCase( type ) ) { 1202 // ERR0026=データ登録済みエラー。キー={0}、値={1} のデータは、すでに存在しています。 1203 if( count > 0 ) { 1204 if( isErrThrow ) { error( NG, "ERR0026", "{#" + ns + "}", repVals ); } // 5.6.3.1 (2013/04/05) 1205 return false; 1206 } 1207 } 1208 else if( "one".equalsIgnoreCase( type ) ) { 1209 // ERR0027=データ2重登録エラー。キー={0}、値={1} のデータは、重複して存在しています。 1210 if( count > 1 ) { 1211 if( isErrThrow ) { error( NG, "ERR0027", "{#" + ns + "}", repVals ); } // 5.6.3.1 (2013/04/05) 1212 return false; 1213 } 1214 } 1215 else { 1216 // 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 1217 final String errMsg = "typeは、true、false、oneのいずれかで指定する必要があります。" + CR 1218 + " type = [" + type + "]"; 1219 throw new OgRuntimeException( errMsg ); 1220 } 1221 return true; 1222 } 1223 1224 /** 1225 * 引数に指定されたキー、値をマップ形式に変換します。 1226 * 1227 * @og.rev 5.5.7.2 (2012/10/09) HybsDateUtil を利用するように修正します。 1228 * @og.rev 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 1229 */ 1230 private void makeParamMap() { 1231 if( keys != null && vals != null ) { 1232 if( keys.length == vals.length ) { 1233 for( int i=0; i<keys.length; i++ ) { 1234 variableMap.put( keys[i], vals[i] ); 1235 } 1236 } 1237 else { 1238 // 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 1239 final String errMsg = "keysとvalsの個数が異なります。" + CR 1240 + " keys =" + Arrays.toString( keys ) + CR 1241 + " vals =" + Arrays.toString( vals ) ; 1242 throw new OgRuntimeException( errMsg ); 1243 } 1244 } 1245 1246 final String ymdh = DateSet.getDate( "yyyyMMddHHmmss" ); // 5.5.7.2 (2012/10/09) HybsDateUtil を利用 1247 variableMap.put( "CON.YMDH", ymdh ); 1248 variableMap.put( "CON.YMD", ymdh.substring( 0,8 ) ); 1249 variableMap.put( "CON.HMS", ymdh.substring( 8 ) ); 1250 1251 variableMap.put( "CON.PGID", this.getClass().getSimpleName() ); 1252 } 1253 1254 /** 1255 * {@XXXX}形式及び[XXXX]形式の文字列配列の置き換えを行います。 1256 * 1257 * @og.rev 6.2.2.0 (2015/03/27) #replaceParam( String[] , int , ArrayTableModel ) 廃止に伴う処置 1258 * 1259 * @param str 置き換え対象の配列 1260 * 1261 * @return 置き換え結果の文字列 1262 */ 1263 private String[] replaceParam( final String[] str ) { 1264 for( int i=0; i<str.length; i++ ) { 1265 str[i] = replaceParam( str[i], row, table ); 1266 } 1267 return str; 1268 } 1269 1270 /** 1271 * {@XXXX}形式及び[XXXX]形式の文字列の置き換えを行います。 1272 * 1273 * @param str 置き換え対象の文字列 1274 * 1275 * @return 置き換え結果の文字列 1276 */ 1277 private String replaceParam( final String str ) { 1278 return replaceParam( str, row, table ); 1279 } 1280 1281 /** 1282 * {@XXXX}形式及び[XXXX]形式の文字列の置き換えを行います。 1283 * isRepTableにfalseを指定した場合、Formatterによる[XXXX]変換は行われません。 1284 * (SQLの変換の場合は、PreparedStatementで処理させるため、[XXXX]の変換は行わない。) 1285 * 1286 * @param str 置き換え対象の文字列 1287 * @param isRepTable Formatterによる[XXXX]変換を行うか 1288 * 1289 * @return 置き換え結果の文字列 1290 */ 1291 private String replaceParam( final String str, final boolean isRepTable ) { 1292 return isRepTable ? replaceParam( str, row, table) : replaceParam( str, 0, null ) ; 1293 } 1294 1295 /** 1296 * {@XXXX}形式及び[XXXX]形式の文字列の置き換えを行います。 1297 * [XXXX]形式の置き換えには、引数で指定された配列型テーブルモデル、行番号(インデックス)を使用します。 1298 * 1299 * @og.rev 5.1.8.0 (2010/07/01) 引数チェック漏れ対応 1300 * @og.rev 5.3.9.0 (2011/09/01) nullが連続する場合にゼロストリングに置き換えられないバグを修正 1301 * @og.rev 6.4.3.2 (2016/02/19) Formatterを、値が null の場合は、ゼロ文字列を設定する。 1302 * @og.rev 6.7.9.1 (2017/05/19) ArrayTableModel をDataModel に変更。 1303 * 1304 * @param str 置き換え対象の文字列 1305 * @param rw 行番号(インデックス) 1306 * @param tbl 配列型テーブルモデル 1307 * 1308 * @return 置き換え結果の文字列 1309 */ 1310 private String replaceParam( final String str, final int rw, final DataModel<String> tbl ) { 1311 // 5.1.8.0 (2010/07/01) 引数チェック漏れ対応 1312 if( str == null || str.isEmpty() ) { return ""; } 1313 1314 String rtn = str; 1315 1316 // {@XXXX}の変換 1317 if( !variableMap.isEmpty() && rtn.indexOf( "{@" ) >= 0 ) { // 6.1.1.0 (2015/01/17) refactoring 1318 final SystemParameter sysParam = getSysParam( rtn ); 1319 rtn = sysParam.replace( variableMap ); 1320 } 1321 1322 // [XXXX]の変換 1323 if( tbl != null && rtn.indexOf( '[' ) >= 0 ) { 1324 final Formatter format = getFormatter( rtn, tbl ); 1325 rtn = format.getFormatString( rw ); 1326 } 1327 1328 return rtn; 1329 } 1330 1331 /** 1332 * [XXXX]変換を行うためのFormatterを取得します。 1333 * 1334 * @og.rev 6.4.3.4 (2016/03/11) Formatterに新しいコンストラクターを追加する。 1335 * @og.rev 6.4.3.4 (2016/03/11) Map#computeIfAbsent で対応する。 1336 * @og.rev 6.7.9.1 (2017/05/19) ArrayTableModel をDataModel に変更。 1337 * 1338 * @param str 変換文字列 1339 * @param tbl 配列型テーブルモデル 1340 * 1341 * @return Formatterオブジェクト 1342 */ 1343 private Formatter getFormatter( final String str, final DataModel<String> tbl ) { 1344 // Map#computeIfAbsent : 戻り値は、既存の、または計算された値。追加有り、置換なし、削除なし 1345 final String key = str + tbl.toString(); 1346 return formatMap.computeIfAbsent( key , k -> new Formatter( tbl,str ) ); 1347 } 1348 1349 /** 1350 * {@XXXX}変換を行うためのSystemParameterオブジェクトを取得します。 1351 * 1352 * @og.rev 6.4.3.3 (2016/03/04) ConcurrentHashMap の not null制限のチェック追加 1353 * 1354 * @param str 変換文字列 1355 * 1356 * @return SystemParameterオブジェクト 1357 */ 1358 private SystemParameter getSysParam( final String str ) { 1359 // 6.4.3.3 (2016/03/04) キーが null のときも、SystemParameter オブジェクトを構築しているので、 1360 // それも合わせて、Mapで管理するようにします。 1361 final String key = str == null ? "NULL" : str ; 1362 // Map#computeIfAbsent : 戻り値は、既存の、または計算された値。追加有り、置換なし、削除なし 1363 return sysParamMap.computeIfAbsent( key , k -> new SystemParameter( k ) ); 1364 } 1365 1366 /** 1367 * 検索SQLを実行し、結果を配列型テーブルモデルとして返します。 1368 * SQL文には、{@XXXX}形式及び[XXXX]形式の変数を使用することができます。 1369 * また、検索件数については、var("SQL_ROWCOUNT")で取得することができます。 1370 * 1371 * @og.rev 6.7.9.1 (2017/05/19) ArrayTableModel をDataModel に変更。 1372 * 1373 * @param sq SQL文 1374 * 1375 * @return 配列型テーブルモデル 1376 */ 1377 protected final DataModel<String> createTableBySql( final String sq ) { 1378 return createTableBySql( sq, row, table ); 1379 } 1380 1381 /** 1382 * 検索SQLを実行し、結果を配列型テーブルモデルとして返します。 1383 * SQL文には、{@XXXX}形式及び[XXXX]形式の変数を使用することができます。 1384 * [XXXX]形式の変数の置き換えには、引数で指定された配列型テーブルモデルの行が使用されます。 1385 * また、検索件数については、var("SQL_ROWCOUNT")で取得することができます。 1386 * 1387 * @og.rev 6.7.9.1 (2017/05/19) ArrayTableModel をDataModel に変更。 1388 * 1389 * @param sq SQL文 1390 * @param rw 行番号(インデックス) 1391 * @param tbl 配列型テーブルモデル 1392 * 1393 * @return 配列型テーブルモデル 1394 */ 1395 protected final DataModel<String> createTableBySql( final String sq, final int rw, final DataModel<String> tbl ) { 1396 return execSQL( sq, rw, tbl ); 1397 } 1398 1399 /** 1400 * 変数に関連付けた値を、返します。 1401 * これは、BizLogicから、呼び出し元のJSPに、RETURN 変数以外の {@XXXX} パラメータを返します。 1402 * 既存のアトリビュートがあれば、上書きされます。 1403 * 1404 * @og.rev 6.9.9.0 (2018/08/20) 戻り値を返せるようにします。 1405 * 1406 * @param key キー 1407 * @param val 値 1408 * 1409 */ 1410 protected final void setRtnMap( final String key, final String val ) { 1411 if( key != null && val != null ) { // ConcurrentMap なので。 1412 rtnMap.put( key, val ); 1413 } 1414 } 1415 1416 /** 1417 * 変数に関連付けた値を、返します。 1418 * これは、BizLogicから、呼び出し元のJSPに、RETURN 変数以外の {@XXXX} パラメータを返します。 1419 * 既存のアトリビュートがあれば、上書きされます。 1420 * 1421 * @og.rev 6.9.9.0 (2018/08/20) 戻り値を返せるようにします。 1422 * 1423 * @return 内部マップオブジェクト 1424 */ 1425 protected final Map<String,String> getReturnMap() { 1426 return rtnMap; 1427 } 1428}