package org.simpleflatmapper.jdbc.spring; import org.simpleflatmapper.jdbc.JdbcColumnKey; import org.simpleflatmapper.jdbc.named.NamedParameter; import org.simpleflatmapper.jdbc.named.NamedSqlQuery; import org.simpleflatmapper.map.MapperConfig; import org.simpleflatmapper.map.PropertyWithGetter; import org.simpleflatmapper.map.property.ConstantValueProperty; import org.simpleflatmapper.map.property.FieldMapperColumnDefinition; import org.simpleflatmapper.map.mapper.PropertyMapping; import org.simpleflatmapper.map.mapper.PropertyMappingsBuilder; import org.simpleflatmapper.reflect.ReflectionService; import org.simpleflatmapper.reflect.ScoredGetter; import org.simpleflatmapper.reflect.getter.ConstantGetter; import org.simpleflatmapper.reflect.meta.ClassMeta; import org.simpleflatmapper.reflect.meta.ObjectPropertyMeta; import org.simpleflatmapper.reflect.meta.PropertyMeta; import org.simpleflatmapper.util.ForEachCallBack; import org.simpleflatmapper.util.TypeHelper; import org.springframework.jdbc.core.StatementCreatorUtils; public final class SqlParameterSourceBuilder<T> { private final PropertyMappingsBuilder<T, JdbcColumnKey, FieldMapperColumnDefinition<JdbcColumnKey>> builder; private final MapperConfig<JdbcColumnKey, FieldMapperColumnDefinition<JdbcColumnKey>> mapperConfig; private final ReflectionService reflectionService; private int index = 1; public SqlParameterSourceBuilder( ClassMeta<T> classMeta, MapperConfig<JdbcColumnKey, FieldMapperColumnDefinition<JdbcColumnKey>> mapperConfig) { this.mapperConfig = mapperConfig; this.reflectionService = classMeta.getReflectionService(); this.builder = PropertyMappingsBuilder.of(classMeta, mapperConfig, PropertyWithGetter.INSTANCE); } public SqlParameterSourceBuilder<T> add(String column) { return add(new JdbcColumnKey(column, index++), FieldMapperColumnDefinition.<JdbcColumnKey>identity()); } public SqlParameterSourceBuilder<T> add(JdbcColumnKey key, FieldMapperColumnDefinition<JdbcColumnKey> columnDefinition) { final FieldMapperColumnDefinition<JdbcColumnKey> composedDefinition = columnDefinition.compose(mapperConfig.columnDefinitions().getColumnDefinition(key)); final JdbcColumnKey mappedColumnKey = composedDefinition.rename(key); if (composedDefinition.has(ConstantValueProperty.class)) { ConstantValueProperty staticValueProperty = composedDefinition.lookFor(ConstantValueProperty.class); PropertyMeta<T, Object> meta = new ObjectPropertyMeta<T, Object>(key.getName(), builder.getClassMeta().getType(), reflectionService, staticValueProperty.getType(), ScoredGetter.of(new ConstantGetter<T, Object>(staticValueProperty.getValue()), 1), null, null); builder.addProperty(key, columnDefinition, meta); } else { builder.addProperty(mappedColumnKey, composedDefinition); } return this; } @SuppressWarnings("unchecked") public SqlParameterSourceFactory<T> buildFactory(String sql) { NamedSqlQuery namedSqlQuery = NamedSqlQuery.parse(sql); for(int i = 0; i < namedSqlQuery.getParametersSize(); i++) { NamedParameter parameter = namedSqlQuery.getParameter(i); add(parameter.getName()); } return buildFactory(); } @SuppressWarnings("unchecked") public PlaceHolderValueGetterSource<T> buildSource() { final PlaceHolderValueGetter<T>[] parameters = new PlaceHolderValueGetter[builder.size()]; builder.forEachProperties( new ForEachCallBack<PropertyMapping<T,?,JdbcColumnKey,FieldMapperColumnDefinition<JdbcColumnKey>>>(){ int i = 0; @Override public void handle(PropertyMapping<T, ?, JdbcColumnKey, FieldMapperColumnDefinition<JdbcColumnKey>> pm) { PlaceHolderValueGetter parameter = new PlaceHolderValueGetter(pm.getColumnKey().getOrginalName(), StatementCreatorUtils.javaTypeToSqlParameterType(TypeHelper.toClass(pm.getPropertyMeta().getPropertyType())), null, pm.getPropertyMeta().getGetter()); parameters[i] = parameter; i++; } }); return parameters.length > 10 ? new ArrayPlaceHolderValueGetterSource<T>(parameters) : new MapPlaceHolderValueGetterSource<T>(parameters) ; } public SqlParameterSourceFactory<T> buildFactory() { return new SqlParameterSourceFactory<T>(buildSource()); } }