/*
 * 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 static org.opengion.fukurou.util.StringUtil.nval;

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

import org.opengion.fukurou.util.Options;
import org.opengion.fukurou.util.StringUtil;
import org.opengion.fukurou.util.TagBuffer;
import org.opengion.fukurou.util.XHTMLTag;
import org.opengion.hayabusa.common.HybsSystem;
import org.opengion.hayabusa.common.HybsSystemException;

/**
 * プルダウンメニューを作成するHTML拡張タグです。
 *
 * プルダウンメニュー内の選択肢は、selectタグの内容であるoptionタグ、
 * またはqueryOptionタグによって指定します。
 * optionタグがセットされない場合は、name属性の、コードリソース からoption文字列より、
 * プルダウンメニューの選択肢を作成します。
 * name 属性に ラベルリソース のキーを与えることで、 ロケールにあわせたリソースを使用して、
 * 画面に表示します。ロケールは、ユーザー情報の lang 属性を初期値で使用し、
 * セットされていない場合は、リクエスト情報のロケールから取得します。
 * language 属性で定義されている場合は、そちらを優先します。
 *
 * @og.formSample
 * ●形式：&lt;og:select name="…" /&gt;
 * ●body：あり
 *
 * ●Tag定義：
 *   &lt;og:select
 *       name             ○【TAG】メニューの名称を指定します。(必須)
 *       value              【TAG】値を指定します
 *       defaultVal         【TAG】value属性に値がセットされていないとき使用する、初期値を指定します
 *       lbl                【TAG】ラベルリソースのラベルIDを指定します
 *       must               【TAG】必須入力を表す色に変えるかどうか[true/false]を指定します(初期値:false)
 *       mustAny            【TAG】選択必須入力(どれかひとつ必須)を表す色[true/mustAny/その他]を指定します(初期値:無指定)
 *       addNoValue         【TAG】値なしのOptionを含めるかどうか[true/false]を指定します(初期値:false)
 *       td                 【TAG】テーブル形式の &lt;td&gt; タグを使用するかどうか[yes/no/false]を指定します(初期値:yes)
 *       colspan            【TAG】フィールド部分の colspan を指定します
 *       optionAttributes   【TAG】JavaScript などの HTML基本タグ以外の属性を、そのままタグとして使用します
 *       size               【TAG】リストボックスとして表示する場合の表示行数を指定します
 *       multiple           【TAG】複数選択を可能(multiple)にします(初期値:未設定)
 *       id                 【HTML】要素に対して固有の名前(id)をつける場合に設定します
 *       caseKey            【TAG】このタグ自体を利用するかどうかの条件キーを指定します(初期値:null)
 *       caseVal            【TAG】このタグ自体を利用するかどうかの条件値を指定します(初期値:null)
 *       lang               【HTML】要素の内容と他の属性値の言語(lang,xml:lang)を指定します
 *       dir                【HTML】文字表記の方向(dir)を指定します
 *       title              【HTML】要素に対する補足的情報(title)を設定します
 *       style              【HTML】この要素に対して適用させるスタイルシート(style)を設定します
 *       disabled           【TAG】その部品に対して、選択や変更が出来ないように(disabled)指定します(サーバーに送信されない)
 *       tabindex           【HTML】タブの移動順(tabindex)を指定します(0 ～ 32767)
 *       clazz              【HTML】要素に対して class 属性を設定します
 *       language           【TAG】タグ内部で使用する言語コード[ja/en/zh/…]を指定します
 *       onClick            【HTML】JavaScriptのイベント onClick を設定します(例:onClick="renew('query.jsp','QUERY');")
 *       onChange           【HTML】JavaScriptのイベント onChange を設定します(例:onChange="renew('query.jsp','QUERY');")
 *       onBlur             【HTML】JavaScriptのイベント onBlur を設定します(例:onBlur="this.value=value.toUpperCase();")
 *       onFocus            【HTML】JavaScriptのイベント onFocus を設定します
 *       ondblClick         【HTML】JavaScriptのイベント ondblClick を設定します
 *       onMouseDown        【HTML】JavaScriptのイベント onMouseDown を設定します
 *       onMouseUp          【HTML】JavaScriptのイベント onMouseUp を設定します
 *       onMouseMove        【HTML】JavaScriptのイベント onMouseMove を設定します
 *       onMouseOut         【HTML】JavaScriptのイベント onMouseOut を設定します
 *       onMouseOver        【HTML】JavaScriptのイベント onMouseOver を設定します
 *       onSelect           【HTML】JavaScriptのイベント onSelect を設定します
 *       onKeydown          【HTML】JavaScriptのイベント onKeydown を設定します
 *       onKeypress         【HTML】JavaScriptのイベント onKeypress を設定します
 *       onKeyup            【HTML】JavaScriptのイベント onKeyup を設定します
 *       roles              【TAG】ロールをセットします
 *       eventColumn        【TAG】イベントカラム(親カラム)を指定します
 *       eventURL           【TAG】イベントカラム指定時に呼び出すURL
 *       eventCallback      【TAG】eventColumn実行後のcallbak関数指定
 *       debug              【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false)
 *   &gt;   ... Body ...
 *   &lt;/og:select&gt;
 *
 * ●使用例
 *    &lt;og:select name="CDC"&gt;                       CodeResource プロパティの値を使用したいときはcode属性を使います。
 *        &lt;og:option code="CDC" /&gt;
 *    &lt;/og:select&gt;
 *
 *    &lt;og:select name="CDC"&gt;                       選択項目の一番上に項目を付け足すことも可能です。
 *        &lt;og:option msg="MSG0001" /&gt;              MessageResource プロパティの値を使用したいとききはmsg属性を使います。
 *        &lt;og:option code="CDC" /&gt;
 *    &lt;/og:select&gt;
 *
 *    &lt;og:select name="CDC"&gt;                       選択項目の一番上に項目を付け足すことも可能です。
 *        &lt;og:option lbl="CDC1" /&gt;                 LabelResource プロパティの値を使用したいとききはlbl属性を使います。
 *        &lt;og:option code="CDC" /&gt;
 *    &lt;/og:select&gt;
 *
 *    &lt;og:select name="CDC" multiple="multiple"&gt;   選択肢の中から複数選択できるようにするときはmultiple属性を使います。
 *        &lt;og:option code="CDC" /&gt;
 *    &lt;/og:select&gt;
 *
 *    &lt;og:select name="CDC" disabled="disabled"&gt;   選択不可にするときはdisabled属性を使います。
 *        &lt;og:option code="CDC" /&gt;
 *    &lt;/og:select&gt;
 *
 *    &lt;og:select name="CDC"&gt;                       選択肢をSELECT文の結果から作成したいときはqueryOptionタグと組み合わせて使います。
 *        &lt;og:queryOption&gt;
 *                    select NOSYN,NOSYN,':',NMSYN from DB01 ORDER BY 1
 *        &lt;/og:queryOption&gt;
 *    &lt;/og:select&gt;
 *
 *    &lt;og:select name="CDC" eventColumn="OYA" &gt;    親子関係のプルダウンを作る場合
 *        &lt;og:queryOption&gt;
 *                    select NOSYN,NOSYN,':',NMSYN from DB01
 *                     where CLM = "{&#64;OYA}" ORDER BY 1
 *        &lt;/og:queryOption&gt;
 *    &lt;/og:select&gt;
 *
 * @og.group 選択データ制御
 *
 * @version  4.0
 * @author	 Kazuhiko Hasegawa
 * @since    JDK5.0,
 */
public class SelectTag extends HTMLTagSupport {
	//* このプログラムのVERSION文字列を設定します。	{@value} */
	private static final String VERSION = "4.0.0 (2005/08/31)" ;

	private static final long serialVersionUID = 4000 ;	// 4.0.0 (2005/01/31)

	// 4.0.0 (2005/01/31) HTML_LABEL_SEPARATOR を boolean 変数として取得します。
	private final String CLM = ( HybsSystem.sysBool( "HTML_LABEL_SEPARATOR" ) ) ? ":" : "" ;

	// 4.0.0 (2005/01/31) USE_MULTI_KEY_SELECT を定義しておきます。
	private final boolean USE_MULTI_KEY_SELECT =  HybsSystem.sysBool( "USE_MULTI_KEY_SELECT" ) ;

	// 4.3.6.0 (2009/04/01) JSPの位置を取っておく
//	private static final String JSP = HybsSystem.sys( "JSP" );

	private transient Options option		= new Options();
	private String  td_flag		= "yes";	// yes:<td> タグを使用 / false:フィールドのみ / no:ラベルとフィールド

	// 3.0.1.3 (2003/03/11) colspan 属性を追加。
	private String  colspan     = null;

	// 3.5.4.0 (2003/11/25) value ,defaultVal  属性を追加。
	private String  value       = null;
	private String	defaultVal	= null;		// value がセットされていないときの初期値
	private boolean multipleAll	= false;	// 3.8.0.9 (2005/10/17) 複数選択可能時に全選択を設定する。
	private String eventColumn	= null;		// 4.3.6.0 (2009/04/01) イベントカラム
//	private String eventURL		= JSP + "/" + HybsSystem.sys( "EVENT_COLUMN_URL" ); // 4.3.6.0 (2009/04/01) 処理JSPの設定
	private String eventURL		= null;		// 5.1.9.0 (2010/08/01) 動的プルダウン不具合対応

