a8f2347c9613c0ad9e790c291293e204dd628efe
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / core / dom / ASTNode.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
13
14 import java.util.AbstractList;
15 import java.util.ArrayList;
16 import java.util.Collections;
17 import java.util.HashMap;
18 import java.util.Iterator;
19 import java.util.List;
20 import java.util.Map;
21
22 import net.sourceforge.phpdt.internal.core.dom.NaiveASTFlattener;
23
24 /**
25  * Abstract superclass of all Abstract Syntax Tree (AST) node types.
26  * <p>
27  * An AST node represents a Java source code construct, such
28  * as a name, type, expression, statement, or declaration.
29  * </p>
30  * <p>
31  * Each AST node belongs to a unique AST instance, called the owning AST.
32  * The children of an AST node always have the same owner as their parent node.
33  * If a node from one AST is to be added to a different AST, the subtree must
34  * be cloned first to ensure that the added nodes have the correct owning AST.
35  * </p>
36  * <p>
37  * When an AST node is part of an AST, it has a unique parent node.
38  * Clients can navigate upwards, from child to parent, as well as downwards,
39  * from parent to child. Newly created nodes are unparented. When an 
40  * unparented node is set as a child of a node (using a 
41  * <code>set<i>CHILD</i></code> method), its parent link is set automatically
42  * and the parent link of the former child is set to <code>null</code>.
43  * For nodes with properties that include a list of children (for example,
44  * <code>Block</code> whose <code>statements</code> property is a list
45  * of statements), adding or removing an element to/for the list property
46  * automatically updates the parent links. These lists support the 
47  * <code>List.set</code> method; however, the constraint that the same
48  * node cannot appear more than once means that this method cannot be used
49  * to swap elements without first removing the node.
50  * </p>
51  * <p>
52  * ASTs must not contain cycles. All operations that could create a cycle
53  * detect this possibility and fail.
54  * </p>
55  * <p>
56  * ASTs do not contain "holes" (missing subtrees). If a node is required to
57  * have a certain property, a syntactically plausible initial value is
58  * always supplied. 
59  * </p>
60  * <p>
61  * The hierarchy of AST node types has some convenient groupings marked
62  * by abstract superclasses:
63  * <ul>
64  * <li>expressions - <code>Expression</code></li>
65  * <li>names - <code>Name</code> (a sub-kind of expression)</li>
66  * <li>statements - <code>Statement</code></li>
67  * <li>types - <code>Type</code></li>
68  * <li>type body declarations - <code>BodyDeclaration</code></li>
69  * </ul>
70  * </p>
71  * <p>
72  * Abstract syntax trees may be hand constructed by clients, using the
73  * <code>new<i>TYPE</i></code> factory methods (see <code>AST</code>) to
74  * create new nodes, and the various <code>set<i>CHILD</i></code> methods
75  * to connect them together.
76  * </p>
77  * <p>
78  * The class {@link ASTParser} parses a string
79  * containing a Java source code and returns an abstract syntax tree
80  * for it. The resulting nodes carry source ranges relating the node back to
81  * the original source characters. The source range covers the construct
82  * as a whole.
83  * </p>
84  * <p>
85  * Each AST node carries bit flags, which may convey additional information about
86  * the node. For instance, the parser uses a flag to indicate a syntax error.
87  * Newly created nodes have no flags set.
88  * </p>
89  * <p>
90  * Each AST node is capable of carrying an open-ended collection of
91  * client-defined properties. Newly created nodes have none. 
92  * <code>getProperty</code> and <code>setProperty</code> are used to access
93  * these properties.
94  * </p>
95  * <p>
96  * AST nodes are thread-safe for readers provided there are no active writers.
97  * If one thread is modifying an AST, including creating new nodes or cloning
98  * existing ones, it is <b>not</b> safe for another thread to read, visit,
99  * write, create, or clone <em>any</em> of the nodes on the same AST.
100  * When synchronization is required, consider using the common AST
101  * object that owns the node; that is, use  
102  * <code>synchronize (node.getAST()) {...}</code>.
103  * </p>
104  * <p>
105  * ASTs also support the visitor pattern; see the class <code>ASTVisitor</code>
106  * for details.
107  * </p>
108  * <p>
109  * Compilation units created by <code>ASTParser</code> from a
110  * source document can be serialized after arbitrary modifications
111  * with minimal loss of original formatting. See 
112  * {@link CompilationUnit#recordModifications()} for details.
113  * See also {@link org.eclipse.jdt.core.dom.rewrite.ASTRewrite} for
114  * an alternative way to describe and serialize changes to a
115  * read-only AST.
116  * </p>
117  * 
118  * @see ASTParser
119  * @see ASTVisitor
120  * @since 2.0
121  * @noextend This class is not intended to be subclassed by clients.
122  */
123 public abstract class ASTNode {
124         /*
125          * INSTRUCTIONS FOR ADDING NEW CONCRETE AST NODE TYPES
126          * 
127          * There are several things that need to be changed when a
128          * new concrete AST node type (call it "FooBar"):
129          * 
130          * 1. Create the FooBar AST node type class.
131          * The most effective way to do this is to copy a similar
132          * existing concrete node class to get a template that
133      * includes all the framework methods that must be implemented.
134          * 
135          * 2. Add node type constant ASTNode.FOO_BAR.
136          * Node constants are numbered consecutively. Add the
137          * constant after the existing ones.
138          * 
139          * 3. Add entry to ASTNode.nodeClassForType(int).
140          * 
141          * 4. Add AST.newFooBar() factory method.
142          * 
143          * 5. Add ASTVisitor.visit(FooBar) and endVisit(FooBar) methods.
144          * 
145          * 6. Add ASTMatcher.match(FooBar,Object) method.
146          * 
147          * 7. Ensure that SimpleName.isDeclaration() covers FooBar
148          * nodes if required.
149          * 
150          * 8. Add NaiveASTFlattener.visit(FooBar) method to illustrate
151          * how these nodes should be serialized.
152          * 
153          * 9. Update the AST test suites.
154          * 
155          * The next steps are to update AST.parse* to start generating
156          * the new type of nodes, and ASTRewrite to serialize them back out.
157          */
158         
159         /**
160          * Node type constant indicating a node of type 
161          * <code>AnonymousClassDeclaration</code>.
162          * @see AnonymousClassDeclaration
163          */
164         public static final int ANONYMOUS_CLASS_DECLARATION = 1;
165
166         /**
167          * Node type constant indicating a node of type 
168          * <code>ArrayAccess</code>.
169          * @see ArrayAccess
170          */
171         public static final int ARRAY_ACCESS = 2;
172
173         /**
174          * Node type constant indicating a node of type 
175          * <code>ArrayCreation</code>.
176          * @see ArrayCreation
177          */
178         public static final int ARRAY_CREATION = 3;
179
180         /**
181          * Node type constant indicating a node of type 
182          * <code>ArrayInitializer</code>.
183          * @see ArrayInitializer
184          */
185         public static final int ARRAY_INITIALIZER = 4;
186
187         /**
188          * Node type constant indicating a node of type 
189          * <code>ArrayType</code>.
190          * @see ArrayType
191          */
192         public static final int ARRAY_TYPE = 5;
193
194         /**
195          * Node type constant indicating a node of type 
196          * <code>AssertStatement</code>.
197          * @see AssertStatement
198          */
199         public static final int ASSERT_STATEMENT = 6;
200
201         /**
202          * Node type constant indicating a node of type 
203          * <code>Assignment</code>.
204          * @see Assignment
205          */
206         public static final int ASSIGNMENT = 7;
207
208         /**
209          * Node type constant indicating a node of type 
210          * <code>Block</code>.
211          * @see Block
212          */
213         public static final int BLOCK = 8;
214
215         /**
216          * Node type constant indicating a node of type 
217          * <code>BooleanLiteral</code>.
218          * @see BooleanLiteral
219          */
220         public static final int BOOLEAN_LITERAL = 9;
221
222         /**
223          * Node type constant indicating a node of type 
224          * <code>BreakStatement</code>.
225          * @see BreakStatement
226          */
227         public static final int BREAK_STATEMENT = 10;
228
229         /**
230          * Node type constant indicating a node of type 
231          * <code>CastExpression</code>.
232          * @see CastExpression
233          */
234         public static final int CAST_EXPRESSION = 11;
235
236         /**
237          * Node type constant indicating a node of type 
238          * <code>CatchClause</code>.
239          * @see CatchClause
240          */
241         public static final int CATCH_CLAUSE = 12;
242
243         /**
244          * Node type constant indicating a node of type 
245          * <code>CharacterLiteral</code>.
246          * @see CharacterLiteral
247          */
248         public static final int CHARACTER_LITERAL = 13;
249
250         /**
251          * Node type constant indicating a node of type 
252          * <code>ClassInstanceCreation</code>.
253          * @see ClassInstanceCreation
254          */
255         public static final int CLASS_INSTANCE_CREATION = 14;
256
257         /**
258          * Node type constant indicating a node of type 
259          * <code>CompilationUnit</code>.
260          * @see CompilationUnit
261          */
262         public static final int COMPILATION_UNIT = 15;
263
264         /**
265          * Node type constant indicating a node of type 
266          * <code>ConditionalExpression</code>.
267          * @see ConditionalExpression
268          */
269         public static final int CONDITIONAL_EXPRESSION = 16;
270
271         /**
272          * Node type constant indicating a node of type 
273          * <code>ConstructorInvocation</code>.
274          * @see ConstructorInvocation
275          */
276         public static final int CONSTRUCTOR_INVOCATION = 17;
277
278         /**
279          * Node type constant indicating a node of type 
280          * <code>ContinueStatement</code>.
281          * @see ContinueStatement
282          */
283         public static final int CONTINUE_STATEMENT = 18;
284
285         /**
286          * Node type constant indicating a node of type 
287          * <code>DoStatement</code>.
288          * @see DoStatement
289          */
290         public static final int DO_STATEMENT = 19;
291
292         /**
293          * Node type constant indicating a node of type 
294          * <code>EmptyStatement</code>.
295          * @see EmptyStatement
296          */
297         public static final int EMPTY_STATEMENT = 20;
298
299         /**
300          * Node type constant indicating a node of type 
301          * <code>ExpressionStatement</code>.
302          * @see ExpressionStatement
303          */
304         public static final int EXPRESSION_STATEMENT = 21;
305
306         /**
307          * Node type constant indicating a node of type 
308          * <code>FieldAccess</code>.
309          * @see FieldAccess
310          */
311         public static final int FIELD_ACCESS = 22;
312
313         /**
314          * Node type constant indicating a node of type 
315          * <code>FieldDeclaration</code>.
316          * @see FieldDeclaration
317          */
318         public static final int FIELD_DECLARATION = 23;
319
320         /**
321          * Node type constant indicating a node of type 
322          * <code>ForStatement</code>.
323          * @see ForStatement
324          */
325         public static final int FOR_STATEMENT = 24;
326
327         /**
328          * Node type constant indicating a node of type 
329          * <code>IfStatement</code>.
330          * @see IfStatement
331          */
332         public static final int IF_STATEMENT = 25;
333
334         /**
335          * Node type constant indicating a node of type 
336          * <code>ImportDeclaration</code>.
337          * @see ImportDeclaration
338          */
339         public static final int IMPORT_DECLARATION = 26;
340
341         /**
342          * Node type constant indicating a node of type 
343          * <code>InfixExpression</code>.
344          * @see InfixExpression
345          */
346         public static final int INFIX_EXPRESSION = 27;
347
348         /**
349          * Node type constant indicating a node of type 
350          * <code>Initializer</code>.
351          * @see Initializer
352          */
353         public static final int INITIALIZER = 28;
354
355         /**
356          * Node type constant indicating a node of type 
357          * <code>Javadoc</code>.
358          * @see Javadoc
359          */
360         public static final int JAVADOC = 29;
361
362         /**
363          * Node type constant indicating a node of type 
364          * <code>LabeledStatement</code>.
365          * @see LabeledStatement
366          */
367         public static final int LABELED_STATEMENT = 30;
368
369         /**
370          * Node type constant indicating a node of type 
371          * <code>MethodDeclaration</code>.
372          * @see MethodDeclaration
373          */
374         public static final int METHOD_DECLARATION = 31;
375
376         /**
377          * Node type constant indicating a node of type 
378          * <code>MethodInvocation</code>.
379          * @see MethodInvocation
380          */
381         public static final int METHOD_INVOCATION = 32;
382
383         /**
384          * Node type constant indicating a node of type 
385          * <code>NullLiteral</code>.
386          * @see NullLiteral
387          */
388         public static final int NULL_LITERAL = 33;
389
390         /**
391          * Node type constant indicating a node of type 
392          * <code>NumberLiteral</code>.
393          * @see NumberLiteral
394          */
395         public static final int NUMBER_LITERAL = 34;
396
397         /**
398          * Node type constant indicating a node of type 
399          * <code>PackageDeclaration</code>.
400          * @see PackageDeclaration
401          */
402         public static final int PACKAGE_DECLARATION = 35;
403
404         /**
405          * Node type constant indicating a node of type 
406          * <code>ParenthesizedExpression</code>.
407          * @see ParenthesizedExpression
408          */
409         public static final int PARENTHESIZED_EXPRESSION = 36;
410
411         /**
412          * Node type constant indicating a node of type 
413          * <code>PostfixExpression</code>.
414          * @see PostfixExpression
415          */
416         public static final int POSTFIX_EXPRESSION = 37;
417
418         /**
419          * Node type constant indicating a node of type 
420          * <code>PrefixExpression</code>.
421          * @see PrefixExpression
422          */
423         public static final int PREFIX_EXPRESSION = 38;
424
425         /**
426          * Node type constant indicating a node of type 
427          * <code>PrimitiveType</code>.
428          * @see PrimitiveType
429          */
430         public static final int PRIMITIVE_TYPE = 39;
431
432         /**
433          * Node type constant indicating a node of type 
434          * <code>QualifiedName</code>.
435          * @see QualifiedName
436          */
437         public static final int QUALIFIED_NAME = 40;
438
439         /**
440          * Node type constant indicating a node of type 
441          * <code>ReturnStatement</code>.
442          * @see ReturnStatement
443          */
444         public static final int RETURN_STATEMENT = 41;
445
446         /**
447          * Node type constant indicating a node of type 
448          * <code>SimpleName</code>.
449          * @see SimpleName
450          */
451         public static final int SIMPLE_NAME = 42;
452
453         /**
454          * Node type constant indicating a node of type 
455          * <code>SimpleType</code>.
456          * @see SimpleType
457          */
458         public static final int SIMPLE_TYPE = 43;
459
460         /**
461          * Node type constant indicating a node of type 
462          * <code>SingleVariableDeclaration</code>.
463          * @see SingleVariableDeclaration
464          */
465         public static final int SINGLE_VARIABLE_DECLARATION = 44;
466
467         /**
468          * Node type constant indicating a node of type 
469          * <code>StringLiteral</code>.
470          * @see StringLiteral
471          */
472         public static final int STRING_LITERAL = 45;
473
474         /**
475          * Node type constant indicating a node of type 
476          * <code>SuperConstructorInvocation</code>.
477          * @see SuperConstructorInvocation
478          */
479         public static final int SUPER_CONSTRUCTOR_INVOCATION = 46;
480
481         /**
482          * Node type constant indicating a node of type 
483          * <code>SuperFieldAccess</code>.
484          * @see SuperFieldAccess
485          */
486         public static final int SUPER_FIELD_ACCESS = 47;
487
488         /**
489          * Node type constant indicating a node of type 
490          * <code>SuperMethodInvocation</code>.
491          * @see SuperMethodInvocation
492          */
493         public static final int SUPER_METHOD_INVOCATION = 48;
494
495         /**
496          * Node type constant indicating a node of type 
497          * <code>SwitchCase</code>.
498          * @see SwitchCase
499          */
500         public static final int SWITCH_CASE = 49;
501
502         /**
503          * Node type constant indicating a node of type 
504          * <code>SwitchStatement</code>.
505          * @see SwitchStatement
506          */
507         public static final int SWITCH_STATEMENT = 50;
508
509         /**
510          * Node type constant indicating a node of type 
511          * <code>SynchronizedStatement</code>.
512          * @see SynchronizedStatement
513          */
514         public static final int SYNCHRONIZED_STATEMENT = 51;
515
516         /**
517          * Node type constant indicating a node of type 
518          * <code>ThisExpression</code>.
519          * @see ThisExpression
520          */
521         public static final int THIS_EXPRESSION = 52;
522
523         /**
524          * Node type constant indicating a node of type 
525          * <code>ThrowStatement</code>.
526          * @see ThrowStatement
527          */
528         public static final int THROW_STATEMENT = 53;
529
530         /**
531          * Node type constant indicating a node of type 
532          * <code>TryStatement</code>.
533          * @see TryStatement
534          */
535         public static final int TRY_STATEMENT = 54;
536
537         /**
538          * Node type constant indicating a node of type 
539          * <code>TypeDeclaration</code>.
540          * @see TypeDeclaration
541          */
542         public static final int TYPE_DECLARATION = 55;
543
544         /**
545          * Node type constant indicating a node of type 
546          * <code>TypeDeclarationStatement</code>.
547          * @see TypeDeclarationStatement
548          */
549         public static final int TYPE_DECLARATION_STATEMENT = 56;
550
551         /**
552          * Node type constant indicating a node of type 
553          * <code>TypeLiteral</code>.
554          * @see TypeLiteral
555          */
556         public static final int TYPE_LITERAL = 57;
557
558         /**
559          * Node type constant indicating a node of type 
560          * <code>VariableDeclarationExpression</code>.
561          * @see VariableDeclarationExpression
562          */
563         public static final int VARIABLE_DECLARATION_EXPRESSION = 58;
564
565         /**
566          * Node type constant indicating a node of type 
567          * <code>VariableDeclarationFragment</code>.
568          * @see VariableDeclarationFragment
569          */
570         public static final int VARIABLE_DECLARATION_FRAGMENT = 59;
571
572         /**
573          * Node type constant indicating a node of type 
574          * <code>VariableDeclarationStatement</code>.
575          * @see VariableDeclarationStatement
576          */
577         public static final int VARIABLE_DECLARATION_STATEMENT = 60;
578
579         /**
580          * Node type constant indicating a node of type 
581          * <code>WhileStatement</code>.
582          * @see WhileStatement
583          */
584         public static final int WHILE_STATEMENT = 61;
585
586         /**
587          * Node type constant indicating a node of type 
588          * <code>InstanceofExpression</code>.
589          * @see InstanceofExpression
590          */
591         public static final int INSTANCEOF_EXPRESSION = 62;
592
593         /**
594          * Node type constant indicating a node of type 
595          * <code>LineComment</code>.
596          * @see LineComment
597          * @since 3.0
598          */
599         public static final int LINE_COMMENT = 63;
600
601         /**
602          * Node type constant indicating a node of type 
603          * <code>BlockComment</code>.
604          * @see BlockComment
605          * @since 3.0
606          */
607         public static final int BLOCK_COMMENT = 64;
608
609         /**
610          * Node type constant indicating a node of type 
611          * <code>TagElement</code>.
612          * @see TagElement
613          * @since 3.0
614          */
615         public static final int TAG_ELEMENT = 65;
616
617         /**
618          * Node type constant indicating a node of type 
619          * <code>TextElement</code>.
620          * @see TextElement
621          * @since 3.0
622          */
623         public static final int TEXT_ELEMENT = 66;
624
625         /**
626          * Node type constant indicating a node of type 
627          * <code>MemberRef</code>.
628          * @see MemberRef
629          * @since 3.0
630          */
631         public static final int MEMBER_REF = 67;
632
633         /**
634          * Node type constant indicating a node of type 
635          * <code>MethodRef</code>.
636          * @see MethodRef
637          * @since 3.0
638          */
639         public static final int METHOD_REF = 68;
640
641         /**
642          * Node type constant indicating a node of type 
643          * <code>MethodRefParameter</code>.
644          * @see MethodRefParameter
645          * @since 3.0
646          */
647         public static final int METHOD_REF_PARAMETER = 69;
648
649         /**
650          * Node type constant indicating a node of type 
651          * <code>EnhancedForStatement</code>.
652          * @see EnhancedForStatement
653          * @since 3.1
654          */
655         public static final int ENHANCED_FOR_STATEMENT = 70;
656
657         /**
658          * Node type constant indicating a node of type 
659          * <code>EnumDeclaration</code>.
660          * @see EnumDeclaration
661          * @since 3.1
662          */
663         public static final int ENUM_DECLARATION = 71;
664         
665         /**
666          * Node type constant indicating a node of type 
667          * <code>EnumConstantDeclaration</code>.
668          * @see EnumConstantDeclaration
669          * @since 3.1
670          */
671         public static final int ENUM_CONSTANT_DECLARATION = 72;
672         
673         /**
674          * Node type constant indicating a node of type 
675          * <code>TypeParameter</code>.
676          * @see TypeParameter
677          * @since 3.1
678          */
679         public static final int TYPE_PARAMETER = 73;
680
681         /**
682          * Node type constant indicating a node of type 
683          * <code>ParameterizedType</code>.
684          * @see ParameterizedType
685          * @since 3.1
686          */
687         public static final int PARAMETERIZED_TYPE = 74;
688
689         /**
690          * Node type constant indicating a node of type 
691          * <code>QualifiedType</code>.
692          * @see QualifiedType
693          * @since 3.1
694          */
695         public static final int QUALIFIED_TYPE = 75;
696         
697         /**
698          * Node type constant indicating a node of type 
699          * <code>WildcardType</code>.
700          * @see WildcardType
701          * @since 3.1
702          */
703         public static final int WILDCARD_TYPE = 76;
704         
705         /**
706          * Node type constant indicating a node of type 
707          * <code>NormalAnnotation</code>.
708          * @see NormalAnnotation
709          * @since 3.1
710          */
711         public static final int NORMAL_ANNOTATION = 77;
712         
713         /**
714          * Node type constant indicating a node of type 
715          * <code>MarkerAnnotation</code>.
716          * @see MarkerAnnotation
717          * @since 3.1
718          */
719         public static final int MARKER_ANNOTATION = 78;
720         
721         /**
722          * Node type constant indicating a node of type 
723          * <code>SingleMemberAnnotation</code>.
724          * @see SingleMemberAnnotation
725          * @since 3.1
726          */
727         public static final int SINGLE_MEMBER_ANNOTATION = 79;
728         
729         /**
730          * Node type constant indicating a node of type 
731          * <code>MemberValuePair</code>.
732          * @see MemberValuePair
733          * @since 3.1
734          */
735         public static final int MEMBER_VALUE_PAIR = 80;
736         
737         /**
738          * Node type constant indicating a node of type 
739          * <code>AnnotationTypeDeclaration</code>.
740          * @see AnnotationTypeDeclaration
741          * @since 3.1
742          */
743         public static final int ANNOTATION_TYPE_DECLARATION = 81;
744         
745         /**
746          * Node type constant indicating a node of type 
747          * <code>AnnotationTypeMemberDeclaration</code>.
748          * @see AnnotationTypeMemberDeclaration
749          * @since 3.1
750          */
751         public static final int ANNOTATION_TYPE_MEMBER_DECLARATION = 82;
752         
753         /**
754          * Node type constant indicating a node of type 
755          * <code>Modifier</code>.
756          * @see Modifier
757          * @since 3.1
758          */
759         public static final int MODIFIER = 83;
760         
761         /**
762          * Returns the node class for the corresponding node type.
763          * 
764          * @param nodeType AST node type
765          * @return the corresponding <code>ASTNode</code> subclass
766          * @exception IllegalArgumentException if <code>nodeType</code> is 
767          * not a legal AST node type
768          * @see #getNodeType()
769          * @since 3.0
770          */
771         public static Class nodeClassForType(int nodeType) {
772                 switch (nodeType) {
773                         case ANNOTATION_TYPE_DECLARATION :
774                                 return AnnotationTypeDeclaration.class;
775                         case ANNOTATION_TYPE_MEMBER_DECLARATION :
776                                 return AnnotationTypeMemberDeclaration.class;
777                         case ANONYMOUS_CLASS_DECLARATION :
778                                 return AnonymousClassDeclaration.class;
779                         case ARRAY_ACCESS :
780                                 return ArrayAccess.class;
781                         case ARRAY_CREATION :
782                                 return ArrayCreation.class;
783                         case ARRAY_INITIALIZER :
784                                 return ArrayInitializer.class;
785                         case ARRAY_TYPE :
786                                 return ArrayType.class;
787                         case ASSERT_STATEMENT :
788                                 return AssertStatement.class;
789                         case ASSIGNMENT :
790                                 return Assignment.class;
791                         case BLOCK :
792                                 return Block.class;
793                         case BLOCK_COMMENT :
794                                 return BlockComment.class;
795                         case BOOLEAN_LITERAL :
796                                 return BooleanLiteral.class;
797                         case BREAK_STATEMENT :
798                                 return BreakStatement.class;
799                         case CAST_EXPRESSION :
800                                 return CastExpression.class;
801                         case CATCH_CLAUSE :
802                                 return CatchClause.class;
803                         case CHARACTER_LITERAL :
804                                 return CharacterLiteral.class;
805                         case CLASS_INSTANCE_CREATION :
806                                 return ClassInstanceCreation.class;
807                         case COMPILATION_UNIT :
808                                 return CompilationUnit.class;
809                         case CONDITIONAL_EXPRESSION :
810                                 return ConditionalExpression.class;
811                         case CONSTRUCTOR_INVOCATION :
812                                 return ConstructorInvocation.class;
813                         case CONTINUE_STATEMENT :
814                                 return ContinueStatement.class;
815                         case DO_STATEMENT :
816                                 return DoStatement.class;
817                         case EMPTY_STATEMENT :
818                                 return EmptyStatement.class;
819                         case ENHANCED_FOR_STATEMENT :
820                                 return EnhancedForStatement.class;
821                         case ENUM_CONSTANT_DECLARATION :
822                                 return EnumConstantDeclaration.class;
823                         case ENUM_DECLARATION :
824                                 return EnumDeclaration.class;
825                         case EXPRESSION_STATEMENT :
826                                 return ExpressionStatement.class;
827                         case FIELD_ACCESS :
828                                 return FieldAccess.class;
829                         case FIELD_DECLARATION :
830                                 return FieldDeclaration.class;
831                         case FOR_STATEMENT :
832                                 return ForStatement.class;
833                         case IF_STATEMENT :
834                                 return IfStatement.class;
835                         case IMPORT_DECLARATION :
836                                 return ImportDeclaration.class;
837                         case INFIX_EXPRESSION :
838                                 return InfixExpression.class;
839                         case INITIALIZER :
840                                 return Initializer.class;
841                         case INSTANCEOF_EXPRESSION :
842                                 return InstanceofExpression.class;
843                         case JAVADOC :
844                                 return Javadoc.class;
845                         case LABELED_STATEMENT :
846                                 return LabeledStatement.class;
847                         case LINE_COMMENT :
848                                 return LineComment.class;
849                         case MARKER_ANNOTATION :
850                                 return MarkerAnnotation.class;
851                         case MEMBER_REF :
852                                 return MemberRef.class;
853                         case MEMBER_VALUE_PAIR :
854                                 return MemberValuePair.class;
855                         case METHOD_DECLARATION :
856                                 return MethodDeclaration.class;
857                         case METHOD_INVOCATION :
858                                 return MethodInvocation.class;
859                         case METHOD_REF :
860                                 return MethodRef.class;
861                         case METHOD_REF_PARAMETER :
862                                 return MethodRefParameter.class;
863                         case MODIFIER :
864                                 return Modifier.class;
865                         case NORMAL_ANNOTATION :
866                                 return NormalAnnotation.class;
867                         case NULL_LITERAL :
868                                 return NullLiteral.class;
869                         case NUMBER_LITERAL :
870                                 return NumberLiteral.class;
871                         case PACKAGE_DECLARATION :
872                                 return PackageDeclaration.class;
873                         case PARAMETERIZED_TYPE :
874                                 return ParameterizedType.class;
875                         case PARENTHESIZED_EXPRESSION :
876                                 return ParenthesizedExpression.class;
877                         case POSTFIX_EXPRESSION :
878                                 return PostfixExpression.class;
879                         case PREFIX_EXPRESSION :
880                                 return PrefixExpression.class;
881                         case PRIMITIVE_TYPE :
882                                 return PrimitiveType.class;
883                         case QUALIFIED_NAME :
884                                 return QualifiedName.class;
885                         case QUALIFIED_TYPE :
886                                 return QualifiedType.class;
887                         case RETURN_STATEMENT :
888                                 return ReturnStatement.class;
889                         case SIMPLE_NAME :
890                                 return SimpleName.class;
891                         case SIMPLE_TYPE :
892                                 return SimpleType.class;
893                         case SINGLE_MEMBER_ANNOTATION :
894                                 return SingleMemberAnnotation.class;
895                         case SINGLE_VARIABLE_DECLARATION :
896                                 return SingleVariableDeclaration.class;
897                         case STRING_LITERAL :
898                                 return StringLiteral.class;
899                         case SUPER_CONSTRUCTOR_INVOCATION :
900                                 return SuperConstructorInvocation.class;
901                         case SUPER_FIELD_ACCESS :
902                                 return SuperFieldAccess.class;
903                         case SUPER_METHOD_INVOCATION :
904                                 return SuperMethodInvocation.class;
905                         case SWITCH_CASE:
906                                 return SwitchCase.class;
907                         case SWITCH_STATEMENT :
908                                 return SwitchStatement.class;
909                         case SYNCHRONIZED_STATEMENT :
910                                 return SynchronizedStatement.class;
911                         case TAG_ELEMENT :
912                                 return TagElement.class;
913                         case TEXT_ELEMENT :
914                                 return TextElement.class;
915                         case THIS_EXPRESSION :
916                                 return ThisExpression.class;
917                         case THROW_STATEMENT :
918                                 return ThrowStatement.class;
919                         case TRY_STATEMENT :
920                                 return TryStatement.class;
921                         case TYPE_DECLARATION :
922                                 return TypeDeclaration.class;
923                         case TYPE_DECLARATION_STATEMENT :
924                                 return TypeDeclarationStatement.class;
925                         case TYPE_LITERAL :
926                                 return TypeLiteral.class;
927                         case TYPE_PARAMETER :
928                                 return TypeParameter.class;
929                         case VARIABLE_DECLARATION_EXPRESSION :
930                                 return VariableDeclarationExpression.class;
931                         case VARIABLE_DECLARATION_FRAGMENT :
932                                 return VariableDeclarationFragment.class;
933                         case VARIABLE_DECLARATION_STATEMENT :
934                                 return VariableDeclarationStatement.class;
935                         case WHILE_STATEMENT :
936                                 return WhileStatement.class;
937                         case WILDCARD_TYPE :
938                                 return WildcardType.class;
939                 }
940                 throw new IllegalArgumentException();
941         }
942         
943         /**
944          * Owning AST.
945      * <p>
946      * N.B. This ia a private field, but declared as package-visible
947      * for more efficient access from inner classes.
948      * </p>
949          */
950         final AST ast;
951         
952         /**
953          * Parent AST node, or <code>null</code> if this node is a root.
954          * Initially <code>null</code>.
955          */
956         private ASTNode parent = null;
957         
958         /**
959          * An unmodifiable empty map (used to implement <code>properties()</code>).
960          */
961         private static final Map UNMODIFIABLE_EMPTY_MAP
962                 = Collections.unmodifiableMap(new HashMap(1));
963         
964         /**
965          * Primary field used in representing node properties efficiently.
966          * If <code>null</code>, this node has no properties.
967          * If a <code>String</code>, this is the name of this node's sole property,
968          * and <code>property2</code> contains its value.
969          * If a <code>HashMap</code>, this is the table of property name-value
970          * mappings; <code>property2</code>, if non-null is its unmodifiable
971          * equivalent.
972          * Initially <code>null</code>.
973          * 
974          * @see #property2
975          */
976         private Object property1 = null;
977         
978         /**
979          * Auxillary field used in representing node properties efficiently.
980          * 
981          * @see #property1
982          */
983         private Object property2 = null;
984         
985         /**
986          * A character index into the original source string, 
987          * or <code>-1</code> if no source position information is available
988          * for this node; <code>-1</code> by default.
989          */
990         private int startPosition = -1;
991
992         /**
993          * A character length, or <code>0</code> if no source position
994          * information is recorded for this node; <code>0</code> by default.
995          */
996         private int length = 0;
997         
998         /**
999          * Flag constant (bit mask, value 1) indicating that there is something
1000          * not quite right with this AST node.
1001          * <p>
1002          * The standard parser (<code>ASTParser</code>) sets this
1003          * flag on a node to indicate a syntax error detected in the vicinity.
1004          * </p>
1005          */
1006         public static final int MALFORMED = 1;
1007
1008         /**
1009          * Flag constant (bit mask, value 2) indicating that this is a node
1010          * that was created by the parser (as opposed to one created by another
1011          * party).
1012          * <p>
1013          * The standard parser (<code>ASTParser</code>) sets this
1014          * flag on the nodes it creates.
1015          * </p>
1016          * @since 3.0
1017          */
1018         public static final int ORIGINAL = 2;
1019
1020         /**
1021          * Flag constant (bit mask, value 4) indicating that this node
1022          * is unmodifiable. When a node is marked unmodifiable, the
1023          * following operations result in a runtime exception:
1024          * <ul>
1025          * <li>Change a simple property of this node.</li>
1026          * <li>Add or remove a child node from this node.</li>
1027          * <li>Parent (or reparent) this node.</li>
1028          * </ul>
1029          * <p>
1030          * The standard parser (<code>ASTParser</code>) does not set
1031          * this flag on the nodes it creates. However, clients may set
1032          * this flag on a node to prevent further modification of the
1033          * its structural properties.
1034          * </p>
1035          * @since 3.0
1036          */
1037         public static final int PROTECT = 4;
1038
1039         /**
1040          * Flag constant (bit mask, value 8) indicating that this node
1041          * or a part of this node is recovered from source that contains
1042          * a syntax error detected in the vicinity.
1043          * <p>
1044          * The standard parser (<code>ASTParser</code>) sets this
1045          * flag on a node to indicate a recovered node.
1046          * </p>
1047          * @since 3.2
1048          */
1049         public static final int RECOVERED = 8;
1050         
1051         /**
1052          * int containing the node type in the top 16 bits and
1053          * flags in the bottom 16 bits; none set by default.
1054      * <p>
1055      * N.B. This is a private field, but declared as package-visible
1056      * for more efficient access from inner classes.
1057      * </p>
1058          * 
1059          * @see #MALFORMED
1060          */
1061         int typeAndFlags = 0;
1062                 
1063         /**
1064          * Property of parent in which this node is a child, or <code>null</code>
1065          * if this node is a root. Initially <code>null</code>.
1066          * 
1067          * @see #getLocationInParent
1068          * @since 3.0
1069          */
1070         private StructuralPropertyDescriptor location = null;
1071         
1072         /** Internal convenience constant indicating that there is definite risk of cycles.
1073          * @since 3.0
1074          */ 
1075         static final boolean CYCLE_RISK = true;
1076         
1077         /** Internal convenience constant indicating that there is no risk of cycles.
1078          * @since 3.0
1079          */ 
1080         static final boolean NO_CYCLE_RISK = false;
1081         
1082         /** Internal convenience constant indicating that a structural property is mandatory.
1083          * @since 3.0
1084          */ 
1085         static final boolean MANDATORY = true;
1086         
1087         /** Internal convenience constant indicating that a structural property is optional.
1088          * @since 3.0
1089          */ 
1090         static final boolean OPTIONAL = false;
1091         
1092         /**
1093          * A specialized implementation of a list of ASTNodes. The
1094          * implementation is based on an ArrayList.
1095          */ 
1096         class NodeList extends AbstractList {
1097                 
1098                 /**
1099                  * The underlying list in which the nodes of this list are
1100                  * stored (element type: <code>ASTNode</code>).
1101                  * <p>
1102                  * Be stingy on storage - assume that list will be empty.
1103                  * </p>
1104                  * <p>
1105                  * This field declared default visibility (rather than private)
1106                  * so that accesses from <code>NodeList.Cursor</code> do not require
1107                  * a synthetic accessor method.
1108                  * </p>
1109                  */
1110                 ArrayList store = new ArrayList(0);
1111                 
1112                 /**
1113                  * The property descriptor for this list.
1114                  */
1115                 ChildListPropertyDescriptor propertyDescriptor;
1116                 
1117                 /**
1118                  * A cursor for iterating over the elements of the list.
1119                  * Does not lose its position if the list is changed during
1120                  * the iteration.
1121                  */
1122                 class Cursor implements Iterator {
1123                         /**
1124                          * The position of the cursor between elements. If the value
1125                          * is N, then the cursor sits between the element at positions
1126                          * N-1 and N. Initially just before the first element of the
1127                          * list.
1128                          */
1129                         private int position = 0;
1130                         
1131                         /* (non-Javadoc)
1132                          * Method declared on <code>Iterator</code>.
1133                          */
1134                         public boolean hasNext() {
1135                                 return this.position < NodeList.this.store.size();
1136                         }
1137                         
1138                         /* (non-Javadoc)
1139                          * Method declared on <code>Iterator</code>.
1140                          */
1141                         public Object next() {
1142                                 Object result = NodeList.this.store.get(this.position);
1143                                 this.position++;
1144                                 return result;
1145                     }
1146                         
1147                         /* (non-Javadoc)
1148                          * Method declared on <code>Iterator</code>.
1149                          */
1150                         public void remove() {
1151                                 throw new UnsupportedOperationException();
1152                         }
1153                         
1154                         /**
1155                          * Adjusts this cursor to accomodate an add/remove at the given
1156                          * index.
1157                          * 
1158                          * @param index the position at which the element was added
1159                          *    or removed
1160                          * @param delta +1 for add, and -1 for remove
1161                          */
1162                         void update(int index, int delta) {
1163                                 if (this.position > index) {
1164                                         // the cursor has passed the added or removed element
1165                                         this.position += delta;
1166                                 }
1167                         }
1168                 }
1169
1170                 /**
1171                  * A list of currently active cursors (element type:
1172                  * <code>Cursor</code>), or <code>null</code> if there are no
1173                  * active cursors.
1174                  * <p>
1175                  * It is important for storage considerations to maintain the
1176                  * null-means-empty invariant; otherwise, every NodeList instance
1177                  * will waste a lot of space. A cursor is needed only for the duration
1178                  * of a visit to the child nodes. Under normal circumstances, only a 
1179                  * single cursor is needed; multiple cursors are only required if there
1180                  * are multiple visits going on at the same time.
1181                  * </p>
1182                  */
1183                 private List cursors = null;
1184
1185                 /**
1186                  * Creates a new empty list of nodes owned by this node.
1187                  * This node will be the common parent of all nodes added to 
1188                  * this list.
1189                  * 
1190                  * @param property the property descriptor
1191                  * @since 3.0
1192                  */
1193                 NodeList(ChildListPropertyDescriptor property) {
1194                         super();
1195                         this.propertyDescriptor = property;
1196                 }
1197         
1198                 /* (non-javadoc)
1199                  * @see java.util.AbstractCollection#size()
1200                  */
1201                 public int size() {
1202                         return this.store.size();
1203                 }
1204         
1205                 /* (non-javadoc)
1206                  * @see AbstractList#get(int)
1207                  */
1208                 public Object get(int index) {
1209                         return this.store.get(index);
1210                 }
1211         
1212                 /* (non-javadoc)
1213                  * @see List#set(int, java.lang.Object)
1214                  */
1215                 public Object set(int index, Object element) {
1216                     if (element == null) {
1217                         throw new IllegalArgumentException();
1218                     }
1219                         if ((ASTNode.this.typeAndFlags & PROTECT) != 0) {
1220                                 // this node is protected => cannot gain or lose children
1221                                 throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
1222                         }
1223                         // delink old child from parent, and link new child to parent
1224                         ASTNode newChild = (ASTNode) element;
1225                         ASTNode oldChild = (ASTNode) this.store.get(index);
1226                         if (oldChild == newChild) {
1227                                 return oldChild;
1228                         }
1229                         if ((oldChild.typeAndFlags & PROTECT) != 0) {
1230                                 // old child is protected => cannot be unparented
1231                                 throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
1232                         }
1233                         ASTNode.checkNewChild(ASTNode.this, newChild, this.propertyDescriptor.cycleRisk, this.propertyDescriptor.elementType);
1234                         ASTNode.this.ast.preReplaceChildEvent(ASTNode.this, oldChild, newChild, this.propertyDescriptor);
1235                         
1236                         Object result = this.store.set(index, newChild);
1237                         // n.b. setParent will call ast.modifying()
1238                         oldChild.setParent(null, null);
1239                         newChild.setParent(ASTNode.this, this.propertyDescriptor);
1240                         ASTNode.this.ast.postReplaceChildEvent(ASTNode.this, oldChild, newChild, this.propertyDescriptor);
1241                         return result;
1242                 }
1243                 
1244                 /* (non-javadoc)
1245                  * @see List#add(int, java.lang.Object)
1246                  */
1247                 public void add(int index, Object element) {
1248                     if (element == null) {
1249                         throw new IllegalArgumentException();
1250                     }
1251                         if ((ASTNode.this.typeAndFlags & PROTECT) != 0) {
1252                                 // this node is protected => cannot gain or lose children
1253                                 throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
1254                         }
1255                         // link new child to parent
1256                         ASTNode newChild = (ASTNode) element;
1257                         ASTNode.checkNewChild(ASTNode.this, newChild, this.propertyDescriptor.cycleRisk, this.propertyDescriptor.elementType);
1258                         ASTNode.this.ast.preAddChildEvent(ASTNode.this, newChild, this.propertyDescriptor);
1259                         
1260                         
1261                         this.store.add(index, element);
1262                         updateCursors(index, +1);
1263                         // n.b. setParent will call ast.modifying()
1264                         newChild.setParent(ASTNode.this, this.propertyDescriptor);
1265                         ASTNode.this.ast.postAddChildEvent(ASTNode.this, newChild, this.propertyDescriptor);
1266                 }
1267                 
1268                 /* (non-javadoc)
1269                  * @see List#remove(int)
1270                  */
1271                 public Object remove(int index) {
1272                         if ((ASTNode.this.typeAndFlags & PROTECT) != 0) {
1273                                 // this node is protected => cannot gain or lose children
1274                                 throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
1275                         }
1276                         // delink old child from parent
1277                         ASTNode oldChild = (ASTNode) this.store.get(index);
1278                         if ((oldChild.typeAndFlags & PROTECT) != 0) {
1279                                 // old child is protected => cannot be unparented
1280                                 throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
1281                         }
1282                         
1283                         ASTNode.this.ast.preRemoveChildEvent(ASTNode.this, oldChild, this.propertyDescriptor);
1284                         // n.b. setParent will call ast.modifying()
1285                         oldChild.setParent(null, null);
1286                         Object result = this.store.remove(index);
1287                         updateCursors(index, -1);
1288                         ASTNode.this.ast.postRemoveChildEvent(ASTNode.this, oldChild, this.propertyDescriptor);
1289                         return result;
1290
1291                 }
1292                 
1293                 /**
1294                  * Allocate a cursor to use for a visit. The client must call
1295                  * <code>releaseCursor</code> when done.
1296                  * <p>
1297                  * This method is internally synchronized on this NodeList.
1298                  * It is thread-safe to create a cursor.
1299                  * </p>
1300                  * 
1301                  * @return a new cursor positioned before the first element 
1302                  *    of the list
1303                  */
1304                 Cursor newCursor() {
1305                         synchronized (this) {
1306                                 // serialize cursor management on this NodeList
1307                                 if (this.cursors == null) {
1308                                         // convert null to empty list
1309                                         this.cursors = new ArrayList(1);
1310                                 }
1311                                 Cursor result = new Cursor();
1312                                 this.cursors.add(result);
1313                                 return result;
1314                         }
1315                 }
1316                 
1317                 /**
1318                  * Releases the given cursor at the end of a visit.
1319                  * <p>
1320                  * This method is internally synchronized on this NodeList.
1321                  * It is thread-safe to release a cursor.
1322                  * </p>
1323                  * 
1324                  * @param cursor the cursor
1325                  */
1326                 void releaseCursor(Cursor cursor) {
1327                         synchronized (this) {
1328                                 // serialize cursor management on this NodeList
1329                                 this.cursors.remove(cursor);
1330                                 if (this.cursors.isEmpty()) {
1331                                         // important: convert empty list back to null
1332                                         // otherwise the node will hang on to needless junk
1333                                         this.cursors = null;
1334                                 }
1335                         }
1336                 }
1337
1338                 /**
1339                  * Adjusts all cursors to accomodate an add/remove at the given
1340                  * index.
1341                  * <p>
1342                  * This method is only used when the list is being modified.
1343                  * The AST is not thread-safe if any of the clients are modifying it.
1344                  * </p>
1345                  * 
1346                  * @param index the position at which the element was added
1347                  *    or removed
1348                  * @param delta +1 for add, and -1 for remove
1349                  */
1350                 private void updateCursors(int index, int delta) {
1351                         if (this.cursors == null) {
1352                                 // there are no cursors to worry about
1353                                 return;
1354                         }
1355                         for (Iterator it = this.cursors.iterator(); it.hasNext(); ) {
1356                                 Cursor c = (Cursor) it.next();
1357                                 c.update(index, delta);
1358                         }
1359                 }
1360                 
1361                 /**
1362                  * Returns an estimate of the memory footprint of this node list 
1363                  * instance in bytes.
1364              * <ul>
1365              * <li>1 object header for the NodeList instance</li>
1366              * <li>5 4-byte fields of the NodeList instance</li>
1367              * <li>0 for cursors since null unless walk in progress</li>
1368              * <li>1 object header for the ArrayList instance</li>
1369              * <li>2 4-byte fields of the ArrayList instance</li>
1370              * <li>1 object header for an Object[] instance</li>
1371              * <li>4 bytes in array for each element</li>
1372              * </ul>
1373                  * 
1374                  * @return the size of this node list in bytes
1375                  */
1376                 int memSize() {
1377                         int result = HEADERS + 5 * 4;
1378                         result += HEADERS + 2 * 4;
1379                         result += HEADERS + 4 * size();
1380                         return result;
1381                 }
1382
1383                 /**
1384                  * Returns an estimate of the memory footprint in bytes of this node
1385                  * list and all its subtrees.
1386                  * 
1387                  * @return the size of this list of subtrees in bytes
1388                  */
1389                 int listSize() {
1390                         int result = memSize();
1391                         for (Iterator it = iterator(); it.hasNext(); ) {
1392                                 ASTNode child = (ASTNode) it.next();
1393                                 result += child.treeSize();
1394                         }
1395                         return result;
1396                 }
1397         }
1398
1399         /**
1400          * Creates a new AST node owned by the given AST. Once established,
1401          * the relationship between an AST node and its owning AST does not change
1402          * over the lifetime of the node. The new node has no parent node,
1403          * and no properties.
1404          * <p>
1405          * N.B. This constructor is package-private; all subclasses my be 
1406          * declared in the same package; clients are unable to declare 
1407          * additional subclasses.
1408          * </p>
1409          * 
1410          * @param ast the AST that is to own this node
1411          */
1412         ASTNode(AST ast) {
1413                 if (ast == null) {
1414                         throw new IllegalArgumentException();
1415                 }
1416                 
1417                 this.ast = ast;
1418                 setNodeType(getNodeType0());
1419                 setFlags(ast.getDefaultNodeFlag());
1420                 // setFlags calls modifying();
1421         }
1422         
1423         /**
1424          * Returns this node's AST.
1425          * <p>
1426          * Note that the relationship between an AST node and its owing AST does
1427          * not change over the lifetime of a node.
1428          * </p>
1429          * 
1430          * @return the AST that owns this node
1431          */ 
1432         public final AST getAST() {
1433                 return this.ast;
1434         }
1435         
1436         /**
1437          * Returns this node's parent node, or <code>null</code> if this is the
1438          * root node.
1439          * <p>
1440          * Note that the relationship between an AST node and its parent node
1441          * may change over the lifetime of a node.
1442          * </p>
1443          * 
1444          * @return the parent of this node, or <code>null</code> if none
1445          */ 
1446         public final ASTNode getParent() {
1447                 return this.parent;
1448         }
1449                 
1450         /**
1451          * Returns the location of this node within its parent,
1452          * or <code>null</code> if this is a root node.
1453          * <p>
1454          * <pre>
1455          * ASTNode node = ...;
1456          * ASTNode parent = node.getParent();
1457          * StructuralPropertyDescriptor location = node.getLocationInParent();
1458          * assert (parent != null) == (location != null);
1459          * if ((location != null) && location.isChildProperty())
1460          *    assert parent.getStructuralProperty(location) == node;
1461          * if ((location != null) && location.isChildListProperty())
1462          *    assert ((List) parent.getStructuralProperty(location)).contains(node);
1463          * </pre>
1464          * </p>
1465          * <p>
1466          * Note that the relationship between an AST node and its parent node
1467          * may change over the lifetime of a node.
1468          * </p>
1469          * 
1470          * @return the location of this node in its parent, 
1471          * or <code>null</code> if this node has no parent
1472          * @since 3.0
1473          */ 
1474         public final StructuralPropertyDescriptor getLocationInParent() {
1475                 return this.location;
1476         }
1477                 
1478         /**
1479          * Returns the root node at or above this node; returns this node if 
1480          * it is a root.
1481          * 
1482          * @return the root node at or above this node
1483          */ 
1484         public final ASTNode getRoot() {
1485                 ASTNode candidate = this;
1486                 while (true) {
1487                         ASTNode p = candidate.getParent();
1488                         if (p == null) {
1489                                 // candidate has no parent - that's the guy
1490                                 return candidate;
1491                         }
1492                         candidate = p;
1493                 }
1494         }
1495         
1496         /**
1497          * Returns the value of the given structural property for this node. The value
1498          * returned depends on the kind of property:
1499          * <ul>
1500          * <li>{@link SimplePropertyDescriptor} - the value of the given simple property,
1501          * or <code>null</code> if none; primitive values are "boxed"</li>
1502          * <li>{@link ChildPropertyDescriptor} - the child node (type <code>ASTNode</code>),
1503          * or <code>null</code> if none</li>
1504          * <li>{@link ChildListPropertyDescriptor} - the list (element type: {@link ASTNode})</li>
1505          * </ul>
1506          * 
1507          * @param property the property
1508          * @return the value, or <code>null</code> if none
1509          * @exception RuntimeException if this node does not have the given property
1510          * @since 3.0
1511          */
1512         public final Object getStructuralProperty(StructuralPropertyDescriptor property) {
1513                 if (property instanceof SimplePropertyDescriptor) {
1514                         SimplePropertyDescriptor p = (SimplePropertyDescriptor) property;
1515                         if (p.getValueType() == int.class) {
1516                                 int result = internalGetSetIntProperty(p, true, 0);
1517                                 return new Integer(result);
1518                         } else if (p.getValueType() == boolean.class) {
1519                                 boolean result = internalGetSetBooleanProperty(p, true, false);
1520                                 return Boolean.valueOf(result);
1521                         } else {
1522                                 return internalGetSetObjectProperty(p, true, null);
1523                         }
1524                 }
1525                 if (property instanceof ChildPropertyDescriptor) {
1526                         return internalGetSetChildProperty((ChildPropertyDescriptor) property, true, null);
1527                 }
1528                 if (property instanceof ChildListPropertyDescriptor) {
1529                         return internalGetChildListProperty((ChildListPropertyDescriptor) property);
1530                 }
1531                 throw new IllegalArgumentException();
1532         }
1533         
1534         /**
1535          * Sets the value of the given structural property for this node. The value
1536          * passed depends on the kind of property:
1537          * <ul>
1538          * <li>{@link SimplePropertyDescriptor} - the new value of the given simple property,
1539          * or <code>null</code> if none; primitive values are "boxed"</li>
1540          * <li>{@link ChildPropertyDescriptor} - the new child node (type <code>ASTNode</code>),
1541          * or <code>null</code> if none</li>
1542          * <li>{@link ChildListPropertyDescriptor} - not allowed</li>
1543          * </ul>
1544          * 
1545          * @param property the property
1546          * @param value the property value
1547          * @exception RuntimeException if this node does not have the
1548          * given property, or if the given property cannot be set
1549          * @since 3.0
1550          */
1551         public final void setStructuralProperty(StructuralPropertyDescriptor property, Object value) {
1552                 if (property instanceof SimplePropertyDescriptor) {
1553                         SimplePropertyDescriptor p = (SimplePropertyDescriptor) property;
1554                         if (p.getValueType() == int.class) {
1555                                 int arg = ((Integer) value).intValue();
1556                                 internalGetSetIntProperty(p, false, arg);
1557                                 return;
1558                         } else if (p.getValueType() == boolean.class) {
1559                                 boolean arg = ((Boolean) value).booleanValue();
1560                                 internalGetSetBooleanProperty(p, false, arg);
1561                                 return;
1562                         } else {
1563                                 if (value == null && p.isMandatory()) {
1564                                         throw new IllegalArgumentException();
1565                                 }
1566                                 internalGetSetObjectProperty(p, false, value);
1567                                 return;
1568                         }
1569                 }
1570                 if (property instanceof ChildPropertyDescriptor) {
1571                         ChildPropertyDescriptor p = (ChildPropertyDescriptor) property;
1572                         ASTNode child = (ASTNode) value;
1573                         if (child == null && p.isMandatory()) {
1574                                 throw new IllegalArgumentException();
1575                         }
1576                         internalGetSetChildProperty(p, false, child);
1577                         return;
1578                 }
1579                 if (property instanceof ChildListPropertyDescriptor) {
1580                         throw new IllegalArgumentException("Cannot set the list of child list property");  //$NON-NLS-1$
1581                 }
1582         }
1583
1584         /**
1585          * Sets the value of the given int-valued property for this node.
1586          * The default implementation of this method throws an exception explaining
1587          * that this node does not have such a property. This method should be
1588          * extended in subclasses that have at leasy one simple property whose value
1589          * type is int.
1590          * 
1591          * @param property the property
1592          * @param get <code>true</code> for a get operation, and 
1593          * <code>false</code> for a set operation
1594          * @param value the new property value; ignored for get operations
1595          * @return the value; always returns
1596          * <code>0</code> for set operations
1597          * @exception RuntimeException if this node does not have the 
1598          * given property, or if the given value cannot be set as specified
1599          * @since 3.0
1600          */
1601         int internalGetSetIntProperty(SimplePropertyDescriptor property, boolean get, int value) {
1602                 throw new RuntimeException("Node does not have this property");  //$NON-NLS-1$
1603         }
1604         
1605         /**
1606          * Sets the value of the given boolean-valued property for this node.
1607          * The default implementation of this method throws an exception explaining
1608          * that this node does not have such a property. This method should be
1609          * extended in subclasses that have at leasy one simple property whose value
1610          * type is boolean.
1611          * 
1612          * @param property the property
1613          * @param get <code>true</code> for a get operation, and 
1614          * <code>false</code> for a set operation
1615          * @param value the new property value; ignored for get operations
1616          * @return the value; always returns
1617          * <code>false</code> for set operations
1618          * @exception RuntimeException if this node does not have the 
1619          * given property, or if the given value cannot be set as specified
1620          * @since 3.0
1621          */
1622         boolean internalGetSetBooleanProperty(SimplePropertyDescriptor property, boolean get, boolean value) {
1623                 throw new RuntimeException("Node does not have this property");  //$NON-NLS-1$
1624         }
1625         
1626         /**
1627          * Sets the value of the given property for this node.
1628          * The default implementation of this method throws an exception explaining
1629          * that this node does not have such a property. This method should be
1630          * extended in subclasses that have at leasy one simple property whose value
1631          * type is a reference type.
1632          * 
1633          * @param property the property
1634          * @param get <code>true</code> for a get operation, and 
1635          * <code>false</code> for a set operation
1636          * @param value the new property value, or <code>null</code> if none;
1637          * ignored for get operations
1638          * @return the value, or <code>null</code> if none; always returns
1639          * <code>null</code> for set operations
1640          * @exception RuntimeException if this node does not have the 
1641          * given property, or if the given value cannot be set as specified
1642          * @since 3.0
1643          */
1644         Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
1645                 throw new RuntimeException("Node does not have this property");  //$NON-NLS-1$
1646         }
1647
1648         /**
1649          * Sets the child value of the given property for this node.
1650          * The default implementation of this method throws an exception explaining
1651          * that this node does not have such a property. This method should be
1652          * extended in subclasses that have at leasy one child property.
1653          * 
1654          * @param property the property
1655          * @param get <code>true</code> for a get operation, and 
1656          * <code>false</code> for a set operation
1657          * @param child the new child value, or <code>null</code> if none;
1658          * always <code>null</code> for get operations
1659          * @return the child, or <code>null</code> if none; always returns
1660          * <code>null</code> for set operations
1661          * @exception RuntimeException if this node does not have the
1662          * given property, or if the given child cannot be set as specified
1663          * @since 3.0
1664          */
1665         ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
1666                 throw new RuntimeException("Node does not have this property");  //$NON-NLS-1$
1667         }
1668         
1669         /**
1670          * Returns the list value of the given property for this node.
1671          * The default implementation of this method throws an exception explaining
1672          * that this noed does not have such a property. This method should be
1673          * extended in subclasses that have at leasy one child list property.
1674          * 
1675          * @param property the property
1676          * @return the list (element type: {@link ASTNode})
1677          * @exception RuntimeException if the given node does not have the
1678          * given property
1679          * @since 3.0
1680          */
1681         List internalGetChildListProperty(ChildListPropertyDescriptor property) {
1682                 throw new RuntimeException("Node does not have this property");  //$NON-NLS-1$
1683         }
1684         
1685         /**
1686          * Returns a list of structural property descriptors for nodes of the
1687          * same type as this node. Clients must not modify the result.
1688          * <p>
1689          * Note that property descriptors are a meta-level mechanism
1690          * for manipulating ASTNodes in a generic way. They are
1691          * unrelated to <code>get/setProperty</code>.
1692          * </p>
1693          * 
1694          * @return a list of property descriptors (element type: 
1695          * {@link StructuralPropertyDescriptor})
1696          * @since 3.0
1697          */
1698         public final List structuralPropertiesForType() {
1699                 return internalStructuralPropertiesForType(this.ast.apiLevel);
1700         }
1701         
1702         /**
1703          * Returns a list of property descriptors for this node type.
1704          * Clients must not modify the result. This abstract method
1705          * must be implemented in each concrete AST node type.
1706          * <p>
1707          * N.B. This method is package-private, so that the implementations
1708          * of this method in each of the concrete AST node types do not
1709          * clutter up the API doc.
1710          * </p>
1711          * 
1712          * @param apiLevel the API level; one of the <code>AST.JLS*</code> constants
1713          * @return a list of property descriptors (element type: 
1714          * {@link StructuralPropertyDescriptor})
1715          * @since 3.0
1716          */
1717         abstract List internalStructuralPropertiesForType(int apiLevel);
1718         
1719         /**
1720          * Internal helper method that starts the building a list of
1721          * property descriptors for the given node type.
1722          * 
1723          * @param nodeClass the class for a concrete node type
1724          * @param propertyList empty list
1725          */
1726         static void createPropertyList(Class nodeClass, List propertyList) {
1727                 // stuff nodeClass at head of list for future ref
1728                 propertyList.add(nodeClass);
1729         }
1730         
1731         /**
1732          * Internal helper method that adding a property descriptor.
1733          * 
1734          * @param property the structural property descriptor
1735          * @param propertyList list beginning with the AST node class
1736          * followed by accumulated structural property descriptors
1737          */
1738         static void addProperty(StructuralPropertyDescriptor property, List propertyList) {
1739                 Class nodeClass = (Class) propertyList.get(0);
1740                 if (property.getNodeClass() != nodeClass) {
1741                         // easily made cut-and-paste mistake
1742                         throw new RuntimeException("Structural property descriptor has wrong node class!");  //$NON-NLS-1$
1743                 }
1744                 propertyList.add(property);
1745         }
1746                 
1747         /**
1748          * Internal helper method that completes the building of
1749          * a node type's structural property descriptor list.
1750          * 
1751          * @param propertyList list beginning with the AST node class
1752          * followed by accumulated structural property descriptors
1753          * @return unmodifiable list of structural property descriptors
1754          * (element type: <code>StructuralPropertyDescriptor</code>)
1755          */
1756         static List reapPropertyList(List propertyList) {
1757                 propertyList.remove(0); // remove nodeClass
1758                 // compact
1759                 ArrayList a = new ArrayList(propertyList.size());
1760                 a.addAll(propertyList); 
1761                 return Collections.unmodifiableList(a);
1762         }
1763         
1764         /**
1765      * Checks that this AST operation is not used when
1766      * building JLS2 level ASTs.
1767
1768      * @exception UnsupportedOperationException
1769          * @since 3.0
1770      */
1771         final void unsupportedIn2() {
1772           if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
1773                 throw new UnsupportedOperationException("Operation not supported in JLS2 AST"); //$NON-NLS-1$
1774           }
1775         }
1776
1777         /**
1778      * Checks that this AST operation is only used when
1779      * building JLS2 level ASTs.
1780
1781      * @exception UnsupportedOperationException
1782          * @since 3.0
1783      */
1784         final void supportedOnlyIn2() {
1785           if (this.ast.apiLevel != AST.JLS2_INTERNAL) {
1786                 throw new UnsupportedOperationException("Operation only supported in JLS2 AST"); //$NON-NLS-1$
1787           }
1788         }
1789
1790         /**
1791          * Sets or clears this node's parent node and location.
1792          * <p>
1793          * Note that this method is package-private. The pointer from a node
1794          * to its parent is set implicitly as a side effect of inserting or
1795          * removing the node as a child of another node. This method calls
1796          * <code>ast.modifying()</code>.
1797          * </p>
1798          * 
1799          * @param parent the new parent of this node, or <code>null</code> if none
1800          * @param property the location of this node in its parent, 
1801          * or <code>null</code> if <code>parent</code> is <code>null</code>
1802          * @see #getLocationInParent
1803          * @see #getParent
1804          * @since 3.0
1805          */ 
1806         final void setParent(ASTNode parent, StructuralPropertyDescriptor property) {
1807                 this.ast.modifying();
1808                 this.parent = parent;
1809                 this.location = property;
1810         }
1811         
1812         /**
1813          * Removes this node from its parent. Has no effect if this node
1814          * is unparented. If this node appears as an element of a child list
1815          * property of its parent, then this node is removed from the
1816          * list using <code>List.remove</code>.
1817          * If this node appears as the value of a child property of its
1818          * parent, then this node is detached from its parent 
1819          * by passing <code>null</code> to the appropriate setter method;
1820          * this operation fails if this node is in a mandatory property.
1821          * 
1822          * @since 3.0
1823          */ 
1824         public final void delete() {
1825                 StructuralPropertyDescriptor p = getLocationInParent();
1826                 if (p == null) {
1827                         // node is unparented
1828                         return;
1829                 }
1830                 if (p.isChildProperty()) {
1831                         getParent().setStructuralProperty(this.location, null);
1832                         return;
1833                 }
1834                 if (p.isChildListProperty()) {
1835                         List l = (List) getParent().getStructuralProperty(this.location);
1836                         l.remove(this);
1837                 }
1838         }
1839
1840         /**
1841          * Checks whether the given new child node is a node 
1842          * in a different AST from its parent-to-be, whether it is
1843          * already has a parent, whether adding it to its
1844          * parent-to-be would create a cycle, and whether the child is of
1845          * the right type. The parent-to-be is the enclosing instance.
1846          * 
1847          * @param node the parent-to-be node
1848          * @param newChild the new child of the parent
1849          * @param cycleCheck <code>true</code> if cycles are possible and need 
1850          *   to be checked, <code>false</code> if cycles are impossible and do 
1851          *   not need to be checked
1852          * @param nodeType a type constraint on child nodes, or <code>null</code>
1853          *   if no special check is required
1854          * @exception IllegalArgumentException if:
1855          * <ul>
1856          * <li>the child is null</li>
1857          * <li>the node belongs to a different AST</li>
1858          * <li>the child has the incorrect node type</li>
1859          * <li>the node already has a parent</li>
1860          * <li>a cycle in would be created</li>
1861          * </ul>
1862          */ 
1863         static void checkNewChild(ASTNode node, ASTNode newChild,
1864                         boolean cycleCheck, Class nodeType) {
1865                 if (newChild.ast != node.ast) {
1866                         // new child is from a different AST
1867                         throw new IllegalArgumentException();
1868                 }               
1869                 if (newChild.getParent() != null) {
1870                         // new child currently has a different parent
1871                         throw new IllegalArgumentException();
1872                 }
1873                 if (cycleCheck && newChild == node.getRoot()) {
1874                         // inserting new child would create a cycle
1875                         throw new IllegalArgumentException();
1876                 }
1877                 Class childClass = newChild.getClass();
1878                 if (nodeType != null && !nodeType.isAssignableFrom(childClass)) {
1879                         // new child is not of the right type
1880                         throw new ClassCastException();
1881                 }
1882                 if ((newChild.typeAndFlags & PROTECT) != 0) {
1883                         // new child node is protected => cannot be parented
1884                         throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
1885                 }
1886         }
1887
1888         /**
1889      * Prelude portion of the "3 step program" for replacing the
1890          * old child of this node with another node.
1891      * Here is the code pattern found in all AST node subclasses:
1892      * <pre>
1893      * ASTNode oldChild = this.foo;
1894      * preReplaceChild(oldChild, newFoo, FOO_PROPERTY);
1895      * this.foo = newFoo;
1896      * postReplaceChild(oldChild, newFoo, FOO_PROPERTY);
1897      * </pre>
1898      * The first part (preReplaceChild) does all the precondition checks,
1899      * reports pre-delete events, and changes parent links.
1900          * The old child is delinked from its parent (making it a root node),
1901          * and the new child node is linked to its parent. The new child node
1902          * must be a root node in the same AST as its new parent, and must not
1903          * be an ancestor of this node. All three nodes must be
1904      * modifiable (not PROTECTED). The replace operation must fail
1905      * atomically; so it is crucial that all precondition checks
1906      * be done before any linking and delinking happens.
1907      * The final part (postReplaceChild )reports post-add events.
1908          * <p>
1909          * This method calls <code>ast.modifying()</code> for the nodes affected.
1910          * </p>
1911          * 
1912          * @param oldChild the old child of this node, or <code>null</code> if
1913          *   there was no old child to replace
1914          * @param newChild the new child of this node, or <code>null</code> if
1915          *   there is no replacement child
1916          * @param property the property descriptor of this node describing
1917      * the relationship between node and child
1918          * @exception RuntimeException if:
1919          * <ul>
1920          * <li>the node belongs to a different AST</li>
1921          * <li>the node already has a parent</li>
1922          * <li>a cycle in would be created</li>
1923          * <li>any of the nodes involved are unmodifiable</li>
1924          * </ul>
1925          * @since 3.0
1926          */ 
1927         final void preReplaceChild(ASTNode oldChild, ASTNode newChild, ChildPropertyDescriptor property) {
1928                 if ((this.typeAndFlags & PROTECT) != 0) {
1929                         // this node is protected => cannot gain or lose children
1930                         throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
1931                 }
1932                 if (newChild != null) {
1933                         checkNewChild(this, newChild, property.cycleRisk, null);
1934                 }
1935                 // delink old child from parent
1936                 if (oldChild != null) {
1937                         if ((oldChild.typeAndFlags & PROTECT) != 0) {
1938                                 // old child node is protected => cannot be unparented
1939                                 throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
1940                         }
1941                         if (newChild != null) {
1942                                 this.ast.preReplaceChildEvent(this, oldChild, newChild, property);
1943                         } else {
1944                                 this.ast.preRemoveChildEvent(this, oldChild, property);
1945                         }
1946                         oldChild.setParent(null, null);
1947                 } else {
1948                         if(newChild != null) {
1949                                 this.ast.preAddChildEvent(this, newChild, property);
1950                         }
1951                 }
1952                 // link new child to parent
1953                 if (newChild != null) {
1954                         newChild.setParent(this, property);
1955                         // cannot notify postAddChildEvent until parent is linked to child too
1956                 }
1957         }
1958
1959         /**
1960      * Postlude portion of the "3 step program" for replacing the
1961          * old child of this node with another node.
1962      * See {@link #preReplaceChild(ASTNode, ASTNode, ChildPropertyDescriptor)}
1963      * for details.
1964          * @since 3.0
1965          */ 
1966         final void postReplaceChild(ASTNode oldChild, ASTNode newChild, ChildPropertyDescriptor property) {
1967                 // link new child to parent
1968                 if (newChild != null) {
1969                         if (oldChild != null) {
1970                                 this.ast.postReplaceChildEvent(this, oldChild, newChild, property);
1971                         } else {
1972                                 this.ast.postAddChildEvent(this, newChild, property);
1973                         }
1974                 } else {
1975                         this.ast.postRemoveChildEvent(this, oldChild, property);
1976                 }
1977         }
1978         
1979         /**
1980      * Prelude portion of the "3 step program" for changing the
1981          * value of a simple property of this node.
1982      * Here is the code pattern found in all AST node subclasses:
1983      * <pre>
1984      * preValueChange(FOO_PROPERTY);
1985      * this.foo = newFoo;
1986      * postValueChange(FOO_PROPERTY);
1987      * </pre>
1988      * The first part (preValueChange) does the precondition check
1989      * to make sure the node is modifiable (not PROTECTED).
1990      * The change operation must fail atomically; so it is crucial
1991      * that the precondition checks are done before the field is
1992      * hammered. The final part (postValueChange)reports post-change
1993      * events.
1994          * <p>
1995          * This method calls <code>ast.modifying()</code> for the node affected.
1996          * </p>
1997          * 
1998          * @param property the property descriptor of this node 
1999          * @exception RuntimeException if:
2000          * <ul>
2001          * <li>this node is unmodifiable</li>
2002          * </ul>
2003          * @since 3.0
2004          */ 
2005         final void preValueChange(SimplePropertyDescriptor property) {
2006                 if ((this.typeAndFlags & PROTECT) != 0) {
2007                         // this node is protected => cannot change valure of properties
2008                         throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
2009                 }
2010                 this.ast.preValueChangeEvent(this, property);
2011                 this.ast.modifying();
2012         }
2013
2014         /**
2015      * Postlude portion of the "3 step program" for replacing the
2016          * old child of this node with another node.
2017      * See {@link #preValueChange(SimplePropertyDescriptor)} for details.
2018          * @since 3.0
2019          */ 
2020         final void postValueChange(SimplePropertyDescriptor property) {
2021                 this.ast.postValueChangeEvent(this, property);
2022         }
2023         
2024         /**
2025      * Ensures that this node is modifiable (that is, not marked PROTECTED).
2026      * If successful, calls ast.modifying().
2027      * @exception RuntimeException is not modifiable
2028      */
2029         final void checkModifiable() {
2030                 if ((this.typeAndFlags & PROTECT) != 0) {
2031                         throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
2032                 }
2033                 this.ast.modifying();
2034         }
2035         
2036         /**
2037      * Begin lazy initialization of this node.
2038      * Here is the code pattern found in all AST
2039      * node subclasses:
2040      * <pre>
2041      * if (this.foo == null) {
2042          *    // lazy init must be thread-safe for readers
2043      *    synchronized (this) {
2044      *       if (this.foo == null) {
2045      *          preLazyInit();
2046      *          this.foo = ...; // code to create new node
2047      *          postLazyInit(this.foo, FOO_PROPERTY);
2048      *       }
2049      *    }
2050      * }
2051      * </pre>
2052      * @since 3.0
2053      */
2054         final void preLazyInit() {
2055                 // IMPORTANT: this method is called by readers
2056                 // ASTNode.this is locked at this point
2057                 this.ast.disableEvents();
2058                 // will turn events back on in postLasyInit
2059         }
2060         
2061         /**
2062      * End lazy initialization of this node.
2063      * 
2064          * @param newChild the new child of this node, or <code>null</code> if
2065          *   there is no replacement child
2066          * @param property the property descriptor of this node describing
2067      * the relationship between node and child
2068      * @since 3.0
2069      */
2070         final void postLazyInit(ASTNode newChild, ChildPropertyDescriptor property) {
2071                 // IMPORTANT: this method is called by readers
2072                 // ASTNode.this is locked at this point
2073                 // newChild is brand new (so no chance of concurrent access)
2074                 newChild.setParent(this, property);
2075                 // turn events back on (they were turned off in corresponding preLazyInit)
2076                 this.ast.reenableEvents();
2077         }
2078
2079         /**
2080          * Returns the named property of this node, or <code>null</code> if none.
2081          * 
2082          * @param propertyName the property name
2083          * @return the property value, or <code>null</code> if none
2084          * @see #setProperty(String,Object)
2085          */
2086         public final Object getProperty(String propertyName) {
2087                 if (propertyName == null) {
2088                         throw new IllegalArgumentException();
2089                 }
2090                 if (this.property1 == null) {
2091                         // node has no properties at all
2092                         return null;
2093                 }
2094                 if (this.property1 instanceof String) {
2095                         // node has only a single property
2096                         if (propertyName.equals(this.property1)) {
2097                                 return this.property2;
2098                         } else {
2099                                 return null;
2100                         }
2101                 }
2102                 // otherwise node has table of properties
2103                 Map m = (Map) this.property1;
2104                 return m.get(propertyName);
2105         }
2106         
2107         /**
2108          * Sets the named property of this node to the given value,
2109          * or to <code>null</code> to clear it.
2110          * <p>
2111          * Clients should employ property names that are sufficiently unique
2112          * to avoid inadvertent conflicts with other clients that might also be
2113          * setting properties on the same node.
2114          * </p>
2115          * <p>
2116          * Note that modifying a property is not considered a modification to the 
2117          * AST itself. This is to allow clients to decorate existing nodes with 
2118          * their own properties without jeopardizing certain things (like the 
2119          * validity of bindings), which rely on the underlying tree remaining static.
2120          * </p>
2121          * 
2122          * @param propertyName the property name
2123          * @param data the new property value, or <code>null</code> if none
2124          * @see #getProperty(String)
2125          */
2126         public final void setProperty(String propertyName, Object data) {
2127                 if (propertyName == null) {
2128                         throw new IllegalArgumentException();
2129                 }
2130                 // N.B. DO NOT CALL ast.modifying();
2131
2132                 if (this.property1 == null) {
2133                         // node has no properties at all
2134                         if (data == null) {
2135                                 // we already know this
2136                                 return;
2137                         }
2138                         // node gets its fist property
2139                         this.property1 = propertyName;
2140                         this.property2 = data;
2141                         return;
2142                 }
2143
2144                 if (this.property1 instanceof String) {
2145                         // node has only a single property
2146                         if (propertyName.equals(this.property1)) {
2147                                 // we're in luck
2148                                 this.property2 = data;
2149                                 if (data == null) {
2150                                         // just deleted last property
2151                                         this.property1 = null;
2152                                         this.property2 = null;
2153                                 }
2154                                 return;
2155                         }
2156                         if (data == null) {
2157                                 // we already know this
2158                                 return;
2159                         }
2160                         // node already has one property - getting its second
2161                         // convert to more flexible representation
2162                         HashMap m = new HashMap(2);
2163                         m.put(this.property1, this.property2);
2164                         m.put(propertyName, data);
2165                         this.property1 = m;
2166                         this.property2 = null;
2167                         return;
2168                 }
2169                         
2170                 // node has two or more properties
2171                 HashMap m = (HashMap) this.property1;
2172                 if (data == null) {
2173                         m.remove(propertyName);
2174                         // check for just one property left
2175                         if (m.size() == 1) {
2176                                 // convert to more efficient representation
2177                                 Map.Entry[] entries = (Map.Entry[]) m.entrySet().toArray(new Map.Entry[1]);
2178                                 this.property1 = entries[0].getKey();
2179                                 this.property2 = entries[0].getValue();
2180                         }
2181                         return;
2182                 } else {
2183                         m.put(propertyName, data);
2184                         // still has two or more properties
2185                         return;
2186                 }
2187         }
2188
2189         /**
2190          * Returns an unmodifiable table of the properties of this node with 
2191          * non-<code>null</code> values.
2192          * 
2193          * @return the table of property values keyed by property name
2194          *   (key type: <code>String</code>; value type: <code>Object</code>)
2195          */
2196         public final Map properties() {
2197                 if (this.property1 == null) {
2198                         // node has no properties at all
2199                         return UNMODIFIABLE_EMPTY_MAP;
2200                 } 
2201                 if (this.property1 instanceof String) {
2202                         // node has a single property
2203                         return Collections.singletonMap(this.property1, this.property2);
2204                 }
2205                 
2206                 // node has two or more properties
2207                 if (this.property2 == null) {
2208                         this.property2 = Collections.unmodifiableMap((Map) this.property1);
2209                 }
2210                 // property2 is unmodifiable wrapper for map in property1
2211                 return (Map) this.property2;
2212         }
2213         
2214         /**
2215          * Returns the flags associated with this node.
2216          * <p>
2217          * No flags are associated with newly created nodes.
2218          * </p>
2219          * <p>
2220          * The flags are the bitwise-or of individual flags.
2221          * The following flags are currently defined:
2222          * <ul>
2223          * <li>{@link #MALFORMED} - indicates node is syntactically 
2224          *   malformed</li>
2225          * <li>{@link #ORIGINAL} - indicates original node
2226          * created by ASTParser</li>
2227          * <li>{@link #PROTECT} - indicates node is protected
2228          * from further modification</li>
2229          * <li>{@link #RECOVERED} - indicates node or a part of this node
2230          *  is recovered from source that contains a syntax error</li>
2231          * </ul>
2232          * Other bit positions are reserved for future use.
2233          * </p>
2234          * 
2235          * @return the bitwise-or of individual flags
2236          * @see #setFlags(int)
2237          */
2238         public final int getFlags() {
2239                 return this.typeAndFlags & 0xFFFF;
2240         }
2241         
2242         /**
2243          * Sets the flags associated with this node to the given value.
2244          * <p>
2245          * The flags are the bitwise-or of individual flags.
2246          * The following flags are currently defined:
2247          * <ul>
2248          * <li>{@link #MALFORMED} - indicates node is syntactically 
2249          *   malformed</li>
2250          * <li>{@link #ORIGINAL} - indicates original node
2251          * created by ASTParser</li>
2252          * <li>{@link #PROTECT} - indicates node is protected
2253          * from further modification</li>
2254          * <li>{@link #RECOVERED} - indicates node or a part of this node
2255          *  is recovered from source that contains a syntax error</li>
2256          * </ul>
2257          * Other bit positions are reserved for future use.
2258          * </p>
2259          * <p>
2260          * Note that the flags are <em>not</em> considered a structural
2261          * property of the node, and can be changed even if the
2262          * node is marked as protected.
2263          * </p>
2264          * 
2265          * @param flags the bitwise-or of individual flags
2266          * @see #getFlags()
2267          */
2268         public final void setFlags(int flags) {
2269                 this.ast.modifying();
2270                 int old = this.typeAndFlags & 0xFFFF0000;
2271                 this.typeAndFlags = old | (flags & 0xFFFF);
2272         }
2273
2274         /**
2275          * Returns an integer value identifying the type of this concrete AST node.
2276          * The values are small positive integers, suitable for use in switch statements.
2277          * <p>
2278          * For each concrete node type there is a unique node type constant (name
2279          * and value). The unique node type constant for a concrete node type such as 
2280          * <code>CastExpression</code> is <code>ASTNode.CAST_EXPRESSION</code>.
2281          * </p>
2282          * 
2283          * @return one of the node type constants
2284          */
2285         public final int getNodeType() {
2286                 return this.typeAndFlags >>> 16;
2287         }
2288         
2289         /**
2290          * Sets the integer value identifying the type of this concrete AST node.
2291          * The values are small positive integers, suitable for use in switch statements.
2292          * 
2293          * @param nodeType one of the node type constants
2294          */
2295         private void setNodeType(int nodeType) {
2296                 int old = this.typeAndFlags & 0xFFFF0000;
2297                 this.typeAndFlags = old | (nodeType << 16);
2298         }
2299         
2300         /**
2301          * Returns an integer value identifying the type of this concrete AST node.
2302          * <p>
2303          * This internal method is implemented in each of the
2304          * concrete node subclasses.
2305          * </p>
2306          * 
2307          * @return one of the node type constants
2308          */
2309         abstract int getNodeType0();
2310         
2311         /**
2312          * The <code>ASTNode</code> implementation of this <code>Object</code>
2313          * method uses object identity (==). Use <code>subtreeMatch</code> to
2314          * compare two subtrees for equality.
2315          * 
2316          * @param obj {@inheritDoc}
2317          * @return {@inheritDoc}
2318          * @see #subtreeMatch(ASTMatcher matcher, Object other)
2319          */
2320         public final boolean equals(Object obj) {
2321                 return this == obj; // equivalent to Object.equals
2322         }
2323         
2324         /*
2325          * (non-Javadoc)
2326          * This makes it consistent with the fact that a equals methods has been provided.
2327          * @see java.lang.Object#hashCode()
2328          */
2329         public final int hashCode() {
2330                 return super.hashCode();
2331         }
2332
2333         /**
2334          * Returns whether the subtree rooted at the given node matches the
2335          * given other object as decided by the given matcher.
2336          * 
2337          * @param matcher the matcher
2338          * @param other the other object, or <code>null</code>
2339          * @return <code>true</code> if the subtree matches, or 
2340          * <code>false</code> if they do not match
2341          */
2342         public final boolean subtreeMatch(ASTMatcher matcher, Object other) {
2343                 return subtreeMatch0(matcher, other);
2344         }
2345         
2346         /**
2347          * Returns whether the subtree rooted at the given node matches the
2348          * given other object as decided by the given matcher.
2349          * <p>
2350          * This internal method is implemented in each of the
2351          * concrete node subclasses.
2352          * </p>
2353          * 
2354          * @param matcher the matcher
2355          * @param other the other object, or <code>null</code>
2356          * @return <code>true</code> if the subtree matches, or 
2357          * <code>false</code> if they do not match
2358          */
2359         abstract boolean subtreeMatch0(ASTMatcher matcher, Object other);
2360         
2361         /**
2362          * Returns a deep copy of the subtree of AST nodes rooted at the
2363          * given node. The resulting nodes are owned by the given AST,
2364          * which may be different from the ASTs of the given node. 
2365          * Even if the given node has a parent, the result node will be unparented.
2366          * <p>
2367          * Source range information on the original nodes is automatically copied to the new
2368          * nodes. Client properties (<code>properties</code>) are not carried over.
2369          * </p>
2370          * <p>
2371          * The node's <code>AST</code> and the target <code>AST</code> must support
2372      * the same API level.
2373          * </p>
2374          * 
2375          * @param target the AST that is to own the nodes in the result
2376          * @param node the node to copy, or <code>null</code> if none
2377          * @return the copied node, or <code>null</code> if <code>node</code>
2378          *    is <code>null</code>
2379          */
2380         public static ASTNode copySubtree(AST target, ASTNode node) {
2381                 if (node == null) {
2382                         return null;
2383                 }
2384                 if (target == null) {
2385                         throw new IllegalArgumentException();
2386                 }
2387                 if (target.apiLevel() != node.getAST().apiLevel()) {
2388                         throw new UnsupportedOperationException();
2389                 }
2390                 ASTNode newNode = node.clone(target);
2391                 return newNode;
2392         }
2393
2394         /**
2395          * Returns a deep copy of the subtrees of AST nodes rooted at the
2396          * given list of nodes. The resulting nodes are owned by the given AST,
2397          * which may be different from the ASTs of the nodes in the list. 
2398          * Even if the nodes in the list have parents, the nodes in the result
2399          * will be unparented.
2400          * <p>
2401          * Source range information on the original nodes is automatically copied to the new
2402          * nodes. Client properties (<code>properties</code>) are not carried over.
2403          * </p>
2404          * 
2405          * @param target the AST that is to own the nodes in the result
2406          * @param nodes the list of nodes to copy
2407          *    (element type: <code>ASTNode</code>)
2408          * @return the list of copied subtrees
2409          *    (element type: <code>ASTNode</code>)
2410          */
2411         public static List copySubtrees(AST target, List nodes) {
2412                 List result = new ArrayList(nodes.size());
2413                 for (Iterator it = nodes.iterator(); it.hasNext(); ) {
2414                         ASTNode oldNode = (ASTNode) it.next();
2415                         ASTNode newNode = oldNode.clone(target);
2416                         result.add(newNode);
2417                 }
2418                 return result;
2419         }
2420
2421         /**
2422          * Returns a deep copy of the subtree of AST nodes rooted at this node.
2423          * The resulting nodes are owned by the given AST, which may be different
2424          * from the AST of this node. Even if this node has a parent, the 
2425          * result node will be unparented.
2426          * <p>
2427          * This method reports pre- and post-clone events, and dispatches
2428          * to <code>clone0(AST)</code> which is reimplemented in node subclasses.
2429          * </p>
2430          * 
2431          * @param target the AST that is to own the nodes in the result
2432          * @return the root node of the copies subtree
2433          */
2434         final ASTNode clone(AST target) {
2435                 this.ast.preCloneNodeEvent(this);
2436                 ASTNode c = this.clone0(target);
2437                 this.ast.postCloneNodeEvent(this, c);
2438                 return c;
2439         }
2440
2441         /**
2442          * Returns a deep copy of the subtree of AST nodes rooted at this node.
2443          * The resulting nodes are owned by the given AST, which may be different
2444          * from the AST of this node. Even if this node has a parent, the 
2445          * result node will be unparented.
2446          * <p>
2447          * This method must be implemented in subclasses.
2448          * </p>
2449          * <p>
2450          * This method does not report pre- and post-clone events.
2451          * All callers should instead call <code>clone(AST)</code>
2452          * to ensure that pre- and post-clone events are reported.
2453          * </p>
2454          * <p>
2455          * N.B. This method is package-private, so that the implementations
2456          * of this method in each of the concrete AST node types do not
2457          * clutter up the API doc. 
2458          * </p>
2459          * 
2460          * @param target the AST that is to own the nodes in the result
2461          * @return the root node of the copies subtree
2462          */
2463         abstract ASTNode clone0(AST target);
2464         
2465         /**
2466          * Accepts the given visitor on a visit of the current node.
2467          * 
2468          * @param visitor the visitor object
2469          * @exception IllegalArgumentException if the visitor is null
2470          */
2471         public final void accept(ASTVisitor visitor) {
2472                 if (visitor == null) {
2473                         throw new IllegalArgumentException();
2474                 }
2475                 // begin with the generic pre-visit
2476                 visitor.preVisit(this);
2477                 // dynamic dispatch to internal method for type-specific visit/endVisit
2478                 accept0(visitor);
2479                 // end with the generic post-visit
2480                 visitor.postVisit(this);
2481         }
2482
2483         /**
2484          * Accepts the given visitor on a type-specific visit of the current node.
2485          * This method must be implemented in all concrete AST node types.
2486          * <p>
2487          * General template for implementation on each concrete ASTNode class:
2488          * <pre>
2489          * <code>
2490          * boolean visitChildren = visitor.visit(this);
2491          * if (visitChildren) {
2492          *    // visit children in normal left to right reading order
2493          *    acceptChild(visitor, getProperty1());
2494          *    acceptChildren(visitor, rawListProperty);
2495          *    acceptChild(visitor, getProperty2());
2496          * }
2497          * visitor.endVisit(this);
2498          * </code>
2499          * </pre>
2500          * Note that the caller (<code>accept</code>) take cares of invoking
2501          * <code>visitor.preVisit(this)</code> and <code>visitor.postVisit(this)</code>.
2502          * </p>
2503          * 
2504          * @param visitor the visitor object
2505          */
2506         abstract void accept0(ASTVisitor visitor);
2507
2508         /**
2509          * Accepts the given visitor on a visit of the current node.
2510          * <p>
2511          * This method should be used by the concrete implementations of
2512          * <code>accept0</code> to traverse optional properties. Equivalent
2513          * to <code>child.accept(visitor)</code> if <code>child</code>
2514          * is not <code>null</code>.
2515          * </p>
2516          * 
2517          * @param visitor the visitor object
2518          * @param child the child AST node to dispatch too, or <code>null</code>
2519          *    if none
2520          */
2521         final void acceptChild(ASTVisitor visitor, ASTNode child) {
2522                 if (child == null) {
2523                         return;
2524                 }
2525                 child.accept(visitor);
2526         }
2527
2528         /**
2529          * Accepts the given visitor on a visit of the given live list of
2530          * child nodes. 
2531          * <p>
2532          * This method must be used by the concrete implementations of
2533          * <code>accept</code> to traverse list-values properties; it
2534          * encapsulates the proper handling of on-the-fly changes to the list.
2535          * </p>
2536          * 
2537          * @param visitor the visitor object
2538          * @param children the child AST node to dispatch too, or <code>null</code>
2539          *    if none
2540          */
2541         final void acceptChildren(ASTVisitor visitor, ASTNode.NodeList children) {
2542                 // use a cursor to keep track of where we are up to
2543                 // (the list may be changing under foot)
2544                 NodeList.Cursor cursor = children.newCursor();
2545                 try {
2546                         while (cursor.hasNext()) {
2547                                 ASTNode child = (ASTNode) cursor.next();
2548                                 child.accept(visitor);
2549                         }
2550                 } finally {
2551                         children.releaseCursor(cursor);
2552                 }
2553         }
2554
2555         /**
2556          * Returns the character index into the original source file indicating
2557          * where the source fragment corresponding to this node begins.
2558          * <p>
2559          * The parser supplies useful well-defined source ranges to the nodes it creates.
2560          * See {@link ASTParser#setKind(int)} for details
2561          * on precisely where source ranges begin and end.
2562          * </p>
2563          * 
2564          * @return the 0-based character index, or <code>-1</code>
2565          *    if no source position information is recorded for this node
2566          * @see #getLength()
2567          * @see ASTParser
2568          */
2569         public final int getStartPosition() {
2570                 return this.startPosition;
2571         }
2572
2573         /**
2574          * Returns the length in characters of the original source file indicating
2575          * where the source fragment corresponding to this node ends.
2576          * <p>
2577          * The parser supplies useful well-defined source ranges to the nodes it creates.
2578          * See {@link ASTParser#setKind(int)} methods for details
2579          * on precisely where source ranges begin and end.
2580          * </p>
2581          * 
2582          * @return a (possibly 0) length, or <code>0</code>
2583          *    if no source position information is recorded for this node
2584          * @see #getStartPosition()
2585          * @see ASTParser
2586          */
2587         public final int getLength() {
2588                 return this.length;
2589         }
2590
2591         /**
2592          * Sets the source range of the original source file where the source
2593          * fragment corresponding to this node was found.
2594          * <p>
2595          * See {@link ASTParser#setKind(int)} for details
2596          * on precisely where source ranges are supposed to begin and end.
2597          * </p>
2598          * 
2599          * @param startPosition a 0-based character index, 
2600          *    or <code>-1</code> if no source position information is 
2601          *    available for this node
2602          * @param length a (possibly 0) length, 
2603          *    or <code>0</code> if no source position information is recorded 
2604          *    for this node
2605          * @see #getStartPosition()
2606          * @see #getLength()
2607          * @see ASTParser
2608          */
2609         public final void setSourceRange(int startPosition, int length) {
2610                 if (startPosition >= 0 && length < 0) {
2611                         throw new IllegalArgumentException();
2612                 }
2613                 if (startPosition < 0 && length != 0) {
2614                         throw new IllegalArgumentException();
2615                 }
2616                 // source positions are not considered a structural property
2617                 // but we protect them nevertheless
2618                 checkModifiable();
2619                 this.startPosition = startPosition;
2620                 this.length = length;
2621         }
2622         
2623         /**
2624          * Returns a string representation of this node suitable for debugging
2625          * purposes only.
2626          * 
2627          * @return a debug string 
2628          */
2629         public final String toString() {
2630                 StringBuffer buffer = new StringBuffer();
2631                 int p = buffer.length();
2632                 try {
2633                         appendDebugString(buffer);
2634                 } catch (RuntimeException e) {
2635                         // since debugger sometimes call toString methods, problems can easily happen when
2636                         // toString is called on an instance that is being initialized
2637                         buffer.setLength(p);
2638                         buffer.append("!"); //$NON-NLS-1$
2639                         buffer.append(standardToString());
2640                 }
2641                 return buffer.toString();
2642         }
2643         
2644         /**
2645          * Returns the string representation of this node produced by the standard
2646          * <code>Object.toString</code> method.
2647          * 
2648          * @return a debug string 
2649          */
2650         final String standardToString() {
2651                 return super.toString();
2652         }
2653         
2654         /**
2655          * Appends a debug representation of this node to the given string buffer.
2656          * <p>
2657          * The <code>ASTNode</code> implementation of this method prints out the entire 
2658          * subtree. Subclasses may override to provide a more succinct representation.
2659          * </p>
2660          * 
2661          * @param buffer the string buffer to append to
2662          */
2663         void appendDebugString(StringBuffer buffer) {
2664                 // print the subtree by default
2665                 appendPrintString(buffer);
2666         }
2667                 
2668         /**
2669          * Appends a standard Java source code representation of this subtree to the given
2670          * string buffer.
2671          * 
2672          * @param buffer the string buffer to append to
2673          */
2674         final void appendPrintString(StringBuffer buffer) {
2675                 NaiveASTFlattener printer = new NaiveASTFlattener();
2676                 this.accept(printer);
2677                 buffer.append(printer.getResult());
2678         }
2679         
2680         /**
2681          * Estimate of size of an object header in bytes.
2682          */
2683         static final int HEADERS = 12;
2684         
2685         /**
2686          * Approximate base size of an AST node instance in bytes, 
2687          * including object header and instance fields.
2688          * That is, HEADERS + (# instance vars in ASTNode)*4.
2689          */
2690         static final int BASE_NODE_SIZE = HEADERS + 7 * 4;
2691         
2692         /**
2693          * Returns an estimate of the memory footprint, in bytes,
2694          * of the given string.
2695          * 
2696          * @param string the string to measure, or <code>null</code>
2697          * @return the size of this string object in bytes, or
2698          *   0 if the string is <code>null</code>
2699      * @since 3.0
2700          */
2701         static int stringSize(String string) {
2702                 int size = 0;
2703                 if (string != null) {
2704                         // Strings usually have 4 instance fields, one of which is a char[]
2705                         size += HEADERS + 4 * 4;
2706                         // char[] has 2 bytes per character
2707                         size += HEADERS + 2 * string.length();
2708                 }
2709                 return size;
2710         }
2711         
2712         /**
2713          * Returns an estimate of the memory footprint in bytes of the entire 
2714          * subtree rooted at this node.
2715          * 
2716          * @return the size of this subtree in bytes
2717          */
2718         public final int subtreeBytes() {
2719                 return treeSize();
2720         }
2721                 
2722         /**
2723          * Returns an estimate of the memory footprint in bytes of the entire 
2724          * subtree rooted at this node.
2725          * <p>
2726          * N.B. This method is package-private, so that the implementations
2727          * of this method in each of the concrete AST node types do not
2728          * clutter up the API doc.
2729          * </p>
2730          * 
2731          * @return the size of this subtree in bytes
2732          */
2733         abstract int treeSize();
2734
2735         /**
2736          * Returns an estimate of the memory footprint of this node in bytes.
2737          * The estimate does not include the space occupied by child nodes.
2738          * 
2739          * @return the size of this node in bytes
2740          */
2741         abstract int memSize();
2742 }