diff --git a/main/filesystem-api/src/main/java/org/cryptomator/filesystem/FileSystemVisitor.java b/main/filesystem-api/src/main/java/org/cryptomator/filesystem/FileSystemVisitor.java index 41b278031..3493e28fd 100644 --- a/main/filesystem-api/src/main/java/org/cryptomator/filesystem/FileSystemVisitor.java +++ b/main/filesystem-api/src/main/java/org/cryptomator/filesystem/FileSystemVisitor.java @@ -1,5 +1,7 @@ package org.cryptomator.filesystem; +import static java.lang.String.format; + import java.util.function.Consumer; public class FileSystemVisitor { @@ -7,11 +9,15 @@ public class FileSystemVisitor { private final Consumer beforeFolderVisitor; private final Consumer afterFolderVisitor; private final Consumer fileVisitor; + private final Consumer nodeVisitor; + private final int maxDepth; - private FileSystemVisitor(Consumer beforeFolderVisitor, Consumer afterFolderVisitor, Consumer fileVisitor) { - this.beforeFolderVisitor = beforeFolderVisitor; - this.afterFolderVisitor = afterFolderVisitor; - this.fileVisitor = fileVisitor; + public FileSystemVisitor(FileSystemVisitorBuilder builder) { + this.beforeFolderVisitor = builder.beforeFolderVisitor; + this.afterFolderVisitor = builder.afterFolderVisitor; + this.fileVisitor = builder.fileVisitor; + this.nodeVisitor = builder.nodeVisitor; + this.maxDepth = builder.maxDepth; } public static FileSystemVisitorBuilder fileSystemVisitor() { @@ -19,14 +25,27 @@ public class FileSystemVisitor { } public FileSystemVisitor visit(Folder folder) { + return visit(folder, 0); + } + + public FileSystemVisitor visit(File file) { + return visit(file, 0); + } + + private FileSystemVisitor visit(Folder folder, int depth) { beforeFolderVisitor.accept(folder); - folder.folders().forEach(this::visit); - folder.files().forEach(this::visit); + nodeVisitor.accept(folder); + final int childDepth = depth + 1; + if (childDepth <= maxDepth) { + folder.folders().forEach(childFolder -> visit(childFolder, childDepth)); + folder.files().forEach(childFile -> visit(childFile, childDepth)); + } afterFolderVisitor.accept(folder); return this; } - public FileSystemVisitor visit(File file) { + private FileSystemVisitor visit(File file, int depth) { + nodeVisitor.accept(file); fileVisitor.accept(file); return this; } @@ -36,6 +55,8 @@ public class FileSystemVisitor { private Consumer beforeFolderVisitor = noOp(); private Consumer afterFolderVisitor = noOp(); private Consumer fileVisitor = noOp(); + private Consumer nodeVisitor = noOp(); + private int maxDepth = Integer.MAX_VALUE; private FileSystemVisitorBuilder() { } @@ -64,6 +85,22 @@ public class FileSystemVisitor { return this; } + public FileSystemVisitorBuilder forEachNode(Consumer nodeVisitor) { + if (nodeVisitor == null) { + throw new IllegalArgumentException("Vistior may not be null"); + } + this.nodeVisitor = nodeVisitor; + return this; + } + + public FileSystemVisitorBuilder withMaxDepth(int maxDepth) { + if (maxDepth < 0) { + throw new IllegalArgumentException(format("maxDepth must not be smaller 0 but was %d", maxDepth)); + } + this.maxDepth = maxDepth; + return this; + } + public FileSystemVisitor visit(Folder folder) { return build().visit(folder); } @@ -73,7 +110,7 @@ public class FileSystemVisitor { } public FileSystemVisitor build() { - return new FileSystemVisitor(beforeFolderVisitor, afterFolderVisitor, fileVisitor); + return new FileSystemVisitor(this); } private static Consumer noOp() { diff --git a/main/filesystem-crypto/src/test/java/org/cryptomator/crypto/fs/CryptoFileSystemTest.java b/main/filesystem-crypto/src/test/java/org/cryptomator/crypto/fs/CryptoFileSystemTest.java index 2538c8140..aa31362db 100644 --- a/main/filesystem-crypto/src/test/java/org/cryptomator/crypto/fs/CryptoFileSystemTest.java +++ b/main/filesystem-crypto/src/test/java/org/cryptomator/crypto/fs/CryptoFileSystemTest.java @@ -8,6 +8,8 @@ *******************************************************************************/ package org.cryptomator.crypto.fs; +import static org.cryptomator.filesystem.FileSystemVisitor.fileSystemVisitor; + import java.io.IOException; import java.io.UncheckedIOException; import java.nio.ByteBuffer; @@ -175,15 +177,16 @@ public class CryptoFileSystemTest { */ private static int countDataFolders(Folder dataRoot) { final AtomicInteger num = new AtomicInteger(); - DirectoryWalker.walk(dataRoot, 0, 2, (node) -> { - if (node instanceof Folder) { - final Folder nodeParent = node.parent().get(); - final Folder nodeParentParent = nodeParent.parent().orElse(null); - if (nodeParentParent != null && nodeParentParent.equals(dataRoot)) { - num.incrementAndGet(); - } - } - }); + fileSystemVisitor() // + .afterFolder(folder -> { + final Folder parent = folder.parent().get(); + final Folder parentOfParent = parent.parent().orElse(null); + if (parentOfParent != null && parentOfParent.equals(dataRoot)) { + num.incrementAndGet(); + } + }) // + .withMaxDepth(2) // + .visit(dataRoot); return num.get(); } diff --git a/main/filesystem-crypto/src/test/java/org/cryptomator/crypto/fs/DirectoryPrinter.java b/main/filesystem-crypto/src/test/java/org/cryptomator/crypto/fs/DirectoryPrinter.java index 85859b1eb..0f7b72621 100644 --- a/main/filesystem-crypto/src/test/java/org/cryptomator/crypto/fs/DirectoryPrinter.java +++ b/main/filesystem-crypto/src/test/java/org/cryptomator/crypto/fs/DirectoryPrinter.java @@ -8,9 +8,8 @@ *******************************************************************************/ package org.cryptomator.crypto.fs; -import java.util.Optional; +import static org.cryptomator.filesystem.FileSystemVisitor.fileSystemVisitor; -import org.cryptomator.filesystem.File; import org.cryptomator.filesystem.Folder; public final class DirectoryPrinter { @@ -18,23 +17,21 @@ public final class DirectoryPrinter { private DirectoryPrinter() { } - public static String print(Folder folder) { - StringBuilder sb = new StringBuilder(folder.name()).append('\n'); - - DirectoryWalker.walk(folder, (node) -> { - Optional parent = node.parent(); - while (parent.isPresent()) { - sb.append(" "); - parent = parent.get().parent(); - } - if (node instanceof Folder) { - sb.append(node.name()).append('/').append('\n'); - } else if (node instanceof File) { - sb.append(node.name()).append('\n'); - } - }); - - return sb.toString(); + public static String print(Folder rootFolder) { + StringBuilder result = new StringBuilder(); + StringBuilder identation = new StringBuilder(); + fileSystemVisitor() // + .beforeFolder(folder -> { + result.append(identation).append(folder.name()).append("/\n"); + identation.append(" "); + }) // + .afterFolder(folder -> { + identation.delete(identation.length() - 2, identation.length()); + }).forEachFile(file -> { + result.append(identation).append(file.name()).append('\n'); + }) // + .visit(rootFolder); + return result.toString(); } } diff --git a/main/filesystem-crypto/src/test/java/org/cryptomator/crypto/fs/DirectoryWalker.java b/main/filesystem-crypto/src/test/java/org/cryptomator/crypto/fs/DirectoryWalker.java deleted file mode 100644 index df5a802b5..000000000 --- a/main/filesystem-crypto/src/test/java/org/cryptomator/crypto/fs/DirectoryWalker.java +++ /dev/null @@ -1,38 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Sebastian Stenzel and others. - * This file is licensed under the terms of the MIT license. - * See the LICENSE.txt file for more info. - * - * Contributors: - * Sebastian Stenzel - initial API and implementation - *******************************************************************************/ -package org.cryptomator.crypto.fs; - -import java.util.function.Consumer; - -import org.cryptomator.filesystem.Folder; -import org.cryptomator.filesystem.Node; - -final class DirectoryWalker { - - private DirectoryWalker() { - } - - public static void walk(Folder folder, Consumer visitor) { - walk(folder, 0, Integer.MAX_VALUE, visitor); - } - - public static void walk(Folder folder, int depth, int maxDepth, Consumer visitor) { - folder.files().forEach(visitor); - if (depth == maxDepth) { - return; - } else { - folder.folders().forEach(childFolder -> { - visitor.accept(childFolder); - walk(childFolder, depth + 1, maxDepth, visitor); - }); - } - - } - -} diff --git a/main/filesystem-crypto/src/test/java/org/cryptomator/crypto/fs/EncryptAndShortenIntegrationTest.java b/main/filesystem-crypto/src/test/java/org/cryptomator/crypto/fs/EncryptAndShortenIntegrationTest.java index 84a1b44fb..ddee2cda6 100644 --- a/main/filesystem-crypto/src/test/java/org/cryptomator/crypto/fs/EncryptAndShortenIntegrationTest.java +++ b/main/filesystem-crypto/src/test/java/org/cryptomator/crypto/fs/EncryptAndShortenIntegrationTest.java @@ -1,5 +1,7 @@ package org.cryptomator.crypto.fs; +import static org.cryptomator.filesystem.FileSystemVisitor.fileSystemVisitor; + import java.nio.ByteBuffer; import java.util.Arrays; @@ -43,10 +45,11 @@ public class EncryptAndShortenIntegrationTest { // names: // LOG.debug("Unlimited filename length:\n" + // DirectoryPrinter.print(shorteningFs)); - DirectoryWalker.walk(shorteningFs, node -> { - Assert.assertFalse(node.name().endsWith(".lng")); - }); - + fileSystemVisitor() // + .forEachNode(node -> { + Assert.assertFalse(node.name().endsWith(".lng")); + }) // + .visit(shorteningFs); // on the third (cleartext layer) we have cleartext names on the root // level: // LOG.debug("Cleartext files:\n" + DirectoryPrinter.print(fs));