KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > core > dom > ASTNode


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

11
12 package org.eclipse.jdt.core.dom;
13
14 import java.util.AbstractList JavaDoc;
15 import java.util.ArrayList JavaDoc;
16 import java.util.Collections JavaDoc;
17 import java.util.HashMap JavaDoc;
18 import java.util.Iterator JavaDoc;
19 import java.util.List JavaDoc;
20 import java.util.Map JavaDoc;
21
22 /**
23  * Abstract superclass of all Abstract Syntax Tree (AST) node types.
24  * <p>
25  * An AST node represents a Java source code construct, such
26  * as a name, type, expression, statement, or declaration.
27  * </p>
28  * <p>
29  * Each AST node belongs to a unique AST instance, called the owning AST.
30  * The children of an AST node always have the same owner as their parent node.
31  * If a node from one AST is to be added to a different AST, the subtree must
32  * be cloned first to ensure that the added nodes have the correct owning AST.
33  * </p>
34  * <p>
35  * When an AST node is part of an AST, it has a unique parent node.
36  * Clients can navigate upwards, from child to parent, as well as downwards,
37  * from parent to child. Newly created nodes are unparented. When an
38  * unparented node is set as a child of a node (using a
39  * <code>set<i>CHILD</i></code> method), its parent link is set automatically
40  * and the parent link of the former child is set to <code>null</code>.
41  * For nodes with properties that include a list of children (for example,
42  * <code>Block</code> whose <code>statements</code> property is a list
43  * of statements), adding or removing an element to/for the list property
44  * automatically updates the parent links. These lists support the
45  * <code>List.set</code> method; however, the constraint that the same
46  * node cannot appear more than once means that this method cannot be used
47  * to swap elements without first removing the node.
48  * </p>
49  * <p>
50  * ASTs must not contain cycles. All operations that could create a cycle
51  * detect this possibility and fail.
52  * </p>
53  * <p>
54  * ASTs do not contain "holes" (missing subtrees). If a node is required to
55  * have a certain property, a syntactically plausible initial value is
56  * always supplied.
57  * </p>
58  * <p>
59  * The hierarchy of AST node types has some convenient groupings marked
60  * by abstract superclasses:
61  * <ul>
62  * <li>expressions - <code>Expression</code></li>
63  * <li>names - <code>Name</code> (a sub-kind of expression)</li>
64  * <li>statements - <code>Statement</code></li>
65  * <li>types - <code>Type</code></li>
66  * <li>type body declarations - <code>BodyDeclaration</code></li>
67  * </ul>
68  * </p>
69  * <p>
70  * Abstract syntax trees may be hand constructed by clients, using the
71  * <code>new<i>TYPE</i></code> factory methods (see <code>AST</code>) to
72  * create new nodes, and the various <code>set<i>CHILD</i></code> methods
73  * to connect them together.
74  * </p>
75  * <p>
76  * The class {@link ASTParser} parses a string
77  * containing a Java source code and returns an abstract syntax tree
78  * for it. The resulting nodes carry source ranges relating the node back to
79  * the original source characters. The source range covers the construct
80  * as a whole.
81  * </p>
82  * <p>
83  * Each AST node carries bit flags, which may convey additional information about
84  * the node. For instance, the parser uses a flag to indicate a syntax error.
85  * Newly created nodes have no flags set.
86  * </p>
87  * <p>
88  * Each AST node is capable of carrying an open-ended collection of
89  * client-defined properties. Newly created nodes have none.
90  * <code>getProperty</code> and <code>setProperty</code> are used to access
91  * these properties.
92  * </p>
93  * <p>
94  * AST nodes are thread-safe for readers provided there are no active writers.
95  * If one thread is modifying an AST, including creating new nodes or cloning
96  * existing ones, it is <b>not</b> safe for another thread to read, visit,
97  * write, create, or clone <em>any</em> of the nodes on the same AST.
98  * When synchronization is required, consider using the common AST
99  * object that owns the node; that is, use
100  * <code>synchronize (node.getAST()) {...}</code>.
101  * </p>
102  * <p>
103  * ASTs also support the visitor pattern; see the class <code>ASTVisitor</code>
104  * for details.
105  * </p>
106  * <p>
107  * Compilation units created by <code>ASTParser</code> from a
108  * source document can be serialized after arbitrary modifications
109  * with minimal loss of original formatting. See
110  * {@link CompilationUnit#recordModifications()} for details.
111  * See also {@link org.eclipse.jdt.core.dom.rewrite.ASTRewrite} for
112  * an alternative way to describe and serialize changes to a
113  * read-only AST.
114  * </p>
115  * This class is not intended to be subclassed by clients.
116  *
117  * @see ASTParser
118  * @see ASTVisitor
119  * @since 2.0
120  */

