Home | History | Annotate | Download | only in reflect
      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 
     17 package libcore.reflect;
     18 
     19 import java.lang.reflect.GenericArrayType;
     20 import java.lang.reflect.ParameterizedType;
     21 import java.lang.reflect.Type;
     22 import java.lang.reflect.TypeVariable;
     23 import java.util.HashMap;
     24 import java.util.Map;
     25 import libcore.util.EmptyArray;
     26 
     27 public final class Types {
     28     private Types() {
     29     }
     30 
     31     // Holds a mapping from Java type names to native type codes.
     32     private static final Map<Class<?>, String> PRIMITIVE_TO_SIGNATURE;
     33     static {
     34         PRIMITIVE_TO_SIGNATURE = new HashMap<Class<?>, String>(9);
     35         PRIMITIVE_TO_SIGNATURE.put(byte.class, "B");
     36         PRIMITIVE_TO_SIGNATURE.put(char.class, "C");
     37         PRIMITIVE_TO_SIGNATURE.put(short.class, "S");
     38         PRIMITIVE_TO_SIGNATURE.put(int.class, "I");
     39         PRIMITIVE_TO_SIGNATURE.put(long.class, "J");
     40         PRIMITIVE_TO_SIGNATURE.put(float.class, "F");
     41         PRIMITIVE_TO_SIGNATURE.put(double.class, "D");
     42         PRIMITIVE_TO_SIGNATURE.put(void.class, "V");
     43         PRIMITIVE_TO_SIGNATURE.put(boolean.class, "Z");
     44     }
     45 
     46     public static Type[] getTypeArray(ListOfTypes types, boolean clone) {
     47         if (types.length() == 0) {
     48             return EmptyArray.TYPE;
     49         }
     50         Type[] result = types.getResolvedTypes();
     51         return clone ? result.clone() : result;
     52     }
     53 
     54     public static Type getType(Type type) {
     55         if (type instanceof ParameterizedTypeImpl) {
     56             return ((ParameterizedTypeImpl)type).getResolvedType();
     57         }
     58         return type;
     59     }
     60 
     61     /**
     62      * Returns the internal name of {@code clazz} (also known as the descriptor).
     63      */
     64     public static String getSignature(Class<?> clazz) {
     65         String primitiveSignature = PRIMITIVE_TO_SIGNATURE.get(clazz);
     66         if (primitiveSignature != null) {
     67             return primitiveSignature;
     68         } else if (clazz.isArray()) {
     69             return "[" + getSignature(clazz.getComponentType());
     70         } else {
     71             // TODO: this separates packages with '.' rather than '/'
     72             return "L" + clazz.getName() + ";";
     73         }
     74     }
     75 
     76     /**
     77      * Returns the names of {@code types} separated by commas.
     78      */
     79     public static String toString(Class<?>[] types) {
     80         if (types.length == 0) {
     81             return "";
     82         }
     83         StringBuilder result = new StringBuilder();
     84         appendTypeName(result, types[0]);
     85         for (int i = 1; i < types.length; i++) {
     86             result.append(',');
     87             appendTypeName(result, types[i]);
     88         }
     89         return result.toString();
     90     }
     91 
     92     /**
     93      * Appends the best {@link #toString} name for {@code c} to {@code out}.
     94      * This works around the fact that {@link Class#getName} is lousy for
     95      * primitive arrays (it writes "[C" instead of "char[]") and {@link
     96      * Class#getCanonicalName()} is lousy for nested classes (it uses a "."
     97      * separator rather than a "$" separator).
     98      */
     99     public static void appendTypeName(StringBuilder out, Class<?> c) {
    100         int dimensions = 0;
    101         while (c.isArray()) {
    102             c = c.getComponentType();
    103             dimensions++;
    104         }
    105         out.append(c.getName());
    106         for (int d = 0; d < dimensions; d++) {
    107             out.append("[]");
    108         }
    109     }
    110 
    111     /**
    112      * Appends names of the {@code types} to {@code out} separated by commas.
    113      */
    114     public static void appendArrayGenericType(StringBuilder out, Type[] types) {
    115         if (types.length == 0) {
    116             return;
    117         }
    118         appendGenericType(out, types[0]);
    119         for (int i = 1; i < types.length; i++) {
    120             out.append(',');
    121             appendGenericType(out, types[i]);
    122         }
    123     }
    124 
    125     public static void appendGenericType(StringBuilder out, Type type) {
    126         if (type instanceof TypeVariable) {
    127             out.append(((TypeVariable) type).getName());
    128         } else if (type instanceof ParameterizedType) {
    129             out.append(type.toString());
    130         } else if (type instanceof GenericArrayType) {
    131             Type simplified = ((GenericArrayType) type).getGenericComponentType();
    132             appendGenericType(out, simplified);
    133             out.append("[]");
    134         } else if (type instanceof Class) {
    135             Class c = (Class<?>) type;
    136             if (c.isArray()){
    137                 String as[] = c.getName().split("\\[");
    138                 int len = as.length-1;
    139                 if (as[len].length() > 1){
    140                     out.append(as[len].substring(1, as[len].length() - 1));
    141                 } else {
    142                     char ch = as[len].charAt(0);
    143                     if (ch == 'I') {
    144                         out.append("int");
    145                     } else if (ch == 'B') {
    146                         out.append("byte");
    147                     } else if (ch == 'J') {
    148                         out.append("long");
    149                     } else if (ch == 'F') {
    150                         out.append("float");
    151                     } else if (ch == 'D') {
    152                         out.append("double");
    153                     } else if (ch == 'S') {
    154                         out.append("short");
    155                     } else if (ch == 'C') {
    156                         out.append("char");
    157                     } else if (ch == 'Z') {
    158                         out.append("boolean");
    159                     } else if (ch == 'V') {
    160                         out.append("void");
    161                     }
    162                 }
    163                 for (int i = 0; i < len; i++){
    164                     out.append("[]");
    165                 }
    166             } else {
    167                 out.append(c.getName());
    168             }
    169         }
    170     }
    171 }
    172