/*
 * 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.db;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.opengion.fukurou.db.Transaction;
import org.opengion.fukurou.db.ConnectionFactory;		// 5.3.8.0 (2011/08/01)
import org.opengion.fukurou.util.ErrorMessage;
import org.opengion.hayabusa.common.HybsSystem;
import org.opengion.hayabusa.common.HybsSystemException;
import org.opengion.hayabusa.resource.ResourceManager;

/**
 * Query インターフェースを継承した Query の実装クラスです。
 * クエリークラスにステートメントを与えて execute()することにより内部に DBTableModel を
 * 作成します。
 * このクラスは、Abstract クラスのため、実装は個々のサブクラスで行います。
 * 唯一実装する必要があるのは, execute() メソッドだけです。
 *
 * @og.group ＤＢ検索
 * @og.group ＤＢ登録
 *
 * @version  4.0
 * @author	 Kazuhiko Hasegawa
 * @since    JDK5.0,
 */
public class AbstractQuery implements Query {
	private Connection		connection	= null ;
	private Transaction		transaction	= null ;	// 5.1.9.0 (2010/08/01)
	private int 			rtnCode		= ErrorMessage.OK;
	private ErrorMessage	errMessage	= null;
	private ResourceManager resource	= null;
//	private ApplicationInfo appInfo		= null;		// 5.1.9.0 (2010/08/01) ローカル化

	private DBTableModel table			= null;
	private String		 connID			= null;
	private String		 stmtString		= null;
	private int 		 executeCount	= -1 ;
	private int 		 skipRowCount	= 0 ;
	private int 		 maxRowCount	= HybsSystem.sysInt( "DB_MAX_ROW_COUNT" ) ;
	private boolean		 updateFlag		= true ;
	private DBEditConfig config			= null; // 5.3.6.0 (2011/06/01)

	// 5.1.9.0 (2010/08/01) DB_RETRY_COUNT,DB_RETRY_TIME 廃止
//	private static final int DB_RETRY_COUNT		= HybsSystem.sysInt( "DB_RETRY_COUNT" ) ;
//	private static final int DB_RETRY_TIME		= HybsSystem.sysInt( "DB_RETRY_TIME" ) ;
	protected static final int DB_MAX_QUERY_TIMEOUT	= HybsSystem.sysInt( "DB_MAX_QUERY_TIMEOUT" ) ;

	// 3.5.2.0 (2003/10/20) 内部オブジェクトタイプ名を システムパラメータ で定義します。
	/** 内部オブジェクトタイプ名  {@value} */
	public static final String ARG_ARRAY		= "ARG_ARRAY" ;
	/** 内部オブジェクトタイプ名  {@value} */
	public static final String SYSARG_ARRAY		= "SYSARG_ARRAY" ;
	/** 内部オブジェクトタイプ名  {@value} */
	public static final String ERR_MSG 			= "ERR_MSG" ;
	/** 内部オブジェクトタイプ名  {@value} */
	public static final String ERR_MSG_ARRAY	= "ERR_MSG_ARRAY" ;

	/**
	 * Queryオブジェクトを初期化します。
	 * これは、QueryFactory のプールから取り出すときに(または戻すとき)に
	 * 初期化するのに使用します。
	 *
	 * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。
	 * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為,ApplicationInfoオブジェクトを設定
	 * @og.rev 5.1.9.0 (2010/08/01) transaction 属性(外部Transactionの使用)追加
	 * @og.rev 5.3.6.0 (2011/06/01) DBEditConfig 追加
	 *
	 */
	public void init() {
		close();					// 先にクローズ処理を行います。(transaction = null がセット)
		rtnCode			= ErrorMessage.OK;
		errMessage		= null;
		resource		= null;
//		appInfo			= null;		// 5.1.9.0 (2010/08/01) ローカル化
		table			= null;
		connID			= null;
		stmtString		= null;
		executeCount	= -1 ;
		skipRowCount	= 0 ;
		maxRowCount		= HybsSystem.sysInt( "DB_MAX_ROW_COUNT" ) ;
		updateFlag		= true ;
		connection		= null;		// 5.1.9.0 (2010/08/01) キャッシュの初期化
		config			= null;		// 5.3.6.0 (2011/06/01) DBEditConfig追加
	}

