/** * Parse type variables for generics * * @param variables * @return */ protected static TypeVar[] ParseTypeVariables(TypeVariable[] variables, ParamTag[] tags) { TypeVar[] vars = null; if (variables != null && variables.length > 0) { ArrayList<TypeVar> varsList = new ArrayList<TypeVar>(); for (TypeVariable variable : variables) { TypeVar var = new TypeVar(); var.name = variable.typeName(); Type[] bounds = variable.bounds(); if (bounds != null && bounds.length > 0) { ArrayList<String> list = new ArrayList<String>(); for (Type bound : bounds) { list.add(bound.qualifiedTypeName()); } var.bounds = list.toArray(new String[] {}); } for (ParamTag tag : tags) if (tag.parameterName().equals(var.name)) var.comment = tag.parameterComment(); varsList.add(var); } vars = varsList.toArray(new TypeVar[] {}); } return vars; }
private DeclaredType getDeclaredTypeForTypeVariable(TypeVariable typeVariable) { Name name = typeVariable.asElement().getSimpleName(); if (!_typeArguments.containsKey(name)) { throw new UnsupportedOperationException( String.format( "Unknown parameterized type: %s. Available types in this context: %s", typeVariable.toString(), _typeArguments)); } else { return _typeArguments.get(name); } }
@Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; return typeVariable.equals(((TypeVarBoundedType) o).typeVariable); }
/** * @param typeParameter The TypeVariable parameter * @return A {@link BoundedType} for easy bound information, if first bound is a TypeVariable then * retrieve BoundedType of this TypeVariable */ private BoundedType boundsOf(TypeVariable typeParameter) { if (typeParameter.getBounds()[0] instanceof TypeVariable) { return boundsOf((TypeVariable) typeParameter.getBounds()[0]); } return new TypeVarBoundedType(typeParameter); }
@Override public int hashCode() { return typeVariable.hashCode(); }
/** * On a Type Variable (typeVar extends C_0 & I_1 & I_2 & etc), will return an array containing * I_1 and I_2. * * @return other bounds for this type, these bounds can only be only interfaces as the JLS says, * empty array if no other bound declared. */ public Type[] interfaceBounds() { Type[] interfaceBounds = new Type[typeVariable.getBounds().length - 1]; System.arraycopy( typeVariable.getBounds(), 1, interfaceBounds, 0, typeVariable.getBounds().length - 1); return interfaceBounds; }
/** * @return either a class or an interface (parameterized or not), if no bounds declared Object * is returned. */ public Type firstBound() { return typeVariable.getBounds()[0]; // }
private void readTypeVariables() { for (Type type : typeVariable.getBounds()) { registerTypeVariablesOn(type); } registerTypeVariablesOn(getActualTypeArgumentFor(typeVariable)); }
protected void _resolveBindings(Type t) { if (t == null) return; Class<?> raw; if (t instanceof ParameterizedType) { ParameterizedType pt = (ParameterizedType) t; Type[] args = pt.getActualTypeArguments(); if (args != null && args.length > 0) { Class<?> rawType = (Class<?>) pt.getRawType(); TypeVariable<?>[] vars = rawType.getTypeParameters(); if (vars.length != args.length) { throw new IllegalArgumentException( "Strange parametrized type (in class " + rawType.getName() + "): number of type arguments != number of type parameters (" + args.length + " vs " + vars.length + ")"); } for (int i = 0, len = args.length; i < len; ++i) { TypeVariable<?> var = vars[i]; String name = var.getName(); if (_bindings == null) { _bindings = new LinkedHashMap<String, JavaType>(); } else { /* 24-Mar-2010, tatu: Better ensure that we do not overwrite something * collected earlier (since we descend towards super-classes): */ if (_bindings.containsKey(name)) continue; } // first: add a placeholder to prevent infinite loops _addPlaceholder(name); // then resolve type _bindings.put(name, _typeFactory._constructType(args[i], this)); } } raw = (Class<?>) pt.getRawType(); } else if (t instanceof Class<?>) { raw = (Class<?>) t; /* [JACKSON-677]: If this is an inner class then the generics are defined on the * enclosing class so we have to check there as well. We don't * need to call getEnclosingClass since anonymous classes declare * generics */ _resolveBindings(raw.getDeclaringClass()); /* 24-Mar-2010, tatu: Can not have true generics definitions, but can * have lower bounds ("<T extends BeanBase>") in declaration itself */ TypeVariable<?>[] vars = raw.getTypeParameters(); if (vars != null && vars.length > 0) { JavaType[] typeParams = null; if (_contextType != null && raw.isAssignableFrom(_contextType.getRawClass())) { typeParams = _typeFactory.findTypeParameters(_contextType, raw); } for (int i = 0; i < vars.length; i++) { TypeVariable<?> var = vars[i]; String name = var.getName(); Type varType = var.getBounds()[0]; if (varType != null) { if (_bindings == null) { _bindings = new LinkedHashMap<String, JavaType>(); } else { // and no overwriting... if (_bindings.containsKey(name)) continue; } _addPlaceholder(name); // to prevent infinite loops if (typeParams != null) { _bindings.put(name, typeParams[i]); } else { _bindings.put(name, _typeFactory._constructType(varType, this)); } } } } } else { // probably can't be any of these... so let's skip for now // if (type instanceof GenericArrayType) { // if (type instanceof TypeVariable<?>) { // if (type instanceof WildcardType) { return; } // but even if it's not a parameterized type, its super types may be: _resolveBindings(raw.getGenericSuperclass()); for (Type intType : raw.getGenericInterfaces()) { _resolveBindings(intType); } }