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

info.novatec.testit.webtester.internal.postconstruct.PostConstructMustBeChecker Maven / Gradle / Ivy

package info.novatec.testit.webtester.internal.postconstruct;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;

import lombok.experimental.UtilityClass;

import info.novatec.testit.webtester.conditions.Condition;
import info.novatec.testit.webtester.internal.exceptions.IllegalSignatureException;
import info.novatec.testit.webtester.pagefragments.PageFragment;
import info.novatec.testit.webtester.pagefragments.annotations.IdentifyUsing;
import info.novatec.testit.webtester.pagefragments.annotations.PostConstructMustBe;
import info.novatec.testit.webtester.pages.Page;


@UtilityClass
public class PostConstructMustBeChecker {

    private static final String ILLEGAL_SIGNATURE_MSG =
        "invalid @PostConstructMustBe method declarations (must not have parameters): ";

    private static Predicate isIdentificationMethod = method -> method.isAnnotationPresent(IdentifyUsing.class);
    private static Predicate isMustMethod = method -> method.isAnnotationPresent(PostConstructMustBe.class);
    private static Predicate isRelevantMethod = isIdentificationMethod.and(isMustMethod);
    private static Predicate hasNoParams = method -> method.getParameterCount() == 0;
    private static Predicate isValidMethod = hasNoParams;

    public static void checkMustMethods(Class pageClass, Page page) {
        // NOTE: since page is a proxy, the original class needs to be provided from outside!
        doInvokeMustMethods(pageClass, page);
    }

    public static void checkMustMethods(Class pageFragmentClass, PageFragment pageFragment) {
        // NOTE: since pageFragment is a proxy, the original class needs to be provided from outside!
        doInvokeMustMethods(pageFragmentClass, pageFragment);
    }

    private static void doInvokeMustMethods(Class objectClass, Object object) {

        List mustMethods = getMustMethods(objectClass);
        assertThatAllMethodsHaveValidSignature(mustMethods);

        Map singularMethods = new HashMap<>();
        mustMethods.forEach(method -> singularMethods.put(method.getName(), method));

        singularMethods.values().forEach(method -> invoke(method, object));

    }

    private static List getMustMethods(Class objectClass) {
        List mustMethods = new ArrayList<>();
        Arrays.stream(objectClass.getInterfaces())
            .flatMap(aClass -> Arrays.stream(aClass.getDeclaredMethods()))
            .filter(isRelevantMethod)
            .forEach(mustMethods::add);
        Arrays.stream(objectClass.getDeclaredMethods()).filter(isRelevantMethod).forEach(mustMethods::add);
        return mustMethods;
    }

    private static void assertThatAllMethodsHaveValidSignature(List mustMethods) {
        List illegalMethods = new ArrayList<>();
        mustMethods.forEach(method -> {
            if (!isValidMethod.test(method)) {
                illegalMethods.add(method);
            }
        });
        if (!illegalMethods.isEmpty()) {
            throw new IllegalSignatureException(ILLEGAL_SIGNATURE_MSG + illegalMethods);
        }
    }

    private static void invoke(Method method, Object object) {
        try {
            PostConstructMustBe annotation = method.getAnnotation(PostConstructMustBe.class);
            Object fragment = method.invoke(object);
            Condition condition = annotation.value().newInstance();
            if (!doInvoke(fragment, condition)) {
                throw new PostConstructMustBeConditionException(
                    "condition not met for method (" + method + "): " + condition);
            }
        } catch (IllegalAccessException | InvocationTargetException | InstantiationException | ClassCastException e) {
            throw new PostConstructMustBeConditionException(e);
        }
    }

    @SuppressWarnings("unchecked")
    private static boolean doInvoke(Object fragment, Condition condition) {
        try {
            return condition.test(fragment);
        } catch (ClassCastException e) {
            throw new PostConstructMustBeConditionException(
                "Condition '" + name(condition) + "' can't handle type '" + name(fragment) + "'!");
        }
    }

    private static String name(Object object) {
        return object.getClass().getSimpleName();
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy