X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2Forg%2Fmxchange%2Faddressbook%2Fclient%2Fconsole%2FConsoleClient.java;h=d53c53b168ce36b02952b3301cab4ea708d391cf;hb=015fbc4cc69c0bdbb644da6bab24133290e9ca68;hp=b97600e42d1643e88202ac0868b2f37454524a39;hpb=31fce847a127086ff40fa9b4edde6137a8ef7e3f;p=addressbook-swing.git diff --git a/src/org/mxchange/addressbook/client/console/ConsoleClient.java b/src/org/mxchange/addressbook/client/console/ConsoleClient.java index b97600e..d53c53b 100644 --- a/src/org/mxchange/addressbook/client/console/ConsoleClient.java +++ b/src/org/mxchange/addressbook/client/console/ConsoleClient.java @@ -1,505 +1,659 @@ -/* - * Copyright (C) 2015 Roland Haeder - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.mxchange.addressbook.client.console; - -import java.text.MessageFormat; -import java.util.Arrays; -import java.util.Scanner; -import org.mxchange.addressbook.UnhandledUserChoiceException; -import org.mxchange.addressbook.application.AddressbookApplication; -import org.mxchange.addressbook.application.Application; -import org.mxchange.addressbook.client.BaseClient; -import org.mxchange.addressbook.client.Client; -import org.mxchange.addressbook.contact.Contact; -import org.mxchange.addressbook.contact.user.UserContact; -import org.mxchange.addressbook.menu.Menu; -import org.mxchange.addressbook.menu.MenuTools; -import org.mxchange.addressbook.menu.console.ConsoleMenu; -import org.mxchange.addressbook.menu.item.SelectableMenuItem; -import org.mxchange.addressbook.menu.item.console.ConsoleMenuItem; - -/** - * A client for the console - * - * @author Roland Haeder - */ -public class ConsoleClient extends BaseClient implements Client { - /** - * Scanner instance for reading data from console input - */ - private final Scanner scanner; - - /** - * Parameterless constructor - * @param application An instance of an Application class - */ - public ConsoleClient (final Application application) { - super(); - - // Set application instance - this.setApplication(application); - - // Init scanner instance - this.scanner = new Scanner(System.in); - } - - /** - * Displays a textual address "box" of given contact - * - * @param contact Contact to show address for - */ - @Override - public void displayAddressBox (final Contact contact) { - // Simple display ... - this.outputMessage(MessageFormat.format("Strasse, PLZ Ort, Land: {0}\n{1} {2}\n{3}", contact.getStreet(), contact.getZipCode(), contact.getCity(), contact.getCountryCode())); - } - - /** - * Displays a textual name "box" of given contact - * - * @param contact Contact to show name for - */ - @Override - public void displayNameBox (final Contact contact) { - // Get translated gender as the user may want to see "Mr.", "Mrs." - String gender = contact.getTranslatedGender(); - - // Get company name - String companyName = contact.getCompanyName(); - - // If it is empty/null, then assume private contact - if ((companyName == null) || (companyName.isEmpty())) { - // Now put all together: gender, surname, family name - // @todo Use mask - this.outputMessage(MessageFormat.format("Anrede, Vorname, Name: {0} {1} {2}", gender, contact.getSurname(), contact.getFamilyName())); - } else { - // Company contact - this.outputMessage(MessageFormat.format("Firma: {0}\nAnsprechpartner: {1} {2} {3}", companyName, gender, contact.getSurname(), contact.getFamilyName())); - } - } - - /** - * Displays a textual other data "box" of given contact - * - * @param contact Contact to show other data for - */ - @Override - public void displayOtherDataBox (final Contact contact) { - // Cellphone and such ... - this.outputMessage(MessageFormat.format("Telefonnumer: {0}\nFaxnummer: {1}\nHandy: {2}\nKommentar:\n{3}", contact.getPhoneNumber(), contact.getFaxNumber(), contact.getCellphoneNumber(), contact.getComment())); - } - - @Override - public void doChangeOwnAddressData (final Contact contact) { - // Make sure it is own contact - if (!contact.isOwnContact()) { - // Not own contact - throw new IllegalArgumentException("Contact is not own data."); - } - - // Own address data - String street = this.getContactManager().enterOwnStreet(); - - // Get zip code - int zipCode = this.getContactManager().enterOwnZipCode(); - - // Get city name - String city = this.getContactManager().enterOwnCity(); - - // Get country code - String countryCode = this.getContactManager().enterOwnCountryCode(); - - // Update address data - contact.updateAddressData(street, zipCode, city, countryCode); - } - - @Override - public void doChangeOwnNameData (final Contact contact) { - // Make sure it is own contact - if (!contact.isOwnContact()) { - // Not own contact - throw new IllegalArgumentException("Contact is not own data."); - } - - // Gender: - char gender = this.getContactManager().enterOwnGender(); - - // Surname - String surname = this.getContactManager().enterOwnSurname(); - - // Family name - String familyName = this.getContactManager().enterOwnFamilyName(); - - // And company - String companyName = this.getContactManager().enterOwnCompanyName(); - - // Update contact instance - contact.updateNameData(gender, surname, familyName, companyName); - } - - @Override - public void doChangeOwnOtherData (final Contact contact) { - // Make sure it is own contact - if (!contact.isOwnContact()) { - // Not own contact - throw new IllegalArgumentException("Contact is not own data."); - } - - // Phone number - String phoneNumber = this.getContactManager().enterOwnPhoneNumber(); - - // Phone number - String cellNumber = this.getContactManager().enterOwnCellNumber(); - - // Fax number - String faxNumber = this.getContactManager().enterOwnFaxNumber(); - - // Email address - String email = this.getContactManager().enterOwnEmailAddress(); - - // Comment - String comment = this.getContactManager().enterOwnComment(); - - // Update contact instance - contact.updateOtherData(phoneNumber, cellNumber, faxNumber, email, null, comment); - } - - @Override - public Contact doEnterOwnData () { - // First ask for gender - char gender = this.getContactManager().enterOwnGender(); - - // 2nd for surname - String surname = this.getContactManager().enterOwnSurname(); - - // And 3rd for family name - String familyName = this.getContactManager().enterOwnFamilyName(); - - // Company name ... - String companyName = this.getContactManager().enterOwnCompanyName(); - - // Construct UserContact instance - Contact contact = new UserContact(gender, surname, familyName, companyName); - - // And return object - return contact; - } - - /** - * Shutdown this client - */ - @Override - public void doShutdown () { - // Parent call - super.doShutdown(); - - // @TODO Add other shutdown stuff - } - - @Override - public void doUserMenuChoice () throws UnhandledUserChoiceException { - // Get all access keys from menu - char[] accessKeys = MenuTools.getAccessKeysFromMenuMap(this.getMenus(), this.getCurrentMenu()); - - // Output textural message and ask for a char as input - char choice = this.enterChar(accessKeys, "Bitte Auswahl eingeben (0=Programm beenden): "); - - // @TODO Rewrite this ugly switch() block - switch (choice) { - case '1': // Enter/add own data - this.getContactManager().doEnterOwnData(); - break; - - case '2': // Change own data - this.getContactManager().changeOwnData(); - break; - - case '3': // Add new addess - this.getContactManager().addOtherAddress(); - break; - - case '4': // List contacts - this.getContactManager().listContacts(); - break; - - case '5': // Search addresses - this.getContactManager().searchContacts(); - break; - - case '6': // Change other addess - this.getContactManager().changeOtherAddress(); - break; - - case '7': // Delete other address - this.getContactManager().deleteOtherAddress(); - break; - - case '0': // Program exit - this.getApplication().doShutdown(); - break; - - default: - // @TODO throw own exception - throw new UnhandledUserChoiceException(MessageFormat.format("Choice '{0}' not handled yet.", choice)); - } - } - - /** - * Asks the the user to enter a single character which must match validChars - * @param validChars Valid chars that are accepted - * @param message Message to user - * @return Allowed character - */ - @Override - public char enterChar (final char[] validChars, final String message) { - char input = 0; - - // Sort array, else binarySearch() won't work - Arrays.sort(validChars); - - // Keep asking until valid char has been entered - while (Arrays.binarySearch(validChars, input) < 0) { - // Output message - System.out.print(message); - - // Read char - input = this.readChar(); - } - - // Return read char - return input; - } - - /** - * Reads an integer (int) with a textural message from the user - * - * @param minimum Minimum allowed number - * @param maximum Maximum allowed number - * @param message Messager to display in console - * @return - */ - @Override - public int enterInt (final int minimum, final int maximum, final String message) { - // Minimum should not be below zero - assert(minimum >= 0); - assert(maximum > minimum); - - // Init input - int input = -1; - - while ((input < minimum) || (input > maximum)) { - // Output message - System.out.print(message); - - // Read integer from user - input = this.readInt(); - } - - // Return it - return input; - } - - /** - * Reads a string of minimum and maximum length from the user - * - * @param minLength Minimum length of the string to read - * @param maxLength Maximum length of the string to read - * @param message Message to user - * @param allowEmpty Whether to allow empty string - * @return Entered string by user or null for empty strings - */ - @Override - public String enterString (final int minLength, final int maxLength, final String message, final boolean allowEmpty) { - // Check on length, e.g. country codes are excactly 2 chars long - assert(maxLength >= minLength); - - // Init input - String input = null; - - // Check if it is to short or to long - while (((input == null) || ((input.length() < minLength) && (!allowEmpty))) || ((input.length() > 0) && (input.length() < minLength) && (allowEmpty)) || ((input instanceof String) && (input.length() > maxLength))) { - // Output message - System.out.print(message); - - // Read line - input = this.readString(); - } - - // Return it - return input; - } - - /** - * Returns a console menu item - * - * @param accessKey Key to access the menu - * @param text Text to show to user - * @return A SelectableMenuItem - * @todo Make sure the access key is unique - */ - @Override - public SelectableMenuItem getMenuItem (final char accessKey, final String text) { - // Return a new console menu item - return new ConsoleMenuItem(accessKey,text); - } - - /** - * Inizializes this client - */ - @Override - public void initClient () { - // Init contact manager here - this.initContactManager(); - - // Fill menu map - this.fillMenuMap(); - } - - /** - * Displays textural message to the user - * @param message - */ - @Override - public void outputMessage (final String message) { - System.out.println(message); - } - - /** - * Shows textural menu on console - */ - @Override - public void showCurrentMenu () { - this.showMenu(this.getCurrentMenu()); - } - - /** - * Shows given menu entry to user - * - * @param item Menu entry - */ - @Override - public void showEntry (final SelectableMenuItem item) { - // Access key then text - this.outputMessage("[" + item.getAccessKey() + "] " + item.getText()); - } - - /** - * Shows a textural message to the user - */ - @Override - public void showWelcome () { - this.outputMessage(MessageFormat.format("Welcome to {0}", AddressbookApplication.printableTitle())); - this.outputMessage(""); - this.outputMessage("Copyright(c) 2015 by Roland Haeder, this is free software"); - - // Debug message - this.getLogger().debug("Intro shown to user"); - } - - @Override - public void userChooseChangeContactData (final Contact contact) throws UnhandledUserChoiceException { - // Ask the user for editing [name], [a]ddress or [other] data - 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) "); - - // @TODO Get rid of this ugly switch block, too - switch (choice) { - case 'n': // Name data - this.getContactManager().doChangeNameData(contact, this); - break; - - case 'a': // Address data - this.getContactManager().doChangeAddressData(contact, this); - break; - - case 'o': // Other data - this.getContactManager().doChangeOtherData(contact, this); - break; - - case 'x': // Exit this menu - // Ignored as it should go back - break; - - default: - // @TODO throw own exception - throw new UnhandledUserChoiceException(MessageFormat.format("Choice '{0}' not handled yet.", choice)); - } - } - - /** - * Reads one character - * - * @return A single character - */ - private char readChar () { - // Read line - String input = this.scanner.nextLine(); - - // This must be only one character - if (input.length() != 1) { - // Return zero - return 0; - } - - // Get char from first (and only) position - return input.charAt(0); - } - - /** - * Reads an integer (int) from user - * - * @return An integer number - */ - private int readInt () { - // First read a string - String input = this.readString(); - - // Init number with invalid value - int num = -1; - - // Parse number, this can be risky - try { - num = Integer.parseInt(input); - } catch (final NumberFormatException e) { - this.outputMessage("Bitte geben Sie nur Zahlen ein!"); - this.getLogger().warn(MessageFormat.format("No numbers-only entered. input={0},message={1}", input, e.getMessage())); - } - - // Return read number - return num; - } - - /** - * Reads a string from a scanner until RETURN is pressed - * - * @return Read string from scanner - */ - private String readString () { - return this.scanner.nextLine(); - } - - /** - * Fills menu map with menu entries - */ - @Override - protected final void fillMenuMap () { - // Initialize first (main) menu - Menu menu = new ConsoleMenu("main", this); - - // Add it - this.getMenus().put("main", menu); - } -} +/* + * Copyright (C) 2016 Roland Haeder + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.mxchange.addressbook.client.console; + +import java.io.IOException; +import java.sql.SQLException; +import java.text.MessageFormat; +import java.util.Arrays; +import java.util.Scanner; +import org.mxchange.addressbook.application.AddressbookApplication; +import org.mxchange.addressbook.client.AddressbookClient; +import org.mxchange.addressbook.client.BaseAddressbookClient; +import org.mxchange.addressbook.facade.contact.ContactFacade; +import org.mxchange.addressbook.menu.Menu; +import org.mxchange.addressbook.menu.MenuTools; +import org.mxchange.addressbook.menu.console.ConsoleMenu; +import org.mxchange.addressbook.menu.item.SelectableMenuItem; +import org.mxchange.addressbook.menu.item.console.ConsoleMenuItem; +import org.mxchange.jcontacts.contact.Contact; +import org.mxchange.jcontacts.contact.UserContact; +import org.mxchange.jcontacts.contact.gender.Gender; +import org.mxchange.jcontacts.contact.gender.GenderUtils; +import org.mxchange.jcontacts.exceptions.ContactAlreadyAddedException; +import org.mxchange.jcore.application.Application; +import org.mxchange.jcore.exceptions.MenuInitializationException; +import org.mxchange.jcore.exceptions.UnhandledUserChoiceException; +import org.mxchange.jcountry.data.Country; +import org.mxchange.jphone.phonenumbers.cellphone.DialableCellphoneNumber; +import org.mxchange.jphone.phonenumbers.fax.DialableFaxNumber; +import org.mxchange.jphone.phonenumbers.landline.DialableLandLineNumber; + +/** + * A client for the console + *

+ * @author Roland Haeder + */ +public class ConsoleClient extends BaseAddressbookClient implements AddressbookClient { + + /** + * Scanner instance for reading data from console input + */ + private final Scanner scanner; + + /** + * Parameterless constructor + *

+ * @param application An instance of an Application class + */ + public ConsoleClient (final Application application) { + // Trace message + this.getLoggerBeanLocal().logTrace(MessageFormat.format("application={0} - CALLED!", application)); //NOI18N + + // Set application instance + this.setApplication(application); + + // Init scanner instance + this.scanner = new Scanner(System.in, "UTF-8"); //NOI18N + + // Trace message + this.getLoggerBeanLocal().logTrace("EXIT!"); //NOI18N + } + + @Override + public void displayAddressBox (final Contact contact) { + // Trace message + this.getLoggerBeanLocal().logTrace(MessageFormat.format("contact={0} - CALLED!", contact)); //NOI18N + + // Is it null? + if (null == contact) { + // Abort here + throw new NullPointerException("contact is null"); //NOI18N + } + + // Simple display ... + this.outputMessage(MessageFormat.format("Strasse, PLZ Ort, Land: {0}\n{1} {2}\n{3}", contact.getContactStreet(), contact.getContactZipCode(), contact.getContactCity(), contact.getContactCountry())); + + // Trace message + this.getLoggerBeanLocal().logTrace("EXIT!"); //NOI18N + } + + @Override + public void displayNameBox (final Contact contact) { + // Trace message + this.getLoggerBeanLocal().logTrace(MessageFormat.format("contact={0} - CALLED!", contact)); //NOI18N + + // Is it null? + if (null == contact) { + // Abort here + throw new NullPointerException("contact is null"); //NOI18N + } + + // Get translated gender as the user may want to see "Mr.", "Mrs." + String gender = GenderUtils.getTranslatedGender(contact); + + // Now put all together: gender, surname, family name + this.outputMessage(MessageFormat.format("Anrede, Vorname, Name: {0} {1} {2}", gender, contact.getContactFirstName(), contact.getContactFamilyName())); + + // Trace message + this.getLoggerBeanLocal().logTrace("EXIT!"); //NOI18N + } + + @Override + public void displayOtherDataBox (final Contact contact) { + // Trace message + this.getLoggerBeanLocal().logTrace(MessageFormat.format("contact={0} - CALLED!", contact)); //NOI18N + + // Is it null? + if (null == contact) { + // Abort here + throw new NullPointerException("contact is null"); //NOI18N + } + + // Cellphone and such ... + this.outputMessage(MessageFormat.format("Telefonnumer: {0}\nFaxnummer: {1}\nHandy: {2}\nKommentar:\n{3}", contact.getContactPhoneNumber(), contact.getContactFaxNumber(), contact.getContactCellphoneNumber(), contact.getContactComment())); + + // Trace message + this.getLoggerBeanLocal().logTrace("EXIT!"); //NOI18N + } + + @Override + public void doChangeOwnAddressData (final Contact contact) { + // Trace message + this.getLoggerBeanLocal().logTrace(MessageFormat.format("contact={0} - CALLED!", contact)); //NOI18N + + // Is it null? + if (null == contact) { + // Abort here + throw new NullPointerException("contact is null"); //NOI18N + } + + // Make sure it is own contact + if (!contact.isOwnContact()) { + // Not own contact + throw new IllegalArgumentException("Contact is not own data."); //NOI18N + } + + // Get manager and cast it + ContactFacade manager = (ContactFacade) this.getFacade(); + + // Own street and number + String streetNumber = manager.enterOwnStreet(); + + // Get zip code + Integer zipCode = manager.enterOwnZipCode(); + + // Get city name + String city = manager.enterOwnCity(); + + // Get country code + Country country = manager.enterOwnCountryCode(); + + // Update address data + contact.setContactStreet(streetNumber); + contact.setContactZipCode(zipCode); + contact.setContactCity(city); + contact.setContactCountry(country); + + // Trace message + this.getLoggerBeanLocal().logTrace("EXIT!"); //NOI18N + } + + @Override + public void doChangeOwnNameData (final Contact contact) { + // Trace message + this.getLoggerBeanLocal().logTrace(MessageFormat.format("contact={0} - CALLED!", contact)); //NOI18N + + // Is it null? + if (null == contact) { + // Abort here + throw new NullPointerException("contact is null"); //NOI18N + } + + // Make sure it is own contact + if (!contact.isOwnContact()) { + // Not own contact + throw new IllegalArgumentException("Contact is not own data."); //NOI18N + } + + // Get manager and cast it + ContactFacade manager = (ContactFacade) this.getFacade(); + + // Gender: + Gender gender = manager.enterOwnGender(); + + // Surname + String firstName = manager.enterOwnFirstName(); + + // Family name + String familyName = manager.enterOwnFamilyName(); + + // Update contact instance + contact.setContactGender(gender); + contact.setContactFirstName(firstName); + contact.setContactFamilyName(familyName); + + // Trace message + this.getLoggerBeanLocal().logTrace("EXIT!"); //NOI18N + } + + @Override + public void doChangeOwnOtherData (final Contact contact) { + // Trace message + this.getLoggerBeanLocal().logTrace(MessageFormat.format("contact={0} - CALLED!", contact)); //NOI18N + + // Is it null? + if (null == contact) { + // Abort here + throw new NullPointerException("contact is null"); //NOI18N + } + + // Make sure it is own contact + if (!contact.isOwnContact()) { + // Not own contact + throw new IllegalArgumentException("Contact is not own data."); //NOI18N + } + + // Get manager and cast it + ContactFacade manager = (ContactFacade) this.getFacade(); + + // Phone number + DialableLandLineNumber phoneNumber = manager.enterOwnPhoneNumber(); + + // Phone number + DialableCellphoneNumber cellphonePhoneNumber = manager.enterOwnCellNumber(); + + // Fax number + DialableFaxNumber faxNumber = manager.enterOwnFaxNumber(); + + // Email address + String email = manager.enterOwnEmailAddress(); + + // Comment + String comment = manager.enterOwnComment(); + + // Update contact instance + contact.setContactPhoneNumber(phoneNumber); + contact.setContactCellphoneNumber(cellphonePhoneNumber); + contact.setContactFaxNumber(faxNumber); + contact.setContactEmailAddress(email); + contact.setContactComment(comment); + + // Trace message + this.getLoggerBeanLocal().logTrace("EXIT!"); //NOI18N + } + + @Override + public Contact doEnterOwnData () { + // Trace message + this.getLoggerBeanLocal().logTrace("CALLED!"); //NOI18N + + // Get manager and cast it + ContactFacade manager = (ContactFacade) this.getFacade(); + + // First ask for gender + Gender gender = manager.enterOwnGender(); + + // 2nd for first name + String firstName = manager.enterOwnFirstName(); + + // And 3rd for family name + String familyName = manager.enterOwnFamilyName(); + + // Construct UserContact instance + Contact contact = new UserContact(gender, firstName, familyName); + + // Trace message + this.getLoggerBeanLocal().logTrace(MessageFormat.format("contact={0} - EXIT!", contact)); //NOI18N + + // And return object + return contact; + } + + @Override + public void doShutdown () throws SQLException, IOException { + // Trace message + this.getLoggerBeanLocal().logTrace("CALLED!"); //NOI18N + + // Parent call + super.doShutdown(); + + // TODO Add other shutdown stuff + // Trace message + this.getLoggerBeanLocal().logTrace("EXIT!"); //NOI18N + } + + @Override + public void doUserMenuChoice () throws UnhandledUserChoiceException, MenuInitializationException { + // Trace message + this.getLoggerBeanLocal().logTrace("CALLED!"); //NOI18N + + // Get all access keys from menu + char[] accessKeys = MenuTools.getAccessKeysFromMenuMap(this.getMenus(), this.getCurrentMenu()); + + // Output textural message and ask for a char as input + char choice = this.enterChar(accessKeys, "Bitte Auswahl eingeben (0=Programm beenden): "); + + // Get manager and cast it + ContactFacade manager = (ContactFacade) this.getFacade(); + + // TODO Rewrite this ugly switch() block + switch (choice) { + case '1': + try { + // Enter/add own data + manager.doEnterOwnData(); + } catch (final ContactAlreadyAddedException ex) { + // Already added + this.outputMessage("Sie haben bereits Ihre eigenen Daten eingegeben."); + } + break; + + case '2': // Change own data + manager.doChangeOwnData(); + break; + + case '3': // Add new addess + manager.doAddOtherAddress(); + break; + + case '4': // List contacts + manager.doListContacts(); + break; + + case '5': // Search addresses + manager.doSearchContacts(); + break; + + case '6': // Change other addess + manager.doChangeOtherAddress(); + break; + + case '7': // Delete other address + manager.doDeleteOtherAddress(); + break; + + case '0': + try { + // Program exit + this.getApplication().doShutdown(); + } catch (final SQLException | IOException ex) { + this.abortProgramWithException(ex); + } + break; + + default: + // TODO throw own exception + throw new UnhandledUserChoiceException(MessageFormat.format("Choice '{0}' not handled yet.", choice)); //NOI18N + } + + // Trace message + this.getLoggerBeanLocal().logTrace("EXIT!"); //NOI18N + } + + @Override + public char enterChar (final char[] validChars, final String message) { + // Trace message + this.getLoggerBeanLocal().logTrace(MessageFormat.format("validChars={0},message={1} - CALLED!", Arrays.toString(validChars), message)); //NOI18N + + // The validChars must not null be null and filled with at least one char + if (null == validChars) { + // Is null + throw new NullPointerException("validChars is null"); //NOI18N + } else if (validChars.length == 0) { + // Is not filled + throw new IllegalArgumentException("validChars is not filled."); //NOI18N + } + + char input = 0; + + // Sort array, else binarySearch() won't work + Arrays.sort(validChars); + + // Keep asking until valid char has been entered + while (Arrays.binarySearch(validChars, input) < 0) { + // Output message + System.out.print(message); + + // Read char + input = this.readChar(); + } + + // Trace message + this.getLoggerBeanLocal().logTrace(MessageFormat.format("input={0} - EXIT!", input)); //NOI18N + + // Return read char + return input; + } + + @Override + public Gender enterGender (final String message) { + // Trace message + this.getLoggerBeanLocal().logTrace(MessageFormat.format("message={0} - CALLED!", message)); //NOI18N + + // Get valid chars + char[] validChars = Gender.validChars(); + + // Debug message + //* NOISY-DEBUG: */ System.out.println(validChars); + // Call inner method + char gender = this.enterChar(validChars, message); + + // Now get a Gender instance back + Gender g = Gender.fromChar(gender); + + // g must not be null + assert (g instanceof Gender) : "g is not set."; //NOI18N + + // Trace message + this.getLoggerBeanLocal().logTrace(MessageFormat.format("g={0} - EXIT!", g)); //NOI18N + + // Return it + return g; + } + + @Override + public int enterInt (final int minimum, final int maximum, final String message) { + // Trace message + this.getLoggerBeanLocal().logTrace(MessageFormat.format("minimum={0},maximum={1},message={2} - CALLED!", minimum, maximum, message)); //NOI18N + + // Minimum should not be below zero + assert (minimum >= 0) : MessageFormat.format("minimum={0} is below zero", minimum); //NOI18N + assert (maximum > minimum) : MessageFormat.format("maximum {0} is smaller than minimum {1}", maximum, minimum); //NOI18N + + // Init input + int input = -1; + + while ((input < minimum) || (input > maximum)) { + // Output message + System.out.print(message); + + // Read integer from user + input = this.readInt(); + } + + // Trace message + this.getLoggerBeanLocal().logTrace(MessageFormat.format("input={0} - EXIT!", input)); //NOI18N + + // Return it + return input; + } + + @Override + public String enterString (final int minLength, final int maxLength, final String message, final boolean allowEmpty) { + // Trace message + this.getLoggerBeanLocal().logTrace(MessageFormat.format("minLength={0},maxLength={1},message={2}allowEmpty={3} - CALLED!", minLength, maxLength, message, allowEmpty)); //NOI18N + + // Check on length, e.g. country codes are excactly 2 chars long + assert (maxLength >= minLength); + + // Init input + String input = null; + + // Check if it is to short or to long + while (((null == input) || ((input.length() < minLength) && (!allowEmpty))) || ((input.length() > 0) && (input.length() < minLength) && (allowEmpty)) || ((input instanceof String) && (input.length() > maxLength))) { + // Output message + System.out.print(message); + + // Read line + input = this.readString(); + } + + // Trace message + this.getLoggerBeanLocal().logTrace(MessageFormat.format("input={0} - EXIT!", input)); //NOI18N + + // Return it + return input; + } + + @Override + public SelectableMenuItem getMenuItem (final char accessKey, final String text) { + // Return a new console menu item + return new ConsoleMenuItem(accessKey, text); + } + + @Override + public void init () { + // Trace message + this.getLoggerBeanLocal().logTrace("CALLED!"); //NOI18N + + // Init contact manager here + try { + this.initContactManager(); + } catch (final SQLException ex) { + // End here + this.abortProgramWithException(ex); + } + + // Fill menu map + this.fillMenuMap(); + + // Trace message + this.getLoggerBeanLocal().logTrace("EXIT!"); //NOI18N + } + + @Override + public void outputMessage (final String message) { + System.out.println(message); + } + + @Override + public void show (final Contact contact) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @Override + public void showCurrentMenu () { + this.showMenu(this.getCurrentMenu()); + } + + @Override + public void showEntry (final SelectableMenuItem item) { + // Access key then text + this.outputMessage(MessageFormat.format("[{0}] {1}", item.getAccessKey(), item.getText())); //NOI18N + } + + @Override + public void showWelcome () { + this.outputMessage(MessageFormat.format("Welcome to {0}", AddressbookApplication.printableTitle())); //NOI18N + this.outputMessage(""); //NOI18N + this.outputMessage("Copyright(c) 2016 by Roland Haeder, this is free software"); //NOI18N + + // Debug message + this.getLoggerBeanLocal().logDebug("Intro shown to user"); //NOI18N + } + + @Override + public void userChooseChangeContactData (final Contact contact) throws UnhandledUserChoiceException { + // Trace message + this.getLoggerBeanLocal().logTrace(MessageFormat.format("contact={0} CALLED!", contact)); //NOI18N + + // Contact must not be null + if (null == contact) { + // Abort here + throw new NullPointerException("contact is null"); //NOI18N + } + + // Ask the user for editing [name], [a]ddress or [other] data + 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) "); + + // Get manager and cast it + ContactFacade manager = (ContactFacade) this.getFacade(); + + // TODO Get rid of this ugly switch block, too + switch (choice) { + case 'n': // Name data + manager.doChangeNameData(contact); + break; + + case 'a': // Address data + manager.doChangeAddressData(contact); + break; + + case 'o': // Other data + manager.doChangeOtherData(contact); + break; + + case 'x': // Exit this menu + // Ignored as it should go back + break; + + default: + // TODO throw own exception + throw new UnhandledUserChoiceException(MessageFormat.format("Choice '{0}' not handled yet.", choice)); //NOI18N + } + + // Trace message + this.getLoggerBeanLocal().logTrace("EXIT!"); //NOI18N + } + + /** + * Reads one character + *

+ * @return A single character + */ + private char readChar () { + // Read line + String input = this.readString(); + + // Debug message + this.getLoggerBeanLocal().logDebug(MessageFormat.format("input={0}", input)); //NOI18N + + // This must be only one character + if (input.length() != 1) { + // Return zero + return 0; + } + + // Get char from first (and only) position + return input.charAt(0); + } + + /** + * Reads an integer (int) from user + *

+ * @return An integer number + */ + private int readInt () { + // First read a string + String input = this.readString(); + + // Debug message + this.getLoggerBeanLocal().logDebug(MessageFormat.format("input={0}", input)); //NOI18N + + // Init number with invalid value + int num = -1; + + // Parse number, this can be risky + try { + num = Integer.parseInt(input); + } catch (final NumberFormatException e) { + this.outputMessage("Bitte geben Sie nur Zahlen ein!"); + this.getLoggerBeanLocal().logWarning(MessageFormat.format("No numbers-only entered. input={0},message={1}", input, e.getMessage())); //NOI18N + } + + // Trace message + this.getLoggerBeanLocal().logTrace(MessageFormat.format("num={0} - EXIT!", num)); //NOI18N + + // Return read number + return num; + } + + /** + * Reads a string from a scanner until RETURN is pressed + *

+ * @return Read string from scanner + */ + private String readString () { + return this.scanner.nextLine(); + } + + @Override + protected void fillMenuMap () { + // Trace message + this.getLoggerBeanLocal().logTrace("CALLED!"); //NOI18N + + // Initialize first (main) menu + Menu menu = new ConsoleMenu("main", this); //NOI18N + + // Add it + this.getMenus().put("main", menu); //NOI18N + + // Trace message + this.getLoggerBeanLocal().logTrace("EXIT!"); //NOI18N + } +}