/*
 * 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.fukurou.system.OgRuntimeException ;			// 6.4.2.0 (2016/01/29)
import org.opengion.hayabusa.common.HybsSystem;
import org.opengion.hayabusa.common.HybsSystemException;
import org.opengion.hayabusa.common.HybsOverflowException;		// 6.2.2.0 (2015/03/27)
import org.opengion.hayabusa.db.DBTableModelUtil;				// 6.2.1.0 (2015/03/13)
import org.opengion.hayabusa.db.DBTableModel;
import org.opengion.hayabusa.db.DBColumn;
import org.opengion.hayabusa.db.ColumnActionListener;			// 6.2.2.0 (2015/03/27)
import org.opengion.hayabusa.io.TableReader;
import org.opengion.fukurou.util.ErrorMessage;
import org.opengion.fukurou.util.StringUtil ;
import org.opengion.fukurou.system.ThrowUtil ;					// 6.4.2.0 (2016/01/29)
import org.opengion.fukurou.util.ToString;						// 6.1.1.0 (2015/01/17)
import org.opengion.fukurou.util.FileInfo;						// 6.2.0.0 (2015/02/27)
import org.opengion.fukurou.util.ArraySet;						// 6.4.3.4 (2016/03/11)

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

import java.util.Locale ;
import java.util.List ;											// 6.2.5.0 (2015/06/05)
import java.util.ArrayList ;									// 6.2.5.0 (2015/06/05)
import java.util.Set;											// 6.4.3.4 (2016/03/11)
import java.io.File;
// import java.io.ObjectOutputStream;
// import java.io.ObjectInputStream;
// import java.io.IOException;

/**
 * 指定のファイルを DBTableModelオブジェクトに読み取るファイル入力タグです。
 *
 * データ(DBTableModel)と、コントローラ(ReadTableタグ)を与えて、外部からコントロールすることで、
 * 各種形式で データ(DBTableModel)を表示させることが できます。
 * ReadTableタグ に対して、コマンドを与えることにより、内部のコントローラの実装に対応した
 * 形式でデータを作成します。
 * すべての読取の初期クラス名を リソースファイルの TABLE_READER_DEFAULT_CLASS で指定可能です。
 * その場合、AutoReader を指定すると、Excel と Text(テキスト) を以下の順番で試します。
 * Excel,Calc,Text(UnicodeLittle),Text(Windows-31J),Text(UTF-8),Text(EUC-JP),POI
 * UTF-8 のTEXTとWindows-31JのTEXTは、ヘッダー部での区別ができないため、正確なTextの自動読取できません。
 * 
 * ※ 6.2.5.0 (2015/06/05) 仕様変更
 *    ・AutoReader で、encode を指定すると、Text(encode) を先に試します。
 *    ・Textで、encode を指定しない場合は、システム変数の FILE_ENCODE を使用します。
 *
 * 入力件数を"DB.COUNT" キーでリクエストにセットしています。
 *
 * @og.formSample
 * ●形式：
 *     &lt;og:readTable
 *         command      = "NEW"
 *         fileURL      = "{&#064;USER.ID}"     読取元ディレクトリ名
 *         filename     = "{&#064;filename}"    読取元ファイル名
 *         encode       = "UnicodeLittle"       読取元ファイルエンコード名
 *         maxRowCount  = "10000"               読取最大件数(初期値:0:[無制限])
 *     /&gt;
 * ●body：なし
 *
 * ●Tag定義：
 *   &lt;og:readTable
 *       readerClass        【TAG】実際に読み出すクラス名の略称(TableReader_**** の ****)をセットします
 *                                  (初期値:TABLE_READER_DEFAULT_CLASS[={@og.value SystemData#TABLE_READER_DEFAULT_CLASS}])
 *       command            【TAG】コマンド (NEW,RENEW)をセットします(初期値:NEW)
 *       fileURL            【TAG】読取元ディレクトリ名を指定します(初期値:FILE_URL)
 *       filename           【TAG】ファイルを読み出すときのファイル名をセットします (初期値:FILE_FILENAME[=file.xls])
 *       encode             【TAG】ファイルを読み出すときのファイルエンコーディング名をセットします(初期値:FILE_ENCODE)
 *       skipRowCount       【TAG】(通常は使いません)データの読み飛ばし件数を設定します
 *       maxRowCount        【TAG】読取時の最大取り込み件数をセットします (初期値:0:[無制限])
 *       errRowCount        【TAG】読取時の最大エラー件数をセットします (初期値:{@og.value #ERROR_ROW_COUNT})(0:[無制限])
 *       separator          【TAG】可変長ファイルを読み出すときの項目区切り文字をセットします
 *       columns            【TAG】読取元ファイルのカラム列を、外部(タグ)よりCSV形式で指定します
 *       omitNames          【TAG】読取対象外のカラム列を、外部(タグ)よりCSV形式で指定します
 *       modifyType         【TAG】ファイル取り込み時の モディファイタイプ(A(追加),C(更新),D(削除))を指定します
 *       displayMsg         【TAG】query の結果を画面上に表示するメッセージIDを指定します(初期値:VIEW_DISPLAY_MSG[={@og.value SystemData#VIEW_DISPLAY_MSG}]))
 *       overflowMsg        【TAG】読取データが最大検索数をオーバーした場合に表示するメッセージリソースIDを指定します (初期値:MSG0007[検索結果が、制限行数を超えましたので、残りはカットされました])
 *       notfoundMsg        【TAG】検索結果がゼロ件の場合に表示するメッセージリソースIDを指定します(初期値:MSG0077[対象データはありませんでした])
 *  ※   sheetName          【TAG】EXCELファイルを読み込むときのシート名を設定します(初期値:指定なし)
 *  ※   sheetNos           【TAG】EXCELファイルを読み込むときのシート番号を複数設定できます(初期値:0)
 *  ※   sheetConstKeys     【TAG】EXCELファイルを読み込むときの固定値となるカラム名(CSV形式)
 *  ※   sheetConstAdrs     【TAG】EXCELファイルを読み込むときの固定値となるアドレス(行-列,行-列,・・・)
 *       nullBreakClm       【TAG】カラム列に NULL が現れた時点で読取を中止します(複数Sheetの場合は、次のSheetを読みます)。
 *       nullSkipClm        【TAG】カラム列に NULL が現れたレコードは読み飛ばします。
 *       useNumber          【TAG】行番号情報を、使用している/していない[true/false]を指定します(初期値:true)
 *       useRenderer        【TAG】読取処理でKEY:VAL形式のコードリソースから、KEYを取り出す処理を行うかどうかを指定します(初期値:USE_TABLE_READER_RENDERER[=false])
 *       adjustColumns      【TAG】読取元ファイルのデータ変換を行うカラム列をカンマ指定します("*" で全カラム)
 *       checkColumns       【TAG】読取元ファイルの整合性チェックを行うカラム列をカンマ指定します("*" で全カラム)
 *       nullCheck          【TAG】NULL チェックすべきカラム列をCSV形式(CVS形式)で指定します
 *       language           【TAG】タグ内部で使用する言語コード[ja/en/zh/…]を指定します
 *       stopZero           【TAG】読込件数が０件のとき処理を続行するかどうか[true/false]を指定します(初期値:false[続行する])
 *       mainTrans          【TAG】(通常使いません)タグで処理される処理がメインとなるトランザクション処理かどうかを指定します(初期値:false)
 *       tableId            【TAG】(通常使いません)sessionから所得する DBTableModelオブジェクトの ID
 *       scope              【TAG】キャッシュする場合のスコープ[request/page/session/applicaton]を指定します(初期値:session)
 *       caseKey            【TAG】このタグ自体を利用するかどうかの条件キーを指定します(初期値:null) 5.7.7.2 (2014/06/20)
 *       caseVal            【TAG】このタグ自体を利用するかどうかの条件値を指定します(初期値:null) 5.7.7.2 (2014/06/20)
 *       caseNN             【TAG】指定の値が、null/ゼロ文字列 でない場合(Not Null=NN)は、このタグは使用されます(初期値:判定しない) 5.7.7.2 (2014/06/20)
 *       caseNull           【TAG】指定の値が、null/ゼロ文字列 の場合は、このタグは使用されます(初期値:判定しない) 5.7.7.2 (2014/06/20)
 *       caseIf             【TAG】指定の値が、true/TRUE文字列の場合は、このタグは使用されます(初期値:判定しない)
 *       debug              【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false)
 *   /&gt;
 *
 * ●使用例
 *
 *     &lt;og:readTable
 *         command        = "NEW"
 *         readerClass    = "Fixed"               固定長データの読取
 *         modifyType     = "{&#064;modifyType}"  読取時のモディファイタイプ(A,C等)
 *         fileURL        = "{&#064;USER.ID}"     読取元ディレクトリ名
 *         filename       = "{&#064;filename}"    読取元ファイル名
 *         encode         = "Shift_JIS"           読取元ファイルエンコード名
 *         maxRowCount    = "10000"               読取最大件数(0:[無制限])
 *         columns        = "OYA,KO,HJO,SU,DYSTR,DYEND"   #NAME に対応するカラム列
 *         useNumber      = "false"               行番号の存在しないデータを読取ます。
 *         adjustColumns  = "OYA,KO,HJO,SU"       データ変換するカラム列("*" で全カラム)
 *         checkColumns   = "OYA,KO,HJO,SU"       整合性チェックするカラム列("*" で全カラム)
 *         nullCheck      = "OYA,KO,SU"           NULLチェックを実行します("*" で全カラム)
 *         stopZero       = "true"                取得0件の場合に以降の処理を停止します
 *         skipRowCount   = "4"                   データの読み飛ばし件数(読み込み開始は、この数字＋１行目から)
 *     /&gt;
 *
 * @og.group ファイル入力
 *
 * @version  4.0
 * @author   Kazuhiko Hasegawa
 * @since    JDK5.0,
 */
public class ReadTableTag extends CommonTagSupport {
	/** このプログラムのVERSION文字列を設定します。	{@value} */
	private static final String VERSION = "6.4.3.4 (2016/03/11)" ;
	private static final long serialVersionUID = 643420160311L ;

	private static final int ERROR_ROW_COUNT = 200 ;	// 4.0.0 (2007/05/25)

