All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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