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 ManageableContactAddressbook {
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
133 } if (!(this.getClient() instanceof AddressbookClient)) {
135 throw new IllegalArgumentException(MessageFormat.format("this.getClient()={0} does not implement AddressbookClient", this.getClient())); //NOI18N
138 // Get and cast client instance
139 AddressbookClient client = (AddressbookClient) this.getClient();
141 // First display it again
142 client.displayAddressBox(contact);
145 if (contact.isOwnContact()) {
146 // Deligate to client
147 client.doChangeOwnAddressData(contact);
149 // Other contact's address data to change
150 throw new UnsupportedOperationException("Changing contact entries not finished."); //NOI18N
154 this.getLogger().trace("EXIT!"); //NOI18N
158 * Let the user change "name data"
160 * @param contact Instance to change data
163 public void doChangeNameData (final Contact contact) {
165 this.getLogger().trace(MessageFormat.format("contact={0} CALLED!", contact)); //NOI18N
167 // Contact must not be null
168 if (null == contact) {
170 throw new NullPointerException("contact is null"); //NOI18N
173 // Get and cast client instance
174 AddressbookClient client = (AddressbookClient) this.getClient();
176 // First display them again
177 client.displayNameBox(contact);
180 if (contact.isOwnContact()) {
182 client.doChangeOwnNameData(contact);
184 // Then re-ask them ...
185 throw new UnsupportedOperationException("Changing contact entries not finished."); //NOI18N
189 this.getLogger().trace("EXIT!"); //NOI18N
193 * Let the user change other address
196 public void doChangeOtherAddress () {
197 throw new UnsupportedOperationException("Not supported yet."); //NOI18N
201 * Let the user change other data
203 * @param contact Instance to change data
204 * TODO Didn't handle birthday
207 public void doChangeOtherData (final Contact contact) {
209 this.getLogger().trace(MessageFormat.format("contact={0} CALLED!", contact)); //NOI18N
211 // Contact must not be null
212 if (null == contact) {
214 throw new NullPointerException("contact is null"); //NOI18N
217 // Get and cast client instance
218 AddressbookClient client = (AddressbookClient) this.getClient();
220 // First display them again
221 client.displayOtherDataBox(contact);
224 if (contact.isOwnContact()) {
226 client.doChangeOwnOtherData(contact);
228 // Then re-ask them ...
229 throw new UnsupportedOperationException("Changing contact entries not finished."); //NOI18N
233 this.getLogger().trace("EXIT!"); //NOI18N
237 * Allows the user to change his/her own data
240 public void doChangeOwnData () throws IOException, SQLException, NoSuchMethodException, IllegalAccessException, InvocationTargetException{
242 this.getLogger().trace("CALLED!"); //NOI18N
245 * First check if the user has registered own contact, before that
246 * nothing can be changed.
248 if (!this.isOwnContactAdded()) {
250 this.getClient().outputMessage("Sie haben noch nicht Ihre Daten eingegeben."); //NOI18N
252 // Skip any below code
257 Contact contact = this.getOwnContact();
260 assert (contact instanceof Contact);
263 contact.show(this.getClient());
265 // Get and cast client instance
266 AddressbookClient client = (AddressbookClient) this.getClient();
269 // Ask user what to change
270 client.userChooseChangeContactData(contact);
271 } catch (final UnhandledUserChoiceException ex) {
272 this.getLogger().catching(ex);
276 this.getLogger().trace("EXIT!"); //NOI18N
280 * Let the user delete other address
283 public void doDeleteOtherAddress () {
284 throw new UnsupportedOperationException("Not supported yet."); //NOI18N
288 * Asks user for own data
291 public void doEnterOwnData () throws ContactAlreadyAddedException, IOException {
293 this.getLogger().trace("CALLED!"); //NOI18N
295 // Is own contact already added?
296 if (this.isOwnContactAdded()) {
297 // Don't continue here
298 throw new ContactAlreadyAddedException();
301 // Get and cast client instance
302 AddressbookClient client = (AddressbookClient) this.getClient();
304 // Deligate this call to the client
305 Contact contact = client.doEnterOwnData();
308 if (contact instanceof Contact) {
309 // Add it to contact "book"
310 this.registerContact(contact);
314 this.getLogger().trace("EXIT!"); //NOI18N
318 public void doListContacts () {
319 throw new UnsupportedOperationException("Not supported yet."); //NOI18N
323 public void doSearchContacts () {
324 throw new UnsupportedOperationException("Not supported yet."); //NOI18N
328 * Shuts down this contact manager
330 * @throws java.sql.SQLException If an SQL error occurs
331 * @throws java.io.IOException If an IO error occurs
334 public void doShutdown () throws SQLException, IOException {
336 this.getLogger().trace("CALLED!"); //NOI18N
338 // Shut down the database layer
339 ((AddressbookContactFrontend) this.getFrontend()).doShutdown();
342 this.getLogger().trace("EXIT!"); //NOI18N
346 * Asks the user for his/her cellphone number
348 * @return User's cellphone number
351 public String enterOwnCellNumber () {
353 this.getLogger().trace("CALLED!"); //NOI18N
355 // Get and cast client instance
356 AddressbookClient client = (AddressbookClient) this.getClient();
358 return client.enterString(5, 30, "Bitte geben Sie Ihre Handynummer an: ", true);
362 * Asks the user for his/her city's name
364 * @return City's name of the user
367 public String enterOwnCity () {
369 this.getLogger().trace("CALLED!"); //NOI18N
371 // Get and cast client instance
372 AddressbookClient client = (AddressbookClient) this.getClient();
374 return client.enterString(3, 50, "Bitte geben Sie Ihre Wohnort ein: ", false);
378 * Asks the user for his/her city's name
380 * @return City's name of the user
383 public String enterOwnComment () {
385 this.getLogger().trace("CALLED!"); //NOI18N
387 // Get and cast client instance
388 AddressbookClient client = (AddressbookClient) this.getClient();
390 return client.enterString(0, 100, "Kommentar zu Ihrem Eintrag: ", true);
394 * Asks the user for his/her company name
396 * @return User's company name
399 public String enterOwnCompanyName () {
401 this.getLogger().trace("CALLED!"); //NOI18N
403 // Get and cast client instance
404 AddressbookClient client = (AddressbookClient) this.getClient();
406 return client.enterString(5, 50, "Bitte geben Sie Ihre Firmenbezeichnung ein: ", true);
410 * Asks user for his/her own country code
412 * @return User's own country code
415 public String enterOwnCountryCode () {
417 this.getLogger().trace("CALLED!"); //NOI18N
419 // Get and cast client instance
420 AddressbookClient client = (AddressbookClient) this.getClient();
422 return client.enterString(2, 2, "Bitte geben Sie den zweistelligen Ländercode von Ihrem Land ein: ", false).toUpperCase();
426 * Asks user for his/her own country code
428 * @return User's own country code
431 public String enterOwnEmailAddress () {
433 this.getLogger().trace("CALLED!"); //NOI18N
435 // Get and cast client instance
436 AddressbookClient client = (AddressbookClient) this.getClient();
438 return client.enterString(10, 50, "Bitte geben Sie Ihre Email-Adresse ein: ", true);
442 * Asks the user for family name
444 * @return Family name of the user
447 public String enterOwnFamilyName () {
449 this.getLogger().trace("CALLED!"); //NOI18N
451 // Get and cast client instance
452 AddressbookClient client = (AddressbookClient) this.getClient();
454 return client.enterString(2, 50, "Bitte geben Sie Ihren Nachnamen ein: ", false);
458 * Asks the user for family name
460 * @return Family name of the user
463 public String enterOwnFaxNumber () {
465 this.getLogger().trace("CALLED!"); //NOI18N
467 // Get and cast client instance
468 AddressbookClient client = (AddressbookClient) this.getClient();
470 return client.enterString(5, 30, "Bitte geben Sie Ihre Faxnummer an: ", true);
474 * Asks the user for surname
476 * @return Surname of the user
479 public String enterOwnFirstName () {
481 this.getLogger().trace("CALLED!"); //NOI18N
483 // Get and cast client instance
484 AddressbookClient client = (AddressbookClient) this.getClient();
486 return client.enterString(2, 50, "Bitte geben Sie Ihren Vornamen ein: ", false);
490 * Asks the user for gender, until a valid has been entered
492 * @return Gender of the user
495 public Gender enterOwnGender () {
497 this.getLogger().trace("CALLED!"); //NOI18N
499 // Get and cast client instance
500 AddressbookClient client = (AddressbookClient) this.getClient();
502 return client.enterGender("Bitte geben Sie die Anrede ein: (M=Herr, F=Frau, C=Firma): ");
506 * Asks the user for phone number
508 * @return Phone number of the user
511 public String enterOwnPhoneNumber () {
513 this.getLogger().trace("CALLED!"); //NOI18N
515 // Get and cast client instance
516 AddressbookClient client = (AddressbookClient) this.getClient();
518 return client.enterString(5, 30, "Bitte geben Sie Ihre Telefonnummer an: ", true);
522 * Asks the user for own street (including number)
524 * @return Own street an number
527 public String enterOwnStreet () {
529 this.getLogger().trace("CALLED!"); //NOI18N
531 // Get and cast client instance
532 AddressbookClient client = (AddressbookClient) this.getClient();
534 return client.enterString(5, 50, "Bitte geben Sie Ihre Strasse und Hausnummer ein: ", false);
538 * Asks the user for own ZIP code
543 public int enterOwnZipCode () {
545 this.getLogger().trace("CALLED!"); //NOI18N
547 // Get and cast client instance
548 AddressbookClient client = (AddressbookClient) this.getClient();
550 return client.enterInt(0, 99_999, "Bitte geben Sie Ihre Postleitzahl ein: ");
554 public final int getColumnCount () {
555 assert (this.columnNames instanceof List) : "this.columnNames is not initialized"; //NOI18N
557 return this.columnNames.size();
561 public String getColumnName (final int columnIndex) {
562 assert (this.columnNames instanceof List) : "this.columnNames is not initialized"; //NOI18N
564 // Get column name at index
565 return this.columnNames.get(columnIndex);
569 public String getTranslatedColumnName (final int columnIndex) {
570 assert (this.translatedColumnNames instanceof List) : "this.translatedColumnNames is not initialized"; //NOI18N
572 // Get column name at index
573 return this.translatedColumnNames.get(columnIndex);
577 public Object getValueFromRowColumn (final int rowIndex, final int columnIndex) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
579 this.getLogger().trace(MessageFormat.format("rowIndex={0},columnIndex={1} CALLED!", rowIndex, columnIndex)); //NOI18N
581 // Then get specific row from database which is a Contact instance
582 Storable storable = this.getFrontend().getStorableAtRow(rowIndex);
585 this.getLogger().debug(MessageFormat.format("storable={0}", storable)); //NOI18N
587 // It may return null
588 if (null == storable) {
590 this.getLogger().warn("contact is null - returning null ..."); //NOI18N
594 // Convert column index -> name
595 String columnName = this.getColumnName(columnIndex);
598 this.getLogger().debug(MessageFormat.format("columnName={0}", columnName)); //NOI18N
600 // Now get that column
603 value = storable.getValueFromColumn(columnName);
604 } catch (final IllegalArgumentException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ex) {
605 this.abortProgramWithException(ex);
609 this.getLogger().trace(MessageFormat.format("value={0} - EXIT!", value)); //NOI18N
616 * Checks whether own contact is already added by checking all entries for
619 * @return Whether own contact is already added
622 public boolean isOwnContactAdded () throws IOException {
624 this.getLogger().trace("CALLED!"); //NOI18N
627 boolean isAdded = false;
630 // Deligate this call to frontend
631 isAdded = ((AddressbookContactFrontend) this.getFrontend()).isOwnContactFound();
632 } catch (final SQLException | IOException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ex) {
633 // Something bad happened
634 this.abortProgramWithException(ex);
638 this.getLogger().trace(MessageFormat.format("isAdded={0} : EXIT!", isAdded)); //NOI18N
645 * Adds given contact to address book and flushes all entries to database
647 * @param contact Contact being added
648 * TODO Add check for book size
651 public void registerContact (final Contact contact) {
653 this.getLogger().trace(MessageFormat.format("contact={0} CALLED!", contact)); //NOI18N
656 if (null == contact) {
658 throw new NullPointerException("contact is null"); //NOI18N
662 /* NOISY-DEBUG: */ this.getLogger().debug(MessageFormat.format("Adding '{0}' '{1}' at pos '{2}' ...", contact.getFirstName(), contact.getFamilyName(), this.size())); //NOI18N
664 // Check if contact is found
665 if (((AddressbookContactFrontend) this.getFrontend()).isContactFound(contact)) {
666 // Contact already added
667 // TODO Do something here
668 } else if ((contact.isOwnContact()) && (this.isOwnContactAdded())) {
669 // Own contact already added
673 // Add contact to internal list
674 this.addContact(contact);
675 } catch (final ContactAlreadyAddedException | SQLException | IOException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ex) {
677 this.abortProgramWithException(ex);
681 this.getLogger().trace("EXIT!"); //NOI18N
685 public final int size () throws IOException {
690 size = ((AddressbookContactFrontend) this.getFrontend()).getContactsCount();
691 } catch (final SQLException ex) {
692 // Something happened
693 this.abortProgramWithException(ex);
701 * Fills the column names array with strings from bundle
703 private void fillColumnNamesFromBundle () {
704 assert (this.columnNames instanceof List) : "this.columnNames is not initialized"; //NOI18N
705 assert (this.translatedColumnNames instanceof List) : "this.translatedColumnNames is not initialized"; //NOI18N
708 this.getLogger().trace("CALLED!"); //NOI18N
710 // First get an iterator from key set to iterate over
711 Iterator<String> iterator = this.getBundle().keySet().iterator();
713 // Then iterate over all
714 while (iterator.hasNext()) {
716 String key = iterator.next().toLowerCase();
718 // Does the key start with AddressbookContactManager.columnName ?
719 if (key.startsWith("ContactManager.columnName")) { //NOI18N
720 // This is the wanted entry.
721 this.getLogger().debug(MessageFormat.format("key={0}", key)); //NOI18N
723 // Convert string to array based on delimiter '.'
724 String[] tokens = this.getArrayFromString(key, "."); //NOI18N
726 // Token array must contain 4 elements (AddressbookContactManager.columnName.foo.text)
727 assert(tokens.length == 4) : MessageFormat.format("Array tokens contains not 4 elements: {0}", Arrays.toString(tokens)); //NOI18N
729 // Get pre-last element
730 String columnName = tokens[tokens.length - 2];
733 this.getLogger().debug(MessageFormat.format("columnName={0} - adding ...", columnName)); //NOI18N
736 this.columnNames.add(columnName);
737 this.translatedColumnNames.add(this.getBundle().getString(key));
742 this.getLogger().trace(MessageFormat.format("getColumnCount()={0}: EXIT!", this.getColumnCount())); //NOI18N
746 * "Getter" for own contact instance or null if not found
748 * @return Contact instance or null
749 * @throws java.sql.SQLException If an SQL error occurs
750 * @throws java.io.IOException If an IO error occurs
751 * @throws java.lang.NoSuchMethodException If a method cannot be found
752 * @throws java.lang.IllegalAccessException If a method is not accessible
753 * @throws java.lang.reflect.InvocationTargetException Any other problems?
755 private Contact getOwnContact () throws IOException, SQLException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
757 this.getLogger().trace("CALLED!"); //NOI18N
759 // Deligate this call to database frontend
760 Contact contact = ((AddressbookContactFrontend) this.getFrontend()).getOwnContact();
763 this.getLogger().trace(MessageFormat.format("contact={0} - EXIT!", contact)); //NOI18N
765 // Return instance or null