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