]> git.mxchange.org Git - jfinancials-swing.git/blob - Addressbook/src/org/mxchange/addressbook/manager/contact/ContactManager.java
Added a lot trace messages + sanity checks for null references and such things
[jfinancials-swing.git] / Addressbook / src / org / mxchange / addressbook / manager / contact / ContactManager.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.manager.contact;
18
19 import java.text.MessageFormat;
20 import java.util.ArrayList;
21 import java.util.Collections;
22 import java.util.Iterator;
23 import java.util.List;
24 import org.mxchange.addressbook.client.Client;
25 import org.mxchange.addressbook.contact.Contact;
26 import org.mxchange.addressbook.contact.Gender;
27 import org.mxchange.addressbook.database.frontend.contact.ContactDatabaseFrontend;
28 import org.mxchange.addressbook.database.frontend.contact.ContactWrapper;
29 import org.mxchange.addressbook.exceptions.UnhandledUserChoiceException;
30 import org.mxchange.addressbook.manager.BaseManager;
31
32 /**
33  * A manager for contacts, please note that this implementation loads the whole
34  * list into RAM.
35  *
36  * @author Roland Haeder
37  * @version 0.0
38  */
39 public class ContactManager extends BaseManager implements ManageableContact {
40
41         /**
42          * Column name list
43          */
44         private final List<String> columnNames;
45
46         /**
47          * A ContactWrapper instance
48          */
49         private final ContactWrapper contactDatabase;
50
51         /**
52          * A list of all contacts
53          */
54         private final List<Contact> contacts;
55
56         /**
57          * Constructor which accepts maxContacts for maximum (initial) contacts and
58          * a client instance.
59          *
60          * @param maxContacts Maximum allowed contacts
61          * @param client Client instance to use
62          */
63         public ContactManager (final int maxContacts, final Client client) {
64                 // Always call super constructor first
65                 super();
66
67                 // Trace message
68                 this.getLogger().trace(MessageFormat.format("maxContacts={0},client={1} - CALLED!", maxContacts, client)); //NOI18N
69
70                 // Make sure all parameters are set correctly
71                 if (maxContacts <= 0) {
72                         // Must not be zero or smaller
73                         throw new IllegalArgumentException(MessageFormat.format("maxContacts is below or zero: {0}", maxContacts)); //NOI18N
74                 } else if (client == null) {
75                         // Abort here
76                         throw new NullPointerException("client is null"); //NOI18N
77                 }
78
79                 // Set client instance
80                 this.setClient(client);
81
82                 // Init contacts
83                 this.contacts = new ArrayList<>(maxContacts);
84
85                 // Init database connection
86                 this.contactDatabase = new ContactDatabaseFrontend(this);
87
88                 // Initialize list
89                 this.columnNames = new ArrayList<>(15);
90
91                 // And fill it
92                 this.fillColumnNamesFromBundle();
93
94                 // Read all entries
95                 this.contactDatabase.readAllContacts();
96
97                 // Debug message
98                 //* NOISY-DEBUG: */ this.getLogger().debug("client=" + client);
99         }
100
101         /**
102          * Adds given Contact instance to list
103          *
104          * @param contact Contact instance to add
105          */
106         @Override
107         public void addContact (final Contact contact) {
108                 assert (this.contacts instanceof List) : "this.contacts is not initialized"; //NOI18N
109
110                 // Trace message
111                 this.getLogger().trace(MessageFormat.format("contact={0} - CALLED!", contact)); //NOI18N
112
113                 // Contact instance must not be null
114                 if (contact == null) {
115                         // Abort here
116                         throw new NullPointerException("contact is null"); //NOI18N
117                 }
118
119                 // Add it
120                 this.contacts.add(contact);
121
122                 // Trace message
123                 this.getLogger().trace("EXIT!"); //NOI18N
124         }
125
126         /**
127          * Let the user add a new other address
128          */
129         @Override
130         public void doAddOtherAddress () {
131                 throw new UnsupportedOperationException("Not supported yet."); //NOI18N
132         }
133
134         /**
135          * Let the user change address data
136          *
137          * @param contact Instance to change data
138          */
139         @Override
140         public void doChangeAddressData (final Contact contact) {
141                 // Trace message
142                 this.getLogger().trace(MessageFormat.format("contact={0} CALLED!", contact)); //NOI18N
143
144                 // Contact must not be null
145                 if (contact == null) {
146                         // Abort here
147                         throw new NullPointerException("contact is null"); //NOI18N
148                 }
149
150                 // First display it again
151                 this.getClient().displayAddressBox(contact);
152
153                 // Is it own data?
154                 if (contact.isOwnContact()) {
155                         // Deligate to client
156                         this.getClient().doChangeOwnAddressData(contact);
157                 } else {
158                         // Other contact's address data to change
159                         throw new UnsupportedOperationException("Changing contact entries not finished."); //NOI18N
160                 }
161
162                 // Flush whole list
163                 this.flush();
164
165                 // Trace message
166                 this.getLogger().trace("EXIT!"); //NOI18N
167         }
168
169         /**
170          * Let the user change "name data"
171          *
172          * @param contact Instance to change data
173          */
174         @Override
175         public void doChangeNameData (final Contact contact) {
176                 // Trace message
177                 this.getLogger().trace(MessageFormat.format("contact={0} CALLED!", contact)); //NOI18N
178
179                 // Contact must not be null
180                 if (contact == null) {
181                         // Abort here
182                         throw new NullPointerException("contact is null"); //NOI18N
183                 }
184
185                 // First display them again
186                 this.getClient().displayNameBox(contact);
187
188                 // Is this own data?
189                 if (contact.isOwnContact()) {
190                         // Re-ask own data
191                         this.getClient().doChangeOwnNameData(contact);
192                 } else {
193                         // Then re-ask them ...
194                         throw new UnsupportedOperationException("Changing contact entries not finished."); //NOI18N
195                 }
196
197                 // Flush whole list
198                 this.flush();
199                 // Trace message
200                 this.getLogger().trace("EXIT!"); //NOI18N
201         }
202
203         /**
204          * Let the user change other address
205          */
206         @Override
207         public void doChangeOtherAddress () {
208                 throw new UnsupportedOperationException("Not supported yet."); //NOI18N
209         }
210
211         /**
212          * Let the user change other data
213          *
214          * @param contact Instance to change data
215          * @todo Didn't handle birthday
216          */
217         @Override
218         public void doChangeOtherData (final Contact contact) {
219                 // Trace message
220                 this.getLogger().trace(MessageFormat.format("contact={0} CALLED!", contact)); //NOI18N
221
222                 // Contact must not be null
223                 if (contact == null) {
224                         // Abort here
225                         throw new NullPointerException("contact is null"); //NOI18N
226                 }
227
228                 // First display them again
229                 this.getClient().displayOtherDataBox(contact);
230
231                 // Is this own data?
232                 if (contact.isOwnContact()) {
233                         // Re-ask own data
234                         this.getClient().doChangeOwnOtherData(contact);
235                 } else {
236                         // Then re-ask them ...
237                         throw new UnsupportedOperationException("Changing contact entries not finished."); //NOI18N
238                 }
239
240                 // Flush whole list
241                 this.flush();
242
243                 // Trace message
244                 this.getLogger().trace("EXIT!"); //NOI18N
245         }
246
247         /**
248          * Allows the user to change his/her own data
249          */
250         @Override
251         public void doChangeOwnData () {
252                 // Trace message
253                 this.getLogger().trace("CALLED!"); //NOI18N
254
255                 /*
256                  * First check if the user has registered own contact, before that
257                  * nothing can be changed.
258                  */
259                 if (!this.isOwnContactAdded()) {
260                         // Not added
261                         this.getClient().outputMessage("Sie haben noch nicht Ihre Daten eingegeben."); //NOI18N
262
263                         // Skip any below code
264                         return;
265                 }
266
267                 // Instance
268                 Contact contact = this.getOwnContact();
269
270                 // It must be found
271                 assert (contact instanceof Contact);
272
273                 // Display contact
274                 contact.show(this.getClient());
275
276                 try {
277                         // Ask user what to change
278                         this.getClient().userChooseChangeContactData(contact);
279                 } catch (final UnhandledUserChoiceException ex) {
280                         this.getLogger().catching(ex);
281                 }
282
283                 // Trace message
284                 this.getLogger().trace("EXIT!"); //NOI18N
285         }
286
287         /**
288          * Let the user delete other address
289          */
290         @Override
291         public void doDeleteOtherAddress () {
292                 throw new UnsupportedOperationException("Not supported yet."); //NOI18N
293         }
294
295         /**
296          * Asks user for own data
297          */
298         @Override
299         public void doEnterOwnData () {
300                 // Trace message
301                 this.getLogger().trace("CALLED!"); //NOI18N
302
303                 // Deligate this call to the client
304                 Contact contact = this.getClient().doEnterOwnData();
305
306                 // Is it set?
307                 if (contact instanceof Contact) {
308                         // Add it to contact "book"
309                         this.registerContact(contact);
310                 }
311
312                 // Trace message
313                 this.getLogger().trace("EXIT!"); //NOI18N
314         }
315
316         @Override
317         public void doListContacts () {
318                 throw new UnsupportedOperationException("Not supported yet."); //NOI18N
319         }
320
321         @Override
322         public void doSearchContacts () {
323                 throw new UnsupportedOperationException("Not supported yet."); //NOI18N
324         }
325
326         /**
327          * Shuts down this contact manager
328          */
329         @Override
330         public void doShutdown () {
331                 // Trace message
332                 this.getLogger().trace("CALLED!"); //NOI18N
333
334                 // Shut down the database layer
335                 this.getContactDatabase().doShutdown();
336
337                 // Trace message
338                 this.getLogger().trace("EXIT!"); //NOI18N
339         }
340
341         /**
342          * Asks the user for his/her cellphone number
343          *
344          * @return User's cellphone number
345          */
346         @Override
347         public String enterOwnCellNumber () {
348                 // Trace message
349                 this.getLogger().trace("CALLED!"); //NOI18N
350
351                 return this.getClient().enterString(5, 30, "Bitte geben Sie Ihre Handynummer an: ", true);
352         }
353
354         /**
355          * Asks the user for his/her city's name
356          *
357          * @return City's name of the user
358          */
359         @Override
360         public String enterOwnCity () {
361                 // Trace message
362                 this.getLogger().trace("CALLED!"); //NOI18N
363
364                 return this.getClient().enterString(3, 50, "Bitte geben Sie Ihre Wohnort ein: ", false);
365         }
366
367         /**
368          * Asks the user for his/her city's name
369          *
370          * @return City's name of the user
371          */
372         @Override
373         public String enterOwnComment () {
374                 // Trace message
375                 this.getLogger().trace("CALLED!"); //NOI18N
376
377                 return this.getClient().enterString(0, 100, "Kommentar zu Ihrem Eintrag: ", true);
378         }
379
380         /**
381          * Asks the user for his/her company name
382          *
383          * @return User's company name
384          */
385         @Override
386         public String enterOwnCompanyName () {
387                 // Trace message
388                 this.getLogger().trace("CALLED!"); //NOI18N
389
390                 return this.getClient().enterString(5, 50, "Bitte geben Sie Ihre Firmenbezeichnung ein: ", true);
391         }
392
393         /**
394          * Asks user for his/her own country code
395          *
396          * @return User's own country code
397          */
398         @Override
399         public String enterOwnCountryCode () {
400                 // Trace message
401                 this.getLogger().trace("CALLED!"); //NOI18N
402
403                 return this.getClient().enterString(2, 2, "Bitte geben Sie den zweistelligen Ländercode von Ihrem Land ein: ", false).toUpperCase();
404         }
405
406         /**
407          * Asks user for his/her own country code
408          *
409          * @return User's own country code
410          */
411         @Override
412         public String enterOwnEmailAddress () {
413                 // Trace message
414                 this.getLogger().trace("CALLED!"); //NOI18N
415
416                 return this.getClient().enterString(10, 50, "Bitte geben Sie Ihre Email-Adresse ein: ", true);
417         }
418
419         /**
420          * Asks the user for family name
421          *
422          * @return Family name of the user
423          */
424         @Override
425         public String enterOwnFamilyName () {
426                 // Trace message
427                 this.getLogger().trace("CALLED!"); //NOI18N
428
429                 return this.getClient().enterString(2, 50, "Bitte geben Sie Ihren Nachnamen ein: ", false);
430         }
431
432         /**
433          * Asks the user for family name
434          *
435          * @return Family name of the user
436          */
437         @Override
438         public String enterOwnFaxNumber () {
439                 // Trace message
440                 this.getLogger().trace("CALLED!"); //NOI18N
441
442                 return this.getClient().enterString(5, 30, "Bitte geben Sie Ihre Faxnummer an: ", true);
443         }
444
445         /**
446          * Asks the user for gender, until a valid has been entered
447          *
448          * @return Gender of the user
449          */
450         @Override
451         public Gender enterOwnGender () {
452                 // Trace message
453                 this.getLogger().trace("CALLED!"); //NOI18N
454
455                 return this.getClient().enterGender("Bitte geben Sie die Anrede ein: (M=Herr, F=Frau, C=Firma): ");
456         }
457
458         /**
459          * Asks the user for phone number
460          *
461          * @return Phone number of the user
462          */
463         @Override
464         public String enterOwnPhoneNumber () {
465                 // Trace message
466                 this.getLogger().trace("CALLED!"); //NOI18N
467
468                 return this.getClient().enterString(5, 30, "Bitte geben Sie Ihre Telefonnummer an: ", true);
469         }
470
471         /**
472          * Asks the user for own street (including number)
473          *
474          * @return Own street an number
475          */
476         @Override
477         public String enterOwnStreet () {
478                 // Trace message
479                 this.getLogger().trace("CALLED!"); //NOI18N
480
481                 return this.getClient().enterString(5, 50, "Bitte geben Sie Ihre Strasse und Hausnummer ein: ", false);
482         }
483
484         /**
485          * Asks the user for surname
486          *
487          * @return Surname of the user
488          */
489         @Override
490         public String enterOwnSurname () {
491                 // Trace message
492                 this.getLogger().trace("CALLED!"); //NOI18N
493
494                 return this.getClient().enterString(2, 50, "Bitte geben Sie Ihren Vornamen ein: ", false);
495         }
496
497         /**
498          * Asks the user for own ZIP code
499          *
500          * @return ZIP code
501          */
502         @Override
503         public int enterOwnZipCode () {
504                 // Trace message
505                 this.getLogger().trace("CALLED!"); //NOI18N
506
507                 return this.getClient().enterInt(0, 99_999, "Bitte geben Sie Ihre Postleitzahl ein: ");
508         }
509
510         @Override
511         public final int getColumnCount () {
512                 assert (this.columnNames instanceof List) : "this.columnNames is not initialized"; //NOI18N
513
514                 return this.columnNames.size();
515         }
516
517         /**
518          * Getter for column name at given index.
519          *
520          * @param columnIndex Column index
521          * @return Human-readable column name
522          */
523         @Override
524         public String getColumnName (final int columnIndex) {
525                 assert (this.columnNames instanceof List) : "this.columnNames is not initialized"; //NOI18N
526
527                 // Get column name at index
528                 return this.columnNames.get(columnIndex);
529         }
530
531         /**
532          * Getter for whole contact list
533          *
534          * @return List of all contacts
535          */
536         @Override
537         public List<Contact> getList () {
538                 assert (this.contacts instanceof List) : "this.contacts is not initialized"; //NOI18N
539                 return Collections.unmodifiableList(this.contacts);
540         }
541
542         /**
543          * Checks whether own contact is already added by checking all entries for
544          * isOwnContact flag
545          *
546          * @return Whether own contact is already added
547          */
548         @Override
549         public boolean isOwnContactAdded () {
550                 // Trace message
551                 this.getLogger().trace("CALLED!"); //NOI18N
552
553                 assert (this.contacts instanceof List) : "this.contacts is not initialized"; //NOI18N
554
555                 // Default is not added
556                 boolean isAdded = false;
557
558                 // Now get it back from address book, first get an iterator
559                 Iterator<Contact> iterator = this.contacts.iterator();
560
561                 // Check entries
562                 while (iterator.hasNext()) {
563                         // Get next entry
564                         Contact contact = iterator.next();
565
566                         // Is it valid?
567                         if (contact instanceof Contact) {
568                                 // Get flag
569                                 isAdded = contact.isOwnContact();
570
571                                 // Is this own contact?
572                                 if (isAdded) {
573                                         // Then abort loop
574                                         break;
575                                 }
576                         }
577                 }
578
579                 // Trace message
580                 this.getLogger().trace(MessageFormat.format("isAdded={0} : EXIT!", isAdded)); //NOI18N
581
582                 // Return result
583                 return isAdded;
584         }
585
586         /**
587          * Adds given contact to address book and flushes all entries to database
588          *
589          * @param contact Contact being added
590          * @todo Add check for book size
591          */
592         @Override
593         public void registerContact (final Contact contact) {
594                 // Trace message
595                 this.getLogger().trace(MessageFormat.format("contact={0} CALLED!", contact)); //NOI18N
596
597                 // Contact must not be null
598                 if (contact == null) {
599                         // Abort here
600                         throw new NullPointerException("contact is null"); //NOI18N
601                 }
602
603                 // Sanity check
604                 if (contact == null) {
605                         // Abort here
606                         throw new NullPointerException("contact is null"); //NOI18N
607                 }
608
609                 // Check if contact is found
610                 if (this.isContactAlreadyAdded(contact)) {
611                         // Contact already added
612                         // @todo Do something here
613                 } else if ((contact.isOwnContact()) && (this.isOwnContactAdded())) {
614                         // Own contact already added
615                         // @todo Do something
616                 }
617
618                 // Debug message
619                 /* NOISY-DEBUG: */ this.getLogger().debug(MessageFormat.format("Adding '{0}' '{1}' at pos '{2}' ...", contact.getSurname(), contact.getFamilyName(), this.size())); //NOI18N
620
621                 // Add contact to internal list
622                 this.addContact(contact);
623
624                 // Flush whole list
625                 this.flush();
626         }
627
628         /**
629          * Getter for size
630          *
631          * @return size of contact "book"
632          */
633         @Override
634         public final int size () {
635                 assert (this.contacts instanceof List) : "this.contacts is not initialized"; //NOI18N
636                 return this.contacts.size();
637         }
638
639         /**
640          * Fills the column names array with strings from bundle
641          */
642         private void fillColumnNamesFromBundle () {
643                 assert (this.columnNames instanceof List) : "this.columnNames is not initialized"; //NOI18N
644
645                 // Debug message
646                 this.getLogger().trace("CALLED!"); //NOI18N
647
648                 // First get an iterator from key set to iterate over
649                 Iterator<String> iterator = this.getBundle().keySet().iterator();
650
651                 // Then iterate over all
652                 while (iterator.hasNext()) {
653                         // Get next element
654                         String key = iterator.next();
655
656                         // Does the key start with ContactManager.columnName ?
657                         if (key.startsWith("ContactManager.columnName")) { //NOI18N
658                                 // This is the wanted entry.
659                                 this.getLogger().debug(MessageFormat.format("key={0}", key)); //NOI18N
660
661                                 // So add it
662                                 this.columnNames.add(this.getBundle().getString(key));
663                         }
664                 }
665
666                 // Debug message
667                 this.getLogger().trace(MessageFormat.format("getColumnCount()={0}: EXIT!", this.getColumnCount())); //NOI18N
668         }
669
670         /**
671          * Flushes all entries by calling database backend
672          */
673         private void flush () {
674                 // Trace message
675                 this.getLogger().trace("CALLED!"); //NOI18N
676
677                 // Flusgh all
678                 this.getContactDatabase().flushAllContacts();
679
680                 // Trace message
681                 this.getLogger().trace("EXIT!"); //NOI18N
682         }
683
684         /**
685          * A ContactWrapper instance
686          *
687          * @return the database
688          */
689         private ContactWrapper getContactDatabase () {
690                 return this.contactDatabase;
691         }
692
693         /**
694          * "Getter" for own contact instance or null if not found
695          *
696          * @return Contact instance or null
697          */
698         private Contact getOwnContact () {
699                 assert (this.contacts instanceof List) : "this.contacts is not initialized"; //NOI18N
700
701                 // Trace message
702                 this.getLogger().trace("CALLED!"); //NOI18N
703
704                 // Now get it back from address book, first get an iterator
705                 Iterator<Contact> iterator = this.contacts.iterator();
706
707                 // Init instance
708                 Contact contact = null;
709
710                 // Search all contact
711                 while (iterator.hasNext()) {
712                         // Get next instance
713                         Contact next = iterator.next();
714
715                         // Is this own contact?
716                         if (next.isOwnContact()) {
717                                 // Found it
718                                 contact = next;
719                                 break;
720
721                         }
722                 }
723
724                 // Trace message
725                 this.getLogger().trace(MessageFormat.format("contact={0} - EXIT!", contact)); //NOI18N
726
727                 // Return instance or null
728                 return contact;
729         }
730
731         /**
732          * Checks whether given contact was found in "address book"
733          *
734          * @param checkContact Contact to be checked
735          * @return TRUE if found, FALSE if not found
736          */
737         private boolean isContactAlreadyAdded (final Contact checkContact) throws NullPointerException {
738                 assert (this.contacts instanceof List) : "this.contacts is not initialized"; //NOI18N
739
740                 // Trace message
741                 this.getLogger().trace(MessageFormat.format("checkContact={0} - CALLED!", checkContact)); //NOI18N
742
743                 // Contact instance must not be null
744                 if (checkContact == null) {
745                         // Abort here
746                         throw new NullPointerException("checkContact is null");
747                 }
748
749                 // Default is not found
750                 boolean isFound = false;
751
752                 // Debug message
753                 //* NOISY-DEBUG: */ this.getLogger().debug("Checking '" +  this.contacts.length + "' entries...");
754                 // Now get it back from address book, first get an iterator
755                 Iterator<Contact> iterator = this.contacts.iterator();
756
757                 // Check entries
758                 while (iterator.hasNext()) {
759                         // Get next entry
760                         Contact contact = iterator.next();
761
762                         // Debug message
763                         //* NOISY-DEBUG: */ this.getLogger().debug("contact=" + contact + ",checkContent=" + checkContact);
764                         // Is it valid?
765                         if ((contact instanceof Contact) && ((contact.equals(checkContact)))) {
766                                 // Found matching entry
767                                 isFound = true;
768                                 break;
769                         }
770                 }
771
772                 // Trace message
773                 this.getLogger().trace(MessageFormat.format("isFound={0} - EXIT!", isFound)); //NOI18N
774
775                 // Return result
776                 return isFound;
777         }
778 }