	/**
	 * ステートメント文字列をセットします。
	 *
	 * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。
	 *
	 * @param	stmt ステートメント文字列
	 *
	 */
	public void setStatement( final String stmt ) {
		this.stmtString = stmt.trim();
	}

	/**
	 * ステートメント文字列を取り出します。
	 *
	 * @return	 ステートメント文字列
	 *
	 */
	public String getStatement() {
		return stmtString;
	}

	/**
	 * クエリーを実行します。
	 * 実行方法等は各サブクラスの実装に依存します。
	 * セットされているステートメント文字列とそのタイプが合っていない場合は,
	 * エラーになります。
	 * 実行結果は、DBTableModel にセットされます。
	 * 実行結果の件数は #getExecuteCount() で取得できます。
	 * ※ このクラスでは実装されていません。
	 *
	 * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。
	 *
	 */
	public void execute() {
		String errMsg = "このクラスでは実装されていません。execute()";
		throw new UnsupportedOperationException( errMsg );
	}

	/**
	 * 引数配列付のクエリーを実行します。
	 * 処理自体は, #execute() と同様に、各サブクラスの実装に依存します。
	 * これは、PreparedQuery で使用する引数を配列でセットするものです。
	 * select * from emp where deptno = ? and job = ? などの PreparedQuery や
	 * { call xxxx( ?,?,? ) } などの CallableStatement の ? 部分の引数を
	 * 順番にセットしていきます。
	 * ※ このクラスでは実装されていません。
	 *
	 * @param	args オブジェクトの引数配列
	 */
	public void execute( final String[] args ) {
		String errMsg = "このクラスでは実装されていません。execute( String[] )";
		throw new UnsupportedOperationException( errMsg );
	}

	/**
	 * 引数配列付のクエリーを実行します。
	 * 処理自体は, #execute() と同様に、各サブクラスの実装に依存します。
	 * これは、PreparedQuery で使用する引数を配列でセットするものです。
	 * select * from emp where deptno = ? and job = ? などの PreparedQuery の
	 * ? 部分の引数を
	 * 順番にセットしていきます。
	 * ※ このクラスでは実装されていません。
	 *
	 * @og.rev 4.0.0.0 (2005/01/31) 新規追加
	 *
	 * @param   keys オブジェクトのキー配列
	 * @param   args オブジェクトの引数配列
	 */
	public void execute( final String[] keys, final String[] args ) {
		String errMsg = "このクラスでは実装されていません。execute( String[],String[] )";
		throw new UnsupportedOperationException( errMsg );
	}

	/**
	 * 引数配列付のクエリーを実行します。
	 * 処理自体は, #execute() と同様に、各サブクラスの実装に依存します。
	 * これは、PreparedQuery で使用する引数を配列でセットするものです。
	 * select * from emp where deptno = ? and job = ? などの PreparedQuery の
	 * ? 部分の引数を
	 * 順番にセットしていきます。
	 * ※ このクラスでは実装されていません。
	 *
	 * @og.rev 4.0.0.0 (2005/01/31) 引数をすべて受け取って実行するメソッドを標準メソッドとして追加
	 *
	 * @param	names		カラム名(CSV形式)
	 * @param	dbArrayType	アレイタイプ名称
	 * @param	sysArg		DBSysArg配列
	 * @param	userArg		DBUserArg配列
	 */
	public void execute( final String names,final String dbArrayType,
						final DBSysArg[] sysArg,final DBUserArg[] userArg ) {
		String errMsg = "このクラスでは実装されていません。execute( String,String,DBSysArg[],DBUserArg[] )";
		throw new UnsupportedOperationException( errMsg );
	}

	/**
	 * 引数配列付のクエリーを実行します。
	 * 処理自体は, #execute() と同様に、各サブクラスの実装に依存します。
	 * これは、PreparedQuery で使用する引数を配列でセットするものです。
	 * select * from emp where deptno = ? and job = ? などの PreparedQuery の
	 * [カラム名] 部分の引数を、DBTableModelから順番にセットしていきます。
	 * ※ このクラスでは実装されていません。
	 *
	 * @param   rowNo 選択された行番号配列(登録する対象行)
	 * @param   table DBTableModelオブジェクト(登録する元データ)
	 */
	public void execute( final int[] rowNo, final DBTableModel table ) {
		String errMsg = "このクラスでは実装されていません。execute( final int[] rowNo, final DBTableModel table )";
		throw new UnsupportedOperationException( errMsg );
	}

	/**
	 * コミットを行います。
	 *
	 * 外部からコネクションが与えられた場合は、何も行いません。
	 *
	 * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。
	 * @og.rev 3.8.0.8 (2005/10/03) エラーメッセージの出力順をメッセージ＋Queryに変更します。
	 * @og.rev 5.1.9.0 (2010/08/01) transaction 属性追加。
	 *
	 */
	public void commit() {
		if( transaction == null ) { return; }

		if( !transaction.commit() ) {
			transaction.rollback();
			realClose();
			String errMsg = "コミットすることが出来ませんでした。" + HybsSystem.CR
						+ getStatement() + HybsSystem.CR ;
			throw new HybsSystemException( errMsg );
		}

//		if( connection == null ) { return; }
//		try {
//			connection.commit();
//		}
//		catch( SQLException ex ) {
//			transaction.rollback();				// 5.1.9.0 (2010/08/01)
//			realClose();
//			String errMsg = "コミットすることが出来ませんでした。" + HybsSystem.CR
//						+ ex.getMessage() + ":" + ex.getSQLState()
//						+ HybsSystem.CR + getStatement() + HybsSystem.CR ;
//			throw new HybsSystemException( errMsg,ex );		// 3.5.5.4 (2004/04/15) 引数の並び順変更
//		}
	}

	/**
	 * ロールバックを行います。
	 *
	 * 外部からコネクションが与えられた場合は、何も行いません。
	 *
	 * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。
	 * @og.rev 3.8.0.8 (2005/10/03) エラーメッセージの出力順をメッセージ＋Queryに変更します。
	 * @og.rev 5.1.9.0 (2010/08/01) transaction 属性追加。
	 *
	 */
	public void rollback() {
		if( transaction == null ) { return; }

		if( !transaction.rollback() ) {
			realClose();
			String errMsg = "ロールバックすることが出来ません。" + HybsSystem.CR
						 + getStatement() + HybsSystem.CR ;
			throw new HybsSystemException( errMsg );
		}

//		if( connection == null ) { return; }
//		try {
//			connection.rollback();
//		}
//		catch( SQLException ex ) {
//			if( transaction != null ) { transaction.rollback(); }	// 5.1.9.0 (2010/08/01)
//			realClose();
//			String errMsg = "ロールバックすることが出来ません。" + HybsSystem.CR
//						 + ex.getMessage() + ":" + ex.getSQLState()
//						 + HybsSystem.CR + getStatement() + HybsSystem.CR ;
//			throw new HybsSystemException( errMsg,ex );		// 3.5.5.4 (2004/04/15) 引数の並び順変更
//		}
	}

	/**
	 * 使用した Statementオブジェクトをクロースし、Connection オブジェクトを
	 * プールに返します。
	 * 主に、正常終了した場合のクローズ処理になります。
	 *
	 * 外部からコネクションが与えられた場合は、何も行いません。
	 *
	 * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。
	 * @og.rev 3.6.0.4 (2004/10/14) SQLWarning の取得(getWarning)をコメントアウトします。
	 * @og.rev 5.1.9.0 (2010/08/01) transaction 属性追加。
	 * @og.rev 5.3.8.0 (2011/08/01) Transaction発生箇所でclose()するため、ここではclose() しない。
	 *
	 */
	public void close() {
//		if( transaction != null ) {
//			transaction.close();	// 正常な場合のクローズ
//			transaction = null;
//		}

//		if( connection != null ) {
//			try {
//				// 4.0.0 (2005/01/31)
//				if( rtnCode > ErrorMessage.NG ) {
//					realClose();
//				}
//			}
//			finally {
//				ConnectionFactory.close( connection,connID );	// 4.0.0 (2005/01/31)
//				connection = null;
//			}
//		}
	}

