org.simpleflatmapper.map.mapper.DiscriminatorConstantSourceMapperBuilder Maven / Gradle / Ivy
Show all versions of sfm-map Show documentation
package org.simpleflatmapper.map.mapper;
import org.simpleflatmapper.map.FieldKey;
import org.simpleflatmapper.map.FieldMapper;
import org.simpleflatmapper.map.MapperBuilderErrorHandler;
import org.simpleflatmapper.map.MapperBuildingException;
import org.simpleflatmapper.map.MapperConfig;
import org.simpleflatmapper.map.MappingContext;
import org.simpleflatmapper.map.SourceFieldMapper;
import org.simpleflatmapper.map.context.MappingContextFactory;
import org.simpleflatmapper.map.context.MappingContextFactoryBuilder;
import org.simpleflatmapper.map.impl.DiscriminatorPropertyFinder;
import org.simpleflatmapper.map.property.OptionalProperty;
import org.simpleflatmapper.reflect.BiInstantiator;
import org.simpleflatmapper.reflect.Getter;
import org.simpleflatmapper.reflect.meta.ClassMeta;
import org.simpleflatmapper.reflect.meta.PropertyFinder;
import org.simpleflatmapper.reflect.meta.PropertyMeta;
import org.simpleflatmapper.util.BiConsumer;
import org.simpleflatmapper.util.EqualsPredicate;
import org.simpleflatmapper.util.ForEachCallBack;
import org.simpleflatmapper.util.Predicate;
import org.simpleflatmapper.util.TypeHelper;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
public class DiscriminatorConstantSourceMapperBuilder> extends ConstantSourceMapperBuilder {
private final DiscriminatedBuilder[] builders;
private final MappingContextFactoryBuilder mappingContextFactoryBuilder;
private final CaptureError mapperBuilderErrorHandler;
private final MapperConfig mapperConfig;
@SuppressWarnings("unchecked")
public DiscriminatorConstantSourceMapperBuilder(
MapperConfig.Discriminator super S, T> discriminator,
final MapperSource super S, K> mapperSource,
final ClassMeta classMeta,
final MapperConfig mapperConfig,
MappingContextFactoryBuilder mappingContextFactoryBuilder,
KeyFactory keyFactory,
PropertyFinder propertyFinder) throws MapperBuildingException {
this.mappingContextFactoryBuilder = mappingContextFactoryBuilder;
this.mapperConfig = mapperConfig;
builders = new DiscriminatedBuilder[discriminator.cases.length];
mapperBuilderErrorHandler = new CaptureError(mapperConfig.mapperBuilderErrorHandler(), builders.length);
MapperConfig kMapperConfig = mapperConfig.mapperBuilderErrorHandler(mapperBuilderErrorHandler);
for(int i = 0; i < discriminator.cases.length; i++) {
MapperConfig.DiscriminatorCase super S, ? extends T> discriminatorCase = discriminator.cases[i];
PropertyFinder subPropertyFinder = propertyFinder;
if (propertyFinder instanceof DiscriminatorPropertyFinder) {
subPropertyFinder = ((DiscriminatorPropertyFinder)subPropertyFinder).getImplementationPropertyFinder(discriminatorCase.classMeta.getType());
}
builders[i] = getDiscriminatedBuilder(mapperSource, mappingContextFactoryBuilder, keyFactory, subPropertyFinder, kMapperConfig, discriminatorCase, classMeta);
}
}
private DiscriminatedBuilder getDiscriminatedBuilder(MapperSource super S, K> mapperSource, MappingContextFactoryBuilder mappingContextFactoryBuilder, KeyFactory keyFactory, PropertyFinder propertyFinder, MapperConfig kMapperConfig, MapperConfig.DiscriminatorCase super S, ? extends T> discrimnatorCase, ClassMeta commonClassMeta) {
return new DiscriminatedBuilder((MapperConfig.DiscriminatorCase super S, T>) discrimnatorCase,
new DefaultConstantSourceMapperBuilder(mapperSource, (ClassMeta) discrimnatorCase.classMeta.withReflectionService(commonClassMeta.getReflectionService()), kMapperConfig, mappingContextFactoryBuilder, keyFactory, propertyFinder));
}
@Override
public ConstantSourceMapperBuilder addMapping(K key, ColumnDefinition columnDefinition) {
for(DiscriminatedBuilder builder : builders) {
builder.builder.addMapping(key, columnDefinition);
}
final ColumnDefinition composedDefinition = columnDefinition.compose(mapperConfig.columnDefinitions().getColumnDefinition(key));
mapperBuilderErrorHandler.successfullyMapAtLeastToOne(composedDefinition);
return this;
}
@Override
protected void addMapping(final K columnKey, final ColumnDefinition columnDefinition, final PropertyMeta prop) {
if (prop instanceof DiscriminatorPropertyFinder.DiscriminatorPropertyMeta) {
DiscriminatorPropertyFinder.DiscriminatorPropertyMeta pm = (DiscriminatorPropertyFinder.DiscriminatorPropertyMeta) prop;
pm.forEachProperty(new BiConsumer>() {
@Override
public void accept(Type type, PropertyMeta, ?> propertyMeta) {
getBuilder(type).addMapping(columnKey, columnDefinition, propertyMeta);
}
});
} else {
for (DiscriminatedBuilder builder : builders) {
builder.builder.addMapping(columnKey, columnDefinition, prop);
}
}
}
private ConstantSourceMapperBuilder getBuilder(Type type) {
for (DiscriminatedBuilder builder : builders) {
if (TypeHelper.areEquals(builder.builder.getTargetType(), type)) {
return builder.builder;
}
}
throw new IllegalArgumentException("Unknown type " + type);
}
@Override
public List getKeys() {
HashSet keys = new HashSet();
for(DiscriminatedBuilder builder : builders) {
keys.addAll(builder.builder.getKeys());
}
return new ArrayList(keys);
}
@Override
public >> H forEachProperties(H handler) {
for(DiscriminatedBuilder builder : builders) {
builder.builder.forEachProperties(handler);
}
return handler;
}
@Override
public ContextualSourceFieldMapperImpl mapper() {
SourceFieldMapper mapper = sourceFieldMapper();
return new ContextualSourceFieldMapperImpl(mappingContextFactoryBuilder.build(), mapper);
}
@SuppressWarnings("unchecked")
@Override
public SourceFieldMapper sourceFieldMapper() {
PredicatedInstantiator[] predicatedInstantiator = new PredicatedInstantiator[builders.length];
List> fieldMappers = new ArrayList>();
for(int i = 0; i < builders.length; i++) {
DiscriminatedBuilder builder = builders[i];
final Predicate super S> predicate = builder.discrimnatorCase.predicate;
DefaultConstantSourceMapperBuilder.GenericBuilderMapping genericBuilderMapping = builder.builder.getGenericBuilderMapping();
predicatedInstantiator[i] = new PredicatedInstantiator(predicate, genericBuilderMapping.genericBuilderInstantiator);
final FieldMapper[] targetFieldMappers = genericBuilderMapping.targetFieldMappers;
fieldMappers.add(new FieldMapper() {
@Override
public void mapTo(S source, T target, MappingContext super S> context) throws Exception {
if (predicate.test(source)) {
for(FieldMapper fm : targetFieldMappers) {
fm.mapTo(source, target, context);
}
}
}
});
}
boolean oneColumn = isOneColumn(predicatedInstantiator);
BiInstantiator, GenericBuilder> gbi =
oneColumn ?
new OneColumnBuildBiInstantiator(predicatedInstantiator) :
new GenericBuildBiInstantiator(predicatedInstantiator);
DiscriminatorGenericBuilderMapper mapper = new DiscriminatorGenericBuilderMapper(gbi);
FieldMapper[] targetFieldMappers = fieldMappers.toArray(new FieldMapper[0]);
//
return new TransformSourceFieldMapper, T>(mapper, targetFieldMappers, GenericBuilder.buildFunction());
}
private boolean isOneColumn(PredicatedInstantiator[] predicatedInstantiator) {
Getter getter = null;
for(PredicatedInstantiator pi : predicatedInstantiator) {
if (!(pi.predicate instanceof AbstractMapperFactory.DiscriminatorConditionBuilder.SourcePredicate)) {
return false;
}
AbstractMapperFactory.DiscriminatorConditionBuilder.SourcePredicate sp = (AbstractMapperFactory.DiscriminatorConditionBuilder.SourcePredicate) pi.predicate;
Getter lg = sp.getter;
if (getter == null) {
getter = lg;
} else if (getter != lg) return false;
if (!(sp.predicate instanceof EqualsPredicate)) return false;
}
return true;
}
@Override
public boolean isRootAggregate() {
return builders[0].builder.isRootAggregate();
}
@Override
public MappingContextFactory super S> contextFactory() {
return builders[0].builder.contextFactory();
}
@Override
public void addMapper(FieldMapper mapper) {
for(DiscriminatedBuilder builder : builders) {
builder.builder.addMapper(mapper);
}
}
private static class DiscriminatedBuilder> {
private final MapperConfig.DiscriminatorCase super S, T> discrimnatorCase;
private final DefaultConstantSourceMapperBuilder builder;
private DiscriminatedBuilder(MapperConfig.DiscriminatorCase super S, T> discrimnatorCase, DefaultConstantSourceMapperBuilder builder) {
this.discrimnatorCase = discrimnatorCase;
this.builder = builder;
}
}
private static class GenericBuildBiInstantiator implements BiInstantiator, GenericBuilder> {
private final PredicatedInstantiator[] predicatedInstantiators;
public GenericBuildBiInstantiator(PredicatedInstantiator[] predicatedInstantiators) {
this.predicatedInstantiators = predicatedInstantiators;
}
@SuppressWarnings("unchecked")
@Override
public GenericBuilder newInstance(S o, MappingContext super S> o2) throws Exception {
for(PredicatedInstantiator pi : predicatedInstantiators) {
//noinspection unchecked
if (pi.predicate.test(o)) {
return pi.instantiator.newInstance(o, o2);
}
}
throw new IllegalArgumentException("No discrimator matched " + o);
}
}
private static class OneColumnBuildBiInstantiator implements BiInstantiator, GenericBuilder> {
private final Getter getter;
private final Map