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

org.sfm.map.impl.AbstractFieldMapperMapperBuilder Maven / Gradle / Ivy

package org.sfm.map.impl;

import org.sfm.jdbc.impl.getter.MapperGetterAdapter;
import org.sfm.map.*;
import org.sfm.map.impl.fieldmapper.MapperFieldMapper;
import org.sfm.reflect.*;
import org.sfm.reflect.impl.NullGetter;
import org.sfm.reflect.meta.*;
import org.sfm.tuples.Tuple2;
import org.sfm.utils.ErrorHelper;
import org.sfm.utils.ForEachCallBack;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public abstract class AbstractFieldMapperMapperBuilder>  {

	private final Type source;
	private final Type target;

	private final FieldMapperFactory> fieldMapperFactory;
	private final GetterFactory getterFactory;

	protected final PropertyMappingsBuilder> propertyMappingsBuilder;
	protected final ReflectionService reflectionService;
	
	protected final ColumnDefinitionProvider, K> columnDefinitions;
	private final List> additionalMappers = new ArrayList>();
	protected final PropertyNameMatcherFactory propertyNameMatcherFactory;

	protected final MapperBuilderErrorHandler mapperBuilderErrorHandler;
	private FieldMapperErrorHandler fieldMapperErrorHandler;
    protected final MappingContextFactoryBuilder mappingContextFactoryBuilder;

    public AbstractFieldMapperMapperBuilder(final Type source,
                                            final ClassMeta classMeta,
                                            GetterFactory getterFactory,
                                            FieldMapperFactory> fieldMapperFactory,
                                            ColumnDefinitionProvider, K> columnDefinitions,
                                            PropertyNameMatcherFactory propertyNameMatcherFactory,
                                            MapperBuilderErrorHandler mapperBuilderErrorHandler, MappingContextFactoryBuilder mappingContextFactoryBuilder) throws MapperBuildingException {
        this.mappingContextFactoryBuilder = mappingContextFactoryBuilder;
        if (source == null) {
			throw new NullPointerException("source is null");
		}
		if (classMeta == null) {
			throw new NullPointerException("classMeta is null");
		}
		if (getterFactory == null) {
			throw new NullPointerException("getterFactory is null");
		}
		if (fieldMapperFactory == null) {
			throw new NullPointerException("fieldMapperFactory is null");
		}
		if (columnDefinitions == null) {
			throw new NullPointerException("columnDefinitions is null");
		}
		if (propertyNameMatcherFactory == null) {
			throw new NullPointerException("propertyNameMatcherFactory is null");
		}
		if (mapperBuilderErrorHandler == null) {
			throw new NullPointerException("mapperBuilderErrorHandler is null");
		}
		this.source = source;
		this.getterFactory = getterFactory;
		this.fieldMapperFactory = fieldMapperFactory;
		this.propertyMappingsBuilder = new PropertyMappingsBuilder>(classMeta, propertyNameMatcherFactory, mapperBuilderErrorHandler);
		this.propertyNameMatcherFactory = propertyNameMatcherFactory;
		this.target = classMeta.getType();
		this.reflectionService = classMeta.getReflectionService();
		this.columnDefinitions = columnDefinitions;
		this.mapperBuilderErrorHandler = mapperBuilderErrorHandler;

	}

	protected Class getTargetClass() {
		return TypeHelper.toClass(target);
	}

	@SuppressWarnings("unchecked")
	protected Tuple2[], Instantiator> getConstructorFieldMappersAndInstantiator() throws MapperBuildingException {

		InstantiatorFactory instantiatorFactory = reflectionService.getInstantiatorFactory();
		try {
            Tuple2>, FieldMapper[]> constructorInjections = constructorInjections();
            Map> injections = constructorInjections.first();
            Instantiator instantiator = instantiatorFactory.getInstantiator(source, target, propertyMappingsBuilder, injections, getterFactory);
            return new Tuple2[], Instantiator>(constructorInjections.second(), instantiator);
		} catch(Exception e) {
            return ErrorHelper.rethrow(e);
		}
	}

	@SuppressWarnings("unchecked")
    private Tuple2>, FieldMapper[]> constructorInjections() {
		final Map> injections = new HashMap>();
		final List> fieldMappers = new ArrayList>();
		propertyMappingsBuilder.forEachConstructorProperties(new ForEachCallBack>>() {
			@SuppressWarnings("unchecked")
			@Override
			public void handle(PropertyMapping> t) {
				PropertyMeta pm  = t.getPropertyMeta();
                ConstructorPropertyMeta cProp = (ConstructorPropertyMeta) pm;
                Parameter parameter = cProp.getParameter();
                injections.put(parameter, getterFor(t, parameter.getGenericType()));
			}
		});

        for(Tuple2, List>>> e :
                getSubPropertyPerOwner()) {
            if (e.first().isConstructorProperty()) {
                final List>> properties = e.second();

                final MappingContextFactoryBuilder currentBuilder = getMapperContextFactoryBuilder(e.first(), properties);

                final Mapper mapper = subPropertyMapper(e.first(), properties, currentBuilder);

                ConstructorPropertyMeta meta = (ConstructorPropertyMeta) e.first();

                injections.put(meta.getParameter(), newMapperGetterAdapter(mapper, currentBuilder));
                fieldMappers.add(newMapperFieldMapper(properties, meta, mapper, currentBuilder));
            }
        }
		return new Tuple2>, FieldMapper[]>(injections, fieldMappers.toArray(new FieldMapper[0]));
	}

    private MappingContextFactoryBuilder getMapperContextFactoryBuilder(PropertyMeta owner, List>> properties) {
        final List subKeys = getSubKeys(properties);
        return mappingContextFactoryBuilder.newBuilder(subKeys, owner);
    }

    @SuppressWarnings("unchecked")
    private 

FieldMapper newMapperFieldMapper(List>> properties, PropertyMeta meta, Mapper mapper, MappingContextFactoryBuilder mappingContextFactoryBuilder) { final Getter getter = (Getter) meta.getGetter(); if (mappingContextFactoryBuilder.isEmpty() && getter instanceof NullGetter) { throw new MapperBuildingException("Cannot get a getter on " + meta + " needed to work with join " + mappingContextFactoryBuilder); } final MapperFieldMapper fieldMapper = new MapperFieldMapper((Mapper) mapper, (Setter) meta.getSetter(), getter, mappingContextFactoryBuilder.nullChecker(), mappingContextFactoryBuilder.breakDetectorGetter()); if (fieldMapperErrorHandler != null) { return new FieldErrorHandlerMapper(properties.get(0).getColumnKey(), fieldMapper, fieldMapperErrorHandler); } else { return fieldMapper; } } @SuppressWarnings("unchecked") private

Getter newMapperGetterAdapter(Mapper mapper, MappingContextFactoryBuilder builder) { return new MapperGetterAdapter((Mapper)mapper, builder.nullChecker()); } @SuppressWarnings("unchecked") protected void _addMapping(K key, final FieldMapperColumnDefinition columnDefinition) { final FieldMapperColumnDefinition composedDefinition = FieldMapperColumnDefinition.compose(columnDefinition, columnDefinitions.getColumnDefinition(key)); final K mappedColumnKey = composedDefinition.rename(key); if (columnDefinition.getCustomFieldMapper() != null) { _addMapper((FieldMapper) columnDefinition.getCustomFieldMapper()); } else { final PropertyMeta property = propertyMappingsBuilder.addProperty(mappedColumnKey, composedDefinition); if (property != null && composedDefinition.isKey()) { if (composedDefinition.keyAppliesTo().test(property)) { mappingContextFactoryBuilder.addKey(key); } } } } // call use towards sub mapper // the keys are initialised protected

void addMapping(K columnKey, FieldMapperColumnDefinition columnDefinition, PropertyMeta prop) { propertyMappingsBuilder.addProperty(columnKey, columnDefinition, prop); } @SuppressWarnings("unchecked") public final FieldMapper[] fields() { final List> fields = new ArrayList>(); propertyMappingsBuilder.forEachProperties(new ForEachCallBack>>() { @Override public void handle(PropertyMapping> t) { if (t == null) return; PropertyMeta meta = t.getPropertyMeta(); if (meta == null || (meta instanceof DirectClassMeta.DirectPropertyMeta)) return; if (!meta.isConstructorProperty() && !meta.isSubProperty()) { fields.add(newFieldMapper(t)); } } }); for(Tuple2, List>>> e : getSubPropertyPerOwner()) { if (!e.first().isConstructorProperty()) { final MappingContextFactoryBuilder currentBuilder = getMapperContextFactoryBuilder(e.first(), e.second()); final Mapper mapper = subPropertyMapper(e.first(), e.second(), currentBuilder); fields.add(newMapperFieldMapper(e.second(), e.first(), mapper, currentBuilder)); } } for(FieldMapper mapper : additionalMappers) { fields.add(mapper); } return fields.toArray(new FieldMapper[fields.size()]); } private List, List>>>> getSubPropertyPerOwner() { final List, List>>>> subPropertiesList = new ArrayList, List>>>>(); 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 (meta.isSubProperty()) { addSubProperty(t, (SubPropertyMeta) meta, t.getColumnKey()); } } private

void addSubProperty(PropertyMapping> pm, SubPropertyMeta subPropertyMeta, K key) { PropertyMeta propertyOwner = subPropertyMeta.getOwnerProperty(); List>> props = getList(propertyOwner); if (props == null) { props = new ArrayList>>(); subPropertiesList.add(new Tuple2, List>>>(propertyOwner, props)); } props.add(pm); } private List>> getList(PropertyMeta owner) { for(Tuple2, List>>> tuple : subPropertiesList) { if (tuple.first().equals(owner)) { return tuple.second(); } } return null; } }); return subPropertiesList; } @SuppressWarnings("unchecked") private

