/*
 * 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.ToString;						// 6.1.1.0 (2015/01/17)

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

/**
 * タブ形式のリンクを表示する場合に、タブそのものを表示するタグです。
 *
 * tabLinkタグを親タグとし、listType="TAG"を指定した場合に、このタグを使用して
 * タブを個別に定義します。
 *
 * タグの使用方法については、tabLinkタグのドキュメントを参照して下さい。
 *
 * 各属性は、{&#064;XXXX} 変数が使用できます。
 * これは、ServletRequest から、XXXXをキーに値を取り出し,この変数に割り当てます。
 * つまり、このXXXXをキーにリクエストすれば、この変数に値をセットすることができます。
 *
 * @og.formSample
 * ●形式：&lt;og:tabLink href="…" &gt; &lt;og:tabList name="TAB1" … /&gt; … &lt;/og:tabLink &gt;
 * ●body：なし
 *
 * ●Tag定義：
 *   &lt;og:tabList
 *       name             ○【TAG】要素に対して固有の名前をつけます(必須)。
 *       lbl                【TAG】ラベルリソースのラベルIDを指定します
 *       href               【TAG】リンク先のJSPを指定します(初期値:result.jsp)
 *       term               【TAG】処理する条件を指定します(初期値:null)
 *       termList           【TAG】処理する条件を含むような文字列を指定します
 *       delTerm            【TAG】処理しないタブを選択する条件を指定します(初期値:null)
 *       delTermList        【TAG】処理しない条件を含むような文字列を指定します
 *       unselClass         【TAG】非選択タブのクラスを指定します(初期値:unselTab)
 *       keys               【TAG】リンク先のJSPに引数として渡すキーをCSV形式で指定します
 *       vals               【TAG】リンク先のJSPに引数として渡す値をCSV形式で指定します
 *       roles              【TAG】ロールをセットします
 *       debug              【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false)
 *   /&gt;
 *
 * ●使用例
 *   tabListタグからタブリストを生成する場合
 *      &lt;og:tabLink
 *          listType        = "DB"                      タブの一覧をどこから取得するか
 *          href            = "result.jsp"              リンク先のJSP
 *          target          = "RESULT"                  リンクターゲット
 *          openTab         = "[true/false]"            タブ表示後にタブを自動で開く
 *          openTabName     = "{&#064;PN}               自動で開くタブの名前
 *          constKeys       = "KEY1"                    次画面に固定で渡すキー一覧
 *          constVals       = "{&#064;VAL1}"            次画面に固定で渡す値一覧
 *          listCount       = "10"                      1行辺りに表示するタブの数
 *          selClass        = "selTab"                  選択タブのクラス
 *          unselClass      = "unselTab"                非選択タブのクラス
 *          width           = "100px"                   タブリンクの幅
 *          height          = "50px"                    タブリンクの高さ
 *       &gt;
 *          &lt;og:tabList name="TAB1" href="result1.jsp" keys="PN,CDK" vals="ABC,V" /&gt;
 *          &lt;og:tabList name="TAB2" href="result2.jsp" keys="PN,CDK" vals="BCD,W" /&gt;
 *          &lt;og:tabList name="TAB3" href="result3.jsp" keys="PN,CDK" vals="CDE,X" /&gt;
 *      &lt;/og:tabLink&gt;
 *
 * @og.group 画面表示
 *
 * @version 4.3.5.0 (2008/02/01)
 * @author Nakamura
 * @since JDK1.4,
 */
public class TabListTag extends CommonTagSupport {
	/** このプログラムのVERSION文字列を設定します。	{@value} */
	private static final String VERSION = "6.4.2.0 (2016/01/29)" ;
	private static final long serialVersionUID = 642020160129L ;

	private String	name		;
	private String	href		;
	private String	unselClass	;

	private String[] keys		;
	private String[] vals		;

	private String	term		;
	private String	termList	;
	private String	delTerm		;
	private String	delTermList	;
	private boolean	visible		;
//	private TabLinkTag tabLink  ;				// 6.3.9.0 (2015/11/06)

