From 34de8e3ff4872c7e48e78d1fa102aa029ac2b261 Mon Sep 17 00:00:00 2001
From: Kai Reinhard <K.Reinhard@micromata.de>
Date: Fri, 28 Dec 2018 02:10:33 +0000
Subject: [PATCH] It's a long way, but is it also useful?

---
 borgbutler-server/src/main/java/de/micromata/borgbutler/server/Main.java                  |    6 
 borgbutler-core/src/main/java/de/micromata/borgbutler/BorgCommands.java                   |    5 
 borgbutler-core/src/test/java/de/micromata/borgbutler/cache/FilesystemTest.java           |   34 ++
 borgbutler-core/src/test/java/de/micromata/borgbutler/cache/CacheTest.java                |    3 
 borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/ArchivesRest.java     |   10 
 borgbutler-core/src/test/java/de/micromata/borgbutler/data/FileSystemFilterTest.java      |   21 
 borgbutler-core/src/main/java/de/micromata/borgbutler/cache/Filesystem.java               |   25 +
 borgbutler-core/src/test/java/de/micromata/borgbutler/DiffToolTest.java                   |   84 +++---
 borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ArchiveFilelistCache.java     |   22 
 borgbutler-core/src/test/java/de/micromata/borgbutler/cache/ArchiveFilelistCacheTest.java |   21 
 borgbutler-core/src/main/java/de/micromata/borgbutler/json/borg/BorgFilesystemItem.java   |  160 ----------
 borgbutler-core/src/main/java/de/micromata/borgbutler/DiffTool.java                       |   28 +-
 borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ButlerCache.java              |   28 -
 borgbutler-core/src/main/java/de/micromata/borgbutler/cache/FilesystemItem.java           |  187 +++++++++++++
 borgbutler-core/src/main/java/de/micromata/borgbutler/data/FileSystemFilter.java          |  153 ++++------
 15 files changed, 430 insertions(+), 357 deletions(-)

diff --git a/borgbutler-core/src/main/java/de/micromata/borgbutler/BorgCommands.java b/borgbutler-core/src/main/java/de/micromata/borgbutler/BorgCommands.java
index 3599d83..2332fcd 100644
--- a/borgbutler-core/src/main/java/de/micromata/borgbutler/BorgCommands.java
+++ b/borgbutler-core/src/main/java/de/micromata/borgbutler/BorgCommands.java
@@ -1,5 +1,6 @@
 package de.micromata.borgbutler;
 
+import de.micromata.borgbutler.cache.FilesystemItem;
 import de.micromata.borgbutler.config.BorgRepoConfig;
 import de.micromata.borgbutler.data.Archive;
 import de.micromata.borgbutler.data.Repository;
@@ -16,7 +17,6 @@
 import java.io.IOException;
 import java.time.LocalDateTime;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.List;
 import java.util.Scanner;
 
@@ -178,12 +178,11 @@
         try (Scanner scanner = new Scanner(command.getResponse())) {
             while (scanner.hasNextLine()) {
                 String json = scanner.nextLine();
-                BorgFilesystemItem item = JsonUtils.fromJson(BorgFilesystemItem.class, json);
+                FilesystemItem item = JsonUtils.fromJson(FilesystemItem.class, json);
                 item.setMtime(DateUtils.format(item.getMtime()));
                 content.add(item);
             }
         }
-        Collections.sort(content); // Sort by path.
         return content;
     }
 
diff --git a/borgbutler-core/src/main/java/de/micromata/borgbutler/DiffTool.java b/borgbutler-core/src/main/java/de/micromata/borgbutler/DiffTool.java
index a0a16a1..6dc9692 100644
--- a/borgbutler-core/src/main/java/de/micromata/borgbutler/DiffTool.java
+++ b/borgbutler-core/src/main/java/de/micromata/borgbutler/DiffTool.java
@@ -1,6 +1,6 @@
 package de.micromata.borgbutler;
 
-import de.micromata.borgbutler.json.borg.BorgFilesystemItem;
+import de.micromata.borgbutler.cache.FilesystemItem;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -19,14 +19,14 @@
      * @param otherItems Sorted list of items of the archive to extract differences.
      * @return A list of differing items (new, removed and modified ones).
      */
-    public static List<BorgFilesystemItem> extractDifferences(List<BorgFilesystemItem> items, List<BorgFilesystemItem> otherItems) {
-        List<BorgFilesystemItem> currentList = items != null ? items : new ArrayList<>();
-        List<BorgFilesystemItem> otherList = otherItems != null ? otherItems : new ArrayList<>();
-        List<BorgFilesystemItem> result = new ArrayList<>();
-        Iterator<BorgFilesystemItem> currentIt = currentList.iterator();
-        Iterator<BorgFilesystemItem> otherIt = otherList.iterator();
-        BorgFilesystemItem current = null;
-        BorgFilesystemItem other = null;
+    public static List<FilesystemItem> extractDifferences(List<FilesystemItem> items, List<FilesystemItem> otherItems) {
+        List<FilesystemItem> currentList = items != null ? items : new ArrayList<>();
+        List<FilesystemItem> otherList = otherItems != null ? otherItems : new ArrayList<>();
+        List<FilesystemItem> result = new ArrayList<>();
+        Iterator<FilesystemItem> currentIt = currentList.iterator();
+        Iterator<FilesystemItem> otherIt = otherList.iterator();
+        FilesystemItem current = null;
+        FilesystemItem other = null;
         while (true) {
             if (current == null && currentIt.hasNext())
                 current = currentIt.next();
@@ -42,25 +42,25 @@
                     continue;
                 }
                 // Current entry differs:
-                current.setDiffStatus(BorgFilesystemItem.DiffStatus.MODIFIED);
+                current.setDiffStatus(FilesystemItem.DiffStatus.MODIFIED);
                 current.setDiffItem(other);
                 current.buildDifferencesString();
                 result.add(current);
                 current = other = null; // increment both iterators.
             } else if (cmp < 0) {
-                result.add(current.setDiffStatus(BorgFilesystemItem.DiffStatus.NEW));
+                result.add(current.setDiffStatus(FilesystemItem.DiffStatus.NEW));
                 current = currentIt.hasNext() ? currentIt.next() : null;
             } else {
-                result.add(other.setDiffStatus(BorgFilesystemItem.DiffStatus.REMOVED));
+                result.add(other.setDiffStatus(FilesystemItem.DiffStatus.REMOVED));
                 other = otherIt.hasNext() ? otherIt.next() : null;
             }
         }
         while (current != null) {
-            result.add(current.setDiffStatus(BorgFilesystemItem.DiffStatus.NEW));
+            result.add(current.setDiffStatus(FilesystemItem.DiffStatus.NEW));
             current = currentIt.hasNext() ? currentIt.next() : null;
         }
         while (other != null) {
-            result.add(other.setDiffStatus(BorgFilesystemItem.DiffStatus.REMOVED));
+            result.add(other.setDiffStatus(FilesystemItem.DiffStatus.REMOVED));
             other = otherIt.hasNext() ? otherIt.next() : null;
         }
         return result;
diff --git a/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ArchiveFilelistCache.java b/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ArchiveFilelistCache.java
index 5e06d74..6be9b6e 100644
--- a/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ArchiveFilelistCache.java
+++ b/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ArchiveFilelistCache.java
@@ -4,9 +4,7 @@
 import de.micromata.borgbutler.data.Archive;
 import de.micromata.borgbutler.data.FileSystemFilter;
 import de.micromata.borgbutler.data.Repository;
-import de.micromata.borgbutler.json.borg.BorgFilesystemItem;
 import de.micromata.borgbutler.utils.ReplaceUtils;
-import lombok.Getter;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
 import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream;
