/**
   * 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$
    }
  }
  /**
   * Returns an internal folder to store all files deleted from a given folder. Provides fast access
   * when searching for files deleted from a given folder.
   */
  private Node legacyGetTrashFolderIdNode(
      final Session session,
      final PentahoJcrConstants pentahoJcrConstants,
      final String origParentFolderPath)
      throws RepositoryException {

    // get folder id
    String folderId = null;
    if (session.itemExists(origParentFolderPath)) {
      folderId = ((Node) session.getItem(origParentFolderPath)).getIdentifier();
    } else {
      throw new RuntimeException(
          Messages.getInstance()
              .getString("DefaultDeleteHelper.ERROR_0001_PATH_NOT_FOUND")); // $NON-NLS-1$
    }

    final String prefix = session.getNamespacePrefix(PentahoJcrConstants.PHO_NS) + ":";
    Node trashInternalFolderNode = getOrCreateTrashInternalFolderNode(session, pentahoJcrConstants);
    if (NodeHelper.hasNode(trashInternalFolderNode, prefix, folderId)) {
      return NodeHelper.getNode(trashInternalFolderNode, prefix, folderId);
    } else {
      // if Trash Structure 1 (legacy) doesn't exist, no need to create it now
      return null;
    }
  }
 public RepositoryFile getFile(final String path, final boolean loadLocaleMaps) {
   return callLogThrow(
       new Callable<RepositoryFile>() {
         public RepositoryFile call() throws Exception {
           return delegatee.getFile(path, loadLocaleMaps);
         }
       },
       Messages.getInstance().getString("ExceptionLoggingDecorator.getFile", path)); // $NON-NLS-1$
 }
 public List<RepositoryFile> getReferrers(final Serializable fileId) {
   return callLogThrow(
       new Callable<List<RepositoryFile>>() {
         public List<RepositoryFile> call() throws Exception {
           return delegatee.getReferrers(fileId);
         }
       },
       Messages.getInstance()
           .getString("ExceptionLoggingDecorator.getReferrers", fileId)); // $NON-NLS-1$
 }
 public boolean hasAccess(final String path, final EnumSet<RepositoryFilePermission> permissions) {
   return callLogThrow(
       new Callable<Boolean>() {
         public Boolean call() throws Exception {
           return delegatee.hasAccess(path, permissions);
         }
       },
       Messages.getInstance()
           .getString("ExceptionLoggingDecorator.hasAccess", path)); // $NON-NLS-1$
 }
 public Map<String, Serializable> getFileMetadata(final Serializable fileId) {
   return callLogThrow(
       new Callable<Map<String, Serializable>>() {
         public Map<String, Serializable> call() throws Exception {
           return delegatee.getFileMetadata(fileId);
         }
       },
       Messages.getInstance()
           .getString("ExceptionLoggingDecorator.getFileMetadata", fileId)); // $NON-NLS-1$
 }
 public List<VersionSummary> getVersionSummaries(final Serializable fileId) {
   return callLogThrow(
       new Callable<List<VersionSummary>>() {
         public List<VersionSummary> call() throws Exception {
           return delegatee.getVersionSummaries(fileId);
         }
       },
       Messages.getInstance()
           .getString("ExceptionLoggingDecorator.getVersionSummaries", fileId)); // $NON-NLS-1$
 }
 public List<VersionSummary> getVersionSummaryInBatch(final List<RepositoryFile> files) {
   return callLogThrow(
       new Callable<List<VersionSummary>>() {
         public List<VersionSummary> call() throws Exception {
           return delegatee.getVersionSummaryInBatch(files);
         }
       },
       Messages.getInstance()
           .getString("ExceptionLoggingDecorator.getVersionSummaryInBatch")); // $NON-NLS-1$
 }
 public RepositoryFile getFileById(final Serializable fileId) {
   return callLogThrow(
       new Callable<RepositoryFile>() {
         public RepositoryFile call() throws Exception {
           return delegatee.getFileById(fileId);
         }
       },
       Messages.getInstance()
           .getString("ExceptionLoggingDecorator.getFileById", fileId)); // $NON-NLS-1$
 }
 public List<Character> getReservedChars() {
   return callLogThrow(
       new Callable<List<Character>>() {
         public List<Character> call() throws Exception {
           return delegatee.getReservedChars();
         }
       },
       Messages.getInstance()
           .getString("ExceptionLoggingDecorator.getReservedChars")); // $NON-NLS-1$
 }
 public List<RepositoryFile> getDeletedFiles() {
   return callLogThrow(
       new Callable<List<RepositoryFile>>() {
         public List<RepositoryFile> call() throws Exception {
           return delegatee.getDeletedFiles();
         }
       },
       Messages.getInstance()
           .getString("ExceptionLoggingDecorator.getDeletedFiles")); // $NON-NLS-1$
 }
 public RepositoryFileTree getTree(
     final String path, final int depth, final String filter, final boolean showHidden) {
   return callLogThrow(
       new Callable<RepositoryFileTree>() {
         public RepositoryFileTree call() throws Exception {
           return delegatee.getTree(path, depth, filter, showHidden);
         }
       },
       Messages.getInstance().getString("ExceptionLoggingDecorator.getTree", path)); // $NON-NLS-1$
 }
 public boolean canUnlockFile(final Serializable fileId) {
   return callLogThrow(
       new Callable<Boolean>() {
         public Boolean call() throws Exception {
           return delegatee.canUnlockFile(fileId);
         }
       },
       Messages.getInstance()
           .getString("ExceptionLoggingDecorator.canUnlockFile", fileId)); // $NON-NLS-1$
 }
 public List<RepositoryFile> getChildren(final Serializable folderId, final String filter) {
   return callLogThrow(
       new Callable<List<RepositoryFile>>() {
         public List<RepositoryFile> call() throws Exception {
           return delegatee.getChildren(folderId, filter);
         }
       },
       Messages.getInstance()
           .getString("ExceptionLoggingDecorator.getChildren", folderId)); // $NON-NLS-1$
 }
 public List<RepositoryFileAce> getEffectiveAces(
     final Serializable fileId, final boolean forceEntriesInheriting) {
   return callLogThrow(
       new Callable<List<RepositoryFileAce>>() {
         public List<RepositoryFileAce> call() throws Exception {
           return delegatee.getEffectiveAces(fileId, forceEntriesInheriting);
         }
       },
       Messages.getInstance()
           .getString("ExceptionLoggingDecorator.getEffectiveAces", fileId)); // $NON-NLS-1$
 }
 public <T extends IRepositoryFileData> List<T> getDataForReadInBatch(
     final List<RepositoryFile> files, final Class<T> dataClass) {
   return callLogThrow(
       new Callable<List<T>>() {
         public List<T> call() throws Exception {
           return delegatee.getDataForReadInBatch(files, dataClass);
         }
       },
       Messages.getInstance()
           .getString("ExceptionLoggingDecorator.getDataInBatch")); // $NON-NLS-1$
 }
 public <T extends IRepositoryFileData> T getDataForRead(
     final Serializable fileId, final Class<T> dataClass) {
   return callLogThrow(
       new Callable<T>() {
         public T call() throws Exception {
           return delegatee.getDataForRead(fileId, dataClass);
         }
       },
       Messages.getInstance()
           .getString("ExceptionLoggingDecorator.getData", fileId)); // $NON-NLS-1$
 }
 public void unlockFile(final Serializable fileId) {
   callLogThrow(
       new Callable<Void>() {
         public Void call() throws Exception {
           delegatee.unlockFile(fileId);
           return null;
         }
       },
       Messages.getInstance()
           .getString("ExceptionLoggingDecorator.unlockFile", fileId)); // $NON-NLS-1$
 }
 public RepositoryFile createFolder(
     final Serializable parentFolderId, final RepositoryFile file, final String versionMessage) {
   return callLogThrow(
       new Callable<RepositoryFile>() {
         public RepositoryFile call() throws Exception {
           return delegatee.createFolder(parentFolderId, file, versionMessage);
         }
       },
       Messages.getInstance()
           .getString("ExceptionLoggingDecorator.createFolder", file.getName())); // $NON-NLS-1$
 }
 public void deleteFile(
     final Serializable fileId, final boolean permanent, final String versionMessage) {
   callLogThrow(
       new Callable<Void>() {
         public Void call() throws Exception {
           delegatee.deleteFile(fileId, permanent, versionMessage);
           return null;
         }
       },
       Messages.getInstance()
           .getString("ExceptionLoggingDecorator.deleteFile", fileId)); // $NON-NLS-1$
 }
 @Override
 public List<Locale> getAvailableLocalesForFileByPath(final String relPath) {
   return callLogThrow(
       new Callable<List<Locale>>() {
         public List<Locale> call() throws Exception {
           return delegatee.getAvailableLocalesForFileByPath(relPath);
         }
       },
       Messages.getInstance()
           .getString(
               "ExceptionLoggingDecorator.getAvailableLocalesForFile", relPath)); // $NON-NLS-1$
 }
 @Override
 public Properties getLocalePropertiesForFileByPath(final String relPath, final String locale) {
   return callLogThrow(
       new Callable<Properties>() {
         public Properties call() throws Exception {
           return delegatee.getLocalePropertiesForFileByPath(relPath, locale);
         }
       },
       Messages.getInstance()
           .getString(
               "ExceptionLoggingDecorator.getLocalePropertiesForFile", relPath)); // $NON-NLS-1$
 }
 @Override
 public RepositoryFile getFileById(
     final Serializable fileId, final boolean loadLocaleMaps, final IPentahoLocale locale) {
   return callLogThrow(
       new Callable<RepositoryFile>() {
         public RepositoryFile call() throws Exception {
           return delegatee.getFileById(fileId, loadLocaleMaps, locale);
         }
       },
       Messages.getInstance()
           .getString("ExceptionLoggingDecorator.getFileById", fileId)); // $NON-NLS-1$
 }
 public List<RepositoryFile> getDeletedFiles(final String origParentFolderPath) {
   return callLogThrow(
       new Callable<List<RepositoryFile>>() {
         public List<RepositoryFile> call() throws Exception {
           return delegatee.getDeletedFiles(origParentFolderPath);
         }
       },
       Messages.getInstance()
           .getString(
               "ExceptionLoggingDecorator.getDeletedFilesInFolder",
               origParentFolderPath)); //$NON-NLS-1$
 }
 public void copyFile(
     final Serializable fileId, final String destAbsPath, final String versionMessage) {
   callLogThrow(
       new Callable<Void>() {
         public Void call() throws Exception {
           delegatee.copyFile(fileId, destAbsPath, versionMessage);
           return null;
         }
       },
       Messages.getInstance()
           .getString("ExceptionLoggingDecorator.copyFile", fileId, destAbsPath)); // $NON-NLS-1$
 }
 public void deleteFileAtVersion(final Serializable fileId, final Serializable versionId) {
   callLogThrow(
       new Callable<Void>() {
         public Void call() throws Exception {
           delegatee.deleteFileAtVersion(fileId, versionId);
           return null;
         }
       },
       Messages.getInstance()
           .getString(
               "ExceptionLoggingDecorator.deleteFileAtVersion", fileId, versionId)); // $NON-NLS-1$
 }
 public RepositoryFileAcl updateAcl(final RepositoryFileAcl acl) {
   return callLogThrow(
       new Callable<RepositoryFileAcl>() {
         public RepositoryFileAcl call() throws Exception {
           return delegatee.updateAcl(acl);
         }
       },
       Messages.getInstance()
           .getString(
               "ExceptionLoggingDecorator.updateAcl",
               acl != null ? acl.getId() : null)); // $NON-NLS-1$
 }
 @Override
 public RepositoryFile updateFolder(final RepositoryFile folder, final String versionMessage) {
   return callLogThrow(
       new Callable<RepositoryFile>() {
         public RepositoryFile call() throws Exception {
           return delegatee.updateFolder(folder, versionMessage);
         }
       },
       Messages.getInstance()
           .getString(
               "ExceptionLoggingDecorator.updateFile",
               folder != null ? folder.getId() : null)); // $NON-NLS-1$
 }
 public void setFileMetadata(
     final Serializable fileId, final Map<String, Serializable> metadataMap) {
   callLogThrow(
       new Callable<Void>() {
         public Void call() throws Exception {
           delegatee.setFileMetadata(fileId, metadataMap);
           return null;
         }
       },
       Messages.getInstance()
           .getString(
               "ExceptionLoggingDecorator.setFileMetadata", fileId, metadataMap)); // $NON-NLS-1$
 }
 public RepositoryFile updateFile(
     final RepositoryFile file, final IRepositoryFileData data, final String versionMessage) {
   return callLogThrow(
       new Callable<RepositoryFile>() {
         public RepositoryFile call() throws Exception {
           return delegatee.updateFile(file, data, versionMessage);
         }
       },
       Messages.getInstance()
           .getString(
               "ExceptionLoggingDecorator.updateFile",
               file != null ? file.getId() : null)); // $NON-NLS-1$
 }