    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.hayabusa.db;
    017
    018import java.sql.ResultSet;
    019import java.sql.SQLException;
    020
    021import static org.opengion.fukurou.system.HybsConst.CR ;                // 6.1.0.0 (2014/12/26)
    022import org.opengion.fukurou.db.Transaction;
    023import org.opengion.fukurou.db.TransactionReal;
    024import org.opengion.fukurou.db.ResultSetValue;                          // 6.0.4.0 (2014/11/28)
    025import org.opengion.fukurou.db.ApplicationInfo;
    026import org.opengion.fukurou.util.ErrorMessage;
    027import org.opengion.fukurou.util.StringUtil;
    028import org.opengion.hayabusa.common.HybsSystemException;
    029import org.opengion.hayabusa.resource.LabelData;
    030import org.opengion.hayabusa.resource.ResourceManager;
    031
    032/**
    033 * データベース関連の便利なメソッドを集めた簡易ユーティリティークラスです。
    034 * 全てのメソッドは、static メソッドになっています。
    035 *
    036 * @og.rev 2.1.1.1 (2002/11/15) Serializable インターフェースを削除する。
    037 * @og.rev 4.0.0.0 (2007/10/16) 名称変更(DBUtil ⇒ DBTableModelUtil) DBアクセス関係のメソッドはfukurou/db/DBUtilに移動
    038 * @og.group ＤＢ/Shell制御
    039 *
    040 * @version  4.0
    041 * @author   Kazuhiko Hasegawa
    042 * @since    JDK5.0,
    043 */
    044public final class DBTableModelUtil {
    045        /**
    046         * インスタンスを作らないので、コンストラクタは、private に設定します。
    047         */
    048        private DBTableModelUtil() {}
    049
    050        /**
    051         * 初期データベースに接続して、Queryを実行します。
    052         * ステートメントと引数により、Prepared クエリーの検索のみ実行します。
    053         * 結果は、DBTableModel として返されます。
    054         *
    055         * @og.rev 3.0.0.0 (2002/12/25) 新規追加
    056         * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為、ApplicationInfoオブジェクトを設定
    057         * @og.rev 4.0.0.0 (2005/01/31) lang ⇒ ResourceManager へ変更
    058         * @og.rev 4.0.0.0 (2007/10/10) dbid の初期値を、"DEFAULT" から null に変更
    059         *
    060         * @param   stmt ステートメント文字列
    061         * @param   args オブジェクトの引数配列
    062         * @param   resource リソースマネージャー
    063         * @param   appInfo アプリ情報オブジェクト
    064         *
    065         * @return  検索結果の配列
    066         */
    067        public static DBTableModel makeDBTable( final String stmt ,final String[] args, final ResourceManager resource, final ApplicationInfo appInfo ) {
    068                return makeDBTable( stmt,args,resource,appInfo,null );
    069        }
    070
    071        /**
    072         * 検索するデータベースを指定して、Queryを実行します。
    073         * ステートメントと引数により、Prepared クエリーの検索のみ実行します。
    074         * 結果は、DBTableModel として返されます。
    075         * 検索以外のSQLも実行できます。結果は、null を返します。
    076         *
    077         * @og.rev 3.0.0.0 (2002/12/25) 新規追加
    078         * @og.rev 3.0.0.1 (2003/02/14) ヘッダー、フッター情報が null のときの処理追加。
    079         * @og.rev 3.5.6.0 (2004/06/18) nullに対する無駄な比較を削除します。
    080         * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為、ApplicationInfoオブジェクトを設定
    081         * @og.rev 4.0.0.0 (2005/01/31) lang ⇒ ResourceManager へ変更
    082         * @og.rev 5.1.9.0 (2010/08/01) Transaction 対応
    083         * @og.rev 5.3.7.0 (2011/07/01) TransactionReal の引数変更
    084         * @og.rev 5.3.8.0 (2011/08/01) Transaction発生箇所でclose()
    085         * @og.rev 6.3.6.1 (2015/08/28) Transaction でAutoCloseableを使用したtry-with-resources構築に対応。
    086         * @og.rev 6.3.6.1 (2015/08/28) QueryFactory.close( Query ) 廃止。Queryはキャッシュしません。
    087         *
    088         * @param   stmt        ステートメント文字列
    089         * @param   args        オブジェクトの引数配列
    090         * @param   resource リソースマネージャー
    091         * @param   appInfo アプリ情報オブジェクト
    092         * @param   dbid        接続先ID
    093         *
    094         * @return  検索結果の配列
    095         */
    096        public static DBTableModel makeDBTable( final String stmt ,final String[] args ,
    097                                                                                        final ResourceManager resource, final ApplicationInfo appInfo, final String dbid ) {
    098                if( stmt == null || stmt.isEmpty() ) { return null; }
    099
    100                DBTableModel table = null;
    101
    102                try( Transaction tran = new TransactionReal( appInfo ) ) {
    103                        final Query query = QueryFactory.newInstance( "JDBCPrepared" );
    104                        query.setConnection( tran.getConnection( dbid ) );                      // 6.3.6.1 (2015/08/28)
    105                        query.setResourceManager( resource );   // 4.0.0 (2005/01/31)
    106                        query.setStatement( stmt );
    107                        query.execute( args );
    108
    109                        final int errCode = query.getErrorCode();
    110                        final int executeCount = query.getExecuteCount();
    111                        if( errCode < ErrorMessage.NG && executeCount >= 0 ) {          // 異常以外の場合
    112                                table = query.getDBTableModel();
    113                                tran.commit();                          // 6.3.6.1 (2015/08/28)
    114                        }
    115                        else {
    116                                tran.rollback();                        // 6.3.6.1 (2015/08/28)
    117                                final ErrorMessage errMessage = query.getErrorMessage();
    118                                throw new HybsSystemException( errMessage.toString() );
    119                        }
    120                }
    121
    122                return table;
    123        }
    124
    125        /**
    126         * 空の DBTableModelオブジェクトを作成します。
    127         * これは、本来、ファクトリクラスで作成すべきですが、簡易作成メソッドとして
    128         * DBUtil の static メソッドとして実装します。
    129         *
    130         * @og.rev 4.0.0.0 (2005/01/31) 新規追加
    131         *
    132         * @return  DBTableModelオブジェクト
    133         * @og.rtnNotNull
    134         */
    135        public static DBTableModel newDBTable() {
    136                return new DBTableModelImpl();
    137        }
    138
    139        /**
    140         * カラム名の配列及びデータの2次元配列からDBテーブルモデルを作成します。
    141         * カラム名がセットされていない若しくはデータがセットされていない場合は、nullを返します。
    142         *
    143         * @og.rev 4.2.1.0 (2008/04/26) 新規追加
    144         *
    145         * @param   clms カラム名の配列
    146         * @param   vals 値の配列
    147         * @param   resource リソースマネージャー
    148         *
    149         * @return  DBテーブルモデル
    150         */
    151        public static DBTableModel makeDBTable( final String[] clms, final String[][] vals, final ResourceManager resource ) {
    152                if( clms == null || clms.length == 0
    153                                || vals == null || vals.length == 0 || vals[0] == null || vals[0].length == 0 ) {
    154                        return null;
    155                }
    156
    157                if( clms.length != vals[0].length ) {
    158                        final String errMsg = "キーのカラム数とデータのカラム数が一致していません。"
    159                                                + CR
    160                                                + " clms.length=[" + clms.length + "]  vals.length=[" + vals[0].length + "]"
    161                                                + " clms=" + StringUtil.array2csv( clms ) + CR
    162                                                + " vals=" + StringUtil.array2csv( vals[0] )  ; // 5.1.8.0 (2010/07/01) errMsg 修正
    163                        throw new HybsSystemException( errMsg );
    164                }
    165
    166                final int numberOfColumns = clms.length;
    167                final DBTableModel table = newDBTable() ;
    168                table.init( numberOfColumns );
    169
    170                DBColumn[] dbColumn = new DBColumn[numberOfColumns];
    171                for( int column=0; column<numberOfColumns; column++ ) {
    172                        dbColumn[column] = resource.makeDBColumn( clms[column] );
    173                        table.setDBColumn( column,dbColumn[column] );
    174                }
    175
    176                final int numberOfRows = vals.length;
    177                for( int row=0; row<numberOfRows; row++ ) {
    178                        table.addColumnValues( vals[row] );
    179                }
    180
    181                return table;
    182        }
    183
    184        /**
    185         * 検索結果オブジェクトからDBテーブルモデルを作成します。
    186         * 検索結果オブジェクトまたはリソースオブジェクトがセットされていない場合は、nullを返します。
    187         *
    188         * @og.rev 5.3.6.0 (2011/06/01) 新規追加
    189         * @og.rev 5.5.5.4 (2012/08/18) TIMESTAMP 型もCLOBと同様に処理を分ける。
    190         * @og.rev 6.0.4.0 (2014/11/28) ResultSetValue を使用するように変更。
    191         *
    192         * @param   result 検索結果オブジェクト
    193         * @param   skipRowCount 読み飛ばし件数
    194         * @param       maxRowCount 最大検索件数
    195         * @param   resource リソースマネージャー
    196         *
    197         * @return  DBテーブルモデル
    198         * @throws      SQLException データベースアクセスエラー
    199         */
    200        public static DBTableModel makeDBTable( final ResultSet result, final int skipRowCount, final int maxRowCount, final ResourceManager resource ) throws SQLException {
    201                if( result == null || resource == null ) { return null; }
    202
    203                final ResultSetValue rsv = new ResultSetValue( result );
    204
    205                final int clmSize =  rsv.getColumnCount();
    206
    207                final DBTableModel table = DBTableModelUtil.newDBTable() ;
    208                table.init( clmSize );
    209
    210                for( int clmNo=0; clmNo<clmSize; clmNo++ ) {
    211                        final String    name    = rsv.getColumnName(clmNo) ;
    212                        DBColumn dbColumn = resource.getDBColumn( name );
    213                        if( dbColumn == null ) {
    214                                dbColumn = makeDBColumn( name,clmNo,rsv,resource );
    215                        }
    216                        table.setDBColumn( clmNo,dbColumn );
    217                }
    218
    219                // データ部の設定
    220                int numberOfRows = 0;
    221                while( numberOfRows < skipRowCount && rsv.next() ) {
    222                        // 注意 rsv.next() を先に判定すると必ず１件読み飛ばしてしまう。
    223                        numberOfRows ++ ;
    224                }
    225                numberOfRows = 0;
    226
    227                while( numberOfRows < maxRowCount && rsv.next() ) {
    228                        numberOfRows ++ ;
    229                        table.addColumnValues( rsv.getValues() );
    230                }
    231
    232                // 最大件数が、超えた場合でかつ次のデータがある場合は、オーバーフロー
    233                if( numberOfRows >= maxRowCount && rsv.next() ) {
    234                        table.setOverflow( true );
    235                }
    236
    237                return table;
    238        }
    239
    240        /**
    241         * 検索結果オブジェクトから編集設定に基づいて変換されたDBテーブルモデルを作成します。
    242         * 検索結果オブジェクトまたはリソースオブジェクトまたは編集設定オブジェクトがセットされていない場合は、nullを返します。
    243         *
    244         * @og.rev 5.3.6.0 (2011/06/01) 新規追加
    245         *
    246         * @param   result 検索結果オブジェクト
    247         * @param   skipRowCount 読み飛ばし件数
    248         * @param       maxRowCount 最大検索件数
    249         * @param   resource リソースマネージャー
    250         * @param       config 編集設定オブジェクト
    251         *
    252         * @return  DBテーブルモデル
    253         * @throws      SQLException データベースアクセスエラー
    254         */
    255        public static DBTableModel makeEditDBTable( final ResultSet result, final int skipRowCount, final int maxRowCount, final ResourceManager resource, final DBEditConfig config ) throws SQLException {
    256                if( result == null || resource == null ) { return null; }
    257                final DBTableModel table = new DBTableModelEditor();
    258                ((DBTableModelEditor)table).create( result, skipRowCount, maxRowCount, resource, config );
    259                return table;
    260        }
    261
    262        /**
    263         * ResultSetValue から、DBColumn オブジェクトを作成します。
    264         *
    265         * DBColumn オブジェクト がリソースファイルに定義されていない場合に、
    266         * データベースの検索結果のメタデータを利用して、DBColumn オブジェクトを
    267         * 作成します。
    268         *
    269         * @og.rev 3.4.0.0 (2003/09/01) 表示パラメータ、編集パラメータ、文字パラメータの追加。
    270         * @og.rev 3.4.0.2 (2003/09/05) DBType のデフォルト値を、'X' から 'XK' に変更します。
    271         * @og.rev 3.6.0.7 (2004/11/06) DBColumn の official属性追加
    272         * @og.rev 4.0.0.0 (2005/01/31) lang 変数を取得
    273         * @og.rev 5.3.6.0 (2011/06/01) AbstractQueryから移動
    274         * @og.rev 6.0.2.1 (2014/09/26) org.opengion.fukurou.db.DBUtil#type2ClassName(int) に移動
    275         * @og.rev 6.0.4.0 (2014/11/28) ResultSetValue を使用するように変更。
    276         * @og.rev 6.2.0.0 (2015/02/27) フィールドサイズ 追加(VIEW_LENGTHと分離して、役割を明確にする)
    277         *
    278         * @param       name            カラム名
    279         * @param       column          カラム番号
    280         * @param   rsv                 ResultSetValueオブジェクト
    281         * @param   resource    リソースマネージャー
    282         * @return      DBColumnオブジェクト
    283         */
    284        public static DBColumn makeDBColumn( final String name,final int column,
    285                                                        final ResultSetValue rsv, final ResourceManager resource ) {
    286                final DBColumn dbColumn ;
    287
    288                final LabelData labelData = resource.getLabelData( name );
    289                final String    lang      = resource.getLang();
    290
    291                try {
    292                        final String    clsName  = rsv.getClassName(column);                                                    // 6.0.4.0 (2014/11/28)
    293                        int     size     = rsv.getColumnDisplaySize(column);                                                    // 6.0.4.0 (2014/11/28)
    294                        if( size == 0 ) { size = 60; }
    295                        final boolean writable = rsv.isWritable(column);                                                                // 6.0.4.0 (2014/11/28)
    296                        final String    dbType   = "NUMBER".equals( clsName ) ? "S9" : "XK" ;
    297                        final String    defValue = "NUMBER".equals( clsName ) ? "0"  : ""  ;
    298                        final DBColumnConfig config = new DBColumnConfig(
    299                                lang,                                                   // 言語
    300                                name,                                                   // カラム名
    301                                labelData,                                              // カラムのラベルデータオブジェクト
    302                                clsName ,                                               // カラムのクラスを文字列にした名称
    303                                null ,                                                  // 入力枠サイズ                                                               // 6.2.0.0 (2015/02/27)
    304                                null ,                                                  // カラムの表示文字数                                            // 6.2.0.0 (2015/02/27)
    305                                String.valueOf( size ) ,                // カラムの最大桁数
    306                                String.valueOf( writable ) ,    // カラムが書き込み可能かどうか
    307                                null ,                                                  // データの表示用レンデラー
    308                                null ,                                                  // データの編集用エディター
    309                                null ,                                                  // メニューの項目コードデータオブジェクト
    310                                dbType ,                                                // データのタイプ
    311                                defValue,                                               // データのデフォルト値
    312                                null ,                                                  // 表示用レンデラーのパラメータ
    313                                null ,                                                  // 編集用エディターのパラメータ
    314                                null ,                                                  // データのタイプのパラメータ
    315                                null ,                                                  // カラムロール
    316                                false,                                                  // 正式なカラムオブジェクトかどうか
    317                                null                                                    // データベース接続先ID
    318                        );
    319
    320                        dbColumn = new DBColumn( config );              // 4.0.0 (2005/01/31)
    321                }
    322                // 6.0.4.0 (2014/11/28) ResultSetValue を使用するように変更。
    323                catch( final RuntimeException ex2 ) {
    324                        final String errMsg = "予期せぬエラーが発生しました。name=[" + name + " , label=[" + labelData + "]";
    325                        throw new HybsSystemException( errMsg,ex2 );            // 3.6.0.0 (2004/09/17)
    326                }
    327
    328                return dbColumn;
    329        }
    330}