/*
 * 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.StringUtil ;
import org.opengion.fukurou.util.ToString;						// 6.1.1.0 (2015/01/17)
import org.opengion.fukurou.util.ArraySet;						// 6.4.3.4 (2016/03/11)

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

import java.util.Locale ;
import java.util.Set;											// 6.4.3.4 (2016/03/11)

/**
 * val1 属性 と val2 属性の文字列表現の比較により BODY を表示/非表示を切り替えるタグです。
 *
 * val1.equals( val2 ) が 成立すれば､ BODY を表示します。
 * val1 が null( or ゼロ文字列) の場合は、無条件で非成立になります。
 *  ( val1 == val2 ) はチェックしないというイメージです。
 * val1 が null( or ゼロ文字列) かどうか判断する場合は、nullCheck="true" を使用してください。
 * その他の属性は、比較方法を指定します。
 *
 * @og.formSample
 * ●形式：&lt;og:equals val1="…" val2="[…]" ･･･ &gt;･･･&lt;/og:equals&gt;
 * ●body：あり(EVAL_BODY_INCLUDE:BODYをインクルードし、{&#064;XXXX} は解析しません)
 *
 * ●Tag定義：
 *   &lt;og:equals
 *       val1             ○【TAG】equals で比較するときの、第１引数(左辺)を指定します(必須)。
 *       val2               【TAG】equals で比較するときの、第２引数(右辺)を指定します
 *       ignoreCase         【TAG】大文字/小文字を区別しないかどうか[true/false]を指定します(初期値:false(区別する))
 *       useTrim            【TAG】比較対象の引数を、trim()するかどうか[true/false]を指定します(初期値:false(trimしない))
 *       startsWith         【TAG】この文字列が、指定された接頭辞で始まるかどうか[true/false]を判定します(初期値:false)
 *       endsWith           【TAG】指定された接尾辞で終るかどうか[true/false]を判定します(初期値:false)
 *       nullCheck          【TAG】null チェックを行うかどうか[true/false]を指定します(初期値:false)
 *       notEquals          【TAG】判定結果を反転させるかどうか[true/false]を指定します(初期値:false)
 *       contains           【TAG】文字列が含まれているかどうか[true/false]の判定します(初期値:false)
 *       matches            【TAG】指定された正規表現と一致するかどうか[true/false]を判定します(初期値:false)
 *       useStop            【TAG】BODYを処理後に停止するかどうか[true/false]を指定します(初期値:false)
 *       operator           【TAG】比較する操作を EQ,LT,LE,GT,GE から指定します(初期値:EQ)
 *       compareType        【TAG】大小比較する方法(STRING:前方比較 、NUMBER:数値比較)を指定します(初期値:STRING)
 *       debug              【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false)
 *   &gt;   ... Body ...
 *   &lt;/og:equals&gt;
 *
 * ●使用例
 *      ・&lt;og:equals val1="ABCD" val2="{&#064;value}" &gt;
 *            val1.equals( val2 ) 時に実行したい内容
 *        &lt;/og:equals&gt;
 *
 *      ・&lt;og:equals val1="{&#064;value}" nullCheck="true" &gt;
 *            val1がnullの時に実行したい内容
 *        &lt;/og:equals&gt;
 *
 *      ・&lt;og:equals val1="AbcD" val2="{&#064;value}" ignoreCase="true" &gt;
 *            val1.equalsIgnoreCase( val2 ) 時に実行したい内容
 *        &lt;/og:equals&gt;
 *
 *      ・&lt;og:equals val1="ABCD" val2="{&#064;value}" startsWith="true" &gt;
 *            val1.startsWith( val2 ) 時に実行したい内容
 *        &lt;/og:equals&gt;
 *
 * @og.group 画面制御
 * @og.rev 6.4.2.0 (2016/01/29) ソースの内部構造の全体的な見直し。
 *
 * @version  4.0
 * @author   Kazuhiko Hasegawa
 * @since    JDK5.0,
 */