	/**
	 * Connection オブジェクトを実際にクローズ(破棄)します。
	 * プールからも削除します。
	 * 実行時エラー等が発生したときに、このメソッドを呼び出します。
	 *
	 * 外部からコネクションが与えられた場合は、何も行いません。
	 *
	 * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。
	 * @og.rev 5.1.9.0 (2010/08/01) transaction 属性追加。
	 * @og.rev 5.3.8.0 (2011/08/01) Transaction発生箇所でclose()するため、ここではclose() しない。
	 *
	 */
	public void realClose() {
//		if( transaction != null ) {
//			transaction.close( true );	// エラーが発生した場合のクローズ
//			transaction = null;
//		}

//		if( connection != null ) {
//			ConnectionFactory.remove( connection,connID );
//			connection = null;
//		}
	}

	/**
	 * クエリーの実行結果件数をセットします。
	 * 初期値は -1 です。(クエリーが失敗した場合や,CallableStatement の呼び出し等で
	 * 実行件数が明確でない場合の戻り値)。
	 *
	 * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。
	 *
	 * @param	executeCount 実行結果件数
	 */
	protected void setExecuteCount( final int executeCount ) {
		this.executeCount = executeCount;
	}

	/**
	 * クエリーの実行結果を返します。
	 * クエリーが失敗した場合や,CallableStatement の呼び出し等で実行件数が明確でない
	 * 場合は, -1 が返されます。
	 *
	 * @return	実行結果件数
	 */
	public int getExecuteCount() {
		return executeCount;
	}

	/**
	 * DBTableModel をセットします。
	 * なお、検索系実行前に setDBTableModel() でテーブルをセットしていたとしても
	 * そのオブジェクトは破棄されて、新しい DBTableModel が生成されます。
	 *
	 * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。
	 *
	 * @param	table DBTableModelオブジェクト
	 */
	protected void setDBTableModel( final DBTableModel table ) {
		this.table = table;
	}

	/**
	 * 実行結果の DBTableModel を返します。
	 *
	 * @return	DBTableModelオブジェクト
	 */
	public DBTableModel getDBTableModel() {
		return table;
	}

	/**
	 * データベースの最大検索件数を返します。
	 *		(初期値:DB_MAX_ROW_COUNT[={@og.value org.opengion.hayabusa.common.SystemData#DB_MAX_ROW_COUNT}])。
	 * データベース自体の検索は,指定されたSQLの全件を検索しますが,
	 * DBTableModelのデータとして登録する最大件数をこの値に設定します。0は無制限です。
	 * サーバーのメモリ資源と応答時間の確保の為です。
	 *
	 * @return	最大検索件数
	 */
	public int getMaxRowCount() {
		return maxRowCount;
	}

	/**
	 * データベースの最大検索件数をセットします。
	 * データベース自体の検索は,指定されたSQLの全件を検索しますが,
	 * DBTableModelのデータとして登録する最大件数をこの値に設定します。
	 * サーバーのメモリ資源と応答時間の確保の為です。
	 * ゼロ、または、負の値を設定すると、無制限(Integer.MAX_VALUE)になります。
	 *
	 * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。
	 * @og.rev 4.0.0.0 (2005/08/31) ゼロ、または、負の値は、無制限(Integer.MAX_VALUE)にする。
	 *
	 * @param	maxRowCount 最大検索件数
	 */
	public void setMaxRowCount( final int maxRowCount ) {
		this.maxRowCount = ( maxRowCount > 0 ) ? maxRowCount : Integer.MAX_VALUE ;
	}

	/**
	 * データベースの検索スキップ件数を返します。
	 * データベース自体の検索は,指定されたSQLの全件を検索しますが,
	 * DBTableModelのデータとしては、スキップ件数分は登録されません。
	 * サーバーのメモリ資源と応答時間の確保の為です。
	 *
	 * @return	最大検索件数
	 */
	public int getSkipRowCount() {
		return skipRowCount;
	}

