/*******************************************************************************
* Copyright (c) 2014, 2015 Google, Inc 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:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.refactoring.rename;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceProxy;
import org.eclipse.core.resources.IResourceProxyVisitor;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.ltk.core.refactoring.Change;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext;
import org.eclipse.ltk.core.refactoring.participants.ISharableParticipant;
import org.eclipse.ltk.core.refactoring.participants.MoveArguments;
import org.eclipse.ltk.core.refactoring.participants.MoveParticipant;
import org.eclipse.ltk.core.refactoring.participants.RefactoringArguments;
/**
* Updates include statements and include guards in response to a file or a folder move.
*/
public class HeaderFileMoveParticipant extends MoveParticipant implements ISharableParticipant {
private Map<IResource, MoveArguments> movedResources;
private Change change;
public HeaderFileMoveParticipant() {
}
@Override
protected boolean initialize(Object element) {
addElement(element, getArguments());
return movedResources != null;
}
@Override
public void addElement(Object element, RefactoringArguments arguments) {
if (element instanceof IResource && arguments instanceof MoveArguments) {
if (movedResources == null)
movedResources = new HashMap<>();
movedResources.put((IResource) element, (MoveArguments) arguments);
}
}
@Override
public RefactoringStatus checkConditions(IProgressMonitor pm, CheckConditionsContext context)
throws OperationCanceledException {
try {
if (movedResources == null)
return RefactoringStatus.create(Status.OK_STATUS);
// Maps the affected files to new, not yet existing, files.
final Map<IFile, IFile> movedFiles = new HashMap<>();
for (Map.Entry<IResource, MoveArguments> entry : movedResources.entrySet()) {
IResource movedResource = entry.getKey();
MoveArguments args = entry.getValue();
if (!args.getUpdateReferences())
continue;
if (movedResource.isLinked())
continue;
Object destinationResource = args.getDestination();
if (!(destinationResource instanceof IContainer))
continue;
final IContainer destination = (IContainer) destinationResource;
final IPath destinationLocation = destination.getLocation();
if (destinationLocation.equals(movedResource.getLocation().removeLastSegments(1)))
continue;
if (movedResource instanceof IFolder) {
IFolder folder = (IFolder) movedResource;
final int prefixLength = folder.getFullPath().segmentCount() - 1;
folder.accept(new IResourceProxyVisitor() {
@Override
public boolean visit(IResourceProxy proxy) throws CoreException {
if (proxy.isLinked())
return false;
if (proxy.getType() == IResource.FILE) {
IFile file = (IFile) proxy.requestResource();
movedFiles.put(file, destination.getFile(file.getFullPath().removeFirstSegments(prefixLength)));
return false;
}
return true;
}
}, IResource.NONE);
} else if (movedResource instanceof IFile) {
IFile file = (IFile) movedResource;
movedFiles.put(file, destination.getFile(new Path(movedResource.getName())));
}
}
HeaderFileReferenceAdjuster includeAdjuster = new HeaderFileReferenceAdjuster(movedFiles,
Collections.<IContainer, IContainer>emptyMap(), getProcessor());
change = includeAdjuster.createChange(context, pm);
} catch (CoreException e) {
return RefactoringStatus.create(e.getStatus());
} finally {
pm.done();
}
return RefactoringStatus.create(Status.OK_STATUS);
}
@Override
public Change createPreChange(IProgressMonitor pm) throws CoreException, OperationCanceledException {
change = RenameParticipantHelper.postprocessParticipantChange(change, this);
pm.done();
return change;
}
@Override
public Change createChange(IProgressMonitor pm) throws CoreException, OperationCanceledException {
pm.done();
return null;
}
@Override
public String getName() {
return RenameMessages.HeaderFileMoveParticipant_name;
}
}