@@ -31,7 +29,7 @@
     private int cacheArchiveContentMaxDiscSizeMB;
     private long FILES_EXPIRE_TIME = 7 * 24 * 3660 * 1000; // Expires after 7 days.
 
-    public void save(BorgRepoConfig repoConfig, Archive archive, List<BorgFilesystemItem> filesystemItems) {
+    public void save(BorgRepoConfig repoConfig, Archive archive, List<FilesystemItem> filesystemItems) {
         if (CollectionUtils.isEmpty(filesystemItems)) {
             return;
         }
@@ -39,7 +37,7 @@
         log.info("Saving archive content as file list: " + file.getAbsolutePath());
         try (ObjectOutputStream outputStream = new ObjectOutputStream(new BufferedOutputStream(new GzipCompressorOutputStream(new FileOutputStream(file))))) {
             outputStream.writeObject(filesystemItems.size());
-            for (BorgFilesystemItem item : filesystemItems) {
+            for (FilesystemItem item : filesystemItems) {
                 outputStream.writeObject(item);
             }
             outputStream.writeObject("EOF");
@@ -66,7 +64,7 @@
      * @param archive
      * @return
      */
-    public List<BorgFilesystemItem> load(BorgRepoConfig repoConfig, Archive archive) {
+    public List<FilesystemItem> load(BorgRepoConfig repoConfig, Archive archive) {
         return load(repoConfig, archive, null);
     }
 
@@ -80,7 +78,7 @@
      * @param filter     If given, only file items matching this filter are returned.
      * @return
      */
-    public List<BorgFilesystemItem> load(BorgRepoConfig repoConfig, Archive archive, FileSystemFilter filter) {
+    public List<FilesystemItem> load(BorgRepoConfig repoConfig, Archive archive, FileSystemFilter filter) {
         File file = getFile(repoConfig, archive);
         if (!file.exists()) {
             return null;
@@ -93,13 +91,13 @@
      * @param filter If given, only file items matching this filter are returned.
      * @return
      */
-    public List<BorgFilesystemItem> load(File file, FileSystemFilter filter) {
+    public List<FilesystemItem> load(File file, FileSystemFilter filter) {
         if (!file.exists()) {
             log.error("File '" + file.getAbsolutePath() + "' doesn't exist. Can't get archive content files.");
             return null;
         }
         log.info("Loading archive content as file list from: " + file.getAbsolutePath());
-        List<BorgFilesystemItem> list = null;
+        List<FilesystemItem> list = null;
         try {
             // Set last modified time of file:
             Files.setAttribute(file.toPath(), "lastModifiedTime", FileTime.fromMillis(System.currentTimeMillis()));
@@ -118,9 +116,9 @@
             for (int i = 0; i < size; i++) {
                 ++fileNumber;
                 obj = inputStream.readObject();
-                if (obj instanceof BorgFilesystemItem) {
-                    BorgFilesystemItem item = (BorgFilesystemItem) obj;
-                    item.setFileNumber(fileNumber);
+                if (obj instanceof FilesystemItem) {
+                    FilesystemItem item = (FilesystemItem) obj;
+                   // item.setFileNumber(fileNumber);
                     if (filter == null || filter.matches(item)) {
                         list.add(item);
                         if (filter != null && filter.isFinished()) break;
@@ -138,7 +136,7 @@
         Collections.sort(list); // Sort by path (if archive list order wasn't correct).
         log.info("Loading done.");
         if (filter != null) {
-            return filter.reduce(list);
+           // return filter.reduce(list);
         }
         return list;
     }
diff --git a/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ButlerCache.java b/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ButlerCache.java
index 4dceafd..3acdc82 100644
--- a/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ButlerCache.java
+++ b/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ButlerCache.java
@@ -187,7 +187,7 @@
         return archive;
     }
 
-    public List<BorgFilesystemItem> getArchiveContent(String archiveId) {
+    public List<FilesystemItem> getArchiveContent(String archiveId) {
         return getArchiveContent(archiveId, true, null);
     }
 
@@ -232,7 +232,7 @@
      * @param filter    If not null, the result will be filtered.
      * @return
      */
-    public List<BorgFilesystemItem> getArchiveContent(String archiveId, boolean forceLoad, FileSystemFilter filter) {
+    public List<FilesystemItem> getArchiveContent(String archiveId, boolean forceLoad, FileSystemFilter filter) {
         Archive archive = getArchive(archiveId);
         if (archive == null) {
             log.error("Can't find archive with id '" + archiveId + "'. May-be it doesn't exist or the archives of the target repository aren't yet loaded.");
@@ -247,7 +247,7 @@
      * @param archive
      * @return
      */
-    public List<BorgFilesystemItem> getArchiveContent(BorgRepoConfig repoConfig, Archive archive) {
+    public List<FilesystemItem> getArchiveContent(BorgRepoConfig repoConfig, Archive archive) {
         return getArchiveContent(repoConfig, archive, true, null);
     }
 
@@ -257,28 +257,26 @@
      * @param filter     If given, only the items matching this filter are returned..
      * @return
      */
-    public List<BorgFilesystemItem> getArchiveContent(BorgRepoConfig repoConfig, Archive archive, boolean forceLoad,
-                                                      FileSystemFilter filter) {
+    public List<FilesystemItem> getArchiveContent(BorgRepoConfig repoConfig, Archive archive, boolean forceLoad,
+                                                  FileSystemFilter filter) {
         if (archive == null || StringUtils.isBlank(archive.getName())) {
             return null;
         }
-        List<BorgFilesystemItem> items = archiveFilelistCache.load(repoConfig, archive, filter);
+        List<FilesystemItem> items = archiveFilelistCache.load(repoConfig, archive, filter);
         if (items == null && forceLoad) {
-            List<BorgFilesystemItem> list = BorgCommands.listArchiveContent(repoConfig, archive);
-            if (CollectionUtils.isNotEmpty(list)) {
-                archiveFilelistCache.save(repoConfig, archive, list);
+            List<BorgFilesystemItem> borgList = BorgCommands.listArchiveContent(repoConfig, archive);
+            FilesystemItem root =  Filesystem.build(borgList);
+            if (CollectionUtils.isNotEmpty(root.getChilds())) {
+                archiveFilelistCache.save(repoConfig, archive, root.getChilds());
                 items = new ArrayList<>();
-                int fileNumber = -1;
-                for (BorgFilesystemItem item : list) {
-                    ++fileNumber;
-                    item.setFileNumber(fileNumber);
+                for (FilesystemItem item : list) {
                     if (filter == null || filter.matches(item)) {
                         items.add(item);
                         if (filter != null && filter.isFinished()) break;
                     }
                 }
                 if (filter != null) {
-                    items = filter.reduce(items);
+                   // items = filter.reduce(items);
                 }
             }
         }
@@ -288,7 +286,7 @@
         return items;
     }
 
-    public List<BorgFilesystemItem> getArchiveContent(File file) {
+    public List<FilesystemItem> getArchiveContent(File file) {
         return archiveFilelistCache.load(file, null);
     }
 
diff --git a/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/Filesystem.java b/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/Filesystem.java
new file mode 100644
index 0000000..00fa417
--- /dev/null
+++ b/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/Filesystem.java
@@ -0,0 +1,25 @@
+package de.micromata.borgbutler.cache;
+
+import de.micromata.borgbutler.json.borg.BorgFilesystemItem;
+import org.apache.commons.collections4.CollectionUtils;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Collections;
+import java.util.List;
+
+public class Filesystem {
+
+    public static FilesystemItem build(List<BorgFilesystemItem> itemList) {
+        FilesystemItem root = new FilesystemItem();
+        if (CollectionUtils.isEmpty(itemList)) {
+            return root;
+        }
+        Collections.sort(itemList);
+        for (BorgFilesystemItem item : itemList) {
+            Path path = Paths.get(item.getPath());
+            root.add(path, 0, item);
+        }
+        return root;
+    }
+}
diff --git a/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/FilesystemItem.java b/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/FilesystemItem.java
new file mode 100644
index 0000000..33b4d1b
--- /dev/null
+++ b/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/FilesystemItem.java
@@ -0,0 +1,187 @@
+package de.micromata.borgbutler.cache;
+
+import de.micromata.borgbutler.json.borg.BorgFilesystemItem;
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.Serializable;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+
+public class FilesystemItem extends BorgFilesystemItem implements Serializable {
+    private transient static Logger log = LoggerFactory.getLogger(FilesystemItem.class);
+    private static final long serialVersionUID = 6561019300264543523L;
+
+    @Getter
+    @Setter
+    private List<FilesystemItem> childs;
+    @Getter
+    @Setter
+    private String name;
+
+    public FilesystemItem() {
+
+    }
+
+    public FilesystemItem(BorgFilesystemItem item) {
+        this.path = item.getPath();
+        this.mode = item.getMode();
+        this.mtime = item.getMtime();
+        this.flags = item.getFlags();
+        this.size = item.getSize();
+        this.type = item.getType();
+        this.gid = item.getGid();
+        this.group = item.getGroup();
+        this.healthy = item.isHealthy();
+        this.linktarget = item.getLinktarget();
+        this.source = item.getSource();
+        this.uid = item.getUid();
+        this.user = item.getUser();
+    }
+
+
+    /**
+     * If running in diff mode, this flag specifies the type of difference. Null represents unmodified.
+     */
+    public enum DiffStatus {NEW, REMOVED, MODIFIED}
+
+    @Setter
+    @Getter
+    protected String displayPath;
+
+    /**
+     * If created by diff tool, this flag represents the type of difference.
+     */
+    @Getter
+    @Setter
+    private FilesystemItem.DiffStatus diffStatus;
+    /**
+     * If created by diff tool, this object holds the file item of the other archive (diff archive).
+     */
+    @Getter
+    @Setter
+    private FilesystemItem diffItem;
+    /**
+     * If created by diff tool, this String contains all differences between current and other item for {@link FilesystemItem.DiffStatus#MODIFIED}.
+     * This String may used for displaying.
+     */
+    @Getter
+    private String differences;
+
+    /**
+     * Compares all fields and creates human readable string with differences.
+     */
+    public void buildDifferencesString() {
+        if (diffItem == null) {
+            // Nothing to do.
+            return;
+        }
+        if (!StringUtils.equals(this.path, diffItem.getPath())) {
+            log.error("*** Internal error: Differences should only be made on same path object: current='" + path
+                    + "', other='" + diffItem.getPath() + "'.");
+            return;
+        }
+        StringBuilder sb = new StringBuilder();
+        appendDiff(sb, "type", this.type, diffItem.getType());
+        //appendDiff(sb, "mode", this.mode, diffItem.mode); // Done by frontend (jsx)
+        appendDiff(sb, "user", this.user, diffItem.getUser());
+        appendDiff(sb, "group", this.group, diffItem.getGroup());
+        appendDiff(sb, "uid", this.uid, diffItem.getUid());
+        appendDiff(sb, "gid", this.gid, diffItem.getGid());
+        //appendDiff(sb, "mtime", this.mtime, diffItem.mtime); // Done by frontend (jsx)
+        //appendDiff(sb, "size", this.size, diffItem.size); // Done by frontend (jsx)
+        if (sb.length() > 0) {
+            diffStatus = FilesystemItem.DiffStatus.MODIFIED;
+            this.differences = sb.toString();
+        }
+    }
+
+    private void appendDiff(StringBuilder sb, String field, String current, String other) {
+        if (StringUtils.equals(current, other)) {
+            // Not modified.
+            return;
+        }
+        if (sb.length() > 0) {
+            sb.append(", ");
+        }
+        sb.append(field + ":['" + other + "'->'" + current + "']");
+    }
+
+    private void appendDiff(StringBuilder sb, String field, long current, long other) {
+        if (current == other) {
+            // Not modified.
+            return;
+        }
+        if (sb.length() > 0) {
+            sb.append(", ");
+        }
+        sb.append(field + ": ['" + current + "' -> '" + other + "']");
+    }
+
+    @Override
+    public String toString() {
+        return path;
+    }
+
+    FilesystemItem add(Path path, int count, BorgFilesystemItem borgItem) {
+        if (childs == null) {
+            childs = new ArrayList<>();
+        }
+        if (count + 1 == path.getNameCount()) {
+            FilesystemItem item = new FilesystemItem(borgItem);
+            item.setName(path.getFileName().toString());
+            childs.add(item);
+            return item;
+        }
+        String name = path.getName(count).toString();
+        FilesystemItem child = null;
+        for (FilesystemItem ch : childs) {
+            if (StringUtils.equals(ch.name, name)) {
+                child = ch;
+                break;
+            }
+        }
+        if (child == null) {
+            child = new FilesystemItem();
+            child.setName(name);
+            childs.add(child);
+        }
+        return child.add(path, count + 1, borgItem);
+    }
+
+    public FilesystemItem find(String pathString) {
+        if (StringUtils.isBlank(pathString)) {
+            return this;
+        }
+        Path path = Paths.get(pathString);
+        if (path.getNameCount() == 0) {
+            return this;
+        }
+        return find(path, 0);
+    }
+
+    private FilesystemItem find(Path path, int count) {
+        if (childs == null) {
+            return null;
+        }
+        for (FilesystemItem child : childs) {
+            String name = path.getName(count).toString();
+            if (StringUtils.equals(child.name, name)) {
+                if (path.getNameCount() == count + 1)
+                    return child;
+                else
+                    return child.find(path, count + 1);
+            }
+        }
+        return null;
+    }
+
+    public int getFileNumber() {
+        return path.hashCode();
+    }
+}
\ No newline at end of file
diff --git a/borgbutler-core/src/main/java/de/micromata/borgbutler/data/FileSystemFilter.java b/borgbutler-core/src/main/java/de/micromata/borgbutler/data/FileSystemFilter.java
index cd971c3..4bb9fa9 100644
--- a/borgbutler-core/src/main/java/de/micromata/borgbutler/data/FileSystemFilter.java
+++ b/borgbutler-core/src/main/java/de/micromata/borgbutler/data/FileSystemFilter.java
@@ -1,15 +1,15 @@
 package de.micromata.borgbutler.data;
 
-import de.micromata.borgbutler.json.borg.BorgFilesystemItem;
+import de.micromata.borgbutler.cache.FilesystemItem;
 import lombok.Getter;
 import lombok.Setter;
 import org.apache.commons.collections4.CollectionUtils;
-import org.apache.commons.collections4.MapUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.List;
 
 public class FileSystemFilter {
     private Logger log = LoggerFactory.getLogger(FileSystemFilter.class);
@@ -22,8 +22,6 @@
     private Mode mode;
     @Getter
     private String currentDirectory;
-    // For storing sub directories of the currentDirectory
-    private Map<String, BorgFilesystemItem> subDirectories;
     @Getter
     @Setter
     private int maxResultSize = -1;
@@ -39,6 +37,43 @@
     @Getter
     private boolean finished;
 
+    public List<FilesystemItem> buildMatchList(FilesystemItem root) {
+        FilesystemItem current = root;
+        if (StringUtils.isNotBlank(currentDirectory)) {
+            current = root.find(currentDirectory);
+            if (current == null) {
+                current = root;
+                log.warn("Directory '" + currentDirectory + "' not found. Searching in root directory.");
+                currentDirectory = null;
+            }
+        }
+        List<FilesystemItem> resultList = new ArrayList<>();
+        if (CollectionUtils.isNotEmpty(current.getChilds())) {
+            for (FilesystemItem item : current.getChilds()) {
+                buildMatchList(item, resultList);
+            }
+        }
+        return resultList;
+    }
+
+    private void buildMatchList(FilesystemItem item, List<FilesystemItem> resultList) {
+        String pathString = item.getPath();
+        if (mode == Mode.TREE && currentDirectory != null) {
+            if (matchesRecursive(item)) {
+                resultList.add(item);
+            }
+            return;
+        }
+        if (matches(item)) {
+            resultList.add(item);
+            if (CollectionUtils.isEmpty(item.getChilds()))
+                return;
+            for (FilesystemItem child : item.getChilds()) {
+                buildMatchList(child, resultList);
+            }
+        }
+    }
+
     /**
      * Please ensure that you call matches exactly ones for every file item. If matches returns true, the internal
      * item counter is incremented (for maxResultSize functionality).
@@ -48,7 +83,7 @@
      * @param item
      * @return true if the given item matches this filter.
      */
-    public boolean matches(BorgFilesystemItem item) {
+    public boolean matches(FilesystemItem item) {
         item.setDisplayPath(item.getPath());
         if (fileNumber != null) {
             if (item.getFileNumber() == fileNumber) {
@@ -57,24 +92,18 @@
             }
             return false;
         }
+        if (item.getPath() == null) {
+            return false;
+        }
         if (mode == Mode.TREE) {
-            // In this run only register all direct childs of currentDirectory.
-            String topLevelDir = getTopLevel(item.getPath());
-            if (topLevelDir == null) {
-                // item is not inside the current directory.
+            if (currentDirectory != null && item.getPath().startsWith(currentDirectory) == false) {
                 return false;
             }
-            if (!subDirectories.containsKey(topLevelDir)) {
-                subDirectories.put(topLevelDir, item);
-            }
         }
         if (searchKeyWords == null && blackListSearchKeyWords == null) {
             processFinishedFlag();
             return true;
         }
-        if (item.getPath() == null) {
-            return false;
-        }
         String path = item.getPath().toLowerCase();
         if (searchKeyWords != null) {
             for (String searchKeyWord : searchKeyWords) {
@@ -93,86 +122,27 @@
     }
 
     /**
-     * After processing a list by using {@link #matches(BorgFilesystemItem)} you should call finally this method with
-     * your result list to reduce the files and directories for mode {@link Mode#TREE}. For the mode {@link Mode#FLAT}
-     * nothing is done.
+     * Please ensure that you call matches exactly ones for every file item. If matches returns true, the internal
+     * item counter is incremented (for maxResultSize functionality).
      * <br>
-     * Reorders the list (.files will be displayed after normal files).
+     * If the number of positive matches is greater than {@link #maxResultSize}, the finished flag is set to true.
      *
-     * @param list
-     * @return The original list for mode {@link Mode#FLAT} or the reduced list for the tree view.
+     * @param item
+     * @return true if the given item matches this filter.
      */
-    public List<BorgFilesystemItem> reduce(List<BorgFilesystemItem> list) {
-        if (mode == FileSystemFilter.Mode.TREE) {
-            if (MapUtils.isEmpty(subDirectories)) {
-                // If matches was not called before, do this now for getting all subdirectories.
-                subDirectories = new HashMap<>();
-                for (BorgFilesystemItem item : list) {
-                    // Needed for building subdirectories...
-                    this.matches(item);
-                }
-            }
-            Set<String> set = new HashSet<>();
-            List<BorgFilesystemItem> list2 = list;
-            list = new ArrayList<>();
-            for (BorgFilesystemItem item : list2) {
-                String topLevel = getTopLevel(item.getPath());
-                if (topLevel == null) {
-                    continue;
-                }
-                if (set.contains(topLevel) == false) {
-                    set.add(topLevel);
-                    BorgFilesystemItem topItem = subDirectories.get(topLevel);
-                    topItem.setDisplayPath(StringUtils.removeStart(topItem.getPath(), currentDirectory));
-                    list.add(topItem);
-                }
-            }
-            list2 = list;
-            // Re-ordering (show dot files at last)
-            list = new ArrayList<>();
-            // First add normal files:
-            for (BorgFilesystemItem item : list2) {
-                if (!item.getDisplayPath().startsWith(".")) {
-                    list.add(item);
-                }
-            }
-            // Now add dot files:
-            for (BorgFilesystemItem item : list2) {
-                if (item.getDisplayPath().startsWith(".")) {
-                    list.add(item);
+    public boolean matchesRecursive(FilesystemItem item) {
+        boolean matches = matches(item);
+        if (matches == true) {
+            return true;
+        }
+        if (item.getChilds() != null) {
+            for (FilesystemItem child : item.getChilds()) {
+                if (matchesRecursive(child)) {
+                    return true;
                 }
             }
         }
-        return list;
-    }
-
-    /**
-     * @param path The path of the current item.
-     * @return null if the item is not a child of the current directory otherwise the top level sub directory name of
-     * the current directory.
-     */
-    String getTopLevel(String path) {
-        if (StringUtils.isEmpty(currentDirectory)) {
-            int pos = path.indexOf('/');
-            if (pos < 0) {
-                return path;
-            }
-            return path.substring(0, pos);
-        }
-        if (!path.startsWith(currentDirectory)) {
-            // item is not a child of currentDirectory.
-            return null;
-        }
-        if (path.length() <= currentDirectory.length() + 1) {
-            // Don't show the current directory itself.
-            return null;
-        }
-        path = StringUtils.removeStart(path, currentDirectory);
-        int pos = path.indexOf('/');
-        if (pos < 0) {
-            return path;
-        }
-        return path.substring(0, pos);
+        return false;
     }
 
     /**
@@ -227,9 +197,6 @@
      */
     public FileSystemFilter setMode(Mode mode) {
         this.mode = mode;
-        if (mode == Mode.TREE) {
-            this.subDirectories = new HashMap<>(); // needed only for tree view.
-        }
         return this;
     }
 
diff --git a/borgbutler-core/src/main/java/de/micromata/borgbutler/json/borg/BorgFilesystemItem.java b/borgbutler-core/src/main/java/de/micromata/borgbutler/json/borg/BorgFilesystemItem.java
index 72ab6bb..9658050 100644
--- a/borgbutler-core/src/main/java/de/micromata/borgbutler/json/borg/BorgFilesystemItem.java
+++ b/borgbutler-core/src/main/java/de/micromata/borgbutler/json/borg/BorgFilesystemItem.java
@@ -2,87 +2,49 @@
 
 import lombok.Getter;
 import lombok.Setter;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.lang3.builder.EqualsBuilder;
-import org.apache.commons.lang3.builder.HashCodeBuilder;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import java.io.Serializable;
 
 public class BorgFilesystemItem implements Serializable, Comparable<BorgFilesystemItem> {
-    private transient static Logger log = LoggerFactory.getLogger(BorgFilesystemItem.class);
     private static final long serialVersionUID = -5545350851640655468L;
 
     /**
-     * If running in diff mode, this flag specifies the type of difference. Null represents unmodified.
-     */
-    public enum DiffStatus {NEW, REMOVED, MODIFIED}
-
-    /**
      * d (directory), - (file)
      */
     @Getter
     @Setter
-    private String type;
+    protected String type;
     /**
      * Unix mode, e. g. <tt>drwxr-xr-x</tt>
      */
     @Getter
     @Setter
-    private String mode;
+    protected String mode;
     @Getter
-    private String user;
+    protected String user;
     @Getter
-    private String group;
+    protected String group;
     @Getter
-    private long uid;
+    protected long uid;
     @Getter
-    private long gid;
+    protected long gid;
     @Getter
     @Setter
-    private String path;
-    @Setter
+    protected String path;
     @Getter
-    private String displayPath;
+    protected boolean healthy;
     @Getter
-    private boolean healthy;
+    protected String source;
     @Getter
-    private String source;
+    protected String linktarget;
     @Getter
-    private String linktarget;
-    @Getter
-    private String flags;
+    protected String flags;
     @Getter
     @Setter
-    private String mtime;
+    protected String mtime;
     @Getter
     @Setter
-    private long size;
-    /**
-     * Represents the number of the file in the archive (for downloading). This field is created and only known by BorgButler.
-     */
-    @Getter
-    @Setter
-    private int fileNumber;
-    /**
-     * If created by diff tool, this flag represents the type of difference.
-     */
-    @Getter
-    @Setter
-    private DiffStatus diffStatus;
-    /**
-     * If created by diff tool, this object holds the file item of the other archive (diff archive).
-     */
-    @Getter
-    @Setter
-    private BorgFilesystemItem diffItem;
-    /**
-     * If created by diff tool, this String contains all differences between current and other item for {@link DiffStatus#MODIFIED}.
-     * This String may used for displaying.
-     */
-    @Getter
-    private String differences;
+    protected long size;
 
     @Override
     public int compareTo(BorgFilesystemItem o) {
@@ -97,100 +59,4 @@
         }
         return path.compareToIgnoreCase(o.path);
     }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (obj == null) {
-            return false;
-        }
-        if (obj == this) {
-            return true;
-        }
-        if (obj.getClass() != getClass()) {
-            return false;
-        }
-        BorgFilesystemItem rhs = (BorgFilesystemItem) obj;
-        return new EqualsBuilder()
-                .append(path, rhs.path)
-                .append(type, rhs.type)
-                .append(mode, rhs.mode)
-                .append(user, rhs.user)
-                .append(group, rhs.group)
-                .append(uid, rhs.uid)
-                .append(gid, rhs.gid)
-                .append(mtime, rhs.mtime)
-                .append(size, rhs.size)
-                .append(flags, rhs.flags)
-                .isEquals();
-    }
-
-    @Override
-    public int hashCode() {
-        return new HashCodeBuilder()
-                .append(path)
-                .append(type)
-                .append(mode)
-                .append(user)
-                .append(group)
-                .append(uid)
-                .append(gid)
-                .append(mtime)
-                .append(size)
-                .append(flags)
-                .toHashCode();
-    }
-
-    /**
-     * Compares all fields and creates human readable string with differences.
-     */
-    public void buildDifferencesString() {
-        if (diffItem == null) {
-            // Nothing to do.
-            return;
-        }
-        if (!StringUtils.equals(this.path, diffItem.path)) {
-            log.error("*** Internal error: Differences should only be made on same path object: current='" + path + "', other='" + diffItem.path + "'.");
-            return;
-        }
-        StringBuilder sb = new StringBuilder();
-        appendDiff(sb, "type", this.type, diffItem.type);
-        //appendDiff(sb, "mode", this.mode, diffItem.mode); // Done by frontend (jsx)
-        appendDiff(sb, "user", this.user, diffItem.user);
-        appendDiff(sb, "group", this.group, diffItem.group);
-        appendDiff(sb, "uid", this.uid, diffItem.uid);
-        appendDiff(sb, "gid", this.gid, diffItem.gid);
-        //appendDiff(sb, "mtime", this.mtime, diffItem.mtime); // Done by frontend (jsx)
-        //appendDiff(sb, "size", this.size, diffItem.size); // Done by frontend (jsx)
-        if (sb.length() > 0) {
-            diffStatus = DiffStatus.MODIFIED;
-            this.differences = sb.toString();
-        }
-    }
-
-    private void appendDiff(StringBuilder sb, String field, String current, String other) {
-        if (StringUtils.equals(current, other)) {
-            // Not modified.
-            return;
-        }
-        if (sb.length() > 0) {
-            sb.append(", ");
-        }
-        sb.append(field + ":['" + other + "'->'" + current + "']");
-    }
-
-    private void appendDiff(StringBuilder sb, String field, long current, long other) {
-        if (current == other) {
-            // Not modified.
-            return;
-        }
-        if (sb.length() > 0) {
-            sb.append(", ");
-        }
-        sb.append(field + ": ['" + current + "' -> '" + other + "']");
-    }
-
-    @Override
-    public String toString() {
-        return path;
-    }
 }
diff --git a/borgbutler-core/src/test/java/de/micromata/borgbutler/DiffToolTest.java b/borgbutler-core/src/test/java/de/micromata/borgbutler/DiffToolTest.java
index 24a87c8..de85cfc 100644
--- a/borgbutler-core/src/test/java/de/micromata/borgbutler/DiffToolTest.java
+++ b/borgbutler-core/src/test/java/de/micromata/borgbutler/DiffToolTest.java
@@ -1,6 +1,6 @@
 package de.micromata.borgbutler;
 
-import de.micromata.borgbutler.json.borg.BorgFilesystemItem;
+import de.micromata.borgbutler.cache.FilesystemItem;
 import org.junit.jupiter.api.Test;
 
 import java.util.ArrayList;
@@ -12,8 +12,8 @@
 public class DiffToolTest {
     @Test
     void differencesTest() {
-        BorgFilesystemItem i1 = create("etc", true, "drwx------", 0, "2018-11-21");
-        BorgFilesystemItem i2 = create("etc", true, "drwx------", 0, "2018-11-21");
+        FilesystemItem i1 = create("etc", true, "drwx------", 0, "2018-11-21");
+        FilesystemItem i2 = create("etc", true, "drwx------", 0, "2018-11-21");
         assertTrue(i1.equals(i2));
         i1.setType("-").setMode("drwxrwxrwx").setMtime("2018-11-22");
         assertFalse(i1.equals(i2));
@@ -23,19 +23,19 @@
 
     @Test
     void diffToolTest() {
-        List<BorgFilesystemItem> l1 = null;
-        List<BorgFilesystemItem> l2 = null;
-        List<BorgFilesystemItem> result;
+        List<FilesystemItem> l1 = null;
+        List<FilesystemItem> l2 = null;
+        List<FilesystemItem> result;
         assertEquals(0, DiffTool.extractDifferences(l1, l2).size());
         l1 = create();
         result = DiffTool.extractDifferences(l1, l2);
         assertEquals(7, result.size());
-        assertEquals(BorgFilesystemItem.DiffStatus.NEW, result.get(0).getDiffStatus());
-        assertEquals(BorgFilesystemItem.DiffStatus.NEW, result.get(1).getDiffStatus());
+        assertEquals(FilesystemItem.DiffStatus.NEW, result.get(0).getDiffStatus());
+        assertEquals(FilesystemItem.DiffStatus.NEW, result.get(1).getDiffStatus());
         result = DiffTool.extractDifferences(l2, l1);
         assertEquals(7, result.size());
-        assertEquals(BorgFilesystemItem.DiffStatus.REMOVED, result.get(0).getDiffStatus());
-        assertEquals(BorgFilesystemItem.DiffStatus.REMOVED, result.get(1).getDiffStatus());
+        assertEquals(FilesystemItem.DiffStatus.REMOVED, result.get(0).getDiffStatus());
+        assertEquals(FilesystemItem.DiffStatus.REMOVED, result.get(1).getDiffStatus());
 
         l1 = create();
         l2 = create();
@@ -47,17 +47,17 @@
         get(l1, "home/kai/.borgbutler/borgbutler-config.json").setSize(712).setMtime("2018-11-22"); // 3
         result = DiffTool.extractDifferences(l1, l2);
         assertEquals(4, result.size());
-        assertEquals(BorgFilesystemItem.DiffStatus.NEW, result.get(0).getDiffStatus());
-        assertEquals(BorgFilesystemItem.DiffStatus.NEW, result.get(1).getDiffStatus());
-        assertEquals(BorgFilesystemItem.DiffStatus.REMOVED, result.get(2).getDiffStatus());
-        assertEquals(BorgFilesystemItem.DiffStatus.MODIFIED, result.get(3).getDiffStatus());
+        assertEquals(FilesystemItem.DiffStatus.NEW, result.get(0).getDiffStatus());
+        assertEquals(FilesystemItem.DiffStatus.NEW, result.get(1).getDiffStatus());
+        assertEquals(FilesystemItem.DiffStatus.REMOVED, result.get(2).getDiffStatus());
+        assertEquals(FilesystemItem.DiffStatus.MODIFIED, result.get(3).getDiffStatus());
 
         result = DiffTool.extractDifferences(l2, l1);
         assertEquals(4, result.size());
-        assertEquals(BorgFilesystemItem.DiffStatus.REMOVED, result.get(0).getDiffStatus());
-        assertEquals(BorgFilesystemItem.DiffStatus.REMOVED, result.get(1).getDiffStatus());
-        assertEquals(BorgFilesystemItem.DiffStatus.NEW, result.get(2).getDiffStatus());
-        assertEquals(BorgFilesystemItem.DiffStatus.MODIFIED, result.get(3).getDiffStatus());
+        assertEquals(FilesystemItem.DiffStatus.REMOVED, result.get(0).getDiffStatus());
+        assertEquals(FilesystemItem.DiffStatus.REMOVED, result.get(1).getDiffStatus());
+        assertEquals(FilesystemItem.DiffStatus.NEW, result.get(2).getDiffStatus());
+        assertEquals(FilesystemItem.DiffStatus.MODIFIED, result.get(3).getDiffStatus());
 
         l1 = create();
         l2 = create();
@@ -66,14 +66,14 @@
         remove(l1, "home/kai/.borgbutler/borgbutler-config.json"); // 2
         result = DiffTool.extractDifferences(l1, l2);
         assertEquals(3, result.size());
-        assertEquals(BorgFilesystemItem.DiffStatus.NEW, result.get(0).getDiffStatus());
-        assertEquals(BorgFilesystemItem.DiffStatus.NEW, result.get(1).getDiffStatus());
-        assertEquals(BorgFilesystemItem.DiffStatus.REMOVED, result.get(2).getDiffStatus());
+        assertEquals(FilesystemItem.DiffStatus.NEW, result.get(0).getDiffStatus());
+        assertEquals(FilesystemItem.DiffStatus.NEW, result.get(1).getDiffStatus());
+        assertEquals(FilesystemItem.DiffStatus.REMOVED, result.get(2).getDiffStatus());
         result = DiffTool.extractDifferences(l2, l1);
         assertEquals(3, result.size());
-        assertEquals(BorgFilesystemItem.DiffStatus.REMOVED, result.get(0).getDiffStatus());
-        assertEquals(BorgFilesystemItem.DiffStatus.REMOVED, result.get(1).getDiffStatus());
-        assertEquals(BorgFilesystemItem.DiffStatus.NEW, result.get(2).getDiffStatus());
+        assertEquals(FilesystemItem.DiffStatus.REMOVED, result.get(0).getDiffStatus());
+        assertEquals(FilesystemItem.DiffStatus.REMOVED, result.get(1).getDiffStatus());
+        assertEquals(FilesystemItem.DiffStatus.NEW, result.get(2).getDiffStatus());
 
 
         l1 = create();
@@ -82,12 +82,12 @@
         remove(l2, "home/kai/.borgbutler/borgbutler-config.json");
         result = DiffTool.extractDifferences(l1, l2);
         assertEquals(2, result.size());
-        assertEquals(BorgFilesystemItem.DiffStatus.REMOVED, result.get(0).getDiffStatus());
-        assertEquals(BorgFilesystemItem.DiffStatus.NEW, result.get(1).getDiffStatus());
+        assertEquals(FilesystemItem.DiffStatus.REMOVED, result.get(0).getDiffStatus());
+        assertEquals(FilesystemItem.DiffStatus.NEW, result.get(1).getDiffStatus());
         result = DiffTool.extractDifferences(l2, l1);
         assertEquals(2, result.size());
-        assertEquals(BorgFilesystemItem.DiffStatus.NEW, result.get(0).getDiffStatus());
-        assertEquals(BorgFilesystemItem.DiffStatus.REMOVED, result.get(1).getDiffStatus());
+        assertEquals(FilesystemItem.DiffStatus.NEW, result.get(0).getDiffStatus());
+        assertEquals(FilesystemItem.DiffStatus.REMOVED, result.get(1).getDiffStatus());
 
         l1 = create();
         l2 = create();
@@ -96,18 +96,18 @@
         remove(l2, "home/kai/.borgbutler/borgbutler-config-bak.json");
         result = DiffTool.extractDifferences(l1, l2);
         assertEquals(3, result.size());
-        assertEquals(BorgFilesystemItem.DiffStatus.REMOVED, result.get(0).getDiffStatus());
-        assertEquals(BorgFilesystemItem.DiffStatus.REMOVED, result.get(1).getDiffStatus());
-        assertEquals(BorgFilesystemItem.DiffStatus.NEW, result.get(2).getDiffStatus());
+        assertEquals(FilesystemItem.DiffStatus.REMOVED, result.get(0).getDiffStatus());
+        assertEquals(FilesystemItem.DiffStatus.REMOVED, result.get(1).getDiffStatus());
+        assertEquals(FilesystemItem.DiffStatus.NEW, result.get(2).getDiffStatus());
         result = DiffTool.extractDifferences(l2, l1);
         assertEquals(3, result.size());
-        assertEquals(BorgFilesystemItem.DiffStatus.NEW, result.get(0).getDiffStatus());
-        assertEquals(BorgFilesystemItem.DiffStatus.NEW, result.get(1).getDiffStatus());
-        assertEquals(BorgFilesystemItem.DiffStatus.REMOVED, result.get(2).getDiffStatus());
+        assertEquals(FilesystemItem.DiffStatus.NEW, result.get(0).getDiffStatus());
+        assertEquals(FilesystemItem.DiffStatus.NEW, result.get(1).getDiffStatus());
+        assertEquals(FilesystemItem.DiffStatus.REMOVED, result.get(2).getDiffStatus());
     }
 
-    private BorgFilesystemItem create(String path, boolean directory, String mode, long size, String mtime) {
-        return new BorgFilesystemItem()
+    private FilesystemItem create(String path, boolean directory, String mode, long size, String mtime) {
+        return (FilesystemItem)new FilesystemItem()
                 .setPath(path)
                 .setType(directory ? "d" : "-")
                 .setMode(mode)
@@ -115,8 +115,8 @@
                 .setMtime(mtime);
     }
 
-    private List<BorgFilesystemItem> create() {
-        List<BorgFilesystemItem> list = new ArrayList<>();
+    private List<FilesystemItem> create() {
+        List<FilesystemItem> list = new ArrayList<>();
         list.add(create("etc", true, "drwx------", 0, "2018-11-21"));
         list.add(create("etc/passwd", false, "-rwx------", 100, "2018-11-21"));
         list.add(create("home", true, "drwx------", 0, "2018-11-21"));
@@ -128,13 +128,13 @@
         return list;
     }
 
-    private void remove(List<BorgFilesystemItem> list, String path) {
-        BorgFilesystemItem item = get(list, path);
+    private void remove(List<FilesystemItem> list, String path) {
+        FilesystemItem item = get(list, path);
         list.remove(item);
     }
 
-    private BorgFilesystemItem get(List<BorgFilesystemItem> list, String path) {
-        for (BorgFilesystemItem item : list) {
+    private FilesystemItem get(List<FilesystemItem> list, String path) {
+        for (FilesystemItem item : list) {
             if (item.getPath().equals(path)) {
                 return item;
             }
diff --git a/borgbutler-core/src/test/java/de/micromata/borgbutler/cache/ArchiveFilelistCacheTest.java b/borgbutler-core/src/test/java/de/micromata/borgbutler/cache/ArchiveFilelistCacheTest.java
index c866ee1..86bfcb9 100644
--- a/borgbutler-core/src/test/java/de/micromata/borgbutler/cache/ArchiveFilelistCacheTest.java
+++ b/borgbutler-core/src/test/java/de/micromata/borgbutler/cache/ArchiveFilelistCacheTest.java
@@ -2,7 +2,6 @@
 
 import de.micromata.borgbutler.config.BorgRepoConfig;
 import de.micromata.borgbutler.data.Archive;
-import de.micromata.borgbutler.json.borg.BorgFilesystemItem;
 import org.junit.jupiter.api.Test;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -24,7 +23,7 @@
 
     @Test
     void readWriteTest() throws Exception {
-        List<BorgFilesystemItem> list = createList(1000000);
+        List<FilesystemItem> list = createList(1000000);
         ArchiveFilelistCache cache = new ArchiveFilelistCache(new File("out"), 100);
         cache.removeAllCacheFiles();
         BorgRepoConfig repoConfig = new BorgRepoConfig();
@@ -34,7 +33,7 @@
         cache.save(repoConfig, archive, list);
         log.info("Saving done.");
         log.info("Loading items from out dir.");
-        List<BorgFilesystemItem> filesystemItems = cache.load(repoConfig, archive);
+        List<FilesystemItem> filesystemItems = cache.load(repoConfig, archive);
         log.info("Loading " + filesystemItems.size() + " items done.");
         assertEquals(list.size(), filesystemItems.size());
         for (int i = 0; i < filesystemItems.size(); i++) {
@@ -45,7 +44,7 @@
 
     @Test
     void readWriteEmptyTest() throws Exception {
-        List<BorgFilesystemItem> list = new ArrayList<>();
+        List<FilesystemItem> list = new ArrayList<>();
         ArchiveFilelistCache cache = new ArchiveFilelistCache(new File("out"), 100);
         cache.removeAllCacheFiles();
         BorgRepoConfig repoConfig = new BorgRepoConfig();
@@ -53,14 +52,14 @@
         Archive archive = createArchive("2018-12-09");
         assertNull(cache.load(repoConfig, archive));
         cache.save(repoConfig, archive, list);
-        List<BorgFilesystemItem> filesystemItems = cache.load(repoConfig, archive);
+        List<FilesystemItem> filesystemItems = cache.load(repoConfig, archive);
         assertNull(cache.load(repoConfig, archive));
         cache.removeAllCacheFiles();
     }
 
     @Test
     void cleanUpMaximumSizeTest() throws Exception {
-        List<BorgFilesystemItem> list = createList(1000000);
+        List<FilesystemItem> list = createList(1000000);
         ArchiveFilelistCache cache = new ArchiveFilelistCache(new File("out"), 3);
         cache.removeAllCacheFiles();
         BorgRepoConfig repoConfig = new BorgRepoConfig();
@@ -96,7 +95,7 @@
 
     @Test
     void cleanUpExpiredTest() throws Exception {
-        List<BorgFilesystemItem> list = createList(1000);
+        List<FilesystemItem> list = createList(1000);
         ArchiveFilelistCache cache = new ArchiveFilelistCache(new File("out"), 3);
         cache.removeAllCacheFiles();
         BorgRepoConfig repoConfig = new BorgRepoConfig();
@@ -123,16 +122,16 @@
         cache.removeAllCacheFiles();
     }
 
-    private List<BorgFilesystemItem> createList(int number) throws Exception {
-        List<BorgFilesystemItem> list = new ArrayList<>();
+    private List<FilesystemItem> createList(int number) throws Exception {
+        List<FilesystemItem> list = new ArrayList<>();
         for (int i = 0; i < 1000000; i++) {
             list.add(create(i));
         }
         return list;
     }
 
-    private BorgFilesystemItem create(int i) throws Exception {
-        BorgFilesystemItem item = new BorgFilesystemItem();
+    private FilesystemItem create(int i) throws Exception {
+        FilesystemItem item = new FilesystemItem();
         set(item, "type", "-").set(item, "mode", "drwxr-xr-x")
                 .set(item, "user", "kai").set(item, "group", "user")
                 .set(item, "path", "/Users/kai/Test" + i + ".java").set(item, "size", 1000);
diff --git a/borgbutler-core/src/test/java/de/micromata/borgbutler/cache/CacheTest.java b/borgbutler-core/src/test/java/de/micromata/borgbutler/cache/CacheTest.java
index 85e21e3..7d2a92a 100644
--- a/borgbutler-core/src/test/java/de/micromata/borgbutler/cache/CacheTest.java
+++ b/borgbutler-core/src/test/java/de/micromata/borgbutler/cache/CacheTest.java
@@ -5,7 +5,6 @@
 import de.micromata.borgbutler.config.ConfigurationHandler;
 import de.micromata.borgbutler.data.Archive;
 import de.micromata.borgbutler.data.Repository;
-import de.micromata.borgbutler.json.borg.BorgFilesystemItem;
 import org.apache.commons.collections4.CollectionUtils;
 import org.junit.jupiter.api.Test;
 import org.slf4j.Logger;
@@ -57,7 +56,7 @@
                 assertNotNull(archive2);
                 archive = ButlerCache.getInstance().getArchive(repoConfig.getRepo(), archive.getId());
                 assertNotNull(archive2);
-                List<BorgFilesystemItem> content = ButlerCache.getInstance().getArchiveContent(repoConfig, archive2);
+                List<FilesystemItem> content = ButlerCache.getInstance().getArchiveContent(repoConfig, archive2);
                 log.info("Number of items (content) of archive: " + content.size());
                 content = ButlerCache.getInstance().getArchiveContent(repoConfig, archive2);
                 log.info("Number of items (content) of archive: " + content.size());
diff --git a/borgbutler-core/src/test/java/de/micromata/borgbutler/cache/FilesystemTest.java b/borgbutler-core/src/test/java/de/micromata/borgbutler/cache/FilesystemTest.java
new file mode 100644
index 0000000..78c554c
--- /dev/null
+++ b/borgbutler-core/src/test/java/de/micromata/borgbutler/cache/FilesystemTest.java
@@ -0,0 +1,34 @@
+package de.micromata.borgbutler.cache;
+
+import de.micromata.borgbutler.json.borg.BorgFilesystemItem;
+import org.junit.jupiter.api.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+
+public class FilesystemTest {
+    private static Logger log = LoggerFactory.getLogger(FilesystemTest.class);
+
+    @Test
+    void filesystemTest() {
+        List<BorgFilesystemItem> borgList = new ArrayList<>();
+        borgList.add(create("home/kai/test.xls"));
+        FilesystemItem root = Filesystem.build(borgList);
+        List<FilesystemItem> list  = root.getChilds();
+        assertEquals(1, list.size());
+        assertEquals("home", list.get(0).getName());
+        assertEquals("kai", list.get(0).getChilds().get(0).getName());
+        assertEquals("test.xls", list.get(0).getChilds().get(0).getChilds().get(0).getName());
+        assertEquals("home", root.find("home").getName());
+        assertEquals("kai", root.find("home/kai").getName());
+    }
+
+    private BorgFilesystemItem create(String path) {
+        return new BorgFilesystemItem().setPath(path);
+    }
+}
diff --git a/borgbutler-core/src/test/java/de/micromata/borgbutler/data/FileSystemFilterTest.java b/borgbutler-core/src/test/java/de/micromata/borgbutler/data/FileSystemFilterTest.java
index 3454bc0..531759b 100644
--- a/borgbutler-core/src/test/java/de/micromata/borgbutler/data/FileSystemFilterTest.java
+++ b/borgbutler-core/src/test/java/de/micromata/borgbutler/data/FileSystemFilterTest.java
@@ -1,6 +1,6 @@
 package de.micromata.borgbutler.data;
 
-import de.micromata.borgbutler.json.borg.BorgFilesystemItem;
+import de.micromata.borgbutler.cache.FilesystemItem;
 import org.junit.jupiter.api.Test;
 
 import java.util.ArrayList;
@@ -21,31 +21,32 @@
         assertEquals("kai", filter.getTopLevel("home/kai"));
         assertEquals("kai", filter.getTopLevel("home/kai/test.java"));
         assertNull(filter.getTopLevel("etc/test"));
-        List<BorgFilesystemItem> list = createList();
+        List<FilesystemItem> list = createList();
         filter.setCurrentDirectory("").setMode(FileSystemFilter.Mode.TREE);
-        for (BorgFilesystemItem item : list) {
+        for (FilesystemItem item : list) {
             if (filter.matches(item)) {
                 // Do nothing.
             }
         }
-        list = filter.reduce(list);
+       // list = filter.reduce(list);
         assertEquals(2, list.size());
         list = createList();
         filter.setCurrentDirectory("home");
-        for (BorgFilesystemItem item : list) {
+        for (FilesystemItem item : list) {
             if (filter.matches(item)) {
                 // Do nothing.
             }
         }
-        list = filter.reduce(list);
+      //  list = filter.reduce(list);
         assertEquals(4, list.size());
         assertEquals(".bashrc", list.get(0).getDisplayPath());
         assertEquals(".borgbutler", list.get(1).getDisplayPath());
 
     }
 
-    private BorgFilesystemItem create(String path, boolean directory) {
-        BorgFilesystemItem item = new BorgFilesystemItem().setPath(path);
+    private FilesystemItem create(String path, boolean directory) {
+        FilesystemItem item = new FilesystemItem();
+        item.setPath(path);
         if (directory) {
             item.setType("d");
         } else {
@@ -54,8 +55,8 @@
         return item;
     }
 
-    private List<BorgFilesystemItem> createList() {
-        List<BorgFilesystemItem> list = new ArrayList<>();
+    private List<FilesystemItem> createList() {
+        List<FilesystemItem> list = new ArrayList<>();
         list.add(create("home", true));
         list.add(create("home/.bashrc", false));
         list.add(create("home/.borgbutler", true));
diff --git a/borgbutler-server/src/main/java/de/micromata/borgbutler/server/Main.java b/borgbutler-server/src/main/java/de/micromata/borgbutler/server/Main.java
index 07f1b63..3bf1b5a 100644
--- a/borgbutler-server/src/main/java/de/micromata/borgbutler/server/Main.java
+++ b/borgbutler-server/src/main/java/de/micromata/borgbutler/server/Main.java
@@ -2,7 +2,7 @@
 
 import de.micromata.borgbutler.cache.ButlerCache;
 import de.micromata.borgbutler.config.ConfigurationHandler;
-import de.micromata.borgbutler.json.borg.BorgFilesystemItem;
+import de.micromata.borgbutler.cache.FilesystemItem;
 import de.micromata.borgbutler.server.jetty.JettyServer;
 import de.micromata.borgbutler.server.user.SingleUserManager;
 import de.micromata.borgbutler.server.user.UserManager;
@@ -139,7 +139,7 @@
 
     private static void printArchiveContent(String fileName) {
         File file = new File(fileName);
-        List<BorgFilesystemItem> fileList = ButlerCache.getInstance().getArchiveContent(file);
+        List<FilesystemItem> fileList = ButlerCache.getInstance().getArchiveContent(file);
         boolean parseFormatExceptionPrinted = false;
         if (fileList != null && fileList.size() > 0) {
             TimeZone tz = TimeZone.getTimeZone("UTC");
@@ -149,7 +149,7 @@
             File out = new File(FilenameUtils.getBaseName(fileName) + ".txt.gz");
             log.info("Writing file list to: " + out.getAbsolutePath());
             try (PrintWriter writer = new PrintWriter(new BufferedOutputStream(new GzipCompressorOutputStream(new FileOutputStream(out))))) {
-                for (BorgFilesystemItem item : fileList) {
+                for (FilesystemItem item : fileList) {
                     String time = item.getMtime();
                     if (time.indexOf('T') > 0) {
                         try {
diff --git a/borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/ArchivesRest.java b/borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/ArchivesRest.java
index 2d75037..385e1b7 100644
--- a/borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/ArchivesRest.java
+++ b/borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/ArchivesRest.java
@@ -9,7 +9,7 @@
 import de.micromata.borgbutler.data.FileSystemFilter;
 import de.micromata.borgbutler.data.Repository;
 import de.micromata.borgbutler.json.JsonUtils;
-import de.micromata.borgbutler.json.borg.BorgFilesystemItem;
+import de.micromata.borgbutler.cache.FilesystemItem;
 import de.micromata.borgbutler.utils.DirUtils;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
@@ -79,7 +79,7 @@
                 .setMaxResultSize(maxSize)
                 .setMode(mode)
                 .setCurrentDirectory(currentDirectory);
-        List<BorgFilesystemItem> items = null;
+        List<FilesystemItem> items = null;
         if (StringUtils.isBlank(diffArchiveId)) {
             // Get file list (without running diff).
             items = ButlerCache.getInstance().getArchiveContent(archiveId, force,
@@ -90,7 +90,7 @@
         } else {
             filter.setMode(FileSystemFilter.Mode.FLAT).setMaxResultSize(-1);
             items = ButlerCache.getInstance().getArchiveContent(archiveId, true, filter);
-            List<BorgFilesystemItem> diffItems = ButlerCache.getInstance().getArchiveContent(diffArchiveId, true,
+            List<FilesystemItem> diffItems = ButlerCache.getInstance().getArchiveContent(diffArchiveId, true,
                     filter);
             items = DiffTool.extractDifferences(items, diffItems);
             filter.setMaxResultSize(maxSize)
@@ -110,7 +110,7 @@
     public Response restore(@QueryParam("archiveId") String archiveId, @QueryParam("fileNumber") int fileNumber) {
         log.info("Requesting file #" + fileNumber + " of archive '" + archiveId + "'.");
         FileSystemFilter filter = new FileSystemFilter().setFileNumber(fileNumber);
-        List<BorgFilesystemItem> items = ButlerCache.getInstance().getArchiveContent(archiveId, false,
+        List<FilesystemItem> items = ButlerCache.getInstance().getArchiveContent(archiveId, false,
                 filter);
         if (CollectionUtils.isEmpty(items)) {
             log.error("Requested file #" + fileNumber + " not found in archive '" + archiveId
@@ -131,7 +131,7 @@
         }
         BorgRepoConfig repoConfig = ConfigurationHandler.getConfiguration().getRepoConfig(archive.getRepoId());
         try {
-            BorgFilesystemItem item = items.get(0);
+            FilesystemItem item = items.get(0);
             File restoreHomeDir = ConfigurationHandler.getConfiguration().getRestoreHomeDir();
             File restoreDir = BorgCommands.extractFiles(restoreHomeDir, repoConfig, archive, item.getPath());
             List<java.nio.file.Path> files = DirUtils.listFiles(restoreDir.toPath());

--
Gitblit v1.10.0