    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    }