6eb79eeb4a5f6c489214ed0245be364c0e2d02df
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / core / JavaElement.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 import java.util.HashMap;
15 import java.util.Iterator;
16
17 import net.sourceforge.phpdt.core.ICompilationUnit;
18 import net.sourceforge.phpdt.core.IJavaElement;
19 import net.sourceforge.phpdt.core.IJavaModel;
20 import net.sourceforge.phpdt.core.IJavaModelStatusConstants;
21 import net.sourceforge.phpdt.core.IJavaProject;
22 import net.sourceforge.phpdt.core.IMember;
23 import net.sourceforge.phpdt.core.IOpenable;
24 import net.sourceforge.phpdt.core.IParent;
25 import net.sourceforge.phpdt.core.ISourceRange;
26 import net.sourceforge.phpdt.core.ISourceReference;
27 import net.sourceforge.phpdt.core.JavaModelException;
28 import net.sourceforge.phpdt.core.jdom.IDOMCompilationUnit;
29 import net.sourceforge.phpdt.core.jdom.IDOMNode;
30 import net.sourceforge.phpdt.internal.core.util.Util;
31 import net.sourceforge.phpdt.internal.corext.Assert;
32
33 import org.eclipse.core.resources.IResource;
34 import org.eclipse.core.resources.IResourceStatus;
35 import org.eclipse.core.resources.ResourcesPlugin;
36 import org.eclipse.core.runtime.CoreException;
37 import org.eclipse.core.runtime.IAdaptable;
38 import org.eclipse.core.runtime.IPath;
39 import org.eclipse.core.runtime.IProgressMonitor;
40 import org.eclipse.core.runtime.Path;
41 import org.eclipse.core.runtime.PlatformObject;
42 import org.eclipse.core.runtime.jobs.ISchedulingRule;
43
44 /**
45  * Root of Java element handle hierarchy.
46  * 
47  * @see IJavaElement
48  */
49 public abstract class JavaElement extends PlatformObject
50                 implements
51                         IJavaElement {
52
53         public static final char JEM_JAVAPROJECT = '=';
54         public static final char JEM_PACKAGEFRAGMENTROOT = Path.SEPARATOR;
55         public static final char JEM_PACKAGEFRAGMENT = '<';
56         public static final char JEM_FIELD = '^';
57         public static final char JEM_METHOD = '~';
58         public static final char JEM_INITIALIZER = '|';
59         public static final char JEM_COMPILATIONUNIT = '{';
60         public static final char JEM_CLASSFILE = '(';
61         public static final char JEM_TYPE = '[';
62         public static final char JEM_PACKAGEDECLARATION = '%';
63         public static final char JEM_IMPORTDECLARATION = '#';
64
65         /**
66          * A count to uniquely identify this element in the case that a duplicate
67          * named element exists. For example, if there are two fields in a
68          * compilation unit with the same name, the occurrence count is used to
69          * distinguish them. The occurrence count starts at 1 (thus the first
70          * occurrence is occurrence 1, not occurrence 0).
71          */
72         protected int occurrenceCount = 1;
73
74         /**
75          * This element's type - one of the constants defined in
76          * IJavaLanguageElementTypes.
77          */
78         //protected int fLEType = 0;
79         /**
80          * This element's parent, or <code>null</code> if this element does not
81          * have a parent.
82          */
83         protected IJavaElement parent;
84
85         /**
86          * This element's name, or an empty <code>String</code> if this element
87          * does not have a name.
88          */
89         protected String name;
90
91         protected static final Object NO_INFO = new Object();
92
93         /**
94          * Constructs a handle for a java element with the given parent element and
95          * name.
96          * 
97          * @param parent
98          *            The parent of java element
99          * @param name
100          *            The name of java element
101          * 
102          * @exception IllegalArgumentException
103          *                if the type is not one of the valid Java element type
104          *                constants
105          *  
106          */
107         protected JavaElement(JavaElement parent, String name)
108                         throws IllegalArgumentException {
109                 this.parent = parent;
110                 this.name = name;
111         }
112         /**
113          * @see IOpenable
114          */
115         public void close() throws JavaModelException {
116                 JavaModelManager.getJavaModelManager().removeInfoAndChildren(this);
117         }
118         /**
119          * This element is being closed. Do any necessary cleanup.
120          */
121         protected abstract void closing(Object info) throws JavaModelException;
122         /*
123          * Returns a new element info for this element.
124          */
125         protected abstract Object createElementInfo();
126         /**
127          * Returns true if this handle represents the same Java element as the given
128          * handle. By default, two handles represent the same element if they are
129          * identical or if they represent the same type of element, have equal
130          * names, parents, and occurrence counts.
131          * 
132          * <p>
133          * If a subclass has other requirements for equality, this method must be
134          * overridden.
135          * 
136          * @see Object#equals
137          */
138         public boolean equals(Object o) {
139
140                 if (this == o)
141                         return true;
142
143                 // Java model parent is null
144                 if (this.parent == null)
145                         return super.equals(o);
146                 if (o instanceof JavaElement) {
147                         // assume instanceof check is done in subclass
148                         JavaElement other = (JavaElement) o;
149                         return this.occurrenceCount == other.occurrenceCount
150                                         && this.name.equals(other.name)
151                                         && this.parent.equals(other.parent);
152                 }
153                 return false;
154         }
155         /**
156          * Returns true if this <code>JavaElement</code> is equivalent to the
157          * given <code>IDOMNode</code>.
158          */
159         protected boolean equalsDOMNode(IDOMNode node) throws JavaModelException {
160                 return false;
161         }
162         /**
163          * @see IJavaElement
164          */
165         public boolean exists() {
166
167                 try {
168                         getElementInfo();
169                         return true;
170                 } catch (JavaModelException e) {
171                 }
172                 return false;
173         }
174
175         /**
176          * Returns the <code>IDOMNode</code> that corresponds to this
177          * <code>JavaElement</code> or <code>null</code> if there is no
178          * corresponding node.
179          */
180         public IDOMNode findNode(IDOMCompilationUnit dom) {
181                 int type = getElementType();
182                 if (type == IJavaElement.COMPILATION_UNIT || type == IJavaElement.FIELD
183                                 || type == IJavaElement.IMPORT_DECLARATION
184                                 || type == IJavaElement.INITIALIZER
185                                 || type == IJavaElement.METHOD
186                                 || type == IJavaElement.PACKAGE_DECLARATION
187                                 || type == IJavaElement.TYPE) {
188                         ArrayList path = new ArrayList();
189                         IJavaElement element = this;
190                         while (element != null
191                                         && element.getElementType() != IJavaElement.COMPILATION_UNIT) {
192                                 if (element.getElementType() != IJavaElement.IMPORT_CONTAINER) {
193                                         // the DOM does not have import containers, so skip them
194                                         path.add(0, element);
195                                 }
196                                 element = element.getParent();
197                         }
198                         if (path.size() == 0) {
199                                 try {
200                                         if (equalsDOMNode(dom)) {
201                                                 return dom;
202                                         } else {
203                                                 return null;
204                                         }
205                                 } catch (JavaModelException e) {
206                                         return null;
207                                 }
208                         }
209                         return ((JavaElement) path.get(0)).followPath(path, 0, dom
210                                         .getFirstChild());
211                 } else {
212                         return null;
213                 }
214         }
215         /**
216          */
217         protected IDOMNode followPath(ArrayList path, int position, IDOMNode node) {
218
219                 try {
220                         if (equalsDOMNode(node)) {
221                                 if (position == (path.size() - 1)) {
222                                         return node;
223                                 } else {
224                                         if (node.getFirstChild() != null) {
225                                                 position++;
226                                                 return ((JavaElement) path.get(position)).followPath(
227                                                                 path, position, node.getFirstChild());
228                                         } else {
229                                                 return null;
230                                         }
231                                 }
232                         } else if (node.getNextNode() != null) {
233                                 return followPath(path, position, node.getNextNode());
234                         } else {
235                                 return null;
236                         }
237                 } catch (JavaModelException e) {
238                         return null;
239                 }
240
241         }
242         /**
243          * @see IJavaElement
244          */
245         public IJavaElement getAncestor(int ancestorType) {
246
247                 IJavaElement element = this;
248                 while (element != null) {
249                         if (element.getElementType() == ancestorType)
250                                 return element;
251                         element = element.getParent();
252                 }
253                 return null;
254         }
255         /**
256          * Generates the element infos for this element, its ancestors (if they are
257          * not opened) and its children (if it is an Openable). Puts the newly
258          * created element info in the given map.
259          */
260         protected abstract void generateInfos(Object info, HashMap newElements,
261                         IProgressMonitor pm) throws JavaModelException;
262
263         /**
264          * @see IParent
265          */
266         public IJavaElement[] getChildren() throws JavaModelException {
267                 return ((JavaElementInfo) getElementInfo()).getChildren();
268         }
269         /**
270          * Returns a collection of (immediate) children of this node of the
271          * specified type.
272          * 
273          * @param type -
274          *            one of constants defined by IJavaLanguageElementTypes
275          */
276         public ArrayList getChildrenOfType(int type) throws JavaModelException {
277                 IJavaElement[] children = getChildren();
278                 int size = children.length;
279                 ArrayList list = new ArrayList(size);
280                 for (int i = 0; i < size; ++i) {
281                         JavaElement elt = (JavaElement) children[i];
282                         if (elt.getElementType() == type) {
283                                 list.add(elt);
284                         }
285                 }
286                 return list;
287         }
288         /**
289          * @see IMember
290          */
291         //      public IClassFile getClassFile() {
292         //              return null;
293         //      }
294         /**
295          * @see IMember
296          */
297         public ICompilationUnit getCompilationUnit() {
298                 return null;
299         }
300         /**
301          * Returns the info for this handle. If this element is not already open, it
302          * and all of its parents are opened. Does not return null. NOTE: BinaryType
303          * infos are NOT rooted under JavaElementInfo.
304          * 
305          * @exception JavaModelException
306          *                if the element is not present or not accessible
307          */
308         public Object getElementInfo() throws JavaModelException {
309                 return getElementInfo(null);
310         }
311         /**
312          * Returns the info for this handle. If this element is not already open, it
313          * and all of its parents are opened. Does not return null. NOTE: BinaryType
314          * infos are NOT rooted under JavaElementInfo.
315          * 
316          * @exception JavaModelException
317          *                if the element is not present or not accessible
318          */
319         public Object getElementInfo(IProgressMonitor monitor)
320                         throws JavaModelException {
321
322                 JavaModelManager manager = JavaModelManager.getJavaModelManager();
323                 Object info = manager.getInfo(this);
324                 if (info != null)
325                         return info;
326                 return openWhenClosed(createElementInfo(), monitor);
327         }
328         /**
329          * @see IAdaptable
330          */
331         public String getElementName() {
332                 return name;
333         }
334
335         /**
336          * @see IJavaElement
337          */
338         public String getHandleIdentifier() {
339                 return getHandleMemento();
340         }
341         /**
342          * @see JavaElement#getHandleMemento()
343          */
344         public String getHandleMemento() {
345                 StringBuffer buff = new StringBuffer(((JavaElement) getParent())
346                                 .getHandleMemento());
347                 buff.append(getHandleMementoDelimiter());
348                 buff.append(getElementName());
349                 return buff.toString();
350         }
351         /**
352          * Returns the <code>char</code> that marks the start of this handles
353          * contribution to a memento.
354          */
355         protected abstract char getHandleMementoDelimiter();
356         /**
357          * @see IJavaElement
358          */
359         public IJavaModel getJavaModel() {
360                 IJavaElement current = this;
361                 do {
362                         if (current instanceof IJavaModel)
363                                 return (IJavaModel) current;
364                 } while ((current = current.getParent()) != null);
365                 return null;
366         }
367
368         /**
369          * @see IJavaElement
370          */
371         public IJavaProject getJavaProject() {
372                 IJavaElement current = this;
373                 do {
374                         if (current instanceof IJavaProject)
375                                 return (IJavaProject) current;
376                 } while ((current = current.getParent()) != null);
377                 return null;
378         }
379         /**
380          * Returns the occurrence count of the handle.
381          */
382         protected int getOccurrenceCount() {
383                 return occurrenceCount;
384         }
385         /*
386          * @see IJavaElement
387          */
388         public IOpenable getOpenable() {
389                 return this.getOpenableParent();
390         }
391         /**
392          * Return the first instance of IOpenable in the parent hierarchy of this
393          * element.
394          * 
395          * <p>
396          * Subclasses that are not IOpenable's must override this method.
397          */
398         public IOpenable getOpenableParent() {
399
400                 return (IOpenable) parent;
401         }
402         /**
403          * @see IJavaElement
404          */
405         public IJavaElement getParent() {
406                 return parent;
407         }
408
409         /*
410          * @see IJavaElement#getPrimaryElement()
411          */
412         public IJavaElement getPrimaryElement() {
413                 return getPrimaryElement(true);
414         }
415         /*
416          * Returns the primary element. If checkOwner, and the cu owner is primary,
417          * return this element.
418          */
419         public IJavaElement getPrimaryElement(boolean checkOwner) {
420                 return this;
421         }
422         /**
423          * Returns the element that is located at the given source position in this
424          * element. This is a helper method for
425          * <code>ICompilationUnit#getElementAt</code>, and only works on
426          * compilation units and types. The position given is known to be within
427          * this element's source range already, and if no finer grained element is
428          * found at the position, this element is returned.
429          */
430         protected IJavaElement getSourceElementAt(int position)
431                         throws JavaModelException {
432                 if (this instanceof ISourceReference) {
433                         IJavaElement[] children = getChildren();
434                         int i;
435                         for (i = 0; i < children.length; i++) {
436                                 IJavaElement aChild = children[i];
437                                 if (aChild instanceof SourceRefElement) {
438                                         SourceRefElement child = (SourceRefElement) children[i];
439                                         ISourceRange range = child.getSourceRange();
440                                         if (position < range.getOffset() + range.getLength()
441                                                         && position >= range.getOffset()) {
442                                                 if (child instanceof IParent) {
443                                                         return child.getSourceElementAt(position);
444                                                 } else {
445                                                         return child;
446                                                 }
447                                         }
448                                 }
449                         }
450                 } else {
451                         // should not happen
452                         Assert.isTrue(false);
453                 }
454                 return this;
455         }
456         /**
457          * Returns the SourceMapper facility for this element, or <code>null</code>
458          * if this element does not have a SourceMapper.
459          */
460         //      public SourceMapper getSourceMapper() {
461         //              return ((JavaElement)getParent()).getSourceMapper();
462         //      }
463         /*
464          * (non-Javadoc)
465          * 
466          * @see org.eclipse.jdt.core.IJavaElement#getSchedulingRule()
467          */
468         public ISchedulingRule getSchedulingRule() {
469                 IResource resource = getResource();
470                 if (resource == null) {
471                         class NoResourceSchedulingRule implements ISchedulingRule {
472                                 public IPath path;
473                                 public NoResourceSchedulingRule(IPath path) {
474                                         this.path = path;
475                                 }
476                                 public boolean contains(ISchedulingRule rule) {
477                                         if (rule instanceof NoResourceSchedulingRule) {
478                                                 return this.path
479                                                                 .isPrefixOf(((NoResourceSchedulingRule) rule).path);
480                                         } else {
481                                                 return false;
482                                         }
483                                 }
484                                 public boolean isConflicting(ISchedulingRule rule) {
485                                         if (rule instanceof NoResourceSchedulingRule) {
486                                                 IPath otherPath = ((NoResourceSchedulingRule) rule).path;
487                                                 return this.path.isPrefixOf(otherPath)
488                                                                 || otherPath.isPrefixOf(this.path);
489                                         } else {
490                                                 return false;
491                                         }
492                                 }
493                         }
494                         return new NoResourceSchedulingRule(getPath());
495                 } else {
496                         return resource;
497                 }
498         }
499         /**
500          * @see IParent
501          */
502         public boolean hasChildren() throws JavaModelException {
503                 // if I am not open, return true to avoid opening (case of a Java
504                 // project, a compilation unit or a class file).
505                 // also see https://bugs.eclipse.org/bugs/show_bug.cgi?id=52474
506                 Object elementInfo = JavaModelManager.getJavaModelManager().getInfo(
507                                 this);
508                 if (elementInfo instanceof JavaElementInfo) {
509                         return ((JavaElementInfo) elementInfo).getChildren().length > 0;
510                 } else {
511                         return true;
512                 }
513         }
514
515         /**
516          * Returns the hash code for this Java element. By default, the hash code
517          * for an element is a combination of its name and parent's hash code.
518          * Elements with other requirements must override this method.
519          */
520         public int hashCode() {
521                 if (this.parent == null)
522                         return super.hashCode();
523                 return Util.combineHashCodes(this.name.hashCode(), this.parent
524                                 .hashCode());
525         }
526
527         /**
528          * Returns true if this element is an ancestor of the given element,
529          * otherwise false.
530          */
531         protected boolean isAncestorOf(IJavaElement e) {
532                 IJavaElement parent = e.getParent();
533                 while (parent != null && !parent.equals(this)) {
534                         parent = parent.getParent();
535                 }
536                 return parent != null;
537         }
538
539         /**
540          * @see IJavaElement
541          */
542         public boolean isReadOnly() {
543                 return false;
544         }
545         /**
546          * @see IJavaElement
547          */
548         public boolean isStructureKnown() throws JavaModelException {
549                 return ((JavaElementInfo) getElementInfo()).isStructureKnown();
550         }
551         /**
552          * Creates and returns and not present exception for this element.
553          */
554         protected JavaModelException newNotPresentException() {
555                 return new JavaModelException(new JavaModelStatus(
556                                 IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
557         }
558         /**
559          * Opens this element and all parents that are not already open.
560          * 
561          * @exception JavaModelException
562          *                this element is not present or accessible
563          */
564         //      protected void openHierarchy() throws JavaModelException {
565         //              if (this instanceof IOpenable) {
566         //                      ((Openable) this).openWhenClosed(null);
567         //              } else {
568         //                      Openable openableParent = (Openable)getOpenableParent();
569         //                      if (openableParent != null) {
570         //                              JavaElementInfo openableParentInfo = (JavaElementInfo)
571         // JavaModelManager.getJavaModelManager().getInfo((IJavaElement)
572         // openableParent);
573         //                              if (openableParentInfo == null) {
574         //                                      openableParent.openWhenClosed(null);
575         //                              } else {
576         //                                      throw newNotPresentException();
577         //                              }
578         //                      }
579         //              }
580         //      }
581         /**
582          * This element has just been opened. Do any necessary setup.
583          */
584         protected void opening(Object info) {
585         }
586         /*
587          * Opens an <code> Openable </code> that is known to be closed (no check for
588          * <code> isOpen() </code> ). Returns the created element info.
589          */
590         protected Object openWhenClosed(Object info, IProgressMonitor monitor)
591                         throws JavaModelException {
592                 JavaModelManager manager = JavaModelManager.getJavaModelManager();
593                 boolean hadTemporaryCache = manager.hasTemporaryCache();
594                 try {
595                         HashMap newElements = manager.getTemporaryCache();
596                         generateInfos(info, newElements, monitor);
597                         if (info == null) {
598                                 info = newElements.get(this);
599                         }
600                         if (info == null) { // a source ref element could not be opened
601                                 // close any buffer that was opened for the openable parent
602                                 Iterator iterator = newElements.keySet().iterator();
603                                 while (iterator.hasNext()) {
604                                         IJavaElement element = (IJavaElement) iterator.next();
605                                         if (element instanceof Openable) {
606                                                 ((Openable) element).closeBuffer();
607                                         }
608                                 }
609                                 throw newNotPresentException();
610                         }
611                         if (!hadTemporaryCache) {
612                                 manager.putInfos(this, newElements);
613                         }
614                 } finally {
615                         if (!hadTemporaryCache) {
616                                 manager.resetTemporaryCache();
617                         }
618                 }
619                 return info;
620         }
621         /**
622          */
623         public String readableName() {
624                 return this.getElementName();
625         }
626         /**
627          * Removes all cached info from the Java Model, including all children, but
628          * does not close this element.
629          */
630         //      protected void removeInfo() {
631         //              Object info = JavaModelManager.getJavaModelManager().peekAtInfo(this);
632         //              if (info != null) {
633         //                      if (this instanceof IParent) {
634         //                              IJavaElement[] children = ((JavaElementInfo)info).getChildren();
635         //                              for (int i = 0, size = children.length; i < size; ++i) {
636         //                                      JavaElement child = (JavaElement) children[i];
637         //                                      child.removeInfo();
638         //                              }
639         //                      }
640         //                      JavaModelManager.getJavaModelManager().removeInfo(this);
641         //              }
642         //      }
643         //      /**
644         //       * Returns a copy of this element rooted at the given project.
645         //       */
646         //      public abstract IJavaElement rootedAt(IJavaProject project);
647         /**
648          * Runs a Java Model Operation
649          */
650         public static void runOperation(JavaModelOperation operation,
651                         IProgressMonitor monitor) throws JavaModelException {
652                 try {
653                         if (operation.isReadOnly()
654                                         || ResourcesPlugin.getWorkspace().isTreeLocked()) {
655                                 operation.run(monitor);
656                         } else {
657                                 // use IWorkspace.run(...) to ensure that a build will be done
658                                 // in autobuild mode
659                                 ResourcesPlugin.getWorkspace().run(operation, monitor);
660                         }
661                 } catch (CoreException ce) {
662                         if (ce instanceof JavaModelException) {
663                                 throw (JavaModelException) ce;
664                         } else {
665                                 if (ce.getStatus().getCode() == IResourceStatus.OPERATION_FAILED) {
666                                         Throwable e = ce.getStatus().getException();
667                                         if (e instanceof JavaModelException) {
668                                                 throw (JavaModelException) e;
669                                         }
670                                 }
671                                 throw new JavaModelException(ce);
672                         }
673                 }
674         }
675         /**
676          * Sets the occurrence count of the handle.
677          */
678         protected void setOccurrenceCount(int count) {
679                 occurrenceCount = count;
680         }
681         protected String tabString(int tab) {
682                 StringBuffer buffer = new StringBuffer();
683                 for (int i = tab; i > 0; i--)
684                         buffer.append("  "); //$NON-NLS-1$
685                 return buffer.toString();
686         }
687         /**
688          * Debugging purposes
689          */
690         public String toDebugString() {
691                 StringBuffer buffer = new StringBuffer();
692                 this.toStringInfo(0, buffer, NO_INFO);
693                 return buffer.toString();
694         }
695         /**
696          * Debugging purposes
697          */
698         public String toString() {
699                 StringBuffer buffer = new StringBuffer();
700                 toString(0, buffer);
701                 return buffer.toString();
702         }
703         /**
704          *  Debugging purposes
705          */
706         protected void toStringName(StringBuffer buffer) {
707                 buffer.append(getElementName());
708                 if (this.occurrenceCount > 1) {
709                         buffer.append("#"); //$NON-NLS-1$
710                         buffer.append(this.occurrenceCount);
711                 }
712         }
713         /**
714          * Debugging purposes
715          */
716         protected void toString(int tab, StringBuffer buffer) {
717                 //      Object info = this.toStringInfo(tab, buffer);
718                 Object info = null;
719                 if (tab == 0) {
720                         this.toStringAncestors(buffer);
721                 }
722                 this.toStringChildren(tab, buffer, info);
723         }
724         /**
725          * Debugging purposes
726          */
727         public String toStringWithAncestors() {
728                 StringBuffer buffer = new StringBuffer();
729                 this.toStringInfo(0, buffer, NO_INFO);
730                 this.toStringAncestors(buffer);
731                 return buffer.toString();
732         }
733         /**
734          * Debugging purposes
735          */
736         protected void toStringAncestors(StringBuffer buffer) {
737                 JavaElement parent = (JavaElement) this.getParent();
738                 if (parent != null && parent.getParent() != null) {
739                         buffer.append(" [in "); //$NON-NLS-1$
740                         parent.toStringInfo(0, buffer, NO_INFO);
741                         parent.toStringAncestors(buffer);
742                         buffer.append("]"); //$NON-NLS-1$
743                 }
744         }
745         /**
746          * Debugging purposes
747          */
748         protected void toStringChildren(int tab, StringBuffer buffer, Object info) {
749                 if (info == null || !(info instanceof JavaElementInfo))
750                         return;
751                 IJavaElement[] children = ((JavaElementInfo) info).getChildren();
752                 for (int i = 0; i < children.length; i++) {
753                         buffer.append("\n"); //$NON-NLS-1$
754                         ((JavaElement) children[i]).toString(tab + 1, buffer);
755                 }
756         }
757         /**
758          * Debugging purposes
759          */
760         //      public Object toStringInfo(int tab, StringBuffer buffer) {
761         //              Object info = JavaModelManager.getJavaModelManager().peekAtInfo(this);
762         //              this.toStringInfo(tab, buffer, info);
763         //              return info;
764         //      }
765         /**
766          * Debugging purposes
767          */
768         protected void toStringInfo(int tab, StringBuffer buffer, Object info) {
769                 buffer.append(this.tabString(tab));
770                 buffer.append(getElementName());
771                 if (info == null) {
772                         buffer.append(" (not open)"); //$NON-NLS-1$
773                 }
774         }
775 }