	/** command 引数に渡す事の出来る コマンド  新規作成 {@value} */
	public static final String CMD_NEW   = "NEW" ;
	/** command 引数に渡す事の出来る コマンド  再検索 {@value} */
	public static final String CMD_RENEW = "RENEW" ;

//	private static final String[] COMMAND_LIST = { CMD_NEW , CMD_RENEW };
	// 6.4.3.4 (2016/03/11) String配列 から、Setに置き換えます。
	private static final Set<String> COMMAND_SET = new ArraySet<>( CMD_NEW , CMD_RENEW );

	// 6.2.0.0 (2015/02/27) AutoReaderの対応方法変更。拡張子に応じて、チェック対象を変更する。null は全対象
	// 6.2.2.0 (2015/03/27) マクロ付Excel(.xlsm)対応
	// 6.2.5.0 (2015/06/05) 文字列配列から、内部クラスに変更

	private static final List<AutoReaderParam> AUTO_READER_PARAM = new ArrayList<>() ;
	static {
		AUTO_READER_PARAM.add( new AutoReaderParam( "Excel"	,	null			,	"xls,xlsx,xlsm"	) );
		AUTO_READER_PARAM.add( new AutoReaderParam( "Calc"	,	null			,	"ods"			) );
		AUTO_READER_PARAM.add( new AutoReaderParam( "Text"	,	"UnicodeLittle"	,	null			) );
		AUTO_READER_PARAM.add( new AutoReaderParam( "Text"	,	"Windows-31J"	,	null			) );
		AUTO_READER_PARAM.add( new AutoReaderParam( "Text"	,	"UTF-8"			,	null			) );
		AUTO_READER_PARAM.add( new AutoReaderParam( "Text"	,	"EUC-JP"		,	null			) );
		AUTO_READER_PARAM.add( new AutoReaderParam( "POI"	,	null			,	"ppt,pptx,doc,docx,xls,xlsx,xlsm" ) );		// 6.2.5.0 (2015/06/05) 追加
	}

	protected String separator		= TableReader.TAB_SEPARATOR;				 // 項目区切り文字 6.2.0.0 (2015/02/27) protected化
	private String	fileURL 		= HybsSystem.sys( "FILE_URL"			);
	private String	filename		= HybsSystem.sys( "FILE_FILENAME"		);	 // ファイル名
	protected String encode			;											 // 6.2.5.0 (2015/06/05) ファイルエンコーディング
	protected String readerClass	;														// 6.2.0.0 (2015/02/27) protected化
	protected int	maxRowCount		;														// 6.2.0.0 (2015/02/27) 初期値を無制限に変更
	protected String displayMsg		= HybsSystem.sys( "VIEW_DISPLAY_MSG" );					// 6.2.0.0 (2015/02/27) protected化
	private String	overflowMsg		= "MSG0007";	// 検索結果が、制限行数を超えましたので、残りはカットされました。
	private String	notfoundMsg		= "MSG0077";	// 対象データはありませんでした。
	protected int 	executeCount	= -1;			// 検索/実行件数
	private String	modifyType		;

	private transient DBTableModel table	;
	private String	command			= CMD_NEW;
	private String	tableId			= HybsSystem.TBL_MDL_KEY ;
	protected String sheetName		;				// 3.5.4.2 (2003/12/15)
	protected String sheetNos		;				// 5.5.7.2 (2012/10/09) 複数シートを指定できるようにシート番号を指定できるようにする。
	protected String sheetConstKeys	;				// 5.5.8.2 (2012/11/09) 固定値となるカラム名(CSV形式)
	protected String sheetConstAdrs	;				// 5.5.8.2 (2012/11/09) 固定値となるアドレス(行-列,行-列,・・・)
	protected String nullBreakClm	;				// 5.5.8.2 (2012/11/09) 取込み条件/Sheet BREAK条件
	protected String nullSkipClm	;				// 6.2.3.0 (2015/05/01) 行読み飛ばし

	// 3.5.4.5 (2004/01/23) 外部よりカラム列(CSV形式)を指定できるようにする。
	protected String columns		;				// 6.2.0.0 (2015/02/27) protected化
	// 6.1.0.0 (2014/12/26) 読取対象外のカラム列を、外部(タグ)より指定する。
	protected boolean useNumber		= true;			// 3.7.0.5 (2005/04/11)

	protected boolean stopZero		;				// 4.3.7.0 (2009/06/01) stopZero属性追加

	private boolean	isMainTrans		= true;			// 5.1.6.0 (2010/05/01) DBLastSqlの処理の見直し
	protected int	skipRowCount	;				// 5.1.6.0 (2010/05/01) データの読み飛ばし設定

	// 6.2.2.0 (2015/03/27) ColumnAction インナークラスでパラメータを整理する。
//	protected ColumnAction clmAct	= new ColumnAction();			// 6.2.2.0 (2015/03/27)
	protected transient	ColumnAction clmAct	= new ColumnAction();	// 6.3.9.0 (2015/11/06) transient 追加

	// 6.3.6.1 (2015/08/28) DirectTableInsertTag でSQLException発生時にセットする。（暫定対応）
	protected boolean sqlError		;				// 6.3.6.1 (2015/08/28)

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

	/**
	 * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。
	 *
	 * @og.rev 3.0.1.4 (2003/03/17) displayMsg が ０Byteの場合は、件数も表示しないように変更。
	 * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。
	 * @og.rev 3.5.4.1 (2003/12/01) 引数の BufferedReader を、InputStream に変更。
	 * @og.rev 3.5.4.3 (2004/01/05) 引数の InputStream を、 BufferedReader に戻す。
	 * @og.rev 3.5.6.5 (2004/08/09) 暫定的に、DBTableModelを先行削除します。
	 * @og.rev 3.6.0.0 (2004/09/24) DBTableModel の先行削除は、scope="session" の場合のみ。
	 * @og.rev 3.6.0.2 (2004/10/04) 取り込み時チェック用に、checkColumns,adjustColumns 属性追加
	 * @og.rev 3.6.0.8 (2004/11/19) DBTableModel をセーブする時に、トランザクションチェックを行います。
	 * @og.rev 3.8.5.3 (2006/08/07) readerClassが "Excel"でエラーが発生したとき、もう一度Defaultで再読取を行います。
	 * @og.rev 4.0.0.0 (2007/10/12) checkTableColumn 前に、modifyType 設定を行います。
	 * @og.rev 4.0.0.0 (2007/10/18) メッセージリソース統合( getResource().getMessage ⇒ getResource().getLabel )
	 * @og.rev 4.3.1.1 (2008/10/08) columnsが指定されている場合は、AutoReader禁止
	 * @og.rev 4.3.7.0 (2009/06/01) stopZero機能,DB.COUNTリクエストキーへ読込件数セットを追加
	 * @og.rev 5.1.6.0 (2010/05/01) DBLastSqlの処理は、DBTableModelが新規作成された処理でのみ行う。
	 * @og.rev 5.1.8.0 (2010/07/01) AutoReaderのCalc対応
	 * @og.rev 5.1.9.0 (2010/08/01) AutoReaderでのExceptionの判定をThrowableに変更
	 * @og.rev 5.7.1.2 (2013/12/20) tempMsg.toString() ⇒ errMsg 変更
	 * @og.rev 5.7.7.2 (2014/06/20) caseKey,caseVal,caseNN,caseNull 属性を追加
	 * @og.rev 6.0.2.5 (2014/10/31) debug=true 時のエラー情報を増やします。
	 * @og.rev 6.2.0.0 (2015/02/27) TableReader クラスの呼び出し元メソッドの共通化(EXCEL,TEXT)
	 * @og.rev 6.2.0.0 (2015/02/27) EXCEL出力のparamLevel初期値変更 3:標準推奨 → 4:個人設定可
	 * @og.rev 6.2.2.0 (2015/03/27) ColumnAction インナークラスでパラメータを整理する。
	 * @og.rev 6.2.3.0 (2015/05/01) 複数処理を考慮して、例外処理は発行しない。
	 * @og.rev 6.2.3.0 (2015/05/01) columnsが指定されていても、AutoReader を使えるようにします。
	 * @og.rev 6.2.4.2 (2015/05/29) エラーを画面に出します。
	 * @og.rev 6.2.5.0 (2015/06/05) AutoReaderの仕様変更。
	 * @og.rev 6.3.6.1 (2015/08/28) DirectTableInsertTag でSQLException発生時のみ throwする。
	 * @og.rev 6.4.2.0 (2016/01/29) StringUtil#ogStackTrace(Throwable) を、ThrowUtil#ogStackTrace(String,Throwable) に置き換え。
	 * @og.rev 6.4.3.4 (2016/03/11) String配列 から、Setに置き換えます。
	 *
	 * @return	後続処理の指示
	 */
	@Override
	public int doEndTag() {
		debugPrint();		// 4.0.0 (2005/02/28)
		// 5.7.7.2 (2014/06/20) caseKey,caseVal,caseNN,caseNull 属性を追加
		if( !useTag() ) { return EVAL_PAGE ; }

		int rtnCode = EVAL_PAGE;

//		if( check( command, COMMAND_LIST ) ) {
		if( check( command, COMMAND_SET ) ) {
			useMainTrans( isMainTrans );			// 5.1.6.0 (2010/05/01) DBLastSqlの処理の見直し
			startQueryTransaction( tableId );		// 3.6.0.8 (2004/11/19)

			// 3.5.6.5 (2004/08/09) 削除するのは、セッションのオブジェクトでよい。
			// 3.6.0.0 (2004/09/24) 削除するのは、scope="session" の場合のみ。
			if( "session".equals( getScope() ) ) {
				removeSessionAttribute( tableId );
				removeSessionAttribute( HybsSystem.VIEWFORM_KEY );
			}

			// 6.2.5.0 (2015/06/05) AutoReaderの仕様変更。

			// 6.2.0.0 (2015/02/27) EXCEL出力のparamLevel初期値変更 3:標準推奨 → 4:個人設定可
			if( readerClass == null ) {
				readerClass = nval( sys( "TABLE_READER_DEFAULT_CLASS" ) , "AutoReader" );
			}

			// ファイル の読み込み：AutoReader 処理
			// 6.2.5.0 (2015/06/05) AutoReaderParam 内部クラスを使用します。
			final List<AutoReaderParam> readerParam = new ArrayList<>() ;

			if( "AutoReader".equalsIgnoreCase( readerClass ) ) {
				// 4.3.1.1 (2008/10/08)
	//			// 6.2.3.0 (2015/05/01) columnsが指定されていても、AutoReader を使えるようにします。
	//			if( columns != null && columns.length() > 0 ) {
	//				final String errMsg = "columnsが指定されている場合は、readerClass=\"AutoReader\"は使えません";
	//				throw new HybsSystemException( errMsg );	// 4.3.4.4 (2009/01/01)
	//			}
				// 6.2.5.0 (2015/06/05) AutoReaderParam 内部クラスを使用します。
				if( encode != null ) { readerParam.add( new AutoReaderParam( "Text" , encode , null ) ); }		// encode 指定時は優先
				readerParam.addAll( AUTO_READER_PARAM );		// 標準のパラメータを追加します。
			}
			else {
				// 6.2.5.0 (2015/06/05) readerClass が "Text" で、encode が null の場合は、FILE_ENCODE を使用する。
				if( "Text".equalsIgnoreCase( readerClass ) && encode == null ) { encode = HybsSystem.sys( "FILE_ENCODE" ); }
				readerParam.add( new AutoReaderParam( readerClass , encode , null ) );
			}

			final String directory = HybsSystem.url2dir( fileURL );
			final File file = new File( directory,filename );

			final String sufix = FileInfo.getSUFIX( file ) ;		// 6.2.3.0 (2015/05/01) 拡張子に応じて、チェックを変更する。

			StringBuilder tempMsg = new StringBuilder( BUFFER_MIDDLE );
			// 6.2.5.0 (2015/06/05) AutoReaderParam 内部クラスを使用します。
			for( final AutoReaderParam arParam : readerParam ) {
				// 6.2.0.0 (2015/02/27) 拡張子に応じて、チェックを変更する。
				if( !arParam.useSufix( sufix ) ) { continue; }		// false:対象外の場合は、次のreaderClassを使う。

				readerClass = arParam.CLASS;
				encode      = arParam.ENCODE;

				if( isDebug() ) {
					final String errMsg = "File=[" + file + "] , class=[" + readerClass + "] , encode=[" + encode + "]" + BR ;
					jspPrint( errMsg );
					System.out.println( errMsg );
				}

				try {
					clmAct.isDebug = isDebug();
					sqlError = false;	// 6.3.6.1 (2015/08/28) DirectTableInsertTag でSQLException発生時のみ処理する。
					create( file );		// 6.2.0.0 (2015/02/27) TableReader クラスの呼び出し元メソッドの共通化(EXCEL,TEXT)

					// 成功すれば、エラーメッセージをクリアして、その場で抜ける。
					tempMsg = null;
					break;
				}
				// 6.2.2.0 (2015/03/27) HybsOverflowException処理をタグ側で行う。
				catch( HybsOverflowException ex ) {
					// table.setOverflow( true ); は、処理済み。ループから抜けて処理を継続する。
					tempMsg = null;
					break;
				}
				// 6.3.6.1 (2015/08/28) DirectTableInsertTag でSQLException発生時のみ処理する。
				catch( HybsSystemException ex ) {
					if( sqlError ) { throw ex; }	// SQLException発生時は処理中止
				}
				// 3.8.5.3 (2006/08/07) readerClassが "Excel"でエラーが発生したとき、もう一度Defaultで再読取を行います。
				// 5.1.9.0 (2010/08/01) RuntimeException系のExceptionがキャッチできないため、Throwableで受ける
				catch( Throwable th ) {
					tempMsg.append( "File=["  ).append( file )
							.append( "] , Class=["   ).append( readerClass )
							.append( "] , Encode=["  ).append( encode )
							.append( "] Error!"      ).append( CR )
							.append( th.getMessage() ).append( CR ) ;
					if( isDebug() ) {
						jspPrint( "<pre>" + tempMsg.toString() + "</pre>" );				// 6.2.4.2 (2015/05/29) 画面にも出力します。
//						tempMsg.append( StringUtil.ogStackTrace( th ) ).append( CR ) ;
						tempMsg.append( ThrowUtil.ogStackTrace( th ) ).append( CR ) ;		// 6.4.2.0 (2016/01/29)
					}
				}
			}

			// 6.2.3.0 (2015/05/01) 複数処理を考慮して、例外処理は発行しない。
			// 6.4.1.1 (2016/01/16) PMD refactoring. Avoid if (x != y) ..; else ..;
			if( tempMsg == null ) {
				// 6.2.2.0 (2015/03/27) #afterEnd() メソッド 新規作成。
				rtnCode = afterEnd();
			}
			else {								// 最後までエラーがあれば、例外処理を発行します。
//			if( tempMsg != null ) {				// 最後までエラーがあれば、例外処理を発行します。
				final String errMsg = tempMsg.toString();
				System.err.print( errMsg );
				jspPrint( "<pre>" + errMsg + "</pre>" );		// 6.2.4.0 (2015/05/15) エラーを画面に出します。
//				throw new HybsSystemException( errMsg );		// 5.7.1.2 (2013/12/20) msg ⇒ errMsg 変更
				rtnCode = SKIP_PAGE;							// 6.2.4.2 (2015/05/29) エラー時はSKIP
			}
//			else {
//				// 6.2.2.0 (2015/03/27) #afterEnd() メソッド 新規作成。
//				rtnCode = afterEnd();
//			}
		}

		return rtnCode ;
	}

