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 java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.sfm.jdbc.impl.getter.MapperGetterAdapter;
import org.sfm.map.FieldMapperErrorHandler;
import org.sfm.map.Mapper;
import org.sfm.map.MapperBuilderErrorHandler;
import org.sfm.map.MapperBuildingException;
import org.sfm.map.impl.fieldmapper.FieldMapperImpl;
import org.sfm.reflect.Getter;
import org.sfm.reflect.Instantiator;
import org.sfm.reflect.InstantiatorFactory;
import org.sfm.reflect.ReflectionService;
import org.sfm.reflect.Setter;
import org.sfm.reflect.TypeHelper;
import org.sfm.reflect.asm.ConstructorParameter;
import org.sfm.reflect.meta.ClassMeta;
import org.sfm.reflect.meta.ConstructorPropertyMeta;
import org.sfm.reflect.meta.PropertyMeta;
import org.sfm.reflect.meta.SubPropertyMeta;
import org.sfm.utils.ForEachCallBack;

public abstract class AbstractFieldMapperMapperBuilder>  {

	private final Type source;
	protected final Type target;

	private final FieldMapperFactory fieldMapperFactory;
	private final GetterFactory getterFactory;

	private final PropertyMappingsBuilder propertyMappingsBuilder;
	protected final ReflectionService reflectionService;
	
	protected final Map aliases;
	protected final Map> customMappings;
	protected final List> mappers;

	
	private MapperBuilderErrorHandler mapperBuilderErrorHandler = new RethrowMapperBuilderErrorHandler();
	private FieldMapperErrorHandler fieldMapperErrorHandler;
	
	public AbstractFieldMapperMapperBuilder(final Type target, final Type source, final ClassMeta classMeta,   
			GetterFactory getterFactory, FieldMapperFactory fieldMapperFactory, 
			Map aliases, Map> customMappings
			) throws MapperBuildingException {
		this.source = source;
		this.getterFactory = getterFactory;
		this.fieldMapperFactory = fieldMapperFactory;
		this.propertyMappingsBuilder = new PropertyMappingsBuilder(classMeta);
		this.target = target;
		this.reflectionService = classMeta.getReflectionService();
		this.aliases = aliases;
		this.customMappings = customMappings;
		this.mappers = new ArrayList>();
	}

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

	@SuppressWarnings("unchecked")
	protected Instantiator getInstantiator() throws MapperBuildingException {
		InstantiatorFactory instantiatorFactory = reflectionService.getInstantiatorFactory();
		
		if (TypeHelper.isArray(target)) {
			return instantiatorFactory.getArrayInstantiator(TypeHelper.toClass(TypeHelper.getComponentType(target)), propertyMappingsBuilder.forEachProperties(new CalculateMaxIndex()).maxIndex + 1);
		} else {
			if (!reflectionService.isAsmPresent()) {
				try {
					return (Instantiator) instantiatorFactory.getInstantiator(TypeHelper.toClass(source), propertyMappingsBuilder.getPropertyFinder().getClassToInstantiate());
				} catch(Exception e) {
					throw new MapperBuildingException(e.getMessage(), e);
				}
			} else {
				try {
					return instantiatorFactory.getInstantiator(TypeHelper.toClass(source), propertyMappingsBuilder.getPropertyFinder().getEligibleConstructorDefinitions(), constructorInjections());
				} catch(Exception e) {
					throw new MapperBuildingException(e.getMessage(), e);
				}
			}
		}
	}

