/*******************************************************************************
* Copyright (c) 2012-2015 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.projecttype.wizard.presenter;
import org.eclipse.che.api.project.shared.dto.BuildersDescriptor;
import org.eclipse.che.api.project.shared.dto.GeneratorDescription;
import org.eclipse.che.api.project.shared.dto.ImportProject;
import org.eclipse.che.api.project.shared.dto.ItemReference;
import org.eclipse.che.api.project.shared.dto.NewProject;
import org.eclipse.che.api.project.shared.dto.ProjectDescriptor;
import org.eclipse.che.api.project.shared.dto.ProjectTemplateDescriptor;
import org.eclipse.che.api.project.shared.dto.ProjectTypeDefinition;
import org.eclipse.che.api.project.shared.dto.RunnersDescriptor;
import org.eclipse.che.api.project.shared.dto.Source;
import org.eclipse.che.ide.api.project.type.wizard.ProjectWizardMode;
import org.eclipse.che.ide.api.project.type.wizard.ProjectWizardRegistrar;
import org.eclipse.che.ide.api.project.type.wizard.ProjectWizardRegistry;
import org.eclipse.che.ide.api.wizard.Wizard;
import org.eclipse.che.ide.api.wizard.WizardPage;
import org.eclipse.che.ide.collections.Array;
import org.eclipse.che.ide.dto.DtoFactory;
import org.eclipse.che.ide.projecttype.wizard.ProjectWizard;
import org.eclipse.che.ide.projecttype.wizard.categoriespage.CategoriesPagePresenter;
import org.eclipse.che.ide.projecttype.wizard.runnerspage.RunnersPagePresenter;
import org.eclipse.che.ide.projecttype.wizard.ProjectWizardFactory;
import org.eclipse.che.ide.projecttype.wizard.categoriespage.CategoriesPagePresenter;
import org.eclipse.che.ide.ui.dialogs.DialogFactory;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.Map;
import static org.eclipse.che.ide.api.project.type.wizard.ProjectWizardMode.CREATE;
import static org.eclipse.che.ide.api.project.type.wizard.ProjectWizardMode.CREATE_MODULE;
import static org.eclipse.che.ide.api.project.type.wizard.ProjectWizardMode.IMPORT;
import static org.eclipse.che.ide.api.project.type.wizard.ProjectWizardMode.UPDATE;
/**
* Presenter for project wizard.
*
* @author Evgen Vidolob
* @author Oleksii Orel
* @author Sergii Leschenko
* @author Artem Zatsarynnyy
*/
@Singleton
public class ProjectWizardPresenter implements Wizard.UpdateDelegate,
ProjectWizardView.ActionDelegate,
CategoriesPagePresenter.ProjectTypeSelectionListener,
CategoriesPagePresenter.ProjectTemplateSelectionListener {
private final ProjectWizardView view;
private final DtoFactory dtoFactory;
private final DialogFactory dialogFactory;
private final BuilderRegistry builderRegistry;
private final RunnersRegistry runnersRegistry;
private final ProjectWizardFactory projectWizardFactory;
private final ProjectWizardRegistry wizardRegistry;
private final Provider<CategoriesPagePresenter> categoriesPageProvider;
private final Provider<RunnersPagePresenter> runnersPageProvider;
private final Map<ProjectTypeDefinition, ProjectWizard> wizardsCache;
private CategoriesPagePresenter categoriesPage;
private RunnersPagePresenter runnersPage;
private ProjectWizard wizard;
private ProjectWizard importWizard;
private WizardPage currentPage;
private ProjectWizardMode wizardMode;
/** Contains project's path when project wizard opened for updating project. */
private String projectPath;
@Inject
public ProjectWizardPresenter(ProjectWizardView view,
DtoFactory dtoFactory,
DialogFactory dialogFactory,
BuilderRegistry builderRegistry,
RunnersRegistry runnersRegistry,
ProjectWizardFactory projectWizardFactory,
ProjectWizardRegistry wizardRegistry,
Provider<CategoriesPagePresenter> categoriesPageProvider,
Provider<RunnersPagePresenter> runnersPageProvider) {
this.view = view;
this.dtoFactory = dtoFactory;
this.dialogFactory = dialogFactory;
this.builderRegistry = builderRegistry;
this.runnersRegistry = runnersRegistry;
this.projectWizardFactory = projectWizardFactory;
this.wizardRegistry = wizardRegistry;
this.categoriesPageProvider = categoriesPageProvider;
this.runnersPageProvider = runnersPageProvider;
wizardsCache = new HashMap<>();
view.setDelegate(this);
}
@Override
public void onBackClicked() {
final WizardPage prevPage = wizard.navigateToPrevious();
if (prevPage != null) {
showPage(prevPage);
}
}
@Override
public void onNextClicked() {
final WizardPage nextPage = wizard.navigateToNext();
if (nextPage != null) {
showPage(nextPage);
}
}
@Override
public void onSaveClicked() {
view.setLoaderVisibility(true);
wizard.complete(new Wizard.CompleteCallback() {
@Override
public void onCompleted() {
view.close();
}
@Override
public void onFailure(Throwable e) {
view.setLoaderVisibility(false);
dialogFactory.createMessageDialog("", e.getMessage(), null).show();
}
});
}
@Override
public void onCancelClicked() {
view.close();
}
@Override
public void updateControls() {
view.setPreviousButtonEnabled(wizard.hasPrevious());
view.setNextButtonEnabled(wizard.hasNext() && currentPage.isCompleted());
view.setFinishButtonEnabled(wizard.canComplete());
}
/** Open the project wizard for creating a new project. */
public void show() {
resetState();
wizardMode = CREATE;
showDialog(null);
}
/** Open the project wizard for updating the given {@code project}. */
public void show(@Nonnull ProjectDescriptor project) {
resetState();
wizardMode = UPDATE;
projectPath = project.getPath();
final ImportProject dataObject = dtoFactory.createDto(ImportProject.class)
.withProject(dtoFactory.createDto(NewProject.class)
.withType(project.getType())
.withName(project.getName())
.withDescription(project.getDescription())
.withVisibility(project.getVisibility())
.withAttributes(new HashMap<>(project.getAttributes()))
.withBuilders(project.getBuilders())
.withRunners(project.getRunners()));
dataObject.getProject().setMixinTypes(project.getMixins());
showDialog(dataObject);
}
/** Open the project wizard for creating module from the given {@code folder}. */
public void show(@Nonnull ItemReference folder) {
resetState();
wizardMode = CREATE_MODULE;
projectPath = folder.getPath();
final ImportProject dataObject = dtoFactory.createDto(ImportProject.class)
.withProject(dtoFactory.createDto(NewProject.class)
.withName(folder.getName()));
showDialog(dataObject);
}
private void resetState() {
wizardsCache.clear();
categoriesPage = categoriesPageProvider.get();
runnersPage = runnersPageProvider.get();
wizardMode = null;
categoriesPage.setProjectTypeSelectionListener(this);
categoriesPage.setProjectTemplateSelectionListener(this);
projectPath = null;
importWizard = null;
}
private void showDialog(@Nullable ImportProject dataObject) {
wizard = createDefaultWizard(dataObject, wizardMode);
final WizardPage<ImportProject> firstPage = wizard.navigateToFirst();
if (firstPage != null) {
showPage(firstPage);
view.showDialog(wizardMode);
}
}
@Override
public void onProjectTypeSelected(ProjectTypeDefinition projectType) {
updateView(projectType.getDefaultBuilder(), projectType.getDefaultRunner());
final ImportProject prevData = wizard.getDataObject();
wizard = getWizardForProjectType(projectType);
wizard.navigateToFirst();
final NewProject newProject = wizard.getDataObject().getProject();
// some values should be shared between wizards for different project types
NewProject prevDataProject = prevData.getProject();
newProject.setName(prevDataProject.getName());
newProject.setDescription(prevDataProject.getDescription());
newProject.setVisibility(prevDataProject.getVisibility());
newProject.setMixinTypes(prevDataProject.getMixinTypes());
if (wizardMode == UPDATE) {
newProject.setAttributes(prevDataProject.getAttributes());
}
// set dataObject's values from projectType
newProject.setType(projectType.getId());
newProject.setBuilders(dtoFactory.createDto(BuildersDescriptor.class).withDefault(projectType.getDefaultBuilder()));
if (newProject.getRunners() == null) {
newProject.setRunners(prevDataProject.getRunners());
}
}
@Override
public void onProjectTemplateSelected(ProjectTemplateDescriptor projectTemplate) {
final BuildersDescriptor builders = projectTemplate.getBuilders();
final RunnersDescriptor runners = projectTemplate.getRunners();
updateView(builders == null ? null : builders.getDefault(),
runners == null ? null : runners.getDefault());
final ImportProject prevData = wizard.getDataObject();
wizard = importWizard == null ? importWizard = createDefaultWizard(null, IMPORT) : importWizard;
wizard.navigateToFirst();
final ImportProject dataObject = wizard.getDataObject();
final NewProject newProject = dataObject.getProject();
// some values should be shared between wizards for different project types
newProject.setName(prevData.getProject().getName());
newProject.setDescription(prevData.getProject().getDescription());
newProject.setVisibility(prevData.getProject().getVisibility());
// set dataObject's values from projectTemplate
newProject.setType(projectTemplate.getProjectType());
newProject.setBuilders(builders);
newProject.setRunners(runners);
dataObject.getSource().setProject(projectTemplate.getSource());
}
private void updateView(@Nullable String builderName, @Nullable String runnerId) {
if (builderName != null) {
final String builderEnvName = builderRegistry.getDefaultEnvironmentName(builderName);
view.setBuilderEnvironmentConfig(builderEnvName);
} else {
view.setBuilderEnvironmentConfig(null);
}
if (runnerId != null) {
final String runnerDescription = runnersRegistry.getDescription(runnerId);
view.setRunnerEnvironmentConfig(runnerDescription);
} else {
view.setRunnerEnvironmentConfig(null);
}
}
/** Creates or returns project wizard for the specified projectType with the given dataObject. */
private ProjectWizard getWizardForProjectType(@Nonnull ProjectTypeDefinition projectType) {
if (wizardsCache.containsKey(projectType)) {
return wizardsCache.get(projectType);
}
final ProjectWizardRegistrar wizardRegistrar = wizardRegistry.getWizardRegistrar(projectType.getId());
if (wizardRegistrar == null) {
// should never occur
throw new IllegalStateException("WizardRegistrar for the project type " + projectType.getId() + " isn't registered.");
}
Array<Provider<? extends WizardPage<ImportProject>>> pageProviders = wizardRegistrar.getWizardPages();
final ProjectWizard projectWizard = createDefaultWizard(null, wizardMode);
for (Provider<? extends WizardPage<ImportProject>> provider : pageProviders.asIterable()) {
projectWizard.addPage(provider.get(), 1, false);
}
wizardsCache.put(projectType, projectWizard);
return projectWizard;
}
/** Creates and returns 'default' project wizard with pre-defined pages only. */
private ProjectWizard createDefaultWizard(@Nullable ImportProject dataObject, @Nonnull ProjectWizardMode mode) {
if (dataObject == null) {
dataObject = dtoFactory.createDto(ImportProject.class)
.withSource(dtoFactory.createDto(Source.class))
.withProject(dtoFactory.createDto(NewProject.class)
.withGeneratorDescription(dtoFactory.createDto(GeneratorDescription.class)));
}
final ProjectWizard projectWizard = projectWizardFactory.newWizard(dataObject, mode, projectPath);
projectWizard.setUpdateDelegate(this);
// add pre-defined pages - first and last
projectWizard.addPage(categoriesPage);
if (mode != IMPORT) {
projectWizard.addPage(runnersPage);
}
return projectWizard;
}
private void showPage(@Nonnull WizardPage wizardPage) {
currentPage = wizardPage;
updateControls();
view.showPage(currentPage);
}
}