]> git.mxchange.org Git - addressbook-swing.git/blobdiff - src/org/mxchange/addressbook/client/console/ConsoleClient.java
Updated copyright year
[addressbook-swing.git] / src / org / mxchange / addressbook / client / console / ConsoleClient.java
index b97600e42d1643e88202ac0868b2f37454524a39..d53c53b168ce36b02952b3301cab4ea708d391cf 100644 (file)
-/*\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.text.MessageFormat;\r
-import java.util.Arrays;\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.contact.user.UserContact;\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
-     * 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 scanner instance\r
-       this.scanner = new Scanner(System.in);\r
-    }\r
-\r
-    /**\r
-     * Displays a textual address "box" of given contact\r
-     *\r
-     * @param contact Contact to show address for\r
-     */\r
-    @Override\r
-    public void displayAddressBox (final Contact contact) {\r
-       // Simple display ...\r
-       this.outputMessage(MessageFormat.format("Strasse, PLZ Ort, Land: {0}\n{1} {2}\n{3}", contact.getStreet(), contact.getZipCode(), contact.getCity(), 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(MessageFormat.format("Anrede, Vorname, Name: {0} {1} {2}", gender, contact.getSurname(), contact.getFamilyName()));\r
-       } else {\r
-           // Company contact\r
-           this.outputMessage(MessageFormat.format("Firma: {0}\nAnsprechpartner: {1} {2} {3}", companyName, 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(MessageFormat.format("Telefonnumer: {0}\nFaxnummer: {1}\nHandy: {2}\nKommentar:\n{3}", contact.getPhoneNumber(), contact.getFaxNumber(), contact.getCellphoneNumber(), contact.getComment()));\r
-    }\r
-\r
-    @Override\r
-    public void doChangeOwnAddressData (final Contact contact) {\r
-       // Make sure it is own contact\r
-       if (!contact.isOwnContact()) {\r
-           // Not own contact\r
-           throw new IllegalArgumentException("Contact is not own data.");\r
-       }\r
-\r
-       // Own address data\r
-       String street = this.getContactManager().enterOwnStreet();\r
-\r
-       // Get zip code\r
-       int zipCode = this.getContactManager().enterOwnZipCode();\r
-\r
-       // Get city name\r
-       String city = this.getContactManager().enterOwnCity();\r
-\r
-       // Get country code\r
-       String countryCode = this.getContactManager().enterOwnCountryCode();\r
-\r
-       // Update address data\r
-       contact.updateAddressData(street, zipCode, city, countryCode);\r
-    }\r
-\r
-    @Override\r
-    public void doChangeOwnNameData (final Contact contact) {\r
-       // Make sure it is own contact\r
-       if (!contact.isOwnContact()) {\r
-           // Not own contact\r
-           throw new IllegalArgumentException("Contact is not own data.");\r
-       }\r
-\r
-       // Gender:\r
-       char gender = this.getContactManager().enterOwnGender();\r
-\r
-       // Surname\r
-       String surname = this.getContactManager().enterOwnSurname();\r
-\r
-       // Family name\r
-       String familyName = this.getContactManager().enterOwnFamilyName();\r
-\r
-       // And company\r
-       String companyName = this.getContactManager().enterOwnCompanyName();\r
-\r
-       // Update contact instance\r
-       contact.updateNameData(gender, surname, familyName, companyName);\r
-    }\r
-\r
-    @Override\r
-    public void doChangeOwnOtherData (final Contact contact) {\r
-       // Make sure it is own contact\r
-       if (!contact.isOwnContact()) {\r
-           // Not own contact\r
-           throw new IllegalArgumentException("Contact is not own data.");\r
-       }\r
-\r
-       // Phone number\r
-       String phoneNumber = this.getContactManager().enterOwnPhoneNumber();\r
-\r
-       // Phone number\r
-       String cellNumber = this.getContactManager().enterOwnCellNumber();\r
-\r
-       // Fax number\r
-       String faxNumber = this.getContactManager().enterOwnFaxNumber();\r
-\r
-       // Email address\r
-       String email = this.getContactManager().enterOwnEmailAddress();\r
-\r
-       // Comment\r
-       String comment = this.getContactManager().enterOwnComment();\r
-\r
-       // Update contact instance\r
-       contact.updateOtherData(phoneNumber, cellNumber, faxNumber, email, null, comment);\r
-    }\r
-\r
-    @Override\r
-    public Contact doEnterOwnData () {\r
-       // First ask for gender\r
-       char gender = this.getContactManager().enterOwnGender();\r
-\r
-       // 2nd for surname\r
-       String surname = this.getContactManager().enterOwnSurname();\r
-       \r
-       // And 3rd for family name\r
-       String familyName = this.getContactManager().enterOwnFamilyName();\r
-\r
-       // Company name ...\r
-       String companyName = this.getContactManager().enterOwnCompanyName();\r
-\r
-       // Construct UserContact instance\r
-       Contact contact = new UserContact(gender, surname, familyName, companyName);\r
-\r
-       // And return object\r
-       return contact;\r
-    }\r
-\r
-    /**\r
-     * Shutdown this client\r
-     */\r
-    @Override\r
-    public void doShutdown () {\r
-       // Parent call\r
-       super.doShutdown();\r
-\r
-       // @TODO Add other shutdown stuff\r
-    }\r
-\r
-    @Override\r
-    public void doUserMenuChoice () throws UnhandledUserChoiceException {\r
-       // Get all access keys from menu\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=Programm beenden): ");\r
-\r
-       // @TODO Rewrite this ugly switch() block\r
-       switch (choice) {\r
-           case '1': // Enter/add own data\r
-               this.getContactManager().doEnterOwnData();\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': // 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 '7': // Delete other address\r
-               this.getContactManager().deleteOtherAddress();\r
-               break;\r
-\r
-           case '0': // Program exit\r
-               this.getApplication().doShutdown();\r
-               break;\r
-       \r
-           default:\r
-               // @TODO throw own exception\r
-               throw new UnhandledUserChoiceException(MessageFormat.format("Choice '{0}' not handled yet.", choice));\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 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
-     * @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, 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) && (!allowEmpty))) || ((input.length() > 0) && (input.length() < minLength) && (allowEmpty)) || ((input instanceof String) && (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
-     * Inizializes this client\r
-     */\r
-    @Override\r
-    public void initClient () {\r
-       // Init contact manager here\r
-       this.initContactManager();\r
-\r
-       // Fill menu map\r
-       this.fillMenuMap();\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
-    @Override\r
-    public void showCurrentMenu () {\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.outputMessage("[" + item.getAccessKey() + "] " + item.getText());\r
-    }\r
-\r
-    /**\r
-     * Shows a textural message to the user\r
-     */\r
-    @Override\r
-    public void showWelcome () {\r
-       this.outputMessage(MessageFormat.format("Welcome to {0}", AddressbookApplication.printableTitle()));\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
-    @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
-       // @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(MessageFormat.format("Choice '{0}' not handled yet.", choice));\r
-       }\r
-    }\r
-\r
-    /**\r
-     * Reads one character\r
-     * \r
-     * @return A single character\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 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
-     * @return Read string from scanner\r
-     */\r
-    private String readString () {\r
-       return this.scanner.nextLine();\r
-    }\r
-\r
-    /**\r
-     * Fills menu map with menu entries\r
-     */\r
-    @Override\r
-    protected final void fillMenuMap () {\r
-       // Initialize first (main) menu\r
-       Menu menu = new ConsoleMenu("main", this);\r
-       \r
-       // Add it\r
-       this.getMenus().put("main", menu);\r
-    }\r
-}\r
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+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
+ * <p>
+ * @author Roland Haeder
+ */
+public class ConsoleClient extends BaseAddressbookClient implements AddressbookClient {
+
+       /**
+        * Scanner instance for reading data from console input
+        */
+       private final Scanner scanner;
+
+       /**
+        * Parameterless constructor
+        * <p>
+        * @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
+        * <p>
+        * @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
+        * <p>
+        * @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
+        * <p>
+        * @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
+       }
+}