else mappedType = getMappedType(type, Collections.emptyMap()); return ((ParameterizedType) mappedType).getActualTypeArguments(); Map<String, Type> varMapping = createVariableMapping(type, rawType); if (targetType.isInterface()) { if (Collection.class.isAssignableFrom(interfaces[i])) { Type genericInterface = rawType.getGenericInterfaces()[i]; Type mappedInterface = getMappedType(genericInterface, varMapping); return getElementTypes(mappedInterface, interfaces[i], targetType); if (targetType.isAssignableFrom(rawSupertype)) { Type genericSuperclass = rawType.getGenericSuperclass(); Type mappedSuperclass = getMappedType(genericSuperclass, varMapping); return getElementTypes(mappedSuperclass, rawSupertype, targetType);
private static <T> Map<String, Type> createVariableMapping(Type type, Class<T> rawType) { if (type instanceof ParameterizedType) { TypeVariable<Class<T>>[] vars = rawType.getTypeParameters(); Type[] args = ((ParameterizedType) type).getActualTypeArguments(); Map<String, Type> newVarMapping = new HashMap<>(capacity(vars.length)); for (int i = 0; i < vars.length; i++) { Type actualType = Object.class; if (i < args.length) { actualType = args[i]; if (actualType instanceof WildcardType) actualType = ((WildcardType) actualType).getUpperBounds()[0]; } newVarMapping.put(vars[i].getName(), actualType); } return newVarMapping; } return Collections.emptyMap(); }
private static void collectExpectedTypes(Type type, Collection<Type> types) { if (isEither(type)) { if (type instanceof ParameterizedType) { for (Type typeArgument : ((ParameterizedType) type).getActualTypeArguments()) { collectExpectedTypes(typeArgument, types); } } if (type instanceof Class) { for (Type typeParameter : ((Class<?>) type).getTypeParameters()) { collectExpectedTypes(typeParameter, types); } } } else { types.add(type); } }
/** * Determine the actual type arguments of the given type token with regard to the given target type. */ public static Type[] getElementTypes(TypeToken<?> typeToken, Class<?> targetType) { return getElementTypes(typeToken.getType(), typeToken.getRawType(), targetType); }
/** * Test whether the given type is Either. */ public static boolean isEither(Type type) { if (type instanceof ParameterizedType) { return isEither(((ParameterizedType) type).getRawType()); } if (type instanceof Class) { return Either.class.isAssignableFrom((Class<?>) type); } return false; }
/** * Return all possible types that can be expected when an element of the given type is parsed. * If the type satisfies {@link #isEither(Type)}, a list of the corresponding type arguments is returned, * otherwise a list containg the type itself is returned. Type parameters are <em>not</em> resolved * by this method (use {@link #getElementTypes(TypeToken, Class)} to get resolved parameters). */ public static Collection<Type> getExpectedTypes(Type type) { Collection<Type> result = new ArrayList<>(); collectExpectedTypes(type, result); return result; }
@SuppressWarnings("unchecked") public EitherTypeArgument(Gson gson, Type type) { this.typeToken = (TypeToken<T>) TypeToken.get(type); this.adapter = gson.getAdapter(this.typeToken); this.expectedTokens = new HashSet<>(); for (Type expectedType : TypeUtils.getExpectedTypes(type)) { Class<?> rawType = TypeToken.get(expectedType).getRawType(); JsonToken expectedToken = getExpectedToken(rawType); expectedTokens.add(expectedToken); } }
private static Type getMappedType(Type type, Map<String, Type> varMapping) { if (type instanceof TypeVariable) { String name = ((TypeVariable<?>) type).getName(); if (varMapping.containsKey(name)) return varMapping.get(name); } if (type instanceof WildcardType) { return getMappedType(((WildcardType) type).getUpperBounds()[0], varMapping); } if (type instanceof ParameterizedType) { ParameterizedType pt = (ParameterizedType) type; Type[] origArgs = pt.getActualTypeArguments(); Type[] mappedArgs = new Type[origArgs.length]; for (int i = 0; i < origArgs.length; i++) { mappedArgs[i] = getMappedType(origArgs[i], varMapping); } return new ParameterizedTypeImpl(pt, mappedArgs); } return type; }
public EitherTypeAdapter(Gson gson, TypeToken<Either<L, R>> typeToken, Predicate<JsonElement> leftChecker, Predicate<JsonElement> rightChecker) { this.typeToken = typeToken; Type[] elementTypes = TypeUtils.getElementTypes(typeToken, Either.class); this.left = new EitherTypeArgument<L>(gson, elementTypes[0]); this.right = new EitherTypeArgument<R>(gson, elementTypes[1]); this.leftChecker = leftChecker; this.rightChecker = rightChecker; }
/** * Test whether the given type is Either. */ public static boolean isEither(Type type) { if (type instanceof ParameterizedType) { return isEither(((ParameterizedType) type).getRawType()); } if (type instanceof Class) { return Either.class.isAssignableFrom((Class<?>) type); } return false; }
/** * Return all possible types that can be expected when an element of the given type is parsed. * If the type satisfies {@link #isEither(Type)}, a list of the corresponding type arguments is returned, * otherwise a list containg the type itself is returned. Type parameters are <em>not</em> resolved * by this method (use {@link #getElementTypes(TypeToken, Class)} to get resolved parameters). */ public static Collection<Type> getExpectedTypes(Type type) { Collection<Type> result = new ArrayList<>(); collectExpectedTypes(type, result); return result; }
@SuppressWarnings("unchecked") public EitherTypeArgument(Gson gson, Type type) { this.typeToken = (TypeToken<T>) TypeToken.get(type); this.adapter = gson.getAdapter(this.typeToken); this.expectedTokens = new HashSet<>(); for (Type expectedType : TypeUtils.getExpectedTypes(type)) { Class<?> rawType = TypeToken.get(expectedType).getRawType(); JsonToken expectedToken = getExpectedToken(rawType); expectedTokens.add(expectedToken); } }
private static Type getMappedType(Type type, Map<String, Type> varMapping) { if (type instanceof TypeVariable) { String name = ((TypeVariable<?>) type).getName(); if (varMapping.containsKey(name)) return varMapping.get(name); } if (type instanceof WildcardType) { return getMappedType(((WildcardType) type).getUpperBounds()[0], varMapping); } if (type instanceof ParameterizedType) { ParameterizedType pt = (ParameterizedType) type; Type[] origArgs = pt.getActualTypeArguments(); Type[] mappedArgs = new Type[origArgs.length]; for (int i = 0; i < origArgs.length; i++) { mappedArgs[i] = getMappedType(origArgs[i], varMapping); } return new ParameterizedTypeImpl(pt, mappedArgs); } return type; }
else mappedType = getMappedType(type, Collections.emptyMap()); return ((ParameterizedType) mappedType).getActualTypeArguments(); Map<String, Type> varMapping = createVariableMapping(type, rawType); if (targetType.isInterface()) { if (Collection.class.isAssignableFrom(interfaces[i])) { Type genericInterface = rawType.getGenericInterfaces()[i]; Type mappedInterface = getMappedType(genericInterface, varMapping); return getElementTypes(mappedInterface, interfaces[i], targetType); if (targetType.isAssignableFrom(rawSupertype)) { Type genericSuperclass = rawType.getGenericSuperclass(); Type mappedSuperclass = getMappedType(genericSuperclass, varMapping); return getElementTypes(mappedSuperclass, rawSupertype, targetType);
/** * Determine the actual type arguments of the given type token with regard to the given target type. */ public static Type[] getElementTypes(TypeToken<?> typeToken, Class<?> targetType) { return getElementTypes(typeToken.getType(), typeToken.getRawType(), targetType); }
private static void collectExpectedTypes(Type type, Collection<Type> types) { if (isEither(type)) { if (type instanceof ParameterizedType) { for (Type typeArgument : ((ParameterizedType) type).getActualTypeArguments()) { collectExpectedTypes(typeArgument, types); } } if (type instanceof Class) { for (Type typeParameter : ((Class<?>) type).getTypeParameters()) { collectExpectedTypes(typeParameter, types); } } } else { types.add(type); } }
@SuppressWarnings({ "rawtypes", "unchecked" }) @Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) { if (!TypeUtils.isEither(typeToken.getType())) { return null; } return new EitherTypeAdapter(gson, typeToken); }
private static <T> Map<String, Type> createVariableMapping(Type type, Class<T> rawType) { if (type instanceof ParameterizedType) { TypeVariable<Class<T>>[] vars = rawType.getTypeParameters(); Type[] args = ((ParameterizedType) type).getActualTypeArguments(); Map<String, Type> newVarMapping = new HashMap<>(capacity(vars.length)); for (int i = 0; i < vars.length; i++) { Type actualType = Object.class; if (i < args.length) { actualType = args[i]; if (actualType instanceof WildcardType) actualType = ((WildcardType) actualType).getUpperBounds()[0]; } newVarMapping.put(vars[i].getName(), actualType); } return newVarMapping; } return Collections.emptyMap(); }
public EitherTypeAdapter(Gson gson, TypeToken<Either<L, R>> typeToken, Predicate<JsonElement> leftChecker, Predicate<JsonElement> rightChecker) { this.typeToken = typeToken; Type[] elementTypes = TypeUtils.getElementTypes(typeToken, Either.class); this.left = new EitherTypeArgument<L>(gson, elementTypes[0]); this.right = new EitherTypeArgument<R>(gson, elementTypes[1]); this.leftChecker = leftChecker; this.rightChecker = rightChecker; }
@SuppressWarnings({ "rawtypes", "unchecked" }) @Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) { if (!TypeUtils.isEither(typeToken.getType())) { return null; } return new EitherTypeAdapter(gson, typeToken); }