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