Home | History | Annotate | Download | only in dexmaker
      1 /*
      2  * Copyright (C) 2011 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 com.google.dexmaker;
     18 
     19 import com.android.dx.rop.cst.CstType;
     20 import java.util.HashMap;
     21 import java.util.Map;
     22 
     23 /**
     24  * A primitive type, interface or class.
     25  *
     26  * <p><strong>Warning:</strong> Use care when dealing with boxed primitive
     27  * types. Java's lack of support for parameterized primitive types means that
     28  * a primitive type like {@code int} and its boxed type {@code
     29  * java.lang.Integer} have the same type parameter: {@code TypeId<Integer>}.
     30  * These types are different and it will be a runtime error if the boxed type
     31  * {@code java.lang.Integer} is used where the primitive type {@code int} is
     32  * expected.
     33  */
     34 public final class TypeId<T> {
     35     /** The {@code boolean} primitive type. */
     36     public static final TypeId<Boolean> BOOLEAN
     37             = new TypeId<Boolean>(com.android.dx.rop.type.Type.BOOLEAN);
     38 
     39     /** The {@code byte} primitive type. */
     40     public static final TypeId<Byte> BYTE = new TypeId<Byte>(com.android.dx.rop.type.Type.BYTE);
     41 
     42     /** The {@code char} primitive type. */
     43     public static final TypeId<Character> CHAR
     44             = new TypeId<Character>(com.android.dx.rop.type.Type.CHAR);
     45 
     46     /** The {@code double} primitive type. */
     47     public static final TypeId<Double> DOUBLE = new TypeId<Double>(com.android.dx.rop.type.Type.DOUBLE);
     48 
     49     /** The {@code float} primitive type. */
     50     public static final TypeId<Float> FLOAT = new TypeId<Float>(com.android.dx.rop.type.Type.FLOAT);
     51 
     52     /** The {@code int} primitive type. */
     53     public static final TypeId<Integer> INT = new TypeId<Integer>(com.android.dx.rop.type.Type.INT);
     54 
     55     /** The {@code long} primitive type. */
     56     public static final TypeId<Long> LONG = new TypeId<Long>(com.android.dx.rop.type.Type.LONG);
     57 
     58     /** The {@code short} primitive type. */
     59     public static final TypeId<Short> SHORT = new TypeId<Short>(com.android.dx.rop.type.Type.SHORT);
     60 
     61     /** The {@code void} primitive type. Only used as a return type. */
     62     public static final TypeId<Void> VOID = new TypeId<Void>(com.android.dx.rop.type.Type.VOID);
     63 
     64     /** The {@code Object} type. */
     65     public static final TypeId<Object> OBJECT = new TypeId<Object>(com.android.dx.rop.type.Type.OBJECT);
     66 
     67     /** The {@code String} type. */
     68     public static final TypeId<String> STRING = new TypeId<String>(com.android.dx.rop.type.Type.STRING);
     69 
     70     private static final Map<Class<?>, TypeId<?>> PRIMITIVE_TO_TYPE
     71             = new HashMap<Class<?>, TypeId<?>>();
     72     static {
     73         PRIMITIVE_TO_TYPE.put(boolean.class, BOOLEAN);
     74         PRIMITIVE_TO_TYPE.put(byte.class, BYTE);
     75         PRIMITIVE_TO_TYPE.put(char.class, CHAR);
     76         PRIMITIVE_TO_TYPE.put(double.class, DOUBLE);
     77         PRIMITIVE_TO_TYPE.put(float.class, FLOAT);
     78         PRIMITIVE_TO_TYPE.put(int.class, INT);
     79         PRIMITIVE_TO_TYPE.put(long.class, LONG);
     80         PRIMITIVE_TO_TYPE.put(short.class, SHORT);
     81         PRIMITIVE_TO_TYPE.put(void.class, VOID);
     82     }
     83 
     84     final String name;
     85 
     86     /** cached converted values */
     87     final com.android.dx.rop.type.Type ropType;
     88     final CstType constant;
     89 
     90     TypeId(com.android.dx.rop.type.Type ropType) {
     91         this(ropType.getDescriptor(), ropType);
     92     }
     93 
     94     TypeId(String name, com.android.dx.rop.type.Type ropType) {
     95         if (name == null || ropType == null) {
     96             throw new NullPointerException();
     97         }
     98         this.name = name;
     99         this.ropType = ropType;
    100         this.constant = CstType.intern(ropType);
    101     }
    102 
    103     /**
    104      * @param name a descriptor like "Ljava/lang/Class;".
    105      */
    106     public static <T> TypeId<T> get(String name) {
    107         return new TypeId<T>(name, com.android.dx.rop.type.Type.internReturnType(name));
    108     }
    109 
    110     public static <T> TypeId<T> get(Class<T> type) {
    111         if (type.isPrimitive()) {
    112             @SuppressWarnings("unchecked") // guarded by equals
    113                     TypeId<T> result = (TypeId<T>) PRIMITIVE_TO_TYPE.get(type);
    114             return result;
    115         }
    116         String name = type.getName().replace('.', '/');
    117         return get(type.isArray() ? name : 'L' + name + ';');
    118     }
    119 
    120     public <V> FieldId<T, V> getField(TypeId<V> type, String name) {
    121         return new FieldId<T, V>(this, type, name);
    122     }
    123 
    124     public MethodId<T, Void> getConstructor(TypeId<?>... parameters) {
    125         return new MethodId<T, Void>(this, VOID, "<init>", new TypeList(parameters));
    126     }
    127 
    128     public <R> MethodId<T, R> getMethod(TypeId<R> returnType, String name, TypeId<?>... parameters) {
    129         return new MethodId<T, R>(this, returnType, name, new TypeList(parameters));
    130     }
    131 
    132     public String getName() {
    133         return name;
    134     }
    135 
    136     @Override public boolean equals(Object o) {
    137         return o instanceof TypeId
    138                 && ((TypeId) o).name.equals(name);
    139     }
    140 
    141     @Override public int hashCode() {
    142         return name.hashCode();
    143     }
    144 
    145     @Override public String toString() {
    146         return name;
    147     }
    148 }
    149