/*
 * 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 org.opengion.hayabusa.db.DBColumn;
import org.opengion.hayabusa.db.DBColumnConfig;
import org.opengion.hayabusa.resource.CodeData ;
import org.opengion.hayabusa.resource.RoleMode ;
import org.opengion.fukurou.util.Attributes;
import org.opengion.fukurou.util.XHTMLTag;
import org.opengion.fukurou.util.StringUtil;
import static org.opengion.fukurou.util.StringUtil.nval ;

/**
 * カラムリソースに基づいた、入力フィールドなどを作成するHTML拡張タグです。
 *
 * name 属性に カラムリソースのキーを与えることにより、指定した表示形式にて画面に表示します。
 * column タグは、リソースの設定が反映されるため、アプリケーションを修正せずに、
 * 機能拡張することが可能です。たとえば、テキストフィールド入力に設定していたカラムを、
 * プルダウンメニューに即座に変更可能です。
 * カラム定義でロールが指定されている場合、ログインユーザーでアクセス許可がない場合は
 * カラムは表示されません。
 * カラムリソースに存在しない場合や特殊用途に使用する場合は、inputタグを使用してください。
 *
 * @og.formSample
 * ●形式：&lt;og:column name=… value=… /&gt;
 * ●body：あり
 *
 * ●使用例
 *    &lt;og:column name="PN" /&gt;                                 編集種別がTexｔの場合は、テキストフィールドが表示されます。
 *                                                                   通常はNAME属性を指定するだけです。
 *    &lt;og:column name="CDC" /&gt;                                編集種別がMenuの場合は、メニューが表示されます。
 *    &lt;og:column name="PN" value="syokichi" /&gt;                初期値をセットするときはvalue属性を使います。
 *    &lt;og:column name="PN" lbl="PNL" /&gt;                       ラベルを変更するときはlbl属性を使います。
 *    &lt;og:column name="CDC" /&gt;                                リソースファイルからコンボボックスも自動作成されます。
 *    &lt;og:column name="CDC" addNoValue="false" /&gt;             NULL値を消すときはaddNoValue属性を使います。
 *    &lt;og:column name="CDC" addNoValue="false" must="true" /&gt; 属性は、複数組み合わせて使えます。
 *    &lt;og:column name="PN" must="true" /&gt;                     色を変更するときはmust属性を使います。
 *    &lt;og:column name="PN" td="false" /&gt;                      自動作成されるtdタグやラベルを外すときはtd属性を使います。
 *    &lt;og:column name="PN" td="no" /&gt;                         自動作成されるtdタグを外し、ラベルとフィールドは残します。
 *    &lt;og:column name="PN" writable="false" /&gt;                非入力にするときはwritable属性を使います。
 *    &lt;og:column name="PN" size="20" /&gt;                       強制的にSIZEの変更をするときはsize属性を使います。
 *    &lt;og:column name="A"  nextForm="B" /&gt;                    最大桁数入力後、フォーム B にフォーカスが移動します。
 *    &lt;og:column name="B" /&gt;
 *
 *    BODY 部分に記述した値は、カラムフィールドの直後にセットされます。
 *    &lt;og:column name="PN" &gt;
 *      &lt;button type="button" onclick="popup(･･･);return false;"&gt;
 *          &lt;og:message lbl="POPUP" comment="▼" /&gt;
 *      &lt;/button&gt;
 *    &lt;/og:column&gt;
 *
 *    eventColumnを利用すると、親カラムの変更に従って子カラムの内容を変える事が可能です。
 *    ・親子関係のプルダウンを作成する場合
 *    &lt;og:column name="OYA" /&gt;
 *    &lt;og:column name="KO" eventColumn="OYA" param="SELECT ... WHERE COL = '{&#64;OYA}'" /&gt;
 *    
 *    ・親子関係の入力欄（親のデータで子をDBから検索）を作成する場合
 *    &lt;og:column name="OYA" /&gt;
 *    &lt;og:column name="KO" eventColumn="OYA" param="SELECT A AS VALUE WHERE COL = {&#64;OYA}" /&gt;
 *    
 *    ・親子関係の要素をカスタム化されたJSPを利用して作成する場合
 *    変更するカラムはJSPで記述されており、指定する事が可能です。
 *    &lt;og:column name="OYA" /&gt;
 *    &lt;og:column name="KO" eventColumn="OYA" param="{&#64;OYA}" eventURL="custom_makeColumn.jsp" /&gt;
 *
 * @og.group 画面部品
 *
 * @version  4.0
 * @author   Kazuhiko Hasegawa
 * @since    JDK5.0,
 */
public class ColumnTag 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" ) ) ? ":" : "" ;
	
	private String  td_flag		= "yes";	// yes:<td> タグを使用 / false:フィールドのみ / no:ラベルとフィールド
	private boolean addNoValue	= true;		// 値なしのOptionをSelectに含めるかどうか
	private String  name		= null;
	private String  value		= null;
	private boolean writable	= true;		// 書き込み/ラベルを指定する。（true で書き込み）
	private String	defaultVal	= "";		// value がセットされていないときの初期値
	//	 2.1.0.0 (2002/10/11) useDefaultPropertieVal 属性を追加。
