    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 * (&amp;#xZZZZ;)文字との相互変換を行います。
    037 * 入力文字を、キャラクタ(char)型に分解し、(&amp;#xZZZZ;)に変換していきます。
    038 * よって、通常に１文字(Shift-JISで２Byte,UTF-8で３Byte)が、８Byteになります。
    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         * 初期処理(ファイルオープン、ＤＢオープン等)に使用します。
    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                                                                + "先頭１文字目(大文字)で判定しています。";
    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         * 終了処理(ファイルクローズ、ＤＢクローズ等)に使用します。
    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( "よって、通常に１文字(Shift-JISで２Byte,UTF-8で３Byte)が、８Byteになります。"      ).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}