/*
 * 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.hayabusa.taglib;

import org.opengion.hayabusa.html.ViewTimeTableParam;

import static org.opengion.fukurou.util.StringUtil.nval ;

import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.IOException;

/**
 * viewタグの viewFormType が HTMLTimeTable の場合にパラメータを設定します。
 *
 * 時間軸を持つタイムテーブルの表示を行う、ViewForm_HTMLTimeTable クラスに対して、
 * 各種パラメータを設定します。
 * パラメータが設定されていない場合は、ViewForm_HTMLTimeTable の初期値が使用されます。
 * (パラメータを使用するには、viewタグのuseParam 属性をtrueに設定する必要があります。)
 *
 * SELECT文は、日付、キー、備考、開始時刻、終了時刻、リンクが、必須項目で、この並び順は、
 * 完全に固定です。よって、カラム位置を指定する必要はありませんが、SELECT文を自由に
 * 設定することも出来ませんので、ご注意ください。
 * この固定化に伴い、WRITABLE 指定も使用できません。
 * なお、日付、キー、備考 に関しては、columnDisplay 属性で、表示の ON/OFF 制御は可能です。
 * また、日付ブレイク、キーブレイクの設定で、カラム自体をテーブルの外に出すことが可能です。
 * (キーと備考はセットになっています。)
 *
 * タイムテーブルが空きの場合のリンクは、ViewTimeTableParam.NULL_LINK_CLM_ID で指定します。
 * (ViewTimeTableParam の nullLinkColumn 属性)
 * 指定しない場合は、空きのリンクは作成されません。
 * このリンクは、特殊で、引数に、パラメータを追加できますが、"($1)"、"($2)" で指定します。
 * この($1)、($2)は、開始時刻、終了時刻がセットされますが、SELECT文の固定カラムと同じ
 * 並び順ですが、DBTableModelの値を設定しているわけではありません。
 * 空きの場合は、データ自体が存在しない場合と、日付、キー のみが 外部結合で生成された
 * レコードが実際に存在する場合がありますが、外部結合で生成されたレコードには、
 * 開始時刻、終了時刻はありません。($1) と($2)には、それぞれ、最小開始時刻と最大終了時刻を
 * セットします。
 *
 * 例として、&amp;TMSTART=($1)&amp;TMEND=($2) という文字列の ($*) 部分を解析して割当ます。
 *
 * 各属性は、{&#064;XXXX} 変数が使用できます。
 * これは、ServletRequest から、XXXX をキーに値を取り出し,この変数に割り当てます。
 * つまり、このXXXXをキーにリクエストすれば、この変数に値をセットすることができます。
 *
 * http://localhost/query.jsp?KEY1=VLA1&amp;KEY2=VAL2
 *
 * のようなリクエストで、{&#064;KEY1} とすれば、 VAL1 がセットされます。
 *
 * @og.formSample
 * ●形式：&lt;og:timeTableParam minStartTime="･･･" ･･･ /&gt;
 * ●body：なし
 *
 * ●Tag定義：
 *   &lt;og:timeTableParam
 *       minStartTime       【TAG】タイムテーブルの開始時刻(含む)をセットします(初期値:0800)
 *       maxEndTime         【TAG】タイムテーブルの終了時刻(含まない)をセットします(初期値:2100)
 *       timeInterval       【TAG】タイムテーブルのインターバル時間をセットします(初期値:30)
 *       nullLinkColumn     【TAG】タイムテーブルが空きの場合のリンクを指定しているカラム名をセットします
 *       useDyBreak         【TAG】日付でブレーク処理を行うかどうかを指定します(初期値:true)
 *       tdClassColumn      【TAG】タイムテーブルにデータを入れるTDタグにclass属性を付与する場合のカラム名をセットします
 *       useBookingMerge    【TAG】同一日付でブッキング時にマージ処理を行うかどうかを指定します(初期値:false)
 *   /&gt;
 *
 * ●使用例
 *     ViewFormTag の viewFormType が、HTMLTimeTable の場合に使用します。
 *     useParam 属性を設定しておかないと、使用されません。
 *     &lt;og:view
 *         viewFormType = &quot;HTMLTimeTable&quot;
 *         command      = &quot;{&#064;command}&quot;
 *         startNo      = &quot;0&quot;
 *         pageSize     = &quot;20&quot;
 *         <b>useParam     = &quot;true&quot;</b>
 *     &gt;
 *         &lt;og:timeTableParam
 *             minStartTime   = "0800"       : タイムテーブルの開始時刻(含む)をセットします(初期値:0800)
 *             maxEndTime     = "2100"       : タイムテーブルの終了時刻(含まない)をセットします(初期値:2100)
 *             timeInterval   = "30"         : タイムテーブルのインターバル時間をセットします(初期値:30)
 *             nullLinkColumn = "DYUSE"      : NULL時リンクを作成するベースとなるカラム名
 *             tdClassColumn  = "FGCDACTION" : データを入れるTDタグにclass属性を付与する場合のカラム名
 *         /&gt;
 *     &lt;/og:view &gt;
 *
 * @og.group 画面表示
 * @og.rev 5.4.0.0 (2011/10/01) 新規追加
 *
 * @version  4.0
 * @author	 Kazuhiko Hasegawa
 * @since    JDK5.0,
 */
