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