code: private static void populateTypeMapFromParameterizedType(ParameterizedType type, Map<Type, Type> typeVariableMap) {
      if (type.getRawType() instanceof Class) {
        Type[] actualTypeArguments = type.getActualTypeArguments();
        TypeVariable[] typeVariables = ((Class) type.getRawType()).getTypeParameters();
        for (int i = 0; i < actualTypeArguments.length; i++) {
          Type actualTypeArgument = actualTypeArguments[i];
          TypeVariable variable = typeVariables[i];
          if (actualTypeArgument instanceof Class) {
            typeVariableMap.put(variable, actualTypeArgument);
          } else if (actualTypeArgument instanceof GenericArrayType) {
            typeVariableMap.put(variable, actualTypeArgument);
          } else if (actualTypeArgument instanceof ParameterizedType) {
            typeVariableMap.put(variable, actualTypeArgument);
          } else if (actualTypeArgument instanceof TypeVariable) {
            // We have a type that is parameterized at instantiation time
            // the nearest match on the bridge method will be the bounded type.
            TypeVariable typeVariableArgument = (TypeVariable) actualTypeArgument;
            Type resolvedType = typeVariableMap.get(typeVariableArgument);
            if (resolvedType == null) {
              resolvedType = extractBoundForTypeVariable(typeVariableArgument);
            }
            typeVariableMap.put(variable, resolvedType);
          }
        }
      }
    }
docs: Read the {@link TypeVariable TypeVariables} from the supplied {@link
  ParameterizedType} and add mappings corresponding to the {@link TypeVariable#getName
  TypeVariable name} -> concrete type to the supplied {@link Map}.
  <p/>
  Consider this case:
  <p/>
  <pre class="code> public interface Foo&lt;S, T&gt; { .. } public class FooImpl
  implements Foo&lt;String, Integer&gt; { .. } </pre>
  <p/>
  For '<code>FooImpl' the following mappings would be added to the {@link Map}:
  {S=java.lang.String, T=java.lang.Integer}.