/*
 * 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 java.util.ArrayList;
import java.util.List;
import java.util.Set;											// 6.4.3.4 (2016/03/11)
import java.util.regex.Pattern;									// 7.0.1.8 (2019/01/28)

import org.opengion.fukurou.util.ErrorMessage;
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 org.opengion.hayabusa.common.HybsSystem;
import org.opengion.hayabusa.common.HybsSystemException;
import org.opengion.hayabusa.db.DBTableModel;
import org.opengion.hayabusa.db.Query;
import org.opengion.hayabusa.resource.GUIInfo;

import static org.opengion.fukurou.util.StringUtil.nval;
import static org.opengion.fukurou.system.HybsConst.BR;			// 6.1.0.0 (2014/12/26) refactoring

/**
 * SQL文を直接指定して、データベースに追加/更新/削除を行います(queryType="JDBCTableUpdate")。
 *
 * 存在チェックを行う場合は、tableExist タグと併用してください。
 * 複雑な処理が必要な場合は、従来より使用しています、PLSQLをCALLする、
 * plsqlUpdateタグを使用してください。
 * また、tableUpdateParam タグを使用する事で、テーブル名とsqlTypeの指定で動的に
 * SQL文を自動生成できます。これにより、追加、更新、削除やテーブルに関して、
 * 単一のJSP画面ですべて対応できるようになります。
 *
 * 7.2.9.3 (2020/11/06)
 *   queryType="JDBCTableMerge" と、"JDBCTableUpdate" を相互運用します。
 *   tableUpdateParam ﾀｸﾞのsqlType="MERGE" を指定しておくと、
 *   UPDATE文とINSERT文を両方とも作成して、有れば更新なければ追加処理を行います。
 *   その場合、queryTypeを、JDBCTableMerge に変更します。
 *   sqlType が従来の"INSERT"や"UPDATE" の場合は、queryTypeを、JDBCTableUpdate
 *   に変更します。
 *   この変換は、"JDBCTableMerge" と、"JDBCTableUpdate" を相互運用します。
 *
 * ※ このタグは、Transaction タグの対象です。
 *
 * @og.formSample
 * ●形式：&lt;og:tableUpdate command="…" names="…" queryType="JDBCTableUpdate" &gt;
 *             {&#064;SQL}
 *         &lt;/og:update&gt;
 * ●body：あり(EVAL_BODY_BUFFERED:BODYを評価し、{&#064;XXXX} を解析します)
 *
 * ●Tag定義：
 *   &lt;og:tableUpdate
 *       queryType          【TAG】Query を発行する為のクラスID(JDBCTableUpdate,JDBCTableMerge)を指定します({@og.doc03Link queryType 初期値:JDBCTableUpdate})
 *       sqlType            【TAG】BODY部に書かれている Param の SQLタイプを指定します(INSERT,COPY,UPDATE,MODIFY,DELETE,MERGE,無指定)
 *       command            【TAG】コマンド (NEW,RENEW)をセットします(PlsqlUpdateTag,UpdateTag の場合は、ENTRY)
 *       scope              【TAG】キャッシュする場合のスコープ[request/page/session/application]を指定します(初期値:session)
 *       displayMsg         【TAG】検索結果を画面上に表示するメッセージリソースIDを指定します (初期値:VIEW_DISPLAY_MSG[=])
 *       resourceType       【特殊】クリアするリソースの種類[GEA03/GEA04/GEA08]を指定します
 *       conditionKey       【TAG】条件判定するカラムＩＤを指定します(初期値:null)
 *       conditionList      【TAG】条件判定する値のリストを、"|"で区切って登録します(初期値:無条件) 7.0.1.8 (2019/01/28) 正規表現に変更
 *       tableId            【TAG】(通常は使いません)結果のDBTableModelを、sessionに登録するときのキーを指定します
 *       dbid               【TAG】(通常は使いません)Queryオブジェクトを作成する時のDB接続IDを指定します
 *       selectedAll        【TAG】データを全件選択済みとして処理するかどうか[true/false]を指定します(初期値:false)
 *       commitTableModel   【特殊】SQL実行後に結果をDBTableModelに反映させるかどうか[true/false]を指定します(初期値:true)
 *       followCdkh         【TAG】DBTableModelの改廃Cに従って処理を行うかを指定します
 *       quotCheck          【TAG】リクエスト情報の シングルクォート(') 存在チェックを実施するかどうか[true/false]を設定します(初期値:false)
 *       useTimeView        【TAG】処理時間を表示する TimeView を表示するかどうかを指定します
 *										(初期値:VIEW_USE_TIMEBAR[={@og.value SystemData#VIEW_USE_TIMEBAR}])。
 *       useSLabel          【TAG】7.0.7.0 (2019/12/13) ｴﾗｰﾒｯｾｰｼﾞにSLABELを利用するかどうか[true/false]を指定します(初期値:false)
 *       caseKey            【TAG】このタグ自体を利用するかどうかの条件キーを指定します(初期値:null)
 *       caseVal            【TAG】このタグ自体を利用するかどうかの条件値を指定します(初期値:null)
 *       caseNN             【TAG】指定の値が、null/ゼロ文字列 でない場合(Not Null=NN)は、このタグは使用されます(初期値:判定しない)
 *       caseNull           【TAG】指定の値が、null/ゼロ文字列 の場合は、このタグは使用されます(初期値:判定しない)
 *       caseIf             【TAG】指定の値が、true/TRUE文字列の場合は、このタグは使用されます(初期値:判定しない)
 *       debug              【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false)
 *   &gt;   ... Body ...
 *   &lt;/og:tableUpdate&gt;
 *
 * ●使用例
 *    ・QUERYを他のJSPから渡す場合
 *    【copy.jsp】
 *        &lt;og:hidden name=&quot;SQL&quot; &gt;
 *          INSERT INTO GE41
 *               (CLM,NAME_JA,LABEL_NAME,KBSAKU,SYSTEM_ID,LANG,
 *               FGJ,DYSET,DYUPD,USRSET,USRUPD,PGUPD)
 *          VALUES
 *               ([CLM],[NAME_JA],[LABEL_NAME],[KBSAKU],[SYSTEM_ID],[LANG],
 *               &#39;1&#39;,&#39;{&#064;USER.YMDH}&#39;,&#39;{&#064;USER.YMDH}&#39;,&#39;{&#064;USER.ID}&#39;,&#39;{&#064;USER.ID}&#39;,&#39;{&#064;GUI.KEY}&#39;)
 *        &lt;/og:value&gt;
 *
 *    【entry.jsp】
 *        &lt;og:tableUpdate
 *            command   = &quot;{&#064;command}&quot;
 *            queryType = &quot;JDBCTableUpdate&quot;
 *        {&#064;SQL}
 *        &lt;/og:tableUpdate&gt;
 *
 *    ・tableUpdateParamを使用する場合
 *    【entry.jsp】
 *        &lt;og:tableUpdate
 *            command   = &quot;{&#064;command}&quot;
 *            queryType = &quot;JDBCTableUpdate&quot;
 *            sqlType   = &quot;{&#064;sqlType}&quot;        // tableUpdateParam の sqlType と一致
 *        &gt;
 *            &lt;og:tableUpdateParam
 *                sqlType     = &quot;{&#064;sqlType}"       // INSERT,COPY,UPDATE,MODIFY,DELETE,MERGE
 *                table       = &quot;{&#064;TABLE_NAME}"    // 処理対象のテーブル名
 *                names       = &quot;{&#064;names}"         // 処理対象のカラム名
 *                omitNames   = &quot;{&#064;omitNames}"     // 処理対象外のカラム名
 *                where       = &quot;{&#064;where}"         // 処理対象を特定するキー
 *                constKeys   = &quot;{&#064;constKeys}"     // 処理カラム名の中の固定情報カラム名
 *                constVals   = &quot;{&#064;constVals}"     // 処理カラム名の中の固定情報設定値
 *            /&gt;
 *        &lt;/og:tableUpdate&gt;
 *
 *    ・処理の可否を指定する場合
 *    【entry.jsp】
 *        &lt;og:tableUpdate
 *            command   = &quot;{&#064;command}&quot;
 *            queryType = &quot;JDBCTableUpdate&quot;
 *            conditionKey  ="…"      : 条件判定するカラムＩＤを指定(初期値は columnId )
 *            conditionList ="…"      : 条件判定する値のリストを、"|"で区切って登録(初期値は、無条件)
 *        {&#064;SQL}
 *        &lt;/og:tableUpdate&gt;
 *
 *    ・JDBCTableUpdate のまま、sqlType="MERGE" を指定する場合。
 *      一つのtableUpdateParamで、両方(UPDATE,INSERT)の処理を実行します。
 *    【entry.jsp】
 *        &lt;og:tableUpdate
 *            command   = "{&#064;command}"
 *            queryType = "JDBCTableUpdate"
 *            &lt;og:tableUpdateParam
 *                sqlType     = "MERGE"                // INSERT or UPDATE
 *                table       = "{&#064;TABLE_NAME}"    // 処理対象のテーブル名
 *                names       = "{&#064;names}"         // 処理対象のカラム名
 *                omitNames   = "{&#064;omitNames}"     // 処理対象外のカラム名
 *                where       = "{&#064;where}"         // 処理対象を特定するキー（INSERT時には使われず、UPDAET時に使われる。）
 *                constKeys   = "{&#064;constKeys}"     // 処理カラム名の中の固定情報カラム名
 *                constVals   = "{&#064;constVals}"     // 処理カラム名の中の固定情報設定値
 *            /&gt;
 *        &lt;/og:tableUpdate&gt;
 *
 * @og.rev 3.8.8.0 (2007/12/22) 新規作成
 * @og.group ＤＢ登録
 *
 * @version  4.0
 * @author   Kazuhiko Hasegawa
 * @since    JDK5.0,
 */
