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.exceptions.UnhandledUserChoiceException;
31 import org.mxchange.jcore.manager.BaseManager;
32 import org.mxchange.jcore.model.contact.Contact;
33 import org.mxchange.jcore.model.contact.gender.Gender;
34 import org.mxchange.jcoreeelogger.beans.local.logger.LoggerBeanLocal;
37 * A manager for contacts.
39 * @author Roland Haeder
42 public class AddressbookContactManager extends BaseManager implements ManageableContactAddressbook {
47 private final List<String> columnNames;
50 * Translated column name list
52 private final List<String> translatedColumnNames;
57 private LoggerBeanLocal logger;
60 * Constructor which accepts maxContacts for maximum (initial) contacts and
63 * @param client Client instance to use
64 * @throws java.sql.SQLException If an SQL error occurs
66 public AddressbookContactManager (final Client client) throws SQLException {
68 this.getLogger().logTrace(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().logDebug("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().logTrace(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().logTrace("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().logTrace(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
140 if (!(this.getClient() instanceof AddressbookClient)) {
142 throw new IllegalArgumentException(MessageFormat.format("this.getClient()={0} does not implement AddressbookClient", this.getClient())); //NOI18N
145 // Get and cast client instance
146 AddressbookClient client = (AddressbookClient) this.getClient();
148 // First display it again
149 client.displayAddressBox(contact);
152 if (contact.isOwnContact()) {
153 // Deligate to client
154 client.doChangeOwnAddressData(contact);
156 // Other contact's address data to change
157 throw new UnsupportedOperationException("Changing contact entries not finished."); //NOI18N
161 this.getLogger().logTrace("EXIT!"); //NOI18N
165 * Let the user change "name data"
167 * @param contact Instance to change data
170 public void doChangeNameData (final Contact contact) {
172 this.getLogger().logTrace(MessageFormat.format("contact={0} CALLED!", contact)); //NOI18N
174 // Contact must not be null
175 if (null == contact) {
177 throw new NullPointerException("contact is null"); //NOI18N
180 // Get and cast client instance
181 AddressbookClient client = (AddressbookClient) this.getClient();
183 // First display them again
184 client.displayNameBox(contact);
187 if (contact.isOwnContact()) {
189 client.doChangeOwnNameData(contact);
191 // Then re-ask them ...
192 throw new UnsupportedOperationException("Changing contact entries not finished."); //NOI18N
196 this.getLogger().logTrace("EXIT!"); //NOI18N
200 * Let the user change other address
203 public void doChangeOtherAddress () {
204 throw new UnsupportedOperationException("Not supported yet."); //NOI18N
208 * Let the user change other data
210 * @param contact Instance to change data TODO Didn't handle birthday
213 public void doChangeOtherData (final Contact contact) {
215 this.getLogger().logTrace(MessageFormat.format("contact={0} CALLED!", contact)); //NOI18N
217 // Contact must not be null
218 if (null == contact) {
220 throw new NullPointerException("contact is null"); //NOI18N
223 // Get and cast client instance
224 AddressbookClient client = (AddressbookClient) this.getClient();
226 // First display them again
227 client.displayOtherDataBox(contact);
230 if (contact.isOwnContact()) {
232 client.doChangeOwnOtherData(contact);
234 // Then re-ask them ...
235 throw new UnsupportedOperationException("Changing contact entries not finished."); //NOI18N
239 this.getLogger().logTrace("EXIT!"); //NOI18N
243 * Allows the user to change his/her own data
246 public void doChangeOwnData () throws IOException, SQLException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
248 this.getLogger().logTrace("CALLED!"); //NOI18N
251 * First check if the user has registered own contact, before that
252 * nothing can be changed.
254 if (!this.isOwnContactAdded()) {
256 this.getClient().outputMessage("Sie haben noch nicht Ihre Daten eingegeben."); //NOI18N
258 // Skip any below code
263 Contact contact = this.getOwnContact();
266 assert (contact instanceof Contact) : ": contact is not implementing Contact: " + contact;
269 this.getClient().show(contact);
271 // Get and cast client instance
272 AddressbookClient client = (AddressbookClient) this.getClient();
275 // Ask user what to change
276 client.userChooseChangeContactData(contact);
277 } catch (final UnhandledUserChoiceException ex) {
278 this.getLogger().logException(ex);
282 this.getLogger().logTrace("EXIT!"); //NOI18N
286 * Let the user delete other address
289 public void doDeleteOtherAddress () {
290 throw new UnsupportedOperationException("Not supported yet."); //NOI18N
294 * Asks user for own data
297 public void doEnterOwnData () throws ContactAlreadyAddedException, IOException {
299 this.getLogger().logTrace("CALLED!"); //NOI18N
301 // Is own contact already added?
302 if (this.isOwnContactAdded()) {
303 // Don't continue here
304 throw new ContactAlreadyAddedException();
307 // Get and cast client instance
308 AddressbookClient client = (AddressbookClient) this.getClient();
310 // Deligate this call to the client
311 Contact contact = client.doEnterOwnData();
314 if (contact instanceof Contact) {
315 // Add it to contact "book"
316 this.registerContact(contact);
320 this.getLogger().logTrace("EXIT!"); //NOI18N
324 public void doListContacts () {
325 throw new UnsupportedOperationException("Not supported yet."); //NOI18N
329 public void doSearchContacts () {
330 throw new UnsupportedOperationException("Not supported yet."); //NOI18N
334 * Shuts down this contact manager
336 * @throws java.sql.SQLException If an SQL error occurs
337 * @throws java.io.IOException If an IO error occurs
340 public void doShutdown () throws SQLException, IOException {
342 this.getLogger().logTrace("CALLED!"); //NOI18N
344 // Shut down the database layer
345 ((AddressbookContactFrontend) this.getFrontend()).doShutdown();
348 this.getLogger().logTrace("EXIT!"); //NOI18N
352 * Asks the user for his/her cellphone number
354 * @return User's cellphone number
357 public String enterOwnCellNumber () {
359 this.getLogger().logTrace("CALLED!"); //NOI18N
361 // Get and cast client instance
362 AddressbookClient client = (AddressbookClient) this.getClient();
364 return client.enterString(5, 30, "Bitte geben Sie Ihre Handynummer an: ", true);
368 * Asks the user for his/her city's name
370 * @return City's name of the user
373 public String enterOwnCity () {
375 this.getLogger().logTrace("CALLED!"); //NOI18N
377 // Get and cast client instance
378 AddressbookClient client = (AddressbookClient) this.getClient();
380 return client.enterString(3, 50, "Bitte geben Sie Ihre Wohnort ein: ", false);
384 * Asks the user for his/her city's name
386 * @return City's name of the user
389 public String enterOwnComment () {
391 this.getLogger().logTrace("CALLED!"); //NOI18N
393 // Get and cast client instance
394 AddressbookClient client = (AddressbookClient) this.getClient();
396 return client.enterString(0, 100, "Kommentar zu Ihrem Eintrag: ", true);
400 * Asks the user for his/her company name
402 * @return User's company name
405 public String enterOwnCompanyName () {
407 this.getLogger().logTrace("CALLED!"); //NOI18N
409 // Get and cast client instance
410 AddressbookClient client = (AddressbookClient) this.getClient();
412 return client.enterString(5, 50, "Bitte geben Sie Ihre Firmenbezeichnung ein: ", true);
416 * Asks user for his/her own country code
418 * @return User's own country code
421 public String enterOwnCountryCode () {
423 this.getLogger().logTrace("CALLED!"); //NOI18N
425 // Get and cast client instance
426 AddressbookClient client = (AddressbookClient) this.getClient();
428 return client.enterString(2, 2, "Bitte geben Sie den zweistelligen Ländercode von Ihrem Land ein: ", false).toUpperCase();
432 * Asks user for his/her own country code
434 * @return User's own country code
437 public String enterOwnEmailAddress () {
439 this.getLogger().logTrace("CALLED!"); //NOI18N
441 // Get and cast client instance
442 AddressbookClient client = (AddressbookClient) this.getClient();
444 return client.enterString(10, 50, "Bitte geben Sie Ihre Email-Adresse ein: ", true);
448 * Asks the user for family name
450 * @return Family name of the user
453 public String enterOwnFamilyName () {
455 this.getLogger().logTrace("CALLED!"); //NOI18N
457 // Get and cast client instance
458 AddressbookClient client = (AddressbookClient) this.getClient();
460 return client.enterString(2, 50, "Bitte geben Sie Ihren Nachnamen ein: ", false);
464 * Asks the user for family name
466 * @return Family name of the user
469 public String enterOwnFaxNumber () {
471 this.getLogger().logTrace("CALLED!"); //NOI18N
473 // Get and cast client instance
474 AddressbookClient client = (AddressbookClient) this.getClient();
476 return client.enterString(5, 30, "Bitte geben Sie Ihre Faxnummer an: ", true);
480 * Asks the user for surname
482 * @return Surname of the user
485 public String enterOwnFirstName () {
487 this.getLogger().logTrace("CALLED!"); //NOI18N
489 // Get and cast client instance
490 AddressbookClient client = (AddressbookClient) this.getClient();
492 return client.enterString(2, 50, "Bitte geben Sie Ihren Vornamen ein: ", false);
496 * Asks the user for gender, until a valid has been entered
498 * @return Gender of the user
501 public Gender enterOwnGender () {
503 this.getLogger().logTrace("CALLED!"); //NOI18N
505 // Get and cast client instance
506 AddressbookClient client = (AddressbookClient) this.getClient();
508 return client.enterGender("Bitte geben Sie die Anrede ein: (M=Herr, F=Frau, C=Firma): ");
512 * Asks the user for phone number
514 * @return Phone number of the user
517 public String enterOwnPhoneNumber () {
519 this.getLogger().logTrace("CALLED!"); //NOI18N
521 // Get and cast client instance
522 AddressbookClient client = (AddressbookClient) this.getClient();
524 return client.enterString(5, 30, "Bitte geben Sie Ihre Telefonnummer an: ", true);
528 * Asks the user for own street (including number)
530 * @return Own street an number
533 public String enterOwnStreet () {
535 this.getLogger().logTrace("CALLED!"); //NOI18N
537 // Get and cast client instance
538 AddressbookClient client = (AddressbookClient) this.getClient();
540 return client.enterString(5, 50, "Bitte geben Sie Ihre Strasse und Hausnummer ein: ", false);
544 * Asks the user for own ZIP code
549 public int enterOwnZipCode () {
551 this.getLogger().logTrace("CALLED!"); //NOI18N
553 // Get and cast client instance
554 AddressbookClient client = (AddressbookClient) this.getClient();
556 return client.enterInt(0, 99_999, "Bitte geben Sie Ihre Postleitzahl ein: ");
560 public final int getColumnCount () {
561 assert (this.columnNames instanceof List) : "this.columnNames is not initialized"; //NOI18N
563 return this.columnNames.size();
567 public String getColumnName (final int columnIndex) {
568 assert (this.columnNames instanceof List) : "this.columnNames is not initialized"; //NOI18N
570 // Get column name at index
571 return this.columnNames.get(columnIndex);
575 public String getTranslatedColumnName (final int columnIndex) {
576 assert (this.translatedColumnNames instanceof List) : "this.translatedColumnNames is not initialized"; //NOI18N
578 // Get column name at index
579 return this.translatedColumnNames.get(columnIndex);
583 public Object getValueFromRowColumn (final int rowIndex, final int columnIndex) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
585 this.getLogger().logTrace(MessageFormat.format("rowIndex={0},columnIndex={1} CALLED!", rowIndex, columnIndex)); //NOI18N
587 // Then get specific row from database which is a Contact instance
588 Storable storable = this.getFrontend().getStorableAtRow(rowIndex);
591 this.getLogger().logDebug(MessageFormat.format("storable={0}", storable)); //NOI18N
593 // It may return null
594 if (null == storable) {
596 this.getLogger().logWarning("contact is null - returning null ..."); //NOI18N
600 // Convert column index -> name
601 String columnName = this.getColumnName(columnIndex);
604 this.getLogger().logDebug(MessageFormat.format("columnName={0}", columnName)); //NOI18N
606 // Now get that column
609 value = storable.getValueFromColumn(columnName);
610 } catch (final IllegalArgumentException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ex) {
611 this.abortProgramWithException(ex);
615 this.getLogger().logTrace(MessageFormat.format("value={0} - EXIT!", value)); //NOI18N
622 * Checks whether own contact is already added by checking all entries for
625 * @return Whether own contact is already added
628 public boolean isOwnContactAdded () throws IOException {
630 this.getLogger().logTrace("CALLED!"); //NOI18N
633 boolean isAdded = false;
636 // Deligate this call to frontend
637 isAdded = ((AddressbookContactFrontend) this.getFrontend()).isOwnContactFound();
638 } catch (final SQLException | IOException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ex) {
639 // Something bad happened
640 this.abortProgramWithException(ex);
644 this.getLogger().logTrace(MessageFormat.format("isAdded={0} : EXIT!", isAdded)); //NOI18N
651 public void logException (final Throwable exception) {
652 this.getLogger().logException(exception);
656 * Adds given contact to address book and flushes all entries to database
658 * @param contact Contact being added TODO Add check for book size
661 public void registerContact (final Contact contact) {
663 this.getLogger().logTrace(MessageFormat.format("contact={0} CALLED!", contact)); //NOI18N
666 if (null == contact) {
668 throw new NullPointerException("contact is null"); //NOI18N
671 // Check if contact is found
672 if (((AddressbookContactFrontend) this.getFrontend()).isContactFound(contact)) {
673 // Contact already added
674 // TODO Do something here
675 } else if ((contact.isOwnContact()) && (this.isOwnContactAdded())) {
676 // Own contact already added
680 // Add contact to internal list
681 this.addContact(contact);
682 } catch (final ContactAlreadyAddedException | SQLException | IOException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ex) {
684 this.abortProgramWithException(ex);
688 this.getLogger().logTrace("EXIT!"); //NOI18N
692 * Logs given exception and exits program
694 * @param throwable Throwable
696 private void abortProgramWithException (Throwable throwable) {
698 this.logException(throwable);
705 * Fills the column names array with strings from bundle
707 private void fillColumnNamesFromBundle () {
708 assert (this.columnNames instanceof List) : "this.columnNames is not initialized"; //NOI18N
709 assert (this.translatedColumnNames instanceof List) : "this.translatedColumnNames is not initialized"; //NOI18N
712 this.getLogger().logTrace("CALLED!"); //NOI18N
714 // First get an iterator from key set to iterate over
715 Iterator<String> iterator = this.getBundle().keySet().iterator();
717 // Then iterate over all
718 while (iterator.hasNext()) {
720 String key = iterator.next().toLowerCase();
722 // Does the key start with AddressbookContactManager.columnName ?
723 if (key.startsWith("ContactManager.columnName")) { //NOI18N
724 // This is the wanted entry.
725 this.getLogger().logDebug(MessageFormat.format("key={0}", key)); //NOI18N
727 // Convert string to array based on delimiter '.'
728 String[] tokens = this.getArrayFromString(key, "."); //NOI18N
730 // Token array must contain 4 elements (AddressbookContactManager.columnName.foo.text)
731 assert (tokens.length == 4) : MessageFormat.format("Array tokens contains not 4 elements: {0}", Arrays.toString(tokens)); //NOI18N
733 // Get pre-last element
734 String columnName = tokens[tokens.length - 2];
737 this.getLogger().logDebug(MessageFormat.format("columnName={0} - adding ...", columnName)); //NOI18N
740 this.columnNames.add(columnName);
741 this.translatedColumnNames.add(this.getBundle().getString(key));
746 this.getLogger().logTrace(MessageFormat.format("getColumnCount()={0}: EXIT!", this.getColumnCount())); //NOI18N
750 * Getter for logger instance
752 * @return Logger instance
754 private LoggerBeanLocal getLogger () {
759 * "Getter" for own contact instance or null if not found
761 * @return Contact instance or null
762 * @throws java.sql.SQLException If an SQL error occurs
763 * @throws java.io.IOException If an IO error occurs
764 * @throws java.lang.NoSuchMethodException If a method cannot be found
765 * @throws java.lang.IllegalAccessException If a method is not accessible
766 * @throws java.lang.reflect.InvocationTargetException Any other problems?
768 private Contact getOwnContact () throws IOException, SQLException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
770 this.getLogger().logTrace("CALLED!"); //NOI18N
772 // Deligate this call to database frontend
773 Contact contact = ((AddressbookContactFrontend) this.getFrontend()).getOwnContact();
776 this.getLogger().logTrace(MessageFormat.format("contact={0} - EXIT!", contact)); //NOI18N
778 // Return instance or null