]> git.mxchange.org Git - jaddressbook-lib.git/blob - Addressbook/src/org/mxchange/addressbook/manager/contact/ContactManager.java
f502e1e3daef2001ddb543f90fdf2eea557392af
[jaddressbook-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.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                 // Set client instance
68                 this.setClient(client);
69
70                 // Init contacts
71                 this.contacts = new ArrayList<>(maxContacts);
72
73                 // Init database connection
74                 this.contactDatabase = new ContactDatabaseFrontend(this);
75
76                 // Initialize list
77                 this.columnNames = new ArrayList<>(15);
78
79                 // And fill it
80                 this.fillColumnNamesFromBundle();
81
82                 // Read all entries
83                 this.contactDatabase.readAllContacts();
84
85                 // Debug message
86                 //* NOISY-DEBUG: */ this.getLogger().debug("client=" + client);
87         }
88
89         /**
90          * Adds given Contact instance to list
91          *
92          * @param contact Contact instance to add
93          */
94         @Override
95         public void addContact (final Contact contact) {
96                 assert (this.contacts instanceof List) : "this.contacts is not initialized";
97
98                 this.contacts.add(contact);
99         }
100
101         /**
102          * Let the user add a new other address
103          */
104         @Override
105         public void doAddOtherAddress () {
106                 throw new UnsupportedOperationException("Not supported yet.");
107         }
108
109         /**
110          * Let the user change address data
111          *
112          * @param contact Instance to change data
113          * @param client Client instance to call back
114          */
115         @Override
116         public void doChangeAddressData (final Contact contact, final Client client) {
117                 // First display it again
118                 client.displayAddressBox(contact);
119
120                 // Is it own data?
121                 if (contact.isOwnContact()) {
122                         // Deligate to client
123                         this.getClient().doChangeOwnAddressData(contact);
124                 } else {
125                         // Other contact's address data to change
126                         throw new UnsupportedOperationException("Changing contact entries not finished.");
127                 }
128
129                 // Flush whole list
130                 this.flush();
131         }
132
133         /**
134          * Let the user change "name data"
135          *
136          * @param contact Instance to change data
137          * @param client Client instance to call back
138          */
139         @Override
140         public void doChangeNameData (final Contact contact, final Client client) {
141                 // First display them again
142                 client.displayNameBox(contact);
143
144                 // Is this own data?
145                 if (contact.isOwnContact()) {
146                         // Re-ask own data
147                         this.getClient().doChangeOwnNameData(contact);
148                 } else {
149                         // Then re-ask them ...
150                         throw new UnsupportedOperationException("Changing contact entries not finished.");
151                 }
152
153                 // Flush whole list
154                 this.flush();
155         }
156
157         /**
158          * Let the user change other address
159          */
160         @Override
161         public void doChangeOtherAddress () {
162                 throw new UnsupportedOperationException("Not supported yet.");
163         }
164
165         /**
166          * Let the user change other data
167          *
168          * @param contact Instance to change data
169          * @param client Client instance to call back
170          * @todo Didn't handle birthday
171          */
172         @Override
173         public void doChangeOtherData (final Contact contact, final Client client) {
174                 // First display them again
175                 this.getClient().displayOtherDataBox(contact);
176
177                 // Is this own data?
178                 if (contact.isOwnContact()) {
179                         // Re-ask own data
180                         this.getClient().doChangeOwnOtherData(contact);
181                 } else {
182                         // Then re-ask them ...
183                         throw new UnsupportedOperationException("Changing contact entries not finished.");
184                 }
185
186                 // Flush whole list
187                 this.flush();
188         }
189
190         /**
191          * Allows the user to change his/her own data
192          */
193         @Override
194         public void doChangeOwnData () {
195                 /*
196                  * First check if the user has registered own contact, before that
197                  * nothing can be changed.
198                  */
199                 if (!this.isOwnContactAdded()) {
200                         // Not added
201                         this.getClient().outputMessage("Sie haben noch nicht Ihre Daten eingegeben.");
202
203                         // Skip any below code
204                         return;
205                 }
206
207                 // Instance
208                 Contact contact = this.getOwnContact();
209
210                 // It must be found
211                 assert (contact instanceof Contact);
212
213                 // Display contact
214                 contact.show(this.getClient());
215
216                 try {
217                         // Ask user what to change
218                         this.getClient().userChooseChangeContactData(contact);
219                 } catch (final UnhandledUserChoiceException ex) {
220                         this.getLogger().catching(ex);
221                 }
222         }
223
224         /**
225          * Let the user delete other address
226          */
227         @Override
228         public void doDeleteOtherAddress () {
229                 throw new UnsupportedOperationException("Not supported yet.");
230         }
231
232         /**
233          * Asks user for own data
234          */
235         @Override
236         public void doEnterOwnData () {
237                 // Deligate this call to the client
238                 Contact contact = this.getClient().doEnterOwnData();
239
240                 // Is it set?
241                 if (contact instanceof Contact) {
242                         // Add it to contact "book"
243                         this.registerContact(contact);
244                 }
245         }
246
247         @Override
248         public void doListContacts () {
249                 throw new UnsupportedOperationException("Not supported yet.");
250         }
251
252         @Override
253         public void doSearchContacts () {
254                 throw new UnsupportedOperationException("Not supported yet.");
255         }
256
257         /**
258          * Shuts down this contact manager
259          */
260         @Override
261         public void doShutdown () {
262                 // Shut down the database layer
263                 this.getContactDatabase().doShutdown();
264         }
265
266         /**
267          * Asks the user for his/her cellphone number
268          *
269          * @return User's cellphone number
270          */
271         @Override
272         public String enterOwnCellNumber () {
273                 return this.getClient().enterString(5, 30, "Bitte geben Sie Ihre Handynummer an: ", true);
274         }
275
276         /**
277          * Asks the user for his/her city's name
278          *
279          * @return City's name of the user
280          */
281         @Override
282         public String enterOwnCity () {
283                 return this.getClient().enterString(3, 50, "Bitte geben Sie Ihre Wohnort ein: ", false);
284         }
285
286         /**
287          * Asks the user for his/her city's name
288          *
289          * @return City's name of the user
290          */
291         @Override
292         public String enterOwnComment () {
293                 return this.getClient().enterString(0, 100, "Kommentar zu Ihrem Eintrag: ", true);
294         }
295
296         /**
297          * Asks the user for his/her company name
298          *
299          * @return User's company name
300          */
301         @Override
302         public String enterOwnCompanyName () {
303                 return this.getClient().enterString(5, 50, "Bitte geben Sie Ihre Firmenbezeichnung ein: ", true);
304         }
305
306         /**
307          * Asks user for his/her own country code
308          *
309          * @return User's own country code
310          */
311         @Override
312         public String enterOwnCountryCode () {
313                 return this.getClient().enterString(2, 2, "Bitte geben Sie den zweistelligen Ländercode von Ihrem Land ein: ", false).toUpperCase();
314         }
315
316         /**
317          * Asks user for his/her own country code
318          *
319          * @return User's own country code
320          */
321         @Override
322         public String enterOwnEmailAddress () {
323                 return this.getClient().enterString(10, 50, "Bitte geben Sie Ihre Email-Adresse ein: ", true);
324         }
325
326         /**
327          * Asks the user for family name
328          *
329          * @return Family name of the user
330          */
331         @Override
332         public String enterOwnFamilyName () {
333                 return this.getClient().enterString(2, 50, "Bitte geben Sie Ihren Nachnamen ein: ", false);
334         }
335
336         /**
337          * Asks the user for family name
338          *
339          * @return Family name of the user
340          */
341         @Override
342         public String enterOwnFaxNumber () {
343                 return this.getClient().enterString(5, 30, "Bitte geben Sie Ihre Faxnummer an: ", true);
344         }
345
346         /**
347          * Asks the user for gender, until a valid has been entered
348          *
349          * @return Gender of the user
350          */
351         @Override
352         public Gender enterOwnGender () {
353                 return this.getClient().enterGender("Bitte geben Sie die Anrede ein: (M=Herr, F=Frau, C=Firma): ");
354         }
355
356         /**
357          * Asks the user for phone number
358          *
359          * @return Phone number of the user
360          */
361         @Override
362         public String enterOwnPhoneNumber () {
363                 return this.getClient().enterString(5, 30, "Bitte geben Sie Ihre Telefonnummer an: ", true);
364         }
365
366         /**
367          * Asks the user for own street (including number)
368          *
369          * @return Own street an number
370          */
371         @Override
372         public String enterOwnStreet () {
373                 return this.getClient().enterString(5, 50, "Bitte geben Sie Ihre Strasse und Hausnummer ein: ", false);
374         }
375
376         /**
377          * Asks the user for surname
378          *
379          * @return Surname of the user
380          */
381         @Override
382         public String enterOwnSurname () {
383                 return this.getClient().enterString(2, 50, "Bitte geben Sie Ihren Vornamen ein: ", false);
384         }
385
386         /**
387          * Asks the user for own ZIP code
388          *
389          * @return ZIP code
390          */
391         @Override
392         public int enterOwnZipCode () {
393                 return this.getClient().enterInt(0, 99_999, "Bitte geben Sie Ihre Postleitzahl ein: ");
394         }
395
396         @Override
397         public final int getColumnCount () {
398                 assert (this.columnNames instanceof List) : "this.columnNames is not initialized";
399
400                 return this.columnNames.size();
401         }
402
403         /**
404          * Getter for column name at given index.
405          *
406          * @param columnIndex Column index
407          * @return Human-readable column name
408          */
409         @Override
410         public String getColumnName (final int columnIndex) {
411                 assert (this.columnNames instanceof List) : "this.columnNames is not initialized";
412
413                 // Get column name at index
414                 return this.columnNames.get(columnIndex);
415         }
416
417         /**
418          * Getter for whole contact list
419          *
420          * @return List of all contacts
421          */
422         @Override
423         public List<Contact> getList () {
424                 assert (this.contacts instanceof List) : "this.contacts is not initialized";
425                 return Collections.unmodifiableList(this.contacts);
426         }
427
428         /**
429          * Checks whether own contact is already added by checking all entries for
430          * isOwnContact flag
431          *
432          * @return Whether own contact is already added
433          */
434         @Override
435         public boolean isOwnContactAdded () {
436                 // Trace message
437                 this.getLogger().trace("CALLED!");
438
439                 assert (this.contacts instanceof List) : "this.contacts is not initialized";
440
441                 // Default is not added
442                 boolean isAdded = false;
443
444                 // Now get it back from address book, first get an iterator
445                 Iterator<Contact> iterator = this.contacts.iterator();
446
447                 // Check entries
448                 while (iterator.hasNext()) {
449                         // Get next entry
450                         Contact contact = iterator.next();
451
452                         // Is it valid?
453                         if (contact instanceof Contact) {
454                                 // Get flag
455                                 isAdded = contact.isOwnContact();
456
457                                 // Is this own contact?
458                                 if (isAdded) {
459                                         // Then abort loop
460                                         break;
461                                 }
462                         }
463                 }
464
465                 // Trace message
466                 this.getLogger().trace(MessageFormat.format("isAdded={0} : EXIT!", isAdded));
467
468                 // Return result
469                 return isAdded;
470         }
471
472         /**
473          * Adds given contact to address book and flushes all entries to database
474          *
475          * @param contact Contact being added
476          * @todo Add check for book size
477          */
478         @Override
479         public void registerContact (final Contact contact) {
480                 // Sanity check
481                 if (contact == null) {
482                         // Abort here
483                         throw new NullPointerException("contact is null");
484                 }
485
486                 // Check if contact is found
487                 if (this.isContactAlreadyAdded(contact)) {
488                         // Contact already added
489                         // @todo Do something here
490                 } else if ((contact.isOwnContact()) && (this.isOwnContactAdded())) {
491                         // Own contact already added
492                         // @todo Do something
493                 }
494
495                 // Debug message
496                 /* NOISY-DEBUG: */ this.getLogger().debug(MessageFormat.format("Adding '{0}' '{1}' at pos '{2}' ...", contact.getSurname(), contact.getFamilyName(), this.size()));
497
498                 // Add contact to internal list
499                 this.addContact(contact);
500
501                 // Flush whole list
502                 this.flush();
503         }
504
505         /**
506          * Getter for size
507          *
508          * @return size of contact "book"
509          */
510         @Override
511         public final int size () {
512                 assert (this.contacts instanceof List) : "this.contacts is not initialized";
513                 return this.contacts.size();
514         }
515
516         /**
517          * Fills the column names array with strings from bundle
518          */
519         private void fillColumnNamesFromBundle () {
520                 assert (this.columnNames instanceof List) : "this.columnNames is not initialized";
521
522                 // Debug message
523                 this.getLogger().trace("CALLED!");
524
525                 // First get an iterator from key set to iterate over
526                 Iterator<String> iterator = this.getBundle().keySet().iterator();
527
528                 // Then iterate over all
529                 while (iterator.hasNext()) {
530                         // Get next element
531                         String key = iterator.next();
532
533                         // Does the key start with ContactManager.columnName ?
534                         if (key.startsWith("ContactManager.columnName")) {
535                                 // This is the wanted entry.
536                                 this.getLogger().debug(MessageFormat.format("key={0}", key));
537
538                                 // So add it
539                                 this.columnNames.add(this.getBundle().getString(key));
540                         }
541                 }
542
543                 // Debug message
544                 this.getLogger().trace(MessageFormat.format("getColumnCount()={0}: EXIT!", this.getColumnCount()));
545         }
546
547         /**
548          * Flushes all entries by calling database backend
549          */
550         private void flush () {
551                 // Flusgh all
552                 this.getContactDatabase().flushAllContacts();
553         }
554
555         /**
556          * A ContactWrapper instance
557          *
558          * @return the database
559          */
560         private ContactWrapper getContactDatabase () {
561                 return this.contactDatabase;
562         }
563
564         /**
565          * "Getter" for own contact instance or null if not found
566          *
567          * @return Contact instance or null
568          */
569         private Contact getOwnContact () {
570                 assert (this.contacts instanceof List) : "this.contacts is not initialized";
571
572                 // Now get it back from address book, first get an iterator
573                 Iterator<Contact> iterator = this.contacts.iterator();
574
575                 // Init instance
576                 Contact contact = null;
577
578                 // Search all contact
579                 while (iterator.hasNext()) {
580                         // Get next instance
581                         Contact next = iterator.next();
582
583                         // Is this own contact?
584                         if (next.isOwnContact()) {
585                                 // Found it
586                                 contact = next;
587                                 break;
588
589                         }
590                 }
591
592                 // Return instance or null
593                 return contact;
594         }
595
596         /**
597          * Checks whether given contact was found in "address book"
598          *
599          * @param checkContact Contact to be checked
600          * @return TRUE if found, FALSE if not found
601          */
602         private boolean isContactAlreadyAdded (final Contact checkContact) throws NullPointerException {
603                 assert (this.contacts instanceof List) : "this.contacts is not initialized";
604
605                 // Default is not found
606                 boolean isFound = false;
607
608                 // Debug message
609                 //* NOISY-DEBUG: */ this.getLogger().debug("Checking '" +  this.contacts.length + "' entries...");
610                 // Now get it back from address book, first get an iterator
611                 Iterator<Contact> iterator = this.contacts.iterator();
612
613                 // Check entries
614                 while (iterator.hasNext()) {
615                         // Get next entry
616                         Contact contact = iterator.next();
617
618                         // Debug message
619                         //* NOISY-DEBUG: */ this.getLogger().debug("contact=" + contact + ",checkContent=" + checkContact);
620                         // Is it valid?
621                         if ((contact instanceof Contact) && ((contact.equals(checkContact)))) {
622                                 // Found matching entry
623                                 isFound = true;
624                                 break;
625                         }
626                 }
627
628                 // Return result
629                 return isFound;
630         }
631 }