	/**
	 * デフォルトコンストラクター
	 *
	 * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor.
	 */
	public TabListTag() {
		super();		// これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。
	}

//	/**
//	 * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。
//	 *
//	 * @og.rev 6.3.9.0 (2015/11/06) TabLinkTagの取得タイミングを、#doEndTag() に移す。
//	 *
//	 * @return	後続処理の指示( SKIP_BODY )
//	 */
//	@Override
//	public int doStartTag() {
//		tabLink = (TabLinkTag)findAncestorWithClass( this,TabLinkTag.class );
//		if( tabLink == null ) {
//			final String errMsg = "tabLink タグの BODY部で使用してください。";
//			throw new HybsSystemException( errMsg );
//		}
//		return SKIP_BODY ;	// Body を評価する。( extends BodyTagSupport 時)
//	}

	/**
	 * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。
	 *
	 * @og.rev 6.3.9.0 (2015/11/06) TabLinkTagの取得タイミングを、#doEndTag() に移す。
	 *
	 * @return	後続処理の指示
	 */
	@Override
	public int doEndTag() {
		debugPrint();

		visible = getUser().isAccess( get( "roles" ) );

		// delTermが優先
		if( visible ) {
			visible = delTermList == null || delTerm == null || delTermList.indexOf( delTerm ) < 0 ;
		}

		// delTermで表示対象となった場合に、termを処理
		if( visible ) {
			visible = termList == null || term == null || termList.indexOf( term ) >= 0 ;
		}

		// 6.3.9.0 (2015/11/06) TabLinkTagの取得タイミングを、#doEndTag() に移す。
		final TabLinkTag tabLink = (TabLinkTag)findAncestorWithClass( this,TabLinkTag.class );
		if( tabLink == null ) {
			final String errMsg = "tabLink タグの BODY部で使用してください。";
			throw new HybsSystemException( errMsg );
		}

		tabLink.addTag( href, name, getMsglbl(), unselClass, visible, keys, vals );

		return EVAL_PAGE ;
	}

	/**
	 * タグリブオブジェクトをリリースします。
	 * キャッシュされて再利用されるので、フィールドの初期設定を行います。
	 *
	 * @og.rev 6.3.9.0 (2015/11/06) TabLinkTagの取得タイミングを、#doEndTag() に移す。
	 */
	@Override
	protected void release2() {
		super.release2();
		name			= null;
		href			= null;
		term			= null;
		termList		= null;
		delTerm			= null;
		delTermList		= null;
		unselClass		= null;
		keys			= null;
		vals			= null;
		visible			= false;
//		tabLink			= null;				// 6.3.9.0 (2015/11/06)
	}

	/**
	 * 【TAG】要素に対して固有の名前をつけます。
	 *
	 * @og.tag
	 * 要素に対して固有の名前をつけます。
	 * ここで設定された名称は、自動でタブを表示するためのopenTabName属性判定にも使用されます。
	 *
	 * @param   nm タブ名
	 */
	public void setName( final String nm ) {
		name = nval( getRequestParameter( nm ), name );
	}

	/**
	 * 【TAG】リンク先のJSPを指定します(初期値:result.jsp)。
	 *
	 * @og.tag
	 * リンク先のJSPを指定します。
	 * ここで指定しない場合は、tagLinkタグの値が適用されます。
	 *
	 * @param	hr リンク先のJSP
	 */
	public void setHref( final String hr ) {
		href = nval( getRequestParameter( hr ), href );
	}

	/**
	 * 【TAG】処理する条件を指定します(初期値:null)。
	 *
	 * @og.tag
	 * termListで与えられた文字列に、term文字列(大文字/小文字の区別あり)が
	 * 含まれていれば、OPEN選択タブとして処理します。
	 * OPEN選択タブでないタブは、初期値OPENにならないだけで、タブそのものは表示されます。
	 * OPEN選択とDELETE選択が競合した場合は、DELETE選択が優先されます。
	 * 初期値は、 null です。
	 *
	 * @param	str 処理する条件文字列
	 */
	public void setTerm( final String str ) {
		term = nval( getRequestParameter( str ),term );
	}

	/**
	 * 【TAG】処理する条件を含むような文字列を指定します。
	 *
	 * @og.tag
	 * termListで与えられた文字列に、term文字列(大文字/小文字の区別あり)が
	 * 含まれていれば、OPEN選択タブとして処理します。
	 * 例えば、"A","B","C" という文字列が、term で指定された
	 * 場合に処理するようにしたい場合は、"A|B|C" をセットします。
	 * 初期値は、 null です。
	 * 判定は、文字列を含むかどうかなので、１文字のみの場合は、"|"区切りにする
	 * 必要はありません。
	 * OPEN選択とDELETE選択が競合した場合は、DELETE選択が優先されます。
	 *
	 * @param	list 処理する条件 (indexOf による含む/含まない判定)
	 */
	public void setTermList( final String list ) {
		termList = nval( getRequestParameter( list ),termList );
	}

