0043ee3f5987385150bad584effee335c491aa05
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / core / dom / PackageDeclaration.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.ArrayList;
15 import java.util.List;
16
17 /**
18  * Package declaration AST node type.
19  * For JLS2:
20  * <pre>
21  * PackageDeclaration:
22  *    <b>package</b> Name <b>;</b>
23  * </pre>
24  * For JLS3, annotations and doc comment
25  * were added:
26  * <pre>
27  * PackageDeclaration:
28  *    [ Javadoc ] { Annotation } <b>package</b> Name <b>;</b>
29  * </pre>
30  * Note that the standard AST parser only recognizes a Javadoc comment
31  * immediately preceding the package declaration when it occurs in the
32  * special <code>package-info.java</code> compilation unit (JLS3 7.4.1.1).
33  * The Javadoc comment in that file contains the package description.
34  * 
35  * @since 2.0
36  * @noinstantiate This class is not intended to be instantiated by clients.
37  */
38 public class PackageDeclaration extends ASTNode {
39         
40         /**
41          * The "javadoc" structural property of this node type.
42          * @since 3.0
43          */
44         public static final ChildPropertyDescriptor JAVADOC_PROPERTY = 
45                 new ChildPropertyDescriptor(PackageDeclaration.class, "javadoc", Javadoc.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
46
47         /**
48          * The "annotations" structural property of this node type (added in JLS3 API).
49          * @since 3.1
50          */
51         public static final ChildListPropertyDescriptor ANNOTATIONS_PROPERTY = 
52                 new ChildListPropertyDescriptor(PackageDeclaration.class, "annotations", Annotation.class, CYCLE_RISK); //$NON-NLS-1$
53         
54         /**
55          * The "name" structural property of this node type.
56          * @since 3.0
57          */
58         public static final ChildPropertyDescriptor NAME_PROPERTY = 
59                 new ChildPropertyDescriptor(PackageDeclaration.class, "name", Name.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
60
61         /**
62          * A list of property descriptors (element type: 
63          * {@link StructuralPropertyDescriptor}),
64          * or null if uninitialized.
65          * @since 3.0
66          */
67         private static final List PROPERTY_DESCRIPTORS_2_0;
68         
69         /**
70          * A list of property descriptors (element type: 
71          * {@link StructuralPropertyDescriptor}),
72          * or null if uninitialized.
73          * @since 3.1
74          */
75         private static final List PROPERTY_DESCRIPTORS_3_0;
76         
77         static {
78                 List propertyList = new ArrayList(2);
79                 createPropertyList(PackageDeclaration.class, propertyList);
80                 addProperty(NAME_PROPERTY, propertyList);
81                 PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
82                 
83                 propertyList = new ArrayList(4);
84                 createPropertyList(PackageDeclaration.class, propertyList);
85                 addProperty(JAVADOC_PROPERTY, propertyList);
86                 addProperty(ANNOTATIONS_PROPERTY, propertyList);
87                 addProperty(NAME_PROPERTY, propertyList);
88                 PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
89         }
90
91         /**
92          * Returns a list of structural property descriptors for this node type.
93          * Clients must not modify the result.
94          * 
95          * @param apiLevel the API level; one of the
96          * <code>AST.JLS*</code> constants
97
98          * @return a list of property descriptors (element type: 
99          * {@link StructuralPropertyDescriptor})
100          * @since 3.0
101          */
102         public static List propertyDescriptors(int apiLevel) {
103                 if (apiLevel == AST.JLS2_INTERNAL) {
104                         return PROPERTY_DESCRIPTORS_2_0;
105                 } else {
106                         return PROPERTY_DESCRIPTORS_3_0;
107                 }
108         }
109                         
110         /**
111          * The doc comment, or <code>null</code> if none.
112          * Defaults to none.
113          * @since 3.0
114          */
115         Javadoc optionalDocComment = null;
116
117         /**
118          * The annotations (element type: <code>Annotation</code>). 
119          * Null in JLS2. Added in JLS3; defaults to an empty list
120          * (see constructor).
121          * @since 3.1
122          */
123         private ASTNode.NodeList annotations = null;
124         
125         /**
126          * The package name; lazily initialized; defaults to a unspecified,
127          * legal Java package identifier.
128          */
129         private Name packageName = null;
130
131         /**
132          * Creates a new AST node for a package declaration owned by the
133          * given AST. The package declaration initially has an unspecified,
134          * but legal, Java identifier; and an empty list of annotations.
135          * <p>
136          * N.B. This constructor is package-private; all subclasses must be 
137          * declared in the same package; clients are unable to declare 
138          * additional subclasses.
139          * </p>
140          * 
141          * @param ast the AST that is to own this node
142          */
143         PackageDeclaration(AST ast) {
144                 super(ast);
145                 if (ast.apiLevel >= AST.JLS3) {
146                         this.annotations = new ASTNode.NodeList(ANNOTATIONS_PROPERTY);
147                 }
148         }
149
150         /* (omit javadoc for this method)
151          * Method declared on ASTNode.
152          */
153         final List internalStructuralPropertiesForType(int apiLevel) {
154                 return propertyDescriptors(apiLevel);
155         }
156         
157         /* (omit javadoc for this method)
158          * Method declared on ASTNode.
159          */
160         final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
161                 if (property == JAVADOC_PROPERTY) {
162                         if (get) {
163                                 return getJavadoc();
164                         } else {
165                                 setJavadoc((Javadoc) child);
166                                 return null;
167                         }
168                 }
169                 if (property == NAME_PROPERTY) {
170                         if (get) {
171                                 return getName();
172                         } else {
173                                 setName((Name) child);
174                                 return null;
175                         }
176                 }
177                 // allow default implementation to flag the error
178                 return super.internalGetSetChildProperty(property, get, child);
179         }
180         
181         /* (omit javadoc for this method)
182          * Method declared on ASTNode.
183          */
184         final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
185                 if (property == ANNOTATIONS_PROPERTY) {
186                         return annotations();
187                 }
188                 // allow default implementation to flag the error
189                 return super.internalGetChildListProperty(property);
190         }
191
192         /* (omit javadoc for this method)
193          * Method declared on ASTNode.
194          */
195         final int getNodeType0() {
196                 return PACKAGE_DECLARATION;
197         }
198
199         /* (omit javadoc for this method)
200          * Method declared on ASTNode.
201          */
202         ASTNode clone0(AST target) {
203                 PackageDeclaration result = new PackageDeclaration(target);
204                 result.setSourceRange(this.getStartPosition(), this.getLength());
205                 if (this.ast.apiLevel >= AST.JLS3) {
206                         result.setJavadoc((Javadoc) ASTNode.copySubtree(target, getJavadoc()));
207                         result.annotations().addAll(ASTNode.copySubtrees(target, annotations()));
208                 }
209                 result.setName((Name) getName().clone(target));
210                 return result;
211         }
212
213         /* (omit javadoc for this method)
214          * Method declared on ASTNode.
215          */
216         final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
217                 // dispatch to correct overloaded match method
218                 return matcher.match(this, other);
219         }
220
221         /* (omit javadoc for this method)
222          * Method declared on ASTNode.
223          */
224         void accept0(ASTVisitor visitor) {
225                 boolean visitChildren = visitor.visit(this);
226                 if (visitChildren) {
227                         if (this.ast.apiLevel >= AST.JLS3) {
228                                 acceptChild(visitor, getJavadoc());
229                                 acceptChildren(visitor, this.annotations);
230                         }
231                         acceptChild(visitor, getName());
232                 }
233                 visitor.endVisit(this);
234         }
235         
236         /**
237          * Returns the live ordered list of annotations of this 
238          * package declaration (added in JLS3 API).
239          * 
240          * @return the live list of annotations
241          *    (element type: <code>Annotation</code>)
242          * @exception UnsupportedOperationException if this operation is used in
243          * a JLS2 AST
244          * @since 3.1
245          */ 
246         public List annotations() {
247                 // more efficient than just calling unsupportedIn2() to check
248                 if (this.annotations == null) {
249                         unsupportedIn2();
250                 }
251                 return this.annotations;
252         }
253         
254         /**
255          * Returns the doc comment node.
256          * 
257          * @return the doc comment node, or <code>null</code> if none
258          * @exception UnsupportedOperationException if this operation is used in
259          * a JLS2 AST
260          * @since 3.0
261          */
262         public Javadoc getJavadoc() {
263                 // more efficient than just calling unsupportedIn2() to check
264                 if (this.annotations == null) {
265                         unsupportedIn2();
266                 }
267                 return this.optionalDocComment;
268         }
269
270         /**
271          * Sets or clears the doc comment node.
272          * 
273          * @param docComment the doc comment node, or <code>null</code> if none
274          * @exception IllegalArgumentException if the doc comment string is invalid
275          * @exception UnsupportedOperationException if this operation is used in
276          * a JLS2 AST
277          * @since 3.0
278          */
279         public void setJavadoc(Javadoc docComment) {
280                 // more efficient than just calling unsupportedIn2() to check
281                 if (this.annotations == null) {
282                         unsupportedIn2();
283                 }
284                 ASTNode oldChild = this.optionalDocComment;
285                 preReplaceChild(oldChild, docComment, JAVADOC_PROPERTY);
286                 this.optionalDocComment = docComment;
287                 postReplaceChild(oldChild, docComment, JAVADOC_PROPERTY);
288         }
289
290         /**
291          * Returns the package name of this package declaration.
292          * 
293          * @return the package name node
294          */ 
295         public Name getName() {
296                 if (this.packageName == null) {
297                         // lazy init must be thread-safe for readers
298                         synchronized (this) {
299                                 if (this.packageName == null) {
300                                         preLazyInit();
301                                         this.packageName = new SimpleName(this.ast);
302                                         postLazyInit(this.packageName, NAME_PROPERTY);
303                                 }
304                         }
305                 }
306                 return this.packageName;
307         }
308         
309         /**
310          * Sets the package name of this package declaration to the given name.
311          * 
312          * @param name the new package name
313          * @exception IllegalArgumentException if`:
314          * <ul>
315          * <li>the node belongs to a different AST</li>
316          * <li>the node already has a parent</li>
317          * </ul>
318          */ 
319         public void setName(Name name) {
320                 if (name == null) {
321                         throw new IllegalArgumentException();
322                 }
323                 ASTNode oldChild = this.packageName;
324                 preReplaceChild(oldChild, name, NAME_PROPERTY);
325                 this.packageName = name;
326                 postReplaceChild(oldChild, name, NAME_PROPERTY);
327         }
328         
329         /**
330          * Resolves and returns the binding for the package declared in this package
331          * declaration.
332          * <p>
333          * Note that bindings are generally unavailable unless requested when the
334          * AST is being built.
335          * </p>
336          * 
337          * @return the binding, or <code>null</code> if the binding cannot be 
338          *    resolved
339          */     
340         public IPackageBinding resolveBinding() {
341                 return this.ast.getBindingResolver().resolvePackage(this);
342         }
343         
344         /* (omit javadoc for this method)
345          * Method declared on ASTNode.
346          */
347         int memSize() {
348                 return BASE_NODE_SIZE + 3 * 4;
349         }
350         
351         /* (omit javadoc for this method)
352          * Method declared on ASTNode.
353          */
354         int treeSize() {
355                 return
356                         memSize()
357                         + (this.optionalDocComment == null ? 0 : getJavadoc().treeSize())
358                         + (this.annotations == null ? 0 : this.annotations.listSize())
359                         + (this.packageName == null ? 0 : getName().treeSize());
360         }
361 }
362