public class EqualsTag extends CommonTagSupport {
	/** このプログラムのVERSION文字列を設定します。	{@value} */
	private static final String VERSION = "6.4.3.4 (2016/03/11)" ;
	private static final long serialVersionUID = 643420160311L ;

//	// 3.8.1.3B (2006/01/30) operator に指定できる定数を定義
//	private static final String[] OPERATOR_LIST = { "EQ","LT","LE","GT","GE","GE" };

//	// 3.8.1.3B (2006/01/30) compareType に指定できる定数を定義
//	private static final String[] COMP_TYPE_LIST = { "STRING","NUMBER" };

	// 6.4.3.4 (2016/03/11) String配列 から、Setに置き換えます。
	private static final Set<String> OPERATOR_SET = new ArraySet<>( "EQ","LT","LE","GT","GE","GE" );
	private static final Set<String> COMP_TYPE_SET = new ArraySet<>( "STRING","NUMBER" );

	private String  value1		;
	private String  value2		;
	// 5.1.2.0 (2010/01/01)
	private boolean ignoreCase	;	// 大文字/小文字の区別
	private boolean useTrim		;	// 6.4.2.0 (2016/01/29) trimするかどうか
	private boolean isStartsWith;	// 先頭から始まるかどうかのチェック(startsWith)
	private boolean nullCheck	;	// null チェックを行う場合うかどうか？
	private boolean notEquals	;	// 判定結果を反転させて処理します。

	// 3.2.0.0 (2003/05/22) 判定方法に以下の３方法を追加します。
	private boolean isContains	;	// 文字列が含まれているかどうかの判定
	private boolean isEndsWith	;	// 指定された接尾辞で終るかどうかを判定(endsWith)
	private boolean isMatches	;	// 指定された正規表現と一致するかどうかを判定

	// 3.8.1.2 (2005/12/19) BODYを処理後に停止するかどうかを指定します。
	private boolean useStop		;	// BODYを処理後に停止(true)するかどうか

	// 3.8.1.3B (2006/01/30) operator、compareType 属性を追加します。
	private String  operator	= "EQ";
	private String  compareType	= "STRING";

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

	/**
	 * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。
	 *
	 * @og.rev 3.2.0.0 (2003/05/22) 判定方法に,contains,endsWith,matches の方法を追加
	 * @og.rev 3.8.1.3B (2006/01/30) operator、compareType 属性を追加します。
	 * @og.rev 3.8.5.1 (2006/04/28) equals の結果が true 時のみ、useStop="true" を有効にする。
	 * @og.rev 6.4.2.0 (2016/01/29) ソースの内部構造の全体的な見直し。
	 *
	 * @return	後続処理の指示
	 */
	@Override
	public int doStartTag() {
		// 6.4.2.0 (2016/01/29) useTrim の追加。
		if( useTrim ) {
			if( value1 != null ) { value1 = value1.trim(); }
			if( value2 != null ) { value2 = value2.trim(); }
		}

		// 6.4.2.0 (2016/01/29) ignoreCase の先行対応。
		if( ignoreCase ) {
			if( value1 != null ) { value1 = value1.toUpperCase(Locale.JAPAN); }
			if( value2 != null ) { value2 = value2.toUpperCase(Locale.JAPAN); }
		}

		// 6.4.2.0 (2016/01/29) 排他的論理和 で、判定結果の反転。
		final boolean flag =
					(	( isStartsWith	&& startsWith(	value1,value2 )	)	||	// 先に isStartsWith をチェック
						( isContains	&& contains(	value1,value2 ) )	||
						( isEndsWith	&& endsWith(	value1,value2 ) )	||
						( isMatches		&& matches(		value1,value2 ) )	||
						( nullCheck		&& isNullCheck( value1 )  )			||
//						( operation( value1,value2,operator,compareType,ignoreCase ) )
						( operation( value1,value2,operator,compareType ) )
					) ^ notEquals;

//		boolean rtn = notEquals;
//		if( ( isStartsWith	&& startsWith(	value1,value2 )	)	||	// 先に isStartsWith をチェック
//			( isContains	&& contains(	value1,value2 ) )	||
//			( isEndsWith	&& endsWith(	value1,value2 ) )	||
//			( isMatches		&& matches(		value1,value2 ) )	||
//			( nullCheck		&& isNullCheck( value1 )  )			||
//			( operation( value1,value2,operator,compareType,ignoreCase ) ) ) {
//				rtn = ! notEquals;
//		}

		// 3.8.5.1 (2006/04/28) equals の結果が true 時のみ、useStop="true" を有効にする。
//		useStop = useStop && rtn ;		// 少し回りくどいが判りやすいでしょ。
		useStop = useStop && flag ;		// 少し回りくどいが判りやすいでしょ。

//		if( rtn ) { return EVAL_BODY_INCLUDE ; }
//		else      { return SKIP_BODY ;         }

		return flag ? EVAL_BODY_INCLUDE : SKIP_BODY ; 
	}

