1 11 package org.eclipse.ltk.ui.refactoring.model; 12 13 import java.io.IOException ; 14 import java.io.InputStream ; 15 import java.util.HashSet ; 16 import java.util.Set ; 17 18 import org.eclipse.team.core.diff.IDiff; 19 import org.eclipse.team.core.diff.IThreeWayDiff; 20 import org.eclipse.team.core.diff.ITwoWayDiff; 21 import org.eclipse.team.core.history.IFileRevision; 22 import org.eclipse.team.core.mapping.IMergeContext; 23 import org.eclipse.team.core.mapping.IMergeStatus; 24 import org.eclipse.team.core.mapping.IResourceDiff; 25 import org.eclipse.team.core.mapping.ResourceMappingMerger; 26 import org.eclipse.team.core.mapping.provider.MergeStatus; 27 28 import org.eclipse.core.runtime.Assert; 29 import org.eclipse.core.runtime.CoreException; 30 import org.eclipse.core.runtime.IProgressMonitor; 31 import org.eclipse.core.runtime.IStatus; 32 import org.eclipse.core.runtime.NullProgressMonitor; 33 import org.eclipse.core.runtime.Status; 34 import org.eclipse.core.runtime.SubProgressMonitor; 35 36 import org.eclipse.core.resources.IProject; 37 import org.eclipse.core.resources.IStorage; 38 import org.eclipse.core.resources.IWorkspaceRoot; 39 import org.eclipse.core.resources.ResourcesPlugin; 40 import org.eclipse.core.resources.mapping.ModelProvider; 41 import org.eclipse.core.resources.mapping.ResourceMapping; 42 43 import org.eclipse.ltk.core.refactoring.RefactoringCore; 44 import org.eclipse.ltk.core.refactoring.RefactoringDescriptor; 45 import org.eclipse.ltk.core.refactoring.RefactoringDescriptorProxy; 46 import org.eclipse.ltk.core.refactoring.history.RefactoringHistory; 47 48 import org.eclipse.ltk.internal.core.refactoring.history.RefactoringHistoryImplementation; 49 import org.eclipse.ltk.internal.core.refactoring.history.RefactoringHistoryService; 50 import org.eclipse.ltk.internal.ui.refactoring.RefactoringUIMessages; 51 import org.eclipse.ltk.internal.ui.refactoring.RefactoringUIPlugin; 52 import org.eclipse.ltk.internal.ui.refactoring.model.RefactoringHistoryMergeWizard; 53 54 import org.eclipse.swt.widgets.Display; 55 import org.eclipse.swt.widgets.Shell; 56 57 import org.eclipse.jface.dialogs.MessageDialog; 58 import org.eclipse.jface.window.Window; 59 import org.eclipse.jface.wizard.WizardDialog; 60 61 import org.eclipse.ui.IWorkbench; 62 import org.eclipse.ui.IWorkbenchWindow; 63 import org.eclipse.ui.PlatformUI; 64 65 import org.eclipse.ltk.ui.refactoring.history.RefactoringHistoryControlConfiguration; 66 67 85 public abstract class AbstractResourceMappingMerger extends ResourceMappingMerger { 86 87 88 private static final class RefactoringHistoryModelMergeConfiguration extends RefactoringHistoryControlConfiguration { 89 90 96 public RefactoringHistoryModelMergeConfiguration(final IProject project) { 97 super(project, false, false); 98 } 99 100 103 public String getProjectPattern() { 104 return RefactoringUIMessages.RefactoringModelMerger_project_pattern; 105 } 106 107 110 public String getWorkspaceCaption() { 111 return RefactoringUIMessages.RefactoringModelMerger_workspace_caption; 112 } 113 } 114 115 116 private static final class RefactoringHistoryModelMergeWizard extends RefactoringHistoryMergeWizard { 117 118 121 public RefactoringHistoryModelMergeWizard() { 122 super(RefactoringUIMessages.RefactoringWizard_refactoring, RefactoringUIMessages.AbstractRefactoringModelMerger_wizard_title, RefactoringUIMessages.AbstractRefactoringModelMerger_wizard_description); 123 } 124 } 125 126 131 private static Shell getActiveShell() { 132 final IWorkbench workbench= PlatformUI.getWorkbench(); 133 if (workbench != null) { 134 final IWorkbenchWindow window= workbench.getActiveWorkbenchWindow(); 135 if (window != null) 136 return window.getShell(); 137 } 138 return null; 139 } 140 141 149 private static IProject[] getAffectedProjects(final RefactoringHistory history) { 150 final Set set= new HashSet (); 151 final RefactoringDescriptorProxy[] proxies= history.getDescriptors(); 152 final IWorkspaceRoot root= ResourcesPlugin.getWorkspace().getRoot(); 153 for (int index= 0; index < proxies.length; index++) { 154 final String name= proxies[index].getProject(); 155 if (name != null && !"".equals(name)) set.add(root.getProject(name)); 157 else 158 return null; 159 } 160 final IProject[] projects= new IProject[set.size()]; 161 set.toArray(projects); 162 return projects; 163 } 164 165 170 private static Shell getDialogShell() { 171 final Shell[] shell= new Shell[] { null}; 172 Display.getDefault().syncExec(new Runnable () { 173 174 public final void run() { 175 shell[0]= getActiveShell(); 176 } 177 }); 178 return shell[0]; 179 } 180 181 182 private final ModelProvider fModelProvider; 183 184 190 protected AbstractResourceMappingMerger(final ModelProvider provider) { 191 Assert.isNotNull(provider); 192 fModelProvider= provider; 193 } 194 195 214 protected IStatus aboutToPerformMerge(final IMergeContext context, final IProgressMonitor monitor) { 215 Assert.isNotNull(context); 216 Assert.isNotNull(monitor); 217 try { 218 monitor.beginTask(RefactoringUIMessages.RefactoringModelMerger_merge_message, 100); 219 final IDiff[] diffs= getDiffs(context); 220 final RefactoringHistory history= getRefactoringHistory(diffs, monitor); 221 if (history != null && !history.isEmpty()) { 222 boolean execute= true; 223 final IProject[] projects= getAffectedProjects(history); 224 if (projects != null) { 225 final IProject[] dependencies= getDependencies(projects); 226 if (dependencies.length == 0) 227 execute= false; 228 } 229 if (execute) { 230 final Shell shell= getDialogShell(); 231 shell.getDisplay().syncExec(new Runnable () { 232 233 public final void run() { 234 if (MessageDialog.openQuestion(shell, RefactoringUIMessages.RefactoringWizard_refactoring, RefactoringUIMessages.AbstractRefactoringModelMerger_accept_question)) { 235 final RefactoringHistoryMergeWizard wizard= new RefactoringHistoryModelMergeWizard(); 236 int result= Window.OK; 237 try { 238 wizard.setConfiguration(new RefactoringHistoryModelMergeConfiguration((projects != null && projects.length == 1) ? projects[0] : null)); 239 wizard.setInput(history); 240 result= new WizardDialog(shell, wizard).open(); 241 } finally { 242 if (result != Window.CANCEL) 243 wizard.resolveConflicts(context); 244 } 245 } 246 } 247 }); 248 } 249 } 250 } finally { 251 monitor.done(); 252 } 253 return new Status(IStatus.OK, RefactoringCore.ID_PLUGIN, 0, "", null); } 255 256 265 private IStatus createMergeStatus(final IMergeContext context, final IStatus status) { 266 if (status.getCode() == IMergeStatus.CONFLICTS) 267 return new MergeStatus(status.getPlugin(), status.getMessage(), context.getScope().getMappings(fModelProvider.getDescriptor().getId())); 268 return status; 269 } 270 271 287 protected abstract IProject[] getDependencies(IProject[] projects); 288 289 296 private IDiff[] getDiffs(final IMergeContext context) { 297 final ResourceMapping[] mappings= context.getScope().getMappings(fModelProvider.getDescriptor().getId()); 298 final Set set= new HashSet (); 299 for (int index= 0; index < mappings.length; index++) { 300 final IDiff[] diffs= context.getDiffTree().getDiffs(context.getScope().getTraversals(mappings[index])); 301 for (int offset= 0; offset < diffs.length; offset++) 302 set.add(diffs[offset]); 303 } 304 return (IDiff[]) set.toArray(new IDiff[set.size()]); 305 } 306 307 310 protected final ModelProvider getModelProvider() { 311 return fModelProvider; 312 } 313 314 323 private RefactoringHistory getRefactoringHistory(final IDiff[] diffs, final IProgressMonitor monitor) { 324 final Set result= new HashSet (); 325 try { 326 monitor.beginTask(RefactoringUIMessages.RefactoringModelMerger_retrieving_refactorings, diffs.length * 2); 327 for (int index= 0; index < diffs.length; index++) { 328 final IDiff diff= diffs[index]; 329 if (diff instanceof IThreeWayDiff) { 330 final IThreeWayDiff threeWay= (IThreeWayDiff) diff; 331 final Set localDescriptors= new HashSet (); 332 final Set remoteDescriptors= new HashSet (); 333 final ITwoWayDiff localDiff= threeWay.getLocalChange(); 334 if (localDiff instanceof IResourceDiff && localDiff.getKind() != IDiff.NO_CHANGE) { 335 final IResourceDiff resourceDiff= (IResourceDiff) localDiff; 336 final IFileRevision revision= resourceDiff.getAfterState(); 337 if (revision != null) { 338 final String name= revision.getName(); 339 if (name.equalsIgnoreCase(RefactoringHistoryService.NAME_HISTORY_FILE)) 340 getRefactoringDescriptors(revision, localDescriptors, new SubProgressMonitor(monitor, 1, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL)); 341 } 342 } 343 final ITwoWayDiff remoteDiff= threeWay.getLocalChange(); 344 if (remoteDiff instanceof IResourceDiff && remoteDiff.getKind() != IDiff.NO_CHANGE) { 345 final IResourceDiff resourceDiff= (IResourceDiff) remoteDiff; 346 final IFileRevision revision= resourceDiff.getAfterState(); 347 if (revision != null) { 348 final String name= revision.getName(); 349 if (name.equalsIgnoreCase(RefactoringHistoryService.NAME_HISTORY_FILE)) 350 getRefactoringDescriptors(revision, remoteDescriptors, new SubProgressMonitor(monitor, 1, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL)); 351 } 352 } 353 remoteDescriptors.removeAll(localDescriptors); 354 result.addAll(remoteDescriptors); 355 } 356 } 357 } finally { 358 monitor.done(); 359 } 360 return new RefactoringHistoryImplementation((RefactoringDescriptorProxy[]) result.toArray(new RefactoringDescriptorProxy[result.size()])); 361 } 362 363 374 static final void getRefactoringDescriptors(final IFileRevision revision, final Set descriptors, final IProgressMonitor monitor) { 375 try { 376 monitor.beginTask(RefactoringUIMessages.RefactoringModelMerger_retrieving_refactorings, 1); 377 IStorage storage= null; 378 try { 379 storage= revision.getStorage(new SubProgressMonitor(monitor, 1, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL)); 380 } catch (CoreException exception) { 381 RefactoringUIPlugin.log(exception); 382 } 383 if (storage != null) { 384 InputStream stream= null; 385 try { 386 stream= storage.getContents(); 387 final RefactoringHistory history= RefactoringHistoryService.getInstance().readRefactoringHistory(stream, RefactoringDescriptor.MULTI_CHANGE); 388 final RefactoringDescriptorProxy[] proxies= history.getDescriptors(); 389 for (int offset= 0; offset < proxies.length; offset++) 390 descriptors.add(proxies[offset].requestDescriptor(null)); 391 } catch (CoreException exception) { 392 RefactoringUIPlugin.log(exception); 393 } finally { 394 if (stream != null) { 395 try { 396 stream.close(); 397 } catch (IOException exception) { 398 } 400 } 401 } 402 } 403 } finally { 404 monitor.done(); 405 } 406 } 407 408 411 public IStatus merge(final IMergeContext context, IProgressMonitor monitor) throws CoreException { 412 Assert.isNotNull(context); 413 IStatus status= new Status(IStatus.OK, RefactoringCore.ID_PLUGIN, 0, "", null); if (monitor == null) 415 monitor= new NullProgressMonitor(); 416 try { 417 monitor.beginTask(RefactoringUIMessages.RefactoringModelMerger_merge_message, 200); 418 if (status.getSeverity() != IStatus.ERROR) { 420 final IDiff[] diffs= getDiffs(context); 421 status= createMergeStatus(context, context.merge(diffs, false, new SubProgressMonitor(monitor, 100))); 422 final int code= status.getCode(); 423 if (status.getSeverity() != IStatus.ERROR && code != IMergeStatus.CONFLICTS && code != IMergeStatus.INTERNAL_ERROR) 424 status= mergePerformed(context, new SubProgressMonitor(monitor, 25)); 425 } 426 } finally { 427 monitor.done(); 428 } 429 return status; 430 } 431 432 449 protected IStatus mergePerformed(final IMergeContext context, final IProgressMonitor monitor) { 450 Assert.isNotNull(context); 451 Assert.isNotNull(monitor); 452 try { 453 monitor.beginTask(RefactoringUIMessages.RefactoringModelMerger_merge_message, 1); 454 return new Status(IStatus.OK, RefactoringCore.ID_PLUGIN, 0, "", null); } finally { 456 monitor.done(); 457 } 458 } 459 } 460 | Popular Tags |