/*
 * Copyright (c) 2009 The openGion Project.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
package org.opengion.plugin.view;

import java.io.Serializable;
import java.util.List;
import java.util.ArrayList;

import org.opengion.fukurou.util.StringUtil;
import org.opengion.hayabusa.common.HybsSystem;
import org.opengion.hayabusa.common.HybsSystemException;
import org.opengion.hayabusa.db.DBTableModel;
import org.opengion.hayabusa.html.ViewTimeTableParam;

/**
 * 時間軸を持つタイムテーブルの表示を行うクラスです。
 *
 * パラメータが必要な場合は、ViewTimeTableParamTag を使用してください。
 *
 * パラメータが設定されていない場合は、ViewForm_HTMLTimeTable の初期値が使用されます。
 * (パラメータを使用するには、viewタグのuseParam 属性をtrueに設定する必要があります。)
 *
 * SELECT文は、日付、キー、備考、開始時刻、終了時刻、リンクが、必須項目で、この並び順は、
 * 完全に固定です。よって、カラム位置を指定する必要はありませんが、SELECT文を自由に
 * 設定することも出来ませんので、ご注意ください。<br/>
 * この固定化に伴い、WRITABLE 指定も使用できません。
 * なお、日付、キー、備考 に関しては、columnDisplay 属性で、表示の ON/OFF 制御は可能です。
 * また、日付ブレイク、キーブレイクの設定で、カラム自体をテーブルの外に出すことが可能です。
 * （キーと備考はセットになっています。）<br/>
 *
 * タイムテーブルが空きの場合のリンクを指定できます。（ViewTimeTableParam.NULL_LINK_CLM_ID）
 * (ViewTimeTableParam の nullLinkColumn 属性)
 * 指定しない場合は、空きのリンクは作成されません。
 * このリンクは、特殊で、引数に、パラメータを追加できますが、"($1)"、"($2)" で指定します。
 * この($1)、($2)は、開始時刻、終了時刻がセットされますが、SELECT文の固定カラムと同じ
 * 並び順ですが、DBTableModelの値を設定しているわけではありません。
 * 空きの場合は、データ自体が存在しない場合と、日付、キー のみが 外部結合で生成された
 * レコードが実際に存在する場合がありますが、外部結合で生成されたレコードには、
 * 開始時刻、終了時刻はありません。($1) と($2)には、それぞれ、最小開始時刻と最大終了時刻を
 * セットします。
 *
 * 例として、&TMSTART=($1)&TMEND=($2) という文字列の ($*) 部分を解析して割当ます。
 *
 * ブレーク処理を行うカラムＩＤをCSV形式でセットできます。(ViewTimeTableParam.BREAK_CLMS)
 * (ViewTimeTableParam の breakClms 属性)
 * これは、ブレイク毎にテーブルが分かれて、テーブルの先頭に、ブレイクした
 * 値が表示されます。
 * 例えば、日付カラムをブレイクカラムとして設定すると、日付がブレイクするたび、
 * 日付をヘッダーに出して、テーブルを作成します。
 * ブレークカラムは、CSV形式で複数指定できます。その場合は、複数指定のカラムの
 * 合成された値で、キーブレイクの判定を行います。(簡単に言うとＯＲ判定になります。)
 * なお、ブレイクカラムを指定した場合は、自動的に、noDisplay 属性にその値をセット
 * します。
 *
 * @og.rev 5.4.0.0 (2011/10/01) 新規追加
 * @og.group 画面表示
 *
 * @version  4.0
 * @author	 Kazuhiko Hasegawa
 * @since    JDK5.0,
 */
public class ViewForm_HTMLTimeTable extends ViewForm_HTMLTable {
	//* このプログラムのVERSION文字列を設定します。	{@value} */
	private static final String VERSION = "5.4.0.0 (2011/10/01)" ;

	private int		minStTime	= 80;			// 08:00 のこと。30分=5 換算
	private int		maxEdTime	= 210;			// 21:00 のこと。
	private int		intval		= 5;			// 30分=5 単位に colspan を設定する。

