/*******************************************************************************
* 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.part.explorer.project.synchronize;
import com.google.common.base.Optional;
import com.google.inject.Inject;
import com.google.inject.Singleton;
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.workspace.shared.dto.SourceStorageDto;
import org.eclipse.che.ide.CoreLocalizationConstant;
import org.eclipse.che.ide.api.app.AppContext;
import org.eclipse.che.ide.api.data.tree.Node;
import org.eclipse.che.ide.api.dialogs.DialogFactory;
import org.eclipse.che.ide.api.notification.NotificationManager;
import org.eclipse.che.ide.api.resources.Project;
import org.eclipse.che.ide.api.resources.Resource;
import org.eclipse.che.ide.api.resources.marker.Marker;
import org.eclipse.che.ide.part.explorer.project.ProjectExplorerPresenter;
import org.eclipse.che.ide.resources.tree.ResourceNode;
import org.eclipse.che.ide.util.loging.Log;
import java.util.List;
import java.util.Map;
import static com.google.common.base.Strings.isNullOrEmpty;
import static org.eclipse.che.api.core.ErrorCodes.NO_PROJECT_ON_FILE_SYSTEM;
import static org.eclipse.che.ide.api.notification.StatusNotification.DisplayMode.EMERGE_MODE;
import static org.eclipse.che.ide.api.notification.StatusNotification.Status.SUCCESS;
import static org.eclipse.che.ide.api.resources.Project.ProblemProjectMarker.PROBLEM_PROJECT;
/**
* Synchronize projects in workspace with projects on file system.
* The synchronization performs based on project problems.
* Project problem with code 10 means that project exist in workspace but it is absent on file system.
*/
@Singleton
public class ProjectConfigSynchronized {
private final AppContext appContext;
private final DialogFactory dialogFactory;
private final CoreLocalizationConstant locale;
private final NotificationManager notificationManager;
private final ChangeLocationWidget changeLocationWidget;
@Inject
public ProjectConfigSynchronized(AppContext appContext,
ProjectExplorerPresenter projectExplorerPresenter,
DialogFactory dialogFactory,
CoreLocalizationConstant locale,
NotificationManager notificationManager,
ChangeLocationWidget changeLocationWidget) {
this.appContext = appContext;
this.dialogFactory = dialogFactory;
this.locale = locale;
this.notificationManager = notificationManager;
this.changeLocationWidget = changeLocationWidget;
projectExplorerPresenter.getTree().getNodeLoader().addBeforeLoadHandler(event -> {
final Node requestedNode = event.getRequestedNode();
if (requestedNode == null || !(requestedNode instanceof ResourceNode)) {
return;
}
final ResourceNode resourceNode = (ResourceNode)requestedNode;
final Resource data = resourceNode.getData();
if (!data.isProject()) {
return;
}
checkProjectProblems((Project)data);
});
}
private void checkProjectProblems(Project project) {
final Optional<Marker> marker = project.getMarker(PROBLEM_PROJECT);
if (!marker.isPresent()) {
return;
}
final Project.ProblemProjectMarker problemProjectMarker = (Project.ProblemProjectMarker)marker.get();
final Map<Integer, String> problems = problemProjectMarker.getProblems();
//If no project folder on file system
final String noProjectFolderProblem = problems.get(NO_PROJECT_ON_FILE_SYSTEM);
final List<String> importingProjects = appContext.getImportingProjects();
if (!isNullOrEmpty(noProjectFolderProblem) && !importingProjects.contains(project.getPath())) {
showImportDialog(project);
}
}
private void showImportDialog(Project project) {
dialogFactory.createConfirmDialog(locale.synchronizeDialogTitle(),
locale.existInWorkspaceDialogContent(project.getName()),
locale.buttonImport(),
locale.buttonRemove(),
() -> importCallback(project),
() -> deleteCallback(project)).show();
}
private Promise<Void> deleteCallback(Project project) {
return project.delete().then(deletedProject -> {
notificationManager.notify(locale.projectRemoved(project.getName()),
SUCCESS,
EMERGE_MODE);
});
}
private void importCallback(Project project) {
final String location = project.getSource().getLocation();
if (isNullOrEmpty(location)) {
changeLocation(project);
return;
}
importProject(project);
}
private void changeLocation(Project project) {
dialogFactory.createConfirmDialog(locale.synchronizeDialogTitle(), changeLocationWidget, () -> {
final SourceStorageDto source = (SourceStorageDto)project.getSource();
source.setLocation(changeLocationWidget.getText());
source.setType("github");
importProject(project);
}, null).show();
}
private void importProject(Project project) {
appContext.getWorkspaceRoot().importProject().withBody(project).send().then(new Operation<Project>() {
@Override
public void apply(Project project) throws OperationException {
Log.info(getClass(), "Project " + project.getName() + " imported.");
}
});
}
}