121 public abstract class ASTNode {
122     /*
123      * INSTRUCTIONS FOR ADDING NEW CONCRETE AST NODE TYPES
124      *
125      * There are several things that need to be changed when a
126      * new concrete AST node type (call it "FooBar"):
127      *
128      * 1. Create the FooBar AST node type class.
129      * The most effective way to do this is to copy a similar
130      * existing concrete node class to get a template that
131      * includes all the framework methods that must be implemented.
132      *
133      * 2. Add node type constant ASTNode.FOO_BAR.
134      * Node constants are numbered consecutively. Add the
135      * constant after the existing ones.
136      *
137      * 3. Add entry to ASTNode.nodeClassForType(int).
138      *
139      * 4. Add AST.newFooBar() factory method.
140      *
141      * 5. Add ASTVisitor.visit(FooBar) and endVisit(FooBar) methods.
142      *
143      * 6. Add ASTMatcher.match(FooBar,Object) method.
144      *
145      * 7. Ensure that SimpleName.isDeclaration() covers FooBar
146      * nodes if required.
147      *
148      * 8. Add NaiveASTFlattener.visit(FooBar) method to illustrate
149      * how these nodes should be serialized.
150      *
151      * 9. Update the AST test suites.
152      *
153      * The next steps are to update AST.parse* to start generating
154      * the new type of nodes, and ASTRewrite to serialize them back out.
155      */

156     
157     /**
158      * Node type constant indicating a node of type
159      * <code>AnonymousClassDeclaration</code>.
160      * @see AnonymousClassDeclaration
161      */

162     public static final int ANONYMOUS_CLASS_DECLARATION = 1;
163
164     /**
165      * Node type constant indicating a node of type
166      * <code>ArrayAccess</code>.
167      * @see ArrayAccess
168      */

169     public static final int ARRAY_ACCESS = 2;
170
171     /**
172      * Node type constant indicating a node of type
173      * <code>ArrayCreation</code>.
174      * @see ArrayCreation
175      */

176     public static final int ARRAY_CREATION = 3;
177
178     /**
179      * Node type constant indicating a node of type
180      * <code>ArrayInitializer</code>.
181      * @see ArrayInitializer
182      */

183     public static final int ARRAY_INITIALIZER = 4;
184
185     /**
186      * Node type constant indicating a node of type
187      * <code>ArrayType</code>.
188      * @see ArrayType
189      */

190     public static final int ARRAY_TYPE = 5;
191
192     /**
193      * Node type constant indicating a node of type
194      * <code>AssertStatement</code>.
195      * @see AssertStatement
196      */

197     public static final int ASSERT_STATEMENT = 6;
198
199     /**
200      * Node type constant indicating a node of type
201      * <code>Assignment</code>.
202      * @see Assignment
203      */

204     public static final int ASSIGNMENT = 7;
205
206     /**
207      * Node type constant indicating a node of type
208      * <code>Block</code>.
209      * @see Block
210      */

211     public static final int BLOCK = 8;
212
213     /**
214      * Node type constant indicating a node of type
215      * <code>BooleanLiteral</code>.
216      * @see BooleanLiteral
217      */

218     public static final int BOOLEAN_LITERAL = 9;
219
220     /**
221      * Node type constant indicating a node of type
222      * <code>BreakStatement</code>.
223      * @see BreakStatement
224      */

225     public static final int BREAK_STATEMENT = 10;
226
227     /**
228      * Node type constant indicating a node of type
229      * <code>CastExpression</code>.
230      * @see CastExpression
231      */

232     public static final int CAST_EXPRESSION = 11;
233
234     /**
235      * Node type constant indicating a node of type
236      * <code>CatchClause</code>.
237      * @see CatchClause
238      */

239     public static final int CATCH_CLAUSE = 12;
240
241     /**
242      * Node type constant indicating a node of type
243      * <code>CharacterLiteral</code>.
244      * @see CharacterLiteral
245      */

246     public static final int CHARACTER_LITERAL = 13;
247
248     /**
249      * Node type constant indicating a node of type
250      * <code>ClassInstanceCreation</code>.
251      * @see ClassInstanceCreation
252      */

253     public static final int CLASS_INSTANCE_CREATION = 14;
254
255     /**
256      * Node type constant indicating a node of type
257      * <code>CompilationUnit</code>.
258      * @see CompilationUnit
259      */

260     public static final int COMPILATION_UNIT = 15;
261
262     /**
263      * Node type constant indicating a node of type
264      * <code>ConditionalExpression</code>.
265      * @see ConditionalExpression
266      */

267     public static final int CONDITIONAL_EXPRESSION = 16;
268
269     /**
270      * Node type constant indicating a node of type
271      * <code>ConstructorInvocation</code>.
272      * @see ConstructorInvocation
273      */

274     public static final int CONSTRUCTOR_INVOCATION = 17;
275
276     /**
277      * Node type constant indicating a node of type
278      * <code>ContinueStatement</code>.
279      * @see ContinueStatement
280      */

281     public static final int CONTINUE_STATEMENT = 18;
282
283     /**
284      * Node type constant indicating a node of type
285      * <code>DoStatement</code>.
286      * @see DoStatement
287      */

288     public static final int DO_STATEMENT = 19;
289
290     /**
291      * Node type constant indicating a node of type
292      * <code>EmptyStatement</code>.
293      * @see EmptyStatement
294      */

295     public static final int EMPTY_STATEMENT = 20;
296
297     /**
298      * Node type constant indicating a node of type
299      * <code>ExpressionStatement</code>.
300      * @see ExpressionStatement
301      */

302     public static final int EXPRESSION_STATEMENT = 21;
303
304     /**
305      * Node type constant indicating a node of type
306      * <code>FieldAccess</code>.
307      * @see FieldAccess
308      */

309     public static final int FIELD_ACCESS = 22;
310
311     /**
312      * Node type constant indicating a node of type
313      * <code>FieldDeclaration</code>.
314      * @see FieldDeclaration
315      */

316     public static final int FIELD_DECLARATION = 23;
317
318     /**
319      * Node type constant indicating a node of type
320      * <code>ForStatement</code>.
321      * @see ForStatement
322      */

323     public static final int FOR_STATEMENT = 24;
324
325     /**
326      * Node type constant indicating a node of type
327      * <code>IfStatement</code>.
328      * @see IfStatement
329      */

330     public static final int IF_STATEMENT = 25;
331
332     /**
333      * Node type constant indicating a node of type
334      * <code>ImportDeclaration</code>.
335      * @see ImportDeclaration
336      */

337     public static final int IMPORT_DECLARATION = 26;
338
339     /**
340      * Node type constant indicating a node of type
341      * <code>InfixExpression</code>.
342      * @see InfixExpression
343      */

344     public static final int INFIX_EXPRESSION = 27;
345
346     /**
347      * Node type constant indicating a node of type
348      * <code>Initializer</code>.
349      * @see Initializer
350      */

351     public static final int INITIALIZER = 28;
352
353     /**
354      * Node type constant indicating a node of type
355      * <code>Javadoc</code>.
356      * @see Javadoc
357      */

358     public static final int JAVADOC = 29;
359
360     /**
361      * Node type constant indicating a node of type
362      * <code>LabeledStatement</code>.
363      * @see LabeledStatement
364      */

365     public static final int LABELED_STATEMENT = 30;
366
367     /**
368      * Node type constant indicating a node of type
369      * <code>MethodDeclaration</code>.
370      * @see MethodDeclaration
371      */

372     public static final int METHOD_DECLARATION = 31;
373
374     /**
375      * Node type constant indicating a node of type
376      * <code>MethodInvocation</code>.
377      * @see MethodInvocation
378      */

379     public static final int METHOD_INVOCATION = 32;
380
381     /**
382      * Node type constant indicating a node of type
383      * <code>NullLiteral</code>.
384      * @see NullLiteral
385      */

386     public static final int NULL_LITERAL = 33;
387
388     /**
389      * Node type constant indicating a node of type
390      * <code>NumberLiteral</code>.
391      * @see NumberLiteral
392      */

393     public static final int NUMBER_LITERAL = 34;
394
395     /**
396      * Node type constant indicating a node of type
397      * <code>PackageDeclaration</code>.
398      * @see PackageDeclaration
399      */

400     public static final int PACKAGE_DECLARATION = 35;
401
402     /**
403      * Node type constant indicating a node of type
404      * <code>ParenthesizedExpression</code>.
405      * @see ParenthesizedExpression
406      */

407     public static final int PARENTHESIZED_EXPRESSION = 36;
408
409     /**
410      * Node type constant indicating a node of type
411      * <code>PostfixExpression</code>.
412      * @see PostfixExpression
413      */

414     public static final int POSTFIX_EXPRESSION = 37;
415
416     /**
417      * Node type constant indicating a node of type
418      * <code>PrefixExpression</code>.
419      * @see PrefixExpression
420      */

421     public static final int PREFIX_EXPRESSION = 38;
422
423     /**
424      * Node type constant indicating a node of type
425      * <code>PrimitiveType</code>.
426      * @see PrimitiveType
427      */

428     public static final int PRIMITIVE_TYPE = 39;
429
430     /**
431      * Node type constant indicating a node of type
432      * <code>QualifiedName</code>.
433      * @see QualifiedName
434      */

435     public static final int QUALIFIED_NAME = 40;
436
437     /**
438      * Node type constant indicating a node of type
439      * <code>ReturnStatement</code>.
440      * @see ReturnStatement
441      */

442     public static final int RETURN_STATEMENT = 41;
443
444     /**
445      * Node type constant indicating a node of type
446      * <code>SimpleName</code>.
447      * @see SimpleName
448      */

449     public static final int SIMPLE_NAME = 42;
450
451     /**
452      * Node type constant indicating a node of type
453      * <code>SimpleType</code>.
454      * @see SimpleType
455      */

456     public static final int SIMPLE_TYPE = 43;
457
458     /**
459      * Node type constant indicating a node of type
460      * <code>SingleVariableDeclaration</code>.
461      * @see SingleVariableDeclaration
462      */

463     public static final int SINGLE_VARIABLE_DECLARATION = 44;
464
465     /**
466      * Node type constant indicating a node of type
467      * <code>StringLiteral</code>.
468      * @see StringLiteral
469      */

470     public static final int STRING_LITERAL = 45;
471
472     /**
473      * Node type constant indicating a node of type
474      * <code>SuperConstructorInvocation</code>.
475      * @see SuperConstructorInvocation
476      */

477     public static final int SUPER_CONSTRUCTOR_INVOCATION = 46;
478
479     /**
480      * Node type constant indicating a node of type
481      * <code>SuperFieldAccess</code>.
482      * @see SuperFieldAccess
483      */

484     public static final int SUPER_FIELD_ACCESS = 47;
485
486     /**
487      * Node type constant indicating a node of type
488      * <code>SuperMethodInvocation</code>.
489      * @see SuperMethodInvocation
490      */

491     public static final int SUPER_METHOD_INVOCATION = 48;
492
493     /**
494      * Node type constant indicating a node of type
495      * <code>SwitchCase</code>.
496      * @see SwitchCase
497      */

498     public static final int SWITCH_CASE = 49;
499
500     /**
501      * Node type constant indicating a node of type
502      * <code>SwitchStatement</code>.
503      * @see SwitchStatement
504      */

505     public static final int SWITCH_STATEMENT = 50;
506
507     /**
508      * Node type constant indicating a node of type
509      * <code>SynchronizedStatement</code>.
510      * @see SynchronizedStatement
511      */

512     public static final int SYNCHRONIZED_STATEMENT = 51;
513
514     /**
515      * Node type constant indicating a node of type
516      * <code>ThisExpression</code>.
517      * @see ThisExpression
518      */

519     public static final int THIS_EXPRESSION = 52;
520
521     /**
522      * Node type constant indicating a node of type
523      * <code>ThrowStatement</code>.
524      * @see ThrowStatement
525      */

526     public static final int THROW_STATEMENT = 53;
527
528     /**
529      * Node type constant indicating a node of type
530      * <code>TryStatement</code>.
531      * @see TryStatement
532      */

533     public static final int TRY_STATEMENT = 54;
534
535     /**
536      * Node type constant indicating a node of type
537      * <code>TypeDeclaration</code>.
538      * @see TypeDeclaration
539      */

540     public static final int TYPE_DECLARATION = 55;
541
542     /**
543      * Node type constant indicating a node of type
544      * <code>TypeDeclarationStatement</code>.
545      * @see TypeDeclarationStatement
546      */

547     public static final int TYPE_DECLARATION_STATEMENT = 56;
548
549     /**
550      * Node type constant indicating a node of type
551      * <code>TypeLiteral</code>.
552      * @see TypeLiteral
553      */

554     public static final int TYPE_LITERAL = 57;
555
556     /**
557      * Node type constant indicating a node of type
558      * <code>VariableDeclarationExpression</code>.
559      * @see VariableDeclarationExpression
560      */

561     public static final int VARIABLE_DECLARATION_EXPRESSION = 58;
562
563     /**
564      * Node type constant indicating a node of type
565      * <code>VariableDeclarationFragment</code>.
566      * @see VariableDeclarationFragment
567      */

568     public static final int VARIABLE_DECLARATION_FRAGMENT = 59;
569
570     /**
571      * Node type constant indicating a node of type
572      * <code>VariableDeclarationStatement</code>.
573      * @see VariableDeclarationStatement
574      */

575     public static final int VARIABLE_DECLARATION_STATEMENT = 60;
576
577     /**
578      * Node type constant indicating a node of type
579      * <code>WhileStatement</code>.
580      * @see WhileStatement
581      */

582     public static final int WHILE_STATEMENT = 61;
583
584     /**
585      * Node type constant indicating a node of type
586      * <code>InstanceofExpression</code>.
587      * @see InstanceofExpression
588      */

589     public static final int INSTANCEOF_EXPRESSION = 62;
590
591     /**
592      * Node type constant indicating a node of type
593      * <code>LineComment</code>.
594      * @see LineComment
595      * @since 3.0
596      */

597     public static final int LINE_COMMENT = 63;
598
599     /**
600      * Node type constant indicating a node of type
601      * <code>BlockComment</code>.
602      * @see BlockComment
603      * @since 3.0
604      */

605     public static final int BLOCK_COMMENT = 64;
606
607     /**
608      * Node type constant indicating a node of type
609      * <code>TagElement</code>.
610      * @see TagElement
611      * @since 3.0
612      */

613     public static final int TAG_ELEMENT = 65;
614
615     /**
616      * Node type constant indicating a node of type
617      * <code>TextElement</code>.
618      * @see TextElement
619      * @since 3.0
620      */

621     public static final int TEXT_ELEMENT = 66;
622
623     /**
624      * Node type constant indicating a node of type
625      * <code>MemberRef</code>.
626      * @see MemberRef
627      * @since 3.0
628      */

629     public static final int MEMBER_REF = 67;
630
631     /**
632      * Node type constant indicating a node of type
633      * <code>MethodRef</code>.
634      * @see MethodRef
635      * @since 3.0
636      */

637     public static final int METHOD_REF = 68;
638
639     /**
640      * Node type constant indicating a node of type
641      * <code>MethodRefParameter</code>.
642      * @see MethodRefParameter
643      * @since 3.0
644      */

645     public static final int METHOD_REF_PARAMETER = 69;
646
647     /**
648      * Node type constant indicating a node of type
649      * <code>EnhancedForStatement</code>.
650      * @see EnhancedForStatement
651      * @since 3.1
652      */

653     public static final int ENHANCED_FOR_STATEMENT = 70;
654
655     /**
656      * Node type constant indicating a node of type
657      * <code>EnumDeclaration</code>.
658      * @see EnumDeclaration
659      * @since 3.1
660      */

661     public static final int ENUM_DECLARATION = 71;
662     
663     /**
664      * Node type constant indicating a node of type
665      * <code>EnumConstantDeclaration</code>.
666      * @see EnumConstantDeclaration
667      * @since 3.1
668      */

669     public static final int ENUM_CONSTANT_DECLARATION = 72;
670     
671     /**
672      * Node type constant indicating a node of type
673      * <code>TypeParameter</code>.
674      * @see TypeParameter
675      * @since 3.1
676      */

677     public static final int TYPE_PARAMETER = 73;
678
679     /**
680      * Node type constant indicating a node of type
681      * <code>ParameterizedType</code>.
682      * @see ParameterizedType
683      * @since 3.1
684      */

685     public static final int PARAMETERIZED_TYPE = 74;
686
687     /**
688      * Node type constant indicating a node of type
689      * <code>QualifiedType</code>.
690      * @see QualifiedType
691      * @since 3.1
692      */

693     public static final int QUALIFIED_TYPE = 75;
694     
695     /**
696      * Node type constant indicating a node of type
697      * <code>WildcardType</code>.
698      * @see WildcardType
699      * @since 3.1
700      */

701     public static final int WILDCARD_TYPE = 76;
702     
703     /**
704      * Node type constant indicating a node of type
705      * <code>NormalAnnotation</code>.
706      * @see NormalAnnotation
707      * @since 3.1
708      */

709     public static final int NORMAL_ANNOTATION = 77;
710     
711     /**
712      * Node type constant indicating a node of type
713      * <code>MarkerAnnotation</code>.
714      * @see MarkerAnnotation
715      * @since 3.1
716      */

717     public static final int MARKER_ANNOTATION = 78;
718     
719     /**
720      * Node type constant indicating a node of type
721      * <code>SingleMemberAnnotation</code>.
722      * @see SingleMemberAnnotation
723      * @since 3.1
724      */

725     public static final int SINGLE_MEMBER_ANNOTATION = 79;
726     
727     /**
728      * Node type constant indicating a node of type
729      * <code>MemberValuePair</code>.
730      * @see MemberValuePair
731      * @since 3.1
732      */

733     public static final int MEMBER_VALUE_PAIR = 80;
734     
735     /**
736      * Node type constant indicating a node of type
737      * <code>AnnotationTypeDeclaration</code>.
738      * @see AnnotationTypeDeclaration
739      * @since 3.1
740      */

741     public static final int ANNOTATION_TYPE_DECLARATION = 81;
742     
743     /**
744      * Node type constant indicating a node of type
745      * <code>AnnotationTypeMemberDeclaration</code>.
746      * @see AnnotationTypeMemberDeclaration
747      * @since 3.1
748      */

749     public static final int ANNOTATION_TYPE_MEMBER_DECLARATION = 82;
750     
751     /**
752      * Node type constant indicating a node of type
753      * <code>Modifier</code>.
754      * @see Modifier
755      * @since 3.1
756      */

757     public static final int MODIFIER = 83;
758     
759     /**
760      * Returns the node class for the corresponding node type.
761      *
762      * @param nodeType AST node type
763      * @return the corresponding <code>ASTNode</code> subclass
764      * @exception IllegalArgumentException if <code>nodeType</code> is
765      * not a legal AST node type
766      * @see #getNodeType()
767      * @since 3.0
768      */

769     public static Class JavaDoc nodeClassForType(int nodeType) {
770         switch (nodeType) {
771             case ANNOTATION_TYPE_DECLARATION :
772                 return AnnotationTypeDeclaration.class;
773             case ANNOTATION_TYPE_MEMBER_DECLARATION :
774                 return AnnotationTypeMemberDeclaration.class;
775             case ANONYMOUS_CLASS_DECLARATION :
776                 return AnonymousClassDeclaration.class;
777             case ARRAY_ACCESS :
778                 return ArrayAccess.class;
779             case ARRAY_CREATION :
780                 return ArrayCreation.class;
781             case ARRAY_INITIALIZER :
782                 return ArrayInitializer.class;
783             case ARRAY_TYPE :
784                 return ArrayType.class;
785             case ASSERT_STATEMENT :
786                 return AssertStatement.class;
787             case ASSIGNMENT :
788                 return Assignment.class;
789             case BLOCK :
790                 return Block.class;
791             case BLOCK_COMMENT :
792                 return BlockComment.class;
793             case BOOLEAN_LITERAL :
794                 return BooleanLiteral.class;
795             case BREAK_STATEMENT :
796                 return BreakStatement.class;
797             case CAST_EXPRESSION :
798                 return CastExpression.class;
799             case CATCH_CLAUSE :
800                 return CatchClause.class;
801             case CHARACTER_LITERAL :
802                 return CharacterLiteral.class;
803             case CLASS_INSTANCE_CREATION :
804                 return ClassInstanceCreation.class;
805             case COMPILATION_UNIT :
806                 return CompilationUnit.class;
807             case CONDITIONAL_EXPRESSION :
808                 return ConditionalExpression.class;
809             case CONSTRUCTOR_INVOCATION :
810                 return ConstructorInvocation.class;
811             case CONTINUE_STATEMENT :
812                 return ContinueStatement.class;
813             case DO_STATEMENT :
814                 return DoStatement.class;
815             case EMPTY_STATEMENT :
816                 return EmptyStatement.class;
817             case ENHANCED_FOR_STATEMENT :
818                 return EnhancedForStatement.class;
819             case ENUM_CONSTANT_DECLARATION :
820                 return EnumConstantDeclaration.class;
821             case ENUM_DECLARATION :
822                 return EnumDeclaration.class;
823             case EXPRESSION_STATEMENT :
824                 return ExpressionStatement.class;
825             case FIELD_ACCESS :
826                 return FieldAccess.class;
827             case FIELD_DECLARATION :
828                 return FieldDeclaration.class;
829             case FOR_STATEMENT :
830                 return ForStatement.class;
831             case IF_STATEMENT :
832                 return IfStatement.class;
833             case IMPORT_DECLARATION :
834                 return ImportDeclaration.class;
835             case INFIX_EXPRESSION :
836                 return InfixExpression.class;
837             case INITIALIZER :
838                 return Initializer.class;
839             case INSTANCEOF_EXPRESSION :
840                 return InstanceofExpression.class;
841             case JAVADOC :
842                 return Javadoc.class;
843             case LABELED_STATEMENT :
844                 return LabeledStatement.class;
845             case LINE_COMMENT :
846                 return LineComment.class;
847             case MARKER_ANNOTATION :
848                 return MarkerAnnotation.class;
849             case MEMBER_REF :
850                 return MemberRef.class;
851             case MEMBER_VALUE_PAIR :
852                 return MemberValuePair.class;
853             case METHOD_DECLARATION :
854                 return MethodDeclaration.class;
855             case METHOD_INVOCATION :
856                 return MethodInvocation.class;
857             case METHOD_REF :
858                 return MethodRef.class;
859             case METHOD_REF_PARAMETER :
860                 return MethodRefParameter.class;
861             case MODIFIER :
862                 return Modifier.class;
863             case NORMAL_ANNOTATION :
864                 return NormalAnnotation.class;
865             case NULL_LITERAL :
866                 return NullLiteral.class;
867             case NUMBER_LITERAL :
868                 return NumberLiteral.class;
869             case PACKAGE_DECLARATION :
870                 return PackageDeclaration.class;
871             case PARAMETERIZED_TYPE :
872                 return ParameterizedType.class;
873             case PARENTHESIZED_EXPRESSION :
874                 return ParenthesizedExpression.class;
875             case POSTFIX_EXPRESSION :
876                 return PostfixExpression.class;
877             case PREFIX_EXPRESSION :
878                 return PrefixExpression.class;
879             case PRIMITIVE_TYPE :
880                 return PrimitiveType.class;
881             case QUALIFIED_NAME :
882                 return QualifiedName.class;
883             case QUALIFIED_TYPE :
884                 return QualifiedType.class;
885             case RETURN_STATEMENT :
886                 return ReturnStatement.class;
887             case SIMPLE_NAME :
888                 return SimpleName.class;
889             case SIMPLE_TYPE :
890                 return SimpleType.class;
891             case SINGLE_MEMBER_ANNOTATION :
892                 return SingleMemberAnnotation.class;
893             case SINGLE_VARIABLE_DECLARATION :
894                 return SingleVariableDeclaration.class;
895             case STRING_LITERAL :
896                 return StringLiteral.class;
897             case SUPER_CONSTRUCTOR_INVOCATION :
898                 return SuperConstructorInvocation.class;
899             case SUPER_FIELD_ACCESS :
900                 return SuperFieldAccess.class;
901             case SUPER_METHOD_INVOCATION :
902                 return SuperMethodInvocation.class;
903             case SWITCH_CASE:
904                 return SwitchCase.class;
905             case SWITCH_STATEMENT :
906                 return SwitchStatement.class;
907             case SYNCHRONIZED_STATEMENT :
908                 return SynchronizedStatement.class;
909             case TAG_ELEMENT :
910                 return TagElement.class;
911             case TEXT_ELEMENT :
912                 return TextElement.class;
913             case THIS_EXPRESSION :
914                 return ThisExpression.class;
915             case THROW_STATEMENT :
916                 return ThrowStatement.class;
917             case TRY_STATEMENT :
918                 return TryStatement.class;
919             case TYPE_DECLARATION :
920                 return TypeDeclaration.class;
921             case TYPE_DECLARATION_STATEMENT :
922                 return TypeDeclarationStatement.class;
923             case TYPE_LITERAL :
924                 return TypeLiteral.class;
925             case TYPE_PARAMETER :
926                 return TypeParameter.class;
927             case VARIABLE_DECLARATION_EXPRESSION :
928                 return VariableDeclarationExpression.class;
929             case VARIABLE_DECLARATION_FRAGMENT :
930                 return VariableDeclarationFragment.class;
931             case VARIABLE_DECLARATION_STATEMENT :
932                 return VariableDeclarationStatement.class;
933             case WHILE_STATEMENT :
934                 return WhileStatement.class;
935             case WILDCARD_TYPE :
936                 return WildcardType.class;
937         }
938         throw new IllegalArgumentException JavaDoc();
939     }
940     
941     /**
942      * Owning AST.
943      * <p>
944      * N.B. This ia a private field, but declared as package-visible
945      * for more efficient access from inner classes.
946      * </p>
947      */

948     final AST ast;
949     
950     /**
951      * Parent AST node, or <code>null</code> if this node is a root.
952      * Initially <code>null</code>.
953      */

954     private ASTNode parent = null;
955     
956     /**
957      * An unmodifiable empty map (used to implement <code>properties()</code>).
958      */

959     private static final Map JavaDoc UNMODIFIABLE_EMPTY_MAP
960         = Collections.unmodifiableMap(new HashMap JavaDoc(1));
961     
962     /**
963      * Primary field used in representing node properties efficiently.
964      * If <code>null</code>, this node has no properties.
965      * If a <code>String</code>, this is the name of this node's sole property,
966      * and <code>property2</code> contains its value.
967      * If a <code>HashMap</code>, this is the table of property name-value
968      * mappings; <code>property2</code>, if non-null is its unmodifiable
969      * equivalent.
970      * Initially <code>null</code>.
971      *
972      * @see #property2
973      */

974     private Object JavaDoc property1 = null;
975     
976     /**
977      * Auxillary field used in representing node properties efficiently.
978      *
979      * @see #property1
980      */

981     private Object JavaDoc property2 = null;
982     
983     /**
984      * A character index into the original source string,
985      * or <code>-1</code> if no source position information is available
986      * for this node; <code>-1</code> by default.
987      */

988     private int startPosition = -1;
989
990     /**
991      * A character length, or <code>0</code> if no source position
992      * information is recorded for this node; <code>0</code> by default.
993      */

994     private int length = 0;
995     
996     /**
997      * Flag constant (bit mask, value 1) indicating that there is something
998      * not quite right with this AST node.
999      * <p>
1000     * The standard parser (<code>ASTParser</code>) sets this
1001     * flag on a node to indicate a syntax error detected in the vicinity.
1002     * </p>
1003     */

1004    public static final int MALFORMED = 1;
1005
1006    /**
1007     * Flag constant (bit mask, value 2) indicating that this is a node
1008     * that was created by the parser (as opposed to one created by another
1009     * party).
1010     * <p>
1011     * The standard parser (<code>ASTParser</code>) sets this
1012     * flag on the nodes it creates.
1013     * </p>
1014     * @since 3.0
1015     */

1016    public static final int ORIGINAL = 2;
1017
1018    /**
1019     * Flag constant (bit mask, value 4) indicating that this node
1020     * is unmodifiable. When a node is marked unmodifiable, the
1021     * following operations result in a runtime exception:
1022     * <ul>
1023     * <li>Change a simple property of this node.</li>
1024     * <li>Add or remove a child node from this node.</li>
1025     * <li>Parent (or reparent) this node.</li>
1026     * </ul>
1027     * <p>
1028     * The standard parser (<code>ASTParser</code>) does not set
1029     * this flag on the nodes it creates. However, clients may set
1030     * this flag on a node to prevent further modification of the
1031     * its structural properties.
1032     * </p>
1033     * @since 3.0
1034     */

1035    public static final int PROTECT = 4;
1036
1037    /**
1038     * Flag constant (bit mask, value 8) indicating that this node
1039     * or a part of this node is recovered from source that contains
1040     * a syntax error detected in the vicinity.
1041     * <p>
1042     * The standard parser (<code>ASTParser</code>) sets this
1043     * flag on a node to indicate a recovered node.
1044     * </p>
1045     * @since 3.2
1046     */

1047    public static final int RECOVERED = 8;
1048    
1049    /**
1050     * int containing the node type in the top 16 bits and
1051     * flags in the bottom 16 bits; none set by default.
1052     * <p>
1053     * N.B. This is a private field, but declared as package-visible
1054     * for more efficient access from inner classes.
1055     * </p>
1056     *
1057     * @see #MALFORMED
1058     */

1059    int typeAndFlags = 0;
1060        
1061    /**
1062     * Property of parent in which this node is a child, or <code>null</code>
1063     * if this node is a root. Initially <code>null</code>.
1064     *
1065     * @see #getLocationInParent
1066     * @since 3.0
1067     */

1068    private StructuralPropertyDescriptor location = null;
1069    
1070    /** Internal convenience constant indicating that there is definite risk of cycles.
1071     * @since 3.0
1072     */

1073    static final boolean CYCLE_RISK = true;
1074    
1075    /** Internal convenience constant indicating that there is no risk of cycles.
1076     * @since 3.0
1077     */

1078    static final boolean NO_CYCLE_RISK = false;
1079    
1080    /** Internal convenience constant indicating that a structural property is mandatory.
1081     * @since 3.0
1082     */

1083    static final boolean MANDATORY = true;
1084    
1085    /** Internal convenience constant indicating that a structural property is optional.
1086     * @since 3.0
1087     */

1088    static final boolean OPTIONAL = false;
1089    
1090    /**
1091     * A specialized implementation of a list of ASTNodes. The
1092     * implementation is based on an ArrayList.
1093     */

1094    class NodeList extends AbstractList JavaDoc {
1095        
1096        /**
1097         * The underlying list in which the nodes of this list are
1098         * stored (element type: <code>ASTNode</code>).
1099         * <p>
1100         * Be stingy on storage - assume that list will be empty.
1101         * </p>
1102         * <p>
1103         * This field declared default visibility (rather than private)
1104         * so that accesses from <code>NodeList.Cursor</code> do not require
1105         * a synthetic accessor method.
1106         * </p>
1107         */

1108        ArrayList JavaDoc store = new ArrayList JavaDoc(0);
1109        
1110        /**
1111         * The property descriptor for this list.
1112         */

1113        ChildListPropertyDescriptor propertyDescriptor;
1114        
1115        /**
1116         * A cursor for iterating over the elements of the list.
1117         * Does not lose its position if the list is changed during
1118         * the iteration.
1119         */

1120        class Cursor implements Iterator JavaDoc {
1121            /**
1122             * The position of the cursor between elements. If the value
1123             * is N, then the cursor sits between the element at positions
1124             * N-1 and N. Initially just before the first element of the
1125             * list.
1126             */

1127            private int position = 0;
1128            
1129            /* (non-Javadoc)
1130             * Method declared on <code>Iterator</code>.
1131             */

1132            public boolean hasNext() {
1133                return this.position < NodeList.this.store.size();
1134            }
1135            
1136            /* (non-Javadoc)
1137             * Method declared on <code>Iterator</code>.
1138             */

1139            public Object JavaDoc next() {
1140                Object JavaDoc result = NodeList.this.store.get(this.position);
1141                this.position++;
1142                return result;
1143            }
1144            
1145            /* (non-Javadoc)
1146             * Method declared on <code>Iterator</code>.
1147             */

1148            public void remove() {
1149                throw new UnsupportedOperationException JavaDoc();
1150            }
1151            
1152            /**
1153             * Adjusts this cursor to accomodate an add/remove at the given
1154             * index.
1155             *
1156             * @param index the position at which the element was added
1157             * or removed
1158             * @param delta +1 for add, and -1 for remove
1159             */

1160            void update(int index, int delta) {
1161                if (this.position > index) {
1162                    // the cursor has passed the added or removed element
1163
this.position += delta;
1164                }
1165            }
1166        }
1167
1168        /**
1169         * A list of currently active cursors (element type:
1170         * <code>Cursor</code>), or <code>null</code> if there are no
1171         * active cursors.
1172         * <p>
1173         * It is important for storage considerations to maintain the
1174         * null-means-empty invariant; otherwise, every NodeList instance
1175         * will waste a lot of space. A cursor is needed only for the duration
1176         * of a visit to the child nodes. Under normal circumstances, only a
1177         * single cursor is needed; multiple cursors are only required if there
1178         * are multiple visits going on at the same time.
1179         * </p>
1180         */

1181        private List JavaDoc cursors = null;
1182
1183        /**
1184         * Creates a new empty list of nodes owned by this node.
1185         * This node will be the common parent of all nodes added to
1186         * this list.
1187         *
1188         * @param property the property descriptor
1189         * @since 3.0
1190         */

1191        NodeList(ChildListPropertyDescriptor property) {
1192            super();
1193            this.propertyDescriptor = property;
1194        }
1195    
1196        /* (non-javadoc)
1197         * @see java.util.AbstractCollection#size()
1198         */

1199        public int size() {
1200            return this.store.size();
1201        }
1202    
1203        /* (non-javadoc)
1204         * @see AbstractList#get(int)
1205         */

1206        public Object JavaDoc get(int index) {
1207            return this.store.get(index);
1208        }
1209    
1210        /* (non-javadoc)
1211         * @see List#set(int, java.lang.Object)
1212         */

1213        public Object JavaDoc set(int index, Object JavaDoc element) {
1214            if (element == null) {
1215                throw new IllegalArgumentException JavaDoc();
1216            }
1217            if ((ASTNode.this.typeAndFlags & PROTECT) != 0) {
1218                // this node is protected => cannot gain or lose children
1219
throw new IllegalArgumentException JavaDoc("AST node cannot be modified"); //$NON-NLS-1$
1220
}
1221            // delink old child from parent, and link new child to parent
1222
ASTNode newChild = (ASTNode) element;
1223            ASTNode oldChild = (ASTNode) this.store.get(index);
1224            if (oldChild == newChild) {
1225                return oldChild;
1226            }
1227            if ((oldChild.typeAndFlags & PROTECT) != 0) {
1228                // old child is protected => cannot be unparented
1229
throw new IllegalArgumentException JavaDoc("AST node cannot be modified"); //$NON-NLS-1$
1230
}
1231            ASTNode.checkNewChild(ASTNode.this, newChild, this.propertyDescriptor.cycleRisk, this.propertyDescriptor.elementType);
1232            ASTNode.this.ast.preReplaceChildEvent(ASTNode.this, oldChild, newChild, this.propertyDescriptor);
1233            
1234            Object JavaDoc result = this.store.set(index, newChild);
1235            // n.b. setParent will call ast.modifying()
1236
oldChild.setParent(null, null);
1237            newChild.setParent(ASTNode.this, this.propertyDescriptor);
1238            ASTNode.this.ast.postReplaceChildEvent(ASTNode.this, oldChild, newChild, this.propertyDescriptor);
1239            return result;
1240        }
1241        
1242        /* (non-javadoc)
1243         * @see List#add(int, java.lang.Object)
1244         */

1245        public void add(int index, Object JavaDoc element) {
1246            if (element == null) {
1247                throw new IllegalArgumentException JavaDoc();
1248            }
1249            if ((ASTNode.this.typeAndFlags & PROTECT) != 0) {
1250                // this node is protected => cannot gain or lose children
1251
throw new IllegalArgumentException JavaDoc("AST node cannot be modified"); //$NON-NLS-1$
1252
}
1253            // link new child to parent
1254
ASTNode newChild = (ASTNode) element;
1255            ASTNode.checkNewChild(ASTNode.this, newChild, this.propertyDescriptor.cycleRisk, this.propertyDescriptor.elementType);
1256            ASTNode.this.ast.preAddChildEvent(ASTNode.this, newChild, this.propertyDescriptor);
1257            
1258            
1259            this.store.add(index, element);
1260            updateCursors(index, +1);
1261            // n.b. setParent will call ast.modifying()
1262
newChild.setParent(ASTNode.this, this.propertyDescriptor);
1263            ASTNode.this.ast.postAddChildEvent(ASTNode.this, newChild, this.propertyDescriptor);
1264        }
1265        
1266        /* (non-javadoc)
1267         * @see List#remove(int)
1268         */

1269        public Object JavaDoc remove(int index) {
1270            if ((ASTNode.this.typeAndFlags & PROTECT) != 0) {
1271                // this node is protected => cannot gain or lose children
1272
throw new IllegalArgumentException JavaDoc("AST node cannot be modified"); //$NON-NLS-1$
1273
}
1274            // delink old child from parent
1275
ASTNode oldChild = (ASTNode) this.store.get(index);
1276            if ((oldChild.typeAndFlags & PROTECT) != 0) {
1277                // old child is protected => cannot be unparented
1278
throw new IllegalArgumentException JavaDoc("AST node cannot be modified"); //$NON-NLS-1$
1279
}
1280            
1281            ASTNode.this.ast.preRemoveChildEvent(ASTNode.this, oldChild, this.propertyDescriptor);
1282            // n.b. setParent will call ast.modifying()
1283
oldChild.setParent(null, null);
1284            Object JavaDoc result = this.store.remove(index);
1285            updateCursors(index, -1);
1286            ASTNode.this.ast.postRemoveChildEvent(ASTNode.this, oldChild, this.propertyDescriptor);
1287            return result;
1288
1289        }
1290        
1291        /**
1292         * Allocate a cursor to use for a visit. The client must call
1293         * <code>releaseCursor</code> when done.
1294         * <p>
1295         * This method is internally synchronized on this NodeList.
1296         * It is thread-safe to create a cursor.
1297         * </p>
1298         *
1299         * @return a new cursor positioned before the first element
1300         * of the list
1301         */

1302        Cursor newCursor() {
1303            synchronized (this) {
1304                // serialize cursor management on this NodeList
1305
if (this.cursors == null) {
1306                    // convert null to empty list
1307
this.cursors = new ArrayList JavaDoc(1);
1308                }
1309                Cursor result = new Cursor();
1310                this.cursors.add(result);
1311                return result;
1312            }
1313        }
1314        
1315        /**
1316         * Releases the given cursor at the end of a visit.
1317         * <p>
1318         * This method is internally synchronized on this NodeList.
1319         * It is thread-safe to release a cursor.
1320         * </p>
1321         *
1322         * @param cursor the cursor
1323         */

1324        void releaseCursor(Cursor cursor) {
1325            synchronized (this) {
1326                // serialize cursor management on this NodeList
1327
this.cursors.remove(cursor);
1328                if (this.cursors.isEmpty()) {
1329                    // important: convert empty list back to null
1330
// otherwise the node will hang on to needless junk
1331
this.cursors = null;
1332                }
1333            }
1334        }
1335
1336        /**
1337         * Adjusts all cursors to accomodate an add/remove at the given
1338         * index.
1339         * <p>
1340         * This method is only used when the list is being modified.
1341         * The AST is not thread-safe if any of the clients are modifying it.
1342         * </p>
1343         *
1344         * @param index the position at which the element was added
1345         * or removed
1346         * @param delta +1 for add, and -1 for remove
1347         */

1348        private void updateCursors(int index, int delta) {
1349            if (this.cursors == null) {
1350                // there are no cursors to worry about
1351
return;
1352            }
1353            for (Iterator JavaDoc it = this.cursors.iterator(); it.hasNext(); ) {
1354                Cursor c = (Cursor) it.next();
1355                c.update(index, delta);
1356            }
1357        }
1358        
1359        /**
1360         * Returns an estimate of the memory footprint of this node list
1361         * instance in bytes.
1362         * <ul>
1363         * <li>1 object header for the NodeList instance</li>
1364         * <li>5 4-byte fields of the NodeList instance</li>
1365         * <li>0 for cursors since null unless walk in progress</li>
1366         * <li>1 object header for the ArrayList instance</li>
1367         * <li>2 4-byte fields of the ArrayList instance</li>
1368         * <li>1 object header for an Object[] instance</li>
1369         * <li>4 bytes in array for each element</li>
1370         * </ul>
1371         *
1372         * @return the size of this node list in bytes
1373         */

1374        int memSize() {
1375            int result = HEADERS + 5 * 4;
1376            result += HEADERS + 2 * 4;
1377            result += HEADERS + 4 * size();
1378            return result;
1379        }
1380
1381        /**
1382         * Returns an estimate of the memory footprint in bytes of this node
1383         * list and all its subtrees.
1384         *
1385         * @return the size of this list of subtrees in bytes
1386         */

1387        int listSize() {
1388            int result = memSize();
1389            for (Iterator JavaDoc it = iterator(); it.hasNext(); ) {
1390                ASTNode child = (ASTNode) it.next();
1391                result += child.treeSize();
1392            }
1393            return result;
1394        }
1395    }
1396
1397    /**
1398     * Creates a new AST node owned by the given AST. Once established,
1399     * the relationship between an AST node and its owning AST does not change
1400     * over the lifetime of the node. The new node has no parent node,
1401     * and no properties.
1402     * <p>
1403     * N.B. This constructor is package-private; all subclasses my be
1404     * declared in the same package; clients are unable to declare
1405     * additional subclasses.
1406     * </p>
1407     *
1408     * @param ast the AST that is to own this node
1409     */

1410    ASTNode(AST ast) {
1411        if (ast == null) {
1412            throw new IllegalArgumentException JavaDoc();
1413        }
1414        
1415        this.ast = ast;
1416        setNodeType(getNodeType0());
1417        setFlags(ast.getDefaultNodeFlag());
1418        // setFlags calls modifying();
1419
}
1420    
1421    /**
1422     * Returns this node's AST.
1423     * <p>
1424     * Note that the relationship between an AST node and its owing AST does
1425     * not change over the lifetime of a node.
1426     * </p>
1427     *
1428     * @return the AST that owns this node
1429     */

1430    public final AST getAST() {
1431        return this.ast;
1432    }
1433    
1434    /**
1435     * Returns this node's parent node, or <code>null</code> if this is the
1436     * root node.
1437     * <p>
1438     * Note that the relationship between an AST node and its parent node
1439     * may change over the lifetime of a node.
1440     * </p>
1441     *
1442     * @return the parent of this node, or <code>null</code> if none
1443     */

1444    public final ASTNode getParent() {
1445        return this.parent;
1446    }
1447        
1448    /**
1449     * Returns the location of this node within its parent,
1450     * or <code>null</code> if this is a root node.
1451     * <p>
1452     * <pre>
1453     * ASTNode node = ...;
1454     * ASTNode parent = node.getParent();
1455     * StructuralPropertyDescriptor location = node.getLocationInParent();
1456     * assert (parent != null) == (location != null);
1457     * if ((location != null) && location.isChildProperty())
1458     * assert parent.getStructuralProperty(location) == node;
1459     * if ((location != null) && location.isChildListProperty())
1460     * assert ((List) parent.getStructuralProperty(location)).contains(node);
1461     * </pre>
1462     * </p>
1463     * <p>
1464     * Note that the relationship between an AST node and its parent node
1465     * may change over the lifetime of a node.
1466     * </p>
1467     *
1468     * @return the location of this node in its parent,
1469     * or <code>null</code> if this node has no parent
1470     * @since 3.0
1471     */

1472    public final StructuralPropertyDescriptor getLocationInParent() {
1473        return this.location;
1474    }
1475        
1476    /**
1477     * Returns the root node at or above this node; returns this node if
1478     * it is a root.
1479     *
1480     * @return the root node at or above this node
1481     */

1482    public final ASTNode getRoot() {
1483        ASTNode candidate = this;
1484        while (true) {
1485            ASTNode p = candidate.getParent();
1486            if (p == null) {
1487                // candidate has no parent - that's the guy
1488
return candidate;
1489            }
1490            candidate = p;
1491        }
1492    }
1493    
1494    /**
1495     * Returns the value of the given structural property for this node. The value
1496     * returned depends on the kind of property:
1497     * <ul>
1498     * <li>{@link SimplePropertyDescriptor} - the value of the given simple property,
1499     * or <code>null</code> if none; primitive values are "boxed"</li>
1500     * <li>{@link ChildPropertyDescriptor} - the child node (type <code>ASTNode</code>),
1501     * or <code>null</code> if none</li>
1502     * <li>{@link ChildListPropertyDescriptor} - the list (element type: {@link ASTNode})</li>
1503     * </ul>
1504     *
1505     * @param property the property
1506     * @return the value, or <code>null</code> if none
1507     * @exception RuntimeException if this node does not have the given property
1508     * @since 3.0
1509     */

1510    public final Object JavaDoc getStructuralProperty(StructuralPropertyDescriptor property) {
1511        if (property instanceof SimplePropertyDescriptor) {
1512            SimplePropertyDescriptor p = (SimplePropertyDescriptor) property;
1513            if (p.getValueType() == int.class) {
1514                int result = internalGetSetIntProperty(p, true, 0);
1515                return new Integer JavaDoc(result);
1516            } else if (p.getValueType() == boolean.class) {
1517                boolean result = internalGetSetBooleanProperty(p, true, false);
1518                return Boolean.valueOf(result);
1519            } else {
1520                return internalGetSetObjectProperty(p, true, null);
1521            }
1522        }
1523        if (property instanceof ChildPropertyDescriptor) {
1524            return internalGetSetChildProperty((ChildPropertyDescriptor) property, true, null);
1525        }
1526        if (property instanceof ChildListPropertyDescriptor) {
1527            return internalGetChildListProperty((ChildListPropertyDescriptor) property);
1528        }
1529        throw new IllegalArgumentException JavaDoc();
1530    }
1531    
1532    /**
1533     * Sets the value of the given structural property for this node. The value
1534     * passed depends on the kind of property:
1535     * <ul>
1536     * <li>{@link SimplePropertyDescriptor} - the new value of the given simple property,
1537     * or <code>null</code> if none; primitive values are "boxed"</li>
1538     * <li>{@link ChildPropertyDescriptor} - the new child node (type <code>ASTNode</code>),
1539     * or <code>null</code> if none</li>
1540     * <li>{@link ChildListPropertyDescriptor} - not allowed</li>
1541     * </ul>
1542     *
1543     * @param property the property
1544     * @param value the property value
1545     * @exception RuntimeException if this node does not have the
1546     * given property, or if the given property cannot be set
1547     * @since 3.0
1548     */

1549    public final void setStructuralProperty(StructuralPropertyDescriptor property, Object JavaDoc value) {
1550        if (property instanceof SimplePropertyDescriptor) {
1551            SimplePropertyDescriptor p = (SimplePropertyDescriptor) property;
1552            if (p.getValueType() == int.class) {
1553                int arg = ((Integer JavaDoc) value).intValue();
1554                internalGetSetIntProperty(p, false, arg);
1555                return;
1556            } else if (p.getValueType() == boolean.class) {
1557                boolean arg = ((Boolean JavaDoc) value).booleanValue();
1558                internalGetSetBooleanProperty(p, false, arg);
1559                return;
1560            } else {
1561                if (value == null && p.isMandatory()) {
1562                    throw new IllegalArgumentException JavaDoc();
1563                }
1564                internalGetSetObjectProperty(p, false, value);
1565                return;
1566            }
1567        }
1568        if (property instanceof ChildPropertyDescriptor) {
1569            ChildPropertyDescriptor p = (ChildPropertyDescriptor) property;
1570            ASTNode child = (ASTNode) value;
1571            if (child == null && p.isMandatory()) {
1572                throw new IllegalArgumentException JavaDoc();
1573            }
1574            internalGetSetChildProperty(p, false, child);
1575            return;
1576        }
1577        if (property instanceof ChildListPropertyDescriptor) {
1578            throw new IllegalArgumentException JavaDoc("Cannot set the list of child list property"); //$NON-NLS-1$
1579
}
1580    }
1581
1582    /**
1583     * Sets the value of the given int-valued property for this node.
1584     * The default implementation of this method throws an exception explaining
1585     * that this node does not have such a property. This method should be
1586     * extended in subclasses that have at leasy one simple property whose value
1587     * type is int.
1588     *
1589     * @param property the property
1590     * @param get <code>true</code> for a get operation, and
1591     * <code>false</code> for a set operation
1592     * @param value the new property value; ignored for get operations
1593     * @return the value; always returns
1594     * <code>0</code> for set operations
1595     * @exception RuntimeException if this node does not have the
1596     * given property, or if the given value cannot be set as specified
1597     * @since 3.0
1598     */

1599    int internalGetSetIntProperty(SimplePropertyDescriptor property, boolean get, int value) {
1600        throw new RuntimeException JavaDoc("Node does not have this property"); //$NON-NLS-1$
1601
}
1602    
1603    /**
1604     * Sets the value of the given boolean-valued property for this node.
1605     * The default implementation of this method throws an exception explaining
1606     * that this node does not have such a property. This method should be
1607     * extended in subclasses that have at leasy one simple property whose value
1608     * type is boolean.
1609     *
1610     * @param property the property
1611     * @param get <code>true</code> for a get operation, and
1612     * <code>false</code> for a set operation
1613     * @param value the new property value; ignored for get operations
1614     * @return the value; always returns
1615     * <code>false</code> for set operations
1616     * @exception RuntimeException if this node does not have the
1617     * given property, or if the given value cannot be set as specified
1618     * @since 3.0
1619     */

1620    boolean internalGetSetBooleanProperty(SimplePropertyDescriptor property, boolean get, boolean value) {
1621        throw new RuntimeException JavaDoc("Node does not have this property"); //$NON-NLS-1$
1622
}
1623    
1624    /**
1625     * Sets the value of the given property for this node.
1626     * The default implementation of this method throws an exception explaining
1627     * that this node does not have such a property. This method should be
1628     * extended in subclasses that have at leasy one simple property whose value
1629     * type is a reference type.
1630     *
1631     * @param property the property
1632     * @param get <code>true</code> for a get operation, and
1633     * <code>false</code> for a set operation
1634     * @param value the new property value, or <code>null</code> if none;
1635     * ignored for get operations
1636     * @return the value, or <code>null</code> if none; always returns
1637     * <code>null</code> for set operations
1638     * @exception RuntimeException if this node does not have the
1639     * given property, or if the given value cannot be set as specified
1640     * @since 3.0
1641     */

1642    Object JavaDoc internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object JavaDoc value) {
1643        throw new RuntimeException JavaDoc("Node does not have this property"); //$NON-NLS-1$
1644
}
1645
1646    /**
1647     * Sets the child value of the given property for this node.
1648     * The default implementation of this method throws an exception explaining
1649     * that this node does not have such a property. This method should be
1650     * extended in subclasses that have at leasy one child property.
1651     *
1652     * @param property the property
1653     * @param get <code>true</code> for a get operation, and
1654     * <code>false</code> for a set operation
1655     * @param child the new child value, or <code>null</code> if none;
1656     * always <code>null</code> for get operations
1657     * @return the child, or <code>null</code> if none; always returns
1658     * <code>null</code> for set operations
1659     * @exception RuntimeException if this node does not have the
1660     * given property, or if the given child cannot be set as specified
1661     * @since 3.0
1662     */

