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.Arrays;
019import java.util.List;
020import java.util.ArrayList;
021import java.util.Map;                                           // Collections.unmodifiableMap で使用
022import java.util.HashMap;                                       // Collections.unmodifiableMap で使用
023import java.util.StringJoiner;
024import java.util.Collections;
025import java.util.concurrent.ConcurrentMap;
026import java.util.concurrent.ConcurrentHashMap;
027
028import static org.opengion.fukurou.fileexec.CommandLine.GE70.* ;                // enum を簡素化して使用するための定義
029
030/**
031 * CommandLine は、コマンドリストを管理するクラスです。
032 *
033 *<pre>
034 * コマンドリストは、GE70 テーブルからコマンドを取り出します。
035 *
036 * このクラスは、マルチスレッドに対応していません。
037 *</pre>
038 * @og.rev 7.0.0.0 (2017/07/07) 新規作成
039 *
040 * @version  7.0
041 * @author   Kazuhiko Hasegawa
042 * @since    JDK1.8,
043 */
044public final class CommandLine {
045        private static final XLogger LOGGER= XLogger.getLogger( CommandLine.class.getName() );          // ログ出力
046
047        /** GE70 テーブルのカラム定義の enum */
048        public static enum GE70 {
049                /** GE70 テーブルから検索するカラム名 */
050                SYSTEM_ID,RSRV_NO,NAME_JA,EXECID,FGYKAN,DIR_BASE,DIR_SUB,DIR_WORK,DIR_BKUP_OK,DIR_BKUP_NG,FILE_FILTER ;
051
052                /** order by で、予約番号(RSRV_NO)順に処理されるようにしておきます。 */
053                // 取込予約フラグ 1:登録 2:済 3:実行中 4:停止 5:保留
054                // 起動直後に処理する条件。3:実行中 を含む
055                private static final String FROM_WHERE = " from GE70 where FGJ='1' and FGYKAN in " ;
056
057                // 取込予約フラグ 1:登録 2:済 3:実行中 4:停止 5:保留
058                // 通常のループ時に処理する条件
059                private static final String ORDER_BY = " order by SYSTEM_ID,RSRV_NO" ;
060
061                private static final String FGYKAN1 = "('1','3','4')" ; // 起動直後
062                private static final String FGYKAN2 = "('1','4')" ;             // ループ処理
063
064                /** 列挙子のカンマ区切り文字列 のキャッシュ  */
065                public static final String SELECT1 ;            // 起動直後
066                public static final String SELECT2 ;            // ループ処理
067                static {
068                        final StringJoiner sj = new StringJoiner( "," , "select " , FROM_WHERE );
069                        Arrays.stream( values() ).forEachOrdered( v -> sj.add( v.name() ) );
070                        SELECT1 = sj.toString() + FGYKAN1 + ORDER_BY ;
071                        SELECT2 = sj.toString() + FGYKAN2 + ORDER_BY ;
072                }
073
074                /** 列挙子の序数(カラムの並び順) */
075                public final int NO ;
076
077                /** private コンストラクター */
078                private GE70() { NO = ordinal(); }
079        };
080
081        // 予約フラグ は、値に応じて、セットする値が異なる。
082        /** Collections.unmodifiableMap を使用。 */
083        @SuppressWarnings( "serial" )
084        private static final Map<String,String> IN2OUT = Collections.unmodifiableMap(
085                new HashMap<String, String>() {{
086                        put( "1" , "3" );               // 1:登録 → 3:実行中
087                        put( "4" , "2" );               // 4:停止 → 2:済
088        }});
089
090        // GE70 で、IN2OUT に対応した予約フラグ を更新します。
091        private static final String[] UPD_KEYS  = new String[] { "FGYKAN","DYUPD","PGUPD" };
092        private static final String   UPD_WHERE = "SYSTEM_ID=? and RSRV_NO=? and FGJ='1'";
093
094        private static final String UPD_QUER = DBUtil.getUpdateSQL( "GE70",UPD_KEYS,null,null,UPD_WHERE );
095
096        private final String[]          cmndData        ;
097        private final String            cmndStr         ;                       // toString() 時に使用する、cmndList の文字列表現
098
099        private final ConcurrentMap<String,String> kvMap = new ConcurrentHashMap<>();   // パラメータ(key1=val1 key2=val2 ・・・ のリスト)のMap
100
101        /**
102         * データを引数にとるコンストラクタ
103         * 
104         * SYSTEM_ID,RSRV_NO,NAME_JA,EXECID,FGYKAN,DIR_BASE,DIR_SUB,DIR_WORK,DIR_BKUP_OK,DIR_BKUP_NG,FILE_FILTER
105         * システムID,予約番号,名称,処理ID,取込予約フラグ,取込ベースフォルダ,取込サブフォルダ,処理フォルダ(WORK),処理済フォルダ(正常),処理済フォルダ(異常),検索条件 を
106         * 文字列として順番に持っています。
107         *
108         * @og.rev 6.8.1.5 (2017/09/08) LOGGER.debug 情報の追加
109         *
110         * @param       values  データ
111         * @throws      RuntimeException 引数に不整合があった場合。
112         */
113        private CommandLine( final String[] values ) {
114                cmndData = Arrays.copyOf( values, values.length );
115
116                cmndStr = Arrays.toString( cmndData );
117                LOGGER.debug( () -> "① values=" + cmndStr );
118
119                if( cmndData[RSRV_NO.NO] == null || cmndData[EXECID.NO] == null ) {
120                        // MSG2001 = コマンドリストに、予約番号,取込ID,処理IDは必須です。[{0}]
121                        throw MsgUtil.throwException( "MSG2001" , cmndStr );
122                }
123
124                // key=val のパラメータ文字列を、Map化します。
125                final String filter = cmndData[FILE_FILTER.NO];                                         // 検索条件となるフィルター情報
126                if( filter != null && !filter.trim().isEmpty() && filter.indexOf( '=' ) >= 0 ) {
127                        // 6番目のparamsは、key=valの羅列 
128                        for( final String kvStr : filter.split( " " ) ) {                               // スペースで分割
129                                final int ad = kvStr.indexOf( '=' );                                            // key=val を見つける。
130                                if( ad > 0 ) {
131                                        final String key = kvStr.substring( 0,ad ).trim();
132                                        final String val = kvStr.substring( ad+1 ).trim();
133                                        if( !key.isEmpty() ) { kvMap.put( key , val ); }                // keyが空文字の場合は、無視
134                                }
135                        }
136                }
137        }
138
139        /**
140         * 設定値を返します。
141         *
142         * @param       clm GE70テーブルを定義したenum
143         * @return      設定値
144         */
145        public String getValue( final GE70 clm ) { return cmndData[ clm.NO ]; }
146
147        /**
148         * パラメータ(key1=val1 key2=val2 ・・・ のリスト)のMapを返します。
149         *
150         * @return      パラメータ(key1=val1 key2=val2 ・・・ のリスト)のMap
151         * @og.rtnNotNull
152         */
153        public ConcurrentMap<String,String> getKeyValMap() { return kvMap ; }
154
155        /**
156         * 指定のGE70テーブルを読み込んで、CommandLineオブジェクトのListを作成します。
157         *
158         * @param       isFirst 起動直後の初期処理かどうかの判定フラグ(起動直後は、true)
159         * @return      CommandLineオブジェクトのList
160         */
161        public static List<CommandLine> dbCommand( final boolean isFirst) {
162                final List<CommandLine> cmndList = new ArrayList<>();
163
164                // 更新用の値
165                final List<String[]> upddbData = new ArrayList<>();
166                final String NOW  = StringUtil.getTimeFormat();
167                final String PGID = "CMNDLine";
168
169                final List<String[]> cmdRow = DBUtil.dbQuery( isFirst ? SELECT1 : SELECT2 );    // GE70.SELECT
170                for( final String[] cmdClms : cmdRow ) {
171                        cmndList.add( new CommandLine( cmdClms ) );
172
173                        final String fgKan = IN2OUT.get( cmdClms[FGYKAN.NO] );                  // 予約フラグ
174                        if( fgKan != null ) {                           // 予約フラグ が、対象の場合。
175                                // 予約フラグを、IN2OUT で変換した値に更新します。
176                                // M_FileExec テーブルの更新カラム
177                                final String[] updVals = new String[] {
178                                          fgKan                                         // 予約フラグ                       FGYKAN
179                                        , NOW                                           // 更新日時                 DYUPD
180                                        , PGID                                          // 更新PG                 PGUPD
181                                        , cmdClms[SYSTEM_ID.NO]         // システムID                       SYSTEM_ID
182                                        , cmdClms[RSRV_NO.NO]           // 予約番号                 RSRV_NO
183                                } ;
184                                upddbData.add( updVals );
185                        }
186                }
187
188                if( ! upddbData.isEmpty() ) {
189                        DBUtil.execute( UPD_QUER , upddbData );
190                }
191
192                return cmndList ;
193        }
194
195        /**
196         *コマンドリストクラスの文字列表現を返します。
197         *
198         * @return      コマンドリストクラスの文字列表現
199         */
200        @Override
201        public String toString() { return cmndStr ; }
202}