/*
 * 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 static org.opengion.fukurou.util.StringUtil.*;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.zip.GZIPOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.servlet.ServletResponse ;
import javax.servlet.http.HttpServletResponse ;
import javax.servlet.jsp.JspWriter ;

import org.opengion.fukurou.model.FileOperation;
import org.opengion.fukurou.util.Closer ;
import org.opengion.fukurou.util.FileUtil;
import org.opengion.fukurou.util.HybsEntry;
import org.opengion.fukurou.util.StringUtil ;
import org.opengion.hayabusa.common.HybsSystem;
import org.opengion.hayabusa.common.HybsSystemException;
import org.opengion.hayabusa.db.DBTableModel;
import org.opengion.hayabusa.io.HybsFileOperationFactory;
import org.opengion.hayabusa.io.TableWriter;

/**
 * DBTableModelオブジェクトを指定のファイルに出力するタグです。
 *
 * データ(DBTableModel)と、コントローラ(WriteTableTagForm)を与えて、
 * 外部からコントロールすることで、各種形式で データ(DBTableModel)を表示できます。
 * writeTableタグ に対して、コマンドを与えることにより、内部のコントローラの
 * 実装に対応した、 形式でデータを作成します。
 * 書込み件数をリクエスト変数WRITE.COUNTに出力しています。
 *
 * @og.formSample
 * ●形式：
 *     &lt;og:writeTable
 *         fileURL   = "{&#064;USER.ID}"    保存先ディレクトリ名
 *         filename  = "{&#064;filename}"   保存ファイル名
 *         encode    = "UnicodeLittle"      保存ファイルエンコード名
 *     /&gt;
 *
 * ●body：あり(EVAL_BODY_BUFFERED:BODYを評価し、{&#064;XXXX} を解析します)
 *
 * ●Tag定義：
 *   &lt;og:writeTable
 *       writerClass        【TAG】実際に書き出すクラス名の略称(TableWriter_**** クラスの ****)を指定します(初期値:Default)
 *       separator          【TAG】可変長ファイルを作成するときの項目区切り文字をセットします (初期値:TableWriter#TAB_SEPARATOR[= ])
 *       headerSequence     【TAG】DBTableModelの出力順(LNSCD など)をセットします
 *       fileURL            【TAG】ファイル保存先ディレクトリ名を指定します
 *       filename           【TAG】ファイルを作成するときのファイル名をセットします (初期値:FILE_FILENAME[=UnicodeLittle])
 *       sheetName          【TAG】EXCELファイルを書き出すときのシート名を設定します
 *       beforeDelete       【TAG】事前にファイルを削除するかどうかをセットします (初期値:false)
 *       encode             【TAG】ファイルを作成するときのファイルエンコーディング名をセットします (初期値:FILE_ENCODE[=UnicodeLittle])
 *       fileAppend         【TAG】追加モードで書き込むかどうか[true/false]を指定します(初期値:false[新規モード])
 *       direct             【廃止】結果をダイレクトにEXCEL起動するかどうか[true/false]を指定します(初期値:false[ファイル])
 *       zip                【TAG】結果をファイルに出力するときに、ZIPで圧縮するかどうか[true/false]を指定します(初期値:false)
 *       tableId            【TAG】(通常使いません)sessionから所得する DBTableModelオブジェクトの ID
 *       scope              【TAG】キャッシュする場合のスコープ[request/page/session/applicaton]を指定します(初期値:session)
 *       disposition        【TAG】Content-Disposition (inline:埋め込む/attachment:ダイアログを起動)を指定します(初期値:attachment)
 *       refFileURL         【TAG】EXCEL雛型参照ファイルのディレクトリ名をセットします
 *       refFilename        【TAG】EXCEL雛型参考ファイル名をセットします
 *       refSheetName       【TAG】EXCEL雛型参考ファイルのシート名を設定します
 *       sheetOverwrite     【TAG】EXCELでsheetNameでの指定シート名に対して上書きを行うかどうかを指定します。
 *       recalcSheetName    【TAG】EXCELで、出力処理の最後にセルの計算式の再計算をさせるシート名をカンマ区切りで指定します。
 *       useNumber          【TAG】行番号情報を、出力する/しない[true/false]を指定します(初期値:true)
 *       columns            【TAG】書き込み先ファイルのカラム列を、外部(タグ)より指定します
 *       useRenderer        【TAG】書込処理でコードリソースのラベル変換を行うかどうかを指定します (初期値:USE_TABLE_WRITER_RENDERER[=false])
 *       selectedAll        【TAG】チェック行のみを対象にするかを指定します(初期値:true)。
 *       fontName           【TAG】EXCEL出力時のデフォルトフォント名を設定します (初期値:TABLE_WRITER_DEFAULT_FONT_NAME[=ＭＳ Ｐゴシック])
 *       fontPoint          【TAG】EXCEL出力時のデフォルトフォントポイント数を設定します(初期値:TABLE_WRITER_DEFAULT_FONT_POINTS[=11])
 *       skipRowCount       【TAG】(通常は使いません)データの書き込み開始位置を設定します
 *       language           【TAG】タグ内部で使用する言語コード[ja/en/zh/…]を指定します
 *       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)は、このタグは使用されます(初期値:true) 5.7.7.2 (2014/06/20)
 *       caseNull           【TAG】指定の値が、null/ゼロ文字列 の場合は、このタグは使用されます(初期値:true) 5.7.7.2 (2014/06/20)
 *       storageType		【TAG】保存先ストレージタイプを指定します
 *       bucketName			【TAG】保存先バケット名を指定します
 *       debug              【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false)
 *   &gt;   ... Body ...
 *   &lt;/og:writeTable&gt;
 *
 * ●使用例
 *     &lt;og:writeTable ･････ &gt;
 *         &lt;og:writeTableParam
 *             key  = "Tablename"  value="GE12"
 *         /&gt;
 *         &lt;og:writeTableParam
 *             key  = "First"             First:最初に登録
 *         &gt;
 *                      insert into GE12bk
 *                         select * from GE12
 *                         where SYSTEM_ID='**'
 *         &lt;/og:writeTableParam
 *         &lt;og:writeTableParam
 *             key  = "First"             First:の２番目に登録
 *         &gt;
 *              delete from GE12 where SYSTEM_ID='**' and KBSAKU='0'
 *         &lt;/og:writeTableParam
 *         &lt;og:writeTableParam
 *             key  = "Last"              Last:最後に登録
 *         &gt;
 *              update GE12 set XXXX='YYYY' where SYSTEM_ID='**' and KBSAKU='0'
 *         &lt;/og:writeTableParam
 *     &lt;/og:writeTableParam
 *
 * @og.rev 5.10.9.0 (2019/03/01) oota クラウドストレージ対応を追加。(Fileクラスを拡張)
 * 
 * @og.group ファイル出力
 *
 * @version  4.0
 * @author   Kazuhiko Hasegawa
 * @since    JDK5.0,
 */
public class WriteTableTag extends CommonTagSupport {
	//* このプログラムのVERSION文字列を設定します。	{@value} */
	private static final String VERSION = "5.7.9.0 (2014/08/08)" ;

	private static final long serialVersionUID = 579020140808L ;

	private final String  BASE_URL	= HybsSystem.sys( "FILE_URL" );
	
