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             * @og.rev 5.7.2.2 (2014/01/24) logger と?重になる為、削除
159             */
160            public void run() {
161                    init();
162    
163                    long st = System.currentTimeMillis();
164                    logger.logging( "=================================================================" );
165                    logger.logging( new Date( st ) + " 処?開始します?" );
166                    logger.logging( getClass().getName() );
167    
168                    kekka = RETURN_NG;
169                    LineModel model = null;
170                    int rowNo = 0;
171                    int cnt = list.size();
172                    try {
173                            // 初期?途中でエラーが発生すれ?、終?ます?
174                            logger.logging( "初期化??行います?" );
175            //              if( param != null ) { logger.logging( param.toString() ); }
176    
177                            // List には、FirstProcess と ChainProcess のみ存在する?
178                            HybsProcess process ;
179                            for( int i=0; i<cnt; i++ ) {
180                                    process = list.get(i);
181                                    process.setLoggerProcess( logger );
182                                    process.init( param );
183            //                      logger.logging( process.toString() );
184                            }
185    
186                            logger.logging( "Process を実行します?" );
187                            FirstProcess firstProcess  = (FirstProcess)list.get(0);
188                            ChainProcess chainProcess ;
189                            while( firstProcess.next() ) {
190                                    model = firstProcess.makeLineModel( rowNo );
191                                    for( int i=1; i<cnt && model != null ; i++ ) {
192                                            chainProcess = (ChainProcess)list.get(i);
193                                            model = chainProcess.action( model );
194                                    }
195                                    rowNo++;
196                                    // 5.1.2.0 (2010/01/01) 実行中の経過表示を?標準?力ではなく?エラー出力に変更します?
197                                    if( rowNo%50   == 0 ) { System.err.print( "." ); }
198                                    if( rowNo%1000 == 0 ) { System.err.println( "  Count=[" + rowNo + "]" ); }
199                            }
200                            kekka = RETURN_OK;
201                            logger.logging(     "  Total=[" + rowNo + "]" );
202                            // 5.7.2.2 (2014/01/24) logger と?重になる為、削除
203    //                      System.err.println( "  Total=[" + rowNo + "]" );                // 5.5.4.5 (2012/07/27) 処???に結果を?力します?
204                    }
205                    catch (Throwable th) {
206                            kekka = RETURN_NG;
207    
208                            StringBuilder errMsg = new StringBuilder();
209                            errMsg.append( CR );    // 5.1.5.0 (2010/04/01) 先に改行しておきます?
210                            errMsg.append( "??タ処?に例外が発生しました?[" );
211                            errMsg.append( rowNo ).append( "]行目" ).append( CR );
212                            errMsg.append( th.getMessage() ).append( CR ) ;
213    
214                            if( model != null ) { errMsg.append( model.toString() ).append( CR ) ; }
215    
216                            for( int i=0; i<cnt; i++ ) {
217                                    HybsProcess process = list.get(i);
218                                    errMsg.append( process.toString() );
219                            }
220                            String errStr = errMsg.toString();
221                            logger.errLog( errStr,th );
222                            LogWriter.log( errStr );
223                            // 5.1.5.0 (2010/04/01) 出力が?重?重に出力されるのを回避します?
224    //                      System.out.println( errStr );
225    //                      throw new RuntimeException( errStr,th );        // 4.0.0 (2005/01/31)
226                    }
227                    finally {
228                            // 終??全ての endメソ?をコールします?
229                            logger.logging( "終???行います?" );
230                            StringBuilder buf = new StringBuilder();
231                            // 5.3.4.0 (2011/04/01) ロガーのreport()を呼びます?(タイトルを追?
232                            if( param != null ) {
233                                    buf.append( logger.report() ).append( CR );
234                                    buf.append( param.report() );
235                            }
236    
237                            boolean isOK = (kekka == RETURN_OK);
238                            for( int i=0; i<cnt; i++ ) {
239                                    HybsProcess process = list.get(i);
240                                    if( process != null ) {
241                                            buf.append( CR ).append( process.report() );
242                                            process.end( isOK );
243                                    }
244                            }
245                            // ??に、ParamProcess を終?ます?
246                            if( param  != null ) { param.end( isOK ); }             // 5.5.4.5 (2012/07/27) ??のProcessの end() の?にします?
247    
248                            buf.append( CR );
249                            logger.logging( buf.toString() );
250                            logger.logging( "実行結果は、[" + errCode(kekka) + "] です?" );
251                            long ed = System.currentTimeMillis();
252                            logger.logging( "合計???= " + (ed-st) + " (ms) です?" );
253                            logger.logging( new Date( ed ) + " 終?ました? );
254    
255    //                      // ??に、ParamProcess を終?ます?
256    //                      if( param  != null ) { param.end( isOK ); }
257                            logger.end( isOK );
258                    }
259            }
260    
261            /**
262             * 処??実行結果を返します?
263             *
264             * @return      実行結果
265             * @see #RETURN_INIT
266             */
267            public int getKekka() { return kekka; }
268    
269            /**
270             * 処?行うメインメソ?です?
271             *
272             * @og.rev 4.0.0.0 (2007/11/22) ConnDataFactory の使用を?
273             *
274             * @param       args    コマンド引数配?
275             */
276            public static void main( final String[] args ) {
277                    if( args.length == 0 ) {
278                            LogWriter.log( usage() );
279                            return ;
280                    }
281    
282                    // 引数の?
283                    List<HybsProcess> list = makeHybsProcessList( args );
284    
285                    // 特別に、LoggerProcess がなければ、標準?力を使用するロガーを登録する?
286                    HybsProcess prcs = list.get(0);
287                    if( ! (prcs instanceof LoggerProcess) ) {
288                            LoggerProcess logger = new Process_Logger();
289                            logger.setDisplayWriter( FileUtil.getLogWriter( "System.out" ) );
290                            list.add( 0,logger );
291                    }
292    
293                    // 引数リス?HybsProcessリス?を登録
294                    MainProcess process = new MainProcess();
295                    process.setList( list );
296    
297                    // 処??実行開?
298                    process.run();
299            }
300    
301            /**
302             * メインに渡された引数配? より、各 ChainProcess インスタンス を作?します?
303             *
304             * @param       args    メインに渡された引数配?
305             *
306             * @return      ChainProcessインスタンスのList
307             */
308            private static List<HybsProcess> makeHybsProcessList( final String[] args ) {
309                    ArrayList<HybsProcess> list = new ArrayList<HybsProcess>();
310    
311                    HybsProcess process = null;
312                    Argument argment = new Argument( MainProcess.class.getName() );
313                    for( int i=0; i<args.length; i++ ) {
314                            int type = argment.getArgumentType( args[i] ) ;
315    
316                            switch( type ) {
317                                    case Argument.CMNT : continue;
318                                    case Argument.ARGS :
319                                            process = (HybsProcess)StringUtil.newInstance( args[i] );
320                                            list.add( process );
321                                            break;
322                                    case Argument.PROP :
323                                            if( process != null ) {
324                                                    process.putArgument( args[i] );
325                                            }
326                                            break;
327                                    default: break;
328                            }
329                    }
330                    return list;
331            }
332    
333            /**
334             * エラーコードに対するメ?ージを返します?
335             *
336             * @param       code    エラーコー?
337             *
338             * @return      エラーコードに対するメ?ージ
339             */
340            public String errCode( final int code ) {
341                    final String errMsg ;
342                    switch( code ) {
343                            case RETURN_INIT : errMsg = "初期? ; break;
344                            case RETURN_OK   : errMsg = "正常" ; break;
345                            case RETURN_WARN : errMsg = "警? ; break;
346                            case RETURN_NG   : errMsg = "異常" ; break;
347                            default :errMsg = "未定義エラー" ; break;
348                    }
349                    return errMsg ;
350            }
351    
352            /**
353             * こ?クラスの使用方法を返します?
354             *
355             * @return      こ?クラスの使用方?
356             */
357            private static String usage() {
358    
359                    StringBuilder buf = new StringBuilder();
360    
361                    buf.append( "ChainProcess を実?た各クラスを??実行します?" ).append( CR );
362                    buf.append( "キーと値の間には、スベ?スを?れな?下さ??").append( CR ).append( CR );
363    
364                    buf.append( "Usage: java MainProcess サブChainProcessクラス [[-キー=値] ???] [???]  " ).append( CR );
365                    buf.append( "   サブChainProcessクラス ?ChainProcess を実?たクラス" ).append( CR );
366                    buf.append( "     -キー=値             ?各サブクラス毎?引数?- で始まり?= で?します?" ).append( CR );
367                    buf.append( "     -AAA=BBB             ???できます?" ).append( CR );
368                    buf.append( "   サブChainProcessクラス ???できます?" ).append( CR );
369                    buf.append( "     -CCC=DDD " ).append( CR );
370    
371                    return buf.toString();
372            }
373    }