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