    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.plastic;
    016
    017    import org.apache.tapestry5.internal.plastic.PrimitiveType;
    018
    019    import java.lang.reflect.Method;
    020    import java.util.concurrent.atomic.AtomicLong;
    021
    022    /**
    023     * Utilities for user code making use of Plastic.
    024     */
    025    public class PlasticUtils
    026    {
    027        /**
    028         * The {@code toString()} method inherited from Object.
    029         */
    030        public static final Method TO_STRING = getMethod(Object.class, "toString");
    031
    032        /**
    033         * The MethodDescription version of {@code toString()}.
    034         */
    035        public static final MethodDescription TO_STRING_DESCRIPTION = new MethodDescription(TO_STRING);
    036
    037        private static final AtomicLong UID_GENERATOR = new AtomicLong(System.nanoTime());
    038
    039        /**
    040         * Returns a string that can be used as part of a Java identifier and is unique
    041         * for this JVM. Currently returns a hexadecimal string and initialized by
    042         * System.nanoTime() (but both those details may change in the future).
    043         * <p>
    044         * Note that the returned value may start with a numeric digit, so it should be used as a <em>suffix</em>, not
    045         * <em>prefix</em> of a Java identifier.
    046         *
    047         * @return unique id that can be used as part of a Java identifier
    048         */
    049        public static String nextUID()
    050        {
    051            return Long.toHexString(PlasticUtils.UID_GENERATOR.getAndIncrement());
    052        }
    053
    054        /**
    055         * Converts a type (including array and primitive types) to their type name (the way they are represented in Java
    056         * source files).
    057         */
    058        public static String toTypeName(Class type)
    059        {
    060            if (type.isArray())
    061                return toTypeName(type.getComponentType()) + "[]";
    062
    063            return type.getName();
    064        }
    065
    066        /** Converts a number of types (usually, arguments to a method or constructor) into their type names. */
    067        public static String[] toTypeNames(Class[] types)
    068        {
    069            String[] result = new String[types.length];
    070
    071            for (int i = 0; i < result.length; i++)
    072                result[i] = toTypeName(types[i]);
    073
    074            return result;
    075        }
    076
    077        /**
    078         * Gets the wrapper type for a given type (if primitive)
    079         *
    080         * @param type
    081         *            type to look up
    082         * @return the input type for non-primitive type, or corresponding wrapper type (Boolean.class for boolean.class,
    083         *         etc.)
    084         */
    085        public static Class toWrapperType(Class type)
    086        {
    087            assert type != null;
    088
    089            return type.isPrimitive() ? PrimitiveType.getByPrimitiveType(type).wrapperType : type;
    090        }
    091
    092        /**
    093         * Convenience for getting a method from a class.
    094         *
    095         * @param declaringClass
    096         *            containing class
    097         * @param name
    098         *            name of method
    099         * @param parameterTypes
    100         *            types of parameters
    101         * @return the Method
    102         * @throws RuntimeException
    103         *             if any error (such as method not found)
    104         */
    105        @SuppressWarnings("unchecked")
    106        public static Method getMethod(Class declaringClass, String name, Class... parameterTypes)
    107        {
    108            try
    109            {
    110                return declaringClass.getMethod(name, parameterTypes);
    111            }
    112            catch (Exception ex)
    113            {
    114                throw new RuntimeException(ex);
    115            }
    116        }
    117
    118        /**
    119         * Uses {@link #getMethod(Class, String, Class...)} and wraps the result as a {@link MethodDescription}.
    120         *
    121         * @param declaringClass
    122         *            containing class
    123         * @param name
    124         *            name of method
    125         * @param parameterTypes
    126         *            types of parameters
    127         * @return description for method
    128         * @throws RuntimeException
    129         *             if any error (such as method not found)
    130         */
    131        public static MethodDescription getMethodDescription(Class declaringClass, String name, Class... parameterTypes)
    132        {
    133            return new MethodDescription(getMethod(declaringClass, name, parameterTypes));
    134        }
    135
    136        /**
    137         * Determines if the provided type name is a primitive type.
    138         *
    139         * @param typeName Java type name, such as "boolean" or "java.lang.String"
    140         * @return true if primitive
    141         */
    142        public static boolean isPrimitive(String typeName)
    143        {
    144            return PrimitiveType.getByName(typeName) != null;
    145        }
    146    }