public static Map getTypeParameters()

in wayang-commons/wayang-core/src/main/java/org/apache/wayang/core/util/ReflectionUtils.java [345:394]


    public static Map<String, Type> getTypeParameters(Class<?> subclass, Class<?> superclass) {
        // Gather implemented interfaces and superclass.
        List<Type> genericSupertypes = Stream.concat(
                Stream.of(subclass.getGenericSuperclass()), Stream.of(subclass.getGenericInterfaces())
        ).collect(Collectors.toList());

        for (Type supertype : genericSupertypes) {

            if (supertype instanceof Class<?>) {
                // If the supertype is a Class, there are no type parameters to worry about.
                Class<?> cls = (Class<?>) supertype;
                if (!superclass.isAssignableFrom(cls)) continue;
                return getTypeParameters(cls, superclass);

            } else if (supertype instanceof ParameterizedType) {
                // Handle type parameters.
                ParameterizedType parameterizedType = (ParameterizedType) supertype;
                final Type rawType = parameterizedType.getRawType();
                if (!(rawType instanceof Class<?>)) continue;
                Class<?> cls = (Class<?>) rawType;
                if (!superclass.isAssignableFrom(cls)) continue;
                final Map<String, Type> localTypeArguments = getTypeArguments(parameterizedType);

                if (cls.equals(superclass)) {
                    // If we reached the superclass, we are good.
                    return localTypeArguments;

                } else {
                    // If we are not there yet, we need to consider to "redirect" type parameters.
                    final Map<String, Type> preliminaryResult = getTypeParameters(cls, superclass);
                    final Map<String, Type> result = new HashMap<>(preliminaryResult.size());
                    for (Map.Entry<String, Type> entry : preliminaryResult.entrySet()) {
                        if (entry.getValue() instanceof TypeVariable<?>) {
                            final Type translatedTypeArgument = localTypeArguments.getOrDefault(
                                    ((TypeVariable) entry.getValue()).getName(),
                                    entry.getValue()
                            );
                            result.put(entry.getKey(), translatedTypeArgument);
                        } else {
                            result.put(entry.getKey(), entry.getValue());
                        }
                    }
                    return result;

                }
            }
        }

        return Collections.emptyMap();
    }