/*
  * Filter elements to avoid having files of directory traces listed as
  * separate traces.
  */
 private void filterElements(TracePackageElement parentElement) {
   for (TracePackageElement childElement : parentElement.getChildren()) {
     filterElements(childElement);
     if (childElement instanceof TracePackageTraceElement) {
       // no need to do length check here
       RemoteImportTraceFilesElement filesElement =
           (RemoteImportTraceFilesElement) childElement.getChildren()[0];
       IFileStore parentFile = filesElement.getRemoteFile().getParent();
       if (fDirectoryTraces.contains(
           TmfTraceCoreUtils.newSafePath(parentFile.toURI().getPath()))) {
         removeChild(childElement, parentElement);
         continue;
       }
       IFileStore grandParentFile = parentFile.getParent();
       if (grandParentFile != null
           && fDirectoryTraces.contains(
               TmfTraceCoreUtils.newSafePath(grandParentFile.toURI().getPath()))) {
         // ignore file if grandparent is a directory trace
         // for example: file is a index file of a LTTng kernel trace
         parentElement.removeChild(childElement);
         if (parentElement.getChildren().length == 0) {
           TracePackageElement grandParentElement = parentElement.getParent();
           removeChild(parentElement, grandParentElement);
         }
         continue;
       }
     } else if (childElement instanceof RemoteImportFolderElement) {
       if (childElement.getChildren().length == 0) {
         parentElement.removeChild(childElement);
       }
     }
   }
 }
 /**
  * This method takes the auto-detection case into consideration.
  *
  * <p>{@inheritDoc}
  */
 @Override
 protected boolean matchesDirectoryTrace(
     IPath archivePath, Entry<Pattern, TracePackageTraceElement> entry) {
   if (METADATA_FILE_NAME.equals(archivePath.lastSegment())) {
     IPath archiveParentPath = archivePath.removeLastSegments(1);
     String parentPathString = TmfTraceCoreUtils.safePathToString(archiveParentPath.toString());
     if (entry.getKey().matcher(parentPathString).matches()) {
       String traceType = entry.getValue().getTraceType();
       // empty string is for auto-detection
       if (traceType.isEmpty() || TmfTraceType.isDirectoryTraceType(traceType)) {
         return true;
       }
     }
   }
   return false;
 }
  /**
   * This method takes the auto-detection case into consideration.
   *
   * <p>{@inheritDoc}
   */
  @Override
  protected Entry<Pattern, TracePackageTraceElement> getMatchingTemplateElement(
      IPath fullArchivePath) {
    for (Entry<Pattern, TracePackageTraceElement> entry :
        fTemplatePatternsToTraceElements.entrySet()) {
      // Check for CTF trace (metadata)
      String traceType = entry.getValue().getTraceType();
      // empty string is for auto-detection
      if ((traceType.isEmpty() || TmfTraceType.isDirectoryTraceType(traceType))
          && (matchesDirectoryTrace(fullArchivePath, entry))) {
        return entry;
      } else if (entry
          .getKey()
          .matcher(TmfTraceCoreUtils.safePathToString(fullArchivePath.toString()))
          .matches()) {
        return entry;
      }
    }

    return null;
  }
  /**
   * Scan traceFolder for files that match the patterns specified in the template file. When there
   * is a match, the trace package element is used to determine the trace name and trace type.
   *
   * @param traceGroup The parent trace group element
   * @param parentElement The immediate parent trace group or folder element
   * @param traceFolder The folder to scan
   * @param recursionLevel The recursion level (needed to find directory traces under the
   *     traceFolder
   * @param monitor The progress monitor
   * @throws CoreException Thrown by the file system implementation
   * @throws InterruptedException Thrown if operation was cancelled
   */
  private void generateElementsFromArchive(
      final RemoteImportTraceGroupElement traceGroup,
      final TracePackageElement parentElement,
      final IFileStore traceFolder,
      final int recursionLevel,
      IProgressMonitor monitor)
      throws CoreException, InterruptedException {

    int localRecursionLevel = recursionLevel + 1;
    IFileStore[] sources = traceFolder.childStores(EFS.NONE, monitor);

    for (int i = 0; i < sources.length; i++) {
      ModalContext.checkCanceled(monitor);
      SubMonitor subMonitor = SubMonitor.convert(monitor, sources.length);

      IFileStore fileStore = sources[i];
      IPath fullArchivePath = TmfTraceCoreUtils.newSafePath(fileStore.toURI().getPath());

      IFileInfo sourceInfo = fileStore.fetchInfo();
      if (!sourceInfo.isDirectory()) {

        String rootPathString = traceGroup.getRootImportPath();
        IPath rootPath = TmfTraceCoreUtils.newSafePath(rootPathString);
        IPath relativeTracePath = Path.EMPTY;
        if (rootPath.isPrefixOf(fullArchivePath)) {
          relativeTracePath = fullArchivePath.makeRelativeTo(rootPath);
        }
        Entry<Pattern, TracePackageTraceElement> matchingTemplateEntry =
            getMatchingTemplateElement(relativeTracePath);
        if (matchingTemplateEntry != null) {
          TracePackageTraceElement matchingTemplateElement = matchingTemplateEntry.getValue();
          String traceType = matchingTemplateElement.getTraceType();

          // If a single file is part of a directory trace, use the parent directory instead
          TracePackageElement parent = parentElement;
          if (matchesDirectoryTrace(relativeTracePath, matchingTemplateEntry)) {
            fullArchivePath = fullArchivePath.removeLastSegments(1);
            fDirectoryTraces.add(fullArchivePath);
            fileStore = fileStore.getParent();
            parent = parentElement.getParent();
            // Let the auto-detection choose the best trace type
            traceType = null;
          } else if ((localRecursionLevel > 1) && (!traceGroup.isRecursive())) {
            // Don't consider file traces on level 2 if it's not recursive
            continue;
          }
          String traceName = fullArchivePath.lastSegment();
          String fileName = fileStore.getName();
          // create new elements to decouple from input elements
          TracePackageTraceElement traceElement =
              new TracePackageTraceElement(parent, traceName, traceType);
          RemoteImportTraceFilesElement tracePackageFilesElement =
              new RemoteImportTraceFilesElement(traceElement, fileName, fileStore);
          tracePackageFilesElement.setVisible(false);
        }
      } else {
        if (traceGroup.isRecursive() || localRecursionLevel < 2) {
          RemoteImportFolderElement folder =
              new RemoteImportFolderElement(parentElement, fileStore.getName());
          generateElementsFromArchive(
              traceGroup, folder, fileStore, localRecursionLevel, subMonitor);
        }
      }
    }
  }