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 org.opengion.hayabusa.common.HybsSystem; 019import org.opengion.hayabusa.common.HybsSystemException; 020import org.opengion.hayabusa.db.DBTableModel; 021import org.opengion.fukurou.db.DBUtil; 022 023import org.opengion.fukurou.util.ErrorMessage; 024import org.opengion.fukurou.util.StringUtil ; 025import static org.opengion.fukurou.util.StringUtil.nval ; 026import org.opengion.fukurou.model.Formatter; 027 028import java.util.Locale ; 029import java.util.List ; 030import java.util.ArrayList ; 031 032import java.io.ObjectOutputStream; 033import java.io.ObjectInputStream; 034import java.io.IOException; 035 036/** 037 * 【廃止】登録すべきデータのマスタ存在チェックを行うためのタグです(通常はentry.jspでupdateタグの直前で使用します)。 038 * 039 * この要素の内容に、SQL文を記述します。 040 * names に対応するカラム名を、カンマ区切りで複数与えます。その値を、DBTableModel 041 * より、取得し、先のSQL文の ? に値を設定します。 042 * または、引数部に、[カラム名]を用いたHybs拡張SQL文を指定することも可能です。 043 * 044 * 値の取得は、先に選択された行のみについて、実行されます。 045 * exist 属性に指定された 、「true:存在する」、「false:存在しない」、「one:ひとつ以下」、 046 * の値は、チェック方法を設定しています。 047 * いずれの場合も、成立時は、正常とみなします。 048 * (「true:存在する」 には、データが存在した場合に、OKで、なければエラーです。) 049 * 050 * @og.formSample 051 * ●形式: 052 * ・<og:tableExist 053 * command = "{@command}" 054 * names = "[…]" 055 * from = "…" 必須 056 * where = "…" 必須 057 * exist = "[auto|true|false|one|notuse]" 必須 058 * errRemove = "[true|false]" 059 * /> 060 * 061 * ●body:なし 062 * 063 * ●Tag定義: 064 * <og:tableExist 065 * command 【廃止】コマンド(ENTRY)をセットします 066 * scope 【TAG】キャッシュする場合のスコープ[request/page/session/applicaton]を指定します(初期値:session) 067 * names 【廃止】引数にセットすべき データの名称(カラム名)をCSV形式で複数指定します 068 * from ○【廃止】チェックするデータベース名(from 句)を指定します(必須)。 069 * where ○【廃止】チェックする検索条件(where句)を指定します(必須)。 070 * exist 【廃止】データベースのチェック方法(auto/true/false/one/notuse)を指定します(初期値:「auto:自動」) 071 * tableId 【廃止】(通常は使いません)結果をDBTableModelに書き込んで、sessionに登録するときのキーを指定します 072 * dbid 【廃止】(通常は使いません)Queryオブジェクトを作成する時のDB接続IDを指定します 073 * errRemove 【廃止】エラー時の選択行を取り除いて継続処理を行うかどうか[true/false]を指定します(初期値:false) 074 * debug 【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false) 075 * /> 076 * 077 * ●使用例 078 * ・<og:tableExist 079 * command = "{@command}" 080 * names = "USERID,SYSTEM_ID" 081 * from = "GE10" 082 * where = "USERID=? AND SYSTEM_ID=?" 083 * exist = "true" /> 084 * 085 * ・where 条件の ? 文字に、names で指定したカラム名の値が、DBTableModelより 086 * 取得されます。 087 * 値の取得は、先に選択された行のみについて、実行されます。 088 * ・exist 属性の値に応じて、チェック方法が異なります。 089 * auto , true , false , one , notuse が指定できます。 090 * ・テーブルは、1つのみ指定できます。複数指定や、UNIONで結合する場合は、 091 * ビュー等を作成して対応してください。 092 * 093 * ・<og:tableExist 094 * command = "{@command}" 095 * from = "GE10" 096 * where = "USERID=[USERID] AND SYSTEM_ID=[SYSTEM_ID]" /> 097 * 098 * ・where 条件の [カラム名] 文字に、DBTableModelより値がセットされます。 099 * ・exist は、初期値(auto)になります。内部のA,C,Dに応じて自動判別します。 100 * 101 * @og.rev 3.5.0.0 (2003/09/17) 新規作成 102 * @og.group (廃止)DB登録 103 * 104 * @version 4.0 105 * @author Kazuhiko Hasegawa 106 * @since JDK5.0, 107 * @deprecated 代わりに dataCheckタグを使用してください 108 */ 109@Deprecated public class TableExistTag extends CommonTagSupport { 110 //* このプログラムのVERSION文字列を設定します。 {@value} */ 111 private static final String VERSION = "4.0.0.0 (2007/11/28)" ; 112 113 private static final long serialVersionUID = 400020071128L ; 114 115 /** command 引数に渡す事の出来る コマンド エントリー {@value} */ 116 public static final String CMD_ENTRY = "ENTRY" ; 117 118 /** command 引数に渡す事の出来る コマンド リスト */ 119 private static final String COMMAND_LIST = CMD_ENTRY; 120 121 // 3.5.6.0 (2004/06/18) すべてを protected から private に変更します。 122 private transient DBTableModel table = null; 123 private transient ErrorMessage errMessage = null; 124 private String tableId = HybsSystem.TBL_MDL_KEY; 125 // 4.0.0.0 (2007/10/10) dbid の初期値を、"DEFAULT" から null に変更 126// private String dbid = "DEFAULT"; 127 private String dbid = null; 128 private String command = CMD_ENTRY; 129 private String sql = null; 130 private String names = null; 131 private String from = null; 132 private String where = null; 133 private String exist = "auto"; 134 private boolean errRemove = false; 135 136 /** 137 * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。 138 * 139 * @og.rev 3.7.1.0 (2005/04/15) notuse 値を追加 140 * 141 * @return 後続処理の指示(SKIP_BODY) 142 */ 143 @Override 144 public int doStartTag() { 145 if( !exist.equalsIgnoreCase( "notuse" ) ) { 146 table = (DBTableModel)getObject( tableId ); 147 if( table != null && table.getRowCount() > 0 && check( command, COMMAND_LIST ) ) { 148 sql = makeSQLString(); 149 execute( sql ); 150 } 151 } 152 153 return(SKIP_BODY); // Body を評価しない 154 } 155 156 /** 157 * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。 158 * 159 * @og.rev 3.5.4.2 (2003/12/15) HTMLTableViewForm クラス名変更(⇒ ViewForm_HTMLTable) 160 * @og.rev 3.5.4.4 (2004/01/16) エラー結果を表示するテーブル形式のフォーム修正 161 * @og.rev 3.5.5.2 (2004/04/02) TaglibUtil.makeHTMLErrorTable メソッドを利用 162 * 163 * @return 後続処理の指示 164 */ 165 @Override 166 public int doEndTag() { 167 debugPrint(); // 4.0.0 (2005/02/28) 168 169 int rtnCode = EVAL_PAGE; 170 171 if( CMD_ENTRY.equals( command ) && errMessage != null && ! errMessage.isOK() ) { 172 // 3.5.5.2 (2004/04/02) TaglibUtil.makeHTMLErrorTable メソッドを利用 173 if( !errRemove ) { 174 rtnCode = SKIP_PAGE ; 175 jspPrint( TaglibUtil.makeHTMLErrorTable( errMessage,getResource() ) ); 176 } 177 } 178 179 return( rtnCode ); 180 } 181 182 /** 183 * タグリブオブジェクトをリリースします。 184 * キャッシュされて再利用されるので、フィールドの初期設定を行います。 185 * 186 * @og.rev 4.0.0.0 (2007/10/10) dbid の初期値を、"DEFAULT" から null に変更 187 */ 188 @Override 189 protected void release2() { 190 super.release2(); 191 tableId = HybsSystem.TBL_MDL_KEY; 192// dbid = "DEFAULT"; 193 dbid = null; 194 command = CMD_ENTRY; 195 table = null; 196 sql = null; 197 names = null; 198 errMessage = null; 199 exist = "auto"; 200 errRemove = false; 201 } 202 203 /** 204 * SQL文を構築します。 205 * 206 * @return 構築された、SQL文 207 */ 208 private String makeSQLString() { 209 StringBuilder rtn = new StringBuilder( HybsSystem.BUFFER_MIDDLE ); 210 rtn.append( "select count(*) from " ); 211 rtn.append( from ); 212 rtn.append( " where " ); 213 rtn.append( where ); 214 215 return rtn.toString(); 216 } 217 218 /** 219 * Query を実行します。 220 * 221 * @param sql 検索文字列 222 * 223 * @og.rev 3.8.6.0 (2006/09/29) exist 属性の one を 「one:ひとつのみ」から「one:ひとつ以下」に変更 224 * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為,ApplicationInfoオブジェクトを設定 225 * @og.rev 4.0.0.0 (2005/01/31) getParameterRows() を使用するように変更 226 * @og.rev 4.0.0.0 (2007/11/28) 論理処理の不具合修正(カッコの付ける位置間違い) 227 */ 228 private void execute( final String sql ) { 229 errMessage = new ErrorMessage( "Database Exist Data Error!" ); 230 231 final String query ; 232 final int[] clmNo ; 233 234 int[] rowNo = getParameterRows(); // 4.0.0 (2005/01/31) 235 if( rowNo.length == 0 ) { return; } 236 237 // names なしの場合は、Query より取得する。 4.0.0 (2005/01/31) 238 if( names == null ) { 239// QueryForm form = new QueryForm( sql,table ); 240// clmNo = form.getColumnNos(); 241// query = form.getStatement(); 242// names = StringUtil.array2csv( form.getColumnNames() ); 243 244 Formatter format = new Formatter( table ); 245 format.setFormat( sql ); 246 query = format.getQueryFormatString(); 247 clmNo = format.getClmNos(); 248 names = StringUtil.array2csv( table.getNames() ); 249 } 250 else { 251 clmNo = getTableColumnNo( StringUtil.csv2Array( names ) ); 252 query = sql; 253 } 254 255 int row; 256 boolean okFlag ; 257 List<Integer> list = new ArrayList<Integer>(); 258 String[] values ; 259 for( int j=0; j<rowNo.length; j++ ) { 260 okFlag = true; 261 row = rowNo[j]; 262 values = getTableModelData( clmNo,row ); 263 int cnt = DBUtil.dbExist( query,values,getApplicationInfo(),dbid ); 264 265 String modifyType = table.getModifyType( row ); 266 if( ( exist.equalsIgnoreCase( "true" ) || 267 ( exist.equalsIgnoreCase( "auto" ) && ( 268 DBTableModel.UPDATE_TYPE.equals( modifyType ) || 269 DBTableModel.DELETE_TYPE.equals( modifyType ) ) ) ) && cnt <= 0 ) { 270 // ERR0025=データ未登録エラー。キー={0}、値={1} のデータは、存在していません。 271 String vals = StringUtil.array2csv( values ); 272 errMessage.addMessage( row,ErrorMessage.NG,"ERR0025",names,vals ); 273 okFlag = false; 274 } 275 // 4.0.0.0 (2007/11/28) 論理処理の不具合修正(カッコの付ける位置間違い) 276 else if( ( exist.equalsIgnoreCase( "false" ) || 277 ( exist.equalsIgnoreCase( "auto" ) && 278 DBTableModel.INSERT_TYPE.equals( modifyType ) ) ) && cnt > 0 ) { 279 // ERR0026=データ登録済みエラー。キー={0}、値={1} のデータは、すでに存在しています。 280 String vals = StringUtil.array2csv( values ); 281 errMessage.addMessage( row,ErrorMessage.NG,"ERR0026",names,vals ); 282 okFlag = false; 283 } 284 else if( exist.equalsIgnoreCase( "one" ) && cnt > 1 ) { 285 // ERR0027=データ2重登録エラー。キー={0}、値={1} のデータは、重複して存在しています。 286 String vals = StringUtil.array2csv( values ); 287 errMessage.addMessage( row,ErrorMessage.NG,"ERR0027",names,vals ); 288 okFlag = false; 289 } 290 if( errRemove && okFlag ) { list.add( row ); } 291 } 292 if( errRemove ) { 293 Integer[] in = list.toArray( new Integer[list.size()] ); 294 int[] newRowNo = new int[in.length]; 295 for( int i=0; i<in.length; i++ ) { 296 newRowNo[i] = in[i].intValue(); 297 } 298 setParameterRows( newRowNo ); 299 } 300 } 301 302 /** 303 * 【廃止】(通常は使いません)結果をDBTableModelに書き込んで、sessionに登録するときのキーを指定します。 304 * 305 * @og.tag 306 * (初期値:HybsSystem#TBL_MDL_KEY[={@og.value org.opengion.hayabusa.common.HybsSystem#TBL_MDL_KEY}])。 307 * 308 * @param id sessionに登録する時の ID 309 * @deprecated クラスが廃止されました。 310 */ 311 @Deprecated public void setTableId( final String id ) { 312 tableId = nval( getRequestParameter( id ),tableId ); // 3.8.0.9 (2005/10/17) 313 } 314 315 /** 316 * 【廃止】(通常は使いません)Queryオブジェクトを作成する時のDB接続IDを指定します。 317 * 318 * @og.tag Queryオブジェクトを作成する時のDB接続IDを指定します。 319 * 320 * @param id データベース接続ID 321 * @deprecated クラスが廃止されました。 322 */ 323 @Deprecated public void setDbid( final String id ) { 324 dbid = nval( getRequestParameter( id ),dbid ); 325 } 326 327 /** 328 * 【廃止】コマンド(ENTRY)をセットします。 329 * 330 * @og.tag 331 * コマンドは,HTMLから(get/post)指定されますので,CMD_xxx で設定される 332 * フィールド定数値のいづれかを、指定できます。 333 * 334 * @param cmd コマンド(public static final 宣言されている文字列) 335 * @see <a href="../../../../constant-values.html#org.opengion.hayabusa.taglib.TableExistTag.CMD_NEW">コマンド定数</a> 336 * @deprecated クラスが廃止されました。 337 */ 338 @Deprecated public void setCommand( final String cmd ) { 339 String cmd2 = getRequestParameter( cmd ); 340 if( cmd2 != null && cmd2.length() > 0 ) { command = cmd2.toUpperCase(Locale.JAPAN); } 341 } 342 343 /** 344 * 【廃止】引数にセットすべき データの名称(カラム名)をCSV形式で複数指定します。 345 * 346 * @og.tag 347 * 複数ある場合は、カンマ区切り文字で渡します。 348 * 引数をnames ではなく、[カラム名]形式で直接指定するほうが、SQL文が判りやすくなります。 349 * 350 * @param nm 引数の名称(複数ある場合は、カンマ区切り文字) 351 * @deprecated クラスが廃止されました。 352 */ 353 @Deprecated public void setNames( final String nm ) { 354 names = nval( getRequestParameter( nm ),names ); 355 } 356 357 /** 358 * 【廃止】チェックするデータベース名(from 句)を指定します。 359 * 360 * @og.tag 361 * from 句 に指定するデータベース名です。 362 * 363 * @param fm データベースID 364 * @deprecated クラスが廃止されました。 365 */ 366 @Deprecated public void setFrom( final String fm ) { 367 from = nval( getRequestParameter( fm ),from ); 368 } 369 370 /** 371 * 【廃止】チェックする検索条件(where句)を指定します。 372 * 373 * @og.tag 374 * where 区 に指定する検索条件です。? の部分に、names 属性で指定した 375 * カラムのデータが、DBTableModelより取り出されて適用されます。 376 * または、[カラム名]形式で、直接指定することもできます。その場合は、 377 * name 属性は指定する必要がありません。 378 * [カラム名]の前後に、(')シングルコーテーションは、不要です。 379 * 380 * @param wr 検索条件(where句) 381 * @deprecated クラスが廃止されました。 382 */ 383 @Deprecated public void setWhere( final String wr ) { 384 where = nval( getRequestParameter( wr ),where ); 385 } 386 387 /** 388 * 【廃止】データベースのチェック方法(auto/true/false/one/notuse)を指定します(初期値:「auto:自動」)。 389 * 390 * @og.tag 391 * exist 属性に指定された 、「true:存在する」、「false:存在しない」、「one:ひとつ以下」、 392 * の値は、いずれの場合も、成立時は、正常とみなします。 393 * 「auto:自動」は、DBTableModeleのmodifyType(A,C,D)に応じて、チェックします。 394 * A,C,D は、entryタグにコマンドを渡してデータを作成したときに、内部で作成されます。 395 * notuse は、チェックを行いません。これは、このタグを共有使用する場合に、外部で 396 * チェックを行うかどうかを指定できるようにするために使用します。 397 * (「true:存在する」 には、データが存在した場合に、OKで、なければエラーです。) 398 * 初期値は、「auto:自動」です。 399 * 400 * @param ext チェック方法(「auto:自動」、「true:存在する」、「false:存在しない」、「one:ひとつ以下」、「notuse:チェックしない」) 401 * @deprecated クラスが廃止されました。 402 */ 403 @Deprecated public void setExist( final String ext ) { 404 exist = nval( getRequestParameter( ext ),exist ); 405 if( !"auto".equalsIgnoreCase( exist ) && 406 !"true".equalsIgnoreCase( exist ) && 407 !"false".equalsIgnoreCase( exist ) && 408 !"one".equalsIgnoreCase( exist ) && 409 !"notuse".equalsIgnoreCase( exist ) ) { 410 String errMsg = "exist 属性は、(auto,true,false,one,notuse)を指定してください。 [" + exist + "]" + HybsSystem.CR ; 411 throw new HybsSystemException( errMsg ); 412 } 413 } 414 415 /** 416 * 【廃止】エラー時の選択行を取り除いて継続処理を行うかどうか[true/false]を指定します(初期値:false)。 417 * 418 * @og.tag 419 * exist 属性に指定された 、「true:存在する」、「false:存在しない」、「one:ひとつ以下」、 420 * に対して、エラーが発生した選択行番号を、取り除いて以下の処理を継続するかどうかを 421 * 指定します。 422 * true に設定した場合は、エラーデータを削除し、継続処理を行うことができます。 423 * flase の場合は、エラーデータを表示して、継続処理を停止します。 424 * 初期値は、「false:エラー時停止」です。 425 * 426 * @param flag エラー時の継続処理 [true:エラー行番号を取り除き継続処理/false:エラー時停止] 427 * @deprecated クラスが廃止されました。 428 */ 429 @Deprecated public void setErrRemove( final String flag ) { 430 errRemove = nval( getRequestParameter( flag ),errRemove ); 431 } 432 433 /** 434 * カラム名配列(String[])より、対応するカラムNo配列(int[])を作成します。 435 * 436 * @param nameArray カラム名配列 437 * 438 * @return カラムNo配列 439 */ 440 private int[] getTableColumnNo( final String[] nameArray ) { 441 int[] clmNo = new int[ nameArray.length ]; 442 for( int i=0; i<clmNo.length; i++ ) { 443 clmNo[i] = table.getColumnNo( nameArray[i] ); 444 } 445 return clmNo; 446 } 447 448 /** 449 * 指定の行番号の、カラムNo配列(int[])に対応した値の配列を返します。 450 * 451 * 表示データの HybsSystem.ROW_SEL_KEY を元に、選ばれた 行を 452 * 処理の対象とします。 453 * 454 * @param clmNo カラムNo配列 455 * @param row 行番号 456 * 457 * @return 行番号とカラムNo配列に対応した、値の配列 458 */ 459 private String[] getTableModelData( final int[] clmNo,final int row ) { 460 String[] values = new String[ clmNo.length ]; 461 for( int i=0; i<values.length; i++ ) { 462 values[i] = table.getValue( row,clmNo[i] ) ; 463 } 464 return values; 465 } 466 467 /** 468 * シリアライズ用のカスタムシリアライズ書き込みメソッド 469 * 470 * @og.rev 4.0.0.0 (2006/09/31) 新規追加 471 * @serialData 一部のオブジェクトは、シリアライズされません。 472 * 473 * @param strm ObjectOutputStreamオブジェクト 474 * @throws IOException 入出力エラーが発生した場合 475 */ 476 private void writeObject( final ObjectOutputStream strm ) throws IOException { 477 strm.defaultWriteObject(); 478 } 479 480 /** 481 * シリアライズ用のカスタムシリアライズ読み込みメソッド 482 * 483 * ここでは、transient 宣言された内部変数の内、初期化が必要なフィールドのみ設定します。 484 * 485 * @og.rev 4.0.0.0 (2006/09/31) 新規追加 486 * @serialData 一部のオブジェクトは、シリアライズされません。 487 * 488 * @param strm ObjectInputStreamオブジェクト 489 * @see #release2() 490 * @throws IOException シリアライズに関する入出力エラーが発生した場合 491 * @throws ClassNotFoundException クラスを見つけることができなかった場合 492 */ 493 private void readObject( final ObjectInputStream strm ) throws IOException , ClassNotFoundException { 494 strm.defaultReadObject(); 495 } 496 497 /** 498 * このオブジェクトの文字列表現を返します。 499 * 基本的にデバッグ目的に使用します。 500 * 501 * @return このクラスの文字列表現 502 */ 503 @Override 504 public String toString() { 505 return org.opengion.fukurou.util.ToString.title( this.getClass().getName() ) 506 .println( "VERSION" ,VERSION ) 507 .println( "tableId" ,tableId ) 508 .println( "dbid" ,dbid ) 509 .println( "command" ,command ) 510 .println( "sql" ,sql ) 511 .println( "names" ,names ) 512 .println( "from" ,from ) 513 .println( "where" ,where ) 514 .println( "exist" ,exist ) 515 .println( "CMD_ENTRY" ,CMD_ENTRY ) 516 .println( "Other..." ,getAttributes().getAttribute() ) 517 .fixForm().toString() ; 518 } 519}