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    }