Package org.strecks.util

Source Code of org.strecks.util.ReflectHelper

/*
* Copyright 2005-2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/

package org.strecks.util;

import java.beans.PropertyDescriptor;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;

import org.apache.commons.beanutils.PropertyUtils;
import org.strecks.exceptions.ApplicationRuntimeException;

/**
* Class with reflection-related helper methods
* @author Phil Zoio
*/
public class ReflectHelper
{

  /**
   * Returns the property name associated with a setter method with the given name
   */
  public static String getPropertyName(String setterName)
  {
    Character firstChar = setterName.charAt(3);
    String propertyName = setterName.substring(4);
    propertyName = Character.toLowerCase(firstChar) + propertyName;
    return propertyName;
  }

  /**
   * Gets getter corresponding with setter method
   */
  public static Method getGetter(Method setterMethod)
  {
    PropertyDescriptor property = BeanUtils.findPropertyForMethod(setterMethod);
    if (property == null)
    {
      return null;
    }
    else
    {
      return property.getReadMethod();
    }
  }

  /**
   * Gets setter corresponding with getter method
   */
  public static Method getSetter(Method getterMethod)
  {
    PropertyDescriptor property = BeanUtils.findPropertyForMethod(getterMethod);
    if (property == null)
    {
      return null;
    }
    else
    {
      return property.getWriteMethod();
    }
  }

  /**
   * Checks whether a particular method begins with "set"
   */
  public static String checkSetterMethodName(Method m)
  {
    String methodName = m.getName();
    if (!methodName.startsWith("set"))
    {
      throw new ApplicationRuntimeException("Method " + m + " declared in " + m.getDeclaringClass()
          + " is not a setter method");
    }
    return methodName;
  }

  /**
   * Checks that a method has exactly the specified number of parameters
   */
  public static void checkParameterTypeLength(Method m, int parameterCount)
  {
    Class<?>[] parameterTypes = m.getParameterTypes();
    if (parameterTypes.length != parameterCount)
    {
      throw new ApplicationRuntimeException("Method " + m.getName() + " in class " + m.getDeclaringClass()
          + " must have " + parameterCount + " parameter(s)");
    }
  }

  public static boolean isGetter(Method method)
  {

    PropertyDescriptor property = BeanUtils.findPropertyForMethod(method);

    if (property == null)
      return false;

    return property.getReadMethod().equals(method);

  }

  public static boolean hasReturnValue(Method method)
  {
    Class<?> returnType = method.getReturnType();
    boolean equals = returnType.equals(Void.TYPE);
    return (!equals);
  }

  public static boolean isSetter(Method method)
  {
    boolean isSetter = method.getName().startsWith("set") && method.getParameterTypes() != null
        && method.getParameterTypes().length == 1;
    return isSetter;
  }

  /**
   * Invokes the specified method on the specified object
   * @return
   */
  public static <T extends Object> T invokeMethod(Object o, String methodName, Class<T> returnType)
  {
    Method method = getMethod(o, methodName);
    return invokeMethod(o, method, returnType);
  }

  /**
   * Invokes the specified method on the specified object
   * @return
   */
  public static Object invokeMethod(Object o, String methodName)
  {
    Method method = getMethod(o, methodName);
    return invokeMethod(o, method);

  }

  public static Method getMethod(Object o, String methodName)
  {
    Assert.notNull(o);
    Assert.notNull(methodName);
    Class<? extends Object> clazz = o.getClass();

    return getMethod(methodName, clazz);
  }

  public static Method getMethod(String methodName, Class<? extends Object> clazz)
  {
    Assert.notNull(clazz);
    Assert.notNull(methodName);
    Method method = null;

    try
    {
      method = clazz.getMethod(methodName);
    }
    catch (IllegalArgumentException e)
    {
      throw new ApplicationRuntimeException("Unable to retrieve method " + methodName + "() of class "
          + clazz.getName(), e);
    }
    catch (SecurityException e)
    {
      throw new ApplicationRuntimeException(
          "Security violation " + methodName + "() of class " + clazz.getName(), e);
    }
    catch (NoSuchMethodException e)
    {
      throw new ApplicationRuntimeException("No method " + methodName + "() of class " + clazz.getName(), e);
    }
    return method;
  }

  public static Object invokeMethod(Object o, Method method)
  {
    return invokeMethod(o, method, null);
  }

