package org.peerbox.watchservice.filetree; import java.io.IOException; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; import org.hive2hive.core.processes.files.list.FileNode; import org.peerbox.app.ClientContext; import org.peerbox.watchservice.filetree.composite.FileComponent; import org.peerbox.watchservice.filetree.composite.FileLeaf; import org.peerbox.watchservice.filetree.composite.FolderComposite; import org.peerbox.watchservice.filetree.persistency.LocalFileDao; import org.peerbox.watchservice.states.EstablishedState; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class FileTreeInitializer { private static final Logger logger = LoggerFactory.getLogger(FileTreeInitializer.class); private ClientContext context; public FileTreeInitializer(ClientContext context) { this.context = context; } /** * Creates a tree consisting of the user profile (files) in the DHT combined with the files on disk. * * @throws Exception */ public void initialize(Path topLevel) throws Exception { // root of tree final IFileTree tree = context.getFileEventManager().getFileTree(); // add the files in the DHT to the tree FileNode root = context.getFileManager().listFiles().execute(); List<FileNode> fileList = FileNode.getNodeList(root, true, true); fileList = fileList.stream().filter(node -> node.getFile().toPath(). startsWith(topLevel)).sorted(new Comparator<FileNode>() { @Override public int compare(FileNode o1, FileNode o2) { return o1.getFile().compareTo(o2.getFile()); } }).collect(Collectors.toList()); fileList.forEach(node -> logger.trace("fileList: {}", node.getFile().getPath())); for (FileNode node : fileList) { if(node == root) { continue; // root does not need to be added. } FileComponent component = null; if (node.isFile()) { component = new FileLeaf(node.getFile().toPath(), true); } else { component = new FolderComposite(node.getFile().toPath(), true); } tree.putFile(node.getFile().toPath(), component); component.setIsUploaded(true); component.getAction().setFileEventManager(context.getFileEventManager()); component.getAction().setFile(component); // state: InitialState for all } // Add the files on disk to the tree (if not present yet) Files.walkFileTree(topLevel, new SimpleFileVisitor<Path>() { @Override public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { FileComponent component = tree.getFile(dir); if (component == null) { component = new FolderComposite(dir, true); component.setIsUploaded(false); tree.putFile(dir, component); // state: initial, because not present in network } else { // already exists, i.e. present in network - state: established component.getAction().setCurrentState(new EstablishedState(component.getAction())); } component.getAction().setFileEventManager(context.getFileEventManager()); component.getAction().setFile(component); return super.preVisitDirectory(dir, attrs); } @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { FileComponent component = tree.getFile(file); if (component == null) { component = new FileLeaf(file, true); component.setIsUploaded(false); tree.putFile(file, component); // state: initial, because not present in network } else { // already exists, state: established component.getAction().setCurrentState(new EstablishedState(component.getAction())); } component.getAction().setFileEventManager(context.getFileEventManager()); component.getAction().setFile(component); return super.visitFile(file, attrs); } }); // selective sync: use database to disable sync on some elements final LocalFileDao localFileDao = context.getLocalFileDao(); List<FileComponent> subtreeList = tree.asList().stream().filter(node -> node.getPath(). startsWith(topLevel)).sorted(new Comparator<FileComponent>() { @Override public int compare(FileComponent o1, FileComponent o2) { return o1.getPath().compareTo(o2.getPath()); } }).collect(Collectors.toList()); for (FileComponent c : subtreeList) { Boolean isSync = localFileDao.isSynchronizedByPath(c.getPath()); if (isSync != null && !isSync.booleanValue()) { c.setIsSynchronized(false); } else { if (c.getParent() != null && !c.getParent().isSynchronized()) { c.setIsSynchronized(false); } else { c.setIsSynchronized(true); } } } if (logger.isTraceEnabled()) { logger.trace("Tree initialization finished. Current tree state: "); for (FileComponent c : subtreeList) { logger.trace("... {}", c.toString()); logger.trace("...... {}", c.getAction().toString()); } } } }