package org.maachang.mimdb.core ;

import org.maachang.mimdb.MimdbException;
import org.maachang.mimdb.core.impl.EqualsNoList;

/**
 * Remote用結果メタデータ.
 * 
 * @version 2014/01/20
 * @author masahito suzuki
 * @since MasterInMemDB 1.02
 */
final class RemoteMetaDataImpl implements MimdbMetaData {
    
    /** コネクションテーブル. **/
    protected RemoteConnection connection = null ;
    
    /** コンパイルオブジェクト. **/
    protected QueryCompileInfo compile = null ;
    
    /** 表示カラム条件. **/
    protected EqualsNoList viewColumnList ;
    
    /** ResultSetクリア時に破棄する場合は[true]. **/
    protected boolean isClearFlag ;
    
    /**
     * コンストラクタ.
     */
    public RemoteMetaDataImpl() {}
    
    /**
     * コンストラクタ.
     * @param conn 対象のリモートコネクションオブジェクトを設定します.
     * @param cmp 対象のコンパイル済みオブジェクトを設定します.
     * @param clearFlg [true]の場合は、ResultSetクリア時に情報を破棄します.
     */
    public RemoteMetaDataImpl( RemoteConnection conn,QueryCompileInfo cmp,boolean clearFlg ) {
        create( conn,cmp,clearFlg ) ;
    }
    
    /** ファイナライズ. **/
    protected void finalize() throws Exception {
        clear() ;
    }
    
    /**
     * 情報生成.
     * @param conn 対象のリモートコネクションオブジェクトを設定します.
     * @param cmp 対象のコンパイル済みオブジェクトを設定します.
     * @param clearFlg [true]の場合は、ResultSetクリア時に情報を破棄します.
     */
    public void create( RemoteConnection conn,QueryCompileInfo cmp,boolean clearFlg ) {
        this.connection = conn ;
        this.compile = cmp ;
        this.viewColumnList = cmp.columns ;
        this.isClearFlag = clearFlg ;
    }
    
    /**
     * 情報クリア.
     */
    public void clear() {
        connection = null ;
        compile = null ;
        viewColumnList = null ;
        isClearFlag = true ;
    }
    
    /** 情報がクリアされたかチェック. **/
    protected final boolean isClearData() {
        return connection == null ;
    }
    
    /**
     * 情報がクリアされたかチェック.
     * @return boolean [true]の場合はクリアされています.
     */
    public boolean isClear() {
        return connection == null || connection.isClose() ;
    }
    
    /** チェック. **/
    protected void check() {
        if( isClear() ) {
            throw new MimdbException( "オブジェクトは既にクローズされています" ) ;
        }
    }
    
    /**
     * 更新IDを取得.
     * @return long 更新IDが返却されます.
     */
    public long getDbId() {
        check() ;
        return compile.dbId ;
    }
    
    /**
     * テーブル名の取得.
     * @return String テーブル名が返却されます.
     */
    public String getName() {
        check() ;
        return compile.name ;
    }
    
    /**
     * テーブルオブジェクトを取得.
     * @return BaseTable テーブルオブジェクトが返却されます.
     */
    public BaseTable getTable() {
        check() ;
        try {
            return connection.client.getTable( compile.name ) ;
        } catch( RuntimeException r ) {
            throw r ;
        } catch( Exception e ) {
            throw new MimdbException( e ) ;
        }
    }
    
    /**
     * カラム数の取得.
     * @return int カラム数が返却されます.
     */
    public int getColumnSize() {
        check() ;
        // カウント表示の場合.
        if( compile.countFlag ) {
            return 1 ;
        }
        // 表示カラム条件が設定されている場合.
        if( viewColumnList != null ) {
            return viewColumnList.size() ;
        }
        return getTable().getColumnSize() ;
    }
    
