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 * 2つのフォルダは予め作成しておきます。 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 //1行目にカラム名を出力します。クウォートで囲わない。 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}