Mega Code Archive

 
Categories / Java / Reflection
 

If right-hand side type may be assigned to the left-hand side type following the Java generics rules

/*  * Copyright 2002-2007 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.  */ import java.beans.Introspector; import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Proxy; import java.lang.reflect.Type; import java.lang.reflect.WildcardType; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import junit.framework.Assert; import sun.rmi.runtime.Log; /**  * Utility to work with Java 5 generic type parameters.  * Mainly for internal use within the framework.  *  * @author Ramnivas Laddad  * @author Juergen Hoeller  * @since 2.0.7  */ public abstract class TypeUtils {   /**    * Check if the right-hand side type may be assigned to the left-hand side    * type following the Java generics rules.    * @param lhsType the target type    * @param rhsType the value type that should be assigned to the target type    * @return true if rhs is assignable to lhs    */   public static boolean isAssignable(Type lhsType, Type rhsType) {     if (lhsType.equals(rhsType)) {       return true;     }     if (lhsType instanceof Class && rhsType instanceof Class) {       return ClassUtils.isAssignable((Class) lhsType, (Class) rhsType);     }     if (lhsType instanceof ParameterizedType && rhsType instanceof ParameterizedType) {       return isAssignable((ParameterizedType) lhsType, (ParameterizedType) rhsType);     }     if (lhsType instanceof WildcardType) {       return isAssignable((WildcardType) lhsType, rhsType);     }     return false;   }   private static boolean isAssignable(ParameterizedType lhsType, ParameterizedType rhsType) {     if (lhsType.equals(rhsType)) {       return true;     }     Type[] lhsTypeArguments = lhsType.getActualTypeArguments();     Type[] rhsTypeArguments = rhsType.getActualTypeArguments();     if (lhsTypeArguments.length != rhsTypeArguments.length) {       return false;     }     for (int size = lhsTypeArguments.length, i = 0; i < size; ++i) {       Type lhsArg = lhsTypeArguments[i];       Type rhsArg = rhsTypeArguments[i];       if (!lhsArg.equals(rhsArg) &&           !(lhsArg instanceof WildcardType && isAssignable((WildcardType) lhsArg, rhsArg))) {         return false;       }     }     return true;   }   private static boolean isAssignable(WildcardType lhsType, Type rhsType) {     Type[] upperBounds = lhsType.getUpperBounds();     Type[] lowerBounds = lhsType.getLowerBounds();     for (int size = upperBounds.length, i = 0; i < size; ++i) {       if (!isAssignable(upperBounds[i], rhsType)) {         return false;       }     }     for (int size = lowerBounds.length, i = 0; i < size; ++i) {       if (!isAssignable(rhsType, lowerBounds[i])) {         return false;       }     }     return true;   } } /*  * Copyright 2002-2007 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.  */ /**  * Miscellaneous class utility methods. Mainly for internal use within the  * framework; consider Jakarta's Commons Lang for a more comprehensive suite  * of class utilities.  *  * @author Keith Donald  * @author Rob Harrop  * @author Juergen Hoeller  * @since 1.1  * @see TypeUtils  * @see ReflectionUtils  */  abstract class ClassUtils {   /** Suffix for array class names: "[]" */   public static final String ARRAY_SUFFIX = "[]";   /** Prefix for internal array class names: "[L" */   private static final String INTERNAL_ARRAY_PREFIX = "[L";   /** The package separator character '.' */   private static final char PACKAGE_SEPARATOR = '.';   /** The inner class separator character '$' */   private static final char INNER_CLASS_SEPARATOR = '$';   /** The CGLIB class separator character "$$" */   public static final String CGLIB_CLASS_SEPARATOR = "$$";   /** The ".class" file suffix */   public static final String CLASS_FILE_SUFFIX = ".class";   /**    * Map with primitive wrapper type as key and corresponding primitive    * type as value, for example: Integer.class -> int.class.    */   private static final Map primitiveWrapperTypeMap = new HashMap(8);   /**    * Map with primitive type name as key and corresponding primitive    * type as value, for example: "int" -> "int.class".    */   private static final Map primitiveTypeNameMap = new HashMap(16);   static {     primitiveWrapperTypeMap.put(Boolean.class, boolean.class);     primitiveWrapperTypeMap.put(Byte.class, byte.class);     primitiveWrapperTypeMap.put(Character.class, char.class);     primitiveWrapperTypeMap.put(Double.class, double.class);     primitiveWrapperTypeMap.put(Float.class, float.class);     primitiveWrapperTypeMap.put(Integer.class, int.class);     primitiveWrapperTypeMap.put(Long.class, long.class);     primitiveWrapperTypeMap.put(Short.class, short.class);     Set primitiveTypeNames = new HashSet(16);     primitiveTypeNames.addAll(primitiveWrapperTypeMap.values());     primitiveTypeNames.addAll(Arrays.asList(new Class[] {         boolean[].class, byte[].class, char[].class, double[].class,         float[].class, int[].class, long[].class, short[].class}));     for (Iterator it = primitiveTypeNames.iterator(); it.hasNext();) {       Class primitiveClass = (Class) it.next();       primitiveTypeNameMap.put(primitiveClass.getName(), primitiveClass);     }   }   /**    * Check if the right-hand side type may be assigned to the left-hand side    * type, assuming setting by reflection. Considers primitive wrapper    * classes as assignable to the corresponding primitive types.    * @param lhsType the target type    * @param rhsType the value type that should be assigned to the target type    * @return if the target type is assignable from the value type    * @see TypeUtils#isAssignable    */   public static boolean isAssignable(Class lhsType, Class rhsType) {     return (lhsType.isAssignableFrom(rhsType) ||         lhsType.equals(primitiveWrapperTypeMap.get(rhsType)));   } }