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