package org.itscool.weber.testcase;

import java.sql.Connection;

import org.itscool.commons.connection.ConnectionManager;
import org.itscool.commons.connection.Transaction;
import org.itscool.commons.connection.TransactionException;
import org.itscool.commons.dao.EntityInfoMapping;
import org.itscool.commons.pool.ObjectPool;
import org.itscool.commons.pool.ObjectPoolEventListener;

/**
 * モック用コネクションプールを管理するクラスです<BR>
 * <BR>
 * @author KANO
 * @since jdk1.4.1
 * @version 1.00A 2004/11/1
 */
public class MockConnectionManager implements ConnectionManager, ObjectPoolEventListener{
    private static MockConnectionManager instance = null;
    private ObjectPool pool;				//オブジェクトプール
    private int timeout;                  // Connection取得時のタイムアウト
    private boolean initFlg = false;     //初期化フラグ
    private int initSize = 0;				//プールの初期化サイズ
    private int maxSize = 1;				//プールのMAXサイズ
    private boolean mode = false;        // AutoCommitモード
    private boolean showSql = false;		//SQL表示フラグ
    private String dbType = EntityInfoMapping.DB_HSQL;
    
    public String toString(){
        return "Not Used Connection";
    }
    
    /**
     * 唯一のConnectionManagerインスタンスを取得します
     * @return 唯一のConnectionMangerインスタンスを返します
     */
    public static MockConnectionManager getInstance(){
        if( instance == null){
            instance = new MockConnectionManager();
        }
        return instance;
    }
    
    public void init(){
        pool = new ObjectPool(this, initSize, maxSize);
        for( int i=0; i<initSize; i++ ){
            pool.addNewElement( (Object)newTransaction() );
        }
    }
    
    /**
     * 新規コネクションの作成
     * @return Connectionインスタンスをプールから取得します
     * @throws TransactionException
     */
    private Transaction newTransaction() throws TransactionException{
        Connection con = null;
        MockTransaction trn = null;
        trn = new MockTransaction();
        trn.setShowSql(showSql);
        
        return trn;
    }
    
    /**
     * ConnectionManagerインスタンスが初期化されているか判定します
     * @return 初期化済みの場合はtrueを返します
     */
    public boolean isInit(){
        return initFlg;
    }
    
    /**
     * Transactionインスタンスをプールから取得します
     * プールにTransactionインスタンスがない場合はnullを返します
     * @return Transactionインスタンスを返します
     */
    public Transaction getTransaction(){
        if( timeout != -1 ){
            return (Transaction)pool.getElement(timeout);
        }else{
            return (Transaction)pool.getElement();
            
        }
    }
    
    /**
     * 不要になったTransactionインスタンスをプールに返します
     * @param trn 不要になったTransactionインスタンス
     */
    public void returnTransaction(Transaction trn){
        if(trn == null ){
            trn = newTransaction();
        }else if(trn.isClosed()){
            trn = newTransaction();
        }
        pool.returnElement(trn);
    }
    
    /**
     * コネクションプールを開放し、終了します。
     */
    public void destroy(){
        if(pool != null ){
            pool.release();
        }
        pool = null;
    }
    
    /**
     * org.itscool.commons.pool.Poolクラスから要素の追加を要求
     * するために呼ばれるイベントです<br>
     * 新しいConnectionインスタンスを生成し、Poolクラスに返します<br>
     * org.itscool.commons.pool.Poolクラス以外からこのメソッドを
     * 呼ばないでください
     */
    public Object doMissingElementEvent(){
        Transaction trn = newTransaction();
        return trn;
    }
    
    /**
     * org.itscool.commons.pool.Poolクラスから呼ばれる
     * イベントです<br>
     * 指定されたConnection要素のクローズ処理を実施します<br>
     * org.itscool.commons.pool.Poolクラス以外からこのメソッドを
     * 呼ばないでください
     * @param obj 指定された要素
     */
    public void doReleaseElementEvent(Object obj){
        Transaction trn = (Transaction) obj;
        try {
            trn.close();
        }catch (TransactionException e) {
            throw new TransactionException(e);
        }
    }
    
    /**
     * 現在のプールサイズを返します
     * @return 現在のプールサイズを返します
     */
    public int getPoolSize(){
        if( pool != null ){
            return pool.getPoolSize();
        }else{
            return -1;
        }
    }
    
    /**
     * プールの初期サイズを返します
     * @return プールの初期サイズを返します
     */
    public int getInitSize(){
        return initSize;
    }
    
    /**
     * プールの拡張可能な最大サイズを返します
     * @return 拡張可能なプールサイズを返します
     */
    public int getMaxSize(){
        return maxSize;
    }
    
    /**
     * AutoCommitモードをセットします
     * @param mode AutoCommitモード
     */
    public void setMode(boolean mode) {
        this.mode = mode;
    }
    
    /**
     * SQL表示モードをセットします
     * @param showSql SQL表示モード
     */
    public void setShowSql(boolean showSql) {
        this.showSql = showSql;
    }
    
    /**
     * コネクションタイムアウトをセットします
     * @param timeout コネクションタイムアウト
     */
    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }
    
    /**
     * コネクションプールの初期サイズをセットします
     * @param initSize コネクションプールの初期サイズ
     */
    public void setInitSize(int initSize) {
        this.initSize = initSize;
    }
    
    /**
     * コネクションプールの最大サイズをセットします
     * @param maxSize
     */
    public void setMaxSize(int maxSize) {
        this.maxSize = maxSize;
    }
    
    /**
     * ConnectionMangerインスタンスの初期化状況を取得します
     * @return 初期済みの場合はtrueを返します
     */
    public boolean isInitFlg() {
        return initFlg;
    }
    
    /**
     * AutoCommitModeを取得します
     * @return AutoCommitModeが有効になっている場合はtureを返します
     */
    public boolean getMode() {
        return mode;
    }
    
    /**
     * SQL表示モードを取得します
     * @return SQL表示の場合はtrueを返します
     */
    public boolean getShowSql() {
        return showSql;
    }
    
    /**
     * コネクションタイムアウトを取得します
     * @return コネクションタイムアウトをmsecで取得します
     */
    public int getTimeout() {
        return timeout;
    }
    
    /**
     * データベースタイプをセットします
     * @param dbType データベースタイプ
     */
    public void setDbType(String dbType){
        this.dbType = dbType;
    }
    /**
     * データベースタイプを取得します
     * @return String データベースタイプ
     */
    public String getDbType(){
        return dbType;
    }
}

