/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.ide.ext.java.client.refactoring.move.wizard;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.eclipse.che.api.promises.client.Function;
import org.eclipse.che.api.promises.client.FunctionException;
import org.eclipse.che.api.promises.client.Operation;
import org.eclipse.che.api.promises.client.OperationException;
import org.eclipse.che.api.promises.client.Promise;
import org.eclipse.che.api.promises.client.PromiseError;
import org.eclipse.che.ide.api.editor.EditorAgent;
import org.eclipse.che.ide.api.editor.EditorPartPresenter;
import org.eclipse.che.ide.api.editor.texteditor.TextEditor;
import org.eclipse.che.ide.api.event.ng.ClientServerEventService;
import org.eclipse.che.ide.api.notification.NotificationManager;
import org.eclipse.che.ide.api.notification.StatusNotification.Status;
import org.eclipse.che.ide.api.resources.Container;
import org.eclipse.che.ide.api.resources.Project;
import org.eclipse.che.ide.api.resources.Resource;
import org.eclipse.che.ide.dto.DtoFactory;
import org.eclipse.che.ide.ext.java.client.JavaLocalizationConstant;
import org.eclipse.che.ide.ext.java.client.navigation.service.JavaNavigationService;
import org.eclipse.che.ide.ext.java.client.refactoring.RefactorInfo;
import org.eclipse.che.ide.ext.java.client.refactoring.RefactoringUpdater;
import org.eclipse.che.ide.ext.java.client.refactoring.preview.PreviewPresenter;
import org.eclipse.che.ide.ext.java.client.refactoring.service.RefactoringServiceClient;
import org.eclipse.che.ide.ext.java.client.util.JavaUtil;
import org.eclipse.che.ide.ext.java.shared.dto.model.JavaProject;
import org.eclipse.che.ide.ext.java.shared.dto.refactoring.ChangeCreationResult;
import org.eclipse.che.ide.ext.java.shared.dto.refactoring.ChangeInfo;
import org.eclipse.che.ide.ext.java.shared.dto.refactoring.CreateMoveRefactoring;
import org.eclipse.che.ide.ext.java.shared.dto.refactoring.ElementToMove;
import org.eclipse.che.ide.ext.java.shared.dto.refactoring.MoveSettings;
import org.eclipse.che.ide.ext.java.shared.dto.refactoring.RefactoringSession;
import org.eclipse.che.ide.ext.java.shared.dto.refactoring.RefactoringStatus;
import org.eclipse.che.ide.ext.java.shared.dto.refactoring.ReorgDestination;
import java.util.ArrayList;
import java.util.List;
import static org.eclipse.che.ide.api.notification.StatusNotification.DisplayMode.FLOAT_MODE;
import static org.eclipse.che.ide.ext.java.shared.dto.refactoring.RefactoringStatus.ERROR;
import static org.eclipse.che.ide.ext.java.shared.dto.refactoring.RefactoringStatus.FATAL;
import static org.eclipse.che.ide.ext.java.shared.dto.refactoring.RefactoringStatus.INFO;
import static org.eclipse.che.ide.ext.java.shared.dto.refactoring.RefactoringStatus.OK;
import static org.eclipse.che.ide.ext.java.shared.dto.refactoring.RefactoringStatus.WARNING;
/**
* The class that manages Move panel widget.
*
* @author Dmitry Shnurenko
* @author Valeriy Svydenko
*/
@Singleton
public class MovePresenter implements MoveView.ActionDelegate {
private final MoveView view;
private final RefactoringUpdater refactoringUpdater;
private final EditorAgent editorAgent;
private final PreviewPresenter previewPresenter;
private final DtoFactory dtoFactory;
private final RefactoringServiceClient refactorService;
private final JavaNavigationService navigationService;
private final JavaLocalizationConstant locale;
private final NotificationManager notificationManager;
private final ClientServerEventService clientServerEventService;
protected RefactorInfo refactorInfo;
private String refactoringSessionId;
@Inject
public MovePresenter(MoveView view,
RefactoringUpdater refactoringUpdater,
EditorAgent editorAgent,
PreviewPresenter previewPresenter,
RefactoringServiceClient refactorService,
JavaNavigationService navigationService,
DtoFactory dtoFactory,
JavaLocalizationConstant locale,
NotificationManager notificationManager,
ClientServerEventService clientServerEventService) {
this.view = view;
this.refactoringUpdater = refactoringUpdater;
this.editorAgent = editorAgent;
this.clientServerEventService = clientServerEventService;
this.view.setDelegate(this);
this.previewPresenter = previewPresenter;
this.refactorService = refactorService;
this.navigationService = navigationService;
this.dtoFactory = dtoFactory;
this.locale = locale;
this.notificationManager = notificationManager;
}
/**
* Show Move panel with the special information.
*
* @param refactorInfo
* information about the move operation
*/
public void show(final RefactorInfo refactorInfo) {
this.refactorInfo = refactorInfo;
view.setEnablePreviewButton(false);
view.setEnableAcceptButton(false);
view.clearErrorLabel();
CreateMoveRefactoring moveRefactoring = createMoveDto();
Promise<String> sessionIdPromise = refactorService.createMoveRefactoring(moveRefactoring);
sessionIdPromise.then(new Operation<String>() {
@Override
public void apply(String sessionId) throws OperationException {
MovePresenter.this.refactoringSessionId = sessionId;
showProjectsAndPackages();
}
}).catchError(new Operation<PromiseError>() {
@Override
public void apply(PromiseError error) throws OperationException {
notificationManager.notify(error.getMessage(), Status.FAIL, FLOAT_MODE);
}
});
}
private CreateMoveRefactoring createMoveDto() {
List<ElementToMove> elements = new ArrayList<>();
Project project = null;
for (Resource resource : refactorInfo.getResources()) {
ElementToMove element = dtoFactory.createDto(ElementToMove.class);
if (resource instanceof Container) {
element.setPath(resource.getLocation().toString());
element.setPack(true);
} else {
element.setPath(JavaUtil.resolveFQN(resource));
element.setPack(false);
}
elements.add(element);
if (project == null) {
project = resource.getRelatedProject().get();
}
}
CreateMoveRefactoring moveRefactoring = dtoFactory.createDto(CreateMoveRefactoring.class);
moveRefactoring.setElements(elements);
if (project != null) {
moveRefactoring.setProjectPath(project.getLocation().toString());
}
return moveRefactoring;
}
private void showProjectsAndPackages() {
Promise<List<JavaProject>> projectsPromise = navigationService.getProjectsAndPackages(true);
projectsPromise.then(new Operation<List<JavaProject>>() {
@Override
public void apply(List<JavaProject> projects) throws OperationException {
List<JavaProject> currentProject = new ArrayList<>();
for (JavaProject project : projects) {
currentProject.add(project);
}
view.setTreeOfDestinations(refactorInfo, currentProject);
view.show(refactorInfo);
}
}).catchError(new Operation<PromiseError>() {
@Override
public void apply(PromiseError error) throws OperationException {
notificationManager.notify(locale.showPackagesError(), error.getMessage(), Status.FAIL, FLOAT_MODE);
}
});
}
/** {@inheritDoc} */
@Override
public void onPreviewButtonClicked() {
RefactoringSession session = dtoFactory.createDto(RefactoringSession.class);
session.setSessionId(refactoringSessionId);
prepareMovingChanges(session).then(new Operation<ChangeCreationResult>() {
@Override
public void apply(ChangeCreationResult arg) throws OperationException {
if (arg.isCanShowPreviewPage()) {
previewPresenter.show(refactoringSessionId, refactorInfo);
view.hide();
} else {
view.showStatusMessage(arg.getStatus());
}
}
}).catchError(new Operation<PromiseError>() {
@Override
public void apply(PromiseError error) throws OperationException {
notificationManager.notify(locale.showPreviewError(), error.getMessage(), Status.FAIL, FLOAT_MODE);
}
});
}
/** {@inheritDoc} */
@Override
public void onAcceptButtonClicked() {
final RefactoringSession session = dtoFactory.createDto(RefactoringSession.class);
session.setSessionId(refactoringSessionId);
prepareMovingChanges(session).then(new Operation<ChangeCreationResult>() {
@Override
public void apply(ChangeCreationResult arg) throws OperationException {
if (arg.isCanShowPreviewPage()) {
clientServerEventService.sendFileTrackingSuspendEvent().then(success -> {
applyRefactoring(session);
});
} else {
view.showErrorMessage(arg.getStatus());
}
}
}).catchError(new Operation<PromiseError>() {
@Override
public void apply(PromiseError error) throws OperationException {
notificationManager.notify(locale.applyMoveError(), error.getMessage(), Status.FAIL, FLOAT_MODE);
}
});
}
private void applyRefactoring(RefactoringSession session) {
refactorService.applyRefactoring(session).then(refactoringResult -> {
List<ChangeInfo> changes = refactoringResult.getChanges();
if (refactoringResult.getSeverity() == OK) {
view.hide();
refactoringUpdater.updateAfterRefactoring(changes).then(arg -> {
Project project = null;
Resource[] resources = refactorInfo.getResources();
if (resources != null && resources.length == 1) {
project = resources[0].getProject();
}
if (project != null) {
refactorService.reindexProject(project.getPath());
}
refactoringUpdater.handleMovingFiles(changes).then(clientServerEventService.sendFileTrackingResumeEvent());
});
} else {
view.showErrorMessage(refactoringResult);
refactoringUpdater.handleMovingFiles(changes).then(clientServerEventService.sendFileTrackingResumeEvent());
}
});
}
/** {@inheritDoc} */
@Override
public void onCancelButtonClicked() {
EditorPartPresenter activeEditor = editorAgent.getActiveEditor();
if (activeEditor instanceof TextEditor) {
((TextEditor)activeEditor).setFocus();
}
}
/** {@inheritDoc} */
@Override
public void setMoveDestinationPath(String path, String projectPath) {
ReorgDestination destination = dtoFactory.createDto(ReorgDestination.class);
destination.setType(ReorgDestination.DestinationType.PACKAGE);
destination.setSessionId(refactoringSessionId);
destination.setProjectPath(projectPath);
destination.setDestination(path);
Promise<RefactoringStatus> promise = refactorService.setDestination(destination);
promise.then(new Operation<RefactoringStatus>() {
@Override
public void apply(RefactoringStatus arg) throws OperationException {
view.setEnableAcceptButton(true);
view.setEnablePreviewButton(true);
switch (arg.getSeverity()) {
case INFO:
view.showStatusMessage(arg);
break;
case WARNING:
view.showStatusMessage(arg);
break;
case ERROR:
showErrorMessage(arg);
break;
case FATAL:
showErrorMessage(arg);
break;
case OK:
default:
view.clearStatusMessage();
break;
}
}
});
}
private Promise<ChangeCreationResult> prepareMovingChanges(final RefactoringSession session) {
MoveSettings moveSettings = dtoFactory.createDto(MoveSettings.class);
moveSettings.setSessionId(refactoringSessionId);
moveSettings.setUpdateReferences(view.isUpdateReferences());
moveSettings.setUpdateQualifiedNames(view.isUpdateQualifiedNames());
if (moveSettings.isUpdateQualifiedNames()) {
moveSettings.setFilePatterns(view.getFilePatterns());
}
return refactorService.setMoveSettings(moveSettings).thenPromise(new Function<Void, Promise<ChangeCreationResult>>() {
@Override
public Promise<ChangeCreationResult> apply(Void arg) throws FunctionException {
return refactorService.createChange(session);
}
});
}
private void showErrorMessage(RefactoringStatus arg) {
view.showErrorMessage(arg);
view.setEnableAcceptButton(false);
view.setEnablePreviewButton(false);
}
}