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.io.IOException;
20 import java.lang.reflect.InvocationTargetException;
21 import java.sql.SQLException;
22 import java.text.MessageFormat;
23 import java.util.ArrayList;
24 import java.util.Arrays;
25 import java.util.Iterator;
26 import java.util.List;
27 import org.mxchange.addressbook.client.AddressbookClient;
28 import org.mxchange.addressbook.database.frontend.contact.AddressbookContactDatabaseFrontend;
29 import org.mxchange.addressbook.database.frontend.contact.AddressbookContactFrontend;
30 import org.mxchange.addressbook.exceptions.ContactAlreadyAddedException;
31 import org.mxchange.jcore.client.Client;
32 import org.mxchange.jcore.contact.Contact;
33 import org.mxchange.jcore.contact.Gender;
34 import org.mxchange.jcore.database.frontend.DatabaseFrontend;
35 import org.mxchange.jcore.database.storage.Storable;
36 import org.mxchange.jcore.exceptions.BadTokenException;
37 import org.mxchange.jcore.exceptions.CorruptedDatabaseFileException;
38 import org.mxchange.jcore.exceptions.UnhandledUserChoiceException;
39 import org.mxchange.jcore.exceptions.UnsupportedDatabaseBackendException;
40 import org.mxchange.jcore.manager.BaseManager;
43 * A manager for contacts.
45 * @author Roland Haeder
48 public class AddressbookContactManager extends BaseManager implements ManageableAddressbookContact {
53 private final List<String> columnNames;
56 * Translated column name list
58 private final List<String> translatedColumnNames;
61 * Constructor which accepts maxContacts for maximum (initial) contacts and
64 * @param client Client instance to use
65 * @throws org.mxchange.jcore.exceptions.UnsupportedDatabaseBackendException If the configured database backend is not supported
66 * @throws java.sql.SQLException If an SQL error occurs
68 public AddressbookContactManager (final Client client) throws UnsupportedDatabaseBackendException, SQLException {
70 this.getLogger().trace(MessageFormat.format("client={1} - CALLED!", client)); //NOI18N
72 // Make sure all parameters are set correctly
75 throw new NullPointerException("client is null"); //NOI18N
78 // Set client instance
79 this.setClient(client);
81 // Init database connection
82 DatabaseFrontend frontend = new AddressbookContactDatabaseFrontend(this);
83 this.setFrontend(frontend);
86 this.columnNames = new ArrayList<>(15);
87 this.translatedColumnNames = new ArrayList<>(15);
90 this.fillColumnNamesFromBundle();
93 //* NOISY-DEBUG: */ this.getLogger().debug("client=" + client);
97 * Adds given Contact instance to list
99 * @param contact Contact instance to add
102 public void addContact (final Contact contact) throws ContactAlreadyAddedException {
104 this.getLogger().trace(MessageFormat.format("contact={0} - CALLED!", contact)); //NOI18N
106 // Contact instance must not be null
107 if (null == contact) {
109 throw new NullPointerException("contact is null"); //NOI18N
113 ((AddressbookContactFrontend) this.getFrontend()).addContact(contact);
116 this.getLogger().trace("EXIT!"); //NOI18N
120 * Let the user add a new other address
123 public void doAddOtherAddress () {
124 throw new UnsupportedOperationException("Not supported yet."); //NOI18N
128 * Let the user change address data
130 * @param contact Instance to change data
133 public void doChangeAddressData (final Contact contact) {
135 this.getLogger().trace(MessageFormat.format("contact={0} CALLED!", contact)); //NOI18N
137 // Contact must not be null
138 if (null == contact) {
140 throw new NullPointerException("contact is null"); //NOI18N
143 // Get and cast client instance
144 AddressbookClient client = (AddressbookClient) this.getClient();
146 // First display it again
147 client.displayAddressBox(contact);
150 if (contact.isOwnContact()) {
151 // Deligate to client
152 client.doChangeOwnAddressData(contact);
154 // Other contact's address data to change
155 throw new UnsupportedOperationException("Changing contact entries not finished."); //NOI18N
159 this.getLogger().trace("EXIT!"); //NOI18N
163 * Let the user change "name data"
165 * @param contact Instance to change data
168 public void doChangeNameData (final Contact contact) {
170 this.getLogger().trace(MessageFormat.format("contact={0} CALLED!", contact)); //NOI18N
172 // Contact must not be null
173 if (null == contact) {
175 throw new NullPointerException("contact is null"); //NOI18N
178 // Get and cast client instance
179 AddressbookClient client = (AddressbookClient) this.getClient();
181 // First display them again
182 client.displayNameBox(contact);
185 if (contact.isOwnContact()) {
187 client.doChangeOwnNameData(contact);
189 // Then re-ask them ...
190 throw new UnsupportedOperationException("Changing contact entries not finished."); //NOI18N
194 this.getLogger().trace("EXIT!"); //NOI18N
198 * Let the user change other address
201 public void doChangeOtherAddress () {
202 throw new UnsupportedOperationException("Not supported yet."); //NOI18N
206 * Let the user change other data
208 * @param contact Instance to change data
209 * TODO Didn't handle birthday
212 public void doChangeOtherData (final Contact contact) {
214 this.getLogger().trace(MessageFormat.format("contact={0} CALLED!", contact)); //NOI18N
216 // Contact must not be null
217 if (null == contact) {
219 throw new NullPointerException("contact is null"); //NOI18N
222 // Get and cast client instance
223 AddressbookClient client = (AddressbookClient) this.getClient();
225 // First display them again
226 client.displayOtherDataBox(contact);
229 if (contact.isOwnContact()) {
231 client.doChangeOwnOtherData(contact);
233 // Then re-ask them ...
234 throw new UnsupportedOperationException("Changing contact entries not finished."); //NOI18N
238 this.getLogger().trace("EXIT!"); //NOI18N
242 * Allows the user to change his/her own data
245 public void doChangeOwnData () throws IOException , BadTokenException, CorruptedDatabaseFileException, SQLException, NoSuchMethodException, IllegalAccessException, InvocationTargetException{
247 this.getLogger().trace("CALLED!"); //NOI18N
250 * First check if the user has registered own contact, before that
251 * nothing can be changed.
253 if (!this.isOwnContactAdded()) {
255 this.getClient().outputMessage("Sie haben noch nicht Ihre Daten eingegeben."); //NOI18N
257 // Skip any below code
262 Contact contact = this.getOwnContact();
265 assert (contact instanceof Contact);
268 contact.show(this.getClient());
270 // Get and cast client instance
271 AddressbookClient client = (AddressbookClient) this.getClient();
274 // Ask user what to change
275 client.userChooseChangeContactData(contact);
276 } catch (final UnhandledUserChoiceException ex) {
277 this.getLogger().catching(ex);
281 this.getLogger().trace("EXIT!"); //NOI18N
285 * Let the user delete other address
288 public void doDeleteOtherAddress () {
289 throw new UnsupportedOperationException("Not supported yet."); //NOI18N
293 * Asks user for own data
296 public void doEnterOwnData () throws ContactAlreadyAddedException, IOException , BadTokenException {
298 this.getLogger().trace("CALLED!"); //NOI18N
300 // Is own contact already added?
301 if (this.isOwnContactAdded()) {
302 // Don't continue here
303 throw new ContactAlreadyAddedException();
306 // Get and cast client instance
307 AddressbookClient client = (AddressbookClient) this.getClient();
309 // Deligate this call to the client
310 Contact contact = client.doEnterOwnData();
313 if (contact instanceof Contact) {
314 // Add it to contact "book"
315 this.registerContact(contact);
319 this.getLogger().trace("EXIT!"); //NOI18N
323 public void doListContacts () {
324 throw new UnsupportedOperationException("Not supported yet."); //NOI18N
328 public void doSearchContacts () {
329 throw new UnsupportedOperationException("Not supported yet."); //NOI18N
333 * Shuts down this contact manager
335 * @throws java.sql.SQLException If an SQL error occurs
336 * @throws java.io.IOException If an IO error occurs
339 public void doShutdown () throws SQLException, IOException {
341 this.getLogger().trace("CALLED!"); //NOI18N
343 // Shut down the database layer
344 ((AddressbookContactFrontend) this.getFrontend()).doShutdown();
347 this.getLogger().trace("EXIT!"); //NOI18N
351 * Asks the user for his/her cellphone number
353 * @return User's cellphone number
356 public String enterOwnCellNumber () {
358 this.getLogger().trace("CALLED!"); //NOI18N
360 // Get and cast client instance
361 AddressbookClient client = (AddressbookClient) this.getClient();
363 return client.enterString(5, 30, "Bitte geben Sie Ihre Handynummer an: ", true);
367 * Asks the user for his/her city's name
369 * @return City's name of the user
372 public String enterOwnCity () {
374 this.getLogger().trace("CALLED!"); //NOI18N
376 // Get and cast client instance
377 AddressbookClient client = (AddressbookClient) this.getClient();
379 return client.enterString(3, 50, "Bitte geben Sie Ihre Wohnort ein: ", false);
383 * Asks the user for his/her city's name
385 * @return City's name of the user
388 public String enterOwnComment () {
390 this.getLogger().trace("CALLED!"); //NOI18N
392 // Get and cast client instance
393 AddressbookClient client = (AddressbookClient) this.getClient();
395 return client.enterString(0, 100, "Kommentar zu Ihrem Eintrag: ", true);
399 * Asks the user for his/her company name
401 * @return User's company name
404 public String enterOwnCompanyName () {
406 this.getLogger().trace("CALLED!"); //NOI18N
408 // Get and cast client instance
409 AddressbookClient client = (AddressbookClient) this.getClient();
411 return client.enterString(5, 50, "Bitte geben Sie Ihre Firmenbezeichnung ein: ", true);
415 * Asks user for his/her own country code
417 * @return User's own country code
420 public String enterOwnCountryCode () {
422 this.getLogger().trace("CALLED!"); //NOI18N
424 // Get and cast client instance
425 AddressbookClient client = (AddressbookClient) this.getClient();
427 return client.enterString(2, 2, "Bitte geben Sie den zweistelligen Ländercode von Ihrem Land ein: ", false).toUpperCase();
431 * Asks user for his/her own country code
433 * @return User's own country code
436 public String enterOwnEmailAddress () {
438 this.getLogger().trace("CALLED!"); //NOI18N
440 // Get and cast client instance
441 AddressbookClient client = (AddressbookClient) this.getClient();
443 return client.enterString(10, 50, "Bitte geben Sie Ihre Email-Adresse ein: ", true);
447 * Asks the user for family name
449 * @return Family name of the user
452 public String enterOwnFamilyName () {
454 this.getLogger().trace("CALLED!"); //NOI18N
456 // Get and cast client instance
457 AddressbookClient client = (AddressbookClient) this.getClient();
459 return client.enterString(2, 50, "Bitte geben Sie Ihren Nachnamen ein: ", false);
463 * Asks the user for family name
465 * @return Family name of the user
468 public String enterOwnFaxNumber () {
470 this.getLogger().trace("CALLED!"); //NOI18N
472 // Get and cast client instance
473 AddressbookClient client = (AddressbookClient) this.getClient();
475 return client.enterString(5, 30, "Bitte geben Sie Ihre Faxnummer an: ", true);
479 * Asks the user for surname
481 * @return Surname of the user
484 public String enterOwnFirstName () {
486 this.getLogger().trace("CALLED!"); //NOI18N
488 // Get and cast client instance
489 AddressbookClient client = (AddressbookClient) this.getClient();
491 return client.enterString(2, 50, "Bitte geben Sie Ihren Vornamen ein: ", false);
495 * Asks the user for gender, until a valid has been entered
497 * @return Gender of the user
500 public Gender enterOwnGender () {
502 this.getLogger().trace("CALLED!"); //NOI18N
504 // Get and cast client instance
505 AddressbookClient client = (AddressbookClient) this.getClient();
507 return client.enterGender("Bitte geben Sie die Anrede ein: (M=Herr, F=Frau, C=Firma): ");
511 * Asks the user for phone number
513 * @return Phone number of the user
516 public String enterOwnPhoneNumber () {
518 this.getLogger().trace("CALLED!"); //NOI18N
520 // Get and cast client instance
521 AddressbookClient client = (AddressbookClient) this.getClient();
523 return client.enterString(5, 30, "Bitte geben Sie Ihre Telefonnummer an: ", true);
527 * Asks the user for own street (including number)
529 * @return Own street an number
532 public String enterOwnStreet () {
534 this.getLogger().trace("CALLED!"); //NOI18N
536 // Get and cast client instance
537 AddressbookClient client = (AddressbookClient) this.getClient();
539 return client.enterString(5, 50, "Bitte geben Sie Ihre Strasse und Hausnummer ein: ", false);
543 * Asks the user for own ZIP code
548 public int enterOwnZipCode () {
550 this.getLogger().trace("CALLED!"); //NOI18N
552 // Get and cast client instance
553 AddressbookClient client = (AddressbookClient) this.getClient();
555 return client.enterInt(0, 99_999, "Bitte geben Sie Ihre Postleitzahl ein: ");
559 public final int getColumnCount () {
560 assert (this.columnNames instanceof List) : "this.columnNames is not initialized"; //NOI18N
562 return this.columnNames.size();
566 * Getter for column name at given index.
568 * @param columnIndex Column index
569 * @return Database column name
572 public String getColumnName (final int columnIndex) {
573 assert (this.columnNames instanceof List) : "this.columnNames is not initialized"; //NOI18N
575 // Get column name at index
576 return this.columnNames.get(columnIndex);
580 * Getter for translated column name at given index.
582 * @param columnIndex Column index
583 * @return Human-readable column name
586 public String getTranslatedColumnName (final int columnIndex) {
587 assert (this.translatedColumnNames instanceof List) : "this.translatedColumnNames is not initialized"; //NOI18N
589 // Get column name at index
590 return this.translatedColumnNames.get(columnIndex);
594 * Somewhat "getter" for value from given row and column index
596 * @param rowIndex Row index
597 * @param columnIndex Column index
598 * @return Value from given row/column
601 public Object getValueFromRowColumn (final int rowIndex, final int columnIndex) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
603 this.getLogger().trace(MessageFormat.format("rowIndex={0},columnIndex={1} CALLED!", rowIndex, columnIndex)); //NOI18N
605 // Then get specific row from database which is a Contact instance
606 Storable storeable = this.getFrontend().getStorableAtRow(rowIndex);
609 this.getLogger().debug(MessageFormat.format("storeable={0}", storeable)); //NOI18N
611 // It may return null
612 if (null == storeable) {
614 this.getLogger().warn("contact is null - returning null ..."); //NOI18N
618 // Convert column index -> name
619 String columnName = this.getColumnName(columnIndex);
622 this.getLogger().debug(MessageFormat.format("columnName={0}", columnName)); //NOI18N
624 // Now get that column
627 value = storeable.getValueFromColumn(columnName);
628 } catch (final IllegalArgumentException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ex) {
629 this.abortProgramWithException(ex);
633 this.getLogger().trace(MessageFormat.format("value={0} - EXIT!", value)); //NOI18N
640 * Checks whether own contact is already added by checking all entries for
643 * @return Whether own contact is already added
646 public boolean isOwnContactAdded () throws IOException, BadTokenException {
648 this.getLogger().trace("CALLED!"); //NOI18N
651 boolean isAdded = false;
654 // Deligate this call to frontend
655 isAdded = ((AddressbookContactFrontend) this.getFrontend()).isOwnContactFound();
656 } catch (final SQLException | IOException | BadTokenException | CorruptedDatabaseFileException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ex) {
657 // Something bad happened
658 this.abortProgramWithException(ex);
662 this.getLogger().trace(MessageFormat.format("isAdded={0} : EXIT!", isAdded)); //NOI18N
669 * Adds given contact to address book and flushes all entries to database
671 * @param contact Contact being added
672 * TODO Add check for book size
675 public void registerContact (final Contact contact) {
677 this.getLogger().trace(MessageFormat.format("contact={0} CALLED!", contact)); //NOI18N
680 if (null == contact) {
682 throw new NullPointerException("contact is null"); //NOI18N
686 /* NOISY-DEBUG: */ this.getLogger().debug(MessageFormat.format("Adding '{0}' '{1}' at pos '{2}' ...", contact.getFirstName(), contact.getFamilyName(), this.size())); //NOI18N
688 // Check if contact is found
689 if (((AddressbookContactFrontend) this.getFrontend()).isContactFound(contact)) {
690 // Contact already added
691 // TODO Do something here
692 } else if ((contact.isOwnContact()) && (this.isOwnContactAdded())) {
693 // Own contact already added
697 // Add contact to internal list
698 this.addContact(contact);
699 } catch (final ContactAlreadyAddedException | BadTokenException | SQLException | IOException | CorruptedDatabaseFileException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ex) {
701 this.abortProgramWithException(ex);
705 this.getLogger().trace("EXIT!"); //NOI18N
709 public final int size () throws IOException {
714 size = ((AddressbookContactFrontend) this.getFrontend()).getContactsCount();
715 } catch (final SQLException ex) {
716 // Something happened
717 this.abortProgramWithException(ex);
725 * Fills the column names array with strings from bundle
727 private void fillColumnNamesFromBundle () {
728 assert (this.columnNames instanceof List) : "this.columnNames is not initialized"; //NOI18N
729 assert (this.translatedColumnNames instanceof List) : "this.translatedColumnNames is not initialized"; //NOI18N
732 this.getLogger().trace("CALLED!"); //NOI18N
734 // First get an iterator from key set to iterate over
735 Iterator<String> iterator = this.getBundle().keySet().iterator();
737 // Then iterate over all
738 while (iterator.hasNext()) {
740 String key = iterator.next();
742 // Does the key start with AddressbookContactManager.columnName ?
743 if (key.startsWith("ContactManager.columnName")) { //NOI18N
744 // This is the wanted entry.
745 this.getLogger().debug(MessageFormat.format("key={0}", key)); //NOI18N
747 // Convert string to array based on delimiter '.'
748 String[] tokens = this.getArrayFromString(key, "."); //NOI18N
750 // Token array must contain 4 elements (AddressbookContactManager.columnName.foo.text)
751 assert(tokens.length == 4) : MessageFormat.format("Array tokens contains not 4 elements: {0}", Arrays.toString(tokens)); //NOI18N
753 // Get pre-last element
754 String columnName = tokens[tokens.length - 2];
757 this.getLogger().debug(MessageFormat.format("columnName={0} - adding ...", columnName)); //NOI18N
760 this.columnNames.add(columnName);
761 this.translatedColumnNames.add(this.getBundle().getString(key));
766 this.getLogger().trace(MessageFormat.format("getColumnCount()={0}: EXIT!", this.getColumnCount())); //NOI18N
770 * "Getter" for own contact instance or null if not found
772 * @return Contact instance or null
773 * @throws java.sql.SQLException If an SQL error occurs
774 * @throws java.io.IOException If an IO error occurs
775 * @throws org.mxchange.jcore.exceptions.BadTokenException Continued throw
776 * @throws org.mxchange.jcore.exceptions.CorruptedDatabaseFileException If the database file is damaged
777 * @throws java.lang.NoSuchMethodException If a method cannot be found
778 * @throws java.lang.IllegalAccessException If a method is not accessible
779 * @throws java.lang.reflect.InvocationTargetException Any other problems?
781 private Contact getOwnContact () throws IOException, BadTokenException, CorruptedDatabaseFileException, SQLException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
783 this.getLogger().trace("CALLED!"); //NOI18N
785 // Deligate this call to database frontend
786 Contact contact = ((AddressbookContactFrontend) this.getFrontend()).getOwnContact();
789 this.getLogger().trace(MessageFormat.format("contact={0} - EXIT!", contact)); //NOI18N
791 // Return instance or null