/*
* Copyright 2012 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.kie.workbench.common.screens.projecteditor.client.editor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import javax.enterprise.context.Dependent;
import javax.enterprise.event.Event;
import javax.enterprise.event.Observes;
import javax.enterprise.inject.Instance;
import javax.inject.Inject;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.Widget;
import org.guvnor.common.services.project.client.preferences.ProjectScopedResolutionStrategySupplier;
import org.guvnor.common.services.project.client.repositories.ConflictingRepositoriesPopup;
import org.guvnor.common.services.project.context.ProjectContext;
import org.guvnor.common.services.project.context.ProjectContextChangeHandle;
import org.guvnor.common.services.project.context.ProjectContextChangeHandler;
import org.guvnor.common.services.project.model.Project;
import org.guvnor.common.services.project.preferences.GAVPreferences;
import org.guvnor.common.services.project.security.ProjectAction;
import org.guvnor.common.services.project.service.DeploymentMode;
import org.guvnor.common.services.project.service.GAVAlreadyExistsException;
import org.guvnor.common.services.shared.metadata.model.Metadata;
import org.gwtbootstrap3.client.ui.AnchorListItem;
import org.gwtbootstrap3.client.ui.Button;
import org.gwtbootstrap3.client.ui.ButtonGroup;
import org.gwtbootstrap3.client.ui.DropDownHeader;
import org.gwtbootstrap3.client.ui.DropDownMenu;
import org.jboss.errai.bus.client.api.messaging.Message;
import org.jboss.errai.common.client.api.Caller;
import org.jboss.errai.common.client.api.RemoteCallback;
import org.jboss.errai.common.client.util.CreationalCallback;
import org.jboss.errai.ioc.client.container.IOC;
import org.jboss.errai.ioc.client.container.async.AsyncBeanDef;
import org.jboss.errai.ioc.client.container.async.AsyncBeanManager;
import org.jboss.errai.security.shared.api.identity.User;
import org.kie.workbench.common.screens.projecteditor.client.build.BuildExecutor;
import org.kie.workbench.common.screens.projecteditor.client.editor.extension.BuildOptionExtension;
import org.kie.workbench.common.screens.projecteditor.client.resources.ProjectEditorResources;
import org.kie.workbench.common.screens.projecteditor.client.validation.ProjectNameValidator;
import org.kie.workbench.common.screens.projecteditor.model.ProjectScreenModel;
import org.kie.workbench.common.screens.projecteditor.service.ProjectScreenService;
import org.kie.workbench.common.services.shared.project.KieProject;
import org.kie.workbench.common.services.shared.validation.ValidationService;
import org.kie.workbench.common.widgets.client.callbacks.CommandBuilder;
import org.kie.workbench.common.widgets.client.callbacks.CommandDrivenErrorCallback;
import org.kie.workbench.common.widgets.client.callbacks.CommandWithThrowableDrivenErrorCallback;
import org.kie.workbench.common.widgets.client.resources.i18n.CommonConstants;
import org.uberfire.backend.vfs.ObservablePath;
import org.uberfire.backend.vfs.Path;
import org.uberfire.backend.vfs.PathFactory;
import org.uberfire.backend.vfs.impl.ForceUnlockEvent;
import org.uberfire.backend.vfs.impl.LockInfo;
import org.uberfire.client.annotations.WorkbenchMenu;
import org.uberfire.client.annotations.WorkbenchPartTitle;
import org.uberfire.client.annotations.WorkbenchPartView;
import org.uberfire.client.annotations.WorkbenchScreen;
import org.uberfire.client.mvp.LockManager;
import org.uberfire.client.mvp.LockTarget;
import org.uberfire.client.mvp.LockTarget.TitleProvider;
import org.uberfire.client.mvp.PlaceManager;
import org.uberfire.client.workbench.events.ChangeTitleWidgetEvent;
import org.uberfire.commons.data.Pair;
import org.uberfire.ext.editor.commons.client.file.CommandWithFileNameAndCommitMessage;
import org.uberfire.ext.editor.commons.client.file.FileNameAndCommitMessage;
import org.uberfire.ext.editor.commons.client.file.popups.CopyPopUpPresenter;
import org.uberfire.ext.editor.commons.client.file.popups.DeletePopUpPresenter;
import org.uberfire.ext.editor.commons.client.file.popups.RenamePopUpPresenter;
import org.uberfire.ext.editor.commons.client.file.popups.SavePopUpPresenter;
import org.uberfire.ext.preferences.client.admin.AdminPagePerspective;
import org.uberfire.ext.widgets.common.client.callbacks.HasBusyIndicatorDefaultErrorCallback;
import org.uberfire.ext.widgets.common.client.common.BusyIndicatorView;
import org.uberfire.lifecycle.OnClose;
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.mvp.impl.DefaultPlaceRequest;
import org.uberfire.mvp.impl.PathPlaceRequest;
import org.uberfire.security.authz.ResourceActionRef;
import org.uberfire.workbench.events.NotificationEvent;
import org.uberfire.workbench.events.ResourceUpdatedEvent;
import org.uberfire.workbench.model.menu.MenuFactory;
import org.uberfire.workbench.model.menu.MenuItem;
import org.uberfire.workbench.model.menu.Menus;
import org.uberfire.workbench.model.menu.impl.BaseMenuCustom;
import org.uberfire.workbench.type.ResourceTypeDefinition;
import static org.uberfire.ext.widgets.common.client.common.ConcurrentChangePopup.newConcurrentDelete;
import static org.uberfire.ext.widgets.common.client.common.ConcurrentChangePopup.newConcurrentRename;
import static org.uberfire.ext.widgets.common.client.common.ConcurrentChangePopup.newConcurrentUpdate;
@WorkbenchScreen(identifier = "projectScreen")
public class ProjectScreenPresenter
implements ProjectScreenView.Presenter {
public static final String KIE_DEPLOYMENT_DESCRIPTOR_XML = "kie-deployment-descriptor.xml";
private ProjectScreenView view;
private User user;
private Caller<ValidationService> validationService;
private Caller<ProjectScreenService> projectScreenService;
private ProjectNameValidator projectNameValidator;
private KieProject project;
protected ObservablePath pathToPomXML;
private Event<NotificationEvent> notificationEvent;
private Event<ChangeTitleWidgetEvent> changeTitleWidgetEvent;
private PlaceManager placeManager;
private Menus menus;
private ProjectScreenModel model;
private Integer originalHash;
private PlaceRequest placeRequest;
private BusyIndicatorView busyIndicatorView;
private ObservablePath.OnConcurrentUpdateEvent concurrentUpdateSessionInfo = null;
private ButtonGroup buildOptions;
private Collection<Widget> buildExtensions;
private ProjectContext workbenchContext;
private ProjectContextChangeHandle projectContextChangeHandle;
private Instance<LockManager> lockManagerInstanceProvider;
private Map<Widget, LockManager> lockManagers = new HashMap<Widget, LockManager>();
private Runnable reloadRunnable;
private TitleProvider titleProvider;
private String title;
private Event<ForceUnlockEvent> forceLockReleaseEvent;
private ConflictingRepositoriesPopup conflictingRepositoriesPopup;
protected CopyPopUpPresenter copyPopUpPresenter;
protected RenamePopUpPresenter renamePopUpPresenter;
protected DeletePopUpPresenter deletePopUpPresenter;
protected SavePopUpPresenter savePopUpPresenter;
private Path kieDeploymentDescriptoPath;
private Instance<ResourceTypeDefinition> resourceTypes;
private BuildExecutor buildExecutor;
public ProjectScreenPresenter() {
}
@Inject
public ProjectScreenPresenter(final ProjectScreenView view,
final ProjectContext workbenchContext,
final Caller<ProjectScreenService> projectScreenService,
final User user,
final Event<NotificationEvent> notificationEvent,
final Event<ChangeTitleWidgetEvent> changeTitleWidgetEvent,
final ProjectNameValidator projectNameValidator,
final PlaceManager placeManager,
final BusyIndicatorView busyIndicatorView,
final Caller<ValidationService> validationService,
final Instance<LockManager> lockManagerInstanceProvider,
final Event<ForceUnlockEvent> forceLockReleaseEvent,
final ConflictingRepositoriesPopup conflictingRepositoriesPopup,
final CopyPopUpPresenter copyPopUpPresenter,
final RenamePopUpPresenter renamePopUpPresenter,
final DeletePopUpPresenter deletePopUpPresenter,
final SavePopUpPresenter savePopUpPresenter,
final GAVPreferences gavPreferences,
final ProjectScopedResolutionStrategySupplier projectScopedResolutionStrategySupplier,
final Instance<ResourceTypeDefinition> resourceTypes,
final BuildExecutor buildExecutor) {
this.view = view;
this.user = user;
view.setPresenter(this);
gavPreferences.load(projectScopedResolutionStrategySupplier.get(),
loadedGAVPreferences -> {
view.setGAVCheckDisabledSetting(loadedGAVPreferences.isConflictingGAVCheckDisabled());
},
throwable -> {
throw new RuntimeException(throwable);
});
this.projectScreenService = projectScreenService;
this.notificationEvent = notificationEvent;
this.changeTitleWidgetEvent = changeTitleWidgetEvent;
this.projectNameValidator = projectNameValidator;
this.placeManager = placeManager;
this.validationService = validationService;
this.busyIndicatorView = busyIndicatorView;
this.workbenchContext = workbenchContext;
this.lockManagerInstanceProvider = lockManagerInstanceProvider;
this.forceLockReleaseEvent = forceLockReleaseEvent;
this.conflictingRepositoriesPopup = conflictingRepositoriesPopup;
this.copyPopUpPresenter = copyPopUpPresenter;
this.renamePopUpPresenter = renamePopUpPresenter;
this.deletePopUpPresenter = deletePopUpPresenter;
this.savePopUpPresenter = savePopUpPresenter;
projectContextChangeHandle = workbenchContext.addChangeHandler(new ProjectContextChangeHandler() {
@Override
public void onChange() {
update();
}
});
this.buildOptions = view.getBuildButtons();
menus = makeMenuBar();
reloadRunnable = new Runnable() {
@Override
public void run() {
ProjectScreenPresenter.this.reload();
}
};
titleProvider = new TitleProvider() {
@Override
public String getTitle() {
return (title == null) ? ProjectScreenPresenter.this.getTitle() : title;
}
};
this.resourceTypes = resourceTypes;
this.buildExecutor = buildExecutor;
this.buildExecutor.init(view);
}
protected boolean isDeploymentDescritorEditorAvailable(final Stream<ResourceTypeDefinition> resourceTypes,
final Path path) {
return resourceTypes.anyMatch(r -> r.accept(path) && KIE_DEPLOYMENT_DESCRIPTOR_XML.equals(r.getPrefix() + "." + r.getSuffix()));
}
/**
* This is in no way a permanent fix for the refresh issue.
* We need something reusable for all the multi file editors we have and will have.
*/
void onResourceUpdated(final @Observes ResourceUpdatedEvent resourceUpdatedEvent) {
if (resourceUpdatedEvent.getSessionInfo().getIdentity().equals(user)) {
if (resourceUpdatedEvent.getPath().equals(pathToPomXML)) {
reloadRunnable.run();
}
}
}
private void configureBuildExtensions(final Project project,
final ButtonGroup buildButtonGroup) {
cleanExtensions();
final DropDownMenu buildDropdown = getDropdown(buildButtonGroup);
if (project == null || buildDropdown == null) {
buildExtensions = null;
return;
}
final Pair<Collection<BuildOptionExtension>, Collection<BuildOptionExtension>> pair = getBuildExtensions();
Collection<BuildOptionExtension> allExtensions = pair.getK1();
Collection<BuildOptionExtension> dependentScopedExtensions = pair.getK2();
buildExtensions = new ArrayList<Widget>(allExtensions.size());
for (BuildOptionExtension ext : allExtensions) {
for (Widget option : ext.getBuildOptions(project)) {
if (option instanceof DropDownHeader ||
option instanceof AnchorListItem) {
buildExtensions.add(option);
buildDropdown.add(option);
}
}
}
destroyExtensions(dependentScopedExtensions);
}
private DropDownMenu getDropdown(final ButtonGroup buildButtonGroup) {
for (int i = 0; i < buildButtonGroup.getWidgetCount(); i++) {
final Widget widget = buildButtonGroup.getWidget(i);
if (widget instanceof DropDownMenu) {
return (DropDownMenu) widget;
}
}
return null;
}
private void cleanExtensions() {
if (buildExtensions != null && buildOptions != null) {
final DropDownMenu dropdownMenu = ((DropDownMenu) buildOptions.getWidget(1));
for (Widget ext : buildExtensions) {
dropdownMenu.remove(ext);
}
}
}
protected Pair<Collection<BuildOptionExtension>, Collection<BuildOptionExtension>> getBuildExtensions() {
AsyncBeanManager beanManager = IOC.getAsyncBeanManager();
Collection<AsyncBeanDef<BuildOptionExtension>> beans = beanManager.lookupBeans(BuildOptionExtension.class);
final Collection<BuildOptionExtension> dependentScoped = new ArrayList<BuildOptionExtension>(beans.size());
final Collection<BuildOptionExtension> instances = new ArrayList<BuildOptionExtension>(beans.size());
for (final AsyncBeanDef<BuildOptionExtension> bean : beans) {
/*
* We are assuming that extensions are not marked with @LoadAsync.
* Thus getInstance will immediately invoke the callback.
*/
bean.getInstance(new CreationalCallback<BuildOptionExtension>() {
@Override
public void callback(BuildOptionExtension extension) {
instances.add(extension);
if (bean.getScope().equals(Dependent.class)) {
dependentScoped.add(extension);
}
}
});
}
return new Pair<Collection<BuildOptionExtension>, Collection<BuildOptionExtension>>(instances,
dependentScoped);
}
protected void destroyExtensions(Collection<BuildOptionExtension> extensions) {
AsyncBeanManager beanManager = IOC.getAsyncBeanManager();
for (BuildOptionExtension ext : extensions) {
beanManager.destroyBean(ext);
}
}
@OnStartup
public void onStartup(final PlaceRequest placeRequest) {
this.placeRequest = placeRequest;
update();
}
@OnMayClose
public boolean onMayClose() {
if (isDirty()) {
return view.confirmClose();
}
return true;
}
@OnClose
public void onClose() {
workbenchContext.removeChangeHandler(projectContextChangeHandle);
for (LockManager lockManager : lockManagers.values()) {
lockManager.releaseLock();
lockManagerInstanceProvider.destroy(lockManager);
}
lockManagers.clear();
}
private void update() {
if (workbenchContext.getActiveProject() == null) {
enableMenus(false);
view.showNoProjectSelected();
view.hideBusyIndicator();
} else {
enableMenus(true);
view.showProjectEditor();
showCurrentProjectInfoIfAny((KieProject) workbenchContext.getActiveProject());
}
}
private void showCurrentProjectInfoIfAny(final KieProject project) {
if (project != null && !project.equals(this.project)) {
this.project = project;
this.kieDeploymentDescriptoPath = PathFactory.newPath(KIE_DEPLOYMENT_DESCRIPTOR_XML,
project.getRootPath().toURI() + "/src/main/resources/META-INF/" + KIE_DEPLOYMENT_DESCRIPTOR_XML);
setupPathToPomXML();
init();
}
}
private void init() {
view.showBusyIndicator(CommonConstants.INSTANCE.Loading());
projectScreenService.call(
new RemoteCallback<ProjectScreenModel>() {
@Override
public void callback(ProjectScreenModel model) {
concurrentUpdateSessionInfo = null;
ProjectScreenPresenter.this.model = model;
view.setPOM(model.getPOM());
validateGroupID(model.getPOM().getGav().getGroupId());
validateArtifactID(model.getPOM().getGav().getArtifactId());
validateVersion(model.getPOM().getGav().getVersion());
view.setDependencies(model.getPOM(),
model.getWhiteList());
view.setPomMetadata(model.getPOMMetaData());
view.setPomMetadataUnlockHandler(getUnlockHandler(model.getPOMMetaData().getPath()));
view.setKModule(model.getKModule());
view.setKModuleMetadata(model.getKModuleMetaData());
view.setKModuleMetadataUnlockHandler(getUnlockHandler(model.getKModuleMetaData().getPath()));
view.setImports(model.getProjectImports());
view.setImportsMetadata(model.getProjectImportsMetaData());
view.setImportsMetadataUnlockHandler(getUnlockHandler(model.getProjectImportsMetaData().getPath()));
view.setRepositories(model.getRepositories());
view.setDeploymentDescriptorEnabled(isDeploymentDescritorEditorAvailable(StreamSupport.stream(resourceTypes.spliterator(),
false),
kieDeploymentDescriptoPath));
view.hideBusyIndicator();
originalHash = model.hashCode();
for (MenuItem mi : menus.getItemsMap().values()) {
mi.setEnabled(true);
}
updateEditorTitle();
updateCurrentView();
}
},
new CommandDrivenErrorCallback(view,
new CommandBuilder()
.addNoSuchFileException(view,
menus)
.addFileSystemNotFoundException(view,
menus)
.build())).load(pathToPomXML);
if (model == null) {
view.showGAVPanel();
}
configureBuildExtensions(project,
buildOptions);
}
private void updateEditorTitle() {
title = ProjectEditorResources.CONSTANTS.ProjectScreenWithName(model.getPOM().getGav().getGroupId() + ":" +
model.getPOM().getGav().getArtifactId() + ":" +
model.getPOM().getGav().getVersion());
changeTitleWidgetEvent.fire(new ChangeTitleWidgetEvent(placeRequest,
title));
}
private void updateCurrentView() {
if (view.showsGAVPanel()) {
onGAVPanelSelected();
} else if (view.showsGAVMetadataPanel()) {
onGAVMetadataPanelSelected();
} else if (view.showsKBasePanel()) {
onKBasePanelSelected();
} else if (view.showsKBaseMetadataPanel()) {
onKBaseMetadataPanelSelected();
} else if (view.showsImportsPanel()) {
onImportsPanelSelected();
} else if (view.showsImportsMetadataPanel()) {
onImportsMetadataPanelSelected();
} else if (view.showsRepositoriesPanel()) {
onRepositoriesPanelSelected();
} else if (view.showsDependenciesPanel()) {
onDependenciesSelected();
}
}
protected void setupPathToPomXML() {
if (pathToPomXML != null) {
pathToPomXML.dispose();
}
pathToPomXML = IOC.getBeanManager().lookupBean(ObservablePath.class).getInstance().wrap(project.getPomXMLPath());
pathToPomXML.onConcurrentUpdate(new ParameterizedCommand<ObservablePath.OnConcurrentUpdateEvent>() {
@Override
public void execute(final ObservablePath.OnConcurrentUpdateEvent eventInfo) {
concurrentUpdateSessionInfo = eventInfo;
}
});
pathToPomXML.onConcurrentRename(new ParameterizedCommand<ObservablePath.OnConcurrentRenameEvent>() {
@Override
public void execute(final ObservablePath.OnConcurrentRenameEvent info) {
newConcurrentRename(info.getSource(),
info.getTarget(),
info.getIdentity(),
new Command() {
@Override
public void execute() {
enableMenus(false);
}
},
new Command() {
@Override
public void execute() {
reload();
}
}
).show();
}
});
pathToPomXML.onConcurrentDelete(new ParameterizedCommand<ObservablePath.OnConcurrentDelete>() {
@Override
public void execute(final ObservablePath.OnConcurrentDelete info) {
newConcurrentDelete(info.getPath(),
info.getIdentity(),
new Command() {
@Override
public void execute() {
enableMenus(false);
}
},
new Command() {
@Override
public void execute() {
placeManager.closePlace("projectScreen");
}
}
).show();
}
});
}
void enableMenus(final boolean enabled) {
for (MenuItem mi : menus.getItems()) {
mi.setEnabled(enabled);
}
}
private void reload() {
concurrentUpdateSessionInfo = null;
view.showBusyIndicator(CommonConstants.INSTANCE.Loading());
init();
}
private Menus makeMenuBar() {
return MenuFactory
.newTopLevelMenu(CommonConstants.INSTANCE.Save())
.withPermission(Project.RESOURCE_TYPE,
project,
ProjectAction.UPDATE)
.respondsWith(getSaveCommand(DeploymentMode.VALIDATED))
.endMenu()
.newTopLevelMenu(CommonConstants.INSTANCE.Delete())
.withPermission(Project.RESOURCE_TYPE,
project,
ProjectAction.DELETE)
.respondsWith(getDeleteCommand())
.endMenu()
.newTopLevelMenu(CommonConstants.INSTANCE.Rename())
.withPermission(Project.RESOURCE_TYPE,
project,
ProjectAction.UPDATE)
.respondsWith(getRenameCommand())
.endMenu()
.newTopLevelMenu(CommonConstants.INSTANCE.Copy())
.withPermission(Project.RESOURCE_TYPE,
project,
ProjectAction.CREATE)
.respondsWith(getCopyCommand())
.endMenu()
.newTopLevelMenu(CommonConstants.INSTANCE.Reimport())
.withPermission(Project.RESOURCE_TYPE,
project,
ProjectAction.UPDATE)
.respondsWith(getReImportCommand())
.endMenu()
.newTopLevelCustomMenu(new MenuFactory.CustomMenuBuilder() {
@Override
public void push(MenuFactory.CustomMenuBuilder element) {
}
@Override
public MenuItem build() {
return new BaseMenuCustom<IsWidget>() {
private boolean enabled;
@Override
public IsWidget build() {
return buildOptions;
}
@Override
public boolean isEnabled() {
return enabled;
}
@Override
public void setEnabled(boolean enabled) {
this.enabled = enabled;
((Button) buildOptions.getWidget(0)).setEnabled(enabled);
}
@Override
public List<ResourceActionRef> getResourceActions() {
ResourceActionRef ref = new ResourceActionRef(Project.RESOURCE_TYPE,
project,
ProjectAction.BUILD);
return Collections.singletonList(ref);
}
};
}
}).endMenu()
.build();
}
protected Command getReImportCommand() {
return new Command() {
@Override
public void execute() {
projectScreenService.call(
new RemoteCallback<Void>() {
@Override
public void callback(final Void o) {
busyIndicatorView.hideBusyIndicator();
notificationEvent.fire(new NotificationEvent(CommonConstants.INSTANCE.ReimportSuccessful()));
}
},
new HasBusyIndicatorDefaultErrorCallback(busyIndicatorView)).reImport(project.getPomXMLPath());
}
};
}
private Command getDeleteCommand() {
return new Command() {
@Override
public void execute() {
deletePopUpPresenter.show(new ParameterizedCommand<String>() {
@Override
public void execute(final String comment) {
busyIndicatorView.showBusyIndicator(CommonConstants.INSTANCE.Deleting());
projectScreenService.call(
new RemoteCallback<Void>() {
@Override
public void callback(final Void o) {
busyIndicatorView.hideBusyIndicator();
notificationEvent.fire(new NotificationEvent(CommonConstants.INSTANCE.ItemDeletedSuccessfully()));
placeManager.forceClosePlace(placeRequest);
}
},
new HasBusyIndicatorDefaultErrorCallback(busyIndicatorView)).delete(project.getPomXMLPath(),
comment);
}
});
}
};
}
private Command getCopyCommand() {
return new Command() {
@Override
public void execute() {
copyPopUpPresenter.show(project.getRootPath(),
projectNameValidator,
new CommandWithFileNameAndCommitMessage() {
@Override
public void execute(final FileNameAndCommitMessage details) {
busyIndicatorView.showBusyIndicator(CommonConstants.INSTANCE.Copying());
projectScreenService.call(
new RemoteCallback<Void>() {
@Override
public void callback(final Void o) {
copyPopUpPresenter.getView().hide();
busyIndicatorView.hideBusyIndicator();
notificationEvent.fire(new NotificationEvent(CommonConstants.INSTANCE.ItemCopiedSuccessfully()));
}
},
getCopyErrorCallback(copyPopUpPresenter.getView())).copy(project.getPomXMLPath(),
details.getNewFileName(),
details.getCommitMessage());
}
});
}
};
}
protected HasBusyIndicatorDefaultErrorCallback getCopyErrorCallback(final CopyPopUpPresenter.View copyPopupView) {
return new HasBusyIndicatorDefaultErrorCallback(busyIndicatorView) {
@Override
public boolean error(final Message message,
final Throwable throwable) {
copyPopupView.hide();
return super.error(message,
throwable);
}
};
}
private Command getRenameCommand() {
return new Command() {
@Override
public void execute() {
renamePopUpPresenter.show(project.getRootPath(),
projectNameValidator,
new CommandWithFileNameAndCommitMessage() {
@Override
public void execute(final FileNameAndCommitMessage details) {
busyIndicatorView.showBusyIndicator(CommonConstants.INSTANCE.Renaming());
projectScreenService.call(
new RemoteCallback<ProjectScreenModel>() {
@Override
public void callback(final ProjectScreenModel model) {
renamePopUpPresenter.getView().hide();
busyIndicatorView.hideBusyIndicator();
notificationEvent.fire(new NotificationEvent(CommonConstants.INSTANCE.ItemRenamedSuccessfully()));
}
},
getRenameErrorCallback(renamePopUpPresenter.getView())).rename(project.getPomXMLPath(),
details.getNewFileName(),
details.getCommitMessage());
}
});
}
};
}
protected HasBusyIndicatorDefaultErrorCallback getRenameErrorCallback(final RenamePopUpPresenter.View renamePopupView) {
return new HasBusyIndicatorDefaultErrorCallback(busyIndicatorView) {
@Override
public boolean error(final Message message,
final Throwable throwable) {
renamePopupView.hide();
return super.error(message,
throwable);
}
};
}
private Command getCancelCommand() {
return new Command() {
@Override
public void execute() {
}
};
}
Command getSaveCommand(final DeploymentMode mode) {
return new Command() {
@Override
public void execute() {
saveProject(new RemoteCallback<Void>() {
@Override
public void callback(Void v) {
view.hideBusyIndicator();
notificationEvent.fire(new NotificationEvent(ProjectEditorResources.CONSTANTS.SaveSuccessful(pathToPomXML.getFileName()),
NotificationEvent.NotificationType.SUCCESS));
originalHash = model.hashCode();
}
},
mode);
}
};
}
private Command getSaveAndExecuteCommand(final Command command,
final DeploymentMode mode) {
return new Command() {
@Override
public void execute() {
saveProject(new RemoteCallback<Void>() {
@Override
public void callback(Void v) {
notificationEvent.fire(new NotificationEvent(ProjectEditorResources.CONSTANTS.SaveSuccessful(pathToPomXML.getFileName()),
NotificationEvent.NotificationType.SUCCESS));
originalHash = model.hashCode();
command.execute();
}
},
mode);
}
};
}
private void saveProject(final RemoteCallback<Void> callback,
final DeploymentMode mode) {
if (concurrentUpdateSessionInfo != null) {
newConcurrentUpdate(concurrentUpdateSessionInfo.getPath(),
concurrentUpdateSessionInfo.getIdentity(),
new Command() {
@Override
public void execute() {
save(callback,
mode);
}
},
new Command() {
@Override
public void execute() {
//cancel?
}
},
new Command() {
@Override
public void execute() {
reload();
}
}
).show();
} else {
save(callback,
mode);
}
}
private void save(final RemoteCallback<Void> callback,
final DeploymentMode mode) {
savePopUpPresenter.show(pathToPomXML,
new ParameterizedCommand<String>() {
@Override
public void execute(final String comment) {
doSave(comment,
callback,
mode);
}
});
concurrentUpdateSessionInfo = null;
}
private void doSave(final String comment,
final RemoteCallback<Void> callback,
final DeploymentMode mode) {
view.showBusyIndicator(CommonConstants.INSTANCE.Saving());
//Instantiate a new instance on each "save" operation to pass in commit message
final Map<Class<? extends Throwable>, CommandWithThrowableDrivenErrorCallback.CommandWithThrowable> onSaveGavExistsHandler = new HashMap<Class<? extends Throwable>, CommandWithThrowableDrivenErrorCallback.CommandWithThrowable>() {{
put(GAVAlreadyExistsException.class,
new CommandWithThrowableDrivenErrorCallback.CommandWithThrowable() {
@Override
public void execute(final Throwable parameter) {
view.hideBusyIndicator();
conflictingRepositoriesPopup.setContent(model.getPOM().getGav(),
((GAVAlreadyExistsException) parameter).getRepositories(),
new Command() {
@Override
public void execute() {
conflictingRepositoriesPopup.hide();
doSave(comment,
callback,
DeploymentMode.FORCED);
}
});
conflictingRepositoriesPopup.show();
}
});
}};
projectScreenService.call(new RemoteCallback<Void>() {
@Override
public void callback(Void v) {
project.setPom(model.getPOM());
if (callback != null) {
callback.callback(v);
}
}
},
new CommandWithThrowableDrivenErrorCallback(view,
onSaveGavExistsHandler)).save(pathToPomXML,
model,
comment,
mode);
updateEditorTitle();
}
@Override
public void triggerBuild() {
runBuild(() -> buildExecutor.triggerBuild());
}
@Override
public void triggerBuildAndDeploy() {
runBuild(() -> buildExecutor.triggerBuildAndDeploy());
}
private void runBuild(final Command buildCommand) {
if (isDirty()) {
view.showSaveBeforeContinue(getSaveAndExecuteCommand(buildCommand,
DeploymentMode.VALIDATED),
buildCommand,
getCancelCommand());
} else {
buildCommand.execute();
}
}
@WorkbenchPartTitle
public String getTitle() {
return ProjectEditorResources.CONSTANTS.ProjectScreen();
}
@WorkbenchPartView
public IsWidget asWidget() {
return view.asWidget();
}
@WorkbenchMenu
public Menus getMenus() {
if (menus == null) {
menus = makeMenuBar();
}
return menus;
}
@Override
public void onGAVPanelSelected() {
view.showGAVPanel();
acquireLockOnDemand(model.getPathToPOM(),
view.getPomPart());
}
@Override
public void onGAVMetadataPanelSelected() {
view.showGAVMetadataPanel();
acquireLockOnDemand(model.getPathToPOM(),
view.getPomMetadataPart());
}
@Override
public void onProjectPreferencesSelected() {
Map<String, String> params = new HashMap<>();
params.put("screen",
"project");
params.put("perspectiveIdentifierToGoBackTo",
"AuthoringPerspective");
placeManager.goTo(new DefaultPlaceRequest(AdminPagePerspective.IDENTIFIER,
params));
}
@Override
public void onKBasePanelSelected() {
view.showKBasePanel();
acquireLockOnDemand(model.getPathToKModule(),
view.getKModulePart());
}
@Override
public void onKBaseMetadataPanelSelected() {
view.showKBaseMetadataPanel();
acquireLockOnDemand(model.getPathToKModule(),
view.getKModuleMetadataPart());
}
@Override
public void onImportsPanelSelected() {
view.showImportsPanel();
acquireLockOnDemand(model.getPathToImports(),
view.getImportsPart());
}
@Override
public void onImportsMetadataPanelSelected() {
view.showImportsMetadataPanel();
acquireLockOnDemand(model.getPathToImports(),
view.getImportsMetadataPart());
}
@Override
public void onRepositoriesPanelSelected() {
view.showRepositoriesPanel();
acquireLockOnDemand(model.getPathToRepositories(),
view.getRepositoriesPart());
}
@Override
public void onDependenciesSelected() {
view.showDependenciesPanel();
acquireLockOnDemand(model.getPathToPOM(),
view.getDependenciesPart());
}
@Override
public void onDeploymentDescriptorSelected() {
placeManager.goTo(kieDeploymentDescriptoPath);
}
@Override
public void onPersistenceDescriptorSelected() {
Map<String, Object> attrs = new HashMap<String, Object>();
attrs.put(PathFactory.VERSION_PROPERTY,
new Boolean(true));
PathPlaceRequest placeRequest = new PathPlaceRequest(PathFactory.newPath("persistence.xml",
project.getRootPath().toURI() + "/src/main/resources/META-INF/persistence.xml",
attrs));
placeRequest.addParameter("createIfNotExists",
"true");
placeManager.goTo(placeRequest);
}
private boolean isDirty() {
Integer currentHash = model != null ? model.hashCode() : null;
if (originalHash == null) {
return currentHash != null;
} else {
return !originalHash.equals(currentHash);
}
}
@Override
public void validateGroupID(final String groupId) {
validationService.call(new RemoteCallback<Boolean>() {
@Override
public void callback(final Boolean result) {
view.setValidGroupID(Boolean.TRUE.equals(result));
}
}).validateGroupId(groupId);
}
@Override
public void validateArtifactID(final String artifactId) {
validationService.call(new RemoteCallback<Boolean>() {
@Override
public void callback(final Boolean result) {
view.setValidArtifactID(Boolean.TRUE.equals(result));
}
}).validateArtifactId(artifactId);
}
@Override
public void validateVersion(final String version) {
validationService.call(new RemoteCallback<Boolean>() {
@Override
public void callback(final Boolean result) {
view.setValidVersion(Boolean.TRUE.equals(result));
}
}).validateGAVVersion(version);
}
private void acquireLockOnDemand(final Path path,
final Widget widget) {
final LockManager lockManager = getOrCreateLockManager(widget);
final LockTarget lockTarget = new LockTarget(path,
widget,
placeRequest,
titleProvider,
reloadRunnable);
lockManager.init(lockTarget);
lockManager.acquireLockOnDemand();
}
private LockManager getOrCreateLockManager(final Widget widget) {
LockManager lockManager = lockManagers.get(widget);
if (lockManager == null) {
lockManager = lockManagerInstanceProvider.get();
lockManagers.put(widget,
lockManager);
}
return lockManager;
}
private Runnable getUnlockHandler(final Path path) {
return new Runnable() {
@Override
public void run() {
forceLockReleaseEvent.fire(new ForceUnlockEvent(path));
}
};
}
@SuppressWarnings("unused")
private void onLockChange(@Observes LockInfo lockInfo) {
if (model == null) {
return;
}
final Metadata pomMetaData = model.getPOMMetaData();
if (pomMetaData != null && lockInfo.getFile().equals(pomMetaData.getPath())) {
pomMetaData.setLockInfo(lockInfo);
view.setPomMetadata(pomMetaData);
}
final Metadata kModuleMetaData = model.getKModuleMetaData();
if (kModuleMetaData != null && lockInfo.getFile().equals(kModuleMetaData.getPath())) {
kModuleMetaData.setLockInfo(lockInfo);
view.setKModuleMetadata(kModuleMetaData);
}
final Metadata projectImportsMetaData = model.getProjectImportsMetaData();
if (projectImportsMetaData != null && lockInfo.getFile().equals(projectImportsMetaData.getPath())) {
projectImportsMetaData.setLockInfo(lockInfo);
view.setImportsMetadata(projectImportsMetaData);
}
}
}