Types.java revision 301174b9ed79a73e35d7463f06ae48eb0654c6ca
1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package libcore.reflect;
18
19import java.lang.reflect.GenericArrayType;
20import java.lang.reflect.ParameterizedType;
21import java.lang.reflect.Type;
22import java.lang.reflect.TypeVariable;
23import java.util.HashMap;
24import java.util.Map;
25
26public final class Types {
27    private Types() {
28    }
29
30    // Holds a mapping from Java type names to native type codes.
31    private static final Map<Class<?>, String> PRIMITIVE_TO_SIGNATURE;
32    static {
33        PRIMITIVE_TO_SIGNATURE = new HashMap<Class<?>, String>(9);
34        PRIMITIVE_TO_SIGNATURE.put(byte.class, "B");
35        PRIMITIVE_TO_SIGNATURE.put(char.class, "C");
36        PRIMITIVE_TO_SIGNATURE.put(short.class, "S");
37        PRIMITIVE_TO_SIGNATURE.put(int.class, "I");
38        PRIMITIVE_TO_SIGNATURE.put(long.class, "J");
39        PRIMITIVE_TO_SIGNATURE.put(float.class, "F");
40        PRIMITIVE_TO_SIGNATURE.put(double.class, "D");
41        PRIMITIVE_TO_SIGNATURE.put(void.class, "V");
42        PRIMITIVE_TO_SIGNATURE.put(boolean.class, "Z");
43    }
44
45    public static Type[] getClonedTypeArray(ListOfTypes types) {
46        return types.getResolvedTypes().clone();
47    }
48
49    public static Type getType(Type type) {
50        if (type instanceof ParameterizedTypeImpl) {
51            return ((ParameterizedTypeImpl)type).getResolvedType();
52        } else {
53            return type;
54        }
55    }
56
57    /**
58     * Returns the internal name of {@code clazz} (also known as the descriptor).
59     */
60    public static String getSignature(Class<?> clazz) {
61        String primitiveSignature = PRIMITIVE_TO_SIGNATURE.get(clazz);
62        if (primitiveSignature != null) {
63            return primitiveSignature;
64        } else if (clazz.isArray()) {
65            return "[" + getSignature(clazz.getComponentType());
66        } else {
67            // TODO: this separates packages with '.' rather than '/'
68            return "L" + clazz.getName() + ";";
69        }
70    }
71
72    /**
73     * Returns the names of {@code types} separated by commas.
74     */
75    public static String toString(Class<?>[] types) {
76        if (types.length == 0) {
77            return "";
78        }
79        StringBuilder result = new StringBuilder();
80        appendTypeName(result, types[0]);
81        for (int i = 1; i < types.length; i++) {
82            result.append(',');
83            appendTypeName(result, types[i]);
84        }
85        return result.toString();
86    }
87
88    /**
89     * Appends the best {@link #toString} name for {@code c} to {@code out}.
90     * This works around the fact that {@link Class#getName} is lousy for
91     * primitive arrays (it writes "[C" instead of "char[]") and {@link
92     * Class#getCanonicalName()} is lousy for nested classes (it uses a "."
93     * separator rather than a "$" separator).
94     */
95    public static void appendTypeName(StringBuilder out, Class<?> c) {
96        int dimensions = 0;
97        while (c.isArray()) {
98            c = c.getComponentType();
99            dimensions++;
100        }
101        out.append(c.getName());
102        for (int d = 0; d < dimensions; d++) {
103            out.append("[]");
104        }
105    }
106
107    /**
108     * Appends names of the {@code types} to {@code out} separated by commas.
109     */
110    public static void appendArrayGenericType(StringBuilder out, Type[] types) {
111        if (types.length == 0) {
112            return;
113        }
114        appendGenericType(out, types[0]);
115        for (int i = 1; i < types.length; i++) {
116            out.append(',');
117            appendGenericType(out, types[i]);
118        }
119    }
120
121    public static void appendGenericType(StringBuilder out, Type type) {
122        if (type instanceof TypeVariable) {
123            out.append(((TypeVariable) type).getName());
124        } else if (type instanceof ParameterizedType) {
125            out.append(type.toString());
126        } else if (type instanceof GenericArrayType) {
127            Type simplified = ((GenericArrayType) type).getGenericComponentType();
128            appendGenericType(out, simplified);
129            out.append("[]");
130        } else if (type instanceof Class) {
131            Class c = (Class<?>) type;
132            if (c.isArray()){
133                String as[] = c.getName().split("\\[");
134                int len = as.length-1;
135                if (as[len].length() > 1){
136                    out.append(as[len].substring(1, as[len].length() - 1));
137                } else {
138                    char ch = as[len].charAt(0);
139                    if (ch == 'I') {
140                        out.append("int");
141                    } else if (ch == 'B') {
142                        out.append("byte");
143                    } else if (ch == 'J') {
144                        out.append("long");
145                    } else if (ch == 'F') {
146                        out.append("float");
147                    } else if (ch == 'D') {
148                        out.append("double");
149                    } else if (ch == 'S') {
150                        out.append("short");
151                    } else if (ch == 'C') {
152                        out.append("char");
153                    } else if (ch == 'Z') {
154                        out.append("boolean");
155                    } else if (ch == 'V') {
156                        out.append("void");
157                    }
158                }
159                for (int i = 0; i < len; i++){
160                    out.append("[]");
161                }
162            } else {
163                out.append(c.getName());
164            }
165        }
166    }
167}
168