/*
* Copyright 2015 JBoss, by Red Hat, Inc
*
* 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.ext.plugin.client.editor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import javax.enterprise.context.Dependent;
import javax.enterprise.event.Event;
import javax.enterprise.event.Observes;
import javax.inject.Inject;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.view.client.HasData;
import com.google.gwt.view.client.ListDataProvider;
import org.jboss.errai.common.client.api.Caller;
import org.jboss.errai.common.client.api.RemoteCallback;
import org.uberfire.backend.vfs.ObservablePath;
import org.uberfire.client.annotations.WorkbenchEditor;
import org.uberfire.client.annotations.WorkbenchMenu;
import org.uberfire.client.annotations.WorkbenchPartTitle;
import org.uberfire.client.annotations.WorkbenchPartTitleDecoration;
import org.uberfire.client.annotations.WorkbenchPartView;
import org.uberfire.client.mvp.ActivityBeansCache;
import org.uberfire.client.mvp.UberView;
import org.uberfire.client.workbench.events.ChangeTitleWidgetEvent;
import org.uberfire.ext.editor.commons.client.BaseEditor;
import org.uberfire.ext.editor.commons.client.BaseEditorView;
import org.uberfire.ext.editor.commons.client.file.popups.SavePopUpPresenter;
import org.uberfire.ext.editor.commons.client.validation.Validator;
import org.uberfire.ext.editor.commons.service.support.SupportsCopy;
import org.uberfire.ext.editor.commons.service.support.SupportsDelete;
import org.uberfire.ext.editor.commons.service.support.SupportsRename;
import org.uberfire.ext.plugin.client.resources.i18n.CommonConstants;
import org.uberfire.ext.plugin.client.type.DynamicMenuResourceType;
import org.uberfire.ext.plugin.client.validation.NameValidator;
import org.uberfire.ext.plugin.client.validation.PluginNameValidator;
import org.uberfire.ext.plugin.client.validation.RuleValidator;
import org.uberfire.ext.plugin.event.PluginRenamed;
import org.uberfire.ext.plugin.model.DynamicMenu;
import org.uberfire.ext.plugin.model.DynamicMenuItem;
import org.uberfire.ext.plugin.model.Plugin;
import org.uberfire.ext.plugin.model.PluginType;
import org.uberfire.ext.plugin.service.PluginServices;
import org.uberfire.lifecycle.OnMayClose;
import org.uberfire.lifecycle.OnStartup;
import org.uberfire.mvp.Command;
import org.uberfire.mvp.ParameterizedCommand;
import org.uberfire.mvp.PlaceRequest;
import org.uberfire.workbench.events.NotificationEvent;
import org.uberfire.workbench.model.menu.Menus;
import static org.uberfire.ext.editor.commons.client.menu.MenuItems.COPY;
import static org.uberfire.ext.editor.commons.client.menu.MenuItems.DELETE;
import static org.uberfire.ext.editor.commons.client.menu.MenuItems.RENAME;
import static org.uberfire.ext.editor.commons.client.menu.MenuItems.SAVE;
@Dependent
@WorkbenchEditor(identifier = "Dynamic Menu Editor", supportedTypes = {DynamicMenuResourceType.class}, priority = Integer.MAX_VALUE)
public class DynamicMenuEditorPresenter
extends BaseEditor {
@Inject
private DynamicMenuResourceType resourceType;
@Inject
private Caller<PluginServices> pluginServices;
@Inject
private Event<NotificationEvent> notification;
@Inject
private ActivityBeansCache activityBeansCache;
@Inject
private PluginNameValidator pluginNameValidator;
@Inject
private SavePopUpPresenter savePopUpPresenter;
private ListDataProvider<DynamicMenuItem> dataProvider = new ListDataProvider<DynamicMenuItem>();
private DynamicMenu menuItem;
private Plugin plugin;
@Inject
public DynamicMenuEditorPresenter(final View baseView) {
super(baseView);
}
@OnStartup
public void onStartup(final ObservablePath path,
final PlaceRequest place) {
init(path,
place,
resourceType,
true,
false,
SAVE,
COPY,
RENAME,
DELETE);
// This is only used to define the "name" used by @WorkbenchPartTitle which is called by Uberfire after @OnStartup
// but before the async call in "loadContent()" has returned. When the *real* plugin is loaded this is overwritten
this.plugin = new Plugin(place.getParameter("name",
""),
PluginType.DYNAMIC_MENU,
path);
}
@WorkbenchPartTitleDecoration
public IsWidget getTitle() {
return super.getTitle();
}
@WorkbenchPartTitle
public String getTitleText() {
return CommonConstants.INSTANCE.DynamicMenuEditor() + " [" + plugin.getName() + "]";
}
@WorkbenchMenu
public Menus getMenus() {
return menus;
}
protected void onPlugInRenamed(@Observes final PluginRenamed pluginRenamed) {
if (pluginRenamed.getOldPluginName().equals(plugin.getName()) &&
pluginRenamed.getPlugin().getType().equals(plugin.getType())) {
plugin = new Plugin(pluginRenamed.getPlugin().getName(),
PluginType.DYNAMIC_MENU,
pluginRenamed.getPlugin().getPath());
changeTitleNotification.fire(new ChangeTitleWidgetEvent(place,
getTitleText(),
getTitle()));
}
}
public RuleValidator getMenuItemActivityIdValidator() {
return NameValidator.createNameValidator(getView().emptyActivityID(),
getView().invalidActivityID());
}
public RuleValidator getMenuItemLabelValidator(final DynamicMenuItem menuItem,
final DynamicMenuItem editedMenuItem) {
return new RuleValidator() {
private String error;
private NameValidator menuLabelValidator = NameValidator.createNameValidator(getView().emptyMenuLabel(),
getView().invalidMenuLabel());
@Override
public boolean isValid(final String value) {
if (!menuLabelValidator.isValid(value)) {
this.error = menuLabelValidator.getValidationError();
return false;
}
DynamicMenuItem existingItem = getExistingMenuItem(menuItem,
editedMenuItem);
if (existingItem != null) {
this.error = getView().duplicatedMenuLabel();
return false;
}
this.error = null;
return true;
}
@Override
public String getValidationError() {
return this.error;
}
};
}
public void addMenuItem(final DynamicMenuItem menuItem) {
DynamicMenuItem existingItem = getExistingMenuItem(menuItem,
null);
if (existingItem == null) {
getDynamicMenuItems().add(menuItem);
} else {
//No need to re-select edited item as DynamicMenuEditorView resets itself after *any* edit
dataProvider.refresh();
}
dataProvider.flush();
}
public DynamicMenuItem getExistingMenuItem(final DynamicMenuItem currentMenuItem,
final DynamicMenuItem editedMenuItem) {
DynamicMenuItem existingItem = null;
for (final DynamicMenuItem item : getDynamicMenuItems()) {
if (editedMenuItem != item && currentMenuItem.getMenuLabel().equals(item.getMenuLabel())) {
existingItem = item;
break;
}
}
return existingItem;
}
public void removeObject(DynamicMenuItem object) {
getDynamicMenuItems().remove(object);
}
public void updateIndex(final DynamicMenuItem object,
final int index,
final UpdateIndexOperation operation) {
if (index < 0) {
return;
}
final int newIndex = operation.equals(UpdateIndexOperation.UP) ? index - 1 : index + 1;
if (newIndex < 0 || newIndex >= getDynamicMenuItems().size()) {
return;
}
final DynamicMenuItem oldItem = getDynamicMenuItems().set(newIndex,
object);
if (oldItem != null) {
getDynamicMenuItems().set(index,
oldItem);
}
}
public void setDataDisplay(final HasData<DynamicMenuItem> display) {
dataProvider.addDataDisplay(display);
}
@Override
protected void loadContent() {
getPluginServices().call(new RemoteCallback<DynamicMenu>() {
@Override
public void callback(final DynamicMenu response) {
setOriginalHash(response.hashCode());
menuItem = response;
getDynamicMenuItems().clear();
for (final DynamicMenuItem menuItem : response.getMenuItems()) {
getDynamicMenuItems().add(menuItem);
}
baseView.hideBusyIndicator();
}
}).getDynamicMenuContent(getVersionRecordManager().getCurrentPath());
}
Caller<PluginServices> getPluginServices() {
return pluginServices;
}
protected Command onValidate() {
return new Command() {
@Override
public void execute() {
final Collection<String> invalidActivities = new HashSet<String>();
for (final DynamicMenuItem dynamicMenuItem : getDynamicMenuItems()) {
if (activityBeansCache.getActivity(dynamicMenuItem.getActivityId()) == null) {
invalidActivities.add(dynamicMenuItem.getActivityId());
}
}
if (invalidActivities.isEmpty()) {
notification.fire(new NotificationEvent("Item Validated Successfully",
NotificationEvent.NotificationType.SUCCESS));
} else {
notification.fire(new NotificationEvent("Activity(ies) not found: '" + DynamicMenuEditorPresenter.this.toString(invalidActivities) + "'",
NotificationEvent.NotificationType.ERROR));
}
}
};
}
private String toString(final Collection<String> invalidActivities) {
StringBuilder result = new StringBuilder();
for (final String string : invalidActivities) {
result.append(string).append(",");
}
return result.length() > 0 ? result.substring(
0,
result.length() - 1) : "";
}
protected void save() {
savePopUpPresenter.show(versionRecordManager.getCurrentPath(),
new ParameterizedCommand<String>() {
@Override
public void execute(final String commitMessage) {
getPluginServices().call(getSaveSuccessCallback(getContent().hashCode())).saveMenu(
getContent(),
commitMessage);
}
}
);
concurrentUpdateSessionInfo = null;
}
@WorkbenchPartView
public UberView<DynamicMenuEditorPresenter> getWidget() {
return (UberView<DynamicMenuEditorPresenter>) super.baseView;
}
@OnMayClose
public boolean onMayClose() {
return super.mayClose(getContent().hashCode());
}
public DynamicMenu getContent() {
return new DynamicMenu(menuItem.getName(),
PluginType.DYNAMIC_MENU,
versionRecordManager.getCurrentPath(),
new ArrayList<DynamicMenuItem>(getDynamicMenuItems()));
}
@Override
public Validator getRenameValidator() {
return pluginNameValidator;
}
@Override
public Validator getCopyValidator() {
return pluginNameValidator;
}
protected Caller<? extends SupportsDelete> getDeleteServiceCaller() {
return getPluginServices();
}
protected Caller<? extends SupportsRename> getRenameServiceCaller() {
return getPluginServices();
}
protected Caller<? extends SupportsCopy> getCopyServiceCaller() {
return getPluginServices();
}
public View getView() {
return (View) super.baseView;
}
protected List<DynamicMenuItem> getDynamicMenuItems() {
return dataProvider.getList();
}
enum UpdateIndexOperation {
UP,
DOWN;
}
public interface View extends UberView<DynamicMenuEditorPresenter>,
BaseEditorView {
String emptyActivityID();
String invalidActivityID();
String emptyMenuLabel();
String invalidMenuLabel();
String duplicatedMenuLabel();
}
}