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