001: /*
002: * Copyright 2002-2007 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.util;
018:
019: import java.lang.reflect.ParameterizedType;
020: import java.lang.reflect.Type;
021: import java.lang.reflect.WildcardType;
022:
023: /**
024: * Utility to work with Java 5 generic type parameters.
025: * Mainly for internal use within the framework.
026: *
027: * @author Ramnivas Laddad
028: * @author Juergen Hoeller
029: * @since 2.0.7
030: */
031: public abstract class TypeUtils {
032:
033: /**
034: * Check if the right-hand side type may be assigned to the left-hand side
035: * type following the Java generics rules.
036: * @param lhsType the target type
037: * @param rhsType the value type that should be assigned to the target type
038: * @return true if rhs is assignable to lhs
039: */
040: public static boolean isAssignable(Type lhsType, Type rhsType) {
041: Assert.notNull(lhsType, "Left-hand side type must not be null");
042: Assert
043: .notNull(rhsType,
044: "Right-hand side type must not be null");
045: if (lhsType.equals(rhsType)) {
046: return true;
047: }
048: if (lhsType instanceof Class && rhsType instanceof Class) {
049: return ClassUtils.isAssignable((Class) lhsType,
050: (Class) rhsType);
051: }
052: if (lhsType instanceof ParameterizedType
053: && rhsType instanceof ParameterizedType) {
054: return isAssignable((ParameterizedType) lhsType,
055: (ParameterizedType) rhsType);
056: }
057: if (lhsType instanceof WildcardType) {
058: return isAssignable((WildcardType) lhsType, rhsType);
059: }
060: return false;
061: }
062:
063: private static boolean isAssignable(ParameterizedType lhsType,
064: ParameterizedType rhsType) {
065: if (lhsType.equals(rhsType)) {
066: return true;
067: }
068: Type[] lhsTypeArguments = lhsType.getActualTypeArguments();
069: Type[] rhsTypeArguments = rhsType.getActualTypeArguments();
070: if (lhsTypeArguments.length != rhsTypeArguments.length) {
071: return false;
072: }
073: for (int size = lhsTypeArguments.length, i = 0; i < size; ++i) {
074: Type lhsArg = lhsTypeArguments[i];
075: Type rhsArg = rhsTypeArguments[i];
076: if (!lhsArg.equals(rhsArg)
077: && !(lhsArg instanceof WildcardType && isAssignable(
078: (WildcardType) lhsArg, rhsArg))) {
079: return false;
080: }
081: }
082: return true;
083: }
084:
085: private static boolean isAssignable(WildcardType lhsType,
086: Type rhsType) {
087: Type[] upperBounds = lhsType.getUpperBounds();
088: Type[] lowerBounds = lhsType.getLowerBounds();
089: for (int size = upperBounds.length, i = 0; i < size; ++i) {
090: if (!isAssignable(upperBounds[i], rhsType)) {
091: return false;
092: }
093: }
094: for (int size = lowerBounds.length, i = 0; i < size; ++i) {
095: if (!isAssignable(rhsType, lowerBounds[i])) {
096: return false;
097: }
098: }
099: return true;
100: }
101:
102: }
|