/*
 * 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.common.HybsSystem;
import org.opengion.hayabusa.common.HybsSystemException;

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

import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.IOException;
import java.util.Map;
import java.util.HashMap;

/**
 * viewタグの viewFormType が ImageTimeBar の場合にパラメータを設定します。
 *
 * キー、日時、状況コードを持つ稼働状況の表示を行う、ViewForm_ImageTimeBar クラスに対して、
 * 各種パラメータを設定します。
 * (パラメータを使用するには、viewタグのuseParam 属性をtrueに設定する必要があります。)
 *
 * SELECT文は、キー、日時、状況コードが、必須項目で、カラムの並び順は、完全に固定です。
 * よって、カラム位置を指定する必要はありませんが、SELECT文を自由に設定することも
 * 出来ませんので、ご注意ください。
 * この固定化に伴い、WRITABLE 指定も使用できません。（そもそも書き込み不可です）
 * それ以降のカラムについては、内部処理としては、使用していません。
 * ただし、パラメータで、カラー色指定、ラベル表記部、イメージ重ね合わせ、
 * ポップアップ表記、リンク表記に使えます。
 *
 * データの並び順(ORDER BY)も、キー、日時順にしてください。
 * データは、キー単位に１レコード作成されます。（キーブレイク）その間、日時順に
 * データを処理します。
 *
 * データの表示は、今のレコードの日時から、次のレコードの日時までを一つの状態と
 * して表します。今のレコードを表示するには、次のレコードが必要になります。
 * 画面表示は、表示開始日時(minStartTime) から 表示期間(timeSpan)分を表示します。
 * 通常、開始時刻は、表示開始時刻より前より始まり、次のレコードで、終了時刻が決定
 * されます。最後のデータは、期間満了まで続いていると仮定されます。
 * データが存在しないのであれば、「存在しないデータ」を作成してください。
 * 
 * ImageTimeBar では、キーでまとめた値について、各状況コードをカラー化し、積み上げ
 * 帯グラフ形式でPNG画像化します。
 * この画像を、読み込む HTML を出力することで、画面上に、積み上げ帯グラフを表示します。
 * 状況コードに対応する色は、標準では自動作成ですが、外部から色文字列を与えることで
 * 自由に指定する事も可能です。
 *
 * ポップアップ表記(tipsClm)、リンク表記(linkClm)は、この画像に対するエリア指定タグを出力する事で実現します。
 * 画像ファイルは、全データに対して、１画像だけなので、サイズは大きくなりますが、１レコード
 * 単位に画像を作成しないため、レスポンスは向上します。
 * それぞれ、viewMarker , viewLink を利用することが可能です。特に、リンク表記(linkClm) については、
 * linkタグの hrefTarget 属性を true に設定することで適用できます。
 *
 * 画像ファイルは、java.io.File.createTempFile( File ) で作成するため、JavaVM(=Tomcat)が
 * 正常終了するときに、削除されます。異常終了時には残りますが、temp フォルダを定期的に
 * 整理すれば、それほど大量のファイルが残ることはないと思われます。
 *
 * データは、イベント発生時に作成されると仮定しています。つまり、書き込まれた日時から、
 * 状況コードに対応する状況が発生し、次の状況違いのレコードまで継続していると考えます。
 * よって、データを途中で切り出す場合、切り出す範囲の前の状態が必要になります。
 * 一番最初の状態は、"不明" として扱います。（空欄＝白色）
 *
 * <img src="doc-files/ViewTimeBarParamTag.png" alt="ViewTimeBarParamTag" >
 *
 * @og.formSample
 * ●形式：&lt;og:timeBarParam startDate="･･･" timeSpan="･･･" ･･･ /&gt;
 * ●body：なし
 *
 * ●Tag定義：
 *   &lt;og:timeBarParam
 *       startDate     ○【TAG】タイムテーブルの表示開始日時をセットします(必須)。
 *       timeSpan      ○【TAG】タイムテーブルの表示期間を時間で指定します(必須)。
 *       labelClms       【TAG】一覧表のラベル表示部に表示するカラムをCSV形式で指定します(初期値:キーのRenderer値)。
 *       colorClm        【TAG】レコードに付ける色を色文字列で指定する場合のカラム名を指定します(初期値:指定しない)。
 *       tipsClm         【TAG】レコード単位に、マウスオーバー時のTips表示を行うカラムを指定します(初期値:指定しない)。
 *       linkClm         【TAG】レコード単位に、クリッカブルリンクを設定するカラムを指定します(初期値:指定しない)。
 *       useLegend       【TAG】カラーの凡例を使用するかどうか[true/false]を指定します(初期値:{@og.value #USE_LEGEND})。
 *       maxLabelWidth   【TAG】ラベル表記部の最大サイズをpxで指定します(初期値:{@og.value #MAX_LABEL_WIDTH})。
 *       maxTimeWidth    【TAG】タイム表記部の最大サイズをpxで指定をpxで指定します(初期値:{@og.value #MAX_TIME_WIDTH})。
 *       chartHeight     【TAG】１行のタイムチャートの幅をpxで指定します(初期値:{@og.value #CHART_HEIGHT})。
 *       padding         【TAG】イメージ作成の 全体テーブルの隙間（パディング）をpxで指定します(初期値:{@og.value #CHART_PADDING})。
 *       margin          【TAG】１レコードの文字やタイムチャートのマージンをpxで指定します(初期値:{@og.value #RECODE_MARGIN})。
 *       useLastData     【TAG】行の最後の情報が、継続しているとして使うかどうか[true/false]を指定(初期値:{@og.value #USE_LAST_DATA})。
 *       debug           【TAG】内部情報を出力します(初期値:false)。
 *   /&gt;
 *
 * ●使用例
 *     ViewFormTag の viewFormType が、ImageTimeBar の場合に使用します。
 *     useParam 属性を設定しておかないと、使用されません。
 *     &lt;og:view
 *         viewFormType = "ImageTimeBar"
 *         command      = "{&#064;command}"
 *         <b>useParam     = "true"</b>
 *     &gt;
 *         &lt;og:timeBarParam
 *             startDate   = "{&#064;DYFROM}"
 *             timeSpan    = "24"
 *         /&gt;
 *     &lt;/og:view &gt;
 *
 * @og.group 画面表示
 * @og.rev 5.5.5.6 (2012/08/31) 新規追加
 *
 * @version  4.0
 * @author	 Kazuhiko Hasegawa
 * @since    JDK5.0,
 */
public class ViewTimeBarParamTag extends ViewParamTag {
	//* このプログラムのVERSION文字列を設定します。	{@value} */
	private static final String VERSION = "5.6.1.1 (2013/02/08)" ;

	private static final long serialVersionUID = 561120130208L ;

	private static final String START_DATE		= null;		// タイムテーブルの表示開始日時をセットします(初期値:データの最小日時)。
	private static final String TIME_SPAN		= "24";		// タイムテーブルの表示期間を時間で指定します(初期値:{@og.value #TIME_SPAN})。

	private static final String LABEL_CLMS		= null;		// 一覧表のラベル表示部に表示するカラムをCSV形式で指定します。
	private static final String COLOR_CLM		= null;		// レコードに付ける色を色文字列で指定する場合のカラム名を指定します。
	private static final String TIPS_CLM		= null;		// レコード単位に、マウスオーバー時のTips表示を行うカラム名を指定します。
	private static final String LINK_CLM		= null;		// レコード単位に、クリッカブルリンクを設定するカラム名を指定します。

	private static final String USE_LEGEND		= "true";	// カラーの凡例を使用するかどうか[true/false]を指定します。
	private static final String MAX_LABEL_WIDTH	= null;		// ラベル表記部の最大サイズをpxで指定。何もなければ、可変長サイズ
	private static final String MAX_TIME_WIDTH	= "600";	// タイム表記部の最大サイズをpxで指定。
	private static final String CHART_HEIGHT	= "20";		// １レコードのチャートの間隔をpxで指定。実際の幅は、CHART_HEIGHT＋MARGIN＊２
	private static final String CHART_PADDING	= "5";		// イメージ作成の 全体テーブルの隙間
	private static final String RECODE_MARGIN	= "3";		// 各レコード、文字等の内部の間隔

	private static final String USE_LAST_DATA	= "true";	// 5.6.1.1 (2013/02/08) 行の最後の情報が、継続しているとして使うかどうか[true/false]を指定します。

	/** パラメータの初期値設定 */
	private static final Map<String,String>	INIT_PARAM = new HashMap<String,String>();
	static {
		INIT_PARAM.put( "START_DATE"		, START_DATE		);
		INIT_PARAM.put( "TIME_SPAN"			, TIME_SPAN			);
		INIT_PARAM.put( "LABEL_CLMS"		, LABEL_CLMS		);
		INIT_PARAM.put( "COLOR_CLM"			, COLOR_CLM			);
		INIT_PARAM.put( "TIPS_CLM"			, TIPS_CLM			);
		INIT_PARAM.put( "LINK_CLM"			, LINK_CLM			);
		INIT_PARAM.put( "USE_LEGEND"		, USE_LEGEND		);
		INIT_PARAM.put( "MAX_LABEL_WIDTH"	, MAX_LABEL_WIDTH	);
		INIT_PARAM.put( "MAX_TIME_WIDTH"	, MAX_TIME_WIDTH	);
		INIT_PARAM.put( "CHART_HEIGHT"		, CHART_HEIGHT		);
		INIT_PARAM.put( "CHART_PADDING"		, CHART_PADDING		);
		INIT_PARAM.put( "RECODE_MARGIN"		, RECODE_MARGIN		);
		INIT_PARAM.put( "USE_LAST_DATA"		, USE_LAST_DATA		);		// 5.6.1.1 (2013/02/08)
		INIT_PARAM.put( "TEMP_DIR"			, null				);
		INIT_PARAM.put( "TEMP_URL"			, null				);
	}

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

		final String FILE_DIR		= HybsSystem.sys( "CHART_TEMP_DIR" );		// 画像ファイルの作成DIR

		putParam( "TEMP_DIR" , HybsSystem.url2dir( FILE_DIR ) );
		putParam( "TEMP_URL" , getContextPath() + "/" + FILE_DIR );

		return SKIP_BODY ;				// Body を評価しない
	}

	/**
	 * 【TAG】タイムテーブルの表示開始日時をセットします(初期値:データの最小日時)。
	 *
	 * @og.tag
	 * 表示開始日時を起点として、タイムテーブルを表示します。
	 * 実際に画面に表示されるのは、開始時刻から終了時刻の範囲内だけですが、
	 * 起点は、この日時になります。
	 * 
	 * 指定方法として、フォーマットされた日付、時刻情報も設定可能です。（内部的に処理します）
	 * また、処理後(例：20120824102823）１４ケタ以上の場合は、１４ケタにカットします。
	 * ８ケタ以上の場合は、時刻 000000 を追加します。
	 * それ以下の場合は、設定エラーとして、HybsSystemException を throw します。
	 * 
	 * 表示開始日時が指定されない場合は、データの最小時刻を利用して表示します。
	 * 初期値は、データの最小日時 です。
	 *
	 * @param	startDate 表示開始日時
	 */
	public void setStartDate( final String startDate ) {
		String date = nval( getRequestParameter( startDate ),START_DATE );
		if( date != null ) {
			if( date.indexOf( '-' ) >= 0 ) { date = date.replaceAll( "-","" ); }
			if( date.indexOf( '/' ) >= 0 ) { date = date.replaceAll( "/","" ); }
			if( date.indexOf( ':' ) >= 0 ) { date = date.replaceAll( ":","" ); }
			if( date.indexOf( ' ' ) >= 0 ) { date = date.replaceAll( " ","" ); }

			final int len = date.length();
			if( len > 14 ) { date = date.substring( 0,14 ); }	// ミリ秒まで指定されていると想定
			else if( len > 8 && len < 14 ) { date = ( date + "000000" ).substring( 0,14 ) ; }	// 西暦からの日付は入っていると考えます。
			else {
				final String errMsg = "日付データの設定エラーです。date=[" + startDate + "]" ;
				throw new HybsSystemException( errMsg );
			}
		}
		putParam( "START_DATE" , date );
	}

	/**
	 * 【TAG】タイムテーブルの表示期間を時間で指定します(初期値:{@og.value #TIME_SPAN})。
	 *
	 * @og.tag
	 * 表示開始日時から、どれだけの時間範囲を表示対象とするかを指定します。
	 * 指定する単位は、時間です。
	 * 小数点は指定できません。また、１０日なら、"240" 、１か月（３０日）なら、"720"
	 * １年（３６５日）なら、"8760" を指定します。
	 * 実際に画面に表示されるのは、開始時刻から終了時刻の範囲内だけです。
	 * 初期値は、"{@og.value #TIME_SPAN}" です。
	 *
	 * @param	timeSpan 表示期間(時)
	 */
	public void setTimeSpan( final String timeSpan ) {
		putParam( "TIME_SPAN" , nval( getRequestParameter( timeSpan ),TIME_SPAN ) );
	}

	/**
	 * 【TAG】一覧表のラベル表示部に表示するカラムをCSV形式で指定します(初期値:キーのRenderer値)。
	 *
	 * @og.tag
	 * ラベル表示部に表示するカラムをCSV形式で指定します。
	 * 指定されたカラムの値の、Renderer値を画面上に表示します。
	 * ラベル表記部の最大サイズ（maxLblWidth）を指定しない場合は、ここで指定されたカラムの
	 * 値のそれぞれの最大長を加算した値が、ラベル表記部の最大サイズ（maxLblWidth）になります。
	 * 初期値は、キーのRenderer値 です。
	 *
	 * @param	labelClms ラベルカラム (CSV形式)
	 */
	public void setLabelClms( final String labelClms ) {
		putParam( "LABEL_CLMS" , nval( getRequestParameter( labelClms ),LABEL_CLMS ) );
	}

	/**
	 * 【TAG】レコードに付ける色を色文字列で指定する場合のカラム名を指定します(初期値:指定しない)。
	 *
	 * @og.tag
	 * レコード単位に、色を付ける場合、指定の色を付けたい場合に、外部から色文字列を与えることが可能です。
	 * 色文字列は、java.awt.Color の フィールド定義されているコードと同じ文字列です。
	 * また、#XXXXXX 形式の １６進文字列を与えることで、任意の色を指定可能です。
	 *
	 * 初期値は、"指定しない" です。
	 *
	 * @param	colorClm 色指定カラム名
	 */
	public void setColorClm( final String colorClm ) {
		putParam( "COLOR_CLM" , nval( getRequestParameter( colorClm ),COLOR_CLM ) );
	}

	/**
	 * 【TAG】レコード単位に、マウスオーバー時のTips表示を行うカラムを指定します(初期値:指定しない)。
	 *
	 * @og.tag
	 * レコード単位に、画像にマウスオーバー時のツールチップ表示のためのデータを作成します。
	 * HTMLのareaタグの alt 属性を出力します。
	 *
	 * 通常は、複数の文字列を使用しますので、viewMarker タグ等で整形してください。
	 * 何も指定しない場合は、リンクがなければ、なにも出力しません。
	 * 初期値は、"指定しない" です。
	 *
	 * @param	tipsClm Tips表示カラム名
	 */
	public void setTipsClm( final String tipsClm ) {
		putParam( "TIPS_CLM" , nval( getRequestParameter( tipsClm ),TIPS_CLM ) );
	}

	/**
	 * 【TAG】レコード単位に、クリッカブルリンクを設定するカラムを指定します(初期値:指定しない)。
	 *
	 * @og.tag
	 * レコード単位に、画像にクリッカブルリンクを設定するためのデータを作成します。
	 * HTMLのareaタグ の href 属性を出力します。
	 *
	 * 通常は、viewLink タグ等でリンクを作成してください。
	 * 何も指定しない場合は、Tipsがなければ、なにも出力しません。
	 * 初期値は、"指定しない" です。
	 *
	 * @param	linkClm リンク設定カラム名
	 */
	public void setLinkClm( final String linkClm ) {
		putParam( "LINK_CLM" , nval( getRequestParameter( linkClm ),LINK_CLM ) );
	}

	/**
	 * 【TAG】カラーの凡例を使用可否[true:する/false:しない]を指定します(初期値:{@og.value #USE_LEGEND})。
	 *
	 * @og.tag
	 * 状況コード、または、色文字列等でグラフ作成した場合の色に対する凡例を使用するかどうかを指定します。
	 * 凡例の表示位置は、グラフの上側で、１レコード分出力します。
	 *
	 * 初期値は、"{@og.value #USE_LEGEND}" です。
	 *
	 * @param	useLegend 凡例使用可否 [true:する/false:しない]
	 */
	public void setUseLegend( final String useLegend ) {
		putParam( "USE_LEGEND" , nval( getRequestParameter( useLegend ),USE_LEGEND ) );
	}

	/**
	 * 【TAG】ラベル表記部の最大サイズをpxで指定します(初期値:{@og.value #MAX_LABEL_WIDTH})。
	 *
	 * @og.tag
	 * 画像の１行は、ラベル表記部と、タイムチャート部に分かれます。
	 * その、ラベル表記部の最大サイズを指定します。
	 * 何も指定しなければ、可変長サイズ（ラベルの大きさに合わせた値）になります。
	 * 単位は px です。（pxは記述不要です）
	 * 初期値は、"{@og.value #MAX_LABEL_WIDTH}" です。
	 *
	 * @param	maxLblWidth ラベル最大幅 (px)
	 */
	public void setMaxLabelWidth( final String maxLblWidth ) {
		putPxParam( "MAX_LABEL_WIDTH" , maxLblWidth , MAX_LABEL_WIDTH );
	}

	/**
	 * 【TAG】タイム表記部の最大サイズをpxで指定をpxで指定します(初期値:{@og.value #MAX_TIME_WIDTH})。
	 *
	 * @og.tag
	 * 画像の１行は、ラベル表記部と、タイムチャート部に分かれます。
	 * そのタイムチャート部の最大サイズを指定します。
	 * この幅は、ここで指定した幅に固定されるため、時間範囲が多ければ、１時間当たりの表示幅が
	 * 小さくなります。
	 * たとえば、8H～20H=12H を 600px で表示すれば、１時間=５０px になりますし、24H 表示ならば、
	 * 半分の ２５px 、6H ならば、倍の 100px が、１時間の表示幅になります。
	 *
	 * 単位は px です。（pxは記述不要です）
	 * 初期値は、"{@og.value #MAX_TIME_WIDTH}" です。
	 *
	 * @param	maxTmWidth タイム最大幅(px)
	 */
	public void setMaxTimeWidth( final String maxTmWidth ) {
		putPxParam( "MAX_TIME_WIDTH" , maxTmWidth , MAX_TIME_WIDTH );
	}

	/**
	 * 【TAG】１行のタイムチャートの幅をpxで指定します(初期値:{@og.value #CHART_HEIGHT})。
	 *
	 * @og.tag
	 * 画像の１行の間隔は、上下のRECODE_MARGIN と、このチャート本体の幅になります（CHART_HEIGHT＋RECODE_MARGIN＊２）。
	 * ここでは、チャート本体の幅を指定します。
	 *
	 * 単位は px です。（pxは記述不要です）
	 * 初期値は、"{@og.value #CHART_HEIGHT}" です。
	 *
	 * @param	chartHeight タイムチャートの幅
	 */
	public void setChartHeight( final String chartHeight ) {
		putPxParam( "CHART_HEIGHT" , chartHeight , CHART_HEIGHT );
	}

	/**
	 * 【TAG】イメージ作成のパディング (全体テーブルの隙間)をpxで指定します(初期値:{@og.value #CHART_PADDING})。
	 *
	 * @og.tag
	 * イメージは、データの全行を含んだ１枚の画像ファイルになります。
	 * 画像ファイル自体の大きさと、書き込まれた画像の大きさは異なります。
	 * この、padding は、画像の周りに、余白として指定するサイズをpx単位で指定します。
	 * ここでは、上下左右に、均等にとります。
	 *
	 * 単位は px です。（pxは記述不要です）
	 * 初期値は、"{@og.value #CHART_PADDING}" です。
	 *
	 * @param	padding パディング (全体テーブルの隙間)
	 */
	public void setPadding( final String padding ) {
		putPxParam( "CHART_PADDING" , padding , CHART_PADDING );
	}

	/**
	 * 【TAG】１レコードの文字やタイムチャートのマージンをpxで指定します(初期値:{@og.value #RECODE_MARGIN})。
	 *
	 * @og.tag
	 * イメージは、１レコードづつ書き込まれますが、そのレコードの幅は、chartHeight で指定された
	 * タイムチャートの幅＋マージン＊２ になります。
	 * 同様に、ラベル表記部の文字の書き出し位置も、この、マージンが適用されます。
	 * （文字の場合は、上下左右に適用され、チャート部は、上下のみ適用されます。）
	 *
	 * 単位は px です。（pxは記述不要です）
	 * 初期値は、"{@og.value #RECODE_MARGIN}" です。
	 *
	 * @param	margin マージン(px)
	 */
	public void setMargin( final String margin ) {
		putPxParam( "RECODE_MARGIN" , margin , RECODE_MARGIN );
	}

	/**
	 * 【TAG】行の最後の情報が、継続しているとして使うかどうか[true/false]を指定します(初期値:{@og.value #USE_LAST_DATA})。
	 *
	 * @og.tag
	 * データは、開始時刻を与えられ、次のデータの開始時刻が前のデータの終了時刻として
	 * 処理しています。行の最後のデータは、表示範囲いっぱいまで、続いていると認識する場合は、
	 * この値を true とします。つまり、最後のデータは利用されます。
	 * 最後のデータがそこで処理を停止したイベントの場合、そのデータは使われません。
	 * その場合は、false に設定します。イベント色としては、"不明"（空欄＝白色） として扱います。
	 *
	 * 初期値は、"{@og.value #USE_LAST_DATA}" です。
	 *
	 * @og.rev 5.6.1.1 (2013/02/08) 新規追加
	 *
	 * @param	useLastData 継続使用可否 [true:する/false:しない]
	 */
	public void setUseLastData( final String useLastData ) {
		putPxParam( "USE_LAST_DATA" , useLastData , USE_LAST_DATA );
	}

	/**
	 * 引数の "px" 文字列を取り除く共通メソッド。
	 *
	 * 指定のパラメータに、"px" 文字列を含む場合、"px"文字列以降を削除します。
	 * HTML上には、px を付けた方が分かりやすいケースが考えられるためです。
	 * ここでは、putParam( String , String ) するために必要な、キー、初期値も指定する事で、
	 * 呼び出し元の処理を簡素化します。
	 * この処理では、val 引数を、getRequestParameter 処理し、結果を、nval で 初期値設定したあと、
	 * null 判定で、null でなければ、putParam にセットする処理をおこないます。
	 * この処理の中で、"px" 削除処理をおこないます。
	 *
	 * @param	key putParamする場合のキー
	 * @param	val "px"文字列があれば取り除く値
	 * @param	def 引数がnullの場合の、初期値
	 * @see		#putParam( String , String )
	 */
	private void putPxParam( final String key , final String val , final String def ) {
		String tmp = nval( getRequestParameter( val ),def );
		if( tmp != null ) {
			final int idx = tmp.indexOf( "px" );
			if( idx > 0 ) { tmp = tmp.substring( 0,idx ); }

			putParam( key , tmp );
		}
	}

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

	/**
	 * シリアライズ用のカスタムシリアライズ書き込みメソッド。
	 *
	 * @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();
	}
}