//	private boolean useDefVal	= false;	// properties ファイルの初期値を 使う:true / 使わない:false
	// 5.2.3.0 (2010/12/01) useDefaultPropertieVal 属性の初期値をシステムリソースで定義
	// properties ファイルの初期値を 使う:true / 使わない:false
	private boolean useDefVal	= HybsSystem.sysBool( "USE_DEFAULT_PROPERTIE_VALUE" );

	//	 3.0.0.0 (2002/12/25) colspan 属性を追加。
	private String  colspan		= "";
	//	 3.5.4.2 (2003/12/15) nextForm 属性を追加。
	private String  nextForm	= null;

	//	 3.5.4.9 (2004/02/25) value が null の場合に、リクエスト情報を設定します。
	private boolean useRequestValue	= true;		// 初期値 true

	// 3.5.6.0 (2004/06/18) Attributes 経由でなく、直接 DBColumnConfig に設定します。
	private String	vewSize		= null;
	private String	maxlength	= null;

	// 3.8.0.4 (2005/08/08) BODY 部分に記述した値は、カラムフィールドの直後にセットされます。
	private String  body		= null;
	private String	codeName	= null;			// 3.8.0.6 (2005/09/12)
	private String	codeList	= null;			// 5.1.9.0 (2010/08/01) 新規追加（Codeリソースのサブセット）
	private String	codeGroup	= null;			// 5.1.9.0 (2010/08/01) 新規追加（Codeリソースのサブセット）

	// 4.0.0 (2007/05/30) カラム状態を動的に変更します。
	private String	renderer	= null;
	private String	editor		= null;
	private String	dbType		= null;

	// 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	eventColumn	= null;		// 4.3.6.0 (2009/04/01) 親カラムの指定
	private String	eventURL	= null;		// 4.3.6.0 (2009/04/01) eventColumnで飛ばすURL
	private String	param		= null;		// 4.3.6.0 (2009/04/01) パラメータを変更可能にする

	private boolean	xssCheck	= HybsSystem.sysBool( "USE_XSS_CHECK" ); // 5.1.7.0 (2010/06/01) XSS対策

	/**
	 * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。
	 *
	 * @og.rev 3.8.0.4 (2005/08/08) 新規追加(BODY部の評価)
	 * @og.rev 5.1.7.0 (2010/06/01) command=RENEWの場合はdefaultValを無視する。
	 * @og.rev 5.2.2.0 (2010/11/01) caseKey 、caseVal 属性対応
	 *
	 * @return  int 後続処理の指示( EVAL_BODY_BUFFERED )
	 */
	@Override
	public int doStartTag() {
		// 5.2.2.0 (2010/11/01) caseKey 、caseVal 属性対応
		if( useTag() ) {
			// makeTag() より移動
			if( value == null && useRequestValue ) {		// 3.5.4.9 (2004/02/25)
				// 5.1.7.0 (2010/06/01) command=RENEWの場合はdefaultValを無視する。
				String cmd = pageContext.getRequest().getParameter( "command" );
				if( "RENEW".equals( cmd ) ) {
					value = getRequestValue( name );
				}
				else { 
					value = nval( getRequestValue( name ),defaultVal );
				}
			}

			return( EVAL_BODY_BUFFERED );	// Body を評価する。（ extends BodyTagSupport 時）
		}
		return ( SKIP_BODY );				// Body を評価しない
	}

	/**
	 * Taglibのタグ本体を処理する doAfterBody() を オーバーライドします。
	 *
	 * @og.rev 3.8.0.4 (2005/08/08) 新規追加(BODY部の評価)
	 * @og.rev 5.1.7.0 (2010/06/01) XSS解除対応
	 *
	 * @return  int 後続処理の指示(SKIP_BODY)
	 */
	@Override
	public int doAfterBody() {
		// 5.1.7.0 (2010/06/01) XSS対策
		useXssCheck( xssCheck );

		body = getBodyString();
		return(SKIP_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.0.0 (2002/12/25) colspan 属性を追加。
	 * @og.rev 3.0.1.4 (2003/03/17) colspan 属性の制御方法を変更
	 * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。
	 * @og.rev 3.5.4.2 (2003/12/15) nextForm 属性を追加。
	 * @og.rev 3.5.4.9 (2004/02/25) useRequestValue 属性を追加。
	 * @og.rev 3.5.6.0 (2004/06/18) Attributes 経由でなく、直接 DBColumnConfig に設定します。
	 * @og.rev 3.8.0.4 (2005/08/08) body , useBody 属性を追加。
	 * @og.rev 3.8.0.6 (2005/09/12) codeName 属性を追加。
	 * @og.rev 4.1.2.1 (2008/03/13) must , mustAny 属性を自動化します。
	 * @og.rev 5.1.7.0 (2010/06/01) XSS解除対応
	 * @og.rev 5.1.9.0 (2010/08/01) codeList , codeGroup属性を追加。（Codeリソースのサブセット）
	 * @og.rev 5.2.1.0 (2010/10/01) must , mustAny 属性の処理を、HTMLTagSupport に移します。
	 * @og.rev 5.2.3.0 (2010/12/01) useDefaultPropertieVal 属性の初期値をシステムリソースで定義
	 */
	@Override
	protected void release2() {
		super.release2();
		td_flag     = "yes";	// table形式の <td> タグを使用するかどうか
		addNoValue  = true;		// 値なしのOptionをSelectに含めるかどうか
		name        = null;
		value       = null;
		writable    = true;		// 書き込み/ラベルを指定する。（true で書き込み）
		defaultVal	= "";		// value がセットされていないときの初期値
//		useDefVal   = false;	// properties ファイルの初期値を 使う:true / 使わない:false
		useDefVal	= HybsSystem.sysBool( "USE_DEFAULT_PROPERTIE_VALUE" );		// 5.2.3.0 (2010/12/01)
		colspan     = "";
		nextForm    = null;		// 3.5.4.2 (2003/12/15)
		useRequestValue = true;		// 3.5.4.9 (2004/02/25)
		vewSize		= null;		// 3.5.6.0 (2004/06/18)
		maxlength	= null;		// 3.5.6.0 (2004/06/18)
		body		= null;		// 3.8.0.4 (2005/08/08)
		codeName	= null;		// 3.8.0.6 (2005/09/12)
		codeList	= null;		// 5.1.9.0 (2010/08/01) 新規追加（Codeリソースのサブセット）
		codeGroup	= null;		// 5.1.9.0 (2010/08/01) 新規追加（Codeリソースのサブセット）
		renderer	= null;
		editor		= null;
		dbType		= null;
//		mustType	= null;		// 4.1.2.1 (2008/03/13)		// HTMLTagSupport に移します。
		eventColumn = null;  	// 4.3.6.0 (2009/04/01)
		eventURL	= null;		// 4.3.6.0 (2009/04/01)
		param		= null;		// 4.3.6.0 (2009/04/01)
		xssCheck	= HybsSystem.sysBool( "USE_XSS_CHECK" );	// 5.1.7.0 (2010/06/01) XSS解除対応
	}

	/**
	 * 検索条件の入力用のテキストフィールドを作成します。
	 *
	 * テーブルタグによりフィールドは分割されます。
	 * 使用時は、テーブルタグを前後に使用して下さい。
	 *
	 * @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.0.0 (2002/12/25) colspan 属性を追加。
	 * @og.rev 3.0.1.4 (2003/03/17) colspan 属性の制御方法を変更
	 * @og.rev 3.5.4.9 (2004/02/25) value が null の時の 値の設定方法
	 * @og.rev 3.5.4.9 (2004/02/25) value が null の時の 値の設定方法
	 * @og.rev 3.8.0.4 (2005/08/08) body 属性を追加。
	 * @og.rev 3.8.7.0 (2006/12/15) カラムリソースで指定したカラムラベルを反映させる。
	 * @og.rev 4.0.0 (2005/11/30) カラムロールを考慮
	 * @og.rev 4.1.2.1 (2008/03/13) must , mustAny 属性を自動化します。
	 * @og.rev 4.3.7.1 (2009/06/08) id=labelのclass化
	 * @og.rev 5.2.1.0 (2010/10/01) must , mustAny 属性の処理を、HTMLTagSupport に移します。
	 *
	 * @return  入力用のテキストフィールドタグ
	 */
	protected String makeTag() {
		// 3.8.7.0 (2006/12/15) カラムリソースで指定したカラムラベルを反映させる。
		DBColumn dbColumn = getDBColumn( name );
		String label = getLongLabel() ;
		if( label == null ) { label = dbColumn.getLongLabel() ; }
		
		String tag = getInsertTag( dbColumn,value );

		// 4.0.0 (2005/11/30) カラムロールを考慮
		if( tag == null ) { return ""; }	// アクセス不可の場合は、ゼロ文字列を返す。

		// 3.8.0.4 (2005/08/08) BODY を使用する場合は、カラムフィールドの直後に挿入する。
		if( body != null ) { tag = tag + body; }

		StringBuilder rtn = new StringBuilder( HybsSystem.BUFFER_MIDDLE );
		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( label );
			rtn.append( CLM );
			rtn.append( "</td>" );
			rtn.append( "<td" );
			rtn.append( colspan );
			rtn.append( ">" );
			rtn.append( tag );
			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( label );
			rtn.append( CLM );
			rtn.append( "</span>" );
			rtn.append( tag );
		}
		else {
			rtn.append( tag );
		}

	 	// 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 属性を自動化します。
		if( getMustType() != null ) { rtn.append( makeMustHidden( name ) ); }

		return rtn.toString() ;
	}

	/**
	 * カラムがselectタグの場合に、値なしのオプション文字列を挿入します。
	 *
	 * addNoValue 値が True の場合のみ、挿入します。
	 *
	 * @og.rev 2.1.0.0 (2002/10/11) useDefaultPropertieVal 属性を追加。
	 * @og.rev 3.5.4.2 (2003/12/15) 入力カーソルを自動的に次のフィールドへ移動する機能を追加する。
	 * @og.rev 3.5.5.5 (2004/04/23) DBColumn の size と maxlength の 意味を変更
	 * @og.rev 3.5.5.7 (2004/05/10) DBColumn.getOption( String ) 廃止
	 * @og.rev 3.5.6.0 (2004/06/18) Attributes 経由でなく、直接 DBColumnConfig に設定します。
	 * @og.rev 3.8.0.6 (2005/09/12) codeName 属性を追加。
	 * @og.rev 3.8.7.0 (2006/12/15) カラムリソースで指定したカラムラベルを反映させる。
	 * @og.rev 4.0.0 (2005/01/31) getFieldSize メソッドを XHTMLTag から DBColumn へ移動
	 * @og.rev 4.0.0 (2005/11/30) カラムロールを考慮。アクセス不可の場合は、null を返す。
	 * @og.rev 4.3.0.0 (2008/07/04) ロールモードマルチ対応
	 * @og.rev 4.3.7.2 (2009/06/15) 不要なIDが出力されるバグを修正
	 * @og.rev 5.1.7.0 (2010/06/01) 動的プルダウン実装見直し
	 * @og.rev 5.1.7.0 (2010/06/01) DBColumnの{@XXXX}変数対応
	 * @og.rev 5.1.9.0 (2010/08/01) codeList ,codeGroup 属性を追加（Codeリソースのサブセット）
	 *
	 * @param   clm DBColumn カラムオブジェクト
	 * @param   value String 設定値
	 * @return  入力用のカラムタグ
	 */
	private String getInsertTag( final DBColumn clm, final String value ) {
		String val = value;

		// 4.0.0 (2005/11/30) カラムロールを考慮
//		String roles = get( "roles" );
//		if( roles == null ) { roles = clm.getRoles(); }
//		if( ! getUser().isAccess( roles ) ) { return null; }		// アクセス不可

		// 4.3.0.0 (2008/07/04) ロールモードマルチ対応
		RoleMode roleMode = null;
		String roles = get( "roles" );
		if( roles != null ) {
			roleMode = RoleMode.newInstance( roles );
		}
		else {
			roleMode = clm.getRoleMode();
		}

		byte byteMode = getUser().getAccessBitMode( roleMode ) ;

		if( !RoleMode.isAccess( byteMode ) ) { return null; }	// アクセス不可(rw不可)

		// 書き込み権限のチェック
	//	writable = writable && RoleMode.isWrite( byteMode );

		// 3.5.4.2 (2003/12/15) 入力カーソルを自動的に次のフィールドへ移動する機能
		if( nextForm != null ) {
			if( maxlength == null ) { maxlength = String.valueOf( clm.getTotalSize() ); }		// 4.0.0 (2005/01/31) メソッド名変更

			String onKeyup = "nextForm(this,'" + nextForm + "'," + maxlength + ");" ;
			set( "onKeyup",onKeyup );
		}

		// 3.5.6.0 (2004/06/18) 直接 DBColumnConfig に設定します。
		if( vewSize == null && maxlength != null ) {
			// 4.0.0 (2005/01/31) getFieldSize メソッドを XHTMLTag から DBColumn へ移動
			int fsize = clm.getFieldSize( Integer.parseInt( maxlength ) );
			vewSize = String.valueOf( fsize );
		}

		DBColumnConfig config = clm.getConfig();
		if( maxlength	!= null ) { config.setMaxlength( maxlength	); }
		if( vewSize		!= null ) { config.setViewLength( vewSize	); }	// 4.0.0 (2005/01/31)
		if( renderer	!= null ) { config.setRenderer(  renderer	); }
		if( editor		!= null ) { config.setEditor(	 editor 	); }
		if( dbType		!= null ) { config.setDbType(	 dbType 	); }
		if( eventColumn != null ) { config.setEventColumn( eventColumn ); } // 4.3.6.0 (2009/04/01)
		if( param		!= null ) { // 4.3.6.0 (2009/04/01)
			config.setParameter( getRequestParameter( param ) ); // ここで{@xxx}変換
			config.setRawParameter( param );
		}
		// 5.1.7.0 (2010/06/01) DBColumnの{@XXXX}変数対応
		else if ( clm.isNeedsParamParse() ){
			config.setRendererParam( getRequestParameter( config.getRendererParam() ) );
			config.setEditorParam( getRequestParameter( config.getEditorParam() ) );
		}
		if( eventURL 	!= null ){ config.setEventURL( eventURL );	   } // 4.3.6.0 (2009/04/01)
//		set( "id", name );		// 4.3.6.0 (2009/04/01) // 4.3.7.2 (2009/06/15) 

		// 4.0.0 (2005/01/31)
		if( codeName  != null ) {
			CodeData codeData = getResource().getCodeData( codeName ) ;
			config.setCodeData( codeData );
			config.setRenderer( "MENU" );
			config.setEditor(   "MENU" );
		}

		// codeName で指定のリソースでも、サブセットが作成できます。
		// 5.1.9.0 (2010/08/01) codeList 属性を追加（Codeリソースのサブセット）
		if( codeList != null ) {
			CodeData codeData = config.getCodeData() ;
			if( codeData != null ) {
				config.setCodeData( codeData.subsetList( codeList ) );
			}
		}

		// 5.1.9.0 (2010/08/01) codeGroup 属性を追加（Codeリソースのサブセット）
		if( codeGroup != null ) {
			CodeData codeData = config.getCodeData() ;
			if( codeData != null && codeData.useGroup() ) {
				config.setCodeData( codeData.subsetGroup( codeGroup ) );
			}
		}

		// 5.1.9.0 (2010/08/01) RoleMode 制御を追加（Codeリソースのサブセット）
		CodeData codeData = config.getCodeData() ;
		if( codeData != null && codeData.useRoleMode() ) {
			config.setCodeData( codeData.subsetRole( getUser().getRoleMode() ) );
		}

//		config.setEditorAttributes( getAttributes() );
		Attributes attri = getAttributes();
		config.setEditorAttributes( attri );
		DBColumn column = new DBColumn( config );

		if( useDefVal && ( val == null || val.length() == 0 ) ) {
			val = column.getDefault();
		}

//		final String rtn ;
		String rtn = null;
		if( writable ) {
			String editTag = column.getEditorValue( val );
			StringBuilder tag = new StringBuilder( editTag );
			if( addNoValue && editTag.startsWith( "<select" ) ) {
				int offset = editTag.indexOf( '>' );
				tag.insert( offset+1,"<option value=\"\" ></option>" );
			}
			rtn = tag.toString();
		}
		else {
			if( attri == null || attri.size() == 0 ) {
				rtn = column.getRendererValue( val );
			}
			else {
				attri.set( "body" , column.getRendererValue( val ) );
				rtn = XHTMLTag.span( attri );
			}
		}

		// 4.3.6.0 (2009/04/01) eventColumn対応 生SQL文のセッション保存
		// 5.1.7.0 (2010/06/01) 動的プルダウン実装見直し
		String evCol = column.getEventColumn();
		if( evCol != null && evCol.length() > 0 ){
//			addEventColumnSQL( column.getName(), column.getRawParam() );
			addEventColumn( column );
			rtn = column.getEventColumnTag( rtn, val, writable );
		}

		return rtn;
	}

	/**
	 * 【TAG】カラムの名前を返します。
	 *
	 * @og.tag
	 *  &lt;og:column name="PN" /&gt;
	 *
	 * @og.rev 4.2.4.0 (2008/07/01) 
	 *
	 * @return	String カラムの名前
	 */
	protected String getName() {
		return name;
	}

	/**
	 * 【TAG】カラムの名前を指定します。
	 *
	 * @og.tag
	 *  &lt;og:column name="PN" /&gt;
	 *
	 * @og.rev 3.8.0.9 (2005/10/17) RequestParameter変数({&#064;XXXX})が使用できるように修正
	 *
	 * @param   name String
	 */
	public void setName( final String name ) {
		this.name = nval( getRequestParameter( name ),this.name );
	}

	/**
	 * 【TAG】初期値を指定します。
	 *
	 * @og.tag
	 *  &lt;og:column name="PN" value="syokichi" /&gt;
	 *
	 * @param   val String
	 */
	public void setValue( final String val ) {
		value = nval( getRequestParameter( val ),value );
	}

	/**
	 * 【TAG】value属性に値がセットされていないときに、初期値をセットします。
	 *
	 * @og.tag
	 * value属性に値がセットされていないときに、初期値をセットします。
	 * 
	 * なお、commandがRENEWの場合は、このdefaultValは適用されません。
	 * これは、defaultValの値が埋め込まれた項目が存在する画面に戻った際に、
	 * defaultValの項目の値がnullとなっていた場合に、defaultValの値が復元されると、
	 * 検索結果との不一致が発生するためです。
	 *
	 * @param	dv 初期値
	 */
	public void setDefaultVal( final String dv ) {
		defaultVal = nval( getRequestParameter( dv ),defaultVal );
	}

	/**
	 * 【TAG】リソースファイルの初期値を使うかどうかを指定します(初期値:false)。
	 *
	 * @og.tag
	 * 初期値がセットされていないときに指定します。
	 * 使う場合はtrue、 使わない場合は falseをセットします。
	 * この初期値を、システムリソースの USE_DEFAULT_PROPERTIE_VALUE で設定可能とします。
	 *
	 * @og.rev 2.1.0.0 (2002/10/11) useDefaultPropertieVal 属性を追加。
	 * @og.rev 5.2.3.0 (2010/12/01) 初期値をシステムリソースで定義(USE_DEFAULT_PROPERTIE_VALUE)
	 *
	 * @param	dv ファイルの初期値を 使う:true / 使わない:false(初期値)
	 */
	public void setUseDefaultPropertieVal( final String dv ) {
		useDefVal = nval( getRequestParameter( dv ),useDefVal );
	}

	/**
	 * 【TAG】テーブル形式の &lt;td&gt; タグを使用するかどうか(yes/no/false)を指定します(初期値:yes)。
	 *
	 * @og.tag
	 * yes(初期値) とすると、ラベルとフィールドをテーブルのtdタグでそれぞれ記述します。
	 * no とすると、tdタグを使用せず、ラベルとフィールドを表示します。
	 * false は、ラベルを出さずに、フィールドのみを表示します。
	 *
	 * &lt;td&gt;&lt;og:column name="PN" td="no" /&gt; &lt;/td&gt;
	 *
	 * @og.rev 2.0.0.8 (2002/10/09) yes/no/false で指定するように変更
	 * @og.rev 2.1.2.3 (2002/12/02) errMsg の文字列の修正漏れを訂正
	 *
	 * @param  flag yes:&lt;td&gt; タグを使用 / 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 = "td 属性は、下記の範囲より選定してください。 td=["
						+ td + "  in [|yes|no|false|]";
			throw new HybsSystemException( errMsg );
		}
	}

	/**
	 * 【TAG】コンボボックスの場合、値なしのOptionを含めるかどうか(true/false)を指定します(初期値:true)。
	 *
	 * @og.tag
	 * カラムがプルダウンメニュー形式の場合、選択肢には通常データベース登録できる候補が
	 * 並びます。しかし、検索時には、候補を絞りたくない（指定しない）場合があり、
	 * その様な場合には、値なしのOptionを含める(true)ことで、対応可能です。
	 * 初期値:true(値なしのOptionを含める)なので、検索画面に利用する場合は、そのまま使用できます。
	 *
	 * &lt;og:column name="CDC" addNoValue="false" /&gt;
	 *
	 * @param   flag 含める ("true")／含めない (それ以外)
	 */
	public void setAddNoValue( final String flag ) {
		addNoValue = nval( getRequestParameter( flag ),addNoValue );
	}

	/**
	 * 【TAG】必須入力を表す色に変えるかどうか(true/false)指定します(初期値:false)。
	 *
	 * @og.tag
	 * 初期値は、必須でない("false") です。
	 *
	 * &lt;og:column name="PN" must="true" /&gt;
	 *
	 * @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】書き込みタイプかどうか(true/false)を指定します(初期値:true)。
	 *
	 * @og.tag
	 * 初期値は、書き込みタイプ("true") です。
	 * &lt;og:column name="PN" writable="false" /&gt;
	 *
	 * @param   flag 書き込みタイプ("true")／ラベルタイプ(それ以外)
	 */
	public void setWritable( final String flag ) {
		writable = nval( getRequestParameter( flag ),writable );
	}

	/**
	 * 【TAG】最大入力文字数を指定します(入力可能文字数で、バイト数ではありません)。
	 *
	 * @og.tag
	 *  &lt;og:column name="PN" maxlength="20" /&gt;
	 *
	 * @og.rev 3.5.4.2 (2003/12/15) 最大入力制限数に応じたサイズ自動生成を入れます。
	 * @og.rev 3.5.4.5 (2004/01/23) CSSで処理する場合のクラス属性は、maxlength が ５ 以下の場合とする。
	 * @og.rev 3.5.6.0 (2004/06/18) Attributes 経由でなく、直接 DBColumnConfig に設定します。
	 *
	 * @param   maxlen String
	 */
	public void setMaxlength( final String maxlen ) {
		maxlength = nval( getRequestParameter( maxlen ),null );

		// 3.5.4.5 (2004/01/23) 追加
		if( maxlength != null && maxlength.length() == 1 ) {
			char ch = maxlength.charAt(0);
			if( ch >= '1' && ch <= '5' ) {
				add( "class", "S0" + ch );	// 3.5.5.9 (2004/06/07) セパレータ引数付きのメソッドに変更
			}
		}
	}

	/**
	 * 【TAG】カラムの表示サイズ(横幅)を文字数でセットします(入力文字制限ではありません)。
	 *
	 * @og.tag
	 *  &lt;og:column name="PN" size="20" /&gt;
	 *
	 * @og.rev 3.5.6.0 (2004/06/18) Attributes 経由でなく、直接 DBColumnConfig に設定します。
	 *
	 * @param   size String
	 */
	public void setSize( final String size ) {
		vewSize = nval( getRequestParameter( size ),null );
	}

	/**
	 * 【TAG】フィールド部分の colspan を指定します。
	 *
	 * @og.tag
	 * 通常の出力では、ラベルとフィールドのtdが２つ使用されます。この colspan は、
	 * フィールドに追加されます。
	 * たとえば、3 を指定した場合、フィールドが、次のテーブルの、ラベル、フィールド部分まで
	 * 伸びるため、レイアウト的にすっきりと、長いフィールドを適用する事が可能です。
	 *
	 * &lt;og:column name="PN" colspan="3" /&gt;
	 *
	 * @og.rev 3.0.0.0 (2002/12/25) colspan 属性を追加。
	 * @og.rev 3.0.1.4 (2003/03/17) colspan 属性の制御方法を変更
	 *
	 * @param   sp フィールド部分の colspan
	 */
	public void setColspan( final String sp ) {
		colspan = nval( getRequestParameter( sp ),colspan );
		if( colspan.length() > 0 ) {
			colspan = " colspan=\"" + colspan + "\" ";
		}
	}

	/**
	 * 【TAG】入力カーソルを、指定されたname属性のフィールドへ自動的に移動させます。
	 *
	 * @og.tag
	 * JavaScript の onKeyup イベントを利用して、最大桁数まで入力すると、
	 * 次のフィールドに、自動的にカーソルが飛ぶように設定します。
	 * 引数は、次に飛ばすフィールドの name 属性です。
	 * 実行するには、JavaScript の nextForm 関数が必要です。(default.js で指定)
	 *
	 * @og.rev 3.5.4.2 (2003/12/15) 新規追加
	 *
	 * @param   name String
	 */
	public void setNextForm( final String name ) {
		nextForm = nval( getRequestParameter( name ),nextForm );
	}

	/**
	 * 【TAG】value が null の場合に、name 属性から Request情報 を適用するかどうかを指定します(初期値:true)。
	 *
	 * @og.tag
	 * name 属性に一致するリクエスト情報がある場合、value が null の場合や、
	 * 引数を設定していない場合は、この設定値に応じて、リクエスト情報の値を
	 * 設定します。（初期値 true なので、通常はこの動きです。）
	 * ごくまれに、ENTRY 系の削除を行う場合、リクエスト情報が残り、削除されずに
	 * 再表示（ＤＢ的には削除済み）されるケースでは、使用しない(false)設定が可能です。
	 *
	 *    useRequestValue |      true(初期値）     |   false
	 *  ------------------+------------------------+------------
	 *  value             |Ａ Ａ Ａ Ａ ＿ ＿ ＿ ＿ |＿ ＿ ＿ ＿
	 *  name(Request情報）|Ｂ Ｂ ＿ ＿ Ｂ Ｂ ＿ ＿ |Ｂ Ｂ ＿ ＿
	 *  defaultVal        |Ｃ ＿ Ｃ ＿ Ｃ ＿ Ｃ ＿ |Ｃ ＿ Ｃ ＿
	 *  ==================+========================+============
	 *  設定値            |Ａ Ａ Ａ Ａ Ｂ Ｂ Ｃ ＿ |Ｃ ＿ Ｃ ＿
	 *
	 * @og.rev 3.5.4.9 (2004/02/25) 新規追加
	 *
	 * @param   flag String value が null の時の 値の設定方法
	 */
	public void setUseRequestValue( final String flag ) {
		useRequestValue = nval( getRequestParameter( flag ),useRequestValue );
	}

	/**
	 * 【TAG】コードセレクトのユニークキー(コード名称)をセットします。
	 *
	 * @og.tag
	 * このキーを元に、CodeData オブジェクトを構築します。
	 *
	 * @og.rev 3.8.0.6 (2005/09/12)  新規作成
	 *
	 * @param  name String メニューのユニークキー
	 */
	public void setCodeName( final String name ) {
		codeName = nval( getRequestParameter( name ),codeName );
	}

	/**
	 * 【TAG】コードセレクトのサブセットとなるコードをCSV形式で指定します。
	 *
	 * @og.tag
	 * この値に限定された、コードリソースを、既存の、CodeData の
	 * サブセットとして作成します。
	 * codeName で指定されたリソースでも、サブセットを作成する事ができます。
	 *
	 * @og.rev 5.1.9.0 (2010/08/01)  新規作成
	 *
	 * @param  list String コードセレクトのサブセットとなるコード
	 */
	public void setCodeList( final String list ) {
		codeList = nval( getRequestParameter( list ),codeList );
	}

	/**
	 * 【TAG】コードセレクトのサブセットとなるグループを指定します。
	 *
	 * @og.tag
	 * この値に限定された、コードリソースを、既存の、CodeData の
	 * サブセットとして作成します。
	 * codeName で指定されたリソースでも、サブセットを作成する事ができます。
	 *
	 * @og.rev 5.1.9.0 (2010/08/01)  新規作成
	 *
	 * @param  group String コードセレクトのサブセットとなるグループ
	 */
	public void setCodeGroup( final String group ) {
		codeGroup = nval( getRequestParameter( group ),codeGroup );
	}

	/**
	 * 【TAG】カラムの表示用レンデラー(Renderer_****)をセットします。
	 *
	 * @og.tag
	 * これは、plugin.column 以下の Renderer_**** クラスの **** を
	 * 与えます。これらは、CellRenderer インターフェースを継承したサブクラスです。
	 * 属性クラス定義の {@link org.opengion.hayabusa.db.CellRenderer Renderer} を参照願います。
	 *
	 * @param	rdr カラムの表示用レンデラー(Renderer_**** の ****)
	 * @see		org.opengion.hayabusa.db.CellRenderer
	 */
	public void setRenderer ( final String rdr ) {
		renderer = nval( getRequestParameter( rdr ),renderer );
	}

	/**
	 * 【TAG】カラムの編集用エディター(Editor_****)をセットします。
	 *
	 * @og.tag
	 * これは、plugin.column 以下の Editor_**** クラスの **** を
	 * 与えます。これらは、CellEditor インターフェースを継承したサブクラスです。
	 * 属性クラス定義の {@link org.opengion.hayabusa.db.CellEditor Editor} を参照願います。
	 *
	 * @param	ed カラムの編集用エディター(Editor_**** の ****)
	 * @see		org.opengion.hayabusa.db.CellEditor
	 */
	public void setEditor ( final String ed ) {
		editor = nval( getRequestParameter( ed ),editor );
	}

	/**
	 * 【TAG】ＤＢタイプ(DBType_****)をセットします。
	 *
	 * @og.tag
	 * これは、org.opengion.hayabusa.db.column 以下の DBType_**** クラスの **** を
	 * 与えます。これらは、DBType インターフェースを継承したサブクラスです。
	 * 属性クラス定義の {@link org.opengion.hayabusa.db.DBType DBType} を参照願います。
	 *
	 * @param	dt パラメータ
	 * @see		org.opengion.hayabusa.db.DBType  DBType_**** の ****
	 */
	public void setDbType( final String dt ) {
		dbType = nval( getRequestParameter( dt ),dbType );
	}

	/**
	 * 【TAG】イベントカラム（親カラム）セット
	 *
	 * @og.tag
	 * 親子関係を持った項目の動的な入れ替えを行う場合に利用します。
	 * このカラムを変化させるトリガとなるカラムの名前をセットします。
	 * 
	 * この属性がセットされた場合、親カラムが変更都度子カラム(自身のカラム)が
	 * 再表示されます。
	 * 標準で再表示時に受け継がれる属性は以下の通りです。
	 * (1)editor・renderer
	 * (2)writable
	 * (3)addNoValue
	 * (4)class(must・mustAnyや、DBTypeを含みます)
	 * (5)style(optionAttributes等でセットしたもの)
	 * (6)size
	 * (7)maxlength
	 * これら以外に特殊な設定を行ったカラムに関しては、eventURL属性でカスタムの
	 * 置き換え用JSPを作成し、個別に対応して下さい。
	 * 
	 * また、置き換えの定義は、param属性で定義します。
	 * param属性に定義されたSQL文の結果により、各種エディター、レンデラーによって、以下の
	 * ように置き換えが行われます。
	 * 
	 * (1)DBMENUの場合
	 *   paramに指定されたSQL文により動的にプルダウンを置き変えます。
	 *   SQL文の{@xxx}の記述により、その時点での親カラムの値を参照することができます。
	 *
	 *		例) SELECT A.CODE,B.LNAME FROM GEA04 A,GEA08 B 
	 *			WHERE A.CLM||'.'||A.CODE = B.CLM 
	 *			AND A.SYSTEM_ID = B.SYSTEM_ID 
	 *			AND A.CLM like 'KBSAKU%' 
	 *			AND B.LANG like '{@LANG}' ← name=LANGを持つ項目のその時点での値に変換される
	 *			AND B.SYSTEM_ID = '**'
	 *
	 * (2)DBMENU以外の場合
	 *   paramに指定されたSQL文により値(value値)を置き換えたカラムを作成し、置き換えます。
	 *   DBMENUの場合と同様、SQL文の{@xxx}の記述により、その時点での親カラムの値を参照することができます。
	 *
	 *		例) SELECT LABEL_NAME FROM GF41
	 *			WHERE SYSTEM_ID='{@SYS.SYSTEM_ID}' AND CLM='{@CLM}' AND LANG='{@LANG}'
	 *
	 * なお、いずれの場合も、{@xxx}の部分については、$1,$2...の形式でも記述することができます。
	 * この場合、$1は1番目のeventColumnのカラム、$2は2番目のeventColumnのカラムと指します。
	 * 
	 * (注意点1)イベントカラムによるイベントは、画面表示時に1度実行されます。
	 *          但し、eventColumn属性で、カラム名の先頭に'_'をつけた場合、
	 *          または親カラムの値がNULLの場合は実行されません。
	 *          
	 * (注意点2)SQL文などのパラメーター中に記述された{@xxx}の値の変換はJavaScriptにより行われるため、
	 *          値が取得できる項目は、"画面に書き込み可能状態で表示されているカラム"に限ります。
	 *          テーブルモデル内の変数や表示のみの値については、ここでは利用することはできません。
	 * 
	 * (注意点3)現時点では、INMENU,INDBMENUについては、入れ替え後のJavaScriptが正常に動作しないため、
	 *          イベントカラムが正常に動作しません。
	 *
	 * @og.rev 4.3.6.0 (2009/04/01)
	 * @og.rev 5.1.7.0 (2010/06/01) コメント大幅修正
	 * @param col String 親カラム
	 */
	public void setEventColumn( final String col ) {
		eventColumn = nval( getRequestParameter( col ), eventColumn );
	}
	
	/**
	 * 【TAG】イベントURLのセット
	 *
	 * @og.tag
	 * 初期値はシステムリソースのEVENT_COLUMN_URLです。
	 * イベントカラム指定時に部品を作成するJSPを指定します。
	 * (設定例：eventURL="makeColumn_custom.jsp")
	 * 
	 * 置き換え対象のカラムに特殊な設定がされており、標準のカラム置き換えでは対応できない場合に、
	 * このURLを指定することで、個別に置き換え方法を定義する必要があります。
	 * 
	 * なお、個別に置き換え方法を定義したJSPを作成する場合は、標準(jsp/common/eventColumnMaker.jsp)を
	 * 参考にして作成して下さい。
	 * 
	 * eventColumnから利用するJSPで利用可能なリクエスト変数
	 * {@EC_CNAME}		子カラム名(一覧表示の場合でも行番号__nは付加されません)
	 * {@EC_RENDERER}	子カラムのレンデラー
	 * {@EC_EDITOR}		子カラムのエディター
	 * {@EC_SQL}		子カラムのプルダウン、または値を出力するためのSQL文({@xxx}をカラムのvalue値で置き換えたもの)
	 * {@EC_WRITABLE}	子カラムが編集可能などうか
	 * {@EC_CVALUE}		子カラムの現在の値
	 * {@EC_NOVALUE}	子カラムの最上部Option値が空ならtrue。その他false(addNoValue属性値と同じです) 
	 * {@EC_CLASS}		子カラムのCLASS属性
	 * {@EC_SIZE}		子カラムのSIZE属性
	 * {@EC_MAXLENGTH}	子カラムのMAXLENGTH属性
	 * {@EC_OPTATTRS}	子カラムのその他OPTION属性
	 * {@EC_PNAMEE}		親カラム名(一覧表示の場合でも行番号__nは付加されません)
	 * {@EC_PVALUE}		親カラムの現在の値
	 *
	 * @og.rev 4.3.6.0 (2009/04/01)
	 * @og.rev 5.1.7.0 (2010/06/01) コメント大幅修正
	 * @param url String イベントURL
	 */
	public void setEventURL( final String url ) {
		eventURL = nval( getRequestParameter( url ), eventURL );
	}

	/**
	 * 【TAG】パラメータをセットします
	 *
	 * @og.tag
	 * EditorParam等のパラメータを一括でセットします。
	 * eventColumn利用時は{@xxx}はリクエストパラメータではなく
	 * xxxカラムの実際の値が利用されます。
	 *
	 * @og.rev 4.3.6.0 (2009/04/01)
	 * @param prm String パラメータ
	 */
	public void setParam( final String prm ) {
		param = nval( prm, param ); // ここでは{@xxx}変換をしない
	}

	/**
	 * 【TAG】リクエスト情報の HTMLTag開始/終了文字(&gt;&lt;) 存在チェックを実施するかどうか(true/false)を設定します(初期値:USE_XSS_CHECK)。
	 *
	 * @og.tag
	 * クロスサイトスクリプティング(XSS)対策の一環としてless/greater than signについてのチェックを行います。
	 * (&gt;&lt;) が含まれていたエラーにする（true)／かノーチェックか(false)を指定します。
	 * 初期値は、SystemData#USE_XMLLTAG_CHECK です。
	 *
	 * @og.rev 5.1.7.0 (2010/06/01) 新規追加
	 *
	 * @param flag boolean XSSチェックする (true)／しない (false)
	 */
	public void setXssCheck( final String flag ) {
		xssCheck = nval( getRequestParameter( flag ),xssCheck );
	}

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