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 */
016package org.opengion.fukurou.process;
017
018import org.opengion.fukurou.security.HybsCryptography;
019import org.opengion.fukurou.util.Argument;
020import org.opengion.fukurou.util.StringUtil;
021import org.opengion.fukurou.util.LogWriter;
022
023import java.util.Map ;
024import java.util.LinkedHashMap ;
025
026/**
027 * Process_StringUtil は、上流から受け取ったデータをStringUtilクラスの特定の
028 * メソッドでデータ変換する、CainProcess インターフェースの実装クラスです。
029 *
030 * 上流(プロセスチェインのデータは上流から下流へと渡されます。)から
031 *  LineModel を元に、指定のカラムの文字を、変換します。
032 *
033 * 現時点で利用できるStringUtil のメソッドは、下記の通りです。
034 *    urlEncode        : UTF-8 で、URLエンコードを行う。
035 *    rTrim            : 文字列の後ろのスペースを削除
036 *    htmlFilter       : HTML上のエスケープ文字を変換
037 *    code39           : CODE39 の 文字列を作成(チェックデジット付き)
038 *    getUnicodeEscape : HTML のエスケープ記号(&#xZZZZ;)に変換
039 *    getReplaceEscape : HTML のエスケープ記号(&#xZZZZ;)を戻す
040 *    spanCut          : 引数からspanタグを取り除く
041 *
042 * HybsCryptography のメソッドも呼び出せます。
043 *    getMD5           : MessageDigestにより、MD5 でハッシュした文字に変換
044 *    encrypt          : Hybs独自の暗号化を行います(Hybs内部設定の秘密鍵)
045 *    decrypt          : Hybs独自の復号化を行います(Hybs内部設定の秘密鍵)
046 *
047 * 引数文字列中にスペースを含む場合は、ダブルコーテーション("") で括って下さい。
048 * 引数文字列の 『=』の前後には、スペースは挟めません。必ず、-key=value の様に
049 * 繋げてください。
050 *
051 * @og.formSample
052 *  Process_StringUtil -action=getMD5|encrypt|decrypt|code39|getUnicodeEscape|getReplaceEscape|・・・ -keys=AA,BB,CC
053 *
054 *     -action=ESC|REV        :StringUtilクラスの特定のメソッド名を指定します(必須)。
055 *                              urlEncode|rTrim|htmlFilter|getMD5|code39|getUnicodeEscape|getReplaceEscape|spanCut
056 *     -keys=AA,BB,CC         :変換するカラムをCSV形式で複数指定できます(必須)。
057 *   [ -display=[false/true]] :結果を標準出力に表示する(true)かしない(false)か(初期値:false[表示しない])
058 *   [ -debug=[false/true]  ] :デバッグ情報を標準出力に表示する(true)かしない(false)か(初期値:false[表示しない])
059 *
060 * @og.rev 5.0.0.2 (2009/09/15) 新規クラス作成
061 *
062 * @version  0.9.0  2004/02/27
063 * @author   Kazuhiko Hasegawa
064 * @since    JDK5.0,
065 */
066public class Process_StringUtil extends AbstractProcess implements ChainProcess {
067
068        private static final String STR_ACTION_BASE = "org.opengion.fukurou.process.Process_StringUtil$SU_" ;
069
070        private String          keys            = null;         // 変換するカラム名配列のアドレス
071        private int[]           clmNos          = null;         // 変換するカラム名配列のアドレス
072        private boolean         display         = false;        // 表示しない
073        private boolean         debug           = false;        // 5.7.3.0 (2014/02/07) デバッグ情報
074
075        private boolean         firstRow        = true;         // 最初の一行目
076        private int                     count           = 0;
077        private StrAction       stAction        = null;         // Ver 5.0.0.2 (2009/09/15)
078
079        private static final Map<String,String> mustProparty   ;                // [プロパティ]必須チェック用 Map
080        private static final Map<String,String> usableProparty ;                // [プロパティ]整合性チェック Map
081
082        static {
083                mustProparty = new LinkedHashMap<String,String>();
084                mustProparty.put( "action",             "StringUtilの特定のメソッドを指定します(必須)" + 
085                                                                                CR + "urlEncode , rTrim , htmlFilter , getMD5 , encrypt , decrypt , code39 , getUnicodeEscape , getReplaceEscape , spanCut" );
086
087                mustProparty.put( "keys",               "変換するカラムをCSV形式で複数指定できます(必須)。" );
088
089                usableProparty = new LinkedHashMap<String,String>();
090                usableProparty.put( "display",  "結果を標準出力に表示する(true)かしない(false)か" + 
091                                                                                CR + " (初期値:false[表示しない])" );
092                usableProparty.put( "debug",    "デバッグ情報を標準出力に表示する(true)かしない(false)か" +
093                                                                                CR + "(初期値:false:表示しない)" );             // 5.7.3.0 (2014/02/07) デバッグ情報
094        }
095
096        /**
097         * デフォルトコンストラクター。
098         * このクラスは、動的作成されます。デフォルトコンストラクターで、
099         * super クラスに対して、必要な初期化を行っておきます。
100         *
101         */
102        public Process_StringUtil() {
103                super( "org.opengion.fukurou.process.Process_StringUtil",mustProparty,usableProparty );
104        }
105
106        /**
107         * プロセスの初期化を行います。初めに一度だけ、呼び出されます。
108         * 初期処理(ファイルオープン、DBオープン等)に使用します。
109         *
110         * @param   paramProcess データベースの接続先情報などを持っているオブジェクト
111         */
112        public void init( final ParamProcess paramProcess ) {
113                Argument arg = getArgument();
114
115                keys            = arg.getProparty( "keys",keys );
116                display         = arg.getProparty( "display",display );
117                debug           = arg.getProparty("debug",debug);                               // 5.7.3.0 (2014/02/07) デバッグ情報
118
119                String act      = arg.getProparty( "action" );
120
121                stAction        = (StrAction)StringUtil.newInstance( STR_ACTION_BASE + act );
122        }
123
124        /**
125         * 引数の LineModel を処理するメソッドです。
126         * 変換処理後の LineModel を返します。
127         * 後続処理を行わない場合(データのフィルタリングを行う場合)は、
128         * null データを返します。つまり、null データは、後続処理を行わない
129         * フラグの代わりにも使用しています。
130         * なお、変換処理後の LineModel と、オリジナルの LineModel が、
131         * 同一か、コピー(クローン)かは、各処理メソッド内で決めています。
132         * ドキュメントに明記されていない場合は、副作用が問題になる場合は、
133         * 各処理ごとに自分でコピー(クローン)して下さい。
134         *
135         * @param   data        オリジナルのLineModel
136         *
137         * @return      処理変換後のLineModel
138         */
139        public LineModel action( final LineModel data ) {
140                count++ ;
141                try {
142                        if( firstRow ) {
143                                makeColumnNos( data );
144                                firstRow = false;
145                                if( display ) { println( data.nameLine() ); }           // 5.7.3.0 (2014/02/07) デバッグ情報
146                        }
147
148                        if( debug ) { println( "Before:" + data.dataLine() ); }         // 5.1.2.0 (2010/01/01) display の条件変更
149                        for( int i=0; i<clmNos.length; i++ ) {
150                                String val = (String)data.getValue( clmNos[i] ) ;
151                                data.setValue( clmNos[i],stAction.change( val ) );
152                        }
153
154                        if( debug ) { println( "After :" + data.dataLine() ); }         // 5.1.2.0 (2010/01/01) display の条件変更
155                        else if( display ) { println( data.dataLine() ); }              // 5.1.2.0 (2010/01/01) display の条件変更
156                }
157                catch( Throwable ex ) {
158                        String errMsg = "row=[" + count + "]" + CR +
159                                                "    data=[" + data + "]" + CR ;
160                        throw new RuntimeException( errMsg,ex );
161                }
162                return data;
163        }
164
165        /**
166         * プロセスの終了を行います。最後に一度だけ、呼び出されます。
167         * 終了処理(ファイルクローズ、DBクローズ等)に使用します。
168         *
169         * @param   isOK トータルで、OKだったかどうか[true:成功/false:失敗]
170         */
171        public void end( final boolean isOK ) {
172                keys            = null;         // 変換するカラム名配列のアドレス
173                clmNos          = null;         // 変換するカラム名配列のアドレス
174        }
175
176        /**
177         * プロセスの処理結果のレポート表現を返します。
178         * 処理プログラム名、入力件数、出力件数などの情報です。
179         * この文字列をそのまま、標準出力に出すことで、結果レポートと出来るような
180         * 形式で出してください。
181         *
182         * @return   処理結果のレポート
183         */
184        public String report() {
185                String report = "[" + getClass().getName() + "]" + CR
186                                + TAB + "Output Count : " + count ;
187
188                return report ;
189        }
190
191        /**
192         * カラム番号配列を取得します。
193         * 繰返し処理を行う場合に、事前にアドレスでアクセスできるように処理するカラム番号を
194         * キャッシュしておきます。
195         *
196         * @param       data  LineModelオブジェクト
197         */
198        private void makeColumnNos( final LineModel data ) {
199                String[] clms = StringUtil.csv2Array( keys );
200                int size = clms.length;
201                clmNos = new int[size];
202                for( int i=0; i<size; i++ ) {
203                        clmNos[i] = data.getColumnNo( clms[i] );
204                }
205        }
206
207        /**
208         * このクラスの使用方法を返します。
209         *
210         * @return      このクラスの使用方法
211         */
212        public String usage() {
213                StringBuilder buf = new StringBuilder();
214
215                buf.append( "Process_StringUtil は、上流から受け取ったデータをStringUtilクラスの特定の"       ).append( CR );
216                buf.append( "メソッドでデータ変換する、CainProcess インターフェースの実装クラスです。"                ).append( CR );
217                buf.append( CR );
218                buf.append( "上流(プロセスチェインのデータは上流から下流へと渡されます。)から"                 ).append( CR );
219                buf.append( " LineModel を元に、指定のカラムの文字を、変換します。"                                                  ).append( CR );
220                buf.append( CR );
221                buf.append( "現時点で利用できるStringUtil のメソッドは、下記の通りです。"                                       ).append( CR );
222                buf.append( "  urlEncode        : UTF-8 で、URLエンコードを行う。"                                                 ).append( CR );
223                buf.append( "  rTrim            : 文字列の後ろのスペースを削除"                                                       ).append( CR );
224                buf.append( "  htmlFilter       : HTML上のエスケープ文字を変換"                                                     ).append( CR );
225                buf.append( "  code39           : CODE39 の 文字列を作成(チェックデジット付き)"                          ).append( CR );
226                buf.append( "  getUnicodeEscape : HTML のエスケープ記号(&amp;#xZZZZ;)に変換"                               ).append( CR );
227                buf.append( "  getReplaceEscape : HTML のエスケープ記号(&amp;#xZZZZ;)を戻す"                               ).append( CR );
228                buf.append( "  spanCut          : 引数からspanタグを取り除く"                                                              ).append( CR );
229                buf.append( CR );
230                buf.append( "HybsCryptography のメソッドも呼び出せます。"                                                                    ).append( CR );
231                buf.append( "  getMD5           : MessageDigestにより、MD5 でハッシュした文字に変換"            ).append( CR );
232                buf.append( "  encrypt          : Hybs独自の暗号化を行います(Hybs内部設定の秘密鍵)"                        ).append( CR );
233                buf.append( "  decrypt          : Hybs独自の復号化を行います(Hybs内部設定の秘密鍵)"                        ).append( CR );
234                buf.append( CR );
235                buf.append( "引数文字列中に空白を含む場合は、ダブルコーテーション(\"\") で括って下さい。" ).append( CR );
236                buf.append( "引数文字列の 『=』の前後には、空白は挟めません。必ず、-key=value の様に"                ).append( CR );
237                buf.append( "繋げてください。"                                                                                                                          ).append( CR );
238                buf.append( CR ).append( CR );
239                buf.append( getArgument().usage() ).append( CR );
240
241                return buf.toString();
242        }
243
244        /**
245         * このクラスは、main メソッドから実行できません。
246         *
247         * @param       args    コマンド引数配列
248         */
249        public static void main( final String[] args ) {
250                LogWriter.log( new Process_StringUtil().usage() );
251        }
252
253        /**
254         * インナークラスとして、共通メソッドを定義します(I/Fの代わり)。
255         */
256        public static class StrAction {
257                /**
258                 * 引数を変換します。
259                 *
260                 * @param       val             引数
261                 * @return      変換された文字列
262                 */
263                public String change( final String val ) {
264                        return val;
265                }
266        }
267
268        /**
269         * UTF-8 で、URLエンコードを行います。
270         */
271        public static class SU_urlEncode extends StrAction {
272                /**
273                 * 引数を変換します。
274                 *
275                 * @param       val             引数
276                 * @return      変換された文字列
277                 */
278                @Override
279                public String change( final String val ) {
280                        return StringUtil.urlEncode( val );
281                }
282        }
283
284        /**
285         * 文字列の後ろのスペースを削除します。
286         * 注意:'\u0020' (スペース文字) より小さい文字を切り取ります。
287         */
288        public static class SU_rTrim extends StrAction {
289                /**
290                 * 引数を変換します。
291                 *
292                 * @param       val             引数
293                 * @return      変換された文字列
294                 */
295                @Override
296                public String change( final String val ) {
297                        return StringUtil.rTrim( val );
298                }
299        }
300
301        /**
302         * HTML上のエスケープ文字を変換します。
303         */
304        public static class SU_htmlFilter extends StrAction {
305                /**
306                 * 引数を変換します。
307                 *
308                 * @param       val             引数
309                 * @return      変換された文字列
310                 */
311                @Override
312                public String change( final String val ) {
313                        return StringUtil.htmlFilter( val );
314                }
315        }
316
317        /**
318         * CODE39 の 文字列を作成します。(チェックデジット付き)
319         */
320        public static class SU_code39 extends StrAction {
321                /**
322                 * 引数を変換します。
323                 *
324                 * @param       val             引数
325                 * @return      変換された文字列
326                 */
327                @Override
328                public String change( final String val ) {
329                        return StringUtil.code39( val,true );
330                }
331        }
332
333        /**
334         * Unicode文字列の値を HTML のエスケープ記号(&amp;#xZZZZ;)に変換します。
335         */
336        public static class SU_getUnicodeEscape extends StrAction {
337                /**
338                 * 引数を変換します。
339                 *
340                 * @param       val             引数
341                 * @return      変換された文字列
342                 */
343                @Override
344                public String change( final String val ) {
345                        return StringUtil.getUnicodeEscape( val );
346                }
347        }
348
349        /**
350         * HTML のエスケープ記号(&amp;#xZZZZ;)をUnicode文字列に戻します。
351         */
352        public static class SU_getReplaceEscape extends StrAction {
353                /**
354                 * 引数を変換します。
355                 *
356                 * @param       val             引数
357                 * @return      変換された文字列
358                 */
359                @Override
360                public String change( final String val ) {
361                        return StringUtil.getReplaceEscape( val );
362                }
363        }
364
365        /**
366         * 引数からspanタグを取り除いて返します。
367         */
368        public static class SU_spanCut extends StrAction {
369                /**
370                 * 引数を変換します。
371                 *
372                 * @param       val             引数
373                 * @return      変換された文字列
374                 */
375                @Override
376                public String change( final String val ) {
377                        return StringUtil.spanCut( val );
378                }
379        }
380
381        /**
382         * MessageDigestにより、MD5 でハッシュした文字に変換します。
383         *
384         * @og.rev 5.2.2.0 (2010/11/01) util.StringUtil から security.HybsCryptography へ移動
385         *
386         */
387        public static class SU_getMD5 extends StrAction {
388                /**
389                 * 引数を変換します。
390                 *
391                 * @param       val             引数
392                 * @return      変換された文字列
393                 */
394                @Override
395                public String change( final String val ) {
396                        return HybsCryptography.getMD5( val );
397                }
398        }
399
400        /**
401         * Hybs独自の暗号化を行います(Hybs内部設定の秘密鍵)
402         *
403         * @og.rev 5.2.2.0 (2010/11/01) 新規追加
404         */
405        public static class SU_encrypt extends StrAction {
406                private HybsCryptography crpt = null;
407
408                /**
409                 * 引数を変換します。
410                 *
411                 * @param       val             引数
412                 * @return      変換された文字列
413                 */
414                @Override
415                public String change( final String val ) {
416                        if( crpt == null ) {
417                                crpt = new HybsCryptography();
418                        }
419                        return crpt.encrypt( val );
420                }
421        }
422
423        /**
424         * Hybs独自の復号化を行います(Hybs内部設定の秘密鍵)
425         *
426         * @og.rev 5.2.2.0 (2010/11/01) 新規追加
427         */
428        public static class SU_decrypt extends StrAction {
429                private HybsCryptography crpt = null;
430
431                /**
432                 * 引数を変換します。
433                 *
434                 * @param       val             引数
435                 * @return      変換された文字列
436                 */
437                @Override
438                public String change( final String val ) {
439                        if( crpt == null ) {
440                                crpt = new HybsCryptography();
441                        }
442                        return crpt.decrypt( val );
443                }
444        }
445}