Search in sources :

Example 16 with DevelopmentException

use of io.jmix.core.DevelopmentException in project jmix by jmix-framework.

the class ActionCustomPropertyLoader method load.

public void load(Action instance, String propertyName, String stringValue) {
    String setterName = "set" + StringUtils.capitalize(propertyName);
    try {
        Method method = Arrays.stream(instance.getClass().getMethods()).filter(m -> m.getName().equals(setterName) && m.getParameterCount() == 1).findAny().orElseThrow(() -> new DevelopmentException("Unable to set action property '" + propertyName + "': cannot find setter method with single parameter"));
        Class<?> parameterType = method.getParameterTypes()[0];
        Type genericParameterType = method.getGenericParameterTypes()[0];
        Object value = parseStringValue(stringValue, parameterType, genericParameterType);
        method.invoke(instance, value);
    } catch (IllegalAccessException | InvocationTargetException e) {
        throw new DevelopmentException("Unable to set action property '" + propertyName + "': " + e);
    }
}
Also used : ParameterizedType(java.lang.reflect.ParameterizedType) Type(java.lang.reflect.Type) Method(java.lang.reflect.Method) InvocationTargetException(java.lang.reflect.InvocationTargetException) DevelopmentException(io.jmix.core.DevelopmentException)

Example 17 with DevelopmentException

use of io.jmix.core.DevelopmentException 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)

Example 18 with DevelopmentException

use of io.jmix.core.DevelopmentException in project jmix by jmix-framework.

the class UiControllerDependencyInjector method doInjection.

protected void doInjection(InjectElement injectElement, FrameOwner frameOwner, ScreenOptions options) {
    String name = getInjectionName(injectElement);
    Class<?> type = getInjectionType(injectElement);
    Object instance = getInjectedInstance(type, name, injectElement, frameOwner, options);
    if (instance != null) {
        assignValue(injectElement.getElement(), instance, frameOwner);
    } else if (isInjectionRequired(injectElement)) {
        Class<?> declaringClass = ((Member) injectElement.getElement()).getDeclaringClass();
        Class<? extends FrameOwner> frameClass = frameOwner.getClass();
        String msg;
        if (frameClass == declaringClass) {
            msg = String.format("Unable to find an instance of type '%s' named '%s' for instance of '%s'", type, name, frameClass.getCanonicalName());
        } else {
            msg = String.format("Unable to find an instance of type '%s' named '%s' declared in '%s' for instance of '%s'", type, name, declaringClass.getCanonicalName(), frameClass.getCanonicalName());
        }
        throw new DevelopmentException(msg);
    } else {
        log.trace("Skip injection {} of {} as it is optional and instance not found", name, frameOwner.getClass());
    }
}
Also used : DevelopmentException(io.jmix.core.DevelopmentException)

Example 19 with DevelopmentException

use of io.jmix.core.DevelopmentException in project jmix by jmix-framework.

the class UiControllerDependencyInjector method getInstallTargetSetterMethod.

protected MethodHandle getInstallTargetSetterMethod(Install annotation, Frame frame, Class<?> instanceClass, Method provideMethod) {
    String subjectProperty;
    if (Strings.isNullOrEmpty(annotation.subject()) && annotation.type() == Object.class) {
        InstallSubject installSubjectAnnotation = findMergedAnnotation(instanceClass, InstallSubject.class);
        if (installSubjectAnnotation != null) {
            subjectProperty = installSubjectAnnotation.value();
        } else {
            throw new DevelopmentException(String.format("Unable to determine @Install subject of %s in %s", provideMethod, frame.getId()));
        }
    } else if (annotation.type() != Object.class) {
        subjectProperty = StringUtils.uncapitalize(annotation.type().getSimpleName());
    } else {
        subjectProperty = annotation.subject();
    }
    String subjectSetterName = "set" + StringUtils.capitalize(subjectProperty);
    // Check if addSubject is supported, e.g: addValidator(), addStyleProvider()
    String subjectAddName = "add" + StringUtils.capitalize(subjectProperty);
    MethodHandle targetSetterMethod = reflectionInspector.getInstallTargetMethod(instanceClass, subjectAddName);
    if (targetSetterMethod == null) {
        targetSetterMethod = reflectionInspector.getInstallTargetMethod(instanceClass, subjectSetterName);
    }
    if (targetSetterMethod == null) {
        throw new DevelopmentException(String.format("Unable to find @Install target method %s in %s", subjectProperty, instanceClass));
    }
    return targetSetterMethod;
}
Also used : DevelopmentException(io.jmix.core.DevelopmentException) MethodHandle(java.lang.invoke.MethodHandle)

