package org.eclipse.core.internal.events;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.core.internal.resources.*;
import org.eclipse.core.internal.watson.ElementTree;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
public class ResourceDelta extends PlatformObject implements IResourceDelta {
protected IPath path;
protected ResourceDeltaInfo deltaInfo;
protected int status;
protected ResourceInfo oldInfo;
protected ResourceInfo newInfo;
protected ResourceDelta[] children;
protected IResource cachedResource;
protected static int KIND_MASK = 0xFF;
private static IMarkerDelta[] EMPTY_MARKER_DELTAS = new IMarkerDelta[0];
protected ResourceDelta(IPath path, ResourceDeltaInfo deltaInfo) {
this.path = path;
this.deltaInfo = deltaInfo;
}
@Override
public void accept(IResourceDeltaVisitor visitor) throws CoreException {
accept(visitor, 0);
}
@Override
public void accept(IResourceDeltaVisitor visitor, boolean includePhantoms) throws CoreException {
accept(visitor, includePhantoms ? IContainer.INCLUDE_PHANTOMS : 0);
}
@Override
public void accept(IResourceDeltaVisitor visitor, int memberFlags) throws CoreException {
final boolean includePhantoms = (memberFlags & IContainer.INCLUDE_PHANTOMS) != 0;
final boolean includeTeamPrivate = (memberFlags & IContainer.INCLUDE_TEAM_PRIVATE_MEMBERS) != 0;
final boolean includeHidden = (memberFlags & IContainer.INCLUDE_HIDDEN) != 0;
int mask = includePhantoms ? ALL_WITH_PHANTOMS : REMOVED | ADDED | CHANGED;
if ((getKind() & mask) == 0)
return;
if (!visitor.visit(this))
return;
for (ResourceDelta childDelta : children) {
if (!includeTeamPrivate && childDelta.isTeamPrivate())
continue;
if (!includePhantoms && childDelta.isPhantom())
continue;
if (!includeHidden && childDelta.isHidden())
continue;
childDelta.accept(visitor, memberFlags);
}
}
protected void checkForMarkerDeltas() {
if (deltaInfo.getMarkerDeltas() == null)
return;
int kind = getKind();
if (path.isRoot() || kind == ADDED || kind == REMOVED) {
MarkerSet changes = deltaInfo.getMarkerDeltas().get(path);
if (changes != null && changes.size() > 0) {
status |= MARKERS;
if (kind == 0)
status |= CHANGED;
}
}
}
@Override
public IResourceDelta findMember(IPath path) {
int segmentCount = path.segmentCount();
if (segmentCount == 0)
return this;
ResourceDelta current = this;
segments: for (int i = 0; i < segmentCount; i++) {
IResourceDelta[] currentChildren = current.children;
for (int j = 0, jmax = currentChildren.length; j < jmax; j++) {
if (currentChildren[j].getFullPath().lastSegment().equals(path.segment(i))) {
current = (ResourceDelta) currentChildren[j];
continue segments;
}
}
return null;
}
return current;
}
protected void fixMovesAndMarkers(ElementTree oldTree) {
NodeIDMap nodeIDMap = deltaInfo.getNodeIDMap();
if (!path.isRoot() && !nodeIDMap.isEmpty()) {
int kind = getKind();
switch (kind) {
case CHANGED :
case ADDED :
IPath oldPath = nodeIDMap.getOldPath(newInfo.getNodeId());
if (oldPath != null && !oldPath.equals(path)) {
ResourceInfo actualOldInfo = (ResourceInfo) oldTree.getElementData(oldPath);
status = (status & KIND_MASK) | (deltaInfo.getComparator().compare(actualOldInfo, newInfo) & ~KIND_MASK);
status |= MOVED_FROM;
if (kind == CHANGED)
status = status | REPLACED | CONTENT;
if (oldInfo != null && newInfo != null && oldInfo.getType() != newInfo.getType())
status |= TYPE;
}
}
switch (kind) {
case REMOVED :
case CHANGED :
IPath newPath = nodeIDMap.getNewPath(oldInfo.getNodeId());
if (newPath != null && !newPath.equals(path)) {
status |= MOVED_TO;
if (kind == CHANGED)
status = status | REPLACED | CONTENT;
}
}
}
checkForMarkerDeltas();
for (ResourceDelta element : children)
element.fixMovesAndMarkers(oldTree);
}
@Override
public IResourceDelta[] getAffectedChildren() {
return getAffectedChildren(ADDED | REMOVED | CHANGED, IResource.NONE);
}
@Override
public IResourceDelta[] getAffectedChildren(int kindMask) {
return getAffectedChildren(kindMask, IResource.NONE);
}
@Override
public IResourceDelta[] getAffectedChildren(int kindMask, int memberFlags) {
int numChildren = children.length;
if (numChildren == 0)
return children;
boolean includePhantoms = (memberFlags & IContainer.INCLUDE_PHANTOMS) != 0;
boolean includeTeamPrivate = (memberFlags & IContainer.INCLUDE_TEAM_PRIVATE_MEMBERS) != 0;
boolean includeHidden = (memberFlags & IContainer.INCLUDE_HIDDEN) != 0;
if (includePhantoms)
kindMask |= ADDED_PHANTOM | REMOVED_PHANTOM;
int matching = 0;
for (int i = 0; i < numChildren; i++) {
if ((children[i].getKind() & kindMask) == 0)
continue;
if (!includePhantoms && children[i].isPhantom())
continue;
if (!includeTeamPrivate && children[i].isTeamPrivate())
continue;
if (!includeHidden && children[i].isHidden())
continue;
matching++;
}
if (matching == numChildren) {
IResourceDelta[] result = new IResourceDelta[children.length];
System.arraycopy(children, 0, result, 0, children.length);
return result;
}
IResourceDelta[] result = new IResourceDelta[matching];
int nextPosition = 0;
for (int i = 0; i < numChildren; i++) {
if ((children[i].getKind() & kindMask) == 0)
continue;
if (!includePhantoms && children[i].isPhantom())
continue;
if (!includeTeamPrivate && children[i].isTeamPrivate())
continue;
if (!includeHidden && children[i].isHidden())
continue;
result[nextPosition++] = children[i];
}
return result;
}
protected ResourceDeltaInfo getDeltaInfo() {
return deltaInfo;
}
@Override
public int getFlags() {
return status & ~KIND_MASK;
}
@Override
public IPath getFullPath() {
return path;
}
@Override
public int getKind() {
return status & KIND_MASK;
}
@Override
public IMarkerDelta[] getMarkerDeltas() {
Map<IPath, MarkerSet> markerDeltas = deltaInfo.getMarkerDeltas();
if (markerDeltas == null)
return EMPTY_MARKER_DELTAS;
if (path == null)
path = Path.ROOT;
MarkerSet changes = markerDeltas.get(path);
if (changes == null)
return EMPTY_MARKER_DELTAS;
IMarkerSetElement[] elements = changes.elements();
IMarkerDelta[] result = new IMarkerDelta[elements.length];
for (int i = 0; i < elements.length; i++)
result[i] = (IMarkerDelta) elements[i];
return result;
}
@Override
public IPath getMovedFromPath() {
if ((status & MOVED_FROM) != 0) {
return deltaInfo.getNodeIDMap().getOldPath(newInfo.getNodeId());
}
return null;
}
@Override
public IPath getMovedToPath() {
if ((status & MOVED_TO) != 0) {
return deltaInfo.getNodeIDMap().getNewPath(oldInfo.getNodeId());
}
return null;
}
@Override
public IPath getProjectRelativePath() {
IPath full = getFullPath();
int count = full.segmentCount();
if (count < 0)
return null;
if (count <= 1)
return Path.EMPTY;
return full.removeFirstSegments(1);
}
@Override
public IResource getResource() {
if (cachedResource != null)
return cachedResource;
if (path.segmentCount() == 0)
return deltaInfo.getWorkspace().getRoot();
ResourceInfo info = null;
if ((getKind() & (REMOVED | REMOVED_PHANTOM)) != 0)
info = oldInfo;
else
info = newInfo;
Assert.isNotNull(info, "Do not have resource info for resource in delta: " + path);
cachedResource = deltaInfo.getWorkspace().newResource(path, info.getType());
return cachedResource;
}
protected boolean isPhantom() {
if ((status & (REMOVED | REMOVED_PHANTOM)) != 0)
return ResourceInfo.isSet(oldInfo.getFlags(), ICoreConstants.M_PHANTOM);
return ResourceInfo.isSet(newInfo.getFlags(), ICoreConstants.M_PHANTOM);
}
protected boolean isTeamPrivate() {
if ((status & (REMOVED | REMOVED_PHANTOM)) != 0)
return ResourceInfo.isSet(oldInfo.getFlags(), ICoreConstants.M_TEAM_PRIVATE_MEMBER);
return ResourceInfo.isSet(newInfo.getFlags(), ICoreConstants.M_TEAM_PRIVATE_MEMBER);
}
protected boolean isHidden() {
if ((status & (REMOVED | REMOVED_PHANTOM)) != 0)
return ResourceInfo.isSet(oldInfo.getFlags(), ICoreConstants.M_HIDDEN);
return ResourceInfo.isSet(newInfo.getFlags(), ICoreConstants.M_HIDDEN);
}
protected void setChildren(ResourceDelta[] children) {
this.children = children;
}
protected void setNewInfo(ResourceInfo newInfo) {
this.newInfo = newInfo;
}
protected void setOldInfo(ResourceInfo oldInfo) {
this.oldInfo = oldInfo;
}
protected void setStatus(int status) {
this.status = status;
}
public String toDebugString() {
final StringBuilder buffer = new StringBuilder();
writeDebugString(buffer);
return buffer.toString();
}
public String toDeepDebugString() {
final StringBuilder buffer = new StringBuilder("\n");
writeDebugString(buffer);
for (ResourceDelta element : children)
buffer.append(element.toDeepDebugString());
return buffer.toString();
}
@Override
public String toString() {
return "ResourceDelta(" + path + ')';
}
public void updateMarkers(Map<IPath, MarkerSet> markers) {
deltaInfo.setMarkerDeltas(markers);
}
public void writeDebugString(StringBuilder buffer) {
buffer.append(getFullPath());
buffer.append('[');
switch (getKind()) {
case ADDED :
buffer.append('+');
break;
case ADDED_PHANTOM :
buffer.append('>');
break;
case REMOVED :
buffer.append('-');
break;
case REMOVED_PHANTOM :
buffer.append('<');
break;
case CHANGED :
buffer.append('*');
break;
case NO_CHANGE :
buffer.append('~');
break;
default :
buffer.append('?');
break;
}
buffer.append("]: {");
int changeFlags = getFlags();
boolean prev = false;
if ((changeFlags & CONTENT) != 0) {
if (prev)
buffer.append(" | ");
buffer.append("CONTENT");
prev = true;
}
if ((changeFlags & LOCAL_CHANGED) != 0) {
if (prev)
buffer.append(" | ");
buffer.append("LOCAL_CHANGED");
prev = true;
}
if ((changeFlags & MOVED_FROM) != 0) {
if (prev)
buffer.append(" | ");
buffer.append("MOVED_FROM(" + getMovedFromPath() + ")");
prev = true;
}
if ((changeFlags & MOVED_TO) != 0) {
if (prev)
buffer.append(" | ");
buffer.append("MOVED_TO(" + getMovedToPath() + ")");
prev = true;
}
if ((changeFlags & OPEN) != 0) {
if (prev)
buffer.append(" | ");
buffer.append("OPEN");
prev = true;
}
if ((changeFlags & TYPE) != 0) {
if (prev)
buffer.append(" | ");
buffer.append("TYPE");
prev = true;
}
if ((changeFlags & SYNC) != 0) {
if (prev)
buffer.append(" | ");
buffer.append("SYNC");
prev = true;
}
if ((changeFlags & MARKERS) != 0) {
if (prev)
buffer.append(" | ");
buffer.append("MARKERS");
writeMarkerDebugString(buffer);
prev = true;
}
if ((changeFlags & REPLACED) != 0) {
if (prev)
buffer.append(" | ");
buffer.append("REPLACED");
prev = true;
}
if ((changeFlags & DESCRIPTION) != 0) {
if (prev)
buffer.append(" | ");
buffer.append("DESCRIPTION");
prev = true;
}
if ((changeFlags & ENCODING) != 0) {
if (prev)
buffer.append(" | ");
buffer.append("ENCODING");
prev = true;
}
if ((changeFlags & DERIVED_CHANGED) != 0) {
if (prev)
buffer.append(" | ");
buffer.append("DERIVED_CHANGED");
prev = true;
}
buffer.append("}");
if (isTeamPrivate())
buffer.append(" (team private)");
if (isHidden())
buffer.append(" (hidden)");
}
public void writeMarkerDebugString(StringBuilder buffer) {
Map<IPath, MarkerSet> markerDeltas = deltaInfo.getMarkerDeltas();
if (markerDeltas == null || markerDeltas.isEmpty())
return;
buffer.append('[');
for (Entry<IPath, MarkerSet> entry : markerDeltas.entrySet()) {
IPath key = entry.getKey();
if (getResource().getFullPath().equals(key)) {
MarkerSet set = entry.getValue();
IMarkerSetElement[] deltas = set.elements();
boolean addComma = false;
for (IMarkerSetElement delta2 : deltas) {
IMarkerDelta delta = (IMarkerDelta) delta2;
if (addComma)
buffer.append(',');
switch (delta.getKind()) {
case IResourceDelta.ADDED :
buffer.append('+');
break;
case IResourceDelta.REMOVED :
buffer.append('-');
break;
case IResourceDelta.CHANGED :
buffer.append('*');
break;
}
buffer.append(delta.getId());
addComma = true;
}
}
}
buffer.append(']');
}
}