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