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 java.util.Arrays; 019import java.util.Enumeration; 020import java.util.Locale; 021import java.util.Set; 022import java.util.TreeSet; 023 024import org.opengion.fukurou.util.ErrorMessage; 025import org.opengion.fukurou.util.StringUtil; 026import org.opengion.hayabusa.common.HybsSystem; 027import org.opengion.hayabusa.common.HybsSystemException; 028import org.opengion.hayabusa.db.DBColumn; 029import org.opengion.hayabusa.db.DBTableModel; 030import org.opengion.hayabusa.resource.ResourceManager; // 6.4.0.2 (2015/12/11) 031import org.opengion.fukurou.util.ToString; // 6.1.1.0 (2015/01/17) 032import static org.opengion.fukurou.util.StringUtil.nval; 033 034/** 035 * 登録データの物理チェック(整合性チェック、nullチェック)を行うタグです。 036 * 037 * コマンドに対応したチェック方式で、指定のカラムをチェックします。 038 * command="NEW" の場合は、columns 引数にCSV形式で指定したカラム名より 039 * リクエスト情報を取得して、値をチェックします。 040 * 引数チェックでは、"%" や "_" などのあいまい検索時に指定する記号を 041 * 含むとエラーになるカラムはチェック対象からはずす必要がある為、 042 * チェックすべきカラムを指定する必要があります。 043 * command="ENTRY" の場合は、columns 引数に無関係に、全てのリクエストされたカラム 044 * の値をチェックします。これは、先の検索時の場合と異なり、ENTRYでは 045 * データベースに値を設定する為、無条件にチェックする必要があります。 046 * nullCheck は、command に無関係に指定のカラムが null (ゼロ文字列)かどうかを 047 * 判定します。 048 * maxRowCount は、一覧検索時のチェックされた件数が、指定の値を超えた場合に 049 * エラーになります。minRowCount は、同様に、最小選択件数(設定値を含む)の指定です。 050 * このタグは、エラー時には、それ以降のJSP画面を評価しません。BODY 部に記述された 051 * 値は、エラー時のみ表示され、正常時には、なにも表示されません。これは、エラー時の 052 * メッセージや、ユーザーにエラー時のアクションを行ってもらう場合の処理(例えば、 053 * 画面を戻る為のボタンなど)を表示させます。 054 * useColumnLabel を true にセットすると、エラー時のカラム名(ラベル)を、カラムオブジェクトから 055 * 取得するようになります。動的カラム実行時や、DBTableModelに対して、ColumnEditor等で 056 * ラベルを書き換えた場合に、有効です。false の場合は、基本的にはラベルリソースからの 057 * 取得になりますが、ケースによっては、カラムオブジェクトから取得している場合もあります。 058 * この属性は、互換性を重視し、初期値が、false になっています。 059 * 060 * ERR0012 : 指定のデータがセットされていません。(NULLエラー)。key={0} 061 * ERR0017 : 選択エラー。選択行数({0} 件)が、最大制限値({1} 件)以上選ばれました。 062 * ERR0018 : 選択エラー。選択行数({0} 件)が、最小制限値({1} 件)以下選ばれました。 063 * ERR0036 : 選択必須エラー。以下のデータの内どれかは入力してください。key={0} 064 * ERR0037 : データ整合性エラー。指定のキーは整合性チェックの結果マッチしませんでした。key={0} val={1} regex={2} 065 * 066 * command="MODIFY" , "DELETE" 時には、強制的に、minRowCount="1" で処理します。 067 * 068 * @og.formSample 069 * ●形式:<og:columnCheck command = "…" /> 070 * ●形式:<og:columnCheck command = "…" >エラー時のみ処理 </og:columnCheck> 071 * ●body:なし/あり(EVAL_BODY_BUFFERED:BODYを評価し、{@XXXX} を解析します) 072 * 073 * ●Tag定義: 074 * <og:columnCheck 075 * command 【TAG】コマンド[NEW/RENEW/ENTRY]をセットします(初期値:NEW) 076 * columns 【TAG】チェックすべきカラム列をCSV形式(CSV形式)で指定します 077 * nullCheck 【TAG】NULL チェックすべきカラム列をCSV形式(CSV形式)りで指定します 078 * mustAnyCheck 【TAG】選択必須カラム(指定のカラムの内最低ひとつがNULLでない)を"AA|BB|CC,XX|YY|ZZ" 形式で指定します 079 * checkType 【TAG】チェック対象のデータ[AUTO/NEW/ENTRY]を指定します(初期値:AUTO) 080 * maxRowCount 【TAG】ENTRY時にチェックで選択された行数の最大値を設定します 081 * minRowCount 【TAG】ENTRY時にチェックで選択された行数の最小値を設定します 082 * tableId 【TAG】(通常は使いません) sessionに登録されている DBTableModel を取り出すキーを指定します 083 * matchKeys 【TAG】正規表現でのマッチングを行うカラム列をCSV形式(CSV形式)で指定します 084 * matchVals 【TAG】正規表現でのマッチングを行うカラム列に対する値(正規表現)をCSV形式(CSV形式)で指定します 085 * realTime 【TAG】(通常は使いません)リアルタイムチェックを行う場合に有効にします(初期値:false) 086 * useStrict 【TAG】NEWの場合に、厳密にチェックするかどうか[true/false]を指定します(初期値:false) 087 * useColumnLabel 【TAG】カラムラベルを使用するかどうか[true/false]を指定します(初期値:false) 088 * checkNames 【TAG】リクエスト変数の正規化を行うカラムをCSV形式で複数指定します 089 * useSLabel 【TAG】7.0.7.0 (2019/12/13) エラーメッセージにSLABELを利用するかどうか[true/false]を指定します(初期値:false) 090 * caseKey 【TAG】このタグ自体を利用するかどうかの条件キーを指定します(初期値:null) 091 * caseVal 【TAG】このタグ自体を利用するかどうかの条件値を指定します(初期値:null) 092 * caseNN 【TAG】指定の値が、null/ゼロ文字列 でない場合(Not Null=NN)は、このタグは使用されます(初期値:判定しない) 093 * caseNull 【TAG】指定の値が、null/ゼロ文字列 の場合は、このタグは使用されます(初期値:判定しない) 094 * caseIf 【TAG】指定の値が、true/TRUE文字列の場合は、このタグは使用されます(初期値:判定しない) 095 * debug 【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false) 096 * > ... Body ... 097 * </og:columnCheck> 098 * 099 * ●使用例 100 * <og:columnCheck 101 * command = "{@command}" 102 * columns = "AAA,BBB,CCC" DB定義(DBColumnリソース)で定義した項目(桁数,タイプ等)でチェックします。 103 * maxRowCount = "1" チェックで選ばれた 最大選択件数(設定値を含む)を指定。 104 * minRowCount = "1" チェックで選ばれた 最小選択件数(設定値を含む)を指定。 105 * nullCheck = "AAA,CCC" NULLチェックを実行します。 106 * /> 107 * 108 * [エラー時に、BODY部に記述された内容を出力する。正常時には、このBODY部の記述は出力されません。] 109 * <og:columnCheck 110 * command = "{@command}" 111 * columns = "AAA,BBB,CCC" DB定義(DBColumnリソース)で定義した項目(桁数,タイプ等)でチェックします。 112 * nullCheck = "AAA,CCC" NULLチェックを実行します。 113 * > 114 * <form method="POST" action="forward.jsp" target="RESULT"> 115 * <og:input type="button" onClick="history.back()" msg="MSG0049" accesskey="R" td="false" /> 116 * </form> 117 * </og:columnCheck> 118 * 119 * mustAnyCheck 属性に、選択必須カラムを指定します。 120 * 例:mustAnyCheck="AA|BB|CC" 121 * AA,BB,CC のカラムで選択必須(すべてがnullならエラー) 122 * 例:mustAnyCheck="AA|BB|CC,XX|YY|ZZ" 123 * AA,BB,CC のセットと、XX,YY,ZZのセットでそれぞれ選択必須。 124 * 例:mustAnyCheck="AA|XX,AA|YY,AA|ZZ" 125 * AA に値があればすべて成立。そうでない場合は、XX と YY と ZZ がすべて必須。 126 * 例:mustAnyCheck="AA|BB,BB|CC,AA|CC" 127 * AA,BB,CC の内、どれか2つが必須。AAが成立すればBBかCCが必須。同様に、 128 * BBが成立すれば、AAかCCが必須。 129 * 130 * 例:query.jsp 131 * <og:column name="AA" mustAny="true" /> 132 * <og:column name="BB" mustAny="true" /> 133 * <og:column name="XX" mustAny="XYZ" /> 134 * <og:column name="YY" mustAny="XYZ" /> 135 * result.jsp 136 * <og:columnCheck mustAnyCheck="AA|BB,XX|YY" /> 137 * custom/custom.css 138 * .XYZ { background-color: Green; } 139 * 140 * 例:動的カラムで、entry.jsp でのチェックを行う場合。 141 * entry.jsp 142 * <og:columnCheck command="NEW" columns="*" useColumnLabel="true" /> 143 * 144 * useColumnLabel で、動的に作成されたカラム(SAVE=TRUEでキャッシュ済み)を使って 145 * チェックします。command="NEW" なので、対象カラムを指定するのに、"*" ですべてを選択します。 146 * 147 * @og.group 画面登録 148 * 149 * @version 4.0 150 * @author Kazuhiko Hasegawa 151 * @since JDK5.0, 152 */ 153public class ColumnCheckTag extends CommonTagSupport { 154 /** このプログラムのVERSION文字列を設定します。 {@value} */ 155 private static final String VERSION = "7.0.7.0 (2019/12/13)" ; 156 private static final long serialVersionUID = 707020191213L ; 157 158 /** command 引数に渡す事の出来る コマンド 新規 {@value} */ 159 public static final String CMD_NEW = "NEW" ; 160 /** command 引数に渡す事の出来る コマンド 再検索 {@value} */ 161 public static final String CMD_RENEW = "RENEW" ; 162 /** command 引数に渡す事の出来る コマンド エントリー {@value} */ 163 public static final String CMD_ENTRY = "ENTRY" ; 164 /** command 引数に渡す事の出来る コマンド リスト */ 165 166 // 6.4.3.2 (2016/02/19) ENTRY時にチェックする対象を、tableId指定のテーブルのカラムに限定します。 167 // 4.3.1.1 (2008/08/23) transient 追加 168 169 private String tableId = HybsSystem.TBL_MDL_KEY; // 3.5.4.3 (2004/01/05) 170 private String command = CMD_NEW; // 無指定時は、チェックを行う。 171 private String[] columns ; 172 private String[] nullCheck ; 173 private String[] mustAnyCheck; // 3.8.0.9 (2005/10/17) 174 private int maxRowCount = -1 ; // 初期値として,無制限を指定 175 private int minRowCount = -1 ; // 初期値として,無制限を指定 176 private String checkType = "AUTO"; 177 private String bodyString ; // 3.5.4.2 (2003/12/15) 178 private String[] matchKeys ; // 4.0.0 (2005/11/30) 179 private String[] matchVals ; // 4.0.0 (2005/11/30) 180 private boolean isRealTime ; // 4.3.7.0 (2009/06/01) 181 private boolean isStrict ; // 5.2.2.0 (2010/11/01) NEWの場合に、厳密にチェックするフラグを追加 182 183 private boolean isColumnLabel; // 5.4.3.4 (2012/01/12) true の場合に、カラムラベルを使用します。 184 185 private String checkNames ; // 5.4.3.8 (2012/01/24) 186 187 private boolean useSLabel ; // 7.0.7.0 (2019/12/13) エラーメッセージにSLABELを利用するかどうか[true/false]を指定します(初期値:false) 188 189 /** 190 * デフォルトコンストラクター 191 * 192 * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor. 193 */ 194 public ColumnCheckTag() { super(); } // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。 195 196 /** 197 * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。 198 * 199 * @og.rev 3.5.4.2 (2003/12/15) エラー時に、BODY部に記述された内容を出力する。 200 * @og.rev 5.0.0.2 (2009/09/15) xss対応⇒チェックする 201 * @og.rev 5.7.8.0 (2014/07/04) caseKey,caseVal,caseNN,caseNull 属性を追加 202 * 203 * @return 後続処理の指示( EVAL_BODY_BUFFERED ) 204 */ 205 @Override 206 public int doStartTag() { 207 // 5.0.0.2 (2009/09/15) XSSチェックしない⇒する 208 // useXssCheck( false ); 209 210 // 5.7.8.0 (2014/07/04) 追加 211 return useTag() ? EVAL_BODY_BUFFERED : SKIP_BODY ; 212 } 213 214 /** 215 * Taglibのタグ本体を処理する doAfterBody() を オーバーライドします。 216 * 217 * @og.rev 3.5.4.2 (2003/12/15) エラー時に、BODY部に記述された内容を出力する。 218 * 219 * @return 後続処理の指示(SKIP_BODY) 220 */ 221 @Override 222 public int doAfterBody() { 223 bodyString = getBodyString(); 224 225 return SKIP_BODY ; 226 } 227 228 /** 229 * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。 230 * 231 * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。 232 * @og.rev 3.4.0.3 (2003/09/10) command="NEW" でエラー発生時には、DBTableModel をクリアする。 233 * @og.rev 3.5.4.2 (2003/12/15) HTMLTableViewForm クラス名変更(⇒ ViewForm_HTMLTable) 234 * @og.rev 3.5.4.2 (2003/12/15) エラー時に、BODY部に記述された内容を出力する。 235 * @og.rev 3.5.4.3 (2004/01/05) tableId 属性を追加。 236 * @og.rev 3.5.4.4 (2004/01/16) エラー結果を表示するテーブル形式のフォーム修正 237 * @og.rev 3.5.5.2 (2004/04/02) TaglibUtil.makeHTMLErrorTable メソッドを利用 238 * @og.rev 4.1.2.1 (2008/03/13) table 属性を追加。 239 * @og.rev 4.3.3.0 (2008/10/01) viewSimple属性追加 240 * @og.rev 4.3.7.0 (2009/06/01) viewSimple属性名称変更 ⇒ isRealTime 241 * @og.rev 5.6.8.3 (2013/09/27) checkTypeがAutoの場合のセットをここで行い、tableModelチェックをcheckTypeで行う。 242 * @og.rev 5.7.8.0 (2014/07/04) caseKey,caseVal,caseNN,caseNull 属性を追加 243 * @og.rev 6.4.3.2 (2016/02/19) ENTRY時にチェックする対象を、tableId指定のテーブルのカラムに限定します。 244 * @og.rev 7.0.7.0 (2019/12/13) useSLabel 属性を追加。 245 * 246 * @return 後続処理の指示 247 */ 248 @Override 249 public int doEndTag() { 250 debugPrint(); // 4.0.0 (2005/02/28) 251 252 // 5.7.8.0 (2014/07/04) caseKey,caseVal,caseNN,caseNull 属性を追加 253 if( !useTag() ) { return EVAL_PAGE ; } // ページの残りを評価する。 254 255 int rtnCode = EVAL_PAGE; 256 257 // 6.4.3.2 (2016/02/19) ENTRY時にチェックする対象を、tableId指定のテーブルのカラムに限定します。 258 259 // 5.6.8.3 (2013/09/27) チェックタイプのautoを入れる位置変更 260 if( "AUTO".equals( checkType ) ) { checkType = command; } 261 262 // 6.4.3.2 (2016/02/19) ENTRY時にチェックする対象を、tableId指定のテーブルのカラムに限定します。 263 // 3.5.5.2 (2004/04/02) TaglibUtil.makeHTMLErrorTable メソッドを利用 264 final ErrorMessage errMsg = makeErrorDBTable(); 265 if( errMsg.getKekka() >= ErrorMessage.NG ) { 266 if( bodyString != null ) { jspPrint( bodyString ); } // 3.5.4.2 (2003/12/15) 267 268 // 4.3.3.0 (2008/10/01) 269 // 4.3.7.0 (2009/06/01) 270 // 7.0.7.0 (2019/12/13) useSLabel 属性を追加。 271// if( isRealTime ) { jspPrint( TaglibUtil.makeHTMLSimpleErrorList( errMsg, getResource() ) ); } 272// else { jspPrint( TaglibUtil.makeHTMLErrorTable( errMsg, getResource() ) ); } 273 if( isRealTime ) { jspPrint( TaglibUtil.makeHTMLSimpleErrorList( errMsg, getResource(),useSLabel ) ); } 274 else { jspPrint( TaglibUtil.makeHTMLErrorTable( errMsg, getResource(),useSLabel ) ); } 275 276 if( CMD_NEW.equals( command ) ) { 277 removeObject( tableId ); 278 } 279 rtnCode = SKIP_PAGE ; 280 } 281 else if( errMsg.getKekka() == ErrorMessage.WARNING ) { 282 // 4.3.3.0 (2008/10/01) 283 // 4.3.7.0 (2009/06/01) 284 // 7.0.7.0 (2019/12/13) useSLabel 属性を追加。 285// if( isRealTime ) { jspPrint( TaglibUtil.makeHTMLSimpleErrorList( errMsg, getResource() ) ); } 286// else { jspPrint( TaglibUtil.makeHTMLErrorTable( errMsg, getResource() ) ); } 287 if( isRealTime ) { jspPrint( TaglibUtil.makeHTMLSimpleErrorList( errMsg, getResource(),useSLabel ) ); } 288 else { jspPrint( TaglibUtil.makeHTMLErrorTable( errMsg, getResource(),useSLabel ) ); } 289 } 290 291 return rtnCode ; 292 } 293 294 /** 295 * タグリブオブジェクトをリリースします。 296 * 297 * キャッシュされて再利用されるので、フィールドの初期設定を行います。 298 * 299 * @og.rev 2.0.0.4 (2002/09/27) カスタムタグの release() メソッドを、追加 300 * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。 301 * @og.rev 3.5.4.2 (2003/12/15) エラー時に、BODY部に記述された内容を出力する。 302 * @og.rev 3.5.4.3 (2004/01/05) tableId 属性を追加。 303 * @og.rev 3.8.0.9 (2005/10/17) mustAnyCheck 属性を追加。 304 * @og.rev 4.1.2.1 (2008/03/13) table 属性を追加。 305 * @og.rev 4.3.3.0 (2008/10/01) viewSimple属性追加 306 * @og.rev 4.3.7.0 (2009/06/01) viewSimple属性名称変更 ⇒ isRealTime 307 * @og.rev 5.2.2.0 (2010/11/01) NEWの場合に、厳密にチェックするフラグを追加 308 * @og.rev 5.4.3.4 (2012/01/12) isColumnLabelを追加 309 * @og.rev 6.4.3.2 (2016/02/19) ENTRY時にチェックする対象を、tableId指定のテーブルのカラムに限定します。 310 * @og.rev 7.0.7.0 (2019/12/13) useSLabel 属性を追加。 311 */ 312 @Override 313 protected void release2() { 314 super.release2(); 315 command = CMD_NEW; // 無指定時は、チェックを行う。 316 columns = null; 317 nullCheck = null; 318 maxRowCount = -1 ; // 初期値として,無制限を指定 319 minRowCount = -1 ; // 初期値として,無制限を指定 320 checkType = "AUTO"; 321 bodyString = null ; // 3.5.4.2 (2003/12/15) 322 tableId = HybsSystem.TBL_MDL_KEY; // 3.5.4.3 (2004/01/05) 323 mustAnyCheck= null; // 3.8.0.9 (2005/10/17) 324 matchKeys = null; // 4.0.0 (2005/11/30) 325 matchVals = null; // 4.0.0 (2005/11/30) 326 isRealTime = false; // 4.3.7.0 (2009/06/01) 327 isStrict = false; // 5.2.2.0 (2010/11/01) NEWの場合に、厳密にチェックするフラグを追加 328 isColumnLabel= false; // 5.4.3.4 (2012/01/12) true の場合に、カラムラベルを使用します。 329 checkNames = null; // 5.4.3.8 (2012/01/24) 330 useSLabel = false; // 7.0.7.0 (2019/12/13) エラーメッセージにSLABELを利用するかどうか[true/false]を指定します(初期値:false) 331 } 332 333 /** 334 * DBColumn オブジェクトを作成して、DBColumn#valueCheck( String )で 335 * チェックを行う。その結果の、ErrorMessage オブジェクトを DBTableModel に 336 * 取り込んで、エラーの場合は、その表示を行う。 337 * 表示方法は、そのまま ViewForm オブジェクトを作成して、表示を行う。 338 * 339 * @og.rev 3.5.5.2 (2004/04/02) リターン値を、DBTableModel から ErrorMessage に変更 340 * @og.rev 4.0.0.0 (2005/01/31) リターン値の ErrorMessage は、必ず存在する。 341 * @og.rev 4.1.2.1 (2008/03/13) command="MODIFY" , "DELETE" 時には、強制的に、minRowCount="1" で処理します。 342 * @og.rev 5.6.8.3 (2013/09/27) checkTypeのAuto時設定位置をdoEndTagでするように変更 343 * 344 * @return エラーメッセージのテーブルモデル 345 * @og.rtnNotNull 346 */ 347 private ErrorMessage makeErrorDBTable() { 348 ErrorMessage errMsg = new ErrorMessage(); 349 350 //if( "AUTO".equals( checkType ) ) { checkType = command; } // 5.6.8.3 (2013/09/27) move 351 if( CMD_ENTRY.equals( checkType ) ) { 352 errMsg.setTitle( "Request Column Error!" ); 353 errMsg = makeEntryErrorMessage( errMsg ); 354 errMsg = makeMaxRowCountErrorMessage( errMsg ); 355 errMsg = makeMinRowCountErrorMessage( errMsg ); 356 } 357 else if( CMD_NEW.equals( checkType ) ) { 358 errMsg.setTitle( "Entry Column Error!" ); 359 errMsg = makeErrorMessage( errMsg ); 360 errMsg = makeMaxRowCountErrorMessage( errMsg ); 361 errMsg = makeMinRowCountErrorMessage( errMsg ); 362 } 363 else if( minRowCount >= 0 || maxRowCount >= 0) { // -1 は制限無し 364 errMsg.setTitle( "Row Count Error Limited Error!" ); 365 errMsg = makeMaxRowCountErrorMessage( errMsg ); 366 errMsg = makeMinRowCountErrorMessage( errMsg ); 367 } 368 // 4.1.2.1 (2008/03/13) command="MODIFY" , "DELETE" 時には、強制的に、minRowCount="1" で処理します。 369 // 6.3.9.0 (2015/11/06) 条件は効果がない(findbugs) 370 else if( "MODIFY,DELETE".indexOf( checkType ) >= 0 ) { 371 minRowCount = 1; 372 errMsg = makeMinRowCountErrorMessage( errMsg ); 373 } 374 return errMsg; 375 } 376 377 /** 378 * ErrorMessageをセットします。 379 * 引数のカラム名配列よりリクエスト情報を取得して、値をチェックします。 380 * DBColumn#valueCheck( String ) の結果のErrorMessageをすべて append 381 * していきます。 382 * 383 * @og.rev 3.8.0.9 (2005/10/17) 選択必須 mustAnyCheck のチェック追加 384 * @og.rev 3.8.1.0 (2005/10/24) リクエスト情報の正規化変換(DBColumn#valueSet(String))中止 385 * @og.rev 3.8.5.3 (2006/06/30) リクエストに % , _ が含まれたときは、削除します。 386 * @og.rev 4.1.2.1 (2008/03/13) must , mustAny の自動取得追加 387 * @og.rev 5.0.0.2 (2009/09/15) 個別にxssチェックをfalse 388 * @og.rev 5.1.9.0 (2010/08/01) 同じ名前の項目は、1つにまとめる(ラジオボタン等) 389 * @og.rev 5.2.0.0 (2010/09/01) リアルタイムチェックの場合は、must,mustAnyの自動チェックは行わない 390 * @og.rev 5.2.2.0 (2010/11/01) DBColumn#valueCheck で、甘いチェックを行うように、引数に isStrict を追加 391 * @og.rev 5.4.3.4 (2012/01/12) getLabel( String )を、リソースからに統一するとともに、isColumnLabel 対応を行う。 392 * @og.rev 5.4.3.8 (2012/01/28) checkNames対応 393 * @og.rev 6.4.0.2 (2015/12/11) ResourceManagerの取得を、先に行っておく。 394 * @og.rev 6.8.4.2 (2017/12/25) カラムチェックで、#valueSet(String) で、エラーが発生した場合でも、#valueCheck(String) を行うようにします。 395 * 396 * @param errMsg ErrorMessageオブジェクト 397 * 398 * @return カラムキー + 値 のエラーメッセージオブジェクト 399 */ 400 private ErrorMessage makeErrorMessage( final ErrorMessage errMsg ) { 401 402 // 4.1.2.1 (2008/03/13) must , mustAny の自動取得追加 403 // request から取出す 注意:mustAny 以外の自由形式の値は所得していません。 404 // 5.2.0.0 (2010/09/01) リアルタイムチェックの場合は、must,mustAnyの自動チェックは行わない 405 // (基本的にパラメーターを送らない限り自動チェックは動かないが、RequestCacheにより動くことがある) 406 if( !isRealTime ) { 407 if( nullCheck == null ) { 408 nullCheck = getRequestValues( HybsSystem.MUST_KEY + "must" ); 409 // 5.1.9.0 (2010/08/01) 同じ名前の項目は、1つにまとめる(ラジオボタン等) 410 if( nullCheck != null ) { 411 final Set<String> ss = new TreeSet<>(); 412 ss.addAll( Arrays.asList( nullCheck ) ); 413 nullCheck = ss.toArray( new String[ss.size()] ); // 5.1.9.0 (2010/08/01) K.H 414 } 415 } 416 if( mustAnyCheck == null ) { 417 final String[] mustAnyReq = getRequestValues( HybsSystem.MUST_KEY + "mustAny" ); 418 if( mustAnyReq != null && mustAnyReq.length > 0 ) { 419 mustAnyCheck = new String[] { StringUtil.array2line( mustAnyReq,"|" ) }; 420 } 421 } 422 } 423 424 // 6.4.0.2 (2015/12/11) ResourceManagerの取得を、先に行っておく。 425 final ResourceManager resource = getResource(); 426 427 if( nullCheck != null && nullCheck.length != 0 ) { 428 for( int i=0; i<nullCheck.length; i++ ) { 429 final String clmKey = nullCheck[i]; // 5.4.3.4 (2012/01/12) 430 // String val = getRequestValue( nullCheck[i] ); 431 final String val = getRequestValue( clmKey, false ); // 5.0.0.2 (2009/09/15) 432 if( val == null || val.isEmpty() ) { 433 // 5.4.3.4 (2012/01/12) isColumnLabel 追加 434 final String label = isColumnLabel ? getDBColumn( clmKey ).getLabel() : resource.getLabel( clmKey ); 435 // ERR0012 : 指定のデータがセットされていません。(NULLエラー)。key={0} 436 errMsg.addMessage( 0,ErrorMessage.NG,"ERR0012",label ); 437 } 438 } 439 } 440 // 3.8.0.9 (2005/10/17) 選択必須 mustAnyCheck のチェック追加 441 if( mustAnyCheck != null && mustAnyCheck.length != 0 ) { 442 final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE ); // 6.1.0.0 (2014/12/26) refactoring 443 for( int i=0; i<mustAnyCheck.length; i++ ) { 444 boolean flag = false; 445 final String[] mustSub = StringUtil.csv2Array( mustAnyCheck[i],'|' ); 446 for( int j=0; j<mustSub.length; j++ ) { 447 // String val = getRequestValue( mustSub[j] ); 448 final String val = getRequestValue( mustSub[j], false ); // 5.0.0.2 (2009/09/15) 449 if( val != null && val.length() > 0 ) { 450 flag = true; break; // ひとつでもnullでなければ、OK 451 } 452 } 453 if( ! flag ) { 454 buf.setLength(0); // 6.1.0.0 (2014/12/26) refactoring 455 for( int j=0; j<mustSub.length; j++ ) { 456 final String clmKey = mustSub[j]; // 5.4.3.4 (2012/01/12) 457 // 5.4.3.4 (2012/01/12) isColumnLabel 追加 458 final String label = isColumnLabel ? getDBColumn( clmKey ).getLabel() : resource.getLabel( clmKey ); 459 buf.append( label ).append( ',' ); // 6.0.2.5 (2014/10/31) char を append する。 460 } 461 // ERR0036 : 選択必須エラー。以下のデータの内どれかは入力してください。key={0} 462 errMsg.addMessage( 0,ErrorMessage.NG,"ERR0036",buf.toString() ); 463 } 464 } 465 } 466 if( columns != null && columns.length != 0 ) { 467 for( int i=0; i<columns.length; i++ ) { 468 // 3.8.1.0 (2005/10/24) リクエスト情報の正規化変換(DBColumn#valueSet(String))中止 469 // String clmVal = getRequestValue( columns[i] ); 470 String clmVal = getRequestValue( columns[i], false ); // 5.0.0.2 (2009/09/15) 471 if( clmVal != null && clmVal.length() > 0 ) { 472 clmVal = StringUtil.replace( clmVal,"%","" ); // 3.8.5.3 (2006/06/30) 473 clmVal = StringUtil.replace( clmVal,"_","" ); // 3.8.5.3 (2006/06/30) 474 final DBColumn dbColumn = getDBColumn( columns[i] ); 475 // 5.4.3.8 (2012/01/24) checkNames対応 476 if( ( "," + checkNames + "," ).indexOf( "," + columns[i] + "," ) >= 0 ) { 477 // 6.8.4.2 (2017/12/25) カラムチェックで、#valueSet(String) で、エラーが発生した場合でも、#valueCheck(String) を行うようにします。 478 try { 479 final String val = dbColumn.valueSet( clmVal ); 480 if( val != null ) { clmVal = val; } 481 } 482 catch( RuntimeException ex ) { 483 System.err.println( ex.getMessage() ); // 8.0.0.0 (2021/07/31) 484// ; // #valueSet(String) で、エラーが発生した場合でも、#valueCheck(String) を行うようにします。 485 } 486 } 487 // 5.2.2.0 (2010/11/01) DBColumn#valueCheck で、甘いチェックを行うように、引数に isStrict を追加 488 errMsg.append( dbColumn.valueCheck( clmVal,isStrict ) ); 489 } 490 } 491 } 492 // 4.0.0 (2005/11/30) 正規表現チェックの追加 493 // 6.9.8.0 (2018/05/28) FindBugs:コンストラクタで初期化されていないフィールドを null チェックなしで null 値を利用している 494// if( matchKeys != null && matchKeys.length != 0 ) { 495 if( matchKeys != null && matchKeys.length > 0 && matchVals != null && matchVals.length > 0 ) { 496 for( int i=0; i<matchKeys.length; i++ ) { 497 final String clmKey = matchKeys[i]; // 5.4.3.4 (2012/01/12) 498 // String val = getRequestValue( matchKeys[i] ); 499 final String val = getRequestValue( clmKey, false ); // 5.0.0.2 (2009/09/15) 500 if( val != null && ! val.matches( matchVals[i] ) ) { 501 // 5.4.3.4 (2012/01/12) isColumnLabel 追加 502 final String label = isColumnLabel ? getDBColumn( clmKey ).getLabel() : resource.getLabel( clmKey ); 503 // ERR0037 : データ整合性エラー。指定のキーは整合性チェックの結果マッチしませんでした。key={0} val={1} regex={2} 504 errMsg.addMessage( 0,ErrorMessage.NG,"ERR0037",label,val,matchVals[i] ); 505 } 506 } 507 } 508 509 return errMsg; 510 } 511 512 /** 513 * エントリーデータのErrorMessageをセットします。 514 * 引数のカラム名配列よりエントリーデータ形式のリクエスト情報を取得して、 515 * 値をチェックします。 516 * DBColumn#valueCheck( String ) の結果のErrorMessageをすべて append 517 * していきます。 518 * 519 * @og.rev 3.1.0.0 (2003/03/20) 名前と行番号の区切り記号を "^" から "__" に変更。 520 * @og.rev 3.5.5.0 (2004/03/12) 名前と行番号の区切り記号("__")を、HybsSystem.JOINT_STRING に変更。 521 * @og.rev 3.8.0.9 (2005/10/17) 選択必須 mustAnyCheck のチェック追加 522 * @og.rev 4.1.2.1 (2008/03/13) must , mustAny の自動取得追加 523 * @og.rev 4.3.6.4 (2009/05/01) 削除時に必ずmustAnyチェックエラーになるバグを修正(書込み可能行のみを処理する 524 * @og.rev 4.3.7.0 (2009/06/01) リアルタイムチェックの場合は、must,mustAnyの自動チェックは行わない 525 * @og.rev 5.0.0.2 (2009/09/15) xssチェック 526 * @og.rev 5.4.3.4 (2012/01/12) getLabel( String )を、リソースからに統一するとともに、isColumnLabel 対応を行う。 527 * @og.rev 6.3.9.0 (2015/11/06) コンストラクタで初期化されていないフィールドを null チェックなしで利用している(findbugs) 528 * @og.rev 6.4.0.2 (2015/12/11) ResourceManagerの取得を、先に行っておく。 529 * @og.rev 6.4.3.2 (2016/02/19) ENTRY時にチェックする対象を、tableId指定のテーブルのカラムに限定します。 530 * @og.rev 6.8.4.2 (2017/12/25) カラムチェックで、#valueSet(String) で、エラーが発生した場合でも、#valueCheck(String) を行うようにします。 531 * @og.rev 6.9.3.1 (2018/04/02) カラムチェックで、mustAnyのチェック方法改善 532 * 533 * @param errMsg ErrorMessageオブジェクト 534 * 535 * @return カラムキー + 値 のエラーメッセージオブジェクト 536 */ 537 private ErrorMessage makeEntryErrorMessage( final ErrorMessage errMsg ) { 538 final int[] rowNo = getParameterRows(); 539 if( rowNo.length == 0 ) { return errMsg; } 540 541 // 6.4.3.2 (2016/02/19) ENTRY時にチェックする対象を、tableId指定のテーブルのカラムに限定します。 542 final DBTableModel table = (DBTableModel)getObject( tableId ); 543 if( table == null ) { 544 final String errMsgStr = "検索結果のオブジェクトが存在しません。" 545 + " checkType=[" + checkType + "] , tableId=[" + tableId + "]" ; 546 throw new HybsSystemException( errMsgStr ); 547 } 548 549 // 4.1.2.1 (2008/03/13) must , mustAny の自動取得追加 550 // table から取出す (ソート済み) 551 // 4.3.7.0 (2009/06/01) リアルタイムチェックの場合は、must,mustAnyの自動チェックは行わない 552 if( !isRealTime ) { 553 if( nullCheck == null ) { nullCheck = table.getMustArray(); } 554 if( mustAnyCheck == null ) { mustAnyCheck = table.getMustAnyArray(); } 555 } 556 557 // 3.8.0.9 (2005/10/17) 選択必須 mustAnyCheck のチェック追加 558 boolean[][] rowAnyOne = null; 559 // 4.3.6.4 (2009/05/01) 560 boolean[] rowForCheck = null; 561 if( mustAnyCheck != null && mustAnyCheck.length != 0 ) { 562 rowAnyOne = new boolean[rowNo.length][mustAnyCheck.length]; 563 rowForCheck = new boolean[rowNo.length]; 564 // for( int i=0; i<rowNo.length; i++ ) { 565 // Arrays.fill( rowAnyOne[i],false ); 566 // } 567 } 568 569 // 6.4.3.2 (2016/02/19) tableId 単位にチェックするが、互換性のため、標準の tableId の処理は、従来どおりとする。 570 final boolean useTid = ! HybsSystem.TBL_MDL_KEY.equals( tableId ); // 反転:tableId を使っている=標準のtableIdではない。 571 572 DBColumn dbColumn = null; // 5.4.3.4 (2012/01/12) isColumnLabel 対応 573 final Enumeration<?> enume = getParameterNames(); // 4.3.3.6 (2008/11/15) Generics警告対応 574 while( enume.hasMoreElements() ) { 575 final String key = (String)(enume.nextElement()); 576 final int idx = key.lastIndexOf(HybsSystem.JOINT_STRING); 577 578 if( idx > 0 ) { 579 final String column = key.substring(0,idx); 580 // 6.4.3.2 (2016/02/19) ENTRY時にチェックする対象を、tableId指定のテーブルのカラムに限定します。 581 final int clmNo = table.getColumnNo( column,false ); // エラーを出さない。 582 if( useTid && clmNo < 0 ) { continue; } // 6.4.3.2 (2016/02/19) tableId指定のテーブルのカラムに存在しない場合は、スルーする。 583 584 final int row = Integer.parseInt( key.substring(idx + 2) ); 585 final String val = getRequestValue( key, false ); // 5.0.0.2 (2009/09/15) 586 587 final int i = Arrays.binarySearch( rowNo,row ); 588 if( i >= 0 ) { 589 // 5.4.3.4 (2012/01/12) isColumnLabel 対応 590 // 6.4.3.2 (2016/02/19) tableはnullチェック済みで、clmNoは先に求めている。 591 dbColumn = isColumnLabel && clmNo >= 0 ? table.getDBColumn( clmNo ) : getDBColumn( column ); 592 593 // 6.8.4.2 (2017/12/25) カラムチェックで、#valueSet(String) で、エラーが発生した場合でも、#valueCheck(String) を行うようにします。 594 String val2 = val; 595 try { 596 val2 = dbColumn.valueSet( val ); 597 } 598 catch( RuntimeException ex ) { 599 System.err.println( ex.getMessage() ); // 8.0.0.0 (2021/07/31) 600// ; // #valueSet(String) で、エラーが発生した場合でも、#valueCheck(String) を行うようにします。 601 } 602 603 errMsg.append( row+1,dbColumn.valueCheck( val2 ) ); 604 605 if( nullCheck != null && nullCheck.length != 0 ) { 606 final int j = Arrays.binarySearch( nullCheck,column ); // 6.9.3.1 (2018/04/02) リクエストカラムが、nullCheck対象カラムの場合、正のアドレス 607 if( j>=0 && ( val2 == null || val2.isEmpty() )) { 608 // ERR0012 : 指定のデータがセットされていません。(NULLエラー)。key={0} 609 errMsg.addMessage( row+1,ErrorMessage.NG,"ERR0012",dbColumn.getLabel() ); 610 } 611 } 612 613 // 3.8.0.9 (2005/10/17) 選択必須 mustAnyCheck のチェック追加 (mustAnyCheck="AA|BB|CC,XX|YY|ZZ" という形式を、カンマで分解した配列) 614 if( rowAnyOne != null ) { 615 // 6.9.3.1 (2018/04/02) データが飛んでこないかどうかの判定 616 for( int j=0; j<mustAnyCheck.length; j++ ) { 617 if( mustAnyCheck[j].indexOf( column ) >= 0 ) { 618 if( val2 == null || val2.isEmpty() ) { 619 rowForCheck[i] = true; // (trueは、処理対象) 620 } 621 else { 622 rowAnyOne[i][j] = true; // どれかが存在(trueは、処理対象外) 623 } 624 } 625 626// if( !rowAnyOne[i][j] && 627// mustAnyCheck[j].indexOf( column ) >= 0 && 628// val2 != null && val2.length() > 0 ) { 629// rowAnyOne[i][j] = true; // どれかが存在(trueは、処理対象外) 630// } 631 } 632// // 4.3.6.4 (2009/05/01) 633// rowForCheck[i] = true; // (trueは、処理対象) 634 } 635 636 // 4.0.0 (2005/11/30) 正規表現チェックの追加 637 // 6.9.8.0 (2018/05/28) FindBugs:コンストラクタで初期化されていないフィールドを null チェックなしで null 値を利用している 638// if( matchKeys != null && matchKeys.length != 0 ) { 639 if( matchKeys != null && matchKeys.length > 0 && matchVals != null && matchVals.length > 0 ) { 640 for( int j=0; j<matchKeys.length; j++ ) { 641 if( column.equals( matchKeys[j] ) ) { 642 if( val2 != null && ! val2.matches( matchVals[j] ) ) { 643 // 互換性はなくなっているが、正規表現チェックは余り使っていないので、統一しておく。 644 // 5.4.3.4 (2012/01/12) isColumnLabel 対応 645 // 6.4.3.2 (2016/02/19) dbColumnは、先に、取得済み。 646 647 // ERR0037 : データ整合性エラー。指定のキーは整合性チェックの結果マッチしませんでした。key={0} val={1} regex={2} 648 errMsg.addMessage( row+1,ErrorMessage.NG,"ERR0037",dbColumn.getLabel(),val2,matchVals[i] ); 649 } 650 break; // 発見すれば、ループ終了 651 } 652 } 653 } 654 } 655 } 656 } 657 658 // 6.4.0.2 (2015/12/11) ResourceManagerの取得を、先に行っておく。 659 final ResourceManager resource = getResource(); 660 661 // 3.8.0.9 (2005/10/17) 選択必須 mustAnyCheck のチェック追加 662 if( rowAnyOne != null ) { 663 final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE ); // 6.1.0.0 (2014/12/26) refactoring 664 for( int row=0; row<rowAnyOne.length; row++ ) { 665 // 4.3.6.4 (2009/05/01) 書込み可能行のみを処理する 666 if( rowForCheck[row] ) { 667 for( int i=0; i<mustAnyCheck.length; i++ ) { 668 if( !rowAnyOne[row][i] ) { 669 final String[] mustSub = StringUtil.csv2Array( mustAnyCheck[i], '|' ); 670 671 buf.setLength(0); // 6.1.0.0 (2014/12/26) refactoring 672 buf.append( "row=[" ).append( rowNo[row]+1 ).append( "] " ); 673 for( int j=0; j<mustSub.length; j++ ) { 674 // ここの処理だけ、他と異なるのは、互換性重視のため。(選択必須は利用頻度が高いので。) 675 // 5.4.3.4 (2012/01/12) isColumnLabel 対応 676 String label = null ; 677 // 6.9.8.0 (2018/05/28) FindBugs:null でないことがわかっている値の冗長な null チェック 678// if( isColumnLabel && table != null ) { 679 if( isColumnLabel ) { // tableは、nullチェック済み 680 final int clmNo = table.getColumnNo( mustSub[j],false ); // エラーを出さない。 681 if( clmNo >= 0 ) { 682 dbColumn = table.getDBColumn( clmNo ); 683 } 684 if( dbColumn == null ) { 685 dbColumn = getDBColumn( mustSub[j] ); 686 } 687 label = dbColumn.getLabel(); 688 } 689 else { 690 label = resource.getLabel( mustSub[j] ); // 6.4.0.2 (2015/12/11) 互換性のための処置。 691 } 692 buf.append( label ).append( '|' ); // 6.0.2.5 (2014/10/31) char を append する。 693 } 694 // ERR0036 : 選択必須エラー。以下のデータの内どれかは入力してください。key={0} 695 errMsg.addMessage( rowNo[row]+1, ErrorMessage.NG, "ERR0036", buf.toString() ); 696 } 697 } 698 } 699 } 700 } 701 702 return errMsg; 703 } 704 705 /** 706 * ErrorMessageをセットします。 707 * リクエストされた件数の最大値に制限を加えます。 708 * 1件だけにしたい場合は,通常はViewでチェックボックスを使用せずに 709 * ラジオボタンを使用してください。 710 * 711 * @param errMsg ErrorMessageオブジェクト 712 * 713 * @return カラムキー + 値 のエラーメッセージオブジェクト 714 */ 715 private ErrorMessage makeMaxRowCountErrorMessage( final ErrorMessage errMsg ) { 716 if( maxRowCount < 0 ) { return errMsg; } // 無制限 717 718 // 件数制限のチェック 719 final int[] rowNo = getParameterRows(); 720 final int rowCount = rowNo.length ; 721 if( rowCount > maxRowCount ) { 722 // ERR0017 : 選択エラー。選択行数({0} 件)が、最大制限値({1} 件)以上選ばれました。 723 final String arg0 = String.valueOf( rowCount ); 724 final String arg1 = String.valueOf( maxRowCount ); 725 errMsg.addMessage( 0,ErrorMessage.NG,"ERR0017",arg0,arg1 ); 726 } 727 728 return errMsg; 729 } 730 731 /** 732 * ErrorMessageをセットします。 733 * リクエストされた件数の最小値に制限を加えます。 734 * 1件だけにしたい場合は,通常はViewでチェックボックスを使用せずに 735 * ラジオボタンを使用してください。 736 * 737 * @param errMsg ErrorMessageオブジェクト 738 * 739 * @return カラムキー + 値 のエラーメッセージオブジェクト 740 */ 741 private ErrorMessage makeMinRowCountErrorMessage( final ErrorMessage errMsg ) { 742 if( minRowCount < 0 ) { return errMsg; } // 無制限 743 744 // 件数制限のチェック 745 final int[] rowNo = getParameterRows(); 746 final int rowCount = rowNo.length ; 747 if( rowCount < minRowCount ) { 748 // ERR0018 : 選択エラー。選択行数({0} 件)が、最小制限値({1} 件)以下選ばれました。 749 final String arg0 = String.valueOf( rowCount ); 750 final String arg1 = String.valueOf( minRowCount ); 751 errMsg.addMessage( 0,ErrorMessage.NG,"ERR0018",arg0,arg1 ); 752 } 753 754 return errMsg; 755 } 756 757 /** 758 * 【TAG】チェックすべきカラム列をCSV形式(CSV形式)で指定します。 759 * 760 * @og.tag columns="AAA,BBB,CCC,DDD" 761 * 分解方法は、通常のパラメータ取得後に、CSV分解します。 762 * "*" を指定すると、command="NEW" のときの判定にすべてのリクエスト文字列を 763 * チェック対象とします。通常は、必要分だけ指定しますが、動的カラムなどの 764 * 場合は、カラム名を予め指定できないため、"*" で指定できるようにします。 765 * その場合、"h_" , "hX_" , maxRowCount , command , pageSize , pagePlus , debug , 766 * GAMENID , BACK_JSPID , BACK_GAMENID の予約語は、対象から除きます。 767 * 768 * ※ 6.4.0.2 (2015/12/11) 769 * columns="*" のときのカラムは、リクエスト変数から、上記の予約語も除きますが、 770 * ResourceManager に存在しない(リソース未登録)カラムも除きます。 771 * 772 * @og.rev 3.5.6.2 (2004/07/05) 先に配列に分解してからリクエスト変数の値を取得 773 * @og.rev 3.8.8.5 (2007/03/09) 通常のパラメータ取得後に、CSV分解に戻します。 774 * @og.rev 5.4.3.4 (2012/01/12) command="NEW" のときの動的カラム対応( "*" ですべてのリクエスト) 775 * @og.rev 6.4.0.2 (2015/12/11) columns="*" のときのカラムは、リソースに存在する分のみとする。 776 * 777 * @param clms カラム列(CSV形式) 778 */ 779 public void setColumns( final String clms ) { 780 columns = StringUtil.csv2Array( getRequestParameter( clms ) ); 781 if( columns.length == 0 ) { columns = null; } 782 783 // 5.4.3.4 (2012/01/12) command="NEW" のときの動的カラム対応( "*" ですべてのリクエスト) 784 if( columns != null && "*".equals( columns[0] ) ) { 785 final Set<String> clmSet = new TreeSet<>(); // リクエストはバラバラなので、とりあえずソートしておきます。 786 787 // 6.4.0.2 (2015/12/11) columns="*" のときのカラムは、リソースに存在する分のみとする。 788 final ResourceManager resource = getResource(); 789 790 final Enumeration<?> enume = getParameterNames(); // Generics警告対応 791 while( enume.hasMoreElements() ) { 792 final String clm = (String)(enume.nextElement()); 793 // 予約語以外を登録します。 794 // 6.9.7.0 (2018/05/14) PMD These nested if statements could be combined 795// if( clm != null && !clm.isEmpty() && !clm.startsWith( "h_" ) && !clm.startsWith( "hX_" ) ) { 796// // 6.4.0.2 (2015/12/11) columns="*" のときのカラムは、リソースに存在する分のみとする。 797// if( resource.getDBColumn( clm ) != null ) { // 存在チェックのみで使わない。 798 if( clm != null && !clm.isEmpty() && !clm.startsWith( "h_" ) && !clm.startsWith( "hX_" ) 799 && resource.getDBColumn( clm ) != null ) { // 存在チェックのみで使わない。 800 clmSet.add( clm ); 801// } 802 } 803 } 804 // 予約語を削除します。 805 clmSet.remove( "maxRowCount" ); 806 clmSet.remove( "command" ); 807 clmSet.remove( "pageSize" ); 808 clmSet.remove( "pagePlus" ); 809 clmSet.remove( "debug" ); // 6.4.0.2 (2015/12/11) 810 clmSet.remove( "GAMENID" ); 811 clmSet.remove( "BACK_JSPID" ); 812 clmSet.remove( "BACK_GAMENID" ); 813 814 columns = clmSet.toArray( new String[clmSet.size()] ); 815 } 816 } 817 818 /** 819 * 【TAG】NULL チェックすべきカラム列をCSV形式(CSV形式)で指定します。 820 * 821 * @og.tag 822 * (must 属性のセットにより、自動処理されます) 823 * nullCheck="AAA,BBB,CCC,DDD" 824 * 分解方法は、通常のパラメータ取得後に、CSV分解します。 825 * 826 * @og.rev 3.5.6.2 (2004/07/05) 先に配列に分解してからリクエスト変数の値を取得 827 * @og.rev 3.8.8.5 (2007/03/09) 通常のパラメータ取得後に、CSV分解に戻します。 828 * 829 * @param clms カラム列(CSV形式) 830 */ 831 public void setNullCheck( final String clms ) { 832 nullCheck = StringUtil.csv2Array( getRequestParameter( clms ) ); 833 if( nullCheck.length == 0 ) { nullCheck = null; } 834 else { 835 Arrays.sort( nullCheck ); 836 } 837 } 838 839 /** 840 * 【TAG】選択必須カラム(指定のカラムの内最低ひとつがNULLでない)を"AA|BB|CC,XX|YY|ZZ" 形式で指定します。 841 * 842 * @og.tag 843 * (mustAny 属性のセットにより、自動処理されます) 844 * 複数のカラム属性の値のうち、どれかが null でない場合は正常とし、 845 * すべてが null の場合を警告します。 846 * 847 * 例:mustAnyCheck="AA|BB|CC" 848 * AA,BB,CC のカラムで選択必須(すべてがnullならエラー) 849 * 例:mustAnyCheck="AA|BB|CC,XX|YY|ZZ" 850 * AA,BB,CC のセットと、XX,YY,ZZのセットでそれぞれ選択必須。 851 * 例:mustAnyCheck="AA|XX,AA|YY,AA|ZZ" 852 * AA に値があればすべて成立。そうでない場合は、XX と YY と ZZ がすべて必須。 853 * 例:mustAnyCheck="AA|BB,BB|CC,AA|CC" 854 * AA,BB,CC の内、どれか2つが必須。AAが成立すればBBかCCが必須。同様に、 855 * BBが成立すれば、AAかCCが必須。 856 * 857 * 選択必須は、must と同様に、色づけを行う(query.jsp)画面では、mustAny 属性を 858 * セットします。チェックを行う(result.jsp)画面では、columnCheck タグの 859 * mustAnyCheck 属性に、選択必須カラムを指定します。(上記参照) 860 * column タグ等の mustAny 属性に、mustAny="true" とセットすると、生成される 861 * HTMLは、class="mustAny" が出力されます。エンジン標準では、default.css に 862 * .mustAny が定義されています。( background-color: #CCFFFF; ) 863 * なお、mustAny 属性に、true 以外の値をセットした場合(mustAny="XYZ")は、 864 * 生成されるHTMLに、class="XYZ" が出力されます。これは、複数のグループ間で 865 * 色を変えて、選択必須を指定する場合に使用します。色は、custom/custom.css 866 * で指定します。 867 * 分解方法は、通常のパラメータ取得後に、CSV分解します。 868 * 869 * @og.rev 3.8.0.9 (2005/10/17) 新規追加 870 * @og.rev 3.8.8.5 (2007/03/09) 通常のパラメータ取得後に、CSV分解に戻します。 871 * 872 * @param clms 選択必須カラム 873 */ 874 public void setMustAnyCheck( final String clms ) { 875 mustAnyCheck = StringUtil.csv2Array( getRequestParameter( clms ) ); 876 if( mustAnyCheck.length == 0 ) { mustAnyCheck = null; } 877 else { 878 Arrays.sort( mustAnyCheck ); 879 } 880 } 881 882 /** 883 * 【TAG】コマンド[NEW/RENEW/ENTRY]をセットします(初期値:NEW)。 884 * 885 * @og.tag 886 * コマンドは,HTMLから(get/post)指定されますので,CMD_xxx で設定される 887 * フィールド定数値のいづれかを、指定できます。 888 * 何も設定されない、または、null の場合は、"NEW" が初期値にセットされます。 889 * 890 * @param cmd コマンド (public static final 宣言されている文字列) 891 * @see <a href="../../../../constant-values.html#org.opengion.hayabusa.taglib.ColumnCheckTag.CMD_NEW">コマンド定数</a> 892 */ 893 public void setCommand( final String cmd ) { 894 final String cmd2 = getRequestParameter( cmd ); 895 if( cmd2 != null && cmd2.length() > 0 ) { command = cmd2.toUpperCase(Locale.JAPAN); } 896 } 897 898 /** 899 * 【TAG】 チェック対象のタイプ[AUTO/NEW/ENTRY]を指定します(初期値:AUTO)。 900 * 901 * @og.tag 902 * 通常のリクエストデータタイプは、キーそのものですが,エントリデータは表形式の 903 * データを一括で登録する為、(キー+"__" + 行番号)形式を、バラす必要があります。 904 * 905 * ENTRY は、DBTableModelのリクエスト情報をチェックします。 906 * これは、全データが対象になります。(columns/nullCheck 属性は無効) 907 * AUTO は、command が、上記 NEW か ENTRY かを判断して処理を振り分けます。 908 * 初期値は、AUTO です。 909 * 910 * @param flag チェックタイプ [AUTO/NEW/ENTRY] 911 */ 912 public void setCheckType( final String flag ) { 913 final String ct = getRequestParameter( flag ); 914 if( ct != null && ct.length() > 0 ) { checkType = ct ; } 915 } 916 917 /** 918 * 【TAG】チェックで選択された行数の最大値を設定します(初期値:-1 無制限)。 919 * 920 * @og.tag 921 * 制限をかけたい行数(この件数と同じ場合は正常)を指定します。 922 * 最大選択件数を超えた場合は,エラーメッセージを返します。 923 * 例えば、1件のみを正常とする場合は、maxRowCount="1" とします。 924 * 925 * @param count 最大件数 926 */ 927 public void setMaxRowCount( final String count ) { 928 maxRowCount = nval( getRequestParameter( count ),maxRowCount ); 929 } 930 931 /** 932 * 【TAG】チェックで選択された行数の最小値を設定します(初期値:-1 無制限)。 933 * 934 * @og.tag 935 * 最小選択件数を超えない場合は、エラーメッセージを返します。 936 * 例えば、1件のみを正常とする場合は、minRowCount="1" とします。 937 * 938 * @param count 制限をかけたい行数 (この件数と同じ場合は正常) 939 */ 940 public void setMinRowCount( final String count ) { 941 minRowCount = nval( getRequestParameter( count ), minRowCount ); 942 } 943 944 /** 945 * 【TAG】(通常は使いません)結果のDBTableModelを、sessionに登録するときのキーを指定します 946 * (初期値:HybsSystem#TBL_MDL_KEY[={@og.value HybsSystem#TBL_MDL_KEY}])。 947 * 948 * @og.tag 949 * 検索結果より、DBTableModelオブジェクトを作成します。これを、下流のviewタグ等に 950 * 渡す場合に、通常は、session を利用します。その場合の登録キーです。 951 * query タグを同時に実行して、結果を求める場合、同一メモリに配置される為、 952 * この tableId 属性を利用して、メモリ空間を分けます。 953 * (初期値:HybsSystem#TBL_MDL_KEY[={@og.value HybsSystem#TBL_MDL_KEY}])。 954 * 955 * @og.rev 6.4.3.2 (2016/02/19) ENTRY時にチェックする対象を、tableId指定のテーブルのカラムに限定します。 956 * 957 * @param id テーブルID (sessionに登録する時のID) 958 */ 959 public void setTableId( final String id ) { 960 tableId = nval( getRequestParameter( id ),tableId ); 961 } 962 963 /** 964 * 【TAG】正規表現でのマッチングを行うカラム列をCSV形式(CSV形式)で指定します。 965 * 966 * @og.tag matchKeys="AAA,BBB,CCC,DDD" 967 * matchKeys属性とmatchVals属性の個数は、同じでなければなりません。 968 * 先に配列に分解してからリクエスト変数の値を取得するようにします。 969 * こうする事で、リクエストにCSV形式の値を設定できるようになります。 970 * 971 * @og.rev 4.0.0.0 (2005/11/30) 新規作成 972 * 973 * @param keys カラム列(CSV形式) 974 * @see #setMatchVals( String ) 975 */ 976 public void setMatchKeys( final String keys ) { 977 matchKeys = getCSVParameter( keys ); 978 979 if( matchVals != null && matchKeys.length != matchVals.length ) { 980 final String errMsg = "matchKeys属性とmatchVals属性の個数が合いません。" 981 + CR 982 + " matchKeys=[" + matchKeys.length + "]:KEYS=" 983 + StringUtil.array2csv( matchKeys ) + CR 984 + " matchVals=[" + matchVals.length + "]:VLAS=" 985 + StringUtil.array2csv( matchVals ) + CR ; 986 throw new HybsSystemException( errMsg ); 987 } 988 } 989 990 /** 991 * 【TAG】正規表現でのマッチングを行うカラム列に対する値(正規表現)をCSV形式(CSV形式)で指定します。 992 * 993 * @og.tag matchVals="AAA,BBB,CCC,DDD" 994 * matchKeys属性とmatchVals属性の個数は、同じでなければなりません。 995 * 先に配列に分解してからリクエスト変数の値を取得するようにします。 996 * こうする事で、リクエストにCSV形式の値を設定できるようになります。 997 * 998 * @og.rev 4.0.0.0 (2005/11/30) 新規作成 999 * 1000 * @param vals カラム列に対する値(正規表現)(CSV形式) 1001 * @see #setMatchKeys( String ) 1002 */ 1003 public void setMatchVals( final String vals ) { 1004 matchVals = getCSVParameter( vals ); 1005 1006 if( matchKeys != null && matchKeys.length != matchVals.length ) { 1007 final String errMsg = "matchKeys属性とmatchVals属性の個数が合いません。" 1008 + CR 1009 + " matchKeys=[" + matchKeys.length + "]:KEYS=" 1010 + StringUtil.array2csv( matchKeys ) + CR 1011 + " matchVals=[" + matchVals.length + "]:VLAS=" 1012 + StringUtil.array2csv( matchVals ) + CR ; 1013 throw new HybsSystemException( errMsg ); 1014 } 1015 } 1016 1017 /** 1018 * 【TAG】(通常は使いません)リアルタイムチェックを行う場合に有効にします(初期値:false)。 1019 * 1020 * @og.tag 1021 * リアルタイムチェックを行う場合に有効にする属性です。 1022 * trueが指定された場合、通常のチェックと比較し、以下の差異があります。 1023 * ①エラー結果を簡易フォーマットで出力します。 1024 * (ViewFormType="HTMLSimpleErrorList"で表示されます。) 1025 * この簡易フォーマットで出力した場合は、ラベル(短)の定義で出力され、 1026 * カラム名やデータ等は出力されません。 1027 * ②must,mustAny属性のチェックを行いません。 1028 * 必須及び選択必須は、視覚的に判別できるため、リアルタイムチェックの 1029 * 対象外とします。 1030 * 1031 * @og.rev 4.3.3.0 (2008/10/01) 新規作成 1032 * @og.rev 4.3.7.0 (2009/06/01) viewSimple属性名称変更 ⇒ isRealTime 1033 * 1034 * @param flag リアルタイムチェック [true:する/false:しない] 1035 */ 1036 public void setRealTime( final String flag ) { 1037 isRealTime = nval( getRequestParameter( flag ),isRealTime ); 1038 } 1039 1040 /** 1041 * 【TAG】NEWの場合に、厳密にチェックするかどうか[true/false]を指定します(初期値:false)。 1042 * 1043 * @og.tag 1044 * データをチェックするに当たり、あいまい検索などで厳密にチェックすると 1045 * エラーになるケースがあるため、command="NEW" のチェック時には、甘い目の 1046 * チェックを行っています。DBColumn#valueCheck( String , false ) 1047 * command="ENTRY" のチェックは、厳密なチェックです。 1048 * このフラグは、検索時でも、厳密なチェックを行いたい場合に、true をセットします。 1049 * 1050 * @og.rev 5.2.2.0 (2010/11/01) 新規作成 1051 * 1052 * @param flag 厳密チェックか [true:厳密/false:甘い] 1053 */ 1054 public void setUseStrict( final String flag ) { 1055 isStrict = nval( getRequestParameter( flag ),isStrict ); 1056 } 1057 1058 /** 1059 * 【TAG】カラムラベルを使用するかどうか[true/false]を指定します(初期値:false)。 1060 * 1061 * @og.tag 1062 * カラムラベルはラベルローダーを利用せずにアプリケーション側で 1063 * 追加したラベルをResourceManagerにキャッシュしている所から取り出す 1064 * かどうかを指定します。 1065 * カラムラベルに存在しない場合は、通常のラベルから検索します。 1066 * 1067 * @og.rev 5.4.3.4 (2012/01/12) 新規作成 1068 * 1069 * @param flag カラムラベル使用 [true:する/false:しない] 1070 */ 1071 public void setUseColumnLabel( final String flag ) { 1072 isColumnLabel = nval( getRequestParameter( flag ),isColumnLabel ); 1073 } 1074 1075 /** 1076 * 【TAG】リクエスト変数の正規化を行うカラムをCSV形式で複数指定します。 1077 * 1078 * @og.tag 1079 * カラムチェックで正規化が行われていないプラグインに対して強制的に正規化を行います。 1080 * この属性を利用したチェックを行った場合は、queryタグでPL/SQLを動作させる場合にも 1081 * 同名属性でカラムの指定を行う必要があります。 1082 * (queryタグでcheckNamesを利用しない場合はこの属性はnullにしてください) 1083 * この属性はチェックタイプがNEWの場合のみ有効です。 1084 * リアルタイムチェックでこの機能を利用したい場合は、columnTag等のoptionAttributes 1085 * 属性にrtOption='checkNames=VIEW_DATE'のように記述してください。 1086 * 1087 * @og.rev 5.4.3.8 (2012/01/24) 新規追加 1088 * @og.rev 5.4.4.0 (2012/02/01) コメント修正 1089 * @og.rev 5.6.9.4 (2013/10/31) 空白削除を行う 1090 * @og.rev 6.9.2.1 (2018/03/12) 使用箇所が、1箇所だけなので、StringUtilから移動する。 1091 * 1092 * @param nm 正規化を行うカラム(CSV形式) 1093 */ 1094 public void setCheckNames( final String nm ) { 1095// checkNames = StringUtil.deleteWhitespace( nval( getRequestParameter( nm ),checkNames ) ); // 5.6.9.4 (2013/10/31) 1096 final String tmpNm = nval( getRequestParameter( nm ),checkNames ); 1097 checkNames = StringUtil.isNull( tmpNm ) ? checkNames : tmpNm.replaceAll( "\\s", "" ); // 6.9.2.1 (2018/03/12) 1098 } 1099 1100 /** 1101 * 【TAG】エラーメッセージにSLABELを利用するかどうか[true/false]を指定します(初期値:false)。 1102 * 1103 * @og.tag 1104 * 通常のエラーメッセージは、ラベル(長)が使われますが、これをラベル(短)を使いたい場合に、true にセットします。 1105 * ここでのラベル(短)は、タグ修飾なしの、ラベル(短)です。 1106 * 標準はfalse:利用しない=ラベル(長)です。 1107 * true/false以外を指定した場合はfalse扱いとします。 1108 * 1109 * ラベルリソースの概要説明があれば表示しますが、useSLabel="true" 時は、概要説明を表示しません。 1110 * 1111 * @og.rev 7.0.7.0 (2019/12/13) 新規追加 1112 * 1113 * @param prm SLABEL利用 [true:利用する/false:利用しない] 1114 */ 1115 public void setUseSLabel( final String prm ) { 1116 useSLabel = nval( getRequestParameter( prm ),useSLabel ); 1117 } 1118 1119 /** 1120 * このオブジェクトの文字列表現を返します。 1121 * 基本的にデバッグ目的に使用します。 1122 * 1123 * @return このクラスの文字列表現 1124 * @og.rtnNotNull 1125 */ 1126 @Override 1127 public String toString() { 1128 return ToString.title( this.getClass().getName() ) 1129 .println( "VERSION" ,VERSION ) 1130 .println( "tableId" ,tableId ) 1131 .println( "command" ,command ) 1132 .println( "columns" ,columns ) 1133 .println( "nullCheck" ,nullCheck ) 1134 .println( "mustAnyCheck" ,mustAnyCheck ) 1135 .println( "maxRowCount" ,maxRowCount ) 1136 .println( "minRowCount" ,minRowCount ) 1137 .println( "checkType" ,checkType ) 1138 .println( "matchKeys" ,matchKeys ) 1139 .println( "matchVals" ,matchVals ) 1140 .println( "realTime" ,isRealTime ) 1141 .println( "bodyString" ,StringUtil.htmlFilter( bodyString ) ) 1142 .println( "Other..." ,getAttributes().getAttribute() ) 1143 .fixForm().toString() ; 1144 } 1145}