package org.seasar.dao.impl;

import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.Map;
import java.util.Set;

import org.seasar.dao.BeanMetaData;
import org.seasar.dao.RelationPropertyType;
import org.seasar.extension.jdbc.PropertyType;
import org.seasar.extension.jdbc.ResultSetHandler;
import org.seasar.extension.jdbc.ValueType;
import org.seasar.framework.beans.PropertyDesc;
import org.seasar.framework.util.CaseInsensitiveSet;
import org.seasar.framework.util.ClassUtil;

public abstract class AbstractBeanMetaDataResultSetHandler implements
		ResultSetHandler {

	private BeanMetaData beanMetaData_;

	public AbstractBeanMetaDataResultSetHandler(BeanMetaData beanMetaData) {
		beanMetaData_ = beanMetaData;

	}

	public BeanMetaData getBeanMetaData() {
		return beanMetaData_;
	}

	protected Object createRow(ResultSet rs, Set columnNames)
			throws SQLException {
		Object row = ClassUtil.newInstance(beanMetaData_.getBeanClass());
		for (int i = 0; i < beanMetaData_.getPropertyTypeSize(); ++i) {
			PropertyType pt = beanMetaData_.getPropertyType(i);
			if (!columnNames.contains(pt.getColumnName())) {
				continue;
			}
			ValueType valueType = pt.getValueType();
			Object value = valueType.getValue(rs, pt.getColumnName());
			PropertyDesc pd = pt.getPropertyDesc();
			pd.setValue(row, value);
		}
		return row;
	}

	protected Object createRelationRow(ResultSet rs, RelationPropertyType rpt,
			Set columnNames, Map relKeyValues) throws SQLException {

		Object row = null;
		BeanMetaData bmd = rpt.getBeanMetaData();
		for (int i = 0; i < bmd.getPropertyTypeSize(); ++i) {
			PropertyType pt = bmd.getPropertyType(i);
			String columnName = pt.getColumnName() + "_" + rpt.getRelationNo();
			if (!columnNames.contains(columnName)) {
				continue;
			}
			if (row == null) {
				row = createRelationRow(rpt);
			}
			Object value = null;
			if (relKeyValues != null && relKeyValues.containsKey(columnName)) {
				value = relKeyValues.get(columnName);
			} else {
				ValueType valueType = pt.getValueType();
				value = valueType.getValue(rs, columnName);
			}
			PropertyDesc pd = pt.getPropertyDesc();
			if (value != null) {
				pd.setValue(row, value);
			}

		}
		return row;
	}

	protected Object createRelationRow(RelationPropertyType rpt) {
		return ClassUtil.newInstance(rpt.getPropertyDesc().getPropertyType());
	}

	protected Set createColumnNames(ResultSetMetaData rsmd) throws SQLException {
		int count = rsmd.getColumnCount();
		Set columnNames = new CaseInsensitiveSet();
		for (int i = 0; i < count; ++i) {
			String columnName = rsmd.getColumnLabel(i + 1);
			columnNames.add(columnName);
		}
		return columnNames;
	}
}