| /******************************************************************************* |
| * Copyright (c) 2000, 2018 IBM Corporation and others. |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0. |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| *******************************************************************************/ |
| package org.eclipse.dltk.internal.corext.refactoring.changes; |
| |
| import java.util.HashMap; |
| import java.util.Map; |
| |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.Assert; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.core.runtime.SubProgressMonitor; |
| import org.eclipse.dltk.core.DLTKCore; |
| import org.eclipse.dltk.core.IModelElement; |
| import org.eclipse.dltk.core.IScriptFolder; |
| import org.eclipse.dltk.core.ISourceModule; |
| import org.eclipse.dltk.core.ModelException; |
| import org.eclipse.dltk.internal.corext.refactoring.AbstractModelElementRenameChange; |
| import org.eclipse.dltk.internal.corext.refactoring.RefactoringCoreMessages; |
| import org.eclipse.dltk.internal.corext.refactoring.util.ModelElementUtil; |
| import org.eclipse.dltk.internal.corext.util.Messages; |
| import org.eclipse.ltk.core.refactoring.Change; |
| import org.eclipse.ltk.core.refactoring.NullChange; |
| import org.eclipse.ltk.core.refactoring.RefactoringDescriptor; |
| import org.eclipse.ltk.core.refactoring.RefactoringStatus; |
| |
| public class RenameScriptFolderChange extends AbstractModelElementRenameChange { |
| |
| private Map fSourceModuleStamps; |
| private final boolean fRenameSubpackages; |
| |
| public RenameScriptFolderChange(RefactoringDescriptor descriptor, IScriptFolder pack, String newName, |
| String comment, boolean renameSubpackages) { |
| this(descriptor, pack.getPath(), pack.getElementName(), newName, comment, IResource.NULL_STAMP, null, |
| renameSubpackages); |
| Assert.isTrue(!pack.isReadOnly(), "package must not be read only"); //$NON-NLS-1$ |
| } |
| |
| private RenameScriptFolderChange(RefactoringDescriptor descriptor, IPath resourcePath, String oldName, |
| String newName, String comment, long stampToRestore, Map compilationUnitStamps, boolean renameSubpackages) { |
| super(descriptor, resourcePath, oldName, newName, comment, stampToRestore); |
| fSourceModuleStamps = compilationUnitStamps; |
| fRenameSubpackages = renameSubpackages; |
| } |
| |
| @Override |
| public RefactoringStatus isValid(IProgressMonitor pm) throws CoreException { |
| RefactoringStatus result = new RefactoringStatus(); |
| IModelElement element = (IModelElement) getModifiedElement(); |
| // don't check for read-only since we don't go through |
| // validate edit. |
| result.merge(isValid(DIRTY)); |
| if (result.hasFatalError()) |
| return result; |
| if (element != null && element.exists() && element instanceof IScriptFolder) { |
| IScriptFolder pack = (IScriptFolder) element; |
| if (fRenameSubpackages) { |
| IScriptFolder[] allPackages = ModelElementUtil.getPackageAndSubpackages(pack); |
| pm.beginTask("", allPackages.length); //$NON-NLS-1$ |
| for (int i = 0; i < allPackages.length; i++) { |
| // don't check for read-only since we don't go through |
| // validate edit. |
| checkIfModifiable(result, allPackages[i], DIRTY); |
| if (result.hasFatalError()) |
| return result; |
| isValid(result, allPackages[i], new SubProgressMonitor(pm, 1)); |
| } |
| pm.done(); |
| } else { |
| isValid(result, pack, pm); |
| } |
| } |
| return result; |
| } |
| |
| private void isValid(RefactoringStatus result, IScriptFolder pack, IProgressMonitor pm) throws ModelException { |
| ISourceModule[] units = pack.getSourceModules(); |
| pm.beginTask("", units.length); //$NON-NLS-1$ |
| for (int i = 0; i < units.length; i++) { |
| pm.subTask(Messages.format(RefactoringCoreMessages.RenamePackageChange_checking_change, |
| pack.getElementName())); |
| checkIfModifiable(result, units[i], READ_ONLY | DIRTY); |
| pm.worked(1); |
| } |
| pm.done(); |
| } |
| |
| @Override |
| protected IPath createNewPath() { |
| IScriptFolder oldPackage = getPackage(); |
| IPath oldPackageName = createPath(oldPackage.getElementName()); |
| IPath newPackageName = createPath(getNewName()); |
| return getResourcePath().removeLastSegments(oldPackageName.segmentCount()).append(newPackageName); |
| } |
| |
| private static IPath createPath(String packageName) { |
| return new Path(packageName.replace('.', IPath.SEPARATOR)); |
| } |
| |
| protected IPath createNewPath(IScriptFolder oldPackage) { |
| IPath oldPackagePath = createPath(oldPackage.getElementName()); |
| IPath newPackagePath = createPath(getNewName(oldPackage)); |
| return oldPackage.getPath().removeLastSegments(oldPackagePath.segmentCount()).append(newPackagePath); |
| } |
| |
| private String getNewName(IScriptFolder subpackage) { |
| return getNewName() + subpackage.getElementName().substring(getOldName().length()); |
| } |
| |
| @Override |
| public String getName() { |
| String msg = fRenameSubpackages ? RefactoringCoreMessages.RenamePackageChange_name_with_subpackages |
| : RefactoringCoreMessages.RenamePackageChange_name; |
| return Messages.format(msg, getOldName(), getNewName()); |
| } |
| |
| @Override |
| protected Change createUndoChange(long stampToRestore) throws CoreException { |
| IScriptFolder pack = getPackage(); |
| if (pack == null) |
| return new NullChange(); |
| Map stamps = new HashMap(); |
| if (!fRenameSubpackages) { |
| addStamps(stamps, pack.getSourceModules()); |
| } else { |
| IScriptFolder[] allPackages = ModelElementUtil.getPackageAndSubpackages(pack); |
| for (int i = 0; i < allPackages.length; i++) { |
| IScriptFolder currentPackage = allPackages[i]; |
| addStamps(stamps, currentPackage.getSourceModules()); |
| } |
| } |
| return new RenameScriptFolderChange(null, createNewPath(), getNewName(), getOldName(), getComment(), |
| stampToRestore, stamps, fRenameSubpackages); |
| // Note: This reverse change only works if the renamePackage change did |
| // not merge the source package into an existing target. |
| } |
| |
| private void addStamps(Map stamps, ISourceModule[] units) { |
| for (int i = 0; i < units.length; i++) { |
| IResource resource = units[i].getResource(); |
| long stamp = IResource.NULL_STAMP; |
| if (resource != null && (stamp = resource.getModificationStamp()) != IResource.NULL_STAMP) { |
| stamps.put(resource, Long.valueOf(stamp)); |
| } |
| } |
| } |
| |
| @Override |
| protected void doRename(IProgressMonitor pm) throws CoreException { |
| IScriptFolder pack = getPackage(); |
| if (pack == null) |
| return; |
| |
| if (!fRenameSubpackages) { |
| renamePackage(pack, pm, createNewPath(), getNewName()); |
| } else { |
| IScriptFolder[] allPackages = ModelElementUtil.getPackageAndSubpackages(pack); |
| |
| pm.beginTask("", allPackages.length); //$NON-NLS-1$ |
| try { |
| for (int i = 0; i < allPackages.length; i++) { |
| IScriptFolder currentPackage = allPackages[i]; |
| renamePackage(currentPackage, new SubProgressMonitor(pm, 1), createNewPath(currentPackage), |
| getNewName(currentPackage)); |
| } |
| } finally { |
| pm.done(); |
| } |
| } |
| } |
| |
| private void renamePackage(IScriptFolder pack, IProgressMonitor pm, IPath newPath, String newName) |
| throws ModelException, CoreException { |
| pack.rename(newName, false, pm); |
| if (fSourceModuleStamps != null) { |
| IScriptFolder newPack = (IScriptFolder) DLTKCore |
| .create(ResourcesPlugin.getWorkspace().getRoot().getFolder(newPath)); |
| if (newPack.exists()) { |
| ISourceModule[] units = newPack.getSourceModules(); |
| for (int i = 0; i < units.length; i++) { |
| IResource resource = units[i].getResource(); |
| if (resource != null) { |
| Long stamp = (Long) fSourceModuleStamps.get(resource); |
| if (stamp != null) { |
| resource.revertModificationStamp(stamp.longValue()); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| private IScriptFolder getPackage() { |
| return (IScriptFolder) getModifiedElement(); |
| } |
| } |