Package ch.nerdin.generators.testdata

Source Code of ch.nerdin.generators.testdata.BeanFactory

package ch.nerdin.generators.testdata;

import ch.nerdin.generators.testdata.framework.FieldProperty;
import ch.nerdin.generators.testdata.framework.RandomUtil;
import ch.nerdin.generators.testdata.framework.analyzer.ReturnTypeAnalyzers;
import ch.nerdin.generators.testdata.framework.annotation.CreateTestData;
import ch.nerdin.generators.testdata.inspector.FieldContext;
import ch.nerdin.generators.testdata.inspector.InspectionCatalog;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.chain.Catalog;
import org.apache.commons.chain.Command;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.beans.PropertyDescriptor;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.*;

/**
* Gathers the meta data for the bean to be generated and then delegates the work to instantiate the bean
* and set the values to the BeanBuilder.
*/
@Service
public class BeanFactory {

    private InspectionCatalog catalog;

    @Autowired
    private List<ReturnTypeAnalyzers> returnTypeAnalyzers;

    @Autowired
    private BeanBuilder beanBuilder;

    @Autowired
    private RandomUtil randomUtil;

    @PostConstruct
    public void init() throws Exception {
        catalog = new InspectionCatalog();
        catalog.loadCatalog();
    }

    public Object instantiateBeans(Method method) {
        Object createObject;
        CreateTestData testData = getAnnotation(method);
        int randomSize = randomUtil.randomBetween(testData.min(), testData.max());

        if (Collection.class.isAssignableFrom(method.getReturnType())) {
            Collection collection = newInstance(testData.collectionType());
            for (int i = 0; i < randomSize; i++) {
                collection.add(instantiateBean(method));
            }

            createObject = collection;
        } else if (Map.class.isAssignableFrom(method.getReturnType())) {
            Map map = newInstance(testData.mapType());
            for (int i = 0; i < randomSize; i++) {
                Class<?>[] types = findReturnType(method);
                map.put(instantiateType(types[0]), instantiateType(types[1]));
            }
            createObject = map;
        } else {
            createObject = instantiateBean(method);
        }

        return createObject;
    }

    private Object instantiateType(Class<?> type) {
        return isComplexType(type) ? instantiateBean(type)
                : beanBuilder.instantiateValueForField(new FieldProperty(type));
    }

    private <T> T newInstance(Class<T> collectionType) {
        try {
            return collectionType.newInstance();
        } catch (Exception e) {
            throw new IllegalArgumentException("could not create new instance for collection '" + collectionType
                    + "' check you annotation settings", e);
        }
    }

    public <T> T instantiateBean(Class<T> beanClass) {
        if (!beanBuilder.canProxyBean(beanClass)) {
            return recurseComplexFields(beanClass);
        }

        return beanBuilder.buildBean(beanClass, inspectBean(beanClass));
    }

    private <T> T recurseComplexFields(Class<T> beanClass) {
        Map<String, FieldProperty> fieldProperties = inspectBean(beanClass);
        T bean = beanBuilder.buildBean(beanClass, fieldProperties);
        for (Map.Entry<String, FieldProperty> entry : fieldProperties.entrySet()) {
            Class<?> type = entry.getValue().getType();
            if (isComplexType(type)) {
                try {
                    PropertyDescriptor descriptor = PropertyUtils.getPropertyDescriptor(bean, entry.getKey());
                    beanBuilder.setFieldValue(bean, type, entry.getKey(), instantiateBeans(descriptor.getReadMethod()));
                } catch (Exception e) {
                    //TODO another...
                }
            }
        }
        return bean;
    }

    private boolean isComplexType(Class<?> type) {
        return !(type.getName().startsWith("java.lang") || type.isPrimitive() || type.isEnum());
    }

    private Map<String, FieldProperty> inspectBean(Class<?> type) {
        Map<String, FieldProperty> fieldProperties = new HashMap<String, FieldProperty>();
        Catalog generators = catalog.getCatalog();
        Command inspectorChain = generators.getCommand("InspectorChain");
        FieldContext context = new FieldContext(fieldProperties, type);
        try {
            inspectorChain.execute(context);
        } catch (Exception e) {
            //TODO what now?
        }

        return fieldProperties;
    }

    private Class<?>[] findReturnType(Method method) {
        Class<?>[] foundClass = null;
        Iterator<ReturnTypeAnalyzers> iter = returnTypeAnalyzers.iterator();
        while (foundClass == null && iter.hasNext()) {
            ReturnTypeAnalyzers analyzer = iter.next();
            foundClass = analyzer.findClass(method);
        }

        return foundClass;
    }

    private Object instantiateBean(Method method) {
        Object object = null;
        Class<?>[] returnType = findReturnType(method);
        if (returnType != null) {
            //TODO maps
            object = instantiateBean(returnType[0]);
        }
        return object;
    }

    Object proxyBean(Class<?> bean, String pattern) {
        return beanBuilder.proxyBean(bean, pattern);
    }

    private CreateTestData getAnnotation(Method method) {
        if (method.isAnnotationPresent(CreateTestData.class)) {
            return method.getAnnotation(CreateTestData.class);
        }

        return DEFAULT_DATA_SETTINGS;
    }

    private static final CreateTestData DEFAULT_DATA_SETTINGS = new CreateTestData() {

        public int min() {
            return 50;
        }

        public int max() {
            return 50;
        }

        public Class<? extends Collection> collectionType() {
            return ArrayList.class;
        }

        public Class<? extends Map> mapType() {
            return HashMap.class;
        }

        public Class<? extends Annotation> annotationType() {
            return CreateTestData.class;
        }
    };

}
TOP

Related Classes of ch.nerdin.generators.testdata.BeanFactory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.