  @SuppressWarnings("unchecked")
  public static <T extends Object> T invokeMethod(Object o, Method method, Class<T> returnType)
  {
    Assert.notNull(o);
    Assert.notNull(method);
    try
    {
      Object invoke = method.invoke(o);

      if (returnType != null && invoke != null && !invoke.getClass().isAssignableFrom(returnType))
      {
        throw new ApplicationRuntimeException("Unable to cast result " + invoke + " of method "
            + method.getName() + "() of class " + o.getClass().getName() + " to return type " + returnType);
      }

      return (T) invoke;
    }
    catch (IllegalArgumentException e)
    {
      throw new ApplicationRuntimeException("Unable to invoke method " + method.getName() + " of class "
          + o.getClass(), e);
    }
    catch (SecurityException e)
    {
      throw new ApplicationRuntimeException("Security violation " + method.getName() + " of class "
          + o.getClass(), e);
    }
    catch (IllegalAccessException e)
    {
      throw new ApplicationRuntimeException("Security violation " + method.getName() + " of class "
          + o.getClass(), e);
    }
    catch (InvocationTargetException e)
    {

      Throwable targetException = e.getTargetException();
      Throwable nested = null;

      if (targetException instanceof Exception)
        nested = targetException;
      else
        nested = e;

      throw new ApplicationRuntimeException("Invocation target exception for " + method.getName() + " of class "
          + o.getClass(), nested);

    }
  }

  public static <T extends Object> T createInstance(String className, Class<T> type)
  {
    Assert.notNull(className);

    Class c = null;
    try
    {
      c = Class.forName(className, true, ReflectHelper.class.getClassLoader());
    }
    catch (ClassNotFoundException e)
    {
      throw new ApplicationRuntimeException("Unable to create new instance of " + className
          + " as class cannot be located", e);
    }

    return createInstance(c, type);
  }

  @SuppressWarnings("unchecked")
  public static <T> T createInstance(Class clazz, Class<T> type)
  {
    try
    {

      Object newInstance = clazz.newInstance();

      if (!(type.isAssignableFrom(newInstance.getClass())))
      {
        throw new ApplicationRuntimeException("Class " + clazz.getName()
            + " was instantiated but was not an instance of the type " + type);
      }

      return (T) newInstance;
    }
    catch (InstantiationException e)
    {
      throw new ApplicationRuntimeException("Unable to create new instance of " + clazz
          + " as class cannot be instantiated", e);
    }
    catch (IllegalAccessException e)
    {
      throw new ApplicationRuntimeException("Illegal access in attempting to create instance of " + clazz, e);
    }
  }

  /**
   * Checks that the input type is parameterized by the class expectedType
   * @param inputClass
   *            the class being tested
   * @param genericInterface
   *            is the interface that the inputClass implements
   * @param specificType
   *            the expected parameterization type
   * @return false if the expectedType is not assignable from the actual parameterized type
   */

  @SuppressWarnings("unchecked")
  public static boolean checkGenericType(Class inputClass, Class genericInterface, Class specificType)
  {

    Class c = inputClass;
    Type[] genericInterfaces = c.getGenericInterfaces();

    for (Type type : genericInterfaces)
    {
      if (type instanceof ParameterizedType)
      {
        ParameterizedType t = (ParameterizedType) type;
        Type rawType = t.getRawType();

        if (rawType instanceof Class && rawType.equals(genericInterface))
        {
          Type[] actualTypeArguments = t.getActualTypeArguments();

          if (actualTypeArguments.length > 0)
          {
            Type arg = actualTypeArguments[0];

            if (arg instanceof Class)
            {

              Class<Object> expectedType = (Class<Object>) arg;

              if (!expectedType.isAssignableFrom(specificType))
              {
                return false;

              }
            }
          }
        }
      }
    }

    return true;

  }

  /**
   * Returns the (single) generic parameterization type fo the input class, for a given interface,
   * if this can be determined
   * @return the parameterization class, if this can be determined, otherwise null
   */

  @SuppressWarnings("unchecked")
  public static Class getGenericType(Class c, Class genericInterface)
  {

    Type[] actualTypeArguments = getGenericTypes(c, genericInterface);

    if (actualTypeArguments != null && actualTypeArguments.length > 0)
    {
      Type arg = actualTypeArguments[0];

      if (arg instanceof Class)
      {
        Class<Object> specificType = (Class<Object>) arg;
        return specificType;
      }
    }
    return null;

  }

