private Object convert( Type targetType, Object sourceObject, Action<? super SourceObjectMapping> mapping) { if (targetType instanceof ParameterizedType) { ParameterizedType parameterizedTargetType = (ParameterizedType) targetType; if (parameterizedTargetType.getRawType() instanceof Class) { Class<?> rawClass = (Class<?>) parameterizedTargetType.getRawType(); if (Iterable.class.isAssignableFrom(rawClass)) { Type targetElementType = getElementType(parameterizedTargetType, 0); return convertCollectionInternal( rawClass, targetElementType, (Iterable<?>) sourceObject, mapping); } if (Map.class.isAssignableFrom(rawClass)) { Type targetKeyType = getElementType(parameterizedTargetType, 0); Type targetValueType = getElementType(parameterizedTargetType, 1); return convertMap( rawClass, targetKeyType, targetValueType, (Map<?, ?>) sourceObject, mapping); } } } if (targetType instanceof Class) { if (((Class) targetType).isPrimitive()) { return sourceObject; } return adapt((Class) targetType, sourceObject, mapping); } throw new UnsupportedOperationException( String.format("Cannot convert object of %s to %s.", sourceObject.getClass(), targetType)); }
static Class<?> getTypeClass(Type type) { if (type instanceof Class<?>) { return (Class<?>) type; } if (type instanceof ParameterizedType) { ParameterizedType pt = (ParameterizedType) type; Class<?> c = (Class<?>) pt.getRawType(); if (ValuedEnum.class.isAssignableFrom(c)) { Type[] types = pt.getActualTypeArguments(); if (types == null || types.length != 1) { c = int.class; } else { c = getTypeClass(pt.getActualTypeArguments()[0]); } } return c; } if (type instanceof GenericArrayType) { if (Object.class.isAssignableFrom( getTypeClass(((GenericArrayType) type).getGenericComponentType()))) { return Object[].class; } } throw new UnsupportedOperationException("Unknown type type : " + type.getClass().getName()); }
private static int checkParameterizedType( String subroutineName, ParameterizedType expectedType, ArgumentsList arguments, List<LispObject> args, int argsCounter, int i) { Type rawType = expectedType.getRawType(); Type expectedTypeArguments = expectedType.getActualTypeArguments()[0]; try { if (((Class) rawType).isInstance(args.get(argsCounter))) { Type actualTypeArguments = ((ParameterizedType) (Type) args.get(argsCounter).getClass()) .getActualTypeArguments()[0]; if (!expectedTypeArguments.equals(actualTypeArguments)) { throw new WrongTypeArgumentException( ((Class) rawType).getSimpleName() + "<" + ((Class) expectedTypeArguments).getSimpleName() + ">", args.get(argsCounter)); } arguments.setValue(i, args.get(argsCounter)); return argsCounter + 1; } else { if (arguments.isOptional(i)) return -1; throw new WrongTypeArgumentException(expectedType.toString(), args.get(argsCounter)); } } catch (IndexOutOfBoundsException e) { if (arguments.isOptional(i)) return -1; throw new WrongNumberOfArgumentsException(subroutineName, i); } }
/** * @param type - something like List<T>, List<T extends Number> * @param containingType - the shallowest type in the hierarchy where type is defined. * @return the passed type if nothing to resolve or a copy of the type with the type arguments * resolved. */ private static ParameterizedType resolve(ParameterizedType type, Type containingType) { // Use a copy because we're going to modify it. final Type[] types = type.getActualTypeArguments().clone(); boolean modified = resolve(types, containingType); return modified ? create(type.getRawType(), type.getOwnerType(), types) : type; }
@Nullable private static TypeWrapper wrap(Type type) { if (type == null) { return null; } else if (type instanceof Class) { return new ClassTypeWrapper((Class<?>) type); } else if (type instanceof ParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType) type; return new ParameterizedTypeWrapper( toWrappers(parameterizedType.getActualTypeArguments()), (ClassTypeWrapper) wrap(parameterizedType.getRawType()), wrap(parameterizedType.getOwnerType())); } else if (type instanceof WildcardType) { WildcardType wildcardType = (WildcardType) type; return new WildcardTypeWrapper( toWrappers(wildcardType.getUpperBounds()), toWrappers(wildcardType.getLowerBounds()), type.hashCode()); } else if (type instanceof TypeVariable) { TypeVariable<?> typeVariable = (TypeVariable<?>) type; return new TypeVariableTypeWrapper( typeVariable.getName(), toWrappers(typeVariable.getBounds()), type.hashCode()); } else if (type instanceof GenericArrayType) { GenericArrayType genericArrayType = (GenericArrayType) type; return new GenericArrayTypeWrapper( wrap(genericArrayType.getGenericComponentType()), type.hashCode()); } else { throw new IllegalArgumentException("cannot wrap type of type " + type.getClass()); } }
@Test public void get_generic_type_of_a_field() throws Exception { Field field = Dummy.class.getDeclaredField("stringListField"); ParameterizedType type = (ParameterizedType) field.getGenericType(); assertEquals(List.class, type.getRawType()); assertArrayEquals(new Type[] {String.class}, type.getActualTypeArguments()); assertEquals(null, type.getOwnerType()); }
@Test public void get_generic_type_of_interface_method_parameters() throws Exception { Method method = Interface.class.getDeclaredMethod("stringListMethod", List.class); Type[] types = method.getGenericParameterTypes(); ParameterizedType type = (ParameterizedType) types[0]; assertEquals(List.class, type.getRawType()); assertArrayEquals(new Type[] {String.class}, type.getActualTypeArguments()); assertEquals(null, type.getOwnerType()); }
private void visitType(java.lang.reflect.Type type, StringBuilder builder) { if (type instanceof Class) { Class<?> cl = (Class<?>) type; if (cl.isPrimitive()) { builder.append(Type.getType(cl).getDescriptor()); } else { if (cl.isArray()) { builder.append(cl.getName().replace('.', '/')); } else { builder.append('L'); builder.append(cl.getName().replace('.', '/')); builder.append(';'); } } } else if (type instanceof ParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType) type; visitNested(parameterizedType.getRawType(), builder); builder.append('<'); for (java.lang.reflect.Type param : parameterizedType.getActualTypeArguments()) { visitType(param, builder); } builder.append(">;"); } else if (type instanceof WildcardType) { WildcardType wildcardType = (WildcardType) type; if (wildcardType.getUpperBounds().length == 1 && wildcardType.getUpperBounds()[0].equals(Object.class)) { if (wildcardType.getLowerBounds().length == 0) { builder.append('*'); return; } } else { for (java.lang.reflect.Type upperType : wildcardType.getUpperBounds()) { builder.append('+'); visitType(upperType, builder); } } for (java.lang.reflect.Type lowerType : wildcardType.getLowerBounds()) { builder.append('-'); visitType(lowerType, builder); } } else if (type instanceof TypeVariable) { TypeVariable<?> typeVar = (TypeVariable) type; builder.append('T'); builder.append(typeVar.getName()); builder.append(';'); } else if (type instanceof GenericArrayType) { GenericArrayType arrayType = (GenericArrayType) type; builder.append('['); visitType(arrayType.getGenericComponentType(), builder); } else { throw new IllegalArgumentException( String.format("Cannot generate signature for %s.", type)); } }
/** * Compute the erasure of a type. * * @param type The type to erase. * @return The class representing the erasure of the type. * @throws IllegalArgumentException if <var>type</var> is unerasable (e.g. it is a type variable * or a wildcard). */ public static Class<?> erase(Type type) { if (type instanceof Class) { return (Class<?>) type; } else if (type instanceof ParameterizedType) { ParameterizedType pt = (ParameterizedType) type; Type raw = pt.getRawType(); try { return (Class<?>) raw; } catch (ClassCastException e) { throw new RuntimeException("raw type not a Class", e); } } else { throw new IllegalArgumentException(); } }
private static Type<?> resolveUnresolvedType( RuntimeType<?> rtt, Object o_or_any_or_subParams, Type<?> origTypeArgument) { Type<?> t = origTypeArgument; while (t instanceof UnresolvedType) { int index = ((UnresolvedType) t).getIndex(); if (o_or_any_or_subParams instanceof Any) { Any any = (Any) o_or_any_or_subParams; t = index == -1 ? rtt : any.$getParam(index); } else if (o_or_any_or_subParams instanceof Type<?>[]) { Type<?>[] paramsRTT = (Type<?>[]) o_or_any_or_subParams; t = index == -1 ? rtt : paramsRTT[index]; } else { assert (index == -1); t = rtt; } } if (t instanceof ParameterizedType<?>) { ParameterizedType<?> pt = (ParameterizedType<?>) t; Type<?>[] origTypeArgumentsT = pt.getActualTypeArguments(); Type<?>[] resolvedTypeArgumentsT = new Type<?>[origTypeArgumentsT.length]; for (int i = 0; i < origTypeArgumentsT.length; i++) { resolvedTypeArgumentsT[i] = resolveUnresolvedType(rtt, o_or_any_or_subParams, origTypeArgumentsT[i]); } if (origTypeArgumentsT.length == 1) { t = ParameterizedType.make(pt.getRawType(), resolvedTypeArgumentsT[0]); } else if (origTypeArgumentsT.length == 2) { t = ParameterizedType.make( pt.getRawType(), resolvedTypeArgumentsT[0], resolvedTypeArgumentsT[1]); } else { t = ParameterizedType.make(pt.getRawType(), resolvedTypeArgumentsT); } } return t; }
public static <C, I> Type[] getGenericInterfaceParams( Class<C> checkedClass, Class<I> searchedInterface) { for (Type type : checkedClass.getGenericInterfaces()) { ParameterizedType pt = (ParameterizedType) type; if (searchedInterface.equals(pt.getRawType())) { ParameterizedType pType = ((ParameterizedType) type); return pType.getActualTypeArguments(); } } if (!Object.class.equals(checkedClass.getSuperclass())) return getGenericInterfaceParams(checkedClass.getSuperclass(), searchedInterface); throw new ConfigurationError( checkedClass + " does not implement interface with generic parameters: " + searchedInterface); }
public boolean isAssignableTo(Type<?> superType) { if (this == superType) return true; if (superType == Types.ANY) return true; if (superType instanceof RuntimeType<?>) { RuntimeType<?> rt = (RuntimeType<?>) superType; if (rt.javaClass.isAssignableFrom(javaClass)) { return true; } } if (superType instanceof ParameterizedType) { ParameterizedType<?> pt = (ParameterizedType<?>) superType; if (pt.getRawType().isAssignableFrom(pt.getActualTypeArguments(), this, null)) { return true; } } return false; }
// e.g. C[T1,T2]:Super[Int, T1] -> C[Int,Double]:Super[Int,Int] private final boolean instantiateCheck( Type<?>[] params, RuntimeType<?> rtt, Object o_or_any_or_subParams) { if (rtt.parents != null) { for (Type<?> t : rtt.parents) { if (javaClass.isAssignableFrom(t.getJavaClass())) { if (t instanceof ParameterizedType<?>) { ParameterizedType<?> pt = (ParameterizedType<?>) t; Type<?>[] origTypeArgumentsT = pt.getActualTypeArguments(); Type<?>[] resolvedTypeArgumentsT = new Type<?>[origTypeArgumentsT.length]; for (int i = 0; i < origTypeArgumentsT.length; i++) { resolvedTypeArgumentsT[i] = resolveUnresolvedType(rtt, o_or_any_or_subParams, origTypeArgumentsT[i]); } if (isAssignableFrom(params, pt.getRawType(), resolvedTypeArgumentsT)) { return true; } } } } } return false; }
protected void registerTypeVariablesOn(Type classType) { if (!(classType instanceof ParameterizedType)) { return; } ParameterizedType parameterizedType = (ParameterizedType) classType; TypeVariable[] typeParameters = ((Class<?>) parameterizedType.getRawType()).getTypeParameters(); Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); for (int i = 0; i < actualTypeArguments.length; i++) { TypeVariable typeParameter = typeParameters[i]; Type actualTypeArgument = actualTypeArguments[i]; if (actualTypeArgument instanceof WildcardType) { contextualActualTypeParameters.put( typeParameter, boundsOf((WildcardType) actualTypeArgument)); } else { contextualActualTypeParameters.put(typeParameter, actualTypeArgument); } // logger.log("For '" + parameterizedType + "' found type variable : { '" + typeParameter + // "(" + System.identityHashCode(typeParameter) + ")" + "' : '" + actualTypeArgument + "(" + // System.identityHashCode(typeParameter) + ")" + "' }"); } }
/** * Gets the actual type arguments that are used in a given implementation of a given generic base * class or interface. (Based on code copyright 2007 by Ian Robertson). * * @param base the generic base class or interface * @param implementation the type (potentially) implementing the given base class or interface * @return a list of the raw classes for the actual type arguments. */ @NotNull public static List<Class<?>> getTypeArguments( @NotNull Class<?> base, @NotNull Class<?> implementation) { Map<Type, Type> resolvedTypes = new HashMap<Type, Type>(); // first we need to resolve all supertypes up to the required base class or interface // and find the right Type for it Type type; Queue<Type> toCheck = new LinkedList<Type>(); toCheck.add(implementation); while (true) { // if we have checked everything and not found the base class we return an empty list if (toCheck.isEmpty()) return ImmutableList.of(); type = toCheck.remove(); Class<?> clazz; if (type instanceof Class) { // there is no useful information for us in raw types, so just keep going up the inheritance // chain clazz = (Class) type; if (base.isInterface()) { // if we are actually looking for the type parameters to an interface we also need to // look at all the ones implemented by the given current one toCheck.addAll(Arrays.asList(clazz.getGenericInterfaces())); } } else if (type instanceof ParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType) type; clazz = (Class) parameterizedType.getRawType(); // for instances of ParameterizedType we extract and remember all type arguments TypeVariable<?>[] typeParameters = clazz.getTypeParameters(); Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); for (int i = 0; i < actualTypeArguments.length; i++) { resolvedTypes.put(typeParameters[i], actualTypeArguments[i]); } } else { return ImmutableList.of(); } // we can stop if we have reached the sought for base type if (base.equals(getClass(type))) break; toCheck.add(clazz.getGenericSuperclass()); } // finally, for each actual type argument provided to baseClass, // determine (if possible) the raw class for that type argument. Type[] actualTypeArguments; if (type instanceof Class) { actualTypeArguments = ((Class) type).getTypeParameters(); } else { actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments(); } List<Class<?>> typeArgumentsAsClasses = new ArrayList<Class<?>>(); // resolve types by chasing down type variables. for (Type baseType : actualTypeArguments) { while (resolvedTypes.containsKey(baseType)) { baseType = resolvedTypes.get(baseType); } typeArgumentsAsClasses.add(getClass(baseType)); } return typeArgumentsAsClasses; }
@Override public Class<?> rawType() { return (Class<?>) parameterizedType.getRawType(); }
private void readActualTypeParameters() { registerTypeVariablesOn(parameterizedType.getRawType()); registerTypeVariablesOn(parameterizedType); }
static String toString(ParameterizedType pt) { String s = toString(pt.getActualTypeArguments()); return String.format("%s<%s>", toString(pt.getRawType()), s); }
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); } }
private ClassNode configureParameterizedType(ParameterizedType parameterizedType) { ClassNode base = configureType(parameterizedType.getRawType()); GenericsType[] gts = configureTypeArguments(parameterizedType.getActualTypeArguments()); base.setGenericsTypes(gts); return base; }
private void writeCollection( final OutputStream outputStream, final Type collectionType, final Collection<?> collection, final QName outerTagName) { final Class<?> rawType; if (collectionType instanceof ParameterizedType) { final ParameterizedType returnType = (ParameterizedType) collectionType; rawType = (Class<?>) returnType.getRawType(); } else if (collectionType instanceof Class<?>) { rawType = (Class<?>) collectionType; } else if (collectionType instanceof WildcardType) { final Type[] UpperBounds = ((WildcardType) collectionType).getUpperBounds(); if (UpperBounds.length > 0) { rawType = (Class<?>) UpperBounds[0]; } else { rawType = Object.class; } } else if (collectionType instanceof TypeVariable) { final Type[] UpperBounds = ((TypeVariable<?>) collectionType).getBounds(); if (UpperBounds.length > 0) { rawType = (Class<?>) UpperBounds[0]; } else { rawType = Object.class; } } else { throw new IllegalArgumentException("Unsupported type variable"); } Class<?> elementType; if (Collection.class.isAssignableFrom(rawType)) { final Type[] paramTypes = Types.getTypeParametersFor(Collection.class, collectionType); elementType = Types.toRawType(paramTypes[0]); if (elementType.isInterface()) { // interfaces not supported by jaxb elementType = Types.commonAncestor(collection); } } else { elementType = Types.commonAncestor(collection); } try { // As long as JAXB is an option, we have to know that this is a StAXWriter as JAXB needs to // write to that. try (XmlWriter xmlWriter = XmlStreaming.newWriter(outputStream, "UTF-8")) { Marshaller marshaller = null; XmlWriterUtil.smartStartTag(xmlWriter, outerTagName); for (Object item : collection) { if (item != null) { if (item instanceof XmlSerializable) { ((XmlSerializable) item).serialize(xmlWriter); } else if (item instanceof Node) { XmlWriterUtil.serialize(xmlWriter, (Node) item); } else { if (marshaller == null) { JAXBContext jaxbcontext = null; if (elementType == null) { jaxbcontext = newJAXBContext(JAXBCollectionWrapper.class); } else { jaxbcontext = newJAXBContext(JAXBCollectionWrapper.class, elementType); } marshaller = jaxbcontext.createMarshaller(); } marshaller.marshal(item, (XMLStreamWriter) getDelegateMethod().invoke(xmlWriter)); } } } XmlWriterUtil.endTag(xmlWriter, outerTagName); } } catch (Throwable e) { throw new MessagingException(e); } }