]> git.mxchange.org Git - jfinancials-swing.git/blob - src/org/mxchange/addressbook/client/console/ConsoleClient.java
some fixes, API has changed, no more cellphone, use mobile instead
[jfinancials-swing.git] / src / org / mxchange / addressbook / client / console / ConsoleClient.java
1 /*
2  * Copyright (C) 2016 Roland Häder
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.io.IOException;
20 import java.sql.SQLException;
21 import java.text.MessageFormat;
22 import java.util.Arrays;
23 import java.util.Scanner;
24 import org.mxchange.addressbook.application.AddressbookApplication;
25 import org.mxchange.addressbook.client.AddressbookClient;
26 import org.mxchange.addressbook.client.BaseAddressbookClient;
27 import org.mxchange.addressbook.facade.contact.ContactFacade;
28 import org.mxchange.addressbook.menu.Menu;
29 import org.mxchange.addressbook.menu.MenuTools;
30 import org.mxchange.addressbook.menu.console.ConsoleMenu;
31 import org.mxchange.addressbook.menu.item.SelectableMenuItem;
32 import org.mxchange.addressbook.menu.item.console.ConsoleMenuItem;
33 import org.mxchange.jcontacts.contact.Contact;
34 import org.mxchange.jcontacts.contact.UserContact;
35 import org.mxchange.jcontacts.contact.gender.Gender;
36 import org.mxchange.jcontacts.contact.gender.GenderUtils;
37 import org.mxchange.jcontacts.exceptions.ContactAlreadyAddedException;
38 import org.mxchange.jcore.application.Application;
39 import org.mxchange.jcore.exceptions.MenuInitializationException;
40 import org.mxchange.jcore.exceptions.UnhandledUserChoiceException;
41 import org.mxchange.jcountry.data.Country;
42 import org.mxchange.jphone.phonenumbers.fax.DialableFaxNumber;
43 import org.mxchange.jphone.phonenumbers.landline.DialableLandLineNumber;
44 import org.mxchange.jphone.phonenumbers.mobile.DialableMobileNumber;
45
46 /**
47  * A client for the console
48  * <p>
49  * @author Roland Häder<roland@mxchange.org>
50  */
51 public class ConsoleClient extends BaseAddressbookClient implements AddressbookClient {
52
53         /**
54          * Scanner instance for reading data from console input
55          */
56         private final Scanner scanner;
57
58         /**
59          * Parameterless constructor
60          * <p>
61          * @param application An instance of an Application class
62          */
63         public ConsoleClient (final Application application) {
64                 // Trace message
65                 this.getLoggerBeanLocal().logTrace(MessageFormat.format("application={0} - CALLED!", application)); //NOI18N
66
67                 // Set application instance
68                 this.setApplication(application);
69
70                 // Init scanner instance
71                 this.scanner = new Scanner(System.in, "UTF-8"); //NOI18N
72
73                 // Trace message
74                 this.getLoggerBeanLocal().logTrace("EXIT!"); //NOI18N
75         }
76
77         @Override
78         public void displayAddressBox (final Contact contact) {
79                 // Trace message
80                 this.getLoggerBeanLocal().logTrace(MessageFormat.format("contact={0} - CALLED!", contact)); //NOI18N
81
82                 // Is it null?
83                 if (null == contact) {
84                         // Abort here
85                         throw new NullPointerException("contact is null"); //NOI18N
86                 }
87
88                 // Simple display ...
89                 this.outputMessage(MessageFormat.format("Strasse, PLZ Ort, Land: {0}\n{1} {2}\n{3}", contact.getContactStreet(), contact.getContactZipCode(), contact.getContactCity(), contact.getContactCountry()));
90
91                 // Trace message
92                 this.getLoggerBeanLocal().logTrace("EXIT!"); //NOI18N
93         }
94
95         @Override
96         public void displayNameBox (final Contact contact) {
97                 // Trace message
98                 this.getLoggerBeanLocal().logTrace(MessageFormat.format("contact={0} - CALLED!", contact)); //NOI18N
99
100                 // Is it null?
101                 if (null == contact) {
102                         // Abort here
103                         throw new NullPointerException("contact is null"); //NOI18N
104                 }
105
106                 // Get translated gender as the user may want to see "Mr.", "Mrs."
107                 String gender = GenderUtils.getTranslatedGender(contact);
108
109                 // Now put all together: gender, surname, family name
110                 this.outputMessage(MessageFormat.format("Anrede, Vorname, Name: {0} {1} {2}", gender, contact.getContactFirstName(), contact.getContactFamilyName()));
111
112                 // Trace message
113                 this.getLoggerBeanLocal().logTrace("EXIT!"); //NOI18N
114         }
115
116         @Override
117         public void displayOtherDataBox (final Contact contact) {
118                 // Trace message
119                 this.getLoggerBeanLocal().logTrace(MessageFormat.format("contact={0} - CALLED!", contact)); //NOI18N
120
121                 // Is it null?
122                 if (null == contact) {
123                         // Abort here
124                         throw new NullPointerException("contact is null"); //NOI18N
125                 }
126
127                 // Mobile and such ...
128                 this.outputMessage(MessageFormat.format("Telefonnumer: {0}\nFaxnummer: {1}\nHandy: {2}\nKommentar:\n{3}", contact.getContactLandLineNumber(), contact.getContactFaxNumber(), contact.getContactMobileNumber(), contact.getContactComment()));
129
130                 // Trace message
131                 this.getLoggerBeanLocal().logTrace("EXIT!"); //NOI18N
132         }
133
134         @Override
135         public void doChangeOwnAddressData (final Contact contact) {
136                 // Trace message
137                 this.getLoggerBeanLocal().logTrace(MessageFormat.format("contact={0} - CALLED!", contact)); //NOI18N
138
139                 // Is it null?
140                 if (null == contact) {
141                         // Abort here
142                         throw new NullPointerException("contact is null"); //NOI18N
143                 }
144
145                 // Make sure it is own contact
146                 if (!contact.isOwnContact()) {
147                         // Not own contact
148                         throw new IllegalArgumentException("Contact is not own data."); //NOI18N
149                 }
150
151                 // Get manager and cast it
152                 ContactFacade manager = (ContactFacade) this.getFacade();
153
154                 // Own street and number
155                 String streetNumber = manager.enterOwnStreet();
156
157                 // Get zip code
158                 Integer zipCode = manager.enterOwnZipCode();
159
160                 // Get city name
161                 String city = manager.enterOwnCity();
162
163                 // Get country code
164                 Country country = manager.enterOwnCountryCode();
165
166                 // Update address data
167                 contact.setContactStreet(streetNumber);
168                 contact.setContactZipCode(zipCode);
169                 contact.setContactCity(city);
170                 contact.setContactCountry(country);
171
172                 // Trace message
173                 this.getLoggerBeanLocal().logTrace("EXIT!"); //NOI18N
174         }
175
176         @Override
177         public void doChangeOwnNameData (final Contact contact) {
178                 // Trace message
179                 this.getLoggerBeanLocal().logTrace(MessageFormat.format("contact={0} - CALLED!", contact)); //NOI18N
180
181                 // Is it null?
182                 if (null == contact) {
183                         // Abort here
184                         throw new NullPointerException("contact is null"); //NOI18N
185                 }
186
187                 // Make sure it is own contact
188                 if (!contact.isOwnContact()) {
189                         // Not own contact
190                         throw new IllegalArgumentException("Contact is not own data."); //NOI18N
191                 }
192
193                 // Get manager and cast it
194                 ContactFacade manager = (ContactFacade) this.getFacade();
195
196                 // Gender:
197                 Gender gender = manager.enterOwnGender();
198
199                 // Surname
200                 String firstName = manager.enterOwnFirstName();
201
202                 // Family name
203                 String familyName = manager.enterOwnFamilyName();
204
205                 // Update contact instance
206                 contact.setContactGender(gender);
207                 contact.setContactFirstName(firstName);
208                 contact.setContactFamilyName(familyName);
209
210                 // Trace message
211                 this.getLoggerBeanLocal().logTrace("EXIT!"); //NOI18N
212         }
213
214         @Override
215         public void doChangeOwnOtherData (final Contact contact) {
216                 // Trace message
217                 this.getLoggerBeanLocal().logTrace(MessageFormat.format("contact={0} - CALLED!", contact)); //NOI18N
218
219                 // Is it null?
220                 if (null == contact) {
221                         // Abort here
222                         throw new NullPointerException("contact is null"); //NOI18N
223                 }
224
225                 // Make sure it is own contact
226                 if (!contact.isOwnContact()) {
227                         // Not own contact
228                         throw new IllegalArgumentException("Contact is not own data."); //NOI18N
229                 }
230
231                 // Get manager and cast it
232                 ContactFacade manager = (ContactFacade) this.getFacade();
233
234                 // Phone number
235                 DialableLandLineNumber phoneNumber = manager.enterOwnPhoneNumber();
236
237                 // Phone number
238                 DialableMobileNumber mobileNumber = manager.enterOwnCellNumber();
239
240                 // Fax number
241                 DialableFaxNumber faxNumber = manager.enterOwnFaxNumber();
242
243                 // Email address
244                 String email = manager.enterOwnEmailAddress();
245
246                 // Comment
247                 String comment = manager.enterOwnComment();
248
249                 // Update contact instance
250                 contact.setContactLandLineNumber(phoneNumber);
251                 contact.setContactMobileNumber(mobileNumber);
252                 contact.setContactFaxNumber(faxNumber);
253                 contact.setContactEmailAddress(email);
254                 contact.setContactComment(comment);
255
256                 // Trace message
257                 this.getLoggerBeanLocal().logTrace("EXIT!"); //NOI18N
258         }
259
260         @Override
261         public Contact doEnterOwnData () {
262                 // Trace message
263                 this.getLoggerBeanLocal().logTrace("CALLED!"); //NOI18N
264
265                 // Get manager and cast it
266                 ContactFacade manager = (ContactFacade) this.getFacade();
267
268                 // First ask for gender
269                 Gender gender = manager.enterOwnGender();
270
271                 // 2nd for first name
272                 String firstName = manager.enterOwnFirstName();
273
274                 // And 3rd for family name
275                 String familyName = manager.enterOwnFamilyName();
276
277                 // Construct UserContact instance
278                 Contact contact = new UserContact(gender, firstName, familyName);
279
280                 // Trace message
281                 this.getLoggerBeanLocal().logTrace(MessageFormat.format("contact={0} - EXIT!", contact)); //NOI18N
282
283                 // And return object
284                 return contact;
285         }
286
287         @Override
288         public void doShutdown () throws SQLException, IOException {
289                 // Trace message
290                 this.getLoggerBeanLocal().logTrace("CALLED!"); //NOI18N
291
292                 // Parent call
293                 super.doShutdown();
294
295                 // TODO Add other shutdown stuff
296                 // Trace message
297                 this.getLoggerBeanLocal().logTrace("EXIT!"); //NOI18N
298         }
299
300         @Override
301         public void doUserMenuChoice () throws UnhandledUserChoiceException, MenuInitializationException {
302                 // Trace message
303                 this.getLoggerBeanLocal().logTrace("CALLED!"); //NOI18N
304
305                 // Get all access keys from menu
306                 char[] accessKeys = MenuTools.getAccessKeysFromMenuMap(this.getMenus(), this.getCurrentMenu());
307
308                 // Output textural message and ask for a char as input
309                 char choice = this.enterChar(accessKeys, "Bitte Auswahl eingeben (0=Programm beenden): ");
310
311                 // Get manager and cast it
312                 ContactFacade manager = (ContactFacade) this.getFacade();
313
314                 // TODO Rewrite this ugly switch() block
315                 switch (choice) {
316                         case '1':
317                                 try {
318                                         // Enter/add own data
319                                         manager.doEnterOwnData();
320                                 } catch (final ContactAlreadyAddedException ex) {
321                                         // Already added
322                                         this.outputMessage("Sie haben bereits Ihre eigenen Daten eingegeben.");
323                                 }
324                                 break;
325
326                         case '2': // Change own data
327                                 manager.doChangeOwnData();
328                                 break;
329
330                         case '3': // Add new addess
331                                 manager.doAddOtherAddress();
332                                 break;
333
334                         case '4': // List contacts
335                                 manager.doListContacts();
336                                 break;
337
338                         case '5': // Search addresses
339                                 manager.doSearchContacts();
340                                 break;
341
342                         case '6': // Change other addess
343                                 manager.doChangeOtherAddress();
344                                 break;
345
346                         case '7': // Delete other address
347                                 manager.doDeleteOtherAddress();
348                                 break;
349
350                         case '0':
351                                 try {
352                                         // Program exit
353                                         this.getApplication().doShutdown();
354                                 } catch (final SQLException | IOException ex) {
355                                         this.abortProgramWithException(ex);
356                                 }
357                                 break;
358
359                         default:
360                                 // TODO throw own exception
361                                 throw new UnhandledUserChoiceException(MessageFormat.format("Choice '{0}' not handled yet.", choice)); //NOI18N
362                 }
363
364                 // Trace message
365                 this.getLoggerBeanLocal().logTrace("EXIT!"); //NOI18N
366         }
367
368         @Override
369         @SuppressWarnings ("UseOfSystemOutOrSystemErr")
370         public char enterChar (final char[] validChars, final String message) {
371                 // Trace message
372                 this.getLoggerBeanLocal().logTrace(MessageFormat.format("validChars={0},message={1} - CALLED!", Arrays.toString(validChars), message)); //NOI18N
373
374                 // The validChars must not null be null and filled with at least one char
375                 if (null == validChars) {
376                         // Is null
377                         throw new NullPointerException("validChars is null"); //NOI18N
378                 } else if (validChars.length == 0) {
379                         // Is not filled
380                         throw new IllegalArgumentException("validChars is not filled."); //NOI18N
381                 }
382
383                 char input = 0;
384
385                 // Sort array, else binarySearch() won't work
386                 Arrays.sort(validChars);
387
388                 // Keep asking until valid char has been entered
389                 while (Arrays.binarySearch(validChars, input) < 0) {
390                         // Output message
391                         System.out.print(message);
392
393                         // Read char
394                         input = this.readChar();
395                 }
396
397                 // Trace message
398                 this.getLoggerBeanLocal().logTrace(MessageFormat.format("input={0} - EXIT!", input)); //NOI18N
399
400                 // Return read char
401                 return input;
402         }
403
404         @Override
405         public Gender enterGender (final String message) {
406                 // Trace message
407                 this.getLoggerBeanLocal().logTrace(MessageFormat.format("message={0} - CALLED!", message)); //NOI18N
408
409                 // Get valid chars
410                 char[] validChars = Gender.validChars();
411
412                 // Debug message
413                 //* NOISY-DEBUG: */ System.out.println(validChars);
414                 // Call inner method
415                 char gender = this.enterChar(validChars, message);
416
417                 // Now get a Gender instance back
418                 Gender g = Gender.fromChar(gender);
419
420                 // g must not be null
421                 assert (g instanceof Gender) : "g is not set."; //NOI18N
422
423                 // Trace message
424                 this.getLoggerBeanLocal().logTrace(MessageFormat.format("g={0} - EXIT!", g)); //NOI18N
425
426                 // Return it
427                 return g;
428         }
429
430         @Override
431         @SuppressWarnings ("UseOfSystemOutOrSystemErr")
432         public int enterInt (final int minimum, final int maximum, final String message) {
433                 // Trace message
434                 this.getLoggerBeanLocal().logTrace(MessageFormat.format("minimum={0},maximum={1},message={2} - CALLED!", minimum, maximum, message)); //NOI18N
435
436                 // Minimum should not be below zero
437                 assert (minimum >= 0) : MessageFormat.format("minimum={0} is below zero", minimum); //NOI18N
438                 assert (maximum > minimum) : MessageFormat.format("maximum {0} is smaller than minimum {1}", maximum, minimum); //NOI18N
439
440                 // Init input
441                 int input = -1;
442
443                 while ((input < minimum) || (input > maximum)) {
444                         // Output message
445                         System.out.print(message);
446
447                         // Read integer from user
448                         input = this.readInt();
449                 }
450
451                 // Trace message
452                 this.getLoggerBeanLocal().logTrace(MessageFormat.format("input={0} - EXIT!", input)); //NOI18N
453
454                 // Return it
455                 return input;
456         }
457
458         @Override
459         @SuppressWarnings ("UseOfSystemOutOrSystemErr")
460         public String enterString (final int minLength, final int maxLength, final String message, final boolean allowEmpty) {
461                 // Trace message
462                 this.getLoggerBeanLocal().logTrace(MessageFormat.format("minLength={0},maxLength={1},message={2}allowEmpty={3} - CALLED!", minLength, maxLength, message, allowEmpty)); //NOI18N
463
464                 // Check on length, e.g. country codes are excactly 2 chars long
465                 assert (maxLength >= minLength);
466
467                 // Init input
468                 String input = null;
469
470                 // Check if it is to short or to long
471                 while (((null == input) || ((input.length() < minLength) && (!allowEmpty))) || ((input.length() > 0) && (input.length() < minLength) && (allowEmpty)) || ((input instanceof String) && (input.length() > maxLength))) {
472                         // Output message
473                         System.out.print(message);
474
475                         // Read line
476                         input = this.readString();
477                 }
478
479                 // Trace message
480                 this.getLoggerBeanLocal().logTrace(MessageFormat.format("input={0} - EXIT!", input)); //NOI18N
481
482                 // Return it
483                 return input;
484         }
485
486         @Override
487         public SelectableMenuItem getMenuItem (final char accessKey, final String text) {
488                 // Return a new console menu item
489                 return new ConsoleMenuItem(accessKey, text);
490         }
491
492         @Override
493         public void init () {
494                 // Trace message
495                 this.getLoggerBeanLocal().logTrace("CALLED!"); //NOI18N
496
497                 // Init contact manager here
498                 try {
499                         this.initContactManager();
500                 } catch (final SQLException ex) {
501                         // End here
502                         this.abortProgramWithException(ex);
503                 }
504
505                 // Fill menu map
506                 this.fillMenuMap();
507
508                 // Trace message
509                 this.getLoggerBeanLocal().logTrace("EXIT!"); //NOI18N
510         }
511
512         @Override
513         @SuppressWarnings ("UseOfSystemOutOrSystemErr")
514         public void outputMessage (final String message) {
515                 System.out.println(message);
516         }
517
518         @Override
519         public void show (final Contact contact) {
520                 throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
521         }
522
523         @Override
524         public void showCurrentMenu () {
525                 this.showMenu(this.getCurrentMenu());
526         }
527
528         @Override
529         public void showEntry (final SelectableMenuItem item) {
530                 // Access key then text
531                 this.outputMessage(MessageFormat.format("[{0}] {1}", item.getAccessKey(), item.getText())); //NOI18N
532         }
533
534         @Override
535         public void showWelcome () {
536                 this.outputMessage(MessageFormat.format("Welcome to {0}", AddressbookApplication.printableTitle())); //NOI18N
537                 this.outputMessage(""); //NOI18N
538                 this.outputMessage("Copyright(c) 2016 by Roland Häder, this is free software"); //NOI18N
539
540                 // Debug message
541                 this.getLoggerBeanLocal().logDebug("Intro shown to user"); //NOI18N
542         }
543
544         @Override
545         public void userChooseChangeContactData (final Contact contact) throws UnhandledUserChoiceException {
546                 // Trace message
547                 this.getLoggerBeanLocal().logTrace(MessageFormat.format("contact={0} CALLED!", contact)); //NOI18N
548
549                 // Contact must not be null
550                 if (null == contact) {
551                         // Abort here
552                         throw new NullPointerException("contact is null"); //NOI18N
553                 }
554
555                 // Ask the user for editing [name], [a]ddress or [other] data
556                 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) ");
557
558                 // Get manager and cast it
559                 ContactFacade manager = (ContactFacade) this.getFacade();
560
561                 // TODO Get rid of this ugly switch block, too
562                 switch (choice) {
563                         case 'n': // Name data
564                                 manager.doChangeNameData(contact);
565                                 break;
566
567                         case 'a': // Address data
568                                 manager.doChangeAddressData(contact);
569                                 break;
570
571                         case 'o': // Other data
572                                 manager.doChangeOtherData(contact);
573                                 break;
574
575                         case 'x': // Exit this menu
576                                 // Ignored as it should go back
577                                 break;
578
579                         default:
580                                 // TODO throw own exception
581                                 throw new UnhandledUserChoiceException(MessageFormat.format("Choice '{0}' not handled yet.", choice)); //NOI18N
582                 }
583
584                 // Trace message
585                 this.getLoggerBeanLocal().logTrace("EXIT!"); //NOI18N
586         }
587
588         /**
589          * Reads one character
590          * <p>
591          * @return A single character
592          */
593         private char readChar () {
594                 // Read line
595                 String input = this.readString();
596
597                 // Debug message
598                 this.getLoggerBeanLocal().logDebug(MessageFormat.format("input={0}", input)); //NOI18N
599
600                 // This must be only one character
601                 if (input.length() != 1) {
602                         // Return zero
603                         return 0;
604                 }
605
606                 // Get char from first (and only) position
607                 return input.charAt(0);
608         }
609
610         /**
611          * Reads an integer (int) from user
612          * <p>
613          * @return An integer number
614          */
615         private int readInt () {
616                 // First read a string
617                 String input = this.readString();
618
619                 // Debug message
620                 this.getLoggerBeanLocal().logDebug(MessageFormat.format("input={0}", input)); //NOI18N
621
622                 // Init number with invalid value
623                 int num = -1;
624
625                 // Parse number, this can be risky
626                 try {
627                         num = Integer.parseInt(input);
628                 } catch (final NumberFormatException e) {
629                         this.outputMessage("Bitte geben Sie nur Zahlen ein!");
630                         this.getLoggerBeanLocal().logWarning(MessageFormat.format("No numbers-only entered. input={0},message={1}", input, e.getMessage())); //NOI18N
631                 }
632
633                 // Trace message
634                 this.getLoggerBeanLocal().logTrace(MessageFormat.format("num={0} - EXIT!", num)); //NOI18N
635
636                 // Return read number
637                 return num;
638         }
639
640         /**
641          * Reads a string from a scanner until RETURN is pressed
642          * <p>
643          * @return Read string from scanner
644          */
645         private String readString () {
646                 return this.scanner.nextLine();
647         }
648
649         @Override
650         protected void fillMenuMap () {
651                 // Trace message
652                 this.getLoggerBeanLocal().logTrace("CALLED!"); //NOI18N
653
654                 // Initialize first (main) menu
655                 Menu menu = new ConsoleMenu("main", this); //NOI18N
656
657                 // Add it
658                 this.getMenus().put("main", menu); //NOI18N
659
660                 // Trace message
661                 this.getLoggerBeanLocal().logTrace("EXIT!"); //NOI18N
662         }
663 }