Search in sources :

Example 1 with AnnotatedMethod

use of io.jmix.ui.sys.UiControllerReflectionInspector.AnnotatedMethod in project jmix by jmix-framework.

the class UiControllerDependencyInjector method initInstallMethods.

protected void initInstallMethods(FrameOwner frameOwner, ScreenIntrospectionData screenIntrospectionData) {
    List<AnnotatedMethod<Install>> installMethods = screenIntrospectionData.getInstallMethods();
    for (AnnotatedMethod<Install> annotatedMethod : installMethods) {
        Install annotation = annotatedMethod.getAnnotation();
        Frame frame = UiControllerUtils.getFrame(frameOwner);
        Object targetInstance = getInstallTargetInstance(frameOwner, annotation, frame);
        if (targetInstance == null) {
            if (annotation.required()) {
                throw new DevelopmentException(String.format("Unable to find @Install target for method %s in %s", annotatedMethod.getMethod(), frameOwner.getClass()));
            }
            log.trace("Skip @Install method {} of {} : it is not required and target not found", annotatedMethod.getMethod().getName(), frameOwner.getClass());
            continue;
        }
        Class<?> instanceClass = targetInstance.getClass();
        Method installMethod = annotatedMethod.getMethod();
        MethodHandle targetSetterMethod = getInstallTargetSetterMethod(annotation, frame, instanceClass, installMethod);
        Class<?> targetParameterType = targetSetterMethod.type().parameterList().get(1);
        Object handler = null;
        if (targetInstance instanceof InstallTargetHandler) {
            handler = ((InstallTargetHandler) targetInstance).createInstallHandler(targetParameterType, frameOwner, installMethod);
        }
        if (handler == null) {
            handler = createInstallHandler(frameOwner, installMethod, targetParameterType);
        }
        try {
            targetSetterMethod.invoke(targetInstance, handler);
        } catch (Error e) {
            throw e;
        } catch (Throwable e) {
            throw new RuntimeException("Unable to set declarative @Install handler for " + installMethod, e);
        }
    }
}
Also used : AnnotatedMethod(io.jmix.ui.sys.UiControllerReflectionInspector.AnnotatedMethod) AnnotatedMethod(io.jmix.ui.sys.UiControllerReflectionInspector.AnnotatedMethod) DevelopmentException(io.jmix.core.DevelopmentException) MethodHandle(java.lang.invoke.MethodHandle)

Example 2 with AnnotatedMethod

use of io.jmix.ui.sys.UiControllerReflectionInspector.AnnotatedMethod in project jmix by jmix-framework.

the class UiControllerDependencyInjector method initSubscribeListeners.

