e5b29b03deea81e19c761e7f98c91da0495a3143
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / core / dom / QualifiedName.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 /**
19  * AST node for a qualified name. A qualified name is defined recursively
20  * as a simple name preceded by a name, which qualifies it. Expressing it this
21  * way means that the qualifier and the simple name get their own AST nodes.
22  * <pre>
23  * QualifiedName:
24  *    Name <b>.</b> SimpleName
25  * </pre>
26  * <p>
27  * See <code>FieldAccess</code> for guidelines on handling other expressions
28  * that resemble qualified names.
29  * </p>
30  * 
31  * @see FieldAccess
32  * @since 2.0
33  * @noinstantiate This class is not intended to be instantiated by clients.
34  */
35 public class QualifiedName extends Name {
36         
37         /**
38          * The "qualifier" structural property of this node type.
39          * @since 3.0
40          */
41         public static final ChildPropertyDescriptor QUALIFIER_PROPERTY = 
42                 new ChildPropertyDescriptor(QualifiedName.class, "qualifier", Name.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
43
44         /**
45          * The "name" structural property of this node type.
46          * @since 3.0
47          */
48         public static final ChildPropertyDescriptor NAME_PROPERTY = 
49                 new ChildPropertyDescriptor(QualifiedName.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
50
51         /**
52          * A list of property descriptors (element type: 
53          * {@link StructuralPropertyDescriptor}),
54          * or null if uninitialized.
55          */
56         private static final List PROPERTY_DESCRIPTORS;
57         
58         static {
59                 List propertyList = new ArrayList(3);
60                 createPropertyList(QualifiedName.class, propertyList);
61                 addProperty(QUALIFIER_PROPERTY, propertyList);
62                 addProperty(NAME_PROPERTY, propertyList);
63                 PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
64         }
65
66         /**
67          * Returns a list of structural property descriptors for this node type.
68          * Clients must not modify the result.
69          * 
70          * @param apiLevel the API level; one of the
71          * <code>AST.JLS*</code> constants
72          * @return a list of property descriptors (element type: 
73          * {@link StructuralPropertyDescriptor})
74          * @since 3.0
75          */
76         public static List propertyDescriptors(int apiLevel) {
77                 return PROPERTY_DESCRIPTORS;
78         }
79                         
80         /**
81          * The identifier; lazily initialized; defaults to a unspecified, legal 
82          * Java identifier.
83          */
84         private Name qualifier = null;
85         
86         /**
87          * The name being qualified; lazily initialized; defaults to a unspecified,
88          * legal Java identifier.
89          */
90         private SimpleName name = null;
91         
92         /**
93          * Creates a new AST node for a qualified name owned by the given AST.
94          * <p>
95          * N.B. This constructor is package-private; all subclasses must be 
96          * declared in the same package; clients are unable to declare 
97          * additional subclasses.
98          * </p>
99          * 
100          * @param ast the AST that is to own this node
101          */
102         QualifiedName(AST ast) {
103                 super(ast);
104         }
105         
106         /* (omit javadoc for this method)
107          * Method declared on ASTNode.
108          */
109         final List internalStructuralPropertiesForType(int apiLevel) {
110                 return propertyDescriptors(apiLevel);
111         }
112         
113         /* (omit javadoc for this method)
114          * Method declared on ASTNode.
115          */
116         final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
117                 if (property == QUALIFIER_PROPERTY) {
118                         if (get) {
119                                 return getQualifier();
120                         } else {
121                                 setQualifier((Name) child);
122                                 return null;
123                         }
124                 }
125                 if (property == NAME_PROPERTY) {
126                         if (get) {
127                                 return getName();
128                         } else {
129                                 setName((SimpleName) child);
130                                 return null;
131                         }
132                 }
133                 // allow default implementation to flag the error
134                 return super.internalGetSetChildProperty(property, get, child);
135         }
136         
137         /* (omit javadoc for this method)
138          * Method declared on ASTNode.
139          */
140         final int getNodeType0() {
141                 return QUALIFIED_NAME;
142         }
143
144         /* (omit javadoc for this method)
145          * Method declared on ASTNode.
146          */
147         ASTNode clone0(AST target) {
148                 QualifiedName result = new QualifiedName(target);
149                 result.setSourceRange(this.getStartPosition(), this.getLength());
150                 result.setQualifier((Name) getQualifier().clone(target));
151                 result.setName((SimpleName) getName().clone(target));
152                 return result;
153         }
154
155         /* (omit javadoc for this method)
156          * Method declared on ASTNode.
157          */
158         final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
159                 // dispatch to correct overloaded match method
160                 return matcher.match(this, other);
161         }
162
163         /* (omit javadoc for this method)
164          * Method declared on ASTNode.
165          */
166         void accept0(ASTVisitor visitor) {
167                 boolean visitChildren = visitor.visit(this);
168                 if (visitChildren) {
169                         // visit children in normal left to right reading order
170                         acceptChild(visitor, getQualifier());
171                         acceptChild(visitor, getName());
172                 }
173                 visitor.endVisit(this);
174         }
175         
176         /**
177          * Returns the qualifier part of this qualified name.
178          * 
179          * @return the qualifier part of this qualified name
180          */ 
181         public Name getQualifier() {
182                 if (this.qualifier == null) {
183                         // lazy init must be thread-safe for readers
184                         synchronized (this) {
185                                 if (this.qualifier == null) {
186                                         preLazyInit();
187                                         this.qualifier = new SimpleName(this.ast);
188                                         postLazyInit(this.qualifier, QUALIFIER_PROPERTY);
189                                 }
190                         }
191                 }
192                 return this.qualifier;
193         }
194         
195         /**
196          * Sets the qualifier of this qualified name to the given name.
197          * 
198          * @param qualifier the qualifier of this qualified name
199          * @exception IllegalArgumentException if:
200          * <ul>
201          * <li>the node belongs to a different AST</li>
202          * <li>the node already has a parent</li>
203          * <li>a cycle in would be created</li>
204          * </ul>
205          */ 
206         public void setQualifier(Name qualifier) {
207                 if (qualifier == null) {
208                         throw new IllegalArgumentException();
209                 }
210                 ASTNode oldChild = this.qualifier;
211                 preReplaceChild(oldChild, qualifier, QUALIFIER_PROPERTY);
212                 this.qualifier = qualifier;
213                 postReplaceChild(oldChild, qualifier, QUALIFIER_PROPERTY);
214         }
215         
216         /**
217          * Returns the name part of this qualified name.
218          * 
219          * @return the name being qualified 
220          */ 
221         public SimpleName getName() {
222                 if (this.name == null) {
223                         // lazy init must be thread-safe for readers
224                         synchronized (this) {
225                                 if (this.name == null) {
226                                         preLazyInit();
227                                         this.name = new SimpleName(this.ast);
228                                         postLazyInit(this.name, NAME_PROPERTY);
229                                 }
230                         }
231                 }
232                 return this.name;
233         }
234         
235         /**
236          * Sets the name part of this qualified name to the given simple name.
237          * 
238          * @param name the identifier of this qualified name
239          * @exception IllegalArgumentException if:
240          * <ul>
241          * <li>the node belongs to a different AST</li>
242          * <li>the node already has a parent</li>
243          * </ul>
244          */ 
245         public void setName(SimpleName name) {
246                 if (name == null) {
247                         throw new IllegalArgumentException();
248                 }
249                 ASTNode oldChild = this.name;
250                 preReplaceChild(oldChild, name, NAME_PROPERTY);
251                 this.name = name;
252                 postReplaceChild(oldChild, name, NAME_PROPERTY);
253         }
254         
255         /* (omit javadoc for this method)
256          * Method declared on Name.
257          */
258         void appendName(StringBuffer buffer) {
259                 getQualifier().appendName(buffer);
260                 buffer.append('.');
261                 getName().appendName(buffer);
262         }
263
264         /* (omit javadoc for this method)
265          * Method declared on ASTNode.
266          */
267         int memSize() {
268                 return BASE_NAME_NODE_SIZE + 3 * 4;
269         }
270         
271         /* (omit javadoc for this method)
272          * Method declared on ASTNode.
273          */
274         int treeSize() {
275                 return 
276                         memSize()
277                         + (this.name == null ? 0 : getName().treeSize())
278                         + (this.qualifier == null ? 0 : getQualifier().treeSize());
279         }
280 }
281