1 /******************************************************************************* 2 * Copyright (c) 2000, 2017 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 *******************************************************************************/ 14 package org.eclipse.team.core.subscribers; 15 16 import org.eclipse.core.resources.IResource; 17 import org.eclipse.core.resources.IWorkspaceRunnable; 18 import org.eclipse.core.resources.mapping.ResourceTraversal; 19 import org.eclipse.core.runtime.CoreException; 20 import org.eclipse.core.runtime.IProgressMonitor; 21 import org.eclipse.core.runtime.ProgressMonitorWrapper; 22 import org.eclipse.team.core.diff.DiffFilter; 23 import org.eclipse.team.core.mapping.ISynchronizationScopeManager; 24 import org.eclipse.team.core.mapping.provider.MergeContext; 25 import org.eclipse.team.core.mapping.provider.ResourceDiffTree; 26 import org.eclipse.team.core.synchronize.SyncInfo; 27 import org.eclipse.team.internal.core.mapping.GroupProgressMonitor; 28 import org.eclipse.team.internal.core.subscribers.SubscriberDiffTreeEventHandler; 29 30 /** 31 * A merge context that uses a subscriber to populate the diff tree 32 * used by the context. The population of the diff tree is performed 33 * by a handler that runs in a background job. 34 * 35 * @see Subscriber 36 * @see MergeContext 37 * 38 * @since 3.2 39 */ 40 public abstract class SubscriberMergeContext extends MergeContext { 41 42 private Subscriber subscriber; 43 private SubscriberDiffTreeEventHandler handler; 44 private final ISynchronizationScopeManager manager; 45 46 /** 47 * Create a merge context for the given subscriber 48 * @param subscriber the subscriber 49 * @param manager the scope manager 50 */ SubscriberMergeContext(Subscriber subscriber, ISynchronizationScopeManager manager)51 protected SubscriberMergeContext(Subscriber subscriber, ISynchronizationScopeManager manager) { 52 super(manager, getType(subscriber), new ResourceDiffTree()); 53 this.subscriber = subscriber; 54 this.manager = manager; 55 } 56 getType(Subscriber subscriber)57 private static int getType(Subscriber subscriber) { 58 return subscriber.getResourceComparator().isThreeWay() 59 ? THREE_WAY : TWO_WAY; 60 } 61 62 /** 63 * Initialize the diff tree of this context. This method must 64 * be called before the context is given to clients. 65 */ initialize()66 protected void initialize() { 67 handler = new SubscriberDiffTreeEventHandler(subscriber, manager, (ResourceDiffTree)getDiffTree(), getDiffFilter()); 68 handler.setJobFamily(this); 69 handler.start(); 70 } 71 72 /** 73 * Return the diff filter used to filter the differences that the merge context will present to clients. 74 * @return the diff filter used to filter the differences that the merge context will present to clients 75 * @since 3.3 76 */ getDiffFilter()77 protected DiffFilter getDiffFilter() { 78 return null; 79 } 80 81 @Override refresh(ResourceTraversal[] traversals, int flags, IProgressMonitor monitor)82 public void refresh(ResourceTraversal[] traversals, int flags, 83 IProgressMonitor monitor) throws CoreException { 84 GroupProgressMonitor group = getGroup(monitor); 85 if (group != null) 86 handler.setProgressGroupHint(group.getGroup(), group.getTicks()); 87 handler.initializeIfNeeded(); 88 subscriber.refresh(traversals, monitor); 89 } 90 getGroup(IProgressMonitor monitor)91 private GroupProgressMonitor getGroup(IProgressMonitor monitor) { 92 if (monitor instanceof GroupProgressMonitor) { 93 return (GroupProgressMonitor) monitor; 94 } 95 if (monitor instanceof ProgressMonitorWrapper) { 96 ProgressMonitorWrapper wrapper = (ProgressMonitorWrapper) monitor; 97 return getGroup(wrapper.getWrappedProgressMonitor()); 98 } 99 return null; 100 } 101 102 @Override dispose()103 public void dispose() { 104 handler.shutdown(); 105 super.dispose(); 106 } 107 108 /** 109 * Return the sync info for the given resource. 110 * @param resource the resource 111 * @return the sync info for the resource obtained from the subscriber 112 * @throws CoreException if an error occurs 113 */ getSyncInfo(IResource resource)114 protected SyncInfo getSyncInfo(IResource resource) throws CoreException { 115 return handler.getSubscriber().getSyncInfo(resource); 116 } 117 118 /** 119 * Return the subscriber associated with this context. 120 * @return the subscriber associated with this context 121 */ getSubscriber()122 public Subscriber getSubscriber() { 123 return subscriber; 124 } 125 126 /** 127 * Run the given runnable when the background handler 128 * for this context is idle. The given runnable should not lock 129 * the workspace. 130 * @param runnable the runnable 131 */ runInBackground(IWorkspaceRunnable runnable)132 protected void runInBackground(IWorkspaceRunnable runnable) { 133 handler.run(runnable, false); 134 } 135 136 @Override 137 @SuppressWarnings("unchecked") getAdapter(Class<T> adapter)138 public <T> T getAdapter(Class<T> adapter) { 139 if (adapter == SubscriberDiffTreeEventHandler.class) 140 return (T) handler; 141 return super.getAdapter(adapter); 142 } 143 144 } 145