Mapper subPropertyMapper(PropertyMeta owner, List>> properties, MappingContextFactoryBuilder mappingContextFactoryBuilder) { final AbstractFieldMapperMapperBuilder builder = newSubBuilder(owner.getType(), owner.getClassMeta(), mappingContextFactoryBuilder); for(PropertyMapping> pm : properties) { final SubPropertyMeta propertyMeta = (SubPropertyMeta) pm.getPropertyMeta(); final PropertyMeta subProperty = ((SubPropertyMeta) propertyMeta).getSubProperty(); builder.addMapping(pm.getColumnKey(), pm.getColumnDefinition(), subProperty); } return builder.mapper(); } @SuppressWarnings("unchecked") protected

FieldMapper newFieldMapper(PropertyMapping> t) { FieldMapper fieldMapper = (FieldMapper) t.getColumnDefinition().getCustomFieldMapper(); if (fieldMapper == null) { fieldMapper = fieldMapperFactory.newFieldMapper(t, fieldMapperErrorHandler, mapperBuilderErrorHandler); } if (fieldMapperErrorHandler != null && fieldMapper != null) { fieldMapper = new FieldErrorHandlerMapper(t.getColumnKey(), fieldMapper, fieldMapperErrorHandler); } return fieldMapper; } private Getter getterFor(PropertyMapping> t, Type paramType) { Getter getter = t.getColumnDefinition().getCustomGetter(); if (getter == null) { getter = getterFactory.newGetter(paramType, t.getColumnKey(), t.getColumnDefinition()); } if (getter == null) { mapperBuilderErrorHandler.getterNotFound("Could not find getter for " + t.getColumnKey() + " type " + paramType); } return getter; } protected void _addMapper(FieldMapper mapper) { additionalMappers.add(mapper); } protected abstract AbstractFieldMapperMapperBuilder newSubBuilder(Type type, ClassMeta classMeta, MappingContextFactoryBuilder mappingContextFactoryBuilder); public abstract Mapper mapper(); protected void setFieldMapperErrorHandler( FieldMapperErrorHandler errorHandler) { this.fieldMapperErrorHandler = errorHandler; } @SuppressWarnings("unchecked") private List getSubKeys(List>> properties) { List keys = new ArrayList(); // look for keys property of the object for (PropertyMapping> pm : properties) { SubPropertyMeta subPropertyMeta = (SubPropertyMeta) pm.getPropertyMeta(); if (pm.getColumnDefinition().isKey()) { if (pm.getColumnDefinition().keyAppliesTo().test(subPropertyMeta.getSubProperty())) { keys.add(pm.getColumnKey()); } } } return keys; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy