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 }