/* * 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; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceVisitor; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.ltk.core.refactoring.Change; import org.eclipse.ltk.core.refactoring.Refactoring; import org.eclipse.ltk.core.refactoring.RefactoringStatus; import org.eclipse.ltk.core.refactoring.TextFileChange; import org.teiid.designer.core.ModelerCore; import org.teiid.designer.core.util.KeyInValueHashMap; import org.teiid.designer.core.util.KeyInValueHashMap.KeyFromValueAdapter; import org.teiid.designer.ui.refactor.RefactorResourcesUtils.AbstractResourceCallback; import org.teiid.designer.vdb.refactor.VdbResourceChange; /** * */ public abstract class AbstractResourcesRefactoring extends Refactoring { private final List<IResource> resources; private Set<IResource> resourcesAndChildren; private Map<IResource, Collection<Change>> changes = new LinkedHashMap<IResource, Collection<Change>>(); private final KeyInValueHashMap<String, VdbResourceChange> vdbChanges; private String name; private class VdbResourceChangeAdapter implements KeyFromValueAdapter<String, VdbResourceChange> { @Override public String getKey(VdbResourceChange value) { return value.getParentFolder() + value.getVdbName(); } } /** * Callback implementation for adding vdb resource changes */ public class VdbResourceCallback extends AbstractResourceCallback { @Override public void indexVdb(IResource resource, IFile vdbFile, RefactoringStatus status) { addChange(vdbFile, new VdbResourceChange(vdbFile)); } } /** * Create new instance * * @param name * @param resources */ public AbstractResourcesRefactoring(String name, List<IResource> resources) { super(); this.name = name; this.resources = resources; this.vdbChanges = new KeyInValueHashMap<String, VdbResourceChange>(new VdbResourceChangeAdapter()); } @Override public String getName() { return name; } /** * Get the resources * * @return the resources */ public List<IResource> getResources() { return resources; } /** * Returns all the resources as well as their children * * @param status to be populate if there are any errors with collecting the resources * * @return the resourcesAndChildren */ public Set<IResource> getResourcesAndChildren(RefactoringStatus status) { if (this.resourcesAndChildren == null) { this.resourcesAndChildren = new HashSet<IResource>(); for (IResource resource : resources) { try { resource.accept(new IResourceVisitor() { @Override public boolean visit(IResource visitedResource) { resourcesAndChildren.add(visitedResource); return true; } }, IResource.DEPTH_INFINITE, false); } catch (Exception err) { ModelerCore.Util.log(IStatus.ERROR, err, err.getMessage()); status.merge(RefactoringStatus.createFatalErrorStatus(err.getMessage())); } } } return this.resourcesAndChildren; } /** * Provides a specific set of tests to test the given resource to ensure * that the operation can continue. This can then be used in both the * implementation of createInitialConditions and when testing dependencies. * * @param resource * @param progressMonitor * @param status */ protected abstract void checkResource(IResource resource, IProgressMonitor progressMonitor, RefactoringStatus status); protected void addVdbChange(VdbResourceChange change) { VdbResourceChange mappedChange = vdbChanges.get(change.getParentFolder() + change.getVdbName()); if (mappedChange == null) { vdbChanges.add(change); return; } mappedChange.addReplacements(change.getReplacedResources()); } protected void addVdbChange(IFile vdbFile, IPath invalidResourcePath, IPath newResourcePath) { VdbResourceChange change = vdbChanges.get(vdbFile.getParent().getName() + vdbFile.getName()); if (change == null) { change = new VdbResourceChange(vdbFile); } change.addReplacement(invalidResourcePath.toOSString(), newResourcePath.toOSString()); vdbChanges.add(change); } protected void addChange(IResource resource, Change change) { if (change instanceof VdbResourceChange) { addVdbChange((VdbResourceChange) change); return; } Collection<Change> collection = changes.get(resource); if (collection == null) { collection = new ArrayList<Change>(); changes.put(resource, collection); } collection.add(change); } /** * Add a text change to the refactoring for the given file. * * @param pathpairs the pairs of paths being modified as a result of the move * @param file resource being analysed * * @return true if the text change was added, false otherwise. * * @throws Exception */ protected boolean addTextChange(IFile file, TextFileChange textFileChange) { if (textFileChange == null) return false; if (textFileChange.getEdit() == null || !textFileChange.getEdit().hasChildren()) return false; // Only if the file is actually being changed do we add the text change addChange(file, textFileChange); return true; } protected Collection<Change> getChanges() { List<Change> changeCollection = new ArrayList<Change>(); for (Map.Entry<IResource, Collection<Change>> entry : changes.entrySet()) { changeCollection.addAll(entry.getValue()); } // Add vdb changes last since synchronisation should be done // after all other changes changeCollection.addAll(vdbChanges.values()); return changeCollection; } protected void clearChanges() { changes.clear(); vdbChanges.clear(); } /** * Check wth the resources is populated at all. * * Populate the given status accordingly. * * @param status * @return true if the resources collection is populated, otherwise false. */ protected boolean checkResourcesNotEmpty(RefactoringStatus status) { if (getResources() == null || getResources().isEmpty()) { status.merge(RefactoringStatus.createFatalErrorStatus(RefactorResourcesUtils.getString("ResourcesRefactoring.noResourceError"))); //$NON-NLS-1$ return false; } return true; } }