001    /*
002     * Copyright 2003-2004 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.javadoc;
027    
028    
029    import com.sun.javadoc.*;
030    
031    import com.sun.tools.javac.code.Attribute;
032    import com.sun.tools.javac.code.Symbol.*;
033    import com.sun.tools.javac.code.Type;
034    import com.sun.tools.javac.code.TypeTags;
035    
036    
037    /**
038     * Represents a value of an annotation type element.
039     *
040     * @author Scott Seligman
041     * @since 1.5
042     */
043    
044    public class AnnotationValueImpl implements AnnotationValue {
045    
046        private final DocEnv env;
047        private final Attribute attr;
048    
049    
050        AnnotationValueImpl(DocEnv env, Attribute attr) {
051            this.env = env;
052            this.attr = attr;
053        }
054    
055        /**
056         * Returns the value.
057         * The type of the returned object is one of the following:
058         * <ul><li> a wrapper class for a primitive type
059         *     <li> <code>String</code>
060         *     <li> <code>Type</code> (representing a class literal)
061         *     <li> <code>FieldDoc</code> (representing an enum constant)
062         *     <li> <code>AnnotationDesc</code>
063         *     <li> <code>AnnotationValue[]</code>
064         * </ul>
065         */
066        public Object value() {
067            ValueVisitor vv = new ValueVisitor();
068            attr.accept(vv);
069            return vv.value;
070        }
071    
072        private class ValueVisitor implements Attribute.Visitor {
073            public Object value;
074    
075            public void visitConstant(Attribute.Constant c) {
076                if (c.type.tag == TypeTags.BOOLEAN) {
077                    // javac represents false and true as integers 0 and 1
078                    value = Boolean.valueOf(
079                                    ((Integer)c.value).intValue() != 0);
080                } else {
081                    value = c.value;
082                }
083            }
084    
085            public void visitClass(Attribute.Class c) {
086                value = TypeMaker.getType(env,
087                                          env.types.erasure(c.type));
088            }
089    
090            public void visitEnum(Attribute.Enum e) {
091                value = env.getFieldDoc(e.value);
092            }
093    
094            public void visitCompound(Attribute.Compound c) {
095                value = new AnnotationDescImpl(env, c);
096            }
097    
098            public void visitArray(Attribute.Array a) {
099                AnnotationValue vals[] = new AnnotationValue[a.values.length];
100                for (int i = 0; i < vals.length; i++) {
101                    vals[i] = new AnnotationValueImpl(env, a.values[i]);
102                }
103                value = vals;
104            }
105    
106            public void visitError(Attribute.Error e) {
107                value = "<error>";
108            }
109        }
110    
111        /**
112         * Returns a string representation of the value.
113         *
114         * @return the text of a Java language annotation value expression
115         *          whose value is the value of this annotation type element.
116         */
117        public String toString() {
118            ToStringVisitor tv = new ToStringVisitor();
119            attr.accept(tv);
120            return tv.toString();
121        }
122    
123        private class ToStringVisitor implements Attribute.Visitor {
124            private final StringBuffer sb = new StringBuffer();
125    
126            public String toString() {
127                return sb.toString();
128            }
129    
130            public void visitConstant(Attribute.Constant c) {
131                if (c.type.tag == TypeTags.BOOLEAN) {
132                    // javac represents false and true as integers 0 and 1
133                    sb.append(((Integer)c.value).intValue() != 0);
134                } else {
135                    sb.append(FieldDocImpl.constantValueExpression(c.value));
136                }
137            }
138    
139            public void visitClass(Attribute.Class c) {
140                sb.append(c);
141            }
142    
143            public void visitEnum(Attribute.Enum e) {
144                sb.append(e);
145            }
146    
147            public void visitCompound(Attribute.Compound c) {
148                sb.append(new AnnotationDescImpl(env, c));
149            }
150    
151            public void visitArray(Attribute.Array a) {
152                // Omit braces from singleton.
153                if (a.values.length != 1) sb.append('{');
154    
155                boolean first = true;
156                for (Attribute elem : a.values) {
157                    if (first) {
158                        first = false;
159                    } else {
160                        sb.append(", ");
161                    }
162                    elem.accept(this);
163                }
164                // Omit braces from singleton.
165                if (a.values.length != 1) sb.append('}');
166            }
167    
168            public void visitError(Attribute.Error e) {
169                sb.append("<error>");
170            }
171        }
172    }