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