2d6c99694c74e2dc4adc5dacc1a19c2d2eed67fc
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / core / dom / SingleMemberAnnotation.java
1 /*******************************************************************************
2  * Copyright (c) 2004, 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 package net.sourceforge.phpdt.core.dom;
12
13 import java.util.ArrayList;
14 import java.util.List;
15
16 /**
17  * Single member annotation node (added in JLS3 API). The single member annotation 
18  * "@foo(bar)" is equivalent to the normal annotation "@foo(value=bar)". 
19  * <p>
20  * <pre>
21  * SingleMemberAnnotation:
22  *   <b>@</b> TypeName <b>(</b> Expression  <b>)</b>
23  * </pre>
24  * Within annotations, only certain kinds of expressions are meaningful,
25  * including other annotations.
26  * </p>
27  * 
28  * @since 3.1
29  * @noinstantiate This class is not intended to be instantiated by clients.
30  */
31 public final class SingleMemberAnnotation extends Annotation {
32         
33         /**
34          * The "typeName" structural property of this node type.
35          */
36         public static final ChildPropertyDescriptor TYPE_NAME_PROPERTY = 
37                 internalTypeNamePropertyFactory(SingleMemberAnnotation.class);
38
39         /**
40          * The "value" structural property of this node type.
41          */
42         public static final ChildPropertyDescriptor VALUE_PROPERTY = 
43                 new ChildPropertyDescriptor(SingleMemberAnnotation.class, "value", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
44
45         /**
46          * A list of property descriptors (element type: 
47          * {@link StructuralPropertyDescriptor}),
48          * or null if uninitialized.
49          */
50         private static final List PROPERTY_DESCRIPTORS;
51         
52         static {
53                 List propertyList = new ArrayList(3);
54                 createPropertyList(SingleMemberAnnotation.class, propertyList);
55                 addProperty(TYPE_NAME_PROPERTY, propertyList);
56                 addProperty(VALUE_PROPERTY, propertyList);
57                 PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
58         }
59         
60         /**
61          * Returns a list of structural property descriptors for this node type.
62          * Clients must not modify the result.
63          * 
64          * @param apiLevel the API level; one of the AST.JLS* constants
65          * @return a list of property descriptors (element type: 
66          * {@link StructuralPropertyDescriptor})
67          */
68         public static List propertyDescriptors(int apiLevel) {
69                 return PROPERTY_DESCRIPTORS;
70         }
71         
72         /**
73          * The value; lazily initialized; defaults to a unspecified, but legal,
74          * expression.
75          */
76         private Expression value = null;
77
78         /**
79          * Creates a new unparented normal annotation node owned 
80          * by the given AST.  By default, the annotation has an
81          * unspecified type name and an unspecified value.
82          * <p>
83          * N.B. This constructor is package-private.
84          * </p>
85          * 
86          * @param ast the AST that is to own this node
87          */
88         SingleMemberAnnotation(AST ast) {
89                 super(ast);
90             unsupportedIn2();
91         }
92
93         /* (omit javadoc for this method)
94          * Method declared on ASTNode.
95          */
96         final List internalStructuralPropertiesForType(int apiLevel) {
97                 return propertyDescriptors(apiLevel);
98         }
99         
100         /* (omit javadoc for this method)
101          * Method declared on ASTNode.
102          */
103         final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
104                 if (property == TYPE_NAME_PROPERTY) {
105                         if (get) {
106                                 return getTypeName();
107                         } else {
108                                 setTypeName((Name) child);
109                                 return null;
110                         }
111                 }
112                 if (property == VALUE_PROPERTY) {
113                         if (get) {
114                                 return getValue();
115                         } else {
116                                 setValue((Expression) child);
117                                 return null;
118                         }
119                 }
120                 // allow default implementation to flag the error
121                 return super.internalGetSetChildProperty(property, get, child);
122         }
123         
124         /* (omit javadoc for this method)
125          * Method declared on BodyDeclaration.
126          */
127         final ChildPropertyDescriptor internalTypeNameProperty() {
128                 return TYPE_NAME_PROPERTY;
129         }
130
131         /* (omit javadoc for this method)
132          * Method declared on ASTNode.
133          */
134         final int getNodeType0() {
135                 return SINGLE_MEMBER_ANNOTATION;
136         }
137
138         /* (omit javadoc for this method)
139          * Method declared on ASTNode.
140          */
141         ASTNode clone0(AST target) {
142                 SingleMemberAnnotation result = new SingleMemberAnnotation(target);
143                 result.setSourceRange(this.getStartPosition(), this.getLength());
144                 result.setTypeName((Name) ASTNode.copySubtree(target, getTypeName()));
145                 result.setValue((Expression) ASTNode.copySubtree(target, getValue()));
146                 return result;
147         }
148         
149         /* (omit javadoc for this method)
150          * Method declared on ASTNode.
151          */
152         final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
153                 // dispatch to correct overloaded match method
154                 return matcher.match(this, other);
155         }
156         
157         /* (omit javadoc for this method)
158          * Method declared on ASTNode.
159          */
160         void accept0(ASTVisitor visitor) {
161                 boolean visitChildren = visitor.visit(this);
162                 if (visitChildren) {
163                         // visit children in normal left to right reading order
164                         acceptChild(visitor, getTypeName());
165                         acceptChild(visitor, getValue());
166                 }
167                 visitor.endVisit(this);
168         }
169         
170         /**
171          * Returns the value of this annotation.
172          * 
173          * @return the value node
174          */ 
175         public Expression getValue() {
176                 if (this.value == null) {
177                         // lazy init must be thread-safe for readers
178                         synchronized (this) {
179                                 if (this.value == null) {
180                                         preLazyInit();
181                                         this.value = new SimpleName(this.ast);
182                                         postLazyInit(this.value, VALUE_PROPERTY);
183                                 }
184                         }
185                 }
186                 return this.value;
187         }
188                 
189         /**
190          * Sets the value of this annotation.
191          * 
192          * @param value the new value
193          * @exception IllegalArgumentException if:
194          * <ul>
195          * <li>the node belongs to a different AST</li>
196          * <li>the node already has a parent</li>
197          * <li>a cycle in would be created</li>
198          * </ul>
199          */ 
200         public void setValue(Expression value) {
201                 if (value == null) {
202                         throw new IllegalArgumentException();
203                 }
204                 ASTNode oldChild = this.value;
205                 preReplaceChild(oldChild, value, VALUE_PROPERTY);
206                 this.value = value;
207                 postReplaceChild(oldChild, value, VALUE_PROPERTY);
208         }
209
210         /* (omit javadoc for this method)
211          * Method declared on ASTNode.
212          */
213         int memSize() {
214                 return super.memSize() + 1 * 4;
215         }
216         
217         /* (omit javadoc for this method)
218          * Method declared on ASTNode.
219          */
220         int treeSize() {
221                 return
222                         memSize()
223                         + (this.typeName == null ? 0 : getTypeName().treeSize())
224                         + (this.value == null ? 0 : getValue().treeSize());
225         }
226 }