	private static final int	dyClmNo		= 0;	// ヘッダー1：ただし、グループ化する場合は、外出し
	private static final int	keyClmNo	= 1;	// ヘッダー2：ただし、グループ化する場合は、外出し
	private static final int	bikoClmNo	= 2;	// ヘッダー3：

	private static final int	tmstClmNo	= 3;	// 時間枠の開始時刻(含む)
	private static final int	tmedClmNo	= 4;	// 時間枠の終了時刻(含まない)
	private static final int	linkClmNo	= 5;	// 時間枠に表示する予約情報(変更画面へのリンク)

	private static final int	clmCnt		= 3;	// 決め打ち。今は、dyClm,keyClm の２つだけ表示

	// 引数に、DYUSE=(dyClm)&UNITID=(keyClm)&TMSTART=(stTime)&TMEND=(edTime) を追加する。
//	private String	linkValue	= "<a href=\"../GK0101/index.jsp?command=NEW&NORESERVE="
//									+ "&DYUSE=($1)&UNITID=($2)&TMSTART=($3)&TMEND=($4)"
//									+ "&BACK_GAMENID=GK0000&GAMENID=GK0101&BACK_ADDRESS=/gk/jsp/GK0000/index.jsp\" target=\"CONTENTS\">"
//									+ "<img src=\"../customImage/gk/space.gif\" width=\"100%\" height=\"20px\" />"
//									+ "</a>" ;
	// 引数パース機能付き データが存在しない場合のリンクのベースを設定。
//	private String	linkValue		= "" ;		// null にするとエラーになるので、空文字列
	private int		nullLinkClmNo	= -1 ;		// 固定ではなく可変の場合に利用するリンクカラムNo

//	private int[]	breakClmNos		= null;		// ブレーク処理を行うカラムNo
	private boolean isDyBreak		= true;		// 日付でブレイクするかどうかを指定

	/**
	 * 内容をクリア（初期化）します。
	 *
	 */
	public void clear() {
		super.clear();

		minStTime	= 80;			// 08:00 のこと。30分=5 換算
		maxEdTime	= 210;			// 21:00 のこと。
		intval		= 5;			// 30分=5 単位に colspan を設定する。

//		linkValue		= "" ;			// null にするとエラーになるので、空文字列
		nullLinkClmNo	= -1;			// 固定ではなく可変の場合に利用するリンクカラム
//		breakClmNos		= null;			// ブレーク処理を行うカラムNo
		isDyBreak		= true;			// 日付でブレイクするかどうかを指定
	}