1663    ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
1664        throw new RuntimeException JavaDoc("Node does not have this property"); //$NON-NLS-1$
1665
}
1666    
1667    /**
1668     * Returns the list value of the given property for this node.
1669     * The default implementation of this method throws an exception explaining
1670     * that this noed does not have such a property. This method should be
1671     * extended in subclasses that have at leasy one child list property.
1672     *
1673     * @param property the property
1674     * @return the list (element type: {@link ASTNode})
1675     * @exception RuntimeException if the given node does not have the
1676     * given property
1677     * @since 3.0
1678     */

1679    List JavaDoc internalGetChildListProperty(ChildListPropertyDescriptor property) {
1680        throw new RuntimeException JavaDoc("Node does not have this property"); //$NON-NLS-1$
1681
}
1682    
1683    /**
1684     * Returns a list of structural property descriptors for nodes of the
1685     * same type as this node. Clients must not modify the result.
1686     * <p>
1687     * Note that property descriptors are a meta-level mechanism
1688     * for manipulating ASTNodes in a generic way. They are
1689     * unrelated to <code>get/setProperty</code>.
1690     * </p>
1691     *
1692     * @return a list of property descriptors (element type:
1693     * {@link StructuralPropertyDescriptor})
1694     * @since 3.0
1695     */

1696    public final List JavaDoc structuralPropertiesForType() {
1697        return internalStructuralPropertiesForType(this.ast.apiLevel);
1698    }
1699    
1700    /**
1701     * Returns a list of property descriptors for this node type.
1702     * Clients must not modify the result. This abstract method
1703     * must be implemented in each concrete AST node type.
1704     * <p>
1705     * N.B. This method is package-private, so that the implementations
1706     * of this method in each of the concrete AST node types do not
1707     * clutter up the API doc.
1708     * </p>
1709     *
1710     * @param apiLevel the API level; one of the <code>AST.JLS*</code> constants
1711     * @return a list of property descriptors (element type:
1712     * {@link StructuralPropertyDescriptor})
1713     * @since 3.0
1714     */

