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