	/**
	 * DBTableModel から HTML文字列を作成して返します。
	 * startNo（表示開始位置）から、pageSize（表示件数）までのView文字列を作成します。
	 * 表示残りデータが pageSize 以下の場合は,残りのデータをすべて出力します。
	 *
	 * @param  startNo	  表示開始位置
	 * @param  pageSize   表示件数
	 * @return	DBTableModel から作成された HTML文字列
	 */
	public String create( final int startNo, final int pageSize )  {
		if( getRowCount() == 0 ) { return ""; }	// 暫定処置

		paramInit();
		headerLine	 = null;
		int lastNo = getLastNo( startNo, pageSize );
		int hsc = getHeaderSkipCount();	
		int hscCnt = 1;

		StringBuilder out = new StringBuilder( HybsSystem.BUFFER_LARGE );

		if( isDyBreak ) {
			out.append( getRendererValue( 0,dyClmNo ) ).append( HybsSystem.CR );
			setColumnDisplay( dyClmNo,false );	// 日付ブレイクなら、setColumnDisplay をfalse にセット
		}

		out.append( getHeader() );

		out.append("<tbody>").append( HybsSystem.CR );
		int bgClrCnt = 0;

		int maxColspan = (maxEdTime-minStTime)/intval ;		// この数が、TDの数になる。
		int rowColspan = maxColspan;
		int stTime     = minStTime;

		String backData    = "";	// 初期値。１回目にキーブレイクさせる。

		List<String> dblBooking = new ArrayList<String>();		// 重複データがあったときのデータ格納
		String nlVal	 = null;		// 空リンクのベース値
		String dyVal	 = null;		// 日付項目の値
		String keyVal	 = null;		// キー項目の値
//		String breakVal	 = null;		// キーブレイクの値
		String bk_nlVal	 = null;		// キーブレイク時の元の空リンクのベース値
		String bk_dyVal	 = "";			// キーブレイク時の元の日付
//		String bk_breakVal = "";		// キーブレイクの元の値
		for( int row=startNo; row<lastNo; row++ ) {
			// キーブレイクの判定
			bk_nlVal   = nlVal;
//			bk_dyVal   = dyVal;
//			bk_keyVal  = keyVal;

//			nlVal = (nullLinkClmNo < 0 ) ? linkValue : getRendererValue( row,nullLinkClmNo );
			nlVal = (nullLinkClmNo < 0 ) ? null : getRendererValue( row,nullLinkClmNo );
			dyVal   = getValue( row,dyClmNo );
			keyVal  = getValue( row,keyClmNo );
			if( row==startNo ) { bk_dyVal   = dyVal; }		// 初期データをセット。
			// 
//			if( breakClmNos != null ) {
//				StringBuilder blkVal = new StringBuilder( HybsSystem.BUFFER_MIDDLE );
//				for( int i=0; i<breakClmNos.length; i++ ) {
//					blkVal.append( getValue( row,breakClmNos[i] ) );
//				}
//				breakVal = blkVal.toString();
//			}

			String linkVal = getRendererValue( row,linkClmNo );

			// キーブレイク判定。キーブレイクは、一番初めから来る。
			if( !backData.equals( dyVal + keyVal ) ) {
				backData   = dyVal + keyVal;			// null は来ないはず

				// minStTime < stTime の時だけ、処理を行う。(最初のキーブレイクは処理しないため)
				if( minStTime < stTime ) {
					// まずは、前の td の残りを出力する。ここでは、キーブレイク前の値を使用する。
					if( stTime < maxEdTime ) {
						out.append("  ");		// td タグの出力前の段落
						appendTag( out , "td" , (maxEdTime-stTime)/intval , 
										makeLinkValue( bk_nlVal , stTime , maxEdTime ) );
//										makeLinkValue( bk_nlVal , bk_dyVal , bk_keyVal , stTime , maxEdTime ) );
					}
					out.append("</tr>").append( HybsSystem.CR );
				}
				stTime = minStTime;		// 初期化

				// データかぶりが発生したときの処理
				if( !dblBooking.isEmpty() ) {
					for( String bkdt : dblBooking ) {
						out.append("<tr").append( getBgColorCycleClass( bgClrCnt-1 ) ).append(">").append( HybsSystem.CR );
						out.append( bkdt );
						out.append("</tr>").append( HybsSystem.CR );
					}
					dblBooking.clear();
				}

				// 日付ブレイク処理
				if( isDyBreak && row > startNo && !bk_dyVal.equals( dyVal ) ) {
					bk_dyVal = dyVal;
					out.append("<tr class=\"dummy\">");
					for(int column = 0; column < clmCnt; column++) {
						if( isColumnDisplay( column ) ) {
							out.append("<td/>");
						}
					}
					for( int i=0; i<(maxEdTime-minStTime)/intval ; i++ ) {
						out.append("<td/>");
					}
					out.append("</tr>").append( HybsSystem.CR );
					out.append("</tbody>").append( HybsSystem.CR );
					out.append("</table>").append( HybsSystem.CR );

					out.append( getRendererValue( row,dyClmNo ) ).append( HybsSystem.CR );

					out.append( getHeader() );
					out.append("<tbody>").append( HybsSystem.CR );
					hscCnt = 1;
				}

				// ヘッダー繰り返し属性（ headerSkipCount ）を採用
				if( hsc > 0 && hscCnt % hsc == 0 ) {
					out.append( getHeadLine() );
					hscCnt = 1;
				}
				else {
					// 特殊処理：ここの処理では、一番最初も、実行されるので、＋＋しないように加工しておく。
					if( row > startNo ) { hscCnt ++ ; }
				}

				// ここから、新しい行が始まる。
				out.append("<tr").append( getBgColorCycleClass( bgClrCnt++ ) ).append(">").append( HybsSystem.CR );
				for(int column = 0; column < clmCnt; column++) {
					if( isColumnDisplay( column ) ) {
						// ヘッダー部分に加工しやすいように、class 属性を与えておく。
						out.append("  <td class=\"" ).append( getColumnName( column ) ).append( "\">" );
						out.append( getValueLabel(row,column) );
						out.append("</td>").append( HybsSystem.CR );
					}
				}
			}

			// 文字列型の時分情報を数字に変換する。
//			int clStTime = getStr2Time( getValue( row,tmstClmNo ) , minStTime );
			int clStTime = getStr2Time( getValue( row,tmstClmNo ) , -1 );
			boolean nullData = (clStTime < 0) ;	// 開始時刻が	null の場合、-1 が返されるのでフラグをセットする。
			if( clStTime < minStTime ) { clStTime = minStTime; }	// 最小値以下の場合は、最小値に合せる。

			int clEdTime = getStr2Time( getValue( row,tmedClmNo ) , maxEdTime );
			if( clEdTime > maxEdTime ) { clEdTime = maxEdTime; }	// 最大値以上の場合は、最大値に合せる。

			if( clStTime == clEdTime ) { clEdTime = clEdTime + intval ; }	// 最初と最後が同じ場合は、intval分 進めておく。

			// 最初と最後が異なる場合は、間に空欄が入る。同じ場合は、連続なので、空欄は入らない。
			if( stTime < clStTime ) {
				out.append("  ");		// td タグの出力前の段落
				appendTag( out , "td" , (clStTime-stTime)/intval , 
										makeLinkValue( nlVal , stTime , clStTime ) ).append( HybsSystem.CR );
//										makeLinkValue( nlVal , dyVal , keyVal , stTime , clStTime ) ).append( HybsSystem.CR );
			}
			// 前のデータとかぶっている。つまり、ブッキングデータがある。
			else if( stTime > clStTime ) {
				StringBuilder buf2 = new StringBuilder( HybsSystem.BUFFER_MIDDLE );

				buf2.append("  ");		// td タグの出力前の段落
//				appendTag( buf2 , "td" , clmCnt );									// ヘッダー部分
				for(int column = 0; column < clmCnt; column++) {
					if( isColumnDisplay( column ) ) {
						// ヘッダー部分に加工しやすいように、class 属性を与えておく。
						buf2.append("<td class=\"" ).append( getColumnName( column ) ).append( "\"/>" );
					}
				}

				appendTag( buf2 , "td" , (clStTime-minStTime)/intval );				// 最初からデータまで
				appendTag( buf2 , "td" , (clEdTime-clStTime)/intval , linkVal );	// データ部
				appendTag( buf2 , "td" , (maxEdTime-clEdTime)/intval );				// データから最後まで

				dblBooking.add( buf2.toString() );
				continue;
			}
			// 前も後ろも最小と最大になっているのは、予約レコードが無いため。
//			else if( clStTime == minStTime && clEdTime == maxEdTime ) {
			// stTime == clStTime のケース。nullData = true で、予約レコードが無いため。
			else if( nullData ) {
				linkVal = makeLinkValue( nlVal , minStTime , maxEdTime );
//				linkVal = makeLinkValue( nlVal , dyVal , keyVal , minStTime , maxEdTime );
			}

			out.append("  ");		// td タグの出力前の段落
			appendTag( out , "td" , (clEdTime-clStTime)/intval , linkVal ).append( HybsSystem.CR );

			stTime = clEdTime ;
		}

		// 残処理：データが残っている場合は、書き出す必要がある。
		if( ( minStTime < stTime && stTime < maxEdTime ) ) {
			out.append("  ");		// td タグの出力前の段落
			appendTag( out , "td" , (maxEdTime-stTime)/intval ,
										makeLinkValue( nlVal , stTime , maxEdTime ) );
//										makeLinkValue( nlVal , dyVal , keyVal , stTime , maxEdTime ) );
			out.append("</tr>").append( HybsSystem.CR );

			// データかぶりが発生したときの処理
			if( !dblBooking.isEmpty() ) {
				for( String bkdt : dblBooking ) {
					out.append("<tr").append( getBgColorCycleClass( bgClrCnt-1 ) ).append(">").append( HybsSystem.CR );
					out.append( bkdt );
					out.append("</tr>").append( HybsSystem.CR );
				}
			}
		}
		else {
			out.append("</tr>").append( HybsSystem.CR );
		}

		// カラムの結合があるため、td タグを個別に出力しておかないと、レイアウトがずれる。
		out.append("<tr class=\"dummy\">");
		for(int column = 0; column < clmCnt; column++) {
			if( isColumnDisplay( column ) ) {
				out.append("<td/>");
			}
		}
		for( int i=0; i<(maxEdTime-minStTime)/intval ; i++ ) {
			out.append("<td/>");
		}
		out.append("</tr>").append( HybsSystem.CR );

		out.append("</tbody>").append( HybsSystem.CR );
		out.append("</table>").append( HybsSystem.CR );

		out.append( getScrollBarEndDiv() );	// 3.8.0.3 (2005/07/15)
		return out.toString();
	}

