001: /*******************************************************************************
002: * Copyright (c) 2004, 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: * Single member annotation node (added in JLS3 API). The single member annotation
017: * "@foo(bar)" is equivalent to the normal annotation "@foo(value=bar)".
018: * <p>
019: * <pre>
020: * SingleMemberAnnotation:
021: * <b>@</b> TypeName <b>(</b> Expression <b>)</b>
022: * </pre>
023: * Within annotations, only certain kinds of expressions are meaningful,
024: * including other annotations.
025: * </p>
026: *
027: * @since 3.1
028: */
029: public final class SingleMemberAnnotation extends Annotation {
030:
031: /**
032: * The "typeName" structural property of this node type.
033: */
034: public static final ChildPropertyDescriptor TYPE_NAME_PROPERTY = internalTypeNamePropertyFactory(SingleMemberAnnotation.class);
035:
036: /**
037: * The "value" structural property of this node type.
038: */
039: public static final ChildPropertyDescriptor VALUE_PROPERTY = new ChildPropertyDescriptor(
040: SingleMemberAnnotation.class,
041: "value", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
042:
043: /**
044: * A list of property descriptors (element type:
045: * {@link StructuralPropertyDescriptor}),
046: * or null if uninitialized.
047: */
048: private static final List PROPERTY_DESCRIPTORS;
049:
050: static {
051: List propertyList = new ArrayList(3);
052: createPropertyList(SingleMemberAnnotation.class, propertyList);
053: addProperty(TYPE_NAME_PROPERTY, propertyList);
054: addProperty(VALUE_PROPERTY, propertyList);
055: PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
056: }
057:
058: /**
059: * Returns a list of structural property descriptors for this node type.
060: * Clients must not modify the result.
061: *
062: * @param apiLevel the API level; one of the AST.JLS* constants
063: * @return a list of property descriptors (element type:
064: * {@link StructuralPropertyDescriptor})
065: */
066: public static List propertyDescriptors(int apiLevel) {
067: return PROPERTY_DESCRIPTORS;
068: }
069:
070: /**
071: * The value; lazily initialized; defaults to a unspecified, but legal,
072: * expression.
073: */
074: private Expression value = null;
075:
076: /**
077: * Creates a new unparented normal annotation node owned
078: * by the given AST. By default, the annotation has an
079: * unspecified type name and an unspecified value.
080: * <p>
081: * N.B. This constructor is package-private.
082: * </p>
083: *
084: * @param ast the AST that is to own this node
085: */
086: SingleMemberAnnotation(AST ast) {
087: super (ast);
088: unsupportedIn2();
089: }
090:
091: /* (omit javadoc for this method)
092: * Method declared on ASTNode.
093: */
094: final List internalStructuralPropertiesForType(int apiLevel) {
095: return propertyDescriptors(apiLevel);
096: }
097:
098: /* (omit javadoc for this method)
099: * Method declared on ASTNode.
100: */
101: final ASTNode internalGetSetChildProperty(
102: ChildPropertyDescriptor property, boolean get, ASTNode child) {
103: if (property == TYPE_NAME_PROPERTY) {
104: if (get) {
105: return getTypeName();
106: } else {
107: setTypeName((Name) child);
108: return null;
109: }
110: }
111: if (property == VALUE_PROPERTY) {
112: if (get) {
113: return getValue();
114: } else {
115: setValue((Expression) child);
116: return null;
117: }
118: }
119: // allow default implementation to flag the error
120: return super .internalGetSetChildProperty(property, get, child);
121: }
122:
123: /* (omit javadoc for this method)
124: * Method declared on BodyDeclaration.
125: */
126: final ChildPropertyDescriptor internalTypeNameProperty() {
127: return TYPE_NAME_PROPERTY;
128: }
129:
130: /* (omit javadoc for this method)
131: * Method declared on ASTNode.
132: */
133: final int getNodeType0() {
134: return SINGLE_MEMBER_ANNOTATION;
135: }
136:
137: /* (omit javadoc for this method)
138: * Method declared on ASTNode.
139: */
140: ASTNode clone0(AST target) {
141: SingleMemberAnnotation result = new SingleMemberAnnotation(
142: target);
143: result
144: .setSourceRange(this .getStartPosition(), this
145: .getLength());
146: result.setTypeName((Name) ASTNode.copySubtree(target,
147: getTypeName()));
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, getTypeName());
169: acceptChild(visitor, getValue());
170: }
171: visitor.endVisit(this );
172: }
173:
174: /**
175: * Returns the value of this annotation.
176: *
177: * @return the value node
178: */
179: public Expression getValue() {
180: if (this .value == null) {
181: // lazy init must be thread-safe for readers
182: synchronized (this ) {
183: if (this .value == null) {
184: preLazyInit();
185: this .value = new SimpleName(this .ast);
186: postLazyInit(this .value, VALUE_PROPERTY);
187: }
188: }
189: }
190: return this .value;
191: }
192:
193: /**
194: * Sets the value of this annotation.
195: *
196: * @param value the new value
197: * @exception IllegalArgumentException if:
198: * <ul>
199: * <li>the node belongs to a different AST</li>
200: * <li>the node already has a parent</li>
201: * <li>a cycle in would be created</li>
202: * </ul>
203: */
204: public void setValue(Expression value) {
205: if (value == null) {
206: throw new IllegalArgumentException();
207: }
208: ASTNode oldChild = this .value;
209: preReplaceChild(oldChild, value, VALUE_PROPERTY);
210: this .value = value;
211: postReplaceChild(oldChild, value, VALUE_PROPERTY);
212: }
213:
214: /* (omit javadoc for this method)
215: * Method declared on ASTNode.
216: */
217: int memSize() {
218: return super .memSize() + 1 * 4;
219: }
220:
221: /* (omit javadoc for this method)
222: * Method declared on ASTNode.
223: */
224: int treeSize() {
225: return memSize()
226: + (this .typeName == null ? 0 : getTypeName().treeSize())
227: + (this .value == null ? 0 : getValue().treeSize());
228: }
229: }
|