code: protected Type getGenericDeclaration(Class<?> ancestor, Class<?> descendant) {
  
      if (ancestor == descendant) {
        return null;
      }
      if (!ancestor.isAssignableFrom(descendant)) {
        return null;
      }
      Class<?> child = descendant;
      if (ancestor.isInterface()) {
        while (true) {
          Class<?>[] interfaces = child.getInterfaces();
          for (int i = 0; i < interfaces.length; i++) {
            Class<?> childInterface = interfaces[i];
            if (childInterface == ancestor) {
              return child.getGenericInterfaces()[i];
            } else if (ancestor.isAssignableFrom(childInterface)) {
              child = childInterface;
              break;
            }
          }
        }
      } else {
        Class<?> parent = child.getSuperclass();
        while (parent != ancestor) {
          child = parent;
          parent = child.getSuperclass();
        }
        return child.getGenericSuperclass();
      }
    }
docs: This method walks up the {@link Class}-hierarchy from {@code descendant} up to {@code ancestor} and returns the
  sub-class or sub-interface 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 sub-class or sub-interface on the hierarchy-path from {@code descendant} up to {@code ancestor}.