	/**
	 * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。
	 *
	 * @og.rev 3.8.1.2 (2005/12/19) useStop 属性を処理します。
	 * @og.rev 6.4.2.0 (2016/01/29) ソースの内部構造の全体的な見直し。
	 * @og.rev 6.4.2.1 (2016/02/05) debugPrint() の追加。
	 *
	 * @return	後続処理の指示
	 */
	@Override
	public int doEndTag() {
		debugPrint();				// 6.4.2.1 (2016/02/05)

//		if( useStop ) {
//			return SKIP_PAGE ;		// ページの残りの処理を行わない。
//		}
//		else {
//			return EVAL_PAGE ;		// ページの残りを評価する。
//		}

		return useStop ? SKIP_PAGE : EVAL_PAGE ; 
	}

	/**
	 * タグリブオブジェクトをリリースします。
	 * キャッシュされて再利用されるので、フィールドの初期設定を行います。
	 *
	 * @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.2.0.0 (2003/05/22) 判定方法に,contains,endsWith,matches の方法を追加
	 * @og.rev 3.8.1.2 (2005/12/19) useStop 属性の追加
	 * @og.rev 3.8.1.3 (2006/01/30) operator、compareType 属性を追加します。
	 * @og.rev 5.1.2.0 (2010/01/01) ignoreCase属性の初期値をfalse(大文字、小文字を区別する)
	 * @og.rev 6.4.2.0 (2016/01/29) trim属性を追加します。
	 *
	 */
	@Override
	protected void release2() {
		super.release2();
		value1		= null;
		value2		= null;
		ignoreCase	= false;	// 5.1.2.0 (2010/01/01) 大文字/小文字の区別
		useTrim		= false;	// 6.4.2.0 (2016/01/29) trimするかどうか
		isStartsWith= false;	// 先頭から始まるかどうかのチェック
		nullCheck	= false;	// null チェックを行う場合うかどうか？
		notEquals	= false;	// 判定結果を反転させて処理します。
		isContains	= false;	// 文字列が含まれているかどうかの判定
		isEndsWith	= false;	// 指定された接尾辞で終るかどうかを判定
		isMatches	= false;	// 指定された正規表現と一致するかどうかを判定
		useStop		= false;	// 3.8.1.2 (2005/12/19)
		operator	= "EQ";		// 3.8.1.3B (2006/01/30)
		compareType	= "STRING";	// 3.8.1.3B (2006/01/30)
	}

	/**
	 * operator に対応した比較処理を行います。
	 * val1 または、val2 が null の場合は、無条件で false を返します。
	 *
	 * @og.rev 3.8.1.3 (2006/02/06) 判定方法に, LT, GT, LE, GE, EQ追加
	 * @og.rev 6.4.2.0 (2016/01/29) ソースの内部構造の全体的な見直し。
	 *
	 * @param   val1 第１引数
	 * @param   val2 第２引数
	 * @param   op 比較方法
	 * @param   ty 比較種類
	 *
	 * @return  第１,第２引数が null/ゼロストリング でなく、且つ opeに対応した比較結果を返します。
	 */
//	private boolean operation( final String val1,final String val2,final String op,final String ty,final boolean ig ) {
	private boolean operation( final String val1,final String val2,final String op,final String ty ) {
		if( isNullCheck( val1 ) || isNullCheck( val2 )) { return false; }
		// 文字列比較
		final boolean rtn;
		if( "STRING".equals( ty ) ) {
			switch( op ) {
				case "LT" : rtn = val1.compareTo( val2 ) < 0 ;	break;
				case "GT" : rtn = val1.compareTo( val2 ) > 0 ;	break;
				case "LE" : rtn = val1.compareTo( val2 ) <= 0;	break;
				case "GE" : rtn = val1.compareTo( val2 ) >= 0;	break;
				default   : rtn = val1.equals(    val2 );		break;
			}

//			String va1    = val1;
//			String va2    = val2;
//			// 大文字小文字を区別しない
//			if( ig ) {
//				va1 = val1.toUpperCase(Locale.JAPAN);
//				va2 = val2.toUpperCase(Locale.JAPAN);
//			}
//			if( "LT".equals( op ) ) {
//				rtn = va1.compareTo( va2 ) < 0;
//			} else if( "GT".equals( op ) ) {
//				rtn = va1.compareTo( va2 ) > 0;
//			} else if( "LE".equals( op ) ) {
//				rtn = va1.compareTo( va2 ) <= 0;
//			} else if( "GE".equals( op ) ) {
//				rtn = va1.compareTo( va2 ) >= 0;
//			} else {
//				rtn = va1.equals( va2 );
//			}
		// 数字比較
		} else {
			// 厳密に処理しなくて良いと思うのでBigDecimalは使わない
			final double d1  = StringUtil.parseDouble( val1 );
			final double d2  = StringUtil.parseDouble( val2 );
			switch( op ) {
				case "LT" : rtn = d1 < d2 ;							break;
				case "GT" : rtn = d1 > d2 ;							break;
				case "LE" : rtn = d1 <= d2;							break;
				case "GE" : rtn = d1 >= d2;							break;
				default   : rtn = Math.abs(d1 - d2) < 0.0000001;	break;			// d1 == d2 の事
			}

//			if( "LT".equals( op ) ) {
//				rtn = d1 < d2;
//			} else if( "GT".equals( op ) ) {
//				rtn = d1 > d2;
//			} else if( "LE".equals( op ) ) {
//				rtn = d1 <= d2;
//			} else if( "GE".equals( op ) ) {
//				rtn = d1 >= d2;
//			} else {
//	//			rtn = d1 == d2;
//				rtn = Math.abs(d1 - d2) < 0.0000001 ;
//			}
		}
		return rtn ;
	}

	/**
	 * startsWith で比較するときの、比較メソッド。
	 *
	 * val1 が、比較元の文字列で、val2 が部分文字列になります。
	 * val1.startsWith( val2 );
	 *
	 * @og.rev 6.4.2.0 (2016/01/29) ソースの内部構造の全体的な見直し。
	 *
	 * @param   val1 第１引数
	 * @param   val2 第２引数
	 *
	 * @return  第１,第２引数が null/ゼロストリング でなく、且つ val1.startsWith( val2 ) の結果
	 */
	private boolean startsWith( final String val1,final String val2 ) {
		return ! isNullCheck( val1 ) && ! isNullCheck( val2 ) && val1.startsWith( val2 ) ; 

//		boolean rtn = false;
//		if( ! isNullCheck( val1 ) && ! isNullCheck( val2 ) ) {
//			if( ignoreCase ) { rtn = val1.toUpperCase(Locale.JAPAN).startsWith( val2.toUpperCase(Locale.JAPAN) ) ; }
//			else             { rtn = val1.startsWith( val2 ) ;                              }
//		}
//		return rtn ;
	}

	/**
	 * nullCheck で判定するときの、判定メソッド。
	 *
	 * @og.rev 6.4.2.0 (2016/01/29) ソースの内部構造の全体的な見直し。
	 *
	 * @param   val1 第１引数
	 *
	 * @return  第１引数が null/ゼロストリング の場合 true
	 */
	private boolean isNullCheck( final String val1 ) {
		return val1 == null || val1.isEmpty() ;

//		boolean rtn = true;
//		if( val1 != null && val1.length() > 0 ) {
//			rtn = false;
//		}
//		return rtn ;
	}

