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