	/**
	 * パラメータ内容を初期化します。
	 *
	 */
	private void paramInit() {
		String s_minStTime	= getParam( ViewTimeTableParam.MIN_START_TIME	, null );
		String s_maxEdTime	= getParam( ViewTimeTableParam.MAX_END_TIME		, null );
		String s_intval		= getParam( ViewTimeTableParam.TIME_INTERVAL	, null );

//		String[] s_brkClms	= StringUtil.csv2Array( getParam( ViewTimeTableParam.BREAK_CLMS , null ) );

		isDyBreak			= Boolean.valueOf( getParam( ViewTimeTableParam.USE_DY_BREAK	, "true" ) );

		// nullリンクのカラム名指定。nullClm が優先順位が高い。
		String s_nullClm	= getParam( ViewTimeTableParam.NULL_LINK_CLM_ID	, null );
		if( s_nullClm != null ) { 
			nullLinkClmNo = getColumnNo( s_nullClm );
		}
//		else {
//			linkValue	= getParam( ViewTimeTableParam.BODY_LINK_VALUE	, linkValue );
//		}

		// BREAK_CLMS は、csv2Array しているので、null は来ない。
//		if( s_brkClms.length > 0 ) {
//			breakClmNos	= new int[s_brkClms.length];
//			for( int i=0; i<s_brkClms.length; i++ ) {
//				breakClmNos[i] = getColumnNo( s_brkClms[i] );
//			}
//		}

		minStTime	= getStr2Time( s_minStTime	, minStTime );			// 最小開始時刻。0800 なら、80。 30分=5 換算
		maxEdTime	= getStr2Time( s_maxEdTime	, maxEdTime );			// 最大終了時刻。2100 なら、210。30分=5 換算
		intval		= getStr2Time( s_intval		, intval );				// インターバル。0030 なら、5。  30分=5 換算
	}