	/**
	 * contains で比較するときの、比較メソッド。
	 *
	 * val1 が、比較元の文字列で、val2 が部分文字列になります。
	 * val1.contains( val2 );
	 *
	 * @og.rev 3.2.0.0 (2003/05/22) 判定方法に,contains,endsWith,matches の方法を追加
	 * @og.rev 6.4.2.0 (2016/01/29) ソースの内部構造の全体的な見直し。
	 *
	 * @param   val1 第１引数
	 * @param   val2 第２引数
	 *
	 * @return  第１,第２引数が null/ゼロストリング でなく、且つ val1.contains( val2 ) の結果
	 */
	private boolean contains( final String val1,final String val2 ) {
		return ! isNullCheck( val1 ) && ! isNullCheck( val2 ) && val1.contains( val2 ) ;

//		int rtn = -1;
//		if( ! isNullCheck( val1 ) && ! isNullCheck( val2 ) ) {
//			if( ignoreCase ) { rtn = val1.toUpperCase(Locale.JAPAN).indexOf( val2.toUpperCase(Locale.JAPAN) ) ; }
//			else             { rtn = val1.indexOf( val2 ) ;                              }
//		}
//		return rtn >= 0 ;
	}

	/**
	 * endsWith で比較するときの、比較メソッド。
	 *
	 * val1 が、比較元の文字列で、val2 が部分文字列になります。
	 * val1.endsWith( val2 ) ;
	 *
	 * @og.rev 3.2.0.0 (2003/05/22) 判定方法に,contains,endsWith,matches の方法を追加
	 * @og.rev 6.4.2.0 (2016/01/29) ソースの内部構造の全体的な見直し。
	 *
	 * @param   val1 第１引数
	 * @param   val2 第２引数
	 *
	 * @return  第１,第２引数が null/ゼロストリング でなく、且つ val1.endsWith( val2 ) の結果
	 */
	private boolean endsWith( final String val1,final String val2 ) {
		return ! isNullCheck( val1 ) && ! isNullCheck( val2 ) && val1.endsWith( val2 ) ;

//		boolean rtn = false;
//		if( ! isNullCheck( val1 ) && ! isNullCheck( val2 ) ) {
//			if( ignoreCase ) { rtn = val1.toUpperCase(Locale.JAPAN).endsWith( val2.toUpperCase(Locale.JAPAN) ) ; }
//			else             { rtn = val1.endsWith( val2 ) ;                              }
//		}
//		return rtn ;
	}

	/**
	 * matches で比較するときの、比較メソッド。
	 *
	 * val1 が、比較元の文字列で、val2 が正規表現の文字列になります。
	 * val1.matches( val2 );
	 *
	 * @og.rev 3.2.0.0 (2003/05/22) 判定方法に,contains,endsWith,matches の方法を追加
	 * @og.rev 6.4.2.0 (2016/01/29) ソースの内部構造の全体的な見直し。
	 *
	 * @param   val1 第１引数
	 * @param   val2 第２引数
	 *
	 * @return  第１,第２引数が null/ゼロストリング でなく、且つ val1.matches( val2 ) の結果
	 */
	private boolean matches( final String val1,final String val2 ) {
		return ! isNullCheck( val1 ) && ! isNullCheck( val2 ) && val1.matches( val2 ) ;

//		boolean rtn = false;
//		if( ! isNullCheck( val1 ) && ! isNullCheck( val2 ) ) {
//			rtn = val1.matches( val2 );
//		}
//		return rtn ;
	}

	/**
	 * 【TAG】equals で比較するときの、第１引数(左辺)を指定します。
	 *
	 * @og.tag equals で比較するときの、第１引数を指定します。
	 * val1 が null の場合は、無条件で非成立になります。
	 *  ( val1 == val2 ) はチェックしないというイメージです。
	 * val1 が null かどうか判断する場合は、nullCheck="true" を使用してください。
	 *
	 * @param   val 第１引数
	 */
	public void setVal1( final String val ) {
		this.value1 = getRequestParameter( val );
	}

