3m9 compatible;
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / core / JavaElementDelta.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2003 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpdt.internal.core;
12
13 import java.util.ArrayList;
14
15 import net.sourceforge.phpdt.core.IJavaElement;
16 import net.sourceforge.phpdt.core.IJavaElementDelta;
17 import net.sourceforge.phpdt.core.IJavaProject;
18
19 import org.eclipse.core.resources.IResourceDelta;
20 import net.sourceforge.phpdt.internal.core.SimpleDelta;
21
22
23 /**
24  * @see IJavaElementDelta
25  */
26 public class JavaElementDelta extends SimpleDelta implements IJavaElementDelta {
27         /**
28          * The element that this delta describes the change to.
29          * @see #getElement()
30          */
31         protected IJavaElement fChangedElement;
32         /**
33          * @see #getKind()
34          */
35         private int fKind = 0;
36         /**
37          * @see #getFlags()
38          */
39         private int fChangeFlags = 0;
40         /**
41          * @see #getAffectedChildren()
42          */
43         protected IJavaElementDelta[] fAffectedChildren = fgEmptyDelta;
44
45         /**
46          * Collection of resource deltas that correspond to non java resources deltas.
47          */
48         protected IResourceDelta[] resourceDeltas = null;
49
50         /**
51          * Counter of resource deltas
52          */
53         protected int resourceDeltasCounter;
54         /**
55          * @see #getMovedFromHandle()
56          */
57         protected IJavaElement fMovedFromHandle = null;
58         /**
59          * @see #getMovedToHandle()
60          */
61         protected IJavaElement fMovedToHandle = null;
62         /**
63          * Empty array of IJavaElementDelta
64          */
65         protected static  IJavaElementDelta[] fgEmptyDelta= new IJavaElementDelta[] {};
66 /**
67  * Creates the root delta. To create the nested delta
68  * hierarchies use the following convenience methods. The root
69  * delta can be created at any level (for example: project, package root,
70  * package fragment...).
71  * <ul>
72  * <li><code>added(IJavaElement)</code>
73  * <li><code>changed(IJavaElement)</code>
74  * <li><code>moved(IJavaElement, IJavaElement)</code>
75  * <li><code>removed(IJavaElement)</code>
76  * <li><code>renamed(IJavaElement, IJavaElement)</code>
77  * </ul>
78  */
79 public JavaElementDelta(IJavaElement element) {
80         super();
81         fChangedElement = element;
82 }
83 /**
84  * Adds the child delta to the collection of affected children.  If the
85  * child is already in the collection, walk down the hierarchy.
86  */
87 protected void addAffectedChild(JavaElementDelta child) {
88         switch (fKind) {
89                 case ADDED:
90                 case REMOVED:
91                         // no need to add a child if this parent is added or removed
92                         return;
93                 case CHANGED:
94                         fChangeFlags |= F_CHILDREN;
95                         break;
96                 default:
97                         fKind = CHANGED;
98                         fChangeFlags |= F_CHILDREN;
99         }
100
101         // if a child delta is added to a compilation unit delta or below, 
102         // it's a fine grained delta
103         if (fChangedElement.getElementType() >= IJavaElement.COMPILATION_UNIT) {
104                 this.fineGrained();
105         }
106         
107         if (fAffectedChildren.length == 0) {
108                 fAffectedChildren = new IJavaElementDelta[] {child};
109                 return;
110         }
111         IJavaElementDelta existingChild = null;
112         int existingChildIndex = -1;
113         if (fAffectedChildren != null) {
114                 for (int i = 0; i < fAffectedChildren.length; i++) {
115                         if (this.equalsAndSameParent(fAffectedChildren[i].getElement(), child.getElement())) { // handle case of two jars that can be equals but not in the same project
116                                 existingChild = fAffectedChildren[i];
117                                 existingChildIndex = i;
118                                 break;
119                         }
120                 }
121         }
122         if (existingChild == null) { //new affected child
123                 fAffectedChildren= growAndAddToArray(fAffectedChildren, child);
124         } else {
125                 switch (existingChild.getKind()) {
126                         case ADDED:
127                                 switch (child.getKind()) {
128                                         case ADDED: // child was added then added -> it is added
129                                         case CHANGED: // child was added then changed -> it is added
130                                                 return;
131                                         case REMOVED: // child was added then removed -> noop
132                                                 fAffectedChildren = this.removeAndShrinkArray(fAffectedChildren, existingChildIndex);
133                                                 return;
134                                 }
135                                 break;
136                         case REMOVED:
137                                 switch (child.getKind()) {
138                                         case ADDED: // child was removed then added -> it is changed
139                                                 child.fKind = CHANGED;
140                                                 fAffectedChildren[existingChildIndex] = child;
141                                                 return;
142                                         case CHANGED: // child was removed then changed -> it is removed
143                                         case REMOVED: // child was removed then removed -> it is removed
144                                                 return;
145                                 }
146                                 break;
147                         case CHANGED:
148                                 switch (child.getKind()) {
149                                         case ADDED: // child was changed then added -> it is added
150                                         case REMOVED: // child was changed then removed -> it is removed
151                                                 fAffectedChildren[existingChildIndex] = child;
152                                                 return;
153                                         case CHANGED: // child was changed then changed -> it is changed
154                                                 IJavaElementDelta[] children = child.getAffectedChildren();
155                                                 for (int i = 0; i < children.length; i++) {
156                                                         JavaElementDelta childsChild = (JavaElementDelta) children[i];
157                                                         ((JavaElementDelta) existingChild).addAffectedChild(childsChild);
158                                                 }
159                                                 
160                                                 // update flags if needed
161                                                 switch (((JavaElementDelta) existingChild).fChangeFlags) {
162                                                         case F_ADDED_TO_CLASSPATH:
163                                                         case F_REMOVED_FROM_CLASSPATH:
164                                                         case F_SOURCEATTACHED:
165                                                         case F_SOURCEDETACHED:
166                                                                 ((JavaElementDelta) existingChild).fChangeFlags |= ((JavaElementDelta) child).fChangeFlags;
167                                                                 break;
168                                                 }
169                                                 
170                                                 // add the non-java resource deltas if needed
171                                                 // note that the child delta always takes precedence over this existing child delta
172                                                 // as non-java resource deltas are always created last (by the DeltaProcessor)
173                                                 IResourceDelta[] resDeltas = child.getResourceDeltas();
174                                                 if (resDeltas != null) {
175                                                         ((JavaElementDelta)existingChild).resourceDeltas = resDeltas;
176                                                         ((JavaElementDelta)existingChild).resourceDeltasCounter = child.resourceDeltasCounter;
177                                                 }
178                                                 return;
179                                 }
180                                 break;
181                         default: 
182                                 // unknown -> existing child becomes the child with the existing child's flags
183                                 int flags = existingChild.getFlags();
184                                 fAffectedChildren[existingChildIndex] = child;
185                                 child.fChangeFlags |= flags;
186                 }
187         }
188 }
189 ///**
190 // * Creates the nested deltas resulting from an add operation.
191 // * Convenience method for creating add deltas.
192 // * The constructor should be used to create the root delta 
193 // * and then an add operation should call this method.
194 // */
195 //public void added(IJavaElement element) {
196 //      JavaElementDelta addedDelta = new JavaElementDelta(element);
197 //      addedDelta.fKind = ADDED;
198 //      insertDeltaTree(element, addedDelta);
199 //}
200 /**
201  * Creates the nested deltas resulting from an add operation.
202  * Convenience method for creating add deltas.
203  * The constructor should be used to create the root delta 
204  * and then an add operation should call this method.
205  */
206 public void added(IJavaElement element) {
207         added(element, 0);
208 }
209 public void added(IJavaElement element, int flags) {
210         JavaElementDelta addedDelta = new JavaElementDelta(element);
211         addedDelta.added();
212         addedDelta.changeFlags |= flags;
213         insertDeltaTree(element, addedDelta);
214 }
215 /**
216  * Adds the child delta to the collection of affected children.  If the
217  * child is already in the collection, walk down the hierarchy.
218  */
219 protected void addResourceDelta(IResourceDelta child) {
220         switch (fKind) {
221                 case ADDED:
222                 case REMOVED:
223                         // no need to add a child if this parent is added or removed
224                         return;
225                 case CHANGED:
226                         fChangeFlags |= F_CONTENT;
227                         break;
228                 default:
229                         fKind = CHANGED;
230                         fChangeFlags |= F_CONTENT;
231         }
232         if (resourceDeltas == null) {
233                 resourceDeltas = new IResourceDelta[5];
234                 resourceDeltas[resourceDeltasCounter++] = child;
235                 return;
236         }
237         if (resourceDeltas.length == resourceDeltasCounter) {
238                 // need a resize
239                 System.arraycopy(resourceDeltas, 0, (resourceDeltas = new IResourceDelta[resourceDeltasCounter * 2]), 0, resourceDeltasCounter);
240         }
241         resourceDeltas[resourceDeltasCounter++] = child;
242 }
243 /**
244  * Creates the nested deltas resulting from a change operation.
245  * Convenience method for creating change deltas.
246  * The constructor should be used to create the root delta 
247  * and then a change operation should call this method.
248  */
249 public void changed(IJavaElement element, int changeFlag) {
250         JavaElementDelta changedDelta = new JavaElementDelta(element);
251         changedDelta.fKind = CHANGED;
252         changedDelta.fChangeFlags |= changeFlag;
253         insertDeltaTree(element, changedDelta);
254 }
255 /**
256  * Mark this delta as a content changed delta.
257  */
258 public void contentChanged() {
259         fChangeFlags |= F_CONTENT;
260 }
261 ///**
262 // * Clone this delta so that its elements are rooted at the given project.
263 // */
264 //public IJavaElementDelta clone(IJavaProject project) {
265 //      JavaElementDelta clone = 
266 //              new JavaElementDelta(((JavaElement)fChangedElement).rootedAt(project));
267 //      if (fAffectedChildren != fgEmptyDelta) {
268 //              int length = fAffectedChildren.length;
269 //              IJavaElementDelta[] cloneChildren = new IJavaElementDelta[length];
270 //              for (int i= 0; i < length; i++) {
271 //                      cloneChildren[i] = ((JavaElementDelta)fAffectedChildren[i]).clone(project);
272 //              }
273 //              clone.fAffectedChildren = cloneChildren;
274 //      }       
275 //      clone.fChangeFlags = fChangeFlags;
276 //      clone.fKind = fKind;
277 //      if (fMovedFromHandle != null) {
278 //              clone.fMovedFromHandle = ((JavaElement)fMovedFromHandle).rootedAt(project);
279 //      }
280 //      if (fMovedToHandle != null) {
281 //              clone.fMovedToHandle = ((JavaElement)fMovedToHandle).rootedAt(project);
282 //      }
283 //      clone.resourceDeltas = this.resourceDeltas;
284 //      clone.resourceDeltasCounter = this.resourceDeltasCounter;
285 //      return clone;
286 //}
287
288 /**
289  * Creates the nested deltas for a closed element.
290  */
291 public void closed(IJavaElement element) {
292         JavaElementDelta delta = new JavaElementDelta(element);
293         delta.fKind = CHANGED;
294         delta.fChangeFlags |= F_CLOSED;
295         insertDeltaTree(element, delta);
296 }
297 /**
298  * Creates the nested delta deltas based on the affected element
299  * its delta, and the root of this delta tree. Returns the root
300  * of the created delta tree.
301  */
302 protected JavaElementDelta createDeltaTree(IJavaElement element, JavaElementDelta delta) {
303         JavaElementDelta childDelta = delta;
304         ArrayList ancestors= getAncestors(element);
305         if (ancestors == null) {
306                 if (this.equalsAndSameParent(delta.getElement(), getElement())) { // handle case of two jars that can be equals but not in the same project
307                         // the element being changed is the root element
308                         fKind= delta.fKind;
309                         fChangeFlags = delta.fChangeFlags;
310                         fMovedToHandle = delta.fMovedToHandle;
311                         fMovedFromHandle = delta.fMovedFromHandle;
312                 }
313         } else {
314                 for (int i = 0, size = ancestors.size(); i < size; i++) {
315                         IJavaElement ancestor = (IJavaElement) ancestors.get(i);
316                         JavaElementDelta ancestorDelta = new JavaElementDelta(ancestor);
317                         ancestorDelta.addAffectedChild(childDelta);
318                         childDelta = ancestorDelta;
319                 }
320         }
321         return childDelta;
322 }
323 /**
324  * Returns whether the two java elements are equals and have the same parent.
325  */
326 protected boolean equalsAndSameParent(IJavaElement e1, IJavaElement e2) {
327         IJavaElement parent1;
328         return e1.equals(e2) && ((parent1 = e1.getParent()) != null) && parent1.equals(e2.getParent());
329 }
330 /**
331  * Returns the <code>JavaElementDelta</code> for the given element
332  * in the delta tree, or null, if no delta for the given element is found.
333  */
334 protected JavaElementDelta find(IJavaElement e) {
335         if (this.equalsAndSameParent(fChangedElement, e)) { // handle case of two jars that can be equals but not in the same project
336                 return this;
337         } else {
338                 for (int i = 0; i < fAffectedChildren.length; i++) {
339                         JavaElementDelta delta = ((JavaElementDelta)fAffectedChildren[i]).find(e);
340                         if (delta != null) {
341                                 return delta;
342                         }
343                 }
344         }
345         return null;
346 }
347 /**
348  * Mark this delta as a fine-grained delta.
349  */
350 public void fineGrained() {
351         if (fKind == 0) { // if not set yet
352                 fKind = CHANGED;
353         }
354         fChangeFlags |= F_FINE_GRAINED;
355 }
356 /**
357  * @see IJavaElementDelta
358  */
359 public IJavaElementDelta[] getAddedChildren() {
360         return getChildrenOfType(ADDED);
361 }
362 /**
363  * @see IJavaElementDelta
364  */
365 public IJavaElementDelta[] getAffectedChildren() {
366         return fAffectedChildren;
367 }
368 /**
369  * Returns a collection of all the parents of this element up to (but
370  * not including) the root of this tree in bottom-up order. If the given
371  * element is not a descendant of the root of this tree, <code>null</code>
372  * is returned.
373  */
374 private ArrayList getAncestors(IJavaElement element) {
375         IJavaElement parent = element.getParent();
376         if (parent == null) {
377                 return null;
378         }
379         ArrayList parents = new ArrayList();
380         while (!parent.equals(fChangedElement)) {
381                 parents.add(parent);
382                 parent = parent.getParent();
383                 if (parent == null) {
384                         return null;
385                 }
386         }
387         parents.trimToSize();
388         return parents;
389 }
390 /**
391  * @see IJavaElementDelta
392  */
393 public IJavaElementDelta[] getChangedChildren() {
394         return getChildrenOfType(CHANGED);
395 }
396 /**
397  * @see IJavaElementDelta
398  */
399 protected IJavaElementDelta[] getChildrenOfType(int type) {
400         int length = fAffectedChildren.length;
401         if (length == 0) {
402                 return new IJavaElementDelta[] {};
403         }
404         ArrayList children= new ArrayList(length);
405         for (int i = 0; i < length; i++) {
406                 if (fAffectedChildren[i].getKind() == type) {
407                         children.add(fAffectedChildren[i]);
408                 }
409         }
410
411         IJavaElementDelta[] childrenOfType = new IJavaElementDelta[children.size()];
412         children.toArray(childrenOfType);
413         
414         return childrenOfType;
415 }
416 /**
417  * Returns the delta for a given element.  Only looks below this
418  * delta.
419  */
420 protected JavaElementDelta getDeltaFor(IJavaElement element) {
421         if (this.equalsAndSameParent(getElement(), element)) // handle case of two jars that can be equals but not in the same project
422                 return this;
423         if (fAffectedChildren.length == 0)
424                 return null;
425         int childrenCount = fAffectedChildren.length;
426         for (int i = 0; i < childrenCount; i++) {
427                 JavaElementDelta delta = (JavaElementDelta)fAffectedChildren[i];
428                 if (this.equalsAndSameParent(delta.getElement(), element)) { // handle case of two jars that can be equals but not in the same project
429                         return delta;
430                 } else {
431                         delta = ((JavaElementDelta)delta).getDeltaFor(element);
432                         if (delta != null)
433                                 return delta;
434                 }
435         }
436         return null;
437 }
438 /**
439  * @see IJavaElementDelta
440  */
441 public IJavaElement getElement() {
442         return fChangedElement;
443 }
444 /**
445  * @see IJavaElementDelta
446  */
447 public int getFlags() {
448         return fChangeFlags;
449 }
450 /**
451  * @see IJavaElementDelta
452  */
453 public int getKind() {
454         return fKind;
455 }
456 /**
457  * @see IJavaElementDelta
458  */
459 public IJavaElement getMovedFromElement() {
460         return fMovedFromHandle;
461 }
462 /**
463  * @see IJavaElementDelta
464  */
465 public IJavaElement getMovedToElement() {
466         return fMovedToHandle;
467 }
468 /**
469  * @see IJavaElementDelta
470  */
471 public IJavaElementDelta[] getRemovedChildren() {
472         return getChildrenOfType(REMOVED);
473 }
474 /**
475  * Return the collection of resource deltas. Return null if none.
476  */
477 public IResourceDelta[] getResourceDeltas() {
478         if (resourceDeltas == null) return null;
479         if (resourceDeltas.length != resourceDeltasCounter) {
480                 System.arraycopy(resourceDeltas, 0, resourceDeltas = new IResourceDelta[resourceDeltasCounter], 0, resourceDeltasCounter);
481         }
482         return resourceDeltas;
483 }
484 /**
485  * Adds the new element to a new array that contains all of the elements of the old array.
486  * Returns the new array.
487  */
488 protected IJavaElementDelta[] growAndAddToArray(IJavaElementDelta[] array, IJavaElementDelta addition) {
489         IJavaElementDelta[] old = array;
490         array = new IJavaElementDelta[old.length + 1];
491         System.arraycopy(old, 0, array, 0, old.length);
492         array[old.length] = addition;
493         return array;
494 }
495 /**
496  * Creates the delta tree for the given element and delta, and then
497  * inserts the tree as an affected child of this node.
498  */
499 protected void insertDeltaTree(IJavaElement element, JavaElementDelta delta) {
500         JavaElementDelta childDelta= createDeltaTree(element, delta);
501         if (!this.equalsAndSameParent(element, getElement())) { // handle case of two jars that can be equals but not in the same project
502                 addAffectedChild(childDelta);
503         }
504 }
505 /**
506  * Creates the nested deltas resulting from an move operation.
507  * Convenience method for creating the "move from" delta.
508  * The constructor should be used to create the root delta 
509  * and then the move operation should call this method.
510  */
511 public void movedFrom(IJavaElement movedFromElement, IJavaElement movedToElement) {
512         JavaElementDelta removedDelta = new JavaElementDelta(movedFromElement);
513         removedDelta.fKind = REMOVED;
514         removedDelta.fChangeFlags |= F_MOVED_TO;
515         removedDelta.fMovedToHandle = movedToElement;
516         insertDeltaTree(movedFromElement, removedDelta);
517 }
518 /**
519  * Creates the nested deltas resulting from an move operation.
520  * Convenience method for creating the "move to" delta.
521  * The constructor should be used to create the root delta 
522  * and then the move operation should call this method.
523  */
524 public void movedTo(IJavaElement movedToElement, IJavaElement movedFromElement) {
525         JavaElementDelta addedDelta = new JavaElementDelta(movedToElement);
526         addedDelta.fKind = ADDED;
527         addedDelta.fChangeFlags |= F_MOVED_FROM;
528         addedDelta.fMovedFromHandle = movedFromElement;
529         insertDeltaTree(movedToElement, addedDelta);
530 }
531 /**
532  * Creates the nested deltas for an opened element.
533  */
534 public void opened(IJavaElement element) {
535         JavaElementDelta delta = new JavaElementDelta(element);
536         delta.fKind = CHANGED;
537         delta.fChangeFlags |= F_OPENED;
538         insertDeltaTree(element, delta);
539 }
540 /**
541  * Removes the child delta from the collection of affected children.
542  */
543 protected void removeAffectedChild(JavaElementDelta child) {
544         int index = -1;
545         if (fAffectedChildren != null) {
546                 for (int i = 0; i < fAffectedChildren.length; i++) {
547                         if (this.equalsAndSameParent(fAffectedChildren[i].getElement(), child.getElement())) { // handle case of two jars that can be equals but not in the same project
548                                 index = i;
549                                 break;
550                         }
551                 }
552         }
553         if (index >= 0) {
554                 fAffectedChildren= removeAndShrinkArray(fAffectedChildren, index);
555         }
556 }
557 /**
558  * Removes the element from the array.
559  * Returns the a new array which has shrunk.
560  */
561 protected IJavaElementDelta[] removeAndShrinkArray(IJavaElementDelta[] old, int index) {
562         IJavaElementDelta[] array = new IJavaElementDelta[old.length - 1];
563         if (index > 0)
564                 System.arraycopy(old, 0, array, 0, index);
565         int rest = old.length - index - 1;
566         if (rest > 0)
567                 System.arraycopy(old, index + 1, array, index, rest);
568         return array;
569 }
570 /**
571  * Creates the nested deltas resulting from an delete operation.
572  * Convenience method for creating removed deltas.
573  * The constructor should be used to create the root delta 
574  * and then the delete operation should call this method.
575  */
576 public void removed(IJavaElement element) {
577         removed(element, 0);
578 }
579 public void removed(IJavaElement element, int flags) {
580         JavaElementDelta removedDelta= new JavaElementDelta(element);
581         insertDeltaTree(element, removedDelta);
582         JavaElementDelta actualDelta = getDeltaFor(element);
583         if (actualDelta != null) {
584                 actualDelta.removed();
585                 actualDelta.changeFlags |= flags;
586                 actualDelta.fAffectedChildren = fgEmptyDelta;
587         }
588 }
589
590 /**
591  * Creates the nested deltas resulting from a change operation.
592  * Convenience method for creating change deltas.
593  * The constructor should be used to create the root delta 
594  * and then a change operation should call this method.
595  */
596 public void sourceAttached(IJavaElement element) {
597         JavaElementDelta attachedDelta = new JavaElementDelta(element);
598         attachedDelta.fKind = CHANGED;
599         attachedDelta.fChangeFlags |= F_SOURCEATTACHED;
600         insertDeltaTree(element, attachedDelta);
601 }
602 /**
603  * Creates the nested deltas resulting from a change operation.
604  * Convenience method for creating change deltas.
605  * The constructor should be used to create the root delta 
606  * and then a change operation should call this method.
607  */
608 public void sourceDetached(IJavaElement element) {
609         JavaElementDelta detachedDelta = new JavaElementDelta(element);
610         detachedDelta.fKind = CHANGED;
611         detachedDelta.fChangeFlags |= F_SOURCEDETACHED;
612         insertDeltaTree(element, detachedDelta);
613 }
614 /** 
615  * Returns a string representation of this delta's
616  * structure suitable for debug purposes.
617  *
618  * @see #toString()
619  */
620 public String toDebugString(int depth) {
621         StringBuffer buffer = new StringBuffer();
622         for (int i= 0; i < depth; i++) {
623                 buffer.append('\t');
624         }
625         buffer.append(((JavaElement)getElement()).toDebugString());
626         buffer.append("["); //$NON-NLS-1$
627         switch (getKind()) {
628                 case IJavaElementDelta.ADDED :
629                         buffer.append('+');
630                         break;
631                 case IJavaElementDelta.REMOVED :
632                         buffer.append('-');
633                         break;
634                 case IJavaElementDelta.CHANGED :
635                         buffer.append('*');
636                         break;
637                 default :
638                         buffer.append('?');
639                         break;
640         }
641         buffer.append("]: {"); //$NON-NLS-1$
642         int changeFlags = getFlags();
643         boolean prev = false;
644         if ((changeFlags & IJavaElementDelta.F_CHILDREN) != 0) {
645                 if (prev)
646                         buffer.append(" | "); //$NON-NLS-1$
647                 buffer.append("CHILDREN"); //$NON-NLS-1$
648                 prev = true;
649         }
650         if ((changeFlags & IJavaElementDelta.F_CONTENT) != 0) {
651                 if (prev)
652                         buffer.append(" | "); //$NON-NLS-1$
653                 buffer.append("CONTENT"); //$NON-NLS-1$
654                 prev = true;
655         }
656         if ((changeFlags & IJavaElementDelta.F_MOVED_FROM) != 0) {
657                 if (prev)
658                         buffer.append(" | "); //$NON-NLS-1$
659                 buffer.append("MOVED_FROM(" + ((JavaElement)getMovedFromElement()).toStringWithAncestors() + ")"); //$NON-NLS-1$ //$NON-NLS-2$
660                 prev = true;
661         }
662         if ((changeFlags & IJavaElementDelta.F_MOVED_TO) != 0) {
663                 if (prev)
664                         buffer.append(" | "); //$NON-NLS-1$
665                 buffer.append("MOVED_TO(" + ((JavaElement)getMovedToElement()).toStringWithAncestors() + ")"); //$NON-NLS-1$ //$NON-NLS-2$
666                 prev = true;
667         }
668         if ((changeFlags & IJavaElementDelta.F_ADDED_TO_CLASSPATH) != 0) {
669                 if (prev)
670                         buffer.append(" | "); //$NON-NLS-1$
671                 buffer.append("ADDED TO CLASSPATH"); //$NON-NLS-1$
672                 prev = true;
673         }
674         if ((changeFlags & IJavaElementDelta.F_REMOVED_FROM_CLASSPATH) != 0) {
675                 if (prev)
676                         buffer.append(" | "); //$NON-NLS-1$
677                 buffer.append("REMOVED FROM CLASSPATH"); //$NON-NLS-1$
678                 prev = true;
679         }
680         if ((changeFlags & IJavaElementDelta.F_REORDER) != 0) {
681                 if (prev)
682                         buffer.append(" | "); //$NON-NLS-1$
683                 buffer.append("REORDERED"); //$NON-NLS-1$
684                 prev = true;
685         }
686         if ((changeFlags & IJavaElementDelta.F_ARCHIVE_CONTENT_CHANGED) != 0) {
687                 if (prev)
688                         buffer.append(" | "); //$NON-NLS-1$
689                 buffer.append("ARCHIVE CONTENT CHANGED"); //$NON-NLS-1$
690                 prev = true;
691         }
692         if ((changeFlags & IJavaElementDelta.F_SOURCEATTACHED) != 0) {
693                 if (prev)
694                         buffer.append(" | "); //$NON-NLS-1$
695                 buffer.append("SOURCE ATTACHED"); //$NON-NLS-1$
696                 prev = true;
697         }
698         if ((changeFlags & IJavaElementDelta.F_SOURCEDETACHED) != 0) {
699                 if (prev)
700                         buffer.append(" | "); //$NON-NLS-1$
701                 buffer.append("SOURCE DETACHED"); //$NON-NLS-1$
702                 prev = true;
703         }
704         if ((changeFlags & IJavaElementDelta.F_MODIFIERS) != 0) {
705                 if (prev)
706                         buffer.append(" | "); //$NON-NLS-1$
707                 buffer.append("MODIFIERS CHANGED"); //$NON-NLS-1$
708                 prev = true;
709         }
710         if ((changeFlags & IJavaElementDelta.F_SUPER_TYPES) != 0) {
711                 if (prev)
712                         buffer.append(" | "); //$NON-NLS-1$
713                 buffer.append("SUPER TYPES CHANGED"); //$NON-NLS-1$
714                 prev = true;
715         }
716         if ((changeFlags & IJavaElementDelta.F_FINE_GRAINED) != 0) {
717                 if (prev)
718                         buffer.append(" | "); //$NON-NLS-1$
719                 buffer.append("FINE GRAINED"); //$NON-NLS-1$
720                 prev = true;
721         }
722         buffer.append("}"); //$NON-NLS-1$
723         IJavaElementDelta[] children = getAffectedChildren();
724         if (children != null) {
725                 for (int i = 0; i < children.length; ++i) {
726                         buffer.append("\n"); //$NON-NLS-1$
727                         buffer.append(((JavaElementDelta) children[i]).toDebugString(depth + 1));
728                 }
729         }
730         for (int i = 0; i < resourceDeltasCounter; i++) {
731                 buffer.append("\n");//$NON-NLS-1$
732                 for (int j = 0; j < depth+1; j++) {
733                         buffer.append('\t');
734                 }
735                 IResourceDelta resourceDelta = resourceDeltas[i];
736                 buffer.append(resourceDelta.toString());
737                 buffer.append("["); //$NON-NLS-1$
738                 switch (resourceDelta.getKind()) {
739                         case IResourceDelta.ADDED :
740                                 buffer.append('+');
741                                 break;
742                         case IResourceDelta.REMOVED :
743                                 buffer.append('-');
744                                 break;
745                         case IResourceDelta.CHANGED :
746                                 buffer.append('*');
747                                 break;
748                         default :
749                                 buffer.append('?');
750                                 break;
751                 }
752                 buffer.append("]"); //$NON-NLS-1$
753         }
754         return buffer.toString();
755 }
756 /** 
757  * Returns a string representation of this delta's
758  * structure suitable for debug purposes.
759  */
760 public String toString() {
761         return toDebugString(0);
762 }
763 }