Example 20 with DevelopmentException

use of io.jmix.core.DevelopmentException in project jmix by jmix-framework.

the class ThemeConstantsRepository method loadThemeProperties.

public void loadThemeProperties(String fileName, Map<String, String> themeMap) {
    try (InputStream propertiesStream = resources.getResourceAsStream(fileName)) {
        if (propertiesStream == null) {
            throw new DevelopmentException(String.format("Unable to load theme constants for: '%s'", fileName));
        }
        Properties properties = new Properties();
        try (InputStreamReader propertiesReader = new InputStreamReader(propertiesStream, StandardCharsets.UTF_8)) {
            properties.load(propertiesReader);
        } catch (IOException e) {
            throw new DevelopmentException(String.format("Unable to parse theme constants for: '%s'", fileName));
        }
        String includeValue = properties.getProperty("@include");
        if (includeValue != null) {
            String[] themeIncludes = StringUtils.split(includeValue, " ,");
            for (String include : themeIncludes) {
                loadThemeProperties(include, themeMap);
            }
        }
        for (Map.Entry<Object, Object> entry : properties.entrySet()) {
            Object key = entry.getKey();
            Object value = entry.getValue();
            if (key != null && !"@include".equals(key) && value != null) {
                themeMap.put(key.toString(), value.toString());
            }
        }
    } catch (IOException e) {
        throw new RuntimeException(String.format("Unable to read theme properties from '%s'", fileName));
    }
}
Also used : InputStreamReader(java.io.InputStreamReader) InputStream(java.io.InputStream) IOException(java.io.IOException) DevelopmentException(io.jmix.core.DevelopmentException)

Aggregations

DevelopmentException (io.jmix.core.DevelopmentException)26 MetaClass (io.jmix.core.metamodel.model.MetaClass)10 MethodHandle (java.lang.invoke.MethodHandle)3 DataGrid (com.haulmont.cuba.gui.components.DataGrid)2 FetchPlanProperty (io.jmix.core.FetchPlanProperty)2 MetaProperty (io.jmix.core.metamodel.model.MetaProperty)2 EditorBuilder (io.jmix.ui.builder.EditorBuilder)2 AbstractDataGrid (io.jmix.ui.component.impl.AbstractDataGrid)2 AnnotatedMethod (io.jmix.ui.sys.UiControllerReflectionInspector.AnnotatedMethod)2 InvocationTargetException (java.lang.reflect.InvocationTargetException)2 Method (java.lang.reflect.Method)2 Map (java.util.Map)2 NamePattern (com.haulmont.chile.core.annotations.NamePattern)1 LoadContext (com.haulmont.cuba.core.global.LoadContext)1 ViewBuilder (com.haulmont.cuba.core.global.ViewBuilder)1 Server (com.haulmont.cuba.core.model.common.Server)1 CoreTest (com.haulmont.cuba.core.testsupport.CoreTest)1 AbstractWindow (com.haulmont.cuba.gui.components.AbstractWindow)1 TreeDataGrid (com.haulmont.cuba.gui.components.TreeDataGrid)1 LegacyFragmentAdapter (com.haulmont.cuba.gui.components.compatibility.LegacyFragmentAdapter)1