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    }