
com.github.nill14.utils.init.impl.MethodPojoFactory Maven / Gradle / Ivy
The newest version!
package com.github.nill14.utils.init.impl;
import java.lang.reflect.Method;
import java.util.Collection;
import com.github.nill14.utils.init.api.IBeanDescriptor;
import com.github.nill14.utils.init.api.IMemberDescriptor;
import com.github.nill14.utils.init.api.IParameterType;
import com.github.nill14.utils.init.api.IPojoFactory;
import com.github.nill14.utils.init.api.IPropertyResolver;
import com.github.nill14.utils.init.inject.MethodInjectionDescriptor;
import com.github.nill14.utils.init.inject.PojoInjectionDescriptor;
import com.google.common.reflect.TypeToken;
public final class MethodPojoFactory implements IPojoFactory {
public static MethodPojoFactory of(TypeToken typeToken, Method method, Object instance) {
return new MethodPojoFactory(typeToken, method, instance);
}
private static final long serialVersionUID = 1L;
private final TypeToken typeToken;
/** Cache the beanDescriptor */
private IBeanDescriptor beanDescriptor;
private final Object instance;
private final MethodInjectionDescriptor member;
public MethodPojoFactory(TypeToken typeToken, Method m, Object instance) {
this.typeToken = typeToken;
this.instance = instance;
member = new MethodInjectionDescriptor(m, m.getDeclaringClass());
}
@Override
public T newInstance(IPropertyResolver resolver, CallerContext context) {
T instance = injectMethod(resolver, context);
if (instance != null) {
//take the descriptor of the real instance type, not of the published superclass
PojoInjectionDescriptor> descriptor = new PojoInjectionDescriptor<>(instance.getClass());
resolver.initializeBean(descriptor, instance, context);
}
return instance;
}
@Override
public TypeToken getType() {
return typeToken;
}
@Override
public IBeanDescriptor getDescriptor() {
//avoiding synchronization on purpose
IBeanDescriptor h = beanDescriptor;
if (h == null) {
h = new PojoInjectionDescriptor<>(typeToken);
beanDescriptor = h;
}
return h;
}
public IMemberDescriptor getMethodDescriptor() {
return member;
}
@SuppressWarnings("unchecked")
public T injectMethod(IPropertyResolver resolver, CallerContext context) {
try {
Object[] args = createArgs(resolver, member.getParameterTypes(), context);
return (T) member.invoke(instance, args);
} catch (ReflectiveOperationException | RuntimeException e) {
throw new RuntimeException(String.format(
"Cannot inject %s", member), e);
}
}
private Object[] createArgs(IPropertyResolver resolver, Collection types, CallerContext context) {
if (types.isEmpty()) {
return null;
}
Object[] args = new Object[types.size()];
int i = 0;
for (IParameterType type : types) {
Object arg = resolver.resolve(type, context);
if (null == arg && !type.isNullable()) {
throw new RuntimeException(String.format("Cannot resolve property %s", type.getToken()));
}
args[i++] = arg;
}
return args;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy