class GenericParametersHelper {

    public static Class<?> getGenericTypeArgument(Class<?> classToParse, Class<?> genericClassToFind, Integer argumentIndex) {
        Class<?> result = null;
        ParameterizedType parameterizedType = null;
        Class<?> currentClass = classToParse;
        Map<String, Class<?>> currentParameterValues = new HashMap<String, Class<?>>();
        Type[] previousTypeArguments = null;
        while (parameterizedType == null) {
            final TypeVariable<? extends Class<?>>[] typeParameters = currentClass.getTypeParameters();
            currentParameterValues = getCurrentParameterValues(typeParameters, previousTypeArguments, currentParameterValues);
            parameterizedType = findParametrizedType(currentClass, genericClassToFind, currentParameterValues);
            if (parameterizedType == null) {
                // current class doesn't extend/implement searched class directly. Should parse superclass
                final Type genericSuperclassType = currentClass.getGenericSuperclass();
                if (genericSuperclassType instanceof Class<?>) {
                    log.debug(classToParse.getName() + " is raw subclass of " + genericClassToFind.getName());
                    return null;
                }
                final ParameterizedType genericSuperclass = (ParameterizedType) genericSuperclassType;
                previousTypeArguments = genericSuperclass.getActualTypeArguments();
                currentClass = (Class<?>) genericSuperclass.getRawType();
            }
        }
        final Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
        if (actualTypeArguments[argumentIndex] instanceof Class<?>) {
            result = (Class<?>) actualTypeArguments[argumentIndex];
        } else if (actualTypeArguments[argumentIndex] instanceof TypeVariable) {
            result = currentParameterValues.get(((TypeVariable<?>) actualTypeArguments[argumentIndex]).getName());
        } else if(actualTypeArguments[argumentIndex] instanceof ParameterizedType
                && ((ParameterizedType)actualTypeArguments[argumentIndex]).getRawType() instanceof Class){
            result = (Class<?>) ((ParameterizedType)actualTypeArguments[argumentIndex]).getRawType();
        }
        if (result == null) {
            log.debug("Class " + classToParse.getName() + " has unsupported inheritance structure");
        }
        return result;
    }

}