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.Client;
26 import org.mxchange.addressbook.contact.Contact;
27 import org.mxchange.addressbook.contact.Gender;
28 import org.mxchange.addressbook.database.frontend.contact.ContactDatabaseFrontend;
29 import org.mxchange.addressbook.database.frontend.contact.ContactFrontend;
30 import org.mxchange.addressbook.exceptions.BadTokenException;
31 import org.mxchange.addressbook.exceptions.ContactAlreadyAddedException;
32 import org.mxchange.addressbook.exceptions.UnhandledUserChoiceException;
33 import org.mxchange.addressbook.manager.BaseManager;
36 * A manager for contacts, please note that this implementation loads the whole
39 * @author Roland Haeder
42 public class ContactManager extends BaseManager implements ManageableContact {
47 private final List<String> columnNames;
50 * Translated column name list
52 private final List<String> translatedColumnNames;
55 * A ContactFrontend instance
57 private final ContactFrontend contactDatabase;
60 * Constructor which accepts maxContacts for maximum (initial) contacts and
63 * @param client Client instance to use
65 public ContactManager (final Client client) {
67 this.getLogger().trace(MessageFormat.format("client={1} - CALLED!", client)); //NOI18N
69 // Make sure all parameters are set correctly
72 throw new NullPointerException("client is null"); //NOI18N
75 // Set client instance
76 this.setClient(client);
78 // Init database connection
79 this.contactDatabase = new ContactDatabaseFrontend(this);
82 this.columnNames = new ArrayList<>(15);
83 this.translatedColumnNames = new ArrayList<>(15);
86 this.fillColumnNamesFromBundle();
89 //* NOISY-DEBUG: */ this.getLogger().debug("client=" + client);
93 * Adds given Contact instance to list
95 * @param contact Contact instance to add
98 public void addContact (final Contact contact) throws ContactAlreadyAddedException {
100 this.getLogger().trace(MessageFormat.format("contact={0} - CALLED!", contact)); //NOI18N
102 // Contact instance must not be null
103 if (contact == null) {
105 throw new NullPointerException("contact is null"); //NOI18N
109 this.getContactDatabase().addContact(contact);
112 this.getLogger().trace("EXIT!"); //NOI18N
116 * Let the user add a new other address
119 public void doAddOtherAddress () {
120 throw new UnsupportedOperationException("Not supported yet."); //NOI18N
124 * Let the user change address data
126 * @param contact Instance to change data
129 public void doChangeAddressData (final Contact contact) {
131 this.getLogger().trace(MessageFormat.format("contact={0} CALLED!", contact)); //NOI18N
133 // Contact must not be null
134 if (contact == null) {
136 throw new NullPointerException("contact is null"); //NOI18N
139 // First display it again
140 this.getClient().displayAddressBox(contact);
143 if (contact.isOwnContact()) {
144 // Deligate to client
145 this.getClient().doChangeOwnAddressData(contact);
147 // Other contact's address data to change
148 throw new UnsupportedOperationException("Changing contact entries not finished."); //NOI18N
152 this.getLogger().trace("EXIT!"); //NOI18N
156 * Let the user change "name data"
158 * @param contact Instance to change data
161 public void doChangeNameData (final Contact contact) {
163 this.getLogger().trace(MessageFormat.format("contact={0} CALLED!", contact)); //NOI18N
165 // Contact must not be null
166 if (contact == null) {
168 throw new NullPointerException("contact is null"); //NOI18N
171 // First display them again
172 this.getClient().displayNameBox(contact);
175 if (contact.isOwnContact()) {
177 this.getClient().doChangeOwnNameData(contact);
179 // Then re-ask them ...
180 throw new UnsupportedOperationException("Changing contact entries not finished."); //NOI18N
184 this.getLogger().trace("EXIT!"); //NOI18N
188 * Let the user change other address
191 public void doChangeOtherAddress () {
192 throw new UnsupportedOperationException("Not supported yet."); //NOI18N
196 * Let the user change other data
198 * @param contact Instance to change data
199 * @todo Didn't handle birthday
202 public void doChangeOtherData (final Contact contact) {
204 this.getLogger().trace(MessageFormat.format("contact={0} CALLED!", contact)); //NOI18N
206 // Contact must not be null
207 if (contact == null) {
209 throw new NullPointerException("contact is null"); //NOI18N
212 // First display them again
213 this.getClient().displayOtherDataBox(contact);
216 if (contact.isOwnContact()) {
218 this.getClient().doChangeOwnOtherData(contact);
220 // Then re-ask them ...
221 throw new UnsupportedOperationException("Changing contact entries not finished."); //NOI18N
225 this.getLogger().trace("EXIT!"); //NOI18N
229 * Allows the user to change his/her own data
232 public void doChangeOwnData () {
234 this.getLogger().trace("CALLED!"); //NOI18N
237 * First check if the user has registered own contact, before that
238 * nothing can be changed.
240 if (!this.isOwnContactAdded()) {
242 this.getClient().outputMessage("Sie haben noch nicht Ihre Daten eingegeben."); //NOI18N
244 // Skip any below code
249 Contact contact = this.getOwnContact();
252 assert (contact instanceof Contact);
255 contact.show(this.getClient());
258 // Ask user what to change
259 this.getClient().userChooseChangeContactData(contact);
260 } catch (final UnhandledUserChoiceException ex) {
261 this.getLogger().catching(ex);
265 this.getLogger().trace("EXIT!"); //NOI18N
269 * Let the user delete other address
272 public void doDeleteOtherAddress () {
273 throw new UnsupportedOperationException("Not supported yet."); //NOI18N
277 * Asks user for own data
280 public void doEnterOwnData () throws ContactAlreadyAddedException {
282 this.getLogger().trace("CALLED!"); //NOI18N
284 // Is own contact already added?
285 if (this.isOwnContactAdded()) {
286 // Don't continue here
287 throw new ContactAlreadyAddedException();
290 // Deligate this call to the client
291 Contact contact = this.getClient().doEnterOwnData();
294 if (contact instanceof Contact) {
295 // Add it to contact "book"
296 this.registerContact(contact);
300 this.getLogger().trace("EXIT!"); //NOI18N
304 public void doListContacts () {
305 throw new UnsupportedOperationException("Not supported yet."); //NOI18N
309 public void doSearchContacts () {
310 throw new UnsupportedOperationException("Not supported yet."); //NOI18N
314 * Shuts down this contact manager
317 public void doShutdown () {
319 this.getLogger().trace("CALLED!"); //NOI18N
321 // Shut down the database layer
322 this.getContactDatabase().doShutdown();
325 this.getLogger().trace("EXIT!"); //NOI18N
329 * Asks the user for his/her cellphone number
331 * @return User's cellphone number
334 public String enterOwnCellNumber () {
336 this.getLogger().trace("CALLED!"); //NOI18N
338 return this.getClient().enterString(5, 30, "Bitte geben Sie Ihre Handynummer an: ", true);
342 * Asks the user for his/her city's name
344 * @return City's name of the user
347 public String enterOwnCity () {
349 this.getLogger().trace("CALLED!"); //NOI18N
351 return this.getClient().enterString(3, 50, "Bitte geben Sie Ihre Wohnort ein: ", false);
355 * Asks the user for his/her city's name
357 * @return City's name of the user
360 public String enterOwnComment () {
362 this.getLogger().trace("CALLED!"); //NOI18N
364 return this.getClient().enterString(0, 100, "Kommentar zu Ihrem Eintrag: ", true);
368 * Asks the user for his/her company name
370 * @return User's company name
373 public String enterOwnCompanyName () {
375 this.getLogger().trace("CALLED!"); //NOI18N
377 return this.getClient().enterString(5, 50, "Bitte geben Sie Ihre Firmenbezeichnung ein: ", true);
381 * Asks user for his/her own country code
383 * @return User's own country code
386 public String enterOwnCountryCode () {
388 this.getLogger().trace("CALLED!"); //NOI18N
390 return this.getClient().enterString(2, 2, "Bitte geben Sie den zweistelligen Ländercode von Ihrem Land ein: ", false).toUpperCase();
394 * Asks user for his/her own country code
396 * @return User's own country code
399 public String enterOwnEmailAddress () {
401 this.getLogger().trace("CALLED!"); //NOI18N
403 return this.getClient().enterString(10, 50, "Bitte geben Sie Ihre Email-Adresse ein: ", true);
407 * Asks the user for family name
409 * @return Family name of the user
412 public String enterOwnFamilyName () {
414 this.getLogger().trace("CALLED!"); //NOI18N
416 return this.getClient().enterString(2, 50, "Bitte geben Sie Ihren Nachnamen ein: ", false);
420 * Asks the user for family name
422 * @return Family name of the user
425 public String enterOwnFaxNumber () {
427 this.getLogger().trace("CALLED!"); //NOI18N
429 return this.getClient().enterString(5, 30, "Bitte geben Sie Ihre Faxnummer an: ", true);
433 * Asks the user for gender, until a valid has been entered
435 * @return Gender of the user
438 public Gender enterOwnGender () {
440 this.getLogger().trace("CALLED!"); //NOI18N
442 return this.getClient().enterGender("Bitte geben Sie die Anrede ein: (M=Herr, F=Frau, C=Firma): ");
446 * Asks the user for phone number
448 * @return Phone number of the user
451 public String enterOwnPhoneNumber () {
453 this.getLogger().trace("CALLED!"); //NOI18N
455 return this.getClient().enterString(5, 30, "Bitte geben Sie Ihre Telefonnummer an: ", true);
459 * Asks the user for own street (including number)
461 * @return Own street an number
464 public String enterOwnStreet () {
466 this.getLogger().trace("CALLED!"); //NOI18N
468 return this.getClient().enterString(5, 50, "Bitte geben Sie Ihre Strasse und Hausnummer ein: ", false);
472 * Asks the user for surname
474 * @return Surname of the user
477 public String enterOwnSurname () {
479 this.getLogger().trace("CALLED!"); //NOI18N
481 return this.getClient().enterString(2, 50, "Bitte geben Sie Ihren Vornamen ein: ", false);
485 * Asks the user for own ZIP code
490 public int enterOwnZipCode () {
492 this.getLogger().trace("CALLED!"); //NOI18N
494 return this.getClient().enterInt(0, 99_999, "Bitte geben Sie Ihre Postleitzahl ein: ");
498 public final int getColumnCount () {
499 assert (this.columnNames instanceof List) : "this.columnNames is not initialized"; //NOI18N
501 return this.columnNames.size();
505 * Getter for column name at given index.
507 * @param columnIndex Column index
508 * @return Database column name
511 public String getColumnName (final int columnIndex) {
512 assert (this.columnNames instanceof List) : "this.columnNames is not initialized"; //NOI18N
514 // Get column name at index
515 return this.columnNames.get(columnIndex);
519 * Getter for translated column name at given index.
521 * @param columnIndex Column index
522 * @return Human-readable column name
525 public String getTranslatedColumnName (final int columnIndex) {
526 assert (this.translatedColumnNames instanceof List) : "this.translatedColumnNames is not initialized"; //NOI18N
528 // Get column name at index
529 return this.translatedColumnNames.get(columnIndex);
533 * Somewhat "getter" for value from given row and column index
535 * @param rowIndex Row index
536 * @param columnIndex Column index
537 * @return Value from given row/column
540 public Object getValueFromRowColumn (final int rowIndex, final int columnIndex) {
542 this.getLogger().trace(MessageFormat.format("rowIndex={0},columnIndex={1} CALLED!", rowIndex, columnIndex));
544 // Then get specific row from database which is a Contact instance
545 Contact contact = this.getContactDatabase().readSingleContact(rowIndex);
548 this.getLogger().debug(MessageFormat.format("contact={0}", contact));
550 // It may return null
551 if (contact == null) {
553 this.getLogger().warn("contact is null - returning null ...");
557 // Convert column index -> name
558 String columnName = this.getColumnName(columnIndex);
561 this.getLogger().debug(MessageFormat.format("columnName={0}", columnName));
563 // Now get that column
564 Object value = contact.getValueFromColumn(columnName);
567 this.getLogger().trace(MessageFormat.format("value={0} - EXIT!", value));
574 * Checks whether own contact is already added by checking all entries for
577 * @return Whether own contact is already added
580 public boolean isOwnContactAdded () {
582 this.getLogger().trace("CALLED!"); //NOI18N
585 boolean isAdded = false;
588 // Deligate this call to frontend
589 isAdded = this.getContactDatabase().isOwnContactFound();
590 } catch (final SQLException ex) {
591 // Something bad happened
592 this.abortProgramWithException(ex);
596 this.getLogger().trace(MessageFormat.format("isAdded={0} : EXIT!", isAdded)); //NOI18N
603 * Adds given contact to address book and flushes all entries to database
605 * @param contact Contact being added
606 * @todo Add check for book size
609 public void registerContact (final Contact contact) {
611 this.getLogger().trace(MessageFormat.format("contact={0} CALLED!", contact)); //NOI18N
614 if (contact == null) {
616 throw new NullPointerException("contact is null"); //NOI18N
620 /* NOISY-DEBUG: */ this.getLogger().debug(MessageFormat.format("Adding '{0}' '{1}' at pos '{2}' ...", contact.getSurname(), contact.getFamilyName(), this.size())); //NOI18N
622 // Check if contact is found
623 if (this.getContactDatabase().isContactFound(contact)) {
624 // Contact already added
625 // @todo Do something here
626 } else if ((contact.isOwnContact()) && (this.isOwnContactAdded())) {
627 // Own contact already added
628 // @todo Do something
631 // Add contact to internal list
632 this.addContact(contact);
633 } catch (final ContactAlreadyAddedException ex) {
635 this.abortProgramWithException(ex);
636 } catch (final BadTokenException ex) {
638 this.abortProgramWithException(ex);
642 this.getLogger().trace("EXIT!"); //NOI18N
648 * @return size of contact "book"
651 public final int size () {
656 size = this.getContactDatabase().getContactsCount();
657 } catch (final SQLException ex) {
658 // Something happened
659 this.abortProgramWithException(ex);
667 * Fills the column names array with strings from bundle
669 private void fillColumnNamesFromBundle () {
670 assert (this.columnNames instanceof List) : "this.columnNames is not initialized"; //NOI18N
671 assert (this.translatedColumnNames instanceof List) : "this.translatedColumnNames is not initialized"; //NOI18N
674 this.getLogger().trace("CALLED!"); //NOI18N
676 // First get an iterator from key set to iterate over
677 Iterator<String> iterator = this.getBundle().keySet().iterator();
679 // Then iterate over all
680 while (iterator.hasNext()) {
682 String key = iterator.next();
684 // Does the key start with ContactManager.columnName ?
685 if (key.startsWith("ContactManager.columnName")) { //NOI18N
686 // This is the wanted entry.
687 this.getLogger().debug(MessageFormat.format("key={0}", key)); //NOI18N
689 // Convert string to array based on delimiter '.'
690 String[] tokens = this.getArrayFromString(key, ".", 4);
692 // Token array must contain 4 elements (ContactManager.columnName.foo.text)
693 assert(tokens.length == 4) : MessageFormat.format("Array tokens contains not 4 elements: {0}", Arrays.toString(tokens));
695 // Get pre-last element
696 String columnName = tokens[tokens.length - 2];
699 this.getLogger().debug(MessageFormat.format("columnName={0} - adding ...", columnName));
702 this.columnNames.add(columnName);
703 this.translatedColumnNames.add(this.getBundle().getString(key));
708 this.getLogger().trace(MessageFormat.format("getColumnCount()={0}: EXIT!", this.getColumnCount())); //NOI18N
712 * A ContactFrontend instance
714 * @return the database
716 private ContactFrontend getContactDatabase () {
717 return this.contactDatabase;
721 * "Getter" for own contact instance or null if not found
723 * @return Contact instance or null
725 private Contact getOwnContact () {
727 this.getLogger().trace("CALLED!"); //NOI18N
729 // Deligate this call to database frontend
730 Contact contact = this.getContactDatabase().getOwnContact();
733 this.getLogger().trace(MessageFormat.format("contact={0} - EXIT!", contact)); //NOI18N
735 // Return instance or null