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