/******************************************************************************* * Copyright (c) 2007, 2008 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.ltk.core.refactoring.resource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.SubProgressMonitor; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.ltk.core.refactoring.Change; import org.eclipse.ltk.core.refactoring.ChangeDescriptor; import org.eclipse.ltk.core.refactoring.RefactoringStatus; import org.eclipse.ltk.internal.core.refactoring.BasicElementLabels; import org.eclipse.ltk.internal.core.refactoring.Messages; import org.eclipse.ltk.internal.core.refactoring.RefactoringCoreMessages; /** * {@link Change} that moves a resource. * * @since 3.4 */ public class MoveResourceChange extends ResourceChange { private final IResource fSource; private final IContainer fTarget; private final long fStampToRestore; private final Change fRestoreSourceChange; private ChangeDescriptor fDescriptor; /** * Creates the change. * * @param source the resource to move * @param target the container the resource is moved to. An existing resource at the destination will be * replaced. */ public MoveResourceChange(IResource source, IContainer target) { this(source, target, IResource.NULL_STAMP, null); } /** * Creates the change. * * @param source the resource to move * @param target the container the resource is moved to. An existing resource at the destination will be * replaced. * @param stampToRestore the stamp to restore on the moved resource * @param restoreSourceChange the change to restore a resource at the source or <code>null</code> if no resource * needs to be resourced. */ protected MoveResourceChange(IResource source, IContainer target, long stampToRestore, Change restoreSourceChange) { fSource= source; fTarget= target; fStampToRestore= stampToRestore; fRestoreSourceChange= restoreSourceChange; // We already present a dialog to the user if he // moves read-only resources. Since moving a resource // doesn't do a validate edit (it actually doesn't // change the content we can't check for READ only // here. setValidationMethod(VALIDATE_NOT_DIRTY); } /* (non-Javadoc) * @see org.eclipse.ltk.core.refactoring.Change#getDescriptor() */ public ChangeDescriptor getDescriptor() { return fDescriptor; } /** * Sets the change descriptor to be returned by {@link Change#getDescriptor()}. * * @param descriptor the change descriptor */ public void setDescriptor(ChangeDescriptor descriptor) { fDescriptor= descriptor; } /* (non-Javadoc) * @see org.eclipse.ltk.core.refactoring.Change#perform(org.eclipse.core.runtime.IProgressMonitor) */ public final Change perform(IProgressMonitor monitor) throws CoreException, OperationCanceledException { try { if (monitor == null) monitor= new NullProgressMonitor(); monitor.beginTask(getName(), 4); Change deleteUndo= null; // delete destination if required IResource resourceAtDestination= fTarget.findMember(fSource.getName()); if (resourceAtDestination != null && resourceAtDestination.exists()) { deleteUndo= performDestinationDelete(resourceAtDestination, new SubProgressMonitor(monitor, 1)); } else { monitor.worked(1); } // move resource long currentStamp= fSource.getModificationStamp(); IPath destinationPath= fTarget.getFullPath().append(fSource.getName()); fSource.move(destinationPath, IResource.KEEP_HISTORY | IResource.SHALLOW, new SubProgressMonitor(monitor, 2)); resourceAtDestination= ResourcesPlugin.getWorkspace().getRoot().findMember(destinationPath); // restore timestamp at destination if (fStampToRestore != IResource.NULL_STAMP) { resourceAtDestination.revertModificationStamp(fStampToRestore); } // restore file at source if (fRestoreSourceChange != null) { performSourceRestore(new SubProgressMonitor(monitor, 1)); } else { monitor.worked(1); } return new MoveResourceChange(resourceAtDestination, fSource.getParent(), currentStamp, deleteUndo); } finally { monitor.done(); } } private Change performDestinationDelete(IResource newResource, IProgressMonitor monitor) throws CoreException { monitor.beginTask(RefactoringCoreMessages.MoveResourceChange_progress_delete_destination, 3); try { DeleteResourceChange deleteChange= new DeleteResourceChange(newResource.getFullPath(), true); deleteChange.initializeValidationData(new SubProgressMonitor(monitor, 1)); RefactoringStatus deleteStatus= deleteChange.isValid(new SubProgressMonitor(monitor, 1)); if (!deleteStatus.hasFatalError()) { return deleteChange.perform(new SubProgressMonitor(monitor, 1)); } return null; } finally { monitor.done(); } } private void performSourceRestore(IProgressMonitor monitor) throws CoreException { monitor.beginTask(RefactoringCoreMessages.MoveResourceChange_progress_restore_source, 3); try { fRestoreSourceChange.initializeValidationData(new SubProgressMonitor(monitor, 1)); RefactoringStatus restoreStatus= fRestoreSourceChange.isValid(new SubProgressMonitor(monitor, 1)); if (!restoreStatus.hasFatalError()) { fRestoreSourceChange.perform(new SubProgressMonitor(monitor, 1)); } } finally { monitor.done(); } } /* (non-Javadoc) * @see org.eclipse.ltk.core.refactoring.resource.ResourceChange#getModifiedResource() */ protected IResource getModifiedResource() { return fSource; } /* (non-Javadoc) * @see org.eclipse.ltk.core.refactoring.Change#getName() */ public String getName() { return Messages.format(RefactoringCoreMessages.MoveResourceChange_name, new String[] { BasicElementLabels.getPathLabel(fSource.getFullPath(), false), BasicElementLabels.getResourceName(fTarget) }); } }