	/**
	 * 【TAG】equals で比較するときの、第２引数(右辺)を指定します。
	 *
	 * @og.tag equals で比較するときの、第２引数を指定します。
	 *
	 * @param   val 第２引数
	 */
	public void setVal2( final String val ) {
		this.value2 = getRequestParameter( val );
	}

	/**
	 * 【TAG】大文字/小文字を区別しないかどうか[true/false]を指定します(初期値:false(区別する))。
	 *
	 * @og.tag
	 * startsWith , contains , endsWith , equalsIgnoreCase での比較時に、比較対象の
	 * 大文字/小文字を区別しないかどうかを指定します。
	 * 区別しない ("true") 場合、aaa と AAA は、一致したとみなされます。
	 * 初期値は、区別する ("false") です。
	 *
	 * @param   flag 大文字/小文字を区別しないかどうか [true:しない/それ以外:する]
	 */
	public void setIgnoreCase( final String flag ) {
		ignoreCase = nval( getRequestParameter( flag ),ignoreCase );
	}

	/**
	 * 【TAG】比較対象の引数を、trim()するかどうか[true/false]を指定します(初期値:false(trimしない))。
	 *
	 * @og.tag
	 * equals , startsWith , contains , endsWith 等での比較時に、比較対象の
	 * 引数を、両端空白文字（スペース、タブ、改行など）を削除します。
	 * この処理を行う場合は、一番最初に行います。nullCheck などは、trim() された結果を使用します。
	 * 初期値は、trimしない ("false") です。
	 *
	 * @og.rev 6.4.2.0 (2016/01/29) trim属性を追加します。
	 *
	 * @param   flag trimするかどうか [true:する/それ以外:しない]
	 */
	public void setUseTrim( final String flag ) {
		useTrim = nval( getRequestParameter( flag ),useTrim );
	}

	/**
	 * 【TAG】この文字列が、指定された接頭辞で始まるかどうか[true/false]を判定します(初期値:false)。
	 *
	 * @og.tag
	 * val1.startsWith( val2 ) の書式で判定されます。この場合、"ABCDEFG".startsWith( "ABC" )
	 * の場合に、条件成立します。(つまり、val1 に対して、val2 で始まっているかどうか問合せる)
	 * 初期値は、判定しない ("false")
	 *
	 * @param   flag 接頭辞で始まるかどうか [true:判定する/それ以外:しない]
	 */
	public void setStartsWith( final String flag ) {
		isStartsWith = nval( getRequestParameter( flag ),isStartsWith );
	}

	/**
	 * 【TAG】null チェックを行うかどうか[true/false]を指定します(初期値:false)。
	 *
	 * @og.tag
	 * チェックを行うように指定("true")した場合に、第一引数が null の場合は,
	 * 条件成立して、タグのBody は実行されます。
	 * 初期値は、行わない (true 以外)です。
	 *
	 * @param   flag nullチェックを行うかどうか [true:行う/それ以外:行わない]
	 */
	public void setNullCheck( final String flag ) {
		nullCheck = nval( getRequestParameter( flag ),nullCheck );
	}

	/**
	 * 【TAG】判定結果を反転させるかどうか[true/false]を指定します(初期値:false)。
	 *
	 * @og.tag
	 * 通常の成立条件において、不成立の場合に、BODY を実行します。
	 * 通常の処理結果を求めて、最後に、反転処理を行います。
	 * 初期値は、通常 (true 以外)です。
	 *
	 * @param   flag 反転させるか [true:反転する/それ以外:通常]
	 */
	public void setNotEquals( final String flag ) {
		notEquals = nval( getRequestParameter( flag ),notEquals );
	}

