    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.plugin.report;
    017
    018import java.io.BufferedWriter;
    019import java.io.File;
    020import java.io.FileNotFoundException;
    021import java.io.FileOutputStream;
    022import java.io.OutputStreamWriter;
    023import java.io.UnsupportedEncodingException;
    024import org.opengion.hayabusa.common.HybsSystemException;
    025import org.opengion.hayabusa.common.HybsSystem;
    026import org.opengion.hayabusa.report.AbstractCSVPrintPointService;
    027import org.opengion.fukurou.util.StringUtil;
    028
    029/**
    030 * ユニリタ「Report & Form Warehouse」に対応したCSV形式でデータを作成します。
    031 *
    032 * CSVはシステムリソースRFW_CSV_OUTPUTDIRで指定した場所に[LISTID]_[GRPID]_[YKNO].csvで出力されます。
    033 * 又、RFWはNASに出力する場合はJOB単位にNASサーバを指定する必要があるため、出力先ディレクトリの先頭文字が「\\」
    034 * となっていた際には「_NASサーバ名」を出力先ディレクトリとします。
    035 * 特殊な動作として、デーモングループに"BIG"の文字が入っている場合はCSV出力先ディレクトリ末尾に"_BIG"を付加します。
    036 * ２つのフォルダは予め作成しておきます。
    037 *
    038 * PDF等の最終的な出力先、つまりCSVのコントロールヘッダのRDSetOutputFileNameはGE50で指定します。
    039 * (Defaultのプラグインと出力が異なるので注意が必要です）
    040 *
    041 * データに関しては、全てダブルクウォートで囲って出力されます。
    042 * ダブルクウォートそのものは二重化でエスケープします。
    043 * ヘッダ、フッタが存在する場合、ボディ、ヘッダ、フッタの順番に連結して出力し、カラム名はヘッダはH_、フッタはF_を先頭に追加します。
    044 *
    045 * 区分Excelの場合にどの文字列でヘッダーを出すかはシステムリソースRFW_EXCEL_TYPEで決めます。
    046 * 指定なしの場合はXLSとなります。
    047 * 区分Excel(XLSX)の場合はXLSX固定です。
    048 *
    049 * @og.group 帳票システム
    050 *
    051 * @version  5.9.0.0
    052 * @author       Masakazu Takahashi
    053 * @since    JDK6.0,
    054 */
    055public class CSVPrintPointService_RFW extends AbstractCSVPrintPointService {
    056
    057        private static final String CR          = System.getProperty("line.separator");
    058        private final StringBuilder strCSV      = new StringBuilder();  // CSVはこれに吐く
    059
    060        private static final String     csvEncode       = HybsSystem.sys("REPORT_CSV_TEXT_ENCODE");
    061
    062        private static final String RFW_CSV_OUTPUTDIR = HybsSystem.sys("RFW_CSV_OUTPUTDIR");
    063
    064        private static final String RFW_EXCEL_TYPE = StringUtil.nval( HybsSystem.sys("RFW_EXCEL_TYPE"), "XLS" ) ;
    065
    066        /**
    067         * 発行処理
    068         * ファイル出力
    069         *
    070         * @og.rev 5.9.2.2 ファイル名に標準OrderBy同様にGRPIDを付ける。デーモングループに「BIG」が入っている場合は出力先変更
    071         * @og.rev 5.9.6.2 (2016/03/11) RFWのNAS対応
    072         *
    073         * @return 結果 [true:正常/false:異常]
    074         */
    075        @Override
    076        public boolean execute(){
    077                System.out.print( "CSV create ... " );
    078                BufferedWriter bw = null;
    079                boolean flg = false;
    080
    081                try {
    082                        // 5.9.6.2 (2016/03/11) RFWのNAS出力対応に伴う修正
    083                        // outdirが\\から開始される場合に、次の\もしくは/までの文字列を出力フォルダに付け足す
    084                        // 5.9.6.3 (2016/03/18) かつ、outdirからはサーバ名は削除する
    085                        String nasName = "";
    086                        if( outdir != null && outdir.startsWith( "\\\\" ) ){
    087                                int spl = outdir.indexOf( "\\", 2 );
    088                                int spl2 = outdir.indexOf( "/", 2 );
    089                                spl = spl<0 ? outdir.length() : spl;
    090                                spl2 = spl2<0 ? outdir.length() : spl2;
    091                                spl = spl < spl2 ? spl : spl2;
    092                                nasName = "_" + outdir.substring( 2, spl );
    093                                outdir = outdir.substring(spl+1); // 5.9.6.3
    094                        }
    095
    096                        makeheader();
    097                        makebody();
    098
    099
    100//                      bw = getWriter( RFW_CSV_OUTPUTDIR + File.separator + listid + "_" + ykno + ".csv" ,false,csvEncode);
    101
    102                        // 汎用化も考えたが、予期せぬ出力があると困るのでBIG決め打ち。フォルダ存在しない場合はエラー
    103                        if( dmngrp != null && dmngrp.indexOf( "BIG" ) >= 0 ){ // 5.9.2.2
    104//                              bw = getWriter( RFW_CSV_OUTPUTDIR + "_BIG" + File.separator + listid + "_" + grpid + "_" + ykno + ".csv" ,false,csvEncode);
    105                                bw = getWriter( RFW_CSV_OUTPUTDIR + nasName +  "_BIG" + File.separator + listid + "_" + grpid + "_" + ykno + ".csv" ,false,csvEncode); // 5.9.6.2
    106                        }
    107                        else{
    108//                              bw = getWriter( RFW_CSV_OUTPUTDIR + File.separator + listid + "_" + grpid + "_" + ykno + ".csv" ,false,csvEncode);
    109//                              bw = getWriter( RFW_CSV_OUTPUTDIR + File.separator + listid + "_" + grpid + "_" + ykno + ".csv" ,false,csvEncode);
    110                                bw = getWriter( RFW_CSV_OUTPUTDIR + nasName + File.separator + listid + "_" + grpid + "_" + ykno + ".csv" ,false,csvEncode); // 5.9.6.2
    111                        }
    112                        bw.write( strCSV.toString() );
    113                        bw.flush();
    114                        bw.close();
    115
    116                        flg = true;
    117
    118//                      if( prgfile != null && prgfile.length() > 0){
    119//                              makeShellCommand();
    120//                              flg = programRun();
    121//                      }
    122
    123                }
    124                catch ( Throwable ex ) {
    125                        errMsg.append( "CSV Print Request Execution Error. " ).append( CR );
    126                        errMsg.append( "==============================" ).append( CR );
    127                        errMsg.append( "SYSTEM_ID=[" ).append( systemId ).append( "] , " );
    128                        errMsg.append( "YKNO=["    ).append( ykno    ).append( "] , " );
    129                        errMsg.append( ex.toString() );
    130                        errMsg.append( CR );
    131//                      throw new RuntimeException( errMsg.toString() );
    132                        throw new RuntimeException( errMsg.toString(), ex );
    133                }
    134                return flg;
    135        }
    136
    137        /**
    138         * ヘッダの出力
    139         *
    140         * @og.rev 5.9.1.2 (2015/10/23) RDSetOutputPrinterの値をIDに変更
    141         * @og.rev 5.9.3.0 (2015/12/04) option追加
    142         * @og.rev 5.9.3.2 (2015/12/21) XLSX対応
    143         * @og.rev 5.9.4.2 (2016/01/13) XLSXは区分に持たせるようにする
    144         * @og.rev 5.9.6.0 (2016/03/01) 拡張子対応
    145         */
    146        private void makeheader(){
    147                //ヘッダデータを出力する場合はここで指定する。
    148                strCSV.append( "<rdstart>" ).append( CR );
    149
    150                strCSV.append( "RDSetForm=\"" ).append(modelname).append("\"").append( CR );
    151
    152                //5.9.3.1 (2015/12/16)
    153                strCSV.append( "RDSetUserName=\"" ).append(systemId).append("\"").append( CR );
    154                strCSV.append( "RDSetComputer=\"" ).append( listid + "_" + grpid + "_" + ykno ).append("\"").append( CR );
    155                strCSV.append( "RDSetDocName=\"" ).append(listid).append("\"").append( CR );
    156
    157                String suffix = ""; // 5.9.6.0
    158
    159                // 5.9.6.0 拡張子を自動で付ける対応を入れておく
    160                // PDFの場合
    161                if( FGRUN_PDF.equals( fgrun ) ){
    162                        if( outdir != null && outdir.indexOf(".") < 0 ){
    163                                suffix = ".pdf";
    164                        }
    165
    166                        strCSV.append( "RDSetOutputMode=PDF" ).append( CR );
    167//                      strCSV.append( "RDSetOutputFileName=\"" ).append( outdir ).append("\"").append( CR );
    168                        strCSV.append( "RDSetOutputFileName=\"" ).append( outdir ).append( suffix ).append("\"").append( CR );
    169                }
    170                // Excel(XLS)
    171                else if( FGRUN_EXCEL.equals(fgrun) ){
    172                        if( outdir != null && outdir.indexOf(".") < 0 ){
    173                                suffix = ".xls";
    174                        }
    175//                      strCSV.append( "RDSetOutputMode=XLS" ).append( CR );
    176//                      if( option != null && option.indexOf("RDSetOutputMode") < 0 ){
    177                                strCSV.append( "RDSetOutputMode=" + RFW_EXCEL_TYPE ).append( CR );
    178//                      }
    179//                      strCSV.append( "RDSetOutputFileName=\"" ).append( outdir ).append("\"").append( CR );
    180                        strCSV.append( "RDSetOutputFileName=\"" ).append( outdir ).append( suffix ).append("\"").append( CR );
    181                }
    182                // Excel(XLSX) 5.9.4.2 (2016/01/13)
    183                else if( FGRUN_EXCEL2.equals(fgrun) ){
    184                        if( outdir != null && outdir.indexOf(".") < 0 ){
    185                                suffix = ".xlsx";
    186                        }
    187                        strCSV.append( "RDSetOutputMode=XLSX" ).append( CR );
    188//                      strCSV.append( "RDSetOutputFileName=\"" ).append( outdir ).append("\"").append( CR );
    189                        strCSV.append( "RDSetOutputFileName=\"" ).append( outdir ).append( suffix ).append("\"").append( CR );
    190                }
    191                // 印刷
    192                else{
    193                        strCSV.append( "RDSetOutputMode=SPOOL" ).append( CR );
    194                        //strCSV.append( "RDSetOutputPrinter=\"" ).append(prtName).append( "\"" ).append( CR );
    195                        // プリンタ名ではなく、プリンタIDを出力するように変更
    196                        strCSV.append( "RDSetOutputPrinter=\"" ).append(prtid).append( "\"" ).append( CR );
    197                }
    198
    199                if( option != null && option.length() > 0 ){
    200                        strCSV.append( option ).append( CR ); // 5.9.3.0 (2015/12/04)
    201                }
    202
    203                strCSV.append( "<rdend>" ).append( CR );
    204
    205                //１行目にカラム名を出力します。クウォートで囲わない。
    206                // メインテーブルはNULLではない
    207                for( int clmNo=0; clmNo<table.getColumnCount(); clmNo++ ) {
    208                        // 先頭以外はカンマを付ける
    209                        if( clmNo > 0 ){ strCSV.append( "," ); }
    210                        strCSV.append( table.getColumnName( clmNo ));
    211                }
    212                if( tableH != null){
    213                        for( int clmNo=0; clmNo<tableH.getColumnCount(); clmNo++ ) {
    214                                strCSV.append( "," );
    215                                strCSV.append("H_").append( tableH.getColumnName( clmNo ));
    216                        }
    217                }
    218                if( tableF != null){
    219                        for( int clmNo=0; clmNo<tableF.getColumnCount(); clmNo++ ) {
    220                                strCSV.append( "," );
    221                                strCSV.append("F_").append( tableF.getColumnName( clmNo ));
    222                        }
    223                }
    224                strCSV.append( CR );
    225        }
    226
    227
    228
    229        /**
    230         * 本体の出力を行います
    231         * HTMLエスケープされている場合は戻します
    232         */
    233        private void makebody(){
    234
    235                for( int rowNo=0; rowNo<table.getRowCount(); rowNo++ ) {
    236                        // カラム単位の処理
    237                        for( int clmNo=0; clmNo<table.getColumnCount(); clmNo++ ) {
    238                                // 先頭以外はカンマを付ける
    239                                if( clmNo > 0 ){ strCSV.append( "," ); }
    240                                // 全てダブルクウォートで囲う
    241                                strCSV.append("\"").append( StringUtil.replace( StringUtil.getReplaceEscape( table.getValue( rowNo, clmNo )) ,"\"","\"\"" ) ).append("\"");
    242                        }
    243
    244                        //ヘッダ、フッタは毎行に必ず付加します。
    245                        //例え複数行あったとしても先頭行のみ有効です
    246                        //ヘッダ
    247                        if( tableH != null){
    248                                int rowNoH=0;
    249                                for( int clmNo=0; clmNo<tableH.getColumnCount(); clmNo++ ) {
    250                                        // 必ずカンマを付ける
    251                                        strCSV.append( "," );
    252                                        // 全てダブルクウォートで囲う
    253                                        strCSV.append("\"").append( StringUtil.replace( StringUtil.getReplaceEscape( tableH.getValue( rowNoH, clmNo )) ,"\"","\"\"" ) ).append("\"");
    254                                }
    255                        }
    256
    257                        //フッタ
    258                        if( tableF != null ){
    259                                int rowNoF=0;
    260                                for( int clmNo=0; clmNo<tableF.getColumnCount(); clmNo++ ) {
    261                                        // 必ずカンマを付ける
    262                                        strCSV.append( "," );
    263                                        // 全てダブルクウォートで囲う
    264                                        strCSV.append("\"").append( StringUtil.replace( StringUtil.getReplaceEscape( tableF.getValue( rowNoF, clmNo )) ,"\"","\"\"" ) ).append("\"");
    265                                }
    266                        }
    267
    268                        strCSV.append( CR );
    269                }
    270        }
    271
    272
    273        /**
    274         * ファイル書き込み用のライターを返します。
    275         *
    276         * @param fileName ファイル名
    277         * @param append アベンドするか
    278         * @param encode エンコード
    279         *
    280         * @return ライター
    281         */
    282        private BufferedWriter getWriter( final String fileName, final boolean append, final String encode) {
    283                File file = new File ( fileName );
    284                BufferedWriter bw;
    285
    286                try {
    287                        bw = new BufferedWriter( new OutputStreamWriter( new FileOutputStream( file, append ), encode ) );
    288                }
    289                catch ( UnsupportedEncodingException ex ) {
    290                        errMsg.append( "[ERROR] Input File is written by Unsupported Encoding" );
    291                        throw new HybsSystemException( ex );
    292                }
    293                catch ( FileNotFoundException ex ) {
    294                        errMsg.append( "[ERROR] File not Found" );
    295                        throw new HybsSystemException( ex );
    296                }
    297                return bw;
    298        }
    299
    300}