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