private static int indexOfCause(Throwable parent, Class<? extends Throwable> causeClass,
      final int cindex, final boolean isSubtypeOk) {
    int resultIndex = cindex;
    Throwable cause = parent.getCause();

    // (cause is not null & cause is not of type causeClass)
    if (cause != null && !isMatching(cause, causeClass, isSubtypeOk)) {
      // recurse deeper
      resultIndex = indexOfCause(cause, causeClass, cindex + 1, isSubtypeOk);
    } else if (cause != null && isMatching(cause, causeClass, isSubtypeOk)) {
      resultIndex = cindex != -1 ? cindex + 1 : cindex;
    } else if (cause == null) {
      resultIndex = -1;
    }

    return resultIndex;
  }
Returns the index of a first nested cause which is of the given Throwable type or its sub-type
depending on <code>isSubtypeOk</code> value.
<p />
NOTE: It looks for the "nested" causes & doesn't try to match the <code>causeClass</code> of
the <code>parent</code>.
<p />

Returns -1 if a cause with the given Throwable type is not found.

@param parent parent Throwable instance
@param causeClass type of the nested Throwable cause
@param cindex variable to store current index/depth of the cause
@param isSubtypeOk whether any matching sub-type is required or exact match is required
@return index/depth of the cause starting from the 'top most' Throwable in the stack. -1 if
        can't find it.
geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/util/CauseFinder.java