1/*
2 * Javassist, a Java-bytecode translator toolkit.
3 * Copyright (C) 2004 Bill Burke. All Rights Reserved.
4 *
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License.  Alternatively, the contents of this file may be used under
8 * the terms of the GNU Lesser General Public License Version 2.1 or later.
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 */
15package javassist.bytecode.annotation;
16
17import javassist.ClassPool;
18import javassist.bytecode.ConstPool;
19import java.io.IOException;
20import java.lang.reflect.Array;
21import java.lang.reflect.Method;
22
23/**
24 * Array member.
25 *
26 * @author <a href="mailto:bill@jboss.org">Bill Burke</a>
27 * @author Shigeru Chiba
28 */
29public class ArrayMemberValue extends MemberValue {
30    MemberValue type;
31    MemberValue[] values;
32
33    /**
34     * Constructs an array.  The initial value or type are not specified.
35     */
36    public ArrayMemberValue(ConstPool cp) {
37        super('[', cp);
38        type = null;
39        values = null;
40    }
41
42    /**
43     * Constructs an array.  The initial value is not specified.
44     *
45     * @param t         the type of the array elements.
46     */
47    public ArrayMemberValue(MemberValue t, ConstPool cp) {
48        super('[', cp);
49        type = t;
50        values = null;
51    }
52
53    Object getValue(ClassLoader cl, ClassPool cp, Method method)
54        throws ClassNotFoundException
55    {
56        if (values == null)
57            throw new ClassNotFoundException(
58                        "no array elements found: " + method.getName());
59
60        int size = values.length;
61        Class clazz;
62        if (type == null) {
63            clazz = method.getReturnType().getComponentType();
64            if (clazz == null || size > 0)
65                throw new ClassNotFoundException("broken array type: "
66                                                 + method.getName());
67        }
68        else
69            clazz = type.getType(cl);
70
71        Object a = Array.newInstance(clazz, size);
72        for (int i = 0; i < size; i++)
73            Array.set(a, i, values[i].getValue(cl, cp, method));
74
75        return a;
76    }
77
78    Class getType(ClassLoader cl) throws ClassNotFoundException {
79        if (type == null)
80            throw new ClassNotFoundException("no array type specified");
81
82        Object a = Array.newInstance(type.getType(cl), 0);
83        return a.getClass();
84    }
85
86    /**
87     * Obtains the type of the elements.
88     *
89     * @return null if the type is not specified.
90     */
91    public MemberValue getType() {
92        return type;
93    }
94
95    /**
96     * Obtains the elements of the array.
97     */
98    public MemberValue[] getValue() {
99        return values;
100    }
101
102    /**
103     * Sets the elements of the array.
104     */
105    public void setValue(MemberValue[] elements) {
106        values = elements;
107        if (elements != null && elements.length > 0)
108            type = elements[0];
109    }
110
111    /**
112     * Obtains the string representation of this object.
113     */
114    public String toString() {
115        StringBuffer buf = new StringBuffer("{");
116        if (values != null) {
117            for (int i = 0; i < values.length; i++) {
118                buf.append(values[i].toString());
119                if (i + 1 < values.length)
120                    buf.append(", ");
121                }
122        }
123
124        buf.append("}");
125        return buf.toString();
126    }
127
128    /**
129     * Writes the value.
130     */
131    public void write(AnnotationsWriter writer) throws IOException {
132        int num = values.length;
133        writer.arrayValue(num);
134        for (int i = 0; i < num; ++i)
135            values[i].write(writer);
136    }
137
138    /**
139     * Accepts a visitor.
140     */
141    public void accept(MemberValueVisitor visitor) {
142        visitor.visitArrayMemberValue(this);
143    }
144}
145