+/*\r
+ * Copyright (C) 2015 Roland Haeder\r
+ *\r
+ * This program is free software: you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation, either version 3 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.\r
+ */\r
+package org.mxchange.addressbook.client.console;\r
+\r
+import java.util.Arrays;\r
+import java.util.HashMap;\r
+import java.util.Map;\r
+import java.util.Scanner;\r
+import org.mxchange.addressbook.application.AddressbookApplication;\r
+import org.mxchange.addressbook.application.Application;\r
+import org.mxchange.addressbook.client.BaseClient;\r
+import org.mxchange.addressbook.client.Client;\r
+import org.mxchange.addressbook.menu.Menu;\r
+import org.mxchange.addressbook.menu.MenuTools;\r
+import org.mxchange.addressbook.menu.console.ConsoleMenu;\r
+import org.mxchange.addressbook.menu.item.SelectableMenuItem;\r
+import org.mxchange.addressbook.menu.item.console.ConsoleMenuItem;\r
+\r
+/**\r
+ * A client for the console\r
+ *\r
+ * @author Roland Haeder\r
+ */\r
+public class ConsoleClient extends BaseClient implements Client {\r
+ /**\r
+ * Menu system\r
+ */\r
+ private final Map<String, Menu> menus;\r
+\r
+ /**\r
+ * Scanner instance for reading data from console input\r
+ */\r
+ private final Scanner scanner;\r
+\r
+ /**\r
+ * Parameterless constructor\r
+ * @param application An instance of an Application class\r
+ */\r
+ public ConsoleClient (final Application application) {\r
+ super();\r
+\r
+ // Set application instance\r
+ this.setApplication(application);\r
+\r
+ // Init contact manager here\r
+ this.initContactManager(this);\r
+\r
+ // Init scanner instance\r
+ this.scanner = new Scanner(System.in);\r
+\r
+ // Init menu map\r
+ this.menus = new HashMap<>(10);\r
+\r
+ // Fill menu map\r
+ this.fillConsoleMenuMap();\r
+ }\r
+\r
+ /**\r
+ * Displays textural message to the user\r
+ * @param message \r
+ */\r
+ @Override\r
+ public void displayMessage (final String message) {\r
+ System.out.println(message);\r
+ }\r
+\r
+ @Override\r
+ public void doUserChoice () throws Exception {\r
+ // Get all access keys from menu\r
+ char[] accessKeys = MenuTools.getAccessKeysFromMenuMap(this.menus, this.getCurrentMenu());\r
+\r
+ // Output textural message and ask for a char as input\r
+ char choice = this.enterChar(accessKeys, "Bitte Auswahl eingeben (0=Beenden/Zurück in's vorherhige Menü): ");\r
+\r
+ // @TODO Rewrite this ugly switch() block\r
+ switch (choice) {\r
+ case '1': // Enter/add own data\r
+ this.getContactManager().enterOwnData();\r
+ break;\r
+ \r
+ case '2': // Change own data\r
+ this.getContactManager().changeOwnData();\r
+ break;\r
+ \r
+ case '3': // Add new addess\r
+ this.getContactManager().addOtherAddress();\r
+ break;\r
+ \r
+ case '4': // Change other addess\r
+ this.getContactManager().changeOtherAddress();\r
+ break;\r
+ \r
+ case '5': // Delete other address\r
+ this.getContactManager().deleteOtherAddress();\r
+ break;\r
+\r
+ case '0': // Program exit\r
+ this.disableIsRunning();\r
+ break;\r
+ \r
+ default:\r
+ // @TODO throw on exception\r
+ throw new Exception("choice " + choice + " invalid");\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Asks the the user to enter a single character which must match validChars\r
+ * @param validChars Valid chars that are accepted\r
+ * @param message Message to user\r
+ * @return Allowed character\r
+ */\r
+ @Override\r
+ public char enterChar (final char[] validChars, final String message) {\r
+ char input = 0;\r
+\r
+ // Sort array, else binarySearch() won't work\r
+ Arrays.sort(validChars);\r
+\r
+ // Keep asking until valid char has been entered\r
+ while (Arrays.binarySearch(validChars, input) < 0) {\r
+ // Output message\r
+ System.out.print(message);\r
+\r
+ // Read char\r
+ input = this.readChar();\r
+ }\r
+\r
+ // Return read char\r
+ return input;\r
+ }\r
+\r
+ /**\r
+ * Reads a string of minimum and maximum length from the user\r
+ * @param minLength Minimum length of the string to read\r
+ * @param maxLength Maximum length of the string to read\r
+ * @param message Message to user\r
+ * @return \r
+ */\r
+ @Override\r
+ public String enterString (final int minLength, final int maxLength, final String message) {\r
+ // Init input\r
+ String input = null;\r
+\r
+ // Check if it is to short or to long\r
+ while ((input == null) || (input.length() < minLength) || (input.length() > maxLength)) {\r
+ // Output message\r
+ System.out.print(message);\r
+\r
+ // Read line\r
+ input = this.readString();\r
+ }\r
+\r
+ // Return it\r
+ return input;\r
+ }\r
+\r
+ /**\r
+ * Returns a console menu item\r
+ * \r
+ * @param accessKey Key to access the menu\r
+ * @param text Text to show to user\r
+ * @return A SelectableMenuItem\r
+ * @todo Make sure the access key is unique\r
+ */\r
+ @Override\r
+ public SelectableMenuItem getMenuItem (final char accessKey, final String text) {\r
+ // Return a new console menu item\r
+ return new ConsoleMenuItem(accessKey,text);\r
+ }\r
+\r
+ /**\r
+ * Shows textural menu on console\r
+ */\r
+ @Override\r
+ public void showCurrentMenu () {\r
+ this.showMenu(this.getCurrentMenu());\r
+ }\r
+\r
+ @Override\r
+ public void showEntry (final SelectableMenuItem item) {\r
+ // Access key then text\r
+ this.displayMessage("[" + item.getAccessKey() + "] " + item.getText());\r
+ }\r
+\r
+ /**\r
+ * Shows a textural message to the user\r
+ */\r
+ @Override\r
+ public void showWelcome () {\r
+ this.displayMessage("Welcome to " + AddressbookApplication.APP_TITLE + " v" + AddressbookApplication.APP_VERSION);\r
+ this.displayMessage("");\r
+ this.displayMessage("Copyright(c) 2015 by Roland Haeder, this is free software");\r
+ \r
+ // Debug message\r
+ this.getLogger().debug("Intro shown to user");\r
+ }\r
+\r
+ /**\r
+ * Fills menu map with menu entries\r
+ */\r
+ private void fillConsoleMenuMap () {\r
+ // Initialize first (main) menu\r
+ Menu menu = new ConsoleMenu("main", this);\r
+\r
+ // Add it\r
+ this.menus.put("main", menu);\r
+ }\r
+\r
+ /**\r
+ * "Getter" for given menu type\r
+ * \r
+ * @param menuType Menu type instance to return\r
+ * @return Menu or null if not found\r
+ */\r
+ private Menu getMenu (final String menuType) {\r
+ // Default is not found\r
+ Menu menu = null;\r
+\r
+ // Check array\r
+ if (this.menus.containsKey(menuType)) {\r
+ // Found!\r
+ menu = this.menus.get(menuType);\r
+ }\r
+ \r
+ // Return it\r
+ return menu;\r
+ }\r
+\r
+ /**\r
+ * Reads one character\r
+ * @return \r
+ */\r
+ private char readChar () {\r
+ // Read line\r
+ String input = this.scanner.nextLine();\r
+\r
+ // This must be only one character\r
+ if (input.length() != 1) {\r
+ // Return zero\r
+ return 0;\r
+ }\r
+\r
+ // Get char from first (and only) position\r
+ return input.charAt(0);\r
+ }\r
+\r
+ /**\r
+ * Reads a string from a scanner until RETURN is pressed\r
+ * \r
+ * @return Read string from scanner\r
+ */\r
+ private String readString () {\r
+ return this.scanner.nextLine();\r
+ }\r
+\r
+ /**\r
+ * Shows given menu\r
+ *\r
+ * @param menuType Given menu to show\r
+ */\r
+ private void showMenu (final String menuType) {\r
+ Menu menu = this.getMenu(menuType);\r
+ \r
+ // Is the menu set?\r
+ if (!(menu instanceof Menu)) {\r
+ // Not found\r
+ // @todo Own exception?\r
+ throw new NullPointerException("Menu '" + menuType + "' not found.");\r
+ }\r
+ \r
+ // Show menu\r
+ menu.show(this);\r
+ }\r
+}\r