org.simpleflatmapper.jdbc.PreparedStatementMapperBuilder Maven / Gradle / Ivy
package org.simpleflatmapper.jdbc;
import org.simpleflatmapper.converter.ContextFactoryBuilder;
import org.simpleflatmapper.jdbc.impl.CollectionIndexFieldMapper;
import org.simpleflatmapper.jdbc.impl.MultiIndexQueryPreparer;
import org.simpleflatmapper.jdbc.impl.PreparedStatementIndexedSetterFactory;
import org.simpleflatmapper.jdbc.impl.SingleIndexFieldMapper;
import org.simpleflatmapper.jdbc.impl.MapperQueryPreparer;
import org.simpleflatmapper.jdbc.impl.setter.PreparedStatementIndexSetter;
import org.simpleflatmapper.jdbc.impl.setter.PreparedStatementIndexSetterOnGetter;
import org.simpleflatmapper.jdbc.named.NamedSqlQuery;
import org.simpleflatmapper.map.MappingContext;
import org.simpleflatmapper.map.context.MappingContextFactoryBuilder;
import org.simpleflatmapper.map.mapper.AbstractConstantTargetMapperBuilder;
import org.simpleflatmapper.map.MapperConfig;
import org.simpleflatmapper.map.mapper.ColumnDefinition;
import org.simpleflatmapper.map.property.FieldMapperColumnDefinition;
import org.simpleflatmapper.jdbc.property.IndexedSetterFactoryProperty;
import org.simpleflatmapper.jdbc.property.IndexedSetterProperty;
import org.simpleflatmapper.map.mapper.ConstantTargetFieldMapperFactory;
import org.simpleflatmapper.map.mapper.PropertyMapping;
import org.simpleflatmapper.map.setter.ContextualIndexedSetter;
import org.simpleflatmapper.map.setter.ContextualIndexedSetterAdapter;
import org.simpleflatmapper.map.setter.ContextualIndexedSetterFactory;
import org.simpleflatmapper.reflect.BiInstantiator;
import org.simpleflatmapper.reflect.Getter;
import org.simpleflatmapper.reflect.IndexedGetter;
import org.simpleflatmapper.reflect.IndexedSetter;
import org.simpleflatmapper.reflect.IndexedSetterFactory;
import org.simpleflatmapper.reflect.getter.ArrayIndexedGetter;
import org.simpleflatmapper.reflect.getter.ArraySizeGetter;
import org.simpleflatmapper.reflect.getter.ListIndexedGetter;
import org.simpleflatmapper.reflect.getter.ListSizeGetter;
import org.simpleflatmapper.reflect.meta.*;
import org.simpleflatmapper.reflect.primitive.IntGetter;
import org.simpleflatmapper.util.ConstantPredicate;
import org.simpleflatmapper.util.ErrorDoc;
import org.simpleflatmapper.util.ForEachCallBack;
import org.simpleflatmapper.util.TypeHelper;
import java.sql.PreparedStatement;
import java.util.ArrayList;
import java.util.List;
public class PreparedStatementMapperBuilder extends AbstractConstantTargetMapperBuilder> {
private ContextualIndexedSetterFactory> indexedSetterFactory = PreparedStatementIndexedSetterFactory.INSTANCE;
public PreparedStatementMapperBuilder(
ClassMeta classMeta,
MapperConfig mapperConfig,
ConstantTargetFieldMapperFactory preparedStatementFieldMapperFactory) {
super(classMeta, PreparedStatement.class, mapperConfig, preparedStatementFieldMapperFactory);
}
private PreparedStatementMapperBuilder(PreparedStatementMapperBuilder builder) {
this(builder.classMeta, builder.mapperConfig, builder.fieldAppenderFactory);
}
@Override
protected BiInstantiator, PreparedStatement> getInstantiator() {
return new NullInstantiator();
}
@Override
protected JdbcColumnKey newKey(String column, int i, FieldMapperColumnDefinition columnDefinition) {
JdbcColumnKey key = new JdbcColumnKey(column, i);
SqlTypeColumnProperty typeColumnProperty = columnDefinition.lookFor(SqlTypeColumnProperty.class);
if (typeColumnProperty == null) {
ColumnDefinition globalDef = mapperConfig.columnDefinitions().getColumnDefinition(key);
typeColumnProperty = globalDef.lookFor(SqlTypeColumnProperty.class);
}
if (typeColumnProperty != null) {
return new JdbcColumnKey(key.getName(), key.getIndex(), typeColumnProperty.getSqlType(), key);
}
return key;
}
private static class NullInstantiator implements BiInstantiator, PreparedStatement> {
@Override
public PreparedStatement newInstance(T o, MappingContext super T> context) throws Exception {
throw new UnsupportedOperationException();
}
}
protected int getStartingIndex() {
return 1;
}
public QueryPreparer to(NamedSqlQuery query) {
return to(query, null);
}
public QueryPreparer to(NamedSqlQuery query, String[] generatedKeys) {
PreparedStatementMapperBuilder builder =
new PreparedStatementMapperBuilder(this);
return builder.preparedStatementMapper(query, generatedKeys);
}
private QueryPreparer preparedStatementMapper(NamedSqlQuery query, String[] generatedKeys) {
for(int i = 0; i < query.getParametersSize(); i++) {
addColumn(query.getParameter(i).getName());
}
boolean hasMultiIndex =
propertyMappingsBuilder.forEachProperties(new ForEachCallBack>() {
boolean hasMultiIndex;
@Override
public void handle(PropertyMapping pm) {
hasMultiIndex |= isMultiIndex(pm.getPropertyMeta());
}
}).hasMultiIndex;
if (hasMultiIndex) {
MappingContextFactoryBuilder mappingContextFactoryBuilder = new MappingContextFactoryBuilder(keySourceGetter(), !mapperConfig.unorderedJoin());
return new MultiIndexQueryPreparer(query, buildIndexFieldMappers(mappingContextFactoryBuilder), generatedKeys, mappingContextFactoryBuilder.build());
} else {
return new MapperQueryPreparer(query, mapper(), generatedKeys);
}
}
private boolean isMultiIndex(PropertyMeta, ?> propertyMeta) {
return
TypeHelper.isArray(propertyMeta.getPropertyType())
|| TypeHelper.isAssignable(List.class, propertyMeta.getPropertyType());
}
@SuppressWarnings("unchecked")
public MultiIndexFieldMapper[] buildIndexFieldMappers(final ContextFactoryBuilder contextFactoryBuilder) {
final List> fields = new ArrayList>();
propertyMappingsBuilder.forEachProperties(new ForEachCallBack>() {
@Override
public void handle(PropertyMapping pm) {
if (isMultiIndex(pm.getPropertyMeta())) {
fields.add(newCollectionFieldMapper(pm));
} else {
fields.add(newFieldMapper(pm));
}
}
private MultiIndexFieldMapper newCollectionFieldMapper(PropertyMapping pm) {
PropertyMeta propertyMeta = pm.getPropertyMeta();
IndexedGetter indexedGetter;
IntGetter super C> sizeGetter;
Getter collectionGetter = (Getter) propertyMeta.getGetter();
if (TypeHelper.isAssignable(List.class, propertyMeta.getPropertyType())) {
indexedGetter = (IndexedGetter) new ListIndexedGetter();
sizeGetter = (IntGetter) new ListSizeGetter();
} else if (TypeHelper.isArray(propertyMeta.getPropertyType())) {
indexedGetter = (IndexedGetter) new ArrayIndexedGetter();
sizeGetter = new ArraySizeGetter();
} else {
throw new IllegalArgumentException("Unexpected elementMeta" + propertyMeta);
}
PropertyMeta childProperty =
(PropertyMeta)
pm.getPropertyMeta().getPropertyClassMeta().newPropertyFinder().findProperty(DefaultPropertyNameMatcher.of("0"), pm.getColumnDefinition().properties(), pm.getColumnKey(), PropertyFinder.PropertyFilter.trueFilter());
final PropertyMapping pmchildProperttMeta = pm.propertyMeta(childProperty);
ContextualIndexedSetter setter = getSetter(pmchildProperttMeta);
return new CollectionIndexFieldMapper(setter, collectionGetter, sizeGetter, indexedGetter);
}
private ContextualIndexedSetter getSetter(PropertyMapping pm) {
ContextualIndexedSetter setter = null;
IndexedSetterProperty indexedSetterProperty = pm.getColumnDefinition().lookFor(IndexedSetterProperty.class);
if (indexedSetterProperty != null) {
setter = ContextualIndexedSetterAdapter.of((IndexedSetter) indexedSetterProperty.getIndexedSetter());
}
if (setter == null) {
setter = indexedSetterFactory(pm);
}
if (setter == null) {
mapperConfig.mapperBuilderErrorHandler().accessorNotFound(
"Could not find setter for " + pm.getColumnKey()
+ " type " + pm.getPropertyMeta().getPropertyType()
+ " path " + pm.getPropertyMeta().getPath()
+ " See " + ErrorDoc.CTFM_SETTER_NOT_FOUND.toUrl());
}
return setter;
}
private ContextualIndexedSetter indexedSetterFactory(PropertyMapping pm) {
ContextualIndexedSetter setter = null;
final IndexedSetterFactoryProperty indexedSetterPropertyFactory = pm.getColumnDefinition().lookFor(IndexedSetterFactoryProperty.class);
if (indexedSetterPropertyFactory != null) {
IndexedSetterFactory> setterFactory = (IndexedSetterFactory>) indexedSetterPropertyFactory.getIndexedSetterFactory();
setter = ContextualIndexedSetterAdapter.of(setterFactory.getIndexedSetter(pm));
}
if (setter == null) {
setter = indexedSetterFactory.getIndexedSetter(pm, contextFactoryBuilder);
}
if (setter == null) {
final ClassMeta
classMeta = pm.getPropertyMeta().getPropertyClassMeta();
if (classMeta instanceof ObjectClassMeta) {
ObjectClassMeta
ocm = (ObjectClassMeta
) classMeta;
if (ocm.getNumberOfProperties() == 1) {
PropertyMeta
subProp = ocm.getFirstProperty();
final PropertyMapping, ?, JdbcColumnKey> subPropertyMapping = pm.propertyMeta(subProp);
ContextualIndexedSetter subSetter = indexedSetterFactory(subPropertyMapping);
if (subSetter != null) {
setter = new PreparedStatementIndexSetterOnGetter