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