001: /*******************************************************************************
002: * Copyright (c) 2000, 2005 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.core.dom;
011:
012: import java.util.ArrayList;
013: import java.util.List;
014:
015: /**
016: * AST node for a qualified name. A qualified name is defined recursively
017: * as a simple name preceded by a name, which qualifies it. Expressing it this
018: * way means that the qualifier and the simple name get their own AST nodes.
019: * <pre>
020: * QualifiedName:
021: * Name <b>.</b> SimpleName
022: * </pre>
023: * <p>
024: * See <code>FieldAccess</code> for guidelines on handling other expressions
025: * that resemble qualified names.
026: * </p>
027: *
028: * @see FieldAccess
029: * @since 2.0
030: */
031: public class QualifiedName extends Name {
032:
033: /**
034: * The "qualifier" structural property of this node type.
035: * @since 3.0
036: */
037: public static final ChildPropertyDescriptor QUALIFIER_PROPERTY = new ChildPropertyDescriptor(
038: QualifiedName.class,
039: "qualifier", Name.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
040:
041: /**
042: * The "name" structural property of this node type.
043: * @since 3.0
044: */
045: public static final ChildPropertyDescriptor NAME_PROPERTY = new ChildPropertyDescriptor(
046: QualifiedName.class,
047: "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
048:
049: /**
050: * A list of property descriptors (element type:
051: * {@link StructuralPropertyDescriptor}),
052: * or null if uninitialized.
053: */
054: private static final List PROPERTY_DESCRIPTORS;
055:
056: static {
057: List propertyList = new ArrayList(3);
058: createPropertyList(QualifiedName.class, propertyList);
059: addProperty(QUALIFIER_PROPERTY, propertyList);
060: addProperty(NAME_PROPERTY, propertyList);
061: PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
062: }
063:
064: /**
065: * Returns a list of structural property descriptors for this node type.
066: * Clients must not modify the result.
067: *
068: * @param apiLevel the API level; one of the
069: * <code>AST.JLS*</code> constants
070: * @return a list of property descriptors (element type:
071: * {@link StructuralPropertyDescriptor})
072: * @since 3.0
073: */
074: public static List propertyDescriptors(int apiLevel) {
075: return PROPERTY_DESCRIPTORS;
076: }
077:
078: /**
079: * The identifier; lazily initialized; defaults to a unspecified, legal
080: * Java identifier.
081: */
082: private Name qualifier = null;
083:
084: /**
085: * The name being qualified; lazily initialized; defaults to a unspecified,
086: * legal Java identifier.
087: */
088: private SimpleName name = null;
089:
090: /**
091: * Creates a new AST node for a qualified name owned by the given AST.
092: * <p>
093: * N.B. This constructor is package-private; all subclasses must be
094: * declared in the same package; clients are unable to declare
095: * additional subclasses.
096: * </p>
097: *
098: * @param ast the AST that is to own this node
099: */
100: QualifiedName(AST ast) {
101: super (ast);
102: }
103:
104: /* (omit javadoc for this method)
105: * Method declared on ASTNode.
106: */
107: final List internalStructuralPropertiesForType(int apiLevel) {
108: return propertyDescriptors(apiLevel);
109: }
110:
111: /* (omit javadoc for this method)
112: * Method declared on ASTNode.
113: */
114: final ASTNode internalGetSetChildProperty(
115: ChildPropertyDescriptor property, boolean get, ASTNode child) {
116: if (property == QUALIFIER_PROPERTY) {
117: if (get) {
118: return getQualifier();
119: } else {
120: setQualifier((Name) child);
121: return null;
122: }
123: }
124: if (property == NAME_PROPERTY) {
125: if (get) {
126: return getName();
127: } else {
128: setName((SimpleName) child);
129: return null;
130: }
131: }
132: // allow default implementation to flag the error
133: return super .internalGetSetChildProperty(property, get, child);
134: }
135:
136: /* (omit javadoc for this method)
137: * Method declared on ASTNode.
138: */
139: final int getNodeType0() {
140: return QUALIFIED_NAME;
141: }
142:
143: /* (omit javadoc for this method)
144: * Method declared on ASTNode.
145: */
146: ASTNode clone0(AST target) {
147: QualifiedName result = new QualifiedName(target);
148: result
149: .setSourceRange(this .getStartPosition(), this
150: .getLength());
151: result.setQualifier((Name) getQualifier().clone(target));
152: result.setName((SimpleName) getName().clone(target));
153: return result;
154: }
155:
156: /* (omit javadoc for this method)
157: * Method declared on ASTNode.
158: */
159: final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
160: // dispatch to correct overloaded match method
161: return matcher.match(this , other);
162: }
163:
164: /* (omit javadoc for this method)
165: * Method declared on ASTNode.
166: */
167: void accept0(ASTVisitor visitor) {
168: boolean visitChildren = visitor.visit(this );
169: if (visitChildren) {
170: // visit children in normal left to right reading order
171: acceptChild(visitor, getQualifier());
172: acceptChild(visitor, getName());
173: }
174: visitor.endVisit(this );
175: }
176:
177: /**
178: * Returns the qualifier part of this qualified name.
179: *
180: * @return the qualifier part of this qualified name
181: */
182: public Name getQualifier() {
183: if (this .qualifier == null) {
184: // lazy init must be thread-safe for readers
185: synchronized (this ) {
186: if (this .qualifier == null) {
187: preLazyInit();
188: this .qualifier = new SimpleName(this .ast);
189: postLazyInit(this .qualifier, QUALIFIER_PROPERTY);
190: }
191: }
192: }
193: return this .qualifier;
194: }
195:
196: /**
197: * Sets the qualifier of this qualified name to the given name.
198: *
199: * @param qualifier the qualifier of this qualified name
200: * @exception IllegalArgumentException if:
201: * <ul>
202: * <li>the node belongs to a different AST</li>
203: * <li>the node already has a parent</li>
204: * <li>a cycle in would be created</li>
205: * </ul>
206: */
207: public void setQualifier(Name qualifier) {
208: if (qualifier == null) {
209: throw new IllegalArgumentException();
210: }
211: ASTNode oldChild = this .qualifier;
212: preReplaceChild(oldChild, qualifier, QUALIFIER_PROPERTY);
213: this .qualifier = qualifier;
214: postReplaceChild(oldChild, qualifier, QUALIFIER_PROPERTY);
215: }
216:
217: /**
218: * Returns the name part of this qualified name.
219: *
220: * @return the name being qualified
221: */
222: public SimpleName getName() {
223: if (this .name == null) {
224: // lazy init must be thread-safe for readers
225: synchronized (this ) {
226: if (this .name == null) {
227: preLazyInit();
228: this .name = new SimpleName(this .ast);
229: postLazyInit(this .name, NAME_PROPERTY);
230: }
231: }
232: }
233: return this .name;
234: }
235:
236: /**
237: * Sets the name part of this qualified name to the given simple name.
238: *
239: * @param name the identifier of this qualified name
240: * @exception IllegalArgumentException if:
241: * <ul>
242: * <li>the node belongs to a different AST</li>
243: * <li>the node already has a parent</li>
244: * </ul>
245: */
246: public void setName(SimpleName name) {
247: if (name == null) {
248: throw new IllegalArgumentException();
249: }
250: ASTNode oldChild = this .name;
251: preReplaceChild(oldChild, name, NAME_PROPERTY);
252: this .name = name;
253: postReplaceChild(oldChild, name, NAME_PROPERTY);
254: }
255:
256: /* (omit javadoc for this method)
257: * Method declared on Name.
258: */
259: void appendName(StringBuffer buffer) {
260: getQualifier().appendName(buffer);
261: buffer.append('.');
262: getName().appendName(buffer);
263: }
264:
265: /* (omit javadoc for this method)
266: * Method declared on ASTNode.
267: */
268: int memSize() {
269: return BASE_NAME_NODE_SIZE + 3 * 4;
270: }
271:
272: /* (omit javadoc for this method)
273: * Method declared on ASTNode.
274: */
275: int treeSize() {
276: return memSize()
277: + (this .name == null ? 0 : getName().treeSize())
278: + (this .qualifier == null ? 0 : getQualifier()
279: .treeSize());
280: }
281: }
|