Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
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;
}
}