	/**
	 * データベースの検索スキップ件数をセットします。
	 * データベース自体の検索は,指定されたSQLの全件を検索しますが,
	 * DBTableModelのデータとしては、スキップ件数分は登録されません。
	 * サーバーのメモリ資源と応答時間の確保の為です。
	 *
	 * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。
	 *
	 * @param	skipRowCount スキップ件数
	 */
	public void setSkipRowCount( final int skipRowCount ) {
		this.skipRowCount = skipRowCount;
	}

	/**
	 * データベースの接続先IDをセットします。
	 * システムパラメータ ファイルに定義してある データベース識別IDによって、
	 * 接続先を切り替えます。
	 * この接続先IDを元に,Connection オブジェクトを作成します。
	 *
	 * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。
	 * @og.rev 5.1.9.0 (2010/08/01) 廃止
	 *
	 * @param	connID 接続先ID
	 */
//	public void setConnectionID( final String connID ) {
//		close();
//		this.connID = connID;
//	}

	/**
	 * アップデートフラグをセットします。
	 * これは、Query で更新処理の SQL 文を実行したときにセットされます。
	 * 更新処理が実行：true / 検索処理のみ：false をセットします。
	 * このメソッドを呼び出さない場合は、デフォルト：true	です。
	 *
	 * @og.rev 2.1.2.3 (2002/12/02) データベース更新時に、更新フラグをセットするように変更
	 * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。
	 *
	 * @param	up	アップデートされたかどうか[true:更新処理/false:検索処理]
	 */
	protected void setUpdateFlag( final boolean up ) {
		updateFlag = up;
	}

	/**
	 * アップデートフラグを取得します。
	 * これは、Query で更新処理の SQL 文を実行したときに true にセットされます。
	 * 更新処理が実行：true / 検索処理のみ：false を取得できます。
	 *
	 * @og.rev 2.1.2.3 (2002/12/02) データベース更新時に、更新フラグをセットするように変更
	 * @og.rev 4.0.0.0 (2007/07/20) メソッド名変更( getUpdateFlag() ⇒ isUpdate() )
	 *
	 * @return	 アップデートされたかどうか[true:更新処理/false:検索処理]
	 */
	public boolean isUpdate() {
		return updateFlag ;
	}

	/**
	 * リソースマネージャーをセットします。
	 * これは、言語(ロケール)に応じた DBColumn をあらかじめ設定しておく為に
	 * 必要です。
	 * リソースマネージャーが設定されていない、または、所定のキーの DBColumn が
	 * リソースに存在しない場合は、内部で DBColumn オブジェクトを作成します。
	 *
	 * @og.rev 4.0.0.0 (2005/01/31) lang ⇒ ResourceManager へ変更
	 *
	 * @param	resource リソースマネージャー
	 */
	public void setResourceManager( final ResourceManager resource ) {
		this.resource = resource;
	}

	/**
	 * アクセスログ取得の為,ApplicationInfoオブジェクトを設定します。
	 *
	 * @og.rev 3.8.7.0 (2006/12/15) 新規追加
	 * @og.rev 5.1.9.0 (2010/08/01) 廃止
	 *
	 * @param   appInfo ApplicationInfo
	 */
//	public void setApplicationInfo( final ApplicationInfo appInfo ) {
//		this.appInfo = appInfo;
//	}

	/**
	 * 内部のリソースを元に言語コード を返します。
	 * 内部にリソースが登録されていない場合は, null を返します。
	 *
	 * @og.rev 5.3.6.0 (2011/06/01) 廃止
	 *
	 * @return	 言語コード
	 */
//	public String getLang() {
//		String lang = null;
//		if( resource != null ) { lang = resource.getLang(); }
//		return lang;
//	}

	/**
	 * エラーコード を取得します。
	 * エラーコード は、ErrorMessage クラスで規定されているコードです。
	 *
	 * @return   エラーコード
	 */
	public int getErrorCode() { return rtnCode; }

	/**
	 * エラーコード をセットします。
	 * エラーコード は、ErrorMessage クラスで規定されているコードです。
	 *
	 * @param   cd エラーコード
	 */
	protected void setErrorCode( final int cd ) { rtnCode = cd; }

