package org.hive2hive.client.console;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
/**
* An abstract console menu.
*
* @author Christian
* @author Nico
*
*/
public abstract class ConsoleMenu {
private final List<ConsoleMenuItem> items;
private static final String EXIT_TOKEN = "Q";
private boolean exited;
public ConsoleMenu() {
this.items = new ArrayList<ConsoleMenuItem>();
createItems();
}
/**
* Specifies the {@link H2HConsoleMenuItem}s of this menu.<br/>
* <b>Note:</b> Not all {@link H2HConsoleMenuItem}s are specified here, as they might also be specified
* in-line in {@link ConsoleMenu#addMenuItems()}.</br>
* <b>Note:</b> {@link H2HConsoleMenuItem}s with preconditions should be specified by this method.
*/
protected void createItems() {
// do nothing by default
}
/**
* Enlists the {@link H2HConsoleMenuItem}s of this menu.
*/
protected abstract void addMenuItems();
protected String getExitItemText() {
return "Back";
}
protected final void add(ConsoleMenuItem menuItem) {
items.add(menuItem);
}
public final void open() {
items.clear();
addMenuItems();
this.exited = false;
while (!exited) {
show();
}
onMenuExit();
}
private final void show() {
print();
print(getInstruction());
print();
// print normal items
for (int i = 0; i < items.size(); ++i) {
print(String.format("\t[%s] %s", i + 1, items.get(i).getDisplayText()));
}
// print exit item
print(String.format("\n\t[%s] %s", EXIT_TOKEN, getExitItemText()));
// evaluate input
String input;
boolean validInput = false;
while (!validInput) {
input = awaitStringParameter();
if (input.equalsIgnoreCase(EXIT_TOKEN)) {
validInput = true;
exit();
} else {
try {
int chosen = Integer.valueOf(input);
if (chosen > items.size() || chosen < 1) {
printError(String.format("Invalid option. Please select an option from 1 to %s.", items.size()));
validInput = false;
} else {
items.get(chosen - 1).invoke();
validInput = true;
}
} catch (NumberFormatException e) {
printError(String
.format("This was not a valid input. Please select an option from 1 to %s or press '%s' to exit this menu.",
items.size(), EXIT_TOKEN));
validInput = false;
}
}
}
}
public static String awaitStringParameter() {
// do not close input
@SuppressWarnings("resource")
Scanner input = new Scanner(System.in);
String parameter = null;
boolean success = false;
while (!success) {
try {
parameter = input.next();
success = true;
} catch (Exception e) {
printError("Exception while parsing the parameter: " + e.getMessage());
}
}
return parameter;
}
public static int awaitIntParameter() {
boolean success = false;
int number = 0;
while (!success) {
try {
number = Integer.parseInt(awaitStringParameter());
success = true;
} catch (NumberFormatException e) {
printError("This was not a number... Try again!");
}
}
return number;
}
public static boolean awaitBooleanParameter() {
return Boolean.parseBoolean(awaitStringParameter());
}
public static void print() {
System.out.println();
}
public static void print(String message) {
System.out.println(message);
}
public static void printError(Throwable error) {
if (error.getMessage().isEmpty()) {
printError("An exception has been thrown: ");
error.printStackTrace();
} else {
printError(String.format("An exception has been thrown: %s", error.getMessage()));
}
}
public static void printError(String errorMsg) {
System.err.println(errorMsg);
}
protected void exit() {
exited = true;
}
protected void onMenuExit() {
// do nothing by default
}
protected abstract String getInstruction();
}