    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" ならば、１行分のデータを選択された行番号の次に挿入します。
    044 * また、追加、変更、削除された、DBTableModelオブジェクト でも、内部には元のデータを
    045 * 持っているため、command="RESET" で元の状態に戻すことが可能です。
    046 *
    047 * @og.formSample
    048 * ●形式：
    049 *       ・&lt;og:entry command="…"&gt;
    050 *             &lt;og:columnSet command="…" /&gt;
    051 *         &lt;/og:entry&gt;
    052 *       ・&lt;og:entry command="…" /&gt;
    053 *             ･･･columnSetを使わない場合でもresult.jspから次画面(insert,modify,copy.jsp等)に
    054 *                にDBTableModelをもっていく場合には、必ず２を書いてください。
    055 *                (取消のとき、エンジン内でDBTableModelを操作するのに使用する為)
    056 * ●body：あり(EVAL_BODY_BUFFERED:BODYを評価し、{&#064;XXXX} を解析します)
    057 *
    058 * ●Tag定義：
    059 *   &lt;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】(通常は使いません)カラムＩＤの存在チェックを行うかどうか[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 *   &gt;   ... Body ...
    075 *   &lt;/og:entry&gt;
    076 *
    077 * ●使用例
    078 *    &lt;og:entry command="{&#064;command}"  &gt;
    079 *        &lt;og:columnSet command="{&#064;command}" columnId="ECNO"   action="CLEAR" /&gt;
    080 *        &lt;og:columnSet command="{&#064;command}" columnId="JYOKYO" action="SET" value="1" /&gt;
    081 *    &lt;/og:entry&gt;
    082 *
    083 *    &lt;og:entry command="MODIFY" rows="1" &gt;
    084 *        &lt;og:columnSet  command="MODIFY" columnId="key" action="TBLSET" value="[key][lang]"/&gt;
    085 *    &lt;/og:entry&gt;
    086 *
    087 *    action="ADD" は、DBTypeに依存した方法で、既存の値を、＋１ します。
    088 *    &lt;og:entry command="{&#064;command}" repeatCount="5" &gt;
    089 *        &lt;og:columnSet  command="{&#064;command}" columnId="YKNO" action="ADD" /&gt;
    090 *    &lt;/og:entry&gt;
    091 *
    092 *    action="ADD" は、DBTypeに依存した方法で、既存の値に、value の値を加算します。
    093 *    &lt;og:entry command="{&#064;command}" repeatCount="5" &gt;
    094 *        &lt;og:columnSet  command="{&#064;command}" columnId="YKNO" action="ADD" value="5" /&gt;
    095 *    &lt;/og:entry&gt;
    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   値をクリア(ゼロストリング &quot;&quot; )します。
    117 *      ADD     現在の値を ＋１ します。  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の初期値を利用して、１レコードごとに、＋１した値をセットします。
    130 *      PREFIX  valueの値を後ろから検索し、指定のカラム値の前半部分を取得します(記号は含みません)。
    131 *      SUFIX   valueの値を後ろから検索し、指定のカラム値の後半部分を取得します(記号は含みません)。
    132 *      その他  カラムのDBType の valueAction メソッドを呼び出します。自由に設定可能です。
    133 *
    134 *    [strictCheck属性]は、カラムＩＤの存在チェックを行うかどうかを指定します(初期値:true)
    135 *      true    カラムＩＤがDBTableModel に存在しない場合は、エラーになる。
    136 *      false   カラムＩＤが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 引数に渡す事の出来る アクションコマンド  ＋１ {@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) カラムＩＤの存在チェックを行うかどうかを指定します。
    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 ) {                // ２回目以降
    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の初期値を利用して、１レコードごとに、＋１した値をセットします。
    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) １文字 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の初期値を利用して、１レコードごとに、＋１した値をセットします。
    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 );          // 分割記号は含まないので＋１する。
    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         * 初期値は、１回です。
    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】(通常は使いません)カラムＩＤの存在チェックを行うかどうか[true/false]を指定します(初期値:true)。
    1115         *
    1116         * @og.tag
    1117         * true の場合、カラムＩＤがDBTableModel に存在しない場合は、エラーになります。
    1118         * false の場合、カラムＩＤが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}