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.LogWriter;
021 import org.opengion.fukurou.util.StringUtil; // 5.7.2.3 (2014/01/31)
022
023 import java.util.Map ;
024 import java.util.LinkedHashMap ;
025
026 /**
027 * Process_TableFilter は、上流から受け取ったデータをフィルタする?
028 * ChainProcess インターフェースの実?ラスです?
029 *
030 * 上?プロセスチェインの??タは上流から下流へと渡されます?)から
031 * 受け取ったLineModel を?に??目のフィルタリングを行います?
032 * 条件が?立した?合?、下流に流します??の条件を指定できますが?
033 * すべて AND で判定されます?
034 * (設定条件すべてを?す?合?み、下流に??タを流します?)
035 *
036 * 引数??中にスペ?スを含??合?、ダブルコー??ション("") で括って下さ??
037 * 引数??の ?』?前後には、スペ?スは挟めません。??key=value の様に
038 * 繋げてください?
039 *
040 * @og.formSample
041 * Process_TableFilter
042 *
043 * [ -prefix_XXXX=接頭? ] ??目?XXXX)が???接頭辞で始まる?合?条件成立?
044 * [ -suffix_XXXX=接尾? ] ??目?XXXX)が???接尾辞で終わる?合?条件成立?
045 * [ -instr_XXXX=部?字? ] ??目?XXXX)が???部?字?と??する場合?条件成立?
046 * [ -equals_XXXX=?? ] ??目?XXXX)が???と??する場合?条件成立???は、大?小文字?区別しません(equalsIgnoreCase)?
047 * [ -match_XXXX=正規表現 ] ??目?XXXX)が?正規表現と??する場合?条件成立?
048 * [ -unmatch_XXXX=正規表現 ] ??目?XXXX)が?正規表現と??しな??合?条件成立?
049 * [ -const_XXXX=固定? ] ??const_FGJ=1
050 * ??XXXX)に、固定?を設定します?
051 * [ -replace_XXXX=固定? ] ??replace_BIKO="YYYY⇒ZZZZ" (????、で区?ます?)
052 * ??XXXX)の??から、YYYY と??を ZZZZ に置換します?
053 * -replace_FGJ="_:0 A:1 B:2" (??:新値 の??゚ー?区?)
054 * 区??に ?を使用しな??合?、CASE処?行います?
055 * ??XXXX)の値を??? から 新値 に置換します?(完???)
056 * [ -display=[false/true] ] ?結果を標準?力に表示する(true)かしな?false)?初期値:false[表示しない])
057 * [ -debug=[false/true] ] ?デバッグ??を標準?力に表示する(true)かしな?false)?初期値:false[表示しない])
058 *
059 * @version 4.0
060 * @author Kazuhiko Hasegawa
061 * @since JDK5.0,
062 */
063 public class Process_TableFilter extends AbstractProcess implements ChainProcess {
064 /** replace_ で使用する区?記号 {@value} */
065 public static final char REP_SEP = '? ; // 4.3.1.1 (2008/08/24)
066
067 private static final String PREFIX_KEY = "prefix_" ;
068 private static final String SUFFIX_KEY = "suffix_" ;
069 private static final String INSTR_KEY = "instr_" ;
070 private static final String EQUALS_KEY = "equals_" ;
071 private static final String MATCH_KEY = "match_" ;
072 private static final String UNMATCH_KEY = "unmatch_";
073 private static final String CONST_KEY = "const_" ;
074 private static final String REPLACE_KEY = "replace_" ; // 4.3.1.1 (2008/08/24)
075
076 private final LineModelFilter filter = new LineModelFilter();
077
078 private boolean display = false; // 表示しな?
079 private boolean debug = false; // 5.7.3.0 (2014/02/07) ????
080
081 private String[] cnstClm = null; // 固定?を設定するカラ?
082 private int[] cnstClmNos = null; // 固定?を設定するカラ?号
083 private String[] constVal = null; // カラ?号に対応した固定?
084
085 // 4.3.1.1 (2008/08/24) replace 置換関係に?な??タ
086 private String[] repClm = null; // 置換を設定するカラ?
087 private int[] repClmNos = null; // 置換を設定するカラ?号
088 private String[] repValFrom = null; // カラ?号に対応した置換???
089 private String[] repValTo = null; // カラ?号に対応した置換後文字?
090
091 // 5.7.2.3 (2014/01/31) replace 置換? case処?係に?な??タ
092 private String[] caseVals = null; // カラ?号に対応した置換後文字?
093
094 private boolean firstRow = true; // ??の?目
095 private int count = 0;
096
097 private static final Map<String,String> mustProparty ; // ?プロパティ???チェ?用 Map
098 private static final Map<String,String> usableProparty ; // ?プロパティ?整合?チェ? Map
099
100 static {
101 mustProparty = new LinkedHashMap<String,String>();
102
103 usableProparty = new LinkedHashMap<String,String>();
104 usableProparty.put( PREFIX_KEY , "??XXXX)が???接頭辞で始まる?合?条件成立?" );
105 usableProparty.put( SUFFIX_KEY , "??XXXX)が???接尾辞で終わる?合?条件成立?" );
106 usableProparty.put( INSTR_KEY , "??XXXX)が???部?字?と??する場合?条件成立?" );
107 usableProparty.put( EQUALS_KEY , "??XXXX)が???と??する場合?条件成立?" +
108 CR + "(大?小文字?区別しな?" );
109 usableProparty.put( MATCH_KEY , "??XXXX)が?正規表現と??する場合?条件成立?" );
110 usableProparty.put( UNMATCH_KEY , "??XXXX)が?正規表現と??しな??合?条件成立?" );
111 usableProparty.put( CONST_KEY , "??XXXX)に、固定?を設定します?" );
112 // 4.3.1.1 (2008/08/24) replace 置換関?
113 usableProparty.put( REPLACE_KEY , "??XXXX)の??から、YYYY⇒ZZZZ で部?換します?" +
114 CR + "??XXXX)の??から、_:0 A:1 B:2でCASE置換します?" );
115 usableProparty.put( "display" , "結果を標準?力に表示する(true)かしな?false)? +
116 CR + "(初期値:false:表示しな?" );
117 usableProparty.put( "debug", "????を標準?力に表示する(true)かしな?false)? +
118 CR + "(初期値:false:表示しな?" ); // 5.7.3.0 (2014/02/07) ????
119 }
120
121 /**
122 * ?ォルトコンストラクター?
123 * こ?クラスは、動??されます??ォルトコンストラクターで?
124 * super クラスに対して、?な初期化を行っておきます?
125 *
126 */
127 public Process_TableFilter() {
128 super( "org.opengion.fukurou.process.Process_TableFilter",mustProparty,usableProparty );
129 }
130
131 /**
132 * プロセスの初期化を行います?初めに??、呼び出されます?
133 * 初期処?ファイルオープン??オープン?に使用します?
134 *
135 * @og.rev 4.3.1.1 (2008/08/24) 置換関係対?
136 * @og.rev 5.7.2.3 (2014/01/31) replace 置換? case処??
137 *
138 * @param paramProcess ??タベ?スの接続???などを持って?オブジェク?
139 */
140 public void init( final ParamProcess paramProcess ) {
141 Argument arg = getArgument();
142
143 display = arg.getProparty( "display",display );
144 debug = arg.getProparty("debug",debug); // 5.7.3.0 (2014/02/07) ????
145 // if( debug ) { println( arg.toString() ); } // 5.7.3.0 (2014/02/07) ????
146
147 HybsEntry[] entry = arg.getEntrys( PREFIX_KEY );
148 for( int i=0; i<entry.length; i++ ) {
149 filter.add( FilterOperation.PREFIX, entry[i].getKey(), entry[i].getValue() );
150 }
151
152 entry = arg.getEntrys( SUFFIX_KEY );
153 for( int i=0; i<entry.length; i++ ) {
154 filter.add( FilterOperation.SUFFIX, entry[i].getKey(), entry[i].getValue() );
155 }
156
157 entry = arg.getEntrys( INSTR_KEY );
158 for( int i=0; i<entry.length; i++ ) {
159 filter.add( FilterOperation.INSTR, entry[i].getKey(), entry[i].getValue() );
160 }
161
162 entry = arg.getEntrys( EQUALS_KEY );
163 for( int i=0; i<entry.length; i++ ) {
164 filter.add( FilterOperation.EQUALS, entry[i].getKey(), entry[i].getValue() );
165 }
166
167 entry = arg.getEntrys( MATCH_KEY );
168 for( int i=0; i<entry.length; i++ ) {
169 filter.add( FilterOperation.MATCH, entry[i].getKey(), entry[i].getValue() );
170 }
171
172 entry = arg.getEntrys( UNMATCH_KEY );
173 for( int i=0; i<entry.length; i++ ) {
174 filter.add( FilterOperation.UNMATCH, entry[i].getKey(), entry[i].getValue() );
175 }
176
177 HybsEntry[] cnstKey = arg.getEntrys( CONST_KEY );
178 int csize = cnstKey.length;
179 cnstClm = new String[csize];
180 constVal = new String[csize];
181 for( int i=0; i<csize; i++ ) {
182 cnstClm[i] = cnstKey[i].getKey();
183 constVal[i] = cnstKey[i].getValue();
184 }
185
186 // 4.3.1.1 (2008/08/24) replace 置換関?
187 HybsEntry[] repKey = arg.getEntrys( REPLACE_KEY );
188 int rsize = repKey.length;
189 repClm = new String[rsize];
190 repValFrom = new String[rsize];
191 repValTo = new String[rsize];
192 caseVals = new String[rsize]; // 5.7.2.3 (2014/01/31) replace 置換? case処?
193 for( int i=0; i<rsize; i++ ) {
194 repClm[i] = repKey[i].getKey();
195 String val = repKey[i].getValue(); // val は、YYYY⇒ZZZZ の形?
196 if( val != null ) {
197 int ad = val.indexOf( REP_SEP ); // REP_SEP は??
198 if( ad >= 0 ) {
199 repValFrom[i] = val.substring( 0,ad );
200 repValTo[i] = val.substring( ad+1 );
201 }
202 else {
203 // 5.7.2.3 (2014/01/31) replace 置換? case処?
204 // repValFrom[i] = val; // 昔?、 が無??合?、引数をクリアする処?った?
205 // repValTo[i] = ""; //
206 caseVals[i] = val; // 5.7.2.3 (2014/01/31) replace 置換? case処?
207 }
208 }
209 }
210 }
211
212 /**
213 * 引数の LineModel を??るメソ?です?
214 * 変換処?? LineModel を返します?
215 * 後続??行わな?????タのフィルタリングを行う場?は?
216 * null ??タを返します?つまり?null ??タは、後続??行わな?
217 * フラグの代わりにも使用して?す?
218 * なお?変換処?? LineModel と、オリジナルの LineModel が?
219 * 同?、コピ?(クローン)か?、各処?ソ??決めて?す?
220 * ドキュメントに明記されて???合?、副作用が問題になる?合??
221 * ???とに自?コピ?(クローン)して下さ??
222 *
223 * @og.rev 4.3.1.1 (2008/08/24) 置換関係対?
224 * @og.rev 5.7.2.3 (2014/01/31) replace 置換? case処??
225 *
226 * @param data オリジナルのLineModel
227 *
228 * @return 処?換後?LineModel
229 */
230 public LineModel action( final LineModel data ) {
231 count++ ;
232
233 // if( display ) { println( data.dataLine() ); }
234
235 if( !filter.filter( data ) ) {
236 return null; // 不??
237 }
238
239 if( firstRow ) {
240 int csize = cnstClm.length;
241 cnstClmNos = new int[csize];
242 for( int i=0; i<csize; i++ ) {
243 cnstClmNos[i] = data.getColumnNo( cnstClm[i] );
244 }
245
246 // 4.3.1.1 (2008/08/24) 置換関係対?
247 int rsize = repClm.length;
248 repClmNos = new int[rsize];
249 for( int i=0; i<rsize; i++ ) {
250 repClmNos[i] = data.getColumnNo( repClm[i] );
251 }
252
253 firstRow = false;
254 if( display ) { println( data.nameLine() ); } // 5.7.3.0 (2014/02/07) ????
255 }
256
257 if( debug ) { println( "Before:" + data.dataLine() ); } // 5.1.2.0 (2010/01/01) display の条件変更
258
259 for( int i=0; i<cnstClm.length; i++ ) {
260 data.setValue( cnstClmNos[i],constVal[i] );
261 }
262
263 // 4.3.1.1 (2008/08/24) 置換関係対?
264 for( int i=0; i<repClm.length; i++ ) {
265 // 5.7.2.3 (2014/01/31) Object ?null の時?処?おかしかった?で修正
266 // String val = String.valueOf( data.getValue( repClmNos[i] ) );
267 // if( val != null ) {
268 String val = "";
269 Object obj = data.getValue( repClmNos[i] );
270 if( obj != null ) { val = String.valueOf( obj ); }
271
272 if( caseVals[i] == null ) { // 従来からのリプレース処?
273 val = val.replaceAll( repValFrom[i],repValTo[i] );
274 }
275 else {
276 // 5.7.2.3 (2014/01/31) replace 置換? case処??
277 val = StringUtil.caseReplace( val , caseVals[i] , false );
278 }
279 data.setValue( repClmNos[i],val );
280 }
281
282 if( debug ) { println( "After :" + data.dataLine() ); } // 5.1.2.0 (2010/01/01) display の条件変更
283 else if( display ) { println( data.dataLine() ); } // 5.1.2.0 (2010/01/01) display の条件変更
284 return data;
285 }
286
287 /**
288 * プロセスの終?行います??に??、呼び出されます?
289 * 終???ファイルクローズ??クローズ?に使用します?
290 *
291 * @og.rev 4.3.1.1 (2008/08/24) 置換関係対?
292 * @og.rev 5.7.2.3 (2014/01/31) replace 置換? case処??
293 *
294 * @param isOK ト?タルで、OK?たかど?[true:成功/false:失敗]
295 */
296 public void end( final boolean isOK ) {
297 cnstClm = null; // 固定?を設定するカラ?
298 cnstClmNos = null; // 固定?を設定するカラ?号
299 constVal = null; // カラ?号に対応した固定?
300
301 repClm = null; // 置換を設定するカラ?
302 repClmNos = null; // 置換を設定するカラ?号
303 repValFrom = null; // カラ?号に対応した置換???
304 repValTo = null; // カラ?号に対応した置換後文字?
305 caseVals = null; // 5.7.2.3 (2014/01/31) replace 置換? case処?
306 }
307
308 /**
309 * プロセスの処?果のレポ?ト表現を返します?
310 * 処??ログラ?、?力件数、?力件数などの??です?
311 * こ???をそのまま、標準?力に出すことで、結果レポ?トと出来るよ?
312 * 形式で出してください?
313 *
314 * @return 処?果のレポ??
315 */
316 public String report() {
317 String report = "[" + getClass().getName() + "]" + CR
318 + TAB + "Model Filter : " + filter + CR
319 + TAB + "Output Count : " + count ;
320
321 return report ;
322 }
323
324 /**
325 * こ?クラスの使用方法を返します?
326 *
327 * @return こ?クラスの使用方?
328 */
329 public String usage() {
330 StringBuilder buf = new StringBuilder();
331
332 buf.append( "Process_TableFilter は、上流から受け取ったデータをフィルタする? ).append( CR );
333 buf.append( "ChainProcess インターフェースの実?ラスです?" ).append( CR );
334 buf.append( CR );
335 buf.append( "上?プロセスチェインの??タは上流から下流へと渡されます?)から" ).append( CR );
336 buf.append( "受け取ったLineModel を?に??目のフィルタリングを行います?" ).append( CR );
337 buf.append( "条件が?立した?合?、下流に流します??の条件を指定できますが? ).append( CR );
338 buf.append( "すべて AND で判定されます?" ).append( CR );
339 buf.append( "(設定条件すべてを?す?合?み、下流に??タを流します?)" ).append( CR );
340 buf.append( CR );
341 buf.append( "引数??中に空白を含??合?、ダブルコー??ション(\"\") で括って下さ??" ).append( CR );
342 buf.append( "引数??の ?』?前後には、空白は挟めません。??key=value の様に" ).append( CR );
343 buf.append( "繋げてください? ).append( CR );
344 buf.append( CR ).append( CR );
345 buf.append( getArgument().usage() ).append( CR );
346
347 return buf.toString();
348 }
349
350 /**
351 * こ?クラスは、main メソ?から実行できません?
352 *
353 * @param args コマンド引数配?
354 */
355 public static void main( final String[] args ) {
356 LogWriter.log( new Process_TableFilter().usage() );
357 }
358 }