	// 4.1.2.1 (2008/03/13) must , mustAny 属性を自動化します。
	// 5.2.1.0 (2010/10/01) must , mustAny 属性の処理を、HTMLTagSupport に移します。
//	private String	mustType	= null;		// 4.1.2.1 (2008/03/13)

	private String	rawParam	= null;		// 5.1.7.0 (2010/06/01) 動的プルダウン実装見直し

	// 5.1.9.0 (2010/08/01) 値なしのOptionをSelectに含めるかどうか 新規追加
	private boolean addNoValue  = false;	// 互換性のため、初期値は、false になります。

	/**
	 * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。
	 *
	 * @og.rev 5.0.2.0 (2009/11/01) 複数パラメーターの選択に対応
	 * @og.rev 5.1.7.0 (2010/06/01) command=RENEWの場合はdefaultValを無視する。
	 * @og.rev 5.1.9.0 (2010/08/01) addNoValue 対応
	 * @og.rev 5.2.2.0 (2010/11/01) caseKey 、caseVal 属性対応
	 * @og.rev 5.3.7.0 (2011/07/01) 5.1.7.0 (2010/06/01)の対応で判定条件が逆転しているバグを修正
	 *
	 * @return	後続処理の指示( EVAL_BODY_INCLUDE )
	 */
	@Override
	public int doStartTag() {
		// 5.2.2.0 (2010/11/01) caseKey 、caseVal 属性対応
		if( useTag() ) {
			if( value == null ) {
	//			value = nval( getRequestValue( get( "name" ) ),defaultVal );
				// 5.1.7.0 (2010/06/01) command=RENEWの場合はdefaultValを無視する。
				String cmd = pageContext.getRequest().getParameter( "command" );
				if( "RENEW".equals( cmd ) ) {
					value = StringUtil.array2line( getRequestValues( get( "name" ) ), "|" );
				}
				else {
					value = nval( StringUtil.array2line( getRequestValues( get( "name" ) ), "|" ),defaultVal );
				}
			}

			// 5.1.9.0 (2010/08/01) addNoValue 対応:option を最初にセットする。
			if( addNoValue ) {
				option.add( "<option value=\"\" ></option>" );
			}

			return( EVAL_BODY_INCLUDE );	// Body インクルード( extends TagSupport 時)
		}
		return ( SKIP_BODY );				// Body を評価しない
	}

	/**
	 * タグリブオブジェクトをリリースします。
	 * キャッシュされて再利用されるので、フィールドの初期設定を行います。
	 *
	 * @og.rev 2.0.0.4 (2002/09/27) カスタムタグの release() メソッドを、追加
	 * @og.rev 2.0.0.8 (2002/10/09) yes/no/false で指定するように変更
	 * @og.rev 3.0.1.3 (2003/03/11) colspan 属性を追加。
	 * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。
	 * @og.rev 3.5.4.0 (2003/11/25) value ,defaultVal  属性を追加。
	 * @og.rev 3.8.0.9 (2005/10/17) 複数選択可能時に全選択を設定する。
	 * @og.rev 4.1.2.1 (2008/03/13) must , mustAny 属性を自動化します。
	 * @og.rev 4.3.6.0 (2009/04/01) eventColumn,eventURL追加
	 * @og.rev 5.1.7.0 (2010/06/01) 動的プルダウン実装見直し
	 * @og.rev 5.1.9.0 (2010/08/01) columnタグで動的プルダウンが動作しない不具合に対応
	 * @og.rev 5.1.9.0 (2010/08/01) addNoValue  属性を追加。
	 * @og.rev 5.2.1.0 (2010/10/01) must , mustAny 属性の処理を、HTMLTagSupport に移します。
	 *
	 */
	@Override
	protected void release2() {
		super.release2();
		option		= new Options();
		td_flag     = "yes";	// table形式の <td> タグを使用するかどうか
		colspan     = null;
		value       = null;
		defaultVal	= null;		// value がセットされていないときの初期値
		multipleAll	= false;	// 3.8.0.9 (2005/10/17) 複数選択可能時に全選択を設定する。
//		mustType	= null;		// 4.1.2.1 (2008/03/13)		// HTMLTagSupport に移します。
		eventColumn	= null;		// 4.3.6.0 (2009/04/01)
//		eventURL	= JSP + "/" + HybsSystem.sys( "EVENT_COLUMN_URL" ); // 4.3.6.0 (2009/04/01)
		eventURL	= null;		// 5.1.9.0 (2010/08/01) columnタグで動的プルダウンが動作しない不具合に対応
		rawParam	= null;		// 5.1.7.0 (2010/06/01) 動的プルダウン実装見直し
		addNoValue  = false;	// 5.1.9.0 (2010/08/01) 互換性のため、初期値は、false になります。
	}

