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