	/**
	 * #doEndTag() の後続処理を記述します。
	 * 
	 * これは、サブクラスで、DBTableModel以外の処理を行う場合に、
	 * 処理内容を分けるために用意します。
	 *
	 * @og.rev 6.2.2.0 (2015/03/27) #afterEnd() メソッド 新規作成。
	 * @og.rev 6.2.4.2 (2015/05/29) executeCount の設定がおかしい。ReadTableTagでは、設定されていなかった。
	 * @og.rev 6.2.5.0 (2015/06/05) エラー処理は、継承先でも行うので、メソッド化します。
	 *
	 * @return	後続処理の指示
	 */
	protected int afterEnd() {
		if( table != null ) {
			// 6.2.4.2 (2015/05/29) executeCount が設定されなくなった件
			executeCount = table.getRowCount();

			// 3.6.0.2 (2004/10/04)
			// 4.0.0.0 (2007/10/12) checkTableColumn 前に、modifyType 設定を行います。

			// 6.2.5.0 (2015/06/05) エラー処理は、継承先でも行うので、メソッド化します。
			final ErrorMessage errMsg = clmAct.getErrorMessage();
			if( !errMsg.isOK() ) {
				jspPrint( TaglibUtil.makeHTMLErrorTable( errMsg,getResource() ) );
				return SKIP_PAGE ;
			}
		}

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

		final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE );

		// 実行件数の表示 command="NEW" のときのみ、displayMsg を表示させます。
		// 4.0.0 (2005/11/30) 出力順の変更。一番最初に出力します。
		if( CMD_NEW.equals( command ) ) {
			if( executeCount > 0 && displayMsg != null && displayMsg.length() > 0 ) {
				buf.append( executeCount )
					.append( getResource().getLabel( displayMsg ) )
					.append( BR );
			}
			else if( executeCount == 0 && notfoundMsg != null && notfoundMsg.length() > 0 ) {
				buf.append( getResource().getLabel( notfoundMsg ) )
					.append( BR );
			}
		}

		// 4.3.7.0 (2009/06/01) 読込件数を、"DB.COUNT" キーでリクエストにセットする。
		setRequestAttribute( "DB.COUNT"   , String.valueOf( executeCount ) );

		// 6.2.0.0 (2015/02/27) オーバーフロー時のメッセージを表示
		if( table != null && table.isOverflow() && overflowMsg != null && overflowMsg.length() > 0  ) {
			buf.append( getResource().getLabel( overflowMsg ) )
				.append( BR );
		}

		jspPrint( buf.toString() );

		// 4.3.7.0 (2009/06/01) stopZero機能を追加
		return executeCount == 0 && stopZero ? 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.1.3.0 (2003/04/10) FILE_ENCODE から、エンコード情報を取得する。
	 * @og.rev 3.1.4.0 (2003/04/18) command 属性に、初期値(NEW)を設定する。
	 * @og.rev 3.5.4.2 (2003/12/15) EXCELのシート名を指定できるように変更。
	 * @og.rev 3.5.4.5 (2004/01/23) 外部よりカラム列(CSV形式)を指定できるようにする。
	 * @og.rev 3.6.0.2 (2004/10/04) checkColumns,adjustColumns,allColumnCheck 属性追加
	 * @og.rev 3.7.0.5 (2005/04/11) useNumber 属性を追加します。
	 * @og.rev 3.8.0.2 (2005/06/30) nullCheck 属性追加
	 * @og.rev 3.8.5.3 (2006/08/07) readerClass 属性の初期値をシステムリソースより取得します。
	 * @og.rev 4.3.7.0 (2009/06/01) stopZero属性追加
	 * @og.rev 5.1.6.0 (2010/05/01) DBLastSqlの処理は、DBTableModelが新規作成された処理でのみ行う。
	 * @og.rev 5.1.6.0 (2010/05/01) データの読み飛ばし設定 skipRowCount 属性追加
	 * @og.rev 5.2.1.0 (2010/10/01) 読取処理でコードリソースのラベル変換を行うかどうか useRenderer 属性追加
	 * @og.rev 5.5.7.2 (2012/10/09) 複数シートを指定できるようにシート番号を指定できるように、sheetNos属性追加
	 * @og.rev 5.5.8.2 (2012/11/09) 固定値となるカラム名、アドレスの指定のための、sheetConstKeys、sheetConstAdrs属性追加
	 * @og.rev 5.5.8.2 (2012/11/09) カラム列に NULL が現れた時点で読取を中止する、nullBreakClm属性追加
	 * @og.rev 6.1.0.0 (2014/12/26) omitNames 属性を追加
	 * @og.rev 6.2.0.0 (2015/02/27) オーバーフロー時のメッセージを表示
	 * @og.rev 6.2.0.0 (2015/02/27) EXCEL出力のparamLevel初期値変更 3:標準推奨 → 4:個人設定可
	 * @og.rev 6.2.2.0 (2015/03/27) ColumnAction インナークラスでパラメータを整理する。
	 * @og.rev 6.2.3.0 (2015/05/01) 行読み飛ばし nullSkipClm追加
	 * @og.rev 6.2.5.0 (2015/06/05) ファイルエンコードの初期化を遅らせます。
	 */
	@Override
	protected void release2() {
		super.release2();
		separator		= TableReader.TAB_SEPARATOR;			// 項目区切り文字
		fileURL			= HybsSystem.sys( "FILE_URL" );
		filename		= HybsSystem.sys( "FILE_FILENAME" );	// ファイル名
		encode			= 										// 6.2.5.0 (2015/06/05) ファイルエンコーディング
		readerClass		= null;													// 6.2.0.0 (2015/02/27)
		maxRowCount		= 0 ;													// 6.2.2.0 (2015/03/27)
		displayMsg		= HybsSystem.sys( "VIEW_DISPLAY_MSG" );
		overflowMsg		= "MSG0007";	// 検索結果が、制限行数を超えましたので、残りはカットされました。
		notfoundMsg		= "MSG0077";	// 対象データはありませんでした。
		executeCount	= -1;			// 検索/実行件数
		modifyType		= null;
		command			= CMD_NEW;
		table			= null;
		tableId			= HybsSystem.TBL_MDL_KEY ;
		sheetName		= null;		// 3.5.4.2 (2003/12/15)
		sheetNos		= null;		// 5.5.7.2 (2012/10/09) 複数シートを指定できるようにシート番号を指定できるようにする。
		sheetConstKeys	= null;		// 5.5.8.2 (2012/11/09) 固定値となるカラム名(CSV形式)
		sheetConstAdrs	= null;		// 5.5.8.2 (2012/11/09) 固定値となるアドレス(行-列,行-列,・・・)
		nullBreakClm	= null;		// 5.5.8.2 (2012/11/09) 取込み条件/Sheet BREAK条件
		nullSkipClm		= null;		// 6.2.3.0 (2015/05/01) 行読み飛ばし
		columns			= null;		// 3.5.4.5 (2004/01/23)
		useNumber		= true;		// 3.7.0.5 (2005/04/11)
		stopZero		= false;	// 4.3.7.0 (2009/06/01) soptZero追加
		isMainTrans		= true;		// 5.1.6.0 (2010/05/01) DBLastSqlの処理の見直し
		skipRowCount	= 0;		// 5.1.6.0 (2010/05/01) データの読み飛ばし設定
		clmAct			= new ColumnAction();									// 6.2.2.0 (2015/03/27)
	}