	/**
	 * DBTableModel から テーブルのタグ文字列を作成して返します。
	 *
	 * @return	テーブルのタグ文字列
	 */
	protected String getTableHead() {
		StringBuilder buf = new StringBuilder( HybsSystem.BUFFER_MIDDLE );

		for(int column = 0; column < clmCnt; column++) {
			if( isColumnDisplay( column ) ) {
				buf.append("<colgroup class=\"" );
				buf.append( getColumnDbType(column) );		// 4.0.0 (2005/01/31)
				buf.append("\"/>");
				buf.append( HybsSystem.CR );
			}
		}

		// 3.5.2.0 (2003/10/20) ヘッダー繰り返し部をgetHeadLine()へ移動
		buf.append("<thead id=\"header\">").append( HybsSystem.CR );	// 3.5.6.5 (2004/08/09)
		buf.append( getHeadLine() );
		buf.append("</thead>").append( HybsSystem.CR );

		return buf.toString();
	}

	/**
	 * ヘッダー繰り返し部を、getTableHead()メソッドから分離。
	 *
	 * @param	thTag タグの文字列
	 * @return	テーブルのタグ文字列
	 */
	protected String getHeadLine( final String thTag ) {
		if( headerLine != null ) { return headerLine; }		// キャッシュを返す。

		StringBuilder buf = new StringBuilder( HybsSystem.BUFFER_MIDDLE );

		buf.append("<tr class=\"row_h\"").append(" >").append( HybsSystem.CR );

		buf.append( HybsSystem.CR );
		for(int column = 0; column < clmCnt; column++) {
			if( isColumnDisplay( column ) ) {
//				buf.append( thTag ).append(">");
				buf.append( thTag ).append(" class=\"" ).append( getColumnName( column ) ).append( "\">" );
				buf.append( getColumnLabel(column) );
				buf.append("</th>").append( HybsSystem.CR );
			}
		}

		for(int tm = minStTime; tm < maxEdTime; tm+=10 ) {	// intval づつ進めるべきだが、1時間ごとの箱とする。
			buf.append( thTag ).append(" class=\"timeVar\" colspan=\"2\">");
			buf.append( (tm/10) );
			buf.append("</th>").append( HybsSystem.CR );
		}

		buf.append("</tr>").append( HybsSystem.CR );

		headerLine = buf.toString();
		return headerLine;
	}