	/**
	 * エラーメッセージオブジェクト を取得します。
	 *
	 * @return   エラーメッセージオブジェクト
	 */
	public ErrorMessage getErrorMessage() { return errMessage; }

	/**
	 * エラーメッセージオブジェクト をセットします。
	 *
	 * @param   em エラーメッセージオブジェクト
	 */
	protected void setErrorMessage( final ErrorMessage em ) { errMessage = em; }

	/**
	 * エディット設定オブジェクトをセットします。
	 *
	 * @og.rev 5.3.6.0 (2011/06/01) 新規追加
	 *
	 * @param config エディット設定オブジェクト
	 */
	public void setEditConfig( final DBEditConfig config ) {
		this.config = config;
	}

	/**
	 * エディット設定オブジェクトを取得します。
	 *
	 * @og.rev 5.3.6.0 (2011/06/01) 新規追加
	 *
	 * @return エディット設定オブジェクト
	 */
	protected DBEditConfig getEditConfig() {
		return config;
	}

	//////////////////////////////////////////////////////////////////////////
	//
	//	 継承時にサブクラスから使用するメソッド類( protected )
	//
	//////////////////////////////////////////////////////////////////////////

	/**
	 * ResultSet を DBTableModelに割り当てます。
	 *
	 * 毎回,検索毎に,DBTableModel にコピーするイメージです。
	 * ResulSet 以外のオブジェクトから，DBTableModelを作成する場合は,
	 * このメソッドをオーバーライドします。
	 *
	 * このメソッドは， execute からのみ,呼び出されます。
	 * それ以外からは呼出し出来ません。
	 *
	 * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。
	 * @og.rev 3.3.3.3 (2003/08/06) カラムのラベル名を、大文字に変換する。
	 * @og.rev 3.8.5.0 (2006/03/02) CLOB カラムかどうかを判定しCLOBの場合は、Clob オブジェクトから文字列を取り出します。
	 * @og.rev 3.8.8.8 (2007/05/11) ROWID対応(小数点対応 "0.3" が ".3" と表示される対策)
	 * @og.rev 4.0.0.0 (2006/01/31) CLOB カラムかどうかを判定しCLOBの場合は、ストリームから値を取り出します。
	 * @og.rev 5.3.6.0 (2011/06/01) DBTableModel作成処理をDBTableModelUtilに移動＆集計機能対応
	 *
	 * @param	resultSet ResultSetオブジェクト
	 */
	protected void createTableModel( final ResultSet resultSet ) {
		try {
			if( config == null ) {
				table = DBTableModelUtil.makeDBTable( resultSet, getSkipRowCount(), maxRowCount, resource );
			}
			else {
				table = DBTableModelUtil.makeEditDBTable( resultSet, getSkipRowCount(), maxRowCount, resource, config );
			}

			setExecuteCount( table.getRowCount() );
		}
		catch( SQLException ex ) {
			realClose();
			String errMsg = "テーブルモデルを作成できませんでした。";
			throw new HybsSystemException( errMsg,ex );		// 3.5.5.4 (2004/04/15) 引数の並び順変更
		}
	}

	/**
	 * ConnectionFactory.connection( String ); を利用して,Connection
	 * オブジェクトを取り出します。
	 *
	 * コネクションプールが一杯の場合は、即エラーになります。
	 *
	 * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。
	 * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為,ApplicationInfoオブジェクトを設定
	 * @og.rev 5.1.9.0 (2010/08/01) transaction 属性追加。
	 *
	 * @return	コネクション
	 */
	protected Connection getConnection() {
//		if( connection != null ) { return connection; }

		if( connection == null ) {
			// 5.1.9.0 (2010/08/01) transaction 属性追加。
			if( transaction == null ) {
				String errMsg = "Transaction をセットする前に、コネクションを取り出す要求がなされました。"
								+ HybsSystem.CR
								+ "connID = [" + connID + "]" ;
				throw new HybsSystemException( errMsg );
			}
			else {
				connection = transaction.getConnection( connID );
			}
		}

		return connection;

//		MissingResourceException exTemp = null;
//		for( int i=0; i<DB_RETRY_COUNT; i++ ) {
//			try {
//				connection = ConnectionFactory.connection( connID,appInfo );
//				return connection;
//			}
//			catch( MissingResourceException ex ) {
//				try {
//					exTemp = ex;
//					Thread.sleep( DB_RETRY_TIME );
//				}
//				catch ( InterruptedException ex2) {
//					LogWriter.log( "InterruptedException:" + ex2.getMessage() );
//				}
//			}
//		}
//		String errMsg = "コネクションを取り出すことが出来ませんでした。 "
//						+ HybsSystem.CR
//						+ "connID = [" + connID + "]" ;
//		throw new HybsSystemException( errMsg,exTemp );
	}

