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.EmptyStaticMethodInstantiator;
import org.sfm.reflect.impl.InjectConstructorInstantiator;
import org.sfm.reflect.impl.EmptyConstructorInstantiator;
import org.sfm.reflect.impl.InjectStaticMethodInstantiator;
import org.sfm.utils.ForEachCallBack;
import java.lang.reflect.*;
import java.util.HashMap;
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(), propertyMapping.getColumnDefinition());
}
}).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().getEligibleInstantiatorDefinitions(), constructorParameterGetterMap,useAsmIfEnabled);
}
}
@SuppressWarnings("unchecked")
public Instantiator getInstantiator(Type target, final Class> source, List constructors, Map> injections, boolean useAsmIfEnabled) throws SecurityException {
final InstantiatorDefinition instantiatorDefinition = getSmallerConstructor(constructors);
if (instantiatorDefinition == null) {
throw new IllegalArgumentException("No constructor available for " + target);
}
return newInstantiator(source, injections, useAsmIfEnabled, instantiatorDefinition);
}
@SuppressWarnings("unchecked")
private Instantiator newInstantiator(Class> source, Map> injections, boolean useAsmIfEnabled, InstantiatorDefinition instantiatorDefinition) {
Member executable = instantiatorDefinition.getExecutable();
if (asmFactory != null && Modifier.isPublic(executable.getModifiers()) && useAsmIfEnabled) {
try {
return asmFactory.createInstantiator(source, instantiatorDefinition, injections);
} catch (Exception e) {
// fall back on reflection
}
}
if (executable instanceof Constructor) {
Constructor extends T> c = (Constructor extends T>) executable;
if (c.getParameterTypes().length == 0) {
return new EmptyConstructorInstantiator(c);
} else {
return new InjectConstructorInstantiator(instantiatorDefinition, injections);
}
} else if (executable instanceof Method){
Method m = (Method) executable;
if (m.getParameterTypes().length == 0) {
return new EmptyStaticMethodInstantiator(m);
} else {
return new InjectStaticMethodInstantiator(instantiatorDefinition, injections);
}
} else {
throw new IllegalArgumentException("Unsupported executable type " + executable);
}
}
private InstantiatorDefinition getSmallerConstructor(final List constructors) {
if (constructors == null) {
return null;
}
InstantiatorDefinition selectedConstructor = null;
for(InstantiatorDefinition c : constructors) {
if (selectedConstructor == null || c.compareTo(selectedConstructor) < 0) {
selectedConstructor = c;
}
}
return selectedConstructor;
}
public Instantiator getArrayInstantiator(final Class> elementType, final int length) {
return new ArrayInstantiator(elementType, length);
}
@SuppressWarnings("unchecked")
public Instantiator getOneArgIdentityInstantiator(InstantiatorDefinition id) {
Map> injections = new HashMap>();
injections.put(id.getParameters()[0], new IdentityGetter());
return newInstantiator(id.getParameters()[0].getType(), injections, true, id);
}
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);
}
}
}