org.simpleflatmapper.map.fieldmapper.ConstantSourceFieldMapperFactoryImpl Maven / Gradle / Ivy
package org.simpleflatmapper.map.fieldmapper;
import org.simpleflatmapper.converter.Converter;
import org.simpleflatmapper.converter.ConverterService;
import org.simpleflatmapper.map.property.FieldMapperColumnDefinition;
import org.simpleflatmapper.map.context.MappingContextFactoryBuilder;
import org.simpleflatmapper.map.mapper.PropertyMapping;
import org.simpleflatmapper.reflect.Getter;
import org.simpleflatmapper.reflect.Instantiator;
import org.simpleflatmapper.reflect.InstantiatorDefinition;
import org.simpleflatmapper.reflect.getter.GetterWithConverter;
import org.simpleflatmapper.reflect.instantiator.InstantiatorDefinitions;
import org.simpleflatmapper.reflect.getter.InstantiatorGetter;
import org.simpleflatmapper.reflect.ObjectGetterFactory;
import org.simpleflatmapper.reflect.ObjectSetterFactory;
import org.simpleflatmapper.reflect.Setter;
import org.simpleflatmapper.reflect.getter.GetterFactory;
import org.simpleflatmapper.reflect.meta.ArrayElementPropertyMeta;
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.ErrorDoc;
import org.simpleflatmapper.util.Supplier;
import org.simpleflatmapper.util.TypeHelper;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.HashSet;
public final class ConstantSourceFieldMapperFactoryImpl> implements ConstantSourceFieldMapperFactory {
private final GetterFactory super S, ? super K> getterFactory;
private final ConverterService converterService;
private final Type sourceType;
public ConstantSourceFieldMapperFactoryImpl(GetterFactory super S, ? super 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 Getter super S, ? extends P> getter) {
if (type.equals(Boolean.TYPE)) {
return new BooleanFieldMapper(
ObjectGetterFactory.toBooleanGetter((Getter) getter),
ObjectSetterFactory.toBooleanSetter((Setter) setter));
} else if (type.equals(Integer.TYPE)) {
return new IntFieldMapper(
ObjectGetterFactory.toIntGetter((Getter) getter),
ObjectSetterFactory.toIntSetter((Setter) setter));
} else if (type.equals(Long.TYPE)) {
return new LongFieldMapper(
ObjectGetterFactory.toLongGetter((Getter) getter),
ObjectSetterFactory.toLongSetter((Setter) setter));
} else if (type.equals(Float.TYPE)) {
return new FloatFieldMapper(
ObjectGetterFactory.toFloatGetter((Getter) getter),
ObjectSetterFactory.toFloatSetter((Setter) setter));
} else if (type.equals(Double.TYPE)) {
return new DoubleFieldMapper(
ObjectGetterFactory.toDoubleGetter((Getter) getter),
ObjectSetterFactory.toDoubleSetter((Setter) setter));
} else if (type.equals(Byte.TYPE)) {
return new ByteFieldMapper(
ObjectGetterFactory.toByteGetter((Getter) getter),
ObjectSetterFactory.toByteSetter((Setter) setter));
} else if (type.equals(Character.TYPE)) {
return new CharacterFieldMapper(
ObjectGetterFactory.toCharGetter((Getter) getter),
ObjectSetterFactory.toCharacterSetter((Setter) setter));
} else if (type.equals(Short.TYPE)) {
return new ShortFieldMapper(
ObjectGetterFactory.toShortGetter((Getter) getter),
ObjectSetterFactory.toShortSetter((Setter) setter));
} else {
throw new UnsupportedOperationException("Type " + type
+ " is not primitive");
}
}
@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);
Getter super S, ? extends P> getter = getGetterFromSource(key,
propertyMapping.getPropertyMeta().getPropertyType(),
propertyMapping.getColumnDefinition(), propertyMeta.getPropertyClassMetaSupplier());
if (getter == null) {
mappingErrorHandler.accessorNotFound("Could not find getter for " + key
+ " type " + propertyType
+ " path " + propertyMapping.getPropertyMeta().getPath()
+ " See " + ErrorDoc.toUrl("CSFM_GETTER_NOT_FOUND"));
return null;
} else {
if (type.isPrimitive() ) {
return this.primitiveIndexedFieldMapper(type, setter, getter);
}
if (propertyMapping.getColumnDefinition().isKey() && propertyMapping.getPropertyMeta() instanceof ArrayElementPropertyMeta) {
return new FieldMapperImpl(getter, new NullValueFilterSetter(setter));
} else {
return new FieldMapperImpl(getter, setter);
}
}
}
@Override
public Getter super S, ? extends P> getGetterFromSource(K columnKey, Type propertyType, FieldMapperColumnDefinition columnDefinition, Supplier> propertyClassMetaSupplier) {
@SuppressWarnings("unchecked")
Getter super S, ? extends P> getter = (Getter super S, ? extends P>) columnDefinition.getCustomGetterFrom(sourceType);
if (getter == null) {
GetterFactory super S, K> customGetterFactory = (GetterFactory super S, K>) columnDefinition.getCustomGetterFactoryFrom(sourceType);
if (customGetterFactory != null) {
getter = customGetterFactory.newGetter(propertyType, columnKey, columnDefinition.properties());
}
}
if (getter == null) {
getter = getterFactory.newGetter(propertyType, columnKey, columnDefinition.properties());
}
// try to identify constructor that we could build from
if (getter == null) {
getter = lookForAlternativeGetter(propertyClassMetaSupplier.get(), columnKey, columnDefinition, new HashSet());
}
return getter;
}
private Getter super S, ? extends P> lookForAlternativeGetter(ClassMeta
classMeta, K key, FieldMapperColumnDefinition columnDefinition, Collection types) {
// look for converter
Type propertyType = classMeta.getType();
Type sourceType = key.getType(propertyType);
Object[] properties = columnDefinition.properties();
Converter super J, ? extends P> converter = converterService.findConverter(sourceType, propertyType, properties);
if (converter != null) {
Getter super S, ? extends J> getter = getterFactory.newGetter(sourceType, key, properties);
return new GetterWithConverter(converter, getter);
}
return lookForInstantiatorGetter(classMeta, key, columnDefinition, types);
}
public Getter super S, ? extends P> lookForInstantiatorGetter(ClassMeta
classMeta, K key, FieldMapperColumnDefinition columnDefinition, Collection types) {
InstantiatorDefinitions.CompatibilityScorer scorer = InstantiatorDefinitions.getCompatibilityScorer(key);
InstantiatorDefinition id = InstantiatorDefinitions.lookForCompatibleOneArgument(classMeta.getInstantiatorDefinitions(),
scorer);
if (id != null) {
return getGettetInstantiator(classMeta, id, key, columnDefinition, types);
}
return null;
}
private Getter super S, ? extends P> getGettetInstantiator(
ClassMeta classMeta,
InstantiatorDefinition id, K key, FieldMapperColumnDefinition columnDefinition,
Collection types) {
Instantiator super T, ? extends P> instantiator =
classMeta.getReflectionService().getInstantiatorFactory().getOneArgIdentityInstantiator(id, classMeta.getReflectionService().builderIgnoresNullValues());
final Type sourceType = id.getParameters()[0].getGenericType();
Getter super S, ? extends T> subGetter = getterFactory.newGetter(sourceType, key, columnDefinition);
if (subGetter == null) {
if (types.contains(sourceType)) {
// loop circuit cutter
return null;
}
types.add(sourceType);
subGetter = lookForInstantiatorGetter(classMeta.getReflectionService().getClassMeta(sourceType), key, columnDefinition, types);
}
if (subGetter != null) {
return new InstantiatorGetter(instantiator, subGetter);
} else return null;
}
}