All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.napp.database.impl.EntityMapper Maven / Gradle / Ivy

There is a newer version: 1.1.8
Show newest version
/**
 *
 */
package com.github.napp.database.impl;

import static com.github.napp.util.UClose.CLOSE_RESULT_SET;
import static com.github.napp.util.UClose.CLOSE_STATEMENT;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.github.napp.database.IEntity;
import com.github.napp.util.NullTool;

/**
 * @author Alexandru Bledea
 * @since Sep 25, 2013
 */
class EntityMapper {

	private static final String QUERY = "SELECT * FROM %s WHERE 0 = 1;";

	private final Class entityClass;
	private final List setters;

	private final Collection validFields;

	/**
	 * @param entityClass
	 * @throws SQLException
	 */
	EntityMapper(DAO dao, Class entityClass) throws SQLException {
		this.entityClass = entityClass;

		Map setters2 = getClassSetters(entityClass);
		validFields = setters2.keySet();
		ResultSetMetaData tableMetaData = getTableMetaData(dao.openConnection(), dao.getTableName());
		setters = getSetters(setters2, tableMetaData);
	}

	/**
	 * @param rs
	 * @param columnCount
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 * @throws SQLException
	 * @throws InvocationTargetException
	 * @throws IllegalArgumentException
	 */
	public I mapEntity(ResultSet rs, int columnCount) throws InstantiationException, IllegalAccessException, IllegalArgumentException,
			InvocationTargetException, SQLException {
		I entity = entityClass.newInstance();
		for (int i = 1; i <= columnCount; i++) {
			Method method = setters.get(i);
			if (method != null) {
				method.invoke(entity, rs.getObject(i));
			}
		}
		return entity;
	}

	/**
	 * @param property
	 * @return
	 */
	public void validate(String property) {
		NullTool.forbidNull(property);
		property = property.toUpperCase();
		boolean validField = validFields.contains(property);
		if (!validField) {
			throw new IllegalStateException("No such field!");
		}
	}

	/**
	 * @param clazz
	 * @return
	 */
	private Map getClassSetters(Class clazz) {
		try {
			Map map = new HashMap();
			BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
			PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
			for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
				String property = propertyDescriptor.getName().toUpperCase();
				if (map.containsKey(property)) {
					throw new IllegalStateException(String.format("%s mapped twice. DAOs are case insensitive.", property));
				}
				map.put(property, propertyDescriptor.getWriteMethod());
			}
			return map;
		} catch (IntrospectionException e) {
			throw new IllegalStateException(e);
		}
	}

	/**
	 * @param con
	 * @param tableName
	 * @return
	 * @throws SQLException
	 */
	private ResultSetMetaData getTableMetaData(Connection con, String tableName) throws SQLException {
		Statement stmt = null;
		ResultSet rs = null;
		try {
			stmt = con.createStatement();
			rs = stmt.executeQuery(String.format(QUERY, tableName));
			return rs.getMetaData();
		} finally {
			CLOSE_RESULT_SET.evaluate(rs);
			CLOSE_STATEMENT.evaluate(stmt);
		}
	}

	/**
	 * @param setters
	 * @param tableMetaData
	 * @return
	 * @throws SQLException
	 */
	private List getSetters(Map setters, ResultSetMetaData tableMetaData) throws SQLException {
		List methods = new ArrayList();
		methods.add(null);

		int columnCount = tableMetaData.getColumnCount();
		for (int i = 1; i <= columnCount; i++) {
			String columnName = tableMetaData.getColumnName(i);
			Method method = null;
			if (setters.containsKey(columnName)) {
				method = setters.get(columnName);
			}
			methods.add(method);
		}

		return methods;
	}
}