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