package org.eclipse.core.internal.resources.mapping;
import org.eclipse.core.internal.utils.Policy;
import org.eclipse.core.resources.*;
import org.eclipse.core.resources.mapping.IResourceChangeDescriptionFactory;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
public class ResourceChangeDescriptionFactory implements IResourceChangeDescriptionFactory {
private ProposedResourceDelta root = new ProposedResourceDelta(ResourcesPlugin.getWorkspace().getRoot());
private ProposedResourceDelta buildDeleteDelta(ProposedResourceDelta parentDelta, IResource resource) {
ProposedResourceDelta delta = parentDelta.getChild(resource.getName());
if (delta == null) {
delta = new ProposedResourceDelta(resource);
parentDelta.add(delta);
}
delta.setKind(IResourceDelta.REMOVED);
if (resource.getType() == IResource.FILE)
return delta;
try {
IResource[] members = ((IContainer) resource).members();
int childCount = members.length;
if (childCount > 0) {
ProposedResourceDelta[] childDeltas = new ProposedResourceDelta[childCount];
for (int i = 0; i < childCount; i++)
childDeltas[i] = buildDeleteDelta(delta, members[i]);
}
} catch (CoreException e) {
}
return delta;
}
@Override
public void change(IFile file) {
ProposedResourceDelta delta = getDelta(file);
if (delta.getKind() == 0)
delta.setKind(IResourceDelta.CHANGED);
if (delta.getKind() == IResourceDelta.CHANGED || (delta.getFlags() & IResourceDelta.MOVED_FROM) != 0 || (delta.getFlags() & IResourceDelta.COPIED_FROM) != 0)
delta.addFlags(IResourceDelta.CONTENT);
}
@Override
public void close(IProject project) {
delete(project);
ProposedResourceDelta delta = getDelta(project);
delta.addFlags(IResourceDelta.OPEN);
}
@Override
public void copy(IResource resource, IPath destination) {
moveOrCopyDeep(resource, destination, false );
}
@Override
public void create(IResource resource) {
getDelta(resource).setKind(IResourceDelta.ADDED);
}
@Override
public void delete(IResource resource) {
if (resource.getType() == IResource.ROOT) {
IProject[] projects = ((IWorkspaceRoot) resource).getProjects(IContainer.INCLUDE_HIDDEN);
for (IProject project : projects)
buildDeleteDelta(root, project);
} else {
buildDeleteDelta(getDelta(resource.getParent()), resource);
}
}
private void fail(CoreException e) {
Policy.log(e.getStatus().getSeverity(), "An internal error occurred while accumulating a change description.", e);
}
@Override
public IResourceDelta getDelta() {
return root;
}
ProposedResourceDelta getDelta(IResource resource) {
ProposedResourceDelta delta = (ProposedResourceDelta) root.findMember(resource.getFullPath());
if (delta != null) {
return delta;
}
ProposedResourceDelta parent = getDelta(resource.getParent());
delta = new ProposedResourceDelta(resource);
parent.add(delta);
return delta;
}
protected IResource getDestinationResource(IResource source, IPath sourcePrefix, IPath destinationPrefix) {
IPath relativePath = source.getFullPath().removeFirstSegments(sourcePrefix.segmentCount());
IPath destinationPath = destinationPrefix.append(relativePath);
IResource destination;
IWorkspaceRoot wsRoot = ResourcesPlugin.getWorkspace().getRoot();
switch (source.getType()) {
case IResource.FILE :
destination = wsRoot.getFile(destinationPath);
break;
case IResource.FOLDER :
destination = wsRoot.getFolder(destinationPath);
break;
case IResource.PROJECT :
destination = wsRoot.getProject(destinationPath.segment(0));
break;
default :
destination = null;
}
return destination;
}
@Override
public void move(IResource resource, IPath destination) {
moveOrCopyDeep(resource, destination, true );
}
boolean moveOrCopy(IResource resource, final IPath sourcePrefix, final IPath destinationPrefix, final boolean move) {
ProposedResourceDelta sourceDelta = getDelta(resource);
if (sourceDelta.getKind() == IResourceDelta.REMOVED) {
return false;
}
IResource destinationResource = getDestinationResource(resource, sourcePrefix, destinationPrefix);
ProposedResourceDelta destinationDelta = getDelta(destinationResource);
if ((destinationDelta.getKind() & (IResourceDelta.ADDED | IResourceDelta.CHANGED)) > 0) {
return false;
}
IPath fromPath = resource.getFullPath();
boolean wasAdded = false;
final int sourceFlags = sourceDelta.getFlags();
if (move) {
if (sourceDelta.getKind() == IResourceDelta.ADDED) {
if ((sourceFlags & IResourceDelta.MOVED_FROM) != 0) {
fromPath = sourceDelta.getMovedFromPath();
sourceDelta.setMovedFromPath(null);
}
sourceDelta.setKind(0);
wasAdded = true;
} else {
sourceDelta.setKind(IResourceDelta.REMOVED);
sourceDelta.setFlags(IResourceDelta.MOVED_TO);
sourceDelta.setMovedToPath(destinationPrefix.append(fromPath.removeFirstSegments(sourcePrefix.segmentCount())));
}
}
if (destinationDelta.getKind() == IResourceDelta.REMOVED) {
destinationDelta.setKind(IResourceDelta.CHANGED);
destinationDelta.addFlags(IResourceDelta.REPLACED);
} else {
destinationDelta.setKind(IResourceDelta.ADDED);
}
if (!wasAdded || !fromPath.equals(resource.getFullPath())) {
destinationDelta.addFlags(move ? IResourceDelta.MOVED_FROM : IResourceDelta.COPIED_FROM);
destinationDelta.setMovedFromPath(fromPath);
if (move)
destinationDelta.addFlags(sourceFlags);
}
return true;
}
private void moveOrCopyDeep(IResource resource, IPath destination, final boolean move) {
final IPath sourcePrefix = resource.getFullPath();
final IPath destinationPrefix = destination;
try {
if (resource.isAccessible()) {
resource.accept(child -> moveOrCopy(child, sourcePrefix, destinationPrefix, move));
} else {
moveOrCopy(resource, sourcePrefix, destination, move);
}
} catch (CoreException e) {
fail(e);
}
}
}