/**
   * Calls the Callable and returns the value it returns. If an exception occurs, it is logged and a
   * new non-chained exception is thrown.
   *
   * @param <T> return type
   * @param callable code to call
   * @param message verbose description of operation
   * @return return value of Callable
   */
  private <T> T callLogThrow(final Callable<T> callable, final String message) {
    try {
      return callable.call();
    } catch (Exception e) {
      // generate reference #
      String refNum = UUID.randomUUID().toString();
      if (logger.isDebugEnabled()) {
        logger.debug(
            Messages.getInstance().getString("ExceptionLoggingDecorator.referenceNumber", refNum),
            e); //$NON-NLS-1$
      }

      // list all exceptions in stack
      @SuppressWarnings("unchecked")
      List<Throwable> throwablesInStack = ExceptionUtils.getThrowableList(e);
      // reverse them so most specific exception (root cause) comes first
      Collections.reverse(throwablesInStack);

      for (Throwable t : throwablesInStack) {
        String className = t.getClass().getName();
        if (exceptionConverterMap.containsKey(className)) {
          throw exceptionConverterMap
              .get(className)
              .convertException((Exception) t, message, refNum);
        }
      }

      // no converter; throw general exception
      throw new UnifiedRepositoryException(
          Messages.getInstance()
              .getString(
                  "ExceptionLoggingDecorator.generalException", message, refNum)); // $NON-NLS-1$
    }
  }