    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 static org.opengion.fukurou.util.StringUtil.nval;
    019
    020import java.util.List;
    021import java.util.ArrayList;
    022import java.util.Map;
    023import java.util.LinkedHashMap;
    024import java.util.Collections;
    025import java.util.Locale ;                                                               // 6.7.6.1 (2017/03/17)
    026import java.util.concurrent.ConcurrentMap;                              // 6.7.8.0 (2017/04/21)
    027import java.util.concurrent.ConcurrentHashMap;                  // 6.7.8.0 (2017/04/21)
    028
    029import org.opengion.hayabusa.common.HybsSystem;
    030import org.opengion.hayabusa.db.DBTableModel;
    031import org.opengion.fukurou.util.ToString;                              // 6.8.5.0 (2018/01/09)
    032
    033import static org.opengion.hayabusa.taglib.ValueMapParamTag.VMP_KEYS;   // 6.7.8.0 (2017/04/21)
    034
    035/**
    036 * DBTableModelオブジェクトから、指定のキー情報と、レコードから、Mapオブジェクトを作成し、それを、
    037 * BODY部のフォーマットに対応して、出力します。
    038 *
    039 * valueタグの、command="MAPOBJ" や、ALL_MAPOBJ に相当する処理を、複数キーと行レベルのデータで
    040 * 管理します。
    041 *
    042 * 設定した値は、Mapを優先した、特殊な、{&#064;XXXX} 形式で 取り出すことができます。
    043 *
    044 * keys で、CSV形式でカラム名を指定し、これらを、連結した文字列を、Mapのキー情報に使います。
    045 * Mapの値情報は、そのﾚｺｰﾄﾞの配列になります。
    046 * keys を指定しない場合は、最初のカラムの値が、キーになります。
    047 * キーが重複する場合、先に現れたデータが優先されます。
    048 *
    049 * 値の取出し方法は、キーに対して、{&#064;XXXX} 形式を、適用します。
    050 * Map に存在しないキーは、リクエスト変数や、通常のvalus変数を見ます。
    051 * valClm で、{&#064;XXXX} 形式で取り出す値のカラムを指定できます。
    052 * valClm を指定しない場合は、２番目のカラムを使用します。
    053 *
    054 * 特殊機能
    055 *   ・holdTag属性：{&#064;XXXX} を、指定のタグで囲います。
    056 *     例えば、holdTag="span" とすると、&lt;span class="YYYYの値" &gt;XXXXの値&lt;/span&gt;
    057 *     という文字列を作成します。
    058 *   ・clsClms属性：先の指定のタグで囲う場合、そのタグのclass属性を指定できます。
    059 *     複数指定した場合は、スペースで、連結します。
    060 *   ・{&#064;XXXX cls="B"} とすると、個別の clsClms の値を使用せず、この値を、class属性として使います。
    061 *     clsClms と同様に、holsTag属性を指定しておく必要があります。
    062 *   ・tipsClms属性：先の指定のタグで囲う場合、そのタグのtitle属性を指定できます。
    063 *     マウスオーバーで、チップス表示されます。
    064 *   ・{&#064;XXXX tips="YYYY"} とすると、個別の tipsClms の値を使用せず、この値を、title属性として使います。
    065 *     tipsClms と同様に、holsTag属性を指定しておく必要があります。
    066 *   ・nnClms属性：この属性で指定された値が、nullの場合、{&#064;XXXX} の解析を行いません。
    067 *     正確に言うと、Mapに取り込みません。この場合、先のholdTag属性で指定したタグそのものも
    068 *     出力しません。
    069 *   ・{&#064;XXXX* str="val"} とすると、キーワードのあいまい検索部分に、strで指定した
    070 *     val文字列が存在する場合のみ有効とします。
    071 *   ・キーに対して、Mapは、行データ全部を持っています。{&#064;XXXX} は、最初のカラムの値です。
    072 *   ・２番目を取得する場合は、{&#064;XXXX 1}と、３番目は、{&#064;XXXX 2}と指定します。
    073 *   ・{&#064;XXXX*} を指定すると、キーのあいまい検索で、キーそのものを複数選択することが出来ます。
    074 *     この場合、spanタグで囲う機能と併用すると、複数のspanタグを持つ文字列を合成できます。
    075 *     この特定のタグは、holdTag 属性で指定します。
    076 *     このキーのあいまい検索で、表示する順番は、DBTableModelでMapに読み込んだ順番になります。
    077 *     {&#064;XXXX* 2} のような、取得カラムの指定も可能です。
    078 *     取得カラムの指定も可能ですが、カラム番号は、常に一番最後に記述してください。
    079 *   ・{&#064;XXXX!*} とすると、表示する順番を、逆順にすることが出来ます。取得カラムの指定も可能です。
    080 *   ・{&#064;$XXXX} とすると、holdTagも、clsClms も使用せず、設定値のみ出力します。
    081 *     この場合は、固定値になるため、holsTagも、clsClms も使用しません。
    082 *   ・{&#064;*XXXX!*} とすると、キーのあいまい指定の残り部分の文字列を出力します。連番の場合の番号を取り出せます。
    083 *   ・{&#064;^XXXX} とすると、request.getAttribute()の値を優先して使用します。{&#064;^XXXX*}などのあいまい指定も可能です。
    084 *     この場合、オリジナルのキーは、DBTableModel上に必要です。値の入れ替えのみ、行う感じです。
    085 *
    086 * ※ このタグは、Transaction タグの対象です。
    087 *
    088 * @og.formSample
    089 * ●形式：&lt;og:valueMap /&gt;
    090 * ●body：あり(EVAL_BODY_BUFFERED:BODYを評価し、{&#064;XXXX} を特殊な方法で解析します)
    091 *
    092 * ●Tag定義：
    093 *   &lt;og:valueMap
    094 *       keys               【TAG】パラメータから取り出すキーとなるカラム名を、CSV形式で指定します(初期値:最初のカラム)
    095 *       valClm             【TAG】パラメータから取り出す値のカラム名を指定します(初期値:２番目のカラム)
    096 *       holdTag            【TAG】値の前後を、指定のタグで挟みます
    097 *       clsClms            【TAG】holdTagを使用するとき、そのタグの属性にclass属性を出力する場合のカラム名をCSV形式で指定します
    098 *       tipsClms           【TAG】holdTagを使用するとき、そのタグの属性にtitle属性を出力する場合のカラム名をCSV形式で指定します
    099 *       nnClms             【TAG】パラメータが NULL の時に、設定しないカラム名を、CSV形式で指定します
    100 *       reqAttUpClms       【TAG】{&#064;^XXXX}使用時に request.getAttribute() をセットすると同時に設定するカラム名をCSV形式で指定します 6.9.2.0 (2018/03/05)
    101 *       selectedAll        【TAG】データを全件選択済みとして処理するかどうか[true/false]を指定します(初期値:true)
    102 *       separator          【TAG】キーとなるカラム名の値を連結する項目区切り文字をセットします(初期値:"_")
    103 *       tableId            【TAG】sessionから取得する DBTableModelオブジェクトの ID(初期値:HybsSystem.TBL_MDL_KEY)
    104 *       scope              【TAG】DBTableModelオブジェクトを取得する場合の、scope(初期値:session)
    105 *       xssCheck           【TAG】パラメータの HTMLTag開始/終了文字(&gt;&lt;) 存在チェックを実施するかどうか[true/false]を設定します (初期値:USE_XSS_CHECK[=true])
    106 *       caseKey            【TAG】このタグ自体を利用するかどうかの条件キーを指定します(初期値:null)
    107 *       caseVal            【TAG】このタグ自体を利用するかどうかの条件値を指定します(初期値:null)
    108 *       caseNN             【TAG】指定の値が、null/ゼロ文字列 でない場合(Not Null=NN)は、このタグは使用されます(初期値:判定しない)
    109 *       caseNull           【TAG】指定の値が、null/ゼロ文字列 の場合は、このタグは使用されます(初期値:判定しない)
    110 *       caseIf             【TAG】指定の値が、true/TRUE文字列の場合は、このタグは使用されます(初期値:判定しない)
    111 *       debug              【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false)
    112 *   &gt;   ... Body ...
    113 *   &lt;/og:valueMap&gt;
    114 *
    115 * ●使用例
    116 * &lt;og:query command="{&#064;command}" debug="{&#064;debug}" maxRowCount="{&#064;maxRowCount}"&gt;
    117 *         select CLM,NAME_JA,LABEL_NAME,KBSAKU,SYSTEM_ID,LANG,
    118 *                 FGJ,USRSET,DYSET,USRUPD,DYUPD
    119 *         from GF41
    120 *     &lt;og:where&gt;
    121 *         &lt;og:and value = "SYSTEM_ID  =  '{&#064;SYSTEM_ID}'"  /&gt;
    122 *         &lt;og:and value = "LANG       =  '{&#064;LANG}'"       /&gt;
    123 *         &lt;og:and value = "CLM        like '{&#064;CLM}'"      /&gt;
    124 *         &lt;og:and value = "NAME_JA    like '{&#064;NAME_JA}'"  /&gt;
    125 *         &lt;og:and value = "LABEL_NAME like '{&#064;LABEL_NAME}'" /&gt;
    126 *         &lt;og:and value = "KBSAKU     =    '{&#064;KBSAKU}'"   /&gt;
    127 *     &lt;/og:where&gt;
    128 *     &lt;og:appear startKey = "order by" value = "{&#064;ORDER_BY}"
    129 *                 defaultVal = "SYSTEM_ID,CLM,LANG" /&gt;
    130 * &lt;/og:query&gt;
    131 *
    132 * &lt;og:valueMap keys="SYSTEM_ID,CLM" holdTag="div" separator="_" clsClms="LANG,FGJ" &gt;
    133 * {&#064;XX_AA0001} &lt;br /&gt;   SYSTEM_IDとCLMの値を、separatorで連結。値は、キーの次(LABEL_NAME)
    134 * {&#064;XX_AA0001 1} &lt;br /&gt; 行番号の２番目(上のSQLではNAME_JA)の値
    135 * {&#064;XX_AA0001 2} &lt;br /&gt; 行番号の３番目(上のSQLではLABEL_NAME)の値
    136 *
    137 * {&#064;XX_AA001* 2} &lt;br /&gt; キーの前方一致する行の３番目の値
    138 *
    139 * {&#064;XX_AA000!* 1} キーの前方一致する行の２番目の値を、逆順で表示
    140 *
    141 * &lt;/og:valueMap&gt;
    142 *
    143 *  ・ キーは、select文の１番目のカラム
    144 *     &lt;og:og:valueMap &gt;  ･･･フォーマット･･･ &lt;/og:valueMap&gt;
    145 *  ・ キーが複数で、ユニークになる。(keys)
    146 *     &lt;og:og:valueMap keys="SYSTEM_ID,CLM" &gt;  ･･･フォーマット･･･ &lt;/og:valueMap&gt;
    147 *  ・ 値をdivタグで囲う。(holdTag)
    148 *     &lt;og:og:valueMap keys="SYSTEM_ID,CLM" holdTag="div" &gt;  ･･･フォーマット･･･ &lt;/og:valueMap&gt;
    149 *  ・ キーの連結のセパレータを指定。(separator)
    150 *     &lt;og:og:valueMap keys="SYSTEM_ID,CLM" holdTag="div" separator="_" &gt;  ･･･フォーマット･･･ &lt;/og:valueMap&gt;
    151 *  ・ 値をdivタグで囲う時に、クラス属性を追加します。(clsClms)
    152 *     &lt;og:og:valueMap keys="SYSTEM_ID,CLM" holdTag="div" separator="_" clsClms="LANG,FGJ" &gt;  ･･･フォーマット･･･ &lt;/og:valueMap&gt;
    153 *  ・ 値をdivタグで囲う時に、チップス表示(title属性)を追加します。(tipsClms)
    154 *     &lt;og:og:valueMap keys="SYSTEM_ID,CLM" holdTag="div" separator="_" clsClms="LANG,FGJ" tipsClms="NAME_JA,LABEL_NAME" &gt;  ･･･フォーマット･･･ &lt;/og:valueMap&gt;
    155 *
    156 * @og.group その他部品
    157 * @og.rev 6.7.1.0 (2017/01/05) 新規作成
    158 *
    159 * @version  6.7
    160 * @author   Kazuhiko Hasegawa
    161 * @since    JDK8.0,
    162 */
    163public class ValueMapTag extends CommonTagSupport {
    164        /** このプログラムのVERSION文字列を設定します。   {@value} */
    165        private static final String VERSION = "7.4.2.3 (2021/06/09)" ;
    166        private static final long serialVersionUID = 742320210609L ;
    167
    168        private static final String CLS_KEY  = "cls=" ;         // 6.7.3.0 (2017/01/27) cls指定のｷｰﾜｰﾄﾞ
    169        private static final String TIPS_KEY = "tips=" ;        // 6.7.3.0 (2017/01/27) tips指定のｷｰﾜｰﾄﾞ
    170        private static final String STR_KEY  = "str=" ;         // 6.8.0.1 (2017/06/30) str指定のｷｰﾜｰﾄﾞ
    171
    172        // 8.1.0.0 (2021/12/28) HTML5 準拠に見直し(type="text/css" 不要)
    173//      private static final String NONE1       = "<style type=\"text/css\">." ;        // 6.7.8.0 (2017/04/21)
    174        private static final String NONE1       = "<style>." ;  // 6.7.8.0 (2017/04/21)
    175        private static final String NONE2       = " { display : none ;} </style>" ;     // 6.7.8.0 (2017/04/21)
    176
    177        // 6.9.8.0 (2018/05/28) FindBugs:直列化可能クラスの非 transient で非直列化可能なインスタンスフィールド
    178        private transient       DBTableModel table              ;
    179
    180        private String          tableId         = HybsSystem.TBL_MDL_KEY;
    181        private boolean         selectedAll     = true;
    182        private String          keys            ;
    183        private String          valClm          ;                               // 6.7.2.0 (2017/01/16)
    184        private String          nnClms          ;                               // このカラムの値が、nullのレコードは、使用しません。
    185        private String          holdTag         ;                               // nullの場合は、なにもはさまない。
    186        private String          clsClms         ;                               // holdTagで指定したタグの属性に、class属性を追加します。
    187        private String          tipsClms        ;                               // 6.7.3.0 (2017/01/27) holdTagで指定したタグの属性に、title属性を追加します。
    188        private String          reqAttUpClms;                           // 6.9.2.0 (2018/03/05) request.getAttribute() をセットすると同時に設定するカラム名
    189        private String[]        reqAttClms      ;                               // 6.9.2.0 (2018/03/05) reqAttUpClms を、配列に分解したもの
    190        private String          scope           = "session";    // "request","session"
    191        private String          separator       = "_";                  // 項目区切り文字
    192        private boolean         xssCheck        = HybsSystem.sysBool( "USE_XSS_CHECK" ); // 5.1.7.0 (2010/06/01) XSS対策
    193
    194        private int[]           clsClmsNo       ;                               // clsClmsが指定されない場合は、長さゼロの配列
    195        private int[]           tipsClmsNo      ;                               // 6.7.3.0 (2017/01/27) tipsClmsが指定されない場合は、長さゼロの配列
    196        private int[]           reqAttClmsNo;                           // 6.9.2.0 (2018/03/05) reqAttUpClmsが指定されない場合は、長さゼロの配列
    197        private int                     valClmNo        = 1;                    // valClmが指定されない場合は、２番目のカラム(=1)の値を使用します。
    198
    199        private String          body            ;                               // パラメータ処理済みのBODY部分の文字列
    200        private String          restChangeKey   ;                       // ValueMapParamTag で置き換え処理を行うキーワード
    201        private boolean         useNoneClsKey   ;                       // mapObj の残り処理をおこなうかどうか(true:行う)
    202
    203        // synchronizedMap にする必要性があるのか無いのか、よく判っていません。
    204        /** Collections.synchronizedMap で、同期します。テーブルの行の取得順に、Mapに追加していきます。(先に登録したデータが有効) */
    205        private final Map<String,String[]> mapObj = Collections.synchronizedMap( new LinkedHashMap<>() );
    206
    207        // ValueMapParamTagから受け取った、各種設定情報を、管理するMapオブジェクト。
    208        private final ConcurrentMap<VMP_KEYS,String> paramMap = new ConcurrentHashMap<>();
    209
    210        // ValueMapParamTag で使用する、未使用のキーワードを管理するMap
    211        /** Collections.synchronizedMap で、同期します。テーブルの行の取得順に、Mapに追加していきます。(先に登録したデータが有効) */
    212        private final Map<String,String[]> restMap = Collections.synchronizedMap( new LinkedHashMap<>() );
    213
    214        /**
    215         * デフォルトコンストラクター
    216         *
    217         * @og.rev 6.7.1.0 (2017/01/05) 新規作成
    218         *
    219         */
    220        public ValueMapTag() { super(); }               // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。
    221
    222        /**
    223         * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。
    224         *
    225         * @og.rev 6.7.1.0 (2017/01/05) 新規作成
    226         *
    227         * @return      後続処理の指示
    228         */
    229        @Override
    230        public int doStartTag() {
    231                if( useTag() ) {
    232                        useXssCheck( xssCheck );
    233                        table = (DBTableModel)getObject( tableId );
    234                        if( table != null && table.getRowCount() > 0 && table.getColumnCount() > 0 ) {
    235                                makeMapObj( table );            // Body の評価前にMapを作成する必要がある。
    236
    237                                return EVAL_BODY_BUFFERED ;     // Body を評価する
    238                        }
    239                }
    240                return SKIP_BODY ;                                      // Body を評価しない
    241        }
    242
    243        /**
    244         * Taglibのタグ本体を処理する doAfterBody() を オーバーライドします。
    245         *
    246         * @og.rev 6.7.1.0 (2017/01/05) 新規作成
    247         *
    248         * @return      後続処理の指示(SKIP_BODY)
    249         */
    250        @Override
    251        public int doAfterBody() {
    252                body = getBodyString();
    253
    254                return SKIP_BODY ;
    255        }
    256
    257        /**
    258         * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。
    259         *
    260         * @og.rev 6.7.1.0 (2017/01/05) 新規作成
    261         *
    262         * @return      後続処理の指示
    263         */
    264        @Override
    265        public int doEndTag() {
    266                debugPrint();           // 4.0.0 (2005/02/28)
    267                if( useTag() && body != null ) {
    268                        jspPrint( body );
    269                }
    270
    271                // mapObj の残り処理が必要かどうか。mapObj が空で、NONE_CLS_KEY が存在する場合は、残を隠す。
    272                if( useNoneClsKey ) {
    273                        final String noneClassKey = paramMap.get( VMP_KEYS.NONE_CLS_KEY );
    274                        jspPrint( NONE1 + noneClassKey + NONE2 );
    275                }
    276
    277                return EVAL_PAGE ;
    278        }
    279
    280        /**
    281         * タグリブオブジェクトをリリースします。
    282         * キャッシュされて再利用されるので、フィールドの初期設定を行います。
    283         *
    284         * @og.rev 6.7.1.0 (2017/01/05) 新規作成
    285         * @og.rev 6.7.2.0 (2017/01/16) valClm 追加
    286         * @og.rev 6.7.3.0 (2017/01/27) tipsClms 追加
    287         * @og.rev 6.7.8.0 (2017/04/21) valueMapParam関連
    288         * @og.rev 6.9.2.0 (2018/03/05) reqAttUpClms 追加
    289         */
    290        @Override
    291        protected void release2() {
    292                super.release2();
    293                table           = null;
    294                tableId         = HybsSystem.TBL_MDL_KEY;
    295                selectedAll     = true;
    296                keys            = null;
    297                valClm          = null;                 // 6.7.2.0 (2017/01/16) 新規作成
    298                nnClms          = null;                 // 6.7.2.0 (2017/01/16) 名称変更
    299                holdTag         = null;
    300                clsClms         = null;                 // 6.7.3.0 (2017/01/27) 追加
    301                tipsClms        = null;                 // 6.7.2.0 (2017/01/16) 名称変更
    302                reqAttUpClms= null;                     // 6.9.2.0 (2018/03/05) request.getAttribute() をセットすると同時に設定するカラム名
    303                reqAttClms      = null;                 // 6.9.2.0 (2018/03/05) reqAttUpClms を、配列に分解したもの
    304                scope           = "session";    // DBTableModel の取得先のscope
    305                separator       = "_";
    306                xssCheck        = HybsSystem.sysBool( "USE_XSS_CHECK" );        // 5.1.7.0 (2010/06/01) XSS解除対応
    307                body            = null;
    308                mapObj.clear();
    309
    310                clsClmsNo       = null;                 // clsClmsが指定されない場合は、長さゼロの配列
    311                tipsClmsNo      = null;                 // 6.7.3.0 (2017/01/27) tipsClmsが指定されない場合は、長さゼロの配列
    312                reqAttClmsNo= null;                     // 6.9.2.0 (2018/03/05) reqAttUpClmsが指定されない場合は、長さゼロの配列
    313                valClmNo        = 1;                    // valClmが指定されない場合は、２番目のカラム(=1)の値を使用します。
    314
    315                paramMap.clear();                       // 6.7.8.0 (2017/04/21) valueMapParam関連
    316                restMap.clear();                        // 6.7.8.0 (2017/04/21) valueMapParam関連
    317                restChangeKey   = null ;        // ValueMapParamTag で置き換え処理を行うキーワード
    318                useNoneClsKey   = false ;       // mapObj の残り処理をおこなうかどうか(true:行う)
    319        }
    320
    321        /**
    322         * 指定のスコープの内部キャッシュ情報に、DBTableModel の選択された値を登録します。
    323         *
    324         * @og.rev 6.7.1.0 (2017/01/05) 新規作成
    325         * @og.rev 6.7.2.0 (2017/01/16) valClm 追加
    326         * @og.rev 6.7.3.0 (2017/01/27) tipsClms 追加
    327         * @og.rev 6.7.8.0 (2017/04/21) valueMapParam関連
    328         * @og.rev 6.9.2.0 (2018/03/05) reqAttUpClms 追加
    329         *
    330         * @param table         DBTableModelオブジェクト
    331         */
    332        private void makeMapObj( final DBTableModel table ) {
    333                final int[] rowNo = getParameterRows();
    334                if( rowNo.length == 0 ) { return; }
    335
    336                final int[] keysNo              = getClmNos( table,keys    , 0 );               // keysが指定されない場合は、先頭カラムを使用します。
    337                final int[] nnClmsNo    = getClmNos( table,nnClms  ,-1 );               // nnClmsが指定されない場合は、長さゼロの配列
    338                                        clsClmsNo       = getClmNos( table,clsClms ,-1 );               // clsClmsが指定されない場合は、長さゼロの配列
    339                                        tipsClmsNo      = getClmNos( table,tipsClms,-1 );               // tipsClmsが指定されない場合は、長さゼロの配列
    340                                        reqAttClmsNo= getClmNos( table,reqAttUpClms,-1 );       // 6.9.2.0 (2018/03/05) reqAttClmsが指定されない場合は、長さゼロの配列
    341
    342                if( reqAttUpClms != null && !reqAttUpClms.isEmpty() ) {                 // 6.9.2.0 (2018/03/05) reqAttUpClms を、配列に分解したもの
    343                        reqAttClms = reqAttUpClms.split( "," );
    344                }
    345
    346                for( int j=0; j<rowNo.length; j++ ) {
    347                        final String[] rowData = table.getValues( j );
    348
    349                        // まず、nullチェックして、対象行かどうかを判定する。
    350                        if( isNotNullCheck( rowData , nnClmsNo ) ) {
    351                                // Map に登録するキーを連結して作成します。
    352                                final String mapkey = getAppendKeys( rowData , keysNo , separator );
    353                                mapObj.computeIfAbsent( mapkey, k -> rowData );         // まだ値に関連付けられていない場合、追加します。(先に登録したデータが有効)
    354                //              mapObj.put( mapkey, rowData );                                          // 後で登録したデータが、有効になります。
    355                        }
    356                }
    357                restMap.putAll( mapObj );               // 6.7.8.0 (2017/04/21) 一旦、すべてのMapをコピーします。
    358
    359                // valClmが指定されない場合は、２番目のカラム(=1)の値を使用します。
    360                valClmNo = valClm == null || valClm.isEmpty() ? 1 : table.getColumnNo( valClm.trim() ); // 存在しない場合は、Exception
    361        }
    362
    363        /**
    364         * カラム名のCSV文字列を、DBTableModel の列番号の配列に変換します。
    365         *
    366         * カラム名のCSV文字列が、無指定の場合、no で指定するカラム番号を
    367         * デフォルトとして使用します。no が、マイナスの場合は、長さゼロの
    368         * 配列を返します。
    369         *
    370         * @og.rev 6.7.1.0 (2017/01/05) 新規作成
    371         * @og.rev 6.7.2.0 (2017/01/16) カラム番号の取り方を変更
    372         *
    373         * @param       table           DBTableModelオブジェクト
    374         * @param       clms            カラム名のCSV文字列( nullではない )
    375         * @param       no                      clmsが、nullか、空文字の場合の、カラム番号
    376         * @return      カラム名の列番号の配列
    377         */
    378        private int[] getClmNos( final DBTableModel table , final String clms , final int no ) {
    379                final int[] clmNo ;
    380                if( clms == null || clms.isEmpty() ) {
    381                        if( no < 0 ) { clmNo = new int[0]; }                    // 長さゼロの配列
    382                        else         { clmNo = new int[] { no }; }              // 指定のカラム番号を持つ配列。
    383                }
    384                else {
    385                        final String[] clmAry = clms.split( "," );
    386                        clmNo = new int[clmAry.length];
    387                        for( int i=0; i<clmAry.length; i++ ) {
    388                                clmNo[i] = table.getColumnNo( clmAry[i].trim() );       // 存在しない場合は、Exception
    389                        }
    390                }
    391
    392                return clmNo;
    393        }
    394
    395        /**
    396         * 指定のカラムの値のすべてが、nullか、空文字列でない場合は、true を返します。
    397         *
    398         * @og.rev 6.7.1.0 (2017/01/05) 新規作成
    399         *
    400         * @param       rowData 行データ
    401         * @param       clmNo   カラム番号配列
    402         * @return      nullか、空文字列でない場合は、true
    403         */
    404        private boolean isNotNullCheck( final String[] rowData , final int[] clmNo ) {
    405                boolean rtn = true;                                             // カラムがない場合は、true になります。
    406
    407                // 7.2.9.4 (2020/11/20) PMD:This for loop can be replaced by a foreach loop
    408                for( final int clm : clmNo ) {
    409                        final String val = rowData[ clm ];
    410//              for( int i=0; i<clmNo.length; i++ ) {
    411//                      final String val = rowData[ clmNo[i] ];
    412                        if( val == null || val.isEmpty() ) {
    413                                rtn = false;
    414                                break;
    415                        }
    416                }
    417                return rtn;
    418        }
    419
    420        /**
    421         * Mapのキーとなるキーカラムの値を連結した値を返します。
    422         *
    423         * @param       rowData 行データ
    424         * @param       clmNo   カラム番号配列
    425         * @param       sep             結合させる文字列
    426         *
    427         * @return      Mapのキーとなるキーカラムの値を連結した値
    428         * @og.rtnNotNull
    429         */
    430        private String getAppendKeys( final String[] rowData , final int[] clmNo , final String sep ) {
    431                final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE );
    432
    433                if( clmNo.length > 0 ) {
    434                        buf.append( rowData[ clmNo[0] ] );                              // 最初のひとつ目
    435                        for( int i=1; i<clmNo.length; i++ ) {
    436                                final String val = rowData[ clmNo[i] ];
    437                                if( val != null && !val.isEmpty() ) {
    438                                        buf.append( sep ).append( val );
    439                                }
    440                        }
    441                }
    442                return buf.toString().trim();
    443        }
    444
    445        /**
    446         * Mapの値となる値カラムに対応する文字列配列を返します。
    447         *
    448         * ここでは、行データに対して、配列の添え字(カラム番号)を元に、値を求めます。
    449         * その際、holdTag や、clsClms で指定したクラス名などの付加情報もセットします。
    450         * さらに、{&#064;$XXXX} などの、holdTagの抑止(生データを返す) 処理を行います。
    451         *
    452         * @param       rowData         行の配列データ
    453         * @param       val                     値データ
    454         * @param       isNormal        holdTagを使用せず、ノーマル状態の値を出力するかどうか[true:ノーマルの値]
    455         * @param       cls                     clsClmsNoの使用を抑止し、指定の値を、class属性にセットします。(nullはclsClmsNoを使用、isEmpty() は、classの削除、それ以外は置き換え)
    456         * @param       tips            tipsClmsNoの使用を抑止し、指定の値を、title属性にセットします。(nullはtipsClmsNoを使用、isEmpty() は、titleの削除、それ以外は置き換え)
    457         * @param       sufix           キーのあいまい指定時に、あいまいキー以降の文字列を指定します。あれば、その値を使用します。
    458         *
    459         * @og.rev 6.7.3.0 (2017/01/27) tips 追加
    460         *
    461         * @return      Mapのキーに対応する修飾した値
    462         * @og.rtnNotNull
    463         */
    464        private String getMapVals( final String[] rowData , final String val , final boolean isNormal , final String cls , final String tips , final String sufix ) {
    465                String rtnVal = sufix == null || sufix.isEmpty() ? val : sufix ;
    466
    467                if( !isNormal && holdTag != null && !holdTag.isEmpty() ) {
    468                        // 毎行ごとに、class属性の値は異なる。
    469                        final String clazz = cls  == null ? getAppendKeys( rowData,clsClmsNo ," " ) : cls ;             // class 属性は、スペースで連結
    470                        final String title = tips == null ? getAppendKeys( rowData,tipsClmsNo," " ) : tips ;    // title 属性は、スペースで連結
    471
    472                        final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE );
    473                        buf.append( '<' ).append( holdTag );
    474                        if( !clazz.isEmpty() ) { buf.append( " class=\"" ).append( clazz ).append( '"' ); }
    475                        if( !title.isEmpty() ) { buf.append( " title=\"" ).append( title ).append( '"' ); }
    476                        buf.append( '>' ).append( rtnVal ).append( "</" ).append( holdTag ).append( '>' );
    477
    478                        rtnVal = buf.toString();
    479                }
    480                return rtnVal ;
    481        }
    482
    483        /**
    484         * リクエスト情報の文字列を取得します。
    485         *
    486         * これは、CommonTagSupportの#getRequestValue( String ) を
    487         * オーバーライドして、Mapから、設定値を取得します。
    488         *
    489         * @og.rev 6.7.1.0 (2017/01/05) 新規作成
    490         * @og.rev 6.7.2.0 (2017/01/16) valClm 追加
    491         * @og.rev 6.7.3.0 (2017/01/27) tips 追加
    492         * @og.rev 6.7.6.1 (2017/03/17) 値データを渡すようにします(isAttVal の追加対応)。
    493         * @og.rev 6.7.8.0 (2017/04/21) valueMapParam関連
    494         * @og.rev 6.8.0.1 (2017/06/30) str指定のｷｰﾜｰﾄﾞ
    495         * @og.rev 6.9.2.0 (2018/03/05) reqAttUpClms 追加
    496         *
    497         * @param    key キー
    498         *
    499         * @return   リクエスト情報の文字列
    500         * @see         CommonTagSupport#getRequestValue( String )
    501         */
    502        @Override
    503        protected String getRequestValue( final String key ) {
    504                if( key.equals( restChangeKey ) ) { return makeRestValue(); }           // 6.7.8.0 (2017/04/21)
    505
    506                // {@!XXXX} や、{@*XXXX!*} の場合のキー対応。最初に行う。
    507                final char ch1 = key.charAt(0);
    508                final boolean isNormal = ch1 == '$' ;           // holdTag を使わず、値そのものを出します。
    509                final boolean isSufix  = ch1 == '*' ;           // あいまい検索時に、あいまいで削除された部分文字列を使うかどうか。
    510                final boolean isAttVal = ch1 == '^' ;           // 値を、request.getAttribute()の値を優先して使用します。
    511
    512                final StringBuilder keyBuf = new StringBuilder( key.trim() );
    513
    514                if( isNormal || isSufix || isAttVal ) { keyBuf.deleteCharAt( 0 ); }             // 先頭の文字を削除
    515
    516                // カラム番号の取得のための分割。存在する場合は、必ず一番最後にします。
    517                final int ad1  = keyBuf.lastIndexOf( " " );             // 後ろから検索して、スペースで分割
    518                int       vcNo = valClmNo;
    519                if( ad1 > 0 ) {
    520                        // 必要かどうかはともかく、NumberFormatException で、判定すると、遅くなる気がする。
    521                        final char ch = keyBuf.charAt( ad1 + 1 );       // 数字であろう先頭文字
    522                        if( '0' <= ch && ch <= '9' ) {
    523                                try {
    524                                        vcNo   = Integer.parseInt( keyBuf.substring( ad1 + 1 ) );
    525                                        keyBuf.setLength( ad1 );                                                                        // ｽﾍﾟｰｽが残っている可能性がある
    526                                }
    527                                catch( final NumberFormatException ex ) {               // 数値変換失敗時は、普通のパラメータだった場合。
    528                                        System.err.println( ex.getMessage() );  // 8.0.0.0 (2021/07/31)
    529//                                      ;
    530        //                              vcNo   = valClmNo;              // vcNo は、セットする前にException が発生している。
    531        //                              mapkey = key;                   // mapkey は、スペースも含むすべてのキーになる。･････ NumberFormatException が先なので、setLength されていない。
    532                                }
    533                        }
    534                }
    535
    536                // cls="B" 属性の取得
    537                final String cls = getExtParam( keyBuf,CLS_KEY );               // 6.8.0.1 (2017/06/30) 関数化
    538
    539                // 6.7.3.0 (2017/01/27) tips="YYYY" 属性の取得
    540                final String tips = getExtParam( keyBuf,TIPS_KEY );             // 6.8.0.1 (2017/06/30) 関数化
    541
    542                // 6.8.0.1 (2017/06/30) str指定のｷｰﾜｰﾄﾞ。先に取り除かないと、type 判定時の endsWith が効かない。
    543                final String instr = getExtParam( keyBuf,STR_KEY );
    544
    545                // 中途半端に、ｽﾍﾟｰｽが残っていると厄介なので、削除しておきます。
    546                final String mapkey = keyBuf.toString().trim();
    547
    548                // type==0 は、ｵﾘｼﾞﾅﾙ。それ以外は、キーから取り除く文字数
    549                final int type = mapkey.endsWith( "!*" ) ? 2 : mapkey.endsWith( "*" ) ? 1 : 0 ;
    550
    551                final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE );
    552                if( type == 0 ) {
    553                        final String[] rowData = mapObj.get( mapkey );
    554                        restMap.remove( mapkey );                                                       // 6.7.8.0 (2017/04/21) valueMapParam関連
    555
    556                        if( rowData != null && vcNo < rowData.length ) {
    557                                // isAttVal == true のときは、RequestAttribute から取り出すが、キーは、大文字になっているので注意。
    558                                // 6.9.2.0 (2018/03/05) DBTableModel への値のﾌｨｰﾄﾞﾊﾞｯｸ
    559//                              final String val = isAttVal ? nval( (String)getRequestAttribute( mapkey.toUpperCase(Locale.JAPAN) ) , rowData[vcNo] ) : rowData[vcNo] ;
    560                                if( isAttVal ) {
    561                                        // isAttVal == true のときは、RequestAttribute から取り出すが、キーは、大文字になっているので注意。
    562                                        final String attVal = (String)getRequestAttribute( mapkey.toUpperCase(Locale.JAPAN) );
    563                                        if( attVal != null && !attVal.isEmpty() ) {
    564                                                rowData[vcNo] = attVal; // RequestAttribute をﾃｰﾌﾞﾙに戻す。
    565                                                for( int i=0; i<reqAttClmsNo.length; i++ ) {    // 未設定の場合は、長さゼロの配列。
    566                                                        if( reqAttClmsNo[i] >= 0 ) {
    567                                                                final String reqAtt = (String)getRequestAttribute( reqAttClms[i] );
    568                                                                rowData[reqAttClmsNo[i]] = reqAtt;              // 同時に戻すカラムの値
    569                                                        }
    570                                                }
    571                                        }
    572                                }
    573
    574                                final String val = rowData[vcNo] ;
    575
    576                                buf.append( getMapVals( rowData , val , isNormal , cls , tips , null ) );
    577                        }
    578                        else {
    579                                buf.append( super.getRequestValue( key , xssCheck ) );                          // 添字も合わせて、上位に問い合わせる。
    580                        }
    581                }
    582                else {
    583                        final String subKey = mapkey.substring( 0,mapkey.length()-type );               // ほんとは、keyBuf で処理したかった。
    584                        final List<String> list = new ArrayList<>();
    585                        for( final Map.Entry<String,String[]> entry : mapObj.entrySet() ) {             // {@XXXX}を見つける都度、全Mapをスキャンしているので、非効率
    586                                final String mapkey2 = entry.getKey();
    587                                // 6.8.0.1 (2017/06/30) str指定のｷｰﾜｰﾄﾞ
    588                                if( mapkey2.startsWith( subKey ) && ( instr == null || mapkey2.contains( instr ) ) ) {
    589                                        final String[] rowData = entry.getValue();
    590                                        if( rowData != null && vcNo < rowData.length ) {
    591                                                final String sufix = isSufix ? mapkey2.substring( subKey.length() ) : null ;    // あいまいキーの残りの文字列
    592                                                // isAttVal == true のときは、RequestAttribute から取り出すが、キーは、大文字になっているので注意。
    593                                                // 6.9.2.0 (2018/03/05) DBTableModel への値のﾌｨｰﾄﾞﾊﾞｯｸ
    594//                                              final String val   = isAttVal ? nval( (String)getRequestAttribute( mapkey2.toUpperCase(Locale.JAPAN) ) , rowData[vcNo] ) : rowData[vcNo] ;
    595                                                if( isAttVal ) {
    596                                                        // isAttVal == true のときは、RequestAttribute から取り出すが、キーは、大文字になっているので注意。
    597                                                        final String attVal = (String)getRequestAttribute( mapkey.toUpperCase(Locale.JAPAN) );
    598                                                        if( attVal != null && !attVal.isEmpty() ) {
    599                                                                rowData[vcNo] = attVal; // RequestAttribute をﾃｰﾌﾞﾙに戻す。
    600                                                                for( int i=0; i<reqAttClmsNo.length; i++ ) {    // 未設定の場合は、長さゼロの配列。
    601                                                                        if( reqAttClmsNo[i] >= 0 ) {
    602                                                                                final String reqAtt = (String)getRequestAttribute( reqAttClms[i] );
    603                                                                                rowData[reqAttClmsNo[i]] = reqAtt;              // 同時に戻すカラムの値
    604                                                                        }
    605                                                                }
    606                                                        }
    607                                                }
    608
    609                                                final String val = rowData[vcNo] ;
    610
    611                                                list.add( getMapVals( rowData , val , isNormal , cls , tips , sufix ) );
    612                                                restMap.remove( mapkey2 );                      // 6.7.8.0 (2017/04/21) valueMapParam関連
    613                                        }
    614                                }
    615                        }
    616                        if( type == 2 ) { Collections.reverse( list ); }        // 逆順
    617                        list.forEach( v -> buf.append( v ) );
    618                }
    619
    620                return buf.toString();
    621        }
    622
    623        /**
    624         * 指定の文字列バッファから、キーワードのパラメータを取り出します。
    625         *
    626         * 元の文字列バッファは、そのキーワード部分を削除し、パラメータの値は、RETURNで
    627         * 返します。存在しない場合は、null を返します。
    628         *
    629         * @og.rev 6.7.1.0 (2017/01/05) 新規作成
    630         *
    631         * @param       keyBuf 文字列バッファ
    632         * @param       key キーワード(cls,tips,str)
    633         * @return      パラメータ
    634         */
    635        private String getExtParam( final StringBuilder keyBuf , final String key ) {
    636                // key="XXX" 属性の取得
    637                String rtn = null;
    638                final int ad2 = keyBuf.lastIndexOf( key );                              // = の前後にｽﾍﾟｰｽは入れてはいけない。
    639                if( ad2 > 0 ) {
    640                        final int st = ad2 + key.length() ;
    641                        // cls="B" や、cls='C' のように、文字列指定されているはずなので、その中身を削除します。
    642                        final String qot = keyBuf.substring( st,st+1 );         // １文字取り出す。
    643                        final int    ed  = keyBuf.indexOf(  qot,st+1 );         // 対になる後ろのクオートの位置を見つける。
    644                        if( ed >= 0 ) {
    645                                rtn = keyBuf.substring( st+1 , ed );                    // 前後のクオートは、含まない。
    646                                keyBuf.delete( ad2 , ed+1 ) ;                                   // 間を抜く
    647                        }
    648                        else {
    649                                // 文法間違い。どうするか？
    650                                System.err.println( "指定の文法が間違っています。key=" + key );
    651                        }
    652                }
    653
    654                return rtn;
    655        }
    656
    657        /**
    658         * 表示データの HybsSystem.ROW_SEL_KEY を元に、選ばれた 行を処理の対象とします。
    659         *
    660         * @og.rev 6.7.1.0 (2017/01/05) 新規作成
    661         *
    662         * @return      選択行の配列
    663         * @og.rtnNotNull
    664         */
    665        @Override
    666        protected int[] getParameterRows() {
    667                final int[] rowNo ;
    668                if( selectedAll ) {
    669                        final int rowCnt = table.getRowCount();
    670                        rowNo = new int[ rowCnt ];
    671                        for( int i=0; i<rowCnt; i++ ) {
    672                                rowNo[i] = i;
    673                        }
    674                } else {
    675                        rowNo = super.getParameterRows();
    676                }
    677                return rowNo ;
    678        }
    679
    680        /**
    681         * ValueMapParamTagで設定された各種パラメータ を受け取ります。
    682         *
    683         * @og.rev 6.7.8.0 (2017/04/21) ValueMapParamTag のパラメータを追加します。
    684         *
    685         * @param       pMap ValueMapParamTagで設定された各種パラメータ
    686         */
    687        protected void setParam( final ConcurrentMap<VMP_KEYS,String> pMap ) {
    688                paramMap.putAll( pMap );                                // ValueMapParamTag と分けるために、内容をコピーします。
    689
    690                restChangeKey = paramMap.get( VMP_KEYS.REST_CHANGE_KEY );
    691        }
    692
    693        /**
    694         * ValueMapParamTagで設定された各種パラメータを元に、残カラムを処理します。
    695         *
    696         * 処理としては、{&#064;XXXX} の XXXX 部分を、valueMap の未使用キーに変換します。
    697         * その後、通常のパラメータ処理を行います。
    698         * REST_MARK_CLM が指定されている場合は、DBTableModel に対して、マーク処理を行います。
    699         *
    700         * @og.rev 6.7.8.0 (2017/04/21) ValueMapParamTag のパラメータを追加します。
    701         * @og.rev 6.9.9.0 (2018/08/20) YYYYｷｰﾜｰﾄﾞに置換するｸﾞﾙｰﾌﾟｶﾗﾑ名
    702         * @og.rev 6.9.9.2 (2018/09/18) YYYYｷｰﾜｰﾄﾞで、@のあるなしを対処しておきます(前方一致の必要性)。
    703         * @og.rev 7.4.2.3 (2021/06/09) ｸﾞﾙｰﾌﾟ処理で、未処理データが使用済みになった。
    704         *
    705         * @return      残カラム処理の結果
    706         */
    707        private String makeRestValue() {
    708                // 先にDBTableModel に対して、マーク処理を行います。
    709                // パラメータ処理を行うと、キーワードによっては、restMap から値が削除されるためです。
    710                final String markClm = paramMap.get( VMP_KEYS.REST_MARK_CLM );
    711                final String markVal = paramMap.get( VMP_KEYS.REST_MARK_VAL );
    712
    713                if( !restMap.isEmpty() && markClm != null && markVal != null ) {
    714                        final int   clmNo = table.getColumnNo( markClm , false );       // ifの階層が深くなるのが嫌なので、まとめてチェックします。
    715                        final int[] rowNo = getParameterRows();
    716                        if( clmNo >=0 && rowNo.length > 0 ) {
    717                                final int[] keysNo = getClmNos( table,keys , 0 );               // keysが指定されない場合は、先頭カラムを使用します。
    718
    719                                for( int row=0; row<rowNo.length; row++ ) {
    720                                        final String[] rowData = table.getValues( row );
    721
    722                                        // Map に登録されているキーを連結して作成します。
    723                                        final String mapkey = getAppendKeys( rowData , keysNo , separator );
    724
    725                                        if( restMap.containsKey( mapkey ) ) {                           // 残っている場合
    726                                                table.setValueAt( markVal , row , clmNo );
    727                                        }
    728                                }
    729                        }
    730                }
    731
    732                final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE );
    733                if( restMap.isEmpty() ) {
    734                        // restMap の残り処理が必要かどうか。restMap が空で、NONE_CLS_KEY が存在する場合は、残を隠す。
    735                        useNoneClsKey = paramMap.containsKey( VMP_KEYS.NONE_CLS_KEY );
    736                }
    737                else {
    738                        final String changeVal = paramMap.get( VMP_KEYS.BODY_VAL );
    739                        // パラメータ処理を行うと、キーワードによっては、restMap から値が削除されるためです。
    740                        final String[] restKeys = restMap.keySet().toArray( new String[restMap.size()] );
    741
    742                        final String grpClm   = paramMap.get( VMP_KEYS.GRP_KEY_CLM );           // 6.9.9.0 (2018/08/20)
    743                        final int    grpClmNo = table.getColumnNo( grpClm , false );            // 6.9.9.0 (2018/08/20) 無ければ、-1
    744
    745                        // 6.9.9.0 (2018/08/20) YYYYｷｰﾜｰﾄﾞに置換するｸﾞﾙｰﾌﾟｶﾗﾑ名 対応
    746                        for( final String key : restKeys ) {
    747                                final String repStr = changeVal.replaceAll( "XXXX" , key );
    748
    749                                if( grpClmNo < 0 ) {
    750                                        buf.append( getRequestParameter( repStr ) );                            // 従来どおり、YYYY 処理を行わない。
    751                                }
    752                                else {
    753                                        final String[] vals = restMap.get( key );
    754        //                              if( vals == null ) { continue; }                                                        // ｸﾞﾙｰﾌﾟ処理で、未処理データが使用済みになった。
    755                                        if( vals == null || vals.length == 0 ) { continue; }            // 7.4.2.3 (2021/06/09) ｸﾞﾙｰﾌﾟ処理で、未処理データが使用済みになった。
    756                                        final String grpKey = vals[grpClmNo];
    757                                        final String repStr2 = repStr.replaceAll( "YYYY" , grpKey );
    758                                        buf.append( getRequestParameter( repStr2 ) );
    759                                }
    760                        }
    761
    762//                      // 6.9.9.0 (2018/08/20)
    763//                      for( final String key : restKeys ) {
    764//                              final String repStr = changeVal.replaceAll( "XXXX" , key );
    765//                              buf.append( getRequestParameter( repStr ) );
    766//                      }
    767                }
    768
    769                return buf.toString();
    770        }
    771
    772        /**
    773         * 【TAG】データを全件選択済みとして処理するかどうか[true/false]を指定します(初期値:false)。
    774         *
    775         * @og.tag
    776         * 全てのデータを選択済みデータとして扱って処理します。
    777         * 全件処理する場合に、(true/false)を指定します。
    778         * 初期値は false です。
    779         *
    780         * @og.rev 6.7.1.0 (2017/01/05) 新規作成
    781         *
    782         * @param  all 選択済み処理可否 [true:全件選択済み/false:通常]
    783         */
    784        public void setSelectedAll( final String all ) {
    785                selectedAll = nval( getRequestParameter( all ),selectedAll );
    786        }
    787
    788        /**
    789         * 【TAG】(通常は使いません)結果のDBTableModelを、sessionに登録するときのキーを指定します
    790         *              (初期値:HybsSystem#TBL_MDL_KEY[={@og.value HybsSystem#TBL_MDL_KEY}])。
    791         *
    792         * @og.tag
    793         * 検索結果より、DBTableModelオブジェクトを作成します。これを、下流のviewタグ等に
    794         * 渡す場合に、通常は、session を利用します。その場合の登録キーです。
    795         * query タグを同時に実行して、結果を求める場合、同一メモリに配置される為、
    796         * この tableId 属性を利用して、メモリ空間を分けます。
    797         *              (初期値:HybsSystem#TBL_MDL_KEY[={@og.value HybsSystem#TBL_MDL_KEY}])。
    798         *
    799         * @og.rev 6.7.1.0 (2017/01/05) 新規作成
    800         *
    801         * @param       id テーブルID (sessionに登録する時のID)
    802         */
    803        public void setTableId( final String id ) {
    804                tableId   = nval( getRequestParameter( id ),tableId );
    805        }
    806
    807        /**
    808         * 【TAG】パラメータ に登録するキーをセットします。
    809         *
    810         * @og.tag keysが指定されない場合は、先頭カラムを使用します。
    811         *
    812         * @og.rev 6.7.1.0 (2017/01/05) 新規作成
    813         *
    814         * @param       key1 登録キー
    815         */
    816        public void setKeys( final String key1 ) {
    817                keys = nval( getRequestParameter( key1 ),keys ) ;
    818        }
    819
    820        /**
    821         * 【TAG】パラメータ から取り出す値カラムを指定ます。
    822         *
    823         * @og.tag valClmが指定されない場合は、２番目のカラムを使用します。
    824         *
    825         * @og.rev 6.7.2.0 (2017/01/16) 新規作成
    826         *
    827         * @param       clm 取り出す値カラム
    828         */
    829        public void setValClm( final String clm ) {
    830                valClm = nval( getRequestParameter( clm ),valClm ) ;
    831        }
    832
    833        /**
    834         * 【TAG】パラメータが NULL の時に、設定しないカラム名を、CSV形式で指定します。
    835         *
    836         * @og.tag
    837         *  nnClms属性：この属性で指定された値が、nullの場合、{&#064;XXXX} の解析を行いません。
    838         *  正確に言うと、Mapに取り込みません。この場合、先のholdTag属性で指定したタグそのものも
    839         *  出力しません。
    840         *
    841         * @og.rev 6.7.1.0 (2017/01/05) 新規作成
    842         * @og.rev 6.7.2.0 (2017/01/16) 名称変更
    843         *
    844         * @param       clms NULL の時に、設定しないカラム名を、CSV形式で指定
    845         */
    846        public void setNnClms( final String clms ) {
    847                nnClms = nval( getRequestParameter( clms ),nnClms );
    848        }
    849
    850        /**
    851         * 【TAG】値の前後を、挟むタグを指定します。
    852         *
    853         * @og.tag
    854         *  holdTag属性：{&#064;XXXX} を、指定のタグで囲います。
    855         *  例えば、holdTag="span" とすると、&lt;span class="YYYYの値" &gt;XXXXの値&lt;/span&gt;
    856         *  という文字列を作成します。
    857         *  clsClms 属性や、{&#064;XXXX cls="B"} を使用する場合は、holdTag 属性の指定が必要です。
    858         *
    859         * @og.rev 6.7.1.0 (2017/01/05) 新規作成
    860         *
    861         * @param       tag 値の前後を挟むタグ
    862         * @see         #setClsClms( String )
    863         */
    864        public void setHoldTag( final String tag ) {
    865                holdTag = nval( getRequestParameter( tag ),holdTag );
    866        }
    867
    868        /**
    869         * 【TAG】holdTagを使用するとき、そのタグの属性にclass属性を出力する場合のカラム名をCSV形式で指定します。
    870         *
    871         * @og.tag
    872         *   clsClms属性：先の指定のタグで囲う場合、そのタグのclass属性を指定できます。
    873         *   複数指定した場合は、スペースで、連結します。
    874         *   一括指定ではなく、個別に指定する場合は、{&#064;XXXX cls="B"} 構文を使用します。
    875         *   holdTag属性が設定されていない場合は、どちらも無視されます。
    876         *
    877         * @og.rev 6.7.1.0 (2017/01/05) 新規作成
    878         * @og.rev 6.7.2.0 (2017/01/16) 名称変更
    879         *
    880         * @param       clms class属性を出力する場合のカラム名を、CSV形式で指定
    881         * @see         #setHoldTag( String )
    882         */
    883        public void setClsClms( final String clms ) {
    884                clsClms = nval( getRequestParameter( clms ),clsClms );
    885        }
    886
    887        /**
    888         * 【TAG】holdTagを使用するとき、そのタグの属性にtitle属性を出力する場合のカラム名をCSV形式で指定します。
    889         *
    890         * @og.tag
    891         *   tipsClms属性：先の指定のタグで囲う場合、そのタグのtitle属性を指定できます。
    892         *   複数指定した場合は、スペースで、連結します。
    893         *   一括指定ではなく、個別に指定する場合は、{&#064;XXXX tips="YYYY"} 構文を使用します。
    894         *   holdTag属性が設定されていない場合は、どちらも無視されます。
    895         *
    896         * @og.rev 6.7.3.0 (2017/01/16) 名称変更
    897         *
    898         * @param       clms title属性を出力する場合のカラム名を、CSV形式で指定
    899         * @see         #setHoldTag( String )
    900         */
    901        public void setTipsClms( final String clms ) {
    902                tipsClms = nval( getRequestParameter( clms ),tipsClms );
    903        }
    904
    905        /**
    906         * 【TAG】{&#064;^XXXX}使用時に request.getAttribute() をセットすると同時に設定するカラム名をCSV形式で指定します。
    907         *
    908         * @og.tag
    909         * DBTableModel と別に、value等で設定した値を、{&#064;^XXXX} で置き換えますが、
    910         * その際、DBTableModel のﾃﾞｰﾀも置き換えないと、表示とﾃﾞｰﾀ(例えば、一覧表示やﾌｧｲﾙ出力時)が異なります。
    911         * また、置き換えるに当たって、他の項目(カラム)も置き換えないと、矛盾が生じる恐れがあります。
    912         * そこで、request.getAttribute() をセットする場合に、同時にセットするカラムを指定することで、
    913         * 同時に値の書き換えを行います。
    914         * なお、値は、request.getAttribute() で取得します。
    915         *
    916         * @og.rev 6.9.2.0 (2018/03/05) 新規作成
    917         *
    918         * @param       clms request.getAttribute()使用時に、同時に置き換えるカラム名を、CSV形式で指定
    919         */
    920        public void setReqAttUpClms( final String clms ) {
    921                reqAttUpClms = nval( getRequestParameter( clms ),reqAttUpClms );
    922        }
    923
    924        /**
    925         * 【TAG】キーとなるカラム名の値を連結する項目区切り文字をセットします(初期値:"_")。
    926         *
    927         * @og.tag
    928         * keysで、複数のキーの値を連結して、Mapのキーにしますが、そのときの連結文字列を指定します。
    929         * 初期値は、"_" に設定されています。
    930         *
    931         * @og.rev 6.7.1.0 (2017/01/05) 新規作成
    932         *
    933         * @param   sepa 連結文字列 (初期値:"_")
    934         */
    935        public void setSeparator( final String sepa ) {
    936                separator = nval( getRequestParameter( sepa ),separator );
    937        }
    938
    939        /**
    940         * 【TAG】パラメータの HTMLTag開始/終了文字(&gt;&lt;) 存在チェックを実施するかどうか[true/false]を設定します
    941         *              (初期値:USE_XSS_CHECK[={@og.value SystemData#USE_XSS_CHECK}])。
    942         *
    943         * @og.tag
    944         * クロスサイトスクリプティング(XSS)対策の一環としてless/greater than signについてのチェックを行います。
    945         * (&gt;&lt;) が含まれていたエラーにする(true)／かノーチェックか(false)を指定します。
    946         * (初期値:システム定数のUSE_XSS_CHECK[={@og.value SystemData#USE_XSS_CHECK}])。
    947         *
    948         * @og.rev 6.7.1.0 (2017/01/05) 新規作成
    949         *
    950         * @param       flag    XSSチェック [true:する/false:しない]
    951         * @see         org.opengion.hayabusa.common.SystemData#USE_XSS_CHECK
    952         */
    953        public void setXssCheck( final String flag ) {
    954                xssCheck = nval( getRequestParameter( flag ),xssCheck );
    955        }
    956
    957        /**
    958         * このオブジェクトの文字列表現を返します。
    959         * 基本的にデバッグ目的に使用します。
    960         *
    961         * @og.rev 6.7.1.0 (2017/01/05) 新規作成
    962         *
    963         * @return このクラスの文字列表現
    964         * @og.rtnNotNull
    965         */
    966        @Override
    967        public String toString() {
    968                return ToString.title( this.getClass().getName() )
    969                                .println( "VERSION"                     ,VERSION                )
    970                                .println( "tableId"                     ,tableId                )
    971                                .println( "selectedAll"         ,selectedAll    )
    972                                .println( "keys"                        ,keys                   )
    973                                .println( "holdTag"                     ,holdTag                )
    974                                .println( "clsClms"                     ,clsClms                )
    975                                .println( "tipsClms"            ,tipsClms               )
    976                                .println( "valClm"                      ,valClm                 )
    977                                .println( "nnClms"                      ,nnClms                 )
    978                                .println( "scope"                       ,scope                  )
    979                                .println( "separator"           ,separator              )
    980                                .println( "xssCheck"            ,xssCheck               )
    981                                .println( "Other..."    ,getAttributes().getAttribute() )
    982                                .fixForm().toString() ;
    983        }
    984}