![JAR search and dependency download from the Maven repository](/logo.png)
org.sfm.map.impl.AbstractFieldMapperMapperBuilder Maven / Gradle / Ivy
Show all versions of simpleFlatMapper Show documentation
package org.sfm.map.impl;
import org.sfm.jdbc.impl.getter.MapperGetterAdapter;
import org.sfm.map.*;
import org.sfm.map.impl.fieldmapper.FieldMapperImpl;
import org.sfm.reflect.*;
import org.sfm.reflect.meta.*;
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;
import java.util.Map.Entry;
public abstract class AbstractFieldMapperMapperBuilder> {
private final Type source;
private final Type target;
private final FieldMapperFactory> fieldMapperFactory;
private final GetterFactory getterFactory;
private final PropertyMappingsBuilder> propertyMappingsBuilder;
protected final ReflectionService reflectionService;
protected final ColumnDefinitionProvider, K> columnDefinitions;
private final List> additionalMappers = new ArrayList>();
protected final PropertyNameMatcherFactory propertyNameMatcherFactory;
private final FieldMapperColumnDefinition identity = FieldMapperColumnDefinition.identity();
protected final MapperBuilderErrorHandler mapperBuilderErrorHandler;
private FieldMapperErrorHandler fieldMapperErrorHandler;
public AbstractFieldMapperMapperBuilder(final Type source,
final ClassMeta classMeta,
GetterFactory getterFactory,
FieldMapperFactory> fieldMapperFactory,
ColumnDefinitionProvider, K> columnDefinitions,
PropertyNameMatcherFactory propertyNameMatcherFactory,
MapperBuilderErrorHandler mapperBuilderErrorHandler) throws MapperBuildingException {
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 Instantiator getInstantiator() throws MapperBuildingException {
InstantiatorFactory instantiatorFactory = reflectionService.getInstantiatorFactory();
try {
return instantiatorFactory.getInstantiator(source, target, propertyMappingsBuilder, constructorInjections());
} catch(Exception e) {
throw new MapperBuildingException(e.getMessage(), e);
}
}
private Map> constructorInjections() {
final Map> injections = new HashMap>();
propertyMappingsBuilder.forEachConstructorProperties(new ForEachCallBack>>() {
@SuppressWarnings("unchecked")
@Override
public void handle(PropertyMapping> t) {
PropertyMeta pm = t.getPropertyMeta();
ConstructorPropertyMeta cProp = (ConstructorPropertyMeta) pm;
ConstructorParameter constructorParameter = cProp.getConstructorParameter();
injections.put(constructorParameter, getterFor(t, constructorParameter.getResolvedType()));
}
});
final Map> builderToInject = new HashMap>();
propertyMappingsBuilder.forEachSubProperties(new ForEachCallBack>>() {
@SuppressWarnings("unchecked")
@Override
public void handle(PropertyMapping> t) {
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);
}
addPropertyBuilder(t, subProp, builder);
}
}
@SuppressWarnings("unchecked")
private void addPropertyBuilder(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 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 {
propertyMappingsBuilder.addProperty(mappedColumnKey, composedDefinition);
}
}
protected void addMapping(K columnKey, PropertyMeta prop) {
propertyMappingsBuilder.addProperty(columnKey, identity, 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) {
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(FieldMapper mapper : additionalMappers) {
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;
}
@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 = 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());
}
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);
public abstract Mapper mapper();
protected void setFieldMapperErrorHandler(
FieldMapperErrorHandler errorHandler) {
this.fieldMapperErrorHandler = errorHandler;
}
}