001: /*******************************************************************************
002: * Copyright (c) 2004, 2006 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: * Member value pair node (added in JLS3 API). Member value pairs appear in annotations.
017: * <p>
018: * <pre>
019: * MemberValuePair:
020: * SimpleName <b>=</b> Expression
021: * </pre>
022: * Within annotations, only certain kinds of expressions are meaningful,
023: * including other annotations.
024: * </p>
025: *
026: * @see NormalAnnotation
027: * @since 3.1
028: */
029: public class MemberValuePair extends ASTNode {
030:
031: /**
032: * The "name" structural property of this node type.
033: */
034: public static final ChildPropertyDescriptor NAME_PROPERTY = new ChildPropertyDescriptor(
035: MemberValuePair.class,
036: "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
037:
038: /**
039: * The "value" structural property of this node type.
040: */
041: public static final ChildPropertyDescriptor VALUE_PROPERTY = new ChildPropertyDescriptor(
042: MemberValuePair.class,
043: "value", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
044:
045: /**
046: * A list of property descriptors (element type:
047: * {@link StructuralPropertyDescriptor}),
048: * or null if uninitialized.
049: */
050: private static final List PROPERTY_DESCRIPTORS;
051:
052: static {
053: List propertyList = new ArrayList(3);
054: createPropertyList(MemberValuePair.class, propertyList);
055: addProperty(NAME_PROPERTY, propertyList);
056: addProperty(VALUE_PROPERTY, propertyList);
057: PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
058: }
059:
060: /**
061: * Returns a list of structural property descriptors for this node type.
062: * Clients must not modify the result.
063: *
064: * @param apiLevel the API level; one of the AST.JLS* constants
065: * @return a list of property descriptors (element type:
066: * {@link StructuralPropertyDescriptor})
067: */
068: public static List propertyDescriptors(int apiLevel) {
069: return PROPERTY_DESCRIPTORS;
070: }
071:
072: /**
073: * The member name; lazily initialized; defaults to a unspecified,
074: * legal name.
075: */
076: private SimpleName name = null;
077:
078: /**
079: * The value; lazily initialized; defaults to a unspecified,
080: * legal expression.
081: */
082: private Expression value = null;
083:
084: /**
085: * Creates a new AST node for a member value pair owned by the given
086: * AST. By default, the node has an unspecified (but legal) member
087: * name and value.
088: * <p>
089: * N.B. This constructor is package-private.
090: * </p>
091: *
092: * @param ast the AST that is to own this node
093: */
094: MemberValuePair(AST ast) {
095: super (ast);
096: unsupportedIn2();
097: }
098:
099: /* (omit javadoc for this method)
100: * Method declared on ASTNode.
101: */
102: final List internalStructuralPropertiesForType(int apiLevel) {
103: return propertyDescriptors(apiLevel);
104: }
105:
106: /* (omit javadoc for this method)
107: * Method declared on ASTNode.
108: */
109: final ASTNode internalGetSetChildProperty(
110: ChildPropertyDescriptor property, boolean get, ASTNode child) {
111: if (property == NAME_PROPERTY) {
112: if (get) {
113: return getName();
114: } else {
115: setName((SimpleName) child);
116: return null;
117: }
118: }
119: if (property == VALUE_PROPERTY) {
120: if (get) {
121: return getValue();
122: } else {
123: setValue((Expression) child);
124: return null;
125: }
126: }
127: // allow default implementation to flag the error
128: return super .internalGetSetChildProperty(property, get, child);
129: }
130:
131: /* (omit javadoc for this method)
132: * Method declared on ASTNode.
133: */
134: final int getNodeType0() {
135: return MEMBER_VALUE_PAIR;
136: }
137:
138: /* (omit javadoc for this method)
139: * Method declared on ASTNode.
140: */
141: ASTNode clone0(AST target) {
142: MemberValuePair result = new MemberValuePair(target);
143: result
144: .setSourceRange(this .getStartPosition(), this
145: .getLength());
146: result.setName((SimpleName) ASTNode.copySubtree(target,
147: getName()));
148: result.setValue((Expression) ASTNode.copySubtree(target,
149: getValue()));
150: return result;
151: }
152:
153: /* (omit javadoc for this method)
154: * Method declared on ASTNode.
155: */
156: final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
157: // dispatch to correct overloaded match method
158: return matcher.match(this , other);
159: }
160:
161: /* (omit javadoc for this method)
162: * Method declared on ASTNode.
163: */
164: void accept0(ASTVisitor visitor) {
165: boolean visitChildren = visitor.visit(this );
166: if (visitChildren) {
167: // visit children in normal left to right reading order
168: acceptChild(visitor, getName());
169: acceptChild(visitor, getValue());
170: }
171: visitor.endVisit(this );
172: }
173:
174: /**
175: * Returns the member name.
176: *
177: * @return the member name node
178: */
179: public SimpleName getName() {
180: if (this .name == null) {
181: // lazy init must be thread-safe for readers
182: synchronized (this ) {
183: if (this .name == null) {
184: preLazyInit();
185: this .name = new SimpleName(this .ast);
186: postLazyInit(this .name, NAME_PROPERTY);
187: }
188: }
189: }
190: return this .name;
191: }
192:
193: /**
194: * Resolves and returns the member value pair binding for this member value pair.
195: * <p>
196: * Note that bindings are generally unavailable unless requested when the
197: * AST is being built.
198: * </p>
199: *
200: * @return the binding, or <code>null</code> if the binding cannot be
201: * resolved
202: * @since 3.2
203: */
204: public final IMemberValuePairBinding resolveMemberValuePairBinding() {
205: return this .ast.getBindingResolver().resolveMemberValuePair(
206: this );
207: }
208:
209: /**
210: * Sets the member name.
211: *
212: * @param name the member name node
213: * @exception IllegalArgumentException if:
214: * <ul>
215: * <li>the node belongs to a different AST</li>
216: * <li>the node already has a parent</li>
217: * </ul>
218: */
219: public void setName(SimpleName name) {
220: if (name == null) {
221: throw new IllegalArgumentException();
222: }
223: ASTNode oldChild = this .name;
224: preReplaceChild(oldChild, name, NAME_PROPERTY);
225: this .name = name;
226: postReplaceChild(oldChild, name, NAME_PROPERTY);
227: }
228:
229: /**
230: * Returns the value expression.
231: *
232: * @return the value expression
233: */
234: public Expression getValue() {
235: if (this .value == null) {
236: // lazy init must be thread-safe for readers
237: synchronized (this ) {
238: if (this .value == null) {
239: preLazyInit();
240: this .value = new SimpleName(this .ast);
241: postLazyInit(this .value, VALUE_PROPERTY);
242: }
243: }
244: }
245: return this .value;
246: }
247:
248: /**
249: * Sets the value of this pair.
250: *
251: * @param value the new value
252: * @exception IllegalArgumentException if:
253: * <ul>
254: * <li>the node belongs to a different AST</li>
255: * <li>the node already has a parent</li>
256: * <li>a cycle in would be created</li>
257: * </ul>
258: */
259: public void setValue(Expression value) {
260: if (value == null) {
261: throw new IllegalArgumentException();
262: }
263: ASTNode oldChild = this .value;
264: preReplaceChild(oldChild, value, VALUE_PROPERTY);
265: this .value = value;
266: postReplaceChild(oldChild, value, VALUE_PROPERTY);
267: }
268:
269: /* (omit javadoc for this method)
270: * Method declared on ASTNode.
271: */
272: int memSize() {
273: return BASE_NODE_SIZE + 2 * 4;
274: }
275:
276: /* (omit javadoc for this method)
277: * Method declared on ASTNode.
278: */
279: int treeSize() {
280: return memSize()
281: + (this .name == null ? 0 : getName().treeSize())
282: + (this .value == null ? 0 : getValue().treeSize());
283: }
284: }
|