]> git.mxchange.org Git - jfinancials-swing.git/blob - Addressbook/src/org/mxchange/addressbook/client/console/ConsoleClient.java
9de67f1a2787a11e439683e57506bbed96c9f089
[jfinancials-swing.git] / Addressbook / src / org / mxchange / addressbook / client / console / ConsoleClient.java
1 /*
2  * Copyright (C) 2015 Roland Haeder
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 package org.mxchange.addressbook.client.console;
18
19 import java.text.MessageFormat;
20 import java.util.Arrays;
21 import java.util.Scanner;
22 import org.mxchange.addressbook.application.AddressbookApplication;
23 import org.mxchange.addressbook.application.Application;
24 import org.mxchange.addressbook.client.BaseClient;
25 import org.mxchange.addressbook.client.Client;
26 import org.mxchange.addressbook.contact.Contact;
27 import org.mxchange.addressbook.contact.Gender;
28 import org.mxchange.addressbook.contact.user.UserContact;
29 import org.mxchange.addressbook.exceptions.UnhandledUserChoiceException;
30 import org.mxchange.addressbook.menu.Menu;
31 import org.mxchange.addressbook.menu.MenuTools;
32 import org.mxchange.addressbook.menu.console.ConsoleMenu;
33 import org.mxchange.addressbook.menu.item.SelectableMenuItem;
34 import org.mxchange.addressbook.menu.item.console.ConsoleMenuItem;
35
36 /**
37  * A client for the console
38  *
39  * @author Roland Haeder
40  */
41 public class ConsoleClient extends BaseClient implements Client {
42
43         /**
44          * Scanner instance for reading data from console input
45          */
46         private final Scanner scanner;
47
48         /**
49          * Parameterless constructor
50          *
51          * @param application An instance of an Application class
52          */
53         public ConsoleClient (final Application application) {
54                 super();
55
56                 // Set application instance
57                 this.setApplication(application);
58
59                 // Init scanner instance
60                 this.scanner = new Scanner(System.in);
61         }
62
63         /**
64          * Displays a textual address "box" of given contact
65          *
66          * @param contact Contact to show address for
67          */
68         @Override
69         public void displayAddressBox (final Contact contact) {
70                 // Simple display ...
71                 this.outputMessage(MessageFormat.format("Strasse, PLZ Ort, Land: {0}\n{1} {2}\n{3}", contact.getStreet(), contact.getZipCode(), contact.getCity(), contact.getCountryCode()));
72         }
73
74         /**
75          * Displays a textual name "box" of given contact
76          *
77          * @param contact Contact to show name for
78          */
79         @Override
80         public void displayNameBox (final Contact contact) {
81                 // Get translated gender as the user may want to see "Mr.", "Mrs."
82                 String gender = contact.getTranslatedGender();
83
84                 // Get company name
85                 String companyName = contact.getCompanyName();
86
87                 // If it is empty/null, then assume private contact
88                 if ((companyName == null) || (companyName.isEmpty())) {
89                         // Now put all together: gender, surname, family name
90                         // @todo Use mask
91                         this.outputMessage(MessageFormat.format("Anrede, Vorname, Name: {0} {1} {2}", gender, contact.getSurname(), contact.getFamilyName()));
92                 } else {
93                         // Company contact
94                         this.outputMessage(MessageFormat.format("Firma: {0}\nAnsprechpartner: {1} {2} {3}", companyName, gender, contact.getSurname(), contact.getFamilyName()));
95                 }
96         }
97
98         /**
99          * Displays a textual other data "box" of given contact
100          *
101          * @param contact Contact to show other data for
102          */
103         @Override
104         public void displayOtherDataBox (final Contact contact) {
105                 // Cellphone and such ...
106                 this.outputMessage(MessageFormat.format("Telefonnumer: {0}\nFaxnummer: {1}\nHandy: {2}\nKommentar:\n{3}", contact.getPhoneNumber(), contact.getFaxNumber(), contact.getCellphoneNumber(), contact.getComment()));
107         }
108
109         @Override
110         public void doChangeOwnAddressData (final Contact contact) {
111                 // Make sure it is own contact
112                 if (!contact.isOwnContact()) {
113                         // Not own contact
114                         throw new IllegalArgumentException("Contact is not own data.");
115                 }
116
117                 // Own address data
118                 String street = this.getContactManager().enterOwnStreet();
119
120                 // Get zip code
121                 int zipCode = this.getContactManager().enterOwnZipCode();
122
123                 // Get city name
124                 String city = this.getContactManager().enterOwnCity();
125
126                 // Get country code
127                 String countryCode = this.getContactManager().enterOwnCountryCode();
128
129                 // Update address data
130                 contact.updateAddressData(street, zipCode, city, countryCode);
131         }
132
133         @Override
134         public void doChangeOwnNameData (final Contact contact) {
135                 // Make sure it is own contact
136                 if (!contact.isOwnContact()) {
137                         // Not own contact
138                         throw new IllegalArgumentException("Contact is not own data.");
139                 }
140
141                 // Gender:
142                 Gender gender = this.getContactManager().enterOwnGender();
143
144                 // Surname
145                 String surname = this.getContactManager().enterOwnSurname();
146
147                 // Family name
148                 String familyName = this.getContactManager().enterOwnFamilyName();
149
150                 // And company
151                 String companyName = this.getContactManager().enterOwnCompanyName();
152
153                 // Update contact instance
154                 contact.updateNameData(gender, surname, familyName, companyName);
155         }
156
157         @Override
158         public void doChangeOwnOtherData (final Contact contact) {
159                 // Make sure it is own contact
160                 if (!contact.isOwnContact()) {
161                         // Not own contact
162                         throw new IllegalArgumentException("Contact is not own data.");
163                 }
164
165                 // Phone number
166                 String phoneNumber = this.getContactManager().enterOwnPhoneNumber();
167
168                 // Phone number
169                 String cellNumber = this.getContactManager().enterOwnCellNumber();
170
171                 // Fax number
172                 String faxNumber = this.getContactManager().enterOwnFaxNumber();
173
174                 // Email address
175                 String email = this.getContactManager().enterOwnEmailAddress();
176
177                 // Comment
178                 String comment = this.getContactManager().enterOwnComment();
179
180                 // Update contact instance
181                 contact.updateOtherData(phoneNumber, cellNumber, faxNumber, email, null, comment);
182         }
183
184         @Override
185         public Contact doEnterOwnData () {
186                 // First ask for gender
187                 Gender gender = this.getContactManager().enterOwnGender();
188
189                 // 2nd for surname
190                 String surname = this.getContactManager().enterOwnSurname();
191
192                 // And 3rd for family name
193                 String familyName = this.getContactManager().enterOwnFamilyName();
194
195                 // Company name ...
196                 String companyName = this.getContactManager().enterOwnCompanyName();
197
198                 // Construct UserContact instance
199                 Contact contact = new UserContact(gender, surname, familyName, companyName);
200
201                 // And return object
202                 return contact;
203         }
204
205         /**
206          * Shutdown this client
207          */
208         @Override
209         public void doShutdown () {
210                 // Parent call
211                 super.doShutdown();
212
213                 // @TODO Add other shutdown stuff
214         }
215
216         @Override
217         public void doUserMenuChoice () throws UnhandledUserChoiceException {
218                 // Get all access keys from menu
219                 char[] accessKeys = MenuTools.getAccessKeysFromMenuMap(this.getMenus(), this.getCurrentMenu());
220
221                 // Output textural message and ask for a char as input
222                 char choice = this.enterChar(accessKeys, "Bitte Auswahl eingeben (0=Programm beenden): ");
223
224                 // @TODO Rewrite this ugly switch() block
225                 switch (choice) {
226                         case '1': // Enter/add own data
227                                 this.getContactManager().doEnterOwnData();
228                                 break;
229
230                         case '2': // Change own data
231                                 this.getContactManager().doChangeOwnData();
232                                 break;
233
234                         case '3': // Add new addess
235                                 this.getContactManager().doAddOtherAddress();
236                                 break;
237
238                         case '4': // List contacts
239                                 this.getContactManager().doListContacts();
240                                 break;
241
242                         case '5': // Search addresses
243                                 this.getContactManager().doSearchContacts();
244                                 break;
245
246                         case '6': // Change other addess
247                                 this.getContactManager().doChangeOtherAddress();
248                                 break;
249
250                         case '7': // Delete other address
251                                 this.getContactManager().doDeleteOtherAddress();
252                                 break;
253
254                         case '0': // Program exit
255                                 this.getApplication().doShutdown();
256                                 break;
257
258                         default:
259                                 // @TODO throw own exception
260                                 throw new UnhandledUserChoiceException(MessageFormat.format("Choice '{0}' not handled yet.", choice));
261                 }
262         }
263
264         /**
265          * Asks the the user to enter a single character which must match validChars
266          *
267          * @param       validChars Valid chars that are accepted
268          * @param       message Message to user
269          * @return      Allowed character
270          */
271         @Override
272         public char enterChar (final char[] validChars, final String message) {
273                 char input = 0;
274
275                 // Sort array, else binarySearch() won't work
276                 Arrays.sort(validChars);
277
278                 // Keep asking until valid char has been entered
279                 while (Arrays.binarySearch(validChars, input) < 0) {
280                         // Output message
281                         System.out.print(message);
282
283                         // Read char
284                         input = this.readChar();
285                 }
286
287                 // Return read char
288                 return input;
289         }
290
291         /**
292          * Asks the user to enter his/her gender
293          *
294          * @param message Message to the user
295          * @return Gender enum
296          */
297         @Override
298         public Gender enterGender (final String message) {
299                 // Get valid chars
300                 char[] validChars = Gender.validChars();
301
302                 // Debug message
303                 //* NOISY-DEBUG: */ System.out.println(validChars);
304                 // Call inner method
305                 char gender = this.enterChar(validChars, message);
306
307                 // Now get a Gender instance back
308                 Gender g = Gender.fromChar(gender);
309
310                 // Return it
311                 return g;
312         }
313
314         /**
315          * Reads an integer (int) with a textural message from the user
316          *
317          * @param minimum Minimum allowed number
318          * @param maximum Maximum allowed number
319          * @param message Messager to display in console
320          * @return
321          */
322         @Override
323         public int enterInt (final int minimum, final int maximum, final String message) {
324                 // Minimum should not be below zero
325                 assert (minimum >= 0);
326                 assert (maximum > minimum);
327
328                 // Init input
329                 int input = -1;
330
331                 while ((input < minimum) || (input > maximum)) {
332                         // Output message
333                         System.out.print(message);
334
335                         // Read integer from user
336                         input = this.readInt();
337                 }
338
339                 // Return it
340                 return input;
341         }
342
343         /**
344          * Reads a string of minimum and maximum length from the user
345          *
346          * @param minLength     Minimum length of the string to read
347          * @param maxLength     Maximum length of the string to read
348          * @param message       Message to user
349          * @param allowEmpty Whether to allow empty string
350          * @return Entered string by user or null for empty strings
351          */
352         @Override
353         public String enterString (final int minLength, final int maxLength, final String message, final boolean allowEmpty) {
354                 // Check on length, e.g. country codes are excactly 2 chars long
355                 assert (maxLength >= minLength);
356
357                 // Init input
358                 String input = null;
359
360                 // Check if it is to short or to long
361                 while (((input == null) || ((input.length() < minLength) && (!allowEmpty))) || ((input.length() > 0) && (input.length() < minLength) && (allowEmpty)) || ((input instanceof String) && (input.length() > maxLength))) {
362                         // Output message
363                         System.out.print(message);
364
365                         // Read line
366                         input = this.readString();
367                 }
368
369                 // Return it
370                 return input;
371         }
372
373         /**
374          * Returns a console menu item
375          *
376          * @param accessKey Key to access the menu
377          * @param text Text to show to user
378          * @return A SelectableMenuItem
379          * @todo Make sure the access key is unique
380          */
381         @Override
382         public SelectableMenuItem getMenuItem (final char accessKey, final String text) {
383                 // Return a new console menu item
384                 return new ConsoleMenuItem(accessKey, text);
385         }
386
387         /**
388          * Inizializes this client
389          */
390         @Override
391         public void init () {
392                 // Init contact manager here
393                 this.initContactManager();
394
395                 // Fill menu map
396                 this.fillMenuMap();
397         }
398
399         /**
400          * Displays textural message to the user
401          *
402          * @param message
403          */
404         @Override
405         public void outputMessage (final String message) {
406                 System.out.println(message);
407         }
408
409         /**
410          * Shows textural menu on console
411          */
412         @Override
413         public void showCurrentMenu () {
414                 this.showMenu(this.getCurrentMenu());
415         }
416
417         /**
418          * Shows given menu entry to user
419          *
420          * @param item Menu entry
421          */
422         @Override
423         public void showEntry (final SelectableMenuItem item) {
424                 // Access key then text
425                 this.outputMessage("[" + item.getAccessKey() + "] " + item.getText());
426         }
427
428         /**
429          * Shows a textural message to the user
430          */
431         @Override
432         public void showWelcome () {
433                 this.outputMessage(MessageFormat.format("Welcome to {0}", AddressbookApplication.printableTitle()));
434                 this.outputMessage("");
435                 this.outputMessage("Copyright(c) 2015 by Roland Haeder, this is free software");
436
437                 // Debug message
438                 this.getLogger().debug("Intro shown to user");
439         }
440
441         @Override
442         public void userChooseChangeContactData (final Contact contact) throws UnhandledUserChoiceException {
443                 // Ask the user for editing [name], [a]ddress or [other] data
444                 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) ");
445
446                 // @TODO Get rid of this ugly switch block, too
447                 switch (choice) {
448                         case 'n': // Name data
449                                 this.getContactManager().doChangeNameData(contact, this);
450                                 break;
451
452                         case 'a': // Address data
453                                 this.getContactManager().doChangeAddressData(contact, this);
454                                 break;
455
456                         case 'o': // Other data
457                                 this.getContactManager().doChangeOtherData(contact, this);
458                                 break;
459
460                         case 'x': // Exit this menu
461                                 // Ignored as it should go back
462                                 break;
463
464                         default:
465                                 // @TODO throw own exception
466                                 throw new UnhandledUserChoiceException(MessageFormat.format("Choice '{0}' not handled yet.", choice));
467                 }
468         }
469
470         /**
471          * Reads one character
472          *
473          * @return A single character
474          */
475         private char readChar () {
476                 // Read line
477                 String input = this.readString();
478
479                 // This must be only one character
480                 if (input.length() != 1) {
481                         // Return zero
482                         return 0;
483                 }
484
485                 // Get char from first (and only) position
486                 return input.charAt(0);
487         }
488
489         /**
490          * Reads an integer (int) from user
491          *
492          * @return An integer number
493          */
494         private int readInt () {
495                 // First read a string
496                 String input = this.readString();
497
498                 // Init number with invalid value
499                 int num = -1;
500
501                 // Parse number, this can be risky
502                 try {
503                         num = Integer.parseInt(input);
504                 } catch (final NumberFormatException e) {
505                         this.outputMessage("Bitte geben Sie nur Zahlen ein!");
506                         this.getLogger().warn(MessageFormat.format("No numbers-only entered. input={0},message={1}", input, e.getMessage()));
507                 }
508
509                 // Return read number
510                 return num;
511         }
512
513         /**
514          * Reads a string from a scanner until RETURN is pressed
515          *
516          * @return Read string from scanner
517          */
518         private String readString () {
519                 return this.scanner.nextLine();
520         }
521
522         /**
523          * Fills menu map with menu entries
524          */
525         @Override
526         protected final void fillMenuMap () {
527                 // Initialize first (main) menu
528                 Menu menu = new ConsoleMenu("main", this);
529
530                 // Add it
531                 this.getMenus().put("main", menu);
532         }
533 }