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