protected void initSubscribeListeners(FrameOwner frameOwner, ScreenIntrospectionData screenIntrospectionData) {
    Class<? extends FrameOwner> clazz = frameOwner.getClass();
    List<AnnotatedMethod<Subscribe>> eventListenerMethods = screenIntrospectionData.getSubscribeMethods();
    Frame frame = UiControllerUtils.getFrame(frameOwner);
    ScreenData screenData = getScreenData(frameOwner);
    for (AnnotatedMethod<Subscribe> annotatedMethod : eventListenerMethods) {
        Method method = annotatedMethod.getMethod();
        Subscribe annotation = annotatedMethod.getAnnotation();
        String target = UiDescriptorUtils.getInferredSubscribeId(annotation);
        Parameter parameter = method.getParameters()[0];
        Class<?> eventType = parameter.getType();
        Object eventTarget = null;
        if (Strings.isNullOrEmpty(target)) {
            switch(annotation.target()) {
                // if kept default value
                case COMPONENT:
                case CONTROLLER:
                    eventTarget = frameOwner;
                    break;
                case FRAME:
                    eventTarget = frame;
                    break;
                case PARENT_CONTROLLER:
                    if (frameOwner instanceof Screen) {
                        throw new DevelopmentException(String.format("Screen %s cannot use @Subscribe with target = PARENT_CONTROLLER", frame.getId()));
                    }
                    eventTarget = ((ScreenFragment) frameOwner).getHostController();
                    break;
                case DATA_CONTEXT:
                    eventTarget = screenData.getDataContext();
                    break;
                default:
                    throw new UnsupportedOperationException("Unsupported @Subscribe target " + annotation.target());
            }
        } else {
            switch(annotation.target()) {
                case CONTROLLER:
                    Object componentTarget = findMethodTarget(frame, target);
                    if (!(componentTarget instanceof Fragment)) {
                        throw new UnsupportedOperationException("Unsupported @Subscribe target " + annotation.target() + ". It is not a Fragment.");
                    }
                    eventTarget = ((Fragment) componentTarget).getFrameOwner();
                    break;
                case COMPONENT:
                    // component event
                    eventTarget = findMethodTarget(frame, target);
                    break;
                case DATA_LOADER:
                    if (screenData.getLoaderIds().contains(target)) {
                        eventTarget = screenData.getLoader(target);
                    }
                    break;
                case DATA_CONTAINER:
                    if (screenData.getContainerIds().contains(target)) {
                        eventTarget = screenData.getContainer(target);
                    }
                    break;
                default:
                    throw new UnsupportedOperationException("Unsupported @Subscribe target " + annotation.target());
            }
        }
        if (eventTarget == null) {
            if (annotation.required()) {
                throw new DevelopmentException(String.format("Unable to find @Subscribe target %s in %s", target, frame.getId()));
            }
            log.trace("Skip @Subscribe method {} of {} : it is not required and target not found", annotatedMethod.getMethod().getName(), frameOwner.getClass());
            continue;
        }
        Consumer listener;
        // in Java 17+
        if (SystemUtils.isJavaVersionAtMost(JavaVersion.JAVA_16) || getClass().getClassLoader() == frameOwner.getClass().getClassLoader()) {
            MethodHandle consumerMethodFactory = reflectionInspector.getConsumerMethodFactory(clazz, annotatedMethod, eventType);
            try {
                listener = (Consumer) consumerMethodFactory.invoke(frameOwner);
            } catch (Error e) {
                throw e;
            } catch (Throwable e) {
                throw new RuntimeException("Unable to bind consumer handler", e);
            }
        } else {
            listener = event -> {
                try {
                    annotatedMethod.getMethodHandle().invoke(frameOwner, event);
                } catch (Throwable e) {
                    throw new RuntimeException("Error subscribe listener method invocation", e);
                }
            };
        }
        MethodHandle addListenerMethod = reflectionInspector.getAddListenerMethod(eventTarget.getClass(), eventType);
        if (addListenerMethod == null) {
            throw new DevelopmentException(String.format("Target %s does not support event type %s", eventTarget.getClass().getName(), eventType));
        }
        try {
            addListenerMethod.invoke(eventTarget, listener);
        } catch (Error e) {
            throw e;
        } catch (Throwable e) {
            throw new RuntimeException("Unable to add listener" + method, e);
        }
    }
}
Also used : AnnotatedMethod(io.jmix.ui.sys.UiControllerReflectionInspector.AnnotatedMethod) AnnotatedMethod(io.jmix.ui.sys.UiControllerReflectionInspector.AnnotatedMethod) DevelopmentException(io.jmix.core.DevelopmentException) Consumer(java.util.function.Consumer) UiControllerUtils.getScreenData(io.jmix.ui.screen.UiControllerUtils.getScreenData) ScreenData(io.jmix.ui.model.ScreenData) MethodHandle(java.lang.invoke.MethodHandle)

Aggregations

DevelopmentException (io.jmix.core.DevelopmentException)2 AnnotatedMethod (io.jmix.ui.sys.UiControllerReflectionInspector.AnnotatedMethod)2 MethodHandle (java.lang.invoke.MethodHandle)2 ScreenData (io.jmix.ui.model.ScreenData)1 UiControllerUtils.getScreenData (io.jmix.ui.screen.UiControllerUtils.getScreenData)1 Consumer (java.util.function.Consumer)1