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.fukurou.business;
017
018import org.opengion.fukurou.util.ErrorMessage;
019import org.opengion.fukurou.model.DataModel;                            // 6.7.9.1 (2017/05/19)
020import org.opengion.fukurou.system.OgRuntimeException ;         // 6.4.2.0 (2016/01/29)
021
022/**
023 * 配列型テーブルモデルをメインカーソルとした業務ロジックの構造を定義します。
024 *
025 * 配列型テーブルモデルについては、setTable( ArrayTableModel )によりセットします。
026 * 配列型テーブルモデルが定義されていない場合、エラーとなります。
027 *
028 * このクラスでは、以下に示すメソッドが呼び出されるタイミングのみを定義しています。
029 * メソッドの中身については、サブクラスでオーバーライドし実装して下さい。
030 *
031 * 処理が途中で中断される条件は、以下の3つです。
032 * ①各メソッドの戻り値がfalseの場合
033 * ②チェックメソッド(chk***())が全ての行で実行された後、エラーメッセージに"エラー"が含まれている場合
034 * ③実行時エラーが発生した場合
035 *
036 *  fstchk()              変更区分に関わらず   処理を始める前に呼び出し
037 *    8.0.2.0 (2021/11/30) 行単位ロジックチェックは廃止
038 * <del>useLoop == true
039 *        befchk( int row ) 変更区分に関わらず   各行について呼び出し(insert,modify,deleteの前に呼び出し)
040 *        inschk( int row ) 変更区分が"A"の場合 各行について呼び出し
041 *        modchk( int row ) 変更区分が"C"の場合 各行について呼び出し
042 *        delchk( int row ) 変更区分が"D"の場合 各行について呼び出し
043 *        allchk( int row ) 変更区分に関わらず   各行について呼び出し(insert,modify,deleteの後に呼び出し)
044 * </del>
045 *  first()                       変更区分に関わらず   最初の行でのみ呼び出し
046 *    useLoop == true
047 *      befall( int row ) 変更区分に関わらず   各行について呼び出し(insert,modify,deleteの前に呼び出し)
048 *      insert( int row ) 変更区分が"A"の場合 各行について呼び出し
049 *      modify( int row ) 変更区分が"C"の場合 各行について呼び出し
050 *      delete( int row ) 変更区分が"D"の場合 各行について呼び出し
051 *      allrow( int row ) 変更区分に関わらず   各行について呼び出し(insert,modify,deleteの後に呼び出し)
052 *  last()            変更区分に関わらず   最後の行でのみ呼び出し
053 *
054 * ※ インデックス(row)とは、このArrayTableModel に持つ vals 配列の行のインデックスです。
055 * よって、オリジナルのDBTableModelの行番号ではありません。
056 *
057 * 8.0.2.0 (2021/11/30) 行単位ロジックチェックは廃止。
058 *  befchk,inschk,modchk,delchk,allchk
059 *  必要であれば、fstchk() で、DataModel を取得して処理してください。
060 *
061 * @og.rev 5.1.1.0 (2009/12/01) 新規作成
062 * @og.group 業務ロジック
063 *
064 * @version 5.0
065 * @author Hiroki Nakamura
066 * @since JDK1.6,
067 */
068public class BizLogic_TABLE extends AbstractBizLogic {
069        private boolean useLoop = true;                         // 6.8.5.0 (2018/01/09) ループを回すかどうかを引数で指定します。
070
071        /**
072         * デフォルトコンストラクター
073         *
074         * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor.
075         */
076        public BizLogic_TABLE() { super(); }            // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。
077
078        /**
079         * 処理のメインロジックの前処理を記述します。
080         * (ここでは何もしません)
081         *
082         * このメソッド自体は、protected属性であるため、サブクラスから直接参照することができます。
083         * 但し、これは、各業務ロジックで直接参照することを想定したものではなく、BizLogicの
084         * メイン構造を拡張するサブクラスを定義する際に使用することを想定しています。
085         * (この想定がなければ、本来は、package privateにすべきです)
086         * このため、業務ロジックを各実装クラスでは直接参照しないで下さい。
087         */
088        @Override       // AbstractBizLogic
089        protected void init() {
090                // Document empty method チェック対策
091        }
092
093        /**
094         * 処理のメインロジックを記述します。
095         *
096         * このメソッド自体は、protected属性であるため、サブクラスから直接参照することができます。
097         * 但し、これは、各業務ロジックで直接参照することを想定したものではなく、BizLogicの
098         * メイン構造を拡張するサブクラスを定義する際に使用することを想定しています。
099         * (この想定がなければ、本来は、package privateにすべきです)
100         * このため、業務ロジックを各実装クラスでは直接参照しないで下さい。
101         *
102         * @og.rev 5.1.8.0 (2010/07/01) first,lastは行ループの中で呼び出し
103         * @og.rev 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。
104         * @og.rev 6.7.9.1 (2017/05/19) protected ArrayTableModel を、private DataModel に変更します。
105         * @og.rev 6.8.5.0 (2018/01/09) first(),last() をループから出して、ループを回すかどうかを引数で指定します。
106         * @og.rev 8.0.2.0 (2021/11/30) 行単位ロジックチェックは廃止。
107         *
108         * @return 処理が正常終了したか
109         */
110        @Override       // AbstractBizLogic
111        protected boolean main() {
112                final DataModel<String> table = getTable();             // 6.7.9.1 (2017/05/19)
113
114                if( table == null ) {
115                        // 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。
116                        final String errMsg = "配列型テーブルモデルがセットされていません。" ;
117                        throw new OgRuntimeException( errMsg );
118                }
119
120                row = 0;
121                if( !fstchk() ) { return false; }
122
123//              final int rowLen = table.getRowCount();                 // 6.8.5.0 (2018/01/09)
124
125        //      8.0.2.0 (2021/11/30) 行単位ロジックチェックは廃止。
126        //      if( useLoop ) {                 // 6.8.5.0 (2018/01/09)
127//      //              for( int i=0; i<table.getRowCount(); i++ ) {
128                //      for( int i=0; i<rowLen; i++ ) {
129                //              if( !befchk( row ) ) { return false; }
130
131                //              final String modType = table.getModifyType( row );
132
133                //              // 6.9.7.0 (2018/05/14) PMD These nested if statements could be combined
134                //              if(    "A".equals( modType ) && !inschk( row )
135                //                      || "C".equals( modType ) && !modchk( row )
136                //                      || "D".equals( modType ) && !delchk( row )
137                //                      || !allchk( row ) ) {
138                //                      return false;
139                //              }
140
141//                              if( "A".equals( modType ) ) {
142//                                      if( !inschk( row ) ) { return false; }
143//                              }
144//                              else if( "C".equals( modType ) ) {
145//                                      if( !modchk( row ) ) { return false; }
146//                              }
147//                              else if( "D".equals( modType ) ) {
148//                                      if( !delchk( row ) ) { return false; }
149//                              }
150//
151//                              if( !allchk( row ) ) { return false; }
152
153                //              row++;
154                //      }
155        //      }
156                if( getKekka() >= ErrorMessage.NG ) { return false; }
157
158        //      row = 0;
159                final int rowLen = table.getRowCount();                         // 6.8.5.0 (2018/01/09)
160                if( rowLen > 0 && !first() ) { return false; }          // 6.8.5.0 (2018/01/09) ループの外に出します。
161
162                if( useLoop ) {                 // 6.8.5.0 (2018/01/09)
163//      //              for( int i=0; i<table.getRowCount(); i++ ) {
164                        for( int i=0; i<rowLen; i++ ) {
165//      //                      // 5.1.8.0 (2010/07/01) firstは行ループの中で呼び出し
166//      //                      if( row == 0 ) {
167//      //                              if( !first() ) { return false; }
168//      //                      }
169
170                                if( !befall( row ) ) { return false; }
171
172                                final String modType = table.getModifyType( row );
173
174                                // 6.9.7.0 (2018/05/14) PMD These nested if statements could be combined
175                                if(        "A".equals( modType ) && !insert( row )
176                                        || "C".equals( modType ) && !modify( row )
177                                        || "D".equals( modType ) && !delete( row )
178                                        || !allrow( row ) ) {
179                                        return false;
180                                }
181
182//                              if( !befall( row ) ) { return false; }
183//
184//                              final String modType = table.getModifyType( row );
185//                              if( "A".equals( modType ) ) {
186//                                      if( !insert( row ) ) { return false; }
187//                              }
188//                              else if( "C".equals( modType ) ) {
189//                                      if( !modify( row ) ) { return false; }
190//                              }
191//                              else if( "D".equals( modType ) ) {
192//                                      if( !delete( row ) ) { return false; }
193//                              }
194//
195//                              if( !allrow( row ) ) { return false; }
196//
197//      //                      // 5.1.8.0 (2010/07/01) lastは行ループの中で呼び出し
198//      //                      if( row == table.getRowCount() - 1 ) {
199//      //                              if( !last() ) { return false; }
200//      //                      }
201                                row++;
202                        }
203                }
204
205                if( rowLen > 0 ) {              // 6.8.5.0 (2018/01/09) ループの外に出します。
206                        row = rowLen-1;
207                        if( !last() ) { return false; }
208                }
209
210                return true;
211        }
212
213        /**
214         * このクラスは、テーブルモデルが外部から指定されている必要があります。
215         *
216         * このメソッド自体は、protected属性であるため、サブクラスから直接参照することができます。
217         * 但し、これは、各業務ロジックで直接参照することを想定したものではなく、BizLogicの
218         * メイン構造を拡張するサブクラスを定義する際に使用することを想定しています。
219         * (この想定がなければ、本来は、package privateにすべきです)
220         * このため、業務ロジックを各実装クラスでは直接参照しないで下さい。
221         *
222         * @og.rev 8.0.2.0 (2021/11/30) protected → default 変更(サブクラスからのアクセスはない)
223         *
224         * @return テーブルモデルが外部から指定されている必要があるかどうか(常にtrue)
225         * @see AbstractBizLogic#isRequireTable()
226         */
227        @Override                               // AbstractBizLogic
228//      protected boolean isRequireTable() {
229        /* default */ boolean isRequireTable() {
230                return true;
231        }
232
233        /**
234         * メインカーソルの一番初めで呼ばれるチェックロジックを定義します。
235         * ここでは何も実装されていません。
236         *
237         * @return 処理が正常終了したか
238         */
239        protected boolean fstchk() {
240                return true;
241        }
242
243//      /**
244//       * メインカーソルの各行(変更区分の各処理の前)で呼ばれるチェックロジックを定義します。
245//       * ここでは何も実装されていません。
246//       *
247//       * @og.rev 8.0.2.0 (2021/11/30) 行単位ロジックチェックは廃止。
248//       *
249//       * @param row 行番号(インデックス)
250//       *
251//       * @return 処理が正常終了したか
252//       */
253//      protected boolean befchk( final int row ) {
254//              return true;
255//      }
256
257//      /**
258//       * メインカーソルの各行(変更区分の各処理の後)で呼ばれるチェックロジックを定義します。
259//       * ここでは何も実装されていません。
260//       *
261//       * @og.rev 8.0.2.0 (2021/11/30) 行単位ロジックチェックは廃止。
262//       *
263//       * @param row 行番号(インデックス)
264//       *
265//       * @return 処理が正常終了したか
266//       */
267//      protected boolean allchk( final int row ) {
268//              return true;
269//      }
270
271//      /**
272//       * メインカーソルの各行(変更区分="A")で呼ばれるチェックロジックを定義します。
273//       * ここでは何も実装されていません。
274//       *
275//       * @og.rev 8.0.2.0 (2021/11/30) 行単位ロジックチェックは廃止。
276//       *
277//       * @param row 行番号(インデックス)
278//       *
279//       * @return 処理が正常終了したか
280//       */
281//      protected boolean inschk( final int row ) {
282//              return true;
283//      }
284
285//      /**
286//       * メインカーソルの各行(変更区分="C")で呼ばれるチェックロジックを定義します。
287//       * ここでは何も実装されていません。
288//       *
289//       * @og.rev 8.0.2.0 (2021/11/30) 行単位ロジックチェックは廃止。
290//       *
291//       * @param row 行番号(インデックス)
292//       *
293//       * @return 処理が正常終了したか
294//       */
295//      protected boolean modchk( final int row ) {
296//              return true;
297//      }
298
299//      /**
300//       * メインカーソルの各行(変更区分="D")で呼ばれるチェックロジックを定義します。
301//       * ここでは何も実装されていません。
302//       *
303//       * @og.rev 8.0.2.0 (2021/11/30) 行単位ロジックチェックは廃止。
304//       *
305//       * @param row 行番号(インデックス)
306//       *
307//       * @return 処理が正常終了したか
308//       */
309//      protected boolean delchk( final int row ) {
310//              return true;
311//      }
312
313        /**
314         * メインカーソルの一番初めで呼ばれるロジックを定義します。
315         * ここでは何も実装されていません。
316         *
317         * @return 処理が正常終了したか
318         */
319        protected boolean first() {
320                return true;
321        }
322
323        /**
324         * メインカーソルの一番最後で呼ばれるロジックを定義します。
325         * ここでは何も実装されていません。
326         *
327         * @return 処理が正常終了したか
328         */
329        protected boolean last() {
330                return true;
331        }
332
333        /**
334         * メインカーソルの各行(変更区分の各処理の前)で呼ばれるロジックを定義します。
335         * ここでは何も実装されていません。
336         *
337         * @param row 行番号(インデックス)
338         *
339         * @return 処理が正常終了したか
340         */
341        protected boolean befall( final int row ) {
342                return true;
343        }
344
345        /**
346         * メインカーソルの各行(変更区分の各処理の後)で呼ばれるロジックを定義します。
347         * ここでは何も実装されていません。
348         *
349         * @param row 行番号(インデックス)
350         *
351         * @return 処理が正常終了したか
352         */
353        protected boolean allrow( final int row ) {
354                return true;
355        }
356
357        /**
358         * メインカーソルの各行(変更区分="A")で呼ばれるロジックを定義します。
359         * ここでは何も実装されていません。
360         *
361         * @param row 行番号(インデックス)
362         *
363         * @return 処理が正常終了したか
364         */
365        protected boolean insert( final int row ) {
366                return true;
367        }
368
369        /**
370         * メインカーソルの各行(変更区分="C")で呼ばれるロジックを定義します。
371         * ここでは何も実装されていません。
372         *
373         * @param row 行番号(インデックス)
374         *
375         * @return 処理が正常終了したか
376         */
377        protected boolean modify( final int row ) {
378                return true;
379        }
380
381        /**
382         * メインカーソルの各行(変更区分="D")で呼ばれるロジックを定義します。
383         * ここでは何も実装されていません。
384         *
385         * @param row 行番号(インデックス)
386         *
387         * @return 処理が正常終了したか
388         */
389        protected boolean delete( final int row ) {
390                return true;
391        }
392
393        /**
394         * ループを回すかどうかを指定します。
395         *
396         * ループ処理を使用しない場合の処理速度向上のためのフラグです。
397         *
398         * ループ処理とは、引数に row番号を指定する関数です。
399         * 初期値は、true(ループを回す) です。
400         * false を指定すると、それらのメソッドは使用されず、fstchk()、first()、last() のみ呼び出されます。
401         *
402         * init() と main() は、AbstractBizLogic#exec() から呼ばれるため、通常通り呼び出されます。
403         *
404         * @og.rev 6.8.5.0 (2018/01/09) ループを回すかどうかを引数で指定します。
405         *
406         * @param useLoop ループを回すかどうか
407         */
408        protected final void setUseLoop( final boolean useLoop ) {
409                this.useLoop = useLoop;
410        }
411}