	/**
	 * 【TAG】文字列が含まれているかどうか[true/false]の判定します(初期値:false)。
	 *
	 * @og.tag
	 * val1.indexOf( val2 ) &gt;= 0 の書式で判定されます。この場合、"ABCDEFG".indexOf( "CDE" )
	 * の場合に、条件成立します。(つまり、val1 に対して、val2 が含まれているかどうか問合せる)
	 * 初期値は、判定しない ("false")
	 *
	 * @og.rev 3.2.0.0 (2003/05/22) 判定方法に,contains,endsWith,matches の方法を追加
	 *
	 * @param   flag 含む判定 [true:判定する/それ以外:しない]
	 */
	public void setContains( final String flag ) {
		isContains = nval( getRequestParameter( flag ),isContains );
	}

	/**
	 * 【TAG】指定された接尾辞で終るかどうか[true/false]を判定します(初期値:false)。
	 *
	 * @og.tag
	 * val1.endsWith( val2 ) の書式で判定されます。この場合、"ABCDEFG".endsWith( "EFG" )
	 * の場合に、条件成立します。(つまり、val1 に対して、val2 で終わっているかどうか問合せる)
	 * 初期値は、判定しない ("false")
	 *
	 * @og.rev 3.2.0.0 (2003/05/22) 判定方法に,contains,endsWith,matches の方法を追加
	 *
	 * @param   flag 接尾辞判定 [true:判定する/それ以外:しない]
	 */
	public void setEndsWith( final String flag ) {
		isEndsWith = nval( getRequestParameter( flag ),isEndsWith );
	}

	/**
	 * 【TAG】指定された正規表現と一致するかどうか[true/false]を判定します(初期値:false)。
	 *
	 * @og.tag
	 * val1.matches( val2 ) の書式で判定されます。val2 に指定された正規表現で、
	 * 一致するかどうかを判定します。ここでの正規表現とは、
	 * java.util.regex.Pattern.matches(val1, val2) での判定結果と同じです。
	 * 初期値は、判定しない ("false")
	 *
	 * @og.rev 3.2.0.0 (2003/05/22) 判定方法に,contains,endsWith,matches の方法を追加
	 *
	 * @param   flag 正規表現一致判定 [true:判定する/それ以外:しない]
	 */
	public void setMatches( final String flag ) {
		isMatches = nval( getRequestParameter( flag ),isMatches );
	}

	/**
	 * 【TAG】BODYを処理後に停止するかどうか[true/false]を指定します(初期値:false)。
	 *
	 * @og.tag
	 * 処理結果などに応じて、以下の処理を停止したい場合に、使用します。
	 * ここでは、条件を判定後、true の場合に、BODY部を出力(処理)した後に、
	 * ここにセットされた値に応じて、以下のページ処理を行うかどうかを指定します。
	 * true を指定すると、以下の処理は、行われません。
	 * 初期値は、停止しない ("false")
	 *
	 * @og.rev 3.8.1.2 (2005/12/19) 新規追加
	 *
	 * @param   flag 処理後停止 [true:する/それ以外:しない]
	 */
	public void setUseStop( final String flag ) {
		useStop = nval( getRequestParameter( flag ),useStop );
	}

	/**
	 * 【TAG】比較する操作を EQ,LT,LE,GT,GE から指定します(初期値:EQ)。
	 *
	 * @og.tag
	 * 比較方法として、EQ(==)、LT(&lt;)、LE(&lt;=)、GT(&gt;)、GE(&gt;=) があります。
	 * 初期値は、EQ(同じかどうか)です。
	 * 比較は、val1 に対して行われます。val1 または val2 が null の場合は、常にfalseが
	 * 返されます。通常の A &lt; B ならば、not( B &gt;= A ) の関係は成立しません。
	 * val1 が null でない場合は、val1(5) LT vla2(8) は、true を返します。
	 * ignoreCase属性(大文字/小文字の区別)を指定することで、比較する文字列の
	 * 大文字小文字を統一させることが可能です。
	 * なお、比較時には、compareType 属性にもご注意ください。これは、文字列比較か
	 * 数字比較を指定します。
	 *
	 * @og.rev 3.8.1.3B (2006/01/30) 新規追加
	 * @og.rev 6.3.4.0 (2015/08/01) Arrays.toString から String.join に置き換え。
	 * @og.rev 6.4.3.4 (2016/03/11) String配列 から、Setに置き換えます。
	 *
	 * @param	ope	比較する操作 [EQ/LT/LE/GT/GE]
	 * @see     #setIgnoreCase( String )
	 * @see     #setCompareType( String )
	 */
	public void setOperator( final String ope ) {
		operator = nval( getRequestParameter( ope ),operator );

//		if( !check( operator, OPERATOR_LIST ) ) {
		if( !check( operator, OPERATOR_SET ) ) {
			final String errMsg = "指定のオペレーションはサポートされていません。オペレーションエラー"	+ CR
							+ "operator=[" + ope + "] "													+ CR
//							+ StringUtil.array2csv( OPERATOR_LIST ) ;
//							+ "operatorList=" + String.join( ", " , OPERATOR_LIST ) ;
							+ "operatorList=" + String.join( ", " , OPERATOR_SET ) ;
			throw new HybsSystemException( errMsg );
		}
	}

