    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 *       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 *   &gt;   ... Body ...
    076 *   &lt;/og:entry&gt;
    077 *
    078 * ●使用例
    079 *    &lt;og:entry command="{&#064;command}"  &gt;
    080 *        &lt;og:columnSet command="{&#064;command}" columnId="ECNO"   action="CLEAR" /&gt;
    081 *        &lt;og:columnSet command="{&#064;command}" columnId="JYOKYO" action="SET" value="1" /&gt;
    082 *    &lt;/og:entry&gt;
    083 *
    084 *    &lt;og:entry command="MODIFY" rows="1" &gt;
    085 *        &lt;og:columnSet  command="MODIFY" columnId="key" action="TBLSET" value="[key][lang]"/&gt;
    086 *    &lt;/og:entry&gt;
    087 *
    088 *    action="ADD" は、DBTypeに依存した方法で、既存の値を、＋１ します。
    089 *    &lt;og:entry command="{&#064;command}" repeatCount="5" &gt;
    090 *        &lt;og:columnSet  command="{&#064;command}" columnId="YKNO" action="ADD" /&gt;
    091 *    &lt;/og:entry&gt;
    092 *
    093 *    action="ADD" は、DBTypeに依存した方法で、既存の値に、value の値を加算します。
    094 *    &lt;og:entry command="{&#064;command}" repeatCount="5" &gt;
    095 *        &lt;og:columnSet  command="{&#064;command}" columnId="YKNO" action="ADD" value="5" /&gt;
    096 *    &lt;/og:entry&gt;
    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   値をクリア(ゼロストリング &quot;&quot; )します。
    118 *      ADD     現在の値を ＋１ します。  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の初期値を利用して、１レコードごとに、＋１した値をセットします。
    131 *      PREFIX  valueの値を後ろから検索し、指定のカラム値の前半部分を取得します(記号は含みません)。
    132 *      SUFIX   valueの値を後ろから検索し、指定のカラム値の後半部分を取得します(記号は含みません)。
    133 *      その他  カラムのDBType の valueAction メソッドを呼び出します。自由に設定可能です。
    134 *
    135 *    [strictCheck属性]は、カラムＩＤの存在チェックを行うかどうかを指定します(初期値:true)
    136 *      true    カラムＩＤがDBTableModel に存在しない場合は、エラーになる。
    137 *      false   カラムＩＤが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 引数に渡す事の出来る アクションコマンド  ＋１ {@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) カラムＩＤの存在チェックを行うかどうかを指定します。
    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 ) {                // ２回目以降
    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の初期値を利用して、１レコードごとに、＋１した値をセットします。
    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) １文字 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の初期値を利用して、１レコードごとに、＋１した値をセットします。
    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 );          // 分割記号は含まないので＋１する。
    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         * 初期値は、１回です。
    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】(通常は使いません)カラムＩＤの存在チェックを行うかどうか[true/false]を指定します(初期値:true)。
    1121         *
    1122         * @og.tag
    1123         * true の場合、カラムＩＤがDBTableModel に存在しない場合は、エラーになります。
    1124         * false の場合、カラムＩＤが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}