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

org.khasanof.executors.invoker.InvokerExecutor Maven / Gradle / Ivy

There is a newer version: 1.2.2
Show newest version
package org.khasanof.executors.invoker;

import org.khasanof.annotation.exception.HandleException;
import org.khasanof.collector.Collector;
import org.khasanof.custom.FluentContext;
import org.khasanof.event.MethodV1Event;
import org.khasanof.exceptions.InvalidParamsException;
import org.khasanof.model.SampleModel;
import org.khasanof.model.InvokerResult;
import org.khasanof.utils.MethodUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;
import org.telegram.telegrambots.meta.api.objects.Update;
import org.telegram.telegrambots.meta.bots.AbsSender;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author Nurislom
 * @see org.khasanof.executors.invoker
 * @since 16.07.2023 15:01
 */
@Component
public class InvokerExecutor implements Invoker {

    private final Collector> collector;
    private final InvokerFunctions invokerFunctions;
    private final InvokerResultService resultService;
    private final ApplicationEventPublisher applicationEventPublisher;

    public InvokerExecutor(Collector> collector, InvokerFunctionsImpl invokerFunctions, InvokerResultService resultService, ApplicationEventPublisher applicationEventPublisher) {
        this.collector = collector;
        this.invokerFunctions = invokerFunctions;
        this.resultService = resultService;
        this.applicationEventPublisher = applicationEventPublisher;
    }

    @Override
    public void invoke(SampleModel invokerModelV2) {
        try {
            absInvoker(invokerModelV2);
        } catch (InstantiationException | IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            try {
                exceptionDirector(e.getCause(), invokerModelV2);
                FluentContext.updateExecutorBoolean.set(true);
            } catch (Throwable ex) {
                throw new RuntimeException(ex);
            }
        }
    }

    private void absInvoker(SampleModel invokerModel) throws InstantiationException, IllegalAccessException, InvocationTargetException {
        if (Objects.isNull(invokerModel.getAdditionalParam())) {
            checkListParams(invokerModel.getMethodParams(), invokerModel.getArgs());
        }

        Map.Entry classEntry = resultService.getResultEntry(invokerModel.getInvokerReference());
        Method method = classEntry.getKey();
        method.setAccessible(true);

        if (invokerModel.isCanBeNoParam() && method.getParameterCount() == 0) {
            method.invoke(classEntry.getValue());
        } else {
            pushEvent(invokerModel, classEntry, method);
        }
    }

    private void pushEvent(SampleModel invokerModel, Map.Entry classEntry, Method method) {
        applicationEventPublisher.publishEvent(new MethodV1Event(this, invokerModel, classEntry, method));
    }

    private void checkListParams(List> params, Object[] args) {
        boolean allMatch = Arrays.stream(args).allMatch(arg -> params.contains(arg.getClass()) || params.stream()
                .anyMatch(any -> any.isAssignableFrom(arg.getClass())));
        if (!allMatch) {
            throw new InvalidParamsException("Param type doesn't match expected param!");
        }
    }

    private void exceptionDirector(Throwable throwable, SampleModel prevInvoker) throws Throwable {
        InvokerResult exceptionHandleMethod = getExceptionHandleMethod(throwable);
        if (Objects.isNull(exceptionHandleMethod)) {
            throw throwable;
        }
        SampleModel invokerModel = invokerFunctions.fillAndGet(exceptionHandleMethod, throwable,
                MethodUtils.getArg(prevInvoker.getArgs(), Update.class), MethodUtils.getArg(
                        prevInvoker.getArgs(), AbsSender.class));
        invoke(invokerModel);
    }

    private InvokerResult getExceptionHandleMethod(Throwable throwable) throws Throwable {
        if (collector.hasHandle(HandleException.class)) {
            return collector.getInvokerResult(throwable, HandleException.class);
        }
        throw throwable;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy