package org.seasar.dao.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;

import javax.sql.DataSource;

import org.seasar.dao.BeanMetaData;
import org.seasar.extension.jdbc.UpdateHandler;
import org.seasar.extension.jdbc.impl.BasicHandler;
import org.seasar.framework.exception.SQLRuntimeException;
import org.seasar.framework.log.Logger;
import org.seasar.framework.util.ConnectionUtil;
import org.seasar.framework.util.PreparedStatementUtil;
import org.seasar.framework.util.StatementUtil;

/**
 * @author higa
 *  
 */
public abstract class AbstractAutoHandler extends BasicHandler implements
		UpdateHandler {

	private static Logger logger_ = Logger.getLogger(AbstractAutoHandler.class);

	private BeanMetaData beanMetaData_;

	public AbstractAutoHandler(DataSource dataSource, BeanMetaData beanMetaData) {
		setDataSource(dataSource);
		beanMetaData_ = beanMetaData;
	}

	public BeanMetaData getBeanMetaData() {
		return beanMetaData_;
	}
	
	protected static Logger getLogger() {
		return logger_;
	}

	public int execute(Object[] args) throws SQLRuntimeException {
		Connection connection = getConnection();
		try {
			setupSql();
			return execute(connection, args[0]);
		} finally {
			ConnectionUtil.close(connection);
		}
	}

	protected int execute(Connection connection, Object bean) {
		preUpdateBean(bean);
		Object[] bindVariables = getBindVariables(bean);
		if (logger_.isDebugEnabled()) {
			logger_.debug(getCompleteSql(bindVariables));
		}
		PreparedStatement ps = prepareStatement(connection);
		int ret = -1;
		try {
			bindArgs(ps, bindVariables);
			ret = PreparedStatementUtil.executeUpdate(ps);
		} finally {
			StatementUtil.close(ps);
		}
		postUpdateBean(bean, bindVariables);
		return ret;
	}

	protected void preUpdateBean(Object bean) {	
	}
	
	protected void postUpdateBean(Object bean, Object[] bindVariables) {	
	}
	
	protected abstract void setupSql();

	protected abstract Object[] getBindVariables(Object bean);
}