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    }