    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;
    028import static org.opengion.fukurou.system.HybsConst.BUFFER_MIDDLE ;
    029
    030/**
    031 * ユニリタ「Report ＆ Form Warehouse」に対応したCSV形式でデータを作成します。
    032 *
    033 * CSVPrintPointService_RFWとの違いは出力ファイル名のみです。
    034 * CSVはシステムリソースRFW_CSV_OUTPUTDIRで指定した場所に[GRPID]_[YKNO]_[LISTID].csvで出力されます。
    035 *
    036 * @og.group 帳票システム
    037 *
    038 * @og.rev 5.9.27.1 (2017/12/08) 新規作成
    039 *
    040 * @version  5.9.0.0
    041 * @author       Masakazu Takahashi
    042 * @since    JDK6.0,
    043 */
    044public class CSVPrintPointService_RFW2 extends AbstractCSVPrintPointService {
    045
    046        private static final String CR          = System.getProperty("line.separator");
    047        private final StringBuilder strCSV      = new StringBuilder( BUFFER_MIDDLE );   // CSVはこれに吐く
    048
    049        // 6.8.5.0 (2018/01/09) PMD Variables that are final and static should be all capitals。csvEncode → CSV_ENCODE
    050        private static final String     CSV_ENCODE      = HybsSystem.sys("REPORT_CSV_TEXT_ENCODE");
    051
    052        private static final String RFW_CSV_OUTPUTDIR = HybsSystem.sys("RFW_CSV_OUTPUTDIR");
    053
    054        private static final String RFW_EXCEL_TYPE = StringUtil.nval( HybsSystem.sys("RFW_EXCEL_TYPE"), "XLS" ) ;
    055
    056        /**
    057         * デフォルトコンストラクター
    058         *
    059         * @og.rev 6.9.7.0 (2018/05/14) PMD Each class should declare at least one constructor
    060         */
    061        public CSVPrintPointService_RFW2() { super(); }         // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。
    062
    063        /**
    064         * 発行処理。
    065         *
    066         * ファイル出力
    067         *
    068         * @og.rev 6.8.5.0 (2018/01/09) PMD Variables that are final and static should be all capitals。csvEncode → CSV_ENCODE
    069         *
    070         * @return 結果 [true:正常/false:異常]
    071         */
    072        @Override
    073        public boolean execute(){
    074                System.out.print( "CSV create ... " );
    075                BufferedWriter bw = null;
    076                boolean flg = false;
    077
    078                try {
    079                        // outdirが\\から開始される場合に、次の\もしくは/までの文字列を出力フォルダに付け足す
    080                        // かつ、outdirからはサーバ名は削除する
    081                        String nasName = "";
    082                        if( outdir != null && outdir.startsWith( "\\\\" ) ){
    083                                int spl  = outdir.indexOf( "\\", 2 );
    084                                int spl2 = outdir.indexOf( "/", 2 );
    085                                spl  = spl<0 ? outdir.length() : spl;
    086                                spl2 = spl2<0 ? outdir.length() : spl2;
    087                                spl  = spl < spl2 ? spl : spl2;
    088                                nasName = "_" + outdir.substring( 2, spl );
    089                                outdir  = outdir.substring(spl+1);
    090                        }
    091
    092                        makeheader();
    093                        makebody();
    094
    095                        // 汎用化も考えたが、予期せぬ出力があると困るのでBIG決め打ち。フォルダ存在しない場合はエラー
    096                        final String fnm = File.separator + grpid + "_" + ykno + "_" + listid + ".csv";         // 6.8.5.0 (2018/01/09)
    097                        if( dmngrp != null && dmngrp.indexOf( "BIG" ) >= 0 ){
    098                                bw = getWriter( RFW_CSV_OUTPUTDIR + nasName +  "_BIG" + fnm ,false,CSV_ENCODE);
    099                        }
    100                        else{
    101                                bw = getWriter( RFW_CSV_OUTPUTDIR + nasName + fnm ,false,CSV_ENCODE);
    102                        }
    103                        bw.write( strCSV.toString() );
    104                        bw.flush();
    105                        bw.close();
    106
    107                        flg = true;
    108
    109                        // 先頭が*のデーモングループの場合は約7秒スリープさせる=このスレッドでの連続処理をわざと遅延させる
    110                        // 特殊対応なので決め打ち
    111                        if( dmngrp != null && dmngrp.indexOf( "*" ) == 0 ){
    112                                Thread.sleep(7000);
    113                        }
    114                }
    115                catch ( Throwable ex ) {
    116                        errMsg.append( "CSV Print Request Execution Error. " ).append( CR );
    117                        errMsg.append( "==============================" ).append( CR );
    118                        errMsg.append( "SYSTEM_ID=[" ).append( systemId ).append( "] , " );
    119                        errMsg.append( "YKNO=["    ).append( ykno    ).append( "] , " );
    120                        errMsg.append( ex.toString() );
    121                        errMsg.append( CR );
    122                        throw new RuntimeException( errMsg.toString(), ex );
    123                }
    124                return flg;
    125        }
    126
    127        /**
    128         * ヘッダの出力。
    129         *
    130         */
    131        private void makeheader(){
    132                //ヘッダデータを出力する場合はここで指定する。
    133                strCSV.append( "<rdstart>" ).append( CR )
    134                        .append( "RDSetForm=\""         ).append( modelname ).append( '"' ).append( CR )
    135                        .append( "RDSetUserName=\"" ).append( systemId  ).append( '"' ).append( CR )            //5.9.3.1 (2015/12/16)
    136                        .append( "RDSetComputer=\"" ).append( listid ).append( '_' ).append( grpid ).append( '_' ).append( ykno ).append( '"' ).append( CR )
    137                        .append( "RDSetDocName=\""      ).append( listid ).append( '"' ).append( CR );
    138
    139                String suffix = ""; // 5.9.6.0
    140
    141                // 5.9.6.0 拡張子を自動で付ける対応を入れておく
    142                // PDFの場合
    143                if( FGRUN_PDF.equals( fgrun ) ){
    144                        if( outdir != null && outdir.indexOf( '.' ) < 0 ){
    145                                suffix = ".pdf";
    146                        }
    147
    148                        strCSV.append( "RDSetOutputMode=PDF" ).append( CR )
    149                                .append( "RDSetOutputFileName=\"" ).append( outdir ).append( suffix ).append( '"' ).append( CR );
    150                }
    151                // Excel(XLS)
    152                else if( FGRUN_EXCEL.equals(fgrun) ){
    153                        if( outdir != null && outdir.indexOf( '.' ) < 0 ){
    154                                suffix = ".xls";
    155                        }
    156                        strCSV.append( "RDSetOutputMode=" + RFW_EXCEL_TYPE ).append( CR )
    157                                .append( "RDSetOutputFileName=\"" ).append( outdir ).append( suffix ).append( '"' ).append( CR );
    158                }
    159                else if( FGRUN_EXCEL2.equals(fgrun) ){
    160                        if( outdir != null && outdir.indexOf( '.' ) < 0 ){
    161                                suffix = ".xlsx";
    162                        }
    163                        strCSV.append( "RDSetOutputMode=XLSX" ).append( CR )
    164                                .append( "RDSetOutputFileName=\"" ).append( outdir ).append( suffix ).append( '"' ).append( CR );
    165                }
    166                // 印刷
    167                else{
    168                        strCSV.append( "RDSetOutputMode=SPOOL" ).append( CR )
    169                                .append( "RDSetOutputPrinter=\"" ).append(prtid).append(  '"'  ).append( CR );
    170                }
    171
    172                if( option != null && option.length() > 0 ){
    173                        strCSV.append( option ).append( CR ); // 5.9.3.0 (2015/12/04)
    174                }
    175
    176                strCSV.append( "<rdend>" ).append( CR );
    177
    178                //１行目にカラム名を出力します。クウォートで囲わない。
    179                // メインテーブルはNULLではない
    180                for( int clmNo=0; clmNo<table.getColumnCount(); clmNo++ ) {
    181                        // 先頭以外はカンマを付ける
    182                        if( clmNo > 0 ){ strCSV.append( ',' ); }
    183                        strCSV.append( table.getColumnName( clmNo ));
    184                }
    185                if( tableH != null){
    186                        for( int clmNo=0; clmNo<tableH.getColumnCount(); clmNo++ ) {
    187                                strCSV.append( ",H_" ).append( tableH.getColumnName( clmNo ) );
    188                        }
    189                }
    190                if( tableF != null){
    191                        for( int clmNo=0; clmNo<tableF.getColumnCount(); clmNo++ ) {
    192                                strCSV.append( ",F_" ).append( tableF.getColumnName( clmNo ) );
    193                        }
    194                }
    195                strCSV.append( CR );
    196        }
    197
    198        /**
    199         * 本体の出力を行います。
    200         * HTMLエスケープされている場合は戻します
    201         */
    202        private void makebody(){
    203
    204                for( int rowNo=0; rowNo<table.getRowCount(); rowNo++ ) {
    205                        // カラム単位の処理
    206                        for( int clmNo=0; clmNo<table.getColumnCount(); clmNo++ ) {
    207                                // 先頭以外はカンマを付ける
    208                                if( clmNo > 0 ){ strCSV.append( ',' ); }                                                // 6.9.7.0 (2018/05/14) PMD Avoid appending characters as strings in StringBuffer.append.
    209                                // 原則全てダブルクウォートで囲う
    210                                // 5.9.8.2 (2016/05/16) 但し、先頭カラムが制御コードである//EOR//の場合のみ囲わない
    211                                if( clmNo == 0 && "//EOR//".equals( table.getValue( rowNo, clmNo )) ){
    212                                        strCSV.append( table.getValue( rowNo, clmNo ) );
    213                                }
    214                                else{
    215                                        strCSV.append( '"' )
    216                                                .append( StringUtil.replace( StringUtil.getReplaceEscape( table.getValue( rowNo, clmNo )) ,"\"","\"\"" ) )
    217                                                .append( '"' );
    218                                }
    219                        }
    220
    221                        //ヘッダ、フッタは毎行に必ず付加します。
    222                        //例え複数行あったとしても先頭行のみ有効です
    223                        //ヘッダ
    224                        if( tableH != null){
    225                                final int rowNoH=0;                     // 先頭行のみ有効
    226                                for( int clmNo=0; clmNo<tableH.getColumnCount(); clmNo++ ) {
    227                                        // 必ずカンマを付ける
    228                                        strCSV.append( ",\"" )          // 全てダブルクウォートで囲う
    229                                                .append( StringUtil.replace( StringUtil.getReplaceEscape( tableH.getValue( rowNoH, clmNo )) ,"\"","\"\"" ) )
    230                                                .append( '"' );
    231                                }
    232                        }
    233
    234                        //フッタ
    235                        if( tableF != null ){
    236                                final int rowNoF=0;                     // 先頭行のみ有効
    237                                for( int clmNo=0; clmNo<tableF.getColumnCount(); clmNo++ ) {
    238                                        // 必ずカンマを付ける
    239                                        strCSV.append( ",\"" )          // 全てダブルクウォートで囲う
    240                                                .append( StringUtil.replace( StringUtil.getReplaceEscape( tableF.getValue( rowNoF, clmNo )) ,"\"","\"\"" ) )
    241                                                .append( '"' );
    242                                }
    243                        }
    244                        strCSV.append( CR );
    245                }
    246        }
    247
    248        /**
    249         * ファイル書き込み用のライターを返します。
    250         *
    251         * @param fileName ファイル名
    252         * @param append アベンドするか
    253         * @param encode エンコード
    254         *
    255         * @return ライター
    256         */
    257        private BufferedWriter getWriter( final String fileName, final boolean append, final String encode) {
    258                final File file = new File ( fileName );
    259                BufferedWriter bw;
    260
    261                try {
    262                        bw = new BufferedWriter( new OutputStreamWriter( new FileOutputStream( file, append ), encode ) );
    263                }
    264                catch ( final UnsupportedEncodingException ex ) {
    265                        errMsg.append( "[ERROR] Input File is written by Unsupported Encoding" );
    266                        throw new HybsSystemException( ex );
    267                }
    268                catch ( final FileNotFoundException ex ) {
    269                        errMsg.append( "[ERROR] File not Found" );
    270                        throw new HybsSystemException( ex );
    271                }
    272                return bw;
    273        }
    274}