org.simpleflatmapper.map.fieldmapper.ConstantSourceFieldMapperFactoryImpl Maven / Gradle / Ivy
Show all versions of sfm-map Show documentation
package org.simpleflatmapper.map.fieldmapper;
import org.simpleflatmapper.converter.ContextualConverter;
import org.simpleflatmapper.converter.ConverterService;
import org.simpleflatmapper.map.getter.BooleanContextualGetter;
import org.simpleflatmapper.map.getter.BoxedBooleanContextualGetter;
import org.simpleflatmapper.map.getter.BoxedByteContextualGetter;
import org.simpleflatmapper.map.getter.BoxedCharacterContextualGetter;
import org.simpleflatmapper.map.getter.BoxedDoubleContextualGetter;
import org.simpleflatmapper.map.getter.BoxedFloatContextualGetter;
import org.simpleflatmapper.map.getter.BoxedIntContextualGetter;
import org.simpleflatmapper.map.getter.BoxedLongContextualGetter;
import org.simpleflatmapper.map.getter.BoxedShortContextualGetter;
import org.simpleflatmapper.map.getter.ByteContextualGetter;
import org.simpleflatmapper.map.getter.CharacterContextualGetter;
import org.simpleflatmapper.map.getter.ContextualGetter;
import org.simpleflatmapper.map.getter.DoubleContextualGetter;
import org.simpleflatmapper.map.getter.ContextualGetterFactory;
import org.simpleflatmapper.map.getter.ContextualGetterWithDefaultValue;
import org.simpleflatmapper.map.getter.FloatContextualGetter;
import org.simpleflatmapper.map.getter.InstantiatorContextualGetter;
import org.simpleflatmapper.map.getter.IntContextualGetter;
import org.simpleflatmapper.map.getter.LongContextualGetter;
import org.simpleflatmapper.map.getter.ShortContextualGetter;
import org.simpleflatmapper.map.impl.JoinUtils;
import org.simpleflatmapper.map.mapper.ColumnDefinition;
import org.simpleflatmapper.map.mapper.ConstantSourceMapperBuilder;
import org.simpleflatmapper.map.getter.ContextualGetterAdapter;
import org.simpleflatmapper.map.mapper.DefaultConstantSourceMapperBuilder;
import org.simpleflatmapper.map.property.ConverterProperty;
import org.simpleflatmapper.map.context.MappingContextFactoryBuilder;
import org.simpleflatmapper.map.mapper.PropertyMapping;
import org.simpleflatmapper.map.property.DefaultValueProperty;
import org.simpleflatmapper.reflect.Getter;
import org.simpleflatmapper.reflect.Instantiator;
import org.simpleflatmapper.reflect.InstantiatorDefinition;
import org.simpleflatmapper.reflect.instantiator.InstantiatorDefinitions;
import org.simpleflatmapper.reflect.ObjectSetterFactory;
import org.simpleflatmapper.reflect.Setter;
import org.simpleflatmapper.reflect.getter.GetterFactory;
import org.simpleflatmapper.reflect.meta.ClassMeta;
import org.simpleflatmapper.reflect.meta.PropertyMeta;
import org.simpleflatmapper.map.FieldKey;
import org.simpleflatmapper.map.FieldMapper;
import org.simpleflatmapper.map.MapperBuilderErrorHandler;
import org.simpleflatmapper.util.Supplier;
import org.simpleflatmapper.util.TypeHelper;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
public final class ConstantSourceFieldMapperFactoryImpl> implements ConstantSourceFieldMapperFactory {
private final ContextualGetterFactory super S, K> getterFactory;
private final ConverterService converterService;
private final Type sourceType;
public ConstantSourceFieldMapperFactoryImpl(ContextualGetterFactory super S, K> getterFactory, ConverterService converterService, Type sourceType) {
this.getterFactory = getterFactory;
this.converterService = converterService;
this.sourceType = sourceType;
}
@SuppressWarnings("unchecked")
private FieldMapper primitiveIndexedFieldMapper(final Class type, final Setter super T, ? super P> setter, final ContextualGetter super S, ? extends P> getter) {
if (type.equals(Boolean.TYPE)) {
return new BooleanConstantSourceFieldMapper(
toBooleanGetter((ContextualGetter) getter),
ObjectSetterFactory.toBooleanSetter((Setter) setter));
} else if (type.equals(Integer.TYPE)) {
return new IntConstantSourceFieldMapper(
toIntGetter((ContextualGetter) getter),
ObjectSetterFactory.toIntSetter((Setter) setter));
} else if (type.equals(Long.TYPE)) {
return new LongConstantSourceFieldMapper(
toLongGetter((ContextualGetter) getter),
ObjectSetterFactory.toLongSetter((Setter) setter));
} else if (type.equals(Float.TYPE)) {
return new FloatConstantSourceFieldMapper(
toFloatGetter((ContextualGetter) getter),
ObjectSetterFactory.toFloatSetter((Setter) setter));
} else if (type.equals(Double.TYPE)) {
return new DoubleConstantSourceFieldMapper(
toDoubleGetter((ContextualGetter) getter),
ObjectSetterFactory.toDoubleSetter((Setter) setter));
} else if (type.equals(Byte.TYPE)) {
return new ByteConstantSourceFieldMapper(
toByteGetter((ContextualGetter) getter),
ObjectSetterFactory.toByteSetter((Setter) setter));
} else if (type.equals(Character.TYPE)) {
return new CharacterConstantSourceFieldMapper(
toCharGetter((ContextualGetter) getter),
ObjectSetterFactory.toCharacterSetter((Setter) setter));
} else if (type.equals(Short.TYPE)) {
return new ShortConstantSourceFieldMapper(
toShortGetter((ContextualGetter) getter),
ObjectSetterFactory.toShortSetter((Setter) setter));
} else {
throw new UnsupportedOperationException("Type " + type
+ " is not primitive");
}
}
@SuppressWarnings("unchecked")
public static BooleanContextualGetter toBooleanGetter(final ContextualGetter getter) {
if (getter instanceof BooleanContextualGetter) {
return (BooleanContextualGetter) getter;
} else {
return new BoxedBooleanContextualGetter(getter);
}
}
@SuppressWarnings("unchecked")
public static IntContextualGetter toIntGetter(ContextualGetter getter) {
if (getter instanceof IntContextualGetter) {
return (IntContextualGetter) getter;
} else {
return new BoxedIntContextualGetter(getter);
}
}
@SuppressWarnings("unchecked")
public static LongContextualGetter toLongGetter(ContextualGetter getter) {
if (getter instanceof LongContextualGetter) {
return (LongContextualGetter) getter;
} else {
return new BoxedLongContextualGetter(getter);
}
}
@SuppressWarnings("unchecked")
public static FloatContextualGetter toFloatGetter(ContextualGetter getter) {
if (getter instanceof FloatContextualGetter) {
return (FloatContextualGetter) getter;
} else {
return new BoxedFloatContextualGetter(getter);
}
}
@SuppressWarnings("unchecked")
public static DoubleContextualGetter toDoubleGetter(ContextualGetter getter) {
if (getter instanceof DoubleContextualGetter) {
return (DoubleContextualGetter) getter;
} else {
return new BoxedDoubleContextualGetter(getter);
}
}
@SuppressWarnings("unchecked")
public static ByteContextualGetter toByteGetter(ContextualGetter getter) {
if (getter instanceof ByteContextualGetter) {
return (ByteContextualGetter) getter;
} else {
return new BoxedByteContextualGetter(getter);
}
}
@SuppressWarnings("unchecked")
public static ShortContextualGetter toShortGetter(ContextualGetter getter) {
if (getter instanceof ShortContextualGetter) {
return (ShortContextualGetter) getter;
} else {
return new BoxedShortContextualGetter(getter);
}
}
@SuppressWarnings("unchecked")
public static CharacterContextualGetter toCharGetter(ContextualGetter getter) {
if (getter instanceof CharacterContextualGetter) {
return (CharacterContextualGetter) getter;
} else {
return new BoxedCharacterContextualGetter(getter);
}
}
@Override
@SuppressWarnings("unchecked")
public FieldMapper newFieldMapper(PropertyMapping propertyMapping,
MappingContextFactoryBuilder contextFactoryBuilder,
MapperBuilderErrorHandler mappingErrorHandler
) {
final PropertyMeta propertyMeta = propertyMapping.getPropertyMeta();
final Type propertyType = propertyMeta.getPropertyType();
final Setter super T, ? super P> setter = propertyMeta.getSetter();
final K key = propertyMapping.getColumnKey();
final Class type = TypeHelper.toClass(propertyType);
ContextualGetter super S, ? extends P> getter = getGetterFromSource(key,
propertyMapping.getPropertyMeta().getPropertyType(),
propertyMapping.getColumnDefinition(),
propertyMeta.getPropertyClassMetaSupplier(), contextFactoryBuilder);
if (getter == null) {
mappingErrorHandler.accessorNotFound(DefaultConstantSourceMapperBuilder.getterNotFoundErrorMessage(propertyMapping));
return null;
} else {
if (type.isPrimitive() ) {
return this.primitiveIndexedFieldMapper(type, setter, getter);
}
if (propertyMapping.getColumnDefinition().isInferNull()
&& JoinUtils.isArrayElement(propertyMapping.getPropertyMeta())) {
return new ConstantSourceFieldMapper(getter, new NullValueFilterSetter(setter));
} else {
return new ConstantSourceFieldMapper(getter, setter);
}
}
}
@Override
public ContextualGetter super S, ? extends P> getGetterFromSource(K columnKey, Type propertyType, ColumnDefinition columnDefinition, Supplier> propertyClassMetaSupplier, MappingContextFactoryBuilder, K> mappingContextFactoryBuilder) {
@SuppressWarnings("unchecked")
ContextualGetter super S, ? extends P> getter = ContextualGetterAdapter.of((Getter super S, ? extends P>) columnDefinition.getCustomGetterFrom(sourceType));
if (getter == null) {
ContextualGetterFactory super S, K> customGetterFactory = (ContextualGetterFactory super S, K>) columnDefinition.getCustomGetterFactoryFrom(sourceType);
if (customGetterFactory != null) {
getter = (ContextualGetter super S, ? extends P>) customGetterFactory.newGetter(propertyType, columnKey, mappingContextFactoryBuilder, columnDefinition.properties());
}
}
ConverterProperty converterProperty = columnDefinition.lookFor(ConverterProperty.class);
if (converterProperty != null) {
Type t = converterProperty.inType;
if (Object.class.equals(t)) { // lost type info... assume sql type is right
t = columnKey.getType(t);
}
getter = getterFactory.
newGetter(t, columnKey, mappingContextFactoryBuilder, columnDefinition.properties());
if (getter == null) {
return null;
}
return new FieldMapperGetterWithConverter(converterProperty.function, getter);
}
if (getter == null) {
getter = getterFactory.newGetter(propertyType, columnKey, mappingContextFactoryBuilder, columnDefinition.properties());
}
// try to identify constructor that we could build from
if (getter == null) {
getter = lookForAlternativeGetter(propertyClassMetaSupplier.get(), columnKey, columnDefinition, new HashSet(), mappingContextFactoryBuilder);
}
DefaultValueProperty defaultValueProperty = columnDefinition.lookFor(DefaultValueProperty.class);
if (defaultValueProperty != null) {
Object value = defaultValueProperty.getValue();
if (value != null) {
if (TypeHelper.isAssignable(propertyType, value.getClass())) {
getter = new ContextualGetterWithDefaultValue(getter, (P) value);
} else {
throw new IllegalArgumentException("Incompatible default value " + value + " type " + value.getClass() + " with property " + columnKey + " of type " + propertyType);
}
}
}
return getter;
}
private ContextualGetter super S, ? extends P> lookForAlternativeGetter(ClassMeta
classMeta, K key, ColumnDefinition columnDefinition, Collection types, MappingContextFactoryBuilder, K> mappingContextFactoryBuilder) {
// look for converter
Type propertyType = classMeta.getType();
Type sourceType = key.getType(propertyType);
Object[] properties = columnDefinition.properties();
ContextualConverter super J, ? extends P> converter = converterService.findConverter(sourceType, propertyType, mappingContextFactoryBuilder, properties);
if (converter != null) {
ContextualGetter super S, ? extends J> getter = getterFactory.newGetter(sourceType, key, mappingContextFactoryBuilder, properties);
return new FieldMapperGetterWithConverter(converter, getter);
}
return lookForInstantiatorGetter(classMeta, key, columnDefinition, types, mappingContextFactoryBuilder);
}
public ContextualGetter super S, ? extends P> lookForInstantiatorGetter(ClassMeta
classMeta, K key, ColumnDefinition columnDefinition, Collection types, MappingContextFactoryBuilder, K> mappingContextFactoryBuilder) {
InstantiatorDefinitions.CompatibilityScorer scorer = InstantiatorDefinitions.getCompatibilityScorer(key);
List instantiatorDefinitions = classMeta.getInstantiatorDefinitions();
InstantiatorDefinition id = InstantiatorDefinitions.lookForCompatibleOneArgument(instantiatorDefinitions, scorer);
if (id != null) {
return getGetterInstantiator(classMeta, id, key, columnDefinition, types, mappingContextFactoryBuilder);
}
return null;
}
private ContextualGetter super S, ? extends P> getGetterInstantiator(
ClassMeta classMeta,
InstantiatorDefinition id, K key, ColumnDefinition columnDefinition,
Collection types,
MappingContextFactoryBuilder, K> mappingContextFactoryBuilder) {
Instantiator super T, ? extends P> instantiator =
classMeta.getReflectionService().getInstantiatorFactory().getOneArgIdentityInstantiator(id, classMeta.getReflectionService().builderIgnoresNullValues());
final Type paramType = id.getParameters()[0].getGenericType();
ContextualGetter super S, ? extends T> subGetter = getterFactory.newGetter(paramType, key, mappingContextFactoryBuilder, columnDefinition );
if (subGetter == null) {
if (types.contains(paramType)) {
// loop circuit cutter
return null;
}
types.add(paramType);
// converter?
Type sourceType = key.getType(paramType);
ContextualConverter converter = converterService.findConverter(sourceType, paramType, mappingContextFactoryBuilder, columnDefinition.properties());
if (converter != null) {
ContextualGetter sourceTypeGetter = getterFactory.newGetter(sourceType, key, mappingContextFactoryBuilder, columnDefinition);
subGetter = new FieldMapperGetterWithConverter(converter, sourceTypeGetter);
} else {
subGetter = lookForInstantiatorGetter(classMeta.getReflectionService().getClassMeta(paramType), key, columnDefinition, types, mappingContextFactoryBuilder);
}
}
if (subGetter != null) {
return new InstantiatorContextualGetter(instantiator, subGetter);
} else return null;
}
}