package org.test4j.datafilling.filler.pojo;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.test4j.datafilling.Filler;
import org.test4j.datafilling.common.AttributeInfo;
import org.test4j.datafilling.filler.PoJoFiller;
import org.test4j.datafilling.strategy.DataFactory;
import org.test4j.module.core.utility.MessageHelper;
public class FactoryMethodFiller extends PoJoFiller {
public FactoryMethodFiller(DataFactory strategy, Map<String, Type> argsTypeMap) {
super(strategy, argsTypeMap);
}
/**
* If no publicly accessible constructors are available, the best we can do
* is to find a constructor (e.g. getInstance())<br>
* A candidate factory method is a method which returns the Class type
*
* @param clazz
* @param typeArgsMap
* @param genericTypeArgs
* @return
* @throws Exception
*/
public Object newInstanceUseFactoryMethod(AttributeInfo attrinbute) throws Exception {
List<Method> factoryMethods = attrinbute.getFactoryMethods();
for (Method method : factoryMethods) {
Object[] parameterValues = getMethodParaValues(attrinbute, method);
try {
MessageHelper.info("Could create an instance using " + method);
return method.invoke(attrinbute.getAttrClaz(), parameterValues);
} catch (Throwable t) {
MessageHelper.warn("Could not create an instance for constructor: " + method
+ ". Will try another one...");
}
}
return null;
}
private Object[] getMethodParaValues(AttributeInfo attrinbute, Method method) throws Exception {
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
Type[] parameterTypes = method.getGenericParameterTypes();
Object[] parameterValues = new Object[method.getParameterTypes().length];
int index = 0;
for (Type paramType : parameterTypes) {
List<Annotation> annotations = Arrays.asList(parameterAnnotations[index]);
AttributeInfo paraAttribute = AttributeInfo.exactArgAttributeInfo(paramType, argsTypeMap);
paraAttribute.setAttrAnnotations(annotations);
Object paraInstance = new Filler(this.strategy, argsTypeMap).fillingAttribute(paraAttribute);
parameterValues[index] = paraInstance;
index++;
}
return parameterValues;
}
}