	/**
	 * 入力用のプルダウンメニューを作成します。
	 *
	 * 表示順の項目名タグは、あらかじめ作成済みの値をここでは受け取ります。
	 * hasSelect 属性の値に応じて，タグの作成方法は変わります。
	 *
	 * @og.rev 2.0.0.8 (2002/10/09) yes/no/false で指定するように変更
	 * @og.rev 2.0.1.0 (2002/10/10) ラベルとフィールドのセパレーターとして、コロン(：)を使用するかどうかを指定できる
	 * @og.rev 3.0.1.3 (2003/03/11) colspan 属性を追加。
	 * @og.rev 3.5.4.0 (2003/11/25) value ,defaultVal  属性を追加。
	 * @og.rev 4.0.0 (2005/01/31) マルチセレクションのON/OFFをここで指定。
	 * @og.rev 4.1.2.1 (2008/03/13) must , mustAny 属性を自動化します。
	 * @og.rev 4.3.6.0 (2009/04/01) eventColumn対応
	 * @og.rev 4.3.7.1 (2009/06/08) id=labelのclass化
	 * @og.rev 5.1.7.0 (2010/06/01) 動的プルダウン実装見直し
	 * @og.rev 5.2.1.0 (2010/10/01) must , mustAny 属性の処理を、HTMLTagSupport に移します。
	 * @og.rev 5.5.3.0 (2012/06/01) idのセット見直し
	 * @og.rev 5.6.2.2 (2013/03/15) 自動must処理の出力位置を変更
	 *
	 * @return	表示順選択用のプルダウンメニュータグ
	 */
	@Override
	protected String makeTag() {

		String name = get( "name" );
		if( getMsglbl() == null ) { setLbl( name ); }

		if( colspan != null ) {
			colspan = " colspan=\"" + colspan + "\" ";
		}
		else {
			colspan = "";
		}

		// 4.0.0 (2005/01/31) XHTMLTag.java より移動)
		if( USE_MULTI_KEY_SELECT ) {
			set( "onkeydown", "setKeySelect(this);" );
		}

		StringBuilder rtn = new StringBuilder( HybsSystem.BUFFER_MIDDLE );

		// 5.5.3.0 既にIDが指定されている場合はnameをセットしない
		if( get("id")==null || get("id").length() == 0 ){
			set( "id", name );
		}

		// 4.3.6.0 (2009/04/01) eventColumnの対応
		// 5.1.7.0 (2010/06/01) 動的プルダウン実装見直し
//		if( eventColumn != null && eventColumn.length() > 0 ) {
//			String[] evntCols = StringUtil.csv2Array( eventColumn );
//			for( int i = 0; i < evntCols.length; i++ ) {
//				// SelectTagは"DBMENU"をmakeColumnに渡す。
//				String javaScript =
//					"<script type=\"text/javascript\">" +
//					"$(function(){$('#" + evntCols[i] + "').change(function(){" +
//					"makeColumn('" + name + "','" + name + "',EC_" + name + ",'DBMENU','" + eventURL + "');}).change();});"+
//					"</script>"
//					;
//				rtn.append( javaScript );
//			}
//		}

		String selTag = XHTMLTag.select( getAttributes(), option );

		// 5.1.7.0 (2010/06/01) 動的プルダウン実装見直し
		if( eventColumn != null && eventColumn.length() > 0 ) {
			String editor = null;
			if( rawParam != null && rawParam.length() > 0 ) {
				editor = "DBMENU";
			}
			else {
				editor = "MENU";
			}
			addEventColumn( name, eventColumn, eventURL, "", editor, "", rawParam );
			TagBuffer span = new TagBuffer( "span" );
			span.add( "class", HybsSystem.EVENT_COLUMN_CLASS );
			span.add( HybsSystem.EVENT_COLUMN_ID, name );
			span.add( HybsSystem.EVENT_COLUMN_INITVAL, value );
			span.add( HybsSystem.EVENT_COLUMN_WRITABLE, "true" );
			span.setBody( selTag );
			selTag = span.makeTag();
		}

		if( "yes".equals( td_flag ) ) {
			// 4.3.7.1 (2009/06/08) id=labelのclass化
			// rtn.append( "<td id=\"label\">" );
			rtn.append( "<td class=\"label\">" );
			rtn.append( getLongLabel() );		// 4.0.0 (2005/01/31)
			rtn.append( CLM );
			rtn.append( "</td>" );
			rtn.append( "<td" );
			rtn.append( colspan );
			rtn.append( ">" );
//			rtn.append( XHTMLTag.select( getAttributes(), option ) );
			rtn.append( selTag );
			if( getMustType() != null ) { rtn.append( makeMustHidden( name ) ); } // 5.6.2.2 (2013/03/15)
			rtn.append( "</td>" );
		}
		else if( "no".equals( td_flag ) ) {
			// 4.3.7.1 (2009/06/08) id=labelのclass化
			// rtn.append( "<span id=\"label\">" );
			rtn.append( "<span class=\"label\">" );
			rtn.append( getLongLabel() );		// 4.0.0 (2005/01/31)
			rtn.append( CLM );
			rtn.append( "</span>" );
//			rtn.append( XHTMLTag.select( getAttributes(), option ) );
			rtn.append( selTag );
			if( getMustType() != null ) { rtn.append( makeMustHidden( name ) ); } // 5.6.2.2 (2013/03/15)
		}
		else {
//			rtn.append( XHTMLTag.select( getAttributes(), option ) );
			rtn.append( selTag );
			if( getMustType() != null ) { rtn.append( makeMustHidden( name ) ); } // 5.6.2.2 (2013/03/15)
		}

	 	// 4.1.2.1 (2008/03/13) must , mustAny 属性を自動化します。
//		if( mustType != null ) {
//			rtn.append( XHTMLTag.hidden( HybsSystem.MUST_KEY + mustType, name ) );
//		}
	 	// 5.2.1.0 (2010/10/01) must , mustAny 属性を自動化します。
		// 5.6.2.2 (2013/03/15) tdの外に出力される不正形を正します
//		if( getMustType() != null ) { rtn.append( makeMustHidden( name ) ); }

		return rtn.toString() ;
	}

	/**
	 * メニュー項目の選択項目を追加します。
	 *
	 * select タグのBODY要素の OptionTag よりアクセスされます。
	 *
	 * @og.rev 3.1.2.0 (2003/04/07) taglib パッケージ内部で使用している箇所を protected 化する。
	 * @param	opt 	 オプションタグ文字列
	 */
	protected void addOption( final String opt ) {
		option.add( opt );
	}

	/**
	 * 【TAG】メニューの名称を指定します。
	 *
	 * @og.tag メニューの名称を指定します。
	 *
	 * @param	name 名称
	 */
	public void setName( final String name ) {
		set( "name", getRequestParameter( name ) );
	}

	/**
	 * 【TAG】リストボックスとして表示する場合の表示行数を指定します。
	 *
	 * @og.tag 表示行数を指定します。
	 *
	 * @param	size 表示行数
	 */
	public void setSize( final String size ) {
		set( "size",getRequestParameter( size ) );
	}

	/**
	 * 【TAG】複数選択を可能(multiple)にします(初期値:未設定)。
	 *
	 * @og.tag
	 * multiple 値が "multiple" または "true" の場合、複数選択状態になります。
	 * また、"ALL" を設定する場合は、OptionTag上で、すべてのOption が選択状態に
	 * 初期設定されます。
	 * 大文字、小文字の種別はなくしますが、指定以外の文字が設定された場合は、エラーになります。
	 *
	 * @og.rev 3.8.0.9 (2005/10/17) 複数選択可能時に全選択を設定する。
	 *
	 * @param	multi 複数選択("multiple" または "true") ,初期値全選択( "ALL" )
	 */
	public void setMultiple( final String multi ) {
		String multiple = nval( getRequestParameter( multi ),null );
		if( "multiple".equalsIgnoreCase( multiple ) || "true".equalsIgnoreCase( multiple ) ) {
			set( "multiple","multiple" );
		}
		else if( "ALL".equalsIgnoreCase( multiple ) ) {
			set( "multiple","multiple" );
			multipleAll = true;
		}
		else if( ! ( "false".equalsIgnoreCase( multiple ) || multiple == null ) ) {
			String errMsg = "multiple 属性には、[multiple,true,ALL] 以外は設定できません。"
						+ "multiple=" + multi ;
			throw new HybsSystemException( errMsg );
		}
	}

	/**
	 * 【TAG】必須入力を表す色に変えるかどうか[true/false]指定します(初期値:false)。
	 *
	 * @og.tag
	 * 初期値は、必須でない("false") です。
	 *
	 * @og.rev 4.0.0 (2005/02/28) must属性の登録を、id属性から、class 属性に変更します。
	 * @og.rev 4.1.2.1 (2008/03/13) must属性を自動化します。
	 * @og.rev 5.2.1.0 (2010/10/01) must , mustAny 属性の処理を、HTMLTagSupport に移します。
	 *
	 * @param	flag 必須入力 ("true")／必須でない (それ以外)
	 */
//	public void setMust( final String flag ) {
////		boolean must = nval( getRequestParameter( flag ),false );
//		mustType = nval( getRequestParameter( flag ),null );
//		if( "true".equalsIgnoreCase( mustType ) ) {
//			mustType = "must";
//			add( "class","must" );
//		}
//	}

	/**
	 * 【TAG】選択必須入力(どれかひとつ必須)を表す色(true|mustAny|その他)を指定します(初期値:無指定)。
	 *
	 * @og.tag
	 * 複数のカラムのうち、どれかひとつを必須とする選択必須入力を示す色を指定します。
	 * true または、mustAny を設定すると、class属性に、mustAny がセットされます。
	 * mustAny は、CSSファイルに初期設定されています。true または、mustAny 以外の値をセット
	 * すると、その値がそのまま、class属性にセットされますので、選択必須のグループ化が
	 * 可能です。
	 * なお、実際の選択必須入力チェックは、ここではなく、columnCheck タグで指定が必要です。
	 * 自動処理は、mustAny="true" 指定の場合のみ有効です。
	 * 初期値は、無指定です。
	 *
	 * @og.rev 3.8.0.9 (2005/10/17) 新規追加
	 * @og.rev 4.1.2.1 (2008/03/13) mustAny属性を自動化します。
	 * @og.rev 5.2.1.0 (2010/10/01) must , mustAny 属性の処理を、HTMLTagSupport に移します。
	 *
	 * @param	flag 選択必須入力(どれかひとつ必須)を表す色を指定(true|mustAny|その他)
	 */
//	public void setMustAny( final String flag ) {
//		if( mustType == null ) {	// must 属性と同時設定時には、must 属性を優先します。
//			mustType = nval( getRequestParameter( flag ),null );
//			if( "true".equalsIgnoreCase( mustType ) ) {
//				mustType = "mustAny";
//			}
//			add( "class",mustType );	// mustType == null の場合は、add されません。
//		}
//
////		String str = nval( getRequestParameter( flag ),null );
////		if( str != null ) {
////			if( str.equalsIgnoreCase( "true" ) ) {
////				add( "class","mustAny" );
////			}
////			else {
////				add( "class",str );
////			}
////		}
//	}

	/**
	 * 【TAG】テーブル形式の &lt;td&gt; タグを使用するかどうか[yes/no/false]を指定します(初期値:yes)。
	 *
	 * @og.tag
	 * 初期値は、使用する("yes") です。
	 *
	 * @og.rev 2.0.0.8 (2002/10/09) yes/no/false で指定するように変更
	 * @og.rev 5.5.1.0 (2012/04/03) エラーメッセージ変更
	 *
	 * @param   flag [yes:tdタグを使用/no:ラベルとフィールド/false:フィールドのみ]
	 */
	public void setTd( final String flag ) {
		String td = nval( getRequestParameter( flag ),td_flag );

		if( check( "|" + td + "|" , "|yes|no|false|" ) ) {
			td_flag = td;
		}
		else {
			String errMsg = "Error in SelectTag [td]: " + td;
			//errMsg = errMsg + "  in [|true|false|label|] only used";
			errMsg = errMsg + "  in [|yes|no|false|] only used"; // 5.5.1.0 (2012/04/03)
			throw new HybsSystemException( errMsg );
		}
	}

	/**
	 * 【TAG】フィールド部分の colspan を指定します。
	 *
	 * @og.tag
	 * 通常は、3 を指定して、フィールド、ラベル、フィールドの
	 * 組み合わせ部分に、長いフィールドが適用されるように使用します。
	 *
	 *  &lt;og:select name="CDK" colspan="3" /&gt;
	 *
	 * @og.rev 3.0.1.3 (2003/03/11) colspan 属性を追加。
	 *
	 * @param   sp フィールド部分の colspan
	 */
	public void setColspan( final String sp ) {
		colspan = nval( getRequestParameter( sp ),colspan );
	}

	/**
	 * 【TAG】値を指定します。
	 *
	 * @og.tag
	 *   ここで指定された値が、optionタグの値と同じであれば、選択状態になります。
	 *
	 *    &lt;og:select name="CDC" value="{&#064;ABC}" defaultVal="XYZ"  &gt;
	 *         &lt;og:option value="ABC" lbl="CDC1" /&gt;
	 *         &lt;og:option value="XYZ" lbl="CDC2" /&gt;
	 *    &lt;/og:select&gt;
	 *
	 * @og.rev 3.5.4.0 (2003/11/25) 新規作成
	 * @og.rev 5.0.2.0 (2009/11/01) 複数パラメーターの選択に対応
	 *
	 * @param   val 値
	 */
	public void setValue( final String val ) {
//		value = nval( getRequestParameter( val ),value );
		value = nval( StringUtil.array2line( getRequestParameterValues( val ), "|" ),value );
	}

	/**
	 * 値を外部から取り出します。
	 *
	 * OptionTag で、value を取り出して、内部の値と同じ場合は、選択状態にします。
	 *
	 * @og.rev 3.5.4.0 (2003/11/25) 新規作成
	 *
	 * @return	内部に設定された値
	 */
	protected String getValue() {
		return value;
	}

//	/**
//	 * 親のカラムを取得
//	 *
//	 * QueryOptiontagで、eventColumnを取り出して生SQL文の
//	 * セッションへの登録判断をします
//	 *
//	 * @og.rev 4.3.6.0 (2009/04/01)
//	 *
//	 * @return イベントカラム
//	 */
//	protected String getEventColumn() {
//		return eventColumn;
//	}

	/**
	 * 【TAG】イベントカラム(親カラム)を指定します。
	 *
	 * @og.tag
	 *   親子関係のカラムを作成する場合に利用します。
	 *   queryOptionタグとセットで利用して下さい。
	 *
	 *   ※詳細はcolumnTagのeventColumn属性の説明をご覧下さい。
	 *
	 * @og.rev 4.3.6.0 (2009/04/01)
	 *
	 * @param   col 親カラム名
	 */
	public void setEventColumn( final String col ) {
		eventColumn = nval( getRequestParameter( col ), eventColumn );
	}

	/**
	 * 【TAG】イベントカラム指定時に呼び出すURL。
	 *
	 * @og.tag
	 *   イベントカラム指定時に部品を作成するJSPを指定します。
	 *   初期値はシステムリソースのEVENT_COLUMN_URLです。
	 *   (例：eventURL="makeColumn_custom.jsp")
	 *
	 *   ※詳細はcolumnTagのeventURL属性の説明をご覧下さい。
	 *
	 * @og.rev 4.3.6.0 (2009/04/01)
	 *
	 * @param	url	呼び出すURL
	 */
	public void setEventURL( final String url ) {
		eventURL = nval( getRequestParameter( url ), eventURL );
	}

	/**
	 * 複数選択可能時に全選択を設定するかどうかを返します。
	 *
	 * これは、上位入れ子のタグの OptionTag で、multipleAll を取り出して、
	 * true であれば、全選択に設定します。
	 *
	 * @og.rev 3.8.0.9 (2005/10/17) 新規作成
	 *
	 * @return	全選択:true / 通常:false
	 */
	protected boolean isMultipleAll() {
		return multipleAll;
	}

	/**
	 * 【TAG】value属性に値がセットされていないとき使用する、初期値を指定します。
	 *
	 * @og.tag
	 * value属性に値がセットされていないときに、初期値をセットします。
	 *
	 * なお、commandがRENEWの場合は、このdefaultValは適用されません。
	 * これは、defaultValの値が埋め込まれた項目が存在する画面に戻った際に、
	 * defaultValの項目の値がnullとなっていた場合に、defaultValの値が復元されると、
	 * 検索結果との不一致が発生するためです。
	 *
	 * @og.rev 3.5.4.0 (2003/11/25) 新規作成
	 * @og.rev 5.0.2.0 (2009/11/01) 複数パラメーターの選択に対応
	 *
	 * @param	dv 初期値
	 */
	public void setDefaultVal( final String dv ) {
//		defaultVal = nval( getRequestParameter( dv ),defaultVal );
		defaultVal = nval( StringUtil.array2line( getRequestParameterValues( dv ), "|" ),defaultVal );
	}