	/**
	 * TableReader の実オブジェクトを生成して，BufferedReader に書き込みます。
	 *
	 * @og.rev 3.5.4.1 (2003/12/01) 引数の BufferedReader を、InputStream に変更。
	 * @og.rev 3.5.4.2 (2003/12/15) TableReader のサブクラス名変更。
	 * @og.rev 3.5.4.2 (2003/12/15) EXCELのシート名を指定できるように変更。
	 * @og.rev 3.5.4.3 (2004/01/05) 引数の InputStream を、 BufferedReader に戻す。
	 * @og.rev 3.5.4.5 (2004/01/23) TableReader に、encode を渡すように変更。
	 * @og.rev 3.5.6.0 (2004/06/18) 各種プラグイン関連付け設定を、システムパラメータ に記述します。
	 * @og.rev 3.7.0.5 (2005/04/11) useNumber 属性を追加します。
	 * @og.rev 4.0.0.0 (2005/01/31) キーの指定を、TableReader. から、TableReader_ に変更します。
	 * @og.rev 4.0.0.0 (2005/01/31) lang ⇒ ResourceManager へ変更
	 * @og.rev 5.1.6.0 (2010/05/01) データの読み飛ばし設定 skipRowCount 属性追加
	 * @og.rev 5.2.1.0 (2010/10/01) 読取処理でコードリソースのラベル変換を行うかどうか設定 useRenderer 属性追加
	 * @og.rev 5.5.7.2 (2012/10/09) 複数シートを指定できるようにシート番号を指定できるように、sheetNos属性追加
	 * @og.rev 5.5.8.2 (2012/11/09) 固定値となるカラム名、アドレスの指定のための、sheetConstKeys、sheetConstAdrs属性追加
	 * @og.rev 5.5.8.2 (2012/11/09) カラム列に NULL が現れた時点で読取を中止する、nullBreakClm属性追加
	 * @og.rev 6.0.4.0 (2014/11/28) NullPointerException が発生するので、事前にチェックします。
	 * @og.rev 6.2.0.0 (2015/02/27) TableReader クラスの呼び出し元メソッドの共通化(EXCEL,TEXT)
	 * @og.rev 6.2.2.0 (2015/03/27) ColumnAction インナークラスでパラメータを整理する。
	 * @og.rev 6.2.2.0 (2015/03/27) ColumnActionListener 対応。
	 * @og.rev 6.2.3.0 (2015/05/01) 行読み飛ばし nullSkipClm追加
	 * @og.rev 6.4.1.2 (2016/01/22) setColumnActionListener は、内部処理が走るため、他の設定が終わってから呼び出す。
	 * @og.rev 6.4.3.3 (2016/03/04) HybsSystem.newInstance(String,String) への置き換え。
	 *
	 * @param	file	出力するFileオブジェクト
	 */
	protected void create( final File file )  {
//		final String className = HybsSystem.sys( "TableReader_" + readerClass ) ;		// 4.0.0 (2005/01/31)
//
//		// NullPointerException が発生するので、事前にチェックします。
//		if( className == null ) {
//			final String errMsg = "TableReader クラスが見つかりません。class=" + "TableReader_" + readerClass;
//			throw new OgRuntimeException( errMsg );
//		}
//
//		final TableReader reader = (TableReader)HybsSystem.newInstance( className );	// 3.5.5.3 (2004/04/09)
		table = DBTableModelUtil.newDBTable();			// 6.2.1.0 (2015/03/13)

		/**
		 * ColumnActionListenerインターフェースの内部無名クラス
		 *
		 * @og.rev 6.2.2.0 (2015/03/27) ColumnActionListener 対応。
		 *
		 * @param names カラム名配列
		 */
		final ColumnActionListener listener = new ColumnActionListener() {
			private DBColumn[] dbClms ;				// 6.3.9.1 (2015/11/27) 修飾子を、なし → private に変更。

//			/**
//			 * 初期値を設定します。
//			 *
//			 * @og.rev 6.2.2.0 (2015/03/27) ColumnActionListener 対応。
//			 *
//			 * @param obj Object配列(可変長引数)
//			 */
//			public void init( final Object... obj ) {
//				// 初期化なし
//			}

			/**
			 * カラム名の配列が設定された場合に、呼び出されます。
			 *
			 * @og.rev 6.2.2.0 (2015/03/27) ColumnActionListener 対応。
			 *
			 * @param names カラム名配列
			 */
			@Override
			public void columnNames( final String[] names ) {
				final String[] nms = clmAct.makeNames( names );
				table.init( nms.length );
				dbClms = new DBColumn[nms.length];
				for( int no=0; no<nms.length; no++ ) {
					dbClms[no] = getDBColumn( nms[no] );
					table.setDBColumn( no,dbClms[no] );
				}
			}

			/**
			 * １行分のデータが設定された場合に、呼び出されます。
			 *
			 * @og.rev 6.2.2.0 (2015/03/27) ColumnActionListener 対応。
			 *
			 * @param   vals    文字列値の１行分の配列
			 * @param   rowNo   行番号(0～)
			 */
			@Override
			public void values( final String[] vals, final int rowNo ) {
				if( maxRowCount > 0 && rowNo > maxRowCount ) {		// 読み取り件数オーバーフロー
					table.setOverflow( true );
					throw new HybsOverflowException();
				}

				String[] newVals = clmAct.clmAction( vals , dbClms , rowNo );
				table.addColumnValues( newVals,modifyType,true );	// 値配列、変更タイプ、書込許可
			}
		};
		final TableReader reader = HybsSystem.newInstance( "TableReader_" , readerClass );	// 3.5.5.3 (2004/04/09)

		reader.setSeparator( separator );
		reader.setColumns( columns );					// 3.5.4.5 (2004/01/23) 、6.2.0.0 (2015/02/27) 削除
		reader.setUseNumber( useNumber );				// 3.7.0.5 (2005/04/11)
		reader.setSkipRowCount( skipRowCount );			// 5.1.6.0 (2010/05/01)
//		reader.setColumnActionListener( listener );		// 6.2.2.0 (2015/03/27)
		reader.setDebug( isDebug() );					// 5.5.7.2 (2012/10/09) デバッグ情報を出力するかどうかを指定
		// 6.2.0.0 (2015/02/27) EXCELでない場合でも、メソッドは呼び出す。(空振りします)
		reader.setSheetName( sheetName );			// 3.5.4.2 (2003/12/15)
		reader.setSheetNos( sheetNos );				// 5.5.7.2 (2012/10/09) 複数シートを指定できるようにシート番号を指定できるようにする。
		reader.setSheetConstData( sheetConstKeys,sheetConstAdrs ) ;		// 5.5.8.2 (2012/11/09) 固定値となるカラム名、アドレスの指定
		reader.setNullBreakClm( nullBreakClm ) ;	// 5.5.8.2 (2012/11/09) 取込み条件/Sheet BREAK条件
		reader.setNullSkipClm( nullSkipClm ) ;		// 6.2.3.0 (2015/05/01) 行読み飛ばし
		// 6.4.1.2 (2016/01/22) setColumnActionListener は、内部処理が走るため、他の設定が終わってから呼び出す。
		reader.setColumnActionListener( listener );		// 6.2.2.0 (2015/03/27)

		reader.readDBTable( file,encode );			// 6.2.0.0 (2015/02/27) 追加
	}

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

	/**
	 * 【TAG】可変長ファイルを作成するときの項目区切り文字をセットします。
	 *
	 * @og.tag 可変長ファイルを作成するときの項目区切り文字をセットします。
	 *
	 * @param   separator 項目区切り文字
	 */
	public void setSeparator( final String separator ) {
		this.separator = nval( getRequestParameter( separator ),this.separator );
	}

	/**
	 * 【TAG】読取元ディレクトリ名を指定します
	 *		(初期値:FILE_URL[={@og.value SystemData#FILE_URL}])。
	 *
	 * @og.tag
	 * この属性で指定されるディレクトリより、ファイルを読取ます。
	 * 指定方法は、通常の fileURL 属性と同様に、先頭が、'/' (UNIX) または、２文字目が、
	 * ":" (Windows)の場合は、指定のURLそのままのディレクトリに、そうでない場合は、
	 * fileURL = "{&#064;USER.ID}" と指定すると、FILE_URL 属性で指定のフォルダの下に、
	 * さらに、各個人ID別のフォルダを作成して、そこを操作します。
	 * (初期値:システム定数のFILE_URL[={@og.value SystemData#FILE_URL}])。
	 *
	 * @og.rev 4.0.0.0 (2005/01/31) StringUtil.urlAppend メソッドの利用
	 * @og.rev 4.0.0.0 (2007/11/20) 指定されたディレクトリ名の最後が"\"or"/"で終わっていない場合に、"/"を付加する。
	 * @og.rev 6.4.2.1 (2016/02/05) URLの最後に、"/" を追加する処理を廃止。
	 *
	 * @param	url 読取元ディレクトリ名
	 * @see		org.opengion.hayabusa.common.SystemData#FILE_URL
	 */
	public void setFileURL( final String url ) {
		final String furl = nval( getRequestParameter( url ),null );
		if( furl != null ) {
//			final char ch = furl.charAt( furl.length()-1 );
//			if( ch != '/' && ch != '\\' ) { furl = furl + "/"; }
			fileURL = StringUtil.urlAppend( fileURL,furl );
		}
	}

