class FailureHandler {

    private static final Map<Class<? extends Throwable>, Function<Throwable, ? extends RuntimeException>> FAILURE_CONVERTER = new HashMap<>();
    static {
        FAILURE_CONVERTER.put(UnsolvedSymbolException.class,
                (Throwable th) -> (RuntimeException)th);
    }

    public RuntimeException handle(Throwable th) {
        return handle(th, null);
    }
                                   
    public RuntimeException handle(Throwable th, String message) {
        // searching for exact mapping
        Function<Throwable, ? extends RuntimeException> converter = FAILURE_CONVERTER.get(findRootCause(th).getClass());
        if (converter != null) {
            return converter.apply(th);
        }
        // handle runtime exceptions
        if (RuntimeException.class.isAssignableFrom(th.getClass())) {
            return (RuntimeException) th;
        }
        return getRuntimeExceptionFrom(findRootCause(th), message);
    }

    protected final <E extends Throwable> E findRootCause(Throwable failure) {
        while (failure != null) {
            if (isRootCause(failure)) {
                return (E) failure;
            }
            failure = failure.getCause();
        }
        return null;
    }

    private boolean isRootCause(Throwable th) {
        return th.getCause() == null;
    }
    
    private RuntimeException getRuntimeExceptionFrom(Throwable th, String message) {<FILL_FUNCTION_BODY>}

}

        if (message == null || message.isEmpty())
            return new RuntimeException(findRootCause(th));
        return new RuntimeException(message, findRootCause(th));
    
<no_super_class>