public class TableUpdateTag extends QueryTag {
	/** このプログラムのVERSION文字列を設定します。	{@value} */
	private static final String VERSION = "7.2.9.1 (2020/10/23)" ;
	private static final long serialVersionUID = 729120201023L ;

	/** command 引数に渡す事の出来る コマンド  登録{@value} */
	public static final String CMD_ENTRY  = "ENTRY" ;
	// 6.4.3.4 (2016/03/11) String配列 から、Setに置き換えます。
	private static final Set<String> COMMAND_SET = new ArraySet<>( CMD_ENTRY );

	// 処理を行う、リソースの種類を指定します。(GEA03,GEA04,GEA08 のどれか)
	private String	sqlType			;			// INSERT,COPY,UPDATE,MODIFY,DELETE,MERGE
	private String	resourceType	;
	private int		resTypeColNo	= -1;
	private String	conditionKey	;			// 条件判定するカラムＩＤを指定(初期値は columnId )
	private String	conditionList	;			// 条件判定する値のリストを、"|"で区切って登録(初期値は、無条件) 7.0.1.8 (2019/01/28) 正規表現に変更
	private boolean selectedAll		;
	private boolean commitTableModel= true;		// 4.0.2.0 (2007/12/25)
	private boolean followCdkh		;			// 4.3.2.0 (2008/09/09).
	private boolean	quotCheck		;			// 5.1.7.0 (2010/06/01) quotCheckを指定できるようにする。※但し、初期値はfalse固定。タイミングを見て修正要

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

	/**
	 * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。
	 *
	 * @og.rev 4.0.0.0 (2007/11/14) 0件の場合でもstartQueryTransactionを通すように変更
	 * @og.rev 5.1.7.0 (2010/06/01) quotCheckを指定できるようにする。※但し、初期値はfalse固定。
	 * @og.rev 6.3.4.0 (2015/08/01) caseKey,caseVal,caseNN,caseNull,caseIf 属性対応
	 *
	 * @return	後続処理の指示( EVAL_BODY_BUFFERED )
	 */
	@Override
	public int doStartTag() {
		if( !useTag() ) { return SKIP_BODY ; }	// 6.3.4.0 (2015/08/01)
		dyStart = System.currentTimeMillis();

		table = (DBTableModel)getObject( tableId );
		startQueryTransaction( tableId );		// 4.0.0.0 (2007/11/14) 0件の場合でもdoEndでPAGE_SKIPしないように位置変更。
		if( table == null || table.getRowCount() == 0 ||
			! check( command, COMMAND_SET ) ) { return SKIP_BODY ; }
		super.quotCheck = quotCheck;

		return EVAL_BODY_BUFFERED ;	// Body を評価する。( extends BodyTagSupport 時)
	}

	/**
	 * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。
	 *
	 * @og.rev 4.0.0.0 (2007/10/18) メッセージリソース統合( getResource().getMessage ⇒ getResource().getLabel )
	 * @og.rev 6.3.4.0 (2015/08/01) caseKey,caseVal,caseNN,caseNull,caseIf 属性対応
	 * @og.rev 6.4.1.2 (2016/01/22) QueryTag.errMsgId  → QueryTag.ERR_MSG_ID  refactoring
	 * @og.rev 6.9.9.0 (2018/08/20) ｢ERR0041:検索処理中に割り込みの検索要求がありました｣エラーを、標準のErrorMessageに追加するようにします。
	 * @og.rev 7.0.7.0 (2019/12/13) useSLabel 属性を追加。
	 *
	 * @return	後続処理の指示
	 */
	@Override
	public int doEndTag() {
		debugPrint();
		if( !useTag() ) { return EVAL_PAGE ; }	// 6.3.4.0 (2015/08/01)

		String label  = "";				// 4.0.0 (2005/11/30) 検索しなかった場合。
		if( check( command, COMMAND_SET ) ) {
			final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE );
			if( executeCount > 0 && displayMsg != null && displayMsg.length() > 0 ) {
				buf.append( executeCount )
					.append( getResource().getLabel( displayMsg ) )
					.append( BR );
			}

			// 6.9.9.0 (2018/08/20) ｢ERR0041:検索処理中に割り込みの検索要求がありました｣エラーを、標準のErrorMessageに追加するようにします。
			if( table != null && ! commitTableObject( tableId, table ) ) {
				if( errMessage == null ) { errMessage = new ErrorMessage( "TableUpdateTag Query Error!" ); }
				// ERR0041:検索処理中に割り込みの検索要求がありました。処理されません。
				errMessage.addMessage( 0,ErrorMessage.NG,"ERR0041" );
				errCode = ErrorMessage.NG;
			}

//			final String err = TaglibUtil.makeHTMLErrorTable( errMessage,getResource() );
			final String err = TaglibUtil.makeHTMLErrorTable( errMessage,getResource(),useSLabel );		// 7.0.7.0 (2019/12/13)
			if( err != null && err.length() > 0 ) {
				buf.append( err );
				// 6.4.1.2 (2016/01/22) QueryTag.errMsgId  → QueryTag.ERR_MSG_ID  refactoring
				setSessionAttribute( ERR_MSG_ID,errMessage );
			}
			else {
				// 6.4.1.2 (2016/01/22) QueryTag.errMsgId  → QueryTag.ERR_MSG_ID  refactoring
				removeSessionAttribute( ERR_MSG_ID );
			}
			label = buf.toString();

//			// 6.9.9.0 (2018/08/20) ｢ERR0041:検索処理中に割り込みの検索要求がありました｣エラーを、標準のErrorMessageに追加するようにします。
//			if( table != null && ! commitTableObject( tableId, table )  ) {
//				// 3.6.0.8 (2004/11/19) トランザクションチェックを行います。
//				jspPrint( "TableUpdateTag Query処理が割り込まれました。DBTableModel は登録しません。" );
//				return SKIP_PAGE ;
//			}
		}

