Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.simpleflatmapper.map.mapper.DefaultConstantSourceMapperBuilder Maven / Gradle / Ivy
Go to download
Java library to map flat record - ResultSet, csv - to java object with minimum configuration and low footprint.
package org.simpleflatmapper.map.mapper;
import org.simpleflatmapper.converter.Context;
import org.simpleflatmapper.converter.ConverterService;
import org.simpleflatmapper.map.FieldKey;
import org.simpleflatmapper.map.FieldMapperErrorHandler;
import org.simpleflatmapper.map.MapperBuildingException;
import org.simpleflatmapper.map.MappingContext;
import org.simpleflatmapper.map.SourceFieldMapper;
import org.simpleflatmapper.map.asm.MapperAsmFactory;
import org.simpleflatmapper.map.context.KeyAndPredicate;
import org.simpleflatmapper.map.context.KeySourceGetter;
import org.simpleflatmapper.map.context.MappingContextFactory;
import org.simpleflatmapper.map.getter.ContextualGetter;
import org.simpleflatmapper.map.getter.ContextualGetterFactory;
import org.simpleflatmapper.map.fieldmapper.MapperFieldMapper;
import org.simpleflatmapper.map.getter.NullContextualGetter;
import org.simpleflatmapper.map.impl.DiscriminatorPropertyFinder;
import org.simpleflatmapper.map.impl.GetterMapper;
import org.simpleflatmapper.map.impl.JoinUtils;
import org.simpleflatmapper.map.property.*;
import org.simpleflatmapper.map.context.MappingContextFactoryBuilder;
import org.simpleflatmapper.map.fieldmapper.ConstantSourceFieldMapperFactory;
import org.simpleflatmapper.map.fieldmapper.ConstantSourceFieldMapperFactoryImpl;
import org.simpleflatmapper.reflect.BiInstantiator;
import org.simpleflatmapper.reflect.BuilderInstantiatorDefinition;
import org.simpleflatmapper.reflect.InstantiatorDefinition;
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.ConstantGetter;
import org.simpleflatmapper.reflect.BuilderBiInstantiator;
import org.simpleflatmapper.reflect.meta.ClassMeta;
import org.simpleflatmapper.reflect.meta.ConstructorPropertyMeta;
import org.simpleflatmapper.reflect.meta.PropertyFinder;
import org.simpleflatmapper.reflect.meta.PropertyMeta;
import org.simpleflatmapper.reflect.meta.SelfPropertyMeta;
import org.simpleflatmapper.reflect.meta.SubPropertyMeta;
import org.simpleflatmapper.map.FieldMapper;
import org.simpleflatmapper.map.SourceMapper;
import org.simpleflatmapper.map.MapperConfig;
import org.simpleflatmapper.reflect.setter.NullSetter;
import org.simpleflatmapper.util.*;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.*;
import static org.simpleflatmapper.util.Asserts.requireNonNull;
import static org.simpleflatmapper.util.ErrorDoc.CSFM_GETTER_NOT_FOUND;
public final class DefaultConstantSourceMapperBuilder> extends ConstantSourceMapperBuilder {
private static final FieldKey[] FIELD_KEYS = new FieldKey[0];
public static final FieldMapper[] EMPTY_FIELD_MAPPERS = new FieldMapper[0];
private final Type target;
private final ConstantSourceFieldMapperFactory fieldMapperFactory;
protected final PropertyMappingsBuilder propertyMappingsBuilder;
protected final ReflectionService reflectionService;
private final List> additionalMappers = new ArrayList>();
private final MapperSource super S, K> mapperSource;
private final MapperConfig mapperConfig;
protected final MappingContextFactoryBuilder mappingContextFactoryBuilder;
private final KeyFactory keyFactory;
public DefaultConstantSourceMapperBuilder(
final MapperSource super S, K> mapperSource,
final ClassMeta classMeta,
final MapperConfig mapperConfig,
MappingContextFactoryBuilder mappingContextFactoryBuilder,
KeyFactory keyFactory,
PropertyFinder propertyFinder) throws MapperBuildingException {
final ContextualGetterFactory super S, K> getterFactory = mapperSource.getterFactory();
this.mapperSource = requireNonNull("fieldMapperSource", mapperSource);
this.mapperConfig = requireNonNull("mapperConfig", mapperConfig);
this.mappingContextFactoryBuilder = mappingContextFactoryBuilder;
this.fieldMapperFactory = new ConstantSourceFieldMapperFactoryImpl(getterFactory, ConverterService.getInstance(), mapperSource.source());
this.keyFactory = keyFactory;
this.propertyMappingsBuilder =
PropertyMappingsBuilder.of(classMeta, mapperConfig, new PropertyMappingsBuilder.PropertyPredicateFactory() {
@Override
public PropertyFinder.PropertyFilter predicate(final K k, final Object[] properties, final List accessorNotFounds) {
if (k != null) {
final MappingContextFactoryBuilder mappingContextFactoryBuilder1 = new MappingContextFactoryBuilder(new KeySourceGetter() {
@Override
public Object getValue(K key, Object source) throws Exception {
return null;
}
}, !mapperConfig.unorderedJoin());
Predicate> propertyMetaPredicate = new Predicate>() {
@Override
public boolean test(PropertyMeta, ?> propertyMeta) {
if (!PropertyWithSetterOrConstructor.INSTANCE.test(propertyMeta))
return false;
try {
ContextualGetter super S, ?> getterFromSource = getContextualGetter(propertyMeta);
if (NullContextualGetter.isNull(getterFromSource)) {
accessorNotFounds.add(new PropertyMappingsBuilder.AccessorNotFound(k, propertyMeta.getPath(), propertyMeta.getPropertyType(), CSFM_GETTER_NOT_FOUND, propertyMeta));
return false;
}
return true;
} catch (Exception e) {
return false;
}
}
public ContextualGetter super S, ? extends P> getContextualGetter(PropertyMeta propertyMeta) {
return fieldMapperFactory.getGetterFromSource(
k,
propertyMeta.getPropertyType(),
FieldMapperColumnDefinition.of(properties),
propertyMeta.getPropertyClassMetaSupplier(),
mappingContextFactoryBuilder1);
}
};
return new PropertyFinder.PropertyFilter(propertyMetaPredicate, PropertyWithSetterOrConstructor.INSTANCE);
}
return new PropertyFinder.PropertyFilter(PropertyWithSetterOrConstructor.INSTANCE);
}
}, propertyFinder);
this.target = requireNonNull("classMeta", classMeta).getType();
this.reflectionService = requireNonNull("classMeta", classMeta).getReflectionService();
}
@Override
@SuppressWarnings("unchecked")
public final ConstantSourceMapperBuilder addMapping(K key, final ColumnDefinition columnDefinition) {
final ColumnDefinition composedDefinition = columnDefinition.compose(mapperConfig.columnDefinitions().getColumnDefinition(key));
final K mappedColumnKey = composedDefinition.rename(key);
FieldMapperProperty prop = columnDefinition.lookFor(FieldMapperProperty.class);
if (prop != null) {
addMapper((FieldMapper) prop.getFieldMapper());
} else {
PropertyMapping propertyMapping = propertyMappingsBuilder.addProperty(mappedColumnKey, composedDefinition);
if (propertyMapping != null) {
ColumnDefinition effectiveColumnDefinition = propertyMapping.getColumnDefinition();
if (effectiveColumnDefinition.isKey() && effectiveColumnDefinition.keyAppliesTo().test(propertyMapping.getPropertyMeta())) {
Predicate predicate = buildKeyPredicate(propertyMapping.getPropertyMeta(), effectiveColumnDefinition.keyAppliesTo());
mappingContextFactoryBuilder.addKey(new KeyAndPredicate(mappedColumnKey, predicate));
} else if (effectiveColumnDefinition.isInferNull() && effectiveColumnDefinition.inferNullsAppliesTo().test(propertyMapping.getPropertyMeta())) {
Predicate predicate = buildKeyPredicate(propertyMapping.getPropertyMeta(), effectiveColumnDefinition.inferNullsAppliesTo());
mappingContextFactoryBuilder.addInferNull(new KeyAndPredicate(mappedColumnKey, predicate));
}
}
}
return this;
}
@Override
@SuppressWarnings("unchecked")
public ContextualSourceFieldMapperImpl mapper() {
SourceFieldMapper mapper = sourceFieldMapper();
return new ContextualSourceFieldMapperImpl(mappingContextFactoryBuilder.build(), mapper);
}
@Override
public SourceFieldMapper sourceFieldMapper() {
// look for property with a default value property but no definition.
mapperConfig
.columnDefinitions()
.forEach(
DefaultValueProperty.class,
new BiConsumer, DefaultValueProperty>() {
@Override
public void accept(Predicate super K> predicate, DefaultValueProperty columnProperty) {
if (propertyMappingsBuilder.hasKey(predicate)){
return;
}
if (predicate instanceof Named) {
String name = ((Named)predicate).getName();
GetterProperty getterProperty =
new GetterProperty(new ConstantGetter(columnProperty.getValue()), mapperSource.source(), columnProperty.getValue().getClass());
final FieldMapperColumnDefinition columnDefinition =
FieldMapperColumnDefinition.identity().add(columnProperty,
getterProperty);
propertyMappingsBuilder.addPropertyIfPresent(keyFactory.newKey(name, propertyMappingsBuilder.maxIndex() + 1), columnDefinition);
}
}
});
final List missingProperties = new ArrayList();
//
mapperConfig
.columnDefinitions()
.forEach(
MandatoryProperty.class,
new BiConsumer, MandatoryProperty>() {
@Override
public void accept(Predicate super K> predicate, MandatoryProperty columnProperty) {
if (!propertyMappingsBuilder.hasKey(predicate)){
if (predicate instanceof Named) {
missingProperties.add(((Named)predicate).getName());
} else {
missingProperties.add(predicate.toString());
}
}
}
});
if (!missingProperties.isEmpty()) {
throw new MissingPropertyException(missingProperties);
}
SourceFieldMapper mapper;
List injectionParams = constructorInjections();
if (isTargetForTransformer(injectionParams)) {
mapper = buildMapperWithTransformer(injectionParams);
} else {
ConstructorInjections constructorInjections = toConstructorInjections(injectionParams);
InstantiatorAndFieldMappers constructorFieldMappersAndInstantiator = getConstructorFieldMappersAndInstantiator(constructorInjections);
mapper = buildMapper(targetFieldMappers(), constructorFieldMappersAndInstantiator, getKeys().toArray(FIELD_KEYS), getTargetClass(), reflectionService, mapperSource, mapperConfig);
}
return mapper;
}
private boolean isTargetForTransformer(List injectionParams) {
return
propertyMappingsBuilder.getClassMeta().needTransformer()
|| needGenericBuilder(injectionParams)
// is aggregate and constructor injection
|| (mapperConfig.assumeInjectionModifiesValues() && (!mappingContextFactoryBuilder.hasNoDependentKeys() && !injectionParams.isEmpty()))
;
}
@SuppressWarnings("unchecked")
private SourceFieldMapper buildMapperWithTransformer(List injections) {
boolean forceGenericBuilder = needGenericBuilder(injections);
BuilderInstantiatorDefinition mutableBuilder = getMutableBuilder();
// already has mutable builder
if (!forceGenericBuilder &&
mutableBuilder != null) {
return builderWithTransformer(injections, mutableBuilder);
} else {
return buildWithGenericBuilder(injections, fields(), getKeys().toArray(FIELD_KEYS));
}
}
private boolean needGenericBuilder(List injections) {
boolean forceGenericBuilder = false;
// handle builder with an injection needing transformation
for(InjectionParam ip : injections) {
if (ip.needTransformer()) {
forceGenericBuilder = true;
break;
}
}
return forceGenericBuilder;
}
private BuilderInstantiatorDefinition getMutableBuilder() {
List eligibleInstantiatorDefinitions = propertyMappingsBuilder.getPropertyFinder().getEligibleInstantiatorDefinitions();
for(int i = 0; i < eligibleInstantiatorDefinitions.size(); i++) {
InstantiatorDefinition instantiatorDefinition = eligibleInstantiatorDefinitions.get(i);
if (instantiatorDefinition.getType() == InstantiatorDefinition.Type.BUILDER) {
BuilderInstantiatorDefinition bid = (BuilderInstantiatorDefinition) instantiatorDefinition;
if (bid.isMutable()) {
return bid;
}
}
}
return null;
}
@SuppressWarnings("unchecked")
private SourceFieldMapper buildWithGenericBuilder(
List params,
List fields,
FieldKey[] keys) {
GenericBuilderMapping gbm = getGenericBuilderMapping(params, fields, keys);
return buildWithGenericBuilder(gbm);
}
public GenericBuilderMapping getGenericBuilderMapping() {
return getGenericBuilderMapping(constructorInjections(), fields(), getKeys().toArray(FIELD_KEYS));
}
private GenericBuilderMapping getGenericBuilderMapping(List params, List fields, FieldKey[] keys) {
int nbParams = params.size();
final Parameter[] indexMapping = new Parameter[nbParams];
final Function[] transformers = new Function[nbParams];
List>> genericBuilderFieldMappers = new ArrayList>>();
List> targetConstructorFieldMapper = new ArrayList>();
List> targetFieldMappers = new ArrayList>();
List>> targetFieldSetters = new ArrayList>>();
int i = 0;
// Generic builder can have all as field mapper not need for constructor injection
//
for(InjectionParam p : params) {
GenericBuilderGetterAndFieldMapper getterAndFieldMapper = p.getterAndfieldMapperGenericBuilder(i);
if (getterAndFieldMapper != null) {
if (getterAndFieldMapper.fieldMapper == null) {
throw new IllegalStateException();
}
genericBuilderFieldMappers.add(getterAndFieldMapper.fieldMapper);
if (getterAndFieldMapper.fieldMapperAfterConstruct != null) {
targetConstructorFieldMapper.add(getterAndFieldMapper.fieldMapperAfterConstruct);
}
indexMapping[i] = p.parameter;
transformers[i] = getterAndFieldMapper.transform;
i++;
}
}
for(FieldMeta fm : fields) {
FieldGenericBuilderInfo fieldGenericBuilderInfo = fm.fieldGenericBuilderInfo(i);
targetFieldMappers.add(fieldGenericBuilderInfo.targetFieldMapper);
genericBuilderFieldMappers.add(fieldGenericBuilderInfo.fieldMapperGeneric);
targetFieldSetters.add(fieldGenericBuilderInfo.fieldSetter);
i++;
}
final BiInstantiator targetInstantiatorFromGenericBuilder = targetInstantiatorFromGenericBuilder(indexMapping, transformers);
GenericBuildBiInstantiator genericBuilderInstantiator =
new GenericBuildBiInstantiator(
genericBuilderFieldMappers.>>toArray(EMPTY_FIELD_MAPPERS),
targetInstantiatorFromGenericBuilder,
targetFieldSetters.toArray(new Setter[0]));
InstantiatorAndFieldMappers> instantiatorAndFieldMappers =
new InstantiatorAndFieldMappers>(
new ConstructorInjections(Collections.emptyMap(), new FieldMapper[0]),
genericBuilderInstantiator);
FieldMapper[] targetFMappers = merge(targetConstructorFieldMapper.toArray(EMPTY_FIELD_MAPPERS), targetFieldMappers.toArray(EMPTY_FIELD_MAPPERS));
return new GenericBuilderMapping(
genericBuilderInstantiator,
instantiatorAndFieldMappers,
genericBuilderFieldMappers.toArray(EMPTY_FIELD_MAPPERS),
targetFMappers,
keys
);
}
private SourceFieldMapper buildWithGenericBuilder(GenericBuilderMapping gbm) {
SourceFieldMapper> delegate =
DefaultConstantSourceMapperBuilder., K>buildMapper(
gbm.genericBuilderFieldMappers,
gbm.instantiatorAndFieldMappers,
gbm.keys,
(Class>)(Class)GenericBuilder.class,
reflectionService,
mapperSource,
mapperConfig);
return new TransformSourceFieldMapper, T>(delegate, gbm.targetFieldMappers, GenericBuilder.buildFunction());
}
public Type getTargetType() {
return propertyMappingsBuilder.getClassMeta().getType();
}
public List findAllDiscriminatorKeys(final Object discriminatorId) {
final List keys = new ArrayList();
propertyMappingsBuilder.forEachProperties(new ForEachCallBack>() {
@Override
public void handle(PropertyMapping tkPropertyMapping) {
ColumnDefinition columnDefinition = tkPropertyMapping.getColumnDefinition();
if (columnDefinition.has(DiscriminatorColumnProperty.class)) {
DiscriminatorColumnProperty[] properties = columnDefinition.lookForAll(DiscriminatorColumnProperty.class);
for(DiscriminatorColumnProperty p : properties) {
if (MapperConfig.sameDiscriminatorId(discriminatorId , p.getDiscriminatorId()) &&
p.test(getTargetType())) {
keys.add(tkPropertyMapping.getColumnKey());
return;
}
}
}
}
});
return keys;
}
public static class GenericBuilderMapping> {
public final GenericBuildBiInstantiator genericBuilderInstantiator;
public final InstantiatorAndFieldMappers> instantiatorAndFieldMappers;
public final FieldMapper>[] genericBuilderFieldMappers;
public final FieldMapper[] targetFieldMappers;
public final FieldKey[] keys;
public GenericBuilderMapping(
GenericBuildBiInstantiator genericBuilderInstantiator,
InstantiatorAndFieldMappers> instantiatorAndFieldMappers,
FieldMapper>[] genericBuilderFieldMappers,
FieldMapper[] targetFieldMappers,
FieldKey[] keys) {
this.genericBuilderInstantiator = genericBuilderInstantiator;
this.instantiatorAndFieldMappers = instantiatorAndFieldMappers;
this.genericBuilderFieldMappers = genericBuilderFieldMappers;
this.targetFieldMappers = targetFieldMappers;
this.keys = keys;
}
}
private FieldMapper[] merge(FieldMapper[] fieldMappers, FieldMapper[] fields) {
FieldMapper[] f = new FieldMapper[fieldMappers.length + fields.length];
System.arraycopy(fieldMappers, 0, f, 0, fieldMappers.length);
System.arraycopy(fields, 0, f, fieldMappers.length, fields.length);
return f;
}
private BiInstantiator targetInstantiatorFromGenericBuilder(Parameter[] indexMapping, Function[] transformers) {
InstantiatorFactory instantiatorFactory = reflectionService.getInstantiatorFactory();
Map> params = new HashMap>();
for(int i = 0; i < indexMapping.length; i++) {
Parameter parameter = indexMapping[i];
final int builderIndex = i;
final Function transformer = transformers[i];
if (transformer == null) {
params.put(parameter, new DefaultConstantSourceMapperBuilder.TargetFromBuilderParamBiFunction(builderIndex));
} else {
params.put(parameter, new DefaultConstantSourceMapperBuilder.TargetFromBuilderWithTransformBiFunction(transformer, builderIndex));
}
}
BiInstantiator targetInstantiator = instantiatorFactory.getBiInstantiator(getTargetClass(), Object[].class, Object.class,
propertyMappingsBuilder.getPropertyFinder().getEligibleInstantiatorDefinitions(), params, reflectionService.isAsmActivated(), reflectionService.builderIgnoresNullValues());
return targetInstantiator;
}
public static class GenericBuildBiInstantiator implements BiInstantiator, GenericBuilder> {
private final BiInstantiator targetInstantiatorFromGenericBuilder;
private final Setter>[] targetFieldSetters;
private final FieldMapper>[] genericBuilderFieldMappers;
public GenericBuildBiInstantiator(
FieldMapper>[] genericBuilderFieldMappers,
BiInstantiator targetInstantiatorFromGenericBuilder,
Setter>[] targetFieldSetters) {
this.genericBuilderFieldMappers = genericBuilderFieldMappers;
this.targetInstantiatorFromGenericBuilder = targetInstantiatorFromGenericBuilder;
this.targetFieldSetters = targetFieldSetters;
}
@Override
public GenericBuilder newInstance(S o, MappingContext super S> o2) {
return new GenericBuilder(genericBuilderFieldMappers, targetInstantiatorFromGenericBuilder, targetFieldSetters);
}
}
@SuppressWarnings("unchecked")
private SourceFieldMapper builderWithTransformer(final List params, final BuilderInstantiatorDefinition builder) {
final FieldMapper[] fields = targetFieldMappers();
final Method buildMethod = builder.getBuildMethod();
final Class> targetClass = buildMethod.getDeclaringClass();
final Function f = Modifier.isStatic(buildMethod.getModifiers()) ? new StaticMethodFunction(buildMethod) : new MethodFunction(buildMethod);
ConstructorInjections constructorInjections = toConstructorInjections(params);
InstantiatorFactory instantiatorFactory = reflectionService.getInstantiatorFactory();
final BuilderBiInstantiator builderBiInstantiator = instantiatorFactory.builderBiInstantiator(builder, MapperBiInstantiatorFactory.convertToBiInstantiator(constructorInjections.parameterGetterMap), reflectionService.isAsmActivated(), reflectionService.builderIgnoresNullValues());
InstantiatorAndFieldMappers newConstantSourceMapperBuilder =
new InstantiatorAndFieldMappers(constructorInjections, new BiInstantiator() {
@Override
public Object newInstance(Object o, Object o2) throws Exception {
return builderBiInstantiator.newInitialisedBuilderInstace(o, o2);
}
});
SourceFieldMapper delegate = buildMapper(fields, newConstantSourceMapperBuilder, getKeys().toArray(FIELD_KEYS), targetClass, reflectionService, mapperSource, mapperConfig);
return new TransformSourceFieldMapper(delegate, fields, f);
}
public static > SourceFieldMapper buildMapper(
FieldMapper[] fields,
InstantiatorAndFieldMappers constructorFieldMappersAndInstantiator,
FieldKey>[] keys,
Class target,
ReflectionService reflectionService,
MapperSource super S, K> mapperSource,
MapperConfig mapperConfig) {
SourceFieldMapper mapper;
if (reflectionService.isAsmActivated()
&& fields.length + constructorFieldMappersAndInstantiator.constructorInjections.parameterGetterMap.size() < mapperConfig.asmMapperNbFieldsLimit()) {
try {
MapperAsmFactory mapperAsmFactory = reflectionService
.getAsmFactory(target.getClassLoader())
.registerOrCreate(MapperAsmFactory.class,
new UnaryFactory() {
@Override
public MapperAsmFactory newInstance(AsmFactory asmFactory) {
return new MapperAsmFactory(asmFactory);
}
});
mapper =
mapperAsmFactory
.createMapper(
keys,
fields,
constructorFieldMappersAndInstantiator.constructorInjections.fieldMappers,
constructorFieldMappersAndInstantiator.instantiator,
mapperSource.source(),
target);
} catch (Throwable e) {
if (mapperConfig.failOnAsm()) {
return ErrorHelper.rethrow(e);
} else {
mapper = new MapperImpl(fields, constructorFieldMappersAndInstantiator.constructorInjections.fieldMappers, constructorFieldMappersAndInstantiator.instantiator);
}
}
} else {
mapper = new MapperImpl(fields, constructorFieldMappersAndInstantiator.constructorInjections.fieldMappers, constructorFieldMappersAndInstantiator.instantiator);
}
return mapper;
}
@Override
public boolean isRootAggregate() {
return mappingContextFactoryBuilder.isRoot()
&& !mappingContextFactoryBuilder.hasNoDependentKeys();
}
private Class getTargetClass() {
return TypeHelper.toClass(target);
}
private ConstructorInjections toConstructorInjections(List params) throws MapperBuildingException {
Map> injections = new HashMap>();
List> fieldMappers = new ArrayList>();
for(int i = 0; i < params.size(); i++) {
InjectionParam p = params.get(i);
GetterAndFieldMapper getterAndFieldMapper = p.getterAndfieldMapper();
injections.put(p.parameter, getterAndFieldMapper.getter);
if (getterAndFieldMapper.fieldMapper != null) {
fieldMappers.add((FieldMapper) getterAndFieldMapper.fieldMapper);
}
}
return new ConstructorInjections(injections, fieldMappers.toArray(EMPTY_FIELD_MAPPERS));
}
@SuppressWarnings("unchecked")
private InstantiatorAndFieldMappers getConstructorFieldMappersAndInstantiator(ConstructorInjections constructorInjections) throws MapperBuildingException {
InstantiatorFactory instantiatorFactory = reflectionService.getInstantiatorFactory();
try {
Map> injections = constructorInjections.parameterGetterMap;
MapperBiInstantiatorFactory mapperBiInstantiatorFactory = new MapperBiInstantiatorFactory(instantiatorFactory);
ContextualGetterFactory super S, K> getterFactory = fieldMapperAsGetterFactory();
BiInstantiator, T> instantiator =
mapperBiInstantiatorFactory.
getBiInstantiator(mapperSource.source(), target, propertyMappingsBuilder, injections, getterFactory, reflectionService.builderIgnoresNullValues(), mappingContextFactoryBuilder);
return new InstantiatorAndFieldMappers(constructorInjections, instantiator);
} catch(Exception e) {
return ErrorHelper.rethrow(e);
}
}
private ContextualGetterFactory super S, K> fieldMapperAsGetterFactory() {
return new FieldMapperFactoryGetterFactoryAdapter(mapperConfig.fieldMapperErrorHandler());
}
@SuppressWarnings("unchecked")
/**
* Build the list of constructor prop and fieldmappers
*/
private List constructorInjections() {
final List injectionParams = new ArrayList();
final Set parameters = new HashSet();
propertyMappingsBuilder.forEachConstructorProperties(new ForEachCallBack>() {
@SuppressWarnings("unchecked")
@Override
public void handle(PropertyMapping propertyMapping) {
if (!isTargetForMapperFieldMapper(propertyMapping) && ! propertyMapping.getPropertyMeta().isNonMapped()) {
PropertyMeta pm = propertyMapping.getPropertyMeta();
ConstructorPropertyMeta cProp = (ConstructorPropertyMeta) pm;
injectionParams.add(new ConstructorParam(cProp.getParameter(), cProp, propertyMapping));
parameters.add(cProp.getParameter());
}
}
});
for(PropertyPerOwner e :
getSubPropertyPerOwner()) {
if (e.owner.isConstructorProperty()) {
ConstructorPropertyMeta meta = (ConstructorPropertyMeta) e.owner;
// ignore if no mapped properties
if (hasMappedProperties(e.propertyMappings)) {
injectionParams.add(new SubPropertyParam(meta.getParameter(), meta, e.propertyMappings, this));
parameters.add(meta.getParameter());
}
}
}
addContextParam(injectionParams, parameters);
return injectionParams;
}
private boolean hasMappedProperties(List> propertyMappings) {
for(PropertyMapping pm : propertyMappings) {
if (!pm.getPropertyMeta().isNonMapped()) return true;
}
return false;
}
private void addContextParam(List injectionParams, Set parameters) {
Parameter mappingContext = null;
for(InstantiatorDefinition id : propertyMappingsBuilder.getPropertyFinder().getEligibleInstantiatorDefinitions()) {
for(Parameter p : id.getParameters()) {
if (TypeHelper.areEquals(p.getType(), Context.class) && ! parameters.contains(p)) {
if (mappingContext != null && ! p.equals(mappingContext)) {
// multiple context ignore to avoid constructor selection issue
return;
}
mappingContext = p;
}
}
}
if (mappingContext != null) {
injectionParams.add(new ContextParam(mappingContext, null));
}
}
private SourceMapper getterPropertyMapper(PropertyMeta owner, PropertyMapping propertyMapping) {
PropertyMeta pm = propertyMapping.getPropertyMeta();
final ContextualGetter super S, P> getter =
(ContextualGetter super S, P>) fieldMapperFactory.getGetterFromSource(propertyMapping.getColumnKey(), pm.getPropertyType(), propertyMapping.getColumnDefinition(), pm.getPropertyClassMetaSupplier(), mappingContextFactoryBuilder);
return new GetterMapper(getter);
}
private MappingContextFactoryBuilder getMapperContextFactoryBuilder(PropertyMeta, ?> owner, List> properties) {
final List> subKeys = getSubKeys(properties);
final List> inferNullColumns = getInferNulls(properties);
return mappingContextFactoryBuilder.newBuilder(subKeys, inferNullColumns, owner);
}
@SuppressWarnings("unchecked")
private FieldMapper newMapperFieldMapper(List> properties, PropertyMeta meta, SourceMapper mapper, MappingContextFactoryBuilder mappingContextFactoryBuilder) {
return newMapperFieldMapper(properties, (Setter) meta.getSetter(), mapper, mappingContextFactoryBuilder);
}
private FieldMapper newMapperFieldMapper(List> properties, Setter setter, SourceMapper mapper, MappingContextFactoryBuilder mappingContextFactoryBuilder) {
final MapperFieldMapper fieldMapper =
new MapperFieldMapper(mapper,
(Setter)setter,
mappingContextFactoryBuilder.nullChecker(),
mappingContextFactoryBuilder.currentIndex());
return wrapFieldMapperWithErrorHandler(properties.get(0).getColumnKey(), fieldMapper);
}
@SuppressWarnings("unchecked")
private ContextualGetter newMapperGetterAdapter(SourceMapper mapper, MappingContextFactoryBuilder builder) {
return new MapperFieldMapperGetterAdapter((SourceMapper)mapper, builder.nullChecker(), builder.currentIndex());
}
// call use towards sub jdbcMapper
// the keys are initialised
protected
void addMapping(K columnKey, ColumnDefinition columnDefinition, PropertyMeta prop) {
propertyMappingsBuilder.addProperty(columnKey, columnDefinition, prop);
}
private FieldMapper[] targetFieldMappers() {
List fields = fields();
FieldMapper[] fieldMappers = new FieldMapper[fields.size()];
for(int i = 0; i < fields.size(); i++) {
fieldMappers[i] = fields.get(i).targetFieldMapper();
}
return fieldMappers;
}
@SuppressWarnings("unchecked")
private List fields() {
final List fields = new ArrayList();
propertyMappingsBuilder.forEachProperties(new ForEachCallBack>() {
@Override
public void handle(PropertyMapping t) {
if (t == null || isTargetForMapperFieldMapper(t)) return;
PropertyMeta meta = t.getPropertyMeta();
if (meta == null || (meta instanceof SelfPropertyMeta)) return;
if (!meta.isConstructorProperty() && !isTargetForMapperFieldMapper(t) && !meta.isNonMapped()) {
fields.add(new PropertyFieldMeta(t));
}
}
});
List subPropertyPerOwner = getSubPropertyPerOwner();
for(PropertyPerOwner e : subPropertyPerOwner) {
if (!e.owner.isConstructorProperty()) {
List> propertyMappings = filterNonMappedAndCompress(e.propertyMappings);
if (propertyMappings.isEmpty()) { // non mapped property
continue; // ignore no actual prop
}
final SourceMapper mapper;
final MappingContextFactoryBuilder currentBuilder = getMapperContextFactoryBuilder(e.owner, e.propertyMappings);
if (propertyMappings.size() == 1 && JoinUtils.isArrayElement(propertyMappings.get(0).getPropertyMeta())) {
mapper = getterPropertyMapper(e.owner, propertyMappings.get(0));
} else {
mapper = subPropertyMapper(e.owner, e.propertyMappings, currentBuilder);
}
fields.add(new SubPropertyFieldMeta(mapper, e.propertyMappings, e.owner, currentBuilder));
}
}
for(FieldMapper mapper : additionalMappers) {
fields.add(new FieldMapperFieldMeta(mapper));
}
return fields;
}
private List> filterNonMappedAndCompress(List> propertyMappings) {
ArrayList> filtered = new ArrayList>(propertyMappings);
ListIterator> iterator = filtered.listIterator();
while(iterator.hasNext()) {
PropertyMapping pm = iterator.next();
if (pm.getPropertyMeta().isNonMapped()) {
iterator.remove();
} else {
iterator.set(pm.compressSubSelf());
}
}
return filtered;
}
@Override
public MappingContextFactory super S> contextFactory() {
return mappingContextFactoryBuilder.build();
}
private static class MethodFunction implements Function {
private final Method buildMethod;
public MethodFunction(Method buildMethod) {
this.buildMethod = buildMethod;
}
@Override
public Object apply(Object o) {
try {
return buildMethod.invoke(o);
} catch (Exception e) {
return ErrorHelper.rethrow(e);
}
}
}
private static class StaticMethodFunction implements Function {
private final Method buildMethod;
public StaticMethodFunction(Method buildMethod) {
this.buildMethod = buildMethod;
}
@Override
public Object apply(Object o) {
try {
return buildMethod.invoke(null, o);
} catch (Exception e) {
return ErrorHelper.rethrow(e);
}
}
}
class FieldGenericBuilderInfo {
final FieldMapper targetFieldMapper;
final FieldMapper> fieldMapperGeneric;
final Setter> fieldSetter;
FieldGenericBuilderInfo(FieldMapper targetFieldMapper, FieldMapper> fieldMapperGeneric, Setter> fieldSetter) {
this.targetFieldMapper = targetFieldMapper;
this.fieldMapperGeneric = fieldMapperGeneric;
this.fieldSetter = fieldSetter;
}
}
abstract class FieldMeta {
abstract FieldMapper targetFieldMapper();
public abstract FieldGenericBuilderInfo fieldGenericBuilderInfo(int index);
}
class PropertyFieldMeta extends FieldMeta {
final PropertyMapping propertyMapping;
PropertyFieldMeta(PropertyMapping propertyMapping) {
this.propertyMapping = propertyMapping;
}
public FieldMapper targetFieldMapper() {
return newFieldMapper(propertyMapping);
}
@Override
public FieldGenericBuilderInfo fieldGenericBuilderInfo(final int index) {
final Setter setter = propertyMapping.getPropertyMeta().getSetter();
final ContextualGetter super S, ?> getter = fieldMapperFactory.getGetterFromSource(
propertyMapping.getColumnKey(),
propertyMapping.getPropertyMeta().getPropertyType(),
propertyMapping.getColumnDefinition(),
propertyMapping.getPropertyMeta().getPropertyClassMetaSupplier(), mappingContextFactoryBuilder);
return new FieldGenericBuilderInfo(targetFieldMapper(), new FieldMapper>() {
@Override
public void mapTo(S source, GenericBuilder target, MappingContext super S> context) throws Exception {
target.objects[index] = getter.get(source, context);
}
}, new Setter>() {
@Override
public void set(T target, GenericBuilder value) throws Exception {
setter.set(target, value.objects[index]);
}
});
}
}
class SubPropertyFieldMeta extends FieldMeta {
final SourceMapper mapper;
final List> propertyMappings;
final PropertyMeta owner;
final MappingContextFactoryBuilder currentBuilder;
SubPropertyFieldMeta(SourceMapper mapper, List> propertyMappings, PropertyMeta owner, MappingContextFactoryBuilder currentBuilder) {
this.mapper = mapper;
this.propertyMappings = propertyMappings;
this.owner = owner;
this.currentBuilder = currentBuilder;
}
@Override
FieldMapper targetFieldMapper() {
return newMapperFieldMapper(propertyMappings, owner, mapper, currentBuilder);
}
@Override
public FieldGenericBuilderInfo fieldGenericBuilderInfo(final int index) {
final Setter setter = owner.getSetter();
return new FieldGenericBuilderInfo(
targetFieldMapper(),
(FieldMapper>) newMapperFieldMapper(
propertyMappings,
new Setter() {
@Override
public void set(Object target, Object value) throws Exception {
GenericBuilder genericBuilder = (GenericBuilder) target;
genericBuilder.objects[index] = value;
}
}, mapper, currentBuilder),
new Setter>() {
@Override
public void set(T target, GenericBuilder value) throws Exception {
setter.set(target, value.objects[index]);
}
});
}
}
class FieldMapperFieldMeta extends FieldMeta {
final FieldMapper fieldMapper;
FieldMapperFieldMeta(FieldMapper fieldMapper) {
this.fieldMapper = fieldMapper;
}
@Override
FieldMapper targetFieldMapper() {
return fieldMapper;
}
@Override
public FieldGenericBuilderInfo fieldGenericBuilderInfo(int index) {
throw new UnsupportedOperationException();
}
}
private boolean isTargetForMapperFieldMapper(PropertyMapping pm) {
return
pm.getPropertyMeta().isSubProperty() || (JoinUtils.isArrayElement(pm.getPropertyMeta()) && isKeyOrHasKey(pm));
}
private boolean isKeyOrHasKey(final PropertyMapping pm) {
if (pm.getColumnDefinition().isInferNull()) return true;
// looked for non mapped property with same owner
return propertyMappingsBuilder.forEachProperties(new ForEachCallBack>() {
boolean hasKey;
@Override
public void handle(PropertyMapping tkPropertyMapping) {
if (tkPropertyMapping.getPropertyMeta().isSubProperty()) {
SubPropertyMeta subPropertyMeta = (SubPropertyMeta) tkPropertyMapping.getPropertyMeta();
if (subPropertyMeta.getOwnerProperty().equals(pm.getPropertyMeta())) {
hasKey |= tkPropertyMapping.getColumnDefinition().isInferNull();
}
}
}
}).hasKey;
}
private List getSubPropertyPerOwner() {
final List subPropertiesList = new ArrayList();
propertyMappingsBuilder.forEachProperties(new ForEachCallBack>() {
@SuppressWarnings("unchecked")
@Override
public void handle(PropertyMapping t) {
if (t == null) return;
PropertyMeta meta = t.getPropertyMeta();
if (meta == null) return;
if (isTargetForMapperFieldMapper(t)) {
addSubProperty(t, meta, t.getColumnKey());
}
}
private void addSubProperty(PropertyMapping