KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > core > internal > events > ResourceDelta


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.core.internal.events;
12
13 import java.util.Iterator JavaDoc;
14 import java.util.Map JavaDoc;
15 import org.eclipse.core.internal.resources.*;
16 import org.eclipse.core.internal.watson.ElementTree;
17 import org.eclipse.core.resources.*;
18 import org.eclipse.core.runtime.*;
19
20 /**
21  * Concrete implementation of the IResourceDelta interface. Each ResourceDelta
22  * object represents changes that have occurred between two states of the
23  * resource tree.
24  */

25 public class ResourceDelta extends PlatformObject implements IResourceDelta {
26     protected IPath path;
27     protected ResourceDeltaInfo deltaInfo;
28     protected int status;
29     protected ResourceInfo oldInfo;
30     protected ResourceInfo newInfo;
31     protected ResourceDelta[] children;
32     // don't aggressively set this, but cache it if called once
33
protected IResource cachedResource;
34
35     //
36
protected static int KIND_MASK = 0xFF;
37     private static IMarkerDelta[] EMPTY_MARKER_DELTAS = new IMarkerDelta[0];
38
39     protected ResourceDelta(IPath path, ResourceDeltaInfo deltaInfo) {
40         this.path = path;
41         this.deltaInfo = deltaInfo;
42     }
43
44     /*
45      * @see IResourceDelta#accept(IResourceDeltaVisitor)
46      */

47     public void accept(IResourceDeltaVisitor visitor) throws CoreException {
48         accept(visitor, 0);
49     }
50
51     /*
52      * @see IResourceDelta#accept(IResourceDeltaVisitor, boolean)
53      */

54     public void accept(IResourceDeltaVisitor visitor, boolean includePhantoms) throws CoreException {
55         accept(visitor, includePhantoms ? IContainer.INCLUDE_PHANTOMS : 0);
56     }
57
58     /*
59      * @see IResourceDelta#accept(IResourceDeltaVisitor, int)
60      */

61     public void accept(IResourceDeltaVisitor visitor, int memberFlags) throws CoreException {
62         final boolean includePhantoms = (memberFlags & IContainer.INCLUDE_PHANTOMS) != 0;
63         final boolean includeTeamPrivate = (memberFlags & IContainer.INCLUDE_TEAM_PRIVATE_MEMBERS) != 0;
64         int mask = includePhantoms ? ALL_WITH_PHANTOMS : REMOVED | ADDED | CHANGED;
65         if ((getKind() & mask) == 0)
66             return;
67         if (!visitor.visit(this))
68             return;
69         for (int i = 0; i < children.length; i++) {
70             ResourceDelta childDelta = children[i];
71             // quietly exclude team-private and phantom members unless explicitly included
72
if (!includeTeamPrivate && childDelta.isTeamPrivate())
73                 continue;
74             if (!includePhantoms && childDelta.isPhantom())
75                 continue;
76             childDelta.accept(visitor, memberFlags);
77         }
78     }
79
80     /**
81      * Check for marker deltas, and set the appropriate change flag if there are any.
82      */

83     protected void checkForMarkerDeltas() {
84         if (deltaInfo.getMarkerDeltas() == null)
85             return;
86         int kind = getKind();
87         // Only need to check for added and removed, or for changes on the workspace.
88
// For changed, the bit is set in the comparator.
89
if (path.isRoot() || kind == ADDED || kind == REMOVED) {
90             MarkerSet changes = (MarkerSet) deltaInfo.getMarkerDeltas().get(path);
91             if (changes != null && changes.size() > 0) {
92                 status |= MARKERS;
93                 // If there have been marker changes, then ensure kind is CHANGED (if not ADDED or REMOVED).
94
// See 1FV9K20: ITPUI:WINNT - severe - task list - add or delete not working
95
if (kind == 0)
96                     status |= CHANGED;
97             }
98         }
99     }
100
101     /**
102      * @see IResourceDelta#findMember(IPath)
103      */

104     public IResourceDelta findMember(IPath path) {
105         int segmentCount = path.segmentCount();
106         if (segmentCount == 0)
107             return this;
108
109         //iterate over the path and find matching child delta
110
ResourceDelta current = this;
111         segments: for (int i = 0; i < segmentCount; i++) {
112             IResourceDelta[] currentChildren = current.children;
113             for (int j = 0, jmax = currentChildren.length; j < jmax; j++) {
114                 if (currentChildren[j].getFullPath().lastSegment().equals(path.segment(i))) {
115                     current = (ResourceDelta) currentChildren[j];
116                     continue segments;
117                 }
118             }
119             //matching child not found, return
120
return null;
121         }
122         return current;
123     }
124
125     /**
126      * Delta information on moves and on marker deltas can only be computed after
127      * the delta has been built. This method fixes up the delta to accurately
128      * reflect moves (setting MOVED_FROM and MOVED_TO), and marker changes on
129      * added and removed resources.
130      */

131     protected void fixMovesAndMarkers(ElementTree oldTree) {
132         NodeIDMap nodeIDMap = deltaInfo.getNodeIDMap();
133         if (!path.isRoot() && !nodeIDMap.isEmpty()) {
134             int kind = getKind();
135             switch (kind) {
136                 case CHANGED :
137                 case ADDED :
138                     IPath oldPath = nodeIDMap.getOldPath(newInfo.getNodeId());
139                     if (oldPath != null && !oldPath.equals(path)) {
140                         //get the old info from the old tree
141
ResourceInfo actualOldInfo = (ResourceInfo) oldTree.getElementData(oldPath);
142                         // Replace change flags by comparing old info with new info,
143
// Note that we want to retain the kind flag, but replace all other flags
144
// This is done only for MOVED_FROM, not MOVED_TO, since a resource may be both.
145
status = (status & KIND_MASK) | (deltaInfo.getComparator().compare(actualOldInfo, newInfo) & ~KIND_MASK);
146                         status |= MOVED_FROM;
147                         //our API states that MOVED_FROM must be in conjunction with ADDED | (CHANGED + REPLACED)
148
if (kind == CHANGED)
149                             status = status | REPLACED | CONTENT;
150                         //check for gender change
151
if (oldInfo != null && newInfo != null && oldInfo.getType() != newInfo.getType())
152                             status |= TYPE;
153                     }
154             }
155             switch (kind) {
156                 case REMOVED :
157                 case CHANGED :
158                     IPath newPath = nodeIDMap.getNewPath(oldInfo.getNodeId());
159                     if (newPath != null && !newPath.equals(path)) {
160                         status |= MOVED_TO;
161                         //our API states that MOVED_TO must be in conjunction with REMOVED | (CHANGED + REPLACED)
162
if (kind == CHANGED)
163                             status = status | REPLACED | CONTENT;
164                     }
165             }
166         }
167
168         //check for marker deltas -- this is affected by move computation
169
//so must happen afterwards
170
checkForMarkerDeltas();
171
172         //recurse on children
173
for (int i = 0; i < children.length; i++)
174             children[i].fixMovesAndMarkers(oldTree);
175     }
176
177     /**
178      * @see IResourceDelta#getAffectedChildren()
179      */

180     public IResourceDelta[] getAffectedChildren() {
181         return getAffectedChildren(ADDED | REMOVED | CHANGED, IResource.NONE);
182     }
183
184     /**
185      * @see IResourceDelta#getAffectedChildren(int)
186      */

187     public IResourceDelta[] getAffectedChildren(int kindMask) {
188         return getAffectedChildren(kindMask, IResource.NONE);
189     }
190
191     /*
192      * @see IResourceDelta#getAffectedChildren(int, int)
193      */

194     public IResourceDelta[] getAffectedChildren(int kindMask, int memberFlags) {
195         int numChildren = children.length;
196         //if there are no children, they all match
197
if (numChildren == 0)
198             return children;
199         boolean includePhantoms = (memberFlags & IContainer.INCLUDE_PHANTOMS) != 0;
200         boolean includeTeamPrivate = (memberFlags & IContainer.INCLUDE_TEAM_PRIVATE_MEMBERS) != 0;
201         // reduce INCLUDE_PHANTOMS member flag to kind mask
202
if (includePhantoms)
203             kindMask |= ADDED_PHANTOM | REMOVED_PHANTOM;
204
205         //first count the number of matches so we can allocate the exact array size
206
int matching = 0;
207         for (int i = 0; i < numChildren; i++) {
208             if ((children[i].getKind() & kindMask) == 0)
209                 continue;// child has wrong kind
210
if (!includePhantoms && children[i].isPhantom())
211                 continue;
212             if (!includeTeamPrivate && children[i].isTeamPrivate())
213                 continue; // child has is a team-private member which are not included
214
matching++;
215         }
216         //use arraycopy if all match
217
if (matching == numChildren) {
218             IResourceDelta[] result = new IResourceDelta[children.length];
219             System.arraycopy(children, 0, result, 0, children.length);
220             return result;
221         }
222         //create the appropriate sized array and fill it
223
IResourceDelta[] result = new IResourceDelta[matching];
224         int nextPosition = 0;
225         for (int i = 0; i < numChildren; i++) {
226             if ((children[i].getKind() & kindMask) == 0)
227                 continue; // child has wrong kind
228
if (!includePhantoms && children[i].isPhantom())
229                 continue;
230             if (!includeTeamPrivate && children[i].isTeamPrivate())
231                 continue; // child has is a team-private member which are not included
232
result[nextPosition++] = children[i];
233         }
234         return result;
235     }
236
237     protected ResourceDeltaInfo getDeltaInfo() {
238         return deltaInfo;
239     }
240
241     /**
242      * @see IResourceDelta#getFlags()
243      */

244     public int getFlags() {
245         return status & ~KIND_MASK;
246     }
247
248     /**
249      * @see IResourceDelta#getFullPath()
250      */

251     public IPath getFullPath() {
252         return path;
253     }
254
255     /**
256      * @see IResourceDelta#getKind()
257      */

258     public int getKind() {
259         return status & KIND_MASK;
260     }
261
262     /**
263      * @see IResourceDelta#getMarkerDeltas()
264      */

265     public IMarkerDelta[] getMarkerDeltas() {
266         Map JavaDoc markerDeltas = deltaInfo.getMarkerDeltas();
267         if (markerDeltas == null)
268             return EMPTY_MARKER_DELTAS;
269         if (path == null)
270             path = Path.ROOT;
271         MarkerSet changes = (MarkerSet) markerDeltas.get(path);
272         if (changes == null)
273             return EMPTY_MARKER_DELTAS;
274         IMarkerSetElement[] elements = changes.elements();
275         IMarkerDelta[] result = new IMarkerDelta[elements.length];
276         for (int i = 0; i < elements.length; i++)
277             result[i] = (IMarkerDelta) elements[i];
278         return result;
279     }
280
281     /**
282      * @see IResourceDelta#getMovedFromPath()
283      */

284     public IPath getMovedFromPath() {
285         if ((status & MOVED_FROM) != 0) {
286             return deltaInfo.getNodeIDMap().getOldPath(newInfo.getNodeId());
287         }
288         return null;
289     }
290
291     /**
292      * @see IResourceDelta#getMovedToPath()
293      */

294     public IPath getMovedToPath() {
295         if ((status & MOVED_TO) != 0) {
296             return deltaInfo.getNodeIDMap().getNewPath(oldInfo.getNodeId());
297         }
298         return null;
299     }
300
301     /**
302      * @see IResourceDelta#getProjectRelativePath()
303      */

304     public IPath getProjectRelativePath() {
305         IPath full = getFullPath();
306         int count = full.segmentCount();
307         if (count < 0)
308             return null;
309         if (count <= 1) // 0 or 1
310
return Path.EMPTY;
311         return full.removeFirstSegments(1);
312     }
313
314     /**
315      * @see IResourceDelta#getResource()
316      */

317     public IResource getResource() {
318         // return a cached copy if we have one
319
if (cachedResource != null)
320             return cachedResource;
321
322         // if this is a delta for the root then return the root resource
323
if (path.segmentCount() == 0)
324             return deltaInfo.getWorkspace().getRoot();
325         // if the delta is a remove then we have to look for the old info to find the type
326
// of resource to create.
327
ResourceInfo info = null;
328         if ((getKind() & (REMOVED | REMOVED_PHANTOM)) != 0)
329             info = oldInfo;
330         else
331             info = newInfo;
332         if (info == null)
333             Assert.isNotNull(null, "Do not have resource info for resource in delta: " + path); //$NON-NLS-1$
334
cachedResource = deltaInfo.getWorkspace().newResource(path, info.getType());
335         return cachedResource;
336     }
337
338     /**
339      * Returns true if this delta represents a phantom member, and false
340      * otherwise.
341      */

342     protected boolean isPhantom() {
343         //use old info for removals, and new info for added or changed
344
if ((status & (REMOVED | REMOVED_PHANTOM)) != 0)
345             return ResourceInfo.isSet(oldInfo.getFlags(), ICoreConstants.M_PHANTOM);
346         return ResourceInfo.isSet(newInfo.getFlags(), ICoreConstants.M_PHANTOM);
347     }
348
349     /**
350      * Returns true if this delta represents a team private member, and false
351      * otherwise.
352      */

353     protected boolean isTeamPrivate() {
354         //use old info for removals, and new info for added or changed
355
if ((status & (REMOVED | REMOVED_PHANTOM)) != 0)
356             return ResourceInfo.isSet(oldInfo.getFlags(), ICoreConstants.M_TEAM_PRIVATE_MEMBER);
357         return ResourceInfo.isSet(newInfo.getFlags(), ICoreConstants.M_TEAM_PRIVATE_MEMBER);
358     }
359
360     protected void setChildren(ResourceDelta[] children) {
361         this.children = children;
362     }
363
364     protected void setNewInfo(ResourceInfo newInfo) {
365         this.newInfo = newInfo;
366     }
367
368     protected void setOldInfo(ResourceInfo oldInfo) {
369         this.oldInfo = oldInfo;
370     }
371
372     protected void setStatus(int status) {
373         this.status = status;
374     }
375
376     /**
377      * Returns a string representation of this delta's
378      * immediate structure suitable for debug purposes.
379      */

380     public String JavaDoc toDebugString() {
381         final StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
382         writeDebugString(buffer);
383         return buffer.toString();
384     }
385
386     /**
387      * Returns a string representation of this delta's
388      * deep structure suitable for debug purposes.
389      */

390     public String JavaDoc toDeepDebugString() {
391         final StringBuffer JavaDoc buffer = new StringBuffer JavaDoc("\n"); //$NON-NLS-1$
392
writeDebugString(buffer);
393         for (int i = 0; i < children.length; ++i)
394             buffer.append(children[i].toDeepDebugString());
395         return buffer.toString();
396     }
397
398     /**
399      * For debugging only
400      */

401     public String JavaDoc toString() {
402         return "ResourceDelta(" + path + ')'; //$NON-NLS-1$
403
}
404
405     /**
406      * Provides a new set of markers for the delta. This is used
407      * when the delta is reused in cases where the only changes
408      * are marker changes.
409      */

410     public void updateMarkers(Map JavaDoc markers) {
411         deltaInfo.setMarkerDeltas(markers);
412     }
413
414     /**
415      * Writes a string representation of this delta's
416      * immediate structure on the given string buffer.
417      */

418     public void writeDebugString(StringBuffer JavaDoc buffer) {
419         buffer.append(getFullPath());
420         buffer.append('[');
421         switch (getKind()) {
422             case ADDED :
423                 buffer.append('+');
424                 break;
425             case ADDED_PHANTOM :
426                 buffer.append('>');
427                 break;
428             case REMOVED :
429                 buffer.append('-');
430                 break;
431             case REMOVED_PHANTOM :
432                 buffer.append('<');
433                 break;
434             case CHANGED :
435                 buffer.append('*');
436                 break;
437             case NO_CHANGE :
438                 buffer.append('~');
439                 break;
440             default :
441                 buffer.append('?');
442                 break;
443         }
444         buffer.append("]: {"); //$NON-NLS-1$
445
int changeFlags = getFlags();
446         boolean prev = false;
447         if ((changeFlags & CONTENT) != 0) {
448             if (prev)
449                 buffer.append(" | "); //$NON-NLS-1$
450
buffer.append("CONTENT"); //$NON-NLS-1$
451
prev = true;
452         }
453         if ((changeFlags & MOVED_FROM) != 0) {
454             if (prev)
455                 buffer.append(" | "); //$NON-NLS-1$
456
buffer.append("MOVED_FROM(" + getMovedFromPath() + ")"); //$NON-NLS-1$ //$NON-NLS-2$
457
prev = true;
458         }
459         if ((changeFlags & MOVED_TO) != 0) {
460             if (prev)
461                 buffer.append(" | "); //$NON-NLS-1$
462
buffer.append("MOVED_TO(" + getMovedToPath() + ")"); //$NON-NLS-1$ //$NON-NLS-2$
463
prev = true;
464         }
465         if ((changeFlags & OPEN) != 0) {
466             if (prev)
467                 buffer.append(" | "); //$NON-NLS-1$
468
buffer.append("OPEN"); //$NON-NLS-1$
469
prev = true;
470         }
471         if ((changeFlags & TYPE) != 0) {
472             if (prev)
473                 buffer.append(" | "); //$NON-NLS-1$
474
buffer.append("TYPE"); //$NON-NLS-1$
475
prev = true;
476         }
477         if ((changeFlags & SYNC) != 0) {
478             if (prev)
479                 buffer.append(" | "); //$NON-NLS-1$
480
buffer.append("SYNC"); //$NON-NLS-1$
481
prev = true;
482         }
483         if ((changeFlags & MARKERS) != 0) {
484             if (prev)
485                 buffer.append(" | "); //$NON-NLS-1$
486
buffer.append("MARKERS"); //$NON-NLS-1$
487
writeMarkerDebugString(buffer);
488             prev = true;
489         }
490         if ((changeFlags & REPLACED) != 0) {
491             if (prev)
492                 buffer.append(" | "); //$NON-NLS-1$
493
buffer.append("REPLACED"); //$NON-NLS-1$
494
prev = true;
495         }
496         if ((changeFlags & DESCRIPTION) != 0) {
497             if (prev)
498                 buffer.append(" | "); //$NON-NLS-1$
499
buffer.append("DESCRIPTION"); //$NON-NLS-1$
500
prev = true;
501         }
502         if ((changeFlags & ENCODING) != 0) {
503             if (prev)
504                 buffer.append(" | "); //$NON-NLS-1$
505
buffer.append("ENCODING"); //$NON-NLS-1$
506
prev = true;
507         }
508         buffer.append("}"); //$NON-NLS-1$
509
if (isTeamPrivate())
510             buffer.append(" (team private)"); //$NON-NLS-1$
511
}
512
513     public void writeMarkerDebugString(StringBuffer JavaDoc buffer) {
514         buffer.append('[');
515         for (Iterator JavaDoc e = deltaInfo.getMarkerDeltas().keySet().iterator(); e.hasNext();) {
516             IPath key = (IPath) e.next();
517             if (getResource().getFullPath().equals(key)) {
518                 IMarkerSetElement[] deltas = ((MarkerSet) deltaInfo.getMarkerDeltas().get(key)).elements();
519                 boolean addComma = false;
520                 for (int i = 0; i < deltas.length; i++) {
521                     IMarkerDelta delta = (IMarkerDelta) deltas[i];
522                     if (addComma)
523                         buffer.append(',');
524                     switch (delta.getKind()) {
525                         case IResourceDelta.ADDED :
526                             buffer.append('+');
527                             break;
528                         case IResourceDelta.REMOVED :
529                             buffer.append('-');
530                             break;
531                         case IResourceDelta.CHANGED :
532                             buffer.append('*');
533                             break;
534                     }
535                     buffer.append(delta.getId());
536                     addComma = true;
537                 }
538             }
539         }
540         buffer.append(']');
541     }
542 }
543
Popular Tags