public class ViewTimeTableParamTag extends ViewParamTag {
	//* このプログラムのVERSION文字列を設定します。	{@value} */
	private static final String VERSION = "5.4.4.2 (2012/02/03)" ;

	private static final long serialVersionUID = 544220120203L ;

	/**
	 * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。
	 *
	 * @return	後続処理の指示
	 */
//	@Override
//	public int doStartTag() {
//		return ( EVAL_BODY_BUFFERED );		// Body を評価する
//	}

	/**
	 * Taglibのタグ本体を処理する doAfterBody() を オーバーライドします。
	 *
	 * @return	後続処理の指示(SKIP_BODY)
	 */
//	@Override
//	public int doAfterBody() {
//
//		putParam( ViewTimeTableParam.BODY_LINK_VALUE,
//				  nval( getBodyString(),null ) );
//
//		return ( SKIP_BODY );
//	}

	/**
	 * 【TAG】タイムテーブルの開始時刻(含む)をセットします(初期値:0800)。
	 *
	 * @og.tag
	 * 時間軸の書き始めの時刻(自分自身を含む時分４桁)を指定します。
	 * この時刻は、８:００ なら、"0800" となり、１４:３０ なら、"1430" となります。
	 * 初期値は、"0800" です。
	 *
	 * @param	minStTime タイムテーブルの開始時刻(含む)
	 */
	public void setMinStartTime( final String minStTime ) {
		putParam( ViewTimeTableParam.MIN_START_TIME,
				  nval( getRequestParameter( minStTime ),"0800" ) );
	}

	/**
	 * 【TAG】タイムテーブルの終了時刻(含まない)をセットします(初期値:2100)。
	 *
	 * @og.tag
	 * 時間軸の最後の時刻(自分自身を含まない時分４桁)を指定します。
	 * この時刻は、９:００ なら、"0900" となり、１４:３０ なら、"1430" となります。
	 * 初期値は、"2100" です。
	 *
	 * @param	maxEdTime タイムテーブルの終了時刻(含まない)
	 */
	public void setMaxEndTime( final String maxEdTime ) {
		putParam( ViewTimeTableParam.MAX_END_TIME,
				  nval( getRequestParameter( maxEdTime ),"2100" ) );
	}

	/**
	 * 【TAG】タイムテーブルのインターバル時間をセットします(初期値:30)。
	 *
	 * @og.tag
	 * タイムテーブルのインターバル時間とは、時刻の最終単位の事です。
	 * この時刻は、"30" なら、３０分となります。
	 * 初期値は、"30" です。
	 *
	 * @og.rev 5.4.3.7 (2012/01/20) 指定方法の変更。分を数字で指定します。
	 *
	 * @param	intval タイムテーブルのインターバル時間
	 */
	public void setTimeInterval( final String intval ) {
		putParam( ViewTimeTableParam.TIME_INTERVAL,
				  nval( getRequestParameter( intval ),"30" ) );
	}

	/**
	 * 【TAG】タイムテーブルが空きの場合のリンクを指定しているカラム名をセットします。
	 *
	 * @og.tag
	 * これは、タイムテーブルが空きの場合のリンクを作成するにあたり、ベースとなるリンクが
	 * 適用されているカラムを指定します。
	 * このリンクは、特殊で、引数に、パラメータを追加できますが、($1) 等の記号で指定します。
	 * この($1)、($2)には、開始時刻、終了時刻がセットされますが、SELECT文の
	 * 固定カラムと同じ並び順ですが、DBTableModelの値を設定しているわけではありません。
	 * 空きの場合は、データ自体が存在しない場合がありますが、その場合は、開始時刻、終了時刻は
	 * ありません。
	 * その場合は、それぞれ、最小開始時刻と最大終了時刻がセットされます。
	 *
	 * &amp;TMSTART=($1)&amp;TMEND=($2) という文字列の ($*) 部分を解析して割当ます。
	 *
	 * TMSTARTやTMENDは、リンク作成側で自由に指定できます。
	 *
	 * 同様の機能は、BODY部にリンクを指定することも可能です。
	 * この($1)～($4)には、開始時刻、終了時刻、日付、キーがセットされます。
	 *
	 * 6amp;TMSTART=($1)&amp;TMEND=($2)&amp;DYUSE=($3)&amp;UNITID=($4) という文字列の ($*) 部分を解析して割当ます。
	 *
	 * BODY と nullLinkColumn が両方とも指定された場合は、nullLinkColumn の設定が優先されます。
	 *
	 * @param	clm nullのデータに適用するリンクを設定したカラム名
	 */
	public void setNullLinkColumn( final String clm ) {
		putParam( ViewTimeTableParam.NULL_LINK_CLM_ID,
				  nval( getRequestParameter( clm ),null ) );
	}

