1579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson/* 2579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Copyright (C) 2011 The Android Open Source Project 3579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 4579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Licensed under the Apache License, Version 2.0 (the "License"); 5579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * you may not use this file except in compliance with the License. 6579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * You may obtain a copy of the License at 7579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 8579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * http://www.apache.org/licenses/LICENSE-2.0 9579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 10579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Unless required by applicable law or agreed to in writing, software 11579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS, 12579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * See the License for the specific language governing permissions and 14579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * limitations under the License. 15579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 16579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 17579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonpackage com.google.dexmaker; 18579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 19579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.cst.CstType; 20579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.util.HashMap; 21579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.util.Map; 22579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 23579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson/** 24579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * A primitive type, interface or class. 253e7a2230ec75b59ae9b4aad292f51df2542ced7dJesse Wilson * 263e7a2230ec75b59ae9b4aad292f51df2542ced7dJesse Wilson * <p><strong>Warning:</strong> Use care when dealing with boxed primitive 273e7a2230ec75b59ae9b4aad292f51df2542ced7dJesse Wilson * types. Java's lack of support for parameterized primitive types means that 283e7a2230ec75b59ae9b4aad292f51df2542ced7dJesse Wilson * a primitive type like {@code int} and its boxed type {@code 293e7a2230ec75b59ae9b4aad292f51df2542ced7dJesse Wilson * java.lang.Integer} have the same type parameter: {@code TypeId<Integer>}. 303e7a2230ec75b59ae9b4aad292f51df2542ced7dJesse Wilson * These types are different and it will be a runtime error if the boxed type 313e7a2230ec75b59ae9b4aad292f51df2542ced7dJesse Wilson * {@code java.lang.Integer} is used where the primitive type {@code int} is 323e7a2230ec75b59ae9b4aad292f51df2542ced7dJesse Wilson * expected. 33579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 340e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilsonpublic final class TypeId<T> { 35579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** The {@code boolean} primitive type. */ 360e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson public static final TypeId<Boolean> BOOLEAN 370e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson = new TypeId<Boolean>(com.android.dx.rop.type.Type.BOOLEAN); 38579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 39579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** The {@code byte} primitive type. */ 400e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson public static final TypeId<Byte> BYTE = new TypeId<Byte>(com.android.dx.rop.type.Type.BYTE); 41579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 42579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** The {@code char} primitive type. */ 430e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson public static final TypeId<Character> CHAR 440e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson = new TypeId<Character>(com.android.dx.rop.type.Type.CHAR); 45579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 46579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** The {@code double} primitive type. */ 470e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson public static final TypeId<Double> DOUBLE = new TypeId<Double>(com.android.dx.rop.type.Type.DOUBLE); 48579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 49579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** The {@code float} primitive type. */ 500e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson public static final TypeId<Float> FLOAT = new TypeId<Float>(com.android.dx.rop.type.Type.FLOAT); 51579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 52579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** The {@code int} primitive type. */ 530e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson public static final TypeId<Integer> INT = new TypeId<Integer>(com.android.dx.rop.type.Type.INT); 54579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 55579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** The {@code long} primitive type. */ 560e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson public static final TypeId<Long> LONG = new TypeId<Long>(com.android.dx.rop.type.Type.LONG); 57579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 58579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** The {@code short} primitive type. */ 590e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson public static final TypeId<Short> SHORT = new TypeId<Short>(com.android.dx.rop.type.Type.SHORT); 60579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 61579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** The {@code void} primitive type. Only used as a return type. */ 620e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson public static final TypeId<Void> VOID = new TypeId<Void>(com.android.dx.rop.type.Type.VOID); 63579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 64579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** The {@code Object} type. */ 650e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson public static final TypeId<Object> OBJECT = new TypeId<Object>(com.android.dx.rop.type.Type.OBJECT); 66579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 67579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** The {@code String} type. */ 680e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson public static final TypeId<String> STRING = new TypeId<String>(com.android.dx.rop.type.Type.STRING); 69579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 700e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson private static final Map<Class<?>, TypeId<?>> PRIMITIVE_TO_TYPE 710e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson = new HashMap<Class<?>, TypeId<?>>(); 72579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson static { 73579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson PRIMITIVE_TO_TYPE.put(boolean.class, BOOLEAN); 74579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson PRIMITIVE_TO_TYPE.put(byte.class, BYTE); 75579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson PRIMITIVE_TO_TYPE.put(char.class, CHAR); 76579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson PRIMITIVE_TO_TYPE.put(double.class, DOUBLE); 77579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson PRIMITIVE_TO_TYPE.put(float.class, FLOAT); 78579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson PRIMITIVE_TO_TYPE.put(int.class, INT); 79579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson PRIMITIVE_TO_TYPE.put(long.class, LONG); 80579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson PRIMITIVE_TO_TYPE.put(short.class, SHORT); 81579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson PRIMITIVE_TO_TYPE.put(void.class, VOID); 82579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 83579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 84579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson final String name; 85579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 86579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** cached converted values */ 87579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson final com.android.dx.rop.type.Type ropType; 88579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson final CstType constant; 89579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 900e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson TypeId(com.android.dx.rop.type.Type ropType) { 91579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this(ropType.getDescriptor(), ropType); 92579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 93579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 940e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson TypeId(String name, com.android.dx.rop.type.Type ropType) { 95579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (name == null || ropType == null) { 96579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new NullPointerException(); 97579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 98579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.name = name; 99579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.ropType = ropType; 100579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.constant = CstType.intern(ropType); 101579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 102579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 103579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 104579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param name a descriptor like "Ljava/lang/Class;". 105579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 1060e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson public static <T> TypeId<T> get(String name) { 1070e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson return new TypeId<T>(name, com.android.dx.rop.type.Type.internReturnType(name)); 108579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 109579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1100e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson public static <T> TypeId<T> get(Class<T> type) { 111579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (type.isPrimitive()) { 112579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @SuppressWarnings("unchecked") // guarded by equals 1130e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson TypeId<T> result = (TypeId<T>) PRIMITIVE_TO_TYPE.get(type); 114579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return result; 115579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 116579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson String name = type.getName().replace('.', '/'); 117579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return get(type.isArray() ? name : 'L' + name + ';'); 118579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 119579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1200e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson public <V> FieldId<T, V> getField(TypeId<V> type, String name) { 121579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return new FieldId<T, V>(this, type, name); 122579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 123579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1240e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson public MethodId<T, Void> getConstructor(TypeId<?>... parameters) { 125579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return new MethodId<T, Void>(this, VOID, "<init>", new TypeList(parameters)); 126579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 127579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1280e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson public <R> MethodId<T, R> getMethod(TypeId<R> returnType, String name, TypeId<?>... parameters) { 129579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return new MethodId<T, R>(this, returnType, name, new TypeList(parameters)); 130579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 131579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 132579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public String getName() { 133579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return name; 134579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 135579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 136579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @Override public boolean equals(Object o) { 1370e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson return o instanceof TypeId 1380e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson && ((TypeId) o).name.equals(name); 139579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 140579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 141579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @Override public int hashCode() { 142579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return name.hashCode(); 143579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 144579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 145579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @Override public String toString() { 146579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return name; 147579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 148579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson} 149