001 // Copyright 2011 The Apache Software Foundation
002 //
003 // Licensed under the Apache License, Version 2.0 (the "License");
004 // you may not use this file except in compliance with the License.
005 // You may obtain a copy of the License at
006 //
007 // http://www.apache.org/licenses/LICENSE-2.0
008 //
009 // Unless required by applicable law or agreed to in writing, software
010 // distributed under the License is distributed on an "AS IS" BASIS,
011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012 // See the License for the specific language governing permissions and
013 // limitations under the License.
014
015 package org.apache.tapestry5.internal.plastic;
016
017 import java.util.HashMap;
018 import java.util.Map;
019
020 import org.apache.tapestry5.internal.plastic.asm.Opcodes;
021
022 /**
023 * Collects together information needed to write code that involves primitive types, including
024 * moving between wrapper types and primitive values, or extracting a primitive value from
025 * the {@link StaticContext}.
026 */
027 @SuppressWarnings("rawtypes")
028 public enum PrimitiveType implements Opcodes
029 {
030 VOID("void", "V", void.class, Void.class, null, null, ILOAD, ISTORE, RETURN),
031
032 BOOLEAN("boolean", "Z", boolean.class, Boolean.class, "booleanValue", "getBoolean", ILOAD, ISTORE, IRETURN),
033
034 CHAR("char", "C", char.class, Character.class, "charValue", "getChar", ILOAD, ISTORE, IRETURN),
035
036 BYTE("byte", "B", byte.class, Byte.class, "byteValue", "getByte", ILOAD, ISTORE, IRETURN),
037
038 SHORT("short", "S", short.class, Short.class, "shortValue", "getShort", ILOAD, ISTORE, IRETURN),
039
040 INT("int", "I", int.class, Integer.class, "intValue", "getInt", ILOAD, ISTORE, IRETURN),
041
042 FLOAT("float", "F", float.class, Float.class, "floatValue", "getFloat", FLOAD, FSTORE, FRETURN),
043
044 LONG("long", "J", long.class, Long.class, "longValue", "getLong", LLOAD, LSTORE, LRETURN),
045
046 DOUBLE("double", "D", double.class, Double.class, "doubleValue", "getDouble", DLOAD, DSTORE, DRETURN);
047
048 /**
049 * @param name
050 * the Java source name for the type
051 * @param descriptor
052 * Java descriptor for the type ('Z', 'I', etc.)
053 * @param primitiveType
054 * TODO
055 * @param wrapperType
056 * wrapper type, e.g., java.lang.Integer
057 * @param toValueMethodName
058 * name of method of wrapper class to extract primitive value
059 * @param getFromStaticContextMethodName
060 * name of method of {@link StaticContext} used to extract primitive context value
061 * @param loadOpcode
062 * Correct opcode for loading an argument or local variable onto the stack (ILOAD, LLOAD, FLOAD or
063 * DLOAD)
064 * @param storeOpcode
065 * matching opcode for storing a value to a local variable (ISTORE, LSTORE, FSTORE or DSTORE)
066 * @param returnOpcode
067 * Correct opcode for returning the top value on the stack (IRETURN, LRETURN, FRETURN
068 * or DRETURN)
069 */
070 private PrimitiveType(String name, String descriptor, Class primitiveType, Class wrapperType,
071 String toValueMethodName, String getFromStaticContextMethodName, int loadOpcode, int storeOpcode,
072 int returnOpcode)
073 {
074 this.name = name;
075 this.descriptor = descriptor;
076 this.primitiveType = primitiveType;
077 this.wrapperType = wrapperType;
078 this.wrapperInternalName = wrapperType == null ? null : PlasticInternalUtils.toInternalName(wrapperType
079 .getName());
080 this.toValueMethodName = toValueMethodName;
081 this.getFromStaticContextMethodName = getFromStaticContextMethodName;
082 this.loadOpcode = loadOpcode;
083 this.storeOpcode = storeOpcode;
084 this.returnOpcode = returnOpcode;
085
086 this.valueOfMethodDescriptor = String.format("(%s)L%s;", descriptor, wrapperInternalName);
087 this.toValueMethodDescriptor = "()" + descriptor;
088 this.getFromStaticContextMethodDescriptor = "(I)" + descriptor;
089 }
090
091 public final String name, descriptor, wrapperInternalName, valueOfMethodDescriptor, toValueMethodName,
092 getFromStaticContextMethodName, toValueMethodDescriptor, getFromStaticContextMethodDescriptor;
093
094 public final Class primitiveType, wrapperType;
095
096 public final int loadOpcode, storeOpcode, returnOpcode;
097
098 private static final Map<String, PrimitiveType> BY_NAME = new HashMap<String, PrimitiveType>();
099 private static final Map<String, PrimitiveType> BY_DESC = new HashMap<String, PrimitiveType>();
100 private static final Map<Class, PrimitiveType> BY_PRIMITIVE_TYPE = new HashMap<Class, PrimitiveType>();
101
102 static
103 {
104 for (PrimitiveType type : values())
105 {
106 BY_NAME.put(type.name, type);
107 BY_DESC.put(type.descriptor, type);
108 BY_PRIMITIVE_TYPE.put(type.primitiveType, type);
109 }
110 }
111
112 public boolean isWide()
113 {
114 return this == LONG || this == DOUBLE;
115 }
116
117 /**
118 * Returns the primitive type matching the given type name or null for a non-primitive type (an array type,
119 * or an class name).
120 *
121 * @param name
122 * possible primitive name
123 * @return the type or null
124 */
125 public static PrimitiveType getByName(String name)
126 {
127 return BY_NAME.get(name);
128 }
129
130 public static PrimitiveType getByPrimitiveType(Class primitiveType)
131 {
132 return BY_PRIMITIVE_TYPE.get(primitiveType);
133 }
134 }