	private String	separator		= TableWriter.TAB_SEPARATOR;	 // 項目区切り文字
//	private String	headerSequence	= null;				// ヘッダー項目の並び順
	private String	headerSequence	= HybsSystem.sys( "TABLE_WRITER_DEFAULT_HEADERSEQ" );	// 5.9.20.2 (2017/05/19)
	private String	fileURL 		= BASE_URL;
	private String	filename		= HybsSystem.sys( "FILE_FILENAME" );   // ファイル名
	private String	sheetName		= "Sheet1" ;		// 3.5.4.2 (2003/12/15)
	private String	refFileURL		= BASE_URL;			// 3.5.4.3 (2004/01/05)
	private String	refFilename 	= null;				// 3.5.4.3 (2004/01/05)
	private String	refSheetName	= null ;			// 3.5.4.3 (2004/01/05)
	private String	fontName		= HybsSystem.sys( "TABLE_WRITER_DEFAULT_FONT_NAME" );			// 3.8.5.3 (2006/08/07)
	private String	fontPoint	 	= HybsSystem.sys( "TABLE_WRITER_DEFAULT_FONT_POINTS" );			// 3.8.5.3 (2006/08/07)
	private String	encode			= HybsSystem.sys( "FILE_ENCODE" );	// ファイルエンコーディング  "DEFAULT","JISAutoDetect" ,"JIS", "EUC_JP", "MS932", "SJIS" , "Windows-31J" , "Shift_JIS"
	private String	writerClass 	= HybsSystem.sys( "TABLE_WRITER_DEFAULT_CLASS" );		// 3.8.5.3 (2006/08/07)
	private boolean	fileAppend		= false;			// ファイルをAPPENDモードで出力するか
	private boolean	direct			= false;
	private boolean	zip 			= false;
	private String  disposition     = "attachment";		// 3.8.0.9 (2005/10/17) Content-Disposition 初期値変更 inline ⇒ attachment

	private transient DBTableModel table	  = null;
	private String	tableId 		= HybsSystem.TBL_MDL_KEY ;
	private String	directory		= null ;			// 3.8.6.0 (2006/08/23)

	private transient List<HybsEntry>	param	= null ;		// 4.0.0 (2005/02/28)

	private boolean	useNumber		= true;				// 3.7.0.2 (2005/02/14)
	// 4.0.0 (2005/12/31) 外部よりカラム列(カンマ区切り)を指定できるようにする。
	private String		columns		= null;
	// 5.2.1.0 (2010/10/01) 書込処理でコードリソースのラベル変換を行うかどうか
	private boolean	useRenderer		= HybsSystem.sysBool( "USE_TABLE_WRITER_RENDERER" );	// 5.2.1.0 (2010/10/01)

	// 5.5.5.5 (2012/08/24) チェック対応
	private boolean selectedAll		= true;				// 5.5.5.5 (2012/08/24)

	// 5.5.9.1 (2012/12/07) 事前にファイルを削除するかどうか。互換性のため、false に設定。推奨は、true
	private boolean	beforeDelete	= false;			// 5.5.9.1 (2012/12/07) 事前にファイルを削除するかどうか。

	private int		skipRowCount	= 0;				// 5.7.9.0 (2014/08/08) データの書き込み開始位置設定

	// 5.9.12.1 (2016/09/09)
	private boolean	sheetOverwrite	= false;	// 5.9.12.1(2016/09/09)
	private String recalcSheetName; // 5.9.12.1 (2016/09/09)

