/*
 * 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.db.DBColumn;
import org.opengion.hayabusa.db.DBTableModel;
import org.opengion.fukurou.util.Attributes;
import org.opengion.fukurou.util.ErrorMessage;
import org.opengion.fukurou.util.ToString;						// 6.1.1.0 (2015/01/17)
import org.opengion.fukurou.model.ArrayDataModel;
import org.opengion.fukurou.model.Formatter;
import org.opengion.fukurou.util.StringUtil ;					// 6.2.0.0 (2015/02/27)

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

import java.util.List;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Locale ;

import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.IOException;

/**
 * 検索結果の DBTableModelオブジェクトに値を設定するタグです。
 *
 * columnSet と共に使用する場合は、entryタグ の command属性と、columnSetタグ の command属性が
 * 一致した場合のみ、処理されます。
 * entryタグは、そのコマンドにより、DBTableModelオブジェクトの値を設定します。
 * たとえば、command="INSERT" ならば、１行分のデータを選択された行番号の次に挿入します。
 * また、追加、変更、削除された、DBTableModelオブジェクト でも、内部には元のデータを
 * 持っているため、command="RESET" で元の状態に戻すことが可能です。
 *
 * @og.formSample
 * ●形式：
 *       ・&lt;og:entry command="…"&gt;
 *             &lt;og:columnSet command="…" /&gt;
 *         &lt;/og:entry&gt;
 *       ・&lt;og:entry command="…" /&gt;
 *             ･･･columnSetを使わない場合でもresult.jspから次画面(insert,modify,copy.jsp等)に
 *                にDBTableModelをもっていく場合には、必ず２を書いてください。
 *                (取消のとき、エンジン内でDBTableModelを操作するのに使用する為)
 * ●body：あり(EVAL_BODY_BUFFERED:BODYを評価し、{&#064;XXXX} を解析します)
 *
 * ●Tag定義：
 *   &lt;og:entry
 *       command          ○【TAG】コマンド (INSERT/COPY/MODIFY/DELETE/ENTRY/CHANGE/RESET/ALLRESET/ALLACTION/RESETDATA/INSERTONE/REALDELETE/REQENTRY)を設定します(必須)
 *       scope              【TAG】キャッシュする場合のスコープ[request/page/session/applicaton]を指定します(初期値:session)
 *       repeatCount        【TAG】指定の回数分だけ、繰り返し処理を行う回数を指定します(初期値:1)
 *       tableId            【TAG】(通常使いません)sessionから所得する DBTableModelオブジェクトの ID
 *       useConsistency     【TAG】Consistency キー による整合性チェックを行うかどうかを指定します(初期値:true)
 *       selectedAll        【TAG】データを全件選択済みとして処理するかどうか[true/false]を指定します(初期値:false)
 *       strictCheck        【TAG】カラムＩＤの存在チェックを行うかどうか[true/false]を指定します(初期値:true)
 *       noTransition       【TAG】(通常は使いません)画面遷移を行わない形式の登録方法を使用するかを指定します
 *       debug              【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false)
 *   &gt;   ... Body ...
 *   &lt;/og:entry&gt;
 *
 * ●使用例
 *    &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;
 *
 *    action="ADD" は、DBTypeに依存した方法で、既存の値を、＋１ します。
 *    &lt;og:entry command="{&#064;command}" repeatCount="5" &gt;
 *        &lt;og:columnSet  command="{&#064;command}" columnId="YKNO" action="ADD" /&gt;
 *    &lt;/og:entry&gt;
 *
 *    action="ADD" は、DBTypeに依存した方法で、既存の値に、value の値を加算します。
 *    &lt;og:entry command="{&#064;command}" repeatCount="5" &gt;
 *        &lt;og:columnSet  command="{&#064;command}" columnId="YKNO" action="ADD" value="5" /&gt;
 *    &lt;/og:entry&gt;
 *
 *    command属性 は、columnSetタグのcommand属性と同一の場合のみ、処理します。
 *    [command属性]
 *      INSERT     新規
 *      COPY       複写
 *      MODIFY     変更
 *      DELETE     削除
 *      ENTRY      エントリー
 *      CHANGE     チェンジ
 *      RESET      リセット
 *      ALLRESET   全件リセット
 *      ALLACTION  オールアクション
 *      RESETDATA  リセットデータ
 *      INSERTONE  新規(1行のみ)
 *      REALDELETE 物理削除
 *      REQENTRY   リクエスト変数設定
 *
 *    command属性 は、columnSetタグで指定します。
 *    [action属性]
 *      DEFAULT カラムリソースで定義した初期値をセットします。
 *      CLEAR   値をクリア(ゼロストリング &quot;&quot; )します。
 *      ADD     現在の値を ＋１ します。  0 ⇒ 1 , A ⇒ B , 9 ⇒ 10。value属性と併用すれば、指定の値を加算できます。
 *      SET     value で設定した値を 新しい値として登録します。
 *      NULLSET 元の値が NULL の場合だけ、value で設定した新しい値を登録します。
 *      LOWER   小文字に変換します。
 *      UPPER   大文字に変換します。
 *      COPY    value にコピー元のカラムIDをセットすれば、その値を代入します。
 *      TBLSET  DBTableModel の内容を取り込んで指定の columnId カラムに設定します。[カラム名] で指定できます。
 *              また、これは文字列を解析して、 value を作成しますので,文字列連結等に使用できます。
 *      WRTCTRL writableControl を使用したカラムデータの先頭アンダーバーを削除します。
 *      DBMENU  DBMENUでパラメータ設定(コロン連結文字)を使用したカラムデータの先頭データのみにします。
 *      REQSET  valueで指定したカラムの値をキーに、リクエスト変数から値を取出し、セットします。
 *      SEQSET  valueの初期値を利用して、１レコードごとに、＋１した値をセットします。
 *      PREFIX  valueの値を後ろから検索し、指定のカラム値の前半部分を取得します(記号は含みません)。
 *      SUFIX   valueの値を後ろから検索し、指定のカラム値の後半部分を取得します(記号は含みません)。
 *      その他  カラムのDBType の valueAction メソッドを呼び出します。自由に設定可能です。
 *
 *    [strictCheck属性]は、カラムＩＤの存在チェックを行うかどうかを指定します(初期値:true)
 *      true    カラムＩＤがDBTableModel に存在しない場合は、エラーになる。
 *      false   カラムＩＤがDBTableModel に存在しない場合は、無視する。
 *
 * @og.group 画面登録
 *
 * @version  4.0
 * @author	 Kazuhiko Hasegawa
 * @since    JDK5.0,
 */
public class EntryTag extends CommonTagSupport {
	//* このプログラムのVERSION文字列を設定します。	{@value} */
	private static final String VERSION = "5.7.8.0 (2014/07/04)" ;

	private static final long serialVersionUID = 578020140704L ;

	/** command 引数に渡す事の出来る コマンド  新規 {@value} */
	public static final String CMD_INSERT	= "INSERT" ;
	/** command 引数に渡す事の出来る コマンド  複写 {@value} */
	public static final String CMD_COPY		= "COPY" ;
	/** command 引数に渡す事の出来る コマンド  変更 {@value} */
	public static final String CMD_MODIFY	= "MODIFY" ;
	/** command 引数に渡す事の出来る コマンド  削除 {@value} */
	public static final String CMD_DELETE	= "DELETE" ;
	/** command 引数に渡す事の出来る コマンド  エントリー {@value} */
	public static final String CMD_ENTRY	= "ENTRY" ;
	/** command 引数に渡す事の出来る コマンド  チェンジ {@value} */
	public static final String CMD_CHANGE	= "CHANGE" ;
	/** command 引数に渡す事の出来る コマンド  リセット {@value} */
	public static final String CMD_RESET	= "RESET" ;
	/** command 引数に渡す事の出来る コマンド  全件リセット {@value} */
	public static final String CMD_ALLRESET		= "ALLRESET" ;	// 3.5.6.3 (2004/07/12)
	/** command 引数に渡す事の出来る コマンド  オールアクション{@value} */
	public static final String CMD_ALLACTION	= "ALLACTION" ;
	/** command 引数に渡す事の出来る コマンド  リセット(データのみ){@value} */
	public static final String CMD_RESETDATA	= "RESETDATA" ;		// 4.3.3.0 (2008/10/01)
	/** command 引数に渡す事の出来る コマンド  追加(1行のみ){@value} */
	public static final String CMD_INSERTONE	= "INSERTONE" ;		// 5.1.5.0 (2010/04/01)
	/** command 引数に渡す事の出来る コマンド  物理削除 {@value} */
	public static final String CMD_REALDELETE	= "REALDELETE" ;		// 5.1.6.0 (2010/05/01)
	/** command 引数に渡す事の出来る コマンド  リクエスト変数設定 {@value} */
	public static final String CMD_REQENTRY		= "REQENTRY" ;			// 5.6.1.2 (2013/02/22)

	// 3.5.6.3 (2004/07/12) CMD_ALLRESET	追加
	// 4.3.3.0 (2008/10/01) CMD_RESETDATA	追加
	// 5.1.5.0 (2010/04/01) CMD_INESRTONE	追加
	// 5.1.6.0 (2010/05/01) CMD_REALDELETE	追加
	private static final String[] COMMAND_LIST = new String[] {
		CMD_INSERT,CMD_COPY,CMD_MODIFY,CMD_DELETE,CMD_ENTRY,CMD_CHANGE,CMD_ALLACTION,CMD_RESET,CMD_ALLRESET,CMD_RESETDATA,CMD_INSERTONE,CMD_REALDELETE,CMD_REQENTRY };

	/** action 引数に渡す事の出来る アクションコマンド  初期値:{@value} */
	public static final String ACT_DEFAULT  = "DEFAULT" ;
	/** action 引数に渡す事の出来る アクションコマンド  クリア {@value} */
	public static final String ACT_CLEAR    = "CLEAR" ;
	/** action 引数に渡す事の出来る アクションコマンド  ＋１ {@value} */
	public static final String ACT_ADD      = "ADD" ;
	/** action 引数に渡す事の出来る アクションコマンド  小文字化{@value} */
	public static final String ACT_LOWER    = "LOWER" ;
	/** action 引数に渡す事の出来る アクションコマンド  大文字化{@value} */
	public static final String ACT_UPPER    = "UPPER" ;
	/** action 引数に渡す事の出来る アクションコマンド  コピー {@value} */
	public static final String ACT_COPY     = "COPY" ;
	/** action 引数に渡す事の出来る アクションコマンド  セット {@value} */
	public static final String ACT_SET      = "SET" ;
	// 3.4.0.3 (2003/09/10) NULLSET Action を追加します。
	/** action 引数に渡す事の出来る アクションコマンド  NULLセット {@value} */
	public static final String ACT_NULLSET  = "NULLSET" ;
	/** action 引数に渡す事の出来る アクションコマンド  テーブルセット {@value} */
	public static final String ACT_TBLSET   = "TBLSET" ;
	/** action 引数に渡す事の出来る アクションコマンド  ライトコントロール {@value} */
	public static final String ACT_WRTCTRL  = "WRTCTRL" ;		// 3.8.1.5 (2006/03/30)
	/** action 引数に渡す事の出来る アクションコマンド  DBメニュー {@value} */
	public static final String ACT_DBMENU  = "DBMENU" ;		// 3.8.5.3 (2006/08/07)
	/** action 引数に渡す事の出来る アクションコマンド  リクエスト値セット {@value} */
	public static final String ACT_REQSET  = "REQSET" ;		// 5.4.2.1 (2011/12/09)
	/** action 引数に渡す事の出来る アクションコマンド  連番値セット {@value} */
	public static final String ACT_SEQSET  = "SEQSET" ;		// 5.6.5.2 (2013/06/21)
	/** action 引数に渡す事の出来る アクションコマンド  PREFIX値セット {@value} */
	public static final String ACT_PREFIX  = "PREFIX" ;		// 5.6.6.1 (2013/07/12)
	/** action 引数に渡す事の出来る アクションコマンド  SUFIX値セット {@value} */
	public static final String ACT_SUFIX   = "SUFIX" ;		// 5.6.6.1 (2013/07/12)

	// 3.5.6.0 (2004/06/18) すべてを protected から private に変更します。
	private String				tableId		= HybsSystem.TBL_MDL_KEY;
	private transient DBTableModel	table 	;
	private String				command		;
	private int[]				rowNo      	;
	private List<Attributes>	values		;

	// 3.5.4.2 (2003/12/15) 指定の回数繰り返す機能を追加します。
	private int				repeatCount	= 1;

	// 3.5.5.7 (2004/05/10) Consistency キー による整合性チェックを行うかどうかを指定します。
	private boolean			useConsistency	= HybsSystem.sysBool( "USE_CONSISTENCY" );

	// 3.8.1.1 (2005/11/21) 全件選択されたこととして、処理します。
	private boolean selectedAll	;

	// 3.5.6.4 (2004/07/16) RESET コマンドのデフォルト処理 に、ALLRESET を
	// 使用するかどうかを指定します(初期値:false(使用しない))。
	private final boolean RESET_ACTION_ALL_USE = HybsSystem.sysBool( "RESET_ACTION_ALL_USE" );

	// 4.0.0 (2006/09/31) カラムＩＤの存在チェックを行うかどうかを指定します。
	private boolean strictCheck	= true;

	private boolean noTransition;		// 4.3.3.0 (2008/10/01) 追加

	// 5.6.5.2 (2013/06/21) SEQSET アクションのカウンター
	private int seqsetCnt	;

	/**
	 * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。
	 *
	 * @og.rev 5.1.9.0 (2010/08/01) 戻り値を、EVAL_BODY_INCLUDE → EVAL_BODY_BUFFERED に変更
	 *
	 * @return	後続処理の指示
	 */
	@Override
	public int doStartTag() {
		int rtn = EVAL_BODY_BUFFERED;		// 5.1.9.0 (2010/08/01) 変更

		if( ! check( command, COMMAND_LIST ) ) {
			rtn = SKIP_BODY;
		}

		return rtn;
	}

	/**
	 * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。
	 *
	 * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。
	 * @og.rev 3.5.5.5 (2004/04/23) 登録時の 整合性パラメータチェックを行います。
	 * @og.rev 3.5.5.6 (2004/04/27) JSP画面の作成不具合。ENTRY系で、command を投げた場合は、無視します。
	 * @og.rev 3.5.5.7 (2004/05/10) Consistency キー による整合性チェックを行うかどうかを指定します。
	 * @og.rev 3.5.5.8 (2004/05/20) Consistency キー による整合性チェックを checkConsistency() に集約します。
	 * @og.rev 3.6.0.8 (2004/11/19) DBTableModel をセーブする時に、トランザクションチェックを行います。
	 * @og.rev 4.3.3.0 (2008/10/01) noTransition 属性を追加します。
	 * @og.rev 4.3.8.0 (2009/08/01) noTransition値取得のメソッド名変更
	 * @og.rev 5.1.3.0 (2010/02/01) noTransitionのコントロールは、requestで行う。
	 *
	 * @return	後続処理の指示
	 */
	@Override
	public int doEndTag() {
		debugPrint();		// 4.0.0 (2005/02/28)
		// noTransition = isNoTransitionRequest() || noTransition; // 4.3.3.0 (2008/10/01) 追加
		noTransition = isNoTransitionRequest(); // 5.1.3.0 (2010/02/01)
		startQueryTransaction( tableId );		// 3.6.0.8 (2004/11/19)
		table = (DBTableModel)getObject( tableId );

		if( table != null && check( command, COMMAND_LIST ) ) {
			if( ! checkConsistency() ) { return SKIP_PAGE ; }
			if( rowNo == null ) { rowNo = getParameterRows(); }		// 4.0.0 (2005/01/31)

			commandExec( command );

			// 3.6.0.8 (2004/11/19) トランザクションチェックを行います。
			if( ! commitTableObject( tableId, table ) ) {
				jspPrint( "EntryTag Query処理が割り込まれました。DBTableModel は登録しません。" );
				return SKIP_PAGE;
			}
		}

		return 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.5.4.2 (2003/12/15) 指定の回数繰り返す機能を追加します。
	 * @og.rev 3.5.5.7 (2004/05/10) Consistency キー による整合性チェックを行うかどうかを指定します。
	 * @og.rev 3.8.1.1 (2005/11/21) selectedAll 追加。全件選択されたこととして、処理します。
	 * @og.rev 4.0.0.0 (2006/09/31) strictCheck 追加。
	 * @og.rev 4.3.3.0 (2008/10/01) noTransition 属性を追加します。
	 * @og.rev 5.6.5.2 (2013/06/21) seqsetCnt 属性を追加します。
	 *
	 */
	@Override
	protected void release2() {
		super.release2();
		tableId		= HybsSystem.TBL_MDL_KEY;
		table 		= null;
		command		= null;
		rowNo      	= null;
		values		= null;
		repeatCount	= 1;			// 3.5.4.2 (2003/12/15)
		useConsistency	= HybsSystem.sysBool( "USE_CONSISTENCY" );		// 3.5.5.7 (2004/05/10)
		selectedAll = false;		// 3.8.1.1 (2005/11/21)
		strictCheck = true;			// 4.0.0 (2006/09/31)
		noTransition= false;		// 4.3.3.0 (2008/10/01) 追加
		seqsetCnt	= 0;			// 5.6.5.2 (2013/06/21) SEQSET アクションのカウンター
	}

	/**
	 * 内部タグの ColumnSetTag より、個々のカラムの値を書き換える為の属性を指定します。
	 *
	 * 複数の値を受け取って、後ほど、すべてのカラムに対して処理を行います。
	 *
	 * @og.rev 3.1.0.0 (2003/03/20) Vector を使用している箇所で、非同期でも構わない箇所を、ArrayList に置換え。
	 * @og.rev 3.1.2.0 (2003/04/07) taglib パッケージ内部で使用している箇所を protected 化する。
	 *
	 * @param   attri	属性リスト
	 */
	protected void setAttributes( final Attributes attri ) {
		if( values == null ) { values = new ArrayList<Attributes>(); }
		if( command.equalsIgnoreCase( attri.get( "command" ) ) ) {
			values.add( attri );
		}
	}

	/**
	 * 【TAG】(通常は使いません)結果のDBTableModelを、sessionに登録するときのキーを指定します
	 *		(初期値:HybsSystem#TBL_MDL_KEY[={@og.value org.opengion.hayabusa.common.HybsSystem#TBL_MDL_KEY}])。
	 *
	 * @og.tag
	 * 検索結果より、DBTableModelオブジェクトを作成します。これを、下流のviewタグ等に
	 * 渡す場合に、通常は、session を利用します。その場合の登録キーです。
	 * query タグを同時に実行して、結果を求める場合、同一メモリに配置される為、
	 * この tableId 属性を利用して、メモリ空間を分けます。
	 *		(初期値:HybsSystem#TBL_MDL_KEY[={@og.value org.opengion.hayabusa.common.HybsSystem#TBL_MDL_KEY}])。
	 *
	 * @param	id テーブルID (sessionに登録する時のID)
	 */
	public void setTableId( final String id ) {
		tableId   = nval( getRequestParameter( id ),tableId );	// 3.8.0.9 (2005/10/17)
	}

	/**
	 * 【TAG】コマンド (INSERT,COPY,MODIFY,DELETE,ENTRY,CHANGE,ALLACTION,RESET)をセットします。
	 *
	 * @og.tag
	 * コマンドは,HTMLから(get/post)指定されますので,CMD_xxx で設定される
	 * フィールド定数値のいづれかを、指定できます。
	 *
	 * @param	cmd コマンド (public static final 宣言されている文字列)
	 * @see		<a href="../../../../constant-values.html#org.opengion.hayabusa.taglib.EntryTag.CMD_INSERT">コマンド定数</a>
	 */
	public void setCommand( final String cmd ) {
		final String cmd2 = getRequestParameter( cmd );
		if( cmd2 != null && cmd2.length() > 0 ) { command = cmd2.toUpperCase(Locale.JAPAN); }
	}

	/**
	 * コマンドを実行します。
	 *
	 * コマンドは,HTMLから(get/post)指定されますので,setCommand()メソッドで
	 * 登録します。
	 * コマンドを登録すると同時に,実行も行ないます。
	 *
	 * @og.rev 3.5.6.3 (2004/07/12) ALLRESET コマンドを追加する。
	 * @og.rev 4.3.3.0 (2008/10/01) RESETDATA コマンドを追加する。
	 * @og.rev 5.1.5.0 (2010/04/01) INSERTONE コマンドを追加する。
	 * @og.rev 5.1.6.0 (2010/05/01) REALDELETE コマンドを追加する。
	 * @og.rev 5.6.1.2 (2013/02/22) REQENTRY コマンドを追加する。
	 *
	 * @param   command コマンド (public static final 宣言されている文字列)
	 */
	private void commandExec( final String command ) {

		table.setDefaultRowWritable( false );
		table.setDefaultRowChecked(  false );

		if( CMD_INSERT.equals(      command ) ) { insert() ; }
		else if( CMD_COPY.equals(   command ) ) { copy()   ; }
		else if( CMD_MODIFY.equals( command ) ) { modify() ; }
		else if( CMD_CHANGE.equals( command ) ) { change() ; }
		else if( CMD_DELETE.equals( command ) ) { delete() ; }
		else if( CMD_ENTRY.equals(  command ) ) { entry()  ; }
		else if( CMD_RESET.equals(  command ) ) {
				if( RESET_ACTION_ALL_USE )		{ allReset() ; }	// 3.5.6.4 (2004/07/16)
				else 							{ reset()    ; }
		}
		else if( CMD_ALLRESET.equals(    command ) ) { allReset()  ; }	// 3.5.6.3 (2004/07/12)
		else if( CMD_ALLACTION.equals(   command ) ) { allAction() ; }
		else if( CMD_RESETDATA.equals(   command ) ) { resetData() ; }	// 4.3.3.0 (2008/10/01)
		else if( CMD_INSERTONE.equals(   command ) ) { insertOne() ; }	// 5.1.5.0 (2010/04/01)
		else if( CMD_REALDELETE.equals(  command ) ) { realDelete() ; }	// 5.1.6.0 (2010/05/01)
		else if( CMD_REQENTRY.equals(    command ) ) { reqEntry()  ; }	// 5.6.1.2 (2013/02/22)
	}

	/**
	 * DBTableModelに行を追加します。
	 *
	 * 注意：writableカラムの暫定対応が入っています。単純な空白データを
	 * インサートすると、カラムデータが null になる為､ 制御がおかしく
	 * なります。
	 *
	 * @og.rev 3.5.4.2 (2003/12/15) repeatCount による繰り返し処理を追加
	 * @og.rev 4.3.3.0 (2008/10/01) noTransition 属性対応
	 *
	 */
	private void insert() {
		if( rowNo.length == 0 ) { rowNo = new int[] { -1 }; }

		final boolean rowWritableFlag = "WRITABLE".equalsIgnoreCase( table.getColumnName( 0 ) );	// writable 対策
		// src の作成は、各チェック毎に行う必要はない。最初の一度だけでよい。
		String[] src = new String[ table.getColumnCount() ];
		for( int j=0; j<src.length; j++ ) {
			final DBColumn dbColumn = table.getDBColumn( j );
			src[j] = dbColumn.getDefault();
		}
		if( rowWritableFlag ) { src[0] = "true"; }	// writable 対策

		final int rowCount = table.getRowCount();

		// 逆順にINSERTしないと、行番号がずれてしまう。
		for( int i=rowNo.length-1; i>=0; i-- ) {
			int row = rowNo[i];
			for( int cnt=0; cnt<repeatCount; cnt++ ) {
				if( cnt >= 1 ) {		// ２回目以降
					src = table.getValues( row );
				}

				String[] dst = new String[ table.getColumnCount() ];
				System.arraycopy( src,0,dst,0,dst.length );
				dst = setColumnValues( dst );

				// 4.3.3.0 (2008/10/01) noTransition属性対応
				if( noTransition ) { row = rowCount; }
				else { row ++; }					// 指定行の下に追加する。
				table.addValues( dst,row );
				table.setRowWritable( row,true );
				table.setRowChecked(  row,true );
			}
		}
	}

	/**
	 * DBTableModelに行を追加し、チェックされた行の値をセットします。
	 *
	 * @og.rev 3.5.4.2 (2003/12/15) repeatCount による繰り返し処理を追加
	 * @og.rev 4.3.3.0 (2008/10/01) noTransition 属性対応
	 *
	 */
	private void copy() {
		if( rowNo.length == 0 ) { insert() ; return ;}

		final int rowCount = table.getRowCount();

		// 逆順にCOPYしないと、行番号がずれてしまう。
		for( int i=rowNo.length-1; i>=0; i-- ) {
			for( int cnt=0; cnt<repeatCount; cnt++ ) {
				final String[] src = table.getValues( rowNo[i]+cnt );
				String[] dst = new String[ table.getColumnCount() ];
				System.arraycopy( src,0,dst,0,dst.length );
				dst = setColumnValues( dst );

				// 4.3.3.0 (2008/10/01) noTransition属性対応
				int row = -1;
				if( noTransition ) { row = rowCount; }
				else { row = rowNo[i] + cnt + 1; }			// 指定行の下に追加する。

				table.addValues( dst,row );
				table.setRowWritable( row,true );
				table.setRowChecked(  row,true );
			}
		}
	}

	/**
	 * DBTableModelの行を書込み可とます。
	 *
	 * @og.rev 4.3.4.6 (2009/01/15) 画面遷移なし登録で既に改廃Cがセットされている場合は、columnSetタグの処理を行わない。
	 *
	 */
	private void modify() {
		for( int i=0; i<rowNo.length; i++ ) {
			final String[] src = table.getValues( rowNo[i] );
			String[] dst = new String[ table.getColumnCount() ];
			System.arraycopy( src,0,dst,0,dst.length );

			// 4.3.4.6 (2009/01/15)
			// 画面遷移なし登録の場合、既に改廃Cが付いている(編集されている)場合は、
			// columnSetによる値のセットを行わない。
			// (同じコマンドで複数のボタンを割り当てている場合、複数回の変更・削除によって、先に登録された
			// 値が削除されてしまうため。
			if( !( noTransition && table.getModifyType( rowNo[i] ) != null && table.getModifyType( rowNo[i] ).length() > 0 ) ){
				dst = setColumnValues( dst );
			}

			table.setValues( dst,rowNo[i] );
			table.setRowWritable( rowNo[i],true );
			table.setRowChecked(  rowNo[i],true );
		}
	}

	/**
	 * DBTableModelの行を変更します。

	 * @og.rev 4.3.4.6 (2009/01/15) 画面遷移なし登録で既に改廃Cがセットされている場合は、columnSetタグの処理を行わない。
	 *
	 */
	private void change() {
		for( int i=0; i<rowNo.length; i++ ) {
			final String[] src = table.getValues( rowNo[i] );
			String[] dst = new String[ table.getColumnCount() ];
			System.arraycopy( src,0,dst,0,dst.length );

			// 4.3.4.6 (2009/01/15)
			if( !( noTransition && table.getModifyType( rowNo[i] ) != null && table.getModifyType( rowNo[i] ).length() > 0 ) ){
				dst = setColumnValues( dst );
			}

			table.setValues( dst,rowNo[i] );
		}
	}

	/**
	 * DBTableModelの行を削除します。
	 *
	 * @og.rev 3.5.4.2 (2003/12/15) DELETE時にも値の書き換えができるようにします。
	 * @og.rev 4.3.4.6 (2009/01/15) 画面遷移なし登録で既に改廃Cがセットされている場合は、columnSetタグの処理を行わない。
	 *
	 */
	private void delete() {
		for( int i=0; i<rowNo.length; i++ ) {
			// 3.5.4.2 (2003/12/15) 書き換え処理を追加
			final String[] src = table.getValues( rowNo[i] );
			String[] dst = new String[ table.getColumnCount() ];
			System.arraycopy( src,0,dst,0,dst.length );

			// 4.3.4.6 (2009/01/15)
			if( !( noTransition && table.getModifyType( rowNo[i] ) != null && table.getModifyType( rowNo[i] ).length() > 0 ) ){
				dst = setColumnValues( dst );
			}

			table.rowDelete( dst,rowNo[i] );
			table.setRowWritable( rowNo[i],true );
			table.setRowChecked( rowNo[i],true );
		}
	}

	/**
	 * リクエスト情報から、セットされたカラム名と値を取り出し、設定します。
	 *
	 * 設定値は、個々のキー＋"__" ＋ 行番号 です。
	 * よって、値は,一つだけ設定されています。
	 *
	 * @og.rev 3.5.3.1 (2003/10/31) チェックボックスカラムを指定します。
	 * @og.rev 3.6.0.6 (2004/10/22) chboxNames 属性は廃止します。
	 * @og.rev 5.6.1.2 (2013/02/22) setRequestValuesメソッドの互換性の対応。
	 */
	private void entry() {
		if( rowNo.length > 0 ) {
			setRequestValues( false );		// 5.6.1.2 (2013/02/22) 互換性
			for( int i=0; i<rowNo.length; i++ ) {
				final String[] src = table.getValues( rowNo[i] );
				String[] dst = new String[ table.getColumnCount() ];
				System.arraycopy( src,0,dst,0,dst.length );
				dst = setColumnValues( dst );

				table.setValues( dst,rowNo[i] );
				table.setRowWritable( rowNo[i],true );
				table.setRowChecked(  rowNo[i],true );
			}
		}
	}

	/**
	 * リクエスト情報のテーブルモデルデータを、リセットします。
	 *
	 * @og.rev 5.6.5.2 (2013/06/21) 行ループを 0～最終行の 降順で廻します。
	 */
	private void reset() {
		for( int i=rowNo.length-1; i>=0; i-- ) {
			table.resetRow( rowNo[i] );
		}
	}

	/**
	 * テーブルモデルデータを、全件リセットします。
	 *
	 * @og.rev 3.5.6.3 (2004/07/12) 新規作成
	 * @og.rev 5.6.5.2 (2013/06/21) 行ループを 0～最終行の 降順で廻します。
	 */
	private void allReset() {
		final int rowCount = table.getRowCount();
		for( int row=0; row<rowCount; row++ ) {
			table.resetRow( row );
		}
	}

	/**
	 * DBTableModelの全ての行に対して,値をセットします。
	 *
	 * @og.rev 5.6.5.2 (2013/06/21) 行ループを 0～最終行の 降順で廻します。
	 */
	private void allAction() {
		final int rowCount = table.getRowCount();
		for( int row=0; row<rowCount; row++ ) {
			final String[] src = table.getValues( row );
			String[] dst = new String[ table.getColumnCount() ];
			System.arraycopy( src,0,dst,0,dst.length );
			dst = setColumnValues( dst );

			table.setValues( dst,row );
			table.setRowWritable( row,true );
			table.setRowChecked(  row,true );
		}
	}

	/**
	 * リクエスト情報のテーブルモデルデータを、リセットします。
	 * (但し、リセットされた行は、チェックされた状態のままになります)
	 *
	 * @og.rev 4.3.3.0 (2008/10/01) 新規作成
	 * @og.rev 5.6.5.2 (2013/06/21) 行ループを 0～最終行の 降順で廻します。
	 */
	private void resetData() {
		for( int i=0; i<rowNo.length; i++ ) {
			final String cdkh = table.getModifyType( rowNo[i] );
			table.resetRow( rowNo[i] );
			// 更新又は、削除の時のみ書き込み可能になる。
			if( DBTableModel.UPDATE_TYPE.equals( cdkh ) || DBTableModel.DELETE_TYPE.equals( cdkh ) ) {
				table.setRowWritable( rowNo[i],true );
				table.setRowChecked(  rowNo[i],true );
			}
		}
	}

	/**
	 * DBTableModelに行を追加します。(1行のみ)
	 *
	 * 行が選択されているかどうかに関わらず、1行のみを追加します。
	 * (動きとしては、行が選択されていない状態でINSERTコマンドを発行した場合と同じです)
	 *
	 * @og.rev 5.1.5.0 (2010/04/01) 新規作成
	 *
	 */
	private void insertOne() {
		rowNo = new int[0];
		insert();
	}

	/**
	 * DBTableModelの行を物理削除します。
	 *
	 * 通常のデータベース等で削除する場合は、DELETE行も残しておかないと、どの行を削除するか
	 * 判らなくなります。また、アプリケーションによっては、削除ではなく、フラグだけを立てる
	 * ケースもあるため、現在の commend="DELETE" では、論理削除＋値の書き換えも可能になっています。
	 * ここでの物理削除は、WriteTable など、ファイル出力時には、その行そのものをなくしておくほうが
	 * 良いケースがあるためです。
	 *
	 * @og.rev 5.1.6.0 (2010/05/01) REALDELETE コマンドを追加する。
	 */
	private void realDelete() {
		// 逆順にしないと、行番号がずれてしまう。
		for( int i=rowNo.length-1; i>=0; i-- ) {
			table.removeValue( rowNo[i] );
		}
	}

	/**
	 * リクエスト情報から、セットされたカラム名と値を取り出し、設定します。
	 *
	 * 設定値は、個々のキー＋"__" ＋ 行番号 です。
	 * ENTRYコマンドとの違いは、h_rowSel と無関係に、リクエストされた変数すべてを
	 * 処理します。
	 *
	 * @og.rev 5.6.1.2 (2013/02/22) 新規追加
	 */
	private void reqEntry() {
		setRequestValues( true );	// リクエストされた変数すべてを処理
		final int rowCount = table.getRowCount();
		for( int row=0; row<rowCount; row++ ) {
			final String[] src = table.getValues( row );
			String[] dst = new String[ table.getColumnCount() ];
			System.arraycopy( src,0,dst,0,dst.length );
			dst = setColumnValues( dst );

			table.setValues( dst,row );
			table.setRowWritable( row,true );
			table.setRowChecked(  row,true );
		}
	}

	/**
	 * リクエスト情報から、セットされたカラム名と値を取り出し、設定します。
	 *
	 * 設定値は、個々のキー＋"__" ＋ 行番号 です。
	 * よって、値は,一つだけ設定されています。
	 * 引数のフラグは、選択行番号に関係なく、全件処理するかどうか[true:する/false:しない]を指定できます。
	 *
	 * @og.rev 3.1.0.0 (2003/03/20) 名前と行番号の区切り記号を "^" から "__" に変更。
	 * @og.rev 3.5.5.0 (2004/03/12) 名前と行番号の区切り記号("__")を、HybsSystem.JOINT_STRING  に変更。
	 * @og.rev 3.6.0.6 (2004/10/22) chboxNames 属性は廃止します。
	 * @og.rev 3.8.0.1 (2005/06/17) チェックボックス対応で、エラーチェックをPL/SQLで行う場合の処理機能の追加
	 * @og.rev 3.8.0.2 (2005/07/11) チェックボックス対応で、判定を DBColumnのgetEditor()を使用します
	 * @og.rev 4.0.0.0 (2006/09/31) strictCheck 追加。
	 * @og.rev 4.3.7.3 (2009/06/22) HSQLDB対応でリクエストが空文字の場合はnull文字に変換する
	 * @og.rev 5.0.0.2 (2009/09/15) XSS対応(ALLはチェックしない)
	 * @og.rev 5.6.1.2 (2013/02/22) isAllRow 引数追加
	 *
	 * @param isAllRows 全件処理 [true:する/false:しない]
	 */
	private void setRequestValues( final boolean isAllRows ) {
		final Enumeration<?> enume = getParameterNames();		// 4.3.3.6 (2008/11/15) Generics警告対応

		while( enume.hasMoreElements() ) {
			final String key  = (String)(enume.nextElement());
			final int    idx  = key.lastIndexOf(HybsSystem.JOINT_STRING);

			if( idx > 0 ) {
				final String	column	= key.substring(0,idx);
				final int		clmNo	= table.getColumnNo( column,strictCheck );
				if( clmNo < 0 ) { continue; }	// strictCheck 対応
				final DBColumn dbColumn = table.getDBColumn( clmNo );
				final int      row      = Integer.parseInt( key.substring(idx + 2) );
				// 5.0.0.2 (2009/09/15) 文字種別ALLはXSSチェックしない
				// String   val      = dbColumn.valueSet( getRequestValue( key ) );
				String   val = null;
				if( "ALL".equals( dbColumn.getDbType() ) ){
					val = dbColumn.valueSet( getRequestValue( key, false ) );
				}
				else{
					val = dbColumn.valueSet( getRequestValue( key ) );
				}

				// 3.6.0.6 (2004/10/22) チェックボックスはマルチでデータが来ます。
				// 3.8.0.2 (2005/07/11) 判定を DBColumnのgetEditor()を使用
				if( "0".equals(val) && "CHBOX".equals( dbColumn.getEditor() ) ) {
					final String[] vals = getRequestValues( key );
					if( vals != null ) {
						for( int i=0; i<vals.length; i++ ) {
							if( "1".equals( vals[i] ) ) { val = "1"; break; }
						}
					}
				}

				// 5.6.1.2 (2013/02/22) リクエスト変数すべてのデータを設定
				if( isAllRows ) {
					// 4.3.7.3 (2009/06/22) HSQLDB対応
					if( val != null && val.isEmpty() ){
						val = null;
					}
					table.setValue(row, column, val );
				}
				// 従来のロジック(チェックを外してSUBMITするケースを想定している。)
				else {
					// rowNo は、getParameterRows メソッドでソートされているので、
					// java.util.Arrays#binarySearch(int[] a, int key) が使えるはず。
					// 十分にテストしていないため、今は変更しない。
					for( int i=0; i<rowNo.length; i++ ) {
						if( rowNo[i] == row ) {
							// 4.3.7.3 (2009/06/22) HSQLDB対応
							if( val != null && val.isEmpty() ){
								val = null;
							}
							table.setValue(row, column, val );
						}
					}
				}
			}
		}
	}

	/**
	 * ColumnSetTag で指定された条件を元に、その行の値を書き換えます。
	 *
	 * @og.rev 3.6.0.6 (2004/10/22) conditionKey と、 conditionList 属性を追加
	 * @og.rev 3.8.1.5 (2006/03/30) writableControl を使用したカラムデータの先頭アンダーバーを削除します。
	 * @og.rev 4.0.0.0 (2006/09/31) strictCheck 追加。
	 * @og.rev 4.3.7.3 (2009/06/22) HSQLDB対応で空文字→NULL
	 * @og.rev 5.6.5.2 (2013/06/21) valueの初期値を利用して、１レコードごとに、＋１した値をセットします。
	 * @og.rev 5.7.8.0 (2014/07/04) actionExec の引数を columnId ではなく、DBColumnオブジェクト に変更します。
	 *
	 * @param	val 指定行データ配列
	 *
	 * @return	変更後の指定行データ配列
	 */
	private String[] setColumnValues( final String[] val ) {
		if( values != null ) {
			final int size = values.size();
			for( int i=0; i<size; i++ ) {
				final Attributes attri = values.get( i );
				final String columnId = attri.get( "columnId" );
				final int clmNo = table.getColumnNo( columnId,strictCheck );
				if( clmNo < 0 ) { continue; }	// strictCheck 対応
				final String action = attri.get( "action" );
				final String newVal = attri.get( "value"  );
				final String oldVal = val[clmNo];

				// 3.6.0.6 (2004/10/22) 条件による処理の実行可否判定
				final String conditionList = attri.get( "conditionList" );
				if( conditionList != null ) {	// null の場合は、無条件実行
					final String conditionKey = attri.get( "conditionKey" );
					final int condClmNo = table.getColumnNo( conditionKey );
					final String condValue = "|" + val[condClmNo] + "|";
					if( conditionList.indexOf( condValue ) < 0 ) {
						continue;
					}
				}

				if( ACT_COPY.equals( action ) ) {
					final int copyClmNo = table.getColumnNo( newVal );	// newVal はコピー元カラム名
					val[clmNo] = val[copyClmNo];
				}
				else if( ACT_TBLSET.equals( action ) ) {
					final ArrayDataModel model = new ArrayDataModel( table.getNames() );
					model.setValues( val,0 );
					final Formatter format = new Formatter( model );
					format.setFormat( newVal );		// newValue はフォーマットされた文字列
					val[clmNo] = format.getFormatString( 0 );
				}
				// 3.8.1.5 (2006/03/30) writableControl を使用したカラムデータの先頭アンダーバーを削除します。
				else if( ACT_WRTCTRL.equals( action ) ) {
//					if( oldVal != null && oldVal.length() > 0 && oldVal.charAt(0) == '_' ) {
					if( StringUtil.startsChar( oldVal , '_' ) ) {			// 6.2.0.0 (2015/02/27) １文字 String.startsWith
						val[clmNo] = oldVal.substring( 1 );
					}
				}
				// 3.8.5.3 (2006/08/07) DBMENUでパラメータ設定(コロン連結文字)を使用したカラムデータの先頭データのみにします。
				else if( ACT_DBMENU.equals( action ) ) {
					if( oldVal != null && oldVal.length() > 0 ) {
						final int adrs = oldVal.indexOf( ':' );
						if( adrs >= 0 ) {
							val[clmNo] = oldVal.substring( 0,adrs );
						}
					}
				}
				// 5.4.2.1 (2011/12/09) valueで指定したカラムの値をキーに、リクエスト変数から値を取出し、セットします。
				else if( ACT_REQSET.equals( action ) ) {
					if( newVal != null && newVal.length() > 0 ) {
						final int reqClmNo = table.getColumnNo( newVal );	// newVal はリクエスト取得元カラム名
						String reqClm = val[reqClmNo];				// この時点では、コロン引数が付いている可能性がある。

						final int adrs = reqClm.indexOf( ':' );			// 先頭がカラム名
						if( adrs >= 0 ) {
							reqClm = reqClm.substring( 0,adrs );	// コロンより前方の分だけ取り出す。
						}
						val[clmNo] = getRequestValue( reqClm );
					}
				}
				// 5.6.5.2 (2013/06/21) valueの初期値を利用して、１レコードごとに、＋１した値をセットします。
				else if( ACT_SEQSET.equals( action ) ) {
					int intVal = seqsetCnt ;
					if( newVal != null && newVal.length() > 0 ) {
						intVal += Integer.parseInt( newVal );		// value の設定値
					}
					val[clmNo] = String.valueOf( intVal );
				}
				else {
					// 5.7.8.0 (2014/07/04) actionExec の引数を columnId ではなく、DBColumnオブジェクト に変更します。
//					val[clmNo] = actionExec( action,columnId,oldVal,newVal );
					final DBColumn dbClm = table.getDBColumn( clmNo );
					val[clmNo] = actionExec( action,dbClm,oldVal,newVal );
				}

				// 4.3.7.3 (2009/06/22) HSQLDB対応
				if( val[clmNo] != null && val[clmNo].isEmpty()){
					val[clmNo] = null;
				}
			}
		}
		seqsetCnt ++ ;		// // 5.6.5.2 (2013/06/21) SEQSET のカウンター。

		return val;
	}

	/**
	 * アクションを実行します。
	 *
	 * アクションは,指定のアクションコマンドに対応する処理を入力データに対して行います。
	 *
	 * @og.rev 3.4.0.3 (2003/09/10) NULLSET Action を追加します。
	 * @og.rev 5.6.0.3 (2012/01/24) ADD Action に、value引数の値を加算する機能を追加します。
	 * @og.rev 5.6.6.1 (2013/07/12) action に、PREFIX,SUFIX を追加します。
	 * @og.rev 5.7.8.0 (2014/07/04) columnId ではなく、DBColumnオブジェクト に変更します。
	 *
	 * @param   action アクションコマンド
	 * @param   dbColumn DBColumnオブジェクト
	 * @param   oldValue 入力データ(旧データ)
	 * @param   newValue 入力データ(新データ)
	 *
	 * @return	実行後のデータ
	 * @see		<a href="../../../../constant-values.html#org.opengion.hayabusa.taglib.EntryTag.ACT_DEFAULT">アクション定数</a>
	 */
//	private String actionExec( final String action,final String clmId,final String oldValue,final String newValue ) {
	private String actionExec( final String action,final DBColumn dbColumn,final String oldValue,final String newValue ) {
		String rtnVal = oldValue;

//		DBColumn dbColumn = getDBColumn( clmId );	// 5.7.8.0 (2014/07/04)
		if( ACT_DEFAULT.equals(    action ) ) { rtnVal = dbColumn.getDefault(); }
		else if( ACT_CLEAR.equals( action ) ) { rtnVal = ""; }
		else if( ACT_SET.equals(   action ) ) { rtnVal = dbColumn.valueSet( newValue ); }
		else if( ACT_ADD.equals(   action ) ) { rtnVal = dbColumn.valueAdd( oldValue,newValue ); }	// 5.6.0.3 (2012/01/24)
		else if( ACT_LOWER.equals( action ) ) {
			if( oldValue == null ) { rtnVal = dbColumn.getDefault();  }
			else                   { rtnVal = oldValue.toLowerCase(Locale.JAPAN); }
		}
		else if( ACT_UPPER.equals( action ) ) {
			if( oldValue == null ) { rtnVal = dbColumn.getDefault();  }
			else                   { rtnVal = oldValue.toUpperCase(Locale.JAPAN); }
		}
		// 3.4.0.3 (2003/09/10) NULLSET Action を追加します。
		else if( ACT_NULLSET.equals( action ) ) {
			if( oldValue == null || oldValue.isEmpty() ) {
				rtnVal = dbColumn.valueSet( newValue );
			}
		}
		// 5.6.6.1 (2013/07/12) PREFIX Action を追加します。
		else if( ACT_PREFIX.equals( action ) ) {
			if( oldValue != null && oldValue.length() > 0 && newValue != null && newValue.length() > 0 ) {
				final int indx = oldValue.lastIndexOf( newValue );
				if( indx >= 0 ) {
					rtnVal = oldValue.substring( 0,indx );
				}
			}
		}
		// 5.6.6.1 (2013/07/12) SUFIX Action を追加します。
		else if( ACT_SUFIX.equals( action ) ) {
			if( oldValue != null && oldValue.length() > 0 && newValue != null && newValue.length() > 0 ) {
				final int indx = oldValue.lastIndexOf( newValue );
				if( indx >= 0 ) {
					rtnVal = oldValue.substring( indx+1 );		// 分割記号は含まないので＋１する。
				}
			}
		}
		else {
			rtnVal = dbColumn.valueAction( action,oldValue,newValue );
		}

		if( rtnVal == null ) { rtnVal = dbColumn.getDefault(); }

		return rtnVal;
	}

	/**
	 * 【TAG】指定の回数分だけ、繰り返し処理を行う回数を指定します(初期値:1)。
	 *
	 * @og.tag
	 * 追加や複写時に、指定の回数分だけ、処理を繰り返して、新規に行を
	 * 作成します。
	 * 繰り返しは、指定の行に対して行われ、繰り返し毎に、直前に作成された
	 * 行を元に処理します。これは、例えば、columnSet で、action="ADD"の場合に、
	 * 繰り返す毎に、ADD処理が実行されることを意味します。
	 * 行が指定されていない場合は、先頭空行に追加します。
	 * 初期値は、１回です。
	 *
	 * @og.rev 3.5.4.2 (2003/12/15) 新規追加
	 *
	 * @param	rc	繰り返し処理回数(初期値:1)
	 */
	public void setRepeatCount( final String rc ) {
		repeatCount = nval( getRequestParameter( rc ),repeatCount );
	}

	/**
	 * 【TAG】Consistency キー による整合性チェックを行うかどうか[true/false]を指定します(初期値:true)。
	 *
	 * @og.tag
	 * 検索結果を DBTableModel にセットする時に、整合性キーの Consistency キーを
	 * 作成します。これを、Viewタグでhidden出力しておき、Entryタグでデータ書き換え時に
	 * 整合性チェックを行います。これは、IEの戻るボタンで戻った場合に、画面の
	 * キーと検索結果の DBTableModel の内容が一致しない場合のエラーチェックに
	 * なります。
	 * この属性は、何らかのケースで、このエラーチェックを行いたくない場合に、
	 * false に設定することで、整合性チェックを行いません。
	 * 初期値は、true(整合性チェックを行う)です。
	 *
	 * @og.rev 3.5.5.7 (2004/05/10) 新規登録
	 *
	 * @param	ck	整合性チェック [true:行う/false:行わない]
	 */
	public void setUseConsistency( final String ck ) {
		useConsistency = nval( getRequestParameter( ck ),useConsistency );
	}

	/**
	 * DBTableModel の 整合性パラメータとリクエスト情報を比較チェックします。
	 * リクエスト情報は、その DBTableModel が出力された view で hidden 属性で
	 * 設定されます。
	 * 設定されるキーは、tableId が変更されていなければ、HybsSystem.CONSISTENCY_KEY です。
	 * 変更されていれば、HybsSystem.CONSISTENCY_KEY + tableId です。
	 *
	 * @og.rev 3.5.5.8 (2004/05/20) Consistency キー による整合性チェックを checkConsistency() に集約します。
	 *
	 * @return チェック結果  true:正常/false:異常
	 * @see org.opengion.hayabusa.common.HybsSystem#CONSISTENCY_KEY
	 */
	private boolean checkConsistency() {
		boolean rtn = true;
		final String key = HybsSystem.CONSISTENCY_KEY ;

		final String consisKey = getRequestValue( key );
		if( consisKey != null && consisKey.length() > 0 ) {
			if( useConsistency && ! consisKey.equals( table.getConsistencyKey() ) ) {

				final ErrorMessage errMsgObj = new ErrorMessage( "Consistency Key Check Error!" );
				errMsgObj.addMessage( 0,ErrorMessage.NG,"ERR0033.1" );
				errMsgObj.addMessage( 0,ErrorMessage.NG,"ERR0033.2" );
				errMsgObj.addMessage( 0,ErrorMessage.NG,"ERR0033.3" );
				jspPrint( TaglibUtil.makeHTMLErrorTable( errMsgObj,getResource() ) );
				rtn = false;
			}
		}
		else {
			System.out.println( "EntryTag:Consistency Key is null" );
		}
		return rtn ;
	}

	/**
	 * 表示データの HybsSystem.ROW_SEL_KEY を元に、選ばれた 行を処理の対象とします。
	 *
	 * @og.rev 3.8.1.1 (2005/11/21) selectedAll 追加。全件選択されたこととして、処理します。
	 * @og.rev 4.0.0.0 (2005/01/31) getParameterRows() を使用するように変更
	 *
	 * @return	選択行の配列
	 * @og.rtnNotNull
	 */
	@Override
	protected int[] getParameterRows() {
		final 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)
		}
		return rowNo ;
	}

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

	/**
	 * 【TAG】カラムＩＤの存在チェックを行うかどうか[true/false]を指定します(初期値:true)。
	 *
	 * @og.tag
	 * true の場合、カラムＩＤがDBTableModel に存在しない場合は、エラーになります。
	 * false の場合、カラムＩＤがDBTableModel に存在しない場合は、無視します。
	 * これは、検索条件によって、設定されるカラムが異なる場合でも、entryタグを
	 * 正常に動作させたい場合に、使用します。
	 * 初期値は true (チェックを行う) です。
	 *
	 * @param  check 存在チェック [true:行う/false:行わない]
	 */
	public void setStrictCheck( final String check ) {
		strictCheck = nval( getRequestParameter( check ),strictCheck );
	}

	/**
	 * 【TAG】(通常は使いません)画面遷移を行わない形式の登録方法を使用するかを指定します。
	 *
	 * @og.tag
	 * 画面遷移なしの登録を行うかどうかを指定します。
	 * trueが指定された場合、entryタグでは、行の追加・複写時にDBTableModel上の最終行にデータを
	 * 追加します。
	 * 画面遷移なしモードの場合、途中行に挿入された場合、既にクライアントに出力されている
	 * チェックボックスの行番号や各入力フィールドの変数名との整合性を合わせるためには、
	 * 編集行以降の各変数値を全て再計算する必要があります。
	 * この処理は、レスポンス悪化に繋がるため、DBTableModel上は、中間に行の挿入を行いません。
	 * 但し画面表示上は、通常通り選択行の直下に行が挿入されるため、DBTableModelの順番と標準順が
	 * 異なります。(エンジン側では、各チェックボックスの値で行を識別しているため、問題は発生しません)
	 *
	 * この値は、og:headタグで設定値、または前画面からの値を継承するため、通常、この属性ではセットしません。
	 *
	 * @og.rev 4.3.3.0 (2008/10/01) 新規追加
	 * @og.rev 5.1.3.0 (2010/02/01) noTransition、ajaxSubmitのコントロールは、requestで行う。
	 *
	 * @param   noTrnstn 画面遷移を行わない形式の登録方法を使用するか
	 */
	public void setNoTransition( final String noTrnstn ) {
		setNoTransitionRequest( nval( getRequestParameter( noTrnstn ), isNoTransitionRequest() ) );
	}

	/**
	 * シリアライズ用のカスタムシリアライズ書き込みメソッド。
	 *
	 * @og.rev 4.0.0.0 (2006/09/31) 新規追加
	 * @serialData 一部のオブジェクトは、シリアライズされません。
	 *
	 * @param	strm	ObjectOutputStreamオブジェクト
	 * @throws IOException	シリアライズに関する入出力エラーが発生した場合
	 */
	private void writeObject( final ObjectOutputStream strm ) throws IOException {
		strm.defaultWriteObject();
	}

	/**
	 * シリアライズ用のカスタムシリアライズ読み込みメソッド
	 *
	 * ここでは、transient 宣言された内部変数の内、初期化が必要なフィールドのみ設定します。
	 *
	 * @og.rev 4.0.0.0 (2006/09/31) 新規追加
	 * @serialData 一部のオブジェクトは、シリアライズされません。
	 *
	 * @param	strm	ObjectInputStreamオブジェクト
	 * @see #release2()
	 * @throws IOException	シリアライズに関する入出力エラーが発生した場合
	 * @throws ClassNotFoundException	クラスを見つけることができなかった場合
	 */
	private void readObject( final ObjectInputStream strm ) throws IOException , ClassNotFoundException {
		strm.defaultReadObject();
	}

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