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