	private Map> constructorInjections() {
		final Map> injections = new HashMap>();
		
		propertyMappingsBuilder.forEachConstructorProperties(new ForEachCallBack>() {
			@Override
			public void handle(PropertyMapping t, int index) {
				PropertyMeta pm  = t.getPropertyMeta();
					ConstructorPropertyMeta cProp = (ConstructorPropertyMeta) pm;
					ConstructorParameter constructorParameter = cProp.getConstructorParameter();
					injections.put(constructorParameter, getterFor(t.getColumnKey(), constructorParameter.getType()));
			}
		});
		
		final Map> builderToInject = new HashMap>();
		propertyMappingsBuilder.forEachSubProperties(new ForEachCallBack>() {
			@Override
			public void handle(PropertyMapping t, int index) {
				PropertyMeta pm  = t.getPropertyMeta();
				SubPropertyMeta subProp = (SubPropertyMeta) pm;
				PropertyMeta propOwner = subProp.getOwnerProperty();
				if (propOwner.isConstructorProperty()) {
					ConstructorParameter param = ((ConstructorPropertyMeta)propOwner).getConstructorParameter();
					AbstractFieldMapperMapperBuilder builder = builderToInject.get(param);
					if (builder == null) {
						builder = newSubBuilder(propOwner.getType(), propOwner.getClassMeta());
						builderToInject.put(param, builder);
					}
					addPropertyoBuilder(t, subProp, builder);
				}
			}

			@SuppressWarnings("unchecked")
			private 

void addPropertyoBuilder(PropertyMapping t, SubPropertyMeta subProp, AbstractFieldMapperMapperBuilder builder) { ((AbstractFieldMapperMapperBuilder)builder).addMapping(t.getColumnKey(), ((SubPropertyMeta)subProp).getSubProperty()); } }); for(Entry> e : builderToInject.entrySet()) { injections.put(e.getKey(), newSubMapperGetter(e.getValue())); } return injections; } @SuppressWarnings("unchecked") protected void addMapping(K columnKey) { if (customMappings != null && customMappings.containsKey(columnKey.getName().toUpperCase())) { mappers.add( new KeyFieldMapperCouple(columnKey, (FieldMapper) customMappings.get(columnKey.getName().toUpperCase()))); } else { K alias = alias(columnKey); if (! propertyMappingsBuilder.addProperty(alias)) { mapperBuilderErrorHandler.propertyNotFound(target, columnKey.getName()); } } } private K alias(K key) { if (aliases == null || aliases.isEmpty()) { return key; } String alias = aliases.get(key.getName().toUpperCase()); if (alias == null) { return key; } return key.alias(alias); } protected

void addMapping(K columnKey, PropertyMeta prop) { propertyMappingsBuilder.addProperty(columnKey, prop); } private

Getter newSubMapperGetter(AbstractFieldMapperMapperBuilder value) { return new MapperGetterAdapter(value.mapper()); } @SuppressWarnings("unchecked") public final FieldMapper[] fields() { final List> fields = new ArrayList>(); final Map, AbstractFieldMapperMapperBuilder> buildersByOwner = new HashMap, AbstractFieldMapperMapperBuilder>(); propertyMappingsBuilder.forEachProperties(new ForEachCallBack>() { final Map> builders = new HashMap>(); @Override public void handle(PropertyMapping t, int index) { if (t == null) return; PropertyMeta meta = t.getPropertyMeta(); if (meta == null) return; if (meta.isSubProperty()) { addSubProperty(t, (SubPropertyMeta) meta, t.getColumnKey()); } else if (!meta.isConstructorProperty()) { fields.add(newFieldMapper(t)); } } private

void addSubProperty(PropertyMapping pm, SubPropertyMeta subPropertyMeta, K key) { PropertyMeta propertyOwner = subPropertyMeta.getOwnerProperty(); if (!propertyOwner.isConstructorProperty()) { AbstractFieldMapperMapperBuilder builder = (AbstractFieldMapperMapperBuilder) builders.get(propertyOwner.getName()); if (builder == null) { builder = (AbstractFieldMapperMapperBuilder) newSubBuilder(propertyOwner.getType(), propertyOwner.getClassMeta()); builders.put(propertyOwner.getName(), builder); buildersByOwner.put(pm, builder); } builder.addMapping(key, ((SubPropertyMeta)subPropertyMeta).getSubProperty()); } } }); for(Entry, AbstractFieldMapperMapperBuilder> e : buildersByOwner.entrySet()) { SubPropertyMeta prop = (SubPropertyMeta) e.getKey().getPropertyMeta(); fields.add(newSubFieldMapper(prop.getOwnerProperty(), e.getValue(), e.getKey().getColumnKey())); } for(KeyFieldMapperCouple keyFieldMapper: mappers) { FieldMapper mapper = keyFieldMapper.getFieldMapper(); if (fieldMapperErrorHandler != null) { mapper = new FieldErrorHandlerMapper(keyFieldMapper.getKey(), mapper, fieldMapperErrorHandler); } fields.add(mapper); } return fields.toArray(new FieldMapper[fields.size()]); } @SuppressWarnings("unchecked") private

FieldMapper newSubFieldMapper(PropertyMeta prop, AbstractFieldMapperMapperBuilder builder, K key) { Setter setter = (Setter) prop.getSetter(); return newFieldMapper(builder, setter, key); } @SuppressWarnings("unchecked") private

FieldMapper newFieldMapper( AbstractFieldMapperMapperBuilder builder, Setter setter, K key) { FieldMapper fm = new FieldMapperImpl((Getter) newSubMapperGetter(builder), setter); if (fieldMapperErrorHandler != null) { fm = new FieldErrorHandlerMapper(key, fm, fieldMapperErrorHandler); } return fm; } protected

FieldMapper newFieldMapper(PropertyMapping t) { FieldMapper fieldMapper = fieldMapperFactory.newFieldMapper(t.getPropertyMeta().getType(), t.getPropertyMeta().getSetter(), t.getColumnKey(), fieldMapperErrorHandler, mapperBuilderErrorHandler); if (fieldMapperErrorHandler != null) { fieldMapper = new FieldErrorHandlerMapper(t.getColumnKey(), fieldMapper, fieldMapperErrorHandler); } return fieldMapper; } private Getter getterFor(K key, Type paramType) { Getter getter = getterFactory.newGetter(paramType, key); if (getter == null) { mapperBuilderErrorHandler.getterNotFound("Could not find getter for " + key + " type " + paramType); } return getter; } protected abstract AbstractFieldMapperMapperBuilder newSubBuilder(Type type, ClassMeta classMeta); public abstract Mapper mapper(); protected void setMapperBuilderErrorHandler(MapperBuilderErrorHandler errorHandler) { this.mapperBuilderErrorHandler = errorHandler; } protected void setFieldMapperErrorHandler( FieldMapperErrorHandler errorHandler) { this.fieldMapperErrorHandler = errorHandler; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy