| /*=============================================================================# |
| # Copyright (c) 2014, 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; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IProjectDescription; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.resources.WorkspaceJob; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.MultiStatus; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.core.runtime.SubMonitor; |
| import org.eclipse.osgi.util.NLS; |
| |
| import org.eclipse.statet.eutils.autonature.core.ProjectConfigurator; |
| |
| |
| public class TaskProcessor { |
| |
| |
| private class ConfigJob extends WorkspaceJob { |
| |
| |
| public ConfigJob() { |
| super("Auto Project Configuration"); |
| setUser(false); |
| setRule(ResourcesPlugin.getWorkspace().getRoot()); |
| } |
| |
| |
| @Override |
| public IStatus runInWorkspace(final IProgressMonitor monitor) throws CoreException { |
| return TaskProcessor.this.process(monitor); |
| } |
| |
| } |
| |
| |
| public static void aggregateTasks(final IProject project, final List<AutoConfig> configs, |
| final int flags, |
| List<Task> configurableTasks, List<Task> alreadyConfigTasks, List<Task> notConfigTasks, |
| final SubMonitor m) throws CoreException { |
| final int l= configs.size(); |
| |
| if (configurableTasks == null) { |
| configurableTasks= new ArrayList<>(l); |
| } |
| if (alreadyConfigTasks == null) { |
| alreadyConfigTasks= new ArrayList<>(l); |
| } |
| if (notConfigTasks == null) { |
| notConfigTasks= new ArrayList<>(); |
| } |
| |
| for (int i= 0; i < l; i++) { |
| m.setWorkRemaining(l - i); |
| |
| final AutoConfig config= configs.get(i); |
| if (config.isAvailable()) { |
| for (final Task task : config.getTasks()) { |
| if (!(configurableTasks.contains(task) |
| || alreadyConfigTasks.contains(task) |
| || notConfigTasks.contains(task) )) { |
| switch (task.check(project, flags, m.newChild(1))) { |
| case ProjectConfigurator.CONFIGURABLE: |
| configurableTasks.add(task); |
| break; |
| case ProjectConfigurator.ALREADY_CONFIGURED: |
| alreadyConfigTasks.add(task); |
| break; |
| default: |
| notConfigTasks.add(task); |
| break; |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| public static IStatus process(final IProject project, final Collection<Task> tasks, |
| final SubMonitor m) { |
| try { |
| int taskCount= 0; |
| for (final Task task : tasks) { |
| if (task instanceof ConfiguratorTask) { |
| taskCount++; |
| } |
| } |
| |
| m.beginTask(NLS.bind("Configuring project ''{0}''", project.getName()), 3 + taskCount); |
| final IProjectDescription description= project.getDescription(); |
| boolean descriptionChanged= false; |
| |
| final String[] existingNatureIds= description.getNatureIds(); |
| final List<String> natureIds= new ArrayList<>(existingNatureIds.length + tasks.size()); |
| for (int i= 0; i < existingNatureIds.length; i++) { |
| natureIds.add(existingNatureIds[i]= existingNatureIds[i].intern()); |
| } |
| for (final Task task : tasks) { |
| if (task instanceof NatureTask) { |
| final String natureId= ((NatureTask) task).getNatureId(); |
| if (!contains(existingNatureIds, natureId)) { |
| natureIds.add(natureId); |
| } |
| } |
| } |
| m.worked(1); |
| |
| if (natureIds.size() > existingNatureIds.length) { |
| final ConfigManager configManager= Activator.getInstance().getConfigManager(); |
| configManager.arrangeNatures(natureIds, existingNatureIds.length); |
| description.setNatureIds(natureIds.toArray(new String[natureIds.size()])); |
| descriptionChanged= true; |
| } |
| |
| if (descriptionChanged) { |
| project.setDescription(description, m.newChild(1)); |
| } |
| |
| m.setWorkRemaining(taskCount); |
| for (final Task task : tasks) { |
| if (task instanceof ConfiguratorTask) { |
| ((ConfiguratorTask) task).configure(project, m.newChild(1)); |
| } |
| } |
| |
| return Status.OK_STATUS; |
| } |
| catch (final CoreException e) { |
| return new Status(IStatus.ERROR, Activator.BUNDLE_ID, |
| NLS.bind("An error occurred when configuring project ''{0}''.", project.getName()), |
| e ); |
| } |
| } |
| |
| |
| private Map<IProject, List<Task>> projectTasks; |
| |
| private ConfigJob job; |
| |
| |
| public TaskProcessor() { |
| this.projectTasks= new HashMap<>(); |
| } |
| |
| |
| public synchronized void add(final IProject project, final List<Task> tasks) { |
| final List<Task> allTasks= this.projectTasks.get(project); |
| if (allTasks == null) { |
| this.projectTasks.put(project, new ArrayList<>(tasks)); |
| return; |
| } |
| for (final Task task : tasks) { |
| if (!allTasks.contains(task)) { |
| allTasks.add(task); |
| } |
| } |
| } |
| |
| public synchronized void schedule() { |
| if (this.projectTasks.isEmpty()) { |
| return; |
| } |
| if (this.job == null) { |
| this.job= new ConfigJob(); |
| } |
| this.job.schedule(); |
| } |
| |
| |
| private IStatus process(final IProgressMonitor monitor) { |
| final Map<IProject, List<Task>> tasks; |
| synchronized (this) { |
| tasks= this.projectTasks; |
| if (tasks.isEmpty()) { |
| return Status.OK_STATUS; |
| } |
| this.projectTasks= new HashMap<>(); |
| } |
| |
| final SubMonitor m= SubMonitor.convert(monitor, tasks.size()); |
| List<IStatus> status= null; |
| for (final Map.Entry<IProject, List<Task>> entry : tasks.entrySet()) { |
| final IStatus projectStatus= process(entry.getKey(), entry.getValue(), |
| m.newChild(1, SubMonitor.SUPPRESS_NONE) ); |
| if (!projectStatus.isOK()) { |
| if (status == null) { |
| status= new ArrayList<>(tasks.size()); |
| } |
| status.add(projectStatus); |
| } |
| } |
| |
| if (status != null) { |
| return new MultiStatus(Activator.BUNDLE_ID, 0, status.toArray(new IStatus[status.size()]), |
| (status.size() == 1) ? |
| "The auto project configuration failed for 1 project." : |
| NLS.bind("The auto project configuration failed for {0} projects.", status.size()), |
| null ); |
| } |
| return Status.OK_STATUS; |
| } |
| |
| private static boolean contains(final String[] array, final String s) { |
| for (int i= 0; i < array.length; i++) { |
| if (array[i] == s) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| } |