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.util.Argument;
019import org.opengion.fukurou.util.StringUtil;
020import org.opengion.fukurou.util.LogWriter;
021
022import java.util.Map ;
023import java.util.LinkedHashMap ;
024
025/**
026 * 【廃止】Process_UnicodeEscape は、上流から受け取ったデータをエスケープ変換する
027 * ChainProcess インターフェースの実装クラスです。
028 *
029 *  ※ 5.0.0.2 (2009/09/15) このクラスは、廃止になりました。
030 *     類似機能に、Process_StringUtil を利用してください。
031 *     -action 引数に、getUnicodeEscape か、getReplaceEscape を指定することで、
032 *     ESCAPE(変換)/REVERSE(戻し) の指定と同一の処理を行います。
033 *
034 * 上流(プロセスチェインのデータは上流から下流へと渡されます。)から受け取った
035 * LineModel を元に、指定のカラムのUTF-8 文字コードと、HTML のエスケープ記号
036 * (&#xZZZZ;)文字との相互変換を行います。
037 * 入力文字を、キャラクタ(char)型に分解し、(&#xZZZZ;)に変換していきます。
038 * よって、通常に1文字(Shift-JISで2Byte,UTF-8で3Byte)が、8Byteになります。
039 * この変換された文字列を、HTML上でそのまま取り出すと、元のUnicode文字に戻る為、
040 * 通常のShift-JISでは、扱えない文字(中国語など)でも表示可能になります。
041 *
042 * 引数文字列中にスペースを含む場合は、ダブルコーテーション("") で括って下さい。
043 * 引数文字列の 『=』の前後には、スペースは挟めません。必ず、-key=value の様に
044 * 繋げてください。
045 *
046 * @og.formSample
047 *  Process_UnicodeEscape -action=ESC|REV [-keys=AA,BB,CC] [-all=false|true]
048 *
049 *     -action=ESC|REV        :ESCAPE(変換)/REVERSE(戻し) を指定します。先頭文字で判定します(必須)。
050 *   [ -keys=AA,BB,CC       ] :変換するカラムをCSV形式で複数指定できます。
051 *   [ -all=[false/true]    ] :全カラムを変換する場合は、trueを設定します(初期値:false[部分指定])
052 *   [ -display=[false/true]] :結果を標準出力に表示する(true)かしない(false)か(初期値:false[表示しない])
053 *   [ -debug=[false/true]  ] :デバッグ情報を標準出力に表示する(true)かしない(false)か(初期値:false[表示しない])
054 *
055 * @og.rev 5.0.0.2 (2009/09/15) 廃止クラスです。
056 * @deprecated 5.0.0.2 (2009/09/15) 廃止クラスです。類似機能に、Process_StringUtil を利用してください。
057 * @version  0.9.0  2004/02/27
058 * @author   Kazuhiko Hasegawa
059 * @since    JDK5.0,
060 */
061@Deprecated public class Process_UnicodeEscape extends AbstractProcess implements ChainProcess {
062
063        private boolean         isEscape        = true;         // 変換方法(true:Escape/false:Reverse)
064        private String          keys            = null;         // 変換するカラム名配列のアドレス
065        private int[]           clmNos          = null;         // 変換するカラム名配列のアドレス
066        private boolean         all                     = false;        // 部分指定
067        private boolean         display         = false;        // 表示しない
068        private boolean         debug           = false;        // 5.7.3.0 (2014/02/07) デバッグ情報
069
070        private boolean         firstRow        = true;         // 最初の一行目
071        private int                     count           = 0;
072
073        private static final Map<String,String> mustProparty   ;          // [プロパティ]必須チェック用 Map
074        private static final Map<String,String> usableProparty ;          // [プロパティ]整合性チェック Map
075
076        static {
077                mustProparty = new LinkedHashMap<String,String>();
078                mustProparty.put( "action",             "ESCAPE(変換)/REVERSE(戻し) を指定します(必須)" );
079
080                usableProparty = new LinkedHashMap<String,String>();
081                usableProparty.put( "keys",             "変換するカラムをCSV形式で複数指定できます。" );
082                usableProparty.put( "all",              "全カラムを変換する場合は、trueを設定します。" + 
083                                                                                CR + " (初期値:false:部分指定)" );
084                usableProparty.put( "display",  "結果を標準出力に表示する(true)かしない(false)か" + 
085                                                                                CR + " (初期値:false:表示しない)" );
086                usableProparty.put( "debug",    "デバッグ情報を標準出力に表示する(true)かしない(false)か" +
087                                                                                CR + "(初期値:false:表示しない)" );             // 5.7.3.0 (2014/02/07) デバッグ情報
088        }
089
090        /**
091         * デフォルトコンストラクター。
092         * このクラスは、動的作成されます。デフォルトコンストラクターで、
093         * super クラスに対して、必要な初期化を行っておきます。
094         *
095         */
096        public Process_UnicodeEscape() {
097                super( "org.opengion.fukurou.process.Process_UnicodeEscape",mustProparty,usableProparty );
098        }
099
100        /**
101         * プロセスの初期化を行います。初めに一度だけ、呼び出されます。
102         * 初期処理(ファイルオープン、DBオープン等)に使用します。
103         *
104         * @param   paramProcess データベースの接続先情報などを持っているオブジェクト
105         */
106        public void init( final ParamProcess paramProcess ) {
107                Argument arg = getArgument();
108
109                keys            = arg.getProparty( "keys",keys );
110                all                     = arg.getProparty( "all",all );
111                display         = arg.getProparty( "display",display );
112                debug           = arg.getProparty("debug",debug);                               // 5.7.3.0 (2014/02/07) デバッグ情報
113//              if( debug ) { println( arg.toString() ); }                      // 5.7.3.0 (2014/02/07) デバッグ情報
114
115                String act              = arg.getProparty( "action" );
116
117
118                if(      act.charAt( 0 ) == 'E' ) { isEscape = true;  }
119                else if( act.charAt( 0 ) == 'R' ) { isEscape = false; }
120                else {
121                        String errMsg = "action=[" + act + "] は、E(SCAPE) か、R(EVERSE) を設定して下さい。"
122                                                                + "先頭1文字目(大文字)で判定しています。";
123                        throw new RuntimeException( errMsg );
124                }
125
126                if( ( keys == null || keys.length() == 0 ) && !all ) {
127                        String errMsg = "keys か、all は設定して下さい。"
128                                                                + "keys=[" + keys + "], all=[" + all + "]";
129                        throw new RuntimeException( errMsg );
130                }
131        }
132
133        /**
134         * 引数の LineModel を処理するメソッドです。
135         * 変換処理後の LineModel を返します。
136         * 後続処理を行わない場合(データのフィルタリングを行う場合)は、
137         * null データを返します。つまり、null データは、後続処理を行わない
138         * フラグの代わりにも使用しています。
139         * なお、変換処理後の LineModel と、オリジナルの LineModel が、
140         * 同一か、コピー(クローン)かは、各処理メソッド内で決めています。
141         * ドキュメントに明記されていない場合は、副作用が問題になる場合は、
142         * 各処理ごとに自分でコピー(クローン)して下さい。
143         *
144         * @param   data        オリジナルのLineModel
145         *
146         * @return      処理変換後のLineModel
147         */
148        public LineModel action( final LineModel data ) {
149                count++ ;
150                try {
151                        if( firstRow ) {
152                                makeColumnNos( data );
153                                firstRow = false;
154                                if( display ) { println( data.nameLine() ); }           // 5.7.3.0 (2014/02/07) デバッグ情報
155                        }
156
157                        for( int i=0; i<clmNos.length; i++ ) {
158                                String val = (String)data.getValue( clmNos[i] ) ;
159
160                                if( isEscape ) {
161                                        val = StringUtil.getUnicodeEscape( val ) ;
162                                }
163                                else {
164                                        val = StringUtil.getReplaceEscape( val ) ;
165                                }
166                                data.setValue( clmNos[i],val );
167                        }
168
169//                      if( display ) { printKey( count,data ); }
170                        if( display ) { println( data.dataLine() ); }                   // 5.7.3.0 (2014/02/07) デバッグ情報
171                }
172                catch( Throwable ex ) {
173                        String errMsg = "row=[" + count + "]" + CR +
174                                                "    data=[" + data + "]" + CR ;
175                        throw new RuntimeException( errMsg,ex );
176                }
177                return data;
178        }
179
180        /**
181         * プロセスの終了を行います。最後に一度だけ、呼び出されます。
182         * 終了処理(ファイルクローズ、DBクローズ等)に使用します。
183         *
184         * @param   isOK トータルで、OKだったかどうか[true:成功/false:失敗]
185         */
186        public void end( final boolean isOK ) {
187                keys            = null;         // 変換するカラム名配列のアドレス
188                clmNos          = null;         // 変換するカラム名配列のアドレス
189        }
190
191        /**
192         * プロセスの処理結果のレポート表現を返します。
193         * 処理プログラム名、入力件数、出力件数などの情報です。
194         * この文字列をそのまま、標準出力に出すことで、結果レポートと出来るような
195         * 形式で出してください。
196         *
197         * @return   処理結果のレポート
198         */
199        public String report() {
200                String report = "[" + getClass().getName() + "]" + CR
201                                + TAB + "Output Count : " + count ;
202
203                return report ;
204        }
205
206        /**
207         * カラム番号配列を取得します。
208         * 繰返し処理を行う場合に、事前にアドレスでアクセスできるように処理するカラム番号を
209         * キャッシュしておきます。
210         *
211         * @param       data  ラインモデル
212         */
213        private void makeColumnNos( final LineModel data ) {
214                if( all ) {
215                        String[] names = data.getNames();
216                        int size = names.length;
217                        clmNos = new int[size];
218                        for( int i=0; i<size; i++ ) {
219                                clmNos[i] = i;
220                        }
221                }
222                else {
223                        String[] clms = StringUtil.csv2Array( keys );
224                        int size = clms.length;
225                        clmNos = new int[size];
226                        for( int i=0; i<size; i++ ) {
227                                clmNos[i] = data.getColumnNo( clms[i] );
228                        }
229                }
230        }
231
232        /**
233         * 画面出力用のフォーマットを作成します。
234         *
235         * @og.rev 5.7.3.0 (2014/02/07) 表示方法の変更のため、廃止
236         *
237         * @param       rowNo  データ読み取り件数
238         * @param       data   ラインモデル
239         */
240//      private void printKey( final int rowNo , final LineModel data ) {
241//              StringBuilder buf = new StringBuilder();
242//
243//              buf.append( "row=[" ).append( rowNo ).append( "] : " );
244//              for( int i=0; i < clmNos.length; i++ ) {
245//                      buf.append( data.getName( clmNos[i] ) );
246//                      buf.append( " ⇒ " );
247//                      buf.append( data.getValue( clmNos[i] ) );
248//                      buf.append( " , " );
249//              }
250//
251//              println( buf.toString() );
252//      }
253
254        /**
255         * このクラスの使用方法を返します。
256         *
257         * @return      このクラスの使用方法
258         */
259        public String usage() {
260                StringBuilder buf = new StringBuilder();
261
262                buf.append( "Process_UnicodeEscape は、上流から受け取ったデータをエスケープ変換する"            ).append( CR );
263                buf.append( "CainProcess インターフェースの実装クラスです。"                                                             ).append( CR );
264                buf.append( CR );
265                buf.append( "上流(プロセスチェインのデータは上流から下流へと渡されます。)から"                 ).append( CR );
266                buf.append( " LineModel を元に、指定のカラムのUTF-8 文字コードと、HTML のエスケープ"            ).append( CR );
267                buf.append( "記号(&#xZZZZ;)文字との相互変換を行います。"                                                                    ).append( CR );
268                buf.append( "入力文字を、キャラクタ(char)型に分解し、(&#xZZZZ;)に変換していきます。"           ).append( CR );
269                buf.append( "よって、通常に1文字(Shift-JISで2Byte,UTF-8で3Byte)が、8Byteになります。"      ).append( CR );
270                buf.append( "この変換された文字列を、HTML上でそのまま取り出すと、元のUnicode文字に戻る為"       ).append( CR );
271                buf.append( "通常のShift-JISでは、扱えない文字(中国語など)でも表示可能になります。"                  ).append( CR );
272                buf.append( CR );
273                buf.append( "引数文字列中に空白を含む場合は、ダブルコーテーション(\"\") で括って下さい。" ).append( CR );
274                buf.append( "引数文字列の 『=』の前後には、空白は挟めません。必ず、-key=value の様に"                ).append( CR );
275                buf.append( "繋げてください。"                                                                                                                          ).append( CR );
276                buf.append( CR ).append( CR );
277                buf.append( getArgument().usage() ).append( CR );
278
279                return buf.toString();
280        }
281
282        /**
283         * このクラスは、main メソッドから実行できません。
284         *
285         * @param       args    コマンド引数配列
286         */
287        public static void main( final String[] args ) {
288                LogWriter.log( new Process_UnicodeEscape().usage() );
289        }
290}