package org.simpleflatmapper.jdbc;
import org.simpleflatmapper.map.Mapper;
import org.simpleflatmapper.map.MapperConfig;
import org.simpleflatmapper.map.MappingContext;
import org.simpleflatmapper.map.ConsumerErrorHandler;
import org.simpleflatmapper.map.property.FieldMapperColumnDefinition;
import org.simpleflatmapper.map.context.MappingContextFactory;
import org.simpleflatmapper.map.context.MappingContextFactoryBuilder;
import org.simpleflatmapper.map.mapper.AbstractMapperBuilder;
import org.simpleflatmapper.map.mapper.JoinMapper;
import org.simpleflatmapper.map.mapper.KeyFactory;
import org.simpleflatmapper.map.mapper.MapperSourceImpl;
import org.simpleflatmapper.map.mapper.StaticSetRowMapper;
import org.simpleflatmapper.reflect.ReflectionService;
import org.simpleflatmapper.reflect.getter.GetterFactory;
import org.simpleflatmapper.util.TypeReference;
import org.simpleflatmapper.reflect.meta.ClassMeta;
import org.simpleflatmapper.util.Enumarable;
import org.simpleflatmapper.util.UnaryFactory;
import org.simpleflatmapper.jdbc.impl.ResultSetEnumarable;
import java.lang.reflect.Type;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
/**
* @param <T> the targeted type of the jdbcMapper
*/
public final class JdbcMapperBuilder<T> extends AbstractMapperBuilder<ResultSet, T, JdbcColumnKey, JdbcMapper<T>, JdbcMapperBuilder<T>> {
private static final MapperSourceImpl<ResultSet, JdbcColumnKey> FIELD_MAPPER_SOURCE =
new MapperSourceImpl<ResultSet, JdbcColumnKey>(ResultSet.class, ResultSetGetterFactory.INSTANCE);
private static final KeyFactory<JdbcColumnKey> KEY_FACTORY = new KeyFactory<JdbcColumnKey>() {
@Override
public JdbcColumnKey newKey(String name, int i) {
return new JdbcColumnKey(name, i);
}
};
/**
* Build a new JdbcMapperBuilder targeting the type specified by the TypeReference. The TypeReference
* allow you to provide a generic type with check of T<br>
* <code>new TypeReference<List<String>>() {}</code>
*
* @param target the TypeReference to the type T to map to
*/
public JdbcMapperBuilder(final TypeReference<T> target) {
this(target.getType());
}
/**
* Build a new JdbcMapperBuilder targeting the specified type.
*
* @param target the type
*/
public JdbcMapperBuilder(final Type target) {
this(target, ReflectionService.newInstance());
}
/**
* Build a new JdbcMapperBuilder targeting the specified type with the specified ReflectionService.
*
* @param target the type
* @param reflectService the ReflectionService
*/
public JdbcMapperBuilder(final Type target, ReflectionService reflectService) {
this(reflectService.<T>getClassMeta(target),
MapperConfig.<JdbcColumnKey>fieldMapperConfig(),
ResultSetGetterFactory.INSTANCE,
new JdbcMappingContextFactoryBuilder());
}
/**
* @param classMeta the meta for the target class.
* @param mapperConfig the mapperConfig.
* @param getterFactory the Getter factory.
* @param parentBuilder the parent builder, null if none.
*/
public JdbcMapperBuilder(
final ClassMeta<T> classMeta,
MapperConfig<JdbcColumnKey, FieldMapperColumnDefinition<JdbcColumnKey>> mapperConfig,
GetterFactory<ResultSet, JdbcColumnKey> getterFactory,
MappingContextFactoryBuilder<ResultSet, JdbcColumnKey> parentBuilder) {
super(classMeta,
parentBuilder,
mapperConfig,
FIELD_MAPPER_SOURCE.getterFactory(getterFactory),
KEY_FACTORY, 1);
}
/**
* add a new mapping to the specified property with the specified index and the specified type.
*
* @param column the property name
* @param index the property index
* @param sqlType the property type, @see java.sql.Types
* @return the current builder
*/
public JdbcMapperBuilder<T> addMapping(final String column, final int index, final int sqlType) {
addMapping(column, index, sqlType, FieldMapperColumnDefinition.<JdbcColumnKey>identity());
return this;
}
/**
* add a new mapping to the specified property with the specified index, the specified type.
*
* @param column the property name
* @param index the property index
* @param sqlType the property type, @see java.sql.Types
* @param columnDefinition the property definition
* @return the current builder
*/
public JdbcMapperBuilder<T> addMapping(final String column, final int index, final int sqlType, FieldMapperColumnDefinition<JdbcColumnKey> columnDefinition) {
return addMapping(new JdbcColumnKey(column, index, sqlType), columnDefinition);
}
/**
* add a new mapping to the specified property with the specified index, the specified type.
*
* @param column the property name
* @param index the property index
* @param sqlType the property type, @see java.sql.Types
* @param properties the property properties
* @return the current builder
*/
public JdbcMapperBuilder<T> addMapping(final String column, final int index, final int sqlType, Object... properties) {
return addMapping(new JdbcColumnKey(column, index, sqlType), properties);
}
/**
* add the all the property present in the metaData
*
* @param metaData the metaDAta
* @return the current builder
* @throws SQLException when an error occurs getting the metaData
*/
public JdbcMapperBuilder<T> addMapping(final ResultSetMetaData metaData) throws SQLException {
for (int i = 1; i <= metaData.getColumnCount(); i++) {
addMapping(metaData.getColumnLabel(i), i, metaData.getColumnType(i));
}
return this;
}
@Override
protected JdbcMapper<T> newJoinMapper(Mapper<ResultSet, T> mapper) {
return new JoinJdbcMapper<T>(mapper, mapperConfig.consumerErrorHandler(), mappingContextFactoryBuilder.newFactory());
}
private static class JoinJdbcMapper<T> extends JoinMapper<ResultSet, ResultSet, T, SQLException>
implements JdbcMapper<T> {
public JoinJdbcMapper(Mapper<ResultSet, T> mapper, ConsumerErrorHandler errorHandler, MappingContextFactory<? super ResultSet> mappingContextFactory) {
super(mapper, errorHandler, mappingContextFactory, new ResultSetEnumarableFactory());
}
@Override
public MappingContext<? super ResultSet> newMappingContext(ResultSet rs) {
return getMappingContextFactory().newContext();
}
}
private static class ResultSetEnumarableFactory implements UnaryFactory<ResultSet, Enumarable<ResultSet>> {
@Override
public Enumarable<ResultSet> newInstance(ResultSet rows) {
return new ResultSetEnumarable(rows);
}
}
@Override
protected JdbcMapper<T> newStaticMapper(Mapper<ResultSet, T> mapper) {
return new StaticJdbcSetRowMapper<T>(mapper, mapperConfig.consumerErrorHandler(), mappingContextFactoryBuilder.newFactory());
}
private static class StaticJdbcSetRowMapper<T> extends StaticSetRowMapper<ResultSet, ResultSet, T, SQLException> implements JdbcMapper<T> {
public StaticJdbcSetRowMapper(Mapper<ResultSet, T> mapper, ConsumerErrorHandler errorHandler, MappingContextFactory<? super ResultSet> mappingContextFactory) {
super(mapper, errorHandler, mappingContextFactory, new ResultSetEnumarableFactory());
}
@Override
public MappingContext<? super ResultSet> newMappingContext(ResultSet resultSet) throws SQLException {
return getMappingContextFactory().newContext();
}
}
}