private void readActualTypeParametersOnDeclaringClass() { registerTypeParametersOn(clazz.getTypeParameters()); registerTypeVariablesOn(clazz.getGenericSuperclass()); for (Type genericInterface : clazz.getGenericInterfaces()) { registerTypeVariablesOn(genericInterface); } }
@SuppressWarnings("unchecked") @Override public <P> Getter<GettableByIndexData, P> newGetter( Type target, DatastaxColumnKey key, ColumnDefinition<?, ?> columnDefinition) { Class<?> targetClass = TypeHelper.toClass(target); if (Date.class.equals(targetClass)) { return (Getter<GettableByIndexData, P>) new DatastaxDateGetter(key.getIndex()); } if (boolean.class.equals(targetClass) || Boolean.class.equals(targetClass)) { return (Getter<GettableByIndexData, P>) new DatastaxBooleanGetter(key.getIndex()); } if (InetAddress.class.equals(targetClass)) { return (Getter<GettableByIndexData, P>) new DatastaxInetAddressGetter(key.getIndex()); } if (TupleValue.class.equals(targetClass)) { return (Getter<GettableByIndexData, P>) new DatastaxTupleValueGetter(key.getIndex()); } if (Collection.class.isAssignableFrom(targetClass)) { Type elementType = TypeHelper.getComponentTypeOfListOrArray(target); Class<?> dataTypeClass = Object.class; Class<?> dataTypeElt = null; DataType dtElt = null; if (key.getDataType() != null) { DataType dataType = key.getDataType(); dataTypeClass = dataType.asJavaClass(); if (dataType.isCollection()) { dtElt = key.getDataType().getTypeArguments().get(0); dataTypeElt = dtElt.asJavaClass(); } } else { dataTypeElt = TypeHelper.toClass(elementType); } if (dataTypeElt != null) { if (TypeHelper.areEquals(elementType, dataTypeElt)) { if (Set.class.equals(dataTypeClass)) { if (targetClass.isAssignableFrom(dataTypeClass)) { return new DatastaxSetGetter(key.getIndex(), TypeHelper.toClass(elementType)); } } if (List.class.equals(dataTypeClass)) { if (targetClass.isAssignableFrom(dataTypeClass)) { return new DatastaxListGetter(key.getIndex(), TypeHelper.toClass(elementType)); } } } else { Converter<?, ?> converter = getConverter(elementType, dataTypeElt, dtElt); if (converter != null) { if (Set.class.equals(dataTypeClass)) { if (targetClass.isAssignableFrom(dataTypeClass)) { return new DatastaxSetWithConverterGetter(key.getIndex(), dataTypeElt, converter); } } if (List.class.equals(dataTypeClass)) { if (targetClass.isAssignableFrom(dataTypeClass)) { return new DatastaxListWithConverterGetter(key.getIndex(), dataTypeElt, converter); } } } } } } if (Map.class.equals(targetClass)) { Tuple2<Type, Type> keyValueTypeOfMap = TypeHelper.getKeyValueTypeOfMap(target); Class<?> dtKeyType = null; Class<?> dtValueType = null; DataType dtKey = null; DataType dtValue = null; if (key.getDataType() != null) { List<DataType> typeArguments = key.getDataType().getTypeArguments(); if (typeArguments.size() == 2) { dtKey = typeArguments.get(0); dtKeyType = dtKey.asJavaClass(); dtValue = typeArguments.get(1); dtValueType = dtValue.asJavaClass(); } } else { dtKeyType = TypeHelper.toClass(keyValueTypeOfMap.first()); dtValueType = TypeHelper.toClass(keyValueTypeOfMap.second()); } if (dtKeyType != null && dtValueType != null) { if (TypeHelper.areEquals(keyValueTypeOfMap.first(), dtKeyType) && TypeHelper.areEquals(keyValueTypeOfMap.second(), dtValueType)) { return new DatastaxMapGetter( key.getIndex(), TypeHelper.toClass(keyValueTypeOfMap.first()), TypeHelper.toClass(keyValueTypeOfMap.second())); } else { Converter<?, ?> keyConverter = getConverter(keyValueTypeOfMap.first(), dtKeyType, dtKey); Converter<?, ?> valueConverter = getConverter(keyValueTypeOfMap.second(), dtValueType, dtValue); if (keyConverter != null && valueConverter != null) { return new DatastaxMapWithConverterGetter( key.getIndex(), dtKeyType, dtValueType, keyConverter, valueConverter); } } } } if (Tuples.isTuple(target)) { if (key.getDataType() != null && key.getDataType() instanceof TupleType) { TupleType tt = (TupleType) key.getDataType(); List<DataType> typeArguments = tt.getTypeArguments(); TypeVariable<? extends Class<?>>[] typeParameters = targetClass.getTypeParameters(); if (typeArguments.size() <= typeParameters.length) { return (Getter<GettableByIndexData, P>) DatastaxTupleGetter.newInstance(datastaxMapperFactory, target, tt, key.getIndex()); } } } if (TypeHelper.isEnum(target)) { final Getter<GettableByIndexData, ? extends Enum> getter = enumGetter(key, TypeHelper.toClass(target)); if (getter != null) { return (Getter<GettableByIndexData, P>) getter; } } final GetterFactory<GettableByIndexData, DatastaxColumnKey> rowGetterFactory = getterFactories.get(targetClass); if (rowGetterFactory != null) { return rowGetterFactory.newGetter(target, key, columnDefinition); } final Getter<GettableByIndexData, P> getter = jodaTimeGetterFactory.newGetter(target, key, columnDefinition); if (getter != null) { return getter; } if (key.getDataType() != null && key.getDataType() instanceof UserType) { UserType ut = (UserType) key.getDataType(); return (Getter<GettableByIndexData, P>) DatastaxUDTGetter.newInstance(datastaxMapperFactory, target, ut, key.getIndex()); } return null; }
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; }