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