/*
 * 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.HybsSystemException;
import org.opengion.fukurou.util.Attributes;
import org.opengion.fukurou.util.StringUtil;

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

/**
 * 検索結果の DBTableModel オブジェクトのカラム値を操作(設定、変換、ADDなど)するタグです。
 *
 *entry タグの子タグとして使用します。entryタグと、このcolumnSetタグの command
 * が同じ場合のみ、実行されます。
 * 処理方法は、action で指定します。
 *
 * @og.formSample
 * ●形式：&lt;og:entry command="…"&gt;
 *             &lt;og:setColumn
 *                 command   ="…"          : entryタグのcommandと一致する場合に実行
 *                 columnId  ="…"          : 処理を行うカラムＩＤを指定(必須,複数指定可)
 *                 action    ="…"          : 処理方法を指定
 *                 value     ="…"          : 設定する値を指定(action="TBLSET"のみ[カラム名]使用可能)
 *                 conditionKey  ="…"      : 条件判定するカラムＩＤを指定(初期値は columnId )
 *                 conditionList ="…"      : 条件判定する値のリストを、"|"で区切って登録(初期値は、無条件)
 *             /&gt;
 *         &lt;/og:entry&gt;
 * ●body：なし
 *
 * ●使用例
 *    &lt;og:entry command="{&#064;command}"  &gt;
 *        &lt;og:columnSet command="{&#064;command}" columnId="ECNO"   action="CLEAR" /&gt;
 *        &lt;og:columnSet command="{&#064;command}" columnId="JYOKYO" action="SET" value="1" /&gt;
 *    &lt;/og:entry&gt;
 *
 *    &lt;og:entry command="MODIFY" rows="1" &gt;
 *        &lt;og:columnSet command="MODIFY" columnId="key" action="TBLSET" value ="[key][lang]"/&gt;
 *    &lt;/og:entry&gt;
 *
 *    command属性 は、entryタグのcommand属性と同一の場合のみ、処理します。
 *    [command属性]
 *      INSERT    新規
 *      COPY      複写
 *      MODIFY    変更
 *      DELETE    削除
 *      ENTRY     エントリー
 *      CHANGE    チェンジ
 *      RESET     リセット
 *      ALLACTION オールアクション
 *
 *    [action属性]
 *      DEFAULT カラムリソースで定義した初期値をセットします。
 *      CLEAR   値をクリア(ゼロストリング &quot;&quot; ）します。
 *      ADD     現在の値を ＋１ します。  0 ⇒ 1 , A ⇒ B , 9 ⇒ 10
 *      SET     value で設定した値を 新しい値として登録します。
 *      NULLSET 元の値が NULL の場合だけ、value で設定した新しい値を登録します。
 *      LOWER   小文字に変換します。
 *      UPPER   大文字に変換します。
 *      COPY    value にコピー元のカラムIDをセットすれば、その値を代入します。
 *      TBLSET  DBTableModel の内容を取り込んで指定の columnId カラムに設定します。
 *              [カラム名] で指定できます。
 *              また、これは文字列を解析して、 value を作成しますので,文字列連結等に使用できます。
 *      WRTCTRL writableControl を使用したカラムデータの先頭アンダーバーを削除します。
 *      DBMENU  DBMENUでパラメータ設定(コロン連結文字)を使用したカラムデータの先頭データのみにします。
 *      その他  カラムのDBType の valueAction メソッドを呼び出します。自由に設定可能です。
 *
 * @og.group 画面登録
 *
 * @version  4.0
 * @author	 Kazuhiko Hasegawa
 * @since    JDK5.0,
 */
public class ColumnSetTag extends CommonTagSupport {
	//* このプログラムのVERSION文字列を設定します。	{@value} */
	private static final String VERSION = "4.0.0 (2005/08/31)" ;

	private static final long serialVersionUID = 3606 ;	// 3.6.0.6 (2004/10/22)

	private String columnId		= null;
	private String conditionKey = null;

	/**
	 * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。
	 *
	 * @og.rev 3.6.0.6 (2004/10/22) columnNo に伴なう削除
	 *
	 * @return  int 後続処理の指示(SKIP_BODY)
	 */
	@Override
	public int doStartTag() {
		EntryTag entry = (EntryTag)findAncestorWithClass( this,EntryTag.class );
		if( entry == null ) {
			String errMsg = "このタグは、EntryTag のBODY部に記述される必要があります。";
			throw new HybsSystemException( errMsg );
		}

		Attributes standardAttri = getAttributes();
		String[] clms = StringUtil.csv2Array( columnId );
		for( int i=0; i<clms.length; i++ ) {
			Attributes attri = new Attributes( standardAttri );
			attri.set( "columnId", clms[i] );
			// conditionKey が null の場合は、columnId が設定される。
			attri.set( "conditionKey", nval( conditionKey,clms[i] ) );
			entry.setAttributes( attri );
		}

		return(SKIP_BODY);
	}

	/**
	 * タグリブオブジェクトをリリースします。
	 * キャッシュされて再利用されるので、フィールドの初期設定を行います。
	 *
	 * @og.rev 2.0.0.4 (2002/09/27) カスタムタグの release() メソッドを、追加
	 * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。
	 * @og.rev 3.6.0.6 (2004/10/22) columnNo に伴なう変更
	 *
	 */
	@Override
	protected void release2() {
		super.release2();
		columnId	 = null;
		conditionKey = null;
	}

