package org.hive2hive.core.processes.files.list;

import java.io.File;
import java.util.HashSet;
import java.util.Set;

import org.hive2hive.core.model.UserPermission;
import org.hive2hive.core.security.EncryptionUtil;

/**
 * Gives information about a file in the DHT. Links to child nodes and parent node (if existing)
 * 
 * @author Nico
 * 
 */
public class FileNode {

	// can be null in case of the root
	private final FileNode parent;
	// holds all children
	private final Set<FileNode> children;
	private final String path;
	private final File file;
	private final byte[] md5;
	private final Set<UserPermission> userPermissions;

	FileNode(FileNode parent, File file, String path, byte[] md5, Set<UserPermission> userPermissions) {
		this.parent = parent;
		this.file = file;
		this.path = path;
		this.md5 = md5;
		this.userPermissions = userPermissions;
		this.children = new HashSet<FileNode>();
	}

	/**
	 * Get the parent node or <code>null</code> if this node is the root folder
	 * 
	 * @return
	 */
	public FileNode getParent() {
		return parent;
	}

	/**
	 * Get child nodes. Note that this may be empty
	 * 
	 * @return the children (can be an empty set) or <code>null</code> if this node is a file and not a folder
	 */
	public Set<FileNode> getChildren() {
		if (isFile()) {
			return null;
		}
		return children;
	}

	/**
	 * The name of the file
	 * 
	 * @return the filename
	 */
	public String getName() {
		return file.getName();
	}

	/**
	 * Returns the relative path of the file to the root
	 * 
	 * @return
	 */
	public String getPath() {
		return path;
	}

	/**
	 * Returns the absolute file with respect to the currently logged in user
	 * 
	 * @return the file
	 */
	public File getFile() {
		return file;
	}

	/**
	 * Returns whether the file is a file and not a directory. This is just the reverse option of
	 * {@link FileNode#isFolder()}.
	 * 
	 * @return true when the file is a file and not a folder.
	 */
	public boolean isFile() {
		if (file.exists()) {
			return file.isFile();
		} else {
			return md5 != null;
		}
	}

	/**
	 * Returns whether the file is a directory. This is just the reverse option of {@link FileNode#isFile()}.
	 * 
	 * @return true when the file is a folder.
	 */
	public boolean isFolder() {
		return !isFile();
	}

	/**
	 * The MD5 hash of the file. In case of a folder, this is null.
	 * 
	 * @return the MD5 hash of the newest file version
	 */
	public byte[] getMd5() {
		return md5;
	}

	/**
	 * A list of users that have permissions to this file (including the user itself)
	 * 
	 * @return the users having (any) permission to this file
	 */
	public Set<UserPermission> getUserPermissions() {
		return userPermissions;
	}

	/**
	 * Indicates whether this file is shared with someone
	 * 
	 * @return true when the file is shared
	 */
	public boolean isShared() {
		return getUserPermissions().size() > 1;
	}

	@Override
	public String toString() {
		return String.format("%s: %s [%s] %s", isFile() ? "File" : "Folder", getPath(), getUserPermissions(),
				isFile() ? String.format("(MD5: %s)", EncryptionUtil.byteToHex(getMd5())) : "");
	}
}

@@ -81,22 +81,73 @@
 va.util.
-HashSe
+ArrayList;%0Aimport java.util.HashSet;%0Aimport java.util.Lis
 t;%0Aimpor
@@ -3153,11 +3153,854 @@
  %22%22);%0A%09%7D
+%0A%0A%09/**%0A%09 * Returns a list of all nodes in preorder. One can specify whether only files, folders or both is desired%0A%09 */%0A%09public static List%3CFileNode%3E getNodeList(FileNode root, boolean addFiles, boolean addFolders) %7B%0A%09%09if (!addFiles && !addFolders) %7B%0A%09%09%09throw new IllegalArgumentException(%22Must visit either files, folders or both%22);%0A%09%09%7D%0A%09%09List%3CFileNode%3E list = new ArrayList%3CFileNode%3E();%0A%09%09preorder(root, list, addFiles, addFolders);%0A%09%09return list;%0A%09%7D%0A%0A%09private static void preorder(FileNode current, List%3CFileNode%3E list, boolean addFiles, boolean addFolders) %7B%0A%09%09if (current == null) %7B%0A%09%09%09return;%0A%09%09%7D%0A%0A%09%09if (current.isFile() && addFiles %7C%7C current.isFolder() && addFolders) %7B%0A%09%09%09list.add(current);%0A%09%09%7D%0A%0A%09%09if (current.isFolder()) %7B%0A%09%09%09for (FileNode child : current.getChildren()) %7B%0A%09%09%09%09preorder(child, list, addFiles, addFolders);%0A%09%09%09%7D%0A%09%09%7D%0A%09%7D
 %0A%7D%0A

Add helper method to visit all nodes