		jspPrint( label );

		// セキュリティチェック(データアクセス件数登録)
		final long dyTime = System.currentTimeMillis()-dyStart;
		final GUIInfo guiInfo = (GUIInfo)getSessionAttribute( HybsSystem.GUIINFO_KEY );
		if( guiInfo != null ) { guiInfo.addWriteCount( executeCount,dyTime,sql ); }

		if( useTimeView ) {		// 6.3.6.0 (2015/08/16)
			jspPrint( "<div id=\"queryTime\" value=\"" + (dyTime) + "\"></div>" );	// 3.5.6.3 (2004/07/12)
		}
		return errCode >= ErrorMessage.NG ? SKIP_PAGE : EVAL_PAGE ;
	}

	/**
	 * タグリブオブジェクトをリリースします。
	 * キャッシュされて再利用されるので、フィールドの初期設定を行います。
	 *
	 * @og.rev 4.0.2.0 (2007/12/25) commitTableModel追加
	 * @og.rev 4.1.2.0 (2008/03/12) sqlType追加
	 * @og.rev 5.1.7.0 (2010/06/01) quotCheckを指定できるようにする。※但し、初期値はfalse固定。
	 * @og.rev 7.2.9.1 (2020/10/23) TableUpdateParamTag のマージ(UPDATE,INSERT)対応
	 */
	@Override
	protected void release2() {
		super.release2();
		sqlType			= null;		// INSERT,COPY,UPDATE,MODIFY,DELETE,MERGE
		resourceType	= null;
		resTypeColNo	= -1;
		conditionKey	= null;		// 条件判定するカラムＩＤを指定(初期値は columnId )
		conditionList	= null;		// 条件判定する値のリストを、"|"で区切って登録(初期値は、無条件) 7.0.1.8 (2019/01/28) 正規表現に変更
		selectedAll		= false;
		commitTableModel= true;		// 4.0.2.0 (2007/12/25)
		followCdkh		= false;	// 4.3.2.0 (2008/09/09)
		quotCheck		= false;	// 5.1.7.0 (2010/06/01)
	}

	/**
	 * Query を実行します。
	 *
	 * @og.rev 4.0.2.0 (2007/12/25) commitTableModel追加
	 * @og.rev 6.3.6.1 (2015/08/28) close(),realClose() 廃止。Queryはキャッシュしません。
	 *
	 * @param   query オブジェクト
	 */
	@Override
	protected void execute( final Query query ) {
		final int[] rowNo = getParameterRows();		// 4.0.0 (2005/01/31)
		if( rowNo.length > 0 ) {
			query.execute( rowNo,table );

			errCode = query.getErrorCode();
			errMessage = query.getErrorMessage();

			// リソースクリア処理
			if( resourceType != null ) {
				resTypeColNo = table.getColumnNo( "CLM" );		// キーは、CLM
			}

			// 逆順にDELETEしないと、行番号がずれてしまう。
			int row;
			for( int j=rowNo.length-1; j>=0; j-- ) {
				row = rowNo[j];
				if( resTypeColNo >= 0 ) {
					clearResourceData( table.getValue( row,resTypeColNo ) );		// リソースのクリア
				}

				if( commitTableModel ) {	// 4.0.2.0 (2007/12/25)
					if( DBTableModel.DELETE_TYPE.equals( table.getModifyType( row ) ) ) {
						table.removeValue( row );
					}
					else {
						table.resetModify( row );
					}
				}
			}
		}
	}

	/**
	 * 表示データの HybsSystem.ROW_SEL_KEY を元に、選ばれた 行番号の
	 * 配列を返します。
	 * ここでは、conditionKey に値が設定されている場合は、そのカラムの値が
	 * conditionList にマッチする場合のみ対象選択行として返します。
	 * 値がセットされていない場合は、通常のCommonTagSupport#getParameterRows()
	 * が呼ばれます。
	 * なにも選ばれていない場合は、サイズ０の配列を返します。
	 *
	 * @og.rev 4.3.2.0 (2008/09/09) followCdkh属性対応
	 * @og.rev 7.0.1.8 (2019/01/28) conditionListの判定を、正規表現に変更
	 *
	 * @return	 (選ばれていない場合は、サイズ０の配列を返す)
	 * @og.rtnNotNull
	 */
	@Override
	protected int[] getParameterRows() {
		int[] rowNo ;
		if( selectedAll ) {
			final int rowCnt = table.getRowCount();		// 3.5.5.7 (2004/05/10)
			rowNo = new int[ rowCnt ];
			for( int i=0; i<rowCnt; i++ ) {
				rowNo[i] = i;
			}
		} else {
			rowNo = super.getParameterRows();		// 4.0.0 (2005/01/31)
		}

		// 7.0.1.8 (2019/01/28) conditionListの判定を、正規表現に変更
		if( conditionKey != null && conditionList != null ) {			// 7.0.1.8 (2019/01/28)
			final int col = table.getColumnNo( conditionKey );
			final List<Integer> list = new ArrayList<>();
			final Pattern ptn = Pattern.compile( conditionList );		// 7.0.1.8 (2019/01/28)
			for( int i=0; i<rowNo.length; i++ ) {
				final String val = nval( table.getValue( rowNo[i],col ) , "" );		// 7.0.1.8 (2019/01/28)
				if( ptn.matcher( val ).matches() ) {
					list.add( Integer.valueOf( rowNo[i] ) );
				}
			}

			final int size = list.size();
			rowNo = new int[size];
			for( int i=0; i<size; i++ ) {
				rowNo[i] = list.get(i).intValue();
			}
		}

		// 4.3.2.0 (2008/09/09)
		if( sqlType != null && sqlType.length() > 0 && followCdkh ) {
			final List<Integer> flist = new ArrayList<>();
			for( int i=0; i<rowNo.length; i++ ) {
				final String cdkh = table.getModifyType( rowNo[i] );
				// 6.9.7.0 (2018/05/14) PMD Useless parentheses.
				if( 	( "INSERT".equals( sqlType ) || "COPY".equals(   sqlType ) )	&& DBTableModel.INSERT_TYPE.equals( cdkh )
//					||	( "UPDATE".equals( sqlType ) || "CHANGE".equals( sqlType ) )	&& DBTableModel.UPDATE_TYPE.equals( cdkh )		// 7.2.9.1 (2020/10/23) CHANGE ⇒ MODIFY
					||	( "UPDATE".equals( sqlType ) || "MODIFY".equals( sqlType ) )	&& DBTableModel.UPDATE_TYPE.equals( cdkh )
					||	  "DELETE".equals( sqlType )									&& DBTableModel.DELETE_TYPE.equals( cdkh ) ) {
						flist.add( Integer.valueOf( rowNo[i] ) );
				}
			}

			final int size = flist.size();
			rowNo = new int[size];
			for( int i=0; i<size; i++ ) {
				rowNo[i] = flist.get(i).intValue();
			}
		}

		return rowNo;
	}

