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.report;
017
018import org.opengion.hayabusa.common.HybsSystem;
019import org.opengion.hayabusa.db.DBTableModelUtil;
020import org.opengion.hayabusa.db.DBTableModel;
021import org.opengion.hayabusa.resource.ResourceFactory;
022import org.opengion.hayabusa.resource.ResourceManager;
023import org.opengion.fukurou.util.StringUtil;
024import org.opengion.fukurou.util.FileUtil;
025import org.opengion.fukurou.util.ApplicationInfo;
026import org.opengion.fukurou.db.DBUtil;
027
028import java.io.File;
029
030/**
031 * 【レポート出力】DBTableModelオブジェクトをレポート形式に返還するタグリブクラスです。
032 * このオブジェクトに、 データ(DBTableModel)と、コントローラ(DBTableReport クラス)を与えて、
033 * 外部からコントロールすることで、各種形式で データ(DBTableModel)を表示させることが
034 * 可能です。
035 *
036 * @og.group 帳票システム
037 *
038 * @version  4.0
039 * @author   Kazuhiko Hasegawa
040 * @since    JDK5.0,
041 */
042public class ReportConverter {
043
044        private static final String CR     = HybsSystem.CR ;
045
046        private final StringBuilder errMsg = new StringBuilder();
047
048        // DBTableReport に対して設定する情報
049        private String[]        headerKeys              = null;   // 固定部の key 部分を指定する。カンマで複数指定できる。
050        private String[]        headerVals              = null;   // 固定部の key に対応する値を指定する。
051        private String[]        footerKeys              = null;   // 繰り返し部の終了後に表示する key 部分を指定する。カンマで複数指定できる。
052        private String[]        footerVals              = null;   // 繰り返し部の終了後に表示する key に対する値を指定する。
053        private boolean         pageEndCut              = false;  // ボディー部(繰り返し部)がなくなったときに、それ以降のページを出力するか指定する。
054        private File            templateFile    = null;         // 3.8.0.0 (2005/06/07)
055        private File            firstTemplateFile = null;       // 3.8.0.0 (2005/06/07)
056        private DBTableModel    table           = null;
057        private ResourceManager resource        = null;         // 4.0.0 (2005/01/31)
058
059        // 受け渡し変数
060        private final String    SYSTEM_ID       ;
061        private final String    YKNO            ;
062        private final String    LISTID          ;
063        private final String    HTML_DIR        ;
064        private final String    LANG            ;
065        private final boolean   DEBUG           ;       // 3.8.5.0 (2006/03/06) デバッグ用のフラグを追加
066
067        // GE54 帳票定義マスタ
068        private String          modelDIR        = null;
069        private String          modelFILE       = null;
070        private String          hSQL            = null;
071        private String          fSQL            = null;
072        private String          bSQL            = null;
073        private boolean         fgLOCAL         = false;        // 0:未使用 1:使用 4.0.0 (2005/01/31)
074        private boolean         fgDIRECT        = false;        // 0:未使用 1:使用 4.0.0 (2005/01/31)
075
076        // GE54 の帳票定義情報を取得するSQL文です。
077        // 4.0.0 (2005/01/31) 共有 system_id を、考慮
078        private static final String GE54_SELECT =
079                "SELECT MODELDIR,MODELFILE,FGCUT,HSQL,FSQL,BSQL,FGLOCAL,FGDIRECT,SYSTEM_ID" +   // 4.0.0 (2005/01/31)
080                " FROM GE54" +
081                " WHERE FGJ = '1'" +
082                " AND  SYSTEM_ID IN (?,'**')" +
083                " AND  LISTID = ?" ;
084
085        private static final int GE54_MODELDIR  = 0;
086        private static final int GE54_MODELFILE = 1;
087        private static final int GE54_FGCUT             = 2;
088        private static final int GE54_HSQL              = 3;
089        private static final int GE54_FSQL              = 4;
090        private static final int GE54_BSQL              = 5;
091        private static final int GE54_FGLOCAL   = 6;
092        private static final int GE54_FGDIRECT  = 7;
093        private static final int GE54_SYSTEM_ID = 8;
094
095        /** コネクションにアプリケーション情報を追記するかどうか指定 */
096        public static final boolean USE_DB_APPLICATION_INFO  = HybsSystem.sysBool( "USE_DB_APPLICATION_INFO" ) ;
097
098        // 3.8.7.0 (2006/12/15) アクセスログ取得の為,ApplicationInfoオブジェクトを設定
099        private final ApplicationInfo appInfo;
100        private final String DBID = HybsSystem.sys( "RESOURCE_DBID" );          // 5.5.5.1 (2012/08/07) リソース系DBID 付け忘れ対応
101
102        /**
103         * コンストラクター
104         * 引数を受けとって、インスタンスを作成します。
105         *
106         * @og.rev 3.0.0.4 (2003/02/26) FGRUN が PRT のみのときは,MODELFILE のみセットして終了する。
107         * @og.rev 3.8.0.0 (2005/06/07) FGRUNは,使用しない
108         * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為,ApplicationInfoオブジェクトを設定
109         *
110         * @param system_id システムID
111         * @param ykno 要求番号
112         * @param listId 帳票ID
113         * @param tempDir 出力ディレクトリ
114         * @param lang 言語
115         * @param debug デバッグフラグ言語
116         */
117        public ReportConverter( final String system_id, final String ykno, final String listId,
118                                                         final String tempDir,final String lang,final boolean debug ) {
119                SYSTEM_ID       = system_id;
120                YKNO            = ykno;
121                LISTID          = listId;
122                HTML_DIR        = tempDir;
123                LANG            = lang;
124                DEBUG           = debug;
125
126                // 3.8.7.0 (2006/12/15) アクセスログ取得の為,ApplicationInfoオブジェクトを設定
127                if( USE_DB_APPLICATION_INFO ) {
128                        appInfo = new ApplicationInfo();
129                        // ユーザーID,IPアドレス,ホスト名
130                        appInfo.setClientInfo( SYSTEM_ID,HybsSystem.HOST_ADRS,HybsSystem.HOST_NAME );
131                        // 画面ID,操作,プログラムID
132                        appInfo.setModuleInfo( "ReportConverter",YKNO,LISTID );
133                }
134                else {
135                        appInfo = null;
136                }
137        }
138
139        /**
140         * 変換処理を実行します。
141         *
142         * @og.rev 3.0.0.4 (2003/02/26) FGRUN が PRT のみのときは,MODELFILE のみセットして終了する。
143         * @og.rev 3.5.4.9 (2004/02/25) 存在チェックエラー(原因不明)の暫定対応
144         * @og.rev 3.8.0.0 (2005/06/07) initialDataSet() を ReportProcessing 側で呼び出します。
145         *
146         * @return 結果 [true:正常/false:異常]
147         */
148        public boolean execute() {
149                System.out.print( "ReportConverter Started ... " );
150                boolean flag = true;
151
152                try {
153                        // 雛形ファイルのチェック
154                        // 3.8.0.0 (2005/06/07) 存在チェックは、FileUtil.checkFile で行う。
155                        if( flag ) {
156                                System.out.print( "MDL CK," );
157                                templateFile = FileUtil.checkFile( modelDIR, modelFILE + ".html" );
158                                flag = templateFile != null ;           // チェックの結果が null なら、見つからなかった。
159
160                                if( !flag ) {
161                                        errMsg.append( "ModelFile Not Found Error !" ).append( CR );
162                                        errMsg.append( "MODELDIR=" ).append( modelDIR ).append( CR );
163                                        errMsg.append( "MODELFILE=" ).append( modelFILE + ".html" ).append( CR );
164                                }
165                        }
166
167                        // ファーストページ雛形ファイルのチェック(なくても良い)
168                        // 3.8.0.0 (2005/06/07) 存在チェックは、FileUtil.checkFile で行う。
169                        if( flag ) {
170                                // チェックは、1回のみ行う。
171                                firstTemplateFile = FileUtil.checkFile( modelDIR, modelFILE + "_FIRST.html",1 );
172                        }
173
174                        // ヘッダ,フッタ, ボディー部の SQL を実行します。
175                        if( flag ) {
176                                flag = isHeaderFooter();
177                                if( flag ) { System.out.print( "HF SQL," ); }
178                        }
179
180                        // 帳票変換処理を実行します。
181                        if( flag ) {
182                                flag = reportRun();
183                                if( flag ) { System.out.print( "RPT RUN," ); }
184                        }
185                }
186                catch ( RuntimeException ex ) {
187                        errMsg.append( "ReportConverter Execute Exception Error!" ).append( CR );
188                        errMsg.append( "==============================" ).append( CR );
189                        errMsg.append( StringUtil.stringStackTrace( ex ) ) ;
190                        errMsg.append( CR ) ;
191                        flag = false;
192                }
193
194                System.out.println( "End." );
195                return flag ;
196        }
197
198        /**
199         * 初期データセットを行います。
200         * ここでは、GE54 テーブルより必要な情報を取得します。
201         *
202         * @og.rev 3.8.0.0 (2005/06/07) initialDataSet() を ReportProcessing 側で呼び出します。
203         * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為,ApplicationInfoオブジェクトを設定
204         * @og.rev 4.0.0.0 (2005/01/31) ローカルリソースフラグとダイレクトアクセスフラグを追加
205         * @og.rev 5.5.5.1 (2012/08/07) リソース系DBID 付け忘れ対策
206         *
207         * @return 結果 [true:正常/false:異常]
208         */
209        public boolean initialDataSet() {
210                String[] args = new String[] { SYSTEM_ID,LISTID };
211                // modeldir,modelfile,fgcut,hsql,fsql,bsql,fglocal,fgdirect,system_id
212                String[][] vals = DBUtil.dbExecute( GE54_SELECT,args,appInfo, DBID );           // 5.5.5.1 (2012/08/07)
213                if( vals == null || vals.length == 0 ) {
214                        errMsg.append( "Data does not exist in GE54 table." ).append( CR );
215                        errMsg.append( "==============================" ).append( CR );
216                        errMsg.append( "SYSTEM_ID=[" ).append( SYSTEM_ID ).append( "] , " );
217                        errMsg.append( "LISTID=["    ).append( LISTID    ).append( "]" );
218                        errMsg.append( CR );
219                        return false;
220                }
221
222                int row = 0;
223                // 検索結果が複数帰ったとき、SYSTEM_ID が 指定されている方のデータ(行)を採用する。
224                for( int i=0; i<vals.length; i++ ) {
225                        if( SYSTEM_ID.equalsIgnoreCase( vals[i][GE54_SYSTEM_ID] ) ) { row = i; break; }
226                }
227
228                modelDIR        = StringUtil.nval( vals[row][GE54_MODELDIR],modelDIR );
229                modelFILE       = StringUtil.nval( vals[row][GE54_MODELFILE],modelFILE );
230                pageEndCut      = StringUtil.nval( vals[row][GE54_FGCUT],pageEndCut );  // boolean タイプ
231
232                if( DEBUG ) {
233                        System.out.println( "MODELDIR   = [" + modelDIR   + "]" );
234                        System.out.println( "MODELFILE  = [" + modelFILE  + "]" );
235                        System.out.println( "pageEndCut = [" + pageEndCut + "]" );
236                }
237
238                hSQL = StringUtil.nval( vals[row][GE54_HSQL],hSQL );
239                fSQL = StringUtil.nval( vals[row][GE54_FSQL],fSQL );
240                bSQL = StringUtil.nval( vals[row][GE54_BSQL],bSQL );
241                if( bSQL == null || bSQL.length() == 0 ) {
242                        errMsg.append( "Body SQL Columns does not exist in GE54 table." ).append( CR );
243                        errMsg.append( "==============================" ).append( CR );
244                        errMsg.append( "SYSTEM_ID=[" ).append( SYSTEM_ID ).append( "] , " );
245                        errMsg.append( "LISTID=["    ).append( LISTID    ).append( "] " );
246                        errMsg.append( CR );
247                        return false;
248                }
249
250                // 4.0.0 (2005/01/31) ローカルリソースフラグとダイレクトアクセスフラグを追加
251                fgLOCAL = vals[row][GE54_FGLOCAL]  != null && vals[row][GE54_FGLOCAL].trim().equals( "1" ) ;
252                fgDIRECT= vals[row][GE54_FGDIRECT] != null && vals[row][GE54_FGDIRECT].trim().equals( "1" ) ;
253
254                return true;
255        }
256
257        /**
258         * ヘッダーフッター情報の取得を行います。
259         * GE54 の HSQL,FSQL,BSQL のコマンドを実行して、データを取得します。
260         * ヘッダー情報、フッター情報がなくても異常とは判断されませんが、
261         * ボディ情報が存在しない場合は、エラーとなります。
262         *
263         * @og.rev 3.0.0.1 (2003/02/14) ヘッダー、フッター情報が null のときの処理追加。
264         * @og.rev 3.0.1.3 (2003/03/11) 検索時の最大件数での打ち切りをエラーとする。
265         * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為,ApplicationInfoオブジェクトを設定
266         * @og.rev 4.0.0.0 (2005/01/31) lang ⇒ ResourceManager へ変更 , メソッド名変更
267         *
268         * @return 結果 [true:正常/false:異常]
269         */
270        private boolean isHeaderFooter() {
271                // 4.0.0 (2005/01/31) FGLOCAL 指定時は、SYSTEM_ID を指定してリソース作成
272                if( fgLOCAL ) {
273                        // ローカルリソース指定時は、SYSTEM_ID,LANG を使用します。先読みは、使用しません。
274                        resource = ResourceFactory.newInstance( SYSTEM_ID,LANG,false ); // 4.0.0 (2005/01/31)
275                }
276                else {
277                        // 従来と互換性のあるモード(ローカルリソースは使用しない。
278                        resource = ResourceFactory.newInstance( LANG ); // 4.0.0 (2005/01/31)
279                }
280
281                // 4.0.0 (2005/01/31) FGDIRECT 指定時は、where 条件は、null になります。
282                String[] where = fgDIRECT ? null : new String[] { SYSTEM_ID , YKNO } ;
283
284                // ヘッダー情報の取得
285                DBTableModel header = DBTableModelUtil.makeDBTable( hSQL, where, resource, appInfo );           // 3.8.7.0 (2006/12/15)
286                if( header != null && header.getRowCount() > 0 ) {
287                        headerKeys              = header.getNames();
288                        Object[] obj    = header.getValues(0);
289                        headerVals              = new String[obj.length];
290                        for( int i=0; i<obj.length; i++ ) {
291                                headerVals[i] = obj[i].toString().trim();
292                        }
293                }
294
295                // フッター情報の取得
296                DBTableModel footer = DBTableModelUtil.makeDBTable( fSQL, where, resource ,appInfo );           // 3.8.7.0 (2006/12/15)
297                if( footer != null && footer.getRowCount() > 0 ) {
298                        footerKeys              = footer.getNames();
299                        Object[] obj    = footer.getValues(0);
300                        footerVals              = new String[obj.length];
301                        for( int i=0; i<obj.length; i++ ) {
302                                footerVals[i] = obj[i].toString().trim();
303                        }
304                }
305
306                // ボディー情報の取得
307                table = DBTableModelUtil.makeDBTable( bSQL, where, resource ,appInfo );         // 3.8.7.0 (2006/12/15)
308                if( table.getRowCount() <= 0 ) {
309                        errMsg.append( "Database Body row count is Zero." ).append( CR );
310                        errMsg.append( "==============================" ).append( CR );
311                        errMsg.append( bSQL );
312                        errMsg.append( CR );
313                        return false;
314                }
315                // 3.0.1.3 (2003/03/11) 検索時の最大件数での打ち切りをエラーとする。
316                if( table.isOverflow() ) {
317                        errMsg.append( "Database is Overflow. [" );
318                        errMsg.append( table.getRowCount() );
319                        errMsg.append( "]" ).append( CR ).append( CR );
320                        errMsg.append( "==============================" ).append( CR );
321                        errMsg.append( "Check SystemParameter Data in DB_MAX_ROW_COUNT Overflow" );
322                        errMsg.append( CR );
323                        return false;
324                }
325
326                return true;
327        }
328
329        /**
330         * 実際のレポート変換処理を行います。
331         *
332         * @og.rev 3.5.4.3 (2004/01/05) HTMLDBTableReport のクラス名変更。
333         * @og.rev 3.6.0.0 (2004/09/17) メソッド名の変更。setInputFile ⇒ setTemplateFile
334         * @og.rev 3.6.1.0 (2005/01/05) 帳票ID(LISTID)をセットします。
335         * @og.rev 3.8.5.1 (2006/04/28) setOutputFileKey の代わりに、setYkno を使用します。
336         * @og.rev 4.0.0.0 (2005/01/31) lang ⇒ ResourceManager へ変更
337         *
338         * @return 結果 [true:正常/false:異常]
339         */
340        private boolean reportRun() {
341                DBTableReport report = new DBTableReport_HTML();
342
343                report.setDBTableModel( table );
344                report.setTemplateFile( templateFile );                         // 3.6.0.0 (2004/09/17)
345                report.setFirstTemplateFile( firstTemplateFile );       // 3.6.0.0 (2004/09/17)
346                report.setOutputDir( HTML_DIR );
347                report.setOutputFileKey( YKNO );        // 要求番号をファイル名として使用します。
348                report.setYkno( YKNO );                                                         // 3.8.5.1 (2006/04/28)
349                report.setHeaderKeys( headerKeys );
350                report.setHeaderVals( headerVals );
351                report.setFooterKeys( footerKeys );
352                report.setFooterVals( footerVals );
353                report.setPageEndCut( pageEndCut );
354                report.setResourceManager( resource );          // 4.0.0 (2005/01/31)
355                report.setListId( LISTID );             // 3.6.1.0 (2005/01/05)
356                report.writeReport();
357
358                return true;
359        }
360
361        /**
362         * modelFILE を返します。
363         *
364         * @return modelFILE名
365         */
366        public String modelFile() {
367                return modelFILE ;
368        }
369
370        /**
371         * エラーが存在した場合に、エラーメッセージを返します。
372         *
373         * @return エラーメッセージ String
374         */
375        public String getErrMsg() {
376                return errMsg.toString();
377        }
378}