use of org.simpleflatmapper.reflect.Parameter in project SimpleFlatMapper by arnaudroger.
the class ConstantSourceMapperBuilder method constructorInjections.
@SuppressWarnings("unchecked")
private ConstructorInjections constructorInjections() {
final Map<Parameter, BiFunction<? super S, ? super MappingContext<? super S>, ?>> injections = new HashMap<Parameter, BiFunction<? super S, ? super MappingContext<? super S>, ?>>();
final List<FieldMapper<S, T>> fieldMappers = new ArrayList<FieldMapper<S, T>>();
propertyMappingsBuilder.forEachConstructorProperties(new ForEachCallBack<PropertyMapping<T, ?, K, FieldMapperColumnDefinition<K>>>() {
@SuppressWarnings("unchecked")
@Override
public void handle(PropertyMapping<T, ?, K, FieldMapperColumnDefinition<K>> propertyMapping) {
if (!isTargetForMapperFieldMapper(propertyMapping)) {
PropertyMeta<T, ?> pm = propertyMapping.getPropertyMeta();
ConstructorPropertyMeta<T, ?> cProp = (ConstructorPropertyMeta<T, ?>) pm;
Parameter parameter = cProp.getParameter();
Getter<? super S, ?> getter = fieldMapperFactory.getGetterFromSource(propertyMapping.getColumnKey(), pm.getPropertyType(), propertyMapping.getColumnDefinition(), pm.getPropertyClassMetaSupplier());
if (NullGetter.isNull(getter)) {
mapperConfig.mapperBuilderErrorHandler().accessorNotFound("Could not find getter for " + propertyMapping.getColumnKey() + " type " + propertyMapping.getPropertyMeta().getPropertyType() + " path " + propertyMapping.getPropertyMeta().getPath() + " See " + ErrorDoc.toUrl("FMMB_GETTER_NOT_FOUND"));
} else {
injections.put(parameter, new BiFunctionGetter<S, MappingContext<? super S>, Object>(getter));
}
if (!NullSetter.isNull(cProp.getSetter())) {
fieldMappers.add(fieldMapperFactory.newFieldMapper(propertyMapping, mappingContextFactoryBuilder, mapperConfig.mapperBuilderErrorHandler()));
}
}
}
});
for (PropertyPerOwner e : getSubPropertyPerOwner()) {
if (e.owner.isConstructorProperty()) {
final List<PropertyMapping<T, ?, K, FieldMapperColumnDefinition<K>>> properties = e.propertyMappings;
final MappingContextFactoryBuilder currentBuilder = getMapperContextFactoryBuilder(e.owner, properties);
final Mapper<S, ?> mapper;
if (properties.size() == 1 && JoinUtils.isArrayElement(properties.get(0).getPropertyMeta())) {
mapper = getterPropertyMapper(e.owner, properties.get(0));
} else {
mapper = subPropertyMapper(e.owner, properties, currentBuilder);
}
ConstructorPropertyMeta<T, ?> meta = (ConstructorPropertyMeta<T, ?>) e.owner;
injections.put(meta.getParameter(), newMapperGetterAdapter(mapper, currentBuilder));
fieldMappers.add(newMapperFieldMapper(properties, meta, mapper, currentBuilder));
}
}
return new ConstructorInjections(injections, fieldMappers.toArray(new FieldMapper[0]));
}
use of org.simpleflatmapper.reflect.Parameter in project SimpleFlatMapper by arnaudroger.
the class CellSetterFactory method cellValueReaderFromFactory.
private <P> CellValueReader<P> cellValueReaderFromFactory(PropertyMeta<?, ?> pm, int index, CsvColumnDefinition columnDefinition, ParsingContextFactoryBuilder parsingContextFactoryBuilder) {
Type propertyType = pm.getPropertyType();
CellValueReader<P> reader = null;
if (columnDefinition.hasCustomReaderFactory()) {
CellValueReaderFactory factory = columnDefinition.getCustomCellValueReaderFactory();
reader = factory.getReader(propertyType, index, columnDefinition, parsingContextFactoryBuilder);
}
if (reader == null) {
reader = cellValueReaderFactory.getReader(propertyType, index, columnDefinition, parsingContextFactoryBuilder);
}
if (reader == null) {
if (!pm.isSelf()) {
final ClassMeta<?> classMeta = pm.getPropertyClassMeta();
InstantiatorDefinition id = InstantiatorDefinitions.lookForCompatibleOneArgument(classMeta.getInstantiatorDefinitions(), COMPATIBILITY_SCORER);
if (id != null) {
final Parameter parameter = id.getParameters()[0];
// look for constructor property matching name
final PropertyMeta<?, Object> property = classMeta.newPropertyFinder(new Predicate<PropertyMeta<?, ?>>() {
@Override
public boolean test(PropertyMeta<?, ?> propertyMeta) {
return propertyMeta.isConstructorProperty() || propertyMeta.isSubProperty() && ((SubPropertyMeta) propertyMeta).getOwnerProperty().isConstructorProperty();
}
}).findProperty(DefaultPropertyNameMatcher.exact(parameter.getName()), columnDefinition.properties());
reader = cellValueReaderFromFactory(property, index, columnDefinition, parsingContextFactoryBuilder);
if (reader != null) {
Instantiator<P, P> instantiator = classMeta.getReflectionService().getInstantiatorFactory().getOneArgIdentityInstantiator(id, classMeta.getReflectionService().builderIgnoresNullValues());
return new InstantiatorOnReader<P, P>(instantiator, reader);
}
}
}
}
return reader;
}
use of org.simpleflatmapper.reflect.Parameter in project SimpleFlatMapper by arnaudroger.
the class AsmFactory method createBiInstantiator.
@SuppressWarnings("unchecked")
public <S1, S2, T> BiInstantiator<S1, S2, T> createBiInstantiator(final Class<?> s1, final Class<?> s2, final InstantiatorDefinition instantiatorDefinition, final Map<Parameter, BiFunction<? super S1, ? super S2, ?>> injections, boolean builderIgnoresNullValues) throws Exception {
BiInstantiatorKey instantiatorKey = new BiInstantiatorKey(instantiatorDefinition, injections, s1, s2);
Class<? extends BiInstantiator<?, ?, ?>> instantiator = biInstantiatorCache.get(instantiatorKey);
Instantiator builderInstantiator = null;
if (instantiator == null) {
final String className = generateClassNameForBiInstantiator(instantiatorKey);
final byte[] bytes;
if (instantiatorDefinition instanceof ExecutableInstantiatorDefinition) {
bytes = BiInstantiatorBuilder.createInstantiator(className, s1, s2, (ExecutableInstantiatorDefinition) instantiatorDefinition, injections);
} else {
builderInstantiator = createInstantiator(Void.class, ((BuilderInstantiatorDefinition) instantiatorDefinition).getBuilderInstantiator(), new HashMap<Parameter, Getter<? super Void, ?>>(), builderIgnoresNullValues);
bytes = BiInstantiatorBuilder.createInstantiator(className, s1, s2, builderInstantiator, (BuilderInstantiatorDefinition) instantiatorDefinition, injections, builderIgnoresNullValues);
}
instantiator = (Class<? extends BiInstantiator<?, ?, ?>>) createClass(className, bytes, instantiatorKey.getDeclaringClass().getClassLoader());
biInstantiatorCache.put(instantiatorKey, instantiator);
}
Map<String, BiFunction<? super S1, ? super S2, ?>> factoryPerName = new HashMap<String, BiFunction<? super S1, ? super S2, ?>>();
for (Entry<Parameter, BiFunction<? super S1, ? super S2, ?>> e : injections.entrySet()) {
factoryPerName.put(e.getKey().getName(), e.getValue());
}
if (instantiatorDefinition instanceof ExecutableInstantiatorDefinition) {
return (BiInstantiator<S1, S2, T>) instantiator.getConstructor(Map.class).newInstance(factoryPerName);
} else {
return (BiInstantiator<S1, S2, T>) instantiator.getConstructor(Map.class, Instantiator.class).newInstance(factoryPerName, builderInstantiator);
}
}
use of org.simpleflatmapper.reflect.Parameter in project SimpleFlatMapper by arnaudroger.
the class AsmInstantiatorDefinitionFactory method extractDefinitions.
public static List<InstantiatorDefinition> extractDefinitions(final Type target) throws IOException {
final List<InstantiatorDefinition> constructors = new ArrayList<InstantiatorDefinition>();
final Class<?> targetClass = TypeHelper.toClass(target);
ClassLoader cl = targetClass.getClassLoader();
if (cl == null) {
cl = ClassLoader.getSystemClassLoader();
}
final String fileName = targetClass.getName().replace('.', '/') + ".class";
final InputStream is = cl.getResourceAsStream(fileName);
try {
if (is == null) {
throw new IOException("Cannot find file " + fileName + " in " + cl);
}
ClassReader classReader = new ClassReader(is);
classReader.accept(new ClassVisitor(Opcodes.ASM5) {
List<String> genericTypeNames;
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
if (signature != null) {
genericTypeNames = AsmUtils.extractGenericTypeNames(signature);
} else {
genericTypeNames = Collections.emptyList();
}
super.visit(version, access, name, signature, superName, interfaces);
}
@Override
public MethodVisitor visitMethod(int access, final String methodName, String desc, String signature, String[] exceptions) {
final boolean isConstructor = "<init>".equals(methodName);
if ((Opcodes.ACC_PUBLIC & access) == Opcodes.ACC_PUBLIC && (isConstructor || ((Opcodes.ACC_STATIC & access) == Opcodes.ACC_STATIC && !desc.endsWith("V")))) {
final List<String> descTypes = AsmUtils.extractTypeNamesFromSignature(desc);
final List<String> genericTypes;
final List<String> names = new ArrayList<String>();
if (signature != null) {
genericTypes = AsmUtils.extractTypeNamesFromSignature(signature);
} else {
genericTypes = descTypes;
}
if (!isConstructor) {
if (descTypes.size() > 0) {
try {
final Type genericType = AsmUtils.toGenericType(descTypes.get(descTypes.size() - 1), genericTypeNames, target);
if (!targetClass.isAssignableFrom(TypeHelper.toClass(genericType))) {
return null;
}
} catch (ClassNotFoundException e) {
return null;
}
} else
return null;
}
return new MethodVisitor(Opcodes.ASM5) {
Label firstLabel;
Label lastLabel;
@Override
public void visitLabel(Label label) {
if (firstLabel == null) {
firstLabel = label;
}
lastLabel = label;
}
@Override
public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) {
if (start.equals(firstLabel) && end.equals(lastLabel) && !"this".equals(name)) {
names.add(name);
}
}
@Override
public void visitEnd() {
try {
final List<Parameter> parameters = new ArrayList<Parameter>();
int l = descTypes.size() - (isConstructor ? 0 : 1);
for (int i = 0; i < l; i++) {
String name = "arg" + i;
if (i < names.size()) {
name = names.get(i);
}
parameters.add(createParameter(i, name, descTypes.get(i), genericTypes.get(i)));
}
final Member executable;
if (isConstructor) {
executable = targetClass.getDeclaredConstructor(toTypeArray(parameters));
} else {
executable = targetClass.getDeclaredMethod(methodName, toTypeArray(parameters));
}
constructors.add(new ExecutableInstantiatorDefinition(executable, parameters.toArray(new Parameter[0])));
} catch (Exception e) {
ErrorHelper.rethrow(e);
}
}
private Class<?>[] toTypeArray(List<Parameter> parameters) {
Class<?>[] types = new Class<?>[parameters.size()];
for (int i = 0; i < types.length; i++) {
types[i] = parameters.get(i).getType();
}
return types;
}
private Parameter createParameter(int index, String name, String desc, String signature) {
try {
Type basicType = AsmUtils.toGenericType(desc, genericTypeNames, target);
Type genericType = basicType;
if (signature != null) {
Type type = AsmUtils.toGenericType(signature, genericTypeNames, target);
if (type != null) {
genericType = type;
}
}
return new Parameter(index, name, TypeHelper.toClass(basicType), genericType);
} catch (ClassNotFoundException e) {
throw new Error("Unexpected error " + e, e);
}
}
};
} else {
return null;
}
}
}, 0);
} finally {
if (is != null) {
try {
is.close();
} catch (Exception e) {
}
}
}
return constructors;
}
use of org.simpleflatmapper.reflect.Parameter in project SimpleFlatMapper by arnaudroger.
the class BiInstantiatorBuilder method appendNewInstance.
private static <S1, S2> void appendNewInstance(Class<?> s1, Class<?> s2, ExecutableInstantiatorDefinition instantiatorDefinition, List<InjectionPoint> injectionPoints, ClassWriter cw, String targetType, String s1Type, String s2Type, String classType, Parameter[] parameters) throws NoSuchMethodException {
MethodVisitor mv;
mv = cw.visitMethod(ACC_PUBLIC, "newInstance", "(" + AsmUtils.toTargetTypeDeclaration(s1Type) + AsmUtils.toTargetTypeDeclaration(s2Type) + ")" + AsmUtils.toTargetTypeDeclaration(targetType), null, new String[] { "java/lang/Exception" });
mv.visitCode();
mv.visitTypeInsn(NEW, targetType);
mv.visitInsn(DUP);
StringBuilder sb = new StringBuilder();
for (Parameter p : parameters) {
InjectionPoint function = findFunctionCalls(p, injectionPoints);
sb.append(AsmUtils.toTargetTypeDeclaration(p.getType()));
if (function == null) {
newInstanceNullFunction(mv, p);
} else {
invokeBiFunction(function, classType, s1, s2, mv, null, false);
}
}
Member exec = instantiatorDefinition.getExecutable();
if (exec instanceof Constructor) {
mv.visitMethodInsn(INVOKESPECIAL, targetType, "<init>", "(" + sb.toString() + ")V", false);
} else {
mv.visitMethodInsn(INVOKESTATIC, AsmUtils.toAsmType(((Method) exec).getDeclaringClass()), exec.getName(), AsmUtils.toSignature((Method) exec), false);
}
mv.visitInsn(ARETURN);
mv.visitMaxs(3, 2);
mv.visitEnd();
}
Aggregations