001/*
002 * Copyright (c) 2017 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.fileexec;
017
018import java.util.concurrent.ConcurrentMap;
019import java.util.concurrent.ConcurrentHashMap;
020import java.util.StringJoiner;
021import java.util.Arrays;
022import java.util.List;
023import java.nio.file.Path;
024
025import org.opengion.fukurou.util.StringUtil;
026
027/**
028 * AppliExec は、アプリケーションの実行を行う共通の処理クラスです。
029 *
030 *<pre>
031 *
032 * ここでは、GE72の処理IDに応じた方法で実行します。
033 *
034 *</pre>
035 *
036 * @og.rev 7.0.0.0 (2017/07/07) 新規作成
037 *
038 * @version  7.0
039 * @author   Kazuhiko Hasegawa
040 * @since    JDK1.8,
041 */
042public final class AppliExec {
043        private static final XLogger LOGGER= XLogger.getLogger( AppliExec.class.getName() );            // ログ出力
044
045        /** GE72 テーブルのカラム定義の enum */
046        public static enum GE72 {
047                /** GE72 テーブルから検索するカラム名 */
048                RUNTYPE,RUNPG,CLMS,PARAMS,DBID,TABLE_NAME,SHT_NOS,FILE_ENC,SKIP_CNT ;
049
050                /** order by で、開始日時(ST_TIME)順に処理されるようにしておきます。 */
051                private static final String FROM_WHERE = " from GE72 where SYSTEM_ID=? and EXECID=? and FGJ='1'" ;              // 1件のみのはず
052
053                /** 列挙子のカンマ区切り文字列 のキャッシュ  */
054                public static final String SELECT ;
055                static {
056                        final StringJoiner sj = new StringJoiner( "," , "select " , FROM_WHERE );
057                        Arrays.stream( values() ).forEachOrdered( v -> sj.add( v.name() ) );
058                        SELECT = sj.toString();
059                }
060
061                /** 列挙子の序数(カラムの並び順) */
062                public final int NO ;
063
064                /** private コンストラクター */
065                private GE72() { NO = ordinal(); }
066        };
067
068        private static final ConcurrentMap<String,AppliExec> APP_EXEC_MAP = new ConcurrentHashMap<>();
069
070        private final String[] ge72Data ;
071
072        private final RunExec runexec ;                 // これもキャッシュできますが、とりあえず動くまでは毎回作成します。
073
074        /**
075         * private コンストラクタ
076         *
077         * @og.rev 6.8.1.5 (2017/09/08) LOGGER.debug 情報の追加
078         *
079         * @param       systemId        システムID
080         * @param       execId  処理ID
081         */
082        private AppliExec( final String systemId , final String execId ) {
083                LOGGER.debug( () -> "⑥ systemId=" + systemId + " , execId=" + execId );
084
085                final List<String[]> cmdRow = DBUtil.dbQuery( GE72.SELECT , systemId , execId );
086
087                if( cmdRow.isEmpty() ) {
088                        // MSG2001 = コマンドリストに、予約番号,取込ID,処理IDは必須です。[{0}]
089                        throw MsgUtil.throwException( "MSG2001" , "SYSTEM_ID=" + systemId + " , EXECID=" + execId );
090                }
091
092                ge72Data = cmdRow.get(0);               // 1件のみのはず
093                final String type = ge72Data[GE72.RUNTYPE.NO];
094
095                final String key ;
096                switch( type ) {
097                        case "0" : key = "NONE";        break;                  // なにもしない
098                        case "1" : key = "DBIN";        break;                  // DB入力
099                        case "2" : key = "PLSQL";       break;                  // PL/SQLコール
100                        case "3" : key = "BAT";         break;                  // BATファイルコール
101                        case "4" : key = "JSP";         break;                  // JSPファイルコール(URLコネクション)
102                        default  : key = null;          break;                  // なにもしない(runTypeなしエラー)
103                }
104
105                if( key == null ) {
106                        // MSG2002 = RUNTYPEに対応するRunExec実装クラスがありません。[{0}]
107                        throw MsgUtil.throwException( "MSG2002" , "RUNTYPE=" + type + " , systemId=" + systemId + " , execId=" + execId );
108                }
109
110                runexec = (RunExec)StringUtil.newInstance( "org.opengion.fukurou.fileexec.RunExec_" + key );
111        }
112
113        /**
114         * システムIDと処理IDから、対応するAppliExecオブジェクトを返します。
115         *
116         * AppliExecオブジェクトを、動的に作成します。
117         * このメソッドは、ClassNotFoundException を拾うために、用意した簡易メソッドです。
118         *
119         * 何らかの Exception が、throw された場合は、null を返します。
120         *
121         * @param       systemId        システムID
122         * @param       execId  処理ID
123         * @return      AppliDataオブジェクト(作成できなければ、null)
124         */
125        public static AppliExec newInstance( final String systemId , final String execId ) {
126                final String mapKey = systemId + "_" + execId ;
127
128                return APP_EXEC_MAP.computeIfAbsent( mapKey , key -> new AppliExec( systemId,execId ) );
129        }
130
131        /**
132         * GE72.RUNTYPE に基づいて、各種処理を実行します。
133         *
134         * @og.rev 6.8.1.5 (2017/09/08) LOGGER.debug 情報の追加
135         * 
136         * @param       path 処理するファイルパス
137         * @return      処理件数(正は成功、マイナスは異常時の行番号)
138         */
139        public int exec( final Path path ) {
140                LOGGER.debug( () -> "⑦ exec() : Path=" + path + " , runType=" + ge72Data[GE72.RUNTYPE.NO] );
141
142                return runexec.exec( path,ge72Data ) ;
143        }
144}