package org.hive2hive.client.menu;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import org.apache.commons.io.FileUtils;
import org.hive2hive.client.console.H2HConsoleMenu;
import org.hive2hive.client.console.H2HConsoleMenuItem;
import org.hive2hive.client.console.SelectionMenu;
import org.hive2hive.client.util.MenuContainer;
import org.hive2hive.core.exceptions.Hive2HiveException;
import org.hive2hive.core.exceptions.NoPeerConnectionException;
import org.hive2hive.core.exceptions.NoSessionException;
import org.hive2hive.core.model.IFileVersion;
import org.hive2hive.core.model.PermissionType;
import org.hive2hive.core.processes.files.list.FileNode;
import org.hive2hive.core.processes.files.recover.IVersionSelector;
import org.hive2hive.processframework.exceptions.InvalidProcessStateException;
import org.hive2hive.processframework.exceptions.ProcessExecutionException;
import org.hive2hive.processframework.interfaces.IProcessComponent;
public class FileMenu extends H2HConsoleMenu {
public FileMenu(MenuContainer menus) {
super(menus);
}
@Override
protected void addMenuItems() {
add(new H2HConsoleMenuItem("Add File") {
protected boolean checkPreconditions() {
return menus.getUserMenu().createRootDirectory();
}
protected void execute() throws Hive2HiveException, InterruptedException, InvalidProcessStateException,
ProcessExecutionException, ExecutionException {
File file = askForFile(true);
if (file == null) {
return;
}
IProcessComponent<Void> addFileProcess = menus.getNodeMenu().getNode().getFileManager()
.createAddProcess(file);
addFileProcess.execute();
}
});
add(new H2HConsoleMenuItem("Update File") {
protected boolean checkPreconditions() {
return menus.getUserMenu().createRootDirectory();
}
protected void execute() throws Hive2HiveException, InterruptedException, InvalidProcessStateException,
ProcessExecutionException, ExecutionException {
File file = askForFile(true);
if (file == null) {
return;
}
IProcessComponent<Void> updateFileProcess = menus.getNodeMenu().getNode().getFileManager()
.createUpdateProcess(file);
updateFileProcess.execute();
}
});
add(new H2HConsoleMenuItem("Download File") {
protected boolean checkPreconditions() {
return menus.getUserMenu().createRootDirectory();
}
protected void execute() throws Hive2HiveException, InterruptedException, InvalidProcessStateException,
ProcessExecutionException, ExecutionException {
File file = askForFile(false);
if (file == null) {
return;
}
IProcessComponent<Void> updateFileProcess = menus.getNodeMenu().getNode().getFileManager()
.createDownloadProcess(file);
updateFileProcess.execute();
}
});
add(new H2HConsoleMenuItem("Move File") {
protected boolean checkPreconditions() {
return menus.getUserMenu().createRootDirectory();
}
protected void execute() throws Hive2HiveException, InterruptedException, InvalidProcessStateException,
ProcessExecutionException, ExecutionException, IOException {
File source = askForFile("Specify the relative path of the source file to the root directory '%s'.", true);
if (source == null) {
return;
}
File destination = askForFile(
"Specify the relative path of the destination file to the root directory '%s'.", false);
if (destination == null) {
return;
}
IProcessComponent<Void> moveFileProcess = menus.getNodeMenu().getNode().getFileManager()
.createMoveProcess(source, destination);
moveFileProcess.execute();
if (source.exists()) {
if (source.isFile()) {
FileUtils.moveFile(source, destination);
} else {
FileUtils.moveDirectory(source, destination);
}
}
}
});
add(new H2HConsoleMenuItem("Delete File") {
protected boolean checkPreconditions() {
return menus.getUserMenu().createRootDirectory();
}
protected void execute() throws Hive2HiveException, InterruptedException, InvalidProcessStateException,
ProcessExecutionException, ExecutionException {
File file = askForFile(true);
if (file == null) {
return;
}
IProcessComponent<Void> deleteFileProcess = menus.getNodeMenu().getNode().getFileManager()
.createDeleteProcess(file);
deleteFileProcess.execute();
// finally delete the file
file.delete();
}
});
add(new H2HConsoleMenuItem("Recover File") {
protected boolean checkPreconditions() {
return menus.getUserMenu().createRootDirectory();
}
protected void execute() throws Hive2HiveException, FileNotFoundException, InterruptedException,
InvalidProcessStateException, ProcessExecutionException, ExecutionException {
File file = askForFile(true);
if (file == null) {
return;
}
IVersionSelector versionSelector = new IVersionSelector() {
public IFileVersion selectVersion(List<IFileVersion> availableVersions) {
return new SelectionMenu<IFileVersion>(availableVersions, "Choose the version you want to recover.")
.openAndSelect();
}
public String getRecoveredFileName(String fullName, String name, String extension) {
print(String
.format("Specify the new name for the recovered file '%s' or enter 'default' to take the default values:",
fullName));
String input = awaitStringParameter();
if ("default".equalsIgnoreCase(input)) {
return null;
} else {
return input;
}
}
};
IProcessComponent<Void> recoverFileProcess = menus.getNodeMenu().getNode().getFileManager()
.createRecoverProcess(file, versionSelector);
recoverFileProcess.execute();
}
});
add(new H2HConsoleMenuItem("Share File") {
protected boolean checkPreconditions() {
return menus.getUserMenu().createRootDirectory();
}
protected void execute() throws NoSessionException, NoPeerConnectionException, InvalidProcessStateException,
InterruptedException, ProcessExecutionException, ExecutionException {
File folderToShare = askForFolder(
"Specify the relative path of the folder you want to share to the root directory '%s'.", true);
if (folderToShare == null) {
return;
}
print("Specify the user ID of the user you want to share with.");
String friendID = awaitStringParameter();
PermissionType permission = askForPermission(folderToShare.getAbsolutePath(), friendID);
if (permission == null) {
return;
}
IProcessComponent<Void> shareProcess;
try {
shareProcess = menus.getNodeMenu().getNode().getFileManager()
.createShareProcess(folderToShare, friendID, permission);
} catch (NoPeerConnectionException | NoSessionException | IllegalArgumentException ex) {
printError(ex.getMessage());
return;
}
shareProcess.execute();
}
});
add(new H2HConsoleMenuItem("Print File List") {
@Override
protected void execute() throws Exception {
IProcessComponent<FileNode> fileListProcess = menus.getNodeMenu().getNode().getFileManager()
.createFileListProcess();
FileNode root = fileListProcess.execute();
printRecursively(root, 0);
}
});
add(new H2HConsoleMenuItem("File Observer") {
protected boolean checkPreconditions() {
return menus.getUserMenu().createRootDirectory();
}
protected void execute() {
menus.getFileObserverMenu().open();
}
});
}
private void printRecursively(FileNode node, int level) {
if (node.getParent() != null) {
// skip the root node
StringBuilder spaces = new StringBuilder("*");
for (int i = 0; i < level; i++) {
spaces.append(" ");
}
print(spaces.toString() + node.getName());
}
if (node.isFolder()) {
for (FileNode child : node.getChildren()) {
printRecursively(child, level + 1);
}
}
}
@Override
protected String getInstruction() {
return "Select a file operation:";
}
private File askForFile(boolean expectExistence) {
return askForFile("Specify the relative path to the root directory '%s'.", expectExistence);
}
private File askForFile(String msg, boolean expectExistence) {
return askFor(msg, expectExistence, false);
}
private File askForFolder(String msg, boolean expectExistence) {
return askFor(msg, expectExistence, true);
}
private File askFor(String msg, boolean expectExistence, boolean requireDirectory) {
// TODO find better way to exit this menu
// TODO be more flexible with inputs, e.g. files with whitespaces in
// name
File rootDirectory = menus.getUserMenu().getRootDirectory();
File file = null;
do {
print(String.format(msg.concat(expectExistence ? String.format(" The %s at this path must exist.",
requireDirectory ? "folder" : "file") : ""), rootDirectory.getAbsolutePath()));
print("Or enter 'cancel' in order to go back.");
String input = awaitStringParameter();
if ("cancel".equalsIgnoreCase(input)) {
return null;
}
file = new File(rootDirectory, input);
if (expectExistence && !file.exists()) {
printError(String.format("The specified %s '%s' does not exist. Try again.", requireDirectory ? "folder"
: "file", file.getAbsolutePath()));
continue;
}
if (expectExistence && requireDirectory && !file.isDirectory()) {
printError(String.format("The specified file '%s' is not a folder. Try again.", file.getAbsolutePath()));
}
} while (expectExistence && (file == null || !file.exists() || (requireDirectory && !file.isDirectory())));
return file;
}
private PermissionType askForPermission(String folder, String userID) {
List<PermissionType> permissionTypes = new ArrayList<PermissionType>();
permissionTypes.add(PermissionType.WRITE);
permissionTypes.add(PermissionType.READ);
List<String> displayTexts = new ArrayList<String>();
displayTexts.add("Read and Write");
displayTexts.add("Read Only");
return new SelectionMenu<PermissionType>(permissionTypes, displayTexts, String.format(
"Specify the permissions of folder '%s' for the user '%s'.", folder, userID)).openAndSelect();
}
}