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.report2;
017
018import org.opengion.fukurou.system.OgRuntimeException ;         // 6.4.2.0 (2016/01/29)
019import java.io.File;
020import java.util.Arrays;
021
022import org.opengion.fukurou.db.DBFunctionName;
023import org.opengion.fukurou.db.DBUtil;
024import org.opengion.fukurou.mail.MailTX;
025import org.opengion.fukurou.db.ApplicationInfo;
026import org.opengion.fukurou.system.DateSet;                                             // 6.4.2.0 (2016/01/29)
027import org.opengion.fukurou.system.LogWriter;
028import org.opengion.fukurou.util.StringUtil;
029import org.opengion.fukurou.util.UnicodeCorrecter;                      // 5.9.3.3 (2015/12/26) package を、mail → util に移動のため
030import org.opengion.hayabusa.common.HybsSystem;
031import org.opengion.hayabusa.db.DBTableModel;
032import org.opengion.hayabusa.db.DBTableModelUtil;
033import org.opengion.hayabusa.resource.ResourceFactory;
034import org.opengion.hayabusa.resource.ResourceManager;
035import static org.opengion.fukurou.system.HybsConst.CR ;                // 6.1.0.0 (2014/12/26)
036
037/**
038 * DBからキューを作成するためのクラスです。
039 * キューはGE5xテーブルから作成されます。
040 *
041 * キュー生成時点(処理スレッドにスタックした時点)では、帳票データのテーブルモデルは作成されません。
042 * 帳票データは、各スレッドからset()メソッドを呼び出したタイミングで生成されます。
043 *
044 * 処理開始及び、完了のステータスは、GE50の完成フラグに更新されます。
045 * また、エラー発生時のメッセージは、GE56に更新されます。
046 *
047 * @og.group 帳票システム
048 *
049 * @version  4.0
050 * @author   Hiroki.Nakamura
051 * @since    JDK1.6
052 */
053public final class QueueManager_DB implements QueueManager {
054
055        /** コネクションにアプリケーション情報を追記するかどうか指定 */
056        private static final boolean USE_DB_APPLICATION_INFO  = HybsSystem.sysBool( "USE_DB_APPLICATION_INFO" ) ;
057
058        private static final String DBID = HybsSystem.sys( "RESOURCE_DBID" );           // 5.5.5.1 (2012/08/07) リソース系DBID 付け忘れ対応
059
060        // 4.3.7.0 (2009/06/01) HSQLDB対応
061        // 5.1.4.0 (2010/03/01) データベース名 でなく、DBID名で検索するように変更します。
062        private static final String CON = DBFunctionName.getFunctionName( "CON", null );
063
064        // 5.2.0.0 (2010/09/01) Ver4互換モード対応
065        private static final String OUT_FILE = HybsSystem.sysBool( "VER4_COMPATIBLE_MODE" ) ? "OUTFILE" : "OUT_FILE";
066        private static final String OUT_DIR = HybsSystem.sysBool( "VER4_COMPATIBLE_MODE" ) ? "OUTDIR" : "OUT_DIR";
067
068        // 4.3.3.6 (2008/11/15) マルチサーバ対応追加(GE12から処理対象デーモングループ取得)
069        // 4.3.7.0 (2009/06/01) HSQLDB対応
070        // 5.2.0.0 (2010/09/01) Ver4互換モード対応
071        // 5.4.2.0 (2011/12/26) PRTID,PRGDIR,PRGFILE取得
072        // 5.9.2.2 (2015/11/20) GROUPID追加
073        private static final String SQL_SELECT_GE50 =
074                "SELECT A.SYSTEM_ID, A.YKNO, A.LISTID, A."+OUT_DIR+", A."+OUT_FILE+", A.PDF_PASSWD"
075                + ", B.LANG, B.FGRUN, B.DMN_GRP "
076                + ", C.MODELDIR, C.MODELFILE, D.PRTNM, C.FGLOCAL, C.FGCUT, C.BSQL, C.HSQL, C.FSQL "
077                + " ,B.PRTID, B.PRGDIR, B.PRGFILE "
078                + " ,A.GROUPID "                                                        // 5.9.2.2 (2015/11/20)
079                + "FROM GE50 A "
080                + "INNER JOIN GE53 B "
081                + "ON A.SYSTEM_ID = B.SYSTEM_ID AND A.JOKEN = B.JOKEN "
082                + "INNER JOIN GE54 C "
083                + "ON A.SYSTEM_ID = C.SYSTEM_ID AND A.LISTID = C.LISTID "
084                + "LEFT OUTER JOIN GE55 D "
085                + "ON B.SYSTEM_ID = D.SYSTEM_ID AND B.PRTID = D.PRTID "
086                + "WHERE A.FGKAN='1' "
087                + "AND EXISTS ( SELECT 'X' FROM GE12 E "
088                +                               "WHERE  E.FGJ                           ='1' "
089                +                               "AND            E.SYSTEM_ID     = '"
090                +                               HybsSystem.sys( "SYSTEM_ID" )
091                +                               "' "
092                +                               "AND            E.CONTXT_PATH   = '"
093                +                               HybsSystem.sys( "HOST_URL" )
094                +                               "' "
095                +                               "AND            E.PARAM_ID              LIKE 'REPORT2_HANDLE_DAEMON_%' "
096                +                               "AND            E.PARAM                 = 'RUN_'" + CON + "A.SYSTEM_ID" + CON + "'_'" + CON + "B.DMN_GRP"
097                +                       ") "
098                + "ORDER BY "
099                + HybsSystem.sys( "REPORT_DAEMON_ORDER_BY" );
100
101        // 5.1.2.0 (2010/01/01) ページ数、データ数をGE50に更新する。
102        private static final String SQL_UPDATE_GE50 =
103                "UPDATE GE50 SET FGKAN = ?, DMN_NAME = ?, DMN_HOST = ?, SUDATA = ?, SUPAGE = ?, DYUPD = ? WHERE SYSTEM_ID = ? AND YKNO = ?";
104
105        private static final String SQL_INSERT_GE56 =
106                "INSERT INTO GE56 ( FGJ, SYSTEM_ID, YKNO, ERRMSG, DYSET, DYUPD, USRSET, USRUPD, PGUPD ) "
107                + " VALUES ( '1', ?, ? ,? ,? ,? ,? ,? ,? )" ;
108
109        private static final int STATUS_COMPLETE        = 2;
110        private static final int STATUS_EXECUTE         = 3;
111        private static final int STATUS_ERROR           = 8;
112
113        private static QueueManager manager = new QueueManager_DB();
114
115        /** アプリケーション情報 */
116        private static final ApplicationInfo APP_INFO;          // 6.4.1.1 (2016/01/16) appInfo → APP_INFO refactoring
117        static {
118                if( USE_DB_APPLICATION_INFO ) {
119                        APP_INFO = new ApplicationInfo();
120                        // ユーザーID,IPアドレス,ホスト名
121                        APP_INFO.setClientInfo( "ReportDaemon", HybsSystem.HOST_ADRS, HybsSystem.HOST_NAME );
122                        // 画面ID,操作,プログラムID
123                        APP_INFO.setModuleInfo( "ReportDaemon", "QueueManager", "QueueManager" );
124                }
125                else {
126                        APP_INFO = null;
127                }
128        }
129
130        /**
131         * インスタンスの生成を禁止します。
132         */
133        private QueueManager_DB() {}
134
135        /**
136         * インスタンスを返します。
137         *
138         * @return      帳票処理キューの管理マネージャ
139         */
140        public static QueueManager getInstance() {
141                return manager;
142        }
143
144        /**
145         * 帳票処理キューを作成します。
146         *
147         * @og.rev 4.3.0.0 (2008/07/15) スレッドIDにシステムIDを付加します。
148         * @og.rev 5.1.2.0 (2010/01/01) HSQL,FSQL,BSQLのセットを廃止します。(このクラス内でデータを直接分割)
149         * @og.rev 5.4.3.0 (2011/12/26) PRTIDの取得
150         * @og.rev 5.5.5.1 (2012/08/07) リソース系DBID 付け忘れ対策
151         * @og.rev 6.3.9.0 (2015/11/06) Use block level rather than method level synchronization.(PMD)
152         * @og.rev 5.9.2.2 (2015/11/20) GrpId,DmnGrp 追加
153         */
154        public void create() {
155                // キューをスタックするまでの例外は、ScheduleTagでcatchされデーモンがスリープする。
156                final String[][] ge50vals = DBUtil.dbExecute( SQL_SELECT_GE50, new String[0], APP_INFO, DBID ); // 5.5.5.1 (2012/08/07)
157
158                // 6.3.9.0 (2015/11/06) 元々のsynchronizedの必要性が分からないが、帳票なのでとりあえず入れておきます。
159                synchronized( ge50vals ) {
160                        for( int i=0; i<ge50vals.length; i++ ) {
161                                final ExecQueue queue = new ExecQueue();
162                                queue.setSystemId(      ge50vals[i][0] );
163                                queue.setYkno(          ge50vals[i][1] );
164                                queue.setListId(        ge50vals[i][2] );
165                                queue.setOutputName( new File( ge50vals[i][3] ).getAbsolutePath() , ge50vals[i][4] , ge50vals[i][7] , ge50vals[i][1] ); // 4.3.0.0 (2008/07/18) 要求番号を出力ファイル名に利用
166                                queue.setPdfPasswd( ge50vals[i][5] );
167                                queue.setLang(          ge50vals[i][6] );
168                                queue.setOutputType( ge50vals[i][7] );
169                                queue.setThreadId(      ge50vals[i][0] + "_" + StringUtil.nval( ge50vals[i][8] , "_DEFALUT_" ) ); // 4.3.0.0 (2008/07/15)
170                                queue.setTemplateName( new File( ge50vals[i][9] ).getAbsolutePath() + File.separator + ge50vals[i][10] );
171                                queue.setPrinterName( ge50vals[i][11] );
172                                queue.setFglocal(       "1".equals( ge50vals[i][12] ) );
173                                queue.setFgcut(         "1".equals( ge50vals[i][13] ) );
174
175                                queue.setPrtId(         ge50vals[i][17] );              // 5.4.3.0
176                                queue.setPrgDir(        ge50vals[i][18] );              // 5.4.3.0
177                                queue.setPrgFile(       ge50vals[i][19] );              // 5.4.3.0
178
179                                queue.setGrpId(         ge50vals[i][20] );              // 5.9.2.2 (2015/11/20)
180                                queue.setDmnGrp(        ge50vals[i][8]  );              // 5.9.2.2 (2015/11/20)
181
182                                queue.setManager( this );
183
184                                ExecThreadManager.insertQueue( queue );
185                        }
186                }
187        }
188
189        /**
190         * 帳票処理データをキューにセットします。
191         *
192         * @og.rev 5.1.2.0 (2010/01/01) HSQL,FSQL,BSQLのセットを廃止します。(このクラス内でデータを直接分割)
193         *
194         * @param       queue   ExecQueueオブジェクト
195         */
196        public void set( final ExecQueue queue ) {
197                final String systemId   = queue.getSystemId();
198                final String lang               = queue.getLang();
199                final String listId             = queue.getListId();
200                final String ykno               = queue.getYkno();
201
202                ResourceManager resource = null;
203                if( queue.isFglocal() ) {
204                        resource = ResourceFactory.newInstance( systemId, lang, false );
205                }
206                else {
207                        resource = ResourceFactory.newInstance( lang );
208                }
209
210                // ヘッダー情報の取得
211                final DBTableModel header = new DBTableModelCreator( systemId, listId, ykno, "H", resource ).getTable();
212
213                if( header != null && header.getRowCount() > 0 ) {
214                        queue.setHeader( header );
215                }
216
217                // フッター情報の取得
218                final DBTableModel footer = new DBTableModelCreator( systemId, listId, ykno, "F", resource ).getTable();
219                if( footer != null && footer.getRowCount() > 0 ) {
220                        queue.setFooter( footer );
221                }
222
223                // ボディー情報の取得
224                final DBTableModel body = new DBTableModelCreator( systemId, listId, ykno, "B", resource ).getTable();
225                // レイアウトテーブルがないと固定長を分割するSQL文が設定されず、DBTableModelがnullになる
226                if( body == null ) {
227                        queue.addMsg( "[ERROR] DBTableModel doesn't exists! maybe Layout-Table(GE52) is not configured..." + CR );
228                        queue.setError();
229                        throw new OgRuntimeException();
230                }
231                if( body.getRowCount() <= 0 ) {
232                        queue.addMsg( "[ERROR] Database Body row count is Zero." + ykno + CR );
233                        queue.setError();
234                        throw new OgRuntimeException();
235                }
236                if( body.isOverflow() ) {
237                        queue.addMsg( "[ERROR]Database is Overflow. [" + body.getRowCount() + "]" + CR );
238                        queue.addMsg( "[ERROR]Check SystemParameter Data in DB_MAX_ROW_COUNT Overflow" + CR  );
239                        queue.setError();
240                        throw new OgRuntimeException();
241                }
242                queue.setBody( body );
243        }
244
245        /**
246         * キューを実行中の状態に更新します。
247         *
248         * @param       queue   ExecQueueオブジェクト
249         */
250        public void execute( final ExecQueue queue ) {
251                status( queue, STATUS_EXECUTE );
252        }
253
254        /**
255         * キューを完了済の状態に更新します。
256         *
257         * @param       queue   ExecQueueオブジェクト
258         */
259        public void complete( final ExecQueue queue ) {
260                status( queue, STATUS_COMPLETE );
261        }
262
263        /**
264         * キューをエラーの状態に更新します。
265         *
266         * @param       queue   ExecQueueオブジェクト
267         */
268        public void error( final ExecQueue queue ) {
269                status( queue, STATUS_ERROR );
270                insertErrorMsg( queue );
271        }
272
273        /**
274         * GE50の状況Cを更新します。
275         *
276         * @og.rev 4.2.4.1 (2008/07/09) 更新日時をセット
277         * @og.rev 5.1.2.0 (2010/01/01) 行数、ページ数も更新する
278         * @og.rev 5.5.5.1 (2012/08/07) リソース系DBID 付け忘れ対策
279         * @og.rev 6.4.2.0 (2016/01/29) DateSet.getDate( String ) を利用するように修正します。
280         *
281         * @param       queue   ExecQueueオブジェクト
282         * @param       status  状況C
283         */
284        private void status( final ExecQueue queue, final int status ) {
285
286                final String dyupd = DateSet.getDate( "yyyyMMddHHmmss" ) ;                      // 6.4.2.0 (2016/01/29)
287
288                final String[] args
289                = new String[]{ String.valueOf( status ), queue.getThreadId(), HybsSystem.sys( "HOST_NAME" )
290                                , String.valueOf( queue.getExecRowCnt() ), String.valueOf( queue.getExecPagesCnt() )
291                                , dyupd , queue.getSystemId(), queue.getYkno() };
292
293                DBUtil.dbExecute( SQL_UPDATE_GE50, args, APP_INFO, DBID );      // 5.5.5.1 (2012/08/07)
294        }
295
296        /**
297         * GE56にエラーメッセージを出力します。
298         *
299         * @og.rev 4.4.0.1 (2009/08/08) エラーメッセージ機能追加
300         * @og.rev 5.5.5.1 (2012/08/07) リソース系DBID 付け忘れ対策
301         * @og.rev 6.4.2.0 (2016/01/29) DateSet.getDate( String ) を利用するように修正します。
302         *
303         * @param       queue   ExecQueueオブジェクト
304         */
305        private void insertErrorMsg( final ExecQueue queue ) {
306                String errmsg = queue.getMsg();
307                if( errmsg.length() > 1300 ) {
308                        errmsg = errmsg.substring( errmsg.length() - 1300, errmsg.length() );
309                }
310
311                final String dyset = DateSet.getDate( "yyyyMMddHHmmss" ) ;                      // 6.4.2.0 (2016/01/29)
312
313                final String[] args
314                = new String[]{ queue.getSystemId(), queue.getYkno(), errmsg
315                                , dyset, dyset, "UNKNOWN", "UNKNOWN", "UNKNOWN" };
316
317                DBUtil.dbExecute( SQL_INSERT_GE56, args, APP_INFO, DBID );      // 5.5.5.1 (2012/08/07)
318
319                sendMail( queue, errmsg ); // 4.4.0.1 (2009/08/08)
320        }
321
322        /**
323         * エラー情報のメール送信を行います。
324         * エラーメールは、システムパラメータ の COMMON_MAIL_SERVER(メールサーバー)と
325         * ERROR_MAIL_FROM_USER(エラーメール発信元)と、ERROR_MAIL_TO_USERS(エラーメール受信者)
326         * がすべて設定されている場合に、送信されます。
327         *
328         * @og.rev 4.4.0.1 (2009/08/08) 追加
329         * @og.rev 5.7.0.4 (2013/11/29) listIdの絞込み
330         *
331         * @param       queue           ExecQueueオブジェクト
332         * @param       inErrMsg        エラーメッセージ
333         */
334        private void sendMail( final ExecQueue queue, final String inErrMsg ) {
335
336                final String   host = HybsSystem.sys( "COMMON_MAIL_SERVER" );
337                final String   from = HybsSystem.sys( "ERROR_MAIL_FROM_USER" );
338                final String[] to = StringUtil.csv2Array( HybsSystem.sys( "ERROR_MAIL_TO_USERS" ) );
339                final String   match_txt = HybsSystem.sys( "REPORT_ERRMAIL_REGEX" ); // 5.7.0.4 (2013/11/29) 
340                if( host != null && from != null && to.length > 0 ) {
341                        if( match_txt == null || match_txt.isEmpty() 
342                                        || queue.getListId() == null || queue.getListId().isEmpty()
343                                        || queue.getListId().matches( match_txt )){     // 5.7.0.4 (2013/11/29)
344                                // 5.7.0.4 (2013/11/29) listid追加
345                                final String subject = "SYSTEM_ID=[" + queue.getSystemId() + "] , YKNO=[" + queue.getYkno() + "] , "
346                                                           + "THREAD_ID=[" + queue.getThreadId() + "] , DMN_HOST=[" + HybsSystem.HOST_NAME + "]" 
347                                                           + "LISTID=["+ queue.getListId() + "]";
348                                try {
349                                        final MailTX tx = new MailTX( host );
350                                        tx.setFrom( from );
351                                        tx.setTo( to );
352                                        tx.setSubject( "帳票エラー:" + subject );
353                                        tx.setMessage( inErrMsg );
354                                        tx.sendmail();
355                                }
356                                catch( final Throwable ex ) {
357                                        final String errMsg = "エラー時メール送信に失敗しました。" + CR
358                                                                + " SUBJECT:" + subject                                 + CR
359                                                                + " HOST:" + host                                               + CR
360                                                                + " FROM:" + from                                               + CR
361                                                                + " TO:"   + Arrays.toString( to )              + CR
362                                                                + ex.getMessage();              // 5.1.8.0 (2010/07/01) errMsg 修正
363                                        LogWriter.log( errMsg );
364                                        LogWriter.log( ex );
365                                }
366                        }
367                }
368        }
369
370        /**
371         * 帳票明細データを帳票レイアウトテーブルに従って分割し、その結果をDBTableModelとして
372         * 生成します。
373         * データの分割は、バイト数ベースで行われるため、エンコードを正しく指定する必要があります。
374         * エンコード指定は、システムリソースのDB_ENCODEで指定します。
375         *
376         * レイアウトテーブルが存在しない場合、又は、帳票データが存在しない場合、DBTableModelは
377         * nullで返されます。
378         *
379         * @og.rev 6.9.0.2 (2018/02/13) GE51の検索順(order by)を追加します。
380         */
381        public static final class DBTableModelCreator {
382                // 5.2.0.0 (2010/09/01) Ver4互換モード対応
383                private static final String CLM = HybsSystem.sysBool( "VER4_COMPATIBLE_MODE" ) ? "COLUMN_NAME" : "CLM";
384                private static final String TEXT_DATA = HybsSystem.sysBool( "VER4_COMPATIBLE_MODE" ) ? "TEXT" : "TEXT_DATA";
385
386                // 5.2.0.0 (2010/09/01) Ver4互換モード対応
387                // 5.4.4.3 (2012/02/09) FGUSE条件追加対応
388                private static final String SQL_SELECT_GE52 =
389                        " select " + CLM + ", START_POS, USE_LENGTH"
390                        + " from GE52"
391                        + " where SYSTEM_ID = ?"
392                        + " and LISTID = ?"
393                        + " and KBTEXT = ?"
394                        + " and FGJ = '1'"
395                        + " and FGUSE = '1'" // 5.4.4.3
396                        + " order by SEQ";
397
398                // 5.2.0.0 (2010/09/01) Ver4互換モード対応
399                // 6.9.0.2 (2018/02/13) GE51の検索順(order by)を追加します。
400                private static final String SQL_SELECT_GE51 =
401                        " select " + TEXT_DATA
402                        + " from GE51"
403                        + " where SYSTEM_ID = ?"
404                        + " and YKNO = ?"
405                        + " and KBTEXT = ?"
406                        + " and FGJ = '1'"
407                        + " order by SYSTEM_ID,YKNO,EDNO" ;                             // 6.9.0.2 (2018/02/13)
408
409                private static final String ENCODE = HybsSystem.sys( "DB_ENCODE" );
410
411                private final String systemId;
412                private final String listId;
413                private final String ykno;
414                private final String kbtext;
415                private final ResourceManager resource;
416
417                private DBTableModel table      ;
418
419                /**
420                 * コンストラクタです。
421                 *
422                 * @param sid システムID
423                 * @param lid 帳票ID
424                 * @param yk 要求NO
425                 * @param kt テキスト区分(H:ヘッダー F:フッター B:ボディー)
426                 * @param res リソースマネージャー
427                 */
428                public DBTableModelCreator( final String sid, final String lid, final String yk, final String kt, final ResourceManager res ) {
429                        systemId        = sid;
430                        listId          = lid;
431                        ykno            = yk;
432                        kbtext          = kt;
433                        resource        = res;
434                        create();
435                }
436
437                /**
438                 * 帳票データをレイアウト定義に従い分割します。
439                 *
440                 * @og.rev 5.5.5.1 (2012/08/07) リソース系DBID 付け忘れ対策
441                 * @og.rev 5.9.3.1 (2015/12/18) SJIS-UTF変換時の波ダッシュ問題対応
442                 */
443                private void create() {
444                        final String[] ge52Where = new String[] { systemId, listId, kbtext } ;
445                        final String[][] ge52Vals = DBUtil.dbExecute( SQL_SELECT_GE52, ge52Where, APP_INFO, DBID );     // 5.5.5.1 (2012/08/07)
446                        if( ge52Vals == null || ge52Vals.length == 0 ) {
447                                return;
448                        }
449
450                        final String[] ge51Where = new String[] { systemId, ykno, kbtext } ;
451                        final String[][] ge51Vals = DBUtil.dbExecute( SQL_SELECT_GE51, ge51Where, APP_INFO, DBID );     // 5.5.5.1 (2012/08/07)
452                        if( ge51Vals == null || ge51Vals.length == 0 ) {
453                                return;
454                        }
455
456                        String[] clms = new String[ge52Vals.length];
457                        for( int i=0; i<ge52Vals.length; i++ ) {
458                                clms[i] = ge52Vals[i][0];
459                        }
460
461                        String[][] vals = new String[ge51Vals.length][ge52Vals.length];
462                        for( int i=0; i<ge51Vals.length; i++ ) {
463                                final byte[] bytes = StringUtil.makeByte( UnicodeCorrecter.correctToCP932( ge51Vals[i][0], ENCODE ), ENCODE ); // 5.9.3.1 (2015/12/18)
464                                for( int j=0; j<ge52Vals.length; j++ ) {
465                                        final int strpos = Integer.parseInt( ge52Vals[j][1] ) - 1;      // 6.0.2.4 (2014/10/17) メソッド間違い
466                                        int len = Integer.parseInt( ge52Vals[j][2] );                   // 6.0.2.4 (2014/10/17) メソッド間違い
467                                        if( strpos >= bytes.length ) {
468                                                vals[i][j] = "";
469                                        }
470                                        else {
471                                                if( strpos + len > bytes.length ) {
472                                                        len = bytes.length - strpos;
473                                                }
474                                                vals[i][j] = StringUtil.rTrim( StringUtil.makeString( bytes, strpos, len, ENCODE ) );
475                                        }
476                                }
477                        }
478                        table = DBTableModelUtil.makeDBTable( clms, vals, resource );
479                }
480
481                /**
482                 * 分割後のDBTableModelを返します。
483                 *
484                 * @return 分割後のDBTableModel
485                 */
486                public DBTableModel getTable() {
487                        return table;
488                }
489        }
490}