/** * Present a given type as a Java-esque String. * * @param type the type to create a String representation for, not {@code null} * @return String */ public static String toString(final Type type) { Validate.notNull(type); if (type instanceof Class<?>) { return classToString((Class<?>) type); } if (type instanceof ParameterizedType) { return parameterizedTypeToString((ParameterizedType) type); } if (type instanceof WildcardType) { return wildcardTypeToString((WildcardType) type); } if (type instanceof TypeVariable<?>) { return typeVariableToString((TypeVariable<?>) type); } if (type instanceof GenericArrayType) { return genericArrayTypeToString((GenericArrayType) type); } throw new IllegalArgumentException(type.toString()); }
/** * Learn, recursively, whether any of the type parameters associated with {@code type} are bound to variables. * * @param type the type to check for type variables * @return boolean */ public static boolean containsTypeVariables(final Type type) { if (type instanceof TypeVariable<?>) { return true; } if (type instanceof Class<?>) { return ((Class<?>) type).getTypeParameters().length > 0; } if (type instanceof ParameterizedType) { for (final Type arg : ((ParameterizedType) type).getActualTypeArguments()) { if (containsTypeVariables(arg)) { return true; } } return false; } if (type instanceof WildcardType) { final WildcardType wild = (WildcardType) type; return containsTypeVariables(TypeUtils.getImplicitLowerBounds(wild)[0]) || containsTypeVariables(TypeUtils.getImplicitUpperBounds(wild)[0]); } return false; }
/** * Learn whether {@code t} equals {@code w}. * @param w LHS * @param t RHS * @return boolean */ private static boolean equals(final WildcardType w, final Type t) { if (t instanceof WildcardType) { final WildcardType other = (WildcardType) t; return equals(getImplicitLowerBounds(w), getImplicitLowerBounds(other)) && equals(getImplicitUpperBounds(w), getImplicitUpperBounds(other)); } return false; }
/** * Get the Java element type of a particular container type. * * @param containerType * @return Type or <code>null</code> if <code>containerType</code> is not * some type of {@link Iterable} or array */ public static Type getJavaElementType(Type containerType) { if (TypeUtils.isArrayType(containerType)) { return TypeUtils.getArrayComponentType(containerType); } if (TypeUtils.isAssignable(containerType, Iterable.class)) { Map<TypeVariable<?>, Type> typeArguments = TypeUtils.getTypeArguments(containerType, Iterable.class); Type type = TypeUtils.unrollVariables(typeArguments, ITERABLE_TYPE); return type != null ? type : Object.class; } return null; }
@Override public final Type getGenericType() { if (TypeUtils.containsTypeVariables(genericType)) { final Map<TypeVariable<?>, Type> args = TypeUtils.getTypeArguments(parent.getGenericType(), Object.class); return TypeUtils.unrollVariables(args, genericType); } return genericType; }
typeArguments = Collections.<TypeVariable<?>, Type> emptyMap(); if (containsTypeVariables(type)) { if (type instanceof TypeVariable<?>) { return unrollVariables(typeArguments, typeArguments.get(type)); } else { parameterizedTypeArguments = new HashMap<TypeVariable<?>, Type>(typeArguments); parameterizedTypeArguments.putAll(TypeUtils.getTypeArguments(p)); final Type unrolled = unrollVariables(parameterizedTypeArguments, args[i]); if (unrolled != null) { args[i] = unrolled; return parameterizeWithOwner(p.getOwnerType(), (Class<?>) p.getRawType(), args); return wildcardType().withUpperBounds(unrollBounds(typeArguments, wild.getUpperBounds())) .withLowerBounds(unrollBounds(typeArguments, wild.getLowerBounds())).build();
final Map<TypeVariable<?>, Type> subtypeVarAssigns) { if (type instanceof Class<?>) { return getTypeArguments((Class<?>) type, toClass, subtypeVarAssigns); return getTypeArguments((ParameterizedType) type, toClass, subtypeVarAssigns); return getTypeArguments(((GenericArrayType) type).getGenericComponentType(), toClass .isArray() ? toClass.getComponentType() : toClass, subtypeVarAssigns); for (final Type bound : getImplicitUpperBounds((WildcardType) type)) { if (isAssignable(bound, toClass)) { return getTypeArguments(bound, toClass, subtypeVarAssigns); for (final Type bound : getImplicitBounds((TypeVariable<?>) type)) { if (isAssignable(bound, toClass)) { return getTypeArguments(bound, toClass, subtypeVarAssigns);
final ParameterizedType parameterizedType, final Class<?> toClass, final Map<TypeVariable<?>, Type> subtypeVarAssigns) { final Class<?> cls = getRawType(parameterizedType); if (!isAssignable(cls, toClass)) { return null; typeVarAssigns = getTypeArguments(parameterizedOwnerType, getRawType(parameterizedOwnerType), subtypeVarAssigns); } else { return getTypeArguments(getClosestParentType(cls, toClass), toClass, typeVarAssigns);
final Type[] toUpperBounds = getImplicitUpperBounds(toWildcardType); final Type[] toLowerBounds = getImplicitLowerBounds(toWildcardType); final Type[] upperBounds = getImplicitUpperBounds(wildcardType); final Type[] lowerBounds = getImplicitLowerBounds(wildcardType); toBound = substituteTypeVariables(toBound, typeVarAssigns); if (!isAssignable(bound, toBound, typeVarAssigns)) { return false; toBound = substituteTypeVariables(toBound, typeVarAssigns); if (!isAssignable(toBound, bound, typeVarAssigns)) { return false; if (!isAssignable(type, substituteTypeVariables(toBound, typeVarAssigns), typeVarAssigns)) { return false; if (!isAssignable(substituteTypeVariables(toBound, typeVarAssigns), type, typeVarAssigns)) { return false;
final Map<TypeVariable<?>, Type> subtypeVarAssigns) { if (!isAssignable(cls, toClass)) { return null; return getTypeArguments(getClosestParentType(cls, toClass), toClass, typeVarAssigns);
&& isAssignable(cls.getComponentType(), toComponentType, typeVarAssigns); return isAssignable(((GenericArrayType) type).getGenericComponentType(), toComponentType, typeVarAssigns); for (final Type bound : getImplicitUpperBounds((WildcardType) type)) { if (isAssignable(bound, toGenericArrayType)) { return true; for (final Type bound : getImplicitBounds((TypeVariable<?>) type)) { if (isAssignable(bound, toGenericArrayType)) { return true;
/** * Learn whether {@code t1} equals {@code t2}. * @param t1 LHS * @param t2 RHS * @return boolean */ private static boolean equals(final Type[] t1, final Type[] t2) { if (t1.length == t2.length) { for (int i = 0; i < t1.length; i++) { if (!equals(t1[i], t2[i])) { return false; } } return true; } return false; }
/** * Format a {@link Class} as a {@link String}. * @param c {@code Class} to format * @return String */ private static String classToString(final Class<?> c) { final StringBuilder buf = new StringBuilder(); if (c.getEnclosingClass() != null) { buf.append(classToString(c.getEnclosingClass())).append('.').append(c.getSimpleName()); } else { buf.append(c.getName()); } if (c.getTypeParameters().length > 0) { buf.append('<'); appendAllTo(buf, ", ", c.getTypeParameters()); buf.append('>'); } return buf.toString(); }
final Type[] bounds = getImplicitBounds((TypeVariable<?>) type); if (isAssignable(bound, toTypeVariable, typeVarAssigns)) { return true;
/** * Format a {@link WildcardType} as a {@link String}. * @param w {@code WildcardType} to format * @return String */ private static String wildcardTypeToString(final WildcardType w) { final StringBuilder buf = new StringBuilder().append('?'); final Type[] lowerBounds = w.getLowerBounds(); final Type[] upperBounds = w.getUpperBounds(); if (lowerBounds.length > 1 || lowerBounds.length == 1 && lowerBounds[0] != null) { appendAllTo(buf.append(" super "), " & ", lowerBounds); } else if (upperBounds.length > 1 || upperBounds.length == 1 && !Object.class.equals(upperBounds[0])) { appendAllTo(buf.append(" extends "), " & ", upperBounds); } return buf.toString(); }
typeArguments = Collections.<TypeVariable<?>, Type> emptyMap(); if (containsTypeVariables(type)) { if (type instanceof TypeVariable<?>) { return unrollVariables(typeArguments, typeArguments.get(type)); } else { parameterizedTypeArguments = new HashMap<>(typeArguments); parameterizedTypeArguments.putAll(TypeUtils.getTypeArguments(p)); final Type unrolled = unrollVariables(parameterizedTypeArguments, args[i]); if (unrolled != null) { args[i] = unrolled; return parameterizeWithOwner(p.getOwnerType(), (Class<?>) p.getRawType(), args); return wildcardType().withUpperBounds(unrollBounds(typeArguments, wild.getUpperBounds())) .withLowerBounds(unrollBounds(typeArguments, wild.getLowerBounds())).build();
private Step handleElementByType(Type type) { Type elementType; if (TypeUtils.isArrayType(type)) { elementType = TypeUtils.getArrayComponentType(type); } else if (TypeUtils.isAssignable(type, Map.class)) { elementType = Optional.ofNullable(TypeUtils.getTypeArguments(type, Map.class).get(MAP_VALUE)).orElse(MAP_VALUE); } else if (TypeUtils.isAssignable(type, Iterable.class)) { elementType = Optional.ofNullable(TypeUtils.getTypeArguments(type, Iterable.class).get(ITERABLE_ELEMENT)) .orElse(ITERABLE_ELEMENT); } else { throw Exceptions.create(IllegalArgumentException::new, "Unable to resolve element type of %s", type); } return new TypeWrapper(validatorContext, elementType); }
final Map<TypeVariable<?>, Type> subtypeVarAssigns) { if (type instanceof Class<?>) { return getTypeArguments((Class<?>) type, toClass, subtypeVarAssigns); return getTypeArguments((ParameterizedType) type, toClass, subtypeVarAssigns); return getTypeArguments(((GenericArrayType) type).getGenericComponentType(), toClass .isArray() ? toClass.getComponentType() : toClass, subtypeVarAssigns); for (final Type bound : getImplicitUpperBounds((WildcardType) type)) { if (isAssignable(bound, toClass)) { return getTypeArguments(bound, toClass, subtypeVarAssigns); for (final Type bound : getImplicitBounds((TypeVariable<?>) type)) { if (isAssignable(bound, toClass)) { return getTypeArguments(bound, toClass, subtypeVarAssigns);
final ParameterizedType parameterizedType, final Class<?> toClass, final Map<TypeVariable<?>, Type> subtypeVarAssigns) { final Class<?> cls = getRawType(parameterizedType); if (!isAssignable(cls, toClass)) { return null; typeVarAssigns = getTypeArguments(parameterizedOwnerType, getRawType(parameterizedOwnerType), subtypeVarAssigns); } else { return getTypeArguments(getClosestParentType(cls, toClass), toClass, typeVarAssigns);
final Type[] toUpperBounds = getImplicitUpperBounds(toWildcardType); final Type[] toLowerBounds = getImplicitLowerBounds(toWildcardType); final Type[] upperBounds = getImplicitUpperBounds(wildcardType); final Type[] lowerBounds = getImplicitLowerBounds(wildcardType); toBound = substituteTypeVariables(toBound, typeVarAssigns); if (!isAssignable(bound, toBound, typeVarAssigns)) { return false; toBound = substituteTypeVariables(toBound, typeVarAssigns); if (!isAssignable(toBound, bound, typeVarAssigns)) { return false; if (!isAssignable(type, substituteTypeVariables(toBound, typeVarAssigns), typeVarAssigns)) { return false; if (!isAssignable(substituteTypeVariables(toBound, typeVarAssigns), type, typeVarAssigns)) { return false;