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