/* * Copyright 2015 Red Hat, Inc. and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.uberfire.workbench.model.menu.impl; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Stack; import org.uberfire.mvp.Command; import org.uberfire.mvp.PlaceRequest; import org.uberfire.mvp.impl.DefaultPlaceRequest; import org.uberfire.security.Resource; import org.uberfire.security.ResourceAction; import org.uberfire.security.ResourceRef; import org.uberfire.security.ResourceType; import org.uberfire.security.authz.ResourceActionRef; import org.uberfire.workbench.model.ActivityResourceType; import org.uberfire.workbench.model.menu.EnabledStateChangeListener; import org.uberfire.workbench.model.menu.MenuFactory; import org.uberfire.workbench.model.menu.MenuItem; import org.uberfire.workbench.model.menu.MenuItemCommand; import org.uberfire.workbench.model.menu.MenuItemPerspective; import org.uberfire.workbench.model.menu.MenuItemPlain; import org.uberfire.workbench.model.menu.MenuPosition; import org.uberfire.workbench.model.menu.MenuVisitor; import org.uberfire.workbench.model.menu.Menus; import static org.uberfire.commons.validation.PortablePreconditions.checkNotEmpty; import static org.uberfire.commons.validation.PortablePreconditions.checkNotNull; /** * */ public final class MenuBuilderImpl implements MenuFactory.MenuBuilder, MenuFactory.ContributedMenuBuilder, MenuFactory.TopLevelMenusBuilder, MenuFactory.SubMenuBuilder, MenuFactory.SubMenusBuilder, MenuFactory.TerminalMenu, MenuFactory.TerminalCustomMenu { final List<MenuItem> menuItems = new ArrayList<MenuItem>(); final Stack<MenuFactory.CustomMenuBuilder> context = new Stack<MenuFactory.CustomMenuBuilder>(); int order = 0; public MenuBuilderImpl(final MenuType menuType, final String caption) { final CurrentContext currentContext = new CurrentContext(); currentContext.caption = checkNotEmpty("caption", caption); currentContext.menuType = checkNotNull("menuType", menuType); context.push(currentContext); } public MenuBuilderImpl(final MenuType menuType, final MenuFactory.CustomMenuBuilder builder) { context.push(builder); } @Override public MenuBuilderImpl newContributedMenu(final String caption) { final CurrentContext currentContext = new CurrentContext(); currentContext.caption = checkNotEmpty("caption", caption); currentContext.menuType = MenuType.CONTRIBUTED; context.push(currentContext); return this; } @Override public MenuBuilderImpl newTopLevelMenu(final MenuItem menu) { final CurrentContext currentContext = new CurrentContext(); currentContext.menu = checkNotNull("menu", menu); context.push(currentContext); return this; } @Override public MenuBuilderImpl newTopLevelMenu(final String caption) { final CurrentContext currentContext = new CurrentContext(); currentContext.caption = checkNotEmpty("caption", caption); currentContext.menuType = MenuType.TOP_LEVEL; context.push(currentContext); return this; } @Override public MenuFactory.TerminalCustomMenu newTopLevelCustomMenu(final MenuFactory.CustomMenuBuilder builder) { context.push(builder); return this; } @Override public MenuBuilderImpl menu(final String caption) { final CurrentContext currentContext = new CurrentContext(); currentContext.caption = checkNotEmpty("caption", caption); currentContext.menuType = MenuType.REGULAR; context.push(currentContext); return this; } @Override public MenuBuilderImpl menus() { ((CurrentContext) context.peek()).menuType = MenuType.GROUP; return this; } @Override public MenuFactory.TerminalMenu custom(MenuFactory.CustomMenuBuilder builder) { context.push(builder); return this; } @Override public MenuBuilderImpl submenu(final String caption) { final CurrentContext currentContext = new CurrentContext(); currentContext.caption = checkNotEmpty("caption", caption); currentContext.menuType = MenuType.GROUP; context.push(currentContext); return this; } @Override public MenuBuilderImpl contributeTo(final String contributionPoint) { ((CurrentContext) context.peek()).contributionPoint = checkNotEmpty("contributionPoint", contributionPoint); return this; } @Override public MenuBuilderImpl withItems(final List items) { ((CurrentContext) context.peek()).menuItems = new ArrayList<MenuItem>(checkNotEmpty("items", items)); return this; } @Override public MenuBuilderImpl respondsWith(final Command command) { ((CurrentContext) context.peek()).command = checkNotNull("command", command); return this; } @Override public MenuBuilderImpl perspective(final String identifier) { checkNotNull("perspective", identifier); ((CurrentContext) context.peek()).placeRequest = new DefaultPlaceRequest(identifier); return this; } @Override public MenuBuilderImpl place(final PlaceRequest place) { ((CurrentContext) context.peek()).placeRequest = checkNotNull("place", place); return this; } @Override public MenuBuilderImpl order(final int order) { ((CurrentContext) context.peek()).order = order; return this; } @Override public MenuBuilderImpl position(final MenuPosition position) { ((CurrentContext) context.peek()).position = checkNotNull("position", position); return this; } @Override public MenuBuilderImpl identifier(final String id) { ((CurrentContext) context.peek()).identifier = checkNotEmpty("identifier", id); return this; } @Override public MenuBuilderImpl withPermission(ResourceType resourceType) { ResourceRef resource = new ResourceRef(null, resourceType); ResourceActionRef ref = new ResourceActionRef(resource); ((CurrentContext) context.peek()).resourceActionRefs.add(ref); return this; } @Override public MenuBuilderImpl withPermission(ResourceType resourceType, ResourceAction resourceAction) { ResourceActionRef ref = new ResourceActionRef(resourceType, resourceAction); ((CurrentContext) context.peek()).resourceActionRefs.add(ref); return this; } @Override public MenuBuilderImpl withPermission(ResourceType resourceType, Resource resource, ResourceAction resourceAction) { if (resource == null) { return withPermission(resourceType, resourceAction); } else { return withPermission(resource, resourceAction); } } @Override public MenuBuilderImpl withPermission(Resource resource) { ResourceActionRef ref = new ResourceActionRef(resource); ((CurrentContext) context.peek()).resourceActionRefs.add(ref); return this; } @Override public Object withPermission(String resourceId, ResourceType resourceType) { ResourceRef resource = new ResourceRef(resourceId, resourceType); ResourceActionRef ref = new ResourceActionRef(resource); ((CurrentContext) context.peek()).resourceActionRefs.add(ref); return this; } @Override public Object withPermission(String resourceId, ResourceType resourceType, ResourceAction resourceAction) { ResourceRef resource = new ResourceRef(resourceId, resourceType); ResourceActionRef ref = new ResourceActionRef(resource, resourceAction); ((CurrentContext) context.peek()).resourceActionRefs.add(ref); return this; } @Override public MenuBuilderImpl withPermission(Resource resource, ResourceAction resourceAction) { ResourceActionRef ref = new ResourceActionRef(resource, resourceAction); ((CurrentContext) context.peek()).resourceActionRefs.add(ref); return this; } @Override public MenuBuilderImpl withPermission(String permission) { ((CurrentContext) context.peek()).permissionNames.add(permission); return this; } @Override public MenuBuilderImpl endMenus() { return this; } @Override public MenuBuilderImpl endMenu() { if (context.size() == 1) { menuItems.add(context.pop().build()); } else { final MenuFactory.CustomMenuBuilder active = context.pop(); context.peek().push(active); } return this; } @Override public MenuBuilderImpl orderAll(final int order) { this.order = order; return this; } @Override public Menus build() { context.clear(); return new DefaultMenus(menuItems, order); } public enum MenuType { TOP_LEVEL, CONTRIBUTED, REGULAR, GROUP, CUSTOM } private static class CurrentContext implements MenuFactory.CustomMenuBuilder { MenuItem menu = null; int order = 0; MenuType menuType = MenuType.REGULAR; String caption = null; MenuPosition position = MenuPosition.LEFT; String contributionPoint = null; Command command = null; PlaceRequest placeRequest = null; String identifier = null; List<ResourceActionRef> resourceActionRefs = new ArrayList<>(); List<String> permissionNames = new ArrayList<>(); List menuItems = new ArrayList<MenuItem>(); Stack<MenuFactory.CustomMenuBuilder> menuRawItems = new Stack<MenuFactory.CustomMenuBuilder>(); @Override public void push(MenuFactory.CustomMenuBuilder element) { menuRawItems.push(element); } @Override public MenuItem build() { if (menu != null) { return menu; } if (menuItems.size() > 0 || menuRawItems.size() > 0) { if (menuRawItems.size() > 0) { for (final MenuFactory.CustomMenuBuilder current : menuRawItems) { menuItems.add(current.build()); } } return new DefaultMenuGroup(menuItems, resourceActionRefs, permissionNames, contributionPoint, caption, position, order); } else if (command != null) { return new MenuItemCommand() { private final List<EnabledStateChangeListener> enabledStateChangeListeners = new ArrayList<EnabledStateChangeListener>(); private boolean isEnabled = true; @Override public String getIdentifier() { if (identifier != null) { return identifier; } if (contributionPoint != null) { return getClass().getName() + "#" + contributionPoint + "#" + caption; } return getClass().getName() + "#" + caption; } @Override public List<ResourceActionRef> getResourceActions() { return resourceActionRefs; } @Override public List<String> getPermissions() { return permissionNames; } @Override public Command getCommand() { return command; } @Override public String getContributionPoint() { return contributionPoint; } @Override public String getCaption() { return caption; } @Override public MenuPosition getPosition() { return position; } @Override public int getOrder() { return order; } @Override public boolean isEnabled() { return isEnabled; } @Override public void setEnabled(final boolean enabled) { this.isEnabled = enabled; notifyListeners(enabled); } @Override public void addEnabledStateChangeListener(final EnabledStateChangeListener listener) { enabledStateChangeListeners.add(listener); } @Override public void accept(MenuVisitor visitor) { visitor.visit(this); } private void notifyListeners(final boolean enabled) { for (final EnabledStateChangeListener listener : enabledStateChangeListeners) { listener.enabledStateChanged(enabled); } } }; } else if (placeRequest != null) { return new MenuItemPerspective() { private final List<EnabledStateChangeListener> enabledStateChangeListeners = new ArrayList<EnabledStateChangeListener>(); private boolean isEnabled = true; @Override public PlaceRequest getPlaceRequest() { return placeRequest; } @Override public String getIdentifier() { if (identifier != null) { return identifier; } if (contributionPoint != null) { return getClass().getName() + "#" + contributionPoint + "#" + caption; } return getClass().getName() + "#" + caption; } @Override public List<ResourceActionRef> getResourceActions() { return resourceActionRefs; } @Override public List<String> getPermissions() { return permissionNames; } @Override public List<Resource> getDependencies() { ResourceRef ref = new ResourceRef(placeRequest.getIdentifier(), ActivityResourceType.PERSPECTIVE); return Collections.singletonList(ref); } @Override public String getContributionPoint() { return contributionPoint; } @Override public String getCaption() { return caption; } @Override public MenuPosition getPosition() { return position; } @Override public int getOrder() { return order; } @Override public boolean isEnabled() { return isEnabled; } @Override public void setEnabled(final boolean enabled) { this.isEnabled = enabled; notifyListeners(enabled); } @Override public void addEnabledStateChangeListener(final EnabledStateChangeListener listener) { enabledStateChangeListeners.add(listener); } @Override public void accept(MenuVisitor visitor) { visitor.visit(this); } private void notifyListeners(final boolean enabled) { for (final EnabledStateChangeListener listener : enabledStateChangeListeners) { listener.enabledStateChanged(enabled); } } }; } return new MenuItemPlain() { private final List<EnabledStateChangeListener> enabledStateChangeListeners = new ArrayList<EnabledStateChangeListener>(); private boolean isEnabled = true; @Override public String getIdentifier() { if (identifier != null) { return identifier; } if (contributionPoint != null) { return getClass().getName() + "#" + contributionPoint + "#" + caption; } return getClass().getName() + "#" + caption; } @Override public List<ResourceActionRef> getResourceActions() { return resourceActionRefs; } @Override public List<String> getPermissions() { return permissionNames; } @Override public String getContributionPoint() { return contributionPoint; } @Override public String getCaption() { return caption; } @Override public MenuPosition getPosition() { return position; } @Override public int getOrder() { return order; } @Override public boolean isEnabled() { return isEnabled; } @Override public void setEnabled(final boolean enabled) { this.isEnabled = enabled; notifyListeners(enabled); } @Override public void addEnabledStateChangeListener(final EnabledStateChangeListener listener) { enabledStateChangeListeners.add(listener); } @Override public void accept(MenuVisitor visitor) { visitor.visit(this); } private void notifyListeners(final boolean enabled) { for (final EnabledStateChangeListener listener : enabledStateChangeListeners) { listener.enabledStateChanged(enabled); } } }; } } }