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.io.IOException; 019import java.util.ArrayList; 020import java.util.HashMap; 021import java.util.List; 022import java.util.Locale; 023import java.util.Map; 024import java.util.Set; // 6.4.3.4 (2016/03/11) 025 026import javax.script.ScriptEngine; 027import javax.script.ScriptEngineManager; 028import javax.script.ScriptException; 029import javax.servlet.ServletException; 030 031import org.opengion.fukurou.db.DBUtil; 032import org.opengion.fukurou.db.Transaction; 033import org.opengion.fukurou.model.Formatter; 034import org.opengion.fukurou.util.ErrorMessage; 035import org.opengion.fukurou.util.StringUtil; 036import org.opengion.fukurou.util.ToString; // 6.1.1.0 (2015/01/17) 037import org.opengion.fukurou.util.ArraySet; // 6.4.3.4 (2016/03/11) 038import org.opengion.hayabusa.common.HybsSystem; 039import org.opengion.hayabusa.common.HybsSystemException; 040import org.opengion.hayabusa.db.DBTableModel; 041import org.opengion.hayabusa.resource.ResourceManager; 042 043import static org.opengion.fukurou.util.StringUtil.nval; 044 045/** 046 * 画面で入力されたデータのチェックを行うためのタグです。 047 * 048 * commandがNEWの場合は検索条件等のリクエストパラメータに対してチェックを行います。 049 * commandがENTRYの場合は、登録時のDBテーブルモデルに対するチェックを行います。 050 * (値の取得は、先に選択された行のみについて、実行されます。) 051 * 052 * チェックを行うための定義は、SQL文 又は JavaScriptの式が記述可能です。 053 * これらの式はタグのボディー部分に記述します。 054 * 055 * SQL文によりチェックを行う場合は、必ず件数が返されるように記述して下さい(select count(*) ・・・ 等) 056 * このSQL文で取得された件数とexistの属性値とを照合しチェックを行います。 057 * いずれの場合も、成立時は、正常とみなします。 058 * (「true:存在する」 には、データが存在した場合に、OKで、なければエラーです。) 059 * 060 * JavaScript式を記述する場合は、必ずtrue or falseを返す式を指定して下さい。 061 * この式を評価した結果falseが返される場合は、エラーとみなします。 062 * 式に不等号等を使用する場合は、CDATAセクションで囲うようにして下さい。 063 * 064 * また、いずれのチェック方法の場合でも、引数部に[カラム名]を用いたHybs拡張SQL文を 065 * 指定することが可能です。 066 * メッセージIDの{0},{1}にはそれぞれ[カラム名]指定されたカラム名及びデータがCSV形式で 067 * 自動的に設定されます。 068 * 069 * ※ このタグは、Transaction タグの対象です。 070 * 071 * @og.formSample 072 * <pre> 073 * ●形式: 074 * ・<og:dataCheck 075 * command = "{@command}" 076 * exist = "[auto|true|false|one|notuse]" 077 * errRemove = "[true|false]" 078 * lbl = "{@lbl}" 079 * lblParamKeys = "ZY03" : メッセージリソースのキーをCSV形式で指定。{2} 以降にセット 080 * sqlType = "{@sqlType}" 081 * execType = "INSERT|COPY|UPDATE|MODIFY|DELETE" : sqlType を含む場合、実行 082 * conditionKey = "FGJ" : 条件判定するカラムIDを指定(初期値は columnId ) 083 * conditionList = "0|1|8|9" : 条件判定する値のリストを、"|"で区切って登録(初期値は、無条件) 084 * uniqCheckClms = "CLM,LANG" : DBTableModel内でのユニークキーチェックを行うためのカラム 085 * > 086 * 087 * ●body:あり(EVAL_BODY_BUFFERED:BODYを評価し、{@XXXX} を解析します) 088 * (SQL文 又は JavaScript式) 089 * :なし( from属性、where属性を使用して、SQL文を内部で作成します) 090 * 091 * ●Tag定義: 092 * <og:dataCheck 093 * command 【TAG】コマンド (NEW or ENTRY)をセットします 094 * exist 【TAG】データベースのチェック方法[auto/true/false/one/notuse]を指定します(初期値:auto[自動]) 095 * tableId 【TAG】(通常は使いません)結果をDBTableModelに書き込んで、sessionに登録するときのキーを指定します 096 * dbid 【TAG】(通常は使いません)Queryオブジェクトを作成する時のDB接続IDを指定します(初期値:null) 097 * lbl 【TAG】ラベルリソースIDを指定します 098 * lblParamKeys 【TAG】ラベルリソースの引数をCSV形式で指定します 099 * errRemove 【TAG】エラー時の選択行を取り除いて継続処理を行うかどうか[true/false]を指定します(初期値:false) 100 * sqlType 【TAG】このチェックを行う、SQLタイプ を指定します 101 * execType 【TAG】このチェックを行う、実行タイプ を指定します 102 * conditionKey 【TAG】条件判定するカラムIDを指定します 103 * conditionList 【TAG】条件判定する値のリストを、"|"で区切って登録します(初期値:無条件) 104 * uniqCheckClms 【TAG】指定されたキーに従って、メモリ上のテーブルに対してユニークキーチェックを行います 105 * beforeErrorJsp 【TAG】エラーが発生した際に、エラーメッセージの表示前にincludeするJSPを指定します 106 * afterErrorJsp 【TAG】エラーが発生した際に、エラーメッセージの表示後にincludeするJSPを指定します 107 * selectedAll 【TAG】データを全件選択済みとして処理するかどうか[true/false]を指定します(初期値:false) 108 * from 【TAG】tableExist タグ廃止に伴う、簡易機能追加。チェックするデータベース名(from 句)を指定します。 109 * where 【TAG】tableExist タグ廃止に伴う、簡易機能追加。チェックする検索条件(where句)を指定します。 110 * useSLabel 【TAG】7.0.7.0 (2019/12/13) エラーメッセージにSLABELを利用するかどうか[true/false]を指定します(初期値:false) 111 * caseKey 【TAG】このタグ自体を利用するかどうかの条件キーを指定します(初期値:null) 112 * caseVal 【TAG】このタグ自体を利用するかどうかの条件値を指定します(初期値:null) 113 * caseNN 【TAG】指定の値が、null/ゼロ文字列 でない場合(Not Null=NN)は、このタグは使用されます(初期値:判定しない) 114 * caseNull 【TAG】指定の値が、null/ゼロ文字列 の場合は、このタグは使用されます(初期値:判定しない) 115 * caseIf 【TAG】指定の値が、true/TRUE文字列の場合は、このタグは使用されます(初期値:判定しない) 116 * debug 【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false) 117 * > ... Body ... 118 * </og:dataCheck> 119 * 120 * 【廃止】6.9.0.0 (2018/01/31) 物理削除 121 * // msg 【廃止】メッセージIDを指定します(lbl 属性を使用してください) 122 * // msgParamKeys 【廃止】メッセージリソースの引数をCSV形式で指定します(lblParamKeys 属性を使用してください) 123 * 124 * ●使用例 125 * ・<og:dataCheck 126 * command = "ENTRY" 127 * exist = "true" 128 * lbl = "MSG0001" 129 * > 130 * select count(*) from GEA03 where clm = [CLM] 131 * </og:dataCheck> 132 * 133 * ・exist 属性の値に応じて、チェック方法が異なります。 134 * [ auto , true , false , one , notuse が指定できます。] 135 * 136 * ・<og:dataCheck 137 * command = "ENTRY" 138 * lbl = "MSG0001" 139 * > 140 * <![CDATA[ 141 * [DYSTART] < [DY] && [DY] < [DYEND] 142 * ]]> 143 * </og:dataCheck> 144 * 145 * ・<og:dataCheck 146 * command = "ENTRY" 147 * lbl = "MSG0001" 148 * > 149 * <![CDATA[ 150 * [GOKEI] < [TANKA] * [RITU] 151 * ]]> 152 * </og:dataCheck> 153 * 154 * ※ og:tableExist タグが廃止されました。og:dataCheckタグで置き換えてください。 155 * ・<og:tableExist 156 * command = "{@command}" 157 * names = "USERID,SYSTEM_ID" 158 * from = "GE10" 159 * where = "USERID=? AND SYSTEM_ID=?" 160 * exist = "true" 161 * /> 162 * 163 * ⇒ 164 * ・<og:dataCheck 165 * command = "{@command}" 166 * exist = "true" 167 * from = "GE10" 168 * where = "USERID=[USERID] AND SYSTEM_ID=[SYSTEM_ID]" 169 * /> 170 * 171 * ・<og:tableExist 172 * command = "{@command}" 173 * from = "GE10" 174 * where = "USERID=[USERID] AND SYSTEM_ID=[SYSTEM_ID]" /> 175 * ⇒ 176 * ・<og:dataCheck 177 * command = "{@command}" 178 * from = "GE10" 179 * where = "USERID=[USERID] AND SYSTEM_ID=[SYSTEM_ID]" /> 180 * /> 181 * 182 * </pre> 183 * 184 * @og.rev 4.1.1.1 (2008/02/22) 新規作成 185 * @og.group DB登録 186 * 187 * @version 4.0 188 * @author Hiroki Nakamura 189 * @since JDK5.0, 190 */ 191public class DataCheckTag extends CommonTagSupport { 192 /** このプログラムのVERSION文字列を設定します。 {@value} */ 193 private static final String VERSION = "7.0.7.0 (2019/12/13)" ; 194 private static final long serialVersionUID = 707020191213L ; 195 196 /** command 引数に渡す事の出来る コマンド {@value} */ 197 public static final String CMD_NEW = "NEW"; 198 199 /** command 引数に渡す事の出来る コマンド {@value} */ 200 public static final String CMD_ENTRY = "ENTRY"; 201 202 // 6.4.3.4 (2016/03/11) String配列 から、Setに置き換えます。 203 private static final Set<String> COMMAND_SET = new ArraySet<>( CMD_ENTRY, CMD_NEW ); 204 205 /** 内部変数 */ 206 private transient DBTableModel table ; 207 private transient boolean isSql ; 208 private transient boolean isUniqCheck ; // 4.3.4.0 (2008/12/01) 追加 209 private transient ScriptEngine jsEngine ; 210 private transient String bodyStr ; // 4.3.4.0 (2008/12/01) 追加 211 212 /** タグで設定する属性 */ 213 private String command = CMD_ENTRY; 214 private String exist = "auto"; 215 private String tableId = HybsSystem.TBL_MDL_KEY; 216 private String dbid ; 217 private String lbl ; 218 private String[] lblParamKeys ; // 4.2.0.1 (2008/03/27) 219 private boolean errRemove ; 220 private String sqlType ; // INSERT,COPY,UPDATE,MODIFY,DELETE 221 private String execType ; // INSERT,COPY,UPDATE,MODIFY,DELETE 222 223 private String conditionKey ; // 4.2.0.1 (2008/03/27) 224 private String conditionList ; // 4.2.0.1 (2008/03/27) 225 private String from ; // 4.2.0.1 (2008/03/27) 226 private String where ; // 5.7.6.2 (2014/05/16) tableExist タグに伴う便利機能追加 227 private String[] uniqCheckClms ; // 4.3.4.0 (2008/12/01) 228 229 private String beforeErrorJsp ; // 5.1.9.0 (2010/08/01) 230 private String afterErrorJsp ; // 5.1.9.0 (2010/08/01) 231 private boolean selectedAll ; // 5.1.9.0 (2010/08/01) 232 233 private boolean isExec ; // 6.3.4.0 (2015/08/01) パラメータではなく毎回設定します。 234 235 private boolean useSLabel ; // 7.0.7.0 (2019/12/13) エラーメッセージにSLABELを利用するかどうか[true/false]を指定します(初期値:false) 236 237 /** 238 * デフォルトコンストラクター 239 * 240 * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor. 241 */ 242 public DataCheckTag() { super(); } // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。 243 244 /** 245 * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。 246 * 247 * @og.rev 4.1.1.0 (2008/02/22) 新規作成 248 * @og.rev 4.1.2.0 (2008/03/12) sqlType,execType 判定 249 * @og.rev 6.3.4.0 (2015/08/01) caseKey,caseVal,caseNN,caseNull,caseIf 属性対応 250 * 251 * @return 後続処理の指示 252 */ 253 @Override 254 public int doStartTag() { 255 isExec = useTag() && ( sqlType == null || execType == null || execType.indexOf( sqlType ) >= 0 ) ; 256 257 // 6.4.1.1 (2016/01/16) PMD refactoring. A method should have only one exit point, and that should be the last statement in the method 258 return isExec 259 ? EVAL_BODY_BUFFERED // Body を評価する 260 : SKIP_BODY ; // Body を評価しない 261 } 262 263 /** 264 * Taglibのタグ本体を処理する doAfterBody() を オーバーライドします。 265 * 266 * @og.rev 4.3.4.0 (2008/12/01) 新規追加 267 * @og.rev 6.3.1.1 (2015/07/10) BodyString,BodyRawStringは、CommonTagSupport で、trim() します。 268 * 269 * @return 後続処理の指示(SKIP_BODY) 270 */ 271 @Override 272 public int doAfterBody() { 273 bodyStr = getBodyString(); 274 return SKIP_BODY ; 275 } 276 277 /** 278 * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。 279 * 280 * @og.rev 4.1.1.0 (2008/02/22) 新規作成 281 * @og.rev 4.1.2.0 (2008/03/12) sqlType,execType 判定 282 * @og.rev 4.2.0.1 (2008/03/27) from を取得 283 * @og.rev 4.2.1.0 (2008/04/11) ErrMessageManager対応 284 * @og.rev 4.3.4.0 (2008/12/01) ユニークキーチェック対応。bodyContentの取得を#doAfterBody()で行う。 285 * @og.rev 5.1.9.0 (2010/08/01) エラーメッセージの表示前後にincludeするJSPを指定できるようにする。 286 * @og.rev 5.1.9.0 (2010/08/01) Transaction 対応します。 287 * @og.rev 5.3.7.0 (2011/07/01) TransactionReal の引数変更 、Transaction対応で、close処理を入れる。 288 * @og.rev 6.3.6.1 (2015/08/28) Transaction でAutoCloseableを使用したtry-with-resources構築に対応。 289 * @og.rev 7.0.7.0 (2019/12/13) useSLabel 属性を追加。 290 * 291 * @return 後続処理の指示 292 */ 293 @Override 294 public int doEndTag() { 295 debugPrint(); 296 int rtnCode = EVAL_PAGE; 297 298 // 4.1.2.0 (2008/03/12) 実行条件 isExec を評価 299 if( isExec && check( command, COMMAND_SET ) ) { 300 // exist="notuse"の場合はチェックしない 301 if( "notuse".equalsIgnoreCase( exist ) ) { return rtnCode; } 302 303 // パラメーターから処理のタイプを判別 304 checkParam(); 305 306 // エラーメッセージを管理するクラスを作成します。 307 final ErrMessageManager manager = new ErrMessageManager(); 308 manager.setTitle( "Data Check Error!" ); 309 manager.setParamKeys( lblParamKeys ); 310 manager.setResourceManager( getResource() ); 311 manager.setFrom( from ); 312 313 // 6.3.6.1 (2015/08/28) Transaction でAutoCloseableを使用したtry-with-resources構築に対応。 314 try( final Transaction tran = getTransaction() ) { 315 // command="NEW"の場合 316 if( CMD_NEW.equals( command ) ) { 317 if( isSql ) { 318 checkSql( bodyStr, manager, null, 0, DBTableModel.UPDATE_TYPE, tran ); // 5.1.9.0 (2010/08/01) 319 } 320 else { 321 checkJs( bodyStr, manager, null, 0, jsEngine ); 322 } 323 } 324 // command="ENTRY"の場合(テーブルモデルが存在しない場合は処理しない) 325 else if( CMD_ENTRY.equals( command ) ) { 326 table = (DBTableModel) getObject( tableId ); 327 if( table != null && table.getRowCount() > 0 ) { 328 manager.setDBTableModel( table ); 329 if( isUniqCheck ) { 330 checkUnique( manager ); 331 } 332 else { 333 checkRows( bodyStr, manager, tran ); // 5.1.9.0 (2010/08/01) 334 } 335 } 336 else { 337 System.out.println( "DBTableModel doesn't exist!! need this when command=\"ENTRY\"" ); 338 } 339 } 340 tran.commit(); // 6.3.6.1 (2015/08/28) 341 } 342 343 // エラーが発生した場合は、エラーメッセージを表示して以降の処理を行わない。 344 final ErrorMessage errMessage = manager.getErrMessage() ; 345 if( errMessage != null && !errMessage.isOK() && !errRemove ) { 346 rtnCode = SKIP_PAGE; 347 348 // 5.1.9.0 (2010/08/01) エラーメッセージの表示前にincludeするJSPを指定 349 if( beforeErrorJsp != null && beforeErrorJsp.length() > 0 ) { 350 includeJsp( beforeErrorJsp ); 351 } 352 353// jspPrint( TaglibUtil.makeHTMLErrorTable( errMessage, getResource() ) ); 354 jspPrint( TaglibUtil.makeHTMLErrorTable( errMessage, getResource(),useSLabel ) ); // 7.0.7.0 (2019/12/13) 355 356 // 5.1.9.0 (2010/08/01) エラーメッセージの表示後にincludeするJSPを指定 357 if( afterErrorJsp != null && afterErrorJsp.length() > 0 ) { 358 includeJsp( afterErrorJsp ); 359 } 360 } 361 } 362 363 return rtnCode ; 364 } 365 366 /** 367 * タグリブオブジェクトをリリースします。 368 * キャッシュされて再利用されるので、フィールドの初期設定を行います。 369 * 370 * @og.rev 4.1.1.0 (2008/02/22) 新規作成 371 * @og.rev 4.1.2.0 (2008/03/12) sqlType , execType , isExec 追加 372 * @og.rev 4.2.0.1 (2008/03/27) conditionKey , conditionList , msgParamKeys 追加 373 * @og.rev 5.1.9.0 (2010/08/01) beforeErrorJsp , afterErrorJsp, selectedAll 追加 374 * @og.rev 5.7.6.2 (2014/05/16) where 追加。tableExist タグに伴う便利機能追加 375 * @og.rev 6.3.4.0 (2015/08/01) isExec は、パラメータではなく、ローカル変数。 376 * @og.rev 7.0.7.0 (2019/12/13) useSLabel 属性を追加。 377 */ 378 @Override 379 protected void release2() { 380 super.release2(); 381 tableId = HybsSystem.TBL_MDL_KEY; 382 dbid = null; 383 command = CMD_ENTRY; 384 table = null; 385 exist = "auto"; 386 errRemove = false; 387 lbl = null; 388 lblParamKeys = null; // 4.2.0.1 (2008/03/27) 389 isSql = false; 390 isUniqCheck = false; // 4.3.4.0 (2008/12/01) 391 jsEngine = null; 392 sqlType = null; // INSERT,COPY,UPDATE,MODIFY,DELETE 393 execType = null; // INSERT,COPY,UPDATE,MODIFY,DELETE 394 conditionKey = null; // 4.2.0.1 (2008/03/27) 395 conditionList = null; // 4.2.0.1 (2008/03/27) 396 from = null; // 4.2.0.1 (2008/03/27) 397 where = null; // 5.7.6.2 (2014/05/16) tableExist タグに伴う便利機能追加 398 bodyStr = null; // 4.3.4.0 (2008/12/01)) 399 uniqCheckClms = null; // 4.3.4.0 (2008/12/01) 400 beforeErrorJsp = null; // 5.1.9.0 (2010/08/01) 401 afterErrorJsp = null; // 5.1.9.0 (2010/08/01) 402 selectedAll = false; // 5.1.9.0 (2010/08/01) 403 useSLabel = false; // 7.0.7.0 (2019/12/13) エラーメッセージにSLABELを利用するかどうか[true/false]を指定します(初期値:false) 404 } 405 406 /** 407 * 引数及びボディー部分のチェックを行い、処理のタイプを判別します。 408 * 409 * @og.rev 5.5.8.0 (2012/11/01) タイプ判別変更 410 * @og.rev 5.6.1.1 (2013/02/08) FROM 部の切り出し位置修正 411 * @og.rev 5.7.6.2 (2014/05/16) tableExist タグに伴う便利機能追加。from属性とwhere属性追加 412 */ 413 private void checkParam() { 414 isUniqCheck = uniqCheckClms != null && uniqCheckClms.length > 0 ; 415 if( isUniqCheck ) { 416 if( !CMD_ENTRY.equals( command ) ) { 417 final String errMsg = "ユニークキーチェックは、command=\"ENTRY\"の場合のみ使用可能です。" 418 + " command=" + command ; // 5.1.8.0 (2010/07/01) errMsg 修正 419 throw new HybsSystemException( errMsg ); 420 } 421 } 422 // 5.7.6.2 (2014/05/16) tableExist タグに伴う便利機能追加。from属性とwhere属性追加 423 // 6.4.1.1 (2016/01/16) PMD refactoring. Avoid if (x != y) ..; else ..; 424 else if( from == null ) { 425 if( bodyStr == null || bodyStr.isEmpty() ) { 426 final String errMsg = "Body部分にチェック定義を記述して下さい。"; 427 throw new HybsSystemException( errMsg ); 428 } 429 430 // SQLチェックかJavaScriptによるチェックかの判定 431 final String query = bodyStr.toUpperCase( Locale.JAPAN ); // 4.2.0.1 (2008/03/27) 432 if( query.indexOf( "SELECT" ) == 0 ) { // 5.5.8.0 (2012/11/01) 先頭に限定する。(trim済のため) 433 isSql = true; 434 final int st = query.indexOf( "FROM" ) ; 435 final int ed = query.indexOf( "WHERE" ) ; 436 if( st > 0 && st < ed ) { 437 from = query.substring( st+"FROM".length(),ed ).trim(); // 5.6.1.1 (2013/02/08) 438 } 439 } 440 else { 441 jsEngine = new ScriptEngineManager().getEngineByName( "JavaScript" ); 442 } 443 } 444 else { 445 final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE ) 446 .append( "SELECT count(*) FROM " ).append( from ); 447 if( where != null ) { buf.append( " WHERE " ).append( where ); } 448 bodyStr = buf.toString(); 449 isSql = true; 450 } 451 } 452 453 /** 454 * SQLによるデータチェックを行います。 455 * チェック方法は、exist属性の指定に依存します。 456 * autoの場合は、テーブルモデルの改廃Cから自動でチェック方法が決定されます。 457 * 458 * @param str 実行するSQL文 459 * @param manager ErrMessageManagerオブジェクト 460 * @param values SQL文のパラメータ 461 * @param row 行番号 462 * @param modifyType 改廃C 463 * @param tran トランザクションオブジェクト 464 * 465 * @return 処理の成否 466 * 467 * @og.rev 4.1.1.0 (2008/02/22) 新規作成 468 * @og.rev 4.2.1.0 (2008/04/11) ErrMessageManager対応 469 * @og.rev 5.1.9.0 (2010/08/01) Transaction 対応します。 470 */ 471 private boolean checkSql( final String str, final ErrMessageManager manager, final String[] values 472 , final int row, final String modifyType, final Transaction tran ) { 473 474 final int cnt = DBUtil.dbExist( str, values, tran, dbid ); // 5.1.9.0 (2010/08/01) 475 476 boolean okFlag = true; 477 String id = null; 478 if( ( "true".equalsIgnoreCase( exist ) || ( "auto".equalsIgnoreCase( exist ) 479 && ( DBTableModel.UPDATE_TYPE.equals( modifyType ) || DBTableModel.DELETE_TYPE.equals( modifyType ) ) ) ) && cnt <= 0 ) { 480 // ERR0025=データ未登録エラー。キー={0}、値={1} のデータは、存在していません。 481 id = ( lbl == null ? "ERR0025" : lbl ); 482 okFlag = false; 483 } 484 else if( ( "false".equalsIgnoreCase( exist ) || ( "auto".equalsIgnoreCase( exist ) 485 && DBTableModel.INSERT_TYPE.equals( modifyType ) ) ) && cnt > 0 ) { 486 // ERR0026=データ登録済みエラー。キー={0}、値={1} のデータは、すでに存在しています。 487 id = ( lbl == null ? "ERR0026" : lbl ); 488 okFlag = false; 489 } 490 else if( "one".equalsIgnoreCase( exist ) && cnt > 1 ) { 491 // ERR0027=データ2重登録エラー。キー={0}、値={1} のデータは、重複して存在しています。 492 id = ( lbl == null ? "ERR0027" : lbl ); 493 okFlag = false; 494 } 495 496 if( !okFlag ) { 497 manager.addMessage( row, id, values ); 498 } 499 return okFlag; 500 } 501 502 /** 503 * JavaScriptの式を実行します。 504 * 実行した結果がboolean型でない場合はエラーとなります。 505 * 506 * @param str 実行するSQL文 507 * @param manager オブジェクト 508 * @param values 値配列 509 * @param row 行番号 510 * @param engine JavaScriptエンジン 511 * 512 * @return 処理の成否 513 * 514 * @og.rev 4.1.1.0 (2008/02/22) 新規作成 515 * @og.rev 4.2.0.1 (2008/03/27) getClass().getName() から、instanceof に変更 516 * @og.rev 4.2.1.0 (2008/04/11) ErrMessageManager対応 517 */ 518 private boolean checkJs( final String str, final ErrMessageManager manager, final String[] values 519 , final int row, final ScriptEngine engine ) { 520 // JavaScriptエンジンによる評価 521 Object obj = null; 522 try { 523 obj = engine.eval( str ); 524 } 525 catch( final ScriptException ex ) { 526 final String errMsg = "JavaScript式のパースに失敗しました。[" + str + "]"; 527 throw new HybsSystemException( errMsg , ex ); 528 } 529 530 // 返り値がBoolean型かチェック 531 boolean okFlag = false; 532 // 4.2.0.1 (2008/03/27) instanceof に変更 533 if( obj instanceof Boolean ) { // 4.3.1.1 (2008/08/23) instanceof チェックは、nullチェック不要 534 okFlag = ((Boolean)obj).booleanValue(); 535 } 536 else { 537 final String errMsg = "JavaScript式には true 若しくは false が返るように設定して下さい" 538 + " Object=" + obj ; // 5.1.8.0 (2010/07/01) errMsg 修正 539 throw new HybsSystemException( errMsg ); 540 } 541 542 if( !okFlag ) { 543 // ERR0030=入力したデータが不正です。key={0} value={1} 形式={2} 544 final String id = ( lbl == null ? "ERR0030" : lbl ); 545 546 manager.addMessage( row, id, values ); 547 } 548 549 return okFlag; 550 } 551 552 /** 553 * DBテーブルモデルの各行に対してデータチェックを行います。 554 * 555 * @param str チェック対象の文字列 556 * @param manager ErrMessageManagerオブジェクト 557 * @param tran トランザクションオブジェクト 558 * 559 * @og.rev 4.1.1.0 (2008/02/22) 新規作成 560 * @og.rev 4.2.0.1 (2008/03/27) conditionKey,conditionList 対応 561 * @og.rev 4.2.1.0 (2008/04/11) ErrMessageManager対応 562 * @og.rev 5.1.9.0 (2010/08/01) Transaction 対応します。 563 * @og.rev 6.4.3.4 (2016/03/11) Formatterに新しいコンストラクターを追加する。 564 */ 565 private void checkRows( final String str, final ErrMessageManager manager, final Transaction tran ) { 566 567 final int[] rowNo = getParameterRows(); // 4.0.0 (2005/01/31) 568 if( rowNo.length == 0 ) { return; } 569 570 final Formatter format = new Formatter( table,str ); // 6.4.3.4 (2016/03/11) 571 final int[] clmNo = format.getClmNos(); 572 // 4.2.0.1 (2008/03/27) カラム名のメッセージリソース文字列を作成します。 573 manager.setClmNos( clmNo ); 574 575 // SQL文の場合のみ[xxx]を?に変換したSQL文を取得(JavaScriptの場合はループ内で各行毎に取得 576 String query = null; 577 if( isSql ) { 578 query = format.getQueryFormatString(); 579 } 580 581 // 4.2.0.1 (2008/03/27) conditionKey,conditionList 対応 582 int cndKeyNo = -1; 583 if( conditionKey != null && conditionList != null ) { 584 cndKeyNo = table.getColumnNo( conditionKey ); // 不正指定はエラー 585 } 586 587 final List<Integer> list = new ArrayList<>(); 588 boolean okFlag = false; 589 for( int i=0; i<rowNo.length; i++ ) { 590 final int row = rowNo[i] ; 591 final String[] values = getTableModelData( row, clmNo ); 592 // 4.2.0.1 (2008/03/27) 条件指定がされている場合に、 593 // Listに含まれない場合は、実行されない。 594 // 4.2.1.0 (2008/04/11) 厳密に処理します。 595 if( cndKeyNo >= 0 && conditionList.indexOf( table.getValue( row,cndKeyNo ) ) < 0 ) { 596 final String conVal = "|" + table.getValue( row,cndKeyNo ) + "|" ; 597 if( conditionList.indexOf( conVal ) < 0 ) { continue; } 598 } 599 600 if( isSql ) { 601 okFlag = checkSql( query, manager, values, row, table.getModifyType( row ), tran ); 602 } 603 else { 604 final String jsStr = format.getFormatString( row, "\"" ); 605 okFlag = checkJs( jsStr, manager, values, row, jsEngine ); 606 } 607 608 if( errRemove && okFlag ) { 609 list.add( row ); 610 } 611 } 612 613 if( errRemove ) { 614 final Integer[] in = list.toArray( new Integer[list.size()] ); 615 int[] newRowNo = new int[in.length]; 616 for( int i=0; i<in.length; i++ ) { 617 newRowNo[i] = in[i].intValue(); 618 } 619 setParameterRows( newRowNo ); 620 } 621 } 622 623 /** 624 * DBテーブルモデルの各行にユニークキーのチェックを行います。 625 * 626 * @og.rev 4.3.4.0 (2008/12/01) 新規作成 627 * @og.rev 6.3.9.0 (2015/11/06) コンストラクタで初期化されていないフィールドを null チェックなしで利用している(findbugs) 628 * 629 * @param manager ErrMessageManagerオブジェクト 630 */ 631 private void checkUnique( final ErrMessageManager manager ) { 632 final int[] rowNo = getParameterRows(); 633 if( rowNo.length == 0 ) { return; } 634 635 // 6.3.9.0 (2015/11/06) コンストラクタで初期化されていないフィールドを null チェックなしで利用している(findbugs) 636 if( uniqCheckClms == null ) { return; } 637 638 int[] clmNo = new int[uniqCheckClms.length]; 639 for( int i=0; i<clmNo.length; i++ ) { 640 clmNo[i] = table.getColumnNo( uniqCheckClms[i] ); 641 } 642 643 manager.setClmNos( clmNo ); 644 645 final List<Integer> list = new ArrayList<>(); 646 final Map<String,Integer> map = new HashMap<>(); 647 for( int i=0; i<rowNo.length; i++ ) { 648 final int row = rowNo[i] ; 649 final String[] values = getTableModelData( row, clmNo ); 650 final String key = StringUtil.array2line( values, " + " ); 651 652 if( map.get( key ) == null ) { 653 map.put( key, 1 ); 654 if( errRemove ) { 655 list.add( row ); 656 } 657 } 658 else { 659 // ERR0027=データ2重登録エラー。キー={0}、値={1} のデータは、重複して存在しています。 660 id = ( lbl == null ? "ERR0027" : lbl ); 661 manager.addMessage( row, id, values ); 662 } 663 } 664 665 if( errRemove ) { 666 final Integer[] in = list.toArray( new Integer[list.size()] ); 667 int[] newRowNo = new int[in.length]; 668 for( int i=0; i<in.length; i++ ) { 669 newRowNo[i] = in[i].intValue(); 670 } 671 setParameterRows( newRowNo ); 672 } 673 } 674 675 /** 676 * 【TAG】(通常は使いません)結果のDBTableModelを、sessionに登録するときのキーを指定します 677 * (初期値:HybsSystem#TBL_MDL_KEY[={@og.value HybsSystem#TBL_MDL_KEY}])。 678 * 679 * @og.tag 680 * 検索結果より、DBTableModelオブジェクトを作成します。これを、下流のviewタグ等に 681 * 渡す場合に、通常は、session を利用します。その場合の登録キーです。 682 * query タグを同時に実行して、結果を求める場合、同一メモリに配置される為、 683 * この tableId 属性を利用して、メモリ空間を分けます。 684 * (初期値:HybsSystem#TBL_MDL_KEY[={@og.value HybsSystem#TBL_MDL_KEY}])。 685 * 686 * @param id テーブルID (sessionに登録する時のID) 687 */ 688 public void setTableId( final String id ) { 689 tableId = nval( getRequestParameter( id ), tableId ); 690 } 691 692 /** 693 * 【TAG】(通常は使いません)Queryオブジェクトを作成する時のDB接続IDを指定します(初期値:null)。 694 * 695 * @og.tag Queryオブジェクトを作成する時のDB接続IDを指定します。 696 * 697 * @param id データベース接続ID 698 */ 699 public void setDbid( final String id ) { 700 dbid = nval( getRequestParameter( id ), dbid ); 701 } 702 703 /** 704 * 【TAG】コマンド (NEW or ENTRY)をセットします。 705 * 706 * @og.tag 707 * コマンドは,HTMLから(get/post)指定されますので,CMD_xxx で設定される 708 * フィールド定数値のいづれかを、指定できます。 709 * 710 * @param cmd コマンド (public static final 宣言されている文字列) 711 * @see <a href="../../../../constant-values.html#org.opengion.hayabusa.taglib.DataCheckTag.CMD_NEW">コマンド定数</a> 712 */ 713 public void setCommand( final String cmd ) { 714 final String cmd2 = getRequestParameter( cmd ); 715 if( cmd2 != null && cmd2.length() > 0 ) { 716 command = cmd2.toUpperCase( Locale.JAPAN ); 717 } 718 } 719 720 /** 721 * 【TAG】データベースのチェック方法[auto/true/false/one/notuse]を指定します(初期値:auto[自動])。 722 * 723 * @og.tag 724 * exist 属性に指定された 、「true:存在する」、「false:存在しない」、「one:ひとつ以下」、 725 * の値は、いずれの場合も、成立時は、正常とみなします。 726 * 「auto:自動」は、DBTableModeleのmodifyType(A,C,D)に応じて、チェックします。 727 * A,C,D は、entryタグにコマンドを渡してデータを作成したときに、内部で作成されます。 728 * (command="NEW"の場合は、trueと同じ動きになります。) 729 * notuse は、チェックを行いません。これは、このタグを共有使用する場合に、外部で 730 * チェックを行うかどうかを指定できるようにするために使用します。 731 * (「true:存在する」 には、データが存在した場合に、OKで、なければエラーです。) 732 * 初期値は、「auto:自動」です。 733 * 734 * @param ext チェック方法 [auto:自動/true:存在する/false:存在しない/one:ひとつ以下/notuse:チェックしない] 735 */ 736 public void setExist( final String ext ) { 737 exist = nval( getRequestParameter( ext ), exist ); 738 if( !"auto".equalsIgnoreCase( exist ) 739 && !"true".equalsIgnoreCase( exist ) 740 && !"false".equalsIgnoreCase( exist ) 741 && !"one".equalsIgnoreCase( exist ) 742 && !"notuse".equalsIgnoreCase( exist ) ) { 743 final String errMsg = "exist 属性は、(auto,true,false,one,notuse)を指定してください。 [" + exist + "]" + CR; 744 throw new HybsSystemException( errMsg ); 745 } 746 } 747 748 /** 749 * 【TAG】エラー時の選択行を取り除いて継続処理を行うかどうか[true/false]を指定します(初期値:false)。 750 * 751 * @og.tag 752 * exist 属性に指定された 、「true:存在する」、「false:存在しない」、「one:ひとつ以下」、 753 * に対して、エラーが発生した選択行番号を、取り除いて以下の処理を継続するかどうかを 754 * 指定します。 755 * true に設定した場合は、エラーデータを削除し、継続処理を行うことができます。 756 * flase の場合は、エラーデータを表示して、継続処理を停止します。 757 * 初期値は、「false:エラー時停止」です。 758 * 759 * @param flag エラーデータを除外 [true:継続処理/false:エラー時停止] 760 */ 761 public void setErrRemove( final String flag ) { 762 errRemove = nval( getRequestParameter( flag ), errRemove ); 763 } 764 765 /** 766 * 【TAG】ラベルリソースのラベルIDを指定します。 767 * 768 * @og.tag ラベルリソースIDを指定します。 769 * 各処理に応じた初期設定のラベルリソースIDは、以下の通りです。 770 * exist="true" ERR0025=データ未登録エラー。キー={0}、値={1} のデータは、存在していません。 771 * exist="false" ERR0026=データ登録済みエラー。キー={0}、値={1} のデータは、すでに存在しています。 772 * exist="one" ERR0027=データ2重登録エラー。キー={0}、値={1} のデータは、重複して存在しています。 773 * JavaScript ERR0030=入力したデータが不正です。key={0} value={1} 形式={2} 774 * 引数のパラメータには、通常、チェックに使用した実データが、DBTableModel から取得されます。 775 * 引数を変更する場合は、lblParamKeys を使用してください。 776 * 777 * @param id メッセージID 778 * @see #setLblParamKeys( String ) 779 */ 780 @Override 781 public void setLbl( final String id ) { 782 // 継承親のメソッドを使わない。 783 lbl = nval( getRequestParameter( id ), lbl ); 784 } 785 786 /** 787 * 【TAG】ラベルリソースの引数をCSV形式で指定します。 788 * 789 * @og.tag 790 * ラベルリソースのキーをCSV形式で指定することで、設定します。 791 * ラベルに引数( {0},{1} など ) がある場合、ここで指定した値を 792 * 順番に、{0},{1},{2}・・・ に当てはめていきます。 793 * キーワードは、CSV形式で指定し、それを分解後、ラベルリソースで 794 * リソース変換を行います。(つまり、記述された値そのものでは在りません) 795 * PL/SQL では、"{#PN}" などと指定していた分は、同様に "PN" と指定しです。 796 * 内部的に、where 条件に指定されたキーと値は、@KEY と @VAL に、 797 * from と where の間の文字列は、@TBL に対応付けられます。 798 * {@XXXX} 変数も使用できます。実データの値を取出したい場合は、[PN]と 799 * すれば、DBTableModel の PN の値を取出します。 800 * なにも指定しない場合は、キー={0} 、値={1}、from={2} です。 801 * 802 * @og.rev 4.2.0.1 (2008/03/27) 新規追加 803 * 804 * @param keys メッセージリソースのキー(CSV) 805 * @see #setLbl( String ) 806 */ 807 public void setLblParamKeys( final String keys ) { 808 lblParamKeys = getCSVParameter( keys ); 809 } 810 811 /** 812 * 【TAG】このチェックを行う、SQLタイプ を指定します。 813 * 814 * @og.tag 815 * SQLタイプは、INSERT,COPY,UPDATE,MODIFY,DELETE などの記号を指定します。 816 * 一般には、result 画面から update 画面へ遷移するときの、command と 817 * 同じにしておけばよいでしょう。 818 * これは、execType とマッチした場合のみ、このチェックが処理されます。 819 * 簡易 equals タグの代役に使用できます。 820 * なにも指定しない場合は、チェックは実行されます。 821 * 822 * @og.rev 4.1.2.0 (2008/03/12) 新規追加 823 * 824 * @param type このチェックを行うSQLタイプ 825 */ 826 public void setSqlType( final String type ) { 827 sqlType = nval( getRequestParameter( type ),sqlType ); 828 } 829 830 /** 831 * 【TAG】このチェックを行う、実行タイプ を指定します。 832 * 833 * @og.tag 834 * 実行タイプは、sqlType とマッチした場合のみ、このチェックが処理されます。 835 * 簡易 equals タグの代役に使用できます。 836 * execType は、複数指定が可能です。単純な文字列マッチで、sqlType を 837 * 含めば、実行されます。 838 * 例えば、sqlType={@sqlType} execType="INSERT|COPY" とすれば、 839 * sqlType に、INSERT または、COPY が登録された場合にチェックが掛かります。 840 * なにも指定しない場合は、チェックは実行されます。 841 * 842 * @og.rev 4.1.2.0 (2008/03/12) 新規追加 843 * 844 * @param type このチェックを行う実行タイプ 845 */ 846 public void setExecType( final String type ) { 847 execType = nval( getRequestParameter( type ),execType ); 848 } 849 850 /** 851 * 【TAG】条件判定するカラムIDを指定します(初期値:null)。 852 * 853 * @og.tag 854 * 指定のカラムIDの値と、conditionList の値を比較して、 855 * 存在する場合は、check処理を実行します。 856 * この処理が有効なのは、command="ENTRY" の場合のみです。 857 * 858 * @og.rev 4.2.0.1 (2008/03/27) 新規追加 859 * 860 * @param key カラムID 861 * @see #setConditionList( String ) 862 */ 863 public void setConditionKey( final String key ) { 864 conditionKey = nval( getRequestParameter( key ),null ) ; 865 } 866 867 /** 868 * 【TAG】条件判定する値のリストを、"|"で区切って登録します(初期値:無条件)。 869 * 870 * @og.tag 871 * conditionKey とペアで指定します。ここには、カラムの設定値のリストを 872 * 指定することで、複数条件(OR結合)での比較を行い、リストにカラム値が 873 * 存在する場合のみ、check処理を実行します。 874 * この処理が有効なのは、command="ENTRY" の場合のみです。 875 * 設定しない場合は、無条件に実行します。 876 * 877 * @og.rev 4.2.0.1 (2008/03/27) 新規追加 878 * 879 * @param list 条件判定する値("|"で区切) 880 * @see #setConditionKey( String ) 881 */ 882 public void setConditionList( final String list ) { 883 conditionList = nval( getRequestParameter( list ),null ) ; 884 if( conditionList != null ) { 885 conditionList = "|" + conditionList + "|" ; 886 } 887 } 888 889 /** 890 * 【TAG】指定されたキーに従って、メモリ上のテーブルに対してユニークキーチェックを行います。 891 * 892 * @og.tag 893 * ユニークキーチェックを行うキーを指定します。ここで、指定されたキーに対して、 894 * DBTableModelの値をチェックし、全てのキーに同じ値となっている行が存在すればエラーとなります。 895 * このチェックは、command="ENTRY"の場合のみ有効です。 896 * また、このチェックは他のチェック(DB存在チェックなど)と同時に処理することはできません。 897 * キーが指定され手いる場合は、ボディ部分に記述されている定義は無視されます。 898 * errRemoveの属性がtrueに指定されている場合、重複行は、DBTableModelの並び順から見て、 899 * 最初の行のみ処理され、2つめ以降の重複行は無視されます。 900 * なお、キーはCSV形式(CSV形式)で複数指定が可能です。 901 * 902 * @og.rev 4.3.4.0 (2008/12/01) 新規追加 903 * 904 * @param clm チェックキー(CSV形式) 905 */ 906 public void setUniqCheckClms( final String clm ) { 907 final String tmp = nval( getRequestParameter( clm ),null ); 908 uniqCheckClms = StringUtil.csv2Array( tmp ); 909 } 910 911 /** 912 * 【TAG】エラーが発生した際に、エラーメッセージの表示前にincludeするJSPを指定します。 913 * 914 * @og.tag 915 * エラーが発生した際に、エラーメッセージの表示前にincludeするJSPを指定します。 916 * エラーが発生していない場合は、ここで指定されたJSPが処理されることはありません。 917 * 通常は、戻るリンクなどを指定します。 918 * 919 * 指定の方法は、相対パス、絶対パスの両方で指定することができます。 920 * 但し、絶対パスで指定した場合、その基点は、コンテキストのルートディレクトリになります。 921 * 例) beforeErrorJsp = "/jsp/common/history_back.jsp" 922 * 923 * @og.rev 5.1.9.0 (2010/08/01) 新規追加 924 * 925 * @param jsp 表示前にincludeするJSPファイル名 926 */ 927 public void setBeforeErrorJsp( final String jsp ) { 928 beforeErrorJsp = nval( getRequestParameter( jsp ),beforeErrorJsp ); 929 } 930 931 /** 932 * 【TAG】エラーが発生した際に、エラーメッセージの表示後にincludeするJSPを指定します。 933 * 934 * @og.tag 935 * エラーが発生した際に、エラーメッセージの表示前にincludeするJSPを指定します。 936 * エラーが発生していない場合は、ここで指定されたJSPが処理されることはありません。 937 * 938 * 指定の方法は、相対パス、絶対パスの両方で指定することができます。 939 * 但し、絶対パスで指定した場合、その基点は、コンテキストのルートディレクトリになります。 940 * 例) afterErrorJsp = "/jsp/common/history_back.jsp" 941 * 942 * @og.rev 5.1.9.0 (2010/08/01) 新規追加 943 * 944 * @param jsp 表示後にincludeするJSPファイル名 945 */ 946 public void setAfterErrorJsp( final String jsp ) { 947 afterErrorJsp = nval( getRequestParameter( jsp ),afterErrorJsp ); 948 } 949 950 /** 951 * 【TAG】データを全件選択済みとして処理するかどうか[true/false]を指定します(初期値:false)。 952 * 953 * @og.tag 954 * 全てのデータを選択済みデータとして扱って処理します。 955 * 全件処理する場合に、(true/false)を指定します。 956 * 初期値は false です。 957 * 958 * @og.rev 5.1.9.0 (2010/08/01) 新規追加 959 * 960 * @param all 選択済み処理可否 [true:全件選択済み/false:通常] 961 */ 962 public void setSelectedAll( final String all ) { 963 selectedAll = nval( getRequestParameter( all ),selectedAll ); 964 } 965 966 /** 967 * 【TAG】チェックするデータベース名(from 句)を指定します。 968 * 969 * @og.tag 970 * これは、tableExist タグ廃止に伴う便利機能で、通常、BODYに記述された 971 * SELECT count(*) from XXXX where XXXXX で、チェックしますが、 972 * from 属性 と、where 属性を指定する事で、内部で、チェック用のSQL文を 973 * 作成します。 974 * from が指定された場合は、BODY は無視されますので、ご注意ください。 975 * 976 * @og.rev 5.7.6.2 (2014/05/16) 新規追加 977 * 978 * @param frm チェックするテーブルID 979 */ 980 public void setFrom( final String frm ) { 981 from = nval( getRequestParameter( frm ),from ); 982 } 983 984 /** 985 * 【TAG】チェックする検索条件(where句)を指定します。 986 * 987 * @og.tag 988 * これは、tableExist タグ廃止に伴う便利機能で、通常、BODYに記述された 989 * SELECT count(*) from XXXX where XXXXX で、チェックしますが、 990 * from 属性 と、where 属性を指定する事で、内部で、チェック用のSQL文を 991 * 作成します。 992 * where は、from が指定された場合のみ、有効ですし、where を指定しなければ、 993 * 全件検索になります。 994 * tableExist タグと異なるのは、where の指定の仕方で、tableExist タグでは、 995 * names 属性と、対応する where には、? で記述していましたが、 996 * dataCheck タグでは、通常の [] でDBTableModelの値を指定します。 997 * 998 * @og.rev 5.7.6.2 (2014/05/16) 新規追加 999 * 1000 * @param whr チェックするWHERE条件 1001 */ 1002 public void setWhere( final String whr ) { 1003 where = nval( getRequestParameter( whr ),where ); 1004 } 1005 1006 /** 1007 * 【TAG】エラーメッセージにSLABELを利用するかどうか[true/false]を指定します(初期値:false)。 1008 * 1009 * @og.tag 1010 * 通常のエラーメッセージは、ラベル(長)が使われますが、これをラベル(短)を使いたい場合に、true にセットします。 1011 * ここでのラベル(短)は、タグ修飾なしの、ラベル(短)です。 1012 * 標準はfalse:利用しない=ラベル(長)です。 1013 * true/false以外を指定した場合はfalse扱いとします。 1014 * 1015 * ラベルリソースの概要説明があれば表示しますが、useSLabel="true" 時は、概要説明を表示しません。 1016 * 1017 * @og.rev 7.0.7.0 (2019/12/13) 新規追加 1018 * 1019 * @param prm SLABEL利用 [true:利用する/false:利用しない] 1020 */ 1021 public void setUseSLabel( final String prm ) { 1022 useSLabel = nval( getRequestParameter( prm ),useSLabel ); 1023 } 1024 1025 /** 1026 * 指定の行番号の、カラムNo配列(int[])に対応した値の配列を返します。 1027 * 1028 * 表示データの HybsSystem.ROW_SEL_KEY を元に、選ばれた 行を 1029 * 処理の対象とします。 1030 * 1031 * @og.rev 4.2.0.1 (2008/03/27) row と clm を入れ替えます。(他とあわせます) 1032 * 1033 * @param row 行番号 1034 * @param clmNo カラムNo配列(可変長引数) 1035 * 1036 * @return 行番号とカラムNo配列に対応した、値の配列 1037 */ 1038 private String[] getTableModelData( final int row, final int... clmNo ) { 1039 String[] values = new String[clmNo.length]; 1040 for( int i=0; i<values.length; i++ ) { 1041 values[i] = table.getValue( row, clmNo[i] ); 1042 } 1043 return values; 1044 } 1045 1046 /** 1047 * エラーメッセージの前後に処理するJSPをインクルードします。 1048 * 1049 * @og.rev 5.1.9.0 (2010/08/01) 新規作成 1050 * 1051 * @param jsp JSP名 1052 */ 1053 private void includeJsp( final String jsp ) { 1054 try { 1055 pageContext.include( jsp, false ); 1056 } catch( final IOException ex ) { 1057 final String errMsg = jsp + " の include に失敗しました。 "; 1058 throw new HybsSystemException( errMsg,ex ); 1059 } catch( final ServletException ex ) { 1060 final String errMsg = jsp + " の include に失敗しました。 "; 1061 throw new HybsSystemException( errMsg,ex ); 1062 } 1063 } 1064 1065 /** 1066 * 表示データの HybsSystem.ROW_SEL_KEY を元に、選ばれた 行を処理の対象とします。 1067 * 1068 * @og.rev 5.1.9.0 (2010/08/01) 新規追加 1069 * 1070 * @return 選択行の配列 1071 * @og.rtnNotNull 1072 */ 1073 @Override 1074 protected int[] getParameterRows() { 1075 final int[] rowNo ; 1076 if( selectedAll ) { 1077 final int rowCnt = table.getRowCount(); 1078 rowNo = new int[ rowCnt ]; 1079 for( int i=0; i<rowCnt; i++ ) { 1080 rowNo[i] = i; 1081 } 1082 } else { 1083 rowNo = super.getParameterRows(); 1084 } 1085 return rowNo ; 1086 } 1087 1088 /** 1089 * ErrMessage を管理している メソッド集約型内部クラス 1090 * 1091 * 繰返し処理部と、固定部が混在したエラーメッセージで、固定部を先に処理し、 1092 * 繰返し部は、必要時に処理するようにしました。 1093 * また、実際にエラーが発生して必要になるまで、実行遅延させます。 1094 * 1095 * @og.rev 4.2.1.0 (2008/04/11) 新規追加 1096 * @og.rev 4.3.0.0 (2008/07/24) クラス宣言をstatic化 1097 */ 1098 private static final class ErrMessageManager { 1099 // 引数として初期設定される変数 1100 private ResourceManager resource; 1101 private DBTableModel table ; 1102 private String title ; 1103 private String from ; 1104 private String[] lblKeys ; 1105 private int[] clmNo ; 1106 1107 // 内部引数として処理されたキャッシュ値 1108 private ErrorMessage errMessage ; 1109 private String names ; 1110 private String fromLbl ; 1111 private String[] lblVals ; 1112 1113 private boolean isFirst = true; // 初期化されていない=true 1114 1115 /** 1116 * ErrMessage のタイトルを設定します。 1117 * 1118 * @param title タイトル 1119 */ 1120 public void setTitle( final String title ) { this.title = title; } 1121 1122 /** 1123 * 処理対象のテーブル名を設定します。 1124 * 1125 * @param from テーブル名 1126 */ 1127 public void setFrom( final String from ) { this.from = from; } 1128 1129 /** 1130 * 処理対象のテーブルオブジェクトを設定します。 1131 * 1132 * @param table DBTableModelオブジェクト 1133 */ 1134 public void setDBTableModel( final DBTableModel table ) { this.table = table; } 1135 1136 /** 1137 * ResourceManagerオブジェクトを設定します。 1138 * 1139 * @param resource ResourceManagerオブジェクト 1140 */ 1141 public void setResourceManager( final ResourceManager resource ) { this.resource = resource; } 1142 1143 /** 1144 * lblParamKeys 属性の配列を設定します。 1145 * 1146 * @param lblKeys 属性の配列(可変長引数) 1147 */ 1148 public void setParamKeys( final String... lblKeys ) { this.lblKeys = lblKeys; } 1149 1150 /** 1151 * カラム名列を設定します。 1152 * 1153 * @param clmNo カラム名配列(可変長引数) 1154 */ 1155 public void setClmNos( final int... clmNo ) { this.clmNo = clmNo ; } 1156 1157 /** 1158 * 初期処理を行います。 1159 * エラー処理は、エラー時のみ実行する為、必要のない場合は、処理が不要です。 1160 * 最初のエラー出力までは、内部オブジェクトの構築処理を行いません。 1161 * 2回目以降は、内部変数にキャッシュされた変換値を利用して、高速化します。 1162 * 1163 * @og.rev 4.2.3.2 (2008/06/20) from が、null なら、なにもしない。 1164 */ 1165 private void firstExecute() { 1166 errMessage = new ErrorMessage( title ); 1167 1168 // テーブル(from) をキーにラベルリソースから値を取得します。 1169 // 4.2.3.2 (2008/06/20) from が、null なら、なにもしない。 1170 if( from != null ) { 1171 fromLbl = resource.getLabel( from ); 1172 } 1173 1174 // カラム番号配列から、カラム名のラベルリソース情報のCSV文字列を作成します。 1175 names = getKeysLabel( clmNo ); 1176 1177 if( lblKeys != null && lblKeys.length > 0 ) { 1178 final int size = lblKeys.length; 1179 lblVals = new String[size] ; 1180 1181 for( int i=0; i<size; i++ ) { 1182 final String key = lblKeys[i] ; 1183 if( key != null ) { 1184 if( "@KEY".equals( key ) ) { lblVals[i] = names; } 1185 else if( "@TBL".equals( key ) ) { lblVals[i] = fromLbl;} 1186 else if( key.startsWith( "{#" ) && key.endsWith( "}" ) ) { 1187 lblVals[i] = resource.getLabel( key.substring( 2,key.length()-1 )); 1188 } 1189 else { 1190 lblVals[i] = key; 1191 } 1192 } 1193 } 1194 } 1195 } 1196 1197 /** 1198 * カラムNo配列(int[])に対応したカラム名のメッセージリソース文字列を返します。 1199 * 1200 * @param clmNo カラムNo配列(可変長引数) 1201 * @return カラムNo配列に対応した、カラム名のメッセージリソース 1202 * @og.rtnNotNull 1203 */ 1204 private String getKeysLabel( final int... clmNo ) { 1205 final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE ); 1206 if( table != null && clmNo.length > 0 ) { 1207 String key = table.getColumnName( clmNo[0] ); 1208 buf.append( resource.getLabel( key ) ); 1209 for( int i=1; i<clmNo.length; i++ ) { 1210 key = table.getColumnName( clmNo[i] ); 1211 buf.append( ',' ).append( resource.getLabel( key ) ); // 6.0.2.5 (2014/10/31) char を append する。 1212 } 1213 } 1214 1215 return buf.toString(); 1216 } 1217 1218 /** 1219 * カラム名列を設定します。 1220 * 1221 * @og.rev 4.3.5.7 (2008/03/22) エラーメッセージの行番号を実際の行番号と一致させる。 1222 * 1223 * @param row カラム名 1224 * @param id カラム名 1225 * @param values 指定の行に対する値配列(可変長引数) 1226 */ 1227 public void addMessage( final int row, final String id, final String... values ) { 1228 if( isFirst ) { firstExecute(); isFirst = false; } 1229 1230 final String vals = StringUtil.array2csv( values ); 1231 if( lblVals == null ) { 1232 errMessage.addMessage( row + 1, ErrorMessage.NG, id, names, vals, fromLbl ); 1233 } 1234 else { 1235 final int size = lblKeys.length; 1236 String[] args = new String[size] ; 1237 1238 for( int i=0; i<size; i++ ) { 1239 final String key = lblVals[i] ; 1240 if( key != null ) { 1241 if( "@VAL".equals( key ) ) { args[i] = vals; } 1242 else if( StringUtil.startsChar( key,'[' ) && key.endsWith( "]" ) ) { // 6.4.1.1 (2016/01/16) 1文字 String.startsWith 1243 if( table != null ) { 1244 args[i] = table.getValue( row,key.substring( 1,key.length()-1 ) ); 1245 } 1246 } 1247 else { 1248 args[i] = key; 1249 } 1250 } 1251 } 1252 errMessage.addMessage( row + 1, ErrorMessage.NG, id, args ); 1253 } 1254 } 1255 1256 /** 1257 * ErrorMessageオブジェクトを返します。 1258 * 1259 * @return ErrorMessageオブジェクト 1260 */ 1261 public ErrorMessage getErrMessage() { return errMessage; } 1262 } 1263 1264 /** 1265 * このオブジェクトの文字列表現を返します。 1266 * 基本的にデバッグ目的に使用します。 1267 * 1268 * @return このクラスの文字列表現 1269 * @og.rtnNotNull 1270 */ 1271 @Override 1272 public String toString() { 1273 return ToString.title(this.getClass().getName() ) 1274 .println( "VERSION", VERSION ) 1275 .println( "tableId", tableId ) 1276 .println( "dbid", dbid ) 1277 .println( "command", command ) 1278 .println( "exist", exist ) 1279 .println( "lbl", lbl ) 1280 .println( "Other...", getAttributes().getAttribute() ).fixForm().toString(); 1281 } 1282}