package org.simpleflatmapper.csv;
import org.simpleflatmapper.map.MapperBuildingException;
import org.simpleflatmapper.map.MapperConfig;
import org.simpleflatmapper.map.mapper.ColumnDefinitionProvider;
import org.simpleflatmapper.reflect.Getter;
import org.simpleflatmapper.reflect.Instantiator;
import org.simpleflatmapper.reflect.InstantiatorFactory;
import org.simpleflatmapper.reflect.Parameter;
import org.simpleflatmapper.reflect.ReflectionService;
import org.simpleflatmapper.reflect.Setter;
import org.simpleflatmapper.reflect.asm.AsmFactory;
import org.simpleflatmapper.reflect.getter.GetterFactory;
import org.simpleflatmapper.map.mapper.PropertyMapping;
import org.simpleflatmapper.map.mapper.PropertyMappingsBuilder;
import org.simpleflatmapper.map.mapper.PropertyWithSetterOrConstructor;
import org.simpleflatmapper.reflect.meta.ClassMeta;
import org.simpleflatmapper.reflect.meta.ConstructorPropertyMeta;
import org.simpleflatmapper.reflect.meta.PropertyMeta;
import org.simpleflatmapper.reflect.meta.SelfPropertyMeta;
import org.simpleflatmapper.reflect.meta.SubPropertyMeta;
import org.simpleflatmapper.util.Consumer;
import org.simpleflatmapper.util.TypeReference;
import org.simpleflatmapper.util.UnaryFactory;
import org.simpleflatmapper.csv.property.CustomReaderProperty;
import org.simpleflatmapper.csv.impl.*;
import org.simpleflatmapper.csv.impl.asm.CsvAsmFactory;
import org.simpleflatmapper.csv.mapper.CellSetter;
import org.simpleflatmapper.csv.mapper.CsvMapperCellHandler;
import org.simpleflatmapper.csv.mapper.CsvMapperCellHandlerFactory;
import org.simpleflatmapper.csv.mapper.DelayedCellSetterFactory;
import org.simpleflatmapper.map.property.DefaultDateFormatProperty;
import org.simpleflatmapper.map.property.DefaultValueProperty;
import org.simpleflatmapper.util.BiConsumer;
import org.simpleflatmapper.util.ErrorHelper;
import org.simpleflatmapper.util.ForEachCallBack;
import org.simpleflatmapper.util.Named;
import org.simpleflatmapper.util.Predicate;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class CsvMapperBuilder<T> {
public static final CustomReaderProperty NONE_READER_PROPERTY = new CustomReaderProperty(new CellValueReader() {
@Override
public Object read(char[] chars, int offset, int length, ParsingContext parsingContext) {
throw new UnsupportedOperationException("Default value should not try to read");
}
});
private final Type target;
private final ReflectionService reflectionService;
private final MapperConfig<CsvColumnKey, CsvColumnDefinition> mapperConfig;
private final int minDelayedSetter;
private final CellValueReaderFactory cellValueReaderFactory;
private final PropertyMappingsBuilder<T, CsvColumnKey, CsvColumnDefinition> propertyMappingsBuilder;
private String defaultDateFormat = "yyyy-MM-dd HH:mm:ss";
public CsvMapperBuilder(final Type target) {
this(target, ReflectionService.newInstance());
}
@SuppressWarnings("unchecked")
public CsvMapperBuilder(final Type target, ReflectionService reflectionService) {
this(target, (ClassMeta<T>)reflectionService.getClassMeta(target));
}
public CsvMapperBuilder(final Type target, final ClassMeta<T> classMeta) {
this(target, classMeta, new IdentityCsvColumnDefinitionProvider());
}
public CsvMapperBuilder(final Type target, final ClassMeta<T> classMeta, ColumnDefinitionProvider<CsvColumnDefinition, CsvColumnKey> columnDefinitionProvider) {
this(target, classMeta, 0,
new CellValueReaderFactoryImpl(), MapperConfig.<CsvColumnKey, CsvColumnDefinition>config(columnDefinitionProvider));
}
public CsvMapperBuilder(final Type target,
final ClassMeta<T> classMeta,
int minDelayedSetter,
CellValueReaderFactory cellValueReaderFactory,
MapperConfig<CsvColumnKey, CsvColumnDefinition> mapperConfig
) throws MapperBuildingException {
this.target = target;
this.minDelayedSetter = minDelayedSetter;
this.reflectionService = classMeta.getReflectionService();
this.propertyMappingsBuilder =
PropertyMappingsBuilder.<T, CsvColumnKey, CsvColumnDefinition>of(classMeta, mapperConfig, PropertyWithSetterOrConstructor.INSTANCE);
this.cellValueReaderFactory = cellValueReaderFactory;
this.mapperConfig = mapperConfig;
}
public final CsvMapperBuilder<T> addMapping(final String columnKey) {
return addMapping(columnKey, propertyMappingsBuilder.size());
}
public final CsvMapperBuilder<T> addMapping(final String columnKey, int columnIndex) {
return addMapping(new CsvColumnKey(columnKey, columnIndex), CsvColumnDefinition.identity());
}
public final CsvMapperBuilder<T> addMapping(final String columnKey, final CsvColumnDefinition columnDefinition) {
return addMapping(columnKey, propertyMappingsBuilder.size(), columnDefinition);
}
public final CsvMapperBuilder<T> addMapping(final String columnKey, int columnIndex, CsvColumnDefinition columnDefinition) {
return addMapping(new CsvColumnKey(columnKey, columnIndex), columnDefinition);
}
public final CsvMapperBuilder<T> addMapping(final CsvColumnKey key, final CsvColumnDefinition columnDefinition) {
final CsvColumnDefinition composedDefinition = CsvColumnDefinition.compose(getColumnDefinition(key), columnDefinition);
final CsvColumnKey mappedColumnKey = composedDefinition.rename(key);
propertyMappingsBuilder.addProperty(mappedColumnKey, composedDefinition);
return this;
}
public final CsvMapperBuilder<T> addMapping(final String columnKey, final Object... properties) {
return addMapping(columnKey, propertyMappingsBuilder.size(), properties);
}
public final CsvMapperBuilder<T> addMapping(final String columnKey, int columnIndex, final Object... properties) {
return addMapping(new CsvColumnKey(columnKey, columnIndex), properties);
}
public final CsvMapperBuilder<T> addMapping(final CsvColumnKey key, final Object... properties) {
return addMapping(key, CsvColumnDefinition.of(properties));
}
private <P> void addMapping(PropertyMeta<T, P> propertyMeta, final CsvColumnKey key, final CsvColumnDefinition columnDefinition) {
propertyMappingsBuilder.addProperty(key, columnDefinition, propertyMeta);
}
private CsvColumnDefinition getColumnDefinition(CsvColumnKey key) {
CsvColumnDefinition columnDefinition = mapperConfig.columnDefinitions().getColumnDefinition(key);
return CsvColumnDefinition.compose(CsvColumnDefinition.of(new DefaultDateFormatProperty(defaultDateFormat)), columnDefinition);
}
public void setDefaultDateFormat(String defaultDateFormat) {
this.defaultDateFormat = defaultDateFormat;
}
public final CsvMapper<T> mapper() {
mapperConfig
.columnDefinitions()
.forEach(
DefaultValueProperty.class,
new BiConsumer<Predicate<? super CsvColumnKey>, DefaultValueProperty>() {
@Override
public void accept(Predicate<? super CsvColumnKey> predicate, DefaultValueProperty columnProperty) {
if (propertyMappingsBuilder.hasKey(predicate)){
return;
}
if (predicate instanceof Named) {
String name = ((Named)predicate).getName();
final CsvColumnDefinition columnDefinition = CsvColumnDefinition.identity().add(columnProperty, NONE_READER_PROPERTY);
CsvColumnKey key = new CsvColumnKey(name, propertyMappingsBuilder.size());
propertyMappingsBuilder.addPropertyIfPresent(key, columnDefinition);
}
}
});
ParsingContextFactoryBuilder parsingContextFactoryBuilder = new ParsingContextFactoryBuilder(propertyMappingsBuilder.maxIndex() + 1);
ConstructorParametersDelayedCellSetter constructorParams = buildConstructorParametersDelayedCellSetter();
@SuppressWarnings("unchecked")
final Instantiator<CsvMapperCellHandler<T>, T> instantiator = getInstantiator(constructorParams.parameterGetterMap);
final CsvColumnKey[] keys = getKeys();
// will build the context factory builder
final CellSetter<T>[] setters = getSetters(parsingContextFactoryBuilder, constructorParams.index);
final DelayedCellSetterFactory<T, ?>[] delayedCellSetterFactories = buildDelayedSetters(parsingContextFactoryBuilder, constructorParams.index, constructorParams.hasKeys);
// needs to happen last
final CsvMapperCellHandlerFactory<T> csvMapperCellHandlerFactory = newCsvMapperCellHandlerFactory(parsingContextFactoryBuilder, instantiator, keys, delayedCellSetterFactories, setters);
return new CsvMapperImpl<T>(csvMapperCellHandlerFactory,
delayedCellSetterFactories,
setters, getJoinKeys(), mapperConfig.consumerErrorHandler());
}
private CsvMapperCellHandlerFactory<T> newCsvMapperCellHandlerFactory(ParsingContextFactoryBuilder parsingContextFactoryBuilder,
Instantiator<CsvMapperCellHandler<T>, T> instantiator,
CsvColumnKey[] keys,
DelayedCellSetterFactory<T, ?>[] delayedCellSetterFactories,
CellSetter<T>[] setters
) {
final ParsingContextFactory parsingContextFactory = parsingContextFactoryBuilder.newFactory();
if (isEligibleForAsmHandler()) {
try {
return reflectionService.getAsmFactory()
.registerOrCreate(CsvAsmFactory.class, new UnaryFactory<AsmFactory, CsvAsmFactory>() {
@Override
public CsvAsmFactory newInstance(AsmFactory asmFactory) {
return new CsvAsmFactory(asmFactory);
}
}).<T>createCsvMapperCellHandler(target, delayedCellSetterFactories, setters,
instantiator, keys, parsingContextFactory, mapperConfig.fieldMapperErrorHandler(),
mapperConfig.maxMethodSize());
} catch (Exception e) {
if (mapperConfig.failOnAsm()) {
return ErrorHelper.rethrow(e);
} else {
return new CsvMapperCellHandlerFactory<T>(instantiator, keys, parsingContextFactory, mapperConfig.fieldMapperErrorHandler());
}
}
} else {
return new CsvMapperCellHandlerFactory<T>(instantiator, keys, parsingContextFactory, mapperConfig.fieldMapperErrorHandler());
}
}
private boolean isEligibleForAsmHandler() {
return reflectionService.hasAsmFactory()
&& this.propertyMappingsBuilder.size() < mapperConfig.asmMapperNbFieldsLimit();
}
private CsvColumnKey[] getKeys() {
return propertyMappingsBuilder.getKeys().toArray(new CsvColumnKey[0]);
}
private CsvColumnKey[] getJoinKeys() {
final List<CsvColumnKey> keys = new ArrayList<CsvColumnKey>();
propertyMappingsBuilder.forEachProperties(new ForEachCallBack<PropertyMapping<T, ?, CsvColumnKey, CsvColumnDefinition>>() {
@Override
public void handle(PropertyMapping<T, ?, CsvColumnKey, CsvColumnDefinition> pm) {
if (pm.getColumnDefinition().isKey() && pm.getColumnDefinition().keyAppliesTo().test(pm.getPropertyMeta())) {
keys.add(pm.getColumnKey());
}
}
});
return keys.toArray(new CsvColumnKey[0]);
}
private Instantiator<CsvMapperCellHandler<T>, T> getInstantiator(Map<Parameter, Getter<? super CsvMapperCellHandler<T>, ?>> params) throws MapperBuildingException {
InstantiatorFactory instantiatorFactory = reflectionService.getInstantiatorFactory();
try {
return new MapperInstantiatorFactory(instantiatorFactory)
.getInstantiator(
new TypeReference<CsvMapperCellHandler<T>>(){}.getType(),
target,
propertyMappingsBuilder,
params,
new GetterFactory<CsvMapperCellHandler<T>, CsvColumnKey>() {
@Override
public <P> Getter<CsvMapperCellHandler<T>, P> newGetter(Type target, CsvColumnKey key, Object... properties) {
return newDelayedGetter(target, key, properties);
}
});
} catch(Exception e) {
return ErrorHelper.rethrow(e);
}
}
private ConstructorParametersDelayedCellSetter<T> buildConstructorParametersDelayedCellSetter() {
final BuildConstructorInjections buildConstructorInjections = new BuildConstructorInjections();
propertyMappingsBuilder.forEachProperties(buildConstructorInjections);
return new ConstructorParametersDelayedCellSetter<T>(
buildConstructorInjections.constructorInjections,
buildConstructorInjections.delayedSetterEnd,
buildConstructorInjections.hasKeys);
}
@SuppressWarnings({ "unchecked" })
private DelayedCellSetterFactory<T, ?>[] buildDelayedSetters(final ParsingContextFactoryBuilder parsingContextFactoryBuilder, int delayedSetterEnd, boolean hasKeys) {
final Map<String, CsvMapperBuilder<?>> delegateMapperBuilders = new HashMap<String, CsvMapperBuilder<?>>();
final Map<String, Integer> propertyToMapperIndex = new HashMap<String, Integer>();
final DelayedCellSetterFactory<T, ?>[] delayedSetters = new DelayedCellSetterFactory[delayedSetterEnd];
final int newMinDelayedSetter = minDelayedSetter != 0 ? minDelayedSetter : hasKeys ? delayedSetterEnd : 0;
propertyMappingsBuilder.forEachProperties(new ForEachCallBack<PropertyMapping<T,?,CsvColumnKey, CsvColumnDefinition>>() {
final CellSetterFactory cellSetterFactory = new CellSetterFactory(cellValueReaderFactory, mapperConfig.mapperBuilderErrorHandler());
@Override
public void handle(PropertyMapping<T, ?, CsvColumnKey, CsvColumnDefinition> propMapping) {
if (propMapping != null) {
PropertyMeta<T, ?> prop = propMapping.getPropertyMeta();
CsvColumnKey key = propMapping.getColumnKey();
if (prop != null) {
if (prop.isSubProperty()) {
addSubProperty(delegateMapperBuilders, prop, key, propMapping.getColumnDefinition());
}else {
delayedSetters[propMapping.getColumnKey().getIndex()] = cellSetterFactory.getDelayedCellSetter(prop, key.getIndex(), propMapping.getColumnDefinition(), parsingContextFactoryBuilder);
}
}
}
}
private <I, P> void addSubProperty(
Map<String, CsvMapperBuilder<?>> delegateMapperBuilders,
PropertyMeta<T, P> prop, CsvColumnKey key, CsvColumnDefinition columnDefinition) {
SubPropertyMeta<T, I, P> subPropertyMeta = (SubPropertyMeta<T, I, P>)prop;
final PropertyMeta<T, I> propOwner = subPropertyMeta.getOwnerProperty();
CsvMapperBuilder<I> delegateMapperBuilder = (CsvMapperBuilder<I>) delegateMapperBuilders .get(propOwner.getName());
if (delegateMapperBuilder == null) {
delegateMapperBuilder = new CsvMapperBuilder<I>(propOwner.getPropertyType(), propOwner.getPropertyClassMeta(), newMinDelayedSetter, cellValueReaderFactory, mapperConfig);
delegateMapperBuilders.put(propOwner.getName(), delegateMapperBuilder);
}
Integer currentIndex = propertyToMapperIndex.get(propOwner.getName());
if (currentIndex == null || currentIndex < key.getIndex()) {
propertyToMapperIndex.put(propOwner.getName(), key.getIndex());
}
delegateMapperBuilder.addMapping(subPropertyMeta.getSubProperty(), key, columnDefinition);
}
}, 0, delayedSetterEnd);
final Map<String, CsvMapper<?>> mappers = new HashMap<String, CsvMapper<?>>();
propertyMappingsBuilder.forEachProperties(new ForEachCallBack<PropertyMapping<T,?,CsvColumnKey, CsvColumnDefinition>>() {
@Override
public void handle(PropertyMapping<T, ?, CsvColumnKey, CsvColumnDefinition> propMapping) {
if (propMapping == null) return;
PropertyMeta<T, ?> prop = propMapping.getPropertyMeta();
if (prop.isSubProperty()) {
addSubPropertyDelayedSetter(delegateMapperBuilders, delayedSetters, propMapping.getColumnKey().getIndex(), prop);
}
}
private <I, P> void addSubPropertyDelayedSetter(
Map<String, CsvMapperBuilder<?>> delegateMapperBuilders,
DelayedCellSetterFactory<T, ?>[] delayedSetters,
int setterIndex,
PropertyMeta<T, P> prop) {
PropertyMeta<T, I> subProp = ((SubPropertyMeta<T, I, P>) prop).getOwnerProperty();
final String propName = subProp.getName();
CsvMapper<I> mapper = (CsvMapper<I>) mappers.get(propName);
if (mapper == null) {
CsvMapperBuilder<I> delegateMapperBuilder = (CsvMapperBuilder<I>) delegateMapperBuilders.get(propName);
mapper = delegateMapperBuilder.mapper();
mappers.put(propName, mapper);
}
int indexOfMapper = propertyToMapperIndex.get(propName);
Setter<? super T, ? super I> setter = null;
if (!subProp.isConstructorProperty()) {
setter = subProp.getSetter();
}
delayedSetters[setterIndex] = new DelegateMarkerDelayedCellSetterFactory<T, I>(mapper, setter, setterIndex, indexOfMapper);
}
}, 0, delayedSetterEnd);
return delayedSetters;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private CellSetter<T>[] getSetters(final ParsingContextFactoryBuilder parsingContextFactoryBuilder, final int delayedSetterEnd) {
final Map<String, CsvMapperBuilder<?>> delegateMapperBuilders = new HashMap<String, CsvMapperBuilder<?>>();
final Map<String, Integer> propertyToMapperIndex = new HashMap<String, Integer>();
// calculate maxIndex
int maxIndex = propertyMappingsBuilder.forEachProperties(new ForEachCallBack<PropertyMapping<T,?,CsvColumnKey, CsvColumnDefinition>>() {
int maxIndex = delayedSetterEnd;
@Override
public void handle(PropertyMapping<T, ?, CsvColumnKey, CsvColumnDefinition> propMapping) {
if (propMapping != null) {
maxIndex = Math.max(propMapping.getColumnKey().getIndex(), maxIndex);
PropertyMeta<T, ?> prop = propMapping.getPropertyMeta();
if (prop != null) {
CsvColumnKey key = propMapping.getColumnKey();
if (prop.isConstructorProperty()) {
throw new IllegalStateException("Unexpected ConstructorPropertyMeta at " + key.getIndex());
} else if (prop.isSubProperty()) {
final PropertyMeta<?, ?> propOwner = ((SubPropertyMeta)prop).getOwnerProperty();
CsvMapperBuilder<?> delegateMapperBuilder = delegateMapperBuilders .get(propOwner.getName());
if (delegateMapperBuilder == null) {
delegateMapperBuilder =
new CsvMapperBuilder(propOwner.getPropertyType(), propOwner.getPropertyClassMeta(), minDelayedSetter, cellValueReaderFactory, mapperConfig);
delegateMapperBuilders.put(propOwner.getName(), delegateMapperBuilder);
}
Integer currentIndex = propertyToMapperIndex.get(propOwner.getName());
if (currentIndex == null || currentIndex < key.getIndex()) {
propertyToMapperIndex.put(propOwner.getName(), key.getIndex());
}
delegateMapperBuilder.addMapping(((SubPropertyMeta) prop).getSubProperty(), key, propMapping.getColumnDefinition());
}
}
}
}
}, delayedSetterEnd).maxIndex;
// builder se setters
final CellSetter<T>[] setters = new CellSetter[maxIndex + 1 - delayedSetterEnd];
propertyMappingsBuilder.forEachProperties(new ForEachCallBack<PropertyMapping<T,?,CsvColumnKey, CsvColumnDefinition>>() {
final Map<String, CsvMapperImpl<?>> mappers = new HashMap<String, CsvMapperImpl<?>>();
final CellSetterFactory cellSetterFactory = new CellSetterFactory(cellValueReaderFactory, mapperConfig.mapperBuilderErrorHandler());
@Override
public void handle(PropertyMapping<T, ?, CsvColumnKey, CsvColumnDefinition> propMapping) {
if (propMapping == null) {
return;
}
PropertyMeta<T, ?> prop = propMapping.getPropertyMeta();
if (prop == null || prop instanceof SelfPropertyMeta) {
return;
}
if (prop instanceof SubPropertyMeta) {
DelegateMarkerSetter<T, ?> delegateMarkerSetter = getDelegateMarkerSetter((SubPropertyMeta) prop);
setters[propMapping.getColumnKey().getIndex()- delayedSetterEnd] = delegateMarkerSetter;
} else {
setters[propMapping.getColumnKey().getIndex()- delayedSetterEnd] = cellSetterFactory.getCellSetter(prop, propMapping.getColumnKey().getIndex(), propMapping.getColumnDefinition(), parsingContextFactoryBuilder);
}
}
private <I, P> DelegateMarkerSetter<T, I> getDelegateMarkerSetter(SubPropertyMeta<T, I, P> prop) {
final String propName = prop.getOwnerProperty().getName();
CsvMapperImpl<I> mapper = (CsvMapperImpl<I>) mappers.get(propName);
if (mapper == null) {
CsvMapperBuilder<I> delegateMapperBuilder = (CsvMapperBuilder<I>) delegateMapperBuilders.get(propName);
mapper = (CsvMapperImpl<I>) delegateMapperBuilder.mapper();
mappers.put(propName, mapper);
}
int indexOfMapper = propertyToMapperIndex.get(propName);
return new DelegateMarkerSetter<T, I>(mapper, prop.getOwnerProperty().getSetter(), indexOfMapper);
}
}, delayedSetterEnd);
return setters;
}
public void addDefaultHeaders() {
addDefaultHeaders(propertyMappingsBuilder.getClassMeta(), "");
}
private <P> void addDefaultHeaders(final ClassMeta<P> classMeta, final String prefix) {
classMeta.forEachProperties(new Consumer<PropertyMeta<P,?>>() {
@Override
public void accept(PropertyMeta<P, ?> propertyMeta) {
String currentName = prefix + propertyMeta.getPath();
if (cellValueReaderFactory.getReader(propertyMeta.getPropertyType(), 0, CsvColumnDefinition.identity(), new ParsingContextFactoryBuilder(1)) == null) {
addDefaultHeaders(propertyMeta.getPropertyClassMeta(), currentName + "_");
} else {
addMapping(currentName);
}
}
});
}
private class BuildConstructorInjections implements ForEachCallBack<PropertyMapping<T,?,CsvColumnKey, CsvColumnDefinition>> {
final CellSetterFactory cellSetterFactory;
private final Map<Parameter, Getter<? super CsvMapperCellHandler<T>, ?>> constructorInjections;
int delayedSetterEnd;
boolean hasKeys;
public BuildConstructorInjections() {
this.constructorInjections = new HashMap<Parameter, Getter<? super CsvMapperCellHandler<T>, ?>>();
cellSetterFactory = new CellSetterFactory(cellValueReaderFactory, mapperConfig.mapperBuilderErrorHandler());
delayedSetterEnd = minDelayedSetter;
}
@SuppressWarnings("unchecked")
@Override
public void handle(PropertyMapping<T, ?, CsvColumnKey, CsvColumnDefinition> propMapping) {
if (propMapping == null) return;
PropertyMeta<T, ?> meta = propMapping.getPropertyMeta();
hasKeys = hasKeys || propMapping.getColumnDefinition().isKey();
if (meta == null) return;
final CsvColumnKey key = propMapping.getColumnKey();
if (meta.isConstructorProperty()) {
delayedSetterEnd = Math.max(delayedSetterEnd, key.getIndex() + 1);
Getter<CsvMapperCellHandler<T>, ?> delayedGetter = newDelayedGetter(meta.getPropertyType(), key, propMapping.getColumnDefinition().properties());
constructorInjections.put(((ConstructorPropertyMeta<T, ?>) meta).getParameter(), delayedGetter);
} else if (meta instanceof SelfPropertyMeta) {
delayedSetterEnd = Math.max(delayedSetterEnd, key.getIndex() + 1);
} else if (meta.isSubProperty()) {
SubPropertyMeta<T, ?, ?> subMeta = (SubPropertyMeta<T, ?, ?>) meta;
if (subMeta.getOwnerProperty().isConstructorProperty()) {
ConstructorPropertyMeta<?, ?> constPropMeta = (ConstructorPropertyMeta<?, ?>) subMeta.getOwnerProperty();
Getter<CsvMapperCellHandler<T>, ?> delayedGetter = cellSetterFactory.newDelayedGetter(key, constPropMeta.getPropertyType());
constructorInjections.put(constPropMeta.getParameter(), delayedGetter);
delayedSetterEnd = Math.max(delayedSetterEnd, key.getIndex() + 1);
} else if (
(propMapping.getColumnDefinition().isKey()
&& propMapping.getColumnDefinition().keyAppliesTo().test(propMapping.getPropertyMeta()))
|| subMeta.getSubProperty() instanceof SelfPropertyMeta) {
delayedSetterEnd = Math.max(delayedSetterEnd, key.getIndex() + 1);
}
} else if ((propMapping.getColumnDefinition().isKey()
&& propMapping.getColumnDefinition().keyAppliesTo().test(propMapping.getPropertyMeta()))
|| propMapping.getColumnDefinition().has(DefaultValueProperty.class))
{
delayedSetterEnd = Math.max(delayedSetterEnd, key.getIndex() + 1);
}
}
}
private <P> Getter<CsvMapperCellHandler<T>, P> newDelayedGetter(Type propertyType, CsvColumnKey key, Object... properties) {
final CellSetterFactory cellSetterFactory = new CellSetterFactory(cellValueReaderFactory, mapperConfig.mapperBuilderErrorHandler());
for(Object prop :properties) {
if (prop instanceof DefaultValueProperty) {
return new DelayedGetter<T, P>(key.getIndex());
}
}
return cellSetterFactory.newDelayedGetter(key, propertyType);
}
// Map<Parameter, Getter<? super CsvMapperCellHandler<T>, ?>>, Integer, Boolean
private static class ConstructorParametersDelayedCellSetter<T> {
private final Map<Parameter, Getter<? super CsvMapperCellHandler<T>, ?>> parameterGetterMap;
private final int index;
private final boolean hasKeys;
private ConstructorParametersDelayedCellSetter(Map<Parameter, Getter<? super CsvMapperCellHandler<T>, ?>> parameterGetterMap, int index, boolean hasKeys) {
this.parameterGetterMap = parameterGetterMap;
this.index = index;
this.hasKeys = hasKeys;
}
}
}