package org.simpleflatmapper.map.mapper; import org.simpleflatmapper.map.FieldKey; import org.simpleflatmapper.map.FieldMapper; import org.simpleflatmapper.map.MapperBuilderErrorHandler; import org.simpleflatmapper.map.property.FieldMapperColumnDefinition; import org.simpleflatmapper.map.context.MappingContextFactoryBuilder; import org.simpleflatmapper.reflect.Getter; import org.simpleflatmapper.reflect.Setter; import org.simpleflatmapper.reflect.SetterFactory; import org.simpleflatmapper.reflect.setter.SetterOnGetter; import org.simpleflatmapper.reflect.meta.ClassMeta; import org.simpleflatmapper.reflect.meta.ObjectClassMeta; import org.simpleflatmapper.reflect.meta.PropertyMeta; import org.simpleflatmapper.reflect.primitive.BooleanGetter; import org.simpleflatmapper.reflect.primitive.BooleanSetter; import org.simpleflatmapper.reflect.primitive.ByteGetter; import org.simpleflatmapper.reflect.primitive.ByteSetter; import org.simpleflatmapper.reflect.primitive.CharacterGetter; import org.simpleflatmapper.reflect.primitive.CharacterSetter; import org.simpleflatmapper.reflect.primitive.DoubleGetter; import org.simpleflatmapper.reflect.primitive.DoubleSetter; import org.simpleflatmapper.reflect.primitive.FloatGetter; import org.simpleflatmapper.reflect.primitive.FloatSetter; import org.simpleflatmapper.reflect.primitive.IntGetter; import org.simpleflatmapper.reflect.primitive.IntSetter; import org.simpleflatmapper.reflect.primitive.LongGetter; import org.simpleflatmapper.reflect.primitive.LongSetter; import org.simpleflatmapper.reflect.primitive.ShortGetter; import org.simpleflatmapper.reflect.primitive.ShortSetter; import org.simpleflatmapper.map.fieldmapper.BooleanFieldMapper; import org.simpleflatmapper.map.fieldmapper.ByteFieldMapper; import org.simpleflatmapper.map.fieldmapper.CharacterFieldMapper; import org.simpleflatmapper.map.fieldmapper.DoubleFieldMapper; import org.simpleflatmapper.map.fieldmapper.FieldMapperImpl; import org.simpleflatmapper.map.fieldmapper.FloatFieldMapper; import org.simpleflatmapper.map.fieldmapper.IntFieldMapper; import org.simpleflatmapper.map.fieldmapper.LongFieldMapper; import org.simpleflatmapper.map.fieldmapper.ShortFieldMapper; import org.simpleflatmapper.util.ErrorDoc; import org.simpleflatmapper.util.TypeHelper; import java.lang.reflect.Type; public class ConstantTargetFieldMapperFactoryImpl<T, K extends FieldKey<K>> implements ConstantTargetFieldMapperFactory<T, K> { private final SetterFactory<T, PropertyMapping<?, ?, K, ? extends ColumnDefinition<K, ?>>> setterFactory; private final Type targetType; private ConstantTargetFieldMapperFactoryImpl(SetterFactory<T, PropertyMapping<?, ?, K, ? extends ColumnDefinition<K, ?>>> setterFactory, Type targetType) { this.setterFactory = setterFactory; this.targetType = targetType; } @SuppressWarnings("unchecked") @Override public <S, P> FieldMapper<S, T> newFieldMapper( PropertyMapping<S, P, K, FieldMapperColumnDefinition<K>> pm, MappingContextFactoryBuilder contextFactoryBuilder, MapperBuilderErrorHandler mappingErrorHandler) { Getter<? super S, ? extends P> getter = (Getter<? super S, ? extends P>) pm.getColumnDefinition().getCustomGetterFrom(pm.getPropertyMeta().getOwnerType()); if (getter == null) { getter = pm.getPropertyMeta().getGetter(); } if (getter == null) { mappingErrorHandler.accessorNotFound("Could not find getter for " + pm.getColumnKey() + " type " + pm.getPropertyMeta().getPropertyType() + " path " + pm.getPropertyMeta().getPath() + ", See " + ErrorDoc.toUrl("CTFM_GETTER_NOT_FOUND")); return null; } Setter<? super T, ? super P> setter = getSetterForTarget(pm); if (setter == null) { mappingErrorHandler.accessorNotFound("Could not find setter for " + pm.getColumnKey() + " type " + pm.getPropertyMeta().getPropertyType() + " path " + pm.getPropertyMeta().getPath() + " See " + ErrorDoc.toUrl("CTFM_SETTER_NOT_FOUND")); return null; } Type propertyType = pm.getPropertyMeta().getPropertyType(); return buildFieldMapper(getter, setter, propertyType); } @SuppressWarnings("unchecked") private <S, P> FieldMapper<S, T> buildFieldMapper(Getter<? super S, ? extends P> getter, Setter<? super T, ? super P> setter, Type propertyType) { if (TypeHelper.isPrimitive(propertyType)) { if (getter instanceof BooleanGetter && setter instanceof BooleanSetter) { return new BooleanFieldMapper<S, T>((BooleanGetter<S>)getter, (BooleanSetter<T>) setter); } else if (getter instanceof ByteGetter && setter instanceof ByteSetter) { return new ByteFieldMapper<S, T>((ByteGetter<S>)getter, (ByteSetter<T>) setter); } else if (getter instanceof CharacterGetter && setter instanceof CharacterSetter) { return new CharacterFieldMapper<S, T>((CharacterGetter<S>)getter, (CharacterSetter<T>) setter); } else if (getter instanceof ShortGetter && setter instanceof ShortSetter) { return new ShortFieldMapper<S, T>((ShortGetter<S>)getter, (ShortSetter<T>) setter); } else if (getter instanceof IntGetter && setter instanceof IntSetter) { return new IntFieldMapper<S, T>((IntGetter<S>)getter, (IntSetter<T>) setter); } else if (getter instanceof LongGetter && setter instanceof LongSetter) { return new LongFieldMapper<S, T>((LongGetter<S>)getter, (LongSetter<T>) setter); } else if (getter instanceof FloatGetter && setter instanceof FloatSetter) { return new FloatFieldMapper<S, T>((FloatGetter<S>)getter, (FloatSetter<T>) setter); } else if (getter instanceof DoubleGetter && setter instanceof DoubleSetter) { return new DoubleFieldMapper<S, T>((DoubleGetter<S>)getter, (DoubleSetter<T>) setter); } } return new FieldMapperImpl<S, T, P>(getter, setter); } @SuppressWarnings("unchecked") private <S, P> Setter<T, P> getSetterForTarget(PropertyMapping<S, ?, K, FieldMapperColumnDefinition<K>> pm) { Setter<T, P> setter = (Setter<T, P>) pm.getColumnDefinition().getCustomSetterTo(targetType); final SetterFactory<T, PropertyMapping<?, ?, K, ? extends ColumnDefinition<K, ?>>> customSetterFactory = (SetterFactory<T, PropertyMapping<?, ?, K, ? extends ColumnDefinition<K, ?>>>) pm.getColumnDefinition().getCustomSetterFactoryTo(targetType); if (customSetterFactory != null) { setter = customSetterFactory.getSetter(pm); } if (setter == null){ setter = setterFactory.getSetter(pm); } if (setter == null) { if (!pm.getPropertyMeta().isSelf()) { final ClassMeta<?> propertyClassMeta = pm.getPropertyMeta().getPropertyClassMeta(); if (propertyClassMeta instanceof ObjectClassMeta) { ObjectClassMeta<P> ocm = (ObjectClassMeta<P>) propertyClassMeta; if (ocm.getNumberOfProperties() == 1) { PropertyMeta<P, ?> subProp = ocm.getFirstProperty(); Setter<T, Object> subSetter = getSetterForTarget(pm.propertyMeta(subProp)); if (subSetter != null) { return new SetterOnGetter<T, Object, P>(subSetter, (Getter<P, Object>) subProp.getGetter()); } } } } } return setter; } public static <T, K extends FieldKey<K>> ConstantTargetFieldMapperFactory<T, K> newInstance( SetterFactory<T, PropertyMapping<?, ?, K, ? extends ColumnDefinition<K, ?>>> setterFactory, Type targetType) { return new ConstantTargetFieldMapperFactoryImpl<T, K>(setterFactory, targetType); } }