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 * @param key キー 394 * 395 * @return 変数値 396 */ 397 final protected int vari( final String key ) { 398 return var( key ) == null ? 0 : Integer.valueOf( var( key ) ); 399 } 400 401 /** 402 * 指定されたキーの値をdouble型に変換して返します。 403 * 404 * @param key キー 405 * 406 * @return 変数値 407 */ 408 final protected double vard( final String key ) { 409 return var( key ) == null ? 0.0 : Double.valueOf( var( key ) ); 410 } 411 412 /** 413 * パラメーターのキー一覧を配列形式で返します。 414 * このパラメーターは、業務ロジック内でセットされたパラメーターも含まれますのでご注意下さい。 415 * 416 * @return パラメーターのキー配列 417 */ 418 final protected String[] varKeys() { 419// return variableMap.keySet().toArray( new String[0] ); 420 Set<String> keys = variableMap.keySet(); 421 return keys.toArray( new String[keys.size()] ); 422 } 423 424 /** 425 * 指定されたキーで値を登録します。 426 * パラメーターとしてこの業務ロジックが呼ばれる際の引数となっている場合は、 427 * エラーとなります。 428 * 429 * @og.rev 5.2.1.0 (2010/10/01) チェックのバグを修正 430 * @og.rev 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 431 * 432 * @param key キー 433 * @param val 値 434 */ 435 final protected void set( final String key, final String val ) { 436// if( paramKeysStr.indexOf( key ) >= 0 ) { 437 if( paramKeysStr.indexOf( "|" + key + "|" ) >= 0 ) { 438 // 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 439// throw new RuntimeException( "引数と同じ名前の変数を定義することはできません" ); 440 String errMsg = "引数と同じ名前の変数を定義することはできません。" + CR 441 + " key =" + key + CR 442 + " 引数 =" + paramKeysStr ; 443 throw new RuntimeException( errMsg ); 444 } 445 variableMap.put( key, val ); 446 } 447 448 /** 449 * 指定されたキーで値を登録します。 450 * パラメーターとしてこの業務ロジックが呼ばれる際の引数となっている場合は、 451 * エラーとなります。 452 * 453 * @og.rev 5.1.9.0 (2010/08/01) 新規作成 454 * 455 * @param key キー 456 * @param val 値 457 */ 458 final protected void set( final String key, final int val ) { 459 set( key, String.valueOf( val ) ); 460 } 461 462 /** 463 * 指定されたキーで値(double型)を登録します。 464 * パラメーターとしてこの業務ロジックが呼ばれる際の引数となっている場合は、 465 * エラーとなります。 466 * 467 * @og.rev 5.1.9.0 (2010/08/01) 新規作成 468 * 469 * @param key キー 470 * @param val 値 471 */ 472 final protected void set( final String key, final double val ) { 473 set( key, String.valueOf( val ) ); 474 } 475 476 /** 477 * 処理中の行の指定されたキー(カラム名)の値を返します。 478 * 479 * @param key キー 480 * 481 * @return 値 482 */ 483 final protected String line( final String key ) { 484 return line( key, row ); 485 } 486 487 /** 488 * メインの配列型テーブルモデルに対して、行を指定して値を取得します。 489 * 指定された行が範囲を超えている場合は、nullを返します。 490 * 491 * @og.rev 5.1.8.0 (2010/07/01) テーブルに存在しないカラム名を指定した場合に、NullPointerExceptionが発生するバグを修正 492 * @og.rev 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 493 * 494 * @param key キー 495 * @param rw 行番号(インデックス) 496 * 497 * @return 値 498 */ 499 final protected String line( final String key, final int rw ) { 500// return( rw < 0 || rw >= table.getRowCount() ? null : table.getValue( rw, key ) ); 501 if( table == null ) { 502 // 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 503// throw new RuntimeException( "配列型テーブルモデルがセットされていないため、#line()メソッドはできません。" ); 504 String errMsg = "配列型テーブルモデルがセットされていないため、#line( String,int )メソッドはできません。" + CR 505 + " line( " + key + "," + rw + " );" + CR ; 506 throw new RuntimeException( errMsg ); 507 } 508 else if( rw < 0 || rw >= table.getRowCount() ) { 509 return null; 510 } 511 else { 512 int col = table.getColumnNo( key ); 513 if( col < 0 ) { 514 return null; 515 } 516 else { 517 return table.getValue( rw, col ); 518 } 519 } 520 } 521 522 /** 523 * 処理中の行の指定されたキー(カラム名)の値をint型に変換して返します。 524 * 525 * @param key キー 526 * 527 * @return 値 528 */ 529 final protected int linei( final String key ) { 530 return line( key ) == null ? 0 : Integer.valueOf( line( key ) ); 531 } 532 533 /** 534 * メインの配列型テーブルモデルに対して、行を指定して値をint型に変換して返します。 535 * 指定された行が範囲を超えている場合は、nullを返します。 536 * 537 * @param key キー 538 * @param rw 行番号(インデックス) 539 * 540 * @return 値 541 */ 542 final protected int linei( final String key, final int rw ) { 543 return line( key, rw ) == null ? 0 : Integer.valueOf( line( key, rw ) ); 544 } 545 546 /** 547 * 処理中の行の指定されたキー(カラム名)の値をdouble型に変換して返します。 548 * 549 * @param key キー 550 * 551 * @return 値 552 */ 553 final protected double lined( final String key ) { 554 return line( key ) == null ? 0.0 : Double.valueOf( line( key ) ); 555 } 556 557 /** 558 * メインの配列型テーブルモデルに対して、行を指定して値をdouble型に変換して返します。 559 * 指定された行が範囲を超えている場合は、nullを返します。 560 * 561 * @param key キー 562 * @param rw 行番号(インデックス) 563 * 564 * @return 値 565 */ 566 final protected double lined( final String key, final int rw ) { 567 return line( key, rw ) == null ? 0.0 : Double.valueOf( line( key, rw ) ); 568 } 569 570 /** 571 * テーブルのカラム名の一覧を配列形式で返します。 572 * 573 * @og.rev 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 574 * 575 * @return テーブルのカラム名配列 576 */ 577 final protected String[] lineKeys() { 578 if( table == null ) { 579 // 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 580// throw new RuntimeException( "配列型テーブルモデルがセットされていないため、#line()メソッドはできません。" ); 581 String errMsg = "配列型テーブルモデルがセットされていないため、#lineKeys()メソッドはできません。" ; 582 throw new RuntimeException( errMsg ); 583 } 584 else { 585 return table.getNames(); 586 } 587 } 588 589 /** 590 * テーブルにカラムが存在しているかを返します。 591 * 592 * @og.rev 5.2.0.0 (2010/09/01) 593 * @og.rev 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 594 * 595 * @param clm カラム名 596 * 597 * @return 存在している場合true、存在していない場合false 598 */ 599 final protected boolean isLine( final String clm ) { 600 if( table == null ) { 601 // 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 602// throw new RuntimeException( "配列型テーブルモデルがセットされていないため、#line()メソッドはできません。" ); 603 String errMsg = "配列型テーブルモデルがセットされていないため、#isLine( String )メソッドはできません。" + CR 604 + " isLine( " + clm + " );" + CR ; 605 throw new RuntimeException( errMsg ); 606 } 607 return ( table.getColumnNo( clm ) < 0 ) ? false : true ; 608 } 609 610 /** 611 * 業務ロジックの戻り値をセットします。 612 * 613 * @param rtn 戻り値 614 */ 615 final protected void rtn( final String rtn ) { 616// final protected void setReturn( final String rtn ) { 617// rtn = r; 618 bizRtn = rtn; 619 } 620 621 /** 622 * 子ロジックを実行します。 623 * 実行する子ロジックの呼び出しは、親クラスと同じソースパス、クラスパスで呼び出しされます。 624 * 子ロジックに渡す引数には、{@XXXX}形式及び[XXXX]形式の変数を使用することができます。 625 * また、子ロジックの戻り値は、val("SUB_RETURN")で取得することができます。 626 * 627 * @param subLogicName 子ロジック名 628 * @param key キー(CSV形式) 629 * @param val 値(CSV形式) 630 * 631 * @return 処理が正常終了したか 632 */ 633 final protected boolean call( String subLogicName, String key, String val ) { 634 return call( subLogicName, key, val, row, table ); 635 } 636 637 /** 638 * 子ロジックを実行します。 639 * 実行する子ロジックの呼び出しは、親クラスと同じソースパス、クラスパスで呼び出しされます。 640 * 子ロジックに渡す引数には、{@XXXX}形式及び[XXXX]形式の変数を使用することができます。 641 * この場合の値は、引数で指定された、配列型テーブルモデルの行に対応する値になります。 642 * また、子ロジックの戻り値は、val("RETURN")で取得することができます。 643 * 644 * @og.rev 5.1.9.0 (2010/08/01) シーケンス対応 645 * @og.rev 5.4.1.0 (2011/11/01) 値にカンマが含まれている場合に正しく動作しないバグを修正 646 * @og.rev 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 647 * 648 * @param subLogicName 子ロジック名 649 * @param key キー(CSV形式) 650 * @param val 値(CSV形式) 651 * @param rw 行番号(インデックス) 652 * @param tbl 配列型テーブルモデル 653 * 654 * @return 処理が正常終了したか 655 */ 656 final protected boolean call( String subLogicName, String key, String val, int rw, ArrayTableModel tbl ) { 657 AbstractBizLogic subLogic = (AbstractBizLogic)loader.newInstance( subLogicName ); 658 659 if( subLogic.isRequireTable() ) { 660 // 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 661// throw new RuntimeException( "このクラスは、外部からテーブルモデルをセットする必要があるため、子ロジックとして呼び出すことはできません。[クラス名=" + subLogic.getClass().getName() + "]" ); 662 String errMsg = "このクラスは、外部からテーブルモデルをセットする必要があるため、子ロジックとして呼び出すことはできません。" + CR 663 + " [クラス名=" + subLogic.getClass().getName() + "]" + CR 664 + " subLogicName =" + subLogicName 665 + " key =[" + key + "]" 666 + " val =[" + val + "]" + CR ; 667 throw new RuntimeException( errMsg ); 668 } 669 670// subLogic.setConnection( conn ); 671 subLogic.setTransaction( tran ); 672 subLogic.setLoader( loader ); 673 subLogic.setKeys( StringUtil.csv2Array( key ) ); 674// subLogic.setVals( StringUtil.csv2Array( replaceParam( val, rw, tbl ) ) ); 675 // 5.4.1.0 (2011/11/01) 値にカンマが含まれている場合に正しく動作しないバグを修正 676 String[] vals = StringUtil.csv2Array( val ); 677 for( int i=0; i<vals.length; i++ ) { 678 vals[i] = replaceParam( vals[i], rw, tbl ); 679 } 680 subLogic.setVals( vals ); 681 subLogic.setUserId( variableMap.get( "CON.USERID" ) ); 682 subLogic.setParentPgId( variableMap.get( "CON.PGID" ) ); 683 if( debugFlag ) { 684 subLogic.setDebug(); 685 } 686 687 boolean rtn = false; 688 try { 689 rtn = subLogic.exec(); 690 } 691 catch( Throwable th ) { 692// // 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 693// throw new RuntimeException( "子ロジックの呼び出しでエラーが発生しました。[logic=" + subLogicName + "]", th ); 694 String errMsg = "子ロジックの呼び出しでエラーが発生しました。" + CR 695 + " subLogicName =" + subLogicName + CR 696 + " key =[" + key + "]" 697 + " val =[" + val + "]" + CR ; 698 throw new RuntimeException( errMsg ,th ); 699 } 700 variableMap.put( "RETURN", subLogic.getReturn() ); 701 702 if( debugFlag ) { debug( subLogic.getDebugMsg() ); } 703 704 ErrMsg[] errs = subLogic.getErrMsg().toArray(); 705 if( errs.length > 0 ) { 706 ErrorMessage errMsgTmp = new ErrorMessage(); 707 for( int i = 0; i < errs.length; i++ ) { 708// errMsgTmp.addMessage( errs[i].copy( errs[i].getNo() + rw ) ); 709 errMsgTmp.addMessage( errs[i].copy( rw ) ); 710 } 711 errMsg.append( errMsgTmp ); 712 } 713 714 return rtn; 715 } 716 717 /** 718 * SQLを実行します。 719 * SQL文には、{@XXXX}形式及び[XXXX]形式の変数を使用することができます。 720 * select文を発行した場合、その結果セットは、var(カラム名)で取得することができます。 721 * 2行以上が返された場合でも、1行目のみが登録されます。 722 * また、検索件数、更新件数については、var("SQL_ROWCOUNT")で取得することができます。 723 * 724 * @param sq SQL文字列 725 */ 726 final protected void sql( final String sq ) { 727 sql( sq, row, table ); 728 } 729 730 /** 731 * SQLを実行します。 732 * SQL文には、{@XXXX}形式及び[XXXX]形式の変数を使用することができます。 733 * [XXXX]形式の変数の置き換えには、引数で指定された配列型テーブルモデルの行が使用されます。 734 * select文を発行した場合、その結果セットは、var(カラム名)で取得することができます。 735 * 2行以上が返された場合でも、1行目のみが登録されます。 736 * また、検索件数、更新件数については、var("SQL_ROWCOUNT")で取得することができます。 737 * 738 * @param sq SQL文字列 739 * @param rw 行番号(インデックス) 740 * @param tbl 配列型テーブルモデル 741 */ 742 final protected void sql( final String sq, final int rw, final ArrayTableModel tbl ) { 743 ArrayTableModel tbl2 = execSQL( sq, rw, tbl ); 744 745 if( tbl2 != null && tbl2.getRowCount() > 0 ) { 746 String[] names = tbl2.getNames(); 747 String[] vals = tbl2.getValues( 0 ); 748 for( int i = 0; i < names.length; i++ ) { 749 variableMap.put( names[i], vals[i] ); 750 } 751 } 752 } 753 754 /** 755 * シーケンス名よりシーケンスオブジェクトを検索し、次の値を取り出します。 756 * DBに対するシーケンスオブジェクトは予め作成されている必要があります。 757 * 758 * また、MySQLの場合は、シーケンスオブジェクトが実装されていないため、 759 * 内部的には、引数のシーケンス名と同じ名前のテーブルから、Integer型の 760 * "SEQID"という項目名を検索することにより、シーケンスをエミュレートしています。 761 * 762 * @og.rev 5.1.9.0 (2010/08/01) 新規追加 763 * 764 * @param seqName シーケンス名 765 * 766 * @return シーケンス番号 767 * @see org.opengion.fukurou.db.DBFunctionName#getSequence(String,Transaction) 768 */ 769 final protected int seq( final String seqName ) { 770 return dbName.getSequence( seqName, tran ); 771 } 772 773 /** 774 * SQLを実行します。 775 * 776 * @param sq SQL文字列 777 * @param rw 行番号(インデックス) 778 * @param tbl 配列型テーブルモデル 779 * 780 * @og.rev 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 781 * 782 * @return 結果セット(配列型テーブルモデル) 783 * 784 * @og.rev 5.1.2.0 (2010/01/01) setObject に ParameterMetaData の getParameterType を渡す。(PostgreSQL対応) 785 * @og.rev 5.1.8.0 (2010/07/01) column名は大文字化し、項目名の取得は#getColumnLabel()で行う。(PotgreSQL対応&バグ修正) 786 * @og.rev 5.3.8.0 (2011/08/01) useParamMetaData を ConnectionFactory経由で取得。(PostgreSQL対応)、setNull 対応 787 */ 788 private ArrayTableModel execSQL( final String sq, final int rw, final ArrayTableModel tbl ) { 789 String sql = sq; 790 791 sql = replaceParam( sql, false ); // [XXXX]の変換はここでは行わない。 792 793 Formatter format = null; 794 if( tbl != null && sql.indexOf( '[' ) >= 0 ) { 795 format = getFormatter( sql, tbl ); 796 sql = format.getQueryFormatString(); 797 } 798 799 PreparedStatement pstmt = null; 800 ResultSet result = null; 801 ArrayTableModel tbl2 = null; 802 try { 803 pstmt = conn.prepareStatement( sql ); 804 if( tbl != null && format != null ) { 805 int[] clmNo = format.getClmNos(); 806 807 // 5.1.2.0 (2010/01/01) setObject に ParameterMetaData の getParameterType を渡す。(PostgreSQL対応) 808// boolean useParamMetaData = ApplicationInfo.useParameterMetaData( conn ); // 5.3.8.0 (2011/08/01) 809 if( useParamMetaData ) { 810 ParameterMetaData pMeta = pstmt.getParameterMetaData(); 811 for( int i = 0; i < clmNo.length; i++ ) { 812 int type = pMeta.getParameterType( i+1 ); 813 // 5.3.8.0 (2011/08/01) setNull 対応 814// pstmt.setObject( i+1, tbl.getValue( rw, clmNo[i] ), type ); 815 String val = tbl.getValue( rw, clmNo[i] ); 816 if( val == null || val.isEmpty() ) { 817 pstmt.setNull( i+1, type ); 818 } 819 else { 820 pstmt.setObject( i+1, val, type ); 821 } 822 } 823 } 824 else { 825 for( int i = 0; i < clmNo.length; i++ ) { 826 pstmt.setObject( i+1, tbl.getValue( rw, clmNo[i] ) ); 827 } 828 } 829 } 830 boolean status = pstmt.execute(); 831 result = pstmt.getResultSet(); 832 833 if( status ) { 834 ResultSetMetaData metaData = result.getMetaData(); 835 int cols = metaData.getColumnCount(); 836 837 String[] names = new String[cols]; 838 for( int i = 0; i < cols; i++ ) { 839 // 5.1.8.0 (2010/07/01) column名は大文字化し、項目名の取得は#getColumnLabel()で行う。(PotgreSQL対応&バグ修正) 840// names[i] = metaData.getColumnName( i+1 ); 841 names[i] = metaData.getColumnLabel( i+1 ).toUpperCase( Locale.JAPAN ); 842 } 843 844 String[][] tblVals = DBUtil.resultToArray( result, false ); 845 tbl2 = new ArrayTableModel( names, tblVals ); 846 847 variableMap.put( "SQL_ROWCOUNT", String.valueOf( pstmt.getFetchSize() ) ); 848 } 849 else { 850 variableMap.put( "SQL_ROWCOUNT", String.valueOf( pstmt.getUpdateCount() ) ); 851 } 852 } 853 catch( SQLException ex ) { 854 // 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 855// throw new RuntimeException( "配列型テーブルモデルの生成に失敗しました", ex ); 856 String errMsg = "配列型テーブルモデルの生成に失敗しました。" + CR 857 + " sql =" + sql + CR 858 + " ArrayTableModel=" + tbl ; 859 throw new RuntimeException( errMsg,ex ); 860 } 861 finally { 862 Closer.resultClose( result ); 863 Closer.stmtClose( pstmt ); 864 } 865 return tbl2; 866 } 867 868 /** 869 * エラーメッセージを追加します。 870 * エラーメッセージの引数には、{@XXXX}形式及び[XXXX]形式の変数を使用することができます。 871 * 872 * @param kekka エラーレベル 873 * @param id エラーメッセージID 874 * @param args エラーメッセージパラメーター 875 */ 876 final protected void error( final int kekka, final String id, final String... args ) { 877 error( row, kekka, id, args ); 878 } 879 880 /** 881 * 行指定でエラーメッセージを追加します。 882 * エラーメッセージの引数には、{@XXXX}形式及び[XXXX]形式の変数を使用することができます。 883 * 884 * @param rw 行番号(インデックス) 885 * @param kekka エラーレベル 886 * @param id エラーメッセージID 887 * @param args エラーメッセージパラメーター 888 */ 889 final protected void error( final int rw, final int kekka, final String id, final String... args ) { 890 errMsg.addMessage( rw, kekka, id, replaceParam( args ) ); 891 } 892 893 /** 894 * パラメーターの必須チェックを行います。 895 * キーは、カンマ区切りで複数指定することができます。 896 * 897 * @param cs カラム(カンマ区切り) 898 * 899 * @return エラーが発生した場合はfalse、それ以外はtrue 900 */ 901 final protected boolean must( final String cs ) { 902 if( cs == null || cs.length() == 0 ) { 903 return true; 904 } 905 906 boolean rtn = true; 907 String[] clms = StringUtil.csv2Array( cs ); 908 for( int i=0; i<clms.length; i++ ) { 909 String val = variableMap.get( clms[i] ); 910 if( val == null || val.length() == 0 ) { 911 error( 2, "ERR0012", "{#" + clms[i] + "}" ); 912 rtn = false; 913 } 914 } 915 return rtn; 916 } 917 918 /** 919 * マスタチェックを行います。 920 * 921 * @og.rev 5.6.3.1 (2013/04/05) isErrThrow 引数を追加 922 * 923 * @see #exist(String, String, String, String, String, String) 924 * @param type エラーチェックのタイプ 925 * @param tblId テーブル名 926 * @param ns カラム(カンマ区切り) 927 * @param vs 値(カンマ区切り) 928 * 929 * @return エラーが発生した場合はfalse、それ以外はtrue 930 */ 931 final protected boolean exist( final String type, final String tblId, final String ns, final String vs ) { 932// return exist( type, tblId, ns, vs, null, null ); 933 return exist( type, tblId, ns, vs, null, null,true ); 934 } 935 936 /** 937 * マスタチェックを行います。 938 * 939 * 引数に指定されたテーブル名、及び条件句を生成するためのカラム、値から 940 * 件数を取得し、typeに応じて件数チェックを行います。 941 * (カラム、値には、カンマ区切りで複数指定することができます) 942 * type=true 存在する場合true 存在しない場合false 943 * type=false 存在する場合false 存在しない場合true 944 * type=one 1件以内 true 2件以上 false 945 * 946 * 必須チェックの引数には、{@XXXX}形式及び[XXXX]形式の変数を使用することができます。 947 * 948 * また、固定値カラム、値にも条件となるカラム及び値を指定することができますが、 949 * ここで指定されたカラムは、エラーメッセージ表示時にカラム、値が画面に表示されません。 950 * 951 * @og.rev 5.6.3.1 (2013/04/05) isErrThrow 引数を追加 952 * 953 * @param type エラーチェックのタイプ 954 * @param tblId テーブル名 955 * @param ns カラム(カンマ区切り) 956 * @param vs 値(カンマ区切り) 957 * @param conNs 固定値カラム(カンマ区切り) 958 * @param conVs 固定値(カンマ区切り) 959 * 960 * @return エラーが発生した場合はfalse、それ以外はtrue 961 */ 962 final protected boolean exist( final String type, final String tblId 963 , final String ns, final String vs, final String conNs, final String conVs ) { 964 return exist( type, tblId, ns, vs, conNs, conVs,true ); 965 } 966 967 /** 968 * マスタチェックを行います。 969 * 引数に指定されたテーブル名、及び条件句を生成するためのカラム、値から 970 * 件数を取得し、typeに応じて件数チェックを行います。 971 * (カラム、値には、カンマ区切りで複数指定することができます) 972 * type=true 存在する場合true 存在しない場合false 973 * type=false 存在する場合false 存在しない場合true 974 * type=one 1件以内 true 2件以上 false 975 * 976 * 必須チェックの引数には、{@XXXX}形式及び[XXXX]形式の変数を使用することができます。 977 * 978 * また、固定値カラム、値にも条件となるカラム及び値を指定することができますが、 979 * ここで指定されたカラムは、エラーメッセージ表示時にカラム、値が画面に表示されません。 980 * 981 * isErrThrow は、エラーが発生した場合に、エラーメッセージ(ErrorMessage)に書き込むかどうかを指定します。 982 * 基本は、互換性を考慮し、true(書き込む)です。 983 * false にするケースは、存在チェックを行い、あれば更新、なければ追加 など後続処理を行いたい場合に使います。 984 * 985 * @og.rev 5.6.3.1 (2013/04/05) isErrThrow 引数を追加 986 * @og.rev 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 987 * 988 * @param type エラーチェックのタイプ 989 * @param tblId テーブル名 990 * @param ns カラム(カンマ区切り) 991 * @param vs 値(カンマ区切り) 992 * @param conNs 固定値カラム(カンマ区切り) 993 * @param conVs 固定値(カンマ区切り) 994 * @param isErrThrow 判定結果がfalseの場合に、error関数を呼ぶ場合は、true。呼ばない場合は、falseをセットします。 995 * 996 * @return エラーが発生した場合はfalse、それ以外はtrue 997 */ 998 final protected boolean exist( final String type, final String tblId 999 , final String ns, final String vs, final String conNs, final String conVs, final boolean isErrThrow ) { 1000 if( ns == null || ns.length() == 0 || vs == null || vs.length() == 0 ) { 1001 // 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 1002// throw new RuntimeException( "カラム又は、値にnullは指定できません" ); 1003 String errMsg = "カラム又は、値にnullは指定できません。" + CR 1004 + " ns =[" + ns + "]" 1005 + " vs =[" + vs + "]" ; 1006 throw new RuntimeException( errMsg ); 1007 } 1008 1009 String namesStr = ns + ( conNs == null || conNs.length() == 0 ? "" : "," + conNs ); 1010 String[] namesArr = StringUtil.csv2Array( namesStr ); 1011 String valsStr = vs + ( conVs == null || conVs.length() == 0 ? "" : "," + conVs ); 1012 String[] valsArr = StringUtil.csv2Array( valsStr ); 1013 if( namesArr.length != valsArr.length ) { 1014 // 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 1015// throw new RuntimeException( "カラムと値の個数が異なります" ); 1016 String errMsg = "カラムと値の個数が異なります。" + CR 1017 + " names = [" + namesStr + "]" + CR 1018 + " vals = [" + valsStr + "]"; 1019 throw new RuntimeException( errMsg ); 1020 } 1021 1022 StringBuilder sb = new StringBuilder(); 1023 sb.append( "select count(*) CNT from " ).append( tblId ); 1024 for( int i=0 ;i<namesArr.length; i++ ) { 1025 if( i==0 ) { sb.append( " where " ); } 1026 else { sb.append( " and " ); } 1027 sb.append( namesArr[i] ).append( " = " ).append( valsArr[i] ); 1028 } 1029 1030 int count = 0; 1031 ArrayTableModel tbl2 = execSQL( sb.toString(), row, table ); 1032 if( tbl2 != null && tbl2.getRowCount() >= 0 ) { 1033 count = Integer.valueOf( tbl2.getValues( 0 )[0] ); 1034 } 1035 1036 String repVals = replaceParam( vs ); 1037 if( "true".equalsIgnoreCase( type ) ) { 1038 // ERR0025=データ未登録エラー。キー={0}、値={1} のデータは、存在していません。 1039 if( count <= 0 ) { 1040 if( isErrThrow ) { error( NG, "ERR0025", "{#" + ns + "}", repVals ); } // 5.6.3.1 (2013/04/05) 1041 return false; 1042 } 1043 } 1044 else if( "false".equalsIgnoreCase( type ) ) { 1045 // ERR0026=データ登録済みエラー。キー={0}、値={1} のデータは、すでに存在しています。 1046 if( count > 0 ) { 1047 if( isErrThrow ) { error( NG, "ERR0026", "{#" + ns + "}", repVals ); } // 5.6.3.1 (2013/04/05) 1048 return false; 1049 } 1050 } 1051 else if( "one".equalsIgnoreCase( type ) ) { 1052 // ERR0027=データ2重登録エラー。キー={0}、値={1} のデータは、重複して存在しています。 1053 if( count > 1 ) { 1054 if( isErrThrow ) { error( NG, "ERR0027", "{#" + ns + "}", repVals ); } // 5.6.3.1 (2013/04/05) 1055 return false; 1056 } 1057 } 1058 else { 1059 // 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 1060// throw new RuntimeException( "typeは、true、false、oneのいずれかで指定する必要があります" ); 1061 String errMsg = "typeは、true、false、oneのいずれかで指定する必要があります。" + CR 1062 + " type = [" + type + "]"; 1063 throw new RuntimeException( errMsg ); 1064 } 1065 return true; 1066 } 1067 1068 /** 1069 * 引数に指定されたキー、値をマップ形式に変換します。 1070 * 1071 * @og.rev 5.5.7.2 (2012/10/09) HybsDateUtil を利用するように修正します。 1072 * @og.rev 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 1073 */ 1074 private void makeParamMap() { 1075 if( keys != null && vals != null ) { 1076 if( keys.length == vals.length ) { 1077 for( int i = 0; i < keys.length; i++ ) { 1078 paramKeysStr.append( keys[i] ).append( "|" ); 1079 variableMap.put( keys[i], vals[i] ); 1080 } 1081 } 1082 else { 1083 // 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 1084// throw new RuntimeException( "keyとvalの個数が異なります" ); 1085 String errMsg = "keysとvalsの個数が異なります。" + CR 1086 + " keys =" + Arrays.toString( keys ) + CR 1087 + " vals =" + Arrays.toString( vals ) ; 1088 throw new RuntimeException( errMsg ); 1089 } 1090 } 1091 1092// DateFormat formatter = new SimpleDateFormat( "yyyyMMddHHmmss",Locale.JAPAN ); 1093// String ymdh = formatter.format( new Date() ); 1094 String ymdh = HybsDateUtil.getDate( "yyyyMMddHHmmss" ); // 5.5.7.2 (2012/10/09) HybsDateUtil を利用 1095 variableMap.put( "CON.YMDH", ymdh ); 1096 variableMap.put( "CON.YMD", ymdh.substring( 0,8 ) ); 1097 variableMap.put( "CON.HMS", ymdh.substring( 8 ) ); 1098 1099 variableMap.put( "CON.PGID", this.getClass().getSimpleName() ); 1100 } 1101 1102 /** 1103 * {@XXXX}形式及び[XXXX]形式の文字列の置き換えを行います。 1104 * 1105 * @param str 置き換え対象の文字列 1106 * 1107 * @return 置き換え結果の文字列 1108 */ 1109 private String replaceParam( final String str ) { 1110 return replaceParam( str, row, table ); 1111 } 1112 1113 /** 1114 * {@XXXX}形式及び[XXXX]形式の文字列の置き換えを行います。 1115 * isRepTableにfalseを指定した場合、Formatterによる[XXXX]変換は行われません。 1116 * (SQLの変換の場合は、PreparedStatementで処理させるため、[XXXX]の変換は行わない。) 1117 * 1118 * @param str 置き換え対象の文字列 1119 * @param isRepTable Formatterによる[XXXX]変換を行うか 1120 * 1121 * @return 置き換え結果の文字列 1122 */ 1123 private String replaceParam( final String str, final boolean isRepTable ) { 1124 return ( isRepTable ? replaceParam( str, row, table) : replaceParam( str, 0, null ) ); 1125 } 1126 1127 /** 1128 * {@XXXX}形式及び[XXXX]形式の文字列の置き換えを行います。 1129 * [XXXX]形式の置き換えには、引数で指定された配列型テーブルモデル、行番号(インデックス)を使用します。 1130 * 1131 * @og.rev 5.1.8.0 (2010/07/01) 引数チェック漏れ対応 1132 * @og.rev 5.3.9.0 (2011/09/01) nullが連続する場合にゼロストリングに置き換えられないバグを修正 1133 * 1134 * @param str 置き換え対象の文字列 1135 * @param rw 行番号(インデックス) 1136 * @param tbl 配列型テーブルモデル 1137 * 1138 * @return 置き換え結果の文字列 1139 */ 1140 private String replaceParam( final String str, final int rw, final ArrayTableModel tbl ) { 1141 // 5.1.8.0 (2010/07/01) 引数チェック漏れ対応 1142 if( str == null || str.length() == 0 ) { return ""; } 1143 1144 String rtn = str; 1145 1146 // {@XXXX}の変換 1147 if( variableMap.size() > 0 && rtn.indexOf( "{@" ) >= 0 ) { 1148 SystemParameter sysParam = getSysParam( rtn ); 1149 rtn = sysParam.replace( variableMap ); 1150 } 1151 1152 // [XXXX]の変換 1153 if( tbl != null && rtn.indexOf( '[' ) >= 0 ) { 1154 Formatter format = getFormatter( rtn, tbl ); 1155 rtn = format.getFormatString( rw ); 1156 // 以下3行はFormatterのバグを吸収(値がnullの場合に"null"という文字列で出力されてしまう) 1157// rtn = ',' + rtn + ','; 1158// rtn = rtn.replace( ",null,", ",," ); 1159// rtn = rtn.substring( 1, rtn.length() - 1 ); 1160 // 5.3.9.0 (2011/09/01) nullが連続する場合にゼロストリングに置き換えられないバグを修正 1161 rtn = ',' + rtn; 1162 rtn = rtn.replace( ",null", "," ); 1163 rtn = rtn.substring( 1 ); 1164 } 1165 1166 return rtn; 1167 } 1168 1169 /** 1170 * {@XXXX}形式及び[XXXX]形式の文字列(配列)の置き換えを行います。 1171 * 1172 * @param str 置き換え対象の文字列(配列) 1173 * 1174 * @return 置き換え結果の文字列 1175 */ 1176 private String[] replaceParam( final String[] str ) { 1177 return replaceParam( str, row, table ); 1178 } 1179 1180 /** 1181 * {@XXXX}形式及び[XXXX]形式の文字列(配列)の置き換えを行います。 1182 * [XXXX]形式の置き換えには、引数で指定された配列型テーブルモデル、行番号(インデックス)を使用します。 1183 * 1184 * @param str 置き換え対象の文字列(配列) 1185 * @param rw 行番号(インデックス) 1186 * @param tbl 配列型テーブルモデル 1187 * 1188 * @return 置き換え結果の文字列 1189 */ 1190 private String[] replaceParam( final String[] str, final int rw, final ArrayTableModel tbl ) { 1191 for( int i = 0; i < str.length; i++ ) { 1192 str[i] = replaceParam( str[i], rw, tbl ); 1193 } 1194 return str; 1195 } 1196 1197 /** 1198 * [XXXX]変換を行うためのFormatterを取得します。 1199 * 1200 * @param str 変換文字列 1201 * @param tbl 配列型テーブルモデル 1202 * 1203 * @return Formatterオブジェクト 1204 */ 1205 private Formatter getFormatter( final String str, final ArrayTableModel tbl ) { 1206 Formatter format = formatMap.get( str + tbl.toString() ); 1207 if( format == null ) { 1208 format = new Formatter( tbl ); 1209 format.setFormat( str ); 1210 formatMap.put( str + tbl.toString(), format ); 1211 } 1212 return format; 1213 } 1214 1215 /** 1216 * {@XXXX}変換を行うためのSystemParameterオブジェクトを取得します。 1217 * 1218 * @param str 変換文字列 1219 * 1220 * @return SystemParameterオブジェクト 1221 */ 1222 private SystemParameter getSysParam( final String str ) { 1223 SystemParameter sysParam = sysParamMap.get( str ); 1224 if( sysParam == null ) { 1225 sysParam = new SystemParameter( str ); 1226 sysParamMap.put( str, sysParam ); 1227 } 1228 return sysParam; 1229 } 1230 1231 /** 1232 * 検索SQLを実行し、結果を配列型テーブルモデルとして返します。 1233 * SQL文には、{@XXXX}形式及び[XXXX]形式の変数を使用することができます。 1234 * また、検索件数については、var("SQL_ROWCOUNT")で取得することができます。 1235 * 1236 * @param sq SQL文 1237 * 1238 * @return 配列型テーブルモデル 1239 */ 1240 final protected ArrayTableModel createTableBySql( final String sq ) { 1241 return createTableBySql( sq, row, table ); 1242 } 1243 1244 /** 1245 * 検索SQLを実行し、結果を配列型テーブルモデルとして返します。 1246 * SQL文には、{@XXXX}形式及び[XXXX]形式の変数を使用することができます。 1247 * [XXXX]形式の変数の置き換えには、引数で指定された配列型テーブルモデルの行が使用されます。 1248 * また、検索件数については、var("SQL_ROWCOUNT")で取得することができます。 1249 * 1250 * @param sq SQL文 1251 * @param rw 行番号(インデックス) 1252 * @param tbl 配列型テーブルモデル 1253 * 1254 * @return 配列型テーブルモデル 1255 */ 1256 final protected ArrayTableModel createTableBySql( final String sq, final int rw, final ArrayTableModel tbl ) { 1257 return execSQL( sq, rw, tbl ); 1258 } 1259}