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