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を優先した、特殊な、{@XXXX} 形式で 取り出すことができます。 043 * 044 * keys で、CSV形式でカラム名を指定し、これらを、連結した文字列を、Mapのキー情報に使います。 045 * Mapの値情報は、そのレコードの配列になります。 046 * keys を指定しない場合は、最初のカラムの値が、キーになります。 047 * キーが重複する場合、先に現れたデータが優先されます。 048 * 049 * 値の取出し方法は、キーに対して、{@XXXX} 形式を、適用します。 050 * Map に存在しないキーは、リクエスト変数や、通常のvalus変数を見ます。 051 * valClm で、{@XXXX} 形式で取り出す値のカラムを指定できます。 052 * valClm を指定しない場合は、2番目のカラムを使用します。 053 * 054 * 特殊機能 055 * ・holdTag属性:{@XXXX} を、指定のタグで囲います。 056 * 例えば、holdTag="span" とすると、<span class="YYYYの値" >XXXXの値</span> 057 * という文字列を作成します。 058 * ・clsClms属性:先の指定のタグで囲う場合、そのタグのclass属性を指定できます。 059 * 複数指定した場合は、スペースで、連結します。 060 * ・{@XXXX cls="B"} とすると、個別の clsClms の値を使用せず、この値を、class属性として使います。 061 * clsClms と同様に、holsTag属性を指定しておく必要があります。 062 * ・tipsClms属性:先の指定のタグで囲う場合、そのタグのtitle属性を指定できます。 063 * マウスオーバーで、チップス表示されます。 064 * ・{@XXXX tips="YYYY"} とすると、個別の tipsClms の値を使用せず、この値を、title属性として使います。 065 * tipsClms と同様に、holsTag属性を指定しておく必要があります。 066 * ・nnClms属性:この属性で指定された値が、nullの場合、{@XXXX} の解析を行いません。 067 * 正確に言うと、Mapに取り込みません。この場合、先のholdTag属性で指定したタグそのものも 068 * 出力しません。 069 * ・{@XXXX* str="val"} とすると、キーワードのあいまい検索部分に、strで指定した 070 * val文字列が存在する場合のみ有効とします。 071 * ・キーに対して、Mapは、行データ全部を持っています。{@XXXX} は、最初のカラムの値です。 072 * ・2番目を取得する場合は、{@XXXX 1}と、3番目は、{@XXXX 2}と指定します。 073 * ・{@XXXX*} を指定すると、キーのあいまい検索で、キーそのものを複数選択することが出来ます。 074 * この場合、spanタグで囲う機能と併用すると、複数のspanタグを持つ文字列を合成できます。 075 * この特定のタグは、holdTag 属性で指定します。 076 * このキーのあいまい検索で、表示する順番は、DBTableModelでMapに読み込んだ順番になります。 077 * {@XXXX* 2} のような、取得カラムの指定も可能です。 078 * 取得カラムの指定も可能ですが、カラム番号は、常に一番最後に記述してください。 079 * ・{@XXXX!*} とすると、表示する順番を、逆順にすることが出来ます。取得カラムの指定も可能です。 080 * ・{@$XXXX} とすると、holdTagも、clsClms も使用せず、設定値のみ出力します。 081 * この場合は、固定値になるため、holsTagも、clsClms も使用しません。 082 * ・{@*XXXX!*} とすると、キーのあいまい指定の残り部分の文字列を出力します。連番の場合の番号を取り出せます。 083 * ・{@^XXXX} とすると、request.getAttribute()の値を優先して使用します。{@^XXXX*}などのあいまい指定も可能です。 084 * この場合、オリジナルのキーは、DBTableModel上に必要です。値の入れ替えのみ、行う感じです。 085 * 086 * ※ このタグは、Transaction タグの対象です。 087 * 088 * @og.formSample 089 * ●形式:<og:valueMap /> 090 * ●body:あり(EVAL_BODY_BUFFERED:BODYを評価し、{@XXXX} を特殊な方法で解析します) 091 * 092 * ●Tag定義: 093 * <og:valueMap 094 * keys 【TAG】パラメータから取り出すキーとなるカラム名を、CSV形式で指定します(初期値:最初のカラム) 095 * valClm 【TAG】パラメータから取り出す値のカラム名を指定します(初期値:2番目のカラム) 096 * holdTag 【TAG】値の前後を、指定のタグで挟みます 097 * clsClms 【TAG】holdTagを使用するとき、そのタグの属性にclass属性を出力する場合のカラム名をCSV形式で指定します 098 * tipsClms 【TAG】holdTagを使用するとき、そのタグの属性にtitle属性を出力する場合のカラム名をCSV形式で指定します 099 * nnClms 【TAG】パラメータが NULL の時に、設定しないカラム名を、CSV形式で指定します 100 * reqAttUpClms 【TAG】{@^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開始/終了文字(><) 存在チェックを実施するかどうか[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 * > ... Body ... 113 * </og:valueMap> 114 * 115 * ●使用例 116 * <og:query command="{@command}" debug="{@debug}" maxRowCount="{@maxRowCount}"> 117 * select CLM,NAME_JA,LABEL_NAME,KBSAKU,SYSTEM_ID,LANG, 118 * FGJ,USRSET,DYSET,USRUPD,DYUPD 119 * from GF41 120 * <og:where> 121 * <og:and value = "SYSTEM_ID = '{@SYSTEM_ID}'" /> 122 * <og:and value = "LANG = '{@LANG}'" /> 123 * <og:and value = "CLM like '{@CLM}'" /> 124 * <og:and value = "NAME_JA like '{@NAME_JA}'" /> 125 * <og:and value = "LABEL_NAME like '{@LABEL_NAME}'" /> 126 * <og:and value = "KBSAKU = '{@KBSAKU}'" /> 127 * </og:where> 128 * <og:appear startKey = "order by" value = "{@ORDER_BY}" 129 * defaultVal = "SYSTEM_ID,CLM,LANG" /> 130 * </og:query> 131 * 132 * <og:valueMap keys="SYSTEM_ID,CLM" holdTag="div" separator="_" clsClms="LANG,FGJ" > 133 * {@XX_AA0001} <br /> SYSTEM_IDとCLMの値を、separatorで連結。値は、キーの次(LABEL_NAME) 134 * {@XX_AA0001 1} <br /> 行番号の2番目(上のSQLではNAME_JA)の値 135 * {@XX_AA0001 2} <br /> 行番号の3番目(上のSQLではLABEL_NAME)の値 136 * 137 * {@XX_AA001* 2} <br /> キーの前方一致する行の3番目の値 138 * 139 * {@XX_AA000!* 1} キーの前方一致する行の2番目の値を、逆順で表示 140 * 141 * </og:valueMap> 142 * 143 * ・ キーは、select文の1番目のカラム 144 * <og:og:valueMap > ・・・フォーマット・・・ </og:valueMap> 145 * ・ キーが複数で、ユニークになる。(keys) 146 * <og:og:valueMap keys="SYSTEM_ID,CLM" > ・・・フォーマット・・・ </og:valueMap> 147 * ・ 値をdivタグで囲う。(holdTag) 148 * <og:og:valueMap keys="SYSTEM_ID,CLM" holdTag="div" > ・・・フォーマット・・・ </og:valueMap> 149 * ・ キーの連結のセパレータを指定。(separator) 150 * <og:og:valueMap keys="SYSTEM_ID,CLM" holdTag="div" separator="_" > ・・・フォーマット・・・ </og:valueMap> 151 * ・ 値をdivタグで囲う時に、クラス属性を追加します。(clsClms) 152 * <og:og:valueMap keys="SYSTEM_ID,CLM" holdTag="div" separator="_" clsClms="LANG,FGJ" > ・・・フォーマット・・・ </og:valueMap> 153 * ・ 値をdivタグで囲う時に、チップス表示(title属性)を追加します。(tipsClms) 154 * <og:og:valueMap keys="SYSTEM_ID,CLM" holdTag="div" separator="_" clsClms="LANG,FGJ" tipsClms="NAME_JA,LABEL_NAME" > ・・・フォーマット・・・ </og:valueMap> 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が指定されない場合は、2番目のカラム(=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が指定されない場合は、2番目のカラム(=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が指定されない場合は、2番目のカラム(=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 * さらに、{@$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 ); // 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 * 処理としては、{@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が指定されない場合は、2番目のカラムを使用します。 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の場合、{@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属性:{@XXXX} を、指定のタグで囲います。 855 * 例えば、holdTag="span" とすると、<span class="YYYYの値" >XXXXの値</span> 856 * という文字列を作成します。 857 * clsClms 属性や、{@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 * 一括指定ではなく、個別に指定する場合は、{@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 * 一括指定ではなく、個別に指定する場合は、{@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】{@^XXXX}使用時に request.getAttribute() をセットすると同時に設定するカラム名をCSV形式で指定します。 907 * 908 * @og.tag 909 * DBTableModel と別に、value等で設定した値を、{@^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開始/終了文字(><) 存在チェックを実施するかどうか[true/false]を設定します 941 * (初期値:USE_XSS_CHECK[={@og.value SystemData#USE_XSS_CHECK}])。 942 * 943 * @og.tag 944 * クロスサイトスクリプティング(XSS)対策の一環としてless/greater than signについてのチェックを行います。 945 * (><) が含まれていたエラーにする(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}