blob: b684a67d559b0ef926376101ad5ccf051c7145e3 [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2016, 2021 Stephan Wahlbrink and others.
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License 2.0 which is available at
# https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
# which is available at https://www.apache.org/licenses/LICENSE-2.0.
#
# SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
#
# Contributors:
# Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
#=============================================================================*/
package org.eclipse.statet.internal.eutils.autonature.wizards;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.core.runtime.jobs.IJobManager;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.ui.statushandlers.StatusManager;
import org.eclipse.statet.ecommons.ui.dialogs.DialogUtils;
import org.eclipse.statet.internal.eutils.autonature.Activator;
import org.eclipse.statet.internal.eutils.autonature.AutoConfig;
import org.eclipse.statet.internal.eutils.autonature.ConfigManager;
import org.eclipse.statet.internal.eutils.autonature.ContentFinder;
import org.eclipse.statet.internal.eutils.autonature.Task;
import org.eclipse.statet.internal.eutils.autonature.TaskProcessor;
public class ConfigureProjectWizard extends Wizard {
private final IProject project;
private final ConfigManager configManager;
private ConfigureProjectWizardPage configPage;
private List<Task> allTasks;
public ConfigureProjectWizard(final IProject project) {
this.project= project;
this.configManager= Activator.getInstance().getConfigManager();
setDialogSettings(DialogUtils.getDialogSettings(Activator.getInstance(), "ConfigureProjectWizard")); //$NON-NLS-1$
setWindowTitle("Detect and Add Project Natures");
setNeedsProgressMonitor(true);
}
@Override
public void addPages() {
this.configPage= new ConfigureProjectWizardPage(this.project);
addPage(this.configPage);
}
void runInit() {
if (this.allTasks != null) {
return;
}
try {
final List<Task> allTasks= new ArrayList<>();
final List<Task> notConfigTasks= new ArrayList<>();
final List<Task> alreadyConfigTasks= new ArrayList<>();
final List<Task> selectedTasks= new ArrayList<>();
getContainer().run(true, true, new IRunnableWithProgress() {
@Override
public void run(final IProgressMonitor monitor) throws InvocationTargetException {
final SubMonitor m= SubMonitor.convert(monitor, 3 + 2);
try {
if (monitor.isCanceled()) {
throw new OperationCanceledException();
}
final ContentFinder contentFinder= new ContentFinder(
ConfigureProjectWizard.this.project, null,
ConfigureProjectWizard.this.configManager, ConfigManager.MANUAL_MODE,
m.newChild(3) );
ConfigureProjectWizard.this.project.accept(contentFinder);
if (monitor.isCanceled()) {
throw new OperationCanceledException();
}
final List<AutoConfig> recommendConfigs= contentFinder.getConfigs();
final List<AutoConfig> otherConfigs= new ArrayList<>();
for (final AutoConfig config : ConfigureProjectWizard.this.configManager.getConfigs(ConfigManager.MANUAL_MODE)) {
if (!recommendConfigs.contains(config)) {
otherConfigs.add(config);
}
}
TaskProcessor.aggregateTasks(ConfigureProjectWizard.this.project,
recommendConfigs, Task.CONTENT_MATCH,
selectedTasks, alreadyConfigTasks, notConfigTasks,
m.newChild(1) );
allTasks.addAll(selectedTasks);
TaskProcessor.aggregateTasks(ConfigureProjectWizard.this.project,
otherConfigs, 0,
allTasks, alreadyConfigTasks, notConfigTasks,
m.newChild(1) );
allTasks.addAll(alreadyConfigTasks);
notConfigTasks.addAll(alreadyConfigTasks);
}
catch (final CoreException e) {
if (e.getStatus().getSeverity() == IStatus.CANCEL) {
throw new InvocationTargetException(new OperationCanceledException());
}
throw new InvocationTargetException(e);
}
}
});
this.allTasks= allTasks;
this.configPage.setInput(allTasks, alreadyConfigTasks, selectedTasks);
}
catch (final InterruptedException e) {
return;
}
catch (final InvocationTargetException e) {
final Throwable cause= e.getCause();
if (cause instanceof InterruptedException) {
return;
}
StatusManager.getManager().handle(new Status(IStatus.ERROR, Activator.BUNDLE_ID, 0,
"An error occurred when detecting the project configuration proposal.", e ),
StatusManager.SHOW | StatusManager.LOG );
return;
}
}
void reset() {
this.allTasks= null;
this.configPage.resetInput();
runInit();
}
@Override
public boolean canFinish() {
return (this.configPage != null && this.configPage.isPageComplete());
}
@Override
public boolean performFinish() {
final Collection<Task> configTasks= this.configPage.getConfigTasks();
try {
getContainer().run(true, true, new IRunnableWithProgress() {
@Override
public void run(final IProgressMonitor monitor) throws InvocationTargetException {
final SubMonitor m= SubMonitor.convert(monitor, "Configure projects...", 1);
final IJobManager jobManager= Job.getJobManager();
final ISchedulingRule rule= ConfigureProjectWizard.this.project.getWorkspace().getRoot();
try {
jobManager.beginRule(rule, m);
final IStatus projectStatus= TaskProcessor.process(ConfigureProjectWizard.this.project, configTasks,
m.newChild(1) );
if (!projectStatus.isOK()) {
throw new InvocationTargetException(new CoreException(projectStatus));
}
}
catch (final OperationCanceledException e) {
throw new InvocationTargetException(e);
}
finally {
jobManager.endRule(rule);
}
}
});
}
catch (final InterruptedException e) {
reset();
return false;
}
catch (final InvocationTargetException e) {
final Throwable cause= e.getCause();
if (cause instanceof InterruptedException || cause instanceof OperationCanceledException) {
reset();
return false;
}
StatusManager.getManager().handle(new Status(IStatus.ERROR, Activator.BUNDLE_ID, 0,
"The project configuration failed for 1 project.", cause ),
StatusManager.SHOW | StatusManager.LOG );
return false;
}
return true;
}
}