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