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;
027// import static org.opengion.fukurou.system.HybsConst.CR;                                              // 8.0.0.0 (2021/07/31) Delete
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 = "8.0.0.0 (2021/08/20)" ;
065
066        // 8.0.0.0 (2021/07/31) ローカル変数に置き換え可能
067//      private int noVal               = -1;
068//      private int noJudg              = -1;
069//      private int noRiyu              = -1;
070
071//      private int noType              = -1;
072
073//      private int noCdrec             = -1;
074//      private int noEmin              = -1;
075//      private int noWmin              = -1;
076//      private int noWmax              = -1;
077//      private int noEmax              = -1;
078
079        private DBTableModel table ;
080
081        /**
082         * デフォルトコンストラクター
083         *
084         * @og.rev 6.4.1.1 (2016/01/16) keysMap を、サブクラスから設定させるように変更。
085         */
086        public TableFilter_JUDG() { super(); }
087
088        /**
089         * DBTableModel処理を実行します。
090         *
091         * @og.rev 7.3.1.1 (2021/02/25) USE_CSV 属性追加
092         * @og.rev 7.4.2.3 (2021/06/09) NUMBERやDECIMALフォーマットされているので書き戻す。
093         *
094         * @return 処理結果のDBTableModel
095         */
096        public DBTableModel execute() {
097                table = getDBTableModel();
098                if( table == null ) { return table; }                           // 6.4.0.5 (2016/01/09)
099
100                final ResourceManager resource = ResourceFactory.newInstance( "ja" ) ;
101
102                final  int noVal        = table.getColumnNo( "VAL"                              );      // 値データ(必須)
103                final  int noJudg       = table.getColumnNo( "JUDG"                             );      // 判定結果(必須)
104                final  int noRiyu       = table.getColumnNo( "RIYU"                             );      // 判定理由(必須)
105                final  int noType       = table.getColumnNo( "DATA_TYPE", false );      //
106                final  int noCdrec      = table.getColumnNo( "CDREC"    , false );      //
107                final  int noEmin       = table.getColumnNo( "E_MIN"    , false );      //
108                final  int noWmin       = table.getColumnNo( "W_MIN"    , false );      //
109                final  int noWmax       = table.getColumnNo( "W_MAX"    , false );      //
110                final  int noEmax       = table.getColumnNo( "E_MAX"    , false );      //
111
112                final int rowCnt = table.getRowCount();
113                for( int row=0; row<rowCnt; row++ ) {
114                        final String[] data  = table.getValues( row );
115
116                        final String val     = data[noVal] ;
117                        final String orgJudg = data[noJudg];                                    // 現在の判定結果をキープ(4:保留対応)
118                        final String cdrec   = rowData( row,noCdrec ,"0" );             // 登録方法 0:未決 1:不要 2:任意 4:保留 6:必須
119                        // データが未設定の場合か、1:不要 2:任意 の場合は、登録方法(CDREC) をそのままセットする。
120                        if( val== null || val.isEmpty() || "1".equals( cdrec ) || "2".equals( cdrec ) ) {
121                                data[noJudg] = cdrec;
122                        }
123                        else {
124                                // 判定結果(JUDG) 0:未決 1:不要 2:任意 3:合格 4:保留 5:警告 6:必須 7:不合格
125                                final String dbType= rowData( row,noType,"TP_TEXT" );           // DBタイプ 未指定時は、TP_TEXT:テキスト
126                                if( "TP_ON".equals( dbType ) ) {                                                        // TP_ON : 0:未決 1:OK 2:NG (3:保留)
127                                        if(      "1".equals( val ) ){ data[noJudg] = "3"; }             // 3:合格
128                                        else if( "0".equals( val ) ){ data[noJudg] = "0"; }             // 0:未決
129                                        else if( "3".equals( val ) ){ data[noJudg] = "4"; }             // (3:保留) は使われていないが、あれば、4:保留
130                                        else                                            { data[noJudg] = "7"; }         // 7:不合格
131                                }
132                                else if( "TP_CHECK".equals( dbType ) ) {                                        // TP_CHECK : 1:チェック 0:未
133                                        if(      "1".equals( val ) )    { data[noJudg] = "3"; } // 3:合格
134                //                      else if( "6".equals( cdrec ) )  { data[noJudg] = "6"; } // 合格以外で、登録方法が 6:必須 の場合は、6:必須 をセット
135                                        else                                            { data[noJudg] = cdrec; }       // 合格以外は、登録方法(CDREC) をそのままセット
136                                }
137                                else if( "TP_INT".equals( dbType ) || "TP_REAL".equals( dbType ) ) {
138                                        final double emin = rowData( row,noEmin,Double.NEGATIVE_INFINITY );             // 異常下限(E_MIN)
139                                        final double wmin = rowData( row,noWmin,Double.NEGATIVE_INFINITY );             // 警告下限(W_MIN)
140                                        final double wmax = rowData( row,noWmax,Double.POSITIVE_INFINITY );             // 警告上限(W_MAX)
141                                        final double emax = rowData( row,noEmax,Double.POSITIVE_INFINITY );             // 異常上限(E_MAX)
142
143                                        try {
144                                                final String numVal = StringUtil.deleteChar( val,',' );                         // 7.4.2.3 (2021/06/09) NUMBERやDECIMALフォーマットされているので。
145//                                              final double wval = Double.parseDouble( val );          // DBタイプが、TP_INTかTP_REALなので数値変換出来る
146                                                final double wval = Double.parseDouble( numVal );       // DBタイプが、TP_INTかTP_REALなので数値変換出来る
147
148                                                // 厳しい方からチェックする。
149                                                if( emin > wval ) {                     // 異常下限(E_MIN)より小さい
150                                                        data[noJudg] = "7";             // 7:不合格
151                                                        data[noRiyu] = String.format( "下限値(%.2f)異常 [ > %.2f ]" ,emin,wval );
152                                                }
153                                                else if( emax < wval ) {        // 異常上限(E_MAX)より大きい
154                                                        data[noJudg] = "7";             // 7:不合格
155                                                        data[noRiyu] = String.format( "上限値(%.2f)異常 [ < %.2f ]" ,emax,wval );
156                                                }
157                                                else if( wmin > wval ) {        // 警告下限(W_MIN)より小さい
158                                                        data[noJudg] = "5";             // 5:警告
159                                                        data[noRiyu] = String.format( "下限値(%.2f)警告 [ > %.2f ]" ,wmin,wval );
160                                                }
161                                                else if( wmax < wval ) {        // 警告上限(W_MAX)より大きい
162                                                        data[noJudg] = "5";             // 5:警告
163                                                        data[noRiyu] = String.format( "上限値(%.2f)警告 [ < %.2f ]" ,wmax,wval );
164                                                }
165                                                else {
166                                                        data[noJudg] = "3";             // 3:合格
167                                                        data[noRiyu] = "";              // 判定理由のクリア
168                                                }
169
170                                                data[noVal] = numVal ;          // 7.4.2.3 (2021/06/09) NUMBERやDECIMALフォーマットされているので書き戻す。
171                                        }
172                                        catch( final NumberFormatException ex ) {
173                                                data[noJudg] = "7";                     // 7:不合格
174                                                data[noRiyu] = "数値変換エラー " + val ;
175                                        }
176                                }
177                                // TP_ON,TP_CHECK,TP_INT,TP_REAL 以外はDBTyleで値のチェックを行う。
178                                else {
179                                        final DBColumn clm = resource.makeDBColumn( dbType );
180
181                                        try {
182                                                data[noVal] = clm.valueSet( val ) ;             // 7.4.2.3 (2021/06/09) 実登録データを作成して、書き戻す。
183                                        }
184                                        catch( RuntimeException ex ) {
185                                                System.err.println( ex.getMessage() );  // 8.0.0.0 (2021/07/31)
186//                                              ;       // #valueSet(String) で、エラーが発生した場合でも、#valueCheck(String) を行うようにします。
187                                        }
188
189                                        // エラーチェック。 正常時は null
190                                        final ErrorMessage errMsg = clm.valueCheck( val,false );                        // 厳密にチェックしない
191                                        if( errMsg == null || errMsg.isOK() ) {
192                                                data[noJudg] = "3";             // 3:合格
193                                                data[noRiyu] = "";              // 判定理由のクリア
194                                        }
195                                        else {
196                                                final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE )
197                                                                                .append( "<div class='small'>" );
198
199                                                for( final ErrMsg err : errMsg.toArray() ) {
200                                                        buf.append( resource.getShortErrorMsg( err ) );
201                                                }
202                                                data[noRiyu] = buf.append( "</div>" ).toString();
203
204                                                if( errMsg.getKekka() == ErrorMessage.WARNING ) {
205                                                        data[noJudg] = "5";             // 5:警告
206                                                }
207                                                else {                                          // errMsg.getKekka() >= ErrorMessage.NG だが、警告以外はエラーにします。
208                                                        data[noJudg] = "7";             // 7:不合格
209                                                }
210                                        }
211                                }
212                        }
213
214                        // オリジナルの判定結果が、4:保留 で、5:警告か7:不合格 の場合は、4:保留 のままにしておく。
215                        if( "4".equals( orgJudg ) && ( "5".equals( data[noJudg] ) || "7".equals( data[noJudg] ) ) ) {
216                                data[noJudg] = "4";             // 4:保留
217                        }
218                }
219
220                return table;
221        }
222
223        /**
224         * DBTableModelから、指定行-列のデータを取得します。
225         *
226         * 列番号がマイナスの場合は、カラムが存在していないため、初期値を返します。
227         *
228         * @og.rev 7.3.1.1 (2021/02/25) USE_CSV 属性追加
229         * @og.rev 8.0.0.0 (2021/08/20) spotbugs:Bug kind and pattern: UwF - UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR
230         *
231         * @param       row 行
232         * @param       col 列
233         * @param       defVal 初期値(文字列)
234         *
235         * @return 指定行-列のデータ(文字列)
236         */
237        private String rowData( final int row , final int col , final String defVal ) {
238                String rtn = defVal ;
239//              if( col >= 0 ) {
240                if( col >= 0 && table != null ) {               // 8.0.0.0 (2021/08/20) spotbugs
241                        final String val = table.getValue( row,col );
242                        if( val != null && !val.isEmpty()) {
243                                rtn = val ;
244                        }
245                }
246                return rtn ;
247        }
248
249        /**
250         * DBTableModelから、指定行-列のデータを取得します。
251         *
252         * 列番号がマイナスの場合は、カラムが存在していないため、初期値を返します。
253         *
254         * @og.rev 7.3.1.1 (2021/02/25) USE_CSV 属性追加
255         * @og.rev 8.0.0.0 (2021/08/20) spotbugs:Bug kind and pattern: UwF - UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR
256         *
257         * @param       row 行
258         * @param       col 列
259         * @param       defVal 初期値(数値)
260         *
261         * @return 指定行-列のデータ(数値)
262         */
263        private double rowData( final int row , final int col , final double defVal ) {
264                double rtn = defVal ;
265                if( col >= 0 && table != null ) {               // 8.0.0.0 (2021/08/20) spotbugs
266                        final String val = table.getValue( row,col );
267                        if( val != null && !val.isEmpty()) {
268                                try {
269                                        rtn = Double.parseDouble( val ) ;
270                                }
271                                catch( final NumberFormatException ex ) {
272                                        final String errMsg = "数値項目の数値変換エラー 行=" + row + " , 列=" + col + " , 値=" + val ;
273                                        throw new HybsSystemException( errMsg,ex );
274                                }
275                        }
276                }
277                return rtn ;
278
279//              final String val = col < 0 ? null : table.getValue( row,col ) ;
280//
281//              try {
282//                      return val == null || val.isEmpty() ? defVal : Double.parseDouble( val );
283//              }
284//              catch( final NumberFormatException ex ) {
285//                      final String errMsg = "数値項目の数値変換エラー 行=" + row + " , 列=" + col + " , 値=" + val ;
286//                      throw new HybsSystemException( errMsg,ex );
287//              }
288        }
289}