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;
36 * A manager for contacts.
38 * @author Roland Haeder
41 public class AddressbookContactManager extends BaseManager implements ManageableAddressbookContact {
46 private final List<String> columnNames;
49 * Translated column name list
51 private final List<String> translatedColumnNames;
54 * Constructor which accepts maxContacts for maximum (initial) contacts and
57 * @param client Client instance to use
58 * @throws java.sql.SQLException If an SQL error occurs
60 public AddressbookContactManager (final Client client) throws SQLException {
62 this.getLogger().trace(MessageFormat.format("client={1} - CALLED!", client)); //NOI18N
64 // Make sure all parameters are set correctly
67 throw new NullPointerException("client is null"); //NOI18N
70 // Set client instance
71 this.setClient(client);
73 // Init database connection
74 DatabaseFrontend frontend = new AddressbookContactDatabaseFrontend(this);
75 this.setFrontend(frontend);
78 this.columnNames = new ArrayList<>(15);
79 this.translatedColumnNames = new ArrayList<>(15);
82 this.fillColumnNamesFromBundle();
85 //* NOISY-DEBUG: */ this.getLogger().debug("client=" + client);
89 * Adds given Contact instance to list
91 * @param contact Contact instance to add
94 public void addContact (final Contact contact) throws ContactAlreadyAddedException {
96 this.getLogger().trace(MessageFormat.format("contact={0} - CALLED!", contact)); //NOI18N
98 // Contact instance must not be null
99 if (null == contact) {
101 throw new NullPointerException("contact is null"); //NOI18N
105 ((AddressbookContactFrontend) this.getFrontend()).addContact(contact);
108 this.getLogger().trace("EXIT!"); //NOI18N
112 * Let the user add a new other address
115 public void doAddOtherAddress () {
116 throw new UnsupportedOperationException("Not supported yet."); //NOI18N
120 * Let the user change address data
122 * @param contact Instance to change data
125 public void doChangeAddressData (final Contact contact) {
127 this.getLogger().trace(MessageFormat.format("contact={0} CALLED!", contact)); //NOI18N
129 // Contact must not be null
130 if (null == contact) {
132 throw new NullPointerException("contact is null"); //NOI18N
135 // Get and cast client instance
136 AddressbookClient client = (AddressbookClient) this.getClient();
138 // First display it again
139 client.displayAddressBox(contact);
142 if (contact.isOwnContact()) {
143 // Deligate to client
144 client.doChangeOwnAddressData(contact);
146 // Other contact's address data to change
147 throw new UnsupportedOperationException("Changing contact entries not finished."); //NOI18N
151 this.getLogger().trace("EXIT!"); //NOI18N
155 * Let the user change "name data"
157 * @param contact Instance to change data
160 public void doChangeNameData (final Contact contact) {
162 this.getLogger().trace(MessageFormat.format("contact={0} CALLED!", contact)); //NOI18N
164 // Contact must not be null
165 if (null == contact) {
167 throw new NullPointerException("contact is null"); //NOI18N
170 // Get and cast client instance
171 AddressbookClient client = (AddressbookClient) this.getClient();
173 // First display them again
174 client.displayNameBox(contact);
177 if (contact.isOwnContact()) {
179 client.doChangeOwnNameData(contact);
181 // Then re-ask them ...
182 throw new UnsupportedOperationException("Changing contact entries not finished."); //NOI18N
186 this.getLogger().trace("EXIT!"); //NOI18N
190 * Let the user change other address
193 public void doChangeOtherAddress () {
194 throw new UnsupportedOperationException("Not supported yet."); //NOI18N
198 * Let the user change other data
200 * @param contact Instance to change data
201 * TODO Didn't handle birthday
204 public void doChangeOtherData (final Contact contact) {
206 this.getLogger().trace(MessageFormat.format("contact={0} CALLED!", contact)); //NOI18N
208 // Contact must not be null
209 if (null == contact) {
211 throw new NullPointerException("contact is null"); //NOI18N
214 // Get and cast client instance
215 AddressbookClient client = (AddressbookClient) this.getClient();
217 // First display them again
218 client.displayOtherDataBox(contact);
221 if (contact.isOwnContact()) {
223 client.doChangeOwnOtherData(contact);
225 // Then re-ask them ...
226 throw new UnsupportedOperationException("Changing contact entries not finished."); //NOI18N
230 this.getLogger().trace("EXIT!"); //NOI18N
234 * Allows the user to change his/her own data
237 public void doChangeOwnData () throws IOException, SQLException, NoSuchMethodException, IllegalAccessException, InvocationTargetException{
239 this.getLogger().trace("CALLED!"); //NOI18N
242 * First check if the user has registered own contact, before that
243 * nothing can be changed.
245 if (!this.isOwnContactAdded()) {
247 this.getClient().outputMessage("Sie haben noch nicht Ihre Daten eingegeben."); //NOI18N
249 // Skip any below code
254 Contact contact = this.getOwnContact();
257 assert (contact instanceof Contact);
260 contact.show(this.getClient());
262 // Get and cast client instance
263 AddressbookClient client = (AddressbookClient) this.getClient();
266 // Ask user what to change
267 client.userChooseChangeContactData(contact);
268 } catch (final UnhandledUserChoiceException ex) {
269 this.getLogger().catching(ex);
273 this.getLogger().trace("EXIT!"); //NOI18N
277 * Let the user delete other address
280 public void doDeleteOtherAddress () {
281 throw new UnsupportedOperationException("Not supported yet."); //NOI18N
285 * Asks user for own data
288 public void doEnterOwnData () throws ContactAlreadyAddedException, IOException {
290 this.getLogger().trace("CALLED!"); //NOI18N
292 // Is own contact already added?
293 if (this.isOwnContactAdded()) {
294 // Don't continue here
295 throw new ContactAlreadyAddedException();
298 // Get and cast client instance
299 AddressbookClient client = (AddressbookClient) this.getClient();
301 // Deligate this call to the client
302 Contact contact = client.doEnterOwnData();
305 if (contact instanceof Contact) {
306 // Add it to contact "book"
307 this.registerContact(contact);
311 this.getLogger().trace("EXIT!"); //NOI18N
315 public void doListContacts () {
316 throw new UnsupportedOperationException("Not supported yet."); //NOI18N
320 public void doSearchContacts () {
321 throw new UnsupportedOperationException("Not supported yet."); //NOI18N
325 * Shuts down this contact manager
327 * @throws java.sql.SQLException If an SQL error occurs
328 * @throws java.io.IOException If an IO error occurs
331 public void doShutdown () throws SQLException, IOException {
333 this.getLogger().trace("CALLED!"); //NOI18N
335 // Shut down the database layer
336 ((AddressbookContactFrontend) this.getFrontend()).doShutdown();
339 this.getLogger().trace("EXIT!"); //NOI18N
343 * Asks the user for his/her cellphone number
345 * @return User's cellphone number
348 public String enterOwnCellNumber () {
350 this.getLogger().trace("CALLED!"); //NOI18N
352 // Get and cast client instance
353 AddressbookClient client = (AddressbookClient) this.getClient();
355 return client.enterString(5, 30, "Bitte geben Sie Ihre Handynummer an: ", true);
359 * Asks the user for his/her city's name
361 * @return City's name of the user
364 public String enterOwnCity () {
366 this.getLogger().trace("CALLED!"); //NOI18N
368 // Get and cast client instance
369 AddressbookClient client = (AddressbookClient) this.getClient();
371 return client.enterString(3, 50, "Bitte geben Sie Ihre Wohnort ein: ", false);
375 * Asks the user for his/her city's name
377 * @return City's name of the user
380 public String enterOwnComment () {
382 this.getLogger().trace("CALLED!"); //NOI18N
384 // Get and cast client instance
385 AddressbookClient client = (AddressbookClient) this.getClient();
387 return client.enterString(0, 100, "Kommentar zu Ihrem Eintrag: ", true);
391 * Asks the user for his/her company name
393 * @return User's company name
396 public String enterOwnCompanyName () {
398 this.getLogger().trace("CALLED!"); //NOI18N
400 // Get and cast client instance
401 AddressbookClient client = (AddressbookClient) this.getClient();
403 return client.enterString(5, 50, "Bitte geben Sie Ihre Firmenbezeichnung ein: ", true);
407 * Asks user for his/her own country code
409 * @return User's own country code
412 public String enterOwnCountryCode () {
414 this.getLogger().trace("CALLED!"); //NOI18N
416 // Get and cast client instance
417 AddressbookClient client = (AddressbookClient) this.getClient();
419 return client.enterString(2, 2, "Bitte geben Sie den zweistelligen Ländercode von Ihrem Land ein: ", false).toUpperCase();
423 * Asks user for his/her own country code
425 * @return User's own country code
428 public String enterOwnEmailAddress () {
430 this.getLogger().trace("CALLED!"); //NOI18N
432 // Get and cast client instance
433 AddressbookClient client = (AddressbookClient) this.getClient();
435 return client.enterString(10, 50, "Bitte geben Sie Ihre Email-Adresse ein: ", true);
439 * Asks the user for family name
441 * @return Family name of the user
444 public String enterOwnFamilyName () {
446 this.getLogger().trace("CALLED!"); //NOI18N
448 // Get and cast client instance
449 AddressbookClient client = (AddressbookClient) this.getClient();
451 return client.enterString(2, 50, "Bitte geben Sie Ihren Nachnamen ein: ", false);
455 * Asks the user for family name
457 * @return Family name of the user
460 public String enterOwnFaxNumber () {
462 this.getLogger().trace("CALLED!"); //NOI18N
464 // Get and cast client instance
465 AddressbookClient client = (AddressbookClient) this.getClient();
467 return client.enterString(5, 30, "Bitte geben Sie Ihre Faxnummer an: ", true);
471 * Asks the user for surname
473 * @return Surname of the user
476 public String enterOwnFirstName () {
478 this.getLogger().trace("CALLED!"); //NOI18N
480 // Get and cast client instance
481 AddressbookClient client = (AddressbookClient) this.getClient();
483 return client.enterString(2, 50, "Bitte geben Sie Ihren Vornamen ein: ", false);
487 * Asks the user for gender, until a valid has been entered
489 * @return Gender of the user
492 public Gender enterOwnGender () {
494 this.getLogger().trace("CALLED!"); //NOI18N
496 // Get and cast client instance
497 AddressbookClient client = (AddressbookClient) this.getClient();
499 return client.enterGender("Bitte geben Sie die Anrede ein: (M=Herr, F=Frau, C=Firma): ");
503 * Asks the user for phone number
505 * @return Phone number of the user
508 public String enterOwnPhoneNumber () {
510 this.getLogger().trace("CALLED!"); //NOI18N
512 // Get and cast client instance
513 AddressbookClient client = (AddressbookClient) this.getClient();
515 return client.enterString(5, 30, "Bitte geben Sie Ihre Telefonnummer an: ", true);
519 * Asks the user for own street (including number)
521 * @return Own street an number
524 public String enterOwnStreet () {
526 this.getLogger().trace("CALLED!"); //NOI18N
528 // Get and cast client instance
529 AddressbookClient client = (AddressbookClient) this.getClient();
531 return client.enterString(5, 50, "Bitte geben Sie Ihre Strasse und Hausnummer ein: ", false);
535 * Asks the user for own ZIP code
540 public int enterOwnZipCode () {
542 this.getLogger().trace("CALLED!"); //NOI18N
544 // Get and cast client instance
545 AddressbookClient client = (AddressbookClient) this.getClient();
547 return client.enterInt(0, 99_999, "Bitte geben Sie Ihre Postleitzahl ein: ");
551 public final int getColumnCount () {
552 assert (this.columnNames instanceof List) : "this.columnNames is not initialized"; //NOI18N
554 return this.columnNames.size();
558 public String getColumnName (final int columnIndex) {
559 assert (this.columnNames instanceof List) : "this.columnNames is not initialized"; //NOI18N
561 // Get column name at index
562 return this.columnNames.get(columnIndex);
566 public String getTranslatedColumnName (final int columnIndex) {
567 assert (this.translatedColumnNames instanceof List) : "this.translatedColumnNames is not initialized"; //NOI18N
569 // Get column name at index
570 return this.translatedColumnNames.get(columnIndex);
574 public Object getValueFromRowColumn (final int rowIndex, final int columnIndex) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
576 this.getLogger().trace(MessageFormat.format("rowIndex={0},columnIndex={1} CALLED!", rowIndex, columnIndex)); //NOI18N
578 // Then get specific row from database which is a Contact instance
579 Storable storable = this.getFrontend().getStorableAtRow(rowIndex);
582 this.getLogger().debug(MessageFormat.format("storable={0}", storable)); //NOI18N
584 // It may return null
585 if (null == storable) {
587 this.getLogger().warn("contact is null - returning null ..."); //NOI18N
591 // Convert column index -> name
592 String columnName = this.getColumnName(columnIndex);
595 this.getLogger().debug(MessageFormat.format("columnName={0}", columnName)); //NOI18N
597 // Now get that column
600 value = storable.getValueFromColumn(columnName);
601 } catch (final IllegalArgumentException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ex) {
602 this.abortProgramWithException(ex);
606 this.getLogger().trace(MessageFormat.format("value={0} - EXIT!", value)); //NOI18N
613 * Checks whether own contact is already added by checking all entries for
616 * @return Whether own contact is already added
619 public boolean isOwnContactAdded () throws IOException {
621 this.getLogger().trace("CALLED!"); //NOI18N
624 boolean isAdded = false;
627 // Deligate this call to frontend
628 isAdded = ((AddressbookContactFrontend) this.getFrontend()).isOwnContactFound();
629 } catch (final SQLException | IOException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ex) {
630 // Something bad happened
631 this.abortProgramWithException(ex);
635 this.getLogger().trace(MessageFormat.format("isAdded={0} : EXIT!", isAdded)); //NOI18N
642 * Adds given contact to address book and flushes all entries to database
644 * @param contact Contact being added
645 * TODO Add check for book size
648 public void registerContact (final Contact contact) {
650 this.getLogger().trace(MessageFormat.format("contact={0} CALLED!", contact)); //NOI18N
653 if (null == contact) {
655 throw new NullPointerException("contact is null"); //NOI18N
659 /* NOISY-DEBUG: */ this.getLogger().debug(MessageFormat.format("Adding '{0}' '{1}' at pos '{2}' ...", contact.getFirstName(), contact.getFamilyName(), this.size())); //NOI18N
661 // Check if contact is found
662 if (((AddressbookContactFrontend) this.getFrontend()).isContactFound(contact)) {
663 // Contact already added
664 // TODO Do something here
665 } else if ((contact.isOwnContact()) && (this.isOwnContactAdded())) {
666 // Own contact already added
670 // Add contact to internal list
671 this.addContact(contact);
672 } catch (final ContactAlreadyAddedException | SQLException | IOException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ex) {
674 this.abortProgramWithException(ex);
678 this.getLogger().trace("EXIT!"); //NOI18N
682 public final int size () throws IOException {
687 size = ((AddressbookContactFrontend) this.getFrontend()).getContactsCount();
688 } catch (final SQLException ex) {
689 // Something happened
690 this.abortProgramWithException(ex);
698 * Fills the column names array with strings from bundle
700 private void fillColumnNamesFromBundle () {
701 assert (this.columnNames instanceof List) : "this.columnNames is not initialized"; //NOI18N
702 assert (this.translatedColumnNames instanceof List) : "this.translatedColumnNames is not initialized"; //NOI18N
705 this.getLogger().trace("CALLED!"); //NOI18N
707 // First get an iterator from key set to iterate over
708 Iterator<String> iterator = this.getBundle().keySet().iterator();
710 // Then iterate over all
711 while (iterator.hasNext()) {
713 String key = iterator.next();
715 // Does the key start with AddressbookContactManager.columnName ?
716 if (key.startsWith("ContactManager.columnName")) { //NOI18N
717 // This is the wanted entry.
718 this.getLogger().debug(MessageFormat.format("key={0}", key)); //NOI18N
720 // Convert string to array based on delimiter '.'
721 String[] tokens = this.getArrayFromString(key, "."); //NOI18N
723 // Token array must contain 4 elements (AddressbookContactManager.columnName.foo.text)
724 assert(tokens.length == 4) : MessageFormat.format("Array tokens contains not 4 elements: {0}", Arrays.toString(tokens)); //NOI18N
726 // Get pre-last element
727 String columnName = tokens[tokens.length - 2];
730 this.getLogger().debug(MessageFormat.format("columnName={0} - adding ...", columnName)); //NOI18N
733 this.columnNames.add(columnName);
734 this.translatedColumnNames.add(this.getBundle().getString(key));
739 this.getLogger().trace(MessageFormat.format("getColumnCount()={0}: EXIT!", this.getColumnCount())); //NOI18N
743 * "Getter" for own contact instance or null if not found
745 * @return Contact instance or null
746 * @throws java.sql.SQLException If an SQL error occurs
747 * @throws java.io.IOException If an IO error occurs
748 * @throws java.lang.NoSuchMethodException If a method cannot be found
749 * @throws java.lang.IllegalAccessException If a method is not accessible
750 * @throws java.lang.reflect.InvocationTargetException Any other problems?
752 private Contact getOwnContact () throws IOException, SQLException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
754 this.getLogger().trace("CALLED!"); //NOI18N
756 // Deligate this call to database frontend
757 Contact contact = ((AddressbookContactFrontend) this.getFrontend()).getOwnContact();
760 this.getLogger().trace(MessageFormat.format("contact={0} - EXIT!", contact)); //NOI18N
762 // Return instance or null