MenuBuilder eagerly creates MenuCommand and loads execution params for all menu items #984

This commit is contained in:
Yuriy Artamonov 2018-06-19 17:08:14 +04:00
parent 134d0903b1
commit 6a8a3dd541
5 changed files with 76 additions and 43 deletions

View File

@ -17,7 +17,6 @@
package com.haulmont.cuba.gui.config;
import com.haulmont.bali.util.Dom4j;
import com.haulmont.cuba.core.app.DataService;
import com.haulmont.cuba.core.entity.Entity;
import com.haulmont.cuba.core.global.*;
@ -43,31 +42,29 @@ import java.util.function.Consumer;
public class MenuCommand {
protected MenuItem item;
protected MenuItemCommand command;
public MenuCommand(MenuItem item) {
this.item = item;
createCommand();
this.command = createCommand(item);
}
protected void createCommand() {
protected MenuItemCommand createCommand(MenuItem item) {
Map<String, Object> params = loadParams(item.getDescriptor(), item.getScreen());
if (StringUtils.isNotEmpty(item.getScreen())) {
command = new ScreenCommand(item.getScreen(), item.getDescriptor(), params);
return;
return new ScreenCommand(item.getScreen(), item.getDescriptor(), params);
}
if (StringUtils.isNotEmpty(item.getRunnableClass())) {
command = new RunnableClassCommand(item.getRunnableClass(), params);
return;
return new RunnableClassCommand(item.getRunnableClass(), params);
}
if (StringUtils.isNotEmpty(item.getBean())) {
command = new BeanCommand(item.getBean(), item.getBeanMethod(), params);
return new BeanCommand(item.getBean(), item.getBeanMethod(), params);
}
return null;
}
public void execute() {
@ -84,7 +81,8 @@ public class MenuCommand {
protected Map<String, Object> loadParams(Element descriptor, String screen) {
Map<String, Object> params = new HashMap<>();
for (Element element : Dom4j.elements(descriptor, "param")) {
for (Element element : descriptor.elements("param")) {
String value = element.attributeValue("value");
EntityLoadInfo info = EntityLoadInfo.parse(value);
if (info == null) {
@ -94,8 +92,9 @@ public class MenuCommand {
} else {
if (value.startsWith("${") && value.endsWith("}")) {
String property = AppContext.getProperty(value.substring(2, value.length() - 1));
if (!StringUtils.isEmpty(property))
if (!StringUtils.isEmpty(property)) {
value = property;
}
}
params.put(element.attributeValue("name"), value);
}
@ -127,7 +126,7 @@ public class MenuCommand {
String getDescription();
}
protected class ScreenCommand implements MenuItemCommand {
protected static class ScreenCommand implements MenuItemCommand {
protected String screen;
protected Element descriptor;
@ -147,8 +146,6 @@ public class MenuCommand {
openType = OpenType.valueOf(openTypeStr);
}
WindowManager wm = AppBeans.get(WindowManagerProvider.class).get();
if (openType.getOpenMode() == OpenMode.DIALOG) {
String resizable = descriptor.attributeValue("resizable");
if (StringUtils.isNotEmpty(resizable)) {
@ -159,7 +156,10 @@ public class MenuCommand {
WindowInfo windowInfo = AppBeans.get(WindowConfig.class).getWindowInfo(screen);
final String id = windowInfo.getId();
if (id.endsWith(Window.CREATE_WINDOW_SUFFIX) || id.endsWith(Window.EDITOR_WINDOW_SUFFIX)) {
WindowManager wm = AppBeans.get(WindowManagerProvider.class).get();
if (id.endsWith(Window.CREATE_WINDOW_SUFFIX)
|| id.endsWith(Window.EDITOR_WINDOW_SUFFIX)) {
Entity entityItem;
if (params.containsKey("item")) {
entityItem = (Entity) params.get("item");
@ -188,7 +188,7 @@ public class MenuCommand {
}
}
protected class BeanCommand implements MenuItemCommand {
protected static class BeanCommand implements MenuItemCommand {
protected String bean;
protected String beanMethod;
@ -210,9 +210,9 @@ public class MenuCommand {
return;
}
MethodUtils.invokeMethod(beanInstance, beanMethod, null);
MethodUtils.invokeMethod(beanInstance, beanMethod, (Object[]) null);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
throw new RuntimeException("Unable to execute bean method", e);
}
}
@ -222,7 +222,7 @@ public class MenuCommand {
}
}
protected class RunnableClassCommand implements MenuItemCommand {
protected static class RunnableClassCommand implements MenuItemCommand {
protected String runnableClass;
protected Map<String, Object> params;
@ -232,6 +232,7 @@ public class MenuCommand {
this.params = params;
}
@SuppressWarnings("unchecked")
@Override
public void run() {
Class<?> clazz = AppBeans.get(Scripting.class).loadClass(runnableClass);
@ -239,22 +240,23 @@ public class MenuCommand {
throw new IllegalStateException(String.format("Can't load class: %s", runnableClass));
}
if (!Runnable.class.isAssignableFrom(clazz) && !Consumer.class.isAssignableFrom(clazz)) {
throw new IllegalStateException(String.format("Class \"%s\" should implement Runnable or Consumer<Map<String, Object>>", runnableClass));
if (!Runnable.class.isAssignableFrom(clazz)
&& !Consumer.class.isAssignableFrom(clazz)) {
throw new IllegalStateException(String.format("Class \"%s\" must implement Runnable or Consumer<Map<String, Object>>", runnableClass));
}
Object classInstance;
try {
Object classInstance = clazz.newInstance();
if (classInstance instanceof Consumer) {
((Consumer) classInstance).accept(params);
return;
}
((Runnable) classInstance).run();
classInstance = clazz.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
throw new DevelopmentException(String.format("Failed to get a new instance of %s", runnableClass));
}
if (classInstance instanceof Consumer) {
((Consumer) classInstance).accept(params);
} else {
((Runnable) classInstance).run();
}
}
@Override

View File

@ -353,7 +353,7 @@ public class WebAppMenu extends WebAbstractComponent<CubaMenuBar> implements App
this.command = command;
if (command != null) {
delegateItem.setCommand(event -> this.command.accept(this));
delegateItem.setCommand(this::menuSelected);
} else {
delegateItem.setCommand(null);
}
@ -428,5 +428,9 @@ public class WebAppMenu extends WebAbstractComponent<CubaMenuBar> implements App
protected void setSeparator(boolean separator) {
this.separator = separator;
}
protected void menuSelected(@SuppressWarnings("unused") MenuBar.MenuItem event) {
this.command.accept(this);
}
}
}

View File

@ -483,7 +483,7 @@ public class WebSideMenu extends WebAbstractComponent<CubaSideMenu> implements S
this.command = command;
if (command != null) {
delegateItem.setCommand(event -> this.command.accept(this));
delegateItem.setCommand(this::menuSelected);
} else {
delegateItem.setCommand(null);
}
@ -564,5 +564,10 @@ public class WebSideMenu extends WebAbstractComponent<CubaSideMenu> implements S
}
return ((MenuItemWrapper) delegateItem.getParent()).getMenuItem();
}
@SuppressWarnings("unused")
protected void menuSelected(CubaSideMenu.MenuItemTriggeredEvent event) {
this.command.accept(this);
}
}
}

View File

@ -103,7 +103,7 @@ public class MenuBuilder {
done = true;
if (item.hasChildren()) {
AppMenu.MenuItem[] children =
item.getChildren().toArray(new AppMenu.MenuItem[item.getChildren().size()]);
item.getChildren().toArray(new AppMenu.MenuItem[0]);
for (int i = 0; i < children.length; i++) {
AppMenu.MenuItem child = children[i];
@ -191,10 +191,7 @@ public class MenuBuilder {
}
protected Consumer<AppMenu.MenuItem> createMenuCommandExecutor(MenuItem item) {
MenuCommand menuCommand = new MenuCommand(item);
return menuItem ->
menuCommand.execute();
return new MenuCommandExecutor(item);
}
protected boolean isMenuItemEmpty(AppMenu.MenuItem menuItem) {
@ -233,4 +230,18 @@ public class MenuBuilder {
menuItem.setIcon(conf.getIcon());
}
}
public static class MenuCommandExecutor implements Consumer<AppMenu.MenuItem> {
private final MenuItem item;
public MenuCommandExecutor(MenuItem item) {
this.item = item;
}
@Override
public void accept(AppMenu.MenuItem menuItem) {
MenuCommand command = new MenuCommand(item);
command.execute();
}
}
}

View File

@ -82,7 +82,7 @@ public class SideMenuBuilder {
protected void removeExtraSeparators(SideMenu menuBar) {
List<SideMenu.MenuItem> menuItems = menuBar.getMenuItems();
for (SideMenu.MenuItem item : menuItems.toArray(new SideMenu.MenuItem[menuItems.size()])) {
for (SideMenu.MenuItem item : menuItems.toArray(new SideMenu.MenuItem[0])) {
removeExtraSeparators(item);
if (isMenuItemEmpty(item)) {
menuBar.removeMenuItem(item);
@ -97,7 +97,7 @@ public class SideMenuBuilder {
// SideMenu does not support separator elements
if (item.hasChildren()) {
SideMenu.MenuItem[] menuItems =
item.getChildren().toArray(new SideMenu.MenuItem[item.getChildren().size()]);
item.getChildren().toArray(new SideMenu.MenuItem[0]);
for (SideMenu.MenuItem child : menuItems) {
removeExtraSeparators(child);
@ -174,10 +174,7 @@ public class SideMenuBuilder {
}
protected Consumer<SideMenu.MenuItem> createMenuCommandExecutor(MenuItem item) {
MenuCommand command = new MenuCommand(item);
return event ->
command.execute();
return new MenuCommandExecutor(item);
}
protected boolean isMenuItemEmpty(SideMenu.MenuItem menuItem) {
@ -235,4 +232,18 @@ public class SideMenuBuilder {
}
}
}
public static class MenuCommandExecutor implements Consumer<SideMenu.MenuItem> {
private final MenuItem item;
public MenuCommandExecutor(MenuItem item) {
this.item = item;
}
@Override
public void accept(SideMenu.MenuItem menuItem) {
MenuCommand command = new MenuCommand(item);
command.execute();
}
}
}