001: /*
002: * Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package com.sun.tools.javac.code;
027:
028: import java.util.LinkedHashMap;
029: import java.util.Map;
030: import javax.lang.model.element.AnnotationMirror;
031: import javax.lang.model.element.AnnotationValue;
032: import javax.lang.model.element.AnnotationValueVisitor;
033: import javax.lang.model.element.ExecutableElement;
034: import javax.lang.model.type.DeclaredType;
035: import com.sun.tools.javac.code.Symbol.*;
036: import com.sun.tools.javac.util.*;
037:
038: import static com.sun.tools.javac.code.TypeTags.*;
039:
040: /** An annotation value.
041: *
042: * <p><b>This is NOT part of any API supported by Sun Microsystems. If
043: * you write code that depends on this, you do so at your own risk.
044: * This code and its internal interfaces are subject to change or
045: * deletion without notice.</b>
046: */
047: @Version("@(#)Attribute.java 1.20 07/05/05")
048: public abstract class Attribute implements AnnotationValue {
049:
050: /** The type of the annotation element. */
051: public Type type;
052:
053: public Attribute(Type type) {
054: this .type = type;
055: }
056:
057: public abstract void accept(Visitor v);
058:
059: public Object getValue() {
060: throw new UnsupportedOperationException();
061: }
062:
063: public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) {
064: throw new UnsupportedOperationException();
065: }
066:
067: /** The value for an annotation element of primitive type or String. */
068: public static class Constant extends Attribute {
069: public final Object value;
070:
071: public void accept(Visitor v) {
072: v.visitConstant(this );
073: }
074:
075: public Constant(Type type, Object value) {
076: super (type);
077: this .value = value;
078: }
079:
080: public String toString() {
081: return Constants.format(value, type);
082: }
083:
084: public Object getValue() {
085: return Constants.decode(value, type);
086: }
087:
088: public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) {
089: if (value instanceof String)
090: return v.visitString((String) value, p);
091: if (value instanceof Integer) {
092: int i = (Integer) value;
093: switch (type.tag) {
094: case BOOLEAN:
095: return v.visitBoolean(i != 0, p);
096: case CHAR:
097: return v.visitChar((char) i, p);
098: case BYTE:
099: return v.visitByte((byte) i, p);
100: case SHORT:
101: return v.visitShort((short) i, p);
102: case INT:
103: return v.visitInt(i, p);
104: }
105: }
106: switch (type.tag) {
107: case LONG:
108: return v.visitLong((Long) value, p);
109: case FLOAT:
110: return v.visitFloat((Float) value, p);
111: case DOUBLE:
112: return v.visitDouble((Double) value, p);
113: }
114: throw new AssertionError("Bad annotation element value: "
115: + value);
116: }
117: }
118:
119: /** The value for an annotation element of type java.lang.Class,
120: * represented as a ClassSymbol.
121: */
122: public static class Class extends Attribute {
123: public final Type type;
124:
125: public void accept(Visitor v) {
126: v.visitClass(this );
127: }
128:
129: public Class(Types types, Type type) {
130: super (makeClassType(types, type));
131: this .type = type;
132: }
133:
134: static Type makeClassType(Types types, Type type) {
135: Type arg = type.isPrimitive() ? types.boxedClass(type).type
136: : types.erasure(type);
137: return new Type.ClassType(types.syms.classType
138: .getEnclosingType(), List.of(arg),
139: types.syms.classType.tsym);
140: }
141:
142: public String toString() {
143: return type + ".class";
144: }
145:
146: public Type getValue() {
147: return type;
148: }
149:
150: public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) {
151: return v.visitType(type, p);
152: }
153: }
154:
155: /** A compound annotation element value, the type of which is an
156: * attribute interface.
157: */
158: public static class Compound extends Attribute implements
159: AnnotationMirror {
160: /** The attributes values, as pairs. Each pair contains a
161: * reference to the accessing method in the attribute interface
162: * and the value to be returned when that method is called to
163: * access this attribute.
164: */
165: public final List<Pair<MethodSymbol, Attribute>> values;
166:
167: public Compound(Type type,
168: List<Pair<MethodSymbol, Attribute>> values) {
169: super (type);
170: this .values = values;
171: }
172:
173: public void accept(Visitor v) {
174: v.visitCompound(this );
175: }
176:
177: /**
178: * Returns a string representation of this annotation.
179: * String is of one of the forms:
180: * @com.example.foo(name1=val1, name2=val2)
181: * @com.example.foo(val)
182: * @com.example.foo
183: * Omit parens for marker annotations, and omit "value=" when allowed.
184: */
185: public String toString() {
186: StringBuilder buf = new StringBuilder();
187: buf.append("@");
188: buf.append(type);
189: int len = values.length();
190: if (len > 0) {
191: buf.append('(');
192: boolean first = true;
193: for (Pair<MethodSymbol, Attribute> value : values) {
194: if (!first)
195: buf.append(", ");
196: first = false;
197:
198: Name name = value.fst.name;
199: if (len > 1 || name != name.table.value) {
200: buf.append(name);
201: buf.append('=');
202: }
203: buf.append(value.snd);
204: }
205: buf.append(')');
206: }
207: return buf.toString();
208: }
209:
210: public Attribute member(Name member) {
211: for (Pair<MethodSymbol, Attribute> pair : values)
212: if (pair.fst.name == member)
213: return pair.snd;
214: return null;
215: }
216:
217: public Attribute.Compound getValue() {
218: return this ;
219: }
220:
221: public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) {
222: return v.visitAnnotation(this , p);
223: }
224:
225: public DeclaredType getAnnotationType() {
226: return (DeclaredType) type;
227: }
228:
229: public Map<MethodSymbol, Attribute> getElementValues() {
230: Map<MethodSymbol, Attribute> valmap = new LinkedHashMap<MethodSymbol, Attribute>();
231: for (Pair<MethodSymbol, Attribute> value : values)
232: valmap.put(value.fst, value.snd);
233: return valmap;
234: }
235: }
236:
237: /** The value for an annotation element of an array type.
238: */
239: public static class Array extends Attribute {
240: public final Attribute[] values;
241:
242: public Array(Type type, Attribute[] values) {
243: super (type);
244: this .values = values;
245: }
246:
247: public void accept(Visitor v) {
248: v.visitArray(this );
249: }
250:
251: public String toString() {
252: StringBuilder buf = new StringBuilder();
253: buf.append('{');
254: boolean first = true;
255: for (Attribute value : values) {
256: if (!first)
257: buf.append(", ");
258: first = false;
259: buf.append(value);
260: }
261: buf.append('}');
262: return buf.toString();
263: }
264:
265: public List<Attribute> getValue() {
266: return List.from(values);
267: }
268:
269: public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) {
270: return v.visitArray(getValue(), p);
271: }
272: }
273:
274: /** The value for an annotation element of an enum type.
275: */
276: public static class Enum extends Attribute {
277: public VarSymbol value;
278:
279: public Enum(Type type, VarSymbol value) {
280: super (type);
281: assert value != null;
282: this .value = value;
283: }
284:
285: public void accept(Visitor v) {
286: v.visitEnum(this );
287: }
288:
289: public String toString() {
290: return value.enclClass() + "." + value; // qualified name
291: }
292:
293: public VarSymbol getValue() {
294: return value;
295: }
296:
297: public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) {
298: return v.visitEnumConstant(value, p);
299: }
300: }
301:
302: public static class Error extends Attribute {
303: public Error(Type type) {
304: super (type);
305: }
306:
307: public void accept(Visitor v) {
308: v.visitError(this );
309: }
310:
311: public String toString() {
312: return "<error>";
313: }
314:
315: public String getValue() {
316: return toString();
317: }
318:
319: public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) {
320: return v.visitString(toString(), p);
321: }
322: }
323:
324: /** A visitor type for dynamic dispatch on the kind of attribute value. */
325: public static interface Visitor {
326: void visitConstant(Attribute.Constant value);
327:
328: void visitClass(Attribute.Class clazz);
329:
330: void visitCompound(Attribute.Compound compound);
331:
332: void visitArray(Attribute.Array array);
333:
334: void visitEnum(Attribute.Enum e);
335:
336: void visitError(Attribute.Error e);
337: }
338: }
|