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 */ 016 package org.opengion.fukurou.process; 017 018 import org.opengion.fukurou.util.Argument; 019 import org.opengion.fukurou.util.HybsEntry ; 020 import org.opengion.fukurou.util.FileUtil; 021 import org.opengion.fukurou.util.Closer ; 022 import org.opengion.fukurou.util.LogWriter; 023 024 import java.util.Map ; 025 import java.util.LinkedHashMap ; 026 027 import java.io.File; 028 import java.io.PrintWriter; 029 030 /** 031 * Process_TableWriter は、上流から受け取ったデータをファイルに書き込? 032 * CainProcess インターフェースの実?ラスです? 033 * 034 * 上?プロセスチェインの??タは上流から下流へと渡されます?)から 035 * 受け取ったLineModel を?に、DBTableModel 形式ファイルを?力します? 036 * 037 * 引数??中にスペ?スを含??合?、ダブルコー??ション("") で括って下さ?? 038 * 引数??の ?』?前後には、スペ?スは挟めません。??key=value の様に 039 * 繋げてください? 040 * 041 * @og.formSample 042 * Process_TableWriter -outfile=OUTFILE -sep=, -encode=UTF-8 -append=true 043 * 044 * -outfile=出力ファ??名 ??力ファ??名 045 * [-sep=??゚レー??? ] ?区???初期値:タ? 046 * [-encode=?エ?コ???? ] ??力ファ?????コ?????? 047 * [-append=false|true ] ??力ファ??を、追記す?true)か新規作?する(false)か? 048 * [-useHeader=true|false ] ?ヘッ??ー??(#NAME?を?力す?true)か?力しな?false)か? 049 * [-useNumber=true|false ] ?行番号を?力す?true)か?力しな?false)か? 050 * [-useWquot=false|true ] ??力?ー????ブルク???????で括?true)かそのまま(false)か? 051 * [-omitCTRL=false|true ] ?コ??ー?文字を削除する(true)かそのまま(false)か? 052 * [-const_XXXX=固定? ] ??const_FGJ=1 053 * LineModel のキー(const_ に続く??)の値に、固定?を設定します? 054 * キーが異なれ?、?のカラ?を指定できます? 055 * [-display=false|true ] ?結果を標準?力に表示する(true)かしな?false)?初期値:false[表示しない]) 056 * [-debug=false|true ] ?デバッグ??を標準?力に表示する(true)かしな?false)?初期値:false[表示しない]) 057 * 058 *</pre> 059 * @version 4.0 060 * @author Kazuhiko Hasegawa 061 * @since JDK5.0, 062 */ 063 public class Process_TableWriter extends AbstractProcess implements ChainProcess { 064 private static final String CNST_KEY = "const_" ; 065 066 private String outfile = null; 067 private PrintWriter writer = null; 068 private String separator = TAB; // ?区??? 069 070 private String[] cnstClm = null; // 固定?を設定するカラ? 071 private int[] cnstClmNos = null; // 固定?を設定する?カラ?号 072 private String[] constVal = null; // カラ?号に対応した固定? 073 private File file = null; // 出力ファイル 074 private String encode = System.getProperty("file.encoding"); // 出力ファイルエンコー? 075 private boolean append = false; // ファイル追?true:追?false:通常) 076 private boolean useHeader = true; // ヘッ????(#NAME?を?力す?true)か?力しな?false)か? 077 private boolean useNumber = true; // 行番号を?力す?true)か?力しな?false)か? 078 private boolean useWquot = false; // 出力データをダブルクオー??ションで括?true)かそのまま(false)か? 079 private boolean omitCTRL = false; // コントロール?を削除する(true)かそのまま(false)か? 080 private boolean display = false; // 表示しな? 081 private boolean debug = false; // 5.7.3.0 (2014/02/07) ???? 082 083 private boolean firstRow = true; // ??の?目 084 private int count = 0; 085 086 private static final Map<String,String> mustProparty ; // ?プロパティ???チェ?用 Map 087 private static final Map<String,String> usableProparty ; // ?プロパティ?整合?チェ? Map 088 089 static { 090 mustProparty = new LinkedHashMap<String,String>(); 091 mustProparty.put( "outfile", "出力ファ??名 (??)" ); 092 093 usableProparty = new LinkedHashMap<String,String>(); 094 usableProparty.put( "sep", "区???初期値:???" ); 095 usableProparty.put( "encode", "出力ファ?????コ?????? ); 096 usableProparty.put( "append", "出力ファ??を、追記す?true)か新規作?する(false)か?" ); 097 usableProparty.put( "useHeader", "?ッ??ー??(#NAME?を?力す?true)か?力しな?false)か?" ); 098 usableProparty.put( "useNumber", "行番号を?力す?true)か?力しな?false)か?" ); 099 usableProparty.put( "useWquot", "出力?ー????ブルク???????で括?true)かそのまま(false)か?" ); 100 usableProparty.put( "omitCTRL", "???ー?文字を削除する(true)かそのまま(false)か?" ); 101 usableProparty.put( "const_", "LineModel のキー(const_ に続く??)の値に、固定?? + 102 CR + "設定します?キーが異なれ?、?のカラ?を指定できます?" + 103 CR + "? -const_FGJ=1" ); 104 usableProparty.put( "display", "結果を標準?力に表示する(true)かしな?false)? + 105 CR + " (初期値:false:表示しな?" ); 106 usableProparty.put( "debug", "????を標準?力に表示する(true)かしな?false)? + 107 CR + "(初期値:false:表示しな?" ); // 5.7.3.0 (2014/02/07) ???? 108 } 109 110 /** 111 * ?ォルトコンストラクター? 112 * こ?クラスは、動??されます??ォルトコンストラクターで? 113 * super クラスに対して、?な初期化を行っておきます? 114 * 115 */ 116 public Process_TableWriter() { 117 super( "org.opengion.fukurou.process.Process_TableWriter",mustProparty,usableProparty ); 118 } 119 120 /** 121 * プロセスの初期化を行います?初めに??、呼び出されます? 122 * 初期処?ファイルオープン??オープン?に使用します? 123 * 124 * @param paramProcess ??タベ?スの接続???などを持って?オブジェク? 125 */ 126 public void init( final ParamProcess paramProcess ) { 127 Argument arg = getArgument(); 128 129 outfile = arg.getProparty("outfile"); 130 encode = arg.getProparty("encode",encode); 131 separator = arg.getProparty("sep",separator ); 132 append = arg.getProparty("append",append); 133 useHeader = arg.getProparty("useHeader",useHeader); 134 useNumber = arg.getProparty("useNumber",useNumber); 135 useWquot = arg.getProparty("useWquot",useWquot); 136 omitCTRL = arg.getProparty("omitCTRL",omitCTRL); 137 HybsEntry[] cnstKey = arg.getEntrys( CNST_KEY ); // 配? 138 display = arg.getProparty("display",display); 139 debug = arg.getProparty("debug",debug); // 5.7.3.0 (2014/02/07) ???? 140 // if( debug ) { println( arg.toString() ); } // 5.7.3.0 (2014/02/07) ???? 141 142 int size = cnstKey.length; 143 cnstClm = new String[size]; 144 constVal = new String[size]; 145 for( int i=0; i<size; i++ ) { 146 cnstClm[i] = cnstKey[i].getKey(); 147 constVal[i] = cnstKey[i].getValue(); 148 } 149 150 if( outfile == null ) { 151 String errMsg = "ファイル名が?されて?せん? ; 152 throw new RuntimeException( errMsg ); 153 } 154 155 file = new File( outfile ); 156 File dir = file.getParentFile() ; 157 158 // ?レクトリが存在しな??合?処? 159 if( ! dir.exists() && ! dir.mkdirs() ) { 160 String errMsg = "?レクトリが作?できませんでした?" + dir + "]" ; 161 throw new RuntimeException( errMsg ); 162 } 163 } 164 165 /** 166 * プロセスの終?行います??に??、呼び出されます? 167 * 終???ファイルクローズ??クローズ?に使用します? 168 * 169 * @param isOK ト?タルで、OK?たかど?[true:成功/false:失敗] 170 */ 171 public void end( final boolean isOK ) { 172 if( writer != null ) { 173 writer.flush(); 174 Closer.ioClose( writer ); 175 writer = null; 176 } 177 } 178 179 /** 180 * 引数の LineModel を??るメソ?です? 181 * 変換処?? LineModel を返します? 182 * 後続??行わな?????タのフィルタリングを行う場?は? 183 * null ??タを返します?つまり?null ??タは、後続??行わな? 184 * フラグの代わりにも使用して?す? 185 * なお?変換処?? LineModel と、オリジナルの LineModel が? 186 * 同?、コピ?(クローン)か?、各処?ソ??決めて?す? 187 * ドキュメントに明記されて???合?、副作用が問題になる?合?? 188 * ???とに自?コピ?(クローン)して下さ?? 189 * 190 * @param data オリジナルのLineModel 191 * 192 * @return 処?換後?LineModel 193 */ 194 public LineModel action( final LineModel data ) { 195 count++ ; 196 // if( display ) { println( data.dataLine() ); } 197 if( firstRow ) { 198 writer = FileUtil.getPrintWriter( file,encode,append ); 199 if( useHeader && useNumber ) { writeName( data ); } 200 201 int size = cnstClm.length; 202 cnstClmNos = new int[size]; 203 for( int i=0; i<size; i++ ) { 204 cnstClmNos[i] = data.getColumnNo( cnstClm[i] ); 205 } 206 207 firstRow = false; 208 if( display ) { println( data.nameLine() ); } // 5.7.3.0 (2014/02/07) ???? 209 } 210 211 // 固定?置き換え?? 212 for( int j=0; j<cnstClmNos.length; j++ ) { 213 data.setValue( cnstClmNos[j],constVal[j] ); 214 } 215 216 writeData( data ); 217 218 if( display ) { println( data.dataLine() ); } // 5.1.2.0 (2010/01/01) display の条件変更 219 return data; 220 } 221 222 /** 223 * PrintWriter に LineModelの?名情報を書き込みます? 224 * 第?ラ?は??目名情報を示?"#Name" を書き込みます? 225 * こ?行?、?力形式に無関係に、TAB で区?れます? 226 * 227 * @param data ラインモ? 228 */ 229 private void writeName( final LineModel data ) { 230 int size = data.size(); 231 writer.print( "#Name" ); 232 for( int clm=0; clm<size; clm++ ) { 233 writer.print( TAB ); 234 writer.print( data.getName(clm) ); 235 } 236 writer.println(); 237 } 238 239 /** 240 * PrintWriter に LineModelの??ブル??を書き込みます? 241 * 242 * @og.rev 5.2.2.0 (2010/11/01) 改行を含??合?、ダブルクオートを強制?前後に追?る? 243 * @og.rev 5.2.2.0 (2010/11/01) ?ルクオートを含??合?、その直前に?ルクオートを強制?追?る? 244 * 245 * @param data ラインモ? 246 */ 247 private void writeData( final LineModel data ) { 248 int size = data.size(); 249 250 if( useNumber ) { writer.print( data.getRowNo() ); } // 行番号 251 for( int clm=0; clm<size; clm++ ) { 252 if( useNumber || clm!=0 ) { writer.print( separator ); } 253 Object val = data.getValue(clm); 254 if( val == null ) { val = ""; } 255 256 String sval = String.valueOf( val ); 257 // 5.2.2.0 (2010/11/01) ?ルクオートを含??合?、その直前に?ルクオートを強制?追?る? 258 if( sval.indexOf( '"' ) >= 0 ) { sval = sval.replaceAll( "\"" ,"\"\"" ) ; } 259 if( omitCTRL ) { sval = sval.replaceAll( "\\s" ," " ) ; } 260 // if( useWquot ) { sval = "\"" + sval + "\"" ; } 261 // 5.2.2.0 (2010/11/01) 改行を含??合?、ダブルクオートを強制?前後に追?る? 262 if( useWquot || ( !omitCTRL && sval.indexOf( CR ) >= 0 ) ) { 263 sval = "\"" + sval + "\"" ; 264 } 265 writer.print( sval ); 266 } 267 writer.println(); 268 } 269 270 /** 271 * プロセスの処?果のレポ?ト表現を返します? 272 * 処??ログラ?、?力件数、?力件数などの??です? 273 * こ???をそのまま、標準?力に出すことで、結果レポ?トと出来るよ? 274 * 形式で出してください? 275 * 276 * @return 処?果のレポ?? 277 */ 278 public String report() { 279 String report = "[" + getClass().getName() + "]" + CR 280 + TAB + "Output File : " + outfile + CR 281 + TAB + "Output Count : " + count ; 282 283 return report ; 284 } 285 286 /** 287 * こ?クラスの使用方法を返します? 288 * 289 * @return こ?クラスの使用方? 290 */ 291 public String usage() { 292 StringBuilder buf = new StringBuilder(); 293 294 buf.append( "Process_TableWriter は、上流から受け取ったデータをファイルに書き込? ).append( CR ); 295 buf.append( "CainProcess インターフェースの実?ラスです?" ).append( CR ); 296 buf.append( CR ); 297 buf.append( "上?プロセスチェインの??タは上流から下流へと渡されます?)から" ).append( CR ); 298 buf.append( "受け取ったLineModel を?に、DBTableModel 形式ファイルを?力します?" ).append( CR ); 299 buf.append( CR ); 300 buf.append( "引数??中に空白を含??合?、ダブルコー??ション(\"\") で括って下さ??" ).append( CR ); 301 buf.append( "引数??の ?』?前後には、空白は挟めません。??key=value の様に" ).append( CR ); 302 buf.append( "繋げてください? ).append( CR ); 303 buf.append( CR ).append( CR ); 304 305 buf.append( getArgument().usage() ).append( CR ); 306 307 return buf.toString(); 308 } 309 310 /** 311 * こ?クラスは、main メソ?から実行できません? 312 * 313 * @param args コマンド引数配? 314 */ 315 public static void main( final String[] args ) { 316 LogWriter.log( new Process_TableWriter().usage() ); 317 } 318 }