@Test public void testCyclicGenericTypes() throws SecurityException, NoSuchFieldException { assertNotNull(TypeUtil.expandType(Interval.class.getDeclaredField("min").getGenericType(), Interval.class)); }
public final static Type expandType(final Type type, final Type rootType) { if (type instanceof ExpandedType || type instanceof Class) return type; Map<Type, Type> circularTypes = _circularExpandedType.get(); if (circularTypes == null) { circularTypes = new HashMap<Type, Type>(); _circularExpandedType.set(circularTypes); } if (circularTypes.containsKey(type)) { return circularTypes.get(type); } else { try { circularTypes.put(type, getRawClass(type)); TypeAndRootClassKey key = new TypeAndRootClassKey(type, rootType); Type expandedType = _cache.get(key); if (expandedType == null) { if (type instanceof ParameterizedType) { ParameterizedType pType = (ParameterizedType) type; Type[] args = pType.getActualTypeArguments(); int len = args.length; Type[] expandedArgs = new Type[len]; for (int i = 0; i < len; i++) { expandedArgs[i] = expandType(args[i], rootType); } expandedType = new ExpandedParameterizedType(pType, getRawClass(rootType), expandedArgs); } else if (type instanceof TypeVariable) { @SuppressWarnings("unchecked") TypeVariable<GenericDeclaration> tvType = (TypeVariable<GenericDeclaration>) type; if (rootType instanceof ParameterizedType) { ParameterizedType rootPType = (ParameterizedType) rootType; Type[] typeArgs = rootPType.getActualTypeArguments(); String typeName = tvType.getName(); int idx = 0; for (TypeVariable<?> parameter : genericDeclarationToClass(tvType.getGenericDeclaration()) .getTypeParameters()) { if (typeName.equals(parameter.getName())) { expandedType = typeArgs[idx]; break; } idx++; } } else expandedType = resolveTypeVariable(tvType, getRawClass(rootType)); if (type == expandedType) expandedType = expandType(tvType.getBounds()[0], rootType); } else if (type instanceof GenericArrayType) { GenericArrayType genArrType = (GenericArrayType) type; Type cType = expandType(genArrType.getGenericComponentType(), rootType); if (genArrType.getGenericComponentType() == cType) cType = Object.class; expandedType = new ExpandedGenericArrayType(genArrType, cType, getRawClass(rootType)); } else if (type instanceof WildcardType) { WildcardType wType = (WildcardType) type; expandedType = wType.getUpperBounds().length > 0 ? expandType(wType.getUpperBounds()[0], rootType) : Object.class; } if (expandedType == null) throw new IllegalArgumentException("Type " + type + " not supported for expansion!"); _cache.put(key, expandedType); } return expandedType; } finally { circularTypes.remove(type); } } }
TypeUtil { public final static Type expandType(final Type type, final Type rootType) { if (type instanceof ExpandedType || type instanceof Class) return type; Map<Type, Type> circularTypes = _circularExpandedType.get(); if (circularTypes == null) { circularTypes = new HashMap<Type, Type>(); _circularExpandedType.set(circularTypes); } if (circularTypes.containsKey(type)) { return circularTypes.get(type); } else { try { circularTypes.put(type, getRawClass(type)); TypeAndRootClassKey key = new TypeAndRootClassKey(type, rootType); Type expandedType = _cache.get(key); if (expandedType == null) { if (type instanceof ParameterizedType) { ParameterizedType pType = (ParameterizedType) type; Type[] args = pType.getActualTypeArguments(); int len = args.length; Type[] expandedArgs = new Type[len]; for (int i = 0; i < len; i++) { expandedArgs[i] = expandType(args[i], rootType); } expandedType = new ExpandedParameterizedType(pType, getRawClass(rootType), expandedArgs); } else if (type instanceof TypeVariable) { @SuppressWarnings("unchecked") TypeVariable<GenericDeclaration> tvType = (TypeVariable<GenericDeclaration>) type; if (rootType instanceof ParameterizedType) { ParameterizedType rootPType = (ParameterizedType) rootType; Type[] typeArgs = rootPType.getActualTypeArguments(); String typeName = tvType.getName(); int idx = 0; for (TypeVariable<?> parameter : genericDeclarationToClass(tvType.getGenericDeclaration()) .getTypeParameters()) { if (typeName.equals(parameter.getName())) { expandedType = typeArgs[idx]; break; } idx++; } } else expandedType = resolveTypeVariable(tvType, getRawClass(rootType)); if (type == expandedType) expandedType = expandType(tvType.getBounds()[0], rootType); } else if (type instanceof GenericArrayType) { GenericArrayType genArrType = (GenericArrayType) type; Type cType = expandType(genArrType.getGenericComponentType(), rootType); if (genArrType.getGenericComponentType() == cType) cType = Object.class; expandedType = new ExpandedGenericArrayType(genArrType, cType, getRawClass(rootType)); } else if (type instanceof WildcardType) { WildcardType wType = (WildcardType) type; expandedType = wType.getUpperBounds().length > 0 ? expandType(wType.getUpperBounds()[0], rootType) : Object.class; } if (expandedType == null) throw new IllegalArgumentException("Type " + type + " not supported for expansion!"); _cache.put(key, expandedType); } return expandedType; } finally { circularTypes.remove(type); } } } }
TypeUtil { public final static Type expandType(final Type type, final Type rootType) { if (type instanceof ExpandedType || type instanceof Class) return type; Map<Type, Type> circularTypes = _circularExpandedType.get(); if (circularTypes == null) { circularTypes = new HashMap<Type, Type>(); _circularExpandedType.set(circularTypes); } if (circularTypes.containsKey(type)) { return circularTypes.get(type); } else { try { circularTypes.put(type, getRawClass(type)); TypeAndRootClassKey key = new TypeAndRootClassKey(type, rootType); Type expandedType = _cache.get(key); if (expandedType == null) { if (type instanceof ParameterizedType) { ParameterizedType pType = (ParameterizedType) type; Type[] args = pType.getActualTypeArguments(); int len = args.length; Type[] expandedArgs = new Type[len]; for (int i = 0; i < len; i++) { expandedArgs[i] = expandType(args[i], rootType); } expandedType = new ExpandedParameterizedType(pType, getRawClass(rootType), expandedArgs); } else if (type instanceof TypeVariable) { @SuppressWarnings("unchecked") TypeVariable<GenericDeclaration> tvType = (TypeVariable<GenericDeclaration>) type; if (rootType instanceof ParameterizedType) { ParameterizedType rootPType = (ParameterizedType) rootType; Type[] typeArgs = rootPType.getActualTypeArguments(); String typeName = tvType.getName(); int idx = 0; for (TypeVariable<?> parameter : genericDeclarationToClass(tvType.getGenericDeclaration()) .getTypeParameters()) { if (typeName.equals(parameter.getName())) { expandedType = typeArgs[idx]; break; } idx++; } } else expandedType = resolveTypeVariable(tvType, getRawClass(rootType)); if (type == expandedType) expandedType = expandType(tvType.getBounds()[0], rootType); } else if (type instanceof GenericArrayType) { GenericArrayType genArrType = (GenericArrayType) type; Type cType = expandType(genArrType.getGenericComponentType(), rootType); if (genArrType.getGenericComponentType() == cType) cType = Object.class; expandedType = new ExpandedGenericArrayType(genArrType, cType, getRawClass(rootType)); } else if (type instanceof WildcardType) { WildcardType wType = (WildcardType) type; expandedType = wType.getUpperBounds().length > 0 ? expandType(wType.getUpperBounds()[0], rootType) : Object.class; } if (expandedType == null) throw new IllegalArgumentException("Type " + type + " not supported for expansion!"); _cache.put(key, expandedType); } return expandedType; } finally { circularTypes.remove(type); } } }  }
TypeUtil { public final static Type expandType(final Type type, final Type rootType) { if (type instanceof ExpandedType || type instanceof Class) return type; Map<Type, Type> circularTypes = _circularExpandedType.get(); if (circularTypes == null) { circularTypes = new HashMap<Type, Type>(); _circularExpandedType.set(circularTypes); } if (circularTypes.containsKey(type)) { return circularTypes.get(type); } else { try { circularTypes.put(type, getRawClass(type)); TypeAndRootClassKey key = new TypeAndRootClassKey(type, rootType); Type expandedType = _cache.get(key); if (expandedType == null) { if (type instanceof ParameterizedType) { ParameterizedType pType = (ParameterizedType) type; Type[] args = pType.getActualTypeArguments(); int len = args.length; Type[] expandedArgs = new Type[len]; for (int i = 0; i < len; i++) { expandedArgs[i] = expandType(args[i], rootType); } expandedType = new ExpandedParameterizedType(pType, getRawClass(rootType), expandedArgs); } else if (type instanceof TypeVariable) { @SuppressWarnings("unchecked") TypeVariable<GenericDeclaration> tvType = (TypeVariable<GenericDeclaration>) type; if (rootType instanceof ParameterizedType) { ParameterizedType rootPType = (ParameterizedType) rootType; Type[] typeArgs = rootPType.getActualTypeArguments(); String typeName = tvType.getName(); int idx = 0; for (TypeVariable<?> parameter : genericDeclarationToClass(tvType.getGenericDeclaration()) .getTypeParameters()) { if (typeName.equals(parameter.getName())) { expandedType = typeArgs[idx]; break; } idx++; } } else expandedType = resolveTypeVariable(tvType, getRawClass(rootType)); if (type == expandedType) expandedType = expandType(tvType.getBounds()[0], rootType); } else if (type instanceof GenericArrayType) { GenericArrayType genArrType = (GenericArrayType) type; Type cType = expandType(genArrType.getGenericComponentType(), rootType); if (genArrType.getGenericComponentType() == cType) cType = Object.class; expandedType = new ExpandedGenericArrayType(genArrType, cType, getRawClass(rootType)); } else if (type instanceof WildcardType) { WildcardType wType = (WildcardType) type; expandedType = wType.getUpperBounds().length > 0 ? expandType(wType.getUpperBounds()[0], rootType) : Object.class; } if (expandedType == null) throw new IllegalArgumentException("Type " + type + " not supported for expansion!"); _cache.put(key, expandedType); } return expandedType; } finally { circularTypes.remove(type); } } }  final static Class<?> wrap(Class<?> clazz); final static Type expandType(final Type type, final Type rootType); final static Type lookupGenericType(Class<?> ofClass, Class<?> inClass); final static Class<?> getRawClass(Type type); final static Type getCollectionType(Type type); final static Type resolveTypeVariable(TypeVariable<? extends GenericDeclaration> type, Class<?> inClass); final static boolean match(Type type, Type oType, boolean strictMatch); final static Type typeOf(int parameterIdx, Type fromType); }
TypeUtil { public final static Type expandType(final Type type, final Type rootType) { if (type instanceof ExpandedType || type instanceof Class) return type; Map<Type, Type> circularTypes = _circularExpandedType.get(); if (circularTypes == null) { circularTypes = new HashMap<Type, Type>(); _circularExpandedType.set(circularTypes); } if (circularTypes.containsKey(type)) { return circularTypes.get(type); } else { try { circularTypes.put(type, getRawClass(type)); TypeAndRootClassKey key = new TypeAndRootClassKey(type, rootType); Type expandedType = _cache.get(key); if (expandedType == null) { if (type instanceof ParameterizedType) { ParameterizedType pType = (ParameterizedType) type; Type[] args = pType.getActualTypeArguments(); int len = args.length; Type[] expandedArgs = new Type[len]; for (int i = 0; i < len; i++) { expandedArgs[i] = expandType(args[i], rootType); } expandedType = new ExpandedParameterizedType(pType, getRawClass(rootType), expandedArgs); } else if (type instanceof TypeVariable) { @SuppressWarnings("unchecked") TypeVariable<GenericDeclaration> tvType = (TypeVariable<GenericDeclaration>) type; if (rootType instanceof ParameterizedType) { ParameterizedType rootPType = (ParameterizedType) rootType; Type[] typeArgs = rootPType.getActualTypeArguments(); String typeName = tvType.getName(); int idx = 0; for (TypeVariable<?> parameter : genericDeclarationToClass(tvType.getGenericDeclaration()) .getTypeParameters()) { if (typeName.equals(parameter.getName())) { expandedType = typeArgs[idx]; break; } idx++; } } else expandedType = resolveTypeVariable(tvType, getRawClass(rootType)); if (type == expandedType) expandedType = expandType(tvType.getBounds()[0], rootType); } else if (type instanceof GenericArrayType) { GenericArrayType genArrType = (GenericArrayType) type; Type cType = expandType(genArrType.getGenericComponentType(), rootType); if (genArrType.getGenericComponentType() == cType) cType = Object.class; expandedType = new ExpandedGenericArrayType(genArrType, cType, getRawClass(rootType)); } else if (type instanceof WildcardType) { WildcardType wType = (WildcardType) type; expandedType = wType.getUpperBounds().length > 0 ? expandType(wType.getUpperBounds()[0], rootType) : Object.class; } if (expandedType == null) throw new IllegalArgumentException("Type " + type + " not supported for expansion!"); _cache.put(key, expandedType); } return expandedType; } finally { circularTypes.remove(type); } } }  final static Class<?> wrap(Class<?> clazz); final static Type expandType(final Type type, final Type rootType); final static Type lookupGenericType(Class<?> ofClass, Class<?> inClass); final static Class<?> getRawClass(Type type); final static Type getCollectionType(Type type); final static Type resolveTypeVariable(TypeVariable<? extends GenericDeclaration> type, Class<?> inClass); final static boolean match(Type type, Type oType, boolean strictMatch); final static Type typeOf(int parameterIdx, Type fromType);  }