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

com.fitbur.mockito.internal.creation.instance.ConstructorInstantiator Maven / Gradle / Ivy

There is a newer version: 1.0.0
Show newest version
package com.fitbur.mockito.internal.creation.instance;

import static com.fitbur.mockito.internal.util.StringJoiner.join;
import java.lang.reflect.Constructor;
import com.fitbur.mockito.internal.util.reflection.AccessibilityChanger;

public class ConstructorInstantiator implements Instantiator {

    private final Object outerClassInstance;

    public ConstructorInstantiator(Object outerClassInstance) {
        this.outerClassInstance = outerClassInstance;
    }

    public  T newInstance(Class cls) {
        if (outerClassInstance == null) {
            return noArgConstructor(cls);
        }
        return withParams(cls, outerClassInstance);
    }

    private static  T withParams(Class cls, Object... params) {
        try {
            //this is kind of over-engineered because we don't need to support more params
            //however, I know we will be needing it :)
            for (Constructor constructor : cls.getDeclaredConstructors()) {
                Class[] types = constructor.getParameterTypes();
                if (paramsMatch(types, params)) {
                    return invokeConstructor(constructor, params);
                }
            }
        } catch (Exception e) {
            throw paramsException(cls, e);
        }
        throw paramsException(cls, null);
    }

    @SuppressWarnings("unchecked")
    private static  T invokeConstructor(Constructor constructor, Object... params) throws java.lang.InstantiationException, IllegalAccessException, java.lang.reflect.InvocationTargetException {
        AccessibilityChanger accessibility = new AccessibilityChanger();
        accessibility.enableAccess(constructor);
        return (T) constructor.newInstance(params);
    }

    private static  InstantiationException paramsException(Class cls, Exception e) {
        return new InstantiationException(join(
                "Unable to create instance of '" + cls.getSimpleName() + "'.",
                "Please ensure that the outer instance has correct type and that the target class has 0-arg constructor.")
                , e);
    }

    private static boolean paramsMatch(Class[] types, Object[] params) {
        if (params.length != types.length) {
            return false;
        }
        for (int i = 0; i < params.length; i++) {
            if (!types[i].isInstance(params[i])) {
                return false;
            }
        }
        return true;
    }

    private static  T noArgConstructor(Class cls) {
        try {
            return invokeConstructor(cls.getDeclaredConstructor());
        } catch (Throwable t) {
            throw new InstantiationException(join(
                    "Unable to create instance of '" + cls.getSimpleName() + "'.",
                    "Please ensure it has 0-arg constructor which invokes cleanly."),
                    t);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy