package org.test4j.datafilling.filler;
import java.lang.reflect.Constructor;
import java.lang.reflect.Type;
import java.util.Map;
import org.test4j.datafilling.Filler;
import org.test4j.datafilling.common.AttributeInfo;
import org.test4j.datafilling.common.ClassFieldInfo;
import org.test4j.datafilling.exceptions.PoJoFillException;
import org.test4j.datafilling.filler.pojo.ConstructorFiller;
import org.test4j.datafilling.filler.pojo.FactoryMethodFiller;
import org.test4j.datafilling.filler.pojo.SetterMethodFiller;
import org.test4j.datafilling.strategy.DataFactory;
/**
* PoJo对象填充器
*
* @author darui.wudr
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public class PoJoFiller extends Filler {
public PoJoFiller(DataFactory strategy, Map<String, Type> argsTypeMap) {
super(strategy, argsTypeMap);
}
/**
* Generic method which returns an instance of the given class filled with
* dummy values
*
* @param pojoAttr The generic type arguments for the current generic class
* instance
* @param depth How many times {@code dtoClass} has been found
* @return An instance of <T> filled with dummy values
* @throws PoJoFillException if a problem occurred while creating a POJO
* instance or while setting its state
*/
public <T> T fillingPoJo(AttributeInfo pojoAttr, int depth) throws PoJoFillException {
try {
ClassFieldInfo classInfo = pojoAttr.getClassInfo();
final Map<String, Type> typeArgsMap = pojoAttr.getArgsTypeMap();
if (classInfo.getClassSetters().isEmpty() || pojoAttr.isJavax()) {
Object o = fillingWithConstructorsOrFactory(pojoAttr);
return (T) o;
} else {
SetterMethodFiller filler = new SetterMethodFiller(this.strategy, typeArgsMap);
Object o = filler.fillingWithSetter(pojoAttr, depth);
return (T) o;
}
} catch (Exception e) {
throw new PoJoFillException("An filling exception occurred:" + e.getMessage(), e);
}
}
/**
* It attempts to create an instance of the given class<br>
* 使用工厂方法创建实例对象
* <p>
* This method attempts to create an instance of the given argument for
* classes without setters. These may be either immutable classes (e.g. with
* final attributes and no setters) or Java classes (e.g. belonging to the
* java / javax namespace).<br>
* In case the class does not provide a public, no-arg constructor (e.g.
* Calendar), this method attempts to find a , no-args, factory method (e.g.
* getInstance()) and it invokes it
* </p>
*
* @param clazz The class for which a new instance is required
* @return An instance of the given class
* @throws Exception
*/
public Object fillingWithConstructorsOrFactory(AttributeInfo attrinbuteInfo) throws Exception {
Constructor[] constructors = attrinbuteInfo.getPublicConstructor();
if (constructors.length == 0) {
FactoryMethodFiller filler = new FactoryMethodFiller(strategy, null);
Object o = filler.newInstanceUseFactoryMethod(attrinbuteInfo);
return o;
} else {
ConstructorFiller filler = new ConstructorFiller(strategy, null);
Object o = filler.fillingWithPublicConstructor(attrinbuteInfo.getAttrClaz(), constructors);
return o;
}
}
}