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 */
016package org.opengion.plugin.table;
017
018import org.opengion.hayabusa.common.HybsSystemException;
019import org.opengion.hayabusa.db.AbstractTableFilter;
020import org.opengion.hayabusa.db.DBTableModel;
021import org.opengion.fukurou.util.StringUtil;
022import org.opengion.fukurou.util.ErrorMessage;
023import org.opengion.fukurou.util.ErrMsg;
024import org.opengion.hayabusa.db.DBColumn;
025import org.opengion.hayabusa.resource.ResourceFactory;
026import org.opengion.hayabusa.resource.ResourceManager;
027import static org.opengion.fukurou.system.HybsConst.CR;
028
029/**
030 * TableFilter_JUDG は、TableFilter インターフェースを継承した、DBTableModel 処理用の
031 * 実装クラスです。
032 *
033 * 必要なカラムから、判定結果(JUDG) と 判定理由(RIYU) を設定します。
034 * これは、GG10 の発生日(DY_HATU),登録キー(SET_KEY),設定グループ(SET_GRP),トークン(TOKEN) の
035 * レコードを処理して、判定結果を設定します。
036 *
037 * GG10 書き込むテーブル (必須カラム)
038 *   値データ(VAL)                 値の設定(存在、上限、下限判定)
039 *   判定結果(JUDG)                 0:未決 1:不要 2:任意 3:合格 4:保留 5:警告 6:必須 7:不合格
040 *   判定理由(RIYU)                 上限、下限で判定した結果が入っている。titleに入れてポップアップさせる
041 *
042 * GG01 トークンマスタ (GG02がnullの時)
043 *   データ型(DATA_TYPE)           EDITORを決定
044 *
045 *      GG02 雛形設定マスタ
046 *   登録方法(CDREC)                0:未決 1:不要 2:任意 4:保留 6:必須
047 *   異常下限(E_MIN)                異常値の下限判定に使用
048 *   警告下限(W_MIN)                警告値の下限判定に使用
049 *   警告上限(W_MAX)                警告値の上限判定に使用
050 *   異常上限(E_MAX)                異常値の上限判定に使用
051 *
052 * @og.formSample
053 * ●形式:
054 *      ① <og:tableFilter classId="JUDG" />
055 *
056 * @og.rev 5.6.6.0 (2013/07/05) keys の整合性チェックを追加
057 *
058 * @version  0.9.0  2000/10/17
059 * @author   Kazuhiko Hasegawa
060 * @since    JDK1.1,
061 */
062public class TableFilter_JUDG extends AbstractTableFilter {
063        /** このプログラムのVERSION文字列を設定します。   {@value} */
064        private static final String VERSION = "7.4.2.3 (2021/06/09)" ;
065
066        private int noVal               = -1;
067        private int noJudg              = -1;
068        private int noRiyu              = -1;
069
070        private int noType              = -1;
071
072        private int noCdrec             = -1;
073        private int noEmin              = -1;
074        private int noWmin              = -1;
075        private int noWmax              = -1;
076        private int noEmax              = -1;
077
078        private DBTableModel table ;
079
080        /**
081         * デフォルトコンストラクター
082         *
083         * @og.rev 6.4.1.1 (2016/01/16) keysMap を、サブクラスから設定させるように変更。
084         */
085        public TableFilter_JUDG() { super(); }
086
087        /**
088         * DBTableModel処理を実行します。
089         *
090         * @og.rev 7.3.1.1 (2021/02/25) USE_CSV 属性追加
091         * @og.rev 7.4.2.3 (2021/06/09) NUMBERやDECIMALフォーマットされているので書き戻す。
092         *
093         * @return 処理結果のDBTableModel
094         */
095        public DBTableModel execute() {
096                table = getDBTableModel();
097                if( table == null ) { return table; }                           // 6.4.0.5 (2016/01/09)
098
099                final ResourceManager resource = ResourceFactory.newInstance( "ja" ) ;
100
101                noVal   = table.getColumnNo( "VAL"                              );      // 値データ(必須)
102                noJudg  = table.getColumnNo( "JUDG"                             );      // 判定結果(必須)
103                noRiyu  = table.getColumnNo( "RIYU"                             );      // 判定理由(必須)
104                noType  = table.getColumnNo( "DATA_TYPE", false );      //
105                noCdrec = table.getColumnNo( "CDREC"    , false );      //
106                noEmin  = table.getColumnNo( "E_MIN"    , false );      //
107                noWmin  = table.getColumnNo( "W_MIN"    , false );      //
108                noWmax  = table.getColumnNo( "W_MAX"    , false );      //
109                noEmax  = table.getColumnNo( "E_MAX"    , false );      //
110
111                final int rowCnt = table.getRowCount();
112                for( int row=0; row<rowCnt; row++ ) {
113                        final String[] data  = table.getValues( row );
114
115                        final String val     = data[noVal] ;
116                        final String orgJudg = data[noJudg];                                    // 現在の判定結果をキープ(4:保留対応)
117                        final String cdrec   = rowData( row,noCdrec ,"0" );             // 登録方法 0:未決 1:不要 2:任意 4:保留 6:必須
118                        // データが未設定の場合か、1:不要 2:任意 の場合は、登録方法(CDREC) をそのままセットする。
119                        if( val== null || val.isEmpty() || "1".equals( cdrec ) || "2".equals( cdrec ) ) {
120                                data[noJudg] = cdrec;
121                        }
122                        else {
123                                // 判定結果(JUDG) 0:未決 1:不要 2:任意 3:合格 4:保留 5:警告 6:必須 7:不合格
124                                final String dbType= rowData( row,noType,"TP_TEXT" );           // DBタイプ 未指定時は、TP_TEXT:テキスト
125                                if( "TP_ON".equals( dbType ) ) {                                                        // TP_ON : 0:未決 1:OK 2:NG (3:保留)
126                                        if(      "1".equals( val ) ){ data[noJudg] = "3"; }             // 3:合格
127                                        else if( "0".equals( val ) ){ data[noJudg] = "0"; }             // 0:未決
128                                        else if( "3".equals( val ) ){ data[noJudg] = "4"; }             // (3:保留) は使われていないが、あれば、4:保留
129                                        else                                            { data[noJudg] = "7"; }         // 7:不合格
130                                }
131                                else if( "TP_CHECK".equals( dbType ) ) {                                        // TP_CHECK : 1:チェック 0:未
132                                        if(      "1".equals( val ) )    { data[noJudg] = "3"; } // 3:合格
133                //                      else if( "6".equals( cdrec ) )  { data[noJudg] = "6"; } // 合格以外で、登録方法が 6:必須 の場合は、6:必須 をセット
134                                        else                                            { data[noJudg] = cdrec; }       // 合格以外は、登録方法(CDREC) をそのままセット
135                                }
136                                else if( "TP_INT".equals( dbType ) || "TP_REAL".equals( dbType ) ) {
137                                        final double emin = rowData( row,noEmin,Double.NEGATIVE_INFINITY );             // 異常下限(E_MIN)
138                                        final double wmin = rowData( row,noWmin,Double.NEGATIVE_INFINITY );             // 警告下限(W_MIN)
139                                        final double wmax = rowData( row,noWmax,Double.POSITIVE_INFINITY );             // 警告上限(W_MAX)
140                                        final double emax = rowData( row,noEmax,Double.POSITIVE_INFINITY );             // 異常上限(E_MAX)
141
142                                        try {
143                                                final String numVal = StringUtil.deleteChar( val,',' );                         // 7.4.2.3 (2021/06/09) NUMBERやDECIMALフォーマットされているので。
144//                                              final double wval = Double.parseDouble( val );          // DBタイプが、TP_INTかTP_REALなので数値変換出来る
145                                                final double wval = Double.parseDouble( numVal );       // DBタイプが、TP_INTかTP_REALなので数値変換出来る
146
147                                                // 厳しい方からチェックする。
148                                                if( emin > wval ) {                     // 異常下限(E_MIN)より小さい
149                                                        data[noJudg] = "7";             // 7:不合格
150                                                        data[noRiyu] = String.format( "下限値(%.2f)異常 [ > %.2f ]" ,emin,wval );
151                                                }
152                                                else if( emax < wval ) {        // 異常上限(E_MAX)より大きい
153                                                        data[noJudg] = "7";             // 7:不合格
154                                                        data[noRiyu] = String.format( "上限値(%.2f)異常 [ < %.2f ]" ,emax,wval );
155                                                }
156                                                else if( wmin > wval ) {        // 警告下限(W_MIN)より小さい
157                                                        data[noJudg] = "5";             // 5:警告
158                                                        data[noRiyu] = String.format( "下限値(%.2f)警告 [ > %.2f ]" ,wmin,wval );
159                                                }
160                                                else if( wmax < wval ) {        // 警告上限(W_MAX)より大きい
161                                                        data[noJudg] = "5";             // 5:警告
162                                                        data[noRiyu] = String.format( "上限値(%.2f)警告 [ < %.2f ]" ,wmax,wval );
163                                                }
164                                                else {
165                                                        data[noJudg] = "3";             // 3:合格
166                                                        data[noRiyu] = "";              // 判定理由のクリア
167                                                }
168
169                                                data[noVal] = numVal ;          // 7.4.2.3 (2021/06/09) NUMBERやDECIMALフォーマットされているので書き戻す。
170                                        }
171                                        catch( final NumberFormatException ex ) {
172                                                data[noJudg] = "7";                     // 7:不合格
173                                                data[noRiyu] = "数値変換エラー " + val ;
174                                        }
175                                }
176                                // TP_ON,TP_CHECK,TP_INT,TP_REAL 以外はDBTyleで値のチェックを行う。
177                                else {
178                                        final DBColumn clm = resource.makeDBColumn( dbType );
179
180                                        try {
181                                                data[noVal] = clm.valueSet( val ) ;             // 7.4.2.3 (2021/06/09) 実登録データを作成して、書き戻す。
182                                        }
183                                        catch( RuntimeException ex ) {
184                                                ;       // #valueSet(String) で、エラーが発生した場合でも、#valueCheck(String) を行うようにします。
185                                        }
186
187                                        // エラーチェック。 正常時は null
188                                        final ErrorMessage errMsg = clm.valueCheck( val,false );                        // 厳密にチェックしない
189                                        if( errMsg == null || errMsg.isOK() ) {
190                                                data[noJudg] = "3";             // 3:合格
191                                                data[noRiyu] = "";              // 判定理由のクリア
192                                        }
193                                        else {
194                                                final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE )
195                                                                                .append( "<div class='small'>" );
196
197                                                for( final ErrMsg err : errMsg.toArray() ) {
198                                                        buf.append( resource.getShortErrorMsg( err ) );
199                                                }
200                                                data[noRiyu] = buf.append( "</div>" ).toString();
201
202                                                if( errMsg.getKekka() == ErrorMessage.WARNING ) {
203                                                        data[noJudg] = "5";             // 5:警告
204                                                }
205                                                else {                                          // errMsg.getKekka() >= ErrorMessage.NG だが、警告以外はエラーにします。
206                                                        data[noJudg] = "7";             // 7:不合格
207                                                }
208                                        }
209                                }
210                        }
211
212                        // オリジナルの判定結果が、4:保留 で、5:警告か7:不合格 の場合は、4:保留 のままにしておく。
213                        if( "4".equals( orgJudg ) && ( "5".equals( data[noJudg] ) || "7".equals( data[noJudg] ) ) ) {
214                                data[noJudg] = "4";             // 4:保留
215                        }
216                }
217
218                return table;
219        }
220
221        /**
222         * DBTableModelから、指定行-列のデータを取得します。
223         *
224         * 列番号がマイナスの場合は、カラムが存在していないため、初期値を返します。
225         *
226         * @og.rev 7.3.1.1 (2021/02/25) USE_CSV 属性追加
227         *
228         * @param       row 行
229         * @param       col 列
230         * @param       defVal 初期値(文字列)
231         *
232         * @return 指定行-列のデータ(文字列)
233         */
234        private String rowData( final int row , final int col , final String defVal ) {
235                String rtn = defVal ;
236                if( col >= 0 ) {
237                        final String str = table.getValue( row,col );
238                        if( str != null && !str.isEmpty()) {
239                                rtn = str ;
240                        }
241                }
242                return rtn ;
243        }
244
245        /**
246         * DBTableModelから、指定行-列のデータを取得します。
247         *
248         * 列番号がマイナスの場合は、カラムが存在していないため、初期値を返します。
249         *
250         * @og.rev 7.3.1.1 (2021/02/25) USE_CSV 属性追加
251         *
252         * @param       row 行
253         * @param       col 列
254         * @param       defVal 初期値(数値)
255         *
256         * @return 指定行-列のデータ(数値)
257         */
258        private double rowData( final int row , final int col , final double defVal ) {
259                final String val = col < 0 ? null : table.getValue( row,col ) ;
260
261                try {
262                        return val == null || val.isEmpty() ? defVal : Double.parseDouble( val );
263                }
264                catch( final NumberFormatException ex ) {
265                        final String errMsg = "数値項目の数値変換エラー 行=" + row + " , 列=" + col + " , 値=" + val ;
266                        throw new HybsSystemException( errMsg,ex );
267                }
268        }
269}