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.fukurou.util.StringUtil; 020import org.opengion.fukurou.util.XHTMLTag; 021import org.opengion.hayabusa.html.AbstractViewForm; 022import org.opengion.hayabusa.html.ViewCalendarParam; 023import static org.opengion.fukurou.system.HybsConst.BR; // 6.1.0.0 (2014/12/26) refactoring 024 025import java.util.Calendar; 026 027/** 028 * 1ヶ月分のカレンダー形式で、検索結果を表示する、カレンダー表示クラスです。 029 * 030 * AbstractViewForm により、setter/getterメソッドのデフォルト実装を提供しています。 031 * 各HTMLのタグに必要な setter/getterメソッドのみ,追加定義しています。 032 * 033 * AbstractViewForm を継承している為,ロケールに応じたラベルを出力させる事が出来ます。 034 * 035 * @og.group 画面表示 036 * 037 * @version 4.0 038 * @author Kazuhiko Hasegawa 039 * @since JDK5.0, 040 */ 041public class ViewForm_HTMLCalendar extends AbstractViewForm { 042 /** このプログラムのVERSION文字列を設定します。 {@value} */ 043 private static final String VERSION = "6.4.2.0 (2016/01/29)" ; 044 045 private static final String[] WEEK_JA = { "日" ,"月" ,"火" ,"水" ,"木" ,"金" ,"土" ,"日" ,"月" }; // 6.4.1.1 (2016/01/16) WEEK_ja → WEEK_JA refactoring 046 private static final String[] WEEK_EN = { "SUN","MON","TUE","WED","THU","FRI","SAT","SUN","MON" }; // 6.4.1.1 (2016/01/16) WEEK_en → WEEK_EN refactoring 047 private static final String[] WEEK_MK = { "SUN","", "", "", "", "", "SAT","SUN","" }; 048 049 private String[] week ; 050 private String[] viewKeys ; // カレンダを指定するキー配列 // 3.6.0.0 (2004/09/17) 051 private String ymKey ; // 年月のカラム名 052 private String dayKey ; // 休日(0:通常、1:休日)のカラム名 053 private String valKey ; // カレンダに表示する値のカラム名 054 private boolean valueBrFlag ; // 日付けと値の間に、BRタグを入れるかどうか 055 private int firstWeek ; // 曜日の開始(0:日曜 1:月曜) 056 private int columnSize ; // カレンダの横方向の繰り返し数 // 3.6.0.0 (2004/09/17) 057 058 /** 059 * デフォルトコンストラクター 060 * 061 * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor. 062 */ 063 public ViewForm_HTMLCalendar() { super(); } // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。 064 065 /** 066 * DBTableModel から HTML文字列を作成して返します。 067 * startNo(表示開始位置)から、pageSize(表示件数)までのView文字列を作成します。 068 * 表示残りデータが pageSize 以下の場合は,残りのデータをすべて出力します。 069 * 070 * @og.rev 3.5.2.1 (2003/10/27) 属性値の指定のシングルクオートをダブルクオートに変更。 071 * @og.rev 3.6.0.0 (2004/09/17) 複数カレンダに対応 072 * @og.rev 3.6.0.5 (2004/10/18) calenderParam の viewKeys バグ対応。 073 * @og.rev 3.7.0.1 (2005/01/31) 全件チェックコントロール処理変更 074 * 075 * @param startNo 表示開始位置 076 * @param pageSize 表示件数 077 * 078 * @return DBTableModelから作成された HTML文字列 079 * @og.rtnNotNull 080 */ 081 public String create( final int startNo, final int pageSize ) { 082 if( getRowCount() == 0 ) { return ""; } // 暫定処置 083 084 paramInit(); 085 086 final int lastNo = getLastNo( startNo, pageSize ); 087 088 final StringBuilder out = new StringBuilder( BUFFER_LARGE ) 089 .append( "<table><tr>" ).append( CR ); 090 091// final boolean onlyOne = ( lastNo - startNo ) == 1 ; // 互換性のため、1件の処理のみ変更 092 final boolean onlyOne = lastNo - startNo == 1 ; // 互換性のため、1件の処理のみ変更 // 6.9.7.0 (2018/05/14) PMD Useless parentheses. 093 094 // 3.7.0.1 (2005/01/31) 全件チェックコントロール処理変更 095 if( ! onlyOne && isUseCheckControl() && "checkbox".equals( getSelectedType() ) ) { 096 out.append( "<tr><td>" ).append( getAllCheckControl() ).append( "</td></tr>"); 097 } 098 099 for( int row=startNo; row<lastNo; row++ ) { 100 out.append( "<td valign=\"top\">" ); 101 102 if( isWritable( row ) ) { 103 if( onlyOne ) { 104 out.append( XHTMLTag.hidden( HybsSystem.ROW_SEL_KEY,String.valueOf( row ) ) ) 105 .append( CR ); 106 } 107 else { 108 out.append( "<input type=\"" ).append( getSelectedType() ) 109 .append( "\" name=\"" ).append( HybsSystem.ROW_SEL_KEY ).append( '"' ); 110 if( isChecked( row ) ) { out.append( " checked=\"checked\"" ); } 111 out.append( " value=\"" ).append( row ).append( "\" />" ); 112 } 113 } 114 115 // 3.6.0.5 (2004/10/18) 116 for( int col=0; col<viewKeys.length; col++ ) { 117 if( "_".equals( viewKeys[col] ) ) { continue; } 118 final int newCol = getColumnNo( viewKeys[col] ); 119 out.append("<span id=\"label\">") 120 .append( getColumnLabel( newCol ) ) 121 .append( ":</span>" ) 122 .append( getValueLabel(row,newCol) ) 123 .append( " " ); 124 } 125 out.append( BR ) 126 .append( makeCalendarData( row ) ) 127 .append( "</td>" ); 128 if( (row+1) % columnSize == 0 ) { 129 out.append( "</tr><tr>" ).append( CR ); 130 } 131 } 132 out.append( "</tr></table>" ).append( CR ); 133 134 return out.toString(); 135 } 136 137 /** 138 * DBTableModel の指定の行番号より、カレンダのHTML文字列を作成して返します。 139 * 140 * @og.rev 3.6.0.0 (2004/09/17) create( int startNo, int pageSize ) のロジックを移動 141 * @og.rev 3.6.0.5 (2004/10/18) 印刷時の罫線出力関連機能の追加。id 属性を出力します。 142 * 143 * @param row 指定の行番号 144 * 145 * @return 指定の行番号のカレンダのHTML文字列 146 * @og.rtnNotNull 147 */ 148 private String makeCalendarData( final int row ) { 149 final String yyyymm = getValue( row,getColumnNo( ymKey )); 150 final Calendar currentCal = getCalendar( yyyymm ); 151 152 final StringBuilder out = new StringBuilder( BUFFER_LARGE ) 153 .append( "<table id=\"viewCalendar\" border=\"0\" cellpadding=\"1\" cellspacing=\"2\">" ) 154 .append( CR ) // 3.6.0.5 (2004/10/18) 155 .append( " <tr><td class=\"titleStyle\" colspan=\"7\">" ) 156 .append( getValueLabel( row,getColumnNo( ymKey )) ) 157 .append( "</td></tr>" ).append( CR ); 158 159 // 今月の最終日 160 final int daysInMonth = currentCal.getActualMaximum(Calendar.DAY_OF_MONTH); 161 // カレンダーの週の初めを設定する。月曜開始のカレンダーを作成するときに利用 162 currentCal.setFirstDayOfWeek( Calendar.SUNDAY + firstWeek ); 163 164 // 週を表す番号 0~6 の間 165 int culDay = ( currentCal.get(Calendar.DAY_OF_WEEK) 166 + ( 7 - currentCal.getFirstDayOfWeek() ) ) % 7 ; 167 168 // 曜日欄を記述します。 169 out.append(" <tr>").append( CR ); 170 for( int i=0; i<7; i++ ) { 171 out.append(" <td width=\"14%\" class=\"dayHead" ) 172 .append( WEEK_MK[i+firstWeek] ).append( "\">" ) 173 .append( week[i+firstWeek] ).append( "</td>" ) 174 .append( CR ); 175 } 176 out.append(" </tr>").append( CR ) 177 .append(" <tr>").append( CR ); // 6.1.0.0 (2014/12/26) refactoring 178 179 // 第一週の日付欄の空きスペースの計算 180 if( culDay != 0 ) { 181 out.append(" <td colspan=\"" ).append( culDay ).append( "\"> </td>" ).append( CR ); 182 } 183 184 // 日付欄を埋めます。 185 final String BR = valueBrFlag ? "<br />" : "" ; 186 for( int day=1; day <= daysInMonth; day++ ) { 187 final int daycol = getColumnNo( dayKey + day ); // 動的日付けカラム番号取得 188 final String daylbl = getValueLabel( row,daycol,day ); // ローカルの日付けラベルを求めるメソッド 189 // 6.3.9.1 (2015/11/27) Found 'DD'-anomaly for variable(PMD) 190 final String vallbl = valKey == null ? "" : BR + getValueLabel( row,getColumnNo( valKey + day ) ); // 動的値カラム番号取得 191 192 if( "1".equals( getValue( row,daycol ))) { 193 out.append(" <td class=\"holyday\">" ); 194 } else { 195 out.append(" <td class=\"day" ) 196 .append( WEEK_MK[culDay+firstWeek] ) 197 .append("\">"); 198 } 199 out.append( daylbl ) 200 .append( vallbl ) 201 .append("</td>") 202 .append( CR ); 203 204 // 週の終わりで、行を折り返す。 205 if( culDay == 6 ) { 206 out.append(" </tr>" ).append( CR ) 207 .append( " <tr>").append( CR ); // 6.1.0.0 (2014/12/26) refactoring 208 culDay = 0; 209 } else { 210 culDay++; 211 } 212 } 213 214 // 最終週の日付欄の空きスペースの計算 215 if( 7 != culDay ) { // 6.4.2.1 (2016/02/05) PMD refactoring. Useless parentheses. 216 out.append( " <td colspan=\"" ).append( 7-culDay ).append( "\"> </td>" ); 217 } 218 out.append( CR ) 219 .append( " </tr>" ).append( CR ) 220 .append( "</table>" ).append( CR ); 221 222 return out.toString(); 223 } 224 225 /** 226 * このビーに対する特別な初期化を行う。 227 * 228 * @og.rev 3.5.4.0 (2003/11/25) TableFormatter クラスを使用するように変更。 229 * @og.rev 3.5.5.9 (2004/06/07) ヘッダーの日付け表示に、Locale を加味できるように変更 230 * @og.rev 3.6.0.0 (2004/09/17) viewKeys , columnSize 属性の追加 231 * 232 */ 233 private void paramInit() { 234 235 final String viewKeysCd = getParam( ViewCalendarParam.VIEW_KEYS ,ViewCalendarParam.VIEW_VALUES ); // 3.6.0.0 (2004/09/17) 236 ymKey = getParam( ViewCalendarParam.YM_KEY ,ViewCalendarParam.YM_VALUE ); 237 dayKey = getParam( ViewCalendarParam.DAY_KEY ,ViewCalendarParam.DAY_VALUE ); 238 valKey = getParam( ViewCalendarParam.VALUE_KEY ,null ); 239 final String valueBrCd = getParam( ViewCalendarParam.VALUE_BR_FLAG_KEY ,ViewCalendarParam.VALUE_BR_FLAG_VALUE ); 240 final String firstWeekCd = getParam( ViewCalendarParam.FIRSTWEEK_KEY ,ViewCalendarParam.FIRSTWEEK_VALUE ); 241 final String headerLocale = getParam( ViewCalendarParam.HEADER_LOCALE_KEY ,ViewCalendarParam.HEADER_LOCALE_VALUE ); 242 final String columnSizeCd = getParam( ViewCalendarParam.COLUMN_SIZE_KEY ,ViewCalendarParam.COLUMN_SIZE_VALUE ); // 3.6.0.0 (2004/09/17) 243 244 viewKeys = StringUtil.csv2Array( viewKeysCd ); 245 firstWeek = Integer.parseInt( firstWeekCd ); 246 valueBrFlag = Boolean.parseBoolean( valueBrCd ); // 6.1.0.0 (2014/12/26) refactoring 247 columnSize = Integer.parseInt( columnSizeCd ); // 3.6.0.0 (2004/09/17) 248 249 // 曜日ヘッダーをコピーして作成します。 250 if( "ja".equals( headerLocale ) ) { 251 week = WEEK_JA; 252 } 253 else { 254 week = WEEK_EN; 255 } 256 } 257 258 /** 259 * row行,colum列 のデータの値をHTML文字列に変換して返します。 260 * リソースバンドルが登録されている場合は,リソースに応じた 261 * HTML文字列を作成します。 262 * カレンダーViewに特化した、ラベル値を返します。 263 * 264 * @og.rev 3.8.0.9 (2005/10/17) writableControl 追加による引数変更 265 * 266 * @param row 行番号 267 * @param column カラム番号 268 * @param day 日付 269 * 270 * @return row行,colum列 のデータの値 271 * @og.rtnNotNull 272 */ 273 private String getValueLabel( final int row, final int column, final int day ) { 274 // 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) 275 final String rtn ; 276 if( isColumnWritable( column ) && isWritable( row ) ) { 277 final String val = getValue( row,column ) ; 278 rtn = day + getEditorValue( row,column,val ); 279 } 280 else { 281 rtn = String.valueOf( day ); 282 } 283 return rtn ; 284 } 285 286 /** 287 * 指定のYYYYMM文字列から、カレンダーオブジェクトを作成して返します。 288 * 日にちは、1日にセットされます。 289 * 290 * @param ym YYYYMM文字列 291 * 292 * @return カレンダーオブジェクト 293 */ 294 private Calendar getCalendar( final String ym ) { 295 final Calendar cal = Calendar.getInstance(); 296 297 if( ym != null && ym.length() == 6 ) { 298 final int yyyy = Integer.parseInt( ym.substring( 0,4 ) ); 299 final int mm = Integer.parseInt( ym.substring( 4,6 ) ) - 1; 300 final int dd = 1; 301 cal.set( yyyy,mm,dd,0,0,0 ); 302 } 303 else { 304 // カレンダーを今月の1日に設定する。 305 cal.set(Calendar.DAY_OF_MONTH, 1); 306 } 307 308 return cal ; 309 } 310 311 /** 312 * フォーマットメソッドを使用できるかどうかを問い合わせます。 313 * 314 * @og.rev 3.6.0.0 (2004/09/17) 親クラス変更に伴なう、追加 315 * 316 * @return 使用可能(true)/ 使用不可能 (false) 317 */ 318 public boolean canUseFormat() { 319 return false; 320 } 321 322 /** 323 * 表示項目の編集(並び替え)が可能かどうかを返します。 324 * 325 * @og.rev 5.1.6.0 (2010/05/01) 新規追加 326 * 327 * @return 表示項目の編集(並び替え)が可能かどうか(false:不可能) 328 */ 329 @Override 330 public boolean isEditable() { 331 return false; 332 } 333}