	/**
	 * タグ文字列を簡易的に合成します。
	 * 
	 * タグは、th , td をターゲットにします。
	 * ここでは、主に、colspan を設定することを目的にしているためです。
	 * colspan の値によって、動作を変化させています。
	 *   0: タグそのものを生成しません。これは、第一引数をそのまま返します。
	 *   1: colspan 属性を出力しません。(Default値なので)
	 *   それ以外は、colspan に引数を設定します。
	 * BODY 部も、無指定の場合は、/&gt; 止めのタグを出力します。
	 * 
	 * 返り値の StringBuilder は、第一引数そのものを返します。よって、このメソッドに、
	 * append を連結していくことも可能です。
	 * （return値を使わなくても、第一引数の StringBuilder は変化しています。副作用というやつ。）
	 *
	 * @param  buf   StringBuilder このStringBuilderに append します。
	 * @param  tag String タグ。基本的には、td , th 
	 * @param  colspan int td , th タグ属性に追加する colspan値。
	 *                     0 の場合は、タグ自体を出力しません。1の場合は、colspan を出力しません。
	 * @param  str String... タグの BODY 部に出力する内容(String 可変長引数）０件の場合は、BODYなし
	 * @return	append されたStringBuilder (第一引数と同じオブジェクト)
	 */
	private StringBuilder appendTag( final StringBuilder buf , final String tag , final int colspan , final String... body ) {
		if( colspan == 0 ) { return buf; }

		buf.append( "<" ).append( tag );
		if( colspan > 1 ) {
			buf.append( " colspan=\"" ).append( colspan ).append( "\"" );
		}

		int cnt = body.length;
		if( cnt == 0 ) { buf.append( " />" ); }
		else {
			 buf.append( ">" );
			for( int i=0; i<cnt; i++ ) {
				buf.append( body[i] );
			}
			 buf.append( "</" ).append( tag ).append( ">" );
		}

		return buf;
	}