	/**
	 * 【TAG】ファイルを作成するときのファイル名をセットします
	 *		(初期値:FILE_FILENAME[={@og.value SystemData#FILE_FILENAME}])。
	 *
	 * @og.tag ファイルを作成するときのファイル名をセットします。
	 * (初期値:システム定数のFILE_FILENAME[={@og.value SystemData#FILE_FILENAME}])。
	 *
	 * @param   filename ファイル名
	 * @see		org.opengion.hayabusa.common.SystemData#USE_SQL_INJECTION_CHECK
	 */
	public void setFilename( final String filename ) {
		this.filename = nval( getRequestParameter( filename ),this.filename );
	}

	/**
	 * 【TAG】ファイルを作成するときのファイルエンコーディング名をセットします
	 *		(初期値:FILE_ENCODE[={@og.value SystemData#FILE_ENCODE}])。
	 *
	 * @og.tag
	 * readerClass="AutoReader" の場合、ここで設定した encode が優先されます。
	 * readerClass="Text" の場合、encode が指定されていない場合は、初期値 の FILE_ENCODE が使用されます
	 *
	 * Shift_JIS,MS932,Windows-31J,UTF-8,ISO-8859-1,UnicodeLittle
	 * (初期値:システム定数のFILE_ENCODE[={@og.value SystemData#FILE_ENCODE}])。
	 *
	 * @og.rev 2.2.0.0 (2002/12/17) 中国語(国際化)対応 エンコードの取得方法変更
	 * @og.rev 3.1.3.0 (2003/04/10) FILE_ENCODE から、エンコード情報を取得する。
	 *
	 * @param   enc ファイルエンコーディング名
	 * @see     <a href="http://www.iana.org/assignments/character-sets">IANA Charset Registry</a>
	 * @see		org.opengion.hayabusa.common.SystemData#FILE_ENCODE
	 */
	public void setEncode( final String enc ) {
		encode = nval( getRequestParameter( enc ),encode );
	}

	/**
	 * 【TAG】実際に読み出すクラス名の略称(TableReader_**** の ****)をセットします
	 *		(初期値:TABLE_READER_DEFAULT_CLASS[={@og.value SystemData#TABLE_READER_DEFAULT_CLASS}])。
	 *
	 * @og.tag
	 * 実際に読み出すクラス名(の略称)をセットします。
	 * これは、org.opengion.hayabusa.io 以下の TableReader_**** クラスの **** を
	 * 与えます。これらは、TableReader インターフェースを継承したサブクラスです。
	 * 属性クラス定義の {@link org.opengion.hayabusa.io.TableReader TableReader} を参照願います。
	 * {@og.doc03Link readerClass TableReader_**** クラス}
	 * @og.rev 3.1.3.0 (2003/04/10) FILE_ENCODE から、エンコード情報を取得する。
	 *
	 * "AutoReader" は特別な名前で、Excel と Text(テキスト) を以下の順番で試します。
	 * Excel,Calc,Text(UnicodeLittle),Text(Windows-31J),Text(Windows-31J),Text(UTF-8),Text(EUC-JP)
	 * Excel については、拡張子を自動判定して、(xlsx か xls) 適切な処理を行います。
	 * 従来からの 拡張子のみ、xls のテキストファイルは、#NAME を見つけることができないため、エラーになり、
	 * 次のText読み取りにゆだねられます。
	 * UTF-8 のTEXTとWindows-31JのTEXTは、ヘッダー部での区別ができないため、java.nio.file.Files と Pathを
	 * 使用した読み取り方式に変更しています。
	 * "AutoReader" に設定した場合は、上記の様に、encode を順番に確かめるため、encode属性の指定は無視されます。
	 *		(初期値:TABLE_READER_DEFAULT_CLASS[={@og.value SystemData#TABLE_READER_DEFAULT_CLASS}])。
	 *
	 * @og.rev 6.2.1.0 (2015/03/13) Default廃止に伴い、Defaultが指定された場合は、Textに置き換える。
	 *
	 * @param   readerCls クラス名(の略称)
	 * @see		org.opengion.hayabusa.io.TableReader  TableReaderのサブクラス
	 */
	public void setReaderClass( final String readerCls ) {
		readerClass = nval( getRequestParameter( readerCls ),readerClass );

		// 6.2.1.0 (2015/03/13) 互換性の為。
		if( "Default".equals( readerClass ) ) { readerClass = "Text" ; }
	}

	/**
	 * 【TAG】読取時の最大取り込み件数をセットします(初期値:0:無制限)。
	 *
	 * @og.tag
	 * DBTableModelのデータとして登録する最大件数をこの値に設定します。
	 * サーバーのメモリ資源と応答時間の確保の為です。
	 * 0 をセットすると、無制限になります。
	 * (初期値:0:無制限)
	 *
	 * @og.rev 5.5.8.5 (2012/11/27) 0を無制限として処理します。
	 * @og.rev 6.2.2.0 (2015/03/27) 初期値を、無制限に変更
	 *
	 * @param   count 最大件数
	 */
	public void setMaxRowCount( final String count ) {
		maxRowCount = nval( getRequestParameter( count ),maxRowCount );
	}

	/**
	 * 【TAG】読取時の最大エラー件数をセットします (初期値:{@og.value #ERROR_ROW_COUNT})。
	 *
	 * @og.tag
	 * DBTableModelのデータチェックを行う場合、エラーの最大件数をこの値に設定します。
	 * エラー最大件数がこの値を超えると、処理を打ち切ります。
	 * 0 をセットすると、無制限になります。
	 * (初期値:{@og.value #ERROR_ROW_COUNT})。
	 *
	 * @og.rev 6.2.2.0 (2015/03/27) 読取時の最大エラー件数(errRowCount) を新規追加
	 *
	 * @param   count 最大件数
	 */
	public void setErrRowCount( final String count ) {
		clmAct.errRowCount = nval( getRequestParameter( count ),ERROR_ROW_COUNT );
	}

	/**
	 * 【TAG】コマンド (NEW,RENEW)をセットします(初期値:NEW)。
	 *
	 * @og.tag
	 * コマンドは,HTMLから(get/post)指定されますので,CMD_xxx で設定される
	 * フィールド定数値のいづれかを、指定できます。
	 * 何も設定されない、または、null の場合は、"NEW" が初期値にセットされます。
	 *
	 * @param	cmd コマンド (public static final 宣言されている文字列)
	 * @see		<a href="../../../../constant-values.html#org.opengion.hayabusa.taglib.ReadTableTag.CMD_NEW">コマンド定数</a>
	 */
	public void setCommand( final String cmd ) {
		final String cmd2 = getRequestParameter( cmd );
		if( cmd2 != null && cmd2.length() > 0 ) { command = cmd2.toUpperCase(Locale.JAPAN); }
	}

	/**
	 * 【TAG】query の結果を画面上に表示するメッセージIDを指定します
	 *		(初期値:VIEW_DISPLAY_MSG[={@og.value SystemData#VIEW_DISPLAY_MSG}])。
	 *
	 * @og.tag
	 * ここでは、検索結果の件数や登録された件数をまず出力し、
	 * その次に、ここで指定したメッセージをリソースから取得して
	 * 表示します。
	 * 件数を表示させる場合は、displayMsg = "MSG0033"[　件検索しました] をセットしてください。
	 * 表示させたくない場合は, displayMsg = "" をセットしてください。
	 * (初期値:システム定数のVIEW_DISPLAY_MSG[={@og.value SystemData#VIEW_DISPLAY_MSG}])。
	 *
	 * @og.rev 6.2.0.0 (2015/02/27) リクエスト変数を使用できるように修正。
	 *
	 * @param	id 処理結果表示メッセージID
	 */
	public void setDisplayMsg( final String id ) {
		final String ids = getRequestParameter( id );
		if( ids != null ) { displayMsg = ids; }
	}

	/**
	 * 【TAG】読取データが最大検索数をオーバーした場合に表示するメッセージリソースIDを指定します
	 *		(初期値:MSG0007[検索結果が、制限行数を超えましたので、残りはカットされました])。
	 *
	 * @og.tag
	 * 読取結果が、maxRowCount で設定された値より多い場合、何らかのデータは読取されず
	 * 切り捨てられたことになります。
	 * ここでは、displayMsg を表示した後、必要に応じて、このメッセージを表示します。
	 * 表示させたくない場合は, overflowMsg = "" をセットしてください。
	 * 初期値は、MSG0007[検索結果が、制限行数を超えましたので、残りはカットされました]です。
	 *
	 * @og.rev 6.2.0.0 (2015/02/27) オーバーフロー時のメッセージを表示
	 *
	 * @param	id 検索数オーバー時メッセージID
	 */
	public void setOverflowMsg( final String id ) {
		final String ids = getRequestParameter( id );
		if( ids != null ) { overflowMsg = ids; }
	}

	/**
	 * 【TAG】検索結果がゼロ件の場合に表示するメッセージリソースIDを指定します(初期値:MSG0077[対象データはありませんでした])。
	 *
	 * @og.tag
	 * ここでは、検索結果がゼロ件の場合のみ、特別なメッセージを表示させます。
	 * 従来は、displayMsg と兼用で、『0　件検索しました』という表示でしたが、
	 * displayMsg の初期表示は、OFF になりましたので、ゼロ件の場合のみ別に表示させます。
	 * 表示させたくない場合は, notfoundMsg = "" をセットしてください。
	 * 初期値は、MSG0077[対象データはありませんでした]です。
	 *
	 * @param	id ゼロ件時表示メッセージID
	 */
	public void setNotfoundMsg( final String id ) {
		final String ids = getRequestParameter( id );
		if( ids != null ) { notfoundMsg = ids; }
	}

	/**
	 * 【TAG】ファイル取り込み時の 更新タイプ [A:追加/C:更新/D:削除]を指定します。
	 *
	 * @og.tag
	 * ファイル読み込み時に、そのデータをA(追加)、C(更新)、D(削除)の
	 * 更新タイプをつけた状態にします。
	 * その状態で、そのまま、update する事が可能になります。
	 *
	 * @param   type 更新タイプ [A:追加/C:更新/D:削除]
	 */
	public void setModifyType( final String type ) {
		modifyType = getRequestParameter( type );
	}

	/**
	 * 【TAG】EXCELファイルを読み込むときのシート名を設定します(初期値:指定なし)。
	 *
	 * @og.tag
	 * EXCELファイルを読み込む時に、シート名を指定します。これにより、複数の形式の
	 * 異なるデータを順次読み込むことや、シートを指定して読み取ることが可能になります。
	 * sheetNos と sheetName が同時に指定された場合は、sheetNos が優先されます。エラーにはならないのでご注意ください。
	 * 初期値は、指定なしです。
	 *
	 * @og.rev 3.5.4.2 (2003/12/15) 新規追加
	 *
	 * @param   sheet EXCELファイルのシート名
	 * @see		#setSheetNos( String ) 
	 */
	public void setSheetName( final String sheet ) {
		sheetName = nval( getRequestParameter( sheet ),sheetName );
	}

	/**
	 * 【TAG】EXCELファイルを読み込むときのシート番号を指定します(初期値:0)。
	 *
	 * @og.tag
	 * EXCEL読み込み時に複数シートをマージして取り込みます。
	 * シート番号は、0 から始まる数字で表します。
	 * ヘッダーは、最初のシートのカラム位置に合わせます。（ヘッダータイトルの自動認識はありません。）
	 * よって、指定するシートは、すべて同一レイアウトでないと取り込み時にカラムのずれが発生します。
	 * 
	 * シート番号の指定は、CSV形式で、複数指定できます。また、N-M の様にハイフンで繋げることで、
	 * N 番から、M 番のシート範囲を一括指定可能です。また、"*" による、全シート指定が可能です。
	 * これらの組み合わせも可能です。（ 0,1,3,5-8,10-* ）
	 * ただし、"*" に関しては例外的に、一文字だけで、すべてのシートを表すか、N-* を最後に指定するかの
	 * どちらかです。途中には、"*" は、現れません。
	 * シート番号は、重複(1,1,2,2)、逆転(3,2,1) での指定が可能です。これは、その指定順で、読み込まれます。
	 * sheetNos と sheetName が同時に指定された場合は、sheetNos が優先されます。エラーにはならないのでご注意ください。
	 * 
	 * 初期値は、0（第一シート） です。
	 *
	 * @og.rev 5.5.7.2 (2012/10/09) 新規追加
	 *
	 * @param   sheet EXCELファイルのシート番号（0から始まる）
	 * @see		#setSheetName( String ) 
	 */
	public void setSheetNos( final String sheet ) {
		sheetNos = nval( getRequestParameter( sheet ),sheetNos );
		if( sheetNos != null && sheetNos.length() > 0 ) {
			boolean errFlag = false;
			for( int i=0; i<sheetNos.length(); i++ ) {
				final char ch = sheetNos.charAt(i);
				if( ch == '-' || ch == ',' ) { continue; }
				if( ch == '*' && ( i==0 || i==sheetNos.length()-1 ) ) { continue; }
				if( ch < '0' || ch > '9' ) { errFlag = true; break; }
			}
			if( errFlag ) {
				final String errMsg = "sheetNos の指定を見直してください。sheetNos=[" + sheetNos + "]";
				throw new HybsSystemException( errMsg );
			}
		}
	}

	/**
	 * 【TAG】EXCELファイルを読み込むときのシート単位の固定値を設定するためのカラム名を指定します。
	 *
	 * @og.tag
	 * カラム名は、CSV形式で指定します。
	 * これにより、シートの一か所に書かれている情報を、DBTableModel のカラムに固定値として
	 * 設定することができます。
	 * 例として、DB定義書で、テーブル名をシートの全レコードに設定したい場合などに使います。
	 * このメソッドは、isExcel() == true の場合のみ利用されます。
	 *
	 * @og.rev 5.5.8.2 (2012/11/09) 新規追加
	 *
	 * @param   constKeys 固定値となるカラム名 (CSV形式)
	 * @see		#setSheetConstAdrs( String ) 
	 */
	public void setSheetConstKeys( final String constKeys ) {
		sheetConstKeys = nval( getRequestParameter( constKeys ),null );
	}

	/**
	 * 【TAG】EXCELファイルを読み込むときのシート単位の固定値を設定するためのカラム名に対応するアドレスを指定します。
	 *
	 * @og.tag
	 * アドレスは、EXCEL上の行-列をCSV形式で指定します。
	 * 行列は、EXCELオブジェクトに準拠するため、０から始まる整数です。
	 * 0-0 ⇒ A1 , 1-0 ⇒ A2 , 0-1 ⇒ B1 になります。
	 * これにより、シートの一か所に書かれている情報を、DBTableModel のカラムに固定値として
	 * 設定することができます。
	 * 例として、DB定義書で、テーブル名をシートの全レコードに設定したい場合などに使います。
	 * このメソッドは、isExcel() == true の場合のみ利用されます。
	 *
	 * 5.7.6.3 (2014/05/23) より、
	 *   ①EXCEL表記に準拠した、A1,A2,B1 の記述も処理できるように対応します。
	 *     なお、A1,A2,B1 の記述は、必ず、英字1文字＋数字 にしてください。(A～Zまで)
	 *   ②処理中のEXCELシート名をカラムに割り当てるために、"SHEET" という記号に対応します。
	 * 例えば、sheetConstKeys="CLM,LANG,NAME" とし、sheetConstAdrs="0-0,A2,SHEET" とすると、
	 * NAMEカラムには、シート名を読み込むことができます。
	 * これは、内部処理の簡素化のためです。
	 *
	 * ちなみに、EXCELのセルに、シート名を表示させる場合の関数は、下記の様になります。
	 * =RIGHT(CELL("filename",$A$1),LEN(CELL("filename",$A$1))-FIND("]",CELL("filename",$A$1)))
	 *
	 * @og.rev 5.5.8.2 (2012/11/09) 新規追加
	 *
	 * @param   constAdrs 固定値となるアドレス (行-列,行-列,・・・)
	 * @see		#setSheetConstKeys( String ) 
	 */
	public void setSheetConstAdrs( final String constAdrs ) {
		sheetConstAdrs = nval( getRequestParameter( constAdrs ),null );
	}

	/**
	 * 【TAG】ここに指定されたカラム列に NULL が現れた時点で読取を中止します。
	 *
	 * @og.tag
	 * これは、指定のカラムは必須という事を条件に、そのレコードだけを読み取る処理を行います。
	 * 複数Sheetの場合は、次のSheetを読みます。
	 * 現時点では、Excel の場合のみ有効です。
	 *
	 * @og.rev 5.5.8.2 (2012/11/09) 新規追加
	 *
	 * @param   clm カラム列
	 */
	public void setNullBreakClm( final String clm ) {
		nullBreakClm = nval( getRequestParameter( clm ),null );
	}

	/**
	 * 【TAG】ここに指定されたカラム列に NULL が現れたレコードは読み飛ばします。
	 *
	 * @og.tag
	 * 例えば、更新対象カラムで、null の場合は、何もしない、などのケースで使用できます。
	 * 複数カラムの場合は、AND条件やOR条件などが、考えられるため、
	 * カラムを一つにまとめて、指定してください。
	 *
	 * @og.rev 6.2.3.0 (2015/05/01) 行読み飛ばし nullSkipClm追加
	 *
	 * @param   clm カラム列
	 */
	public void setNullSkipClm( final String clm ) {
		nullSkipClm = nval( getRequestParameter( clm ),null );
	}

	/**
	 * 【TAG】読取元ファイルのカラム列を、外部(タグ)より指定します。
	 *
	 * @og.tag
	 * 読取元ファイルのカラム列を、外部(タグ)より指定します。
	 * ファイルに記述された #NAME より優先して使用されます。
	 * これは、元ファイルのカラムを順番に指定のカラム名に割り当てる機能で
	 * ファイルの特定のカラム列を抜き出して取り込む機能ではありません。
	 *
	 * @og.rev 3.5.4.5 (2004/01/23) 新規作成
	 *
	 * @param   clms 読取元ファイルのカラム列 (CSV形式)
	 */
	public void setColumns( final String clms ) {
		columns = nval( getRequestParameter( clms ),columns );
	}

	/**
	 * 【TAG】読取対象外のカラム列を、外部(タグ)よりCSV形式で指定します。
	 *
	 * @og.tag
	 * 指定するカラム名に対して、読取処理を行いません。
	 * ここで指定するカラム名は、ファイルの #NAME または、columns で
	 * 指定するカラム名に対して、含まれている必要はありません。
	 * その場合は、ここでの指定は無視されます。
	 *
	 * @og.rev 6.1.0.0 (2014/12/26) omitNames 属性を追加
	 * @og.rev 6.2.2.0 (2015/03/27) ColumnAction インナークラスでパラメータを整理する。
	 *
	 * @param   clms 読取対象外のカラム列 (CSV形式)
	 */
	public void setOmitNames( final String clms ) {
		clmAct.omitNames = nval( getRequestParameter( clms ),null );
	}

	/**
	 * 読取対象外のカラム列を、追加指定します。
	 *
	 * 内部的な処理で、DirectTableInsertTag で、WRITABLE,ROWID などの
	 * データベースに存在しないカラムを、omit するための機能です。
	 * 属性定義してもよいのですが、統一的な処理方法が決まらないので、
	 * 取りあえず、暫定的に、サブクラスからのみ、して可能にしておきます。
	 * このメソッドは、setOmitNames( String ) が呼び出された後でしか
	 * 有効に機能しません。
	 *
	 * @og.rev 6.2.4.0 (2015/05/15) 無条件でOMITする名称を指定します。
	 *
	 * @param   omit 読取対象外の追加カラム列 (CSV形式)
	 */
	protected void addOmitNames( final String omit ) {
		if( clmAct.omitNames == null ) {
			clmAct.omitNames = omit;
		}
		else {
			clmAct.omitNames = "," + omit ;
		}
	}

	/**
	 * 【TAG】読取元ファイルの整合性チェックを行うカラム列をカンマ指定します。
	 *
	 * @og.tag
	 * カラムオブジェクトのDBType属性に対応したチェックを行います。
	 * 指定のカラム名をCSV形式(CSV)で複数指定できます。
	 * 全てのカラムのチェックを行う場合は、"*" を指定して下さい。
	 * 分解方法は、通常のパラメータ取得後に、CSV分解します。
	 *
	 * @og.rev 3.6.0.2 (2004/10/04) 新規追加 取り込み時チェック用
	 * @og.rev 3.8.8.5 (2007/03/09) 通常のパラメータ取得後に、CSV分解に戻します。
	 * @og.rev 6.2.2.0 (2015/03/27) ColumnAction インナークラスでパラメータを整理する。
	 *
	 * @param   clms 整合性チェックを行うカラム列 (CSV形式)
	 */
	public void setCheckColumns( final String clms ) {
		clmAct.checkColumns = nval( getRequestParameter( clms ),null );
	}

	/**
	 * 【TAG】読取元ファイルのデータ変換を行うカラム列をカンマ指定します。
	 *
	 * @og.tag
	 * カラムオブジェクトのDBType属性に対応したデータ変換を行います。
	 * 指定のカラム名をCSV形式(CSV)で複数指定できます。
	 * 全てのカラムをデータ変換する場合は、"*" を指定して下さい。
	 * 分解方法は、通常のパラメータ取得後に、CSV分解します。
	 *
	 * @og.rev 3.6.0.2 (2004/10/04) 新規追加 取り込み時データ変換
	 * @og.rev 3.8.8.5 (2007/03/09) 通常のパラメータ取得後に、CSV分解に戻します。
	 * @og.rev 6.2.2.0 (2015/03/27) ColumnAction インナークラスでパラメータを整理する。
	 *
	 * @param   clms データ変換を行うカラム列 (CSV形式)
	 */
	public void setAdjustColumns( final String clms ) {
		clmAct.adjustColumns = nval( getRequestParameter( clms ),null );
	}

	/**
	 * 【TAG】NULL チェックすべきカラム列をCSV形式(CSV形式)で指定します。
	 *
	 * @og.tag nullCheck="AAA,BBB,CCC,DDD"
	 * 分解方法は、通常のパラメータ取得後に、CSV分解します。
	 *
	 * @og.rev 3.8.0.2 (2005/06/30) 新規追加
	 * @og.rev 3.8.8.5 (2007/03/09) 通常のパラメータ取得後に、CSV分解に戻します。
	 * @og.rev 6.2.2.0 (2015/03/27) ColumnAction インナークラスでパラメータを整理する。
	 *
	 * @param   clms カラム列(CVS形式)
	 */
	public void setNullCheck( final String clms ) {
		clmAct.nullCheck = nval( getRequestParameter( clms ),null );
	}

	/**
	 * 【TAG】行番号情報を、使用している/していない[true/false]を指定します(初期値:true)。
	 *
	 * @og.tag
	 * 通常のフォーマットでは、各行の先頭に行番号が出力されています。
	 * 読取時に、#NAME 属性を使用する場合は、この行番号を無視しています。
	 * #NAME 属性を使用せず、columns 属性でカラム名を指定する場合(他システムの
	 * 出力ファイルを読み取るケース等)では、行番号も存在しないケースがあり、
	 * その様な場合に、useNumber="false" を指定すれば、データの最初から読取始めます。
	 * この場合、出力データのカラムの並び順が変更された場合、columns 属性も
	 * 指定しなおす必要がありますので、できるだけ、#NAME 属性を使用するように
	 * してください。
	 * なお、EXCEL 入力には、この設定は適用されません。(暫定対応)
	 * 初期値は、true(使用する) です。
	 *
	 * @og.rev 3.7.0.5 (2005/04/11) 新規追加
	 *
	 * @param   useNo 行番号情報 [true:使用する/false:使用しない]
	 */
	public void setUseNumber( final String useNo ) {
		useNumber = nval( getRequestParameter( useNo ),useNumber );
	}

	/**
	 * 【TAG】読込件数が０件のとき処理を続行するかどうか[true/false]を指定します(初期値:false[続行する])。
	 *
	 * @og.tag
	 * 初期値は、false(続行する)です。
	 *
	 * @og.rev 4.3.7.0 (2009/06/01) 新規追加
	 *
	 * @param  cmd ０件時停止可否 [true:処理を中止する/false:続行する]
	 */
	public void setStopZero( final String cmd ) {
		stopZero = nval( getRequestParameter( cmd ), stopZero );
	}

	/**
	 * 【TAG】(通常使いません)タグで処理される処理がメインとなるトランザクション処理かどうかを指定します(初期値:true)。
	 *
	 * @og.tag
	 * この値は、ファイルダウンロード処理に影響します。この値がtrueに指定された時にcommitされたDBTableModelが
	 * ファイルダウンロードの対象の表になります。
	 *
	 * このパラメーターは、通常、各タグにより実装され、ユーザーが指定する必要はありません。
	 * 但し、1つのJSP内でDBTableModelが複数生成される場合に、前に処理したDBTableModelについてファイルダウンロードをさせたい
	 * 場合は、後ろでDBTableModelを生成するタグで、明示的にこの値をfalseに指定することで、ファイルダウンロード処理の対象から
	 * 除外することができます。
	 *
	 * @og.rev 5.1.6.0 (2010/05/01) 新規作成
	 *
	 * @param  flag メイントランザクションかどうか [true:メイン/false:その他]
	 */
	public void setMainTrans( final String flag ) {
		isMainTrans = nval( getRequestParameter( flag ),isMainTrans );
	}

	/**
	 * 【TAG】(通常は使いません)データの読み飛ばし件数を設定します。
	 *
	 * @og.tag
	 * TAB区切りテキストやEXCEL等のデータの読み始めの初期値を指定します。
	 * ファイルの先頭行が、０行としてカウントしますので、設定値は、読み飛ばす
	 * 件数になります。(１と指定すると、１件読み飛ばし、２行目から読み込みます。)
	 * 読み飛ばしは、コメント行などは、無視しますので、実際の行数分読み飛ばします。
	 * ＃NAME属性や、columns 属性は、有効です。
	 *
	 * @og.rev 5.1.6.0 (2010/05/01) 新規作成
	 *
	 * @param	count 読み始めの初期値
	 */
	public void setSkipRowCount( final String count ) {
		skipRowCount = nval( getRequestParameter( count ),skipRowCount );
	}

	/**
	 * 【TAG】読取処理でKEY:VAL形式のコードリソースから、KEYを取り出す処理を行うかどうかを指定します
	 *		(初期値:USE_TABLE_READER_RENDERER[={@og.value SystemData#USE_TABLE_READER_RENDERER}])。
	 *
	 * @og.tag
	 * TableWriter_Renderer 系のクラスで出力した場合は、コードリソースがラベルで出力されます。
	 * そのファイルを読み取ると、当然、エラーになります。
	 * ここでは、コードリソースのカラムに対して、ラベルからコードを求める逆変換を行うことで、
	 * Renderer 系で出力したファイルを取り込むことができるようにします。
	 *
	 * ここでは、TableWriter 系と同様に、TableReader_Renderer 系のクラスを作るのではなく、
	 * 属性値のフラグで、制御します。
	 * 将来的には、TableWriter 系も廃止して、同様のフラグで制御するように変更する予定です。
	 * (初期値:システム定数のUSE_TABLE_READER_RENDERER[={@og.value SystemData#USE_TABLE_READER_RENDERER}])。
	 *
	 * @og.rev 5.2.1.0 (2010/10/01) 新規作成
	 * @og.rev 6.2.2.0 (2015/03/27) ColumnAction インナークラスでパラメータを整理する。
	 *
	 * @param  flag ラベル逆変換を行うかどうか [true:行う/false:行わない]
	 * @see		org.opengion.hayabusa.common.SystemData#USE_TABLE_READER_RENDERER
	 */
	public void setUseRenderer( final String flag ) {
		clmAct.useRenderer = nval( getRequestParameter( flag ),HybsSystem.sysBool( "USE_TABLE_READER_RENDERER" ) );
	}

	/**
	 * カラム処理を行う、内部クラス
	 *
	 * カラム個別に行う処理をまとめたクラスです。
	 * omitNames        ： 読取対象外のカラム列を、外部(タグ)よりCSV形式で指定します
	 * adjustColumns    ： 読取元ファイルのデータ変換を行うカラム列をカンマ指定します
	 * checkColumns     ： 読取元ファイルの整合性チェックを行うカラム列をカンマ指定します
	 * nullCheck        ： NULL チェックすべきカラム列をCSV形式(CVS形式)で指定します
	 * 
	 * 名前配列設定で対象のカラムをピックアップし、値設定処理で、個々に処理します。
	 *
	 * @og.rev 6.2.2.0 (2015/03/27) ColumnAction 新規作成
	 */
	protected static final class ColumnAction {
		private String	omitNames		;		// 読取対象外のカラム列を、外部(タグ)よりCSV形式で指定します
		private String	adjustColumns	;		// 読取元ファイルのデータ変換を行うカラム列をカンマ指定します
		private String	checkColumns	;		// 読取元ファイルの整合性チェックを行うカラム列をカンマ指定します
		private String	nullCheck		;		// NULL チェックすべきカラム列をCSV形式(CVS形式)で指定します
		private int		errRowCount		= ERROR_ROW_COUNT;		// NULL チェックすべきカラム列をCSV形式(CVS形式)で指定します
		private boolean	useRenderer		;		// 読取処理でKEY:VAL形式のコードリソースから、KEYを取り出す処理を行うかどうかを指定
		private boolean	isDebug			;		// debug ﾌﾗｸﾞ
		private ErrorMessage errMsgObj	;		// 6.2.5.0 (2015/06/05) 初期化します。

		private int[]		clmNos		;		// 新名前配列に対応した、値配列のアドレス
		private int[]		actFlg		;		// カラム処理の実行有無のフラグ管理

		private static final int OMIT    = -1;		// OMIT だけ別。clmNosで、OMITフラグは除外する。
		private static final int ADJUST  = 1;		// adjustColumns 処理フラグ
		private static final int CHECK   = 2;		// checkColumns 処理フラグ
		private static final int NULL_CH = 4;		// nullCheck  処理フラグ

