]> git.mxchange.org Git - jaddressbook-lib.git/blob - Addressbook/src/org/mxchange/addressbook/client/console/ConsoleClient.java
Introduced updateNameData() + changing own "name data" is basicly finished
[jaddressbook-lib.git] / Addressbook / src / org / mxchange / addressbook / client / console / ConsoleClient.java
1 /*\r
2  * Copyright (C) 2015 Roland Haeder\r
3  *\r
4  * This program is free software: you can redistribute it and/or modify\r
5  * it under the terms of the GNU General Public License as published by\r
6  * the Free Software Foundation, either version 3 of the License, or\r
7  * (at your option) any later version.\r
8  *\r
9  * This program is distributed in the hope that it will be useful,\r
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
12  * GNU General Public License for more details.\r
13  *\r
14  * You should have received a copy of the GNU General Public License\r
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.\r
16  */\r
17 package org.mxchange.addressbook.client.console;\r
18 \r
19 import java.util.Arrays;\r
20 import java.util.HashMap;\r
21 import java.util.Map;\r
22 import java.util.Scanner;\r
23 import org.mxchange.addressbook.UnhandledUserChoiceException;\r
24 import org.mxchange.addressbook.application.AddressbookApplication;\r
25 import org.mxchange.addressbook.application.Application;\r
26 import org.mxchange.addressbook.client.BaseClient;\r
27 import org.mxchange.addressbook.client.Client;\r
28 import org.mxchange.addressbook.contact.Contact;\r
29 import org.mxchange.addressbook.menu.Menu;\r
30 import org.mxchange.addressbook.menu.MenuTools;\r
31 import org.mxchange.addressbook.menu.console.ConsoleMenu;\r
32 import org.mxchange.addressbook.menu.item.SelectableMenuItem;\r
33 import org.mxchange.addressbook.menu.item.console.ConsoleMenuItem;\r
34 \r
35 /**\r
36  * A client for the console\r
37  *\r
38  * @author Roland Haeder\r
39  */\r
40 public class ConsoleClient extends BaseClient implements Client {\r
41     /**\r
42      * Menu system\r
43      */\r
44     private final Map<String, Menu> menus;\r
45 \r
46     /**\r
47      * Scanner instance for reading data from console input\r
48      */\r
49     private final Scanner scanner;\r
50 \r
51     /**\r
52      * Parameterless constructor\r
53      * @param application An instance of an Application class\r
54      */\r
55     public ConsoleClient (final Application application) {\r
56         super();\r
57 \r
58         // Set application instance\r
59         this.setApplication(application);\r
60 \r
61         // Init contact manager here\r
62         this.initContactManager(this);\r
63 \r
64         // Init scanner instance\r
65         this.scanner = new Scanner(System.in);\r
66 \r
67         // Init menu map\r
68         this.menus = new HashMap<>(10);\r
69 \r
70         // Fill menu map\r
71         this.fillConsoleMenuMap();\r
72     }\r
73 \r
74     /**\r
75      * Displays a textual address "box" of given contact\r
76      *\r
77      * @param contact Contact to show address for\r
78      * @todo Use mask\r
79      */\r
80     @Override\r
81     public void displayAddressBox (final Contact contact) {\r
82         // Simple display ...\r
83         // @todo Use mask\r
84         this.displayMessage("Strasse, PLZ Ort, Land: " + contact.getStreet() + "\n" + contact.getZipCode() + " " + contact.getCity() +  "\n" + contact.getCountryCode());\r
85     }\r
86 \r
87     /**\r
88      * Displays textural message to the user\r
89      * @param message \r
90      */\r
91     @Override\r
92     public void displayMessage (final String message) {\r
93         System.out.println(message);\r
94     }\r
95 \r
96     /**\r
97      * Displays a textual name "box" of given contact\r
98      *\r
99      * @param contact Contact to show name for\r
100      */\r
101     @Override\r
102     public void displayNameBox (final Contact contact) {\r
103         // Get translated gender as the user may want to see "Mr.", "Mrs."\r
104         String gender = contact.getTranslatedGender();\r
105 \r
106         // Get company name\r
107         String companyName = contact.getCompanyName();\r
108 \r
109         // If it is empty/null, then assume private contact\r
110         if ((companyName == null) || (companyName.isEmpty())) {\r
111             // Now put all together: gender, surname, family name\r
112             // @todo Use mask\r
113             this.displayMessage("Anrede, Vorname, Name: " + gender + " " + contact.getSurname() + " " + contact.getFamilyName());\r
114         } else {\r
115             // Company contact\r
116             this.displayMessage("Firma: " + companyName + "\nAnsprechpartner: " + gender + " " + contact.getSurname() + " " + contact.getFamilyName());\r
117         }\r
118     }\r
119 \r
120     /**\r
121      * Displays a textual other data "box" of given contact\r
122      *\r
123      * @param contact Contact to show other data for\r
124      */\r
125     @Override\r
126     public void displayOtherDataBox (final Contact contact) {\r
127         // Cellphone and such ...\r
128         this.displayMessage("Telefonnumer: " + contact.getPhoneNumber() + "\nFaxnummer: " + contact.getFaxNumber() + "\nHandy: " + contact.getCellphoneNumber() + "\nKommentar:\n" + contact.getComment());\r
129     }\r
130 \r
131     @Override\r
132     public void doUserChangeAdressChoice (final Contact contact) throws UnhandledUserChoiceException {\r
133         // Ask the user for editing [name], [a]ddress or [other] data\r
134         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
135 \r
136         // @TODO Get rid of this ugly switch block, too\r
137         switch (choice) {\r
138             case 'n': // Name data\r
139                 this.getContactManager().changeNameData(contact, this);\r
140                 break;\r
141 \r
142             case 'a': // Address data\r
143                 this.getContactManager().changeAddressData(contact, this);\r
144                 break;\r
145 \r
146             case 'o': // Other data\r
147                 this.getContactManager().changeOtherData(contact, this);\r
148                 break;\r
149 \r
150             case 'x': // Exit this menu\r
151                 // Ignored as it should go back\r
152                 break;\r
153 \r
154             default:\r
155                 // @TODO throw own exception\r
156                 throw new UnhandledUserChoiceException("Choice '" + choice + "' not handled yet.");\r
157         }\r
158     }\r
159 \r
160     @Override\r
161     public void doUserMenuChoice () throws UnhandledUserChoiceException {\r
162         // Get all access keys from menu\r
163         char[] accessKeys = MenuTools.getAccessKeysFromMenuMap(this.menus, this.getCurrentMenu());\r
164 \r
165         // Output textural message and ask for a char as input\r
166         char choice = this.enterChar(accessKeys, "Bitte Auswahl eingeben (0=Programm beenden): ");\r
167 \r
168         // @TODO Rewrite this ugly switch() block\r
169         switch (choice) {\r
170             case '1': // Enter/add own data\r
171                 this.getContactManager().enterOwnData();\r
172                 break;\r
173         \r
174             case '2': // Change own data\r
175                 this.getContactManager().changeOwnData();\r
176                 break;\r
177         \r
178             case '3': // Add new addess\r
179                 this.getContactManager().addOtherAddress();\r
180                 break;\r
181         \r
182             case '4': // Change other addess\r
183                 this.getContactManager().changeOtherAddress();\r
184                 break;\r
185         \r
186             case '5': // Delete other address\r
187                 this.getContactManager().deleteOtherAddress();\r
188                 break;\r
189 \r
190             case '0': // Program exit\r
191                 this.disableIsRunning();\r
192                 break;\r
193         \r
194             default:\r
195                 // @TODO throw own exception\r
196                 throw new UnhandledUserChoiceException("Choice '" + choice + "' not handled yet.");\r
197         }\r
198     }\r
199 \r
200     /**\r
201      * Asks the the user to enter a single character which must match validChars\r
202      * @param   validChars  Valid chars that are accepted\r
203      * @param   message     Message to user\r
204      * @return  Allowed character\r
205      */\r
206     @Override\r
207     public char enterChar (final char[] validChars, final String message) {\r
208         char input = 0;\r
209 \r
210         // Sort array, else binarySearch() won't work\r
211         Arrays.sort(validChars);\r
212 \r
213         // Keep asking until valid char has been entered\r
214         while (Arrays.binarySearch(validChars, input) < 0) {\r
215             // Output message\r
216             System.out.print(message);\r
217 \r
218             // Read char\r
219             input = this.readChar();\r
220         }\r
221 \r
222         // Return read char\r
223         return input;\r
224     }\r
225 \r
226     /**\r
227      * Reads a string of minimum and maximum length from the user\r
228      * @param minLength Minimum length of the string to read\r
229      * @param maxLength Maximum length of the string to read\r
230      * @param message   Message to user\r
231      * @param allowEmpty Whether to allow empty string\r
232      * @return Entered string by user or null for empty strings\r
233      */\r
234     @Override\r
235     public String enterString (final int minLength, final int maxLength, final String message, final boolean allowEmpty) {\r
236         // Init input\r
237         String input = null;\r
238 \r
239         // Check if it is to short or to long\r
240         while (((input == null) || ((input.length() < minLength) && (!allowEmpty))) || ((input.length() > 0) && (input.length() < minLength) && (allowEmpty)) || ((input instanceof String) && (input.length() > maxLength))) {\r
241             // Output message\r
242             System.out.print(message);\r
243 \r
244             // Read line\r
245             input = this.readString();\r
246         }\r
247 \r
248         // Return it\r
249         return input;\r
250     }\r
251 \r
252     /**\r
253      * Returns a console menu item\r
254      * \r
255      * @param accessKey Key to access the menu\r
256      * @param text Text to show to user\r
257      * @return A SelectableMenuItem\r
258      * @todo Make sure the access key is unique\r
259      */\r
260     @Override\r
261     public SelectableMenuItem getMenuItem (final char accessKey, final String text) {\r
262         // Return a new console menu item\r
263         return new ConsoleMenuItem(accessKey,text);\r
264     }\r
265 \r
266     /**\r
267      * Shows textural menu on console\r
268      */\r
269     @Override\r
270     public void showCurrentMenu () {\r
271         this.showMenu(this.getCurrentMenu());\r
272     }\r
273 \r
274     @Override\r
275     public void showEntry (final SelectableMenuItem item) {\r
276         // Access key then text\r
277         this.displayMessage("[" + item.getAccessKey() + "] " + item.getText());\r
278     }\r
279 \r
280     /**\r
281      * Shows a textural message to the user\r
282      */\r
283     @Override\r
284     public void showWelcome () {\r
285          this.displayMessage("Welcome to " + AddressbookApplication.APP_TITLE + " v" + AddressbookApplication.APP_VERSION);\r
286          this.displayMessage("");\r
287          this.displayMessage("Copyright(c) 2015 by Roland Haeder, this is free software");\r
288          \r
289          // Debug message\r
290          this.getLogger().debug("Intro shown to user");\r
291      }\r
292 \r
293     /**\r
294      * Fills menu map with menu entries\r
295      */\r
296     private void fillConsoleMenuMap () {\r
297         // Initialize first (main) menu\r
298         Menu menu = new ConsoleMenu("main", this);\r
299 \r
300         // Add it\r
301         this.menus.put("main", menu);\r
302     }\r
303 \r
304     /**\r
305      * "Getter" for given menu type\r
306      * \r
307      * @param menuType Menu type instance to return\r
308      * @return Menu or null if not found\r
309      */\r
310     private Menu getMenu (final String menuType) {\r
311         // Default is not found\r
312         Menu menu = null;\r
313 \r
314         // Check array\r
315         if (this.menus.containsKey(menuType)) {\r
316             // Found!\r
317             menu = this.menus.get(menuType);\r
318         }\r
319         \r
320         // Return it\r
321         return menu;\r
322     }\r
323 \r
324     /**\r
325      * Reads one character\r
326      * @return \r
327      */\r
328     private char readChar () {\r
329         // Read line\r
330         String input = this.scanner.nextLine();\r
331 \r
332         // This must be only one character\r
333         if (input.length() != 1) {\r
334             // Return zero\r
335             return 0;\r
336         }\r
337 \r
338         // Get char from first (and only) position\r
339         return input.charAt(0);\r
340     }\r
341 \r
342     /**\r
343      * Reads a string from a scanner until RETURN is pressed\r
344      * \r
345      * @return Read string from scanner\r
346      */\r
347     private String readString () {\r
348         return this.scanner.nextLine();\r
349     }\r
350 \r
351     /**\r
352      * Shows given menu\r
353      *\r
354      * @param menuType Given menu to show\r
355      */\r
356     private void showMenu (final String menuType) {\r
357         Menu menu = this.getMenu(menuType);\r
358         \r
359         // Is the menu set?\r
360         if (!(menu instanceof Menu)) {\r
361             // Not found\r
362             // @todo Own exception?\r
363             throw new NullPointerException("Menu '" + menuType + "' not found.");\r
364         }\r
365         \r
366         // Show menu\r
367         menu.show(this);\r
368     }\r
369 }\r