	/**
	 * 【TAG】処理しないタブを選択する条件を指定します(初期値:null)。
	 *
	 * @og.tag
	 * delTermListで与えられた文字列に、delTerm文字列(大文字/小文字の区別あり)が
	 * 含まれていれば、DELETE選択タブとして処理します。
	 * DELETE選択タブは、タブそのものが表示されません。
	 * ただし、タブのselectIndex は、DELETEされたタブも含めて、カウントされますので、
	 * JSPでの設定時の順番がインデックス番号になります。
	 * OPEN選択とDELETE選択が競合した場合は、DELETE選択が優先されます。
	 * 初期値は、 null です。
	 *
	 * @param	str 非表示タブ
	 */
	public void setDelTerm( final String str ) {
		delTerm = nval( getRequestParameter( str ),delTerm );
	}

	/**
	 * 【TAG】処理しない条件を含むような文字列を指定します。
	 *
	 * @og.tag
	 * delTermListで与えられた文字列に、delTerm文字列(大文字/小文字の区別あり)が
	 * 含まれていれば、DELETE選択タブとして処理します。
	 * 例えば、"A","B","C" という文字列が、delTerm で指定された
	 * 場合に処理しないようにしたい場合は、"A|B|C" をセットします。
	 * 初期値は、 null です。
	 * 判定は、文字列を含むかどうかなので、１文字のみの場合は、"|"区切りにする
	 * 必要はありません。
	 * OPEN選択とDELETE選択が競合した場合は、DELETE選択が優先されます。
	 *
	 * @param	list 非表示タブ条件 (indexOf による含む/含まない判定)
	 */
	public void setDelTermList( final String list ) {
		delTermList = nval( getRequestParameter( list ),delTermList );
	}

	/**
	 * 【TAG】非選択タブのクラスを指定します(初期値:unselTab)。
	 *
	 * @og.tag
	 * タブが選択されていない状態にある場合の、タブ部分のクラス名を指定します。
	 * このクラス名を変更する場合は、そのクラスをcustom/custom.css等で再定義して下さい。
	 * tabListタグで指定された値は、tabLinkタグで指定されたものより優先されます。
	 * 初期値は、unselTabです。
	 *
	 * @param	cls 選択タブのクラス名
	 */
	public void setUnselClass( final String cls ) {
		unselClass = nval( getRequestParameter( cls ), unselClass );
	}

	/**
	 * 【TAG】リンク先のJSPに引数として渡すキーをCSV形式で指定します。
	 *
	 * @og.tag
	 * リンク先のJSPに引数として渡すキーをCSV形式で指定します。
	 *
	 * @param	key キー(CSV形式)
	 */
	public void setKeys( final String key ) {
		keys = getCSVParameter( key );
	}

	/**
	 * 【TAG】リンク先のJSPに引数として渡す値をCSV形式で指定します。
	 *
	 * @og.tag
	 * リンク先のJSPに引数として渡す値をCSV形式で指定します。
	 *
	 * @param	val 値(CSV形式)
	 */
	public void setVals( final String val ) {
		vals = getCSVParameter( val );
	}

	/**
	 * 【TAG】ロールをセットします。
	 *
	 * @og.tag
	 * ここで指定したカラムロールを元に、ユーザー毎のアクセス許可がチェックされます。
	 * アクセス許可されないと、表示されません。
	 * このロールを指定しない場合は、カラムリソースのロールが使用されます。
	 *
	 * @param	roles パラメータ
	 */
	public void setRoles( final String roles ) {
		set( "roles",getRequestParameter( roles ) );
	}

	/**
	 * このオブジェクトの文字列表現を返します。
	 * 基本的にデバッグ目的に使用します。
	 *
	 * @return このクラスの文字列表現
	 * @og.rtnNotNull
	 */
	@Override
	public String toString() {
		return ToString.title( this.getClass().getName() )
				.println( "VERSION"		,VERSION	)
				.println( "name"		,name		)
				.println( "href"		,href		)
				.println( "term"		,term		)
				.println( "termList"	,termList	)
				.println( "delTerm"		,delTerm	)
				.println( "delTermList"	,delTermList)
				.println( "Other..."	,getAttributes().getAttribute() )
				.fixForm().toString() ;
	}
}
