*/\r
package org.mxchange.addressbook.client.console;\r
\r
+import java.text.MessageFormat;\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.UnhandledUserChoiceException;\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.contact.Contact;\r
import org.mxchange.addressbook.menu.Menu;\r
import org.mxchange.addressbook.menu.MenuTools;\r
import org.mxchange.addressbook.menu.console.ConsoleMenu;\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
// 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
+ this.fillMenuMap();\r
}\r
\r
/**\r
- * Displays textural message to the user\r
- * @param message \r
+ * Displays a textual address "box" of given contact\r
+ *\r
+ * @param contact Contact to show address for\r
+ * @todo Use mask\r
*/\r
@Override\r
- public void displayMessage (final String message) {\r
- System.out.println(message);\r
+ public void displayAddressBox (final Contact contact) {\r
+ // Simple display ...\r
+ // @todo Use mask\r
+ this.outputMessage("Strasse, PLZ Ort, Land: " + contact.getStreet() + "\n" + contact.getZipCode() + " " + contact.getCity() + "\n" + contact.getCountryCode());\r
+ }\r
+\r
+ /**\r
+ * Displays a textual name "box" of given contact\r
+ *\r
+ * @param contact Contact to show name for\r
+ */\r
+ @Override\r
+ public void displayNameBox (final Contact contact) {\r
+ // Get translated gender as the user may want to see "Mr.", "Mrs."\r
+ String gender = contact.getTranslatedGender();\r
+\r
+ // Get company name\r
+ String companyName = contact.getCompanyName();\r
+\r
+ // If it is empty/null, then assume private contact\r
+ if ((companyName == null) || (companyName.isEmpty())) {\r
+ // Now put all together: gender, surname, family name\r
+ // @todo Use mask\r
+ this.outputMessage("Anrede, Vorname, Name: " + gender + " " + contact.getSurname() + " " + contact.getFamilyName());\r
+ } else {\r
+ // Company contact\r
+ this.outputMessage("Firma: " + companyName + "\nAnsprechpartner: " + gender + " " + contact.getSurname() + " " + contact.getFamilyName());\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Displays a textual other data "box" of given contact\r
+ *\r
+ * @param contact Contact to show other data for\r
+ */\r
+ @Override\r
+ public void displayOtherDataBox (final Contact contact) {\r
+ // Cellphone and such ...\r
+ this.outputMessage("Telefonnumer: " + contact.getPhoneNumber() + "\nFaxnummer: " + contact.getFaxNumber() + "\nHandy: " + contact.getCellphoneNumber() + "\nKommentar:\n" + contact.getComment());\r
}\r
\r
@Override\r
- public void doUserChoice () throws Exception {\r
+ public void doUserMenuChoice () throws UnhandledUserChoiceException {\r
// Get all access keys from menu\r
- char[] accessKeys = MenuTools.getAccessKeysFromMenuMap(this.menus, this.getCurrentMenu());\r
+ char[] accessKeys = MenuTools.getAccessKeysFromMenuMap(this.getMenus(), 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
+ char choice = this.enterChar(accessKeys, "Bitte Auswahl eingeben (0=Programm beenden): ");\r
\r
// @TODO Rewrite this ugly switch() block\r
switch (choice) {\r
case '1': // Enter/add own data\r
- this.getContactManager().enterOwnData();\r
+ this.getContactManager().doEnterOwnData();\r
break;\r
\r
case '2': // Change own data\r
this.getContactManager().addOtherAddress();\r
break;\r
\r
- case '4': // Change other addess\r
+ case '4': // List contacts\r
+ this.getContactManager().listContacts();\r
+ break;\r
+ \r
+ case '5': // Search addresses\r
+ this.getContactManager().searchContacts();\r
+ break;\r
+\r
+ case '6': // Change other addess\r
this.getContactManager().changeOtherAddress();\r
break;\r
\r
- case '5': // Delete other address\r
+ case '7': // Delete other address\r
this.getContactManager().deleteOtherAddress();\r
break;\r
\r
break;\r
\r
default:\r
- // @TODO throw on exception\r
- throw new Exception("choice " + choice + " invalid");\r
+ // @TODO throw own exception\r
+ throw new UnhandledUserChoiceException("Choice '" + choice + "' not handled yet.");\r
}\r
}\r
\r
return input;\r
}\r
\r
+ /**\r
+ * Reads an integer (int) with a textural message from the user\r
+ * \r
+ * @param minimum Minimum allowed number\r
+ * @param maximum Maximum allowed number\r
+ * @param message Messager to display in console\r
+ * @return \r
+ */\r
+ @Override\r
+ public int enterInt (final int minimum, final int maximum, final String message) {\r
+ // Minimum should not be below zero\r
+ assert(minimum >= 0);\r
+ assert(maximum > minimum);\r
+\r
+ // Init input\r
+ int input = -1;\r
+\r
+ while ((input < minimum) || (input > maximum)) {\r
+ // Output message\r
+ System.out.print(message);\r
+\r
+ // Read integer from user\r
+ input = this.readInt();\r
+ }\r
+\r
+ // Return it\r
+ return input;\r
+ }\r
+\r
/**\r
* Reads a string of minimum and maximum length from the user\r
+ * \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
+ * @param allowEmpty Whether to allow empty string\r
+ * @return Entered string by user or null for empty strings\r
*/\r
@Override\r
- public String enterString (final int minLength, final int maxLength, final String message) {\r
+ public String enterString (final int minLength, final int maxLength, final String message, final boolean allowEmpty) {\r
+ // Check on length, e.g. country codes are excactly 2 chars long\r
+ assert(maxLength >= minLength);\r
+\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
+ while (((input == null) || ((input.length() < minLength) && (!allowEmpty))) || ((input.length() > 0) && (input.length() < minLength) && (allowEmpty)) || ((input instanceof String) && (input.length() > maxLength))) {\r
// Output message\r
System.out.print(message);\r
\r
return new ConsoleMenuItem(accessKey,text);\r
}\r
\r
+ /**\r
+ * Displays textural message to the user\r
+ * @param message\r
+ */\r
+ @Override\r
+ public void outputMessage (final String message) {\r
+ System.out.println(message);\r
+ }\r
+\r
/**\r
* Shows textural menu on console\r
*/\r
this.showMenu(this.getCurrentMenu());\r
}\r
\r
+ /**\r
+ * Shows given menu entry to user\r
+ * \r
+ * @param item Menu entry\r
+ */\r
@Override\r
public void showEntry (final SelectableMenuItem item) {\r
// Access key then text\r
- this.displayMessage("[" + item.getAccessKey() + "] " + item.getText());\r
+ this.outputMessage("[" + item.getAccessKey() + "] " + item.getText());\r
}\r
\r
/**\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
+ this.outputMessage("Welcome to " + AddressbookApplication.APP_TITLE + " v" + AddressbookApplication.APP_VERSION);\r
+ this.outputMessage("");\r
+ this.outputMessage("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
- * "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
+ @Override\r
+ public void userChooseChangeContactData (final Contact contact) throws UnhandledUserChoiceException {\r
+ // Ask the user for editing [name], [a]ddress or [other] data\r
+ char choice = this.enterChar(new char[]{'n', 'a', 'o', 'x'}, "Welchen Daten möchten Sie ändern? (n=Namensdaten, a=Anschriftsdaten, o=Andere, x=Zurück zur Hauptauswahl) ");\r
\r
- // Return it\r
- return menu;\r
+ // @TODO Get rid of this ugly switch block, too\r
+ switch (choice) {\r
+ case 'n': // Name data\r
+ this.getContactManager().doChangeNameData(contact, this);\r
+ break;\r
+ \r
+ case 'a': // Address data\r
+ this.getContactManager().doChangeAddressData(contact, this);\r
+ break;\r
+ \r
+ case 'o': // Other data\r
+ this.getContactManager().doChangeOtherData(contact, this);\r
+ break;\r
+ \r
+ case 'x': // Exit this menu\r
+ // Ignored as it should go back\r
+ break;\r
+ \r
+ default:\r
+ // @TODO throw own exception\r
+ throw new UnhandledUserChoiceException("Choice '" + choice + "' not handled yet.");\r
+ }\r
}\r
\r
/**\r
* Reads one character\r
- * @return \r
+ * \r
+ * @return A single character\r
*/\r
private char readChar () {\r
// Read line\r
return input.charAt(0);\r
}\r
\r
+ /**\r
+ * Reads an integer (int) from user\r
+ * \r
+ * @return An integer number\r
+ */\r
+ private int readInt () {\r
+ // First read a string\r
+ String input = this.readString();\r
+\r
+ // Init number with invalid value\r
+ int num = -1;\r
+\r
+ // Parse number, this can be risky\r
+ try {\r
+ num = Integer.parseInt(input);\r
+ } catch (final NumberFormatException e) {\r
+ this.outputMessage("Bitte geben Sie nur Zahlen ein!");\r
+ this.getLogger().warn(MessageFormat.format("No numbers-only entered. input={0},message={1}", input, e.getMessage()));\r
+ }\r
+\r
+ // Return read number\r
+ return num;\r
+ }\r
+\r
/**\r
* Reads a string from a scanner until RETURN is pressed\r
* \r
}\r
\r
/**\r
- * Shows given menu\r
- *\r
- * @param menuType Given menu to show\r
+ * Fills menu map with menu entries\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
+ @Override\r
+ protected final void fillMenuMap () {\r
+ // Initialize first (main) menu\r
+ Menu menu = new ConsoleMenu("main", this);\r
\r
- // Show menu\r
- menu.show(this);\r
+ // Add it\r
+ this.getMenus().put("main", menu);\r
}\r
}\r