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
015package org.apache.tapestry5.plastic;
016
017import org.apache.tapestry5.internal.plastic.PrimitiveType;
018
019import java.lang.reflect.Method;
020import java.util.concurrent.atomic.AtomicLong;
021
022/**
023 * Utilities for user code making use of Plastic.
024 */
025public 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}