	/**
	 * 【TAG】大小比較する方法(STRING:前方比較 、NUMBER:数値比較)を指定します(初期値:STRING)。
	 *
	 * @og.tag
	 * operator 属性で大小を比較する場合、比較方法として、前方比較と数値比較を指定できます。
	 * STRING(前方比較)とは、お互いの文字列を前方から順に比較していきます。例えば、
	 * ABC と AABBCC や、123 と 112233 では、AABBCC や 112233 が小さいと判断されます。
	 * NUMBER(数値比較)では、123 と 112233 では、123 が小さいと判断されます。
	 * NUMBER は、数字に変換できる値である必要があります。
	 * STRING は、ignoreCase属性(大文字/小文字の区別)を指定することで、比較する文字列の
	 * 大文字小文字を統一させることが可能です。
	 * 初期値は、STRING(前方比較)です。
	 *
	 * @og.rev 3.8.1.3B (2006/01/30) 新規追加
	 * @og.rev 6.3.4.0 (2015/08/01) Arrays.toString から String.join に置き換え。
	 * @og.rev 6.4.3.4 (2016/03/11) String配列 から、Setに置き換えます。
	 *
	 * @param   type 判定方法 [STRING:前方比較/NUMBER(数値比較)]
	 * @see     #setIgnoreCase( String )
	 * @see     #setOperator( String )
	 */
	public void setCompareType( final String type ) {
		compareType = nval( getRequestParameter( type ),compareType );

//		if( !check( compareType, COMP_TYPE_LIST ) ) {
		if( !check( compareType, COMP_TYPE_SET ) ) {
			final String errMsg = "指定のcompareTypeはサポートされていません。compareTypeエラー"	+ CR
							+ "compareType=[" + type + "] "											+ CR
//							+ StringUtil.array2csv( COMP_TYPE_LIST ) ;
//							+ "compareTypeList=" + String.join( ", " , COMP_TYPE_LIST ) ;
							+ "compareTypeList=" + String.join( ", " , COMP_TYPE_SET ) ;
			throw new HybsSystemException( errMsg );
		}
	}

	/**
	 * このオブジェクトの文字列表現を返します。
	 * 基本的にデバッグ目的に使用します。
	 *
	 * @og.rev 3.2.0.0 (2003/05/22) 判定方法に,contains,endsWith,matches の方法を追加
	 *
	 * @return このクラスの文字列表現
	 * @og.rtnNotNull
	 */
	@Override
	public String toString() {
		return ToString.title( this.getClass().getName() )
				.println( "VERSION"		,VERSION	)
				.println( "value1"		,value1		)
				.println( "value2"		,value2		)
				.println( "ignoreCase"	,ignoreCase	)
				.println( "useTrim"		,useTrim	)					// 6.4.2.0 (2016/01/29)
				.println( "startsWith"	,isStartsWith	)
				.println( "nullCheck"	,nullCheck	)
				.println( "notEquals"	,notEquals	)
				.println( "contains"	,isContains	)
				.println( "endsWith"	,isEndsWith	)
				.println( "matches"		,isMatches	)
				.println( "useStop"		,useStop	)
				.println( "Other..."	,getAttributes().getAttribute() )
				.fixForm().toString() ;
	}
}
