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