]> git.mxchange.org Git - addressbook-swing.git/blob - Addressbook/src/org/mxchange/addressbook/client/console/ConsoleClient.java
82d80d824e86ceebc5353cf7cda31952d2467662
[addressbook-swing.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.text.MessageFormat;\r
20 import java.util.Arrays;\r
21 import java.util.Scanner;\r
22 import org.mxchange.addressbook.UnhandledUserChoiceException;\r
23 import org.mxchange.addressbook.application.AddressbookApplication;\r
24 import org.mxchange.addressbook.application.Application;\r
25 import org.mxchange.addressbook.client.BaseClient;\r
26 import org.mxchange.addressbook.client.Client;\r
27 import org.mxchange.addressbook.contact.Contact;\r
28 import org.mxchange.addressbook.menu.Menu;\r
29 import org.mxchange.addressbook.menu.MenuTools;\r
30 import org.mxchange.addressbook.menu.console.ConsoleMenu;\r
31 import org.mxchange.addressbook.menu.item.SelectableMenuItem;\r
32 import org.mxchange.addressbook.menu.item.console.ConsoleMenuItem;\r
33 \r
34 /**\r
35  * A client for the console\r
36  *\r
37  * @author Roland Haeder\r
38  */\r
39 public class ConsoleClient extends BaseClient implements Client {\r
40     /**\r
41      * Scanner instance for reading data from console input\r
42      */\r
43     private final Scanner scanner;\r
44 \r
45     /**\r
46      * Parameterless constructor\r
47      * @param application An instance of an Application class\r
48      */\r
49     public ConsoleClient (final Application application) {\r
50         super();\r
51 \r
52         // Set application instance\r
53         this.setApplication(application);\r
54 \r
55         // Init scanner instance\r
56         this.scanner = new Scanner(System.in);\r
57     }\r
58 \r
59     /**\r
60      * Displays a textual address "box" of given contact\r
61      *\r
62      * @param contact Contact to show address for\r
63      * @todo Use mask\r
64      */\r
65     @Override\r
66     public void displayAddressBox (final Contact contact) {\r
67         // Simple display ...\r
68         // @todo Use mask\r
69         this.outputMessage("Strasse, PLZ Ort, Land: " + contact.getStreet() + "\n" + contact.getZipCode() + " " + contact.getCity() +  "\n" + contact.getCountryCode());\r
70     }\r
71 \r
72     /**\r
73      * Displays a textual name "box" of given contact\r
74      *\r
75      * @param contact Contact to show name for\r
76      */\r
77     @Override\r
78     public void displayNameBox (final Contact contact) {\r
79         // Get translated gender as the user may want to see "Mr.", "Mrs."\r
80         String gender = contact.getTranslatedGender();\r
81 \r
82         // Get company name\r
83         String companyName = contact.getCompanyName();\r
84 \r
85         // If it is empty/null, then assume private contact\r
86         if ((companyName == null) || (companyName.isEmpty())) {\r
87             // Now put all together: gender, surname, family name\r
88             // @todo Use mask\r
89             this.outputMessage("Anrede, Vorname, Name: " + gender + " " + contact.getSurname() + " " + contact.getFamilyName());\r
90         } else {\r
91             // Company contact\r
92             this.outputMessage("Firma: " + companyName + "\nAnsprechpartner: " + gender + " " + contact.getSurname() + " " + contact.getFamilyName());\r
93         }\r
94     }\r
95 \r
96     /**\r
97      * Displays a textual other data "box" of given contact\r
98      *\r
99      * @param contact Contact to show other data for\r
100      */\r
101     @Override\r
102     public void displayOtherDataBox (final Contact contact) {\r
103         // Cellphone and such ...\r
104         this.outputMessage("Telefonnumer: " + contact.getPhoneNumber() + "\nFaxnummer: " + contact.getFaxNumber() + "\nHandy: " + contact.getCellphoneNumber() + "\nKommentar:\n" + contact.getComment());\r
105     }\r
106 \r
107     @Override\r
108     public void doUserMenuChoice () throws UnhandledUserChoiceException {\r
109         // Get all access keys from menu\r
110         char[] accessKeys = MenuTools.getAccessKeysFromMenuMap(this.getMenus(), this.getCurrentMenu());\r
111 \r
112         // Output textural message and ask for a char as input\r
113         char choice = this.enterChar(accessKeys, "Bitte Auswahl eingeben (0=Programm beenden): ");\r
114 \r
115         // @TODO Rewrite this ugly switch() block\r
116         switch (choice) {\r
117             case '1': // Enter/add own data\r
118                 this.getContactManager().doEnterOwnData();\r
119                 break;\r
120         \r
121             case '2': // Change own data\r
122                 this.getContactManager().changeOwnData();\r
123                 break;\r
124         \r
125             case '3': // Add new addess\r
126                 this.getContactManager().addOtherAddress();\r
127                 break;\r
128         \r
129             case '4': // List contacts\r
130                 this.getContactManager().listContacts();\r
131                 break;\r
132         \r
133             case '5': // Search addresses\r
134                 this.getContactManager().searchContacts();\r
135                 break;\r
136 \r
137             case '6': // Change other addess\r
138                 this.getContactManager().changeOtherAddress();\r
139                 break;\r
140         \r
141             case '7': // Delete other address\r
142                 this.getContactManager().deleteOtherAddress();\r
143                 break;\r
144 \r
145             case '0': // Program exit\r
146                 this.disableIsRunning();\r
147                 break;\r
148         \r
149             default:\r
150                 // @TODO throw own exception\r
151                 throw new UnhandledUserChoiceException("Choice '" + choice + "' not handled yet.");\r
152         }\r
153     }\r
154 \r
155     /**\r
156      * Asks the the user to enter a single character which must match validChars\r
157      * @param   validChars  Valid chars that are accepted\r
158      * @param   message     Message to user\r
159      * @return  Allowed character\r
160      */\r
161     @Override\r
162     public char enterChar (final char[] validChars, final String message) {\r
163         char input = 0;\r
164 \r
165         // Sort array, else binarySearch() won't work\r
166         Arrays.sort(validChars);\r
167 \r
168         // Keep asking until valid char has been entered\r
169         while (Arrays.binarySearch(validChars, input) < 0) {\r
170             // Output message\r
171             System.out.print(message);\r
172 \r
173             // Read char\r
174             input = this.readChar();\r
175         }\r
176 \r
177         // Return read char\r
178         return input;\r
179     }\r
180 \r
181     /**\r
182      * Reads an integer (int) with a textural message from the user\r
183      * \r
184      * @param minimum Minimum allowed number\r
185      * @param maximum Maximum allowed number\r
186      * @param message Messager to display in console\r
187      * @return \r
188      */\r
189     @Override\r
190     public int enterInt (final int minimum, final int maximum, final String message) {\r
191         // Minimum should not be below zero\r
192         assert(minimum >= 0);\r
193         assert(maximum > minimum);\r
194 \r
195         // Init input\r
196         int input = -1;\r
197 \r
198         while ((input < minimum) || (input > maximum)) {\r
199             // Output message\r
200             System.out.print(message);\r
201 \r
202             // Read integer from user\r
203             input = this.readInt();\r
204         }\r
205 \r
206         // Return it\r
207         return input;\r
208     }\r
209 \r
210     /**\r
211      * Reads a string of minimum and maximum length from the user\r
212      * \r
213      * @param minLength Minimum length of the string to read\r
214      * @param maxLength Maximum length of the string to read\r
215      * @param message   Message to user\r
216      * @param allowEmpty Whether to allow empty string\r
217      * @return Entered string by user or null for empty strings\r
218      */\r
219     @Override\r
220     public String enterString (final int minLength, final int maxLength, final String message, final boolean allowEmpty) {\r
221         // Check on length, e.g. country codes are excactly 2 chars long\r
222         assert(maxLength >= minLength);\r
223 \r
224         // Init input\r
225         String input = null;\r
226 \r
227         // Check if it is to short or to long\r
228         while (((input == null) || ((input.length() < minLength) && (!allowEmpty))) || ((input.length() > 0) && (input.length() < minLength) && (allowEmpty)) || ((input instanceof String) && (input.length() > maxLength))) {\r
229             // Output message\r
230             System.out.print(message);\r
231 \r
232             // Read line\r
233             input = this.readString();\r
234         }\r
235 \r
236         // Return it\r
237         return input;\r
238     }\r
239 \r
240     /**\r
241      * Returns a console menu item\r
242      * \r
243      * @param accessKey Key to access the menu\r
244      * @param text Text to show to user\r
245      * @return A SelectableMenuItem\r
246      * @todo Make sure the access key is unique\r
247      */\r
248     @Override\r
249     public SelectableMenuItem getMenuItem (final char accessKey, final String text) {\r
250         // Return a new console menu item\r
251         return new ConsoleMenuItem(accessKey,text);\r
252     }\r
253 \r
254     /**\r
255      * Inizializes this client\r
256      */\r
257     @Override\r
258     public void initClient () {\r
259         // Init contact manager here\r
260         this.initContactManager();\r
261         \r
262         // Fill menu map\r
263         this.fillMenuMap();\r
264     }\r
265 \r
266     /**\r
267      * Displays textural message to the user\r
268      * @param message\r
269      */\r
270     @Override\r
271     public void outputMessage (final String message) {\r
272         System.out.println(message);\r
273     }\r
274 \r
275     /**\r
276      * Shows textural menu on console\r
277      */\r
278     @Override\r
279     public void showCurrentMenu () {\r
280         this.showMenu(this.getCurrentMenu());\r
281     }\r
282 \r
283     /**\r
284      * Shows given menu entry to user\r
285      * \r
286      * @param item Menu entry\r
287      */\r
288     @Override\r
289     public void showEntry (final SelectableMenuItem item) {\r
290         // Access key then text\r
291         this.outputMessage("[" + item.getAccessKey() + "] " + item.getText());\r
292     }\r
293 \r
294     /**\r
295      * Shows a textural message to the user\r
296      */\r
297     @Override\r
298     public void showWelcome () {\r
299         this.outputMessage("Welcome to " + AddressbookApplication.APP_TITLE + " v" + AddressbookApplication.APP_VERSION);\r
300         this.outputMessage("");\r
301         this.outputMessage("Copyright(c) 2015 by Roland Haeder, this is free software");\r
302         \r
303         // Debug message\r
304         this.getLogger().debug("Intro shown to user");\r
305     }\r
306 \r
307     @Override\r
308     public void userChooseChangeContactData (final Contact contact) throws UnhandledUserChoiceException {\r
309         // Ask the user for editing [name], [a]ddress or [other] data\r
310         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
311         \r
312         // @TODO Get rid of this ugly switch block, too\r
313         switch (choice) {\r
314             case 'n': // Name data\r
315                 this.getContactManager().doChangeNameData(contact, this);\r
316                 break;\r
317                 \r
318             case 'a': // Address data\r
319                 this.getContactManager().doChangeAddressData(contact, this);\r
320                 break;\r
321                 \r
322             case 'o': // Other data\r
323                 this.getContactManager().doChangeOtherData(contact, this);\r
324                 break;\r
325                 \r
326             case 'x': // Exit this menu\r
327                 // Ignored as it should go back\r
328                 break;\r
329                 \r
330             default:\r
331                 // @TODO throw own exception\r
332                 throw new UnhandledUserChoiceException("Choice '" + choice + "' not handled yet.");\r
333         }\r
334     }\r
335 \r
336     /**\r
337      * Reads one character\r
338      * \r
339      * @return A single character\r
340      */\r
341     private char readChar () {\r
342         // Read line\r
343         String input = this.scanner.nextLine();\r
344 \r
345         // This must be only one character\r
346         if (input.length() != 1) {\r
347             // Return zero\r
348             return 0;\r
349         }\r
350 \r
351         // Get char from first (and only) position\r
352         return input.charAt(0);\r
353     }\r
354 \r
355     /**\r
356      * Reads an integer (int) from user\r
357      * \r
358      * @return An integer number\r
359      */\r
360     private int readInt () {\r
361         // First read a string\r
362         String input = this.readString();\r
363 \r
364         // Init number with invalid value\r
365         int num = -1;\r
366 \r
367         // Parse number, this can be risky\r
368         try {\r
369             num = Integer.parseInt(input);\r
370         } catch (final NumberFormatException e) {\r
371             this.outputMessage("Bitte geben Sie nur Zahlen ein!");\r
372             this.getLogger().warn(MessageFormat.format("No numbers-only entered. input={0},message={1}", input, e.getMessage()));\r
373         }\r
374 \r
375         // Return read number\r
376         return num;\r
377     }\r
378 \r
379     /**\r
380      * Reads a string from a scanner until RETURN is pressed\r
381      * \r
382      * @return Read string from scanner\r
383      */\r
384     private String readString () {\r
385         return this.scanner.nextLine();\r
386     }\r
387 \r
388     /**\r
389      * Fills menu map with menu entries\r
390      */\r
391     @Override\r
392     protected final void fillMenuMap () {\r
393         // Initialize first (main) menu\r
394         Menu menu = new ConsoleMenu("main", this);\r
395         \r
396         // Add it\r
397         this.getMenus().put("main", menu);\r
398     }\r
399 }\r