/******************************************************************************* * Copyright (c) 2006, 2009 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at * https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.team.ui.mapping; import java.lang.reflect.InvocationTargetException; import org.eclipse.core.resources.mapping.ResourceTraversal; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.jobs.*; import org.eclipse.team.core.diff.IDiff; import org.eclipse.team.core.mapping.*; import org.eclipse.team.internal.ui.*; import org.eclipse.team.ui.TeamOperation; import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration; import org.eclipse.team.ui.synchronize.ISynchronizePageSite; import org.eclipse.ui.IWorkbenchPart; /** * This operation class can be used by model providers when performing * merge operations triggered from a synchronize participant page * associated with a synchronization or merge context. *
* This class may be subclasses by clients.
*
* @see ISynchronizationContext
* @see IMergeContext
*
* @since 3.2
*/
public abstract class SynchronizationOperation extends TeamOperation {
private final ISynchronizePageConfiguration configuration;
private final Object[] elements;
/*
* Helper method for extracting the part safely from a configuration
*/
private static IWorkbenchPart getPart(ISynchronizePageConfiguration configuration) {
if (configuration != null) {
ISynchronizePageSite site = configuration.getSite();
if (site != null) {
return site.getPart();
}
}
return null;
}
/**
* Create a synchronize operation that operations on the given elements
* @param configuration the configuration for the page the operation is associated with
* @param elements the elements to be operated on
*/
protected SynchronizationOperation(ISynchronizePageConfiguration configuration, Object[] elements) {
super(getPart(configuration), configuration.getRunnableContext());
this.configuration = configuration;
this.elements = elements;
}
/**
* Return the configuration for the page from which this
* operation was launched.
* @return the configuration for the page from which this
* operation was launched
*/
public ISynchronizePageConfiguration getConfiguration() {
return configuration;
}
/**
* Return the synchronization context associated with this action.
* @return the synchronization context associated with this action
*/
protected ISynchronizationContext getContext() {
return (ISynchronizationContext)getConfiguration().getProperty(ITeamContentProviderManager.P_SYNCHRONIZATION_CONTEXT);
}
/**
* Return the model elements that are the target of this operation.
* @return the model elements that are the target of this operation
*/
public Object[] getElements() {
return elements;
}
/**
* Make shouldRun
public so the result
* can be used to provide handler enablement
*/
@Override
public boolean shouldRun() {
return super.shouldRun();
}
/**
* Return the saveable that this operation will write its results
* to or null
if the operation does not buffer
* its results. By default, null
is returned but
* subclasses may override.
* @return the saveable that this operation will write its results
* to or null
*/
public SaveableComparison getSaveable() {
return null;
}
/* (non-Javadoc)
* @see org.eclipse.jface.operation.IRunnableWithProgress#run(org.eclipse.core.runtime.IProgressMonitor)
*/
@Override
public final void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
try {
monitor.beginTask(null, 100);
setContextBusy(Policy.subMonitorFor(monitor, 5));
execute(Policy.subMonitorFor(monitor, 90));
} finally {
clearContextBusy(Policy.subMonitorFor(monitor, 5));
monitor.done();
}
}
private void clearContextBusy(final IProgressMonitor monitor) {
// Add a job change listener to the job manager that will clear the busy
// when there are no more jobs related to the context running
final IJobManager jobManager = Job.getJobManager();
final IJobChangeListener listener = new JobChangeAdapter() {
@Override
public void done(IJobChangeEvent event) {
Job[] jobs = jobManager.find(getContext());
if (jobs.length == 0) {
final IResourceDiffTree diffTree = getContext().getDiffTree();
diffTree.clearBusy(null);
jobManager.removeJobChangeListener(this);
}
}
};
jobManager.addJobChangeListener(listener);
}
private void setContextBusy(final IProgressMonitor monitor) {
try {
// TODO: This may miss setting some diffs (i.e. those that don't exist locally)
ResourceTraversal[] traversals = Utils.getTraversals(getElements());
final IResourceDiffTree diffTree = getContext().getDiffTree();
IDiff[] diffs = diffTree.getDiffs(traversals);
diffTree.setBusy(diffs, monitor);
} catch (CoreException e) {
TeamUIPlugin.log(e);
}
}
/**
* Execute the operation. Subclasses should implement the operations behavior in the
* execute method. Clients should call either {@link #run()} or {@link #run(IProgressMonitor)}
* to invoke the operation.
* @param monitor a progress monitor
* @throws InvocationTargetException
* @throws InterruptedException
*/
protected abstract void execute(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException;
}