	/**
	 * 【TAG】タイムテーブルにデータを入れるTDタグにclass属性を付与する場合のカラム名をセットします。
	 *
	 * @og.tag
	 * これは、タイムテーブルのリンクや説明を入れるTDに、class属性を付与する場合のカラム名を
	 * 指定します。これにより、TD に色を付けたり、表示の条件を外部から指定できます。
	 * もっとも一般的な想定用途は、タイムテーブルのデータの種別に応じた色分けです。
	 *
	 * @og.rev 5.4.3.7 (2012/01/20) 新規追加
	 *
	 * @param	clm nullのデータを入れるTDタグにclass属性を付与する場合のカラム名
	 */
	public void setTdClassColumn( final String clm ) {
		putParam( ViewTimeTableParam.TD_CLASS_COLUMN_ID,
				  nval( getRequestParameter( clm ),null ) );
	}

	/**
	 * 【TAG】ブレーク処理を行うカラムＩＤをCSV形式でセットします(初期値:0030)。
	 *
	 * @og.tag
	 * 指定されたカラムＩＤが、チェンジすると、ブレイク処理を行います。
	 * これは、ブレイク毎にテーブルが分かれて、テーブルの先頭に、ブレイクした
	 * 値が表示されます。
	 * 例えば、日付カラムをブレイクカラムとして設定すると、日付がブレイクするたび、
	 * 日付をヘッダーに出して、テーブルを作成します。
	 * ブレークカラムは、CSV形式で複数指定できます。その場合は、複数指定のカラムの
	 * 合成された値で、キーブレイクの判定を行います。(簡単に言うとＯＲ判定になります。)
	 * なお、ブレイクカラムを指定した場合は、自動的に、noDisplay 属性にその値をセット
	 * します。
	 *
	 * @param	clms ブレーク処理を行うカラムＩＤ(CSV形式)
	 */
//	public void setBreakClms( final String clms ) {
//		putParam( ViewTimeTableParam.BREAK_CLMS,
//				  nval( getRequestParameter( clms ),null ) );
//	}

	/**
	 * 【TAG】日付でブレーク処理を行うかどうかを指定します(初期値:true)。
	 *
	 * @og.tag
	 * 日付でブレーク処理を行う場合、日付単位にテーブルが分かれます。
	 * 日付は、テーブルの先頭に、ブレイクした時点で表示されます。
	 * 日付でブレイクするを指定した場合は、自動的に、noDisplay 属性に日付が
	 * セットされます。
	 * 初期値は、true(日付ブレイクする)です。
	 *
	 * @param	flag 日付でブレーク処理を行うかどうか(true:日付ブレイクする、false しない)
	 */
	public void setUseDyBreak( final String flag ) {
		putParam( ViewTimeTableParam.USE_DY_BREAK,
				  nval( getRequestParameter( flag ),"true" ) );
	}

	/**
	 * 【TAG】同一日付でブッキング時にマージ処理を行うかどうかを指定します(初期値:false)。
	 *
	 * @og.tag
	 * 日付、キー(人や施設)で予定時刻が重複している場合の処理方法を指定します。
	 * 通常(初期値:false)では、ブッキングデータはレコードを分けて表示させます。
	 * 例えば、人の予定であれば、仮予約や会議招集などのケースで、重複を表示しておき
	 * 利用者本人に決めさせるというケースが考えられます。
	 * これを、true に設定すると、予定時刻が重複している場合は、マージして、一つの
	 * 予定として表現します。
	 * 初期値は、false(ブッキング時にマージ処理を行わない)です。
	 *
	 * @og.rev 5.4.4.2 (2012/02/03) 新規追加
	 *
	 * @param	flag 同一日付でブッキング時にマージ処理を行うかどうか(true:行うする、false 行わない)
	 */
	public void setUseBookingMerge( final String flag ) {
		putParam( ViewTimeTableParam.USE_BOOKING_MERGE,
				  nval( getRequestParameter( flag ),"true" ) );
	}

	/**
	 * タグの名称を、返します。
	 * 自分自身のクラス名より、自動的に取り出せないため、このメソッドをオーバーライドします。
	 *
	 * @return  タグの名称
	 */
	@Override
	protected String getTagName() {
		return "timeTableParam" ;
	}

	/**
	 * シリアライズ用のカスタムシリアライズ書き込みメソッド
	 *
	 * @serialData 一部のオブジェクトは、シリアライズされません。
	 *
	 * @param	strm	ObjectOutputStreamオブジェクト
	 * @throws IOException	入出力エラーが発生した場合
	 */
	private void writeObject( final ObjectOutputStream strm ) throws IOException {
		strm.defaultWriteObject();
	}

	/**
	 * シリアライズ用のカスタムシリアライズ読み込みメソッド
	 *
	 * ここでは、transient 宣言された内部変数の内、初期化が必要なフィールドのみ設定します。
	 *
	 * @serialData 一部のオブジェクトは、シリアライズされません。
	 *
	 * @param	strm	ObjectInputStreamオブジェクト
	 * @see #release2()
	 * @throws IOException	シリアライズに関する入出力エラーが発生した場合
	 * @throws ClassNotFoundException	クラスを見つけることができなかった場合
	 */
	private void readObject( final ObjectInputStream strm ) throws IOException , ClassNotFoundException {
		strm.defaultReadObject();
	}
}
