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