	/**
	 * 時間文字列を数字に変換します。
	 *
	 * "0800" は、80に、"2000" は、200 に変換します。
	 * 30分=5 なので、"0830" は、 85 になります。
	 *
	 * @param  val   String 時間文字列の値(0800 など)
	 * @param  defTm int    引数の時間文字列が null の場合の初期値
	 * @return	時間文字列を数字に変換した結果( 80 など)
	 */
	private int getStr2Time( final String val , final int defTm ) {
		if( val == null || val.isEmpty() ) { return defTm; }
		else if( val.length() != 4 ) {
			String errMsg = "時間引数は、４桁必要です。" +
							"  val=[" + val + "]";
			throw new HybsSystemException( errMsg );
		}

		return Integer.parseInt( val.substring( 0,2 ) )*10 + 
					Integer.parseInt( val.substring( 2 ) )/6 ;	// 30分=5 になるように

	}

	/**
	 * 数字を時間文字列に変換します。
	 *
	 * 80は、"0800" に、200 は、"2000" に変換します。
	 * 30分=5 なので、85 は、"0830"  になります。
	 *
	 * @param  timeVal int   引数の時間文字列が null の場合の初期値
	 * @return	数字を時間文字列に変換した結果( "0800" など)
	 */
	private String getInt2StrTime( final int timeVal ) {
		int tmpVal = timeVal;
		if(      tmpVal < minStTime ) { tmpVal = minStTime; }	// 最小値以下の場合は、最小値に合せる
		else if( tmpVal > maxEdTime ) { tmpVal = maxEdTime; }	// 最大値以上の場合は、最大値に合せる。

		//        桁合せ    85→8→800 の変換         85→5→30 の変換      足して、10830 になる。
		int rtn = 10000 + ( tmpVal / 10 ) * 100 + ( ( tmpVal % 10 ) * 6 ) ;

		return String.valueOf( rtn ).substring(1);			// "0830" 部分を返す。
	}

	// 引数に、 を追加する。

	/**
	 * リンク文字列をパースします。
	 *
	 * データの空欄にリンクを作成するときに、元となるリンク文字列の引数を設定します。
	 * 引数は、&TMSTART=(stTime)&TMEND=(edTime) を追加するイメージです。
	 * stTime、edTime は、それぞれ、($1)、($2) の変数が割り当てられます。
	 * stTime、edTime は、#getInt2StrTime( int ) メソッドで変換した文字列を利用します。
	 *
	 * @param  lnkVal  String   リンクのベースとなる値
	 * @param  stTime  int      開始時刻の数字表記
	 * @param  edTime  int      終了時刻の数字表記
	 * @return	リンク文字列をパースした結果
	 */
	private String makeLinkValue( final String lnkVal,final int stTime,final int edTime ) {
//	private String makeLinkValue( final String lnkVal,final String dyClm,final String keyClm,final int stTime,final int edTime ) {
		String rtn = "";
		if( lnkVal != null ) {
	//		rtn = lnkVal.replace( "($1)",getInt2StrTime( stTime ) )
	//						.replace( "($2)",getInt2StrTime( edTime ) ) ;
//							.replace( "($3)",dyClm )
//							.replace( "($4)",keyClm ) ;

			// URLエンコードがかかっている場合。なお、分解して処理しないのは、他にURLエンコードされている箇所を考慮して。
			rtn = lnkVal.replace( "%28%241%29",getInt2StrTime( stTime ) )
							.replace( "%28%242%29",getInt2StrTime( edTime ) ) ;
//							.replace(  "%28%243%29",dyClm )
//							.replace( "%28%244%29",keyClm ) ;
		}

		return rtn;
	}

	/**
	 * 表示項目の編集(並び替え)が可能かどうかを返します
	 *
	 * @return boolean 表示項目の編集(並び替え)が可能かどうか(false:不可能)
	 */
	public boolean isEditable() {
		return false;
	}
}
