code: protected List<Type> getGenericDeclarations(Class<?> ancestor, Class<?> descendant) {
  
      if (!ancestor.isAssignableFrom(descendant)) {
        return null;
      }
      List<Type> declarations = new ArrayList<>();
      if (ancestor != descendant) {
        Class<?> child = descendant;
        if (ancestor.isInterface()) {
          while (child != ancestor) {
            Class<?>[] interfaces = child.getInterfaces();
            Class<?> superInterface = null;
            for (int i = 0; i < interfaces.length; i++) {
              Class<?> currentInterface = interfaces[i];
              if (ancestor.isAssignableFrom(currentInterface)) {
                superInterface = currentInterface;
                Type genericDeclaration = child.getGenericInterfaces()[i];
                declarations.add(genericDeclaration);
                break;
              }
            }
            if (superInterface == null) {
              declarations.add(child.getGenericSuperclass());
              child = child.getSuperclass();
            } else {
              child = superInterface;
            }
          }
        } else {
          while (child != ancestor) {
            Type genericDeclaration = child.getGenericSuperclass();
            declarations.add(genericDeclaration);
            child = child.getSuperclass();
          }
        }
      }
      return declarations;
    }
docs: This method walks up the {@link Class}-hierarchy from {@code descendant} up to {@code ancestor} and
  collects the generic {@link Class#getGenericSuperclass() super-classes} or
  {@link Class#getGenericInterfaces() super-interfaces} of {@code ancestor} on that hierarchy-path. <br>
  Please note that if {@code ancestor} is an {@link Class#isInterface() interface}, the hierarchy may NOT
  be unique. In such case it will be unspecified which of the possible paths is used.
  
  @param ancestor is the super-class or super-interface of {@code descendant}.
  @param descendant is the sub-class or sub-interface of {@code ancestor}.
  @return the {@link List} of the generic super-{@link Type}s from {@code descendant} up to
  {@code ancestor}, where the first element represents the super-{@link Type} of {@code descendant}
  and the last element represents the generic declaration of {@code ancestor} itself.