package org.simpleflatmapper.map.mapper;
import org.simpleflatmapper.map.FieldKey;
import org.simpleflatmapper.map.FieldMapper;
import org.simpleflatmapper.map.Mapper;
import org.simpleflatmapper.map.MapperConfig;
import org.simpleflatmapper.map.property.FieldMapperColumnDefinition;
import org.simpleflatmapper.map.context.MappingContextFactoryBuilder;
import org.simpleflatmapper.reflect.meta.ClassMeta;
/**
* @param <T> the targeted type of the mapper
*/
public abstract class AbstractMapperBuilder<S, T, K extends FieldKey<K>, M, B extends AbstractMapperBuilder<S, T, K, M, B>> {
private final ConstantSourceMapperBuilder<S, T, K> constantSourceMapperBuilder;
protected final MapperConfig<K, FieldMapperColumnDefinition<K>> mapperConfig;
protected final MappingContextFactoryBuilder<? super S, K> mappingContextFactoryBuilder;
private final KeyFactory<K> keyFactory;
private int calculatedIndex;
/**
* @param classMeta the meta for the target class.
* @param parentBuilder the parent builder, null if none.
* @param mapperConfig the mapperConfig.
* @param mapperSource the Mapper source.
* @param keyFactory
* @param startIndex the first property index
*/
public AbstractMapperBuilder(
final ClassMeta<T> classMeta,
MappingContextFactoryBuilder<? super S, K> parentBuilder,
MapperConfig<K, FieldMapperColumnDefinition<K>> mapperConfig,
MapperSource<? super S, K> mapperSource,
KeyFactory<K> keyFactory,
int startIndex) {
this.constantSourceMapperBuilder =
new ConstantSourceMapperBuilder<S, T, K>(
mapperSource,
classMeta,
mapperConfig,
parentBuilder,
keyFactory);
this.keyFactory = keyFactory;
this.mapperConfig = mapperConfig;
this.mappingContextFactoryBuilder = parentBuilder;
this.calculatedIndex = startIndex;
}
/**
* @return a new newInstance of the jdbcMapper based on the current state of the builder.
*/
public final M mapper() {
Mapper<S, T> mapper = constantSourceMapperBuilder.mapper();
if (constantSourceMapperBuilder.hasJoin()) {
return newJoinMapper(mapper);
} else {
return newStaticMapper(mapper);
}
}
/**
* add a new mapping to the specified property with a key property definition and an undefined type.
* The index is incremented for each non indexed property mapping.
*
* @param column the property name
* @return the current builder
*/
public final B addKey(String column) {
return addMapping(column, calculatedIndex++, FieldMapperColumnDefinition.<K>key());
}
/**
* add a new mapping to the specified property with an undefined type. The index is incremented for each non indexed property mapping.
*
* @param column the property name
* @return the current builder
*/
public final B addMapping(String column) {
return addMapping(column, calculatedIndex++);
}
/**
* add a new mapping to the specified property with the specified columnDefinition and an undefined type. The index is incremented for each non indexed property mapping.
*
* @param column the property name
* @param columnDefinition the definition
* @return the current builder
*/
public final B addMapping(final String column, final FieldMapperColumnDefinition<K> columnDefinition) {
return addMapping(column, calculatedIndex++, columnDefinition);
}
/**
* add a new mapping to the specified property with the specified columnDefinition and an undefined type. The index is incremented for each non indexed property mapping.
*
* @param column the property name
* @param properties the definition
* @return the current builder
*/
public final B addMapping(final String column, final Object... properties) {
return addMapping(column, calculatedIndex++, properties);
}
/**
* add a new mapping to the specified property with the specified index and an undefined type.
*
* @param column the property name
* @param index the property index
* @return the current builder
*/
public final B addMapping(String column, int index) {
return addMapping(key(column, index));
}
/**
* add a new mapping to the specified property with the specified index, specified property definition and an undefined type.
*
* @param column the property name
* @param index the property index
* @param columnDefinition the property definition
* @return the current builder
*/
public final B addMapping(String column, int index, final FieldMapperColumnDefinition<K> columnDefinition) {
return addMapping(key(column, index), columnDefinition);
}
/**
* add a new mapping to the specified property with the specified index, specified property definition and an undefined type.
*
* @param column the property name
* @param index the property index
* @param properties the property properties
* @return the current builder
*/
public final B addMapping(String column, int index, final Object... properties) {
return addMapping(key(column, index), properties);
}
/**
* append a FieldMapper to the mapping list.
*
* @param mapper the field jdbcMapper
* @return the current builder
*/
@SuppressWarnings("unchecked")
public final B addMapper(FieldMapper<S, T> mapper) {
constantSourceMapperBuilder.addMapper(mapper);
return (B) this;
}
@SuppressWarnings("unchecked")
public final B addMapping(K key, FieldMapperColumnDefinition<K> columnDefinition) {
constantSourceMapperBuilder.addMapping(key, columnDefinition);
return (B) this;
}
@SuppressWarnings("unchecked")
public final B addMapping(K key, Object... properties) {
if (properties.length == 1) { // catch Object... on column definition
if (properties[0] instanceof ColumnDefinition) {
constantSourceMapperBuilder.addMapping(key, (FieldMapperColumnDefinition<K>) properties[0]);
return (B) this;
}
}
constantSourceMapperBuilder.addMapping(key, FieldMapperColumnDefinition.<K>of(properties));
return (B) this;
}
private final K key(String column, int index) {
return keyFactory.newKey(column, index);
}
protected abstract M newJoinMapper(Mapper<S, T> mapper);
protected abstract M newStaticMapper(Mapper<S, T> mapper);
}