Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 6086f3b90e7817fafac47b634f41ae44542001c1 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
/*******************************************************************************
 * 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.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.IJobChangeListener;
import org.eclipse.core.runtime.jobs.IJobManager;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.team.core.diff.IDiff;
import org.eclipse.team.core.mapping.IMergeContext;
import org.eclipse.team.core.mapping.IResourceDiffTree;
import org.eclipse.team.core.mapping.ISynchronizationContext;
import org.eclipse.team.internal.ui.Policy;
import org.eclipse.team.internal.ui.TeamUIPlugin;
import org.eclipse.team.internal.ui.Utils;
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.
 * <p>
 * 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 <code>shouldRun</code> 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 <code>null</code> if the operation does not buffer
	 * its results. By default, <code>null</code> is returned but
	 * subclasses may override.
	 * @return the saveable that this operation will write its results
	 * to or <code>null</code>
	 */
	public SaveableComparison getSaveable() {
		return null;
	}

	@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;

}

Back to the top