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 java.util.List; 019import java.util.ArrayList; 020 021import org.opengion.hayabusa.common.HybsSystemException; 022import org.opengion.hayabusa.html.ViewTimeTableParam; 023 024/** 025 * 時間軸を持つタイムテーブルの表示を行うクラスです。 026 * 027 * パラメータが必要な場合は、ViewTimeTableParamTag を使用してください。 028 * 029 * パラメータが設定されていない場合は、ViewForm_HTMLTimeTable の初期値が使用されます。 030 * (パラメータを使用するには、viewタグのuseParam 属性をtrueに設定する必要があります。) 031 * 032 * SELECT文は、日付、キー、備考、開始時刻、終了時刻、リンクが、必須項目で、この並び順は、 033 * 完全に固定です。よって、カラム位置を指定する必要はありませんが、SELECT文を自由に 034 * 設定することも出来ませんので、ご注意ください。 035 * この固定化に伴い、WRITABLE 指定も使用できません。 036 * なお、日付、キー、備考 に関しては、columnDisplay 属性で、表示の ON/OFF 制御は可能です。 037 * また、日付ブレイク、キーブレイクの設定で、カラム自体をテーブルの外に出すことが可能です。 038 * (キーと備考はセットになっています。) 039 * 040 * タイムテーブルが空きの場合のリンクを指定できます。(ViewTimeTableParam.NULL_LINK_CLM_ID) 041 * (ViewTimeTableParam の nullLinkColumn 属性) 042 * 指定しない場合は、空きのリンクは作成されません。 043 * このリンクは、特殊で、引数に、パラメータを追加できますが、"($1)"、"($2)" で指定します。 044 * この($1)、($2)は、開始時刻、終了時刻がセットされますが、SELECT文の固定カラムと同じ 045 * 並び順ですが、DBTableModelの値を設定しているわけではありません。 046 * 空きの場合は、データ自体が存在しない場合と、日付、キー のみが 外部結合で生成された 047 * レコードが実際に存在する場合がありますが、外部結合で生成されたレコードには、 048 * 開始時刻、終了時刻はありません。($1) と($2)には、それぞれ、最小開始時刻と最大終了時刻を 049 * セットします。 050 * 051 * 例として、&TMSTART=($1)&TMEND=($2) という文字列の ($*) 部分を解析して割当ます。 052 * 053 * ブレーク処理を行うカラムIDをCSV形式でセットできます。(ViewTimeTableParam.BREAK_CLMS) 054 * (ViewTimeTableParam の breakClms 属性) 055 * これは、ブレイク毎にテーブルが分かれて、テーブルの先頭に、ブレイクした 056 * 値が表示されます。 057 * 例えば、日付カラムをブレイクカラムとして設定すると、日付がブレイクするたび、 058 * 日付をヘッダーに出して、テーブルを作成します。 059 * ブレークカラムは、CSV形式で複数指定できます。その場合は、複数指定のカラムの 060 * 合成された値で、キーブレイクの判定を行います。(簡単に言うとOR判定になります。) 061 * なお、ブレイクカラムを指定した場合は、自動的に、noDisplay 属性にその値をセット 062 * します。 063 * 064 * @og.rev 5.4.0.0 (2011/10/01) 新規追加 065 * @og.group 画面表示 066 * 067 * @version 4.0 068 * @author Kazuhiko Hasegawa 069 * @since JDK5.0, 070 */ 071public class ViewForm_HTMLTimeTable extends ViewForm_HTMLTable { 072 /** このプログラムのVERSION文字列を設定します。 {@value} */ 073 private static final String VERSION = "8.5.6.1 (2024/03/29)" ; 074 075 /** 30分 単位に colspan を設定する。 */ 076 private int intval = 30; 077 /** 08:00 のこと。8H=480M */ 078 private int minStTime = 480; 079 /** 21:00 のこと。21H=1260M */ 080 private int maxEdTime = 1260; 081 082 // 6.4.1.1 (2016/01/16) dyClmNo → DY_CLMNO , keyClmNo → KEY_CLMNO , tmstClmNo → TMST_CLMNO , tmedClmNo → TMED_CLMNO , linkClmNo → LINK_CLMNO , clmCnt → CLM_CNT refactoring 083 /** ヘッダー1:ただし、グループ化する場合は、外出し */ 084 private static final int DY_CLMNO = 0; 085 /** ヘッダー2:ただし、グループ化する場合は、外出し */ 086 private static final int KEY_CLMNO = 1; 087// /** ヘッダー3:(内部では使用していません。) */ 088 // private static final int bikoClmNo = 2; 089 090 /** 時間枠の開始時刻(含む) */ 091 private static final int TMST_CLMNO = 3; 092 /** 時間枠の終了時刻(含まない) */ 093 private static final int TMED_CLMNO = 4; 094 /** 時間枠に表示する予約情報(変更画面へのリンク) */ 095 private static final int LINK_CLMNO = 5; 096 097 /** 決め打ち。今は、dyClm,keyClm の2つだけ表示 */ 098 private static final int CLM_CNT = 3; 099 100 /** 引数パース機能付き データが存在しない場合のリンクのベースを設定。 */ 101 private int nullLinkClmNo = -1 ; // 固定ではなく可変の場合に利用するリンクカラムNo 102 103 /** 5.4.3.7 (2012/01/20) データを入れるTDタグにclass属性を付与する場合のカラムNo */ 104 private int tdClassColumnNo = -1 ; 105 106 /** 日付でブレイクするかどうかを指定 */ 107 private boolean isDyBreak = true; 108 /** 5.4.4.2 (2012/02/03) ブッキングデータをマージするかどうかを指定 */ 109 private boolean isBookingMerge ; 110 111 /** 112 * デフォルトコンストラクター 113 * 114 * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor. 115 */ 116 public ViewForm_HTMLTimeTable() { super(); } // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。 117 118 /** 119 * 内容をクリア(初期化)します。 120 * 121 * @og.rev 5.4.3.7 (2012/01/20) tdClassColumnNo 追加 122 * @og.rev 5.4.4.2 (2012/02/03) isBookingMerge 追加 123 * 124 */ 125 @Override 126 public void clear() { 127 super.clear(); 128 intval = 30; // 30分 単位に colspan を設定する。 129 minStTime = 480; // 08:00 のこと。8H=480M 130 maxEdTime = 1260; // 21:00 のこと。21H=1260M 131 132 nullLinkClmNo = -1; // 固定ではなく可変の場合に利用するリンクカラム 133 tdClassColumnNo = -1 ; // 5.4.3.7 (2012/01/20) データを入れるTDタグにclass属性を付与する場合のカラムNo 134 isDyBreak = true; // 日付でブレイクするかどうかを指定 135 isBookingMerge = false; // 5.4.4.2 (2012/02/03) ブッキングデータをマージするかどうかを指定 136 } 137 138 /** 139 * DBTableModel から HTML文字列を作成して返します。 140 * startNo(表示開始位置)から、pageSize(表示件数)までのView文字列を作成します。 141 * 表示残りデータが pageSize 以下の場合は、残りのデータをすべて出力します。 142 * 143 * @og.rev 5.4.3.7 (2012/01/20) tdClassColumnNo 追加 144 * @og.rev 5.4.4.2 (2012/02/03) isBookingMerge 追加 145 * @og.rev 7.0.1.0 (2018/10/15) XHTML → HTML5 対応(空要素の、"/>" 止めを、">" に変更します)。 146 * 147 * @param startNo 表示開始位置 148 * @param pageSize 表示件数 149 * 150 * @return DBTableModelから作成された HTML文字列 151 * @og.rtnNotNull 152 */ 153 @Override 154 public String create( final int startNo, final int pageSize ) { 155 if( getRowCount() == 0 ) { return ""; } // 暫定処置 156 157 paramInit(); 158 headerLine = null; 159 final int lastNo = getLastNo( startNo, pageSize ); 160 final int hsc = getHeaderSkipCount(); 161 int hscCnt = 1; 162 163 final StringBuilder out = new StringBuilder( BUFFER_LARGE ); 164 165 if( isDyBreak ) { 166 out.append( getRendererValue( 0,DY_CLMNO ) ).append( CR ); 167 setColumnDisplay( DY_CLMNO,false ); // 日付ブレイクなら、setColumnDisplay をfalse にセット 168 } 169 170 out.append( getHeader() ) 171 .append("<tbody>").append( CR ); 172 173 int bgClrCnt = 0; 174 175 final int maxColspan = (maxEdTime-minStTime)/intval ; // この数が、TDの数になる。 176 int rowColspan = 0; // 5.5.0.3(2012/03/12) 1行の累積TD数。最大は、maxColspan で、 177 int stTime = minStTime; 178 179 String backData = ""; // 初期値。1回目にキーブレイクさせる。 180 181 final StringBuilder buf2 = new StringBuilder( BUFFER_MIDDLE ); // 6.1.0.0 (2014/12/26) refactoring 182 183 final List<String> dblBooking = new ArrayList<>(); // 重複データがあったときのデータ格納 184 String nlVal = null; // 空リンクのベース値 185 // 6.3.9.1 (2015/11/27) Found 'DD'-anomaly for variable(PMD) 186 String bkNlVal = null; // キーブレイク時の元の空リンクのベース値 187 String bkDyVal = ""; // キーブレイク時の元の日付 188 for( int row=startNo; row<lastNo; row++ ) { 189 // キーブレイクの判定 190 bkNlVal = nlVal; 191 192 nlVal = nullLinkClmNo < 0 ? null : getRendererValue( row,nullLinkClmNo ); 193 final String tdCls = tdClassColumnNo < 0 ? null : getValue( row,tdClassColumnNo ); // 5.4.3.7 (2012/01/20) tdClassColumnNo 追加 194 final String dyVal = getValue( row,DY_CLMNO ); // 日付項目の値 195 final String keyVal = getValue( row,KEY_CLMNO ); // キー項目の値 196 if( row==startNo ) { bkDyVal = dyVal; } // 初期データをセット。 197 198 String linkVal = getRendererValue( row,LINK_CLMNO ); 199 200 // キーブレイク判定。キーブレイクは、一番初めから来る。 201 if( !backData.equals( dyVal + keyVal ) ) { 202 backData = dyVal + keyVal; // null は来ないはず 203 204 // minStTime < stTime の時だけ、処理を行う。(最初のキーブレイクは処理しないため) 205 if( minStTime < stTime ) { 206 // まずは、前の td の残りを出力する。ここでは、キーブレイク前の値を使用する。 207 if( stTime < maxEdTime ) { 208 out.append(" "); // td タグの出力前の段落 209 // 残データの書き出しは、最大TD数-それまでにセットした数。 210 final int td = maxColspan - rowColspan; // 5.5.0.3(2012/03/12) 211 appendTDTag( out , null , td , // 5.5.0.3(2012/03/12) 212 makeLinkValue( bkNlVal , stTime , maxEdTime ) ); 213 } 214 out.append("</tr>").append( CR ); 215 } 216 stTime = minStTime; // 初期化 217 218 // データかぶりが発生したときの処理 219 if( !dblBooking.isEmpty() ) { 220 for( final String bkdt : dblBooking ) { 221 // 6.0.2.5 (2014/10/31) char を append する。 222 out.append(" <tr").append( getBgColorCycleClass( bgClrCnt-1 ) ).append('>').append( CR ) 223 .append( bkdt ) 224 .append("</tr>").append( CR ); 225 } 226 dblBooking.clear(); 227 } 228 229 // 日付ブレイク処理 230 if( isDyBreak && row > startNo && !bkDyVal.equals( dyVal ) ) { 231 bkDyVal = dyVal; 232 out.append(" <tr class=\"dummy\">"); 233 for( int column=0; column<CLM_CNT; column++ ) { 234 if( isColumnDisplay( column ) ) { 235// out.append("<td/>"); 236 out.append("<td></td>"); // 7.0.1.0 (2018/10/15) 237 } 238 } 239 for( int i=0; i<maxColspan ; i++ ) { // 5.5.0.3(2012/03/12) 空td の出力。TD の colspan の基準になる。 240// out.append("<td/>"); 241 out.append("<td></td>"); // 7.0.1.0 (2018/10/15) 242 } 243 out.append("</tr>").append( CR ) 244 .append("</tbody>").append( CR ) 245 .append("</table>").append( CR ) 246 .append( getRendererValue( row,DY_CLMNO ) ).append( CR ) 247 .append( getHeader() ) 248 .append("<tbody>").append( CR ); 249 hscCnt = 1; 250 } 251 252 // ヘッダー繰り返し属性( headerSkipCount )を採用 253 if( hsc > 0 && hscCnt % hsc == 0 ) { 254 out.append( getHeadLine() ); 255 hscCnt = 1; 256 } 257 else { 258 // 特殊処理:ここの処理では、一番最初も、実行されるので、++しないように加工しておく。 259 if( row > startNo ) { hscCnt ++ ; } 260 } 261 262 // ここから、新しい行が始まる。 263 // 6.0.2.5 (2014/10/31) char を append する。 264 out.append(" <tr").append( getBgColorCycleClass( bgClrCnt++ ) ).append('>').append( CR ); 265 rowColspan = 0 ; // 5.5.0.3(2012/03/12) 初期化 266 267 for( int column=0; column<CLM_CNT; column++ ) { 268 if( isColumnDisplay( column ) ) { 269 // ヘッダー部分に加工しやすいように、class 属性を与えておく。 270 out.append(" <td class=\"" ).append( getColumnName( column ) ).append( "\">" ) 271 .append( getValueLabel(row,column) ) 272 .append("</td>").append( CR ); 273 } 274 } 275 } 276 277 // 文字列型の時分情報を数字に変換する。 278 int clStTime = getStr2Time( getValue( row,TMST_CLMNO ) , -1 ); 279 final boolean nullData = clStTime < 0 ; // 開始時刻が null の場合、-1 が返されるのでフラグをセットする。 280 if( clStTime < minStTime ) { clStTime = minStTime; } // 最小値以下の場合は、最小値に合せる。 281 282 int clEdTime = getStr2Time( getValue( row,TMED_CLMNO ) , maxEdTime ); 283 if( clEdTime > maxEdTime ) { clEdTime = maxEdTime; } // 最大値以上の場合は、最大値に合せる。 284 285 if( clStTime == clEdTime ) { clEdTime = clEdTime + intval ; } // 最初と最後が同じ場合は、intval分 進めておく。 286 287 // 最初と最後が異なる場合は、間に空欄が入る。同じ場合は、連続なので、空欄は入らない。 288 if( stTime < clStTime ) { 289 out.append(" "); // td タグの出力前の段落 290 291 // 5.5.0.3(2012/03/12) 間に空欄が入る場合、その大きさが最小TD単位より大きければ、分割する。 292 // ただし、直前の TD 個数が、最小でない場合のみ。 293 final int td = (clStTime-stTime)/intval; // 5.5.0.3(2012/03/12) 294 rowColspan += td; 295 appendTDTag( out , null , td , // 5.5.0.3(2012/03/12) 296 makeLinkValue( nlVal , stTime , clStTime ) ).append( CR ); 297 } 298 // 前のデータとかぶっている。つまり、ブッキングデータがある。 299 else if( stTime > clStTime ) { 300 // 5.4.4.2 (2012/02/03) ブッキングデータをマージする機能を追加 301 if( isBookingMerge ) { 302 if( stTime < clEdTime ) { 303 final int td = (clEdTime-stTime)/intval; // 5.5.0.3(2012/03/12) 304 rowColspan += td ; 305 appendTDTag( out , tdCls , td , linkVal ).append( CR ); 306 stTime = clEdTime; 307 } 308 continue; 309 } 310 311 buf2.setLength(0); // 6.1.0.0 (2014/12/26) refactoring 312 buf2.append(" "); // td タグの出力前の段落 313 for( int column=0; column<CLM_CNT; column++ ) { 314 if( isColumnDisplay( column ) ) { 315 // ヘッダー部分に加工しやすいように、class 属性を与えておく。 316// buf2.append("<td class=\"" ).append( getColumnName( column ) ).append( "\"/>" ); 317 buf2.append("<td class=\"" ).append( getColumnName( column ) ).append( "\"></td>" ); // 7.0.1.0 (2018/10/15) 318 } 319 } 320 321 // 5.4.3.7 (2012/01/20) 322 appendTDTag( buf2 , null , (clStTime-minStTime)/intval ); // 最初からデータまで 323 appendTDTag( buf2 , tdCls , (clEdTime-clStTime)/intval , linkVal ); // データ部: 5.4.3.7 (2012/01/20) td に class属性追加 324 appendTDTag( buf2 , null , (maxEdTime-clEdTime)/intval ); // データから最後まで 325 326 dblBooking.add( buf2.toString() ); 327 continue; 328 } 329 // 前も後ろも最小と最大になっているのは、予約レコードが無いため。 330 // stTime == clStTime のケース。nullData = true で、予約レコードが無いため。 331 else if( nullData ) { 332 linkVal = makeLinkValue( nlVal , minStTime , maxEdTime ); 333 } 334 // 5.4.3.7 (2012/01/20) linkVal を共通に使用している箇所を修正 335 336 out.append(" "); // td タグの出力前の段落 337 final int td = (clEdTime-clStTime)/intval; // 5.5.0.3(2012/03/12) 338 rowColspan += td ; 339 appendTDTag( out , tdCls , td , linkVal ).append( CR ); // 5.5.0.3(2012/03/12) 340 341 stTime = clEdTime ; 342 } 343 344 // 残処理:データが残っている場合は、書き出す必要がある。 345 if( minStTime < stTime && stTime < maxEdTime ) { 346 out.append(" "); // td タグの出力前の段落 347 // 残データの書き出しは、最大TD数-それまでにセットした数。 348 final int td = maxColspan - rowColspan; // 5.5.0.3(2012/03/12) 349 appendTDTag( out , null , td , // 5.5.0.3(2012/03/12) 350 makeLinkValue( nlVal , stTime , maxEdTime ) ); 351 } 352 out.append("</tr>").append( CR ); 353 354 // データかぶりが発生したときの処理 355 if( !dblBooking.isEmpty() ) { 356 for( final String bkdt : dblBooking ) { 357 // 6.0.2.5 (2014/10/31) char を append する。 358 out.append(" <tr").append( getBgColorCycleClass( bgClrCnt-1 ) ).append('>').append( CR ) 359 .append( bkdt ) 360 .append("</tr>").append( CR ); 361 } 362 } 363 364 // カラムの結合があるため、td タグを個別に出力しておかないと、レイアウトがずれる。 365 out.append(" <tr class=\"dummy\">"); 366 for( int column=0; column<CLM_CNT; column++ ) { 367 if( isColumnDisplay( column ) ) { 368// out.append("<td/>"); 369 out.append("<td></td>"); // 7.0.1.0 (2018/10/15) 370 } 371 } 372 for( int i=0; i<maxColspan ; i++ ) { // 5.5.0.3(2012/03/12) 空td の出力。TD の colspan の基準になる。 373// out.append("<td/>"); 374 out.append("<td></td>"); // 7.0.1.0 (2018/10/15) 375 } 376 377 out.append("</tr>").append( CR ) 378 .append("</tbody>").append( CR ) 379 .append("</table>").append( CR ) 380 .append( getScrollBarEndDiv() ); // 3.8.0.3 (2005/07/15) 381 382 return out.toString(); 383 } 384 385 /** 386 * パラメータ内容を初期化します。 387 * 388 * @og.rev 5.4.3.7 (2012/01/20) tdClassColumnNo 追加。intval の実値化 389 * @og.rev 5.4.4.2 (2012/02/03) isBookingMerge 追加 390 * @og.rev 8.5.4.2 (2024/01/12) PMD 7.0.0 LocalVariableNamingConventions 対応 391 * 392 */ 393 private void paramInit() { 394// final String s_intval = getParam( ViewTimeTableParam.TIME_INTERVAL , null ); 395//// final String s_minStTime = getParam( ViewTimeTableParam.MIN_START_TIME , null ); 396//// final String s_maxEdTime = getParam( ViewTimeTableParam.MAX_END_TIME , null ); 397// final String s_intval = getParam( ViewTimeTableParam.TIME_INTERVAL , null ); 398// final String s_min_sttime = getParam( ViewTimeTableParam.MIN_START_TIME , null ); 399// final String s_max_edtime = getParam( ViewTimeTableParam.MAX_END_TIME , null ); 400 final String tmpIntval = getParam( ViewTimeTableParam.TIME_INTERVAL , null ); 401 final String tmpMinStTime = getParam( ViewTimeTableParam.MIN_START_TIME , null ); 402 final String tmpMaxEdTime = getParam( ViewTimeTableParam.MAX_END_TIME , null ); 403 404 isDyBreak = Boolean.valueOf( getParam( ViewTimeTableParam.USE_DY_BREAK, "true" ) ); 405 406 // 5.4.4.2 (2012/02/03) ブッキングデータをマージするかどうかを指定 407 isBookingMerge = Boolean.valueOf( getParam( ViewTimeTableParam.USE_BOOKING_MERGE, "false" ) ); 408 409 // nullリンクのカラム名指定。nullClm が優先順位が高い。 410// final String s_nullClm = getParam( ViewTimeTableParam.NULL_LINK_CLM_ID , null ); 411// if( s_nullClm != null ) { 412// nullLinkClmNo = getColumnNo( s_nullClm ); 413// } 414 // 8.5.5.1 (2024/02/29) PMD 7.0.0 LocalVariableNamingConventions 415// final String s_nullclm = getParam( ViewTimeTableParam.NULL_LINK_CLM_ID , null ); 416// if( s_nullclm != null ) { 417// nullLinkClmNo = getColumnNo( s_nullclm ); 418// } 419 final String nullclm = getParam( ViewTimeTableParam.NULL_LINK_CLM_ID , null ); 420 if( nullclm != null ) { 421 nullLinkClmNo = getColumnNo( nullclm ); 422 } 423 424 // 5.4.3.7 (2012/01/20) データを入れるTDタグにclass属性を付与する場合のカラムNo 425 // 8.5.4.2 (2024/01/12) PMD 7.0.0 LocalVariableNamingConventions 426// final String s_tdClsClm = getParam( ViewTimeTableParam.TD_CLASS_COLUMN_ID , null ); 427// if( s_tdClsClm != null ) { 428// tdClassColumnNo = getColumnNo( s_tdClsClm ); 429// } 430 final String tdClsClm = getParam( ViewTimeTableParam.TD_CLASS_COLUMN_ID , null ); 431 if( tdClsClm != null ) { 432 tdClassColumnNo = getColumnNo( tdClsClm ); 433 } 434 435 // 8.5.5.1 (2024/02/29) PMD 7.0.0 LocalVariableNamingConventions 436// if( s_intval != null ) { 437// intval = Integer.parseInt( s_intval ) ; // 5.4.3.7 (2012/01/20) 438// } 439 if( tmpIntval != null ) { 440 intval = Integer.parseInt( tmpIntval ) ; // 5.4.3.7 (2012/01/20) 441 } 442//// minStTime = getStr2Time( s_minStTime , minStTime ); // 最小開始時刻。0800 なら、80。 30分=5 換算 443//// maxEdTime = getStr2Time( s_maxEdTime , maxEdTime ); // 最大終了時刻。2100 なら、210。30分=5 換算 444// minStTime = getStr2Time( s_min_sttime , minStTime ); // 最小開始時刻。0800 なら、80。 30分=5 換算 445// maxEdTime = getStr2Time( s_max_edtime , maxEdTime ); // 最大終了時刻。2100 なら、210。30分=5 換算 446 minStTime = getStr2Time( tmpMinStTime , minStTime ); // 最小開始時刻。0800 なら、80。 30分=5 換算 447 maxEdTime = getStr2Time( tmpMaxEdTime , maxEdTime ); // 最大終了時刻。2100 なら、210。30分=5 換算 448 } 449 450 /** 451 * DBTableModel から テーブルのタグ文字列を作成して返します。 452 * 453 * @og.rev 5.4.3.7 (2012/01/20) colgroup は不要 454 * @og.rev 8.5.6.1 (2024/03/29) thead に、固定の id と class 属性を共通に定義します。 455 * 456 * @return テーブルのタグ文字列 457 * @og.rtnNotNull 458 */ 459 @Override 460 protected String getTableHead() { 461 final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE ) 462// .append("<thead id=\"header\">").append( CR ) 463 .append( THEAD_TAG ) // 8.5.6.1 (2024/03/29) 464 .append( getHeadLine() ) 465 .append("</thead>").append( CR ); 466 467 return buf.toString(); 468 } 469 470 /** 471 * ヘッダー繰り返し部を、getTableHead()メソッドから分離。 472 * 473 * @og.rev 6.1.2.0 (2015/01/24) キャッシュを返すのを、#getHeadLine() に移動。 474 * @og.rev 8.5.6.1 (2024/03/29) thead に、固定の id と class 属性を共通に定義します。 475 * 476 * @param thTag タグの文字列 477 * 478 * @return テーブルのタグ文字列 479 * @og.rtnNotNull 480 */ 481 protected String getHeadLine( final String thTag ) { 482 483 final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE ) 484// .append( "<tr class=\"row_h\" >" ).append( CR ); 485 .append( "<tr>" ).append( CR ); // 8.5.6.1 (2024/03/29) row_h は、theadタグへ 486 487 for( int column=0; column<CLM_CNT; column++ ) { 488 if( isColumnDisplay( column ) ) { 489 buf.append( thTag ) 490 .append(" class=\"" ).append( getColumnName( column ) ).append( "\">" ) 491 .append( getColumnLabel(column) ) 492 .append("</th>").append( CR ); 493 } 494 } 495 496 final String thTagTmp = thTag + " class=\"timeVar\" colspan=\"" + 60/intval + "\">" ; 497 498 for( int tm=minStTime; tm<maxEdTime; tm+=60 ) { // ヘッダーは、1時間単位とする。 499 buf.append( thTagTmp ).append( tm/60 ).append("</th>").append( CR ); 500 } 501 502 buf.append("</tr>").append( CR ); 503 504 return buf.toString(); // 6.1.2.0 (2015/01/24) 505 } 506 507 /** 508 * TDタグ文字列を簡易的に合成します。 509 * 510 * ここでは、主に、class 属性、colspan 属性を設定することを目的にしています。 511 * colspan の値によって、動作を変化させています。 512 * 0: タグそのものを生成しません。これは、第一引数をそのまま返します。 513 * 1: colspan 属性を出力しません。(Default値なので) 514 * それ以外は、colspan に引数を設定します。 515 * BODY 部も、無指定の場合は、/> 止めのタグを出力します。 516 * 517 * 返り値の StringBuilder は、第一引数そのものを返します。よって、このメソッドに、 518 * append を連結していくことも可能です。 519 * (return値を使わなくても、第一引数の StringBuilder は変化しています。副作用というやつ。) 520 * 521 * @og.rev 5.4.3.7 (2012/01/20) tdタグ専用に変更。 522 * @og.rev 7.0.1.0 (2018/10/15) XHTML → HTML5 対応(空要素の、"/>" 止めを、">" に変更します)。 523 * 524 * @param buf このStringBuilderに append します。 525 * @param cls 追加する class 属性 526 * @param colspan td , th タグ属性に追加する colspan値。 527 * 0 の場合は、タグ自体を出力しません。 528 * 1 の場合は、colspan を出力しません。 529 * @param body タグの BODY 部に出力する内容(String可変長引数)0件の場合は、BODYなし 530 * 531 * @return appendされたStringBuilder(第一引数と同じオブジェクト) 532 * @og.rtnNotNull 533 */ 534 private StringBuilder appendTDTag( final StringBuilder buf , final String cls , final int colspan , final String... body ) { 535 // 6.3.9.1 (2015/11/27) A method should have only one exit point, and that should be the last statement in the method.(PMD) 536 if( colspan != 0 ) { 537 buf.append( "<td" ); 538 // class 属性の追加 539 if( cls != null && !cls.isEmpty() ) { 540 buf.append( " class=\"" ).append( cls ).append( '"' ); // 6.0.2.5 (2014/10/31) char を append する。 541 } 542 543 // colspan 属性の追加 544 if( colspan > 1 ) { 545 buf.append( " colspan=\"" ).append( colspan ).append( '"' ); // 6.0.2.5 (2014/10/31) char を append する。 546 } 547 548 // 7.0.1.0 (2018/10/15) XHTML → HTML5 対応(空要素の、"/>" 止めを、">" に変更します)。 549 if( body == null || body.length == 0 ) { // 6.3.9.1 (2015/11/27) 可変長引数でもnullは来る。 550// buf.append( " />" ); 551 buf.append( " ></td>" ); // 7.0.1.0 (2018/10/15) 552 } 553 else { 554 buf.append( '>' ); // 6.0.2.5 (2014/10/31) char を append する。 555 for( final String bd : body ) { 556 buf.append( bd ).append( ' ' ); // 6.3.9.1 (2015/11/27) スペースで連結追加 557 } 558 buf.append( "</td>" ); 559 } 560 } 561 562 return buf; 563 } 564 565 /** 566 * 時間文字列を数字に変換します。 567 * 568 * "0800" は、480に、"2100" は、1260 に変換します。 569 * 570 * @og.rev 5.4.3.7 (2012/01/20) 計算方法の変更 571 * 572 * @param val 時間文字列の値(0800 など) 573 * @param defTm 引数の時間文字列が null の場合の初期値 574 * 575 * @return 時間文字列を数字に変換した結果( 80 など) 576 */ 577 private int getStr2Time( final String val , final int defTm ) { 578 // 6.3.9.1 (2015/11/27) A method should have only one exit point, and that should be the last statement in the method.(PMD) 579 final int rtn ; 580 if( val == null || val.isEmpty() ) { rtn = defTm; } 581 else if( val.length() == 4 ) { 582 rtn = Integer.parseInt( val.substring( 0,2 ) )*60 + 583 Integer.parseInt( val.substring( 2 ) ) ; // 5.4.3.7 (2012/01/20) 584 } 585 else { 586 final String errMsg = "時間引数は、4桁必要です。" + 587 " val=[" + val + "]"; 588 throw new HybsSystemException( errMsg ); 589 } 590 591 return rtn ; 592 } 593 594 /** 595 * 数字を時間文字列に変換します。 596 * 597 * 480は、"0800" に、"1260"は、2100 に変換します。 598 * 599 * @og.rev 5.4.3.7 (2012/01/20) 計算方法の変更 600 * 601 * @param timeVal 引数の時間文字列が null の場合の初期値 602 * 603 * @return 数字を時間文字列に変換した結果( "0800" など) 604 * @og.rtnNotNull 605 */ 606 private String getInt2StrTime( final int timeVal ) { 607 int tmpVal = timeVal; 608 if( tmpVal < minStTime ) { tmpVal = minStTime; } // 最小値以下の場合は、最小値に合せる 609 else if( tmpVal > maxEdTime ) { tmpVal = maxEdTime; } // 最大値以上の場合は、最大値に合せる。 610 611 return String.valueOf(100+ tmpVal/60).substring(1) + String.valueOf(100+tmpVal%60).substring(1); 612 } 613 614 /** 615 * リンク文字列をパースします。 616 * 617 * データの空欄にリンクを作成するときに、元となるリンク文字列の引数を設定します。 618 * 引数は、&TMSTART=(stTime)&TMEND=(edTime) を追加するイメージです。 619 * stTime、edTime は、それぞれ、($1)、($2) の変数が割り当てられます。 620 * stTime、edTime は、#getInt2StrTime( int ) メソッドで変換した文字列を利用します。 621 * 622 * @param lnkVal リンクのベースとなる値 623 * @param stTime 開始時刻の数字表記 624 * @param edTime 終了時刻の数字表記 625 * 626 * @return リンク文字列をパースした結果 627 */ 628 private String makeLinkValue( final String lnkVal,final int stTime,final int edTime ) { 629 // 6.3.9.0 (2015/11/06) Found 'DD'-anomaly for variable(PMD) 630 return lnkVal == null ? "" 631 : lnkVal.replace( "%28%241%29",getInt2StrTime( stTime ) ) 632 .replace( "%28%242%29",getInt2StrTime( edTime ) ); 633 } 634 635 /** 636 * 表示項目の編集(並び替え)が可能かどうかを返します。 637 * 638 * @return 表示項目の編集(並び替え)が可能かどうか(false:不可能) 639 */ 640 @Override 641 public boolean isEditable() { 642 return false; 643 } 644}