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.Log;
35 import org.mxchange.jcoreeelogger.beans.local.logger.LoggerBeanLocal;
38 * A manager for contacts.
40 * @author Roland Haeder
43 public class AddressbookContactManager extends BaseManager implements ManageableContactAddressbook {
48 private final List<String> columnNames;
51 * Translated column name list
53 private final List<String> translatedColumnNames;
59 private LoggerBeanLocal logger;
62 * Constructor which accepts maxContacts for maximum (initial) contacts and
65 * @param client Client instance to use
66 * @throws java.sql.SQLException If an SQL error occurs
68 public AddressbookContactManager (final Client client) throws SQLException {
70 this.getLogger().logTrace(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().logDebug("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().logTrace(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().logTrace("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().logTrace(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
142 if (!(this.getClient() instanceof AddressbookClient)) {
144 throw new IllegalArgumentException(MessageFormat.format("this.getClient()={0} does not implement AddressbookClient", this.getClient())); //NOI18N
147 // Get and cast client instance
148 AddressbookClient client = (AddressbookClient) this.getClient();
150 // First display it again
151 client.displayAddressBox(contact);
154 if (contact.isOwnContact()) {
155 // Deligate to client
156 client.doChangeOwnAddressData(contact);
158 // Other contact's address data to change
159 throw new UnsupportedOperationException("Changing contact entries not finished."); //NOI18N
163 this.getLogger().logTrace("EXIT!"); //NOI18N
167 * Let the user change "name data"
169 * @param contact Instance to change data
172 public void doChangeNameData (final Contact contact) {
174 this.getLogger().logTrace(MessageFormat.format("contact={0} CALLED!", contact)); //NOI18N
176 // Contact must not be null
177 if (null == contact) {
179 throw new NullPointerException("contact is null"); //NOI18N
182 // Get and cast client instance
183 AddressbookClient client = (AddressbookClient) this.getClient();
185 // First display them again
186 client.displayNameBox(contact);
189 if (contact.isOwnContact()) {
191 client.doChangeOwnNameData(contact);
193 // Then re-ask them ...
194 throw new UnsupportedOperationException("Changing contact entries not finished."); //NOI18N
198 this.getLogger().logTrace("EXIT!"); //NOI18N
202 * Let the user change other address
205 public void doChangeOtherAddress () {
206 throw new UnsupportedOperationException("Not supported yet."); //NOI18N
210 * Let the user change other data
212 * @param contact Instance to change data TODO Didn't handle birthday
215 public void doChangeOtherData (final Contact contact) {
217 this.getLogger().logTrace(MessageFormat.format("contact={0} CALLED!", contact)); //NOI18N
219 // Contact must not be null
220 if (null == contact) {
222 throw new NullPointerException("contact is null"); //NOI18N
225 // Get and cast client instance
226 AddressbookClient client = (AddressbookClient) this.getClient();
228 // First display them again
229 client.displayOtherDataBox(contact);
232 if (contact.isOwnContact()) {
234 client.doChangeOwnOtherData(contact);
236 // Then re-ask them ...
237 throw new UnsupportedOperationException("Changing contact entries not finished."); //NOI18N
241 this.getLogger().logTrace("EXIT!"); //NOI18N
245 * Allows the user to change his/her own data
248 public void doChangeOwnData () throws IOException, SQLException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
250 this.getLogger().logTrace("CALLED!"); //NOI18N
253 * First check if the user has registered own contact, before that
254 * nothing can be changed.
256 if (!this.isOwnContactAdded()) {
258 this.getClient().outputMessage("Sie haben noch nicht Ihre Daten eingegeben."); //NOI18N
260 // Skip any below code
265 Contact contact = this.getOwnContact();
268 assert (contact instanceof Contact) : ": contact is not implementing Contact: " + contact;
271 this.getClient().show(contact);
273 // Get and cast client instance
274 AddressbookClient client = (AddressbookClient) this.getClient();
277 // Ask user what to change
278 client.userChooseChangeContactData(contact);
279 } catch (final UnhandledUserChoiceException ex) {
280 this.getLogger().logException(ex);
284 this.getLogger().logTrace("EXIT!"); //NOI18N
288 * Let the user delete other address
291 public void doDeleteOtherAddress () {
292 throw new UnsupportedOperationException("Not supported yet."); //NOI18N
296 * Asks user for own data
299 public void doEnterOwnData () throws ContactAlreadyAddedException, IOException {
301 this.getLogger().logTrace("CALLED!"); //NOI18N
303 // Is own contact already added?
304 if (this.isOwnContactAdded()) {
305 // Don't continue here
306 throw new ContactAlreadyAddedException();
309 // Get and cast client instance
310 AddressbookClient client = (AddressbookClient) this.getClient();
312 // Deligate this call to the client
313 Contact contact = client.doEnterOwnData();
316 if (contact instanceof Contact) {
317 // Add it to contact "book"
318 this.registerContact(contact);
322 this.getLogger().logTrace("EXIT!"); //NOI18N
326 public void doListContacts () {
327 throw new UnsupportedOperationException("Not supported yet."); //NOI18N
331 public void doSearchContacts () {
332 throw new UnsupportedOperationException("Not supported yet."); //NOI18N
336 * Shuts down this contact manager
338 * @throws java.sql.SQLException If an SQL error occurs
339 * @throws java.io.IOException If an IO error occurs
342 public void doShutdown () throws SQLException, IOException {
344 this.getLogger().logTrace("CALLED!"); //NOI18N
346 // Shut down the database layer
347 ((AddressbookContactFrontend) this.getFrontend()).doShutdown();
350 this.getLogger().logTrace("EXIT!"); //NOI18N
354 * Asks the user for his/her cellphone number
356 * @return User's cellphone number
359 public String enterOwnCellNumber () {
361 this.getLogger().logTrace("CALLED!"); //NOI18N
363 // Get and cast client instance
364 AddressbookClient client = (AddressbookClient) this.getClient();
366 return client.enterString(5, 30, "Bitte geben Sie Ihre Handynummer an: ", true);
370 * Asks the user for his/her city's name
372 * @return City's name of the user
375 public String enterOwnCity () {
377 this.getLogger().logTrace("CALLED!"); //NOI18N
379 // Get and cast client instance
380 AddressbookClient client = (AddressbookClient) this.getClient();
382 return client.enterString(3, 50, "Bitte geben Sie Ihre Wohnort ein: ", false);
386 * Asks the user for his/her city's name
388 * @return City's name of the user
391 public String enterOwnComment () {
393 this.getLogger().logTrace("CALLED!"); //NOI18N
395 // Get and cast client instance
396 AddressbookClient client = (AddressbookClient) this.getClient();
398 return client.enterString(0, 100, "Kommentar zu Ihrem Eintrag: ", true);
402 * Asks the user for his/her company name
404 * @return User's company name
407 public String enterOwnCompanyName () {
409 this.getLogger().logTrace("CALLED!"); //NOI18N
411 // Get and cast client instance
412 AddressbookClient client = (AddressbookClient) this.getClient();
414 return client.enterString(5, 50, "Bitte geben Sie Ihre Firmenbezeichnung ein: ", true);
418 * Asks user for his/her own country code
420 * @return User's own country code
423 public String enterOwnCountryCode () {
425 this.getLogger().logTrace("CALLED!"); //NOI18N
427 // Get and cast client instance
428 AddressbookClient client = (AddressbookClient) this.getClient();
430 return client.enterString(2, 2, "Bitte geben Sie den zweistelligen Ländercode von Ihrem Land ein: ", false).toUpperCase();
434 * Asks user for his/her own country code
436 * @return User's own country code
439 public String enterOwnEmailAddress () {
441 this.getLogger().logTrace("CALLED!"); //NOI18N
443 // Get and cast client instance
444 AddressbookClient client = (AddressbookClient) this.getClient();
446 return client.enterString(10, 50, "Bitte geben Sie Ihre Email-Adresse ein: ", true);
450 * Asks the user for family name
452 * @return Family name of the user
455 public String enterOwnFamilyName () {
457 this.getLogger().logTrace("CALLED!"); //NOI18N
459 // Get and cast client instance
460 AddressbookClient client = (AddressbookClient) this.getClient();
462 return client.enterString(2, 50, "Bitte geben Sie Ihren Nachnamen ein: ", false);
466 * Asks the user for family name
468 * @return Family name of the user
471 public String enterOwnFaxNumber () {
473 this.getLogger().logTrace("CALLED!"); //NOI18N
475 // Get and cast client instance
476 AddressbookClient client = (AddressbookClient) this.getClient();
478 return client.enterString(5, 30, "Bitte geben Sie Ihre Faxnummer an: ", true);
482 * Asks the user for surname
484 * @return Surname of the user
487 public String enterOwnFirstName () {
489 this.getLogger().logTrace("CALLED!"); //NOI18N
491 // Get and cast client instance
492 AddressbookClient client = (AddressbookClient) this.getClient();
494 return client.enterString(2, 50, "Bitte geben Sie Ihren Vornamen ein: ", false);
498 * Asks the user for gender, until a valid has been entered
500 * @return Gender of the user
503 public Gender enterOwnGender () {
505 this.getLogger().logTrace("CALLED!"); //NOI18N
507 // Get and cast client instance
508 AddressbookClient client = (AddressbookClient) this.getClient();
510 return client.enterGender("Bitte geben Sie die Anrede ein: (M=Herr, F=Frau, C=Firma): ");
514 * Asks the user for phone number
516 * @return Phone number of the user
519 public String enterOwnPhoneNumber () {
521 this.getLogger().logTrace("CALLED!"); //NOI18N
523 // Get and cast client instance
524 AddressbookClient client = (AddressbookClient) this.getClient();
526 return client.enterString(5, 30, "Bitte geben Sie Ihre Telefonnummer an: ", true);
530 * Asks the user for own street (including number)
532 * @return Own street an number
535 public String enterOwnStreet () {
537 this.getLogger().logTrace("CALLED!"); //NOI18N
539 // Get and cast client instance
540 AddressbookClient client = (AddressbookClient) this.getClient();
542 return client.enterString(5, 50, "Bitte geben Sie Ihre Strasse und Hausnummer ein: ", false);
546 * Asks the user for own ZIP code
551 public int enterOwnZipCode () {
553 this.getLogger().logTrace("CALLED!"); //NOI18N
555 // Get and cast client instance
556 AddressbookClient client = (AddressbookClient) this.getClient();
558 return client.enterInt(0, 99_999, "Bitte geben Sie Ihre Postleitzahl ein: ");
562 public final int getColumnCount () {
563 assert (this.columnNames instanceof List) : "this.columnNames is not initialized"; //NOI18N
565 return this.columnNames.size();
569 public String getColumnName (final int columnIndex) {
570 assert (this.columnNames instanceof List) : "this.columnNames is not initialized"; //NOI18N
572 // Get column name at index
573 return this.columnNames.get(columnIndex);
577 public String getTranslatedColumnName (final int columnIndex) {
578 assert (this.translatedColumnNames instanceof List) : "this.translatedColumnNames is not initialized"; //NOI18N
580 // Get column name at index
581 return this.translatedColumnNames.get(columnIndex);
585 public Object getValueFromRowColumn (final int rowIndex, final int columnIndex) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
587 this.getLogger().logTrace(MessageFormat.format("rowIndex={0},columnIndex={1} CALLED!", rowIndex, columnIndex)); //NOI18N
589 // Then get specific row from database which is a Contact instance
590 Storable storable = this.getFrontend().getStorableAtRow(rowIndex);
593 this.getLogger().logDebug(MessageFormat.format("storable={0}", storable)); //NOI18N
595 // It may return null
596 if (null == storable) {
598 this.getLogger().logWarning("contact is null - returning null ..."); //NOI18N
602 // Convert column index -> name
603 String columnName = this.getColumnName(columnIndex);
606 this.getLogger().logDebug(MessageFormat.format("columnName={0}", columnName)); //NOI18N
608 // Now get that column
611 value = storable.getValueFromColumn(columnName);
612 } catch (final IllegalArgumentException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ex) {
613 this.abortProgramWithException(ex);
617 this.getLogger().logTrace(MessageFormat.format("value={0} - EXIT!", value)); //NOI18N
624 * Checks whether own contact is already added by checking all entries for
627 * @return Whether own contact is already added
630 public boolean isOwnContactAdded () throws IOException {
632 this.getLogger().logTrace("CALLED!"); //NOI18N
635 boolean isAdded = false;
638 // Deligate this call to frontend
639 isAdded = ((AddressbookContactFrontend) this.getFrontend()).isOwnContactFound();
640 } catch (final SQLException | IOException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ex) {
641 // Something bad happened
642 this.abortProgramWithException(ex);
646 this.getLogger().logTrace(MessageFormat.format("isAdded={0} : EXIT!", isAdded)); //NOI18N
653 * Logs given exception
655 * @param exception Throwable
657 protected void logException (final Throwable exception) {
658 this.getLogger().logException(exception);
662 * Adds given contact to address book and flushes all entries to database
664 * @param contact Contact being added TODO Add check for book size
667 public void registerContact (final Contact contact) {
669 this.getLogger().logTrace(MessageFormat.format("contact={0} CALLED!", contact)); //NOI18N
672 if (null == contact) {
674 throw new NullPointerException("contact is null"); //NOI18N
677 // Check if contact is found
678 if (((AddressbookContactFrontend) this.getFrontend()).isContactFound(contact)) {
679 // Contact already added
680 // TODO Do something here
681 } else if ((contact.isOwnContact()) && (this.isOwnContactAdded())) {
682 // Own contact already added
686 // Add contact to internal list
687 this.addContact(contact);
688 } catch (final ContactAlreadyAddedException | SQLException | IOException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ex) {
690 this.abortProgramWithException(ex);
694 this.getLogger().logTrace("EXIT!"); //NOI18N
698 * Logs given exception and exits program
700 * @param throwable Throwable
702 private void abortProgramWithException (Throwable throwable) {
704 this.logException(throwable);
711 * Fills the column names array with strings from bundle
713 private void fillColumnNamesFromBundle () {
714 assert (this.columnNames instanceof List) : "this.columnNames is not initialized"; //NOI18N
715 assert (this.translatedColumnNames instanceof List) : "this.translatedColumnNames is not initialized"; //NOI18N
718 this.getLogger().logTrace("CALLED!"); //NOI18N
720 // First get an iterator from key set to iterate over
721 Iterator<String> iterator = this.getBundle().keySet().iterator();
723 // Then iterate over all
724 while (iterator.hasNext()) {
726 String key = iterator.next().toLowerCase();
728 // Does the key start with AddressbookContactManager.columnName ?
729 if (key.startsWith("ContactManager.columnName")) { //NOI18N
730 // This is the wanted entry.
731 this.getLogger().logDebug(MessageFormat.format("key={0}", key)); //NOI18N
733 // Convert string to array based on delimiter '.'
734 String[] tokens = this.getArrayFromString(key, "."); //NOI18N
736 // Token array must contain 4 elements (AddressbookContactManager.columnName.foo.text)
737 assert (tokens.length == 4) : MessageFormat.format("Array tokens contains not 4 elements: {0}", Arrays.toString(tokens)); //NOI18N
739 // Get pre-last element
740 String columnName = tokens[tokens.length - 2];
743 this.getLogger().logDebug(MessageFormat.format("columnName={0} - adding ...", columnName)); //NOI18N
746 this.columnNames.add(columnName);
747 this.translatedColumnNames.add(this.getBundle().getString(key));
752 this.getLogger().logTrace(MessageFormat.format("getColumnCount()={0}: EXIT!", this.getColumnCount())); //NOI18N
756 * Getter for logger instance
758 * @return Logger instance
760 private LoggerBeanLocal getLogger () {
765 * "Getter" for own contact instance or null if not found
767 * @return Contact instance or null
768 * @throws java.sql.SQLException If an SQL error occurs
769 * @throws java.io.IOException If an IO error occurs
770 * @throws java.lang.NoSuchMethodException If a method cannot be found
771 * @throws java.lang.IllegalAccessException If a method is not accessible
772 * @throws java.lang.reflect.InvocationTargetException Any other problems?
774 private Contact getOwnContact () throws IOException, SQLException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
776 this.getLogger().logTrace("CALLED!"); //NOI18N
778 // Deligate this call to database frontend
779 Contact contact = ((AddressbookContactFrontend) this.getFrontend()).getOwnContact();
782 this.getLogger().logTrace(MessageFormat.format("contact={0} - EXIT!", contact)); //NOI18N
784 // Return instance or null