	/**
	 * Transactionオブジェクトを外部から設定します。
	 *
	 * 通常は、ConnectionFactory を使用して、内部で Connection を作成しますが、
	 * 一連のトランザクション処理を実施するには、外部から Transactionオブジェクトを
	 * を与えて、そこから、Connection を取り出す必要があります。
	 *
	 * ここでは、内部の connection が存在しない場合に限り、セットを許可します。
	 *
	 * @og.rev 5.1.9.0 (2010/08/01) 新規追加
	 *
	 * @param	connID	接続先ID
	 * @param	tran	Transactionオブジェクト
	 */
	public void setTransaction( final String connID , final Transaction tran ) {
		if( transaction == null ) {
			transaction	= tran;
			this.connID = connID;
		}
		else {
			String errMsg = "トランザクションは、すでに設定済みです。"
							+ HybsSystem.CR
							+ "connID = [" + connID + "]" ;
			throw new HybsSystemException( errMsg );
		}
	}

	/**
	 * connection オブジェクトから，ワーニングデータを取り出します。
	 *
	 * ワーニングデータは，SQLWarning クラスのオブジェクトに複数件貯えられます。
	 * query 実行後に,確認しておく必要があります。
	 *
	 * このメソッドは， execute からのみ,呼び出されます。
	 * それ以外からは呼出し出来ません。
	 *
	 * @param	connection Connection
	 *
	 * @return	ワーニング ErrorMessage
	 */
	//	protected ErrorMessage getWarning( final Connection connection ) {
	//		if( connection == null ) { return null; }
	//
	//		try {
	//			ErrorMessage em = new ErrorMessage();
	//			for( SQLWarning warning = connection.getWarnings();
	//							warning != null ;
	//							warning = warning.getNextWarning() ) {
	//				em.addMessage( 0,ErrorMessage.WARNING,warning.getMessage(),warning.getSQLState() );
	//			}
	//			return em;
	//		}
	//		catch (SQLException ex) {
	//			realClose();
	//			String errMsg = "ワーニングを取り出すことが出来ませんでした。";
	//			errMsg += System.getProperty( "line.separator" );
	//			errMsg += ex.getMessage() + ":" + ex.getSQLState();
	//			throw new HybsSystemException( errMsg,ex );		// 3.5.5.4 (2004/04/15) 引数の並び順変更
	//		}
	//	}

	/**
	 * この接続が、PreparedStatement#getParameterMetaData() を使用するかどうかを判定します。
	 *
	 * ConnectionFactory#useParameterMetaData(String) の結果を返します。(postgreSQL対応)
	 *
	 * @og.rev 5.3.8.0 (2011/08/01) 新規追加
	 *
	 * @return	使用する場合：true / その他:false
	 * @see org.opengion.fukurou.db.ConnectionFactory#useParameterMetaData(String)
	 */
	protected boolean useParameterMetaData() {
		return ConnectionFactory.useParameterMetaData( connID );
	}

	//////////////////////////////////////////////////////////////////////////
	//
	//	 Object クラスのオーバーライド部分
	//
	//////////////////////////////////////////////////////////////////////////

	/**
	 * オブジェクトの識別子として，最後のクエリーを返します。
	 *
	 * @return	最後のクエリー
	 */
	@Override
	public String toString() {
		return	"LastQuery  :[" + getStatement() + "] ";
	}
}
