/** * Method that tries to create specialized type given base type, and a sub-class thereof (which is * assumed to use same parametrization as supertype). Similar to calling {@link * JavaType#narrowBy(Class)}, but can change underlying {@link JavaType} (from simple to Map, for * example), unliked <code>narrowBy</code> which assumes same logical type. */ public static JavaType specialize(JavaType baseType, Class<?> subclass) { // Currently only SimpleType instances can become something else if (baseType instanceof SimpleType) { // and only if subclass is an array, Collection or Map if (subclass.isArray() || Map.class.isAssignableFrom(subclass) || Collection.class.isAssignableFrom(subclass)) { // need to assert type compatibility... if (!baseType.getRawClass().isAssignableFrom(subclass)) { throw new IllegalArgumentException( "Class " + subclass.getClass().getName() + " not subtype of " + baseType); } // this _should_ work, right? JavaType subtype = instance._fromClass(subclass, new TypeBindings(baseType.getRawClass())); // one more thing: handlers to copy? Object h = baseType.getValueHandler(); if (h != null) { subtype.setValueHandler(h); } h = baseType.getTypeHandler(); if (h != null) { subtype = subtype.withTypeHandler(h); } return subtype; } } // otherwise regular narrowing should work just fine return baseType.narrowBy(subclass); }
/** * Factory method for constructing {@link JavaType} that represents a parameterized type. For * example, to represent type <code>Iterator<String></code>, you could call * * <pre> * TypeFactory.parametricType(Iterator.class, String.class) * </pre> * * @since 1.5 */ public static JavaType parametricType(Class<?> parametrized, Class<?>... parameterClasses) { int len = parameterClasses.length; JavaType[] pt = new JavaType[len]; for (int i = 0; i < len; ++i) { pt[i] = instance._fromClass(parameterClasses[i], null); } return parametricType(parametrized, pt); }
protected static JavaType _resolveVariableViaSubTypes( HierarchicType leafType, String variableName, TypeBindings bindings) { // can't resolve raw types; possible to have as-of-yet-unbound types too: if (leafType != null && leafType.isGeneric()) { TypeVariable<?>[] typeVariables = leafType.getRawClass().getTypeParameters(); for (int i = 0, len = typeVariables.length; i < len; ++i) { TypeVariable<?> tv = typeVariables[i]; if (variableName.equals(tv.getName())) { // further resolution needed? Type type = leafType.asGeneric().getActualTypeArguments()[i]; if (type instanceof TypeVariable<?>) { return _resolveVariableViaSubTypes( leafType.getSubType(), ((TypeVariable<?>) type).getName(), bindings); } // no we're good for the variable (but it may have parameterization of its own) return instance._fromType(type, bindings); } } } return instance._unknownType(); }
/** * Method that is to figure out actual type parameters that given class binds to generic types * defined by given (generic) interface or class. This could mean, for example, trying to figure * out key and value types for Map implementations. * * @since 1.6 */ public static JavaType[] findParameterTypes(Class<?> clz, Class<?> expType) { // First: find full inheritance chain HierarchicType subType = _findSuperTypeChain(clz, expType); // Caller is supposed to ensure this never happens, so: if (subType == null) { throw new IllegalArgumentException( "Class " + clz.getName() + " is not a subtype of " + expType.getName()); } // Ok and then go to the ultimate super-type: HierarchicType superType = subType; while (superType.getSuperType() != null) { superType = superType.getSuperType(); } // which ought to be generic (if not, it's raw type) if (!superType.isGeneric()) { return null; } // Otherwise this becomes a recursive thing // otherwise need to start unwinding ParameterizedType pt = superType.asGeneric(); Type[] actualTypes = pt.getActualTypeArguments(); JavaType[] resultTypes = new JavaType[actualTypes.length]; // TODO: rewrite TypeBindings to also work properly with renaming, aliasing TypeBindings bindings = new TypeBindings(clz); for (int i = 0, len = actualTypes.length; i < len; ++i) { Type t = actualTypes[i]; // Only type variables need immediate resolution if (t instanceof TypeVariable<?>) { resultTypes[i] = _resolveVariableViaSubTypes( superType.getSubType(), ((TypeVariable<?>) t).getName(), bindings); } else { resultTypes[i] = instance._fromType(t, bindings); } } return resultTypes; }
public static JavaType type(Type type, TypeBindings bindings) { return instance._fromType(type, bindings); }
/** * Factory method for constructing {@link JavaType} from given "raw" type; which may be anything * from simple {@link Class} to full generic type. * * @since 1.3 */ public static JavaType type(Type t) { return instance._fromType(t, null); }