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.plugin.view; 017 018import org.opengion.hayabusa.common.HybsSystem; 019import org.opengion.hayabusa.common.HybsSystemException; 020import org.opengion.hayabusa.db.DBTableModel; 021import org.opengion.fukurou.util.StringUtil; 022import org.opengion.hayabusa.html.TableFormatter; 023import org.opengion.hayabusa.html.ViewStackTableParam; 024 025import java.util.Calendar; 026import java.util.Date; 027import java.util.List; 028 029/** 030 * 積上ガント表示専用のViewFormです。 031 * stackParamTagを利用する事でスタックガント用の行を出力する事が可能です。 032 * stackParamTagによりstackColumnsが指定された場合は、そのカラム毎にブレークして、 033 * stacklink属性により積上げ行の判別が可能なtbody行を出力します。 034 * その際、stackColumnsで指定されたカラム以外の[xxx]は処理されません(空白として出力) 035 * [xxx]以外で書かれた箇所、例えば<iGantBar>タグの本体部分等は出力されます。 036 * 037 * ヘッダの表示にはstackHeaderタグを利用します。 038 * 039 * [エンジン内部積上げを行わない場合] 040 * 積上の表示はJavaScriptによってiGantBarタグの箇所に作成されます。 041 * 積上げそのものもiGantBarによって出力されるガントを利用してJavaScriptで行っているため、 042 * 最大検索行数と表示行数に注意して下さい。 043 * 044 * [エンジン内部積上げを行う場合] 045 * 工数積上げをエンジン内部で行いdivタグとして出力します。 046 * その後の描画(位置調整や色等)はJavaScriptで行います。 047 * ガント部分は出力されません。 048 * スタック部分はbody部分の最後尾に新たにtd作成するため、注意してください。 049 * paramタグでの指定で、costColumnが必須です。 050 * 051 * 052 * AbstractViewForm により、setter/getterメソッドのデフォルト実装を提供しています。 053 * 各HTMLのタグに必要な setter/getterメソッドのみ,追加定義しています。 054 * 055 * AbstractViewForm を継承している為,ロケールに応じたラベルを出力させる事が出来ます。 056 * 057 * @og.rev 5.5.7.0 (2012/10/01) 新規作成 058 * @og.rev 5.5.8.3 (2012/11/17) 内部積上げ対応 059 * @og.rev 5.6.1.2 (2013/02/22) キャパシティ対応 060 * @og.group 画面表示 061 * 062 * @version 5.0 063 * @author Takahashi Masakazu 064 * @since JDK5.0, 065 */ 066public class ViewForm_HTMLStackedGanttTable extends ViewForm_HTMLTable { 067 //* このプログラムのVERSION文字列を設定します。 {@value} */ 068 private static final String VERSION = "5.6.2.1 (2013/06/13)" ; 069 070 /** ヘッダーフォーマット変数 */ 071 protected TableFormatter headerFormat = null; 072 /** ボディーフォーマット配列変数 */ 073 protected TableFormatter[] bodyFormats = null; 074 /** フッターフォーマット変数 */ 075 protected TableFormatter footerFormat = null; 076 /** ボディーフォーマット数 */ 077 protected int bodyFormatsCount = 0; 078 079 /** ボディーフォーマット最大数 初期値:{@value} */ 080 protected static final int BODYFORMAT_MAX_COUNT = 10; 081 // stack行の判定出力用 082 protected static final String STACK_TBODY = " stackline='true'"; 083 protected static final String GANTT_TBODY = " stackline='false'"; 084 protected static final String STACK_ID_PREFIX = " id='stack_"; 085 protected static final String STACK_ROW_PREFIX = " stackrow='"; 086 087 // stack,gantt用 088 private int[] stackCols = null; 089 090 // 5.5.8.3 (2012/11/17) 091 private int[] costCols = null; // 工数カラム、開始日カラム、終了日カラム 092 private boolean innerStack = Boolean.parseBoolean( ViewStackTableParam.INNER_STACK_VALUE ); 093 private boolean stackHoliday = Boolean.parseBoolean( ViewStackTableParam.STACK_HOLIDAY_KEY ); 094 String[][] calArray = null; // headで作成されたカレンダーデータ 095 int capCol = -1; // 5.6.1.2 (2013/02/22) 能力値カラム 096 097 /** 098 * DBTableModel から HTML文字列を作成して返します。 099 * startNo(表示開始位置)から、pageSize(表示件数)までのView文字列を作成します。 100 * 表示残りデータが pageSize 以下の場合は,残りのデータをすべて出力します。 101 * 102 * 103 * @og.rev 5.5.8.3 (2012/11/17) 内部積上げ対応 104 * @og.rev 5.6.1.2 (2013/02/22) キャパシティ対応 105 * @og.rev 5.6.2.1 (2013/06/13) 積上不具合修正 106 * 107 * @param sttNo 表示開始位置 108 * @param pgSize 表示件数 109 * 110 * @return DBTableModelから作成された HTML文字列 111 */ 112 @Override 113 public String create( final int sttNo, final int pgSize ) { 114 // ガントは、キーブレイクがあるため、全件表示します。 115 int startNo = 0; 116 int pageSize = getRowCount() ; 117 if( pageSize == 0 ) { return ""; } // 暫定処置 118 119 // 4.3.1.0 (2008/09/08) 120 if( headerFormat == null ) { 121 String errMsg = "ViewTagで canUseFormat() = true の場合、Formatter は必須です。"; 122 throw new HybsSystemException( errMsg ); 123 } 124 125 headerLine = null; // 3.5.3.1 (2003/10/31) キャッシュクリア 126 127 int lastNo = getLastNo( startNo, pageSize ); 128 int blc = getBackLinkCount(); 129 int hsc = getHeaderSkipCount(); 130 int hscCnt = 1; 131 132 // このビューの特有な属性を初期化 133 paramInit(); 134 135 StringBuilder out = new StringBuilder( HybsSystem.BUFFER_LARGE ); 136 137 headerFormat.makeFormat( getDBTableModel() ); // 3.5.6.2 (2004/07/05) 移動 138 139 out.append( getCountForm( startNo,pageSize ) ); 140 out.append( getHeader() ); 141 142 if( bodyFormatsCount == 0 ) { 143 bodyFormats[0] = headerFormat ; 144 bodyFormatsCount ++ ; 145 } 146 else { 147 for( int i=0; i<bodyFormatsCount; i++ ) { 148 bodyFormats[i].makeFormat( getDBTableModel() ); 149 } 150 } 151 152 String[] astrOldStackKeys = new String[stackCols.length]; 153 for( int nIndex =0; nIndex < astrOldStackKeys.length; nIndex++) { 154 astrOldStackKeys[nIndex] = ""; 155 } 156 157 int bgClrCnt = 0; 158 int stackRow = 0; 159 160 // 5.5.8.3 (2012/11/17) 161 double[] costAry = null; 162 Calendar firstCalday = null; 163 Calendar fstCalEnd = null; 164 String calZoom = null; 165 String capacity = null; // 5.6.1.2 (2013/02/22) 166 if( innerStack ){ 167 costAry = new double[calArray.length]; 168 String[] firstCal = calArray[0]; 169 firstCalday = HybsSystem.getCalendar(firstCal[0]); 170 fstCalEnd = HybsSystem.getCalendar(firstCal[2]); 171 172 if( differenceDays(firstCalday.getTime(),fstCalEnd.getTime()) == 1 ){ 173 calZoom = ViewStackTableParam.STACK_ZOOM_DAY; 174 } 175 else if( differenceDays(firstCalday.getTime(),fstCalEnd.getTime()) == 7 ){ 176 calZoom = ViewStackTableParam.STACK_ZOOM_WEEK; 177 } 178 else{ 179 calZoom = ViewStackTableParam.STACK_ZOOM_MONTH; 180 } 181 } 182 183 for( int row=startNo; row<lastNo; row++ ) { 184 // データのスキップは行わない 185 186 // ガントのブレイク 187 // if(! isSameGroup(row, astrOldGroupKeys)) { 188 if( !isSameStack(row, astrOldStackKeys) && stackCols.length > 0 ) { // 積上のブレイク 189 if( !(innerStack && row == startNo) ) { // 5.5.8.3 (2012/11/17) 内部積上げは後から積上げるので、初回は出力しない 190 stackRow = row; 191 192 out.append(makeBodyTable(innerStack ? row -1 : row, stackRow, bgClrCnt, blc, costAry, capacity)); // 5.6.1.2 (2013/02/22) 193 194 if( innerStack ){ 195 costAry = new double[calArray.length]; 196 } 197 } 198 } 199 if( !innerStack ){// 5.5.8.3 (2012/11/17) 内部積上げの場合はガント部分は出力せずに積上げだけする。 200 for( int i=0; i<bodyFormatsCount; i++ ) { 201 TableFormatter bodyFormat = bodyFormats[i]; 202 if( ! bodyFormat.isUse( row,getDBTableModel() ) ) { continue; } // 3.5.4.0 (2003/11/25) 203 out.append("<tbody").append( getBgColorCycleClass( bgClrCnt++,row ) ); 204 if( isNoTransition() ) { // 4.3.3.0 (2008/10/01) 205 out.append( getHiddenRowValue( row ) ); 206 } 207 out.append( GANTT_TBODY ); 208 out.append( STACK_ROW_PREFIX ).append( stackRow ).append("'"); 209 out.append(">"); // 3.7.0.3 (2005/03/01) 210 out.append( bodyFormat.getTrTag() ); 211 212 // 3.5.5.0 (2004/03/12) No 欄そのものの作成判断追加 213 if( isNumberDisplay() ) { 214 String ckboxTD = "<td" + bodyFormat.getRowspan() + ">"; 215 out.append( makeCheckbox( ckboxTD,row,blc ) ); 216 } 217 218 int cl = 0; 219 for( ; cl < bodyFormat.getLocationSize(); cl++ ) { 220 String fmt = bodyFormat.getFormat(cl); 221 int loc = bodyFormat.getLocation(cl); // 3.5.5.0 222 if( ! bodyFormat.isNoClass() && loc >= 0 ) { // 3.5.5.7 (2004/05/10) 223 StringBuilder newtg = new StringBuilder( HybsSystem.BUFFER_LARGE ); 224 newtg.append("<td class=\""); 225 newtg.append( getColumnDbType(loc) ); // 4.0.0 (2005/01/31) 226 newtg.append("\" "); 227 String tdclass = newtg.toString(); 228 fmt = StringUtil.replace( bodyFormat.getFormat(cl) ,"<td", tdclass ); 229 } 230 out.append( fmt ); // 3.5.0.0 231 // 3.5.5.7 (2004/05/10) #,$ 対応 232 if( loc >= 0 ) { 233 switch( bodyFormat.getType(cl) ) { 234 case '#' : out.append( getColumnLabel(loc) ); break; 235 case '$' : out.append( getRendererValue(row,loc) ); break; 236 case '!' : out.append( getValue(row,loc) ); break; 237 default : out.append( getValueLabel(row,loc) ); break; 238 } 239 } 240 else { 241 out.append( bodyFormat.getSystemFormat(row,loc) ); 242 } 243 } 244 out.append( bodyFormat.getFormat(cl) ); 245 out.append("</tbody>").append( HybsSystem.CR ); 246 } 247 } 248 else{ // 内部積上げをする場合 5.5.8.3 (2012/11/17) 249 double costDbl = Double.parseDouble( getValue(row,costCols[0]) ); //工数 250 Calendar startDay = HybsSystem.getCalendar(getValue(row,costCols[1])); 251 Calendar endDay = HybsSystem.getCalendar(getValue(row,costCols[2])); 252 253 Date startDayDate = startDay.getTime(); 254 Date endDayDate = endDay.getTime(); 255 256 // 5.6.1.2 (2013/02/22) 257 if( capCol > -1 ){ 258 capacity = getValue(row,capCol); 259 } 260 else{ 261 capacity = "1"; 262 } 263 264 // 枠はそのままで計算 265 int fromCell = calNumber(startDayDate,calZoom,firstCalday.getTime()); 266 int toCell = calNumber(endDayDate,calZoom,firstCalday.getTime()); 267 268 endDay.add(Calendar.DATE, 1); // 終了日は範囲に入るので1つ進める 269 endDayDate = endDay.getTime(); 270 271 int stackMother = differenceDays(startDayDate,endDayDate); 272 if( !stackHoliday ){ 273 for(int cel = fromCell; cel <= toCell; cel++ ){ 274 if ("1".equals( calArray[cel][1] ) ){ 275 stackMother--; 276 } 277 } 278 } 279 280 Date calFrom; 281 Date calTo; 282 int cellDays = 1; 283 284 for(int cel = fromCell; cel <= toCell; cel++ ){ 285 calFrom = HybsSystem.getCalendar(calArray[cel][0]).getTime(); 286 calTo = HybsSystem.getCalendar(calArray[cel][2]).getTime(); 287 if( calFrom.compareTo( startDayDate ) < 0 ){ 288 calFrom = startDayDate; 289 } 290 if( endDayDate.compareTo( calTo ) < 0 ){ 291 calTo = endDayDate; 292 } 293 cellDays = differenceDays( calFrom, calTo ); 294 if( stackHoliday ){ 295 costAry[cel] += (costDbl / stackMother) * cellDays; 296 } 297 else{ 298 // 休日のみの場合は積上げられない! 299 if (!"1".equals( calArray[cel][1] ) ){ 300 costAry[cel] += (costDbl / stackMother) * cellDays; 301 } 302 } 303 } 304 } 305 } 306 307 308 // 3.5.2.0 (2003/10/20) ヘッダー繰り返し属性( headerSkipCount )を採用 309 if( hsc > 0 && hscCnt % hsc == 0 ) { 310 out.append("<tbody class=\"row_h\"").append(" >"); 311 out.append( getHeadLine() ); 312 out.append("</tbody>"); 313 hscCnt = 1; 314 } 315 else { 316 hscCnt ++ ; 317 } 318 // } // 5.6.5.2 (2013/06/21) 括弧の位置間違いのため修正 319 320 // 内部積上げ時は最終行の出力を行う 321 if( innerStack ){ 322 out.append(makeBodyTable(lastNo-1, stackRow, bgClrCnt, blc, costAry, capacity)); // 5.6.1.2 (2013/02/22) 323 } 324 325 if( footerFormat != null ) { 326 out.append( getTableFoot() ); 327 } 328 329 out.append("</table>").append( HybsSystem.CR ); 330 331 out.append( getScrollBarEndDiv() ); // 3.8.0.3 (2005/07/15) 332 return out.toString(); 333 } 334 335 /** 336 * 内容をクリア(初期化)します。 337 * 338 * @og.rev 5.5.8.3 (2012/11/17) 内部積上げのための修正 339 * @og.rev 5.6.1.2 (2013/02/22) キャパシティ対応 340 * 341 */ 342 @Override 343 public void clear() { 344 super.clear(); 345 headerFormat = null; 346 bodyFormats = null; 347 footerFormat = null; 348 bodyFormatsCount = 0; 349 stackCols = null; // 5.5.8.3 (2012/11/17) 350 costCols = null; // 5.5.8.3 (2012/11/17) 351 innerStack = Boolean.parseBoolean( ViewStackTableParam.INNER_STACK_VALUE ); // 5.5.8.3 (2012/11/17) 352 calArray = null; // 5.5.8.3 (2012/11/17) 353 stackHoliday = Boolean.parseBoolean( ViewStackTableParam.STACK_HOLIDAY_KEY ); // 5.5.8.3 (2012/11/17) 354 capCol = -1; // 5.6.1.2 (2013/02/22) 355 } 356 357 /** 358 * このビューに対する特別な初期化を行う。 359 * 360 * @og.rev 5.5.8.3 (2012/11/17) 361 * @og.rev 5.5.9.0 (2012/12/03) objectではなくArrayList化 362 * @og.rev 5.6.1.2 (2013/02/22) キャパシティ対応 363 * @og.rev 5.6.2.1 (2013/03/08) stackHolidayが抜けていたので追加 364 */ 365 private void paramInit() { 366 String strStackCols = getParam( ViewStackTableParam.STACK_COLUMNS_KEY ,ViewStackTableParam.STACK_COLUMNS_VALUE ); 367 String costCol = getParam( ViewStackTableParam.COST_COLUMNS_KEY, ViewStackTableParam.COST_COLUMNS_VALUE ); // 5.5.8.3 (2012/11/17) 368 innerStack = getBoolParam( ViewStackTableParam.INNER_STACK_KEY ); // 5.5.8.3 (2012/11/17) 369 String capColName = getParam( ViewStackTableParam.CAP_COLUMN_KEY, ViewStackTableParam.CAP_COLUMN_VALUE ); // 5.6.1.2 (2013/02/22) 370 stackHoliday = getBoolParam( ViewStackTableParam.STACK_HOLIDAY_KEY ); // 5.6.2.1 (2013/03/08) 371 372 if( innerStack ){ 373 calArray = getViewArrayList().toArray(new String[][]{}); // 5.5.9.0 (2012/12/03) 374 if( calArray == null || costCol == null){ 375 String errMsg = "ヘッダのカレンダデータ、costColumnsの設定は必須です。"+costCol; 376 throw new HybsSystemException( errMsg ); 377 } 378 } 379 380 DBTableModel table = getDBTableModel(); 381 382 String[] stackKeys = StringUtil.csv2Array(strStackCols); 383 stackCols = new int[stackKeys.length]; 384 for( int nIndex = 0; nIndex < stackCols.length ; nIndex++) { 385 stackCols[nIndex] = table.getColumnNo( stackKeys[nIndex] ); 386 } 387 388 String[] costKeys = StringUtil.csv2Array(costCol); 389 costCols = new int[costKeys.length]; 390 for( int nIndex = 0; nIndex < costCols.length ; nIndex++) { 391 costCols[nIndex] = table.getColumnNo( costKeys[nIndex] ); 392 } 393 394 // 5.6.1.2 (2013/02/22) キャパシティ 395 if( capColName != null && capColName.length() > 0 ){ 396 capCol = table.getColumnNo(capColName); 397 } 398 } 399 400 /** 401 * DBTableModel から テーブルのタグ文字列を作成して返します。 402 * 403 * 404 * @return テーブルのタグ文字列 405 */ 406 @Override 407 protected String getTableHead() { 408 409 StringBuilder buf = new StringBuilder( HybsSystem.BUFFER_MIDDLE ); 410 // 3.5.5.0 (2004/03/12) No 欄そのものの作成判断追加 411 if( isNumberDisplay() ) { 412 buf.append("<colgroup class=\"X\" />"); // 4.0.0 (2005/01/31) 413 buf.append("<colgroup class=\"BIT\" />"); 414 buf.append("<colgroup class=\"S9\" />"); // 4.0.0 (2005/01/31) 415 buf.append(HybsSystem.CR); 416 } 417 418 // 3.5.2.0 (2003/10/20) ヘッダー繰り返し部をgetHeadLine()へ移動 419 buf.append("<thead id=\"header\">").append( HybsSystem.CR ); // 3.5.6.5 (2004/08/09) 420 buf.append( getHeadLine() ); 421 buf.append("</thead>").append( HybsSystem.CR ); 422 423 return buf.toString(); 424 } 425 426 /** 427 * ヘッダー繰り返し部を、getTableHead()メソッドから分離。 428 * 429 * 430 * @return テーブルのタグ文字列 431 */ 432 @Override 433 protected String getHeadLine() { 434 return getHeadLine( "<th" ) ; 435 } 436 437 /** 438 * ヘッダー繰り返し部を、getTableHead()メソッドから分離。 439 * 440 * 441 * @param thTag タグの文字列 442 * 443 * @return テーブルのタグ文字列 444 */ 445 @Override 446 protected String getHeadLine( final String thTag ) { 447 if( headerLine != null ) { return headerLine; } // キャッシュを返す。 448 449 StringBuilder buf = new StringBuilder( HybsSystem.BUFFER_MIDDLE ); 450 451 buf.append( headerFormat.getTrTag() ).append( HybsSystem.CR ); 452 453 // 3.5.5.0 (2004/03/12) No 欄そのものの作成判断追加 454 if( isNumberDisplay() ) { 455 // 3.5.4.3 (2004/01/05) 追加分 456 if( isUseCheckControl() && "checkbox".equals( getSelectedType() ) ) { 457 buf.append( thTag ).append( headerFormat.getRowspan() ).append("></th>"); 458 buf.append( thTag ).append( headerFormat.getRowspan() ); 459 buf.append(">").append( getAllCheckControl() ).append( "</th>"); 460 buf.append( thTag ).append( headerFormat.getRowspan() ); 461 buf.append(">").append( getNumberHeader() ).append("</th>"); // 3.5.4.6 (2004/01/30) 462 } 463 else { 464 buf.append( thTag ).append(" colspan=\"3\""); 465 buf.append( headerFormat.getRowspan() ); 466 buf.append(">").append( getNumberHeader() ).append("</th>"); // 3.5.4.6 (2004/01/30) 467 } 468 } 469 470 int cl = 0; 471 for( ; cl < headerFormat.getLocationSize(); cl++ ) { 472 buf.append( StringUtil.replace( headerFormat.getFormat(cl) ,"td","th" )); 473 int loc = headerFormat.getLocation(cl); 474 if( loc >= 0 ) { buf.append( getSortedColumnLabel(loc) ); } 475 } 476 buf.append( StringUtil.replace( headerFormat.getFormat(cl) ,"td","th" ) ).append( HybsSystem.CR ); 477 478 headerLine = buf.toString(); 479 return headerLine; 480 } 481 482 /** 483 * DBTableModel から テーブルのタグ文字列を作成して返します。 484 * 485 * 486 * @return テーブルのタグ文字列 487 */ 488 protected String getTableFoot() { 489 footerFormat.makeFormat( getDBTableModel() ); 490 491 StringBuilder buf = new StringBuilder( HybsSystem.BUFFER_MIDDLE ); 492 493 buf.append("<tfoot>").append( HybsSystem.CR ); 494 buf.append( footerFormat.getTrTag() ).append( HybsSystem.CR ); 495 496 // 3.5.5.0 (2004/03/12) No 欄そのものの作成判断追加 497 if( isNumberDisplay() ) { 498 buf.append(" <th"); 499 buf.append(" colspan=\"3\""); 500 buf.append( footerFormat.getRowspan() ); 501 buf.append("></th>"); 502 } 503 504 int cl = 0; 505 for( ; cl < footerFormat.getLocationSize(); cl++ ) { 506 int loc = footerFormat.getLocation(cl); 507 if( loc >= 0 ) { buf.append( getSortedColumnLabel(loc) ); } 508 } 509 buf.append( footerFormat.getFormat(cl) ).append( HybsSystem.CR ); 510 buf.append("</tfoot>").append( HybsSystem.CR ); 511 512 return buf.toString(); 513 } 514 515 /** 516 * フォーマットを設定します。 517 * 518 * 519 * @param list TableFormatterのリスト 520 */ 521 @Override 522 public void setFormatterList( final List<TableFormatter> list ) { // 4.3.3.6 (2008/11/15) Generics警告対応 523 bodyFormats = new TableFormatter[BODYFORMAT_MAX_COUNT]; 524 525 bodyFormatsCount = 0; 526 for( int i=0; i<list.size(); i++ ) { 527 TableFormatter format = list.get( i ); // 4.3.3.6 (2008/11/15) Generics警告対応 528 529 switch( format.getFormatType() ) { 530 case TYPE_HEAD : headerFormat = format; break; 531 case TYPE_BODY : bodyFormats[bodyFormatsCount++] = format; break; 532 case TYPE_FOOT : footerFormat = format; break; 533 default : String errMsg = "FormatterType の定義外の値が指定されました。"; 534 // 4.3.4.4 (2009/01/01) 535 throw new HybsSystemException( errMsg ); 536 } 537 } 538 539 // 3.5.5.5 (2004/04/23) headerFormat が定義されていない場合はエラー 540 if( headerFormat == null ) { 541 String errMsg = "h:thead タグの、フォーマットの指定は必須です。"; 542 throw new HybsSystemException( errMsg ); 543 } 544 } 545 546 /** 547 * フォーマットメソッドを使用できるかどうかを問い合わせます。 548 * 549 * @return 使用可能(true)/ 使用不可能 (false) 550 */ 551 @Override 552 public boolean canUseFormat() { 553 return true; 554 } 555 556 /** 557 * ビューで表示したカラムの一覧をカンマ区切りで返します。 558 * 559 * @og.rev 5.1.6.0 (2010/05/01) 新規追加 560 * 561 * @return ビューで表示したカラムの一覧 562 */ 563 @Override 564 public String getViewClms() { 565 DBTableModel table = getDBTableModel(); 566 StringBuilder buf = new StringBuilder( HybsSystem.BUFFER_MIDDLE ); 567 for( int i=0; i<headerFormat.getLocationSize(); i++ ) { 568 if( buf.length() > 0 ) { buf.append( ',' ); } 569 buf.append( table.getColumnName( headerFormat.getLocation( i ) ) ); 570 } 571 return buf.toString(); 572 } 573 574 /** 575 * 上下行のデータが同じ積上かどうかをチェックする。 576 * 577 * @param nRowIndex テーブルモデルの行番号 578 * @param astrOldValues 古いグルプデータ 579 * 580 * @return 使用可能(true)/ 使用不可能 (false) 581 */ 582 private boolean isSameStack(final int nRowIndex, final String[] astrOldValues) { 583 boolean bRet = stackCols.length > 0 ; 584 if( bRet ) { 585 for( int nIndex = 0; bRet && nIndex < stackCols.length ; nIndex++) { 586 bRet = astrOldValues[nIndex].equals( getValue( nRowIndex, stackCols[nIndex] ) ) ; 587 } 588 589 // 不一致時に astrOldValues に 新しい値を設定しておきます。 590 if(!bRet) { 591 for( int nIndex = 0; nIndex < stackCols.length; nIndex++) { 592 astrOldValues[nIndex] = getValue(nRowIndex, stackCols[nIndex]); 593 } 594 } 595 } 596 return bRet; 597 } 598 599 /** 600 * 対象カラムが積上げカラムかどうか 601 * 602 * @param loc 列番号 603 * 604 * @return 対象(true)/ 非対象 (false) 605 */ 606 private boolean isStackClm(final int loc) { 607 boolean rtn = false; 608 for( int nIndex = 0; nIndex < stackCols.length ; nIndex++) { 609 if( stackCols[nIndex] == loc ) { 610 rtn = true; 611 } 612 } 613 return rtn; 614 } 615 616 /** 617 * 2つの日付の差を求めます。 618 * java.util.Date 型の日付 date1 - date2 が何日かを返します。 619 * 620 * @og.rev 5.5.8.3 (2012/11/17) 新規 621 * 622 * @param date1 日付 623 * @param date2 日付 624 * @return 2つの日付の差(日数 2-1) 同日なら0 625 */ 626 public static int differenceDays(final Date date1,final Date date2) { 627 long datetime1 = date1.getTime(); 628 long datetime2 = date2.getTime(); 629 long one_date_time = 1000 * 60 * 60 * 24L; 630 return (int)((datetime2 - datetime1) / one_date_time); 631 } 632 633 634 /** 635 * 日付から枠番号を返す 636 * 637 * @og.rev 5.5.8.3 (2012/11/17) 新規 638 * 639 * @param date 日付(YYYY/MM/DD) 640 * @param zoom Zoom設定値 641 * @param calFD ヘッダ初日 642 * 643 * @return 枠番号 644 */ 645 private int calNumber(final Date date, final String zoom, final Date calFD ) { 646 int rtn = 0; 647 if( zoom.equals( ViewStackTableParam.STACK_ZOOM_MONTH ) ){ 648 // 月だけは別の計算が必要 649 Calendar cal1 = Calendar.getInstance(); 650 cal1.setTime( calFD ); 651 Calendar cal2 = Calendar.getInstance(); 652 cal2.setTime( date ); 653 rtn = ( cal2.get( Calendar.YEAR )-cal1.get( Calendar.YEAR ) ) * 12 654 + ( cal2.get( Calendar.MONTH ) - cal1.get( Calendar.MONTH ) ); 655 } 656 else{ 657 int diff = differenceDays( calFD, date ); 658 if( zoom.equals( ViewStackTableParam.STACK_ZOOM_WEEK )){ 659 rtn = diff/7; 660 } 661 else{ 662 rtn = diff; 663 } 664 } 665 return rtn; 666 } 667 668 /** 669 * テーブル本体の作成 670 * 671 * @og.rev 5.5.8.3 (2012/11/17) 繰り返し利用するため分離 672 * @og.reb 5.6.1.2 (2013/02/22) td終了が抜けていたので追加、キャパシティ対応 673 * 674 * @param row テーブルモデルのrow 675 * @param stackRow スタック行保存用 676 * @param bgClrCnt 背景色カウンタ 677 * @param blc チェックボックス用 678 * @param costAry コスト集計配列 679 * @param cap 能力 680 * 681 * @return テーブル本体のHTML 682 */ 683 private StringBuffer makeBodyTable( final int row, final int stackRow, final int bgClrCnt, final int blc, final double[] costAry, final String cap){ 684 StringBuffer out = new StringBuffer(); 685 int bcCnt = bgClrCnt; // 6.0.0.1 (2014/04/25) 引数を直接変更できなくする。 686 for( int i=0; i<bodyFormatsCount; i++ ) { 687 TableFormatter bodyFormat = bodyFormats[i]; 688 if( ! bodyFormat.isUse( row,getDBTableModel() ) ) { continue; } 689 out.append("<tbody").append( getBgColorCycleClass( bcCnt++,row ) ); 690 if( isNoTransition() ) { 691 out.append( getHiddenRowValue( row ) ); 692 } 693 out.append( STACK_TBODY ); 694 out.append( STACK_ROW_PREFIX ).append( stackRow ).append("'"); 695 out.append( STACK_ID_PREFIX ).append(stackRow).append( "'" ); 696 out.append(">"); 697 out.append( bodyFormat.getTrTag() ); 698 699 // No 欄そのものの作成判断追加 700 if( isNumberDisplay() ) { 701 String ckboxTD = "<td" + bodyFormat.getRowspan() + ">"; 702 out.append( makeCheckbox( ckboxTD,row,blc ) ); 703 } 704 705 int cl = 0; 706 for( ; cl < bodyFormat.getLocationSize(); cl++ ) { 707 String fmt = bodyFormat.getFormat(cl); 708 int loc = bodyFormat.getLocation(cl); // 3.5.5.0 709 if( ! bodyFormat.isNoClass() && loc >= 0 ) { // 3.5.5.7 (2004/05/10) 710 StringBuilder newtg = new StringBuilder( HybsSystem.BUFFER_LARGE ); 711 newtg.append("<td class=\""); 712 newtg.append( getColumnDbType(loc) ); // 4.0.0 (2005/01/31) 713 newtg.append("\" "); 714 String tdclass = newtg.toString(); 715 fmt = StringUtil.replace( bodyFormat.getFormat(cl) ,"<td", tdclass ); 716 } 717 out.append( fmt ); 718 719 // locがstackに入っていれば出力 720 if ( isStackClm(loc) ){ 721 if( loc >= 0 ) { 722 switch( bodyFormat.getType(cl) ) { 723 case '#' : out.append( getColumnLabel(loc) ); break; 724 case '$' : out.append( getRendererValue(row,loc) ); break; 725 case '!' : out.append( getValue(row,loc) ); break; 726 default : out.append( getValueLabel(row,loc) ); break; 727 } 728 } 729 else { 730 out.append( bodyFormat.getSystemFormat(row,loc) ); 731 } 732 } 733 } 734 // 5.5.8.3 (2012/11/17)内部積上げの結果は出力場所の特定が難しいため一番最後尾にtd付きで出力しておきます 735 if( innerStack ){ 736 out.append("</td><td><div class='stackDivParent' capacity='"+ cap + "' style='width:100%; position:relative;'>"); // 5.6.1.2 (2013/02/22) td終了追加 737 for( int cs = 0; cs < costAry.length; cs++ ){ 738 out.append("<div class='stackDiv' style='position:absolute; top:0px;' num='") 739 .append( cs) 740 .append("' stackedCost='") 741 .append( costAry[cs] ) 742 .append( "'></div>"); 743 } 744 out.append("</div>"); 745 } 746 747 out.append( bodyFormat.getFormat(cl) ); 748 out.append("</tbody>").append( HybsSystem.CR ); 749 } 750 return out; 751 } 752}