org.sfm.reflect.InstantiatorFactory Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of simpleFlatMapper Show documentation
Show all versions of simpleFlatMapper Show documentation
Java library to map flat record - ResultSet, csv - to java object with minimum configuration and low footprint.
package org.sfm.reflect;
import org.sfm.map.ColumnDefinition;
import org.sfm.map.impl.CalculateMaxIndex;
import org.sfm.map.FieldKey;
import org.sfm.map.impl.PropertyMapping;
import org.sfm.map.impl.PropertyMappingsBuilder;
import org.sfm.reflect.asm.AsmFactory;
import org.sfm.reflect.impl.InjectConstructorInstantiator;
import org.sfm.reflect.impl.StaticConstructorInstantiator;
import org.sfm.utils.ForEachCallBack;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
public class InstantiatorFactory {
private static final Object[] EMPTY_ARGS = new Object[]{};
private final AsmFactory asmFactory;
public InstantiatorFactory(final AsmFactory asmFactory) {
this.asmFactory = asmFactory;
}
public , D extends ColumnDefinition> Instantiator getInstantiator(Type source, Type target, PropertyMappingsBuilder propertyMappingsBuilder, Map> constructorParameterGetterMap, org.sfm.map.GetterFactory getterFactory) throws NoSuchMethodException {
return getInstantiator(source, target, propertyMappingsBuilder, constructorParameterGetterMap, getterFactory, true);
}
@SuppressWarnings("unchecked")
public , D extends ColumnDefinition> Instantiator getInstantiator(Type source, Type target, PropertyMappingsBuilder propertyMappingsBuilder, Map> constructorParameterGetterMap, final org.sfm.map.GetterFactory getterFactory, boolean useAsmIfEnabled) throws NoSuchMethodException {
if (propertyMappingsBuilder.isDirectProperty()) {
Getter getter = propertyMappingsBuilder.forEachProperties(new ForEachCallBack>() {
public Getter getter;
@Override
public void handle(PropertyMapping propertyMapping) {
getter = getterFactory.newGetter(propertyMapping.getPropertyMeta().getType(), propertyMapping.getColumnKey());
}
}).getter;
return new GetterInstantiator(getter);
}
if (TypeHelper.isArray(target)) {
return getArrayInstantiator(TypeHelper.toClass(TypeHelper.getComponentType(target)), propertyMappingsBuilder.forEachProperties(new CalculateMaxIndex()).maxIndex + 1);
} else {
return getInstantiator(target, TypeHelper.toClass(source), propertyMappingsBuilder.getPropertyFinder().getEligibleConstructorDefinitions(), constructorParameterGetterMap,useAsmIfEnabled);
}
}
public Instantiator getInstantiator(Type target, final Class> source, List> constructors, Map> injections, boolean useAsmIfEnabled) throws SecurityException {
final ConstructorDefinition constructorDefinition = getSmallerConstructor(constructors);
if (constructorDefinition == null) {
throw new IllegalArgumentException("No constructor available for " + target);
}
Constructor extends T> constructor = constructorDefinition.getConstructor();
if (asmFactory != null && Modifier.isPublic(constructor.getModifiers()) && useAsmIfEnabled) {
try {
return asmFactory.createInstantiator(source, constructorDefinition, injections);
} catch (Exception e) {
// fall back on reflection
}
}
constructor.setAccessible(true);
if (constructor.getParameterTypes().length == 0) {
return new StaticConstructorInstantiator(constructor, EMPTY_ARGS);
} else {
return new InjectConstructorInstantiator(constructorDefinition, injections);
}
}
private ConstructorDefinition getSmallerConstructor(final List> constructors) {
if (constructors == null) {
return null;
}
ConstructorDefinition selectedConstructor = null;
for(ConstructorDefinition c : constructors) {
if (selectedConstructor == null || (c.getParameters().length < selectedConstructor.getParameters().length)) {
selectedConstructor = c;
}
}
return selectedConstructor;
}
public Instantiator getArrayInstantiator(final Class> elementType, final int length) {
return new ArrayInstantiator(elementType, length);
}
private static final class ArrayInstantiator implements Instantiator {
private final Class> elementType;
private final int length;
public ArrayInstantiator(Class> elementType, int length) {
this.elementType = elementType;
this.length = length;
}
@SuppressWarnings("unchecked")
@Override
public T newInstance(S s) throws Exception {
return (T) Array.newInstance(elementType, length);
}
}
}