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

io.soffa.foundation.core.operation.OperationsMapping Maven / Gradle / Ivy

The newest version!
package io.soffa.foundation.core.operation;

import io.soffa.foundation.annotations.Handle;
import io.soffa.foundation.commons.TextUtil;
import io.soffa.foundation.core.Operation;
import io.soffa.foundation.core.RequestContext;
import io.soffa.foundation.errors.TechnicalException;
import lombok.Getter;
import lombok.SneakyThrows;
import org.springframework.aop.framework.Advised;
import org.springframework.aop.support.AopUtils;

import java.lang.reflect.Method;
import java.util.*;

@Getter
public class OperationsMapping {

    private final Set> registry;
    // private final Set> registry0;
    private final Map internal = new HashMap<>();
    private final Map> inputTypes = new HashMap<>();

    public OperationsMapping(Set> registry) {
        this.registry = registry;
        register(registry);
    }

    @SneakyThrows
    private Class resolveClass(Object op) {
        Class targetClass = op.getClass();
        if (AopUtils.isAopProxy(op) && op instanceof Advised) {
            Object target = ((Advised) op).getTargetSource().getTarget();
            targetClass = Objects.requireNonNull(target).getClass();
        }
        return targetClass;
    }

    private Optional registerAnyBinding(Class targetClass, Object operation) {
        String bindingName = null;
        Handle binding = targetClass.getAnnotation(Handle.class);
        if (binding != null) {
            if (TextUtil.isEmpty(binding.value())) {
                throw new TechnicalException("@BindOperation on a type should have the property name set.");
            }
            bindingName = binding.value();
            internal.put(binding.value(), operation);
        }
        return Optional.ofNullable(bindingName);
    }

    @SneakyThrows
    private void register(Set operations) {
        for (Object operation : operations) {
            Class targetClass = resolveClass(operation);
            String bindingName = registerAnyBinding(targetClass, operation).orElse(null);

            for (Class intf : targetClass.getInterfaces()) {
                if (Operation.class.isAssignableFrom(intf)) {
                    Method method = Arrays.stream(operation.getClass().getMethods())
                        .filter(m -> "handle".equals(m.getName()) && 2 == m.getParameterCount() && m.getParameterTypes()[1] == RequestContext.class)
                        .findFirst().orElseThrow(() -> new TechnicalException("Invalid operation definition"));

                    if (intf != Operation.class) {
                        register(intf, operation, method, bindingName);
                    }else {
                        register(targetClass, operation, method, bindingName);
                    }
                    break;
                }
            }
        }
    }

    private void register(Class target, Object operation, Method method, String bindingName) {
        internal.put(target.getSimpleName(), operation);
        internal.put(target.getName(), operation);


        Class inputType = method.getParameterTypes()[0];
        inputTypes.put(target.getSimpleName(), inputType);
        inputTypes.put(target.getName(), inputType);

        if (bindingName!=null) {
            inputTypes.put(bindingName, inputType);
        }

    }



}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy