All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.simpleflatmapper.map.mapper.AbstractConstantTargetMapperBuilder Maven / Gradle / Ivy

Go to download

Java library to map flat record - ResultSet, csv - to java object with minimum configuration and low footprint.

There is a newer version: 9.0.2
Show newest version
package org.simpleflatmapper.map.mapper;


import org.simpleflatmapper.map.FieldKey;
import org.simpleflatmapper.map.FieldMapper;
import org.simpleflatmapper.map.MapperConfig;
import org.simpleflatmapper.map.MappingContext;
import org.simpleflatmapper.map.PropertyWithGetter;
import org.simpleflatmapper.map.asm.MapperAsmFactory;
import org.simpleflatmapper.map.property.FieldMapperColumnDefinition;
import org.simpleflatmapper.map.property.ConstantValueProperty;
import org.simpleflatmapper.map.context.KeySourceGetter;
import org.simpleflatmapper.map.context.MappingContextFactoryBuilder;
import org.simpleflatmapper.reflect.BiInstantiator;
import org.simpleflatmapper.reflect.ReflectionService;
import org.simpleflatmapper.reflect.ScoredGetter;
import org.simpleflatmapper.reflect.asm.AsmFactory;
import org.simpleflatmapper.reflect.getter.ConstantGetter;
import org.simpleflatmapper.reflect.meta.ClassMeta;
import org.simpleflatmapper.reflect.meta.ObjectPropertyMeta;
import org.simpleflatmapper.reflect.meta.PropertyMeta;
import org.simpleflatmapper.util.ErrorHelper;
import org.simpleflatmapper.util.ForEachCallBack;
import org.simpleflatmapper.util.Predicate;
import org.simpleflatmapper.util.TypeHelper;
import org.simpleflatmapper.util.UnaryFactory;

import java.util.ArrayList;
import java.util.List;

public abstract class AbstractConstantTargetMapperBuilder, B extends AbstractConstantTargetMapperBuilder> {

    private static KeySourceGetter KEY_SOURCE_GETTER = new KeySourceGetter() {
        @Override
        public Object getValue(Object key, Object source) throws Exception {
            throw new UnsupportedOperationException();
        }
    };
    
    private final ReflectionService reflectionService;
    protected final MapperConfig mapperConfig;

    protected final PropertyMappingsBuilder propertyMappingsBuilder;

    protected final ConstantTargetFieldMapperFactory fieldAppenderFactory;
    protected final ClassMeta classMeta;
    private final Class sourceClass;

    private int currentIndex = getStartingIndex();

    public AbstractConstantTargetMapperBuilder(
            ClassMeta classMeta,
            Class sourceClass, MapperConfig mapperConfig,
            ConstantTargetFieldMapperFactory fieldAppenderFactory) {
        this.sourceClass = sourceClass;
        this.fieldAppenderFactory = fieldAppenderFactory;
        this.reflectionService = classMeta.getReflectionService();
        this.mapperConfig = mapperConfig;
        this.propertyMappingsBuilder =
                PropertyMappingsBuilder.of(classMeta, mapperConfig, new PropertyMappingsBuilder.PropertyPredicateFactory() {
                    @Override
                    public Predicate> predicate(K k, Object[] objects, List accessorNotFounds) {
                        return PropertyWithGetter.INSTANCE;
                    }
                });
        this.classMeta = classMeta;
    }

    public B addColumn(String column) {
        return addColumn(column, FieldMapperColumnDefinition.identity());

    }

    public B addColumn(String column, Object... properties) {
        FieldMapperColumnDefinition columnDefinition = FieldMapperColumnDefinition.of(properties);
        return addColumn(newKey(column, currentIndex++, columnDefinition), columnDefinition);
    }

    public B addColumn(K key, Object... properties) {
        return addColumn(key, FieldMapperColumnDefinition.identity().add(properties));
    }

    public B addColumn(String column,  FieldMapperColumnDefinition columnDefinition) {
        return addColumn(newKey(column, currentIndex++, columnDefinition), columnDefinition);
    }

    @SuppressWarnings("unchecked")
    public B addColumn(K key,   FieldMapperColumnDefinition columnDefinition) {
        final FieldMapperColumnDefinition composedDefinition = columnDefinition.compose(mapperConfig.columnDefinitions().getColumnDefinition(key));
        final K mappedColumnKey = composedDefinition.rename(key);

        if (composedDefinition.has(ConstantValueProperty.class)) {
            ConstantValueProperty staticValueProperty = composedDefinition.lookFor(ConstantValueProperty.class);
            PropertyMeta meta = new ObjectPropertyMeta(key.getName(), classMeta.getType(), reflectionService, staticValueProperty.getType(), ScoredGetter.of(new ConstantGetter(staticValueProperty.getValue()), 1), null, null);
            propertyMappingsBuilder.addProperty(key, columnDefinition, meta);
        } else {
            propertyMappingsBuilder.addProperty(mappedColumnKey, composedDefinition);
        }
        return (B) this;
    }

    @SuppressWarnings("unchecked")
    public ContextualSourceFieldMapperImpl mapper() {

        final List> mappers = new ArrayList>();


        final MappingContextFactoryBuilder mappingContextFactoryBuilder = new MappingContextFactoryBuilder(keySourceGetter(), !mapperConfig.unorderedJoin());

        propertyMappingsBuilder.forEachProperties(
                new ForEachCallBack>() {
                    @Override
                    public void handle(PropertyMapping pm) {
                        preFieldProcess(mappers, pm);
                        FieldMapper fieldMapper =
                                fieldAppenderFactory.newFieldMapper(
                                        pm,
                                        mappingContextFactoryBuilder,
                                        mapperConfig.mapperBuilderErrorHandler());
                        mappers.add(fieldMapper);
                        postFieldProcess(mappers, pm);
                    }
                }
        );
        postMapperProcess(mappers);


        AbstractMapper mapper;
        FieldMapper[] fields = mappers.toArray(new FieldMapper[0]);
        BiInstantiator, S> instantiator = getInstantiator();
        if (mappers.size() < 256) {
            try {
                mapper =
                        reflectionService
                                .getAsmFactory()
                                .registerOrCreate(MapperAsmFactory.class, new UnaryFactory() {
                                    @Override
                                    public MapperAsmFactory newInstance(AsmFactory asmFactory) {
                                        return new MapperAsmFactory(asmFactory);
                                    }
                                })
                                .createMapper(
                                        getKeys(),
                                        fields,
                                        new FieldMapper[0],
                                        instantiator,
                                        TypeHelper.toClass(classMeta.getType()),
                                        sourceClass
                                );
            } catch (Throwable e) {
                if (mapperConfig.failOnAsm()) {
                    return ErrorHelper.rethrow(e);
                } else {
                    mapper = new MapperImpl(fields, new FieldMapper[0], instantiator);
                }
            }

        } else {
            mapper = new MapperImpl(
                    fields,
                    new FieldMapper[0],
                    instantiator);
        }

        return new ContextualSourceFieldMapperImpl(mappingContextFactoryBuilder.build(), mapper);
    }

    protected void postMapperProcess(List> mappers) {
        // override
    }

    protected void postFieldProcess(List> mappers, PropertyMapping pm) {
        // override
    }

    protected void preFieldProcess(List> mappers, PropertyMapping pm) {
        // override
    }

    protected int getStartingIndex() {
        return 0;
    }

    protected abstract BiInstantiator, S> getInstantiator();

    protected abstract K newKey(String column, int i, FieldMapperColumnDefinition columnDefinition);

    private FieldKey[] getKeys() {
        return propertyMappingsBuilder.getKeys().toArray(new FieldKey[0]);
    }

    protected KeySourceGetter keySourceGetter() {
        return KEY_SOURCE_GETTER;
    }


}