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.hayabusa.taglib;
017
018import org.opengion.hayabusa.common.HybsSystem;
019import org.opengion.hayabusa.db.DBColumn;
020import org.opengion.hayabusa.db.DBTableModel;
021import org.opengion.fukurou.model.ArrayDataModel;
022import org.opengion.fukurou.model.Formatter;
023import org.opengion.fukurou.util.Attributes;
024import org.opengion.fukurou.util.ErrorMessage;
025import org.opengion.fukurou.util.ToString;                                              // 6.1.1.0 (2015/01/17)
026import org.opengion.fukurou.util.StringUtil ;                                   // 6.2.0.0 (2015/02/27)
027import org.opengion.fukurou.util.ArraySet;                                              // 6.4.3.4 (2016/03/11)
028
029import static org.opengion.fukurou.util.StringUtil.nval ;
030
031import java.util.List;
032import java.util.ArrayList;
033import java.util.Enumeration;
034import java.util.Locale ;
035import java.util.Set;                                                                                   // 6.4.3.4 (2016/03/11)
036
037/**
038 * 検索結果の DBTableModelオブジェクトに値を設定するタグです。
039 *
040 * columnSet と共に使用する場合は、entryタグ の command属性と、columnSetタグ の command属性が
041 * 一致した場合のみ、処理されます。
042 * entryタグは、そのコマンドにより、DBTableModelオブジェクトの値を設定します。
043 * たとえば、command="INSERT" ならば、1行分のデータを選択された行番号の次に挿入します。
044 * また、追加、変更、削除された、DBTableModelオブジェクト でも、内部には元のデータを
045 * 持っているため、command="RESET" で元の状態に戻すことが可能です。
046 *
047 * @og.formSample
048 * ●形式:
049 *       ・<og:entry command="…">
050 *             <og:columnSet command="…" />
051 *         </og:entry>
052 *       ・<og:entry command="…" />
053 *             ・・・columnSetを使わない場合でもresult.jspから次画面(insert,modify,copy.jsp等)に
054 *                にDBTableModelをもっていく場合には、必ず2を書いてください。
055 *                (取消のとき、エンジン内でDBTableModelを操作するのに使用する為)
056 * ●body:あり(EVAL_BODY_BUFFERED:BODYを評価し、{@XXXX} を解析します)
057 *
058 * ●Tag定義:
059 *   <og:entry
060 *       command          ○【TAG】コマンド (INSERT/COPY/MODIFY/DELETE/ENTRY/CHANGE/RESET/ALLRESET/ALLACTION/RESETDATA/INSERTONE/REALDELETE/REQENTRY)を設定します(必須)
061 *       scope              【TAG】キャッシュする場合のスコープ[request/page/session/application]を指定します(初期値:session)
062 *       repeatCount        【TAG】指定の回数分だけ、繰り返し処理を行う回数を指定します(初期値:1)
063 *       tableId            【TAG】(通常は使いません)sessionから所得する DBTableModelオブジェクトの ID
064 *       useConsistency     【TAG】Consistency キー による整合性チェックを行うかどうかを指定します(初期値:true)
065 *       selectedAll        【TAG】データを全件選択済みとして処理するかどうか[true/false]を指定します(初期値:false)
066 *       strictCheck        【TAG】(通常は使いません)カラムIDの存在チェックを行うかどうか[true/false]を指定します(初期値:true)
067 *       noTransition       【TAG】(通常は使いません)画面遷移を行わない形式の登録方法を使用するかを指定します
068 *       caseKey            【TAG】このタグ自体を利用するかどうかの条件キーを指定します(初期値:null)
069 *       caseVal            【TAG】このタグ自体を利用するかどうかの条件値を指定します(初期値:null)
070 *       caseNN             【TAG】指定の値が、null/ゼロ文字列 でない場合(Not Null=NN)は、このタグは使用されます(初期値:判定しない)
071 *       caseNull           【TAG】指定の値が、null/ゼロ文字列 の場合は、このタグは使用されます(初期値:判定しない)
072 *       caseIf             【TAG】指定の値が、true/TRUE文字列の場合は、このタグは使用されます(初期値:判定しない)
073 *       debug              【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false)
074 *   >   ... Body ...
075 *   </og:entry>
076 *
077 * ●使用例
078 *    <og:entry command="{@command}"  >
079 *        <og:columnSet command="{@command}" columnId="ECNO"   action="CLEAR" />
080 *        <og:columnSet command="{@command}" columnId="JYOKYO" action="SET" value="1" />
081 *    </og:entry>
082 *
083 *    <og:entry command="MODIFY" rows="1" >
084 *        <og:columnSet  command="MODIFY" columnId="key" action="TBLSET" value="[key][lang]"/>
085 *    </og:entry>
086 *
087 *    action="ADD" は、DBTypeに依存した方法で、既存の値を、+1 します。
088 *    <og:entry command="{@command}" repeatCount="5" >
089 *        <og:columnSet  command="{@command}" columnId="YKNO" action="ADD" />
090 *    </og:entry>
091 *
092 *    action="ADD" は、DBTypeに依存した方法で、既存の値に、value の値を加算します。
093 *    <og:entry command="{@command}" repeatCount="5" >
094 *        <og:columnSet  command="{@command}" columnId="YKNO" action="ADD" value="5" />
095 *    </og:entry>
096 *
097 *    command属性 は、columnSetタグのcommand属性と同一の場合のみ、処理します。
098 *    [command属性]
099 *      INSERT     新規
100 *      COPY       複写
101 *      MODIFY     変更
102 *      DELETE     削除
103 *      ENTRY      エントリー
104 *      CHANGE     チェンジ
105 *      RESET      リセット         (RESET_ACTION_ALL_USE=true で、ALLRESET が呼ばれます)
106 *      ALLRESET   全件リセット
107 *      ALLACTION  オールアクション
108 *      RESETDATA  リセットデータ
109 *      INSERTONE  新規(1行のみ)
110 *      REALDELETE 物理削除
111 *      REQENTRY   リクエスト変数設定
112 *
113 *    command属性 は、columnSetタグで指定します。
114 *    [action属性]
115 *      DEFAULT カラムリソースで定義した初期値をセットします。
116 *      CLEAR   値をクリア(ゼロストリング "" )します。
117 *      ADD     現在の値を +1 します。  0 ⇒ 1 , A ⇒ B , 9 ⇒ 10。value属性と併用すれば、指定の値を加算できます。
118 *      SET     value で設定した値を 新しい値として登録します。
119 *      NULLSET 元の値が NULL の場合だけ、value で設定した新しい値を登録します。
120 *      LOWER   小文字に変換します。
121 *      UPPER   大文字に変換します。
122 *      COPY    value にコピー元のカラムIDをセットすれば、その値を代入します。
123 *      TBLSET  DBTableModel の内容を取り込んで指定の columnId カラムに設定します。[カラム名] で指定できます。
124 *              また、これは文字列を解析して、 value を作成しますので,文字列連結等に使用できます。
125 *      TBLNULLSET 元の値が NULL の場合だけ、TBLSETを実行します。         6.9.9.0 (2018/08/20) 追加
126 *      WRTCTRL writableControl を使用したカラムデータの先頭アンダーバーを削除します。
127 *      DBMENU  DBMENUでパラメータ設定(コロン連結文字)を使用したカラムデータの先頭データのみにします。
128 *      REQSET  valueで指定したカラムの値をキーに、リクエスト変数から値を取出し、セットします。
129 *      SEQSET  valueの初期値を利用して、1レコードごとに、+1した値をセットします。
130 *      PREFIX  valueの値を後ろから検索し、指定のカラム値の前半部分を取得します(記号は含みません)。
131 *      SUFIX   valueの値を後ろから検索し、指定のカラム値の後半部分を取得します(記号は含みません)。
132 *      その他  カラムのDBType の valueAction メソッドを呼び出します。自由に設定可能です。
133 *
134 *    [strictCheck属性]は、カラムIDの存在チェックを行うかどうかを指定します(初期値:true)
135 *      true    カラムIDがDBTableModel に存在しない場合は、エラーになる。
136 *      false   カラムIDがDBTableModel に存在しない場合は、無視する。
137 *
138 * @og.group 画面登録
139 *
140 * @version  4.0
141 * @author       Kazuhiko Hasegawa
142 * @since    JDK5.0,
143 */
144public class EntryTag extends CommonTagSupport {
145        /** このプログラムのVERSION文字列を設定します。   {@value} */
146        private static final String VERSION = "6.9.9.0 (2018/08/20)" ;
147        private static final long serialVersionUID = 699020180820L ;
148
149        /** command 引数に渡す事の出来る コマンド  新規 {@value} */
150        public static final String CMD_INSERT   = "INSERT" ;
151        /** command 引数に渡す事の出来る コマンド  複写 {@value} */
152        public static final String CMD_COPY             = "COPY" ;
153        /** command 引数に渡す事の出来る コマンド  変更 {@value} */
154        public static final String CMD_MODIFY   = "MODIFY" ;
155        /** command 引数に渡す事の出来る コマンド  削除 {@value} */
156        public static final String CMD_DELETE   = "DELETE" ;
157        /** command 引数に渡す事の出来る コマンド  エントリー {@value} */
158        public static final String CMD_ENTRY    = "ENTRY" ;
159        /** command 引数に渡す事の出来る コマンド  チェンジ {@value} */
160        public static final String CMD_CHANGE   = "CHANGE" ;
161        /** command 引数に渡す事の出来る コマンド  リセット {@value} */
162        public static final String CMD_RESET    = "RESET" ;
163        /** command 引数に渡す事の出来る コマンド  全件リセット {@value} */
164        public static final String CMD_ALLRESET         = "ALLRESET" ;  // 3.5.6.3 (2004/07/12)
165        /** command 引数に渡す事の出来る コマンド  オールアクション{@value} */
166        public static final String CMD_ALLACTION        = "ALLACTION" ;
167        /** command 引数に渡す事の出来る コマンド  リセット(データのみ){@value} */
168        public static final String CMD_RESETDATA        = "RESETDATA" ;         // 4.3.3.0 (2008/10/01)
169        /** command 引数に渡す事の出来る コマンド  追加(1行のみ){@value} */
170        public static final String CMD_INSERTONE        = "INSERTONE" ;         // 5.1.5.0 (2010/04/01)
171        /** command 引数に渡す事の出来る コマンド  物理削除 {@value} */
172        public static final String CMD_REALDELETE       = "REALDELETE" ;                // 5.1.6.0 (2010/05/01)
173        /** command 引数に渡す事の出来る コマンド  リクエスト変数設定 {@value} */
174        public static final String CMD_REQENTRY         = "REQENTRY" ;                  // 5.6.1.2 (2013/02/22)
175        // 6.4.3.4 (2016/03/11) String配列 から、Setに置き換えます。
176        private static final Set<String> COMMAND_SET = new ArraySet<>(
177                                                        CMD_INSERT,CMD_COPY,CMD_MODIFY,CMD_DELETE,CMD_ENTRY,CMD_CHANGE,CMD_ALLACTION,
178                                                        CMD_RESET,CMD_ALLRESET,CMD_RESETDATA,CMD_INSERTONE,CMD_REALDELETE,CMD_REQENTRY );
179
180        /** action 引数に渡す事の出来る アクションコマンド  初期値:{@value} */
181        public static final String ACT_DEFAULT  = "DEFAULT" ;
182        /** action 引数に渡す事の出来る アクションコマンド  クリア {@value} */
183        public static final String ACT_CLEAR    = "CLEAR" ;
184        /** action 引数に渡す事の出来る アクションコマンド  +1 {@value} */
185        public static final String ACT_ADD      = "ADD" ;
186        /** action 引数に渡す事の出来る アクションコマンド  小文字化{@value} */
187        public static final String ACT_LOWER    = "LOWER" ;
188        /** action 引数に渡す事の出来る アクションコマンド  大文字化{@value} */
189        public static final String ACT_UPPER    = "UPPER" ;
190        /** action 引数に渡す事の出来る アクションコマンド  コピー {@value} */
191        public static final String ACT_COPY     = "COPY" ;
192        /** action 引数に渡す事の出来る アクションコマンド  セット {@value} */
193        public static final String ACT_SET      = "SET" ;
194        // 3.4.0.3 (2003/09/10) NULLSET Action を追加します。
195        /** action 引数に渡す事の出来る アクションコマンド  NULLセット {@value} */
196        public static final String ACT_NULLSET  = "NULLSET" ;
197        /** action 引数に渡す事の出来る アクションコマンド  テーブルセット {@value} */
198        public static final String ACT_TBLSET   = "TBLSET" ;
199        /** action 引数に渡す事の出来る アクションコマンド  テーブルNULLセット {@value} */
200        public static final String ACT_TBLNULLSET   = "TBLNULLSET" ;    // 6.9.9.0 (2018/08/20)
201        /** action 引数に渡す事の出来る アクションコマンド  ライトコントロール {@value} */
202        public static final String ACT_WRTCTRL  = "WRTCTRL" ;                   // 3.8.1.5 (2006/03/30)
203        /** action 引数に渡す事の出来る アクションコマンド  DBメニュー {@value} */
204        public static final String ACT_DBMENU  = "DBMENU" ;                             // 3.8.5.3 (2006/08/07)
205        /** action 引数に渡す事の出来る アクションコマンド  リクエスト値セット {@value} */
206        public static final String ACT_REQSET  = "REQSET" ;                             // 5.4.2.1 (2011/12/09)
207        /** action 引数に渡す事の出来る アクションコマンド  連番値セット {@value} */
208        public static final String ACT_SEQSET  = "SEQSET" ;                             // 5.6.5.2 (2013/06/21)
209        /** action 引数に渡す事の出来る アクションコマンド  PREFIX値セット {@value} */
210        public static final String ACT_PREFIX  = "PREFIX" ;                             // 5.6.6.1 (2013/07/12)
211        /** action 引数に渡す事の出来る アクションコマンド  SUFIX値セット {@value} */
212        public static final String ACT_SUFIX   = "SUFIX" ;                              // 5.6.6.1 (2013/07/12)
213
214        // 3.5.6.0 (2004/06/18) すべてを protected から private に変更します。
215        private transient       DBTableModel            table   ;
216        private transient       List<Attributes>        values  ;               // 6.3.9.0 (2015/11/06) transient 追加
217
218        private String                          tableId         = HybsSystem.TBL_MDL_KEY;
219        private String                          command         ;
220        private int[]                           rowNo           ;
221
222        // 3.5.4.2 (2003/12/15) 指定の回数繰り返す機能を追加します。
223        private int                             repeatCount     = 1;
224
225        // 3.5.5.7 (2004/05/10) Consistency キー による整合性チェックを行うかどうかを指定します。
226        // 6.9.5.0 (2018/04/23) USE_CONSISTENCY 廃止(true固定)
227//      private boolean                 useConsistency  = HybsSystem.sysBool( "USE_CONSISTENCY" );
228        private boolean                 useConsistency  = true;         // 6.9.5.0 (2018/04/23)
229
230        // 3.8.1.1 (2005/11/21) 全件選択されたこととして、処理します。
231        private boolean selectedAll     ;
232
233        // 3.5.6.4 (2004/07/16) RESET コマンドのデフォルト処理 に、ALLRESET を
234        // 使用するかどうかを指定します(初期値:false(使用しない))。
235        // 6.2.6.0 (2015/06/19) 初期値:true(使用する)にします。
236        private final boolean RESET_ACTION_ALL_USE = HybsSystem.sysBool( "RESET_ACTION_ALL_USE" );
237
238        // 4.0.0 (2006/09/31) カラムIDの存在チェックを行うかどうかを指定します。
239        private boolean strictCheck     = true;
240
241        private boolean noTransition;           // 4.3.3.0 (2008/10/01) 追加
242
243        // 5.6.5.2 (2013/06/21) SEQSET アクションのカウンター
244        private int seqsetCnt   ;
245
246        /**
247         * デフォルトコンストラクター
248         *
249         * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor.
250         */
251        public EntryTag() { super(); }          // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。
252
253        /**
254         * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。
255         *
256         * @og.rev 5.1.9.0 (2010/08/01) 戻り値を、EVAL_BODY_INCLUDE → EVAL_BODY_BUFFERED に変更
257         * @og.rev 6.3.4.0 (2015/08/01) caseKey,caseVal,caseNN,caseNull,caseIf 属性対応
258         * @og.rev 6.4.3.4 (2016/03/11) String配列 から、Setに置き換えます。
259         *
260         * @return      後続処理の指示
261         */
262        @Override
263        public int doStartTag() {
264                // 6.3.4.0 (2015/08/01) useTag() の追加と、if条件の反転
265                // 6.4.1.1 (2016/01/16) PMD refactoring. A method should have only one exit point, and that should be the last statement in the method
266                return useTag() && check( command, COMMAND_SET ) ? EVAL_BODY_BUFFERED : SKIP_BODY;
267        }
268
269        /**
270         * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。
271         *
272         * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。
273         * @og.rev 3.5.5.5 (2004/04/23) 登録時の 整合性パラメータチェックを行います。
274         * @og.rev 3.5.5.6 (2004/04/27) JSP画面の作成不具合。ENTRY系で、command を投げた場合は、無視します。
275         * @og.rev 3.5.5.7 (2004/05/10) Consistency キー による整合性チェックを行うかどうかを指定します。
276         * @og.rev 3.5.5.8 (2004/05/20) Consistency キー による整合性チェックを checkConsistency() に集約します。
277         * @og.rev 3.6.0.8 (2004/11/19) DBTableModel をセーブする時に、トランザクションチェックを行います。
278         * @og.rev 4.3.3.0 (2008/10/01) noTransition 属性を追加します。
279         * @og.rev 4.3.8.0 (2009/08/01) noTransition値取得のメソッド名変更
280         * @og.rev 5.1.3.0 (2010/02/01) noTransitionのコントロールは、requestで行う。
281         * @og.rev 6.3.4.0 (2015/08/01) caseKey,caseVal,caseNN,caseNull,caseIf 属性対応
282         * @og.rev 6.4.3.4 (2016/03/11) String配列 から、Setに置き換えます。
283         *
284         * @return      後続処理の指示
285         */
286        @Override
287        public int doEndTag() {
288                debugPrint();           // 4.0.0 (2005/02/28)
289                if( !useTag() ) { return EVAL_PAGE ; }  // 6.3.4.0 (2015/08/01)
290
291                // noTransition = isNoTransitionRequest() || noTransition; // 4.3.3.0 (2008/10/01) 追加
292                noTransition = isNoTransitionRequest(); // 5.1.3.0 (2010/02/01)
293                startQueryTransaction( tableId );               // 3.6.0.8 (2004/11/19)
294                table = (DBTableModel)getObject( tableId );
295                if( table != null && check( command, COMMAND_SET ) ) {
296                        if( ! checkConsistency() ) { return SKIP_PAGE ; }
297                        if( rowNo == null ) { rowNo = getParameterRows(); }             // 4.0.0 (2005/01/31)
298
299                        commandExec( command );
300
301                        // 3.6.0.8 (2004/11/19) トランザクションチェックを行います。
302                        if( ! commitTableObject( tableId, table ) ) {
303                                jspPrint( "EntryTag Query処理が割り込まれました。DBTableModel は登録しません。" );
304                                return SKIP_PAGE;
305                        }
306                }
307
308                return EVAL_PAGE ;
309        }
310
311        /**
312         * タグリブオブジェクトをリリースします。
313         *
314         * キャッシュされて再利用されるので、フィールドの初期設定を行います。
315         *
316         * @og.rev 2.0.0.4 (2002/09/27) カスタムタグの release() メソッドを、追加
317         * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。
318         * @og.rev 3.5.4.2 (2003/12/15) 指定の回数繰り返す機能を追加します。
319         * @og.rev 3.5.5.7 (2004/05/10) Consistency キー による整合性チェックを行うかどうかを指定します。
320         * @og.rev 3.8.1.1 (2005/11/21) selectedAll 追加。全件選択されたこととして、処理します。
321         * @og.rev 4.0.0.0 (2006/09/31) strictCheck 追加。
322         * @og.rev 4.3.3.0 (2008/10/01) noTransition 属性を追加します。
323         * @og.rev 5.6.5.2 (2013/06/21) seqsetCnt 属性を追加します。
324         * @og.rev 6.9.5.0 (2018/04/23) USE_CONSISTENCY 廃止(true固定)
325         *
326         */
327        @Override
328        protected void release2() {
329                super.release2();
330                tableId                 = HybsSystem.TBL_MDL_KEY;
331                table                   = null;
332                command                 = null;
333                rowNo                   = null;
334                values                  = null;
335                repeatCount             = 1;                    // 3.5.4.2 (2003/12/15)
336//              useConsistency  = HybsSystem.sysBool( "USE_CONSISTENCY" );              // 3.5.5.7 (2004/05/10)
337                useConsistency  = true;                 // 6.9.5.0 (2018/04/23) true固定
338                selectedAll             = false;                // 3.8.1.1 (2005/11/21)
339                strictCheck             = true;                 // 4.0.0 (2006/09/31)
340                noTransition    = false;                // 4.3.3.0 (2008/10/01) 追加
341                seqsetCnt               = 0;                    // 5.6.5.2 (2013/06/21) SEQSET アクションのカウンター
342        }
343
344        /**
345         * 内部タグの ColumnSetTag より、個々のカラムの値を書き換える為の属性を指定します。
346         *
347         * 複数の値を受け取って、後ほど、すべてのカラムに対して処理を行います。
348         *
349         * @og.rev 3.1.0.0 (2003/03/20) Vector を使用している箇所で、非同期でも構わない箇所を、ArrayList に置換え。
350         * @og.rev 3.1.2.0 (2003/04/07) taglib パッケージ内部で使用している箇所を protected 化する。
351         *
352         * @param   attri       属性リスト
353         */
354        protected void setAttributes( final Attributes attri ) {
355                if( values == null ) { values = new ArrayList<>(); }
356                if( command.equalsIgnoreCase( attri.get( "command" ) ) ) {
357                        values.add( attri );
358                }
359        }
360
361        /**
362         * 【TAG】(通常は使いません)結果のDBTableModelを、sessionに登録するときのキーを指定します
363         *              (初期値:HybsSystem#TBL_MDL_KEY[={@og.value HybsSystem#TBL_MDL_KEY}])。
364         *
365         * @og.tag
366         * 検索結果より、DBTableModelオブジェクトを作成します。これを、下流のviewタグ等に
367         * 渡す場合に、通常は、session を利用します。その場合の登録キーです。
368         * query タグを同時に実行して、結果を求める場合、同一メモリに配置される為、
369         * この tableId 属性を利用して、メモリ空間を分けます。
370         *              (初期値:HybsSystem#TBL_MDL_KEY[={@og.value HybsSystem#TBL_MDL_KEY}])。
371         *
372         * @param       id テーブルID (sessionに登録する時のID)
373         */
374        public void setTableId( final String id ) {
375                tableId   = nval( getRequestParameter( id ),tableId );  // 3.8.0.9 (2005/10/17)
376        }
377
378        /**
379         * 【TAG】コマンド (INSERT,COPY,MODIFY,DELETE,ENTRY,CHANGE,ALLACTION,RESET)をセットします。
380         *
381         * @og.tag
382         * コマンドは,HTMLから(get/post)指定されますので,CMD_xxx で設定される
383         * フィールド定数値のいづれかを、指定できます。
384         *
385         * @param       cmd コマンド (public static final 宣言されている文字列)
386         * @see         <a href="../../../../constant-values.html#org.opengion.hayabusa.taglib.EntryTag.CMD_INSERT">コマンド定数</a>
387         */
388        public void setCommand( final String cmd ) {
389                final String cmd2 = getRequestParameter( cmd );
390                if( cmd2 != null && cmd2.length() > 0 ) { command = cmd2.toUpperCase(Locale.JAPAN); }
391        }
392
393        /**
394         * コマンドを実行します。
395         *
396         * コマンドは,HTMLから(get/post)指定されますので,setCommand()メソッドで
397         * 登録します。
398         * コマンドを登録すると同時に,実行も行ないます。
399         *
400         * @og.rev 3.5.6.3 (2004/07/12) ALLRESET コマンドを追加する。
401         * @og.rev 4.3.3.0 (2008/10/01) RESETDATA コマンドを追加する。
402         * @og.rev 5.1.5.0 (2010/04/01) INSERTONE コマンドを追加する。
403         * @og.rev 5.1.6.0 (2010/05/01) REALDELETE コマンドを追加する。
404         * @og.rev 5.6.1.2 (2013/02/22) REQENTRY コマンドを追加する。
405         *
406         * @param   command コマンド (public static final 宣言されている文字列)
407         */
408        private void commandExec( final String command ) {
409
410                table.setDefaultRowWritable( false );
411                table.setDefaultRowChecked(  false );
412
413                if( CMD_INSERT.equals(      command ) ) { insert() ; }
414                else if( CMD_COPY.equals(   command ) ) { copy()   ; }
415                else if( CMD_MODIFY.equals( command ) ) { modify() ; }
416                else if( CMD_CHANGE.equals( command ) ) { change() ; }
417                else if( CMD_DELETE.equals( command ) ) { delete() ; }
418                else if( CMD_ENTRY.equals(  command ) ) { entry()  ; }
419                else if( CMD_RESET.equals(  command ) ) {
420                                if( RESET_ACTION_ALL_USE )              { allReset() ; }                // 3.5.6.4 (2004/07/16)
421                                else                                                    { reset()    ; }
422                }
423                else if( CMD_ALLRESET.equals(    command ) ) { allReset()  ; }  // 3.5.6.3 (2004/07/12)
424                else if( CMD_ALLACTION.equals(   command ) ) { allAction() ; }
425                else if( CMD_RESETDATA.equals(   command ) ) { resetData() ; }  // 4.3.3.0 (2008/10/01)
426                else if( CMD_INSERTONE.equals(   command ) ) { insertOne() ; }  // 5.1.5.0 (2010/04/01)
427                else if( CMD_REALDELETE.equals(  command ) ) { realDelete() ; } // 5.1.6.0 (2010/05/01)
428                else if( CMD_REQENTRY.equals(    command ) ) { reqEntry()  ; }  // 5.6.1.2 (2013/02/22)
429        }
430
431        /**
432         * DBTableModelに行を追加します。
433         *
434         * 注意:writableカラムの暫定対応が入っています。単純な空白データを
435         * インサートすると、カラムデータが null になる為、 制御がおかしく
436         * なります。
437         *
438         * @og.rev 3.5.4.2 (2003/12/15) repeatCount による繰り返し処理を追加
439         * @og.rev 4.3.3.0 (2008/10/01) noTransition 属性対応
440         *
441         */
442        private void insert() {
443                if( rowNo.length == 0 ) { rowNo = new int[] { -1 }; }
444
445                final boolean rowWritableFlag = "WRITABLE".equalsIgnoreCase( table.getColumnName( 0 ) );        // writable 対策
446                // src の作成は、各チェック毎に行う必要はない。最初の一度だけでよい。
447                String[] src = new String[ table.getColumnCount() ];
448                for( int j=0; j<src.length; j++ ) {
449                        final DBColumn dbColumn = table.getDBColumn( j );
450                        src[j] = dbColumn.getDefault();
451                }
452                if( rowWritableFlag ) { src[0] = "true"; }      // writable 対策
453
454                final int rowCount = table.getRowCount();
455
456                // 逆順にINSERTしないと、行番号がずれてしまう。
457                for( int i=rowNo.length-1; i>=0; i-- ) {
458                        int row = rowNo[i];
459                        for( int cnt=0; cnt<repeatCount; cnt++ ) {
460                                if( cnt >= 1 ) {                // 2回目以降
461                                        src = table.getValues( row );
462                                }
463
464                                String[] dst = new String[ table.getColumnCount() ];
465                                System.arraycopy( src,0,dst,0,dst.length );
466                                dst = setColumnValues( dst );
467
468                                // 4.3.3.0 (2008/10/01) noTransition属性対応
469                                if( noTransition ) { row = rowCount; }
470                                else { row ++; }                                        // 指定行の下に追加する。
471                                table.addValues( dst,row );
472                                table.setRowWritable( row,true );
473                                table.setRowChecked(  row,true );
474                        }
475                }
476        }
477
478        /**
479         * DBTableModelに行を追加し、チェックされた行の値をセットします。
480         *
481         * @og.rev 3.5.4.2 (2003/12/15) repeatCount による繰り返し処理を追加
482         * @og.rev 4.3.3.0 (2008/10/01) noTransition 属性対応
483         *
484         */
485        private void copy() {
486                if( rowNo.length == 0 ) { insert() ; return ;}
487
488                final int rowCount = table.getRowCount();
489
490                // 逆順にCOPYしないと、行番号がずれてしまう。
491                for( int i=rowNo.length-1; i>=0; i-- ) {
492                        for( int cnt=0; cnt<repeatCount; cnt++ ) {
493                                final String[] src = table.getValues( rowNo[i]+cnt );
494                                String[] dst = new String[ table.getColumnCount() ];
495                                System.arraycopy( src,0,dst,0,dst.length );
496                                dst = setColumnValues( dst );
497
498                                // 4.3.3.0 (2008/10/01) noTransition属性対応
499                                int row = -1;
500                                if( noTransition ) { row = rowCount; }
501                                else { row = rowNo[i] + cnt + 1; }                      // 指定行の下に追加する。
502
503                                table.addValues( dst,row );
504                                table.setRowWritable( row,true );
505                                table.setRowChecked(  row,true );
506                        }
507                }
508        }
509
510        /**
511         * DBTableModelの行を書込み可とます。
512         *
513         * @og.rev 4.3.4.6 (2009/01/15) 画面遷移なし登録で既に改廃Cがセットされている場合は、columnSetタグの処理を行わない。
514         *
515         */
516        private void modify() {
517                for( int i=0; i<rowNo.length; i++ ) {
518                        final String[] src = table.getValues( rowNo[i] );
519                        String[] dst = new String[ table.getColumnCount() ];
520                        System.arraycopy( src,0,dst,0,dst.length );
521
522                        // 4.3.4.6 (2009/01/15)
523                        // 画面遷移なし登録の場合、既に改廃Cが付いている(編集されている)場合は、
524                        // columnSetによる値のセットを行わない。
525                        // (同じコマンドで複数のボタンを割り当てている場合、複数回の変更・削除によって、先に登録された
526                        // 値が削除されてしまうため。
527                        if( !( noTransition && table.getModifyType( rowNo[i] ) != null && table.getModifyType( rowNo[i] ).length() > 0 ) ){
528                                dst = setColumnValues( dst );
529                        }
530
531                        table.setValues( dst,rowNo[i] );
532                        table.setRowWritable( rowNo[i],true );
533                        table.setRowChecked(  rowNo[i],true );
534                }
535        }
536
537        /**
538         * DBTableModelの行を変更します。
539
540         * @og.rev 4.3.4.6 (2009/01/15) 画面遷移なし登録で既に改廃Cがセットされている場合は、columnSetタグの処理を行わない。
541         *
542         */
543        private void change() {
544                for( int i=0; i<rowNo.length; i++ ) {
545                        final String[] src = table.getValues( rowNo[i] );
546                        String[] dst = new String[ table.getColumnCount() ];
547                        System.arraycopy( src,0,dst,0,dst.length );
548
549                        // 4.3.4.6 (2009/01/15)
550                        if( !( noTransition && table.getModifyType( rowNo[i] ) != null && table.getModifyType( rowNo[i] ).length() > 0 ) ){
551                                dst = setColumnValues( dst );
552                        }
553
554                        table.setValues( dst,rowNo[i] );
555                }
556        }
557
558        /**
559         * DBTableModelの行を削除します。
560         *
561         * @og.rev 3.5.4.2 (2003/12/15) DELETE時にも値の書き換えができるようにします。
562         * @og.rev 4.3.4.6 (2009/01/15) 画面遷移なし登録で既に改廃Cがセットされている場合は、columnSetタグの処理を行わない。
563         *
564         */
565        private void delete() {
566                for( int i=0; i<rowNo.length; i++ ) {
567                        // 3.5.4.2 (2003/12/15) 書き換え処理を追加
568                        final String[] src = table.getValues( rowNo[i] );
569                        String[] dst = new String[ table.getColumnCount() ];
570                        System.arraycopy( src,0,dst,0,dst.length );
571
572                        // 4.3.4.6 (2009/01/15)
573                        if( !( noTransition && table.getModifyType( rowNo[i] ) != null && table.getModifyType( rowNo[i] ).length() > 0 ) ){
574                                dst = setColumnValues( dst );
575                        }
576
577                        table.rowDelete( dst,rowNo[i] );
578                        table.setRowWritable( rowNo[i],true );
579                        table.setRowChecked( rowNo[i],true );
580                }
581        }
582
583        /**
584         * リクエスト情報から、セットされたカラム名と値を取り出し、設定します。
585         *
586         * 設定値は、個々のキー+"__" + 行番号 です。
587         * よって、値は,一つだけ設定されています。
588         *
589         * @og.rev 3.5.3.1 (2003/10/31) チェックボックスカラムを指定します。
590         * @og.rev 3.6.0.6 (2004/10/22) chboxNames 属性は廃止します。
591         * @og.rev 5.6.1.2 (2013/02/22) setRequestValuesメソッドの互換性の対応。
592         */
593        private void entry() {
594                if( rowNo.length > 0 ) {
595                        setRequestValues( false );              // 5.6.1.2 (2013/02/22) 互換性
596                        for( int i=0; i<rowNo.length; i++ ) {
597                                final String[] src = table.getValues( rowNo[i] );
598                                String[] dst = new String[ table.getColumnCount() ];
599                                System.arraycopy( src,0,dst,0,dst.length );
600                                dst = setColumnValues( dst );
601
602                                table.setValues( dst,rowNo[i] );
603                                table.setRowWritable( rowNo[i],true );
604                                table.setRowChecked(  rowNo[i],true );
605                        }
606                }
607        }
608
609        /**
610         * リクエスト情報のテーブルモデルデータを、リセットします。
611         *
612         * @og.rev 5.6.5.2 (2013/06/21) 行ループを 0~最終行の 降順で廻します。
613         * @og.rev 6.9.3.1 (2018/04/02) RESET時に、must,mustAny属性をクリアします。
614         */
615        private void reset() {
616                for( int i=rowNo.length-1; i>=0; i-- ) {
617                        table.resetRow( rowNo[i] );
618                }
619                table.addMustType( -1,"clear" );                        // 6.9.3.1 (2018/04/02) RESET時に、must,mustAny属性をクリアします。
620        }
621
622        /**
623         * テーブルモデルデータを、全件リセットします。
624         *
625         * @og.rev 3.5.6.3 (2004/07/12) 新規作成
626         * @og.rev 5.6.5.2 (2013/06/21) 行ループを 0~最終行の 降順で廻します。
627         * @og.rev 6.2.6.0 (2015/06/19) 行ループを 0~最終行の 降順で廻してなかった。
628         * @og.rev 6.9.3.1 (2018/04/02) RESET時に、must,mustAny属性をクリアします。
629         */
630        private void allReset() {
631                final int rowCount = table.getRowCount();
632                for( int row=rowCount-1; row>=0; row-- ) {
633                        table.resetRow( row );
634                }
635                table.addMustType( -1,"clear" );                        // 6.9.3.1 (2018/04/02) RESET時に、must,mustAny属性をクリアします。
636        }
637
638        /**
639         * DBTableModelの全ての行に対して,値をセットします。
640         *
641         * @og.rev 5.6.5.2 (2013/06/21) 行ループを 0~最終行の 降順で廻します。
642         * @og.rev 6.2.6.0 (2015/06/19) 行ループを 0~最終行の 降順で廻してなかった。
643         */
644        private void allAction() {
645                final int rowCount = table.getRowCount();
646                for( int row=rowCount-1; row>=0; row-- ) {
647                        final String[] src = table.getValues( row );
648                        String[] dst = new String[ table.getColumnCount() ];
649                        System.arraycopy( src,0,dst,0,dst.length );
650                        dst = setColumnValues( dst );
651
652                        table.setValues( dst,row );
653                        table.setRowWritable( row,true );
654                        table.setRowChecked(  row,true );
655                }
656        }
657
658        /**
659         * リクエスト情報のテーブルモデルデータを、リセットします。
660         * (但し、リセットされた行は、チェックされた状態のままになります)
661         *
662         * @og.rev 4.3.3.0 (2008/10/01) 新規作成
663         * @og.rev 5.6.5.2 (2013/06/21) 行ループを 0~最終行の 降順で廻します。
664         * @og.rev 6.2.6.0 (2015/06/19) 行ループを 0~最終行の 降順で廻してなかった。
665         */
666        private void resetData() {
667                for( int i=rowNo.length-1; i>=0; i-- ) {
668                        final String cdkh = table.getModifyType( rowNo[i] );
669                        table.resetRow( rowNo[i] );
670                        // 更新又は、削除の時のみ書き込み可能になる。
671                        if( DBTableModel.UPDATE_TYPE.equals( cdkh ) || DBTableModel.DELETE_TYPE.equals( cdkh ) ) {
672                                table.setRowWritable( rowNo[i],true );
673                                table.setRowChecked(  rowNo[i],true );
674                        }
675                }
676        }
677
678        /**
679         * DBTableModelに行を追加します。(1行のみ)
680         *
681         * 行が選択されているかどうかに関わらず、1行のみを追加します。
682         * (動きとしては、行が選択されていない状態でINSERTコマンドを発行した場合と同じです)
683         *
684         * @og.rev 5.1.5.0 (2010/04/01) 新規作成
685         *
686         */
687        private void insertOne() {
688                rowNo = new int[0];
689                insert();
690        }
691
692        /**
693         * DBTableModelの行を物理削除します。
694         *
695         * 通常のデータベース等で削除する場合は、DELETE行も残しておかないと、どの行を削除するか
696         * 判らなくなります。また、アプリケーションによっては、削除ではなく、フラグだけを立てる
697         * ケースもあるため、現在の commend="DELETE" では、論理削除+値の書き換えも可能になっています。
698         * ここでの物理削除は、WriteTable など、ファイル出力時には、その行そのものをなくしておくほうが
699         * 良いケースがあるためです。
700         *
701         * @og.rev 5.1.6.0 (2010/05/01) REALDELETE コマンドを追加する。
702         */
703        private void realDelete() {
704                // 逆順にしないと、行番号がずれてしまう。
705                for( int i=rowNo.length-1; i>=0; i-- ) {
706                        table.removeValue( rowNo[i] );
707                }
708        }
709
710        /**
711         * リクエスト情報から、セットされたカラム名と値を取り出し、設定します。
712         *
713         * 設定値は、個々のキー+"__" + 行番号 です。
714         * ENTRYコマンドとの違いは、h_rowSel と無関係に、リクエストされた変数すべてを
715         * 処理します。
716         *
717         * @og.rev 5.6.1.2 (2013/02/22) 新規追加
718         */
719        private void reqEntry() {
720                setRequestValues( true );       // リクエストされた変数すべてを処理
721                final int rowCount = table.getRowCount();
722                for( int row=0; row<rowCount; row++ ) {
723                        final String[] src = table.getValues( row );
724                        String[] dst = new String[ table.getColumnCount() ];
725                        System.arraycopy( src,0,dst,0,dst.length );
726                        dst = setColumnValues( dst );
727
728                        table.setValues( dst,row );
729                        table.setRowWritable( row,true );
730                        table.setRowChecked(  row,true );
731                }
732        }
733
734        /**
735         * リクエスト情報から、セットされたカラム名と値を取り出し、設定します。
736         *
737         * 設定値は、個々のキー+"__" + 行番号 です。
738         * よって、値は,一つだけ設定されています。
739         * 引数のフラグは、選択行番号に関係なく、全件処理するかどうか[true:する/false:しない]を指定できます。
740         *
741         * @og.rev 3.1.0.0 (2003/03/20) 名前と行番号の区切り記号を "^" から "__" に変更。
742         * @og.rev 3.5.5.0 (2004/03/12) 名前と行番号の区切り記号("__")を、HybsSystem.JOINT_STRING  に変更。
743         * @og.rev 3.6.0.6 (2004/10/22) chboxNames 属性は廃止します。
744         * @og.rev 3.8.0.1 (2005/06/17) チェックボックス対応で、エラーチェックをPL/SQLで行う場合の処理機能の追加
745         * @og.rev 3.8.0.2 (2005/07/11) チェックボックス対応で、判定を DBColumnのgetEditor()を使用します
746         * @og.rev 4.0.0.0 (2006/09/31) strictCheck 追加。
747         * @og.rev 4.3.7.3 (2009/06/22) HSQLDB対応でリクエストが空文字の場合はnull文字に変換する
748         * @og.rev 5.0.0.2 (2009/09/15) XSS対応(ALLはチェックしない)
749         * @og.rev 5.6.1.2 (2013/02/22) isAllRow 引数追加
750         *
751         * @param isAllRows 全件処理 [true:する/false:しない]
752         */
753        private void setRequestValues( final boolean isAllRows ) {
754                final Enumeration<?> enume = getParameterNames();               // 4.3.3.6 (2008/11/15) Generics警告対応
755
756                while( enume.hasMoreElements() ) {
757                        final String key  = (String)(enume.nextElement());
758                        final int    idx  = key.lastIndexOf(HybsSystem.JOINT_STRING);
759
760                        if( idx > 0 ) {
761                                final String    column  = key.substring(0,idx);
762                                final int               clmNo   = table.getColumnNo( column,strictCheck );
763                                if( clmNo < 0 ) { continue; }   // strictCheck 対応
764                                final DBColumn dbColumn = table.getDBColumn( clmNo );
765                                final int      row      = Integer.parseInt( key.substring(idx + 2) );
766                                // 5.0.0.2 (2009/09/15) 文字種別ALLはXSSチェックしない
767                                // String   val      = dbColumn.valueSet( getRequestValue( key ) );
768                                String   val = null;
769                                if( "ALL".equals( dbColumn.getDbType() ) ){
770                                        val = dbColumn.valueSet( getRequestValue( key, false ) );
771                                }
772                                else{
773                                        val = dbColumn.valueSet( getRequestValue( key ) );
774                                }
775
776                                // 3.6.0.6 (2004/10/22) チェックボックスはマルチでデータが来ます。
777                                // 3.8.0.2 (2005/07/11) 判定を DBColumnのgetEditor()を使用
778                                if( "0".equals(val) && "CHBOX".equals( dbColumn.getEditor() ) ) {
779                                        final String[] vals = getRequestValues( key );
780                                        if( vals != null ) {
781                                                for( int i=0; i<vals.length; i++ ) {
782                                                        if( "1".equals( vals[i] ) ) { val = "1"; break; }
783                                                }
784                                        }
785                                }
786
787                                // 5.6.1.2 (2013/02/22) リクエスト変数すべてのデータを設定
788                                if( isAllRows ) {
789                                        // 4.3.7.3 (2009/06/22) HSQLDB対応
790                                        if( val != null && val.isEmpty() ){
791                                                val = null;
792                                        }
793                                        table.setValue(row, column, val );
794                                }
795                                // 従来のロジック(チェックを外してSUBMITするケースを想定している。)
796                                else {
797                                        // rowNo は、getParameterRows メソッドでソートされているので、
798                                        // java.util.Arrays#binarySearch(int[] a, int key) が使えるはず。
799                                        // 十分にテストしていないため、今は変更しない。
800                                        for( int i=0; i<rowNo.length; i++ ) {
801                                                if( rowNo[i] == row ) {
802                                                        // 4.3.7.3 (2009/06/22) HSQLDB対応
803                                                        if( val != null && val.isEmpty() ){
804                                                                val = null;
805                                                        }
806                                                        table.setValue(row, column, val );
807                                                }
808                                        }
809                                }
810                        }
811                }
812        }
813
814        /**
815         * ColumnSetTag で指定された条件を元に、その行の値を書き換えます。
816         *
817         * @og.rev 3.6.0.6 (2004/10/22) conditionKey と、 conditionList 属性を追加
818         * @og.rev 3.8.1.5 (2006/03/30) writableControl を使用したカラムデータの先頭アンダーバーを削除します。
819         * @og.rev 4.0.0.0 (2006/09/31) strictCheck 追加。
820         * @og.rev 4.3.7.3 (2009/06/22) HSQLDB対応で空文字→NULL
821         * @og.rev 5.6.5.2 (2013/06/21) valueの初期値を利用して、1レコードごとに、+1した値をセットします。
822         * @og.rev 5.7.8.0 (2014/07/04) actionExec の引数を columnId ではなく、DBColumnオブジェクト に変更します。
823         * @og.rev 6.4.3.4 (2016/03/11) Formatterに新しいコンストラクターを追加する。
824         * @og.rev 6.9.9.0 (2018/08/20) action に、TBLNULLSETを追加。
825         *
826         * @param       val 指定行データ配列
827         *
828         * @return      変更後の指定行データ配列
829         */
830        private String[] setColumnValues( final String[] val ) {
831                if( values != null ) {
832                        final int size = values.size();
833                        for( int i=0; i<size; i++ ) {
834                                final Attributes attri = values.get( i );
835                                final String columnId = attri.get( "columnId" );
836                                final int clmNo = table.getColumnNo( columnId,strictCheck );
837                                if( clmNo < 0 ) { continue; }   // strictCheck 対応
838                                final String action = attri.get( "action" );
839                                final String newVal = attri.get( "value"  );
840                                final String oldVal = val[clmNo];
841
842                                // 3.6.0.6 (2004/10/22) 条件による処理の実行可否判定
843                                final String conditionList = attri.get( "conditionList" );
844                                if( conditionList != null ) {   // null の場合は、無条件実行
845                                        final String conditionKey = attri.get( "conditionKey" );
846                                        final int condClmNo = table.getColumnNo( conditionKey );
847                                        final String condValue = "|" + val[condClmNo] + "|";
848                                        if( conditionList.indexOf( condValue ) < 0 ) {
849                                                continue;
850                                        }
851                                }
852
853                                if( ACT_COPY.equals( action ) ) {
854                                        final int copyClmNo = table.getColumnNo( newVal );      // newVal はコピー元カラム名
855                                        val[clmNo] = val[copyClmNo];
856                                }
857                                else if( ACT_TBLSET.equals( action ) ) {
858                                        final ArrayDataModel model = new ArrayDataModel( table.getNames() );
859                                        model.setValues( val,0 );
860                                        final Formatter format = new Formatter( model,newVal ); // 6.4.3.4 (2016/03/11)
861                                        val[clmNo] = format.getFormatString( 0 );
862                                }
863                                // 6.9.9.0 (2018/08/20) action に、TBLNULLSETを追加。
864                                else if( ACT_TBLNULLSET.equals( action ) ) {
865                                        if( val[clmNo] == null || val[clmNo].isEmpty() ) {
866                                                final ArrayDataModel model = new ArrayDataModel( table.getNames() );
867                                                model.setValues( val,0 );
868                                                final Formatter format = new Formatter( model,newVal ); // 6.4.3.4 (2016/03/11)
869                                                val[clmNo] = format.getFormatString( 0 );
870                                        }
871                                }
872                                // 3.8.1.5 (2006/03/30) writableControl を使用したカラムデータの先頭アンダーバーを削除します。
873                                else if( ACT_WRTCTRL.equals( action ) ) {
874                                        if( StringUtil.startsChar( oldVal , '_' ) ) {                   // 6.2.0.0 (2015/02/27) 1文字 String.startsWith
875                                                val[clmNo] = oldVal.substring( 1 );
876                                        }
877                                }
878                                // 3.8.5.3 (2006/08/07) DBMENUでパラメータ設定(コロン連結文字)を使用したカラムデータの先頭データのみにします。
879                                else if( ACT_DBMENU.equals( action ) ) {
880                                        if( oldVal != null && oldVal.length() > 0 ) {
881                                                final int adrs = oldVal.indexOf( ':' );
882                                                if( adrs >= 0 ) {
883                                                        val[clmNo] = oldVal.substring( 0,adrs );
884                                                }
885                                        }
886                                }
887                                // 5.4.2.1 (2011/12/09) valueで指定したカラムの値をキーに、リクエスト変数から値を取出し、セットします。
888                                else if( ACT_REQSET.equals( action ) ) {
889                                        if( newVal != null && newVal.length() > 0 ) {
890                                                final int reqClmNo = table.getColumnNo( newVal );       // newVal はリクエスト取得元カラム名
891                                                String reqClm = val[reqClmNo];                          // この時点では、コロン引数が付いている可能性がある。
892
893                                                final int adrs = reqClm.indexOf( ':' );                 // 先頭がカラム名
894                                                if( adrs >= 0 ) {
895                                                        reqClm = reqClm.substring( 0,adrs );    // コロンより前方の分だけ取り出す。
896                                                }
897                                                val[clmNo] = getRequestValue( reqClm );
898                                        }
899                                }
900                                // 5.6.5.2 (2013/06/21) valueの初期値を利用して、1レコードごとに、+1した値をセットします。
901                                else if( ACT_SEQSET.equals( action ) ) {
902                                        int intVal = seqsetCnt ;
903                                        if( newVal != null && newVal.length() > 0 ) {
904                                                intVal += Integer.parseInt( newVal );           // value の設定値
905                                        }
906                                        val[clmNo] = String.valueOf( intVal );
907                                }
908                                else {
909                                        // 5.7.8.0 (2014/07/04) actionExec の引数を columnId ではなく、DBColumnオブジェクト に変更します。
910                                        final DBColumn dbClm = table.getDBColumn( clmNo );
911                                        val[clmNo] = actionExec( action,dbClm,oldVal,newVal );
912                                }
913
914                                // 4.3.7.3 (2009/06/22) HSQLDB対応
915                                if( val[clmNo] != null && val[clmNo].isEmpty()){
916                                        val[clmNo] = null;
917                                }
918                        }
919                }
920                seqsetCnt ++ ;          // // 5.6.5.2 (2013/06/21) SEQSET のカウンター。
921
922                return val;
923        }
924
925        /**
926         * アクションを実行します。
927         *
928         * アクションは,指定のアクションコマンドに対応する処理を入力データに対して行います。
929         *
930         * @og.rev 3.4.0.3 (2003/09/10) NULLSET Action を追加します。
931         * @og.rev 5.6.0.3 (2012/01/24) ADD Action に、value引数の値を加算する機能を追加します。
932         * @og.rev 5.6.6.1 (2013/07/12) action に、PREFIX,SUFIX を追加します。
933         * @og.rev 5.7.8.0 (2014/07/04) columnId ではなく、DBColumnオブジェクト に変更します。
934         *
935         * @param   action アクションコマンド
936         * @param   dbColumn DBColumnオブジェクト
937         * @param   oldValue 入力データ(旧データ)
938         * @param   newValue 入力データ(新データ)
939         *
940         * @return      実行後のデータ
941         * @see         <a href="../../../../constant-values.html#org.opengion.hayabusa.taglib.EntryTag.ACT_DEFAULT">アクション定数</a>
942         */
943        private String actionExec( final String action,final DBColumn dbColumn,final String oldValue,final String newValue ) {
944                String rtnVal = oldValue;
945
946                if( ACT_DEFAULT.equals(    action ) ) { rtnVal = dbColumn.getDefault(); }
947                else if( ACT_CLEAR.equals( action ) ) { rtnVal = ""; }
948                else if( ACT_SET.equals(   action ) ) { rtnVal = dbColumn.valueSet( newValue ); }
949                else if( ACT_ADD.equals(   action ) ) { rtnVal = dbColumn.valueAdd( oldValue,newValue ); }      // 5.6.0.3 (2012/01/24)
950                else if( ACT_LOWER.equals( action ) ) {
951                        if( oldValue == null ) { rtnVal = dbColumn.getDefault();  }
952                        else                   { rtnVal = oldValue.toLowerCase(Locale.JAPAN); }
953                }
954                else if( ACT_UPPER.equals( action ) ) {
955                        if( oldValue == null ) { rtnVal = dbColumn.getDefault();  }
956                        else                   { rtnVal = oldValue.toUpperCase(Locale.JAPAN); }
957                }
958                // 3.4.0.3 (2003/09/10) NULLSET Action を追加します。
959                else if( ACT_NULLSET.equals( action ) ) {
960                        if( oldValue == null || oldValue.isEmpty() ) {
961                                rtnVal = dbColumn.valueSet( newValue );
962                        }
963                }
964                // 5.6.6.1 (2013/07/12) PREFIX Action を追加します。
965                else if( ACT_PREFIX.equals( action ) ) {
966                        if( oldValue != null && oldValue.length() > 0 && newValue != null && newValue.length() > 0 ) {
967                                final int indx = oldValue.lastIndexOf( newValue );
968                                if( indx >= 0 ) {
969                                        rtnVal = oldValue.substring( 0,indx );
970                                }
971                        }
972                }
973                // 5.6.6.1 (2013/07/12) SUFIX Action を追加します。
974                else if( ACT_SUFIX.equals( action ) ) {
975                        if( oldValue != null && oldValue.length() > 0 && newValue != null && newValue.length() > 0 ) {
976                                final int indx = oldValue.lastIndexOf( newValue );
977                                if( indx >= 0 ) {
978                                        rtnVal = oldValue.substring( indx+1 );          // 分割記号は含まないので+1する。
979                                }
980                        }
981                }
982                else {
983                        rtnVal = dbColumn.valueAction( action,oldValue,newValue );
984                }
985
986                if( rtnVal == null ) { rtnVal = dbColumn.getDefault(); }
987
988                return rtnVal;
989        }
990
991        /**
992         * 【TAG】指定の回数分だけ、繰り返し処理を行う回数を指定します(初期値:1)。
993         *
994         * @og.tag
995         * 追加や複写時に、指定の回数分だけ、処理を繰り返して、新規に行を
996         * 作成します。
997         * 繰り返しは、指定の行に対して行われ、繰り返し毎に、直前に作成された
998         * 行を元に処理します。これは、例えば、columnSet で、action="ADD"の場合に、
999         * 繰り返す毎に、ADD処理が実行されることを意味します。
1000         * 行が指定されていない場合は、先頭空行に追加します。
1001         * 初期値は、1回です。
1002         *
1003         * @og.rev 3.5.4.2 (2003/12/15) 新規追加
1004         *
1005         * @param       rc      繰り返し処理回数(初期値:1)
1006         */
1007        public void setRepeatCount( final String rc ) {
1008                repeatCount = nval( getRequestParameter( rc ),repeatCount );
1009        }
1010
1011        /**
1012         * 【TAG】Consistency キー による整合性チェックを行うかどうか[true/false]を指定します(初期値:true)。
1013         *
1014         * @og.tag
1015         * 検索結果を DBTableModel にセットする時に、整合性キーの Consistency キーを
1016         * 作成します。これを、Viewタグでhidden出力しておき、Entryタグでデータ書き換え時に
1017         * 整合性チェックを行います。これは、IEの戻るボタンで戻った場合に、画面の
1018         * キーと検索結果の DBTableModel の内容が一致しない場合のエラーチェックに
1019         * なります。
1020         * この属性は、何らかのケースで、このエラーチェックを行いたくない場合に、
1021         * false に設定することで、整合性チェックを行いません。
1022         * 初期値は、true(整合性チェックを行う)です。
1023         *
1024         * @og.rev 3.5.5.7 (2004/05/10) 新規登録
1025         *
1026         * @param       ck      整合性チェック [true:行う/false:行わない]
1027         */
1028        public void setUseConsistency( final String ck ) {
1029                useConsistency = nval( getRequestParameter( ck ),useConsistency );
1030        }
1031
1032        /**
1033         * DBTableModel の 整合性パラメータとリクエスト情報を比較チェックします。
1034         * リクエスト情報は、その DBTableModel が出力された view で hidden 属性で
1035         * 設定されます。
1036         * 設定されるキーは、tableId が変更されていなければ、HybsSystem.CONSISTENCY_KEY です。
1037         * 変更されていれば、HybsSystem.CONSISTENCY_KEY + tableId です。
1038         *
1039         * @og.rev 3.5.5.8 (2004/05/20) Consistency キー による整合性チェックを checkConsistency() に集約します。
1040         * @og.rev 6.4.2.1 (2016/02/05) useConsistency の判定条件を見直します。
1041         * @og.rev 6.9.8.0 (2018/05/28) consistencyKey に、tableId を考慮します。
1042         *
1043         * @return チェック結果  true:正常/false:異常
1044         * @see org.opengion.hayabusa.common.HybsSystem#CONSISTENCY_KEY
1045         */
1046        private boolean checkConsistency() {
1047                boolean rtn = true;
1048
1049                // 6.4.2.1 (2016/02/05) useConsistency の判定条件を、見直します。
1050                if( useConsistency ) {
1051                        // 6.9.8.0 (2018/05/28) consistencyKey に、tableId を考慮します。
1052                        final String name       = HybsSystem.TBL_MDL_KEY.equals( tableId )
1053                                                                        ? HybsSystem.CONSISTENCY_KEY
1054                                                                        : HybsSystem.CONSISTENCY_KEY + tableId ;
1055//                      final String consisKey = getRequestValue( HybsSystem.CONSISTENCY_KEY );
1056                        final String consisKey = getRequestValue( name );                                               // 6.9.8.0 (2018/05/28)
1057                        if( consisKey != null && consisKey.length() > 0 ) {
1058                                if( ! consisKey.equals( table.getConsistencyKey() ) ) {
1059                                        final ErrorMessage errMsgObj = new ErrorMessage( "Consistency Key Check Error!" );
1060                                        errMsgObj.addMessage( 0,ErrorMessage.NG,"ERR0033.1" );                  // 画面とデータの整合性チェックでエラーが出ました。
1061                                        errMsgObj.addMessage( 0,ErrorMessage.NG,"ERR0033.2" );                  // すでにデータは更新されている為、その画面からは登録できません。
1062                                        errMsgObj.addMessage( 0,ErrorMessage.NG,"ERR0033.3" );                  // ブラウザの戻るボタンで戻り、登録すると、このエラーが出ます。
1063                                        jspPrint( TaglibUtil.makeHTMLErrorTable( errMsgObj,getResource() ) );
1064                                        rtn = false;
1065                                }
1066                        }
1067                        else {
1068                                System.out.println( "EntryTag:Consistency Key is null" );
1069                        }
1070                }
1071                return rtn ;
1072
1073        }
1074
1075        /**
1076         * 表示データの HybsSystem.ROW_SEL_KEY を元に、選ばれた 行を処理の対象とします。
1077         *
1078         * @og.rev 3.8.1.1 (2005/11/21) selectedAll 追加。全件選択されたこととして、処理します。
1079         * @og.rev 4.0.0.0 (2005/01/31) getParameterRows() を使用するように変更
1080         *
1081         * @return      選択行の配列
1082         * @og.rtnNotNull
1083         */
1084        @Override
1085        protected int[] getParameterRows() {
1086                final int[] rowNo ;
1087                if( selectedAll ) {
1088                        final int rowCnt = table.getRowCount();         // 3.5.5.7 (2004/05/10)
1089                        rowNo = new int[ rowCnt ];
1090                        for( int i=0; i<rowCnt; i++ ) {
1091                                rowNo[i] = i;
1092                        }
1093                } else {
1094                        rowNo = super.getParameterRows();               // 4.0.0 (2005/01/31)
1095                }
1096                return rowNo ;
1097        }
1098
1099        /**
1100         * 【TAG】データを全件選択済みとして処理するかどうか[true/false]を指定します(初期値:false)。
1101         *
1102         * @og.tag
1103         * 全てのデータを選択済みデータとして扱って処理します。
1104         * 全件処理する場合に、(true/false)を指定します。
1105         * 初期値は false です。
1106         *
1107         * @param  all 全件選択済み処理 [true:全件選択済み/false:通常]
1108         */
1109        public void setSelectedAll( final String all ) {
1110                selectedAll = nval( getRequestParameter( all ),selectedAll );
1111        }
1112
1113        /**
1114         * 【TAG】(通常は使いません)カラムIDの存在チェックを行うかどうか[true/false]を指定します(初期値:true)。
1115         *
1116         * @og.tag
1117         * true の場合、カラムIDがDBTableModel に存在しない場合は、エラーになります。
1118         * false の場合、カラムIDがDBTableModel に存在しない場合は、無視します。
1119         * これは、検索条件によって、設定されるカラムが異なる場合でも、entryタグを
1120         * 正常に動作させたい場合に、使用します。
1121         * 初期値は true (チェックを行う) です。
1122         *
1123         * @param  check 存在チェック [true:行う/false:行わない]
1124         */
1125        public void setStrictCheck( final String check ) {
1126                strictCheck = nval( getRequestParameter( check ),strictCheck );
1127        }
1128
1129        /**
1130         * 【TAG】(通常は使いません)画面遷移を行わない形式の登録方法を使用するかを指定します。
1131         *
1132         * @og.tag
1133         * 画面遷移なしの登録を行うかどうかを指定します。
1134         * trueが指定された場合、entryタグでは、行の追加・複写時にDBTableModel上の最終行にデータを
1135         * 追加します。
1136         * 画面遷移なしモードの場合、途中行に挿入された場合、既にクライアントに出力されている
1137         * チェックボックスの行番号や各入力フィールドの変数名との整合性を合わせるためには、
1138         * 編集行以降の各変数値を全て再計算する必要があります。
1139         * この処理は、レスポンス悪化に繋がるため、DBTableModel上は、中間に行の挿入を行いません。
1140         * 但し画面表示上は、通常通り選択行の直下に行が挿入されるため、DBTableModelの順番と標準順が
1141         * 異なります。(エンジン側では、各チェックボックスの値で行を識別しているため、問題は発生しません)
1142         *
1143         * この値は、og:headタグで設定値、または前画面からの値を継承するため、通常、この属性ではセットしません。
1144         *
1145         * @og.rev 4.3.3.0 (2008/10/01) 新規追加
1146         * @og.rev 5.1.3.0 (2010/02/01) noTransition、ajaxSubmitのコントロールは、requestで行う。
1147         *
1148         * @param   noTrnstn 画面遷移を行わない形式の登録方法を使用するか
1149         */
1150        public void setNoTransition( final String noTrnstn ) {
1151                setNoTransitionRequest( nval( getRequestParameter( noTrnstn ), isNoTransitionRequest() ) );
1152        }
1153
1154        /**
1155         * このオブジェクトの文字列表現を返します。
1156         * 基本的にデバッグ目的に使用します。
1157         *
1158         * @return このクラスの文字列表現
1159         * @og.rtnNotNull
1160         */
1161        @Override
1162        public String toString() {
1163                return ToString.title( this.getClass().getName() )
1164                                .println( "VERSION"                                     ,VERSION                                )
1165                                .println( "tableId"                                     ,tableId                                )
1166                                .println( "command"                                     ,command                                )
1167                                .println( "rowNo"                               ,rowNo                          )
1168                                .println( "repeatCount"                         ,repeatCount                    )
1169                                .println( "useConsistency"                      ,useConsistency                 )
1170                                .println( "selectedAll"                         ,selectedAll                    )
1171                                .println( "strictCheck"                         ,strictCheck                    )
1172                                .println( "noTransition"                        ,noTransition                   )
1173                                .println( "RESET_ACTION_ALL_USE"        ,RESET_ACTION_ALL_USE   )
1174                                .println( "Other..."                            ,getAttributes().getAttribute() )
1175                                .fixForm().toString() ;
1176        }
1177}