    /**
     * カラム名を取得.
     * @param no カラム項番を設定します.
     * @return String カラム名が返却されます.
     */
    public String getColumnName( int no ) {
        check() ;
        // カウント表示の場合.
        if( compile.countFlag ) {
            if( no != 0 ) {
                return null ;
            }
            return CountMetaDataImpl.COLUMN_NAME ;
        }
        // 表示カラム条件が設定されている場合.
        if( viewColumnList != null ) {
            no = viewColumnList.src( no ) ;
        }
        return getTable().getColumnName( no ) ;
    }
    
    /**
     * 指定カラム名に対する項番を取得.
     * @param name カラム名を設定します.
     * @return int カラム項番が返却されます.
     *             [-1]の場合は対象カラム名は存在しません.
     */
    public int getColumnNameByNo( String name ) {
        check() ;
        // カウント表示の場合.
        if( compile.countFlag ) {
            if( CountMetaDataImpl.COLUMN_NAME.equals( name ) ) {
                return 0 ;
            }
            return -1 ;
        }
        // 表示カラム条件が設定されている場合.
        BaseTable table = getTable() ;
        if( viewColumnList != null ) {
            int ret = table.getColumnNameByNo( name ) ;
            if( !viewColumnList.equals( ret ) ) {
                return -1 ;
            }
            return ret ;
        }
        return table.getColumnNameByNo( name ) ;
    }
    
    /**
     * カラムタイプを取得.
     * @param no カラム項番を設定します.
     * @return int カラムタイプが返却されます.
     *             -1が返却された場合は、対象カラムは存在しません.
     * java.lang.Boolean  : MimdbIndex.COLUMN_BOOL
     * java.lang.Integer  : MimdbIndex.COLUMN_INT
     * java.lang.Long     : MimdbIndex.COLUMN_LONG
     * java.lang.Double   : MimdbIndex.COLUMN_FLOAT
     * java.lang.String   : MimdbIndex.COLUMN_STRING
     * java.sql.Date      : MimdbIndex.COLUMN_DATE
     * java.sql.Time      : MimdbIndex.COLUMN_TIME
     * java.sql.Timestamp : MimdbIndex.COLUMN_TIMESTAMP
     * java.util.Date     : MimdbIndex.COLUMN_DATE
     */
    public int getColumnType( int no ) {
        check() ;
        // カウント表示の場合.
        if( compile.countFlag ) {
            if( no != 0 ) {
                return -1 ;
            }
            return MimdbIndex.COLUMN_INT ;
        }
        // 表示カラム条件が設定されている場合.
        if( viewColumnList != null ) {
            no = viewColumnList.src( no ) ;
        }
        return getTable().getColumnType( no ) ;
    }
    
    /**
     * カラムタイプを取得.
     * @param name 対象のカラム名を設定します.
     * @return int カラムタイプが返却されます.
     *             -1が返却された場合は、対象カラムは存在しません.
     * java.lang.Boolean  : MimdbIndex.COLUMN_BOOL
     * java.lang.Integer  : MimdbIndex.COLUMN_INT
     * java.lang.Long     : MimdbIndex.COLUMN_LONG
     * java.lang.Double   : MimdbIndex.COLUMN_FLOAT
     * java.lang.String   : MimdbIndex.COLUMN_STRING
     * java.sql.Date      : MimdbIndex.COLUMN_DATE
     * java.sql.Time      : MimdbIndex.COLUMN_TIME
     * java.sql.Timestamp : MimdbIndex.COLUMN_TIMESTAMP
     * java.util.Date     : MimdbIndex.COLUMN_DATE
     */
    public int getColumnType( String name ) {
        check() ;
        // カウント表示の場合.
        if( compile.countFlag ) {
            if( CountMetaDataImpl.COLUMN_NAME.equals( name ) ) {
                return MimdbIndex.COLUMN_INT ;
            }
            return -1 ;
        }
        // 表示カラム条件が設定されている場合.
        BaseTable table = getTable() ;
        if( viewColumnList != null ) {
            int no = table.getColumnNameByNo( name ) ;
            if( !viewColumnList.equals( no ) ) {
                return -1 ;
            }
            return table.getColumnType( no ) ;
        }
        return table.getColumnType( name ) ;
    }
    
}
