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.StringUtil;
020    import org.opengion.fukurou.util.FileUtil;
021    import org.opengion.fukurou.util.LogWriter;
022    
023    import java.util.List;
024    import java.util.ArrayList;
025    import java.util.Date;
026    
027    /**
028     * MainProcess は、HybsProcess を継承した、ParamProcess,FirstProcess,ChainProcess
029     * の実è£?‚¯ラスを実行するメインメソãƒ?ƒ‰を持つクラスですã?
030     * ParamProcess は、唯ä¸?æœ??に定義できるクラスで、データベã?ス接続やエラーメール
031     * などの共通なパラメータを定義しますã?なくても構いませんã€?
032     * FirstProcess は、å?ç�?‚’実行する最初ã?クラスで、このクラスでãƒ??タが作æ?されますã?
033     * ループå?ç�??、この FirstProcess でé ?¬¡作æ?されã�?LineModel オブジェクトを
034     * ?‘行づつ下位ã? ChainProcess に流してã�?��ますã?
035     * ChainProcess は、FirstProcess で作æ?されたデータをã?受け取り、å?ç�?�—ますã?
036     * 処ç�?¯¾象から外れるå?合ã?、LineModel ã‚?null に設定する為、下流には流れませんã€?
037     * フィルタチェインの様に使用しますã?なくても構いませんしã?è¤?•°存在しても構いませんã€?
038     *
039     * こã?クラスは、Runnable インターフェースを実è£?�—てã�?�¾すã?
040     *
041     * å�?®Ÿè£?‚¯ラスに引数を指定するå?合ã?ã€?キー=値 形式でæŒ?®šしますã?
042     * キーと値の間には、スベã?スをå?れなã�?�§下さã�??
043     * 先é?ã�?- なら引数ã€?# ならコメンãƒ?になりますã?
044     * - でã‚?# でもなã�?¼•数は、HybsProcess のサブクラスになりますã?
045     *
046     *  Usage: java MainProcess サブChainProcessクラス [[-キー=値] ?¥?¥?¥] [?¥?¥?¥]
047     *    [ParamProcess実è£?‚¯ラス ]?šParamProcess を実è£?�—たクラス
048     *       -キー=値              ?š各サブクラス毎ã?引数ã€?- で始まりã?= でåˆ?‰²しますã?
049     *       -AAA=BBB              ?š引数は、各クラス毎に独自にæŒ?®šしますã?
050     *     FirstProcess実è£?‚¯ラス  ?šFirstProcess を実è£?�—たクラス
051     *       -キー=値              ?š各サブクラス毎ã?引数ã€?- で始まりã?= でåˆ?‰²しますã?
052     *       -AAA=BBB              ?š引数は、各クラス毎に独自にæŒ?®šしますã?
053     *       #-AAA=BBB             ?šå?頭ã�?- なら引数ã€?# ならコメンãƒ?になりますã?
054     *    [ChainProcess実è£?‚¯ラス1]?šChainProcess を実è£?�—たクラス?šè¤?•°æŒ?®šできますã?
055     *       -CCC=DDD
056     *    [ChainProcess実è£?‚¯ラス2]?šChainProcess を実è£?�—たクラス?šè¤?•°æŒ?®šできますã?
057     *       -EEE=FFF
058     *
059     * @version  4.0
060     * @author   Kazuhiko Hasegawa
061     * @since    JDK5.0,
062     */
063    public final class MainProcess implements Runnable {
064            private static final String CR = System.getProperty("line.separator");
065    
066            /** main 処ç�??リターン値  初期åŒ?{@value} */
067            public static final int RETURN_INIT = -1;
068            /** main 処ç�??リターン値  正常値 {@value} */
069            public static final int RETURN_OK = 0;
070            /** main 処ç�??リターン値  正常値 {@value} */
071            public static final int RETURN_WARN = 1;
072            /** main 処ç�??リターン値  異常値 {@value} */
073            public static final int RETURN_NG = 2;
074    
075            private List<HybsProcess> list = null;
076            private ParamProcess  param  = null;
077            private LoggerProcess logger = null;
078            private int kekka = RETURN_INIT;
079    
080            /**
081             * HybsProcess クラスを管ç�?�—てã�?‚‹リストをセãƒ?ƒˆしますã?
082             *
083             * 引数のListオブジェクトã?、æµ?�„コピã?で、取り込みますã?
084             *
085             * @param       list    HybsProcessリスãƒ?
086             * @throws IllegalArgumentException 引数がã?null の場合ã?
087             */
088            public void setList( final List<HybsProcess> list ) {
089                    if( list == null ) {
090                            String errMsg = "引数の List に、null は設定できませんã€? ;
091                            throw new IllegalArgumentException( errMsg );
092                    }
093                    this.list = new ArrayList<HybsProcess>( list );
094            }
095    
096            /**
097             * HybsProcess クラスをå?期化しますã?
098             *
099             * 主に、ParamProcess クラスの取り出ã�?またã?、作æ?)処ç�?‚’åˆ?›¢してã�?�¾すã?
100             *
101             * @og.rev 5.1.5.0 (2010/04/01) 出力が?’重ã€?¼“重に出力されるのを回避しますã?
102             */
103            private void init() {
104                    if( list == null ) {
105                            String errMsg = "リスãƒ?ã�?null ですã?まずã?setList( List<HybsProcess> ) がå¿?¦�ですã?";
106                            throw new RuntimeException( errMsg );
107                    }
108    
109                    try {
110                            // List のæœ?¸Š位ã?、å¿?�š、LoggerProcess をé?備するã?
111                            HybsProcess process = list.get(0);
112                            if( process instanceof LoggerProcess ) {
113                                    logger = (LoggerProcess)process;
114                                    logger.init( null );
115                                    list.remove(0);                 // List上からã?LoggerProcess を削除しておきますã?
116                                    process = list.get(0);  // 次の取得を行っておく。ã?ログラãƒ??都å�?
117                            }
118                            else {
119                                    logger = new Process_Logger();
120                                    logger.putArgument( "logFile"  , "System.out" );
121                                    logger.putArgument( "dispFile" , "System.out" );
122                                    logger.init( null );
123                            }
124    
125                            // そã?次は、ParamProcess かどã�?�‹をチェãƒ?‚¯
126                            if( process instanceof ParamProcess ) {
127                                    param = (ParamProcess)process;
128                                    param.setLoggerProcess( logger );
129                                    param.init( null );
130                                    list.remove(0);                 // List上からã?ParamProcess を削除しておきますã?
131                            }
132                    }
133                    catch (Throwable th) {
134                            StringBuilder errMsg = new StringBuilder();
135                            errMsg.append( "初期化中に例外が発生しましたã€? ).append( CR );
136                            errMsg.append( th.getMessage() ) ;
137                            String errStr = errMsg.toString();
138    
139                            logger.errLog( errStr,th );
140                            LogWriter.log( errStr );
141                            // 5.1.5.0 (2010/04/01) 出力が?’重ã€?¼“重に出力されるのを回避しますã?
142    //                      System.out.println( errStr );
143    
144                            if( param  != null ) { param.end( false ); }
145                            logger.end( false );
146    
147                            throw new RuntimeException( errStr,th );        // 4.0.0 (2005/01/31)
148                    }
149            }
150    
151            /**
152             * HybsProcess クラスを実行しますã?
153             *
154             * @og.rev 5.1.2.0 (2010/01/01) 実行中の経過表示をã?標準å?力ではなくã?エラー出力に変更
155             * @og.rev 5.1.5.0 (2010/04/01) 出力が?’重ã€?¼“重に出力されるのを回避しますã?
156             * @og.rev 5.3.4.0 (2011/04/01) タイトル追åŠ?
157             * @og.rev 5.5.4.5 (2012/07/27) 処ç�??æœ?¾Œに結果をå?力しますã?
158             */
159            public void run() {
160                    init();
161    
162                    long st = System.currentTimeMillis();
163                    logger.logging( "=================================================================" );
164                    logger.logging( new Date( st ) + " 処ç�?‚’開始しますã?" );
165                    logger.logging( getClass().getName() );
166    
167                    kekka = RETURN_NG;
168                    LineModel model = null;
169                    int rowNo = 0;
170                    int cnt = list.size();
171                    try {
172                            // 初期åŒ?途中でエラーが発生すれã?、終äº?�—ますã?
173                            logger.logging( "初期化å?ç�?‚’行いますã?" );
174            //              if( param != null ) { logger.logging( param.toString() ); }
175    
176                            // List には、FirstProcess と ChainProcess のみ存在するã€?
177                            HybsProcess process ;
178                            for( int i=0; i<cnt; i++ ) {
179                                    process = list.get(i);
180                                    process.setLoggerProcess( logger );
181                                    process.init( param );
182            //                      logger.logging( process.toString() );
183                            }
184    
185                            logger.logging( "Process を実行しますã?" );
186                            FirstProcess firstProcess  = (FirstProcess)list.get(0);
187                            ChainProcess chainProcess ;
188                            while( firstProcess.next() ) {
189                                    model = firstProcess.makeLineModel( rowNo );
190                                    for( int i=1; i<cnt && model != null ; i++ ) {
191                                            chainProcess = (ChainProcess)list.get(i);
192                                            model = chainProcess.action( model );
193                                    }
194                                    rowNo++;
195                                    // 5.1.2.0 (2010/01/01) 実行中の経過表示をã?標準å?力ではなくã?エラー出力に変更しますã?
196                                    if( rowNo%50   == 0 ) { System.err.print( "." ); }
197                                    if( rowNo%1000 == 0 ) { System.err.println( "  Count=[" + rowNo + "]" ); }
198                            }
199                            kekka = RETURN_OK;
200                            logger.logging(     "  Total=[" + rowNo + "]" );
201                            System.err.println( "  Total=[" + rowNo + "]" );                // 5.5.4.5 (2012/07/27) 処ç�??æœ?¾Œに結果をå?力しますã?
202                    }
203                    catch (Throwable th) {
204                            kekka = RETURN_NG;
205    
206                            StringBuilder errMsg = new StringBuilder();
207                            errMsg.append( CR );    // 5.1.5.0 (2010/04/01) 先に改行しておきますã?
208                            errMsg.append( "ãƒ??タ処ç�?¸­に例外が発生しましたã€?[" );
209                            errMsg.append( rowNo ).append( "]行目" ).append( CR );
210                            errMsg.append( th.getMessage() ).append( CR ) ;
211    
212                            if( model != null ) { errMsg.append( model.toString() ).append( CR ) ; }
213    
214                            for( int i=0; i<cnt; i++ ) {
215                                    HybsProcess process = list.get(i);
216                                    errMsg.append( process.toString() );
217                            }
218                            String errStr = errMsg.toString();
219                            logger.errLog( errStr,th );
220                            LogWriter.log( errStr );
221                            // 5.1.5.0 (2010/04/01) 出力が?’重ã€?¼“重に出力されるのを回避しますã?
222    //                      System.out.println( errStr );
223    //                      throw new RuntimeException( errStr,th );        // 4.0.0 (2005/01/31)
224                    }
225                    finally {
226                            // 終äº?å¿?�š全ての endメソãƒ?ƒ‰をコールしますã?
227                            logger.logging( "終äº??ç�?‚’行いますã?" );
228                            StringBuilder buf = new StringBuilder();
229                            // 5.3.4.0 (2011/04/01) ロガーのreport()を呼びますã?(タイトルを追åŠ?
230                            if( param != null ) {
231                                    buf.append( logger.report() ).append( CR );
232                                    buf.append( param.report() );
233                            }
234    
235                            boolean isOK = (kekka == RETURN_OK);
236                            for( int i=0; i<cnt; i++ ) {
237                                    HybsProcess process = list.get(i);
238                                    if( process != null ) {
239                                            buf.append( CR ).append( process.report() );
240                                            process.end( isOK );
241                                    }
242                            }
243                            // ä¸?•ªæœ?¾Œに、ParamProcess を終äº?�—ますã?
244                            if( param  != null ) { param.end( isOK ); }             // 5.5.4.5 (2012/07/27) ä¸??のProcessの end() のæœ?¾Œにしますã?
245    
246                            buf.append( CR );
247                            logger.logging( buf.toString() );
248                            logger.logging( "実行結果は、[" + errCode(kekka) + "] ですã?" );
249                            long ed = System.currentTimeMillis();
250                            logger.logging( "合計å?ç�?™‚é–?= " + (ed-st) + " (ms) ですã?" );
251                            logger.logging( new Date( ed ) + " 終äº?�—ましたã€? );
252    
253    //                      // ä¸?•ªæœ?¾Œに、ParamProcess を終äº?�—ますã?
254    //                      if( param  != null ) { param.end( isOK ); }
255                            logger.end( isOK );
256                    }
257            }
258    
259            /**
260             * 処ç�??実行結果を返しますã?
261             *
262             * @return      実行結果
263             * @see #RETURN_INIT
264             */
265            public int getKekka() { return kekka; }
266    
267            /**
268             * 処ç�?‚’行うメインメソãƒ?ƒ‰ですã?
269             *
270             * @og.rev 4.0.0.0 (2007/11/22) ConnDataFactory の使用をå»?­¢
271             *
272             * @param       args    コマンド引数配å?
273             */
274            public static void main( final String[] args ) {
275                    if( args.length == 0 ) {
276                            LogWriter.log( usage() );
277                            return ;
278                    }
279    
280                    // 引数のåŠ?·¥
281                    List<HybsProcess> list = makeHybsProcessList( args );
282    
283                    // 特別に、LoggerProcess がなければ、標準å?力を使用するロガーを登録するã€?
284                    HybsProcess prcs = list.get(0);
285                    if( ! (prcs instanceof LoggerProcess) ) {
286                            LoggerProcess logger = new Process_Logger();
287                            logger.setDisplayWriter( FileUtil.getLogWriter( "System.out" ) );
288                            list.add( 0,logger );
289                    }
290    
291                    // 引数リスãƒ?HybsProcessリスãƒ?を登録
292                    MainProcess process = new MainProcess();
293                    process.setList( list );
294    
295                    // 処ç�??実行開å§?
296                    process.run();
297            }
298    
299            /**
300             * メインに渡された引数配å? より、各 ChainProcess インスタンス を作æ?しますã?
301             *
302             * @param       args    メインに渡された引数配å?
303             *
304             * @return      ChainProcessインスタンスのList
305             */
306            private static List<HybsProcess> makeHybsProcessList( final String[] args ) {
307                    ArrayList<HybsProcess> list = new ArrayList<HybsProcess>();
308    
309                    HybsProcess process = null;
310                    Argument argment = new Argument( MainProcess.class.getName() );
311                    for( int i=0; i<args.length; i++ ) {
312                            int type = argment.getArgumentType( args[i] ) ;
313    
314                            switch( type ) {
315                                    case Argument.CMNT : continue;
316                                    case Argument.ARGS :
317                                            process = (HybsProcess)StringUtil.newInstance( args[i] );
318                                            list.add( process );
319                                            break;
320                                    case Argument.PROP :
321                                            if( process != null ) {
322                                                    process.putArgument( args[i] );
323                                            }
324                                            break;
325                                    default: break;
326                            }
327                    }
328                    return list;
329            }
330    
331            /**
332             * エラーコードに対するメãƒ?‚»ージを返しますã?
333             *
334             * @param       code    エラーコーãƒ?
335             *
336             * @return      エラーコードに対するメãƒ?‚»ージ
337             */
338            public String errCode( final int code ) {
339                    final String errMsg ;
340                    switch( code ) {
341                            case RETURN_INIT : errMsg = "初期åŒ? ; break;
342                            case RETURN_OK   : errMsg = "正常" ; break;
343                            case RETURN_WARN : errMsg = "警å‘? ; break;
344                            case RETURN_NG   : errMsg = "異常" ; break;
345                            default :errMsg = "未定義エラー" ; break;
346                    }
347                    return errMsg ;
348            }
349    
350            /**
351             * こã?クラスの使用方法を返しますã?
352             *
353             * @return      こã?クラスの使用方æ³?
354             */
355            private static String usage() {
356    
357                    StringBuilder buf = new StringBuilder();
358    
359                    buf.append( "ChainProcess を実è£?�—た各クラスをã?é ?¬¡実行しますã?" ).append( CR );
360                    buf.append( "キーと値の間には、スベã?スをå?れなã�?�§下さã�??").append( CR ).append( CR );
361    
362                    buf.append( "Usage: java MainProcess サブChainProcessクラス [[-キー=値] ?¥?¥?¥] [?¥?¥?¥]  " ).append( CR );
363                    buf.append( "   サブChainProcessクラス ?šChainProcess を実è£?�—たクラス" ).append( CR );
364                    buf.append( "     -キー=値             ?š各サブクラス毎ã?引数ã€?- で始まりã?= でåˆ?‰²しますã?" ).append( CR );
365                    buf.append( "     -AAA=BBB             ?šè¤?•°æŒ?®šできますã?" ).append( CR );
366                    buf.append( "   サブChainProcessクラス ?šè¤?•°æŒ?®šできますã?" ).append( CR );
367                    buf.append( "     -CCC=DDD " ).append( CR );
368    
369                    return buf.toString();
370            }
371    }