//	/**
//	 * BODY部の TableUpdateParamTag に書かれたquery文を受け取ります。
//	 *
//	 * typeには、UPDATEかINSERTが指定され、それに応じたqueryを各変数にセットします。
//	 *
//	 * @og.rev 7.2.9.1 (2020/10/23) TableUpdateParamTag のマージ(UPDATE,INSERT)対応
//	 * @og.rev 7.2.9.3 (2020/11/06) QueryTag に移動
//	 *
//	 * @param	type	Queryタイプ(UPDATE,INSERT,その他)
//	 * @param	query	SQL文
//	 */
//	protected void setQuery( final String type , final String query ) {
//		sql = query;													// とりあえず、セットしておく
//		sqlCnt++ ;														// 0の場合はBODYから、1の場合はそのまま、それ以上の場合は、マージ処理。QueryTag のprotected属性
//
//		if( "UPDATE".equalsIgnoreCase( type ) ) {
//			updQuery = query;											// 上位の QueryTag のprotected属性
//		}
//		else if( "INSERT".equalsIgnoreCase( type ) ) {
//			insQuery = query;											// 上位の QueryTag のprotected属性
//		}
//	}

	/**
	 * 【TAG】Query を発行する為のクラスID(JDBCTableUpdate,JDBCTableMerge)を指定します({@og.doc03Link queryType 初期値:JDBCTableUpdate})。
	 *
	 * @og.tag
	 * 引数指定のUPDATE,INSERT,DELETE文を実行する場合の、queryType 属性を使用します。
	 * このタグでは、execute( int[] ,DBTableModel )を実行します。
	 * 代表的なクラスとして、"JDBCTableUpdate" が標準で用意されています。
	 *
	 * タグにより使用できる／出来ないがありますが、これは、org.opengion.hayabusa.db
	 * 以下の Query_**** クラスの **** を与えます。
	 * これらは、Query インターフェースを継承したサブクラスです。
	 * {@og.doc03Link queryType Query_**** クラス}
	 *
	 * @param	id Queryタイプ
	 * @see		org.opengion.hayabusa.db.Query  Queryのサブクラス
	 * @see		org.opengion.hayabusa.db.Query#execute( int[] ,DBTableModel )
	 */
	@Override
	public void setQueryType( final String id ) {
		super.setQueryType( nval( id,"JDBCTableUpdate" ) );
	}

	/**
	 * resourceType が設定されたときのみ使用される、キャッシュの初期化メソッドです。
	 *
	 * @param	key	初期化を行うキー
	 */
	private void clearResourceData( final String key ) {
		getResource().clear( key );
	}

	/**
	 * 【特殊】クリアするリソースの種類[GEA03/GEA04/GEA08]を指定します。
	 *
	 * @og.tag
	 * 注意：この属性は、リソース関連DBのメンテナンス時にのみ、内部リソースキャッシュを
	 * クリアする目的で使用します。一般の属性としては、使用することはないため、
	 * ご注意ください。
	 * リソース関連のテーブルを更新した場合、リソースキャッシュをクリアして
	 * 置かないと、データベースの値が反映されません。
	 * 昔は、リソースの更新ごとに、全件クリアしていましたが、部分クリアが
	 * できるようになったため、部分クリアを行います。
	 * こでは、(GEA03,GEA04,GEA08) のどれかを指定してください。
	 *
	 * @param	type	クリアリソースタイプ [GEA03/GEA04/GEA08]
	 */
	public void setResourceType( final String type ) {
		resourceType = nval( getRequestParameter(type),resourceType );

		if( resourceType != null &&
			"|GEA03|GEA04|GEA08|".indexOf( "|" + resourceType + "|" ) < 0 ) {
				final String errMsg = "resourceTypeは GEA03,GEA04,GEA08 のどれかです。"
							+ "resourceType=" + type ;
				throw new HybsSystemException( errMsg );
		}
	}

	/**
	 * 【TAG】条件判定するカラムＩＤを指定します(初期値:null)。
	 *
	 * @og.tag
	 * 指定のカラムＩＤの値と、conditionList の値を比較して、
	 * 存在する場合は、Query 処理を実行します。
	 * 例えば、conditionKey="CDKH" として、conditionList="A" とすれば、
	 * 改廃コードが"A"のデータで、かつ選択されたデータのみを処理します。
	 * 設定しない場合は、通常の処理と同様に、選択行のみ処理されます。
	 *
	 * @param	key 条件判定カラム
	 * @see		#setConditionList( String )
	 */
	public void setConditionKey( final String key ) {
		conditionKey = nval( getRequestParameter( key ),null ) ;
	}

	/**
	 * 【TAG】条件判定する値のリストを、"|"で区切って登録します(初期値:無条件)。
	 *
	 * @og.tag
	 * conditionKey とペアで指定します。ここには、カラムの設定値のリストを
	 * 指定することで、複数条件(ＯＲ結合)での比較を行い、リストにカラム値が
	 * 存在する場合のみ、Query 処理を実行します。
	 * 値が設定されている場合は、その値とマッチする必要があります。なにもセット
	 * されない場合、または、null の場合は、null データとマッチする場合のみ処理
	 * されますので、ご注意ください。
	 *
	 * @og.rev 7.0.1.8 (2019/01/28) conditionListの判定を、正規表現に変更
	 *
	 * @param	list	条件判定値 ("|"区切のリスト)
	 * @see		#setConditionKey( String )
	 */
	public void setConditionList( final String list ) {
//		conditionList = "|" + nval( getRequestParameter( list ),"" ) + "|" ;
		conditionList = nval( getRequestParameter( list ),"" ) ;
	}

	/**
	 * 【TAG】データを全件選択済みとして処理するかどうか[true/false]を指定します(初期値:false)。
	 *
	 * @og.tag
	 * 全てのデータを選択済みデータとして扱って処理します。
	 * 全件処理する場合に、(true/false)を指定します。
	 * 初期値は false です。
	 *
	 * @param  all データを全件選択済み [true:全件選択済み/false:通常]
	 */
	public void setSelectedAll( final String all ) {
		selectedAll = nval( getRequestParameter( all ),selectedAll );
	}

	/**
	 * 【特殊】SQL実行後に結果をDBTableModelに反映させるかどうか[true/false]を指定します(初期値:true)。
	 *
	 * @og.tag
	 * 注意：この属性は、リソース関連DBのメンテナンス時に、複数DBへの登録を行うための、
	 * 暫定対応として定義しています。
	 * falseにした場合は、実データとDBTableModelの整合性が取れなくなるため、使用には十分注して下さい。
	 * 初期値は true です。
	 *
	 * @og.rev 4.0.2.0 (2007/12/25) 新規作成
	 *
	 * @param  commitTblMdl 反映有無 [true:反映する/false:反映しない]
	 */
	public void setCommitTableModel( final String commitTblMdl ) {
		commitTableModel = nval( getRequestParameter( commitTblMdl ),commitTableModel );
	}

	/**
	 * 引数の名称配列。
	 *
	 * @return	名称配列
	 */
	protected String[] getNames() {
		return table.getNames() ;
	}

	/**
	 * 【TAG】BODY部に書かれている Param の SQLタイプを指定します。
	 *
	 * @og.tag
	 * TableUpdateParamTag は、上位の TableUpdateTag の sqlType 属性 と同じ
	 * sqlType 属性の場合のみ、SQL文を合成・出力します。
	 * つまり、TableUpdateTag側のsqlType 属性をパラメータに、TableUpdateParamTag
	 * の sqlType 属性を固定値にすることで、どのパラメータを使用するかを
	 * 選択できる機能を実現する事が可能です。
	 *
	 * 7.2.9.3 (2020/11/06)
	 *   複数指定できるようにします。
	 *
	 * @og.rev 4.1.2.0 (2008/03/12) 新規追加
	 *
	 * @param	type SQLタイプ
	 */
	public void setSqlType( final String type ) {
		sqlType = nval( getRequestParameter( type ),sqlType );
	}

	/**
	 * 【TAG】DBTableModelの改廃Cに従って処理を行うかを指定します。
	 *
	 * @og.tag
	 * この属性は、sqlTypeが指定されている場合のみ有効です。
	 * sqlTypeが指定されている場合、そのsqlTypeに対応した、改廃Cが設定されている
	 * 行のみを処理します。
	 * 対応関係は、以下の通りです。
	 *  sqlType = "INSERT" or "COPY" ⇒ 改廃C='A'のみ処理
//	 *  sqlType = "UPDATE" or "CHANGE" ⇒ 改廃C='C'のみ処理
	 *  sqlType = "UPDATE" or "MODIFY" ⇒ 改廃C='C'のみ処理
	 *  sqlType = "DELETE" ⇒ 改廃C='D'のみ処理
	 *
	 * @og.rev 4.3.2.0 (2008/09/09) 新規追加
	 *
	 * @param	flag 改廃C処理 [true:行う/false:行わない]
	 */
	public void setFollowCdkh( final String flag ) {
		followCdkh = nval( getRequestParameter( flag ),followCdkh );
	}

	/**
	 * 【TAG】リクエスト情報の シングルクォート(') 存在チェックを実施するかどうか[true/false]を設定します(初期値:false)。
	 *
	 * @og.tag
	 * ＳＱＬインジェクション対策の一つとして、暫定的ではありますが、SQLのパラメータに
	 * 渡す文字列にシングルクォート(') を許さない設定にすれば、ある程度は防止できます。
	 * 数字タイプの引数には、 or 5=5 などのシングルクォートを使用しないコードを埋めても、
	 * 数字チェックで検出可能です。文字タイプの場合は、必ず (')をはずして、
	 * ' or 'A' like 'A のような形式になる為、(')チェックだけでも有効です。
	 * (') が含まれていたエラーにする(true)／かノーチェックか(false)を指定します。
	 * ※(他のタグは、システムリソースのUSE_SQL_INJECTION_CHECK[={@og.value SystemData#USE_SQL_INJECTION_CHECK}])
	 * ですが、JSPの互換性を考慮し、初期値を固定でfalseにしています)
	 *
	 * @og.rev 5.1.7.0 (2010/06/01) 新規追加
	 *
	 * @param   flag クォートチェック [true:する/それ以外:しない]
	 */
	@Override
	public void setQuotCheck( final String flag ) {
		quotCheck = nval( getRequestParameter( flag ),quotCheck );
	}

	/**
	 * SQLタイプを返します。
	 *
	 * @og.rev 4.1.2.0 (2008/03/12) 新規追加
	 *
	 * @return	SQLタイプ
	 */
	protected String getSqlType() {
		return sqlType ;
	}

	/**
	 * このオブジェクトの文字列表現を返します。
	 * 基本的にデバッグ目的に使用します。
	 *
	 * @og.rev 4.0.2.0 (2007/12/25) resourceColumn、commitTableModel追加
	 *
	 * @return このクラスの文字列表現
	 * @og.rtnNotNull
	 */
	@Override
	public String toString() {
		return ToString.title( this.getClass().getName() )
				.println( "VERSION"			,VERSION		)
				.println( "resourceType"	,resourceType	)
				.println( "resTypeColNo"	,resTypeColNo	)
				.println( "conditionKey"	,conditionKey	)
				.println( "conditionList"	,conditionList	)
				.println( "followCdkh"		,followCdkh		)
				.println( "CMD_ENTRY"		,CMD_ENTRY		)
				.println( "commitTabelModel",commitTableModel )		// 4.0.2.0 (2007/12/25)
				.println( "sql"				,sql			)		// 4.1.2.0 (2008/03/12)
				.println( "Other..."	,getAttributes().getAttribute() )
				.fixForm().toString()
			+ CR
			+ super.toString() ;
	}
}
