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 */
016 package org.opengion.plugin.view;
017
018 import org.opengion.hayabusa.common.HybsSystem;
019 import org.opengion.hayabusa.common.HybsSystemException;
020 import org.opengion.fukurou.util.StringUtil;
021 import org.opengion.hayabusa.db.DBTableModel;
022 import org.opengion.hayabusa.html.TableFormatter;
023 import org.opengion.hayabusa.html.ViewGanttTableParam;
024
025 import java.util.regex.Pattern;
026 import java.util.regex.Matcher;
027
028 import java.util.Locale;
029 import java.util.TreeSet;
030 import java.util.List;
031 import java.util.Date;
032 import java.util.Calendar;
033 import java.text.SimpleDateFormat;
034 import java.text.ParseException;
035
036 /**
037 * ガントチャーãƒ?ãƒ??ブル形å¼?を作æ?する、ガントチャート表示クラスですã?
038 *
039 * AbstractViewForm により、setter/getterメソãƒ?ƒ‰のãƒ?ƒ•ォルト実è£?‚’提供してã�?�¾すã?
040 * 各HTMLのタグにå¿?¦�な setter/getterメソãƒ?ƒ‰のみ?Œ追åŠ?®š義してã�?�¾すã?
041 *
042 * AbstractViewForm を継承してã�?‚‹為,ロケールに応じたラベルをå?力させる事が出来ますã?
043 *
044 * @og.group 画面表示
045 *
046 * @version 4.0
047 * @author Kazuhiko Hasegawa
048 * @since JDK5.0,
049 */
050 public class ViewForm_HTMLGanttTable extends ViewForm_HTMLTable {
051 //* こã?プログラãƒ??VERSIONæ–?—å?を設定しますã? {@value} */
052 private static final String VERSION = "5.5.4.4 (2012/07/20)" ;
053
054 // 3.5.4.0 (2003/11/25) TableFormatter クラス追åŠ?
055 private TableFormatter headerFormat = null;
056 private TableFormatter[] bodyFormats = null;
057 private TableFormatter footerFormat = null;
058 private int bodyFormatsCount = 0;
059
060 // 繰り返すTD用 3.5.6.0 (2004/06/18) å»?¢
061 private TableFormatter[] itdFormats = null; // 追åŠ?
062
063 private String ganttHeadLine = null;
064 private int[] groupCols = null;
065 private int posDuration = -1;
066 private int posDystart = -1;
067
068 private String formatDystart = ViewGanttTableParam.DYSTART_FORMAT_VALUE;
069 private double minDuration = StringUtil.parseDouble( ViewGanttTableParam.MIN_DURATION_VALUE ) ; // 3.5.5.8 (2004/05/20)
070 private double headerDuration = minDuration ; // 3.5.5.8 (2004/05/20)
071
072 // 3.5.4.6 (2004/01/30) 初期値変更
073 private static final int BODYFORMAT_MAX_COUNT = 10;
074
075 // <(td|th)(.*)>(.*)</(td|th)>を確認すã‚?
076 private static final Pattern cpTdTh =
077 Pattern.compile("\\<(td|th)([^\\>]*)\\>(.*)\\</(td|th)\\>"
078 , Pattern.DOTALL + Pattern.CASE_INSENSITIVE);
079 // 3.5.5.9 (2004/06/07)
080 private int maxDayCnt = 0;
081 private String headerLocale = null;
082 private String[] headDays = null;
083 private int headDaysCnt = 0;
084
085 // 3.5.6.3 (2004/07/12) 行チェãƒ?‚¯による編é›?”¨の hidden
086 private static final String CHECK_ROW =
087 "<input type=\"hidden\" name=\"" + HybsSystem.ROW_SEL_KEY + "\" value=\"";
088
089 // 3.6.1.0 (2005/01/05) 開始日付けと終äº?—¥付けのæŒ?®?
090 private boolean useSeqDay = false;
091 private String startDay = null;
092 private String endDay = null;
093
094 private boolean useItd = false; // 5.0.0.3 (2009/09/22)
095
096 // 4.3.4.4 (2009/01/01)
097 // /**
098 // * ãƒ?ƒ•ォルトコンストラクター
099 // *
100 // */
101 // public ViewForm_HTMLGanttTable() {
102 // super();
103 // }
104
105 /**
106 * å†?®¹をクリア(初期åŒ?しますã?
107 *
108 * @og.rev 3.1.1.0 (2003/03/28) 同期メソãƒ?ƒ‰(synchronized付き)を非同期に変更するã€?
109 * @og.rev 3.5.0.0 (2003/09/17) Noカラãƒ?�«、表示をå?て消せるよã�?�«、class 属æ?を追åŠ??
110 * @og.rev 3.5.4.0 (2003/11/25) TableFormatter クラスを使用するように変更ã€?
111 * @og.rev 3.5.5.8 (2004/05/20) minDuration , headerDuration 追åŠ?? 不要な変数削除
112 * @og.rev 3.5.6.0 (2004/06/18) ithFormat , itdFormat 属æ?削除、itdFormats属æ?を追åŠ?
113 * @og.rev 3.6.1.0 (2005/01/05) startDay,endDay,useSeqDay 属æ?追åŠ?
114 * @og.rev 5.0.0.3 (2009/09/22) itdタグの有無でcolspan対策ã?tdの出力å?数を調整
115 */
116 @Override
117 public void clear() {
118 super.clear();
119
120 headerFormat = null;
121 bodyFormats = null;
122 footerFormat = null;
123 bodyFormatsCount = 0;
124
125 ganttHeadLine = null;
126 itdFormats = null; // 3.5.6.0 (2004/06/18)
127 groupCols = null;
128 posDuration = -1 ;
129 posDystart = -1;
130 formatDystart = ViewGanttTableParam.DYSTART_FORMAT_VALUE;
131 minDuration = StringUtil.parseDouble( ViewGanttTableParam.MIN_DURATION_VALUE ) ; // 3.5.5.8 (2004/05/20)
132 headerDuration = minDuration ; // 3.5.5.8 (2004/05/20)
133
134 maxDayCnt = 0; // 3.5.5.9 (2004/06/07)
135 headerLocale = null; // 3.5.5.9 (2004/06/07)
136 headDays = null; // 3.5.5.9 (2004/06/07)
137 headDaysCnt = 0; // 3.5.5.9 (2004/06/07)
138
139 useSeqDay = false; // 3.6.1.0 (2005/01/05)
140 startDay = null; // 3.6.1.0 (2005/01/05)
141 endDay = null; // 3.6.1.0 (2005/01/05)
142
143 useItd = false; // 5.0.0.3 (2009/09/22)
144 }
145
146 /**
147 * DBTableModel から HTMLæ–?—å?を作æ?して返しますã?
148 * startNo(表示開始位置)から、pageSize(表示件数)までのViewæ–?—å?を作æ?しますã?
149 * 表示残りãƒ??タã�?pageSize 以下ã?場合ã?,残りのãƒ??タをすべて出力しますã?
150 *
151 * @og.rev 3.5.0.0 (2003/09/17) BODY要ç´?? noClass 属æ?を追åŠ??
152 * @og.rev 3.5.0.0 (2003/09/17) <tr>属æ?は、å?のフォーマットã?まま使用しますã?
153 * @og.rev 3.5.2.0 (2003/10/20) ヘッãƒ??繰り返し属æ?( headerSkipCount )を採用
154 * @og.rev 3.5.3.1 (2003/10/31) skip属æ?を採用。headerLine のキャãƒ?‚·ュクリア
155 * @og.rev 3.5.4.0 (2003/11/25) TableFormatter クラスを使用するように変更ã€?
156 * @og.rev 3.5.5.0 (2004/03/12) systemFormat(例:[KEY.カラãƒ?��]形式ç?の対å¿?
157 * @og.rev 3.5.5.9 (2004/06/07) IEの colspan が上手く動かなã�?¯¾策ã?
158 * @og.rev 3.5.5.9 (2004/06/07) [#カラãƒ?��] , [$カラãƒ?��] に対å¿?
159 * @og.rev 3.5.6.0 (2004/06/18) itdFormat をã?BODY毎ã?Formatを使用するように修正
160 * @og.rev 3.5.6.0 (2004/06/18) '!' 値のみ 追åŠ?既存ã? '$' は、レンãƒ?ƒ©ー
161 * @og.rev 3.5.6.3 (2004/07/12) 行チェãƒ?‚¯による編é›?�Œ出来るよã�?�«機è?を追åŠ?
162 * @og.rev 3.5.6.4 (2004/07/16) ヘッãƒ??とボディー部をJavaScriptでåˆ?›¢
163 * @og.rev 3.6.1.0 (2005/01/05) 行チェãƒ?‚¯による編é›?�Œ、検索即登録時も可能なようにしますã?
164 * @og.rev 4.0.0.0 (2005/01/31) 新規作æ?(getColumnClassName â‡?getColumnDbType)
165 * @og.rev 3.7.0.1 (2005/01/31) E の colspan バグ対応で入れたæœ?µ‚行ã? 空タグを消す為の修正
166 * @og.rev 4.3.1.0 (2008/09/08) フォーマットが設定されてã�?�ªã�??合ã?エラー追åŠ?
167 * @og.rev 4.3.7.4 (2009/07/01) tbodyタグの入れ子を解æ¶?FireFox対å¿?
168 * @og.rev 5.0.0.3 (2009/09/22) itdタグの有無でcolspan対策ã?tdの出力å?数を調整
169 * @og.rev 5.5.4.4 (2012/07/20) 二重チェãƒ?‚¯状態になってしまã�?¯¾ç?
170 *
171 * @param stNo 表示開始位置
172 * @param pgSize 表示件数
173 *
174 * @return DBTableModelから作æ?されã�?HTMLæ–?—å?
175 */
176 @Override
177 public String create( final int stNo, final int pgSize ) {
178 // ガントã?、キーブレイクがあるためã?全件表示しますã?
179 int startNo = 0;
180 int pageSize = getRowCount() ;
181 if( pageSize == 0 ) { return ""; } // 暫定å?置
182 boolean outputCheck = true; // 5.5.4.4. (2012/07/20) チェãƒ?‚¯ボックス出力判å®?
183
184 // 4.3.1.0 (2008/09/08)
185 if( headerFormat == null ) {
186 String errMsg = "ViewTagで canUseFormat() = true の場合ã?Formatter はå¿??ですã?";
187 throw new HybsSystemException( errMsg );
188 }
189
190 headerLine = null; // 3.5.3.1 (2003/10/31) キャãƒ?‚·ュクリア
191
192 int lastNo = getLastNo( startNo, pageSize );
193 int blc = getBackLinkCount();
194 int hsc = getHeaderSkipCount(); // 3.5.2.0 (2003/10/20)
195 int hscCnt = 1; // 3.5.2.0 (2003/10/20)
196
197 // こã?ビューの特有な属æ?をå?期化
198 paramInit();
199
200 StringBuilder out = new StringBuilder( HybsSystem.BUFFER_LARGE );
201
202 out.append( getCountForm( startNo,pageSize ) );
203
204 if( posDuration < 0 ) { ganttHeadLine = getGanttHeadNoDuration(startNo, lastNo); }
205 else { ganttHeadLine = getGanttHead(startNo, lastNo); }
206
207 out.append( getHeader() );
208
209 if( bodyFormatsCount == 0 ) {
210 bodyFormats[0] = headerFormat ;
211 bodyFormatsCount ++ ;
212 }
213 else {
214 for( int i=0; i<bodyFormatsCount; i++ ) {
215 bodyFormats[i].makeFormat( getDBTableModel() );
216 if( itdFormats[i] != null ) {
217 itdFormats[i].makeFormat( getDBTableModel() );
218 }
219 }
220 }
221 // out.append("<tbody>").append( HybsSystem.CR ); // 4.3.7.4 (2009/07/01)
222
223 String[] astrOldGroupKeys = new String[groupCols.length];
224 for( int nIndex =0; nIndex < astrOldGroupKeys.length; nIndex++) {
225 astrOldGroupKeys[nIndex] = "";
226 }
227
228 StringBuilder bodyBuf = null, itdBuf = null;
229 boolean checked = false; // 3.5.6.3 (2004/07/12)
230 int bgClrCnt = 0;
231 TableFormatter itdFormat = null;
232 for( int row=startNo; row<lastNo; row++ ) {
233 outputCheck = true; // 5.5.4.4. (2012/07/20)
234 // ガントでは、データのスキãƒ??は行いませんã€?
235
236 if(! isSameGroup(row, astrOldGroupKeys)) {
237 // 3.5.6.3 (2004/07/12) キーブレイク時にチェãƒ?‚¯行かどã�?�‹を記録
238 checked = getDBTableModel().isRowChecked( row );
239
240 if( row != startNo ) {
241 // ヘッãƒ??日付けが残ってã�?‚‹のに、データがなくなったå?å�?
242 while( headDays != null && headDaysCnt < headDays.length ) {
243 itdBuf.append( "<td></td>" );
244 headDaysCnt++;
245 }
246 out.append(StringUtil.replace(bodyBuf.toString(), TableFormatter.HYBS_ITD_MARKER, itdBuf.toString()));
247 itdBuf = null;
248 headDaysCnt = 0;
249 }
250
251 bodyBuf = new StringBuilder( HybsSystem.BUFFER_LARGE );
252
253 // カラãƒ??グループがブレイクするまで、BodyFormatは同ä¸?�§ある前提
254 for( int i=0; i<bodyFormatsCount; i++ ) {
255 TableFormatter bodyFormat = bodyFormats[i];
256 if( ! bodyFormat.isUse( row,getDBTableModel() ) ) { continue; } // 3.5.4.0 (2003/11/25)
257 itdFormat = itdFormats[i]; //
258
259 bodyBuf.append("<tbody").append( getBgColorCycleClass( bgClrCnt++ ) ).append(">");
260 bodyBuf.append( bodyFormat.getTrTag() );
261
262 // 3.5.5.0 (2004/03/12) No æ¬?��のもã?の作æ?判断追åŠ?
263 if( isNumberDisplay() ) {
264 String ckboxTD = "<td" + bodyFormat.getRowspan() + ">";
265 bodyBuf.append( makeCheckbox( ckboxTD,row,blc ) );
266 outputCheck = false; // 5.5.4.4. (2012/07/20)
267 }
268
269 int cl = 0;
270 for( ; cl < bodyFormat.getLocationSize(); cl++ ) {
271 String fmt = bodyFormat.getFormat(cl);
272 int loc = bodyFormat.getLocation(cl); // 3.5.5.0
273 if( ! bodyFormat.isNoClass() ) {
274 StringBuilder newtg = new StringBuilder( HybsSystem.BUFFER_LARGE );
275 newtg.append("<td class=\"");
276 if( loc >= 0 ) { newtg.append(getColumnDbType(loc)); } // 4.0.0 (2005/01/31)
277 newtg.append("\" ");
278 String tdclass = newtg.toString();
279 fmt = StringUtil.replace( bodyFormat.getFormat(cl) ,"<td", tdclass );
280 }
281 bodyBuf.append( fmt ); // 3.5.0.0
282 // 3.5.5.9 (2004/06/07) #,$ 対å¿?
283 if( loc >= 0 ) {
284 switch( bodyFormat.getType(cl) ) {
285 case '#' : bodyBuf.append( getColumnLabel(loc) ); break;
286 case '$' : bodyBuf.append( getRendererValue(row,loc) ); break;
287 case '!' : bodyBuf.append( getValue(row,loc) ); break;
288 default : bodyBuf.append( getValueLabel(row,loc) ); break;
289 }
290 }
291 else {
292 bodyBuf.append( bodyFormat.getSystemFormat(row,loc) );
293 }
294 }
295 bodyBuf.append( bodyFormat.getFormat(cl) );
296 bodyBuf.append("</tbody>").append( HybsSystem.CR );
297 }
298
299 // 3.5.2.0 (2003/10/20) ヘッãƒ??繰り返し属æ?( headerSkipCount )を採用
300 if( hsc > 0 && hscCnt % hsc == 0 ) {
301 bodyBuf.append("<tbody class=\"row_h\"").append(" >");
302 bodyBuf.append( getHeadLine() );
303 bodyBuf.append("</tbody>");
304 hscCnt = 1;
305 }
306 else {
307 hscCnt ++ ;
308 }
309 }
310
311 // 3.5.6.3 (2004/07/12) キーブレイク時ã?チェãƒ?‚¯行ã?状態を繰り返し行に反映
312 // 3.6.1.0 (2005/01/05) さらに、外部でチェãƒ?‚¯をå?れてã�?‚‹場合ã?、å?別対応するã?
313 // if( checked || isChecked( row ) ) {
314 if( (checked || isChecked( row )) && outputCheck ) { // 5.5.4.4. (2012/07/20)
315 getDBTableModel().setRowWritable( row,true );
316 out.append( CHECK_ROW );
317 out.append( row );
318 out.append( "\" />" );
319 }
320
321 itdBuf = formatItd(row, itdFormat, itdBuf);
322 }
323
324 // 残ったデータをå?åŠ?
325 if( null != itdBuf ) {
326 // ヘッãƒ??日付けが残ってã�?‚‹のに、データがなくなったå?å�?
327 while( headDays != null && headDaysCnt < headDays.length ) {
328 itdBuf.append( "<td></td>" );
329 headDaysCnt++;
330 }
331 out.append(StringUtil.replace(bodyBuf.toString(), TableFormatter.HYBS_ITD_MARKER, itdBuf.toString()));
332 }
333
334 // 3.5.5.9 (2004/06/07) IEの colspan が上手く動かなã�?¯¾策ã?
335 // minDuration がã?1.0 以下ã?場合ã?み実è¡?
336 if( minDuration < 1.0d ) {
337 // int tdCount = (int)Math.round( maxDayCnt / minDuration );
338 // 5.0.0.3 (2009/09/22) itdタグの有無でtdCountを変えるã?
339 int tdCount = useItd ? (int) Math.round( maxDayCnt / minDuration ) : headerFormat.getLocationSize();
340
341 // 3.7.0.1 (2005/01/31) E の colspan バグ対応で入れたæœ?µ‚行ã? 空タグを消す為の修正
342 out.append("<tbody><tr class=\"dummy\">").append( HybsSystem.CR );
343 for( int i=0; i<tdCount; i++ ) {
344 out.append( "<td/>" );
345 }
346 out.append("</tr></tbody>").append( HybsSystem.CR );
347 }
348
349 if( footerFormat != null ) {
350 out.append( getTableFoot() );
351 }
352
353 // out.append("</tbody>").append( HybsSystem.CR ); 4.3.7.4 (2009/07/01)
354 out.append("</table>").append( HybsSystem.CR );
355
356 out.append( getScrollBarEndDiv() ); // 3.8.0.3 (2005/07/15)
357 return out.toString();
358 }
359
360 /**
361 * こã?ビã?に対する特別な初期化を行うã€?
362 *
363 * @og.rev 3.5.4.0 (2003/11/25) TableFormatter クラスを使用するように変更ã€?
364 * @og.rev 3.5.5.9 (2004/06/07) ヘッãƒ??の日付け表示に、Locale を加味できるように変更
365 * @og.rev 3.6.1.0 (2005/01/05) startDay,endDay,useSeqDay 属æ?追åŠ?
366 */
367 private void paramInit() {
368
369 String strGroupCols = getParam( ViewGanttTableParam.GROUP_COLUMNS_KEY ,ViewGanttTableParam.GROUP_COLUMNS_VALUE );
370 String strColDuration = getParam( ViewGanttTableParam.DURATION_COLUMN_KEY ,null );
371 String strColDystart = getParam( ViewGanttTableParam.DYSTART_COLUMN_KEY ,ViewGanttTableParam.DYSTART_COLUMN_VALUE );
372 formatDystart = getParam( ViewGanttTableParam.DYSTART_FORMAT_KEY ,ViewGanttTableParam.DYSTART_FORMAT_VALUE );
373 String strMinDuration = getParam( ViewGanttTableParam.MIN_DURATION_KEY ,ViewGanttTableParam.MIN_DURATION_VALUE );
374 String strHeadDuration = getParam( ViewGanttTableParam.HEADER_DURATION_KEY ,strMinDuration );
375 headerLocale = getParam( ViewGanttTableParam.HEADER_LOCALE_KEY ,ViewGanttTableParam.HEADER_LOCALE_VALUE );
376 startDay = getParam( ViewGanttTableParam.START_DAY_KEY ,null ); // 3.6.1.0 (2005/01/05)
377 endDay = getParam( ViewGanttTableParam.END_DAY_KEY ,null ); // 3.6.1.0 (2005/01/05)
378
379 String seqDay = getParam( ViewGanttTableParam.USE_SEQ_DAY_KEY ,ViewGanttTableParam.USE_SEQ_DAY_VALUE ); // 3.6.1.0 (2005/01/05)
380 useSeqDay = Boolean.valueOf( seqDay ).booleanValue() ;
381
382 DBTableModel table = getDBTableModel();
383
384 // 3.5.5.9 (2004/06/07) durationColumn を指定しなã�??合ã?処ç�?‚’追åŠ?
385 if( strColDuration != null ) {
386 posDuration = table.getColumnNo( strColDuration );
387 }
388
389 posDystart = table.getColumnNo( strColDystart );
390
391 String[] groupKeys = StringUtil.csv2Array(strGroupCols);
392 groupCols = new int[groupKeys.length];
393 for( int nIndex = 0; nIndex < groupCols.length ; nIndex++) {
394 groupCols[nIndex] = table.getColumnNo( groupKeys[nIndex] );
395 }
396
397 minDuration = StringUtil.parseDouble( strMinDuration );
398 if( minDuration <= 0.0d ) {
399 String errMsg = "æœ?°�期間単ä½?minDuration)がã???かそれ以下ですã?";
400 throw new HybsSystemException( errMsg );
401 }
402
403 headerDuration = StringUtil.parseDouble( strHeadDuration );
404 if( headerDuration <= 0.0d ) {
405 String errMsg = "ヘッãƒ??の表示期間(headerDuration)がã???かそれ以下ですã?";
406 throw new HybsSystemException( errMsg );
407 }
408
409 // 3.5.5.9 (2004/06/07) エラーチェãƒ?‚¯の強åŒ?
410 // 4.0.0 (2005/01/31) Equality checks with floating point numbers can lead to unexpected behavior.
411 if( posDuration < 0 && (
412 Double.compare( minDuration,1.0d ) != 0 ||
413 Double.compare( headerDuration,1.0d ) != 0 ) ) {
414
415 String errMsg = "期間カラãƒ?durationColumn)を指定しなã�??合ã?ã€?
416 + "æœ?°�期間単ä½?minDuration)およびã€?
417 + "ヘッãƒ??の表示期間(headerDuration)ã‚?'1' 以外に設定できませんã€?;
418 throw new HybsSystemException( errMsg );
419 }
420 }
421
422 /**
423 * 上下行ã?ãƒ??タが同じグルプかどã�?�‹をチェãƒ?‚¯するã€?
424 *
425 * @param nRowIndex ãƒ??ブルモãƒ?ƒ«の行番号
426 * @param astrOldValues 古ã�?‚°ルプデータ
427 *
428 * @return 使用可能(true)/ 使用不可能 (false)
429 */
430 private boolean isSameGroup(final int nRowIndex, final String[] astrOldValues) {
431 boolean bRet = (groupCols.length > 0);
432 if( bRet ) {
433 for( int nIndex = 0; bRet && ( nIndex < groupCols.length ); nIndex++) {
434 bRet = ( astrOldValues[nIndex].equals(getValue(nRowIndex, groupCols[nIndex])));
435 }
436
437 // 不ä¸??時に astrOldValues に 新しい値を設定しておきますã?
438 if(!bRet) {
439 for( int nIndex = 0; nIndex < groupCols.length; nIndex++) {
440 astrOldValues[nIndex] = getValue(nRowIndex, groupCols[nIndex]);
441 }
442 }
443 }
444
445 return bRet;
446 }
447
448 /**
449 * DBTableModel から ãƒ??ブルのタグæ–?—å?を作æ?して返しますã?
450 *
451 * @og.rev 3.5.0.0 (2003/09/17) <tr>属æ?は、å?のフォーマットã?まま使用しますã?
452 * @og.rev 3.5.1.0 (2003/10/03) Noカラãƒ?�«、numberType 属æ?を追åŠ?
453 * @og.rev 3.5.2.0 (2003/10/20) ヘッãƒ??繰り返し部をgetHeadLine()へ移å‹?
454 * @og.rev 3.5.3.1 (2003/10/31) VERCHAR2 ã‚?VARCHAR2 に修正ã€?
455 * @og.rev 3.5.4.0 (2003/11/25) TableFormatter クラスを使用するように変更ã€?
456 * @og.rev 3.5.6.5 (2004/08/09) thead に、id="header" を追åŠ?
457 * @og.rev 4.0.0.0 (2005/01/31) DBColumn の 属æ?(CLS_NM)から、DBTYPEに変更
458 *
459 * @return ãƒ??ブルのタグæ–?—å?
460 */
461 @Override
462 protected String getTableHead() {
463 headerFormat.makeFormat( getDBTableModel() );
464
465 StringBuilder buf = new StringBuilder( HybsSystem.BUFFER_MIDDLE );
466 // 3.5.5.0 (2004/03/12) No æ¬?��のもã?の作æ?判断追åŠ?
467 if( isNumberDisplay() ) {
468 buf.append("<colgroup class=\"X\" />"); // 4.0.0 (2005/01/31)
469 buf.append("<colgroup class=\"BIT\" />");
470 buf.append("<colgroup class=\"S9\" />"); // 4.0.0 (2005/01/31)
471 buf.append(HybsSystem.CR);
472 }
473
474 // 3.5.2.0 (2003/10/20) ヘッãƒ??繰り返し部をgetHeadLine()へ移å‹?
475 buf.append("<thead id=\"header\">").append( HybsSystem.CR ); // 3.5.6.5 (2004/08/09)
476 buf.append( getHeadLine() );
477 buf.append("</thead>").append( HybsSystem.CR );
478
479 return buf.toString();
480 }
481
482 /**
483 * ヘッãƒ??繰り返し部をã?getTableHead()メソãƒ?ƒ‰からåˆ?›¢ã€?
484 *
485 * @og.rev 3.5.2.0 (2003/10/20) 新規作æ?
486 * @og.rev 3.5.4.0 (2003/11/25) TableFormatter クラスを使用するように変更ã€?
487 * @og.rev 3.5.4.3 (2004/01/05) useCheckControl 属æ?の機è?を追åŠ?
488 * @og.rev 3.5.4.6 (2004/01/30) numberType="none" 時ã?処ç�?‚’追åŠ?Noラベルをå?さなã�?
489 * @og.rev 3.5.4.7 (2004/02/06) ヘッãƒ??にソート機è?用のリンクを追åŠ?�—ますã?
490 * @og.rev 3.5.5.0 (2004/03/12) systemFormat(例:[KEY.カラãƒ?��]形式ç?の対å¿?
491 * @og.rev 3.7.0.1 (2005/01/31) 全件チェãƒ?‚¯コントロール処ç�?¤‰更
492 * @og.rev 5.0.0.3 (2009/09/22) itdの有無を取得しますã?
493 *
494 * @return ãƒ??ブルのタグæ–?—å?
495 */
496 @Override
497 protected String getHeadLine() {
498 if( headerLine != null ) { return headerLine; } // キャãƒ?‚·ュを返すã€?
499
500 StringBuilder buf = new StringBuilder( HybsSystem.BUFFER_MIDDLE );
501
502 buf.append( headerFormat.getTrTag() ).append( HybsSystem.CR );
503
504 // 3.5.5.0 (2004/03/12) No æ¬?��のもã?の作æ?判断追åŠ?
505 if( isNumberDisplay() ) {
506 // 3.5.4.3 (2004/01/05) 追åŠ??
507 if( isUseCheckControl() && "checkbox".equals( getSelectedType() ) ) {
508 buf.append(" <th" ).append( headerFormat.getRowspan() ).append("></th>");
509 buf.append(" <th" ).append( headerFormat.getRowspan() );
510 buf.append(">").append( getAllCheckControl() ).append( "</th>");
511 buf.append(" <th" ).append( headerFormat.getRowspan() );
512 buf.append(">").append( getNumberHeader() ).append("</th>"); // 3.5.4.6 (2004/01/30)
513 }
514 else {
515 buf.append(" <th colspan=\"3\"");
516 buf.append( headerFormat.getRowspan() );
517 buf.append(">").append( getNumberHeader() ).append("</th>"); // 3.5.4.6 (2004/01/30)
518 }
519 }
520
521 int cl = 0;
522 for( ; cl < headerFormat.getLocationSize(); cl++ ) {
523 buf.append( headerFormat.getFormat(cl) );
524 int loc = headerFormat.getLocation(cl);
525 if( loc >= 0 ) { buf.append( getSortedColumnLabel(loc) ); }
526 }
527 buf.append( headerFormat.getFormat(cl) ).append( HybsSystem.CR );
528
529 // 5.0.0.3 (2009/09/22) ITD_MARKERの条件判断追åŠ?
530 if( buf.indexOf( TableFormatter.HYBS_ITD_MARKER ) >= 0 ){
531 useItd = true;
532 }
533 headerLine = StringUtil.replace(buf.toString(), TableFormatter.HYBS_ITD_MARKER, ganttHeadLine);
534
535 return headerLine;
536 }
537
538 /**
539 * ガントチャートã?ãƒ?ƒ€ー繰り返し部をã?getTableHead()メソãƒ?ƒ‰からåˆ?›¢ã€?
540 * こã?メソãƒ?ƒ‰は、durationColumn を利用してã€??続日付けãƒ??タを作æ?しますã?
541 * ãƒ??タはã€?–‹始日と期間ãƒ??タを持ち、ã?ãƒ?ƒ€ーは連続日付けになりますã?
542 * ヘッãƒ??の期間(headerDuration)とãƒ??タのæœ?°�期é–?minDuration)が異なる為ã€?
543 * æœ??の行データより、最終日を求め、headerDuration で割り算したå?数の連続日数ã‚?
544 * 表示させてã�?�¾すã?
545 *
546 * @og.rev 3.5.5.9 (2004/06/07) ヘッãƒ??の日付け表示に、Locale を加味できるように変更
547 * @og.rev 3.5.6.0 (2004/06/18) ithFormat 変数削除
548 *
549 * @param startNo 開始行番号
550 * @param lastNo æœ?µ‚行番号
551 *
552 * @return ãƒ??ブルのタグæ–?—å?
553 */
554 private String getGanttHead(final int startNo, final int lastNo) {
555 String[] astrOldGroupKeys = new String[groupCols.length];
556 for( int nIndex =0; nIndex < astrOldGroupKeys.length; nIndex++) {
557 astrOldGroupKeys[nIndex] = "";
558 }
559
560 // 3.5.5.9 (2004/06/07) ヘッãƒ??の日付け表示に、Locale を加味できるように変更
561 Locale local = new Locale( headerLocale );
562 SimpleDateFormat fmtDate = new SimpleDateFormat( formatDystart,local );
563
564 double nSumDuration = 0.0d ;
565 Date dFirst = null ;
566
567 for( int nRowUp = startNo; nRowUp < lastNo; nRowUp++ ) {
568 // ガントでは、データのスキãƒ??は行いませんã€?
569
570 // æœ??のè¡?またã?、ブレイクするまで
571 if( isSameGroup(nRowUp, astrOldGroupKeys) || (nRowUp == startNo) ) {
572 nSumDuration += StringUtil.parseDouble( getValue(nRowUp, posDuration) );
573 try {
574 if( dFirst == null ) {
575 dFirst = fmtDate.parse(getValue(nRowUp, posDystart));
576 }
577 }
578 catch ( ParseException ex) {
579 String errMsg = "DYSTARTにæŒ?®šした日付形式と異なるデータが存在してã�?�¾すã?"
580 + "[" + getValue(nRowUp , posDystart) + "] => ["
581 + fmtDate.toPattern() + "]" ;
582 throw new HybsSystemException( errMsg,ex );
583 }
584 }
585 else { break; }
586 }
587
588 String thVal = "" ; // <td ?¥?¥?¥> の <td 以下ã? ?¥?¥?¥部åˆ??属æ?æ–?—å?ã€?
589 String ymdForm = "MM/dd" ; // td タグの BODY 部 の 日付けフォーマッãƒ?
590
591 if( headerFormat != null ) {
592 String format = headerFormat.getItdBody().trim() ;
593 Matcher matcher = cpTdTh.matcher(format);
594 if( matcher.find() ) {
595 thVal = matcher.group(2);
596 ymdForm = matcher.group(3);
597 }
598 }
599
600 try {
601 fmtDate.applyPattern(ymdForm);
602 }
603 catch(IllegalArgumentException eArg) {
604 String errMsg = "theadのå†??itdのå†??にæŒ?®šされた日付ã?形式が不正ですã?(" + ymdForm + ")";
605 throw new HybsSystemException( errMsg,eArg );
606 }
607
608 int colspan = (int)Math.round( headerDuration / minDuration );
609 final String th ;
610 if( colspan == 1 ) { th = "<th " + thVal + ">"; }
611 else { th = "<th colspan=\"" + colspan + "\" " + thVal + ">" ; }
612
613 Calendar cal = Calendar.getInstance() ;
614 cal.setTime( dFirst );
615
616 maxDayCnt = (int)Math.round(nSumDuration / headerDuration) ; // 3.5.5.9 (2004/06/07)
617 int addDate ;
618 int field ;
619 if( headerDuration >= 1.0d ) {
620 addDate = (int)Math.round( headerDuration );
621 field = Calendar.DATE ;
622 }
623 else {
624 addDate = (int)Math.round( 24.0d * headerDuration );
625 field = Calendar.HOUR_OF_DAY ;
626 }
627
628 // 端数を指定すると、積算誤差がでますã?
629 StringBuilder buf = new StringBuilder( HybsSystem.BUFFER_MIDDLE );
630
631 for( int nIndex = 0; nIndex < maxDayCnt; nIndex++ ) {
632 buf.append( th );
633 buf.append( fmtDate.format( cal.getTime() ) );
634 buf.append( "</th>" );
635 cal.add( field ,addDate );
636 }
637
638 return buf.toString();
639 }
640
641 /**
642 * ガントチャートã?ãƒ?ƒ€ー繰り返し部をã?getTableHead()メソãƒ?ƒ‰からåˆ?›¢ã€?
643 * こã?メソãƒ?ƒ‰は、durationColumn が指定されてã�?�ªã�??合ã?処ç�?‚’行いますã?
644 * ãƒ??タは、すべての行に関して、同じ日付けのãƒ??タとして扱われますã?
645 * よって、行間で、日付け違いの並びé ?�«なってã�?‚‹とずれることがありますã?
646 * ヘッãƒ??は、最初ã?行ã?日付けをそのまま表示させますã?よって、データと
647 * 日付けが同期されてã�?‚Œば、不é?続な日付けのヘッãƒ??を表示させることも可能ですã?
648 * ヘッãƒ??の期間(headerDuration)とãƒ??タのæœ?°�期é–?minDuration)はã€?
649 * ともにã€?1' であることが前提ですã?
650 * useSeqDay 属æ?にã€?true" を設定するとã€?–‹始日(startDay)と終äº?—¥(endDay)
651 * の日付けをé?続した日付けとしますã?開始日(startDay)ã‚?µ‚äº?—¥(endDay)が指å®?
652 * されてã�?�ªã�??合ã?、dystartColumn 属æ?でæŒ?®šされたカラãƒ??値のæœ?¤§値、最小å?ã‚?
653 * 自動セãƒ?ƒˆしますã?
654 *
655 * @og.rev 3.5.5.9 (2004/06/07) 新規作æ?
656 * @og.rev 3.5.6.0 (2004/06/18) ithFormat 変数削除
657 * @og.rev 3.6.1.0 (2005/01/05) startDay,endDay,useSeqDay 属æ?追åŠ?
658 *
659 * @param startNo 開始行番号
660 * @param lastNo æœ?µ‚行番号
661 *
662 * @return ãƒ??ブルのタグæ–?—å?
663 */
664 private String getGanttHeadNoDuration(final int startNo, final int lastNo) {
665 String[] astrOldGroupKeys = new String[groupCols.length];
666 for( int nIndex =0; nIndex < astrOldGroupKeys.length; nIndex++) {
667 astrOldGroupKeys[nIndex] = "";
668 }
669
670 String thVal = "" ; // <td ?¥?¥?¥> の <td 以下ã? ?¥?¥?¥部åˆ??属æ?æ–?—å?ã€?
671 String ymdForm = "MM/dd" ; // td タグの BODY 部 の 日付けフォーマッãƒ?
672
673 if( headerFormat != null ) {
674 String format = headerFormat.getItdBody().trim() ;
675 Matcher matcher = cpTdTh.matcher(format);
676 if( matcher.find() ) {
677 thVal = matcher.group(2);
678 ymdForm = matcher.group(3);
679 }
680 }
681 String th = "<th " + thVal + ">";
682
683 // 3.5.5.9 (2004/06/07) ヘッãƒ??の日付け表示に、Locale を加味できるように変更
684 Locale local = new Locale( headerLocale );
685 SimpleDateFormat dataFmt = new SimpleDateFormat( formatDystart,local );
686 SimpleDateFormat headFmt = new SimpleDateFormat( ymdForm,Locale.JAPAN );
687 Calendar cal = Calendar.getInstance() ;
688
689 TreeSet<String> daySet = new TreeSet<String>();
690 for( int nRowUp = startNo; nRowUp < lastNo; nRowUp++ ) {
691 // ガントでは、データのスキãƒ??は行いませんã€?
692
693 String day = getValue(nRowUp, posDystart);
694 daySet.add( day );
695 }
696 // 3.6.1.0 (2005/01/05)
697 if( useSeqDay ) {
698 if( startDay == null ) { startDay = daySet.first() ; }
699 if( endDay == null ) { endDay = daySet.last() ; }
700
701 try {
702 Calendar startCal = Calendar.getInstance() ;
703 Date dStart = dataFmt.parse( startDay );
704 startCal.setTime( dStart );
705
706 Calendar endCal = Calendar.getInstance() ;
707 Date dEnd = dataFmt.parse( endDay );
708 endCal.setTime( dEnd );
709 endCal.set( Calendar.HOUR_OF_DAY,12 ); // 日付け比è¼?�™る為ã€?¼‘2時間é?めておくã€?
710
711 while( startCal.before( endCal ) ) {
712 daySet.add( dataFmt.format( startCal.getTime() ) );
713 startCal.add( Calendar.DATE ,1 );
714 }
715 }
716 catch ( ParseException ex) {
717 String errMsg = "startDay,endDayにæŒ?®šした日付形式と異なるデータが存在してã�?�¾すã?"
718 + "[" + startDay + "],["
719 + "[" + endDay + "] => ["
720 + dataFmt.toPattern() + "]" ;
721 throw new HybsSystemException( errMsg,ex );
722 }
723 }
724
725 headDays = daySet.toArray( new String[daySet.size()] ); // 4.0.0 (2005/01/31)
726
727 StringBuilder buf = new StringBuilder( HybsSystem.BUFFER_MIDDLE );
728 for( int i=0; i<headDays.length; i++ ) {
729
730 try {
731 cal.setTime( dataFmt.parse(headDays[i]) );
732 buf.append( th );
733 buf.append( headFmt.format( cal.getTime() ) );
734 buf.append( "</th>" );
735 }
736 catch ( ParseException ex) {
737 String errMsg = "DYSTARTにæŒ?®šした日付形式と異なるデータが存在してã�?�¾すã?"
738 + "[" + headDays[i] + "] => ["
739 + dataFmt.toPattern() + "]" ;
740 throw new HybsSystemException( errMsg,ex );
741 }
742 }
743
744 return buf.toString();
745 }
746
747 /**
748 * DBTableModel から ãƒ??ブルのタグæ–?—å?を作æ?して返しますã?
749 *
750 * @og.rev 3.5.0.0 (2003/09/17) <tr>属æ?は、å?のフォーマットã?まま使用しますã?
751 * @og.rev 3.5.1.0 (2003/10/03) Noカラãƒ?�«、numberType 属æ?を追åŠ?
752 * @og.rev 3.5.4.0 (2003/11/25) TableFormatter クラスを使用するように変更ã€?
753 * @og.rev 3.5.4.7 (2004/02/06) ヘッãƒ??にソート機è?用のリンクを追åŠ?�—ますã?
754 * @og.rev 3.5.5.0 (2004/03/12) systemFormat(例:[KEY.カラãƒ?��]形式ç?の対å¿?
755 *
756 * @return ãƒ??ブルのタグæ–?—å?
757 */
758 protected String getTableFoot() {
759 footerFormat.makeFormat( getDBTableModel() );
760
761 StringBuilder buf = new StringBuilder( HybsSystem.BUFFER_MIDDLE );
762
763 buf.append("<tfoot>").append( HybsSystem.CR );
764 buf.append( footerFormat.getTrTag() ).append( HybsSystem.CR );
765
766 // 3.5.5.0 (2004/03/12) No æ¬?��のもã?の作æ?判断追åŠ?
767 if( isNumberDisplay() ) {
768 buf.append(" <th");
769 buf.append(" colspan=\"3\"");
770 buf.append( footerFormat.getRowspan() );
771 buf.append("></th>");
772 }
773
774 int cl = 0;
775 for( ; cl < footerFormat.getLocationSize(); cl++ ) {
776 int loc = footerFormat.getLocation(cl);
777 if( loc >= 0 ) { buf.append( getSortedColumnLabel(loc) ); }
778 }
779 buf.append( footerFormat.getFormat(cl) ).append( HybsSystem.CR );
780 buf.append("</tfoot>").append( HybsSystem.CR );
781
782 return buf.toString();
783 }
784
785 /**
786 * itaタグの中身を形式化するã€?
787 *
788 * @og.rev 3.5.5.0 (2004/03/12) systemFormat(例:[KEY.カラãƒ?��]形式ç?の対å¿?
789 * @og.rev 3.5.5.9 (2004/06/07) durationColumn を指定しなã�??合ã?処ç�?‚’追åŠ?
790 * @og.rev 3.5.6.0 (2004/06/18) itdタグの[$xx] , [#xx]対å¿?
791 * @og.rev 3.5.6.0 (2004/06/18) '!' 値のみ 追åŠ?既存ã? '$' は、レンãƒ?ƒ©ー
792 *
793 * @param nTblRow ãƒ??ブルモãƒ?ƒ«の行番号
794 * @param myIteFormat TableFormatteオブジェクãƒ?
795 * @param inputBuf 出力データバã?ファ
796 *
797 * @return StringBuilder戻りå?
798 */
799 StringBuilder formatItd(final int nTblRow, final TableFormatter myIteFormat, final StringBuilder inputBuf ) {
800 if( myIteFormat == null ) { return new StringBuilder( "" ); }
801
802 final StringBuilder strBuf ;
803 if( inputBuf != null ) { strBuf = inputBuf; }
804 else { strBuf = new StringBuilder( HybsSystem.BUFFER_LARGE ); }
805
806 int colspan = 1;
807 if( posDuration >= 0 ) {
808 // 3.7.0.0 (2005/01/18) 小数点の桁落ち対ç?
809 colspan = (int)Math.round( StringUtil.parseDouble( getValue(nTblRow, posDuration) ) / minDuration );
810 }
811 else { // 日付けヘッãƒ??未æº??、空タグをå?力しておく
812 String today = getValue(nTblRow, posDystart);
813 int comp = headDays[headDaysCnt].compareTo( today );
814 headDaysCnt++ ;
815 while( comp < 0 && headDaysCnt < headDays.length ) {
816 strBuf.append( "<td></td>" );
817 comp = headDays[headDaysCnt].compareTo( today );
818 headDaysCnt++ ;
819 }
820 if( comp != 0 ) { // 見つからなかっã�?先に日付けが無くなっã�?
821 String errMsg = "日付けヘッãƒ??と日付けãƒ??タに矛盾が発生してã�?�¾すã?"
822 + HybsSystem.CR
823 + "groupColumns で日付けがユニã?クになってã�?�ªã�?�¯能性がありますã?"
824 + "row=[" + (nTblRow +1) + "] , today=[" + today + "]" ;
825 throw new HybsSystemException( errMsg );
826 }
827 }
828
829 int cl = 0;
830 for( ; cl < myIteFormat.getLocationSize(); cl++ ) {
831 String fmt = myIteFormat.getFormat(cl) ;
832 int loc = myIteFormat.getLocation(cl); // 3.5.6.0
833 if( cl == 0 && colspan != 1 ) {
834 fmt = StringUtil.replace(fmt , "<td", "<td colspan=\"" + colspan + "\"");
835 }
836 strBuf.append( fmt ); // 3.5.6.0
837 if( loc >= 0 ) {
838 switch( myIteFormat.getType(cl) ) {
839 case '#' : strBuf.append( getColumnLabel(loc) ); break;
840 case '$' : strBuf.append( getRendererValue(nTblRow,loc) ); break;
841 case '!' : strBuf.append( getValue(nTblRow,loc) ); break;
842 default : strBuf.append( getValueLabel(nTblRow,loc) ); break;
843 }
844 }
845 else {
846 strBuf.append( myIteFormat.getSystemFormat(nTblRow,loc) );
847 }
848 }
849 strBuf.append(myIteFormat.getFormat(cl));
850
851 return strBuf;
852 }
853
854 /**
855 * フォーマットを設定しますã?
856 *
857 * @og.rev 3.5.4.0 (2003/11/25) 新規作æ?
858 * @og.rev 3.5.4.4 (2004/01/16) 配å?のæœ?¤§数を変更
859 * @og.rev 3.5.6.0 (2004/06/18) ithFormat , itdFormat 変数削除
860 *
861 * @param list TableFormatterのリスãƒ?
862 */
863 @Override
864 public void setFormatterList( final List<TableFormatter> list ) { // 4.3.3.6 (2008/11/15) Generics警告対å¿?
865 bodyFormats = new TableFormatter[BODYFORMAT_MAX_COUNT];
866
867 bodyFormatsCount = 0;
868 for( int i=0; i<list.size(); i++ ) {
869 TableFormatter format = list.get( i ); // 4.3.3.6 (2008/11/15) Generics警告対å¿?
870
871 switch( format.getFormatType() ) {
872 case TYPE_HEAD : headerFormat = format; break;
873 case TYPE_BODY : bodyFormats[bodyFormatsCount++] = format; break;
874 case TYPE_FOOT : footerFormat = format; break;
875 default : String errMsg = "FormatterType の定義外ã?値が指定されましたã€?;
876 // 4.3.4.4 (2009/01/01)
877 throw new HybsSystemException( errMsg );
878 }
879 // 3.5.6.0 (2004/06/18) å»?¢
880 }
881
882 // 3.5.6.0 (2004/06/18) itdFormats 処ç�?¿½åŠ?
883 // tbody 配å?åˆ?� け設定しておきますã?
884 itdFormats = new TableFormatter[bodyFormatsCount];
885 for( int i=0; i<bodyFormatsCount; i++ ) {
886 String format = bodyFormats[i].getItdBody().trim();
887 itdFormats[i] = new TableFormatter();
888 itdFormats[i].setFormat( format );
889 }
890 }
891
892 /**
893 * フォーマットメソãƒ?ƒ‰を使用できるかどã�?�‹を問ã�?�ˆわせますã?
894 *
895 * @return 使用可能(true)/ 使用不可能 (false)
896 */
897 @Override
898 public boolean canUseFormat() {
899 return true;
900 }
901
902 /**
903 * 表示é ?›®の編é›?並び替ã�?が可能かどã�?�‹を返しまã�?
904 *
905 * @og.rev 5.1.6.0 (2010/05/01) 新規追åŠ?
906 *
907 * @return 表示é ?›®の編é›?並び替ã�?が可能かどã�?�‹(false:不可能)
908 */
909 @Override
910 public boolean isEditable() {
911 return false;
912 }
913 }