/* * JBoss, Home of Professional Open Source. * * See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing. * * See the AUTHORS.txt file distributed with this work for a full listing of individual contributors. */ package org.teiid.designer.ui.refactor.delete; import java.util.HashSet; import java.util.List; import java.util.Set; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceVisitor; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.Status; import org.eclipse.ltk.core.refactoring.Change; import org.eclipse.ltk.core.refactoring.CompositeChange; import org.eclipse.ltk.core.refactoring.RefactoringStatus; import org.eclipse.ltk.core.refactoring.resource.DeleteResourceChange; import org.teiid.designer.core.refactor.IRefactorModelHandler.RefactorType; import org.teiid.designer.core.refactor.RelatedResourceFinder.Relationship; import org.teiid.designer.core.workspace.ModelUtil; import org.teiid.designer.ui.refactor.AbstractResourcesRefactoring; import org.teiid.designer.ui.refactor.RefactorResourcesUtils; import org.teiid.designer.ui.refactor.RefactorResourcesUtils.AbstractResourceCallback; import org.teiid.designer.ui.refactor.RefactorResourcesUtils.IResourceCallback; /** * */ public class DeleteResourcesRefactoring extends AbstractResourcesRefactoring { private class RelatedResourceCallback extends VdbResourceCallback { private final Set<IResource> indexedResources = new HashSet<IResource>(); @Override public void indexFile(IResource resource, IFile relatedFile, RefactoringStatus status) throws Exception { /* * The related file will be deleted so we don't want to try deleting it twice */ if (indexedResources.contains(relatedFile)) return; indexedResources.add(relatedFile); RefactorResourcesUtils.unloadModelResource(relatedFile); if (! getResourcesAndChildren(status).contains(relatedFile)) { // file is NOT already being deleted DeleteResourceChange change = new DeleteResourceChange(relatedFile.getFullPath(), true, isDeleteContents()); addChange(relatedFile, change); } RefactorResourcesUtils.calculateRelatedVdbResources(relatedFile, status, this); } @Override public void indexVdb(IResource resource, IFile vdbFile, RefactoringStatus status) { if (! getResourcesAndChildren(status).contains(vdbFile)) { // vdb is NOT already being deleted super.indexVdb(resource, vdbFile, status); } } } private boolean deleteContents; /** * @param selectedResources */ public DeleteResourcesRefactoring(final List<IResource> selectedResources) { super(RefactorResourcesUtils.getString("DeleteRefactoring.title"), selectedResources); //$NON-NLS-1$ } /** * Delete projects contents. * @return <code>true</code> if this will delete the project contents. The content delete is not undoable. */ public boolean isDeleteContents() { return deleteContents; } /** * Set to delete the projects content. * * @param deleteContents <code>true</code> if this will delete the project contents. The content delete is not undoable. */ public void setDeleteContents(boolean deleteContents) { this.deleteContents= deleteContents; } /** * Takes into account whether isDeleteContents has been set. If it has not then * the project is just removed from eclipse and the directory being read-only is * irrelevant * * @param project * @param status */ private void checkProjectReadOnly(IProject project, RefactoringStatus status) { if (isDeleteContents() && ModelUtil.isIResourceReadOnly(project)) { status.merge(RefactoringStatus.createFatalErrorStatus(RefactorResourcesUtils.getString("ResourcesRefactoring.readOnlyResourceError", project.getName()))); //$NON-NLS-1$ } } private boolean isSelectedOrChildResource(final IResource child) { if (getResources().contains(child)) return true; final boolean status[] = new boolean[1]; IResourceVisitor childVisitor = new IResourceVisitor() { @Override public boolean visit(IResource resource) { if (resource.equals(child)) { status[0] = true; return false; // found the child so exit the visitor stat! } return true; } }; for (IResource selected : getResources()) { try { selected.accept(childVisitor); if (status[0]) { // child is a descendant of one of the selected return true; } } catch (CoreException ex) { // do nothing } } return false; } @Override protected void checkResource(IResource resource, IProgressMonitor progressMonitor, RefactoringStatus status) { int readOnlyStatusLevel; String readOnlyStatusMsg; if (isSelectedOrChildResource(resource)) { readOnlyStatusLevel = IStatus.WARNING; readOnlyStatusMsg = RefactorResourcesUtils.getString("ResourcesRefactoring.readOnlyResourceError", //$NON-NLS-1$ resource.getName()); } else { readOnlyStatusLevel = IStatus.ERROR; readOnlyStatusMsg = RefactorResourcesUtils.getString("ResourcesRefactoring.readOnlyRelatedResourceError", //$NON-NLS-1$ resource.getName()); } RefactorResourcesUtils.checkResourceExists(resource, status); if (status.getSeverity() > IStatus.WARNING) return; RefactorResourcesUtils.checkResourceSynched(resource, status); if (status.getSeverity() > IStatus.WARNING) return; if (resource instanceof IProject) checkProjectReadOnly((IProject) resource, status); else RefactorResourcesUtils.checkResourceWritable(resource, status, readOnlyStatusLevel, readOnlyStatusMsg); if (status.getSeverity() > IStatus.WARNING) return; RefactorResourcesUtils.checkExtensionManager(resource, RefactorType.DELETE, progressMonitor, status); if (status.getSeverity() > IStatus.WARNING) return; RefactorResourcesUtils.checkSavedResource(resource, status); if (status.getSeverity() > IStatus.WARNING) return; if (! getResources().contains(resource)) { /* * Its okay to delete a resource if an editor for it is open but can cause * problems for related resources, especially if the user previews then * cancels the delete operation. */ RefactorResourcesUtils.checkOpenEditors(resource, status); } } @Override public RefactoringStatus checkInitialConditions(final IProgressMonitor progressMonitor) throws OperationCanceledException { RefactoringStatus status = new RefactoringStatus(); try { progressMonitor.beginTask(RefactorResourcesUtils.getString("DeleteRefactoring.initialConditions"), 1); //$NON-NLS-1$ if (! checkResourcesNotEmpty(status)) return status; // allow only projects or only non-projects to be selected; // note that the selection may contain multiple types of resource if (!(RefactorResourcesUtils.containsOnlyProjects(getResources()) || RefactorResourcesUtils.containsOnlyNonProjects(getResources()))) { return RefactoringStatus.createFatalErrorStatus(RefactorResourcesUtils.getString("DeleteRefactoring.containsProjectsAndResourcesError")); //$NON-NLS-1$ } for (IResource resource : getResources()) { checkResource(resource, progressMonitor, status); if (status.getSeverity() > IStatus.WARNING) break; // Check validity of related resources IResourceCallback callback = new AbstractResourceCallback() { @Override public void checkValidFile(IFile relatedFile, RefactoringStatus validityStatus) { checkResource(relatedFile, progressMonitor, validityStatus); } }; RefactorResourcesUtils.calculateRelatedResources(resource, status, callback, Relationship.DEPENDENT); } } finally { progressMonitor.done(); } return status; } @Override public RefactoringStatus checkFinalConditions(IProgressMonitor progressMonitor) throws OperationCanceledException { RefactoringStatus status = new RefactoringStatus(); clearChanges(); try { progressMonitor.beginTask(RefactorResourcesUtils.getString("DeleteRefactoring.finalConditions"), 2); //$NON-NLS-1$ RelatedResourceCallback callback = new RelatedResourceCallback(); for (IResource resource : getResources()) { addChange(resource, new DeleteResourceChange(resource.getFullPath(), true, isDeleteContents())); RefactorResourcesUtils.calculateRelatedResources(resource, status, callback, Relationship.DEPENDENT); } } finally { progressMonitor.done(); } return status; } @Override public Change createChange(IProgressMonitor progressMonitor) throws OperationCanceledException, CoreException { try { progressMonitor.beginTask(RefactorResourcesUtils.getString("DeleteRefactoring.creatingChange"), 1); //$NON-NLS-1$ CompositeChange change = new DeleteResourcesCompositeChange( getName(), getChanges().toArray(new Change[0]), isDeleteContents(), getResources()); return change; } catch (Exception ex) { throw new CoreException(new Status(IStatus.ERROR, DeleteResourcesDescriptor.REFACTORING_ID, ex.getMessage())); } finally { progressMonitor.done(); } } }