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.exceptions.ContactAlreadyAddedException;
29 import org.mxchange.jcore.client.Client;
30 import org.mxchange.jcore.contact.Contact;
31 import org.mxchange.jcore.contact.gender.Gender;
32 import org.mxchange.jcore.database.frontend.DatabaseFrontend;
33 import org.mxchange.jcore.database.storage.Storable;
34 import org.mxchange.jcore.exceptions.BadTokenException;
35 import org.mxchange.jcore.exceptions.CorruptedDatabaseFileException;
36 import org.mxchange.jcore.exceptions.UnhandledUserChoiceException;
37 import org.mxchange.jcore.exceptions.UnsupportedDatabaseBackendException;
38 import org.mxchange.jcore.manager.BaseManager;
41 * A manager for contacts.
43 * @author Roland Haeder
46 public class AddressbookContactManager extends BaseManager implements ManageableAddressbookContact {
51 private final List<String> columnNames;
54 * Translated column name list
56 private final List<String> translatedColumnNames;
59 * Constructor which accepts maxContacts for maximum (initial) contacts and
62 * @param client Client instance to use
63 * @throws org.mxchange.jcore.exceptions.UnsupportedDatabaseBackendException If the configured database backend is not supported
64 * @throws java.sql.SQLException If an SQL error occurs
66 public AddressbookContactManager (final Client client) throws UnsupportedDatabaseBackendException, SQLException {
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 DatabaseFrontend frontend = new AddressbookContactDatabaseFrontend(this);
81 this.setFrontend(frontend);
84 this.columnNames = new ArrayList<>(15);
85 this.translatedColumnNames = new ArrayList<>(15);
88 this.fillColumnNamesFromBundle();
91 //* NOISY-DEBUG: */ this.getLogger().debug("client=" + client);
95 * Adds given Contact instance to list
97 * @param contact Contact instance to add
100 public void addContact (final Contact contact) throws ContactAlreadyAddedException {
102 this.getLogger().trace(MessageFormat.format("contact={0} - CALLED!", contact)); //NOI18N
104 // Contact instance must not be null
105 if (null == contact) {
107 throw new NullPointerException("contact is null"); //NOI18N
111 ((AddressbookContactFrontend) this.getFrontend()).addContact(contact);
114 this.getLogger().trace("EXIT!"); //NOI18N
118 * Let the user add a new other address
121 public void doAddOtherAddress () {
122 throw new UnsupportedOperationException("Not supported yet."); //NOI18N
126 * Let the user change address data
128 * @param contact Instance to change data
131 public void doChangeAddressData (final Contact contact) {
133 this.getLogger().trace(MessageFormat.format("contact={0} CALLED!", contact)); //NOI18N
135 // Contact must not be null
136 if (null == contact) {
138 throw new NullPointerException("contact is null"); //NOI18N
141 // Get and cast client instance
142 AddressbookClient client = (AddressbookClient) this.getClient();
144 // First display it again
145 client.displayAddressBox(contact);
148 if (contact.isOwnContact()) {
149 // Deligate to client
150 client.doChangeOwnAddressData(contact);
152 // Other contact's address data to change
153 throw new UnsupportedOperationException("Changing contact entries not finished."); //NOI18N
157 this.getLogger().trace("EXIT!"); //NOI18N
161 * Let the user change "name data"
163 * @param contact Instance to change data
166 public void doChangeNameData (final Contact contact) {
168 this.getLogger().trace(MessageFormat.format("contact={0} CALLED!", contact)); //NOI18N
170 // Contact must not be null
171 if (null == contact) {
173 throw new NullPointerException("contact is null"); //NOI18N
176 // Get and cast client instance
177 AddressbookClient client = (AddressbookClient) this.getClient();
179 // First display them again
180 client.displayNameBox(contact);
183 if (contact.isOwnContact()) {
185 client.doChangeOwnNameData(contact);
187 // Then re-ask them ...
188 throw new UnsupportedOperationException("Changing contact entries not finished."); //NOI18N
192 this.getLogger().trace("EXIT!"); //NOI18N
196 * Let the user change other address
199 public void doChangeOtherAddress () {
200 throw new UnsupportedOperationException("Not supported yet."); //NOI18N
204 * Let the user change other data
206 * @param contact Instance to change data
207 * TODO Didn't handle birthday
210 public void doChangeOtherData (final Contact contact) {
212 this.getLogger().trace(MessageFormat.format("contact={0} CALLED!", contact)); //NOI18N
214 // Contact must not be null
215 if (null == contact) {
217 throw new NullPointerException("contact is null"); //NOI18N
220 // Get and cast client instance
221 AddressbookClient client = (AddressbookClient) this.getClient();
223 // First display them again
224 client.displayOtherDataBox(contact);
227 if (contact.isOwnContact()) {
229 client.doChangeOwnOtherData(contact);
231 // Then re-ask them ...
232 throw new UnsupportedOperationException("Changing contact entries not finished."); //NOI18N
236 this.getLogger().trace("EXIT!"); //NOI18N
240 * Allows the user to change his/her own data
243 public void doChangeOwnData () throws IOException , BadTokenException, CorruptedDatabaseFileException, SQLException, NoSuchMethodException, IllegalAccessException, InvocationTargetException{
245 this.getLogger().trace("CALLED!"); //NOI18N
248 * First check if the user has registered own contact, before that
249 * nothing can be changed.
251 if (!this.isOwnContactAdded()) {
253 this.getClient().outputMessage("Sie haben noch nicht Ihre Daten eingegeben."); //NOI18N
255 // Skip any below code
260 Contact contact = this.getOwnContact();
263 assert (contact instanceof Contact);
266 contact.show(this.getClient());
268 // Get and cast client instance
269 AddressbookClient client = (AddressbookClient) this.getClient();
272 // Ask user what to change
273 client.userChooseChangeContactData(contact);
274 } catch (final UnhandledUserChoiceException ex) {
275 this.getLogger().catching(ex);
279 this.getLogger().trace("EXIT!"); //NOI18N
283 * Let the user delete other address
286 public void doDeleteOtherAddress () {
287 throw new UnsupportedOperationException("Not supported yet."); //NOI18N
291 * Asks user for own data
294 public void doEnterOwnData () throws ContactAlreadyAddedException, IOException , BadTokenException {
296 this.getLogger().trace("CALLED!"); //NOI18N
298 // Is own contact already added?
299 if (this.isOwnContactAdded()) {
300 // Don't continue here
301 throw new ContactAlreadyAddedException();
304 // Get and cast client instance
305 AddressbookClient client = (AddressbookClient) this.getClient();
307 // Deligate this call to the client
308 Contact contact = client.doEnterOwnData();
311 if (contact instanceof Contact) {
312 // Add it to contact "book"
313 this.registerContact(contact);
317 this.getLogger().trace("EXIT!"); //NOI18N
321 public void doListContacts () {
322 throw new UnsupportedOperationException("Not supported yet."); //NOI18N
326 public void doSearchContacts () {
327 throw new UnsupportedOperationException("Not supported yet."); //NOI18N
331 * Shuts down this contact manager
333 * @throws java.sql.SQLException If an SQL error occurs
334 * @throws java.io.IOException If an IO error occurs
337 public void doShutdown () throws SQLException, IOException {
339 this.getLogger().trace("CALLED!"); //NOI18N
341 // Shut down the database layer
342 ((AddressbookContactFrontend) this.getFrontend()).doShutdown();
345 this.getLogger().trace("EXIT!"); //NOI18N
349 * Asks the user for his/her cellphone number
351 * @return User's cellphone number
354 public String enterOwnCellNumber () {
356 this.getLogger().trace("CALLED!"); //NOI18N
358 // Get and cast client instance
359 AddressbookClient client = (AddressbookClient) this.getClient();
361 return client.enterString(5, 30, "Bitte geben Sie Ihre Handynummer an: ", true);
365 * Asks the user for his/her city's name
367 * @return City's name of the user
370 public String enterOwnCity () {
372 this.getLogger().trace("CALLED!"); //NOI18N
374 // Get and cast client instance
375 AddressbookClient client = (AddressbookClient) this.getClient();
377 return client.enterString(3, 50, "Bitte geben Sie Ihre Wohnort ein: ", false);
381 * Asks the user for his/her city's name
383 * @return City's name of the user
386 public String enterOwnComment () {
388 this.getLogger().trace("CALLED!"); //NOI18N
390 // Get and cast client instance
391 AddressbookClient client = (AddressbookClient) this.getClient();
393 return client.enterString(0, 100, "Kommentar zu Ihrem Eintrag: ", true);
397 * Asks the user for his/her company name
399 * @return User's company name
402 public String enterOwnCompanyName () {
404 this.getLogger().trace("CALLED!"); //NOI18N
406 // Get and cast client instance
407 AddressbookClient client = (AddressbookClient) this.getClient();
409 return client.enterString(5, 50, "Bitte geben Sie Ihre Firmenbezeichnung ein: ", true);
413 * Asks user for his/her own country code
415 * @return User's own country code
418 public String enterOwnCountryCode () {
420 this.getLogger().trace("CALLED!"); //NOI18N
422 // Get and cast client instance
423 AddressbookClient client = (AddressbookClient) this.getClient();
425 return client.enterString(2, 2, "Bitte geben Sie den zweistelligen Ländercode von Ihrem Land ein: ", false).toUpperCase();
429 * Asks user for his/her own country code
431 * @return User's own country code
434 public String enterOwnEmailAddress () {
436 this.getLogger().trace("CALLED!"); //NOI18N
438 // Get and cast client instance
439 AddressbookClient client = (AddressbookClient) this.getClient();
441 return client.enterString(10, 50, "Bitte geben Sie Ihre Email-Adresse ein: ", true);
445 * Asks the user for family name
447 * @return Family name of the user
450 public String enterOwnFamilyName () {
452 this.getLogger().trace("CALLED!"); //NOI18N
454 // Get and cast client instance
455 AddressbookClient client = (AddressbookClient) this.getClient();
457 return client.enterString(2, 50, "Bitte geben Sie Ihren Nachnamen ein: ", false);
461 * Asks the user for family name
463 * @return Family name of the user
466 public String enterOwnFaxNumber () {
468 this.getLogger().trace("CALLED!"); //NOI18N
470 // Get and cast client instance
471 AddressbookClient client = (AddressbookClient) this.getClient();
473 return client.enterString(5, 30, "Bitte geben Sie Ihre Faxnummer an: ", true);
477 * Asks the user for surname
479 * @return Surname of the user
482 public String enterOwnFirstName () {
484 this.getLogger().trace("CALLED!"); //NOI18N
486 // Get and cast client instance
487 AddressbookClient client = (AddressbookClient) this.getClient();
489 return client.enterString(2, 50, "Bitte geben Sie Ihren Vornamen ein: ", false);
493 * Asks the user for gender, until a valid has been entered
495 * @return Gender of the user
498 public Gender enterOwnGender () {
500 this.getLogger().trace("CALLED!"); //NOI18N
502 // Get and cast client instance
503 AddressbookClient client = (AddressbookClient) this.getClient();
505 return client.enterGender("Bitte geben Sie die Anrede ein: (M=Herr, F=Frau, C=Firma): ");
509 * Asks the user for phone number
511 * @return Phone number of the user
514 public String enterOwnPhoneNumber () {
516 this.getLogger().trace("CALLED!"); //NOI18N
518 // Get and cast client instance
519 AddressbookClient client = (AddressbookClient) this.getClient();
521 return client.enterString(5, 30, "Bitte geben Sie Ihre Telefonnummer an: ", true);
525 * Asks the user for own street (including number)
527 * @return Own street an number
530 public String enterOwnStreet () {
532 this.getLogger().trace("CALLED!"); //NOI18N
534 // Get and cast client instance
535 AddressbookClient client = (AddressbookClient) this.getClient();
537 return client.enterString(5, 50, "Bitte geben Sie Ihre Strasse und Hausnummer ein: ", false);
541 * Asks the user for own ZIP code
546 public int enterOwnZipCode () {
548 this.getLogger().trace("CALLED!"); //NOI18N
550 // Get and cast client instance
551 AddressbookClient client = (AddressbookClient) this.getClient();
553 return client.enterInt(0, 99_999, "Bitte geben Sie Ihre Postleitzahl ein: ");
557 public final int getColumnCount () {
558 assert (this.columnNames instanceof List) : "this.columnNames is not initialized"; //NOI18N
560 return this.columnNames.size();
564 * Getter for column name at given index.
566 * @param columnIndex Column index
567 * @return Database column name
570 public String getColumnName (final int columnIndex) {
571 assert (this.columnNames instanceof List) : "this.columnNames is not initialized"; //NOI18N
573 // Get column name at index
574 return this.columnNames.get(columnIndex);
578 * Getter for translated column name at given index.
580 * @param columnIndex Column index
581 * @return Human-readable column name
584 public String getTranslatedColumnName (final int columnIndex) {
585 assert (this.translatedColumnNames instanceof List) : "this.translatedColumnNames is not initialized"; //NOI18N
587 // Get column name at index
588 return this.translatedColumnNames.get(columnIndex);
592 * Somewhat "getter" for value from given row and column index
594 * @param rowIndex Row index
595 * @param columnIndex Column index
596 * @return Value from given row/column
599 public Object getValueFromRowColumn (final int rowIndex, final int columnIndex) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
601 this.getLogger().trace(MessageFormat.format("rowIndex={0},columnIndex={1} CALLED!", rowIndex, columnIndex)); //NOI18N
603 // Then get specific row from database which is a Contact instance
604 Storable storable = this.getFrontend().getStorableAtRow(rowIndex);
607 this.getLogger().debug(MessageFormat.format("storable={0}", storable)); //NOI18N
609 // It may return null
610 if (null == storable) {
612 this.getLogger().warn("contact is null - returning null ..."); //NOI18N
616 // Convert column index -> name
617 String columnName = this.getColumnName(columnIndex);
620 this.getLogger().debug(MessageFormat.format("columnName={0}", columnName)); //NOI18N
622 // Now get that column
625 value = storable.getValueFromColumn(columnName);
626 } catch (final IllegalArgumentException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ex) {
627 this.abortProgramWithException(ex);
631 this.getLogger().trace(MessageFormat.format("value={0} - EXIT!", value)); //NOI18N
638 * Checks whether own contact is already added by checking all entries for
641 * @return Whether own contact is already added
644 public boolean isOwnContactAdded () throws IOException, BadTokenException {
646 this.getLogger().trace("CALLED!"); //NOI18N
649 boolean isAdded = false;
652 // Deligate this call to frontend
653 isAdded = ((AddressbookContactFrontend) this.getFrontend()).isOwnContactFound();
654 } catch (final SQLException | IOException | BadTokenException | CorruptedDatabaseFileException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ex) {
655 // Something bad happened
656 this.abortProgramWithException(ex);
660 this.getLogger().trace(MessageFormat.format("isAdded={0} : EXIT!", isAdded)); //NOI18N
667 * Adds given contact to address book and flushes all entries to database
669 * @param contact Contact being added
670 * TODO Add check for book size
673 public void registerContact (final Contact contact) {
675 this.getLogger().trace(MessageFormat.format("contact={0} CALLED!", contact)); //NOI18N
678 if (null == contact) {
680 throw new NullPointerException("contact is null"); //NOI18N
684 /* NOISY-DEBUG: */ this.getLogger().debug(MessageFormat.format("Adding '{0}' '{1}' at pos '{2}' ...", contact.getFirstName(), contact.getFamilyName(), this.size())); //NOI18N
686 // Check if contact is found
687 if (((AddressbookContactFrontend) this.getFrontend()).isContactFound(contact)) {
688 // Contact already added
689 // TODO Do something here
690 } else if ((contact.isOwnContact()) && (this.isOwnContactAdded())) {
691 // Own contact already added
695 // Add contact to internal list
696 this.addContact(contact);
697 } catch (final ContactAlreadyAddedException | BadTokenException | SQLException | IOException | CorruptedDatabaseFileException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ex) {
699 this.abortProgramWithException(ex);
703 this.getLogger().trace("EXIT!"); //NOI18N
707 public final int size () throws IOException {
712 size = ((AddressbookContactFrontend) this.getFrontend()).getContactsCount();
713 } catch (final SQLException ex) {
714 // Something happened
715 this.abortProgramWithException(ex);
723 * Fills the column names array with strings from bundle
725 private void fillColumnNamesFromBundle () {
726 assert (this.columnNames instanceof List) : "this.columnNames is not initialized"; //NOI18N
727 assert (this.translatedColumnNames instanceof List) : "this.translatedColumnNames is not initialized"; //NOI18N
730 this.getLogger().trace("CALLED!"); //NOI18N
732 // First get an iterator from key set to iterate over
733 Iterator<String> iterator = this.getBundle().keySet().iterator();
735 // Then iterate over all
736 while (iterator.hasNext()) {
738 String key = iterator.next();
740 // Does the key start with AddressbookContactManager.columnName ?
741 if (key.startsWith("ContactManager.columnName")) { //NOI18N
742 // This is the wanted entry.
743 this.getLogger().debug(MessageFormat.format("key={0}", key)); //NOI18N
745 // Convert string to array based on delimiter '.'
746 String[] tokens = this.getArrayFromString(key, "."); //NOI18N
748 // Token array must contain 4 elements (AddressbookContactManager.columnName.foo.text)
749 assert(tokens.length == 4) : MessageFormat.format("Array tokens contains not 4 elements: {0}", Arrays.toString(tokens)); //NOI18N
751 // Get pre-last element
752 String columnName = tokens[tokens.length - 2];
755 this.getLogger().debug(MessageFormat.format("columnName={0} - adding ...", columnName)); //NOI18N
758 this.columnNames.add(columnName);
759 this.translatedColumnNames.add(this.getBundle().getString(key));
764 this.getLogger().trace(MessageFormat.format("getColumnCount()={0}: EXIT!", this.getColumnCount())); //NOI18N
768 * "Getter" for own contact instance or null if not found
770 * @return Contact instance or null
771 * @throws java.sql.SQLException If an SQL error occurs
772 * @throws java.io.IOException If an IO error occurs
773 * @throws org.mxchange.jcore.exceptions.BadTokenException Continued throw
774 * @throws org.mxchange.jcore.exceptions.CorruptedDatabaseFileException If the database file is damaged
775 * @throws java.lang.NoSuchMethodException If a method cannot be found
776 * @throws java.lang.IllegalAccessException If a method is not accessible
777 * @throws java.lang.reflect.InvocationTargetException Any other problems?
779 private Contact getOwnContact () throws IOException, BadTokenException, CorruptedDatabaseFileException, SQLException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
781 this.getLogger().trace("CALLED!"); //NOI18N
783 // Deligate this call to database frontend
784 Contact contact = ((AddressbookContactFrontend) this.getFrontend()).getOwnContact();
787 this.getLogger().trace(MessageFormat.format("contact={0} - EXIT!", contact)); //NOI18N
789 // Return instance or null