	/**
	 * 【TAG】コマンド(INSERT,COPY,MODIFY,DELETE,ENTRY,CHANGE,RESET,ALLACTION)を設定します。
	 *
	 * @og.tag
	 * 上位の EntryTag のコマンドと一致した場合のみ、処理されます。
	 * ここでは、コマンド文字列の整合性チェックは行っていません。
	 *
	 * @param	command コマンド
	 * @see		<a href="{@docRoot}/constant-values.html#org.opengion.hayabusa.taglib.EntryTag.CMD_INSERT">コマンド定数</a>
	 */
	public void setCommand( final String command ) {
		set( "command",getRequestParameter( command ) );
	}

	/**
	 * 【TAG】値をセットします。
	 *
	 * @og.tag
	 * 設定する値をセットします。
	 *
	 * @param	value String
	 */
	public void setValue( final String value ) {
		set( "value",getRequestParameter( value ) );
	}

	/**
	 * 【TAG】アクション(DEFAULT/CREAR/ADD/SET/NULLSET/LOWER/UPPER/COPY/TBLSET/WRTCTRL/DBMENU)をセットします。
	 *
	 * @og.tag
	 * ここでは、アクション文字列の整合性チェックを行っておりません。
	 *
	 * DEFAULT カラムリソースで定義した初期値をセットします。
	 * CREAR   値をクリア(ゼロストリング &quot;&quot; ）します。
	 * ADD     現在の値を ＋１ します。  0 ⇒ 1 , A ⇒ B , 9 ⇒ 10
	 * SET     value で設定した値を 新しい値として登録します。
	 * NULLSET 元の値が NULL の場合だけ、value で設定した新しい値を登録します。
	 * LOWER   小文字に変換します。
	 * UPPER   大文字に変換します。
	 * COPY    value にコピー元のカラムIDをセットすれば、その値を代入します。
	 * TBLSET  DBTableModel の内容を取り込んで指定の columnId カラムに設定します。[カラム名] で指定できます。
	 * WRTCTRL writableControl を使用したカラムデータの先頭アンダーバーを削除します。
	 * DBMENU  DBMENUでパラメータ設定(コロン連結文字)を使用したカラムデータの先頭データのみにします。
	 * その他  カラムのDBType の valueAction メソッドを呼び出します。自由に設定可能です。
	 *
	 * @param	action String
	 * @see		<a href="{@docRoot}/constant-values.html#org.opengion.hayabusa.taglib.EntryTag.ACT_DEFAULT">アクション定数</a>
	 */
	public void setAction( final String action ) {
		set( "action",getRequestParameter( action ) );
	}

	/**
	 * 【TAG】カラムＩＤをセットします(複数指定時は、カンマ区切り文字で設定する)。
	 *
	 * @og.tag
	 * 処理を適用するカラムＩＤを指定します。
	 * <del>カラム名とカラムNoは同時には登録できません。</del>
	 * 全く同じ内容を設定する場合には、カラム名をＣＳＶ形式(カンマ区切り)で
	 * 複数指定することが可能です。
	 *
	 * @og.rev 3.6.0.6 (2004/10/22) columnNo に伴なう変更
	 *
	 * @param	clmid String
	 */
	public void setColumnId( final String clmid ) {
		columnId = getRequestParameter( clmid );
	}

	/**
	 * 【TAG】条件判定するカラムＩＤを指定します(初期値は columnId )
	 *
	 * @og.tag
	 * 指定のカラムＩＤの値と、conditionList の値を比較して、
	 * 存在する場合は、action処理を実行します。
	 * 例えば、初期値設定(action="DEFAULT")で、値が "0" の場合だけ適用するような
	 * ケースに使用できます。
	 * 指定しない場合は、columnId と同じキーになります。
	 * 注意：columnId は、ＣＳＶ形式で複数同時に指定できます。その場合は、
	 * conditionKey には、複数設定する機能はありませんので、全カラムに
	 * 同一カラムを使用する場合は、conditionKey に値を設定できます。
	 * 値を設定しない場合は、自動的に、columnId と同一になります。
	 *
	 * @og.rev 3.6.0.6 (2004/10/22) 新規追加
	 *
	 * @param	key String
	 * @see		#setConditionList( String )
	 */
	public void setConditionKey( final String key ) {
		conditionKey = nval( getRequestParameter( key ),null ) ;
	}

	/**
	 * 【TAG】条件判定する値のリストを、"|"で区切って登録します(初期値は、無条件)
	 *
	 * @og.tag
	 * conditionKey とペアで指定します。ここには、カラムの設定値のリストを
	 * 指定することで、複数条件(ＯＲ結合)での比較を行い、リストにカラム値が
	 * 存在する場合のみ、action処理を実行します。
	 * 設定しない場合は、無条件に実行します。
	 *
	 * @og.rev 3.6.0.6 (2004/10/22) 新規追加
	 *
	 * @param	list String
	 * @see		#setConditionKey( String )
	 */
	public void setConditionList( final String list ) {
		set( "conditionList","|" + getRequestParameter( list ) + "|" );
	}

	/**
	 * 【TAG】カラムＩＤが存在しないときに無視するかどうかを指定します(初期値:true)
	 *
	 * @og.tag
	 * カラムセットする場合は、DBTableModel に存在するカラムに対してのみ、
	 * 処理を適用するべきで、通常存在しないカラムを使用した場合は、Exception が
	 * throw されます。(strictCheck="true" 初期値の動作です。)
	 * ところが、動的テーブル検索などでカラムが不特定な場合、DBTableModel に
	 * 存在しない場合に、無視したい場合があります。その場合は、strictCheck="false"
	 * に設定すると、カラムが存在しない場合は、エラーにせず、無視します。
	 * 初期値は、true:厳格に処理する です。
	 *
	 * @og.rev 4.0.0 (2006/09/31) 新規追加
	 *
	 * @param	strict String
	 */
	public void setStrictCheck( final String strict ) {
		set( "strictCheck",getRequestParameter( strict ) );
	}

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