org.sfm.map.AbstractMapperBuilderImpl Maven / Gradle / Ivy
package org.sfm.map;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.sfm.jdbc.MapperBuilder;
import org.sfm.jdbc.MapperGetterAdapter;
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.PropertyFinder;
import org.sfm.reflect.meta.PropertyMeta;
import org.sfm.reflect.meta.SubProperty;
import org.sfm.reflect.meta.SubPropertyMeta;
public abstract class AbstractMapperBuilderImpl, B extends MapperBuilder>
implements MapperBuilder {
private FieldMapperErrorHandler fieldMapperErrorHandler;
private MapperBuilderErrorHandler mapperBuilderErrorHandler = new RethrowMapperBuilderErrorHandler();
private final Type target;
private final Type source;
private final PropertyFinder propertyFinder;
private final List> fields = new ArrayList>();
private final Map> constructorInjections;
private final List> subProperties = new ArrayList>();
private final FieldMapperFactory fieldMapperFactory;
private final GetterFactory getterFactory;
protected final ReflectionService reflectionService;
public AbstractMapperBuilderImpl(final Type target, final Type source, final ClassMeta classMeta,
GetterFactory getterFactory, FieldMapperFactory fieldMapperFactory) throws MapperBuildingException {
this.target = target;
this.source = source;
this.reflectionService = classMeta.getReflectionService();
this.constructorInjections = new HashMap>();
this.propertyFinder = classMeta.newPropertyFinder();
this.getterFactory = getterFactory;
this.fieldMapperFactory = fieldMapperFactory;
}
@SuppressWarnings("unchecked")
public final B fieldMapperErrorHandler(final FieldMapperErrorHandler errorHandler) {
if (!fields.isEmpty()) {
throw new IllegalStateException(
"Error Handler need to be set before adding fields");
}
fieldMapperErrorHandler = errorHandler;
return (B) this;
}
@SuppressWarnings("unchecked")
public final B mapperBuilderErrorHandler(final MapperBuilderErrorHandler errorHandler) {
mapperBuilderErrorHandler = errorHandler;
return (B) this;
}
@SuppressWarnings("unchecked")
public final B addMapping(final String propertyName, final K columnKey) {
FieldMapper fieldMapper = getCustomMapper(columnKey);
if (fieldMapper != null) {
if (fieldMapperErrorHandler != null) {
fieldMapper = new FieldErrorHandlerMapper(columnKey, fieldMapper, fieldMapperErrorHandler);
}
fields.add(fieldMapper);
} else {
final PropertyMeta property = propertyFinder.findProperty(propertyName);
if (property == null) {
mapperBuilderErrorHandler.propertyNotFound(target, propertyName);
} else {
addMapping(property, columnKey);
}
}
return (B) this;
}
protected FieldMapper getCustomMapper(K columnKey) {
return null;
}
protected Class getTargetClass() {
return TypeHelper.toClass(target);
}
@SuppressWarnings("unchecked")
protected Instantiator getInstantiator() throws MapperBuildingException {
InstantiatorFactory instantiatorFactory = reflectionService.getInstantiatorFactory();
if (!reflectionService.isAsmPresent()) {
try {
return (Instantiator) instantiatorFactory.getInstantiator(TypeHelper.toClass(source), propertyFinder.getClassToInstantiate());
} catch(Exception e) {
throw new MapperBuildingException(e.getMessage(), e);
}
} else {
try {
return instantiatorFactory.getInstantiator(TypeHelper.toClass(source), propertyFinder.getEligibleConstructorDefinitions(), constructorInjections());
} catch(Exception e) {
throw new MapperBuildingException(e.getMessage(), e);
}
}
}
@SuppressWarnings({ "rawtypes" })
private Map> constructorInjections() {
Map> injections = new HashMap>(constructorInjections);
for(SubProperty subProp : subProperties) {
PropertyMeta prop = subProp.getSubProperty().getProperty();
if (prop instanceof ConstructorPropertyMeta) {
MapperBuilder builder = subProp.getMapperBuilder();
final Mapper mapper = builder.mapper();
Getter getter = new MapperGetterAdapter(mapper);
injections.put(((ConstructorPropertyMeta) prop).getConstructorParameter(), getter);
}
}
return injections;
}
public abstract M mapper();
@SuppressWarnings("unchecked")
public final FieldMapper[] fields() {
List> fields = new ArrayList>(this.fields);
for(SubProperty subProp : subProperties) {
PropertyMeta prop = subProp.getSubProperty().getProperty();
if (!(prop instanceof ConstructorPropertyMeta)) {
Setter setter = (Setter) prop.getSetter();
Mapper mapper = (Mapper) subProp.getMapperBuilder().mapper();
Getter getter = new MapperGetterAdapter(mapper);
fields.add(new FieldMapperImpl(getter, setter));
}
}
return fields.toArray(new FieldMapper[fields.size()]);
}
private SubProperty getOrAddSubPropertyMapperBuilder(SubPropertyMeta property) {
for(SubProperty subProp : subProperties) {
if (subProp.getSubProperty().getName().equals(property.getName())) {
return subProp;
}
}
MapperBuilder builder = newMapperBuilder(property.getType(), property.getClassMeta());
SubProperty subProp = new SubProperty(builder, property);
subProperties.add(subProp);
return subProp;
}
protected abstract MapperBuilder newMapperBuilder(Type type, ClassMeta classMeta);
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public B addMapping(PropertyMeta property, K key) {
if (property instanceof ConstructorPropertyMeta) {
ConstructorParameter constructorParameter = ((ConstructorPropertyMeta) property).getConstructorParameter();
Getter getter = getterFactory.newGetter(constructorParameter.getType(), key);
if (getter == null) {
mapperBuilderErrorHandler.getterNotFound("Could not find getter for " + key + " type " + constructorParameter.getType());
}
constructorInjections.put(constructorParameter, getter);
} else if (property instanceof SubPropertyMeta) {
SubProperty subProp = getOrAddSubPropertyMapperBuilder((SubPropertyMeta)property);
MapperBuilder mapperBuilder = subProp.getMapperBuilder();
mapperBuilder.addMapping(((SubPropertyMeta) property).getSubProperty(), key);
} else {
FieldMapper fieldMapper = fieldMapperFactory.newFieldMapper(property.getSetter(), key, fieldMapperErrorHandler, mapperBuilderErrorHandler);
if (fieldMapperErrorHandler != null) {
fieldMapper = new FieldErrorHandlerMapper(key, fieldMapper, fieldMapperErrorHandler);
}
fields.add(fieldMapper);
}
return (B) this;
}
@SuppressWarnings("unchecked")
public B addMapper(FieldMapper mapper) {
fields.add(mapper);
return (B) this;
}
} © 2015 - 2025 Weber Informatics LLC | Privacy Policy