	private String storageType		= null;		// 5.10.9.0 (2019/03/01) ADD
	private String bucketName		= null;		// 5.10.9.0 (2019/03/01) ADD
	/**
	 * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。
	 *
	 * @og.rev 5.5.9.1 (2012/12/07) 事前にファイルを削除するかどうか（beforeDelete）フラグを追加
	 * @og.rev 5.7.7.2 (2014/06/20) caseKey,caseVal,caseNN,caseNull 属性を追加
	 * @og.rev 5.10.9.0 (2019/03/01) クラウドストレージ対応を追加
	 *
	 * @return	後続処理の指示( EVAL_BODY_BUFFERED )
	 */
	@Override
	public int doStartTag() {
		// 5.7.7.2 (2014/06/20) caseKey,caseVal,caseNN,caseNull 属性を追加
		if( !useTag() ) { return SKIP_BODY ; }

		directory = HybsSystem.url2dir( fileURL );		// 5.5.9.1 (2012/12/07) doEndTag() から移動

		// 5.5.9.1 (2012/12/07) 事前にファイルを削除するかどうか
		if( beforeDelete && !fileAppend ) {
			File delFile = null;
			// 5.10.9.0 (2019/03/01) MODIFY
			//if( zip ) { delFile = new File(directory, filename + ".zip" ); }
			//else { delFile = new File(directory, filename); }
			if( zip ) { delFile = HybsFileOperationFactory.create(storageType, bucketName, directory, filename + ".zip" ); }
			else { delFile = HybsFileOperationFactory.create(storageType, bucketName, directory, filename); }
			if( delFile.exists() ) { delFile.delete(); }
		}

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

	/**
	 * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。
	 *
	 * @og.rev 2.1.3.1 (2002/12/13) ContentType を、x-msexcel から vnd.ms-excel に変更した。
	 * @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.5.0 (2003/04/20) Content-Disposition を外部から指定できるように変更。
	 * @og.rev 3.2.0.0 (2003/05/22) GZIPOutputStream を使用していたが、ZipOutputStream に変更。
	 * @og.rev 3.5.4.1 (2003/12/01) 引数の PrintWriter を、OutputStream に変更。
	 * @og.rev 3.5.4.3 (2004/01/05) 引数を、 PrintWriter に戻す。
	 * @og.rev 3.6.0.2 (2004/10/04) EXCELダイレクト出力時にファイルエンドまで出力されない不具合対策
	 * @og.rev 3.8.0.9 (2005/10/17) disposition属性を使用できるように変更します。
	 * @og.rev 3.8.6.0 (2006/08/23) フォルダがない場合は、複数階層分のフォルダを自動で作成します。
	 * @og.rev 4.3.4.3 (2008/12/22) Excel出力の判別方法を前方一致に変更
	 * @og.rev 5.1.6.0 (2010/05/01) 画面帳票作成機能対応
	 * @og.rev 5.5.2.0 (2012/05/01) ZIP時にもencodeが有効にする
	 * @og.rev 5.5.5.5 (2012/08/24) selectedAllの処理を追加
	 * @og.rev 5.5.9.1 (2012/12/07) beforeDeleteフラグの追加に伴う、ロジック変更
	 * @og.rev 5.7.7.2 (2014/06/20) caseKey,caseVal,caseNN,caseNull 属性を追加
	 * @og.rev 5.9.25.2 (2017/10/27) クラウドストレージ対応
	 * @og.rev 5.10.23.0 (2020/06/01) 書込み件数をリクエスト変数WRITE.COUNTに出力
	 *
	 * @return	後続処理の指示
	 */
	@Override
	public int doEndTag() {
		int tblcnt = 0; // 5.10.23.0 (2020/06/01)
		debugPrint();		// 4.0.0 (2005/02/28)

		// 5.7.7.2 (2014/06/20) caseKey,caseVal,caseNN,caseNull 属性を追加
		if( !useTag() ) { return EVAL_PAGE ; }

		table = (DBTableModel)getObject( tableId );
		if( ! selectedAll ){ // 5.5.5.5 (2012/08/24)
			table = getSelRowsTable( table );
		}
		if( table != null && table.getRowCount() > 0 ) {
			 File dir = new File(directory);
			if( ! dir.exists() && ! dir.mkdirs() ) {
				String errMsg = "ディレクトリの作成に失敗しました。[" + directory + "]";
				throw new HybsSystemException( errMsg );
			}

			PrintWriter pw = null;
			ByteArrayOutputStream bt = null ;
			try {
				if( direct ) {
					if( zip ) {
						bt = new ByteArrayOutputStream();
						pw = new PrintWriter( bt );
						create( pw ) ;
						pw.flush();				// 3.6.0.2 (2004/10/04)
						ServletResponse response = pageContext.getResponse() ;
						((HttpServletResponse)response).addHeader( "Content-Encoding","gzip" );

						GZIPOutputStream gzip = new GZIPOutputStream(bt);
						gzip.finish() ;
						response.setContentLength( bt.size() );

						JspWriter out = pageContext.getOut();
						out.clear();
						out.print( bt );
						out.flush();			// 3.6.0.2 (2004/10/04)
					}
					else {
						bt = new ByteArrayOutputStream();
						pw = new PrintWriter( bt );
						create( pw ) ;
						pw.flush();				// 3.6.0.2 (2004/10/04)
						ServletResponse response = pageContext.getResponse() ;
						response.setContentType( "application/vnd.ms-excel; charset=" + encode );
	//					response.setContentType( "application/x-msexcel; charset=" + encode );
	//					response.setContentType( "text/comma-separated-values ; charset=" + encode );
	//					((HttpServletResponse)response).setHeader( "contentType","application/x-msexcel; charset=Shift_JIS" );
	//					((HttpServletResponse)response).setHeader( "Content-Disposition","attachment; filename=\"" + filename + "\"" );
	//					((HttpServletResponse)response).setHeader( "Content-Disposition","inline; filename=\"" + filename + "\"" );
						// 3.8.0.9 (2005/10/17) disposition属性を使用できるように変更します。
						((HttpServletResponse)response).setHeader( "Content-Disposition",disposition + "; filename=\"" + filename + "\"" );

						JspWriter out = pageContext.getOut();
						out.clear();
						out.print( bt );
						out.flush();			// 3.6.0.2 (2004/10/04)
					}
				}
				else {
				// 3.2.0.0 (2003/05/22) GZIPOutputStream を使用していたが、ZipOutputStream に変更。
					if( zip ) {
						bt = new ByteArrayOutputStream();
						if( writerClass.toUpperCase(Locale.JAPAN).startsWith("EXCEL") // 5.5.2.0(2012/05/01)
								|| writerClass.toUpperCase(Locale.JAPAN).startsWith("CALC") ) {
							pw = new PrintWriter( bt );
						}
						else{
							pw = getPrintWriter(bt);
						}
						create( pw ) ;
						pw.flush();				// 3.6.0.2 (2004/10/04)

						ZipOutputStream gzip = null;
						try {
							gzip = new ZipOutputStream(
											new FileOutputStream(
												StringUtil.urlAppend( directory,filename + ".zip" )));
							gzip.putNextEntry( new ZipEntry( filename ) );
							(bt).writeTo( gzip );
							gzip.finish() ;
						}
						finally {
							Closer.ioClose( gzip );		// 4.0.0 (2006/01/31) close 処理時の IOException を無視
						}
					}
					else {
						// 5.10.9.0 (2019/03/01) ADD fileAppend=true、かつクラウドストレージの場合は、
						// ローカルにダウンロードして、追記モードで利用できるように対応。
						if(fileAppend) {
							// 5.10.9.0 (2019/03/01) ADD 追記モードの場合、クラウドストレージかつ、ファイルの場合は、ローカルにダウンロードする。
							FileOperation file = HybsFileOperationFactory.create(storageType,  bucketName, directory, filename);
							// ディレクトリはdoEndTagメソッドの初期処理で、作成済み。
							if(!file.isLocal()) {
								// 指定のファイルがクラウドストレージに存在しない場合は、エラーとする。
								if(file.isFile()) {
									StringBuilder errMsg = new StringBuilder(HybsSystem.BUFFER_SMALL);
									errMsg.append("指定のファイルが存在しません。path : ").append(file.getAbsolutePath());
									throw new HybsSystemException(errMsg.toString());
								}
								// ファイルダウンロード
								File local = new File(directory, filename);
								FileUtil.copy(file, local);
							}
						}
						
						// if( "Excel".equalsIgnoreCase( writerClass ) ) {
						if( writerClass.toUpperCase(Locale.JAPAN).startsWith("EXCEL") // 4.3.4.3 (2008/12/22)
							||  writerClass.toUpperCase(Locale.JAPAN).startsWith("CALC") ) { // 5.1.6.0 (2010/05/01)
							create( null );
						}
						else {
							pw = getPrintWriter();
							create( pw );
							pw.flush();				// 3.6.0.2 (2004/10/04)
						}
					}
				}
				tblcnt = table.getRowCount(); // 5.10.23.0 (2020/06/01)
			}
			catch( IOException ex ) {
				String errMsg = "テーブル出力時に、IOエラーが発生しました。" + toString();
				throw new HybsSystemException( errMsg,ex );		// 3.5.5.4 (2004/04/15) 引数の並び順変更
			}
			finally {
				Closer.ioClose( pw );		// 4.0.0 (2006/01/31) close 処理時の IOException を無視
				Closer.ioClose( bt );		// 4.0.0 (2006/01/31) close 処理時の IOException を無視
			}

			// 5.9.25.2 (2017/10/27) ADD
			// クラウド上の場合は、ストレージに登録する
			FileOperation fileOperation = HybsFileOperationFactory.create(storageType, bucketName, filename);
			if(!fileOperation.isLocal()){
				if(zip){
					entryStorage(filename + ".zip");
				}else{
					entryStorage(filename);
				}
			}
		}
		setRequestAttribute( "WRITE.COUNT"   , String.valueOf( tblcnt ) ); // 5.10.23.0 (2020/06/01)

		return EVAL_PAGE ;
	}

	/**
	 * 指定されたファイルをクラウド上のストレージに登録します。
	 * 処理後に登録元のファイルを削除します。
	 *
	 * @og.rev 5.9.25.2 (2017/10/27) 新規作成
	 * @og.rev 5.10.9.0 (2019/03/01) クラウドストレージ対応を追加
	 *
	 * @param trgFileName 対象のファイル名
	 */
	private void entryStorage(String trgFileName) {
		FileInputStream fis = null;
		String filePath = StringUtil.urlAppend( directory, trgFileName);
		// ｻｰﾊﾞに作成されたﾌｧｲﾙをｽﾄﾚｰｼﾞに登録する
		try{
			fis = new FileInputStream( filePath );

			FileOperation file = HybsFileOperationFactory.create(storageType, bucketName, filePath);
			file.write(fis);
		}catch(FileNotFoundException e){
			String errMsg = "ファイルが見つかりません。path:" + filePath;
			throw new HybsSystemException( errMsg );
		}catch(IOException ie) {
			throw new HybsSystemException(ie.getMessage() );
		}finally{
			Closer.ioClose(fis);
		}

		// 処理後のｻｰﾊﾞのﾌｧｲﾙは削除
		File file = new File(filePath);
		file.delete();
	}

	/**
	 * タグリブオブジェクトをリリースします。
	 * キャッシュされて再利用されるので、フィールドの初期設定を行います。
	 *
	 * @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.5.0 (2003/04/20) Content-Disposition を外部から指定できるように変更。
	 * @og.rev 3.5.4.2 (2003/12/15) EXCELのシート名を指定できるように変更。
	 * @og.rev 3.5.4.3 (2004/01/05) EXCEL雛型参照ファイルのURL,filenameを追加します。
	 * @og.rev 3.8.5.3 (2006/08/07) writerClass 属性の初期値をシステムリソースより取得します。
	 * @og.rev 3.8.5.3 (2006/08/07) fontName 属性を追加します。
	 * @og.rev 3.8.5.3 (2006/08/07) fontPoint 属性を追加します。
	 * @og.rev 3.8.6.0 (2006/08/23) directory 属性を追加します。
	 * @og.rev 4.0.0.0 (2005/02/28) XMLファイルにセットする、param を追加。
	 * @og.rev 5.2.1.0 (2010/10/01) 書込処理でコードリソースのラベル変換を行うかどうか useRenderer 属性追加
	 * @og.rev 5.5.5.5 (2012/08/24) selectedAll属性を追加
	 * @og.rev 5.5.9.1 (2012/12/07) 事前にファイルを削除するかどうか。互換性のため、false に設定。推奨は、true
	 * @og.rev 5.7.9.0 (2014/08/08) データの書き込み開始位置(skipRowCount)を設定
	 * @og.rev 5.9.12.1 (2016/09/09) sheetOverwrite
	 * @og.rev 5.9.20.2 (2017/05/19) headerSequence
	 *
	 */
	@Override
	protected void release2() {
		super.release2();
		separator		= TableWriter.TAB_SEPARATOR;   // 項目区切り文字
//		headerSequence	= null;				// ヘッダー項目の並び順
		headerSequence	=HybsSystem.sys( "TABLE_WRITER_DEFAULT_HEADERSEQ" );	// 5.9.20.2 (2017/05/19)
		fileURL 		= BASE_URL;
		filename		= HybsSystem.sys( "FILE_FILENAME" );   // ファイル名
		sheetName		= "Sheet1";			// 3.5.4.2 (2003/12/15)
		beforeDelete	= false;			// 5.5.9.1 (2012/12/07)
		refFileURL		= BASE_URL;			// 3.5.4.3 (2004/01/05)
		refFilename 	= null;				// 3.5.4.3 (2004/01/05)
		refSheetName	= null;				// 3.5.4.2 (2003/12/15)
		fontName		= HybsSystem.sys( "TABLE_WRITER_DEFAULT_FONT_NAME" );			// 3.8.5.3 (2006/08/07)
		fontPoint		= HybsSystem.sys( "TABLE_WRITER_DEFAULT_FONT_POINTS" );			// 3.8.5.3 (2006/08/07)
		encode			= HybsSystem.sys( "FILE_ENCODE" );	 // ファイルエンコーディング  "DEFAULT","JISAutoDetect" ,"JIS", "EUC_JP", "MS932", "SJIS" , "Windows-31J" , "Shift_JIS"
		writerClass 	= HybsSystem.sys( "TABLE_WRITER_DEFAULT_CLASS" );		// 3.8.5.3 (2006/08/07)
		fileAppend		= false;			// ファイルをAPPENDモードで出力するか
		direct			= false;
		zip 			= false;
		table			= null;
		tableId 		= HybsSystem.TBL_MDL_KEY ;
		disposition 	= "attachment";		// 3.8.0.9 (2005/10/17) 初期値変更 inline ⇒ attachment
		param			= null ;			// 4.0.0 (2005/01/31)
		useNumber		= true;				// 3.7.0.2 (2005/02/14)
		skipRowCount	= 0;				// 5.7.9.0 (2014/08/08) データの書き込み開始位置を設定
		directory		= null;				// 3.8.6.0 (2006/08/23)
		columns			= null;				// 4.0.0 (2005/12/31)
		useRenderer		= HybsSystem.sysBool( "USE_TABLE_WRITER_RENDERER" );	// 5.2.1.0 (2010/10/01)
		selectedAll		= true;				// 5.5.5.5 (2012/08/24)
		sheetOverwrite	= false;			// 5.9.12.1 (2016/09/09)
		recalcSheetName = null;				// 5.9.12.1 (2016/09/09)
		storageType		= null;				// 5.10.9.0 (2019/03/01) ADD
		bucketName		= null;				// 5.10.9.0 (2019/03/01) ADD
	}

	/**
	 * TableWriter の実オブジェクトを生成して，OutputStream に書き込みます。
	 *
	 * @og.rev 3.5.4.1 (2003/12/01) 引数の PrintWriter を、OutputStream に変更。
	 * @og.rev 3.5.4.2 (2003/12/15) lang 引数も table と同時に設定します。
	 * @og.rev 3.5.4.2 (2003/12/15) TableWriter のサブクラス名変更。
	 * @og.rev 3.5.4.3 (2004/01/05) EXCEL雛型参考ファイルを指定するように変更。
	 * @og.rev 3.5.4.3 (2004/01/05) 引数を、 PrintWriter に戻す。
	 * @og.rev 3.5.4.5 (2004/01/23) 文字エンコードを渡すように変更する。
	 * @og.rev 3.5.6.0 (2004/06/18) 各種プラグイン関連付け設定を、システムパラメータ に記述します。
	 * @og.rev 3.8.5.3 (2006/08/07) EXCEL時に fontName と fontPoint 属性をセットします。
	 * @og.rev 4.0.0.0 (2005/01/31) キーの指定を、TableWriter. から、TableWriter_ に変更します。
	 * @og.rev 4.0.0.0 (2005/12/31) 外部よりカラム列(カンマ区切り)を指定できるようにする。
	 * @og.rev 5.2.1.0 (2010/10/01) 書込処理でコードリソースのラベル変換を行うかどうか設定 useRenderer 属性追加
	 * @og.rev 5.7.9.0 (2014/08/08) データの書き込み開始位置(skipRowCount)を設定
	 * @og.rev 5.9.12.1 (2016/09/09) sheetOverwrite
	 * @og.rev 5.10.23.0 (2020/06/01) headerSequenceのnullセット
	 *
	 * @param   out PrintWriterオブジェクト
	 */
	private void create( final PrintWriter out )  {
		// 5.2.1.0 (2010/10/01) writerClass で Renderer系の場合は、useRendererフラグに変更する。
		if( "ExcelRenderer".equalsIgnoreCase( writerClass ) ) {
			writerClass = "Excel" ;
			useRenderer = true;
		}
		else if( "Renderer".equalsIgnoreCase( writerClass ) ) {
			writerClass = "Default" ;
			useRenderer = true;
		}

		String className = HybsSystem.sys( "TableWriter_" + writerClass ) ;		// 4.0.0 (2005/01/31)
		TableWriter writer = (TableWriter)HybsSystem.newInstance( className );	// 3.5.5.3 (2004/04/09)

		// 5.10.23.0 (2020/06/01) システムリソースでnullは警告が出るので、null文字列の場合はnullセット
		if ( "null".equals( headerSequence ) ) {
			headerSequence = null;
		}
		
		writer.setDBTableModel( table,getLanguage() );
		writer.setSeparator( separator );
		writer.setHeaderSequence( headerSequence );
		writer.setEncode( encode );					// 3.5.4.5 (2004/01/23)
		writer.setAppend( fileAppend );				// 3.5.4.2 (2003/12/15)
		if( param != null ) { writer.setParam( param ); }	// 4.0.0 (2005/01/31)
		writer.setUseNumber( useNumber );			// 3.7.0.2 (2005/02/14)
	//	if( columns == null ) {
	//		columns = (String)getSessionAttribute( HybsSystem.TBL_WRITER_CLMS );
	//		removeSessionAttribute( HybsSystem.TBL_WRITER_CLMS );
	//	}
		writer.setColumns( columns );				// 4.0.0 (2005/12/31)
		writer.setUseRenderer( useRenderer );		// 5.2.1.0 (2010/10/01)
		if( writer.isExcel() ) {					// 3.5.4.3 (2004/01/05)
			writer.setSheetName( sheetName );
			writer.setFilename( StringUtil.urlAppend( directory , filename ) );
			if( refFileURL != null && refFilename != null ) {
				writer.setRefFilename( StringUtil.urlAppend( HybsSystem.url2dir(refFileURL) , refFilename ) );
			}
			if( refSheetName != null && fontPoint.length() > 0 ) {		// 5.7.9.0 (2014/08/08) nullチェック
				writer.setRefSheetName( refSheetName );
			}
//			writer.setFontName( nval( fontName,null ) );				// 3.8.5.3 (2006/08/07)
			writer.setFontName( fontName )	;							// 5.7.9.0 (2014/08/08) nvalはずし
			if( fontPoint != null && fontPoint.length() > 0 ) {
				writer.setFontPoint( Short.parseShort( fontPoint ) );	// 3.8.5.3 (2006/08/07)
			}
			writer.setSkipRowCount( skipRowCount );						// 5.7.9.0 (2014/08/08)

			writer.setSheetOverwrite( sheetOverwrite );		// 5.9.12.1 (2016/09/09)
			writer.setRecalcSheetName( recalcSheetName );	// 5.9.12.1 (2016/09/09)

			writer.writeDBTable();
		}
		else {
			writer.writeDBTable( out );
		}
	}

	/**
	 * PrintWriter を取得します。
	 *
	 * ここでは、一般的なファイル出力を考慮した PrintWriter を作成します。
	 *
	 * @og.rev 2.2.0.0 (2002/12/17) 中国語(国際化)対応 エンコードの取得方法変更
	 * @og.rev 3.1.3.0 (2003/04/10) FILE_ENCODE から、エンコード情報を取得する。
	 * @og.rev 3.5.4.1 (2003/12/01) PrintWriter を、OutputStream に変更。
	 * @og.rev 3.5.5.9 (2004/06/07) FileUtil.getBufferedReader を使用
	 * @og.rev 3.7.1.1 (2005/05/23) フォルダがない場合は、複数階層分のフォルダを自動で作成します。
	 * @og.rev 3.8.0.0 (2005/06/07) FileUtil#getPrintWriter を利用。
	 *
	 * @return	ファイル書き出し用のPrintWriterオブジェクト
	 */
	private PrintWriter getPrintWriter() {
		if( filename == null ) {
			String errMsg = "ファイル名がセットされていません。";
			throw new HybsSystemException( errMsg );
		}
		
		// ※ 注意 StringUtil.urlAppend を組み込んでいる意図が不明。一旦削除していますが、注意
	 	// 3.8.0.0 (2005/06/07) FileUtil#getPrintWriter を利用。
	//	out = FileUtil.getPrintWriter( StringUtil.urlAppend( directory,filename ),fileAppend,encode);
		PrintWriter out = FileUtil.getPrintWriter( new File( directory,filename ),encode,fileAppend );

		return out ;
	}

	/**
	 * PrintWriter を取得します。
	 *
	 * 引数で指定したOutputStreamを利用して出力します。
	 *
	 * @og.rev 5.5.2.0 (2012/05/01) 新規作成
	 *
	 * @param	os	OutputStreamオブジェクト
	 *
	 * @return	指定したstreamに書き出すPrintWriter
	 */
	private PrintWriter getPrintWriter( final OutputStream os ) {
		PrintWriter out = FileUtil.getPrintWriter( os,encode );

		return out ;
	}

	/**
	 * チェック分のテーブルモデルを再構成します。
	 *
	 * @og.rev 5.5.5.5 (2012/08/24) 新規作成
	 * @og.rev 5.5.9.1 (2012/12/07) 内部処理変更
	 *
	 * @param	oldTable	コピー元テーブルモデル
	 *
	 * @return	チェックした分だけで再構成したテーブルモデル
	 */
	private DBTableModel getSelRowsTable( final DBTableModel oldTable ) {
		if( oldTable == null ) { return null; }		// 5.5.9.1 (2012/12/07) 引数のDBTableModelが null の場合の処理。

		DBTableModel newTable = oldTable.newModel();
		final int[] rowNo = getParameterRows();
		final int rowCount = rowNo.length ;

		for( int i=0; i<rowCount; i++ ) {
			newTable.addValues( oldTable.getValues(rowNo[i]), i );
		}
		return newTable;
	}

	/**
	 * 【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 sessionに登録する時の ID
	 */
	public void setTableId( final String id ) {
		tableId = nval( getRequestParameter( id ), tableId );
	}

	/**
	 * 【TAG】可変長ファイルを作成するときの項目区切り文字をセットします
	 *		(初期値:TableWriter#TAB_SEPARATOR[={@og.value TableWriter#TAB_SEPARATOR}])。
	 *
	 * @og.tag 可変長ファイルを作成するときの項目区切り文字をセットします。
	 * (初期値:TableWriter#TAB_SEPARATOR[={@og.value TableWriter#TAB_SEPARATOR}])。
	 *
	 * @param   separator 項目区切り文字
	 * @see		org.opengion.hayabusa.io.TableWriter#TAB_SEPARATOR
	 */
	public void setSeparator( final String separator ) {
		this.separator = nval( getRequestParameter( separator ),this.separator );
	}

	/**
	 * 【TAG】DBTableModelの出力順(LNSCD など)をセットします。
	 *
	 * @og.tag
	 * Label,Name,Size,Class,Data の各フィールドの頭文字のアルファベットで
	 * 出力順を設定します。
	 *
	 * @param   hs 出力順 (LNSCD など)
	 */
	public void setHeaderSequence( final String hs ) {
		String[] headers = getRequestParameterValues( hs );
		if( headers != null ) {
			StringBuilder buf = new StringBuilder();
			for( int i=0; i<headers.length; i++ ) {
				if( headers[i] != null ) { buf.append( headers[i] ); }
			}
			headerSequence = buf.toString();
		}
	}

	/**
	 * 【TAG】ファイル保存先ディレクトリ名を指定します。
	 *
	 * @og.tag
	 * この属性で指定されるディレクトリに、ファイルをセーブします。
	 * 指定方法は、通常の fileURL 属性と同様に、先頭が、'/' (UNIX) または、２文字目が、
	 * ":" (Windows)の場合は、指定のURLそのままのディレクトリに、そうでない場合は、
	 * システムパラメータ の FILE_URL 属性で指定のフォルダの下に、作成されます。
	 * fileURL = "{&#064;USER.ID}" と指定すると、FILE_URL 属性で指定のフォルダの下に、
	 * さらに、各個人ID別のフォルダを作成して、そこにセーブします。
	 *
	 * @og.rev 3.5.4.3 (2004/01/05) 内部処理を、makeFileURL に移動。
	 * @og.rev 4.0.0.0 (2005/01/31) StringUtil.urlAppend メソッドの利用
	 * @og.rev 4.0.0.0 (2007/11/20) 指定されたディレクトリ名の最後が"\"or"/"で終わっていない場合に、"/"を付加する。
	 *
	 * @param	url 保存先ディレクトリ名
	 */
	public void setFileURL( final String url ) {
		String furl = nval( getRequestParameter( url ),null );
		if( furl != null ) {
			char ch = furl.charAt( furl.length()-1 );
			if( ch != '/' && ch != '\\' ) { furl = furl + "/"; }
			fileURL = StringUtil.urlAppend( fileURL,furl );
		}
	}

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

	/**
	 * 【TAG】EXCELファイルを書き出すときのシート名を設定します。
	 *
	 * @og.tag
	 * EXCELファイルを書き出す時に、シート名を指定します。これにより、複数の形式の
	 * 異なるデータを順次書き出したり(appendモードを併用)することや、シートを指定して
	 * 新規にEXCELを作成することが可能になります。
	 * 初期値は、Sheet1 です。
	 *
	 * @og.rev 3.5.4.2 (2003/12/15) 新規追加
	 *
	 * @param   sheet EXCELファイルのシート名
	 */
	public void setSheetName( final String sheet ) {
		sheetName = nval( getRequestParameter( sheet ),sheetName );
	}

	/**
	 * 【TAG】ファイルを作成するときのファイルエンコーディング名をセットします
	 *		(初期値:FILE_ENCODE[={@og.value org.opengion.hayabusa.common.SystemData#FILE_ENCODE}])。
	 *
	 * @og.tag
	 * "DEFAULT","JISAutoDetect" ,"JIS", "EUC_JP", "MS932", "SJIS" , "Windows-31J" , "Shift_JIS"
	 * (初期値:システム定数のFILE_ENCODE[={@og.value org.opengion.hayabusa.common.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】実際に書き出すクラス名の略称({@og.doc03Link writerClass TableWriter_**** クラスの ****})を指定します(初期値:Default)。
	 *
	 * @og.tag
	 * 実際に書き出すクラス名(の略称)をセットします。
	 * org.opengion.hayabusa.io.TableWriter インターフェースを継承したサブクラスです。
	 * これは、org.opengion.plugin.io 以下の TableWriter_**** クラスの **** を与えます。
	 * 属性クラス定義の {@link org.opengion.hayabusa.io.TableWriter TableWriter} を参照願います。
	 * {@og.doc03Link writerClass TableWriter_**** クラス}
	 *
	 * ExcelRenderer と、Renderer は、特別な名前で、useRenderer 属性に、"true" をセットするのと同じ効果があります。
	 * 実際は、ExcelRenderer ⇒ Excel 、Renderer  ⇒ Default のクラスが呼ばれます。
	 *
	 * @param   writerClass クラス名(の略称)
	 * @see		org.opengion.hayabusa.io.TableWriter  TableWriterのサブクラス
	 */
	public void setWriterClass( final String writerClass ) {
		this.writerClass = nval( getRequestParameter( writerClass ),this.writerClass );
	}

	/**
	 * 【TAG】追加モードで書き込むかどうか[true/false]を指定します(初期値:false[新規モード])。
	 *
	 * @og.tag DBTableModelのファイルを、追加モードで書き込むかどうかをセットします。
	 *
	 * @param   flag  [true:追加モード/それ以外:新規モード]
	 */
	public void setFileAppend( final String flag ) {
		fileAppend = nval( getRequestParameter( flag ),fileAppend );
	}

	/**
	 * 【廃止】結果をダイレクトにEXCEL起動するかどうか[true/false]を指定します(初期値:false[ファイル])。
	 *
	 * @og.tag 結果をダイレクトに EXCEL ファイルとして出力するかどうかをセットします。
	 *
	 * @param  flag  [true:ダイレクト/それ以外:ファイル]
	 * @deprecated 結果をダイレクトするとエンコード等でおかしな動きをする可能性がある。
	 */
	@Deprecated public void setDirect( final String flag ) {
		direct = nval( getRequestParameter( flag ),direct );
	}

	/**
	 * 【TAG】結果をファイルに出力するときに、ZIPで圧縮するかどうか[true/false]を指定します(初期値:false)。
	 *
	 * @og.tag
	 * 初期値は、圧縮しないです。
	 *
	 * @param  flag ZIPで圧縮する [true:圧縮する/それ以外:しない]
	 */
	public void setZip( final String flag ) {
		zip = nval( getRequestParameter( flag ),zip );
	}

	/**
	 * 【TAG】Content-Disposition (inline:埋め込む/attachment:ダイアログを起動)を指定します(初期値:attachment)。
	 *
	 * @og.tag
	 * Content-Disposition を指定することで、ブラウザにアプリケーションデータを
	 * 埋め込むのか(inline)、セーブ/オープンのダイアログを起動するのか(attachment)
	 * 指定します。
	 * この属性が有効なのは、direct="true" で、zip="false"(初期値)のときのみです。
	 * 値は、inline 、attachment が指定できます。
	 * 初期値は、attachment です。
	 * 注意：動作検証しましたが、inline と attachment で動作に差が現れませんでした。
	 *
	 * @og.rev 3.1.5.0 (2003/04/20) Content-Disposition を外部から指定できるように変更。
	 * @og.rev 3.8.0.9 (2005/10/17) Content-Disposition 初期値変更 inline ⇒ attachment
	 *
	 * @param  pos Content-Disposition [inline/attachment]
	 */
	public void setDisposition( final String pos ) {
		disposition = nval( getRequestParameter( pos ),disposition );
		if( !"inline".equals( disposition ) && !"attachment".equals( disposition ) ) {
			String errMsg = "disposition には、inline か attachment 以外は指定できません。"
						+ "disposition=[" + disposition + "]" ;
			throw new HybsSystemException( errMsg );
		}
	}

	/**
	 * 【TAG】EXCEL雛型参照ファイルのディレクトリ名をセットします。
	 *
	 * @og.tag
	 * この属性で指定されるディレクトリに、ファイルをセーブします。
	 * 指定方法は、通常の fileURL 属性と同様に、先頭が、'/' (UNIX) または、２文字目が、
	 * ":" (Windows)の場合は、指定のURLそのままのディレクトリに、そうでない場合は、
	 * システムパラメータ の FILE_URL 属性で指定のフォルダの下に、作成されます。
	 * fileURL = "{&#064;USER.ID}" と指定すると、FILE_URL 属性で指定のフォルダの下に、
	 * さらに、各個人ID別のフォルダを作成して、そこにセーブします。
	 *
	 * @og.rev 3.5.4.3 (2004/01/05) 新規作成
	 * @og.rev 4.0.0.0 (2005/01/31) StringUtil.urlAppend メソッドの利用
	 * @og.rev 4.0.0.0 (2007/11/20) 指定されたディレクトリ名の最後が"\"or"/"で終わっていない場合に、"/"を付加する。
	 *
	 * @param	url EXCEL雛型参照ファイルのディレクトリ名
	 */
	public void setRefFileURL( final String url ) {
		String furl = nval( getRequestParameter( url ),null );
		if( furl != null ) {
			char ch = furl.charAt( furl.length()-1 );
			if( ch != '/' && ch != '\\' ) { furl = furl + "/"; }
			refFileURL = StringUtil.urlAppend( refFileURL,furl );
		}
	}

	/**
	 * 【TAG】EXCEL雛型参考ファイル名をセットします。
	 *
	 * @og.tag
	 * 内部処理的には、雛形ファイルの雛形シートをメモリ上に構築し、
	 * そのシートのセルに、データを追加していきます。
	 * 最後には、雛形シートとして存在しない部分は、すべて削除します。
	 * 雛形シートを使わない場合は、新規シートに追加していくことになります。
	 * appendモードの場合は、オリジナルが雛形ファイルになります。
	 * 雛形ファイルの指定は、無効になります。
	 * ※ 互換性の為、同じ名前の設定は有効です。
	 *
	 * ※ Excel2007形式(XSSF)では、行全体を指定した色や罫線は、
	 * セルとして認識されません。範囲指定で、罫線や色付けを行う必要があります。
	 *
	 * @og.rev 3.5.4.3 (2004/01/05) 新規作成
	 *
	 * @param   filename EXCEL雛型参考ファイル名
	 */
	public void setRefFilename( final String filename ) {
		refFilename = nval( getRequestParameter( filename ),refFilename );
	}

	/**
	 * 【TAG】EXCEL雛型参考ファイルのシート名を設定します。
	 *
	 * @og.tag
	 * EXCELファイルを書き出す時に、雛型として参照するシート名を指定します。
	 * これにより、複数の形式の異なるデータを順次書き出したり(appendモードを併用)する
	 * ことや、シートを指定して新規にEXCELを作成する場合にフォームを設定する事が可能になります。
	 * 初期値は、null(第一シート) です。
	 *
	 * @og.rev 3.5.4.3 (2004/01/05) 新規追加
	 *
	 * @param   sheet EXCEL雛型参考ファイルのシート名
	 */
	public void setRefSheetName( final String sheet ) {
		refSheetName = nval( getRequestParameter( sheet ),refSheetName );
	}

	/**
	 * 【TAG】追記モード時に、指定シートが存在した場合は上書きします(初期値:false[上書きしない])。
	 *
	 * @og.tag シート上書きを行うかどうか
	 *
	 * @og.rev 5.9.12.1 (2016/09/09) 追加
	 *
	 * @param   flag  [true:追加モード/それ以外:新規モード]
	 */
	public void setSheetOverwrite( final String flag ) {
		sheetOverwrite = nval( getRequestParameter( flag ),sheetOverwrite );
	}

	/**
	 * 【TAG】EXCELで、出力処理の最後に、セル内の計算式を再計算させるシート名をカンマ区切りで指定します。
	 *
	 * @og.tag
	 * 通常は利用する必要はありません。
	 * 一覧結果を利用した集計用シートを別に持っているような雛形を利用した出力で利用します。
	 *
	 * @og.rev 5.9.12.1 (2016/09/09) 追加
	 *
	 * @param   sheet 対象シート名(カンマ区切り文字)
	 */
	public void setRecalcSheetName( final String sheet ) {
		recalcSheetName = nval( getRequestParameter( sheet ),recalcSheetName );
	}

	/**
	 * 【TAG】EXCEL出力時のデフォルトフォント名を設定します
	 *		(初期値:TABLE_WRITER_DEFAULT_FONT_NAME[={@og.value org.opengion.hayabusa.common.SystemData#TABLE_WRITER_DEFAULT_FONT_NAME}])。
	 *
	 * @og.tag
	 * これは、EXCEL追加機能として実装されています。
	 *
	 * EXCELファイルを書き出す時に、デフォルトフォント名を指定します。
	 * フォント名は、EXCELのフォント名をそのまま使用してください。
	 * 内部的に、POI の org.apache.poi.hssf.usermodel.HSSFFont#setFontName( String )
	 * に設定されます。
	 * (初期値:システム定数のTABLE_WRITER_DEFAULT_FONT_NAME[={@og.value org.opengion.hayabusa.common.SystemData#TABLE_WRITER_DEFAULT_FONT_NAME}])。
	 *
	 * @og.rev 3.8.5.3 (2006/08/07) 新規追加
	 *
	 * @param   name デフォルトフォント名
	 * @see		org.opengion.hayabusa.common.SystemData#TABLE_WRITER_DEFAULT_FONT_NAME
	 */
	public void setFontName( final String name ) {
		fontName = nval( getRequestParameter( name ),fontName );
	}

	/**
	 * 【TAG】EXCEL出力時のデフォルトフォントポイント数を設定します。
	 *
	 * @og.tag
	 * これは、EXCEL追加機能として実装されています。
	 *
	 * EXCELファイルを書き出す時に、デフォルトポイント数を指定します。
	 * 内部的に、POI の org.apache.poi.hssf.usermodel.HSSFFont#setFontHeightInPoints( short )
	 * に設定されます。
	 * 初期値は、システムリソース の TABLE_WRITER_DEFAULT_FONT_POINTS です。
	 *
	 * @og.rev 3.8.5.3 (2006/08/07) 新規追加
	 *
	 * @param   point デフォルトフォントポイント数
	 */
	public void setFontPoint( final String point ) {
		fontPoint = nval( getRequestParameter( point ),fontPoint );
	}

	/**
	 * 【TAG】行番号情報を、出力する/しない[true/false]を指定します(初期値:true)。
	 *
	 * @og.tag
	 * 通常のフォーマットでは、各行の先頭に行番号を出力します。
	 * これは、#NAME 属性を使用する場合には、必ず出力する必要があります。
	 * (#NAME 属性は、読み取り時には、必須です。)
	 * この、先頭の行番号が不要な場合(つまり、他のシステムへのデータ出力、
	 * このシステムでは、#NAME 属性が出力されないため、読み込みできません。)
	 * この行番号を出力しないようにできます。
	 * なお、EXCEL 出力には、この設定は適用されません。(暫定対応)
	 * 初期値は、true(出力する) です。
	 *
	 * @og.rev 3.7.0.2 (2005/02/14) 新規追加
	 *
	 * @param   useNo 行番号情報を指定 [true:出力する/false:しない]
	 */
	public void setUseNumber( final String useNo ) {
		useNumber = nval( getRequestParameter( useNo ),useNumber );
	}

	/**
	 * 【TAG】書き込み先ファイルのカラム列を、外部(タグ)より指定します。
	 *
	 * @og.tag
	 * この指定により、書き込むカラムを限定的に使用することが可能です。
	 * カラム名は、検索したDBTableModel上に含まれる名前で指定する必要があります。
	 * 別名で書き込みたい場合は、予めその名前で検索しておく必要があります。
	 *
	 * @og.rev 4.0.0.0 (2005/12/31) 新規作成
	 *
	 * @param   clms 書き込み先ファイルのカラム列(カンマ区切り文字)
	 */
	public void setColumns( final String clms ) {
		columns = nval( getRequestParameter( clms ),columns );
	}

	/**
	 * 【TAG】書込処理でコードリソースのラベル変換を行うかどうかを指定します
	 *		(初期値:USE_TABLE_WRITER_RENDERER[={@og.value org.opengion.hayabusa.common.SystemData#USE_TABLE_WRITER_RENDERER}])。
	 *
	 * @og.tag
	 * コードリソースをそのままの値で出力すると、数字や記号になり何が書かれているのか
	 * 不明になります。
	 * これは、コードリソースをラベルに変換して出力するかどうかを指定します。
	 * 当然、コードはユニークですが、ラベルはユニークになるかどうか保障はされていませんので
	 * TableReader 系で読み込む場合には、リスクが発生します。
	 * また、TableReader 系で読み込む場合にも、ラベルからコードを求める逆変換を行うように、
	 * setUseRenderer メソッドで指定する必要があります。
	 *
	 * 従来は、TableWriter 系に、TableWriter_Renderer 系のクラスを作って対応していましたが、
	 * このメソッドの属性値のフラグで、制御します。
	 * (初期値:システム定数のUSE_TABLE_WRITER_RENDERER[={@og.value org.opengion.hayabusa.common.SystemData#USE_TABLE_WRITER_RENDERER}])。
	 *
	 * @og.rev 5.2.1.0 (2010/10/01) 新規作成
	 *
	 * @param  flag コードリソースのラベル変換を行うかどうか
	 * @see		org.opengion.hayabusa.common.SystemData#USE_TABLE_WRITER_RENDERER
	 */
	public void setUseRenderer( final String flag ) {
		useRenderer = nval( getRequestParameter( flag ),useRenderer );
	}

	/**
	 * 【TAG】(通常は使いません)データの書き込み開始行番号を設定します(初期値:0)。
	 *
	 * @og.tag
	 * TAB区切りテキストやEXCEL等のデータの書き込みの開始行番号を指定します。
	 * 属性名は、行を飛ばす処理ということで、readTable タグと同じ名称です。
	 * ファイルの先頭行が、０行としてカウントしますので、設定値は、読み飛ばす
	 * 件数になります。(１と指定すると、１行読み飛ばし、２行目から読み込みます。)
	 * 行の読み飛ばしと、カラムの読み飛ばし(columns)、refFileURL、refFilename、
	 * refSheetName とともに使用すれば、ある程度のレイアウト設定が可能です。
	 * なお、この機能は、TableWriter_Excel のみに実装します。
	 *
	 * @og.rev 5.7.9.0 (2014/08/08) 新規作成
	 *
	 * @param	count 書き込み開始行番号
	 */
	public void setSkipRowCount( final String count ) {
		skipRowCount = nval( getRequestParameter( count ),skipRowCount );
	}

	/**
	 * 【TAG】チェック行のみを対象にするかを指定します(初期値:true)。
	 *
	 * @og.tag
	 * falseを指定する事で、前画面でチェックした行のみを出力します。
	 * 初期値は全ての行を出力(true)です。
	 * 出力されるファイルの行番号は、1から振りなおされます。
	 *
	 * @og.rev 5.5.5.5 (2012/08/24) 新規作成
	 *
	 * @param   flag 対象にするか指定 [true:全件/false:対象のみ]
	 */
	public void setSelectedAll( final String flag ) {
		selectedAll = nval( getRequestParameter( flag ),selectedAll );		// 5.5.9.1 (2012/12/07) バグ対応
	}

	/**
	 * 【TAG】事前にファイルを削除するかどうかを指定します(初期値:false)。
	 *
	 * @og.tag
	 * 出力元の DBTableModel が、存在しないか、０件の場合、過去に作成したファイルが
	 * そのまま、残っていると、不要なトラブルのもととなる為、実行前に削除するか
	 * どうかを指定できます。
	 * なお、fileAppend="true"（追加モードで書き込むを指定)時には、データが０件でも
	 * 事前削除は行いません。
	 * 初期値は互換性のため削除しない(false)です。
	 *
	 * @og.rev 5.5.9.1 (2012/12/07) 新規作成
	 *
	 * @param   flag 事前削除するかどうか [true:削除する/false:削除しない]
	 */
	public void setBeforeDelete( final String flag ) {
		beforeDelete = nval( getRequestParameter( flag ),beforeDelete );
	}

	/**
	 * WriteTable オブジェクトに渡すパラメータオブジェクトをセットします。
	 *
	 * @og.tag
	 * WriteTableParamTag クラスよりセットされます。
	 *
	 * @og.rev 4.0.0.0 (2005/02/28) 新規追加
	 *
	 * @param   entry HybsEntryオブジェクト
	 */
	protected void addParam( final HybsEntry entry ) {
		if( param == null ) { param = new ArrayList<HybsEntry>(); }
		param.add( entry );
	}

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

	/**
	 * 【TAG】保存先ストレージタイプを設定します。
	 *  
	 * @og.tag
	 * ファイルを読み取り元の、ストレージタイプを設定します。
	 * 未設定の場合は、システムリソースの「CLOUD_TARGET」が参照されます。
	 * 自身のサーバを指定する場合は、「default」を設定してください。
	 * 
	 * @og.rev 5.10.9.0 (2019/03/01) 新規追加
	 * 
	 * @param storage 保存先ストレージタイプ
	 */
	public void setStorageType( final String storage ) {
		storageType = nval( getRequestParameter( storage ), storageType );
	}
	
	/**
	 * 【TAG】保存先バケット名を設定します。
	 * 
	 * @og.tag
	 * ファイルを読み取り元の、バケット名を指定します。
	 * クラウドストレージ利用時のみ有効です。
	 * 未設定の場合は、システムリソースの「CLOUD_BUKET」が参照されます。
	 * 
	 * @og.rev 5.10.9.0 (2019/03/01) 新規追加
	 * 
	 * @param bucket 保存先バケット名
	 */
	public void setBucketName( final String bucket ) {
		bucketName = nval( getRequestParameter( bucket ), bucketName );
	}
	
	/**
	 * このオブジェクトの文字列表現を返します。
	 * 基本的にデバッグ目的に使用します。
	 *
	 * @og.rev 5.10.9.0 (2019/03/01) 出力対象に、storageType,bucketNameを追加。
	 *
	 * @return このクラスの文字列表現
	 */
	@Override
	public String toString() {
		return org.opengion.fukurou.util.ToString.title( this.getClass().getName() )
				.println( "VERSION"			,VERSION		)
				.println( "BASE_URL"		,BASE_URL		)
				.println( "separator"		,separator		)
				.println( "headerSequence"	,headerSequence	)
				.println( "fileURL"			,fileURL 		)
				.println( "filename"		,filename		)
				.println( "refFileURL"		,refFileURL		)
				.println( "refFilename"		,refFilename 	)
				.println( "encode"			,encode			)
				.println( "writerClass"		,writerClass 	)
				.println( "fileAppend"		,fileAppend		)
				.println( "direct"			,direct			)
				.println( "zip"				,zip 			)
				.println( "disposition"		,disposition	)
				.println( "tableId"			,tableId 		)
				.println( "sheetName"		,sheetName		)
				.println( "refSheetName"	,refSheetName	)
				.println( "useNumber"		,useNumber		)
				.println( "storageType"		,storageType	)
				.println( "bucketName"		,bucketName		)
				.println( "Other..."	,getAttributes().getAttribute() )
				.fixForm().toString() ;
	}
}