	/**
	 * 【TAG】値なしのOptionを含めるかどうか[true/false]を指定します(初期値:false)。
	 *
	 * @og.tag
	 * カラムがプルダウンメニュー形式の場合、選択肢には通常データベース登録できる候補が
	 * 並びます。しかし、検索時には、候補を絞りたくない(指定しない)場合があり、
	 * その様な場合には、値なしのOptionを含める(true)ことで、対応可能です。
	 * 初期値:false(値なしのOptionを含めない)は、過去の互換性を重視しているため、column タグと異なります。
	 *
	 * @og.rev 5.1.9.0 (2010/08/01) 新規追加
	 *
	 * @param   flag  [true:含める/それ以外:含めない]
	 */
	public void setAddNoValue( final String flag ) {
		addNoValue = nval( getRequestParameter( flag ),addNoValue );
	}

	/**
	 * パラメーター変換({&#64;XXXX}の置き換えをしない状態のパラメーターをセットします。
	 *
	 * @og.rev 5.1.7.0 (2010/06/01) 新規作成(動的プルダウン実装見直し)
	 * @og.rev 5.5.4.0 (2012/07/02) 予約語対応
	 *
	 * @param   param パラメーター
	 */
	protected void setRawParam( final String param ) {
//		rawParam = nval( param, rawParam );
		rawParam = nval( getReservedParameter(param), rawParam ); // 5.5.4.0 (2012/07/02)
	}

	/**
	 * 【TAG】eventColumn実行後のcallbak関数指定。
	 *
	 * @og.tag
	 * eventColumnの動作終了後に実行するCallback関数の指定を行います。
	 * 関数名のみを指定して下さい。
	 * 　ex) sampleCallback()を実行する場合はeventCallback="sampleCallback"
	 * 実行する関数の第一引数には自動的に次の要素が入った配列が渡されます
	 * 　[0] 変更された子カラムのID属性値
	 * 　[1] evnetColumn実行後の子カラムの値
	 * 　[2] eventColumn実行前の子カラムの値
	 *
	 * この属性は、optionAttributesへの設定と同様の動作を行います。
	 *
	 * @og.rev 5.5.4.0 (2012/07/02) 新規追加
	 *
	 * @param   callback callbak関数
	 */
	public void setEventCallback( final String callback ) {
		// optionAttributes扱いで登録します。
		if( callback != null && callback.length() > 0 ){
			add( "optionAttributes", "eventCallback='"+getRequestParameter( callback )+"'" );
		}
	}

	/**
	 * シリアライズ用のカスタムシリアライズ書き込みメソッド
	 *
	 * @og.rev 4.0.0 (2006/09/31) 新規追加
	 * @serialData
	 *
	 * @param	strm	ObjectOutputStreamオブジェクト
	 */
	private void writeObject( final ObjectOutputStream strm ) throws IOException {
		strm.defaultWriteObject();
	}

	/**
	 * シリアライズ用のカスタムシリアライズ読み込みメソッド
	 *
	 * ここでは、transient 宣言された内部変数の内、初期化が必要なフィールドのみ設定します。
	 *
	 * @og.rev 4.0.0 (2006/09/31) 新規追加
	 * @serialData
	 *
	 * @param	strm	ObjectInputStreamオブジェクト
	 * @see #release2()
	 */
	private void readObject( final ObjectInputStream strm ) throws IOException , ClassNotFoundException {
		strm.defaultReadObject();
		option = new Options();
	}

	/**
	 * このオブジェクトの文字列表現を返します。
	 * 基本的にデバッグ目的に使用します。
	 *
	 * @return このクラスの文字列表現
	 */
	@Override
	public String toString() {
		return org.opengion.fukurou.util.ToString.title( this.getClass().getName() )
				.println( "VERSION"		,VERSION		)
				.println( "td_flag"		,td_flag		)
				.println( "colspan"		,colspan 		)
				.println( "value"		,value			)
				.println( "defaultVal"	,defaultVal		)
				.println( "multipleAll"	,multipleAll	)
				.println( "Other..."	,getAttributes().getAttribute() )
				.fixForm().toString() ;
	}
}
