package org.maachang.mimdb.core ;

import org.maachang.mimdb.MimdbException;
import org.maachang.mimdb.core.util.ObjectList;

/**
 * クエリー情報.
 * 
 * @version 2014/01/16
 * @author masahito suzuki
 * @since MasterInMemDB 1.02
 */
public final class QueryInfo {
    
    /** テーブル名. **/
    protected String name = null ;
    
    /** 表示カラム名. **/
    protected final ObjectList<String> columns = new ObjectList<String>() ;
    
    /** 全表示カラム. **/
    protected boolean allColumn = true ;
    
    /** 件数取得. **/
    protected boolean countFlag = false ;
    
    /** 検索条件. **/
    protected final ObjectList<MimdbSearchElement> where = new ObjectList<MimdbSearchElement>() ;
    
    /** ソートカラム. **/
    protected final ObjectList<String> sortList = new ObjectList<String>() ;
    
    /** ソート条件. **/
    protected final ObjectList<Boolean> descList = new ObjectList<Boolean>() ;
    
    /**
     * コンストラクタ.
     */
    public QueryInfo() {}
    
    /** デストラクタ. **/
    protected void finalize() throws Exception {
        clear() ;
    }
    
    /**
     * 情報クリア.
     */
    public void clear() {
        name = null ;
        columns.clear() ;
        allColumn = true ;
        countFlag = false ;
        where.clear() ;
        sortList.clear() ;
        descList.clear() ;
    }
    
    /**
     * テーブル名を設定.
     * @param table 対象のテーブル名を設定します.
     * @exception Exception 例外.
     */
    public void setTable( String table ) throws Exception {
        if( table == null || ( table = table.trim().toLowerCase() ).length() <= 0 ) {
            throw new MimdbException( "テーブル名が設定されていません" ) ;
        }
        this.name = table ;
    }
    
    /**
     * テーブル名を取得.
     * @return String テーブル名が返却されます.
     */
    public String getName() {
        return name ;
    }
    
    /**
     * 表示カラム名をセット.
     * @param name 対象カラム名を設定します.
     */
    public void setViewColumn( String name ) {
        if( name == null || ( name = name.trim().toLowerCase() ).length() <= 0 ) {
            throw new MimdbException( "指定カラム名は存在しません" ) ;
        }
        if( "*".equals( name ) ) {
            allColumn = true ;
            countFlag = false ;
        }
        else {
            columns.add( name ) ;
            allColumn = false ;
            countFlag = false ;
        }
    }
    
    /**
     * 件数取得条件をセット.
     */
    public void setViewCount() {
        countFlag = true ;
    }
    
    /**
     * 表示カラム名一覧を取得.
     * @return ObjectList<String> 表示カラム名一覧が返却されます.
     */
    public ObjectList<String> getViewColumn() {
        return columns ;
    }
    
    /**
     * 全カラムが表示対象となっているかチェック.
     * @return boolean [true]の場合、全カラムが表示対象となっています.
     */
    public boolean isAllView() {
        return allColumn ;
    }
    
    /**
     * 検索件数が表示対象となっているかチェック.
     * @return int [true]の場合、検索件数が表示対象となっています.
     */
    public boolean isCountView() {
        return countFlag ;
    }
    
    /**
     * 検索条件を設定.
     * @param search 検索条件を設定します.
     * @exception Exception 例外.
     */
    public void addWhere( MimdbSearchElement search ) throws Exception {
        if( search == null ) {
            throw new MimdbException( "検索条件は無効です" ) ;
        }
        where.add( search ) ;
    }
    
    /**
     * 検索条件を取得.
     * @return ObjectList<MimdbSearchElement> 検索条件が返却されます.
     */
    public ObjectList<MimdbSearchElement> getWhere() {
        return where ;
    }
    
    /**
     * ソート順を設定.
     * @param name ソートカラム名を設定します.
     * @param mode [true]の場合は降順(3,2,1,0)、[false]の場合は昇順(0,1,2,3)となります.
     * @exception Exception 例外.
     */
    public void addSortColumn( String name,boolean desc ) throws Exception {
        if( name == null || ( name = name.trim().toLowerCase() ).length() <= 0 ) {
            throw new MimdbException( "指定カラム名は存在しません" ) ;
        }
        sortList.add( name ) ;
        descList.add( desc ) ;
    }
    
    /**
     * ソート順の情報を取得.
     * @return ObjectList<String> ソート順の情報が返却されます.
     */
    public ObjectList<String> getSortColumn() {
        return sortList ;
    }
    
    /**
     * ソート順を決定させる.
     */
    public ObjectList<Boolean> getDesc() {
        return descList ;
    }
    
    /**
     * SQL文に変換.
     * @return String SQL文に変換されます.
     * @exception Exception 例外.
     */
    public String getSql() throws Exception {
        if( name == null ) {
            throw new MimdbException( "テーブル名が設定されていません" ) ;
        }
        StringBuilder buf = new StringBuilder( 1024 ) ;
        buf.append( "SELECT " ) ;
        if( countFlag ) {
            buf.append( "COUNT(*) " ) ;
        }
        else if( allColumn ) {
            buf.append( "* " ) ;
        }
        else {
            int len = columns.size() ;
            for( int i = 0 ; i < len ; i ++ ) {
                if( i != 0 ) {
                    buf.append( ", " ) ;
                }
                buf.append( columns.get( i ) ).append( " " ) ;
            }
        }
        buf.append( "FROM " ).append( name ).append( " " ) ;
        if( where.size() > 0 ) {
            buf.append( "WHERE " ) ;
            int len = where.size() ;
            for( int i = 0 ; i < len ; i ++ ) {
                buf.append( where.get( i ) ).append( " " ) ;
            }
        }
        if( sortList.size() > 0 ) {
            buf.append( "ORDER BY " ) ;
            int len = sortList.size() ;
            for( int i = 0 ; i < len ; i ++ ) {
                buf.append( sortList.get( i ) ).append( " " ) ;
                if( descList.get( i ) ) {
                    buf.append( "DESC " ) ;
                }
                else {
                    buf.append( "ASC " ) ;
                }
            }
        }
        
        return buf.append( ";" ).toString() ;
    }
}