		/**
		 * 名前配列が設定された場合に、対象カラムのピックアップを行います。
		 * このクラスでは、名前の再設定で、初期化されます。
		 *
		 * @og.rev 6.2.2.0 (2015/03/27) ColumnAction 新規作成
		 * @og.rev 6.2.5.0 (2015/06/05) ErrorMessage を、初期化します。
		 *
		 * @param	orgNms オリジナル名前配列
		 * @return	OMIT等考慮した、新名前配列
		 */
		public String[] makeNames( final String[] orgNms ) {
			errMsgObj = new ErrorMessage( "Check Columns Error!" );		// 6.2.5.0 (2015/06/05) 初期化します。

			// omit だけ、他のフラグセットと異なり、処理された数は、除外されるので逆になります。
			final int[] temp = new int[orgNms.length];
			final int size = orgNms.length - actionFlagSet( omitNames, orgNms, OMIT, temp );

			if( size == 0 ) {	// 有りえないが、omitNames="*" を誤って指定した場合にはありうる。
				final String errMsg = "カラムがありません。omitNames=[" + omitNames + "]";
				throw new HybsSystemException( errMsg );
			}

			final String[] names = new String[size];
			clmNos = new int[size];
			int no = 0;
			for( int i=0; i<temp.length; i++ ) {
				if( temp[i] != OMIT ) {				// 除外しない場合
					names[no] = orgNms[i];			// 名前配列に、オリジナルの名前をセット
					clmNos[no]= i;					// カラムアドレスをセット(TableModelのカラム番号になる)
					no++ ;
				}
			}

			actFlg = new int[size];					// 新名前配列に対応した、処理フラグを作成(フラグを加算)
			actionFlagSet( adjustColumns, names, ADJUST,  actFlg );		// それぞれのフラグが加算される。
			actionFlagSet( checkColumns,  names, CHECK,   actFlg );
			actionFlagSet( nullCheck,     names, NULL_CH, actFlg );

			return names;
		}

		/**
		 * 値配列に対して、変換処理、チェック処理を行った結果を返します。
		 *
		 * @og.rev 6.2.2.0 (2015/03/27) ColumnAction 新規作成
		 * @og.rev 6.3.9.0 (2015/11/06) コンストラクタで初期化されていないフィールドを null チェックなしで利用している(findbugs)
		 * @og.rev 6.4.1.2 (2016/01/22) HybsOverflowException をthrow するとき、最大件数を引数に渡す。
		 *
		 * @param	vals	値配列
		 * @param	dbClms	カラムオブジェクト配列
		 * @param	row		行番号(エラーメッセージの表示用)
		 * @return	変換、チェック処理結果の値配列
		 */
		public String[] clmAction( final String[] vals , final DBColumn[] dbClms , final int row ) {
			// 6.3.9.0 (2015/11/06) コンストラクタで初期化されていないフィールドを null チェックなしで利用している(findbugs)
			if( clmNos == null || actFlg == null ) {
				final String errMsg = "#makeNames(String[])を先に実行しておいてください。" ;
				throw new OgRuntimeException( errMsg );
			}

			final String[] rtnVals = new String[clmNos.length] ;
			boolean isError = false;

			for( int no=0; no<clmNos.length; no++ ) {
				String val = vals[clmNos[no]];
				if( useRenderer ) {												// useRenderer(KEY:VAL) 処理
					val = dbClms[no].getReaderValue( val );
				}
				if( (actFlg[no] & ADJUST) == ADJUST ) {							// adjustColumns 処理
					val = dbClms[no].valueSet( val );
				}
				if( (actFlg[no] & CHECK)  == CHECK  ) {							// checkColumns 処理
					final ErrorMessage msg = dbClms[no].valueCheck( val );
					if( msg.getKekka() > ErrorMessage.OK ) {
						isError = true;
						errMsgObj.append( row+1,msg );
					}
				}
				if( (actFlg[no] & NULL_CH) == NULL_CH ) {						// nullCheck 処理
					if( val == null || val.isEmpty() ) {
						isError = true;
						// ERR0012 : 指定のデータがセットされていません。(NULLエラー)。key={0}
						errMsgObj.addMessage( row+1,ErrorMessage.NG,"ERR0012",dbClms[no].getLabel() );
					}
				}
				rtnVals[no] = val;
			}

			// 5.5.7.2 (2012/10/09) エラー時のデバッグ出力
			if( isDebug && isError ) {
				errMsgObj.addMessage( row+1,ErrorMessage.NG,"Debug",vals );
			}

			// isDebug == true 時には、件数は倍になるが、仕方がない。
//			if( errMsgObj.size() > errRowCount ) { throw new HybsOverflowException(); }
			if( errMsgObj.size() > errRowCount ) { throw new HybsOverflowException( errRowCount ); }		// 6.4.1.1 (2016/01/16)

			// adjustColumns 処理結果を反映させます。
			return rtnVals;
		}

		/**
		 * ErrorMessageオブジェクトを返します。
		 *
		 * @og.rev 6.2.5.0 (2015/06/05) 新規作成
		 *
		 * @return	ErrorMessageオブジェクト
		 */
		public ErrorMessage getErrorMessage() {
			return errMsgObj ;
		}

		/**
		 * 処理実行可否を判断し、フラグをセットします。
		 *
		 * フラグのセットは、"|"(論理和)するのが良いのですが、OMITもここで判定している関係で、
		 * 単なる加算にしています。
		 * (マイナスをフラグにしているので、マイナスの論理和が良く判らないためです(^^))
		 *
		 * @og.rev 6.2.2.0 (2015/03/27) ColumnAction 新規作成
		 *
		 * @param	clms	指定のカラム名 (CSV形式)
		 * @param	names	名前配列
		 * @param	flag	設定するフラグ(既存の配列に加算)
		 * @param	actFlg	オリジナル名前配列
		 * @return	処理を行った件数
		 */
		private int actionFlagSet( final String clms , final String[] names , final int flag , final int[] actFlg ) {
			int cnt = 0;
			if( clms != null ) {
				final String clmStr = ',' + clms.replaceAll( " ","" ) + ',' ;		// 前後に カンマ(',') を追加、中間スペース削除
				for( int i=0; i<names.length; i++ ) {
					// "*" はループの外で判定して、２回それぞれでループを回す方が早い・・・かな？
					if( "*".equals( clms ) || clmStr.indexOf( ',' + names[i] + ',' ) >= 0 ) {
						cnt++ ;
						actFlg[i] += flag;			// 一致するカラムにフラグを加算する。
					}
				}
			}
			return cnt ;
		}
	}

//	/**
//	 * シリアライズ用のカスタムシリアライズ書き込みメソッド。
//	 *
//	 * @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();
//	}

	/**
	 * AutoReader用の 簡易パラメータ管理用の内部クラスです。
	 *
	 * ３つのパラメータ(クラス、エンコード、サフィックス)を管理します。
	 *
	 * CLASS	TableReader_**** クラス の ****部分を指定します。(Excel,Calc,Text,PIO など)
	 * ENCODE	クラスが、Text の場合のエンコード(UnicodeLittle,Windows-31J,UTF-8,EUC-JP など)
	 * SUFIX	処理対象の拡張子(xls,xlsx,xlsm,ods など)
	 *
	 * @og.rev 6.2.5.0 (2015/06/05) 新規追加。AutoReader用の 簡易パラメータ管理用の内部クラス
	 */
	private static final class AutoReaderParam {
		public final String CLASS	;
		public final String ENCODE	;
		public final String SUFIX	;

		/**
		 * AutoReader用の 簡易パラメータ管理用の内部クラスのコンストラクターです。
		 *
		 * ３つのパラメータ(クラス、エンコード、サフィックス)を管理します。
		 *
		 * @og.rev 6.2.5.0 (2015/06/05) 新規追加。AutoReader用の 簡易パラメータ管理用の内部クラス
		 *
		 * @param	cls	TableReader_**** クラス の ****部分を指定します。(Excel,Calc,Text,PIO など)
		 * @param	enc	クラスが、Text の場合のエンコード(UnicodeLittle,Windows-31J,UTF-8,EUC-JP など)
		 * @param	sfx	処理対象の拡張子(xls,xlsx,xlsm,ods など) nullの場合は、すべてを対象とする。
		 */
		public AutoReaderParam( final String cls , final String enc , final String sfx ) {
			CLASS	= cls ;
			ENCODE	= enc ;
			SUFIX	= sfx == null ? null : ',' + sfx + ',' ;		// 判定用なので、
		}

		/**
		 * 引数のサフィックスが、対象かどうか、判定します。
		 * 対象の場合は、true 、対象でない場合は、false を返します。
		 *
		 * @og.rev 6.2.5.0 (2015/06/05) 新規追加。AutoReader用の 簡易パラメータ管理用の内部クラス
		 *
		 * @param	sufix	比較対象の拡張子(小文字のみ判定可能)
		 * @return	対象かどうか[true:対象/false:対象外]
		 */
		public boolean useSufix( final String sufix ) {
			return SUFIX == null || SUFIX.contains( ',' + sufix + ',' ) ;
		}

		/**
		 * オブジェクトの文字列表現を返します。
		 * 対象の場合は、true 、対象でない場合は、false を返します。
		 *
		 * @og.rev 6.2.5.0 (2015/06/05) 新規追加。AutoReader用の 簡易パラメータ管理用の内部クラス
		 *
		 * @return	このオブジェクトの文字列表現
		 */
		@Override
		public String toString() {
			return "class=[" + CLASS + "] , encode=[" + ENCODE + "] , sufix=[" + SUFIX + "]" ;
		}
	}

	/**
	 * このオブジェクトの文字列表現を返します。
	 * 基本的にデバッグ目的に使用します。
	 *
	 * @return このクラスの文字列表現
	 * @og.rtnNotNull
	 */
	@Override
	public String toString() {
		return ToString.title( this.getClass().getName() )
				.println( "VERSION"			,VERSION	)
				.println( "separator"		,separator		)
				.println( "fileURL" 		,fileURL 		)
				.println( "filename"		,filename		)
				.println( "encode"			,encode			)
				.println( "readerClass" 	,readerClass 	)
				.println( "maxRowCount"		,maxRowCount	)
				.println( "displayMsg"		,displayMsg		)
				.println( "executeCount"	,executeCount	)
				.println( "modifyType"		,modifyType		)
				.println( "command"			,command		)
				.println( "tableId"			,tableId		)
				.println( "sheetName"		,sheetName		)
				.println( "sheetNos"		,sheetNos		)		// 5.5.7.2 (2012/10/09)
				.println( "columns"			,columns		)
				.println( "useNumber"		,useNumber		)
				.println( "Other..."	,getAttributes().getAttribute() )
				.fixForm().toString() ;
	}
}