1715    abstract List JavaDoc internalStructuralPropertiesForType(int apiLevel);
1716    
1717    /**
1718     * Internal helper method that starts the building a list of
1719     * property descriptors for the given node type.
1720     *
1721     * @param nodeClass the class for a concrete node type
1722     * @param propertyList empty list
1723     */

1724    static void createPropertyList(Class JavaDoc nodeClass, List JavaDoc propertyList) {
1725        // stuff nodeClass at head of list for future ref
1726
propertyList.add(nodeClass);
1727    }
1728    
1729    /**
1730     * Internal helper method that adding a property descriptor.
1731     *
1732     * @param property the structural property descriptor
1733     * @param propertyList list beginning with the AST node class
1734     * followed by accumulated structural property descriptors
1735     */

1736    static void addProperty(StructuralPropertyDescriptor property, List JavaDoc propertyList) {
1737        Class JavaDoc nodeClass = (Class JavaDoc) propertyList.get(0);
1738        if (property.getNodeClass() != nodeClass) {
1739            // easily made cut-and-paste mistake
1740
throw new RuntimeException JavaDoc("Structural property descriptor has wrong node class!"); //$NON-NLS-1$
1741
}
1742        propertyList.add(property);
1743    }
1744        
1745    /**
1746     * Internal helper method that completes the building of
1747     * a node type's structural property descriptor list.
1748     *
1749     * @param propertyList list beginning with the AST node class
1750     * followed by accumulated structural property descriptors
1751     * @return unmodifiable list of structural property descriptors
1752     * (element type: <code>StructuralPropertyDescriptor</code>)
1753     */

1754    static List JavaDoc reapPropertyList(List JavaDoc propertyList) {
1755        propertyList.remove(0); // remove nodeClass
1756
// compact
1757
ArrayList JavaDoc a = new ArrayList JavaDoc(propertyList.size());
1758        a.addAll(propertyList);
1759        return Collections.unmodifiableList(a);
1760    }
1761    
1762    /**
1763     * Checks that this AST operation is not used when
1764     * building JLS2 level ASTs.
1765
1766     * @exception UnsupportedOperationException
1767     * @since 3.0
1768     */

1769    final void unsupportedIn2() {
1770      if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
1771        throw new UnsupportedOperationException JavaDoc("Operation not supported in JLS2 AST"); //$NON-NLS-1$
1772
}
1773    }
1774
1775    /**
1776     * Checks that this AST operation is only used when
1777     * building JLS2 level ASTs.
1778
1779     * @exception UnsupportedOperationException
1780     * @since 3.0
1781     */

1782    final void supportedOnlyIn2() {
1783      if (this.ast.apiLevel != AST.JLS2_INTERNAL) {
1784        throw new UnsupportedOperationException JavaDoc("Operation only supported in JLS2 AST"); //$NON-NLS-1$
1785
}
1786    }
1787
1788    /**
1789     * Sets or clears this node's parent node and location.
1790     * <p>
1791     * Note that this method is package-private. The pointer from a node
1792     * to its parent is set implicitly as a side effect of inserting or
1793     * removing the node as a child of another node. This method calls
1794     * <code>ast.modifying()</code>.
1795     * </p>
1796     *
1797     * @param parent the new parent of this node, or <code>null</code> if none
1798     * @param property the location of this node in its parent,
1799     * or <code>null</code> if <code>parent</code> is <code>null</code>
1800     * @see #getLocationInParent
1801     * @see #getParent
1802     * @since 3.0
1803     */

1804    final void setParent(ASTNode parent, StructuralPropertyDescriptor property) {
1805        this.ast.modifying();
1806        this.parent = parent;
1807        this.location = property;
1808    }
1809    
1810    /**
1811     * Removes this node from its parent. Has no effect if this node
1812     * is unparented. If this node appears as an element of a child list
1813     * property of its parent, then this node is removed from the
1814     * list using <code>List.remove</code>.
1815     * If this node appears as the value of a child property of its
1816     * parent, then this node is detached from its parent
1817     * by passing <code>null</code> to the appropriate setter method;
1818     * this operation fails if this node is in a mandatory property.
1819     *
1820     * @since 3.0
1821     */

1822    public final void delete() {
1823        StructuralPropertyDescriptor p = getLocationInParent();
1824        if (p == null) {
1825            // node is unparented
1826
return;
1827        }
1828        if (p.isChildProperty()) {
1829            getParent().setStructuralProperty(this.location, null);
1830            return;
1831        }
1832        if (p.isChildListProperty()) {
1833            List JavaDoc l = (List JavaDoc) getParent().getStructuralProperty(this.location);
1834            l.remove(this);
1835        }
1836    }
1837
1838    /**
1839     * Checks whether the given new child node is a node
1840     * in a different AST from its parent-to-be, whether it is
1841     * already has a parent, whether adding it to its
1842     * parent-to-be would create a cycle, and whether the child is of
1843     * the right type. The parent-to-be is the enclosing instance.
1844     *
1845     * @param node the parent-to-be node
1846     * @param newChild the new child of the parent
1847     * @param cycleCheck <code>true</code> if cycles are possible and need
1848     * to be checked, <code>false</code> if cycles are impossible and do
1849     * not need to be checked
1850     * @param nodeType a type constraint on child nodes, or <code>null</code>
1851     * if no special check is required
1852     * @exception IllegalArgumentException if:
1853     * <ul>
1854     * <li>the child is null</li>
1855     * <li>the node belongs to a different AST</li>
1856     * <li>the child has the incorrect node type</li>
1857     * <li>the node already has a parent</li>
1858     * <li>a cycle in would be created</li>
1859     * </ul>
1860     */

1861    static void checkNewChild(ASTNode node, ASTNode newChild,
1862            boolean cycleCheck, Class JavaDoc nodeType) {
1863        if (newChild.ast != node.ast) {
1864            // new child is from a different AST
1865
throw new IllegalArgumentException JavaDoc();
1866        }
1867        if (newChild.getParent() != null) {
1868            // new child currently has a different parent
1869
throw new IllegalArgumentException JavaDoc();
1870        }
1871        if (cycleCheck && newChild == node.getRoot()) {
1872            // inserting new child would create a cycle
1873
throw new IllegalArgumentException JavaDoc();
1874        }
1875        Class JavaDoc childClass = newChild.getClass();
1876        if (nodeType != null && !nodeType.isAssignableFrom(childClass)) {
1877            // new child is not of the right type
1878
throw new ClassCastException JavaDoc();
1879        }
1880        if ((newChild.typeAndFlags & PROTECT) != 0) {
1881            // new child node is protected => cannot be parented
1882
throw new IllegalArgumentException JavaDoc("AST node cannot be modified"); //$NON-NLS-1$
1883
}
1884    }
1885
1886    /**
1887     * Prelude portion of the "3 step program" for replacing the
1888     * old child of this node with another node.
1889     * Here is the code pattern found in all AST node subclasses:
1890     * <pre>
1891     * ASTNode oldChild = this.foo;
1892     * preReplaceChild(oldChild, newFoo, FOO_PROPERTY);
1893     * this.foo = newFoo;
1894     * postReplaceChild(oldChild, newFoo, FOO_PROPERTY);
1895     * </pre>
1896     * The first part (preReplaceChild) does all the precondition checks,
1897     * reports pre-delete events, and changes parent links.
1898     * The old child is delinked from its parent (making it a root node),
1899     * and the new child node is linked to its parent. The new child node
1900     * must be a root node in the same AST as its new parent, and must not
1901     * be an ancestor of this node. All three nodes must be
1902     * modifiable (not PROTECTED). The replace operation must fail
1903     * atomically; so it is crucial that all precondition checks
1904     * be done before any linking and delinking happens.
1905     * The final part (postReplaceChild )reports post-add events.
1906     * <p>
1907     * This method calls <code>ast.modifying()</code> for the nodes affected.
1908     * </p>
1909     *
1910     * @param oldChild the old child of this node, or <code>null</code> if
1911     * there was no old child to replace
1912     * @param newChild the new child of this node, or <code>null</code> if
1913     * there is no replacement child
1914     * @param property the property descriptor of this node describing
1915     * the relationship between node and child
1916     * @exception RuntimeException if:
1917     * <ul>
1918     * <li>the node belongs to a different AST</li>
1919     * <li>the node already has a parent</li>
1920     * <li>a cycle in would be created</li>
1921     * <li>any of the nodes involved are unmodifiable</li>
1922     * </ul>
1923     * @since 3.0
1924     */

1925    final void preReplaceChild(ASTNode oldChild, ASTNode newChild, ChildPropertyDescriptor property) {
1926        if ((this.typeAndFlags & PROTECT) != 0) {
1927            // this node is protected => cannot gain or lose children
1928
throw new IllegalArgumentException JavaDoc("AST node cannot be modified"); //$NON-NLS-1$
1929
}
1930        if (newChild != null) {
1931            checkNewChild(this, newChild, property.cycleRisk, null);
1932        }
1933        // delink old child from parent
1934
if (oldChild != null) {
1935            if ((oldChild.typeAndFlags & PROTECT) != 0) {
1936                // old child node is protected => cannot be unparented
1937
throw new IllegalArgumentException JavaDoc("AST node cannot be modified"); //$NON-NLS-1$
1938
}
1939            if (newChild != null) {
1940                this.ast.preReplaceChildEvent(this, oldChild, newChild, property);
1941            } else {
1942                this.ast.preRemoveChildEvent(this, oldChild, property);
1943            }
1944            oldChild.setParent(null, null);
1945        } else {
1946            if(newChild != null) {
1947                this.ast.preAddChildEvent(this, newChild, property);
1948            }
1949        }
1950        // link new child to parent
1951
if (newChild != null) {
1952            newChild.setParent(this, property);
1953            // cannot notify postAddChildEvent until parent is linked to child too
1954
}
1955    }
1956
1957    /**
1958     * Postlude portion of the "3 step program" for replacing the
1959     * old child of this node with another node.
1960     * See {@link #preReplaceChild(ASTNode, ASTNode, ChildPropertyDescriptor)}
1961     * for details.
1962     * @since 3.0
1963     */

1964    final void postReplaceChild(ASTNode oldChild, ASTNode newChild, ChildPropertyDescriptor property) {
1965        // link new child to parent
1966
if (newChild != null) {
1967            if (oldChild != null) {
1968                this.ast.postReplaceChildEvent(this, oldChild, newChild, property);
1969            } else {
1970                this.ast.postAddChildEvent(this, newChild, property);
1971            }
1972        } else {
1973            this.ast.postRemoveChildEvent(this, oldChild, property);
1974        }
1975    }
1976    
1977    /**
1978     * Prelude portion of the "3 step program" for changing the
1979     * value of a simple property of this node.
1980     * Here is the code pattern found in all AST node subclasses:
1981     * <pre>
1982     * preValueChange(FOO_PROPERTY);
1983     * this.foo = newFoo;
1984     * postValueChange(FOO_PROPERTY);
1985     * </pre>
1986     * The first part (preValueChange) does the precondition check
1987     * to make sure the node is modifiable (not PROTECTED).
1988     * The change operation must fail atomically; so it is crucial
1989     * that the precondition checks are done before the field is
1990     * hammered. The final part (postValueChange)reports post-change
1991     * events.
1992     * <p>
1993     * This method calls <code>ast.modifying()</code> for the node affected.
1994     * </p>
1995     *
1996     * @param property the property descriptor of this node
1997     * @exception RuntimeException if:
1998     * <ul>
1999     * <li>this node is unmodifiable</li>
2000     * </ul>
2001     * @since 3.0
2002     */

2003    final void preValueChange(SimplePropertyDescriptor property) {
2004        if ((this.typeAndFlags & PROTECT) != 0) {
2005            // this node is protected => cannot change valure of properties
2006
throw new IllegalArgumentException JavaDoc("AST node cannot be modified"); //$NON-NLS-1$
2007
}
2008        this.ast.preValueChangeEvent(this, property);
2009        this.ast.modifying();
2010    }
2011
2012    /**
2013     * Postlude portion of the "3 step program" for replacing the
2014     * old child of this node with another node.
2015     * See {@link #preValueChange(SimplePropertyDescriptor)} for details.
2016     * @since 3.0
2017     */

2018    final void postValueChange(SimplePropertyDescriptor property) {
2019        this.ast.postValueChangeEvent(this, property);
2020    }
2021    
2022    /**
2023     * Ensures that this node is modifiable (that is, not marked PROTECTED).
2024     * If successful, calls ast.modifying().
2025     * @exception RuntimeException is not modifiable
2026     */

2027    final void checkModifiable() {
2028        if ((this.typeAndFlags & PROTECT) != 0) {
2029            throw new IllegalArgumentException JavaDoc("AST node cannot be modified"); //$NON-NLS-1$
2030
}
2031        this.ast.modifying();
2032    }
2033    
2034    /**
2035     * Begin lazy initialization of this node.
2036     * Here is the code pattern found in all AST
2037     * node subclasses:
2038     * <pre>
2039     * if (this.foo == null) {
2040     * // lazy init must be thread-safe for readers
2041     * synchronized (this) {
2042     * if (this.foo == null) {
2043     * preLazyInit();
2044     * this.foo = ...; // code to create new node
2045     * postLazyInit(this.foo, FOO_PROPERTY);
2046     * }
2047     * }
2048     * }
2049     * </pre>
2050     * @since 3.0
2051     */

2052    final void preLazyInit() {
2053        // IMPORTANT: this method is called by readers
2054
// ASTNode.this is locked at this point
2055
this.ast.disableEvents();
2056        // will turn events back on in postLasyInit
2057
}
2058    
2059    /**
2060     * End lazy initialization of this node.
2061     *
2062     * @param newChild the new child of this node, or <code>null</code> if
2063     * there is no replacement child
2064     * @param property the property descriptor of this node describing
2065     * the relationship between node and child
2066     * @since 3.0
2067     */

2068    final void postLazyInit(ASTNode newChild, ChildPropertyDescriptor property) {
2069        // IMPORTANT: this method is called by readers
2070
// ASTNode.this is locked at this point
2071
// newChild is brand new (so no chance of concurrent access)
2072
newChild.setParent(this, property);
2073        // turn events back on (they were turned off in corresponding preLazyInit)
2074
this.ast.reenableEvents();
2075    }
2076
2077    /**
2078     * Returns the named property of this node, or <code>null</code> if none.
2079     *
2080     * @param propertyName the property name
2081     * @return the property value, or <code>null</code> if none
2082     * @see #setProperty(String,Object)
2083     */

2084    public final Object JavaDoc getProperty(String JavaDoc propertyName) {
2085        if (propertyName == null) {
2086            throw new IllegalArgumentException JavaDoc();
2087        }
2088        if (this.property1 == null) {
2089            // node has no properties at all
2090
return null;
2091        }
2092        if (this.property1 instanceof String JavaDoc) {
2093            // node has only a single property
2094
if (propertyName.equals(this.property1)) {
2095                return this.property2;
2096            } else {
2097                return null;
2098            }
2099        }
2100        // otherwise node has table of properties
2101
Map JavaDoc m = (Map JavaDoc) this.property1;
2102        return m.get(propertyName);
2103    }
2104    
2105    /**
2106     * Sets the named property of this node to the given value,
2107     * or to <code>null</code> to clear it.
2108     * <p>
2109     * Clients should employ property names that are sufficiently unique
2110     * to avoid inadvertent conflicts with other clients that might also be
2111     * setting properties on the same node.
2112     * </p>
2113     * <p>
2114     * Note that modifying a property is not considered a modification to the
2115     * AST itself. This is to allow clients to decorate existing nodes with
2116     * their own properties without jeopardizing certain things (like the
2117     * validity of bindings), which rely on the underlying tree remaining static.
2118     * </p>
2119     *
2120     * @param propertyName the property name
2121     * @param data the new property value, or <code>null</code> if none
2122     * @see #getProperty(String)
2123     */

2124    public final void setProperty(String JavaDoc propertyName, Object JavaDoc data) {
2125        if (propertyName == null) {
2126            throw new IllegalArgumentException JavaDoc();
2127        }
2128        // N.B. DO NOT CALL ast.modifying();
2129

2130        if (this.property1 == null) {
2131            // node has no properties at all
2132
if (data == null) {
2133                // we already know this
2134
return;
2135            }
2136            // node gets its fist property
2137
this.property1 = propertyName;
2138            this.property2 = data;
2139            return;
2140        }
2141
2142        if (this.property1 instanceof String JavaDoc) {
2143            // node has only a single property
2144
if (propertyName.equals(this.property1)) {
2145                // we're in luck
2146
this.property2 = data;
2147                if (data == null) {
2148                    // just deleted last property
2149
this.property1 = null;
2150                    this.property2 = null;
2151                }
2152                return;
2153            }
2154            if (data == null) {
2155                // we already know this
2156
return;
2157            }
2158            // node already has one property - getting its second
2159
// convert to more flexible representation
2160
HashMap JavaDoc m = new HashMap JavaDoc(2);
2161            m.put(this.property1, this.property2);
2162            m.put(propertyName, data);
2163            this.property1 = m;
2164            this.property2 = null;
2165            return;
2166        }
2167            
2168        // node has two or more properties
2169
HashMap JavaDoc m = (HashMap JavaDoc) this.property1;
2170        if (data == null) {
2171            m.remove(propertyName);
2172            // check for just one property left
2173
if (m.size() == 1) {
2174                // convert to more efficient representation
2175
Map.Entry JavaDoc[] entries = (Map.Entry JavaDoc[]) m.entrySet().toArray(new Map.Entry JavaDoc[1]);
2176                this.property1 = entries[0].getKey();
2177                this.property2 = entries[0].getValue();
2178            }
2179            return;
2180        } else {
2181            m.put(propertyName, data);
2182            // still has two or more properties
2183
return;
2184        }
2185    }
2186
2187    /**
2188     * Returns an unmodifiable table of the properties of this node with
2189     * non-<code>null</code> values.
2190     *
2191     * @return the table of property values keyed by property name
2192     * (key type: <code>String</code>; value type: <code>Object</code>)
2193     */

2194    public final Map JavaDoc properties() {
2195        if (this.property1 == null) {
2196            // node has no properties at all
2197
return UNMODIFIABLE_EMPTY_MAP;
2198        }
2199        if (this.property1 instanceof String JavaDoc) {
2200            // node has a single property
2201
return Collections.singletonMap(this.property1, this.property2);
2202        }
2203        
2204        // node has two or more properties
2205
if (this.property2 == null) {
2206            this.property2 = Collections.unmodifiableMap((Map JavaDoc) this.property1);
2207        }
2208        // property2 is unmodifiable wrapper for map in property1
2209
return (Map JavaDoc) this.property2;
2210    }
2211    
2212    /**
2213     * Returns the flags associated with this node.
2214     * <p>
2215     * No flags are associated with newly created nodes.
2216     * </p>
2217     * <p>
2218     * The flags are the bitwise-or of individual flags.
2219     * The following flags are currently defined:
2220     * <ul>
2221     * <li>{@link #MALFORMED} - indicates node is syntactically
2222     * malformed</li>
2223     * <li>{@link #ORIGINAL} - indicates original node
2224     * created by ASTParser</li>
2225     * <li>{@link #PROTECT} - indicates node is protected
2226     * from further modification</li>
2227     * <li>{@link #RECOVERED} - indicates node or a part of this node
2228     * is recovered from source that contains a syntax error</li>
2229     * </ul>
2230     * Other bit positions are reserved for future use.
2231     * </p>
2232     *
2233     * @return the bitwise-or of individual flags
2234     * @see #setFlags(int)
2235     */

2236    public final int getFlags() {
2237        return this.typeAndFlags & 0xFFFF;
2238    }
2239    
2240    /**
2241     * Sets the flags associated with this node to the given value.
2242     * <p>
2243     * The flags are the bitwise-or of individual flags.
2244     * The following flags are currently defined:
2245     * <ul>
2246     * <li>{@link #MALFORMED} - indicates node is syntactically
2247     * malformed</li>
2248     * <li>{@link #ORIGINAL} - indicates original node
2249     * created by ASTParser</li>
2250     * <li>{@link #PROTECT} - indicates node is protected
2251     * from further modification</li>
2252     * <li>{@link #RECOVERED} - indicates node or a part of this node
2253     * is recovered from source that contains a syntax error</li>
2254     * </ul>
2255     * Other bit positions are reserved for future use.
2256     * </p>
2257     * <p>
2258     * Note that the flags are <em>not</em> considered a structural
2259     * property of the node, and can be changed even if the
2260     * node is marked as protected.
2261     * </p>
2262     *
2263     * @param flags the bitwise-or of individual flags
2264     * @see #getFlags()
2265     */

2266    public final void setFlags(int flags) {
2267        this.ast.modifying();
2268        int old = this.typeAndFlags & 0xFFFF0000;
2269        this.typeAndFlags = old | (flags & 0xFFFF);
2270    }
2271
2272    /**
2273     * Returns an integer value identifying the type of this concrete AST node.
2274     * The values are small positive integers, suitable for use in switch statements.
2275     * <p>
2276     * For each concrete node type there is a unique node type constant (name
2277     * and value). The unique node type constant for a concrete node type such as
2278     * <code>CastExpression</code> is <code>ASTNode.CAST_EXPRESSION</code>.
2279     * </p>
2280     *
2281     * @return one of the node type constants
2282     */

2283    public final int getNodeType() {
2284        return this.typeAndFlags >>> 16;
2285    }
2286    
2287    /**
2288     * Sets the integer value identifying the type of this concrete AST node.
2289     * The values are small positive integers, suitable for use in switch statements.
2290     *
2291     * @param nodeType one of the node type constants
2292     */

2293    private void setNodeType(int nodeType) {
2294        int old = this.typeAndFlags & 0xFFFF0000;
2295        this.typeAndFlags = old | (nodeType << 16);
2296    }
2297    
2298    /**
2299     * Returns an integer value identifying the type of this concrete AST node.
2300     * <p>
2301     * This internal method is implemented in each of the
2302     * concrete node subclasses.
2303     * </p>
2304     *
2305     * @return one of the node type constants
2306     */

2307    abstract int getNodeType0();
2308    
2309    /**
2310     * The <code>ASTNode</code> implementation of this <code>Object</code>
2311     * method uses object identity (==). Use <code>subtreeMatch</code> to
2312     * compare two subtrees for equality.
2313     *
2314     * @param obj {@inheritDoc}
2315     * @return {@inheritDoc}
2316     * @see #subtreeMatch(ASTMatcher matcher, Object other)
2317     */

2318    public final boolean equals(Object JavaDoc obj) {
2319        return this == obj; // equivalent to Object.equals
2320
}
2321    
2322    /*
2323     * (non-Javadoc)
2324     * This makes it consistent with the fact that a equals methods has been provided.
2325     * @see java.lang.Object#hashCode()
2326     */

2327    public final int hashCode() {
2328        return super.hashCode();
2329    }
2330
2331    /**
2332     * Returns whether the subtree rooted at the given node matches the
2333     * given other object as decided by the given matcher.
2334     *
2335     * @param matcher the matcher
2336     * @param other the other object, or <code>null</code>
2337     * @return <code>true</code> if the subtree matches, or
2338     * <code>false</code> if they do not match
2339     */

2340    public final boolean subtreeMatch(ASTMatcher matcher, Object JavaDoc other) {
2341        return subtreeMatch0(matcher, other);
2342    }
2343    
2344    /**
2345     * Returns whether the subtree rooted at the given node matches the
2346     * given other object as decided by the given matcher.
2347     * <p>
2348     * This internal method is implemented in each of the
2349     * concrete node subclasses.
2350     * </p>
2351     *
2352     * @param matcher the matcher
2353     * @param other the other object, or <code>null</code>
2354     * @return <code>true</code> if the subtree matches, or
2355     * <code>false</code> if they do not match
2356     */

2357    abstract boolean subtreeMatch0(ASTMatcher matcher, Object JavaDoc other);
2358    
2359    /**
2360     * Returns a deep copy of the subtree of AST nodes rooted at the
2361     * given node. The resulting nodes are owned by the given AST,
2362     * which may be different from the ASTs of the given node.
2363     * Even if the given node has a parent, the result node will be unparented.
2364     * <p>
2365     * Source range information on the original nodes is automatically copied to the new
2366     * nodes. Client properties (<code>properties</code>) are not carried over.
2367     * </p>
2368     * <p>
2369     * The node's <code>AST</code> and the target <code>AST</code> must support
2370     * the same API level.
2371     * </p>
2372     *
2373     * @param target the AST that is to own the nodes in the result
2374     * @param node the node to copy, or <code>null</code> if none
2375     * @return the copied node, or <code>null</code> if <code>node</code>
2376     * is <code>null</code>
2377     */

2378    public static ASTNode copySubtree(AST target, ASTNode node) {
2379        if (node == null) {
2380            return null;
2381        }
2382        if (target == null) {
2383            throw new IllegalArgumentException JavaDoc();
2384        }
2385        if (target.apiLevel() != node.getAST().apiLevel()) {
2386            throw new UnsupportedOperationException JavaDoc();
2387        }
2388        ASTNode newNode = node.clone(target);
2389        return newNode;
2390    }
2391
2392    /**
2393     * Returns a deep copy of the subtrees of AST nodes rooted at the
2394     * given list of nodes. The resulting nodes are owned by the given AST,
2395     * which may be different from the ASTs of the nodes in the list.
2396     * Even if the nodes in the list have parents, the nodes in the result
2397     * will be unparented.
2398     * <p>
2399     * Source range information on the original nodes is automatically copied to the new
2400     * nodes. Client properties (<code>properties</code>) are not carried over.
2401     * </p>
2402     *
2403     * @param target the AST that is to own the nodes in the result
2404     * @param nodes the list of nodes to copy
2405     * (element type: <code>ASTNode</code>)
2406     * @return the list of copied subtrees
2407     * (element type: <code>ASTNode</code>)
2408     */

2409    public static List JavaDoc copySubtrees(AST target, List JavaDoc nodes) {
2410        List JavaDoc result = new ArrayList JavaDoc(nodes.size());
2411        for (Iterator JavaDoc it = nodes.iterator(); it.hasNext(); ) {
2412            ASTNode oldNode = (ASTNode) it.next();
2413            ASTNode newNode = oldNode.clone(target);
2414            result.add(newNode);
2415        }
2416        return result;
2417    }
2418
2419    /**
2420     * Returns a deep copy of the subtree of AST nodes rooted at this node.
2421     * The resulting nodes are owned by the given AST, which may be different
2422     * from the AST of this node. Even if this node has a parent, the
2423     * result node will be unparented.
2424     * <p>
2425     * This method reports pre- and post-clone events, and dispatches
2426     * to <code>clone0(AST)</code> which is reimplemented in node subclasses.
2427     * </p>
2428     *
2429     * @param target the AST that is to own the nodes in the result
2430     * @return the root node of the copies subtree
2431     */

2432    final ASTNode clone(AST target) {
2433        this.ast.preCloneNodeEvent(this);
2434        ASTNode c = this.clone0(target);
2435        this.ast.postCloneNodeEvent(this, c);
2436        return c;
2437    }
2438
2439    /**
2440     * Returns a deep copy of the subtree of AST nodes rooted at this node.
2441     * The resulting nodes are owned by the given AST, which may be different
2442     * from the AST of this node. Even if this node has a parent, the
2443     * result node will be unparented.
2444     * <p>
2445     * This method must be implemented in subclasses.
2446     * </p>
2447     * <p>
2448     * This method does not report pre- and post-clone events.
2449     * All callers should instead call <code>clone(AST)</code>
2450     * to ensure that pre- and post-clone events are reported.
2451     * </p>
2452     * <p>
2453     * N.B. This method is package-private, so that the implementations
2454     * of this method in each of the concrete AST node types do not
2455     * clutter up the API doc.
2456     * </p>
2457     *
2458     * @param target the AST that is to own the nodes in the result
2459     * @return the root node of the copies subtree
2460     */

2461    abstract ASTNode clone0(AST target);
2462    
2463    /**
2464     * Accepts the given visitor on a visit of the current node.
2465     *
2466     * @param visitor the visitor object
2467     * @exception IllegalArgumentException if the visitor is null
2468     */

2469    public final void accept(ASTVisitor visitor) {
2470        if (visitor == null) {
2471            throw new IllegalArgumentException JavaDoc();
2472        }
2473        // begin with the generic pre-visit
2474
visitor.preVisit(this);
2475        // dynamic dispatch to internal method for type-specific visit/endVisit
2476
accept0(visitor);
2477        // end with the generic post-visit
2478
visitor.postVisit(this);
2479    }
2480
2481    /**
2482     * Accepts the given visitor on a type-specific visit of the current node.
2483     * This method must be implemented in all concrete AST node types.
2484     * <p>
2485     * General template for implementation on each concrete ASTNode class:
2486     * <pre>
2487     * <code>
2488     * boolean visitChildren = visitor.visit(this);
2489     * if (visitChildren) {
2490     * // visit children in normal left to right reading order
2491     * acceptChild(visitor, getProperty1());
2492     * acceptChildren(visitor, rawListProperty);
2493     * acceptChild(visitor, getProperty2());
2494     * }
2495     * visitor.endVisit(this);
2496     * </code>
2497     * </pre>
2498     * Note that the caller (<code>accept</code>) take cares of invoking
2499     * <code>visitor.preVisit(this)</code> and <code>visitor.postVisit(this)</code>.
2500     * </p>
2501     *
2502     * @param visitor the visitor object
2503     */

2504    abstract void accept0(ASTVisitor visitor);
2505
2506    /**
2507     * Accepts the given visitor on a visit of the current node.
2508     * <p>
2509     * This method should be used by the concrete implementations of
2510     * <code>accept0</code> to traverse optional properties. Equivalent
2511     * to <code>child.accept(visitor)</code> if <code>child</code>
2512     * is not <code>null</code>.
2513     * </p>
2514     *
2515     * @param visitor the visitor object
2516     * @param child the child AST node to dispatch too, or <code>null</code>
2517     * if none
2518     */

2519    final void acceptChild(ASTVisitor visitor, ASTNode child) {
2520        if (child == null) {
2521            return;
2522        }
2523        child.accept(visitor);
2524    }
2525
2526    /**
2527     * Accepts the given visitor on a visit of the given live list of
2528     * child nodes.
2529     * <p>
2530     * This method must be used by the concrete implementations of
2531     * <code>accept</code> to traverse list-values properties; it
2532     * encapsulates the proper handling of on-the-fly changes to the list.
2533     * </p>
2534     *
2535     * @param visitor the visitor object
2536     * @param children the child AST node to dispatch too, or <code>null</code>
2537     * if none
2538     */

2539    final void acceptChildren(ASTVisitor visitor, ASTNode.NodeList children) {
2540        // use a cursor to keep track of where we are up to
2541
// (the list may be changing under foot)
2542
NodeList.Cursor cursor = children.newCursor();
2543        try {
2544            while (cursor.hasNext()) {
2545                ASTNode child = (ASTNode) cursor.next();
2546                child.accept(visitor);
2547            }
2548        } finally {
2549            children.releaseCursor(cursor);
2550        }
2551    }
2552
2553    /**
2554     * Returns the character index into the original source file indicating
2555     * where the source fragment corresponding to this node begins.
2556     * <p>
2557     * The parser supplies useful well-defined source ranges to the nodes it creates.
2558     * See {@link ASTParser#setKind(int)} for details
2559     * on precisely where source ranges begin and end.
2560     * </p>
2561     *
2562     * @return the 0-based character index, or <code>-1</code>
2563     * if no source position information is recorded for this node
2564     * @see #getLength()
2565     * @see ASTParser
2566     */

2567    public final int getStartPosition() {
2568        return this.startPosition;
2569    }
2570
2571    /**
2572     * Returns the length in characters of the original source file indicating
2573     * where the source fragment corresponding to this node ends.
2574     * <p>
2575     * The parser supplies useful well-defined source ranges to the nodes it creates.
2576     * See {@link ASTParser#setKind(int)} methods for details
2577     * on precisely where source ranges begin and end.
2578     * </p>
2579     *
2580     * @return a (possibly 0) length, or <code>0</code>
2581     * if no source position information is recorded for this node
2582     * @see #getStartPosition()
2583     * @see ASTParser
2584     */

2585    public final int getLength() {
2586        return this.length;
2587    }
2588
2589    /**
2590     * Sets the source range of the original source file where the source
2591     * fragment corresponding to this node was found.
2592     * <p>
2593     * See {@link ASTParser#setKind(int)} for details
2594     * on precisely where source ranges are supposed to begin and end.
2595     * </p>
2596     *
2597     * @param startPosition a 0-based character index,
2598     * or <code>-1</code> if no source position information is
2599     * available for this node
2600     * @param length a (possibly 0) length,
2601     * or <code>0</code> if no source position information is recorded
2602     * for this node
2603     * @see #getStartPosition()
2604     * @see #getLength()
2605     * @see ASTParser
2606     */

2607    public final void setSourceRange(int startPosition, int length) {
2608        if (startPosition >= 0 && length < 0) {
2609            throw new IllegalArgumentException JavaDoc();
2610        }
2611        if (startPosition < 0 && length != 0) {
2612            throw new IllegalArgumentException JavaDoc();
2613        }
2614        // source positions are not considered a structural property
2615
// but we protect them nevertheless
2616
checkModifiable();
2617        this.startPosition = startPosition;
2618        this.length = length;
2619    }
2620    
2621    /**
2622     * Returns a string representation of this node suitable for debugging
2623     * purposes only.
2624     *
2625     * @return a debug string
2626     */

2627    public final String JavaDoc toString() {
2628        StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
2629        int p = buffer.length();
2630        try {
2631            appendDebugString(buffer);
2632        } catch (RuntimeException JavaDoc e) {
2633            // since debugger sometimes call toString methods, problems can easily happen when
2634
// toString is called on an instance that is being initialized
2635
buffer.setLength(p);
2636            buffer.append("!"); //$NON-NLS-1$
2637
buffer.append(standardToString());
2638        }
2639        return buffer.toString();
2640    }
2641    
2642    /**
2643     * Returns the string representation of this node produced by the standard
2644     * <code>Object.toString</code> method.
2645     *
2646     * @return a debug string
2647     */

2648    final String JavaDoc standardToString() {
2649        return super.toString();
2650    }
2651    
2652    /**
2653     * Appends a debug representation of this node to the given string buffer.
2654     * <p>
2655     * The <code>ASTNode</code> implementation of this method prints out the entire
2656     * subtree. Subclasses may override to provide a more succinct representation.
2657     * </p>
2658     *
2659     * @param buffer the string buffer to append to
2660     */

2661    void appendDebugString(StringBuffer JavaDoc buffer) {
2662        // print the subtree by default
2663
appendPrintString(buffer);
2664    }
2665        
2666    /**
2667     * Appends a standard Java source code representation of this subtree to the given
2668     * string buffer.
2669     *
2670     * @param buffer the string buffer to append to
2671     */

2672    final void appendPrintString(StringBuffer JavaDoc buffer) {
2673        NaiveASTFlattener printer = new NaiveASTFlattener();
2674        this.accept(printer);
2675        buffer.append(printer.getResult());
2676    }
2677    
2678    /**
2679     * Estimate of size of an object header in bytes.
2680     */

2681    static final int HEADERS = 12;
2682    
2683    /**
2684     * Approximate base size of an AST node instance in bytes,
2685     * including object header and instance fields.
2686     * That is, HEADERS + (# instance vars in ASTNode)*4.
2687     */

2688    static final int BASE_NODE_SIZE = HEADERS + 7 * 4;
2689    
2690    /**
2691     * Returns an estimate of the memory footprint, in bytes,
2692     * of the given string.
2693     *
2694     * @param string the string to measure, or <code>null</code>
2695     * @return the size of this string object in bytes, or
2696     * 0 if the string is <code>null</code>
2697     * @since 3.0
2698     */

2699    static int stringSize(String JavaDoc string) {
2700        int size = 0;
2701        if (string != null) {
2702            // Strings usually have 4 instance fields, one of which is a char[]
2703
size += HEADERS + 4 * 4;
2704            // char[] has 2 bytes per character
2705
size += HEADERS + 2 * string.length();
2706        }
2707        return size;
2708    }
2709    
2710    /**
2711     * Returns an estimate of the memory footprint in bytes of the entire
2712     * subtree rooted at this node.
2713     *
2714     * @return the size of this subtree in bytes
2715     */

2716    public final int subtreeBytes() {
2717        return treeSize();
2718    }
2719        
2720    /**
2721     * Returns an estimate of the memory footprint in bytes of the entire
2722     * subtree rooted at this node.
2723     * <p>
2724     * N.B. This method is package-private, so that the implementations
2725     * of this method in each of the concrete AST node types do not
2726     * clutter up the API doc.
2727     * </p>
2728     *
2729     * @return the size of this subtree in bytes
2730     */

2731    abstract int treeSize();
2732
2733    /**
2734     * Returns an estimate of the memory footprint of this node in bytes.
2735     * The estimate does not include the space occupied by child nodes.
2736     *
2737     * @return the size of this node in bytes
2738     */

2739    abstract int memSize();
2740}
2741
Popular Tags