diff --git a/core/src/main/groovy/com/muwire/core/collections/FileCollection.groovy b/core/src/main/groovy/com/muwire/core/collections/FileCollection.groovy index 01f4ac3c..f821a840 100644 --- a/core/src/main/groovy/com/muwire/core/collections/FileCollection.groovy +++ b/core/src/main/groovy/com/muwire/core/collections/FileCollection.groovy @@ -21,6 +21,8 @@ class FileCollection { private final Set files = new LinkedHashSet<>() + final PathTree tree + FileCollection(long timestamp, Persona author, String comment, Set files, SigningPrivateKey spk) { this.timestamp = timestamp; @@ -28,6 +30,11 @@ class FileCollection { this.comment = comment this.files = files + tree = new PathTree(files.first().pathElements.first()) + for(FileCollectionItem item : files) { + tree.add(item.pathElements) + } + byte [] signablePayload = signablePayload() Signature signature = DSAEngine.getInstance().sign(signablePayload, spk) this.sig = signature.getData() @@ -112,6 +119,67 @@ class FileCollection { os.write(payload) } + static class PathTree { + + private final Map keyToNode = new HashMap<>() + + final PathNode root + PathTree(String root) { + this.root = new PathNode(root, null) + keyToNode.put(this.root.key(), this.root) + } + + void add(List paths) { + PathNode current = null + for (String path : paths) { + if (current == null) { + if (path == root.path) { + current = root + continue + } + } + + + PathNode child = new PathNode(path, current) + PathNode.Key childKey = child.key() + if (!keyToNode.containsKey(childKey)) { + keyToNode.put(childKey, child) + current.children.add(child) + } + current = keyToNode.get(childKey) + } + } + } + static class PathNode { + final String path + final PathNode parent + final Set children = new LinkedHashSet<>() + private final int hashCode + + PathNode(String path, PathNode parent) { + this.parent = parent + this.path = path + this.hashCode = Objects.hash(path, parent) + } + + Key key() { + return new Key() + } + + private class Key { + + private final PathNode node = PathNode.this + + public int hashCode() { + hashCode + } + public boolean equals(Object o) { + Key other = (Key)o + Objects.equals(path, other.node.path) && + Objects.equals(parent, other.node.parent) + } + } + } }