  /**
   * Returns the (single) generic parameterization type fo the input class, for a given interface,
   * if this can be determined
   * @return the parameterization class, if this can be determined, otherwise null
   */

  @SuppressWarnings("unchecked")
  public static Type[] getGenericTypes(Class c, Class genericInterface)
  {

    Class inputClass = c;

    ParameterizedType genericType = null;

    do
    {
      genericType = getParameterizedType(genericInterface, inputClass);
    }
    while (genericType == null && ((inputClass = inputClass.getSuperclass()) != null));

    if (genericType != null)
    {

      Type[] actualTypeArguments = genericType.getActualTypeArguments();
      return actualTypeArguments;
    }

    return null;

  }

  static ParameterizedType getParameterizedType(Class genericInterface, Class inputClass)
  {
    Type[] genericInterfaces = inputClass.getGenericInterfaces();

    ParameterizedType genericType = null;

    for (Type type : genericInterfaces)
    {
      if (type instanceof ParameterizedType)
      {
        ParameterizedType t = (ParameterizedType) type;
        Type rawType = t.getRawType();

        if (rawType instanceof Class && rawType.equals(genericInterface))
        {
          genericType = t;
          break;
        }
      }
    }
    return genericType;
  }

  /**
   * Provides basic information on a particular type
   */
  public static String getTypeDescription(Type type)
  {

    Assert.notNull(type);

    if (type instanceof Class)
    {
      return type.toString();
    }
    else if (type instanceof ParameterizedType)
    {
      ParameterizedType pType = (ParameterizedType) type;
      String typeDescription = "parameterized " + getTypeDescription(pType.getRawType());

      Type[] args = pType.getActualTypeArguments();
      String typesDescription = getTypeArrayDescription(args);
      typeDescription = typeDescription + " " + typesDescription;

      return typeDescription;
    }
    else if (type instanceof GenericArrayType)
    {
      GenericArrayType gType = (GenericArrayType) type;
      String typeDescription = "array of " + getTypeDescription(gType.getGenericComponentType());
      return typeDescription;
    }
    else if (type instanceof WildcardType)
    {
      WildcardType wType = (WildcardType) type;
      String typeDescription = "wildcard generic type";

      String upperDesc = getTypeArrayDescription(wType.getUpperBounds());
      String lowerDesc = getTypeArrayDescription(wType.getLowerBounds());

      if (StringUtils.notBlankOrNull(upperDesc))
        typeDescription = typeDescription + " with upper bound " + upperDesc;
      if (StringUtils.notBlankOrNull(lowerDesc))
        typeDescription = typeDescription + " and lower bound " + lowerDesc;

      return typeDescription;
    }
    else if (type instanceof TypeVariable)
    {
      TypeVariable tType = (TypeVariable) type;
      String typeDescription = "type variable named " + tType.getName();

      typeDescription = typeDescription + " bounded by " + getTypeArrayDescription(tType.getBounds());
      return typeDescription;
    }
    return "Unknown";

  }

  public static String getTypeArrayDescription(Type[] types)
  {

    Assert.notNull(types);

    if (types.length == 0)
      return "";

    StringBuffer buffer = new StringBuffer("(");
    for (Type arg : types)
    {
      buffer.append(getTypeDescription(arg)).append(", ");
    }
    StringUtils.shorten(buffer, 2);
    buffer.append(")");

    String typesDescription = buffer.toString();
    return typesDescription;
  }

  /**
   * Fnd the type of a the property of <code>containingBean</code> identified by
   * <code>beanPropertyName</code>
   * @return the type of the bean property as a class <code>Class</code> instance
   */
  public static Class<?> getBeanPropertyType(Object containingBean, String beanPropertyName)
  {
    Class<?> propertyType = null;
    try
    {

      PropertyDescriptor propertyDescriptor = PropertyUtils.getPropertyDescriptor(containingBean,
          beanPropertyName);
      propertyType = propertyDescriptor.getPropertyType();

    }
    catch (Exception e)
    {
      throw new ApplicationRuntimeException("Unable to read property descriptor for bean "
          + containingBean.getClass().getName() + ", property " + beanPropertyName, e);
    }
    return propertyType;
  }

}
TOP

Related Classes of org.strecks.util.ReflectHelper

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.