2 * Copyright (C) 2015 Roland Haeder
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.
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.
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/>.
17 package org.mxchange.addressbook.manager.contact;
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.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.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;
37 * A manager for contacts, please note that this implementation loads the whole
40 * @author Roland Haeder
43 public class ContactManager extends BaseManager implements ManageableContact {
48 private final List<String> columnNames;
51 * Translated column name list
53 private final List<String> translatedColumnNames;
56 * A ContactFrontend instance
58 private final ContactFrontend contactDatabase;
61 * Constructor which accepts maxContacts for maximum (initial) contacts and
64 * @param client Client instance to use
66 public ContactManager (final Client client) {
68 this.getLogger().trace(MessageFormat.format("client={1} - CALLED!", client)); //NOI18N
70 // Make sure all parameters are set correctly
73 throw new NullPointerException("client is null"); //NOI18N
76 // Set client instance
77 this.setClient(client);
79 // Init database connection
80 this.contactDatabase = new ContactDatabaseFrontend(this);
83 this.columnNames = new ArrayList<>(15);
84 this.translatedColumnNames = new ArrayList<>(15);
87 this.fillColumnNamesFromBundle();
90 //* NOISY-DEBUG: */ this.getLogger().debug("client=" + client);
94 * Adds given Contact instance to list
96 * @param contact Contact instance to add
99 public void addContact (final Contact contact) throws ContactAlreadyAddedException {
101 this.getLogger().trace(MessageFormat.format("contact={0} - CALLED!", contact)); //NOI18N
103 // Contact instance must not be null
104 if (contact == null) {
106 throw new NullPointerException("contact is null"); //NOI18N
110 this.getContactDatabase().addContact(contact);
113 this.getLogger().trace("EXIT!"); //NOI18N
117 * Let the user add a new other address
120 public void doAddOtherAddress () {
121 throw new UnsupportedOperationException("Not supported yet."); //NOI18N
125 * Let the user change address data
127 * @param contact Instance to change data
130 public void doChangeAddressData (final Contact contact) {
132 this.getLogger().trace(MessageFormat.format("contact={0} CALLED!", contact)); //NOI18N
134 // Contact must not be null
135 if (contact == null) {
137 throw new NullPointerException("contact is null"); //NOI18N
140 // Get and cast client instance
141 AddressbookClient client = (AddressbookClient) this.getClient();
143 // First display it again
144 client.displayAddressBox(contact);
147 if (contact.isOwnContact()) {
148 // Deligate to client
149 client.doChangeOwnAddressData(contact);
151 // Other contact's address data to change
152 throw new UnsupportedOperationException("Changing contact entries not finished."); //NOI18N
156 this.getLogger().trace("EXIT!"); //NOI18N
160 * Let the user change "name data"
162 * @param contact Instance to change data
165 public void doChangeNameData (final Contact contact) {
167 this.getLogger().trace(MessageFormat.format("contact={0} CALLED!", contact)); //NOI18N
169 // Contact must not be null
170 if (contact == null) {
172 throw new NullPointerException("contact is null"); //NOI18N
175 // Get and cast client instance
176 AddressbookClient client = (AddressbookClient) this.getClient();
178 // First display them again
179 client.displayNameBox(contact);
182 if (contact.isOwnContact()) {
184 client.doChangeOwnNameData(contact);
186 // Then re-ask them ...
187 throw new UnsupportedOperationException("Changing contact entries not finished."); //NOI18N
191 this.getLogger().trace("EXIT!"); //NOI18N
195 * Let the user change other address
198 public void doChangeOtherAddress () {
199 throw new UnsupportedOperationException("Not supported yet."); //NOI18N
203 * Let the user change other data
205 * @param contact Instance to change data
206 * @todo Didn't handle birthday
209 public void doChangeOtherData (final Contact contact) {
211 this.getLogger().trace(MessageFormat.format("contact={0} CALLED!", contact)); //NOI18N
213 // Contact must not be null
214 if (contact == null) {
216 throw new NullPointerException("contact is null"); //NOI18N
219 // Get and cast client instance
220 AddressbookClient client = (AddressbookClient) this.getClient();
222 // First display them again
223 client.displayOtherDataBox(contact);
226 if (contact.isOwnContact()) {
228 client.doChangeOwnOtherData(contact);
230 // Then re-ask them ...
231 throw new UnsupportedOperationException("Changing contact entries not finished."); //NOI18N
235 this.getLogger().trace("EXIT!"); //NOI18N
239 * Allows the user to change his/her own data
242 public void doChangeOwnData () {
244 this.getLogger().trace("CALLED!"); //NOI18N
247 * First check if the user has registered own contact, before that
248 * nothing can be changed.
250 if (!this.isOwnContactAdded()) {
252 this.getClient().outputMessage("Sie haben noch nicht Ihre Daten eingegeben."); //NOI18N
254 // Skip any below code
259 Contact contact = this.getOwnContact();
262 assert (contact instanceof Contact);
265 contact.show(this.getClient());
267 // Get and cast client instance
268 AddressbookClient client = (AddressbookClient) this.getClient();
271 // Ask user what to change
272 client.userChooseChangeContactData(contact);
273 } catch (final UnhandledUserChoiceException ex) {
274 this.getLogger().catching(ex);
278 this.getLogger().trace("EXIT!"); //NOI18N
282 * Let the user delete other address
285 public void doDeleteOtherAddress () {
286 throw new UnsupportedOperationException("Not supported yet."); //NOI18N
290 * Asks user for own data
293 public void doEnterOwnData () throws ContactAlreadyAddedException {
295 this.getLogger().trace("CALLED!"); //NOI18N
297 // Is own contact already added?
298 if (this.isOwnContactAdded()) {
299 // Don't continue here
300 throw new ContactAlreadyAddedException();
303 // Get and cast client instance
304 AddressbookClient client = (AddressbookClient) this.getClient();
306 // Deligate this call to the client
307 Contact contact = client.doEnterOwnData();
310 if (contact instanceof Contact) {
311 // Add it to contact "book"
312 this.registerContact(contact);
316 this.getLogger().trace("EXIT!"); //NOI18N
320 public void doListContacts () {
321 throw new UnsupportedOperationException("Not supported yet."); //NOI18N
325 public void doSearchContacts () {
326 throw new UnsupportedOperationException("Not supported yet."); //NOI18N
330 * Shuts down this contact manager
333 public void doShutdown () {
335 this.getLogger().trace("CALLED!"); //NOI18N
337 // Shut down the database layer
338 this.getContactDatabase().doShutdown();
341 this.getLogger().trace("EXIT!"); //NOI18N
345 * Asks the user for his/her cellphone number
347 * @return User's cellphone number
350 public String enterOwnCellNumber () {
352 this.getLogger().trace("CALLED!"); //NOI18N
354 // Get and cast client instance
355 AddressbookClient client = (AddressbookClient) this.getClient();
357 return client.enterString(5, 30, "Bitte geben Sie Ihre Handynummer an: ", true);
361 * Asks the user for his/her city's name
363 * @return City's name of the user
366 public String enterOwnCity () {
368 this.getLogger().trace("CALLED!"); //NOI18N
370 // Get and cast client instance
371 AddressbookClient client = (AddressbookClient) this.getClient();
373 return client.enterString(3, 50, "Bitte geben Sie Ihre Wohnort ein: ", false);
377 * Asks the user for his/her city's name
379 * @return City's name of the user
382 public String enterOwnComment () {
384 this.getLogger().trace("CALLED!"); //NOI18N
386 // Get and cast client instance
387 AddressbookClient client = (AddressbookClient) this.getClient();
389 return client.enterString(0, 100, "Kommentar zu Ihrem Eintrag: ", true);
393 * Asks the user for his/her company name
395 * @return User's company name
398 public String enterOwnCompanyName () {
400 this.getLogger().trace("CALLED!"); //NOI18N
402 // Get and cast client instance
403 AddressbookClient client = (AddressbookClient) this.getClient();
405 return client.enterString(5, 50, "Bitte geben Sie Ihre Firmenbezeichnung ein: ", true);
409 * Asks user for his/her own country code
411 * @return User's own country code
414 public String enterOwnCountryCode () {
416 this.getLogger().trace("CALLED!"); //NOI18N
418 // Get and cast client instance
419 AddressbookClient client = (AddressbookClient) this.getClient();
421 return client.enterString(2, 2, "Bitte geben Sie den zweistelligen Ländercode von Ihrem Land ein: ", false).toUpperCase();
425 * Asks user for his/her own country code
427 * @return User's own country code
430 public String enterOwnEmailAddress () {
432 this.getLogger().trace("CALLED!"); //NOI18N
434 // Get and cast client instance
435 AddressbookClient client = (AddressbookClient) this.getClient();
437 return client.enterString(10, 50, "Bitte geben Sie Ihre Email-Adresse ein: ", true);
441 * Asks the user for family name
443 * @return Family name of the user
446 public String enterOwnFamilyName () {
448 this.getLogger().trace("CALLED!"); //NOI18N
450 // Get and cast client instance
451 AddressbookClient client = (AddressbookClient) this.getClient();
453 return client.enterString(2, 50, "Bitte geben Sie Ihren Nachnamen ein: ", false);
457 * Asks the user for family name
459 * @return Family name of the user
462 public String enterOwnFaxNumber () {
464 this.getLogger().trace("CALLED!"); //NOI18N
466 // Get and cast client instance
467 AddressbookClient client = (AddressbookClient) this.getClient();
469 return client.enterString(5, 30, "Bitte geben Sie Ihre Faxnummer an: ", true);
473 * Asks the user for gender, until a valid has been entered
475 * @return Gender of the user
478 public Gender enterOwnGender () {
480 this.getLogger().trace("CALLED!"); //NOI18N
482 // Get and cast client instance
483 AddressbookClient client = (AddressbookClient) this.getClient();
485 return client.enterGender("Bitte geben Sie die Anrede ein: (M=Herr, F=Frau, C=Firma): ");
489 * Asks the user for phone number
491 * @return Phone number of the user
494 public String enterOwnPhoneNumber () {
496 this.getLogger().trace("CALLED!"); //NOI18N
498 // Get and cast client instance
499 AddressbookClient client = (AddressbookClient) this.getClient();
501 return client.enterString(5, 30, "Bitte geben Sie Ihre Telefonnummer an: ", true);
505 * Asks the user for own street (including number)
507 * @return Own street an number
510 public String enterOwnStreet () {
512 this.getLogger().trace("CALLED!"); //NOI18N
514 // Get and cast client instance
515 AddressbookClient client = (AddressbookClient) this.getClient();
517 return client.enterString(5, 50, "Bitte geben Sie Ihre Strasse und Hausnummer ein: ", false);
521 * Asks the user for surname
523 * @return Surname of the user
526 public String enterOwnSurname () {
528 this.getLogger().trace("CALLED!"); //NOI18N
530 // Get and cast client instance
531 AddressbookClient client = (AddressbookClient) this.getClient();
533 return client.enterString(2, 50, "Bitte geben Sie Ihren Vornamen ein: ", false);
537 * Asks the user for own ZIP code
542 public int enterOwnZipCode () {
544 this.getLogger().trace("CALLED!"); //NOI18N
546 // Get and cast client instance
547 AddressbookClient client = (AddressbookClient) this.getClient();
549 return client.enterInt(0, 99_999, "Bitte geben Sie Ihre Postleitzahl ein: ");
553 public final int getColumnCount () {
554 assert (this.columnNames instanceof List) : "this.columnNames is not initialized"; //NOI18N
556 return this.columnNames.size();
560 * Getter for column name at given index.
562 * @param columnIndex Column index
563 * @return Database column name
566 public String getColumnName (final int columnIndex) {
567 assert (this.columnNames instanceof List) : "this.columnNames is not initialized"; //NOI18N
569 // Get column name at index
570 return this.columnNames.get(columnIndex);
574 * Getter for translated column name at given index.
576 * @param columnIndex Column index
577 * @return Human-readable column name
580 public String getTranslatedColumnName (final int columnIndex) {
581 assert (this.translatedColumnNames instanceof List) : "this.translatedColumnNames is not initialized"; //NOI18N
583 // Get column name at index
584 return this.translatedColumnNames.get(columnIndex);
588 * Somewhat "getter" for value from given row and column index
590 * @param rowIndex Row index
591 * @param columnIndex Column index
592 * @return Value from given row/column
595 public Object getValueFromRowColumn (final int rowIndex, final int columnIndex) {
597 this.getLogger().trace(MessageFormat.format("rowIndex={0},columnIndex={1} CALLED!", rowIndex, columnIndex));
599 // Then get specific row from database which is a Contact instance
600 Contact contact = this.getContactDatabase().readSingleContact(rowIndex);
603 this.getLogger().debug(MessageFormat.format("contact={0}", contact));
605 // It may return null
606 if (contact == null) {
608 this.getLogger().warn("contact is null - returning null ...");
612 // Convert column index -> name
613 String columnName = this.getColumnName(columnIndex);
616 this.getLogger().debug(MessageFormat.format("columnName={0}", columnName));
618 // Now get that column
619 Object value = contact.getValueFromColumn(columnName);
622 this.getLogger().trace(MessageFormat.format("value={0} - EXIT!", value));
629 * Checks whether own contact is already added by checking all entries for
632 * @return Whether own contact is already added
635 public boolean isOwnContactAdded () {
637 this.getLogger().trace("CALLED!"); //NOI18N
640 boolean isAdded = false;
643 // Deligate this call to frontend
644 isAdded = this.getContactDatabase().isOwnContactFound();
645 } catch (final SQLException ex) {
646 // Something bad happened
647 this.abortProgramWithException(ex);
651 this.getLogger().trace(MessageFormat.format("isAdded={0} : EXIT!", isAdded)); //NOI18N
658 * Adds given contact to address book and flushes all entries to database
660 * @param contact Contact being added
661 * @todo Add check for book size
664 public void registerContact (final Contact contact) {
666 this.getLogger().trace(MessageFormat.format("contact={0} CALLED!", contact)); //NOI18N
669 if (contact == null) {
671 throw new NullPointerException("contact is null"); //NOI18N
675 /* NOISY-DEBUG: */ this.getLogger().debug(MessageFormat.format("Adding '{0}' '{1}' at pos '{2}' ...", contact.getSurname(), contact.getFamilyName(), this.size())); //NOI18N
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
686 // Add contact to internal list
687 this.addContact(contact);
688 } catch (final ContactAlreadyAddedException ex) {
690 this.abortProgramWithException(ex);
691 } catch (final BadTokenException ex) {
693 this.abortProgramWithException(ex);
697 this.getLogger().trace("EXIT!"); //NOI18N
703 * @return size of contact "book"
706 public final int size () {
711 size = this.getContactDatabase().getContactsCount();
712 } catch (final SQLException ex) {
713 // Something happened
714 this.abortProgramWithException(ex);
722 * Fills the column names array with strings from bundle
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
729 this.getLogger().trace("CALLED!"); //NOI18N
731 // First get an iterator from key set to iterate over
732 Iterator<String> iterator = this.getBundle().keySet().iterator();
734 // Then iterate over all
735 while (iterator.hasNext()) {
737 String key = iterator.next();
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
744 // Convert string to array based on delimiter '.'
745 String[] tokens = this.getArrayFromString(key, ".", 4);
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));
750 // Get pre-last element
751 String columnName = tokens[tokens.length - 2];
754 this.getLogger().debug(MessageFormat.format("columnName={0} - adding ...", columnName));
757 this.columnNames.add(columnName);
758 this.translatedColumnNames.add(this.getBundle().getString(key));
763 this.getLogger().trace(MessageFormat.format("getColumnCount()={0}: EXIT!", this.getColumnCount())); //NOI18N
767 * A ContactFrontend instance
769 * @return the database
771 private ContactFrontend getContactDatabase () {
772 return this.contactDatabase;
776 * "Getter" for own contact instance or null if not found
778 * @return Contact instance or null
780 private Contact getOwnContact () {
782 this.getLogger().trace("CALLED!"); //NOI18N
784 // Deligate this call to database frontend
785 Contact contact = this.getContactDatabase().getOwnContact();
788 this.getLogger().trace(MessageFormat.format("contact={0} - EXIT!", contact)); //NOI18N
790 // Return instance or null