Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/operations/ModelParticipantMergeOperation.java')
-rw-r--r--bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/operations/ModelParticipantMergeOperation.java236
1 files changed, 236 insertions, 0 deletions
diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/operations/ModelParticipantMergeOperation.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/operations/ModelParticipantMergeOperation.java
new file mode 100644
index 000000000..86aa17c72
--- /dev/null
+++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/operations/ModelParticipantMergeOperation.java
@@ -0,0 +1,236 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.team.ui.operations;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.compare.CompareConfiguration;
+import org.eclipse.core.resources.mapping.RemoteResourceMappingContext;
+import org.eclipse.core.runtime.*;
+import org.eclipse.core.runtime.jobs.*;
+import org.eclipse.team.core.mapping.*;
+import org.eclipse.team.internal.ui.TeamUIMessages;
+import org.eclipse.team.internal.ui.mapping.ModelParticipantPageDialog;
+import org.eclipse.team.ui.TeamUI;
+import org.eclipse.team.ui.synchronize.*;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.progress.WorkbenchJob;
+
+/**
+ * The steps of an optimistic merge operation are:
+ * <ol>
+ * <li>Obtain the selection to be operated on.
+ * <li>Determine the projection of the selection onto resources
+ * using resource mappings and traversals.
+ * <ul>
+ * <li>this will require traversals using both the ancestor and remote
+ * for three-way merges.
+ * <li>for model providers with registered merger, mapping set need
+ * not be expanded (this is tricky if one of the model providers doesn't
+ * have a merge but all others do).
+ * <li>if the model does not have a custom merger, ensure that additional
+ * mappings are included (i.e. for many model elements to one resource case)
+ * </ul>
+ * <li>Create a MergeContext for the merge
+ * <ul>
+ * <li>Determine the synchronization state of all resources
+ * covered by the input.
+ * <li>Pre-fetch the required contents.
+ * </ul>
+ * <li>Obtain and invoke the merger for each provider
+ * <ul>
+ * <li>This will auto-merge as much as possible
+ * <li>If everything was merged, cleanup and stop
+ * <li>Otherwise, a set of un-merged resource mappings is returned
+ * </ul>
+ * <li>Delegate manual merge to the model provider
+ * <ul>
+ * <li>This hands off the context to the manual merge
+ * <li>Once completed, the manual merge must clean up
+ * </ul>
+ * </ol>
+ *
+ * <p>
+ * Handle multiple model providers where one extends all others by using
+ * the top-most model provider. The assumption is that the model provider
+ * will delegate to lower level model providers when appropriate.
+ * <p>
+ * Special case to support sub-file merges.
+ * <ul>
+ * <li>Restrict when sub-file merging is supported
+ * <ul>
+ * <li>Only one provider involved (i.e. consulting participants results
+ * in participants that are from the model provider or below).
+ * <li>The provider has a custom auto and manual merger.
+ * </ul>
+ * <li>Prompt to warn when sub-file merging is not possible.
+ * <li>Need to display the additional elements that will be affected.
+ * This could be done in a diff tree or some other view. It needs to
+ * consider incoming changes including additions.
+ * </ul>
+ * <p>
+ * Special case to handle conflicting model providers.
+ * <ul>
+ * <li>Prompt user to indicate the conflict
+ * <li>Allow user to exclude one of the models?
+ * <li>Allow use to choose order of evaluation?
+ * <li>Support tabbed sync view
+ * </ul>
+ *
+ * <p>
+ * <strong>EXPERIMENTAL</strong>. This class or interface has been added as
+ * part of a work in progress. There is a guarantee neither that this API will
+ * work nor that it will remain the same. Please do not use this API without
+ * consulting with the Platform/Team team.
+ * </p>
+ *
+ * @since 3.2
+ */
+public abstract class ModelParticipantMergeOperation extends ModelMergeOperation {
+
+ /**
+ * Status code that can be returned from the {@link #performMerge(IProgressMonitor)}
+ * method to indicate that a subclass would like to force a preview of the merge.
+ * The message of such a status should be ignored.
+ */
+ public static final int REQUEST_PREVIEW = 1024;
+
+ private ModelSynchronizeParticipant participant;
+ private boolean ownsParticipant = true;
+
+ /**
+ * Create a merge participant operation for the scope of the given manager.
+ * @param part the workbench part from which the merge was launched or <code>null</code>
+ * @param manager the scope manager
+ */
+ protected ModelParticipantMergeOperation(IWorkbenchPart part, IResourceMappingScopeManager manager) {
+ super(part, manager);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.ui.operations.ModelMergeOperation#initializeContext(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ protected void initializeContext(IProgressMonitor monitor) throws CoreException {
+ if (participant == null) {
+ participant = createParticipant();
+ participant.getContext().refresh(getScope().getTraversals(),
+ RemoteResourceMappingContext.FILE_CONTENTS_REQUIRED, monitor);
+ try {
+ Platform.getJobManager().join(participant.getContext(), monitor);
+ } catch (InterruptedException e) {
+ throw new OperationCanceledException();
+ }
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.ui.operations.ModelMergeOperation#execute(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ protected void execute(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+ try {
+ super.execute(monitor);
+ } finally {
+ if (ownsParticipant && participant != null)
+ participant.dispose();
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.ui.operations.ModelMergeOperation#handlePreviewRequest()
+ */
+ protected void handlePreviewRequest() {
+ Job job = new WorkbenchJob(getJobName()) {
+ public IStatus runInUIThread(IProgressMonitor monitor) {
+ if (isPreviewInDialog()) {
+ CompareConfiguration cc = new CompareConfiguration();
+ ISynchronizePageConfiguration pageConfiguration = participant.createPageConfiguration();
+ // Restrict preview page to only support incomign and conflict modes
+ if (pageConfiguration.getComparisonType() == ISynchronizePageConfiguration.THREE_WAY) {
+ pageConfiguration.setSupportedModes(ISynchronizePageConfiguration.INCOMING_MODE | ISynchronizePageConfiguration.CONFLICTING_MODE);
+ pageConfiguration.setMode(ISynchronizePageConfiguration.INCOMING_MODE);
+ }
+ ParticipantPageDialog dialog = new ModelParticipantPageDialog(getShell(), participant, cc, pageConfiguration);
+ dialog.open();
+ } else {
+ ISynchronizeManager mgr = TeamUI.getSynchronizeManager();
+ ISynchronizeView view = mgr.showSynchronizeViewInActivePage();
+ mgr.addSynchronizeParticipants(new ISynchronizeParticipant[] {participant});
+ view.display(participant);
+ }
+ return Status.OK_STATUS;
+ }
+ };
+ job.addJobChangeListener(new JobChangeAdapter() {
+ public void done(IJobChangeEvent event) {
+ // Ensure that the participant is disposed it it didn't go to the sync view
+ if (TeamUI.getSynchronizeManager().get(participant.getId(), participant.getSecondaryId()) == null)
+ participant.dispose();
+ }
+
+ });
+ ownsParticipant = false;
+ job.schedule();
+ }
+
+ /**
+ * Return whether previews should occur in a dialog or in the synchronize view.
+ * @return whether previews should occur in a dialog or in the synchronize view
+ */
+ protected boolean isPreviewInDialog() {
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.ui.operations.ResourceMappingOperation#getContext()
+ */
+ protected ISynchronizationContext getContext() {
+ if (participant != null)
+ return participant.getContext();
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.ui.operations.ResourceMappingOperation#getPreviewRequestMessage()
+ */
+ protected String getPreviewRequestMessage() {
+ if (!isPreviewRequested()) {
+ return TeamUIMessages.ResourceMappingMergeOperation_4;
+ }
+ return super.getPreviewRequestMessage();
+ }
+
+ /**
+ * Create the synchronize pariticipant to be used by this operation
+ * to preview changes. By default, a {@link ModelSynchronizeParticipant}
+ * is created using the scope manager ({@link #getScopeManager()}) context
+ * from ({@link #createMergeContext()}) and job name ({@link #getJobName()})
+ * of this operation. Subclasses may override this method.
+ * <p>
+ * Once created, it is the responsibility of the participant to dispose of the
+ * synchronization context when it is no longer needed.
+ * @return a newly created synchronize pariticipant to be used by this operation
+ */
+ protected ModelSynchronizeParticipant createParticipant() {
+ return ModelSynchronizeParticipant.createParticipant(getScopeManager(), createMergeContext(), getJobName());
+ }
+
+ /**
+ * Create a merge context for use by this operation. This method
+ * is not long running so the operation should not refresh the
+ * context or perform other long running operations in this thread.
+ * However the context may start initializing in another thread as long
+ * as the job used to perform the initialization belongs to the
+ * family that matches the context.
+ * @return a merge context for use by this operation
+ */
+ protected abstract ISynchronizationContext createMergeContext();
+
+}

Back to the top