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.db; 017 018import java.util.HashMap; 019import java.util.HashSet; 020import java.util.Map; 021import java.util.Set; 022 023import org.opengion.fukurou.util.StringUtil; 024 025/** 026 * エディット設定情報を管理するためのデータ管理クラスです。 027 * ここで管理される各パラメーターの意味は以下の通りです。 028 * (各インデックス番号は、内部的に管理されているインデックス番号を意味します) 029 * 030 * ・0:エディット名 031 * このエディット設定オブジェクトの名称です。 032 * ・1:表示カラム 033 * 表示対象となるカラム一覧です。カンマ区切りで指定します。 034 * この一覧には、非表示のカラムも合わせて管理され、非表示カラムについては、 035 * カラム名の先頭に"!"をつけます。 036 * 例) AAA,!BBB,CCC ⇒ AAA,CCCの順に表示(BBBは非表示) 037 * ・2:集計カラム 038 * 各値をSUMする対象となるカラムです。(カンマ区切りで複数指定が可能) 039 * ここで指定されたカラムは数値型である必要があります。 040 * SQL構文における、SUM関数の引数として指定するカラムに相当します。 041 * ・3:グループカラム 042 * 集計カラムの各値をグルーピングするためのカラムです。(カンマ区切りで複数指定が可能) 043 * SQL構文における、GROUP BYに指定するカラムに相当します。 044 * ・4:小計カラム 045 * 集計カラムの各値に対し、小計行を付加するためのブレイクキーを指定します。(カンマ区切りで複数指定が可能) 046 * ・5:合計カラム 047 * 集計カラムの各値に対し、合計行を付加するためのブレイクキーを指定します。(カンマ区切りで複数指定が可能) 048 * ・6:総合計フラグ 049 * 集計カラムの各値に対し、総合計行を付加するかどうかを指定します。(0以外:追加する 0:追加しない) 050 * ・7:表示順カラム 051 * データの表示順をその順番にカンマ区切りで指定します。 052 * カラム名の先頭に"!"をつけた場合は、そのカラムは降順で表示されます。 053 * SQL構文における、orderby句に相当します。 054 * ・8:共通フラグ 055 * このエディット設定オブジェクトが、共通(全ユーザー公開)エディットかどうかを 056 * 指定します。(0以外:共通 0:個人のみ) 057 * 058 * @og.rev 5.3.6.0 (2011/06/01) 新規追加 059 * 060 * @version 5.0 061 * @author Hiroki Nakamura 062 * @since JDK6.0, 063 */ 064public class DBEditConfig { 065 066 private static final int EDIT_KEY_NAME = 0; 067 private static final int EDIT_KEY_VIEW = 1; 068 private static final int EDIT_KEY_SUM = 2; 069 private static final int EDIT_KEY_GROUP = 3; 070 private static final int EDIT_KEY_SUBTOTAL = 4; 071 private static final int EDIT_KEY_TOTAL = 5; 072 private static final int EDIT_KEY_GRANDTOTAL= 6; 073 private static final int EDIT_KEY_ORDERBY = 7; 074 private static final int EDIT_KEY_COMMON = 8; 075 076 private static final String[] EDIT_KEYS 077 = { "NAME", "VIEW", "SUM", "GROUP", "SUBTOTAL", "TOTAL", "GRANDTOTAL", "ORDERBY", "COMMON" }; 078 079 private static final int EDIT_KEYS_LENGTH = EDIT_KEYS.length; 080 081 private final String[] editVals = new String[EDIT_KEYS_LENGTH]; 082 083 private int sumClmCount; 084 private int groupClmCount; 085 private int subTotalClmCount; 086 private int totalClmCount; 087 private final Map<String,String> orderMap = new HashMap<String,String>(); 088 private String orderByDescClms; 089 090 /** 091 * コンストラクタ 092 * 093 * 空のエディット設定オブジェクトを構築します。 094 */ 095 public DBEditConfig() { 096 } 097 098 /** 099 * コンストラクタ 100 * 101 * 各種パラメーターを指定してエディット設定オブジェクトを構築します。 102 * 103 * @param editName エディット名称 104 * @param viewClms 画面表示カラム 105 * @param sumClms 集計カラム 106 * @param groupClms グループカラム 107 * @param subTotalClms 小計カラム 108 * @param totalClms 合計カラム 109 * @param useGrandTotal 総合計行を追加するか(1:追加する 1以外:追加しない) 110 * @param orderByClms 表示順 111 * @param isCommon 共通エディットかどうか(1:共通 1以外:個人のみ) 112 */ 113 public DBEditConfig( final String editName, final String viewClms 114 , final String sumClms, final String groupClms 115 , final String subTotalClms, final String totalClms 116 , final String useGrandTotal, final String orderByClms 117 , final String isCommon ) { 118 119 editVals[EDIT_KEY_NAME] = editName; 120 editVals[EDIT_KEY_VIEW] = viewClms; 121 editVals[EDIT_KEY_SUM] = sumClms; 122 editVals[EDIT_KEY_GROUP] = groupClms; 123 editVals[EDIT_KEY_SUBTOTAL] = subTotalClms; 124 editVals[EDIT_KEY_TOTAL] = totalClms; 125 editVals[EDIT_KEY_GRANDTOTAL] = useGrandTotal; 126 editVals[EDIT_KEY_ORDERBY] = orderByClms; 127 editVals[EDIT_KEY_COMMON] = isCommon; 128 129 init(); 130 } 131 132 /** 133 * コンストラクタ 134 * 135 * 各種パラメーターを配列で指定してエディット設定オブジェクトを構築します。 136 * 各パラメータの配列インデックスは、{@link #getEditKeys(String,String)}で返される 137 * キー一覧の配列インデックスと一致します。 138 * 各パラメーターの意味については、クラスのJavadoc{@link DBEditConfig}を参照して下さい。 139 * 140 * @param editVals 設定値(配列) 141 * @see DBEditConfig 142 * @see #getEditKeys(String,String) 143 **/ 144 public DBEditConfig( final String[] editVals ) { 145 System.arraycopy( editVals, 0, this.editVals, 0, editVals.length ); 146 init(); 147 } 148 149 /** 150 * エディット設定オブジェクト作成時の初期化処理です。 151 * コンストラクタの引数に基づき内部変数の初期設定を行います。 152 */ 153 private void init() { 154 sumClmCount = StringUtil.csv2Array( editVals[EDIT_KEY_SUM] ).length; 155 groupClmCount = StringUtil.csv2Array( editVals[EDIT_KEY_GROUP] ).length; 156 subTotalClmCount = StringUtil.csv2Array( editVals[EDIT_KEY_SUBTOTAL] ).length; 157 totalClmCount = StringUtil.csv2Array( editVals[EDIT_KEY_TOTAL] ).length; 158 159 if( editVals[EDIT_KEY_ORDERBY] != null ) { 160 StringBuilder buf = new StringBuilder(); 161 String[] ary = StringUtil.csv2Array( editVals[EDIT_KEY_ORDERBY] ); 162 for( int i=0; i<ary.length ;i++ ) { 163 String str = ary[i]; 164 if( str.startsWith( "!" ) ) { 165 str = str.substring( 1 ); 166 if( buf.length() > 0 ) { buf.append( "," ); } 167 buf.append( str ); 168 } 169 orderMap.put( str, String.valueOf( i+1 ) ); 170 } 171 orderByDescClms = buf.toString(); 172 } 173 else { 174 orderByDescClms = null; 175 } 176 } 177 178 /** 179 * キー配列から画面IDとエディット名称のペアの一覧を取り出します。 180 * 181 * キー配列から"EDIT_NAME_"で始まるキーを検索し、"EDIT_NAME_(画面ID)_(エディット名)" 182 * と言う形式に基づき、画面IDとエディット名称のペアを取り出します。 183 * 184 * 画面IDとエディット名称は配列として保存され(インデックス番号は 0:画面ID、1:エディット名) 185 * その一覧がされらに配列に格納されて返されます。 186 * 187 * @param keys キー配列 188 * 189 * @return 画面IDとエディット名称のペアの一覧 190 */ 191 public static String[][] getKeySet( final String[] keys ) { 192 if( keys == null || keys.length == 0 ) { return null; } 193 194 Set<String[]> keySet = new HashSet<String[]>(); 195 for( String key : keys ) { 196 if ( key != null && key.startsWith( "EDIT_NAME_" ) ) { 197 String guikeyEditName = key.substring( ( "EDIT_NAME_" ).length() ); 198 if( guikeyEditName.indexOf( '_' ) >= 0 ) { 199 String guikey = guikeyEditName.substring( 0, guikeyEditName.indexOf( '_' ) ); 200 String editName = guikeyEditName.substring( ( guikey + "_" ).length() ); 201 if( guikey != null && guikey.length() > 0 && editName != null && editName.length() > 0 ) { 202 String[] set = { guikey, editName }; 203 keySet.add( set ); 204 } 205 } 206 } 207 } 208// return keySet.toArray( new String[0][] ); 209 return keySet.toArray( new String[keySet.size()][] ); 210 } 211 212 /** 213 * 画面ID、エディット名をキーに、エディット設定オブジェクトの各設定値の 214 * 管理キーを指定します。 215 * 216 * エディット設定オブジェクトで管理される各キーに対して、 217 * "EDIT_[KEY]_(画面ID)_(エディット名)"というキーを生成し、これを配列にして返します。 218 * 219 * @param guikey 画面ID 220 * @param editName エディット名 221 * 222 * @return エディット設定を管理するためのキー一覧 223 */ 224 public static String[] getEditKeys( final String guikey, final String editName ) { 225 String[] rtn = new String[EDIT_KEYS_LENGTH]; 226 for( int i=0; i<EDIT_KEYS_LENGTH; i++ ) { 227 rtn[i] = "EDIT_" + EDIT_KEYS[i] + "_" + guikey + "_" + editName; 228 } 229 return rtn; 230 } 231 232 /** 233 * エディット設定オブジェクトの各設定値を配列にして返します。 234 * 235 * 配列のインデックス番号は、{@link #getEditKeys(String,String)}で生成されるキーの 236 * インデックス番号と一致します。 237 * 238 * @return エディット設定オブジェクトの設定値一覧(配列) 239 * @see #getEditKeys(String,String) 240 */ 241 public String[] getEditVals() { 242 String[] rtn = new String[editVals.length]; 243 System.arraycopy( editVals, 0, rtn, 0, editVals.length ); 244 return rtn; 245 } 246 247 /** 248 * エディット名を返します。 249 * 250 * @return エディット名 251 */ 252 public String getEditName() { 253 return editVals[EDIT_KEY_NAME]; 254 } 255 256 /** 257 * 表示カラム名の一覧をカンマ区切りで返します。 258 * 非表示カラムについては、カラム名の先頭に"!"をつけて返されます。 259 * 例) AAA,!BBB,CCC ⇒ AAA,CCCの順に表示(BBBは非表示) 260 * 261 * @return 表示カラム名一覧(カンマ区切り) 262 */ 263 public String getViewClms() { 264 return editVals[EDIT_KEY_VIEW]; 265 } 266 267 /** 268 * 表示カラム(CSV形式)をチェックし、変更があれば、反映したカラムを作成します。 269 * 270 * 表示カラムは、並び順や非表示マーカー(!)などが加味され、ユーザー、画面ごとに 271 * データベースに記録されています。JSPソースを修正した場合、データベースに 272 * 書き込まれた表示カラムは、反映されないため、カラム選択画面等に表示されません。 273 * そこで、オリジナルのカラムに追加された場合は、カラムを比較することで、 274 * 追加分のカラムを、非表示カラムとして、後ろに追記します。 275 * 削除された場合は、ViewForm で警告表示することで、ユーザーに変更を促します。 276 * 277 * @og.rev 5.8.2.0 (2014/12/05) JSP修正時の追加カラム対応 278 * 279 * @param orgClms オリジナルのカラム(CSV形式) 280 * 281 * @return 変更後の表示カラム(CSV形式) 282 */ 283 public String getViewClms( final String orgClms ) { 284 String viewClms = editVals[EDIT_KEY_VIEW]; 285 286 if( orgClms == null || orgClms.isEmpty() ) { return viewClms; } // orgClms がなければ、viewClms を返す。 287 // 基本的には、両者のカラムは、一致するはず。 288 String[] vclms = viewClms.split( "," ); // 表示順、非表示処理を行ったカラム 289 String[] fclms = orgClms.split( "," ); // 元々の表示可能カラムすべて(fullClms) 290 291 // 表示可能カラムすべての Set を作成します。 292 Set<String> fset = new HashSet<String>(); 293 for( int i=0; i<fclms.length; i++ ) { // orgClms をSet に追加します。 294 fset.add( fclms[i] ); 295 } 296 297 // 非表示カラムの内、表示可能カラムに存在しない分だけの Set を作成します。 298 // また、表示可能カラムから、順番に、viewClms の値を削除していきます。 299 Set<String> vset = new HashSet<String>(); 300 StringBuilder vbuf = new StringBuilder(); // 新しい viewClms 作成用 301 for( int i=0; i<vclms.length; i++ ) { // viewClms をSet に追加します。 302 String clm = vclms[i]; 303 if( clm == null || clm.isEmpty() ) { continue; } // 6.0.2.5 (2014/10/31) 潜在バグ? 先頭に"," が来るとアベンドする。 304 clm = clm.charAt(0) == '!' ? clm.substring(1) : clm ; // 非表示の (!) は削除します。 305 if( fset.remove( clm ) ) { // fullSet にあれば、削除するとともに、新viewClmsを作成する。 306 if( vbuf.length() > 0 ) { vbuf.append(','); } // 最初以降は、カンマで連結する。 // 6.0.2.5 (2014/10/31) char を append する。 307 vbuf.append( vclms[i] ); // append するのは、(!) 付のカラム 308 } 309 else { 310 vset.add( clm ); // fullSet になければ、viewSet に追加 311 } 312 } 313 314 // この段階で、fset、vset ともに、それぞれ独自のカラムが残っている。 315 // どちらも、残っていなければ、正常なので、viewClms を返す。 316 if( vset.isEmpty() && fset.isEmpty() ) { return viewClms; } 317 318 // fullSet にカラムが残っていれば、非表示で、新viewClmsに、追加する。 319 if( !fset.isEmpty() ) { 320 String[] defClms = fset.toArray( new String[fset.size()] ); 321 for( int i=0; i<defClms.length; i++ ) { 322 if( vbuf.length() > 0 ) { vbuf.append(','); } // 6.0.2.5 (2014/10/31) 最初以降は、カンマで連結する。 323 vbuf.append('!').append( defClms[i] ); // 非表示カラムとして、後ろに追加する。 324 } 325 } 326 viewClms = vbuf.toString(); 327 328 editVals[EDIT_KEY_VIEW] = viewClms; 329 return viewClms; 330 } 331 332 /** 333 * 集計カラムの一覧をカンマ区切りで返します。 334 * 335 * @return 集計カラムの一覧(カンマ区切) 336 */ 337 public String getSumClms() { 338 return editVals[EDIT_KEY_SUM]; 339 } 340 341 /** 342 * 集計処理を行うかどうかを返します。 343 * これは、集計カラムが指定されているか、と同じ意味です。 344 * 345 * @return true:対象 false:非対象 346 */ 347 public boolean useSum() { 348 return ( editVals[EDIT_KEY_SUM] != null && editVals[EDIT_KEY_SUM].length() > 0 ); 349 } 350 351 /** 352 * 指定されたカラムが集計対象のカラムかどうかを返します。 353 * 354 * @param clm カラム 355 * 356 * @return true:対象 false:非対象 357 */ 358 public boolean isSumClm( final String clm ) { 359 if( clm == null || editVals[EDIT_KEY_SUM] == null ) { return false; } 360 return ( ( ","+editVals[EDIT_KEY_SUM]+"," ).indexOf( ","+clm+"," ) >= 0 ); 361 } 362 363 /** 364 * 集計カラムのカラム数を返します。 365 * 366 * @return 集計カラムのカラム数 367 */ 368 public int getSumClmCount() { 369 return sumClmCount; 370 } 371 372 /** 373 * グループカラムの一覧をカンマ区切りで返します。 374 * 375 * @return グループカラムの一覧(カンマ区切) 376 */ 377 public String getGroupClms() { 378 return editVals[EDIT_KEY_GROUP]; 379 } 380 381 /** 382 * グループ処理を行うかどうかを返します。 383 * これは、グループカラムが指定されているか、と同じ意味です。 384 * 385 * @return true:対象 false:非対象 386 */ 387 public boolean useGroup() { 388 return ( editVals[EDIT_KEY_GROUP] != null && editVals[EDIT_KEY_GROUP].length() > 0 ); 389 } 390 391 /** 392 * 指定されたカラムがグループ対象のカラムかどうかを返します。 393 * 394 * @param clm カラム 395 * 396 * @return true:対象 false:非対象 397 */ 398 public boolean isGroupClm( final String clm ) { 399 if( clm == null || editVals[EDIT_KEY_GROUP] == null ) { return false; } 400 return ( ( ","+editVals[EDIT_KEY_GROUP]+"," ).indexOf( ","+clm+"," ) >= 0 ); 401 } 402 403 /** 404 * グループカラムのカラム数を返します。 405 * 406 * @return グループカラムのカラム数 407 */ 408 public int getGroupClmCount() { 409 return groupClmCount; 410 } 411 412 /** 413 * 小計カラムの一覧をカンマ区切りで返します。 414 * 415 * @return 小計カラムの一覧(カンマ区切) 416 */ 417 public String getSubTotalClms() { 418 return editVals[EDIT_KEY_SUBTOTAL]; 419 } 420 421 /** 422 * 小計処理を行うかどうかを返します。 423 * これは、小計カラムが指定されているか、と同じ意味です。 424 * 425 * @return true:対象 false:非対象 426 */ 427 public boolean useSubTotal() { 428 return ( editVals[EDIT_KEY_SUBTOTAL] != null && editVals[EDIT_KEY_SUBTOTAL].length() > 0 ); 429 } 430 431 /** 432 * 指定されたカラムが小計対象のカラムかどうかを返します。 433 * 434 * @param clm カラム 435 * 436 * @return true:対象 false:非対象 437 */ 438 public boolean isSubTotalClm( final String clm ) { 439 if( clm == null || editVals[EDIT_KEY_SUBTOTAL] == null ) { return false; } 440 return ( ( ","+editVals[EDIT_KEY_SUBTOTAL]+"," ).indexOf( ","+clm+"," ) >= 0 ); 441 } 442 443 /** 444 * 小計カラムのカラム数を返します。 445 * 446 * @return グループカラムのカラム数 447 */ 448 public int getSubTotalClmCount() { 449 return subTotalClmCount; 450 } 451 452 /** 453 * 合計カラムの一覧をカンマ区切りで返します。 454 * 455 * @return 合計カラムの一覧(カンマ区切) 456 */ 457 public String getTotalClms() { 458 return editVals[EDIT_KEY_TOTAL]; 459 } 460 461 /** 462 * 合計処理を行うかどうかを返します。 463 * これは、合計カラムが指定されているか、と同じ意味です。 464 * 465 * @return true:対象 false:非対象 466 */ 467 public boolean useTotal() { 468 return ( editVals[EDIT_KEY_TOTAL] != null && editVals[EDIT_KEY_TOTAL].length() > 0 ); 469 } 470 471 /** 472 * 指定されたカラムが合計対象のカラムかどうかを返します。 473 * 474 * @param clm カラム 475 * 476 * @return true:対象 false:非対象 477 */ 478 public boolean isTotalClm( final String clm ) { 479 if( clm == null || editVals[EDIT_KEY_TOTAL] == null ) { return false; } 480 return ( ( ","+editVals[EDIT_KEY_TOTAL]+"," ).indexOf( ","+clm+"," ) >= 0 ); 481 } 482 483 /** 484 * 合計カラムのカラム数を返します。 485 * 486 * @return グループカラムのカラム数 487 */ 488 public int getTotalClmCount() { 489 return totalClmCount; 490 } 491 492 /** 493 * 総合計行を付加するかどうかを返します。 494 * 495 * @return true:対象 false:非対象 496 */ 497 public boolean useGrandTotal() { 498 return StringUtil.nval( editVals[EDIT_KEY_GRANDTOTAL], false ); 499 } 500 501 /** 502 * 表示順カラムをカンマ区切りで返します。 503 * カラムの並び順が表示順としての優先順になります。 504 * また、降順で表示するカラムについては、カラム名の先頭に"!"が付加されます。 505 * 506 * @return 標準順カラムの一覧(カンマ区切) 507 */ 508 public String getOrderByClms() { 509 return editVals[EDIT_KEY_ORDERBY]; 510 } 511 512 /** 513 * 指定されたカラムの表示順の優先番号を返します。 514 * 指定カラムが標準として指定されていない場合は、""(ゼロストリング)を返します。 515 * 516 * @param clm カラム 517 * 518 * @return 表示順の優先番号 519 */ 520 public String getOrder( final String clm ) { 521 if( clm == null || editVals[EDIT_KEY_ORDERBY] == null ) { return ""; } 522 523 String rtn = orderMap.get( clm ); 524 return ( rtn == null ? "" : rtn ); 525 } 526 527 /** 528 * 指定されたカラムの表示順指定が降順であるかどうかを返します。 529 * 標準と指定されていない場合は、falseを返します。 530 * 531 * @param clm カラム 532 * 533 * @return true:降順 false:昇順 534 */ 535 public boolean isOrderByDesc( final String clm ) { 536 if( clm == null || orderByDescClms == null ) { return false; } 537 return ( ( ","+orderByDescClms+"," ).indexOf( ","+clm+"," ) >= 0 ); 538 } 539 540 /** 541 * 並び替え処理を行うかどうかを返します。 542 * これは、表示順カラムが指定されているか、と同じ意味です。 543 * 544 * @return true:対象 false:非対象 545 */ 546 public boolean useOrderBy() { 547 return ( editVals[EDIT_KEY_ORDERBY] != null && editVals[EDIT_KEY_ORDERBY].length() > 0 ); 548 } 549 550 /** 551 * このエディット設定オブジェクトが、共通(全ユーザー公開)エディットか 552 * どうかを返します。 553 * 554 * @return 0以外:共通 0:個人のみ 555 */ 556 public boolean isCommon() { 557 return StringUtil.nval( editVals[EDIT_KEY_COMMON], false ); 558 } 559}