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