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)); }
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); }
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) + ")" + "' }"); } }
@Override public Class<?> rawType() { return (Class<?>) parameterizedType.getRawType(); }
private void readActualTypeParameters() { registerTypeVariablesOn(parameterizedType.getRawType()); registerTypeVariablesOn(parameterizedType); }
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); } }
/** * 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; }