package org.jfox.dao.mapping;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.jfox.dao.DAOException;

/**
 * @author <a href="mailto:yangyong@ufsoft.com.cn">Young Yang</a>
 */

public abstract class ColumnMapping {
    protected String columnName = null;

    protected boolean isPrimaryKey = false;

    /**
     * select count(*) as total from table, total is a alias column
     */
    protected boolean isAlias = false;

    protected Method getterMethod = null;
    protected Method setterMethod = null;

    protected Class columnType = null;

    /**
     * disable getter
     * so will not get value from mapping object
     */
    protected boolean disableGet = false;
    /**
     * disable setter
     * so will not set value to mapping object
     */
    protected boolean disableSet = false;


    /**
     * field like auto-increament may can not set it's value by force
     * it auto evaluated by Database
     */
    protected boolean isAutoEvaluated = false;


    protected ColumnMapping(String columnName, Class type) {
        this.columnName = columnName;
        this.columnType = type;
    }

    public String getColumnName() {
        return columnName;
    }
/*
    public void setColumnName(String columnName) {
        this.columnName = columnName;
    }
*/
    public boolean isPrimaryKey() {
        return isPrimaryKey;
    }

    public void setPrimaryKey(boolean primaryKey) {
        isPrimaryKey = primaryKey;
    }

    public boolean isAlias() {
        return isAlias;
    }

    public void setAlias(boolean alias) {
        isAlias = alias;
    }

    public Method getGetterMethod() {
        return getterMethod;
    }

    public void setGetterMethod(Method getterMethod) {
        this.getterMethod = getterMethod;
    }

    public Method getSetterMethod() {
        return setterMethod;
    }

    public void setSetterMethod(Method setterMethod) {
        this.setterMethod = setterMethod;
    }

    public Class getColumnType() {
        return columnType;
    }

    public void setColumnType(Class columnType) {
        this.columnType = columnType;
    }

    public boolean isAutoEvaluated() {
        return isAutoEvaluated;
    }

    public void setAutoEvaluated(boolean autoEvaluated) {
        isAutoEvaluated = autoEvaluated;
    }

    public boolean isDisableGet() {
        return disableGet;
    }

    public void setDisableGet(boolean disableGet) {
        this.disableGet = disableGet;
    }

    public boolean isDisableSet() {
        return disableSet;
    }

    public void setDisableSet(boolean disableSet) {
        this.disableSet = disableSet;
    }

    public void fillStatementUseValue(){

    }

    public void fillStatement(PreparedStatement pst, Object pObject, int index) throws SQLException, DAOException {
        if(isAutoEvaluated()) {
            throw new DAOException(getColumnName() + " 's value is auto evaluated.");
        }

        if(getterMethod == null) {
            throw new DAOException(getColumnName() + " 's getter method is null.");
        }

        if(isDisableGet()) {
            System.out.println(getColumnName() + " 's getter method is disabled.");
            return;
        }
        try {
            Object value = getGetterMethod().invoke(pObject,null);
            doFillStatement(pst, value, index);
        }
        catch(SQLException e) {
            throw e;
        }
        catch(Exception e) {
            throw new DAOException("fill statement exception", e);
        }

    }

    public void fillObject(Object pObject, ResultSet rset) throws SQLException, DAOException {
        if(isDisableSet()) {
            System.out.println(getColumnName() + " 's setter method is disabled.");
        }
        if(setterMethod == null) {
            throw new DAOException(getColumnName() + " 's setter method is null.");
        }

        try {
            doFillObject(pObject, rset);
        }
        catch(SQLException e) {
            throw e;
        }
        catch(Exception e) {
            throw new DAOException("fill object exception", e);
        }

    }


    /**
     * set the value to PrepareStatement
     *
     * @param pst
     * @param value
     * @param index
     * @throws SQLException
     */
    public abstract void doFillStatement(PreparedStatement pst, Object value, int index) throws SQLException, IllegalAccessException, InvocationTargetException;

    /**
     * set the value to object
     *
     * @param pObject
     * @param rset
     * @throws SQLException DAOException
     */
    public abstract void doFillObject(Object pObject, ResultSet rset) throws SQLException, IllegalAccessException, InvocationTargetException;

}

