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);
}
}
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);
}
}
}
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());
}
}
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;
}
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));
}
}
Aggregations