From 3fc961ed434b91c90884c0d9914a7e93defc7e4a Mon Sep 17 00:00:00 2001 From: Roland Haeder Date: Thu, 30 Jul 2015 14:35:43 +0200 Subject: [PATCH] =?utf8?q?A=20lot=20refacturings=20...=20Signed-off-by:Rol?= =?utf8?q?and=20H=C3=A4der=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- .../addressbook/BaseFrameworkSystem.java | 170 +++++- .../addressbook/client/BaseClient.java | 10 +- .../client/console/ConsoleClient.java | 45 +- .../client/gui/AddressbookFrame.java | 9 +- .../addressbook/contact/BaseContact.java | 34 +- .../mxchange/addressbook/contact/Contact.java | 9 + .../database/backend/DatabaseBackend.java | 21 +- .../backend/csv/Base64CsvDatabaseBackend.java | 497 +++++++++++------- .../backend/mysql/MySqlDatabaseBackend.java | 25 +- .../contact/ContactDatabaseConstants.java | 35 ++ .../frontend/BaseDatabaseFrontend.java | 4 +- .../contact/ContactDatabaseFrontend.java | 153 ++++-- .../frontend/contact/ContactWrapper.java | 40 +- .../ContactAlreadyAddedException.java | 45 ++ .../addressbook/manager/BaseManager.java | 2 - .../application/ApplicationManager.java | 2 - .../manager/contact/ContactManager.java | 214 ++------ .../manager/contact/ManageableContact.java | 15 +- .../mxchange/addressbook/menu/BaseMenu.java | 1 - .../model/contact/ContactTableModel.java | 3 - 20 files changed, 857 insertions(+), 477 deletions(-) create mode 100644 Addressbook/src/org/mxchange/addressbook/database/contact/ContactDatabaseConstants.java create mode 100644 Addressbook/src/org/mxchange/addressbook/exceptions/ContactAlreadyAddedException.java diff --git a/Addressbook/src/org/mxchange/addressbook/BaseFrameworkSystem.java b/Addressbook/src/org/mxchange/addressbook/BaseFrameworkSystem.java index 333f68b..efd21ff 100644 --- a/Addressbook/src/org/mxchange/addressbook/BaseFrameworkSystem.java +++ b/Addressbook/src/org/mxchange/addressbook/BaseFrameworkSystem.java @@ -22,9 +22,12 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.text.MessageFormat; import java.util.Properties; import java.util.ResourceBundle; +import java.util.StringTokenizer; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.mxchange.addressbook.application.Application; @@ -187,7 +190,7 @@ public class BaseFrameworkSystem implements FrameworkInterface { * @param exception Exception to log */ @Override - public void logException (final Throwable exception) { + public final void logException (final Throwable exception) { // Log this exception this.getLogger().catching(exception); } @@ -274,6 +277,107 @@ public class BaseFrameworkSystem implements FrameworkInterface { this.getLogger().trace("EXIT!"); //NOI18N } + /** + * Converts a column name like "foo_bar" to an attribute name like "fooBar" + * + * @param columnName Column name to convert + * @return Attribute name + */ + protected String convertColumnNameToAttribute (final String columnName) { + // Trace message + this.getLogger().trace(MessageFormat.format("columnName={0} - CALLED!", columnName)); + + // First all lower case + String lower = columnName.toLowerCase(); + + // Then split on "_" + StringTokenizer tokenizer = new StringTokenizer(lower, "_"); + + // Resulting string + StringBuilder builder = new StringBuilder(tokenizer.countTokens()); + + // Init counter + int count = 0; + + // Walk through all + while (tokenizer.hasMoreTokens()) { + // Get token + String token = tokenizer.nextToken(); + + // Is later than first element? + if (count > 0) { + // Make first character upper-case + char c = token.charAt(0); + token = String.valueOf(c).toUpperCase() + token.substring(1); + } + + // Add token + builder.append(token); + + // Increment counter + count++; + } + + // Trace message + this.getLogger().trace(MessageFormat.format("builder={0} - EXIT!", builder)); + + // Return result + return builder.toString(); + } + + /** + * Converts a column name like "foo_bar" to a method name like "getFooBar" + * for non-booleans and to "isFooBar" for boolean fields. + * + * @param columnName Column name to convert + * @param isBool Whether the parameter is boolean + * @return Attribute name + */ + protected String convertColumnNameToGetterMethod (final String columnName, boolean isBool) { + // Trace message + this.getLogger().trace(MessageFormat.format("columnName={0} - CALLED!", columnName)); + + // First all lower case + String lower = columnName.toLowerCase(); + + // Then split on "_" + StringTokenizer tokenizer = new StringTokenizer(lower, "_"); + + // Resulting string + StringBuilder builder = new StringBuilder(tokenizer.countTokens()); + + // Is it boolean? + if (isBool) { + // Append "is" + builder.append("is"); + } else { + // Append "get" + builder.append("get"); + } + + // Walk through all + while (tokenizer.hasMoreTokens()) { + // Get token + String token = tokenizer.nextToken(); + + // Debug message + this.getLogger().debug(MessageFormat.format("token={0}", token)); + + // Make it upper-case + char c = token.charAt(0); + token = String.valueOf(c).toUpperCase() + token.substring(1); + + // Add token + builder.append(token); + } + + // Trace message + this.getLogger().trace(MessageFormat.format("builder={0} - EXIT!", builder)); + + // Return result + return builder.toString(); + } + /** * Getter for logger * @@ -289,7 +393,7 @@ public class BaseFrameworkSystem implements FrameworkInterface { * @param key Key to get * @return Propety value */ - protected String getProperty (final String key) { + protected final String getProperty (final String key) { return BaseFrameworkSystem.properties.getProperty(String.format("org.mxchange.addressbook.%s", key)); //NOI18N } @@ -310,4 +414,66 @@ public class BaseFrameworkSystem implements FrameworkInterface { protected final void setTableName (final String tableName) { this.tableName = tableName; } + + /** + * Returns boolean field value from given method call + * + * @param instance The instance to call + * @param targetClass Target class to look in + * @param methodName Method name to look for + * @return Boolean value from field + */ + @SuppressWarnings ("unchecked") + protected boolean getBooleanField (final FrameworkInterface instance, final String targetClass, final String methodName) { + // Trace messahe + this.getLogger().trace(MessageFormat.format("targetClass={0},methodName={1}", targetClass, methodName)); + + // Instance reflaction of this class + Class c = instance.getClass(); + + // Analyze class + while (!targetClass.equals(c.getSimpleName())) { + // Debug message + this.getLogger().debug("c=" + c.getSimpleName()); + + // Get super class (causes unchecked warning) + c = (Class) c.getSuperclass(); + } + + // Init field instance + Method method = null; + + // Use reflection to get all attributes + try { + method = c.getDeclaredMethod(methodName, new Class[0]); + } catch (final SecurityException ex) { + // Security problem + this.abortProgramWithException(ex); + } catch (final NoSuchMethodException ex) { + // Method not found + this.abortProgramWithException(ex); + } + + // Assert on field + assert(method instanceof Method) : "method is not a Method instance"; + + // Get value from field + boolean value = false; + + try { + value = (boolean) method.invoke(instance); + } catch (final IllegalArgumentException ex) { + // Other problem + this.abortProgramWithException(ex); + } catch (final IllegalAccessException ex) { + // Other problem + this.abortProgramWithException(ex); + } catch (final InvocationTargetException ex) { + // Other problem + this.abortProgramWithException(ex); + } + + // Return value + return value; + } } diff --git a/Addressbook/src/org/mxchange/addressbook/client/BaseClient.java b/Addressbook/src/org/mxchange/addressbook/client/BaseClient.java index 6bd281f..df1573e 100644 --- a/Addressbook/src/org/mxchange/addressbook/client/BaseClient.java +++ b/Addressbook/src/org/mxchange/addressbook/client/BaseClient.java @@ -50,8 +50,6 @@ public abstract class BaseClient extends BaseFrameworkSystem { * No instances can be created of this class */ protected BaseClient () { - super(); - // Init menu map this.menus = new HashMap<>(10); } @@ -158,17 +156,17 @@ public abstract class BaseClient extends BaseFrameworkSystem { this.getLogger().trace("CALLED!"); //NOI18N // Debug message - this.getLogger().debug("Initializing contact manager ..."); + this.getLogger().debug("Initializing contact manager ..."); //NOI18N // Init contact manager with console client // @TODO Static initial amount of contacts - ManageableContact manager = new ContactManager(100, (Client) this); + ManageableContact manager = new ContactManager((Client) this); // Set it here this.setContactManager(manager); // Debug message - this.getLogger().debug("Contact manager has been initialized."); + this.getLogger().debug("Contact manager has been initialized."); //NOI18N // Trace message this.getLogger().trace("EXIT!"); //NOI18N @@ -189,7 +187,7 @@ public abstract class BaseClient extends BaseFrameworkSystem { if (!(menu instanceof Menu)) { // Not found // @todo Own exception? - throw new NullPointerException("Menu '" + menuType + "' not found."); + throw new NullPointerException(MessageFormat.format("Menu '{0}' not found.", menuType)); //NOI18N } // Show menu diff --git a/Addressbook/src/org/mxchange/addressbook/client/console/ConsoleClient.java b/Addressbook/src/org/mxchange/addressbook/client/console/ConsoleClient.java index bbefa9e..b523a13 100644 --- a/Addressbook/src/org/mxchange/addressbook/client/console/ConsoleClient.java +++ b/Addressbook/src/org/mxchange/addressbook/client/console/ConsoleClient.java @@ -26,6 +26,7 @@ import org.mxchange.addressbook.client.Client; import org.mxchange.addressbook.contact.Contact; import org.mxchange.addressbook.contact.Gender; import org.mxchange.addressbook.contact.user.UserContact; +import org.mxchange.addressbook.exceptions.ContactAlreadyAddedException; import org.mxchange.addressbook.exceptions.UnhandledUserChoiceException; import org.mxchange.addressbook.menu.Menu; import org.mxchange.addressbook.menu.MenuTools; @@ -72,12 +73,12 @@ public class ConsoleClient extends BaseClient implements Client { @Override public void displayAddressBox (final Contact contact) { // Trace message - this.getLogger().trace("contact=" + contact + " - CALLED!"); //NOI18N + this.getLogger().trace(MessageFormat.format("contact={0} - CALLED!", contact)); //NOI18N // Is it null? if (contact == null) { // Abort here - throw new NullPointerException("contact is null"); + throw new NullPointerException("contact is null"); //NOI18N } // Simple display ... @@ -100,7 +101,7 @@ public class ConsoleClient extends BaseClient implements Client { // Is it null? if (contact == null) { // Abort here - throw new NullPointerException("contact is null"); + throw new NullPointerException("contact is null"); //NOI18N } // Get translated gender as the user may want to see "Mr.", "Mrs." @@ -136,7 +137,7 @@ public class ConsoleClient extends BaseClient implements Client { // Is it null? if (contact == null) { // Abort here - throw new NullPointerException("contact is null"); + throw new NullPointerException("contact is null"); //NOI18N } // Cellphone and such ... @@ -154,13 +155,13 @@ public class ConsoleClient extends BaseClient implements Client { // Is it null? if (contact == null) { // Abort here - throw new NullPointerException("contact is null"); + throw new NullPointerException("contact is null"); //NOI18N } // Make sure it is own contact if (!contact.isOwnContact()) { // Not own contact - throw new IllegalArgumentException("Contact is not own data."); + throw new IllegalArgumentException("Contact is not own data."); //NOI18N } // Own address data @@ -190,13 +191,13 @@ public class ConsoleClient extends BaseClient implements Client { // Is it null? if (contact == null) { // Abort here - throw new NullPointerException("contact is null"); + throw new NullPointerException("contact is null"); //NOI18N } // Make sure it is own contact if (!contact.isOwnContact()) { // Not own contact - throw new IllegalArgumentException("Contact is not own data."); + throw new IllegalArgumentException("Contact is not own data."); //NOI18N } // Gender: @@ -226,13 +227,13 @@ public class ConsoleClient extends BaseClient implements Client { // Is it null? if (contact == null) { // Abort here - throw new NullPointerException("contact is null"); + throw new NullPointerException("contact is null"); //NOI18N } // Make sure it is own contact if (!contact.isOwnContact()) { // Not own contact - throw new IllegalArgumentException("Contact is not own data."); + throw new IllegalArgumentException("Contact is not own data."); //NOI18N } // Phone number @@ -314,8 +315,14 @@ public class ConsoleClient extends BaseClient implements Client { // @TODO Rewrite this ugly switch() block switch (choice) { - case '1': // Enter/add own data - this.getContactManager().doEnterOwnData(); + case '1': + try { + // Enter/add own data + this.getContactManager().doEnterOwnData(); + } catch (final ContactAlreadyAddedException ex) { + // Already added + this.outputMessage("Sie haben bereits Ihre eigenen Daten eingegeben."); + } break; case '2': // Change own data @@ -348,7 +355,7 @@ public class ConsoleClient extends BaseClient implements Client { default: // @TODO throw own exception - throw new UnhandledUserChoiceException(MessageFormat.format("Choice '{0}' not handled yet.", choice)); + throw new UnhandledUserChoiceException(MessageFormat.format("Choice '{0}' not handled yet.", choice)); //NOI18N } // Trace message @@ -370,10 +377,10 @@ public class ConsoleClient extends BaseClient implements Client { // The validChars must not null be null and filled with at least one char if (validChars == null) { // Is null - throw new NullPointerException("validChars is null"); + throw new NullPointerException("validChars is null"); //NOI18N } else if (validChars.length == 0) { // Is not filled - throw new IllegalArgumentException("validChars is not filled."); + throw new IllegalArgumentException("validChars is not filled."); //NOI18N } char input = 0; @@ -420,10 +427,10 @@ public class ConsoleClient extends BaseClient implements Client { Gender g = Gender.fromChar(gender); // g must not be null - assert(g instanceof Gender) : "g is not set."; + assert(g instanceof Gender) : "g is not set."; //NOI18N // Trace message - this.getLogger().trace("g=" + g + " - EXIT!"); //NOI18N + this.getLogger().trace(MessageFormat.format("g={0} - EXIT!", g)); //NOI18N // Return it return g; @@ -458,7 +465,7 @@ public class ConsoleClient extends BaseClient implements Client { } // Trace message - this.getLogger().trace("input=" + input + " - EXIT!"); //NOI18N + this.getLogger().trace(MessageFormat.format("input={0} - EXIT!", input)); //NOI18N // Return it return input; @@ -558,7 +565,7 @@ public class ConsoleClient extends BaseClient implements Client { @Override public void showEntry (final SelectableMenuItem item) { // Access key then text - this.outputMessage("[" + item.getAccessKey() + "] " + item.getText()); + this.outputMessage(MessageFormat.format("[{0}] {1}", item.getAccessKey(), item.getText())); } /** diff --git a/Addressbook/src/org/mxchange/addressbook/client/gui/AddressbookFrame.java b/Addressbook/src/org/mxchange/addressbook/client/gui/AddressbookFrame.java index 06d8d02..1f9db8b 100644 --- a/Addressbook/src/org/mxchange/addressbook/client/gui/AddressbookFrame.java +++ b/Addressbook/src/org/mxchange/addressbook/client/gui/AddressbookFrame.java @@ -49,6 +49,7 @@ import org.mxchange.addressbook.application.AddressbookApplication; import org.mxchange.addressbook.client.Client; import org.mxchange.addressbook.contact.Contact; import org.mxchange.addressbook.contact.Gender; +import org.mxchange.addressbook.exceptions.ContactAlreadyAddedException; import org.mxchange.addressbook.exceptions.FrameAlreadyInitializedException; import org.mxchange.addressbook.model.contact.ContactTableModel; @@ -638,7 +639,13 @@ public class AddressbookFrame extends BaseFrameworkSystem implements ClientFrame */ @Override public void actionPerformed (final ActionEvent e) { - self.getClient().getContactManager().doEnterOwnData(); + try { + self.getClient().getContactManager().doEnterOwnData(); + } catch (final ContactAlreadyAddedException ex) { + // Already added, log away + // @TODO maybe output message here? + self.logException(ex); + } } }); diff --git a/Addressbook/src/org/mxchange/addressbook/contact/BaseContact.java b/Addressbook/src/org/mxchange/addressbook/contact/BaseContact.java index 40326c3..c6afdc9 100644 --- a/Addressbook/src/org/mxchange/addressbook/contact/BaseContact.java +++ b/Addressbook/src/org/mxchange/addressbook/contact/BaseContact.java @@ -114,7 +114,6 @@ public class BaseContact extends BaseFrameworkSystem { * No instances can be created of this class */ protected BaseContact () { - super(); } /** @@ -629,4 +628,37 @@ public class BaseContact extends BaseFrameworkSystem { protected final void setBirthday (final String birthday) { this.birthday = birthday; } + + /** + * Checks if given boolean field is available and set to same value + * + * @param columnName Column name to check + * @param bool Boolean value + * @return Whether all conditions are met + */ + public boolean isValueEqual (final String columnName, final boolean bool) { + // Trace message + this.getLogger().trace(MessageFormat.format("columnName={0},bool={1} - CALLED!", columnName, bool)); + + // Convert column name to field name + String methodName = this.convertColumnNameToGetterMethod(columnName, true); + + // Debug message + this.getLogger().debug(MessageFormat.format("field={0}", methodName)); + + // Init class instance + boolean value = this.getBooleanField(this, "BaseContact", methodName); + + // Debug message + this.getLogger().debug(MessageFormat.format("value={0}", value)); + + // Compare it + boolean isFound = (bool == value); + + // Trace message + this.getLogger().trace("isFound=" + isFound + " - EXIT!"); + + // Return result + return isFound; + } } diff --git a/Addressbook/src/org/mxchange/addressbook/contact/Contact.java b/Addressbook/src/org/mxchange/addressbook/contact/Contact.java index 57bca67..829bb45 100644 --- a/Addressbook/src/org/mxchange/addressbook/contact/Contact.java +++ b/Addressbook/src/org/mxchange/addressbook/contact/Contact.java @@ -144,6 +144,15 @@ public interface Contact extends FrameworkInterface { */ public String getComment (); + /** + * Checks if given boolean value is available and set to same value + * + * @param columnName Column name to check + * @param bool Boolean value + * @return Whether all conditions are met + */ + public boolean isValueEqual (final String columnName, final boolean bool); + /** * Shows the contact to the user * diff --git a/Addressbook/src/org/mxchange/addressbook/database/backend/DatabaseBackend.java b/Addressbook/src/org/mxchange/addressbook/database/backend/DatabaseBackend.java index a38c45b..9a66e94 100644 --- a/Addressbook/src/org/mxchange/addressbook/database/backend/DatabaseBackend.java +++ b/Addressbook/src/org/mxchange/addressbook/database/backend/DatabaseBackend.java @@ -43,6 +43,22 @@ public interface DatabaseBackend extends FrameworkInterface { */ public void doShutdown (); + /** + * Some "getter" for total table row count + * + * @return Total row count + */ + public int getTotalCount (); + + /** + * Checks whether at least one row is found with given boolean value. + * + * @param columnName Column to check for boolean value + * @param bool Boolean value to check + * @return Whether boolean value is found and returns at least one row + */ + public boolean isRowFound (final String columnName, final boolean bool); + /** * Rewinds backend */ @@ -67,8 +83,9 @@ public interface DatabaseBackend extends FrameworkInterface { * Gets an iterator for contacts * * @return Iterator for contacts - * @throws org.mxchange.addressbook.exceptions.BadTokenException If the CSV - * token is badly formulated + * @throws org.mxchange.addressbook.exceptions.BadTokenException If the CSV token is badly formulated + * @deprecated The method is to much "contact" specific */ + @Deprecated public Iterator contactIterator () throws BadTokenException; } diff --git a/Addressbook/src/org/mxchange/addressbook/database/backend/csv/Base64CsvDatabaseBackend.java b/Addressbook/src/org/mxchange/addressbook/database/backend/csv/Base64CsvDatabaseBackend.java index 4423861..12377c6 100644 --- a/Addressbook/src/org/mxchange/addressbook/database/backend/csv/Base64CsvDatabaseBackend.java +++ b/Addressbook/src/org/mxchange/addressbook/database/backend/csv/Base64CsvDatabaseBackend.java @@ -96,6 +96,7 @@ public class Base64CsvDatabaseBackend extends BaseDatabaseBackend implements Dat * underlaying method has found an invalid token */ @Override + @Deprecated public Iterator contactIterator () throws BadTokenException { // Trace message this.getLogger().trace("CALLED!"); //NOI18N @@ -136,6 +137,93 @@ public class Base64CsvDatabaseBackend extends BaseDatabaseBackend implements Dat this.getLogger().trace("EXIT!"); //NOI18N } + /** + * Some "getter" for total row count + * + * @return Total row count + */ + @Override + public int getTotalCount () { + // Trace message + this.getLogger().trace("CALLED!"); //NOI18N + + try { + // Do a deprecated call + // @todo this needs rewrite! + return this.readContactList().size(); + } catch (final BadTokenException ex) { + this.abortProgramWithException(ex); + } + + // Invalid return + this.getLogger().trace("Returning -1 ... : EXIT!"); //NOI18N + return -1; + } + + /** + * Checks whether at least one row is found with given boolean value. + * + * @param columnName Column to check for boolean value + * @param bool Boolean value to check + * @return Whether boolean value is found and returns at least one row + */ + @Override + public boolean isRowFound (final String columnName, final boolean bool) { + // Trace message + this.getLogger().trace(MessageFormat.format("columnName={0},bool={1} - CALLED!", columnName, bool)); //NOI18N + + // Is at least one entry found? + if (this.getTotalCount() == 0) { + // No entry found at all + return false; + } + + // Default is not found + boolean isFound = false; + + // Firsr rewind + this.rewind(); + + // Then loop through all lines + while (!this.isEndOfFile()) { + // Read line + String line = this.readLine(); + + // Debug message + this.getLogger().debug(MessageFormat.format("line={0}", line)); + + try { + // And parse it to a Contact instance + Contact contact = this.parseLineToContact(line); + + // Debug message + this.getLogger().debug(MessageFormat.format("contact={0}", contact)); + + // This should not be null + if (contact == null) { + // Throw exception + throw new NullPointerException("contact is null"); + } + + // Now let the contact object check if it has such attribute + if (contact.isValueEqual(columnName, bool)) { + // Yes, it is set + isFound = true; + break; + } + } catch (final BadTokenException ex) { + // Don't continue with bad data + this.abortProgramWithException(ex); + } + } + + // Trace message + this.getLogger().trace(MessageFormat.format("isFound={0} - EXIT!", isFound)); + + // Return result + return isFound; + } + /** * Get length of underlaying file * @@ -193,7 +281,7 @@ public class Base64CsvDatabaseBackend extends BaseDatabaseBackend implements Dat // Object must not be null if (object == null) { // Abort here - throw new NullPointerException("object is null"); + throw new NullPointerException("object is null"); //NOI18N } // Make sure the instance is there (DataOutput flawor) @@ -290,30 +378,15 @@ public class Base64CsvDatabaseBackend extends BaseDatabaseBackend implements Dat } /** - * Reads the database file, if available, and adds all read lines into the - * list. + * Parses given line and creates a Contact instance + * + * @param line Raw line to parse * - * @return A list with Contact instances + * @return Contact instance */ - private List readContactList () throws BadTokenException { - this.getLogger().trace("CALLED!"); //NOI18N - - // First rewind - this.rewind(); - - // Get file size and divide it by 140 (possible average length of one line) - int lines = Math.round(this.length() / 140 + 0.5f); - - // Debug message - this.getLogger().debug(MessageFormat.format("lines={0}", lines)); //NOI18N - - // Instance list - // @TODO The maximum length could be guessed from file size? - List list = new ArrayList<>(lines); - - // Init variables - StringTokenizer tokenizer; - String line; + private Contact parseLineToContact (final String line) throws BadTokenException { + // Trace message + this.getLogger().trace(MessageFormat.format("line={0} - CALLED!", line)); //NOI18N // Init A lot variables Long num = null; @@ -322,235 +395,273 @@ public class Base64CsvDatabaseBackend extends BaseDatabaseBackend implements Dat int count = 0; Contact contact = null; - // Read all lines - while (!this.isEndOfFile()) { - // Then read a line - line = this.readLine(); + // Debug message + this.getLogger().debug(MessageFormat.format("line={0}", line)); //NOI18N - // Debug message - this.getLogger().debug(MessageFormat.format("line={0}", line)); //NOI18N + // Then tokenize it + // @TODO Move this into separate method + StringTokenizer tokenizer = new StringTokenizer(line, ";"); //NOI18N - // Then tokenize it - // @TODO Move this into separate method - tokenizer = new StringTokenizer(line, ";"); //NOI18N + // Reset variables + count = 0; + contact = null; + // The tokens are now available, so get all + while (tokenizer.hasMoreElements()) { // Reset variables - count = 0; - contact = null; - - // The tokens are now available, so get all - while (tokenizer.hasMoreElements()) { - // Reset variables - num = null; - bool = null; - - // Get next token - String token = tokenizer.nextToken(); - - // If char " is at pos 2 (0,1,2), then cut it of there - if ((token.charAt(0) != '"') && (token.charAt(2) == '"')) { - // UTF-8 writer characters found - token = token.substring(2); - } + num = null; + bool = null; - // Debug message - this.getLogger().debug(MessageFormat.format("token={0}", token)); //NOI18N + // Get next token + String token = tokenizer.nextToken(); - // Verify token, it must have double-quotes on each side - if ((!token.startsWith("\"")) || (!token.endsWith("\""))) { //NOI18N - // Something bad was read - throw new BadTokenException(token, count); //NOI18N - } + // If char " is at pos 2 (0,1,2), then cut it of there + if ((token.charAt(0) != '"') && (token.charAt(2) == '"')) { + // UTF-8 writer characters found + token = token.substring(2); + } - // All fine, so remove it - String strippedToken = token.substring(1, token.length() - 1); + // Debug message + this.getLogger().debug(MessageFormat.format("token={0}", token)); //NOI18N - // Is the string's content "null"? - if (strippedToken.equals("null")) { //NOI18N - // Debug message - this.getLogger().debug(MessageFormat.format("strippedToken={0} - NULL!", strippedToken)); //NOI18N + // Verify token, it must have double-quotes on each side + if ((!token.startsWith("\"")) || (!token.endsWith("\""))) { //NOI18N + // Something bad was read + throw new BadTokenException(token, count); //NOI18N + } - // This needs to be set to null - strippedToken = null; - } + // All fine, so remove it + String strippedToken = token.substring(1, token.length() - 1); + // Is the string's content "null"? + if (strippedToken.equals("null")) { //NOI18N // Debug message - this.getLogger().debug(MessageFormat.format("strippedToken={0}", strippedToken)); //NOI18N + this.getLogger().debug(MessageFormat.format("strippedToken={0} - NULL!", strippedToken)); //NOI18N - // Now, let's try a number check, if no null - if (strippedToken != null) { - // Okay, no null, maybe the string bears a decimal number? - try { - num = Long.valueOf(strippedToken); + // This needs to be set to null + strippedToken = null; + } - // Debug message - this.getLogger().debug(MessageFormat.format("strippedToken={0} - NUMBER!", strippedToken)); //NOI18N - } catch (final NumberFormatException ex) { - // No number, then set default - num = null; - } - } + // Debug message + this.getLogger().debug(MessageFormat.format("strippedToken={0}", strippedToken)); //NOI18N - // Now, let's try a boolean check, if no null - if ((strippedToken != null) && (num == null) && ((strippedToken.equals("true")) || (strippedToken.equals("false")))) { //NOI18N - // Debug message - this.getLogger().debug(MessageFormat.format("strippedToken={0} - BOOLEAN!", strippedToken)); //NOI18N + // Now, let's try a number check, if no null + if (strippedToken != null) { + // Okay, no null, maybe the string bears a decimal number? + try { + num = Long.valueOf(strippedToken); - // parseBoolean() is relaxed, so no exceptions - bool = Boolean.valueOf(strippedToken); + // Debug message + this.getLogger().debug(MessageFormat.format("strippedToken={0} - NUMBER!", strippedToken)); //NOI18N + } catch (final NumberFormatException ex) { + // No number, then set default + num = null; } + } + // Now, let's try a boolean check, if no null + if ((strippedToken != null) && (num == null) && ((strippedToken.equals("true")) || (strippedToken.equals("false")))) { //NOI18N // Debug message - this.getLogger().debug(MessageFormat.format("strippedToken={0},num={1},bool={2}", strippedToken, num, bool)); //NOI18N + this.getLogger().debug(MessageFormat.format("strippedToken={0} - BOOLEAN!", strippedToken)); //NOI18N - // Now, let's try a gender check, if no null - if ((strippedToken != null) && (num == null) && (bool == null) && ((strippedToken.equals("M")) || (strippedToken.equals("F")) || (strippedToken.equals("C")))) { //NOI18N - // Get first character - gender = Gender.fromChar(strippedToken.charAt(0)); + // parseBoolean() is relaxed, so no exceptions + bool = Boolean.valueOf(strippedToken); + } - // Debug message - this.getLogger().debug(MessageFormat.format("strippedToken={0},gender={1}", strippedToken, gender)); //NOI18N + // Debug message + this.getLogger().debug(MessageFormat.format("strippedToken={0},num={1},bool={2}", strippedToken, num, bool)); //NOI18N - // This instance must be there - assert (gender instanceof Gender) : "gender is not set by Gender.fromChar(" + strippedToken + ")"; //NOI18N - } + // Now, let's try a gender check, if no null + if ((strippedToken != null) && (num == null) && (bool == null) && ((strippedToken.equals("M")) || (strippedToken.equals("F")) || (strippedToken.equals("C")))) { //NOI18N + // Get first character + gender = Gender.fromChar(strippedToken.charAt(0)); - // Now it depends on the counter which position we need to check - switch (count) { - case 0: // isOwnContact - assert ((bool instanceof Boolean)); + // Debug message + this.getLogger().debug(MessageFormat.format("strippedToken={0},gender={1}", strippedToken, gender)); //NOI18N - // Debug message - this.getLogger().debug(MessageFormat.format("bool={0}", bool)); //NOI18N + // This instance must be there + assert (gender instanceof Gender) : MessageFormat.format("gender is not set by Gender.fromChar({0})", strippedToken); //NOI18N + } - // Is it own contact? - if (true == bool) { - // Debug message - this.getLogger().debug("Creating UserContact object ..."); //NOI18N + // Now it depends on the counter which position we need to check + switch (count) { + case 0: // isOwnContact + assert ((bool instanceof Boolean)); - // Own entry - contact = new UserContact(); - } else { - // Debug message - this.getLogger().debug("Creating BookContact object ..."); //NOI18N + // Debug message + this.getLogger().debug(MessageFormat.format("bool={0}", bool)); //NOI18N - // Other contact - contact = new BookContact(); - } - break; + // Is it own contact? + if (true == bool) { + // Debug message + this.getLogger().debug("Creating UserContact object ..."); //NOI18N - case 1: // Gender - assert (contact instanceof Contact) : "First token was not boolean"; //NOI18N + // Own entry + contact = new UserContact(); + } else { + // Debug message + this.getLogger().debug("Creating BookContact object ..."); //NOI18N + + // Other contact + contact = new BookContact(); + } + break; - // Update data - contact.updateNameData(gender, null, null, null); - break; + case 1: // Gender + assert (contact instanceof Contact) : "First token was not boolean"; //NOI18N - case 2: // Surname - assert (contact instanceof Contact) : "First token was not boolean"; //NOI18N - assert (gender instanceof Gender) : "gender instance is not set"; //NOI18N + // Update data + contact.updateNameData(gender, null, null, null); + break; - // Update data - contact.updateNameData(gender, strippedToken, null, null); - break; + case 2: // Surname + assert (contact instanceof Contact) : "First token was not boolean"; //NOI18N + assert (gender instanceof Gender) : "gender instance is not set"; //NOI18N - case 3: // Family name - assert (contact instanceof Contact) : "First token was not boolean"; //NOI18N - assert (gender instanceof Gender) : "gender instance is not set"; //NOI18N + // Update data + contact.updateNameData(gender, strippedToken, null, null); + break; - // Update data - contact.updateNameData(gender, null, strippedToken, null); - break; + case 3: // Family name + assert (contact instanceof Contact) : "First token was not boolean"; //NOI18N + assert (gender instanceof Gender) : "gender instance is not set"; //NOI18N - case 4: // Company name - assert (contact instanceof Contact) : "First token was not boolean"; //NOI18N - assert (gender instanceof Gender) : "gender instance is not set"; //NOI18N + // Update data + contact.updateNameData(gender, null, strippedToken, null); + break; - // Update data - contact.updateNameData(gender, null, null, strippedToken); - break; + case 4: // Company name + assert (contact instanceof Contact) : "First token was not boolean"; //NOI18N + assert (gender instanceof Gender) : "gender instance is not set"; //NOI18N - case 5: // Street number - assert (contact instanceof Contact) : "First token was not boolean"; //NOI18N + // Update data + contact.updateNameData(gender, null, null, strippedToken); + break; - // Update data - contact.updateAddressData(strippedToken, 0, null, null); - break; + case 5: // Street number + assert (contact instanceof Contact) : "First token was not boolean"; //NOI18N - case 6: // ZIP code - assert (contact instanceof Contact) : "First token was not boolean"; //NOI18N + // Update data + contact.updateAddressData(strippedToken, 0, null, null); + break; - // Update data - contact.updateAddressData(null, num, null, null); - break; + case 6: // ZIP code + assert (contact instanceof Contact) : "First token was not boolean"; //NOI18N - case 7: // City name - assert (contact instanceof Contact) : "First token was not boolean"; //NOI18N + // Update data + contact.updateAddressData(null, num, null, null); + break; - // Update data - contact.updateAddressData(null, 0, strippedToken, null); - break; + case 7: // City name + assert (contact instanceof Contact) : "First token was not boolean"; //NOI18N - case 8: // Country code - assert (contact instanceof Contact) : "First token was not boolean"; //NOI18N + // Update data + contact.updateAddressData(null, 0, strippedToken, null); + break; - // Update data - contact.updateAddressData(null, 0, null, strippedToken); - break; + case 8: // Country code + assert (contact instanceof Contact) : "First token was not boolean"; //NOI18N - case 9: // Phone number - assert (contact instanceof Contact) : "First token was not boolean"; //NOI18N + // Update data + contact.updateAddressData(null, 0, null, strippedToken); + break; - // Update data - contact.updateOtherData(strippedToken, null, null, null, null, null); - break; + case 9: // Phone number + assert (contact instanceof Contact) : "First token was not boolean"; //NOI18N - case 10: // Fax number - assert (contact instanceof Contact) : "First token was not boolean"; //NOI18N + // Update data + contact.updateOtherData(strippedToken, null, null, null, null, null); + break; - // Update data - contact.updateOtherData(null, strippedToken, null, null, null, null); - break; + case 10: // Fax number + assert (contact instanceof Contact) : "First token was not boolean"; //NOI18N - case 11: // Cellphone number - assert (contact instanceof Contact) : "First token was not boolean"; //NOI18N + // Update data + contact.updateOtherData(null, strippedToken, null, null, null, null); + break; - // Update data - contact.updateOtherData(null, null, strippedToken, null, null, null); - break; + case 11: // Cellphone number + assert (contact instanceof Contact) : "First token was not boolean"; //NOI18N - case 12: // Email address - assert (contact instanceof Contact) : "First token was not boolean"; //NOI18N + // Update data + contact.updateOtherData(null, null, strippedToken, null, null, null); + break; - // Update data - contact.updateOtherData(null, null, null, strippedToken, null, null); - break; + case 12: // Email address + assert (contact instanceof Contact) : "First token was not boolean"; //NOI18N - case 13: // Birthday - assert (contact instanceof Contact) : "First token was not boolean"; //NOI18N + // Update data + contact.updateOtherData(null, null, null, strippedToken, null, null); + break; - // Update data - contact.updateOtherData(null, null, null, null, strippedToken, null); - break; + case 13: // Birthday + assert (contact instanceof Contact) : "First token was not boolean"; //NOI18N - case 14: // Birthday - assert (contact instanceof Contact) : "First token was not boolean"; //NOI18N + // Update data + contact.updateOtherData(null, null, null, null, strippedToken, null); + break; - // Update data - contact.updateOtherData(null, null, null, null, null, strippedToken); - break; + case 14: // Birthday + assert (contact instanceof Contact) : "First token was not boolean"; //NOI18N - default: // New data entry - this.getLogger().warn(MessageFormat.format("Will not handle unknown data {0} at index {1}", strippedToken, count)); //NOI18N - break; - } + // Update data + contact.updateOtherData(null, null, null, null, null, strippedToken); + break; - // Increment counter for next round - count++; + default: // New data entry + this.getLogger().warn(MessageFormat.format("Will not handle unknown data {0} at index {1}", strippedToken, count)); //NOI18N + break; } + // Increment counter for next round + count++; + } + + // Trace message + this.getLogger().trace(MessageFormat.format("contact={0} - EXIT!", contact)); //NOI18N + + // Return finished instance + return contact; + } + + /** + * Reads the database file, if available, and adds all read lines into the + * list. + * + * @return A list with Contact instances + * @deprecated Is to much "contacts" specific + */ + @Deprecated + private List readContactList () throws BadTokenException { + this.getLogger().trace("CALLED!"); //NOI18N + + // First rewind + this.rewind(); + + // Get file size and divide it by 140 (possible average length of one line) + int lines = Math.round(this.length() / 140 + 0.5f); + + // Debug message + this.getLogger().debug(MessageFormat.format("lines={0}", lines)); //NOI18N + + // Instance list + // @TODO The maximum length could be guessed from file size? + List list = new ArrayList<>(lines); + + // Init variables + String line; + Contact contact = null; + + // Read all lines + while (!this.isEndOfFile()) { + // Then read a line + line = this.readLine(); + + // Parse line + contact = this.parseLineToContact(line); + // The contact instance should be there now - assert (contact instanceof Contact) : "contact is not set: " + contact; //NOI18N + assert (contact instanceof Contact) : MessageFormat.format("contact is not set: {0}", contact); //NOI18N // Add contact this.addContactToList(contact, list); diff --git a/Addressbook/src/org/mxchange/addressbook/database/backend/mysql/MySqlDatabaseBackend.java b/Addressbook/src/org/mxchange/addressbook/database/backend/mysql/MySqlDatabaseBackend.java index 89e4c0d..8845521 100644 --- a/Addressbook/src/org/mxchange/addressbook/database/backend/mysql/MySqlDatabaseBackend.java +++ b/Addressbook/src/org/mxchange/addressbook/database/backend/mysql/MySqlDatabaseBackend.java @@ -89,6 +89,7 @@ public class MySqlDatabaseBackend extends BaseDatabaseBackend implements Databas } @Override + @Deprecated public Iterator contactIterator () throws BadTokenException { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } @@ -107,10 +108,32 @@ public class MySqlDatabaseBackend extends BaseDatabaseBackend implements Databas } @Override - public long length () { + public int getTotalCount () { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + /** + * Checks whether at least one row is found with given boolean value. + * + * @param columnName Column to check for boolean value + * @param bool Boolean value to check + * @return Whether boolean value is found and returns at least one row + */ + @Override + public boolean isRowFound (final String columnName, final boolean bool) { + // Is at least one entry found? + if (this.getTotalCount() == 0) { + // No entry found at all + return false; + } throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } + @Override + public long length () { + throw new UnsupportedOperationException("Not implemented for this backend."); //NOI18N + } + @Override public void rewind () { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. diff --git a/Addressbook/src/org/mxchange/addressbook/database/contact/ContactDatabaseConstants.java b/Addressbook/src/org/mxchange/addressbook/database/contact/ContactDatabaseConstants.java new file mode 100644 index 0000000..f42a164 --- /dev/null +++ b/Addressbook/src/org/mxchange/addressbook/database/contact/ContactDatabaseConstants.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2015 Roland Haeder + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.mxchange.addressbook.database.contact; + +/** + * A placeholder for some data + * + * @author Roland Haeder + */ +public final class ContactDatabaseConstants { + /** + * Column own_contact + */ + public static final String COLUMN_NAME_OWN_CONTACT = "own_contact"; //NOI18N + + /** + * No instances are allowed as this class only holds static attributes + */ + private ContactDatabaseConstants () { + } +} diff --git a/Addressbook/src/org/mxchange/addressbook/database/frontend/BaseDatabaseFrontend.java b/Addressbook/src/org/mxchange/addressbook/database/frontend/BaseDatabaseFrontend.java index fb7818f..3873ef6 100644 --- a/Addressbook/src/org/mxchange/addressbook/database/frontend/BaseDatabaseFrontend.java +++ b/Addressbook/src/org/mxchange/addressbook/database/frontend/BaseDatabaseFrontend.java @@ -81,11 +81,11 @@ public class BaseDatabaseFrontend extends BaseFrameworkSystem { case "mysql": // MySQL backend, this requires more information //NOI18N this.backend = new MySqlDatabaseBackend(this.getTableName()); break; - + case "base64csv": // BASE64-encoded CSV rows //NOI18N this.backend = new Base64CsvDatabaseBackend(this.getTableName()); break; - + default: // Unsupported throw new UnsupportedDatabaseBackendException(backendType); } diff --git a/Addressbook/src/org/mxchange/addressbook/database/frontend/contact/ContactDatabaseFrontend.java b/Addressbook/src/org/mxchange/addressbook/database/frontend/contact/ContactDatabaseFrontend.java index d02d739..2f4edd0 100644 --- a/Addressbook/src/org/mxchange/addressbook/database/frontend/contact/ContactDatabaseFrontend.java +++ b/Addressbook/src/org/mxchange/addressbook/database/frontend/contact/ContactDatabaseFrontend.java @@ -20,11 +20,12 @@ import java.io.IOException; import java.sql.SQLException; import java.text.MessageFormat; import java.util.Iterator; -import java.util.List; import org.mxchange.addressbook.contact.Contact; +import org.mxchange.addressbook.database.contact.ContactDatabaseConstants; import org.mxchange.addressbook.database.frontend.BaseDatabaseFrontend; import org.mxchange.addressbook.database.storage.Storeable; import org.mxchange.addressbook.exceptions.BadTokenException; +import org.mxchange.addressbook.exceptions.ContactAlreadyAddedException; import org.mxchange.addressbook.exceptions.UnsupportedDatabaseBackendException; import org.mxchange.addressbook.manager.contact.ContactManager; @@ -38,7 +39,7 @@ public class ContactDatabaseFrontend extends BaseDatabaseFrontend implements Con /** * Constructor which accepts a contact manager * - * @param manager + * @param manager Manager instance */ public ContactDatabaseFrontend (final ContactManager manager) { // Call own constructor @@ -61,8 +62,6 @@ public class ContactDatabaseFrontend extends BaseDatabaseFrontend implements Con * Basic constrcutor */ protected ContactDatabaseFrontend () { - super(); - // Trace message this.getLogger().trace("CALLED!"); //NOI18N @@ -82,86 +81,136 @@ public class ContactDatabaseFrontend extends BaseDatabaseFrontend implements Con } /** - * Shuts down the database layer + * Adds given contact instance to database + * + * @param contact Contact instance + * @throws org.mxchange.addressbook.exceptions.ContactAlreadyAddedException If the contact instance is already found */ @Override - public void doShutdown () { + public void addContact (final Contact contact) throws ContactAlreadyAddedException { // Trace message this.getLogger().trace("CALLED!"); //NOI18N - // Shutdown backend - this.getBackend().doShutdown(); + // Make sure the contact is set + if (contact == null) { + // Abort here + throw new NullPointerException("contact is null"); //NOI18N + } + + try { + // First check if the contact is there + if (this.isContactFound(contact)) { + // Already there + throw new ContactAlreadyAddedException(contact); + } + + // Then add it + this.getBackend().store((Storeable) contact); + } catch (final IOException ex) { + // Abort here + this.abortProgramWithException(ex); + } catch (final BadTokenException ex) { + // Abort here + this.abortProgramWithException(ex); + } // Trace message - this.getLogger().trace("EXIT!"); //NOI18N + this.getLogger().trace("CALLED!"); //NOI18N } /** - * Flushes all contact entries to database + * Shuts down the database layer */ @Override - public void flushAllContacts () { + public void doShutdown () { // Trace message this.getLogger().trace("CALLED!"); //NOI18N - // Get full list - List contacts = this.getContactManager().getList(); - - // Get iterator - Iterator iterator = contacts.iterator(); - - // Rewind backend - this.getBackend().rewind(); - - // Get all entries - while (iterator.hasNext()) { - // Get next entry - Contact contact = iterator.next(); - - try { - // Store this entry - this.getBackend().store((Storeable) contact); - } catch (final IOException ex) { - // Should not happen? - this.abortProgramWithException(ex); - } - } + // Shutdown backend + this.getBackend().doShutdown(); // Trace message this.getLogger().trace("EXIT!"); //NOI18N } /** - * Reads all contacts from database backend and handles them over to the - * contact manager + * Some "getter" for total contact count + * + * @return Total contact count */ @Override - public void readAllContacts () { + public int getContactsCount () { + // And deligate to backend + return this.getBackend().getTotalCount(); //NOI18N + } + + /** + * Some "getter" for own contact instance + * + * @return Own contact instance + */ + @Override + public Contact getOwnContact () { // Trace message this.getLogger().trace("CALLED!"); //NOI18N - // First rewind to beginning - this.getBackend().rewind(); + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } - // Get backend iterator - Iterator iterator = null; - try { - iterator = this.getBackend().contactIterator(); - } catch (final BadTokenException ex) { - // Abort program - this.abortProgramWithException(ex); + /** + * Checks if given Contact is found + * + * @param contact Contact instance to check + * @return Whether the given Contact instance is found + */ + @Override + public boolean isContactFound (final Contact contact) throws BadTokenException { + // Trace message + this.getLogger().trace(MessageFormat.format("contact={0} - CALLED!", contact)); //NOI18N + + // contact should not be null + if (contact == null) { + // Abort here + throw new NullPointerException("contact is null"); //NOI18N } - // Read all entries - while ((iterator instanceof Iterator) && (iterator.hasNext())) { - // Get next entry - Contact contact = iterator.next(); + // Default is not found + boolean isFound = false; + + // Start iteration + Iterator iterator = this.getBackend().contactIterator(); + + // Check all entries + while (iterator.hasNext()) { + // Get next element + Contact c = iterator.next(); + + // Debug message + this.getLogger().debug(MessageFormat.format("c={0},contact={1}", c, contact)); //NOI18N - // Add contact instance to manager - this.getContactManager().addContact(contact); + // Is it added? + if (c.equals(contact)) { + // Is found + isFound = true; + break; + } } // Trace message - this.getLogger().trace("EXIT!"); //NOI18N + this.getLogger().trace(MessageFormat.format("isFound={0} - EXIT!", isFound)); //NOI18N + + // Return it + return isFound; + } + + /** + * Checks whether own contact is found in database + * + * @return Whether own contact is found + */ + @Override + public boolean isOwnContactFound () { + // Deligate this call to backend + return this.getBackend().isRowFound(ContactDatabaseConstants.COLUMN_NAME_OWN_CONTACT, true); } } diff --git a/Addressbook/src/org/mxchange/addressbook/database/frontend/contact/ContactWrapper.java b/Addressbook/src/org/mxchange/addressbook/database/frontend/contact/ContactWrapper.java index 86538a6..fdf0cf3 100644 --- a/Addressbook/src/org/mxchange/addressbook/database/frontend/contact/ContactWrapper.java +++ b/Addressbook/src/org/mxchange/addressbook/database/frontend/contact/ContactWrapper.java @@ -16,7 +16,10 @@ */ package org.mxchange.addressbook.database.frontend.contact; +import org.mxchange.addressbook.contact.Contact; import org.mxchange.addressbook.database.frontend.DatabaseWrapper; +import org.mxchange.addressbook.exceptions.BadTokenException; +import org.mxchange.addressbook.exceptions.ContactAlreadyAddedException; /** * @@ -24,19 +27,46 @@ import org.mxchange.addressbook.database.frontend.DatabaseWrapper; */ public interface ContactWrapper extends DatabaseWrapper { + /** + * Adds given contact instance to database + * + * @param contact Contact instance to add + * @throws org.mxchange.addressbook.exceptions.ContactAlreadyAddedException If the contact is already added + */ + public void addContact (final Contact contact) throws ContactAlreadyAddedException; + /** * Shuts down the database layer */ public void doShutdown (); /** - * Flushes all contact entries to database + * Some "getter" for total contacts count + * + * @return Total contacts count + */ + public int getContactsCount (); + + /** + * Checks if given Contact is found + * + * @param contact Contact instance to check + * @return Whether the given Contact instance is found + * @throws org.mxchange.addressbook.exceptions.BadTokenException Continued throw + */ + public boolean isContactFound (final Contact contact) throws BadTokenException; + + /** + * Some "getter" for own contact instance + * + * @return Own contact instance */ - public void flushAllContacts (); + public Contact getOwnContact (); /** - * Reads all contacts from database backend and handles them over to the - * contact manager + * Checks whether own contact is found + * + * @return Whether own contact is found */ - public void readAllContacts (); + public boolean isOwnContactFound (); } diff --git a/Addressbook/src/org/mxchange/addressbook/exceptions/ContactAlreadyAddedException.java b/Addressbook/src/org/mxchange/addressbook/exceptions/ContactAlreadyAddedException.java new file mode 100644 index 0000000..1bfcf18 --- /dev/null +++ b/Addressbook/src/org/mxchange/addressbook/exceptions/ContactAlreadyAddedException.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2015 Roland Haeder + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.mxchange.addressbook.exceptions; + +import java.text.MessageFormat; +import org.mxchange.addressbook.contact.Contact; + +/** + * Thrown if the given Contact instance is already added + * + * @author Roland Haeder + */ +public class ContactAlreadyAddedException extends Exception { + + /** + * Constructor with a Contact instance + * + * @param contact Contact that is already added + */ + public ContactAlreadyAddedException (final Contact contact) { + super(MessageFormat.format("Contact with gender={0}, surname={1} and familyName={2} already added.", contact.getGender(), contact.getSurname(), contact.getFamilyName())); + } + + /** + * Default constructor, may be used if no contact instance is available + */ + public ContactAlreadyAddedException () { + super("Contact already added"); + } + +} diff --git a/Addressbook/src/org/mxchange/addressbook/manager/BaseManager.java b/Addressbook/src/org/mxchange/addressbook/manager/BaseManager.java index 8be7407..41af226 100644 --- a/Addressbook/src/org/mxchange/addressbook/manager/BaseManager.java +++ b/Addressbook/src/org/mxchange/addressbook/manager/BaseManager.java @@ -31,7 +31,5 @@ public class BaseManager extends BaseFrameworkSystem implements Manageable { * No instances can be created of this class */ protected BaseManager () { - // Call any other super constructors - super(); } } diff --git a/Addressbook/src/org/mxchange/addressbook/manager/application/ApplicationManager.java b/Addressbook/src/org/mxchange/addressbook/manager/application/ApplicationManager.java index f27cfb3..9a74efb 100644 --- a/Addressbook/src/org/mxchange/addressbook/manager/application/ApplicationManager.java +++ b/Addressbook/src/org/mxchange/addressbook/manager/application/ApplicationManager.java @@ -51,8 +51,6 @@ public class ApplicationManager extends BaseManager implements ManageableApplica * @param application An instance of an Application class */ private ApplicationManager (final Application application) { - super(); - // Application instance must be set if (application == null) { // Abort here diff --git a/Addressbook/src/org/mxchange/addressbook/manager/contact/ContactManager.java b/Addressbook/src/org/mxchange/addressbook/manager/contact/ContactManager.java index 128aeeb..93ed118 100644 --- a/Addressbook/src/org/mxchange/addressbook/manager/contact/ContactManager.java +++ b/Addressbook/src/org/mxchange/addressbook/manager/contact/ContactManager.java @@ -18,7 +18,6 @@ package org.mxchange.addressbook.manager.contact; import java.text.MessageFormat; import java.util.ArrayList; -import java.util.Collections; import java.util.Iterator; import java.util.List; import org.mxchange.addressbook.client.Client; @@ -26,6 +25,8 @@ import org.mxchange.addressbook.contact.Contact; import org.mxchange.addressbook.contact.Gender; import org.mxchange.addressbook.database.frontend.contact.ContactDatabaseFrontend; import org.mxchange.addressbook.database.frontend.contact.ContactWrapper; +import org.mxchange.addressbook.exceptions.BadTokenException; +import org.mxchange.addressbook.exceptions.ContactAlreadyAddedException; import org.mxchange.addressbook.exceptions.UnhandledUserChoiceException; import org.mxchange.addressbook.manager.BaseManager; @@ -48,30 +49,18 @@ public class ContactManager extends BaseManager implements ManageableContact { */ private final ContactWrapper contactDatabase; - /** - * A list of all contacts - */ - private final List contacts; - /** * Constructor which accepts maxContacts for maximum (initial) contacts and * a client instance. * - * @param maxContacts Maximum allowed contacts * @param client Client instance to use */ - public ContactManager (final int maxContacts, final Client client) { - // Always call super constructor first - super(); - + public ContactManager (final Client client) { // Trace message - this.getLogger().trace(MessageFormat.format("maxContacts={0},client={1} - CALLED!", maxContacts, client)); //NOI18N + this.getLogger().trace(MessageFormat.format("client={1} - CALLED!", client)); //NOI18N // Make sure all parameters are set correctly - if (maxContacts <= 0) { - // Must not be zero or smaller - throw new IllegalArgumentException(MessageFormat.format("maxContacts is below or zero: {0}", maxContacts)); //NOI18N - } else if (client == null) { + if (client == null) { // Abort here throw new NullPointerException("client is null"); //NOI18N } @@ -79,9 +68,6 @@ public class ContactManager extends BaseManager implements ManageableContact { // Set client instance this.setClient(client); - // Init contacts - this.contacts = new ArrayList<>(maxContacts); - // Init database connection this.contactDatabase = new ContactDatabaseFrontend(this); @@ -91,9 +77,6 @@ public class ContactManager extends BaseManager implements ManageableContact { // And fill it this.fillColumnNamesFromBundle(); - // Read all entries - this.contactDatabase.readAllContacts(); - // Debug message //* NOISY-DEBUG: */ this.getLogger().debug("client=" + client); } @@ -104,9 +87,7 @@ public class ContactManager extends BaseManager implements ManageableContact { * @param contact Contact instance to add */ @Override - public void addContact (final Contact contact) { - assert (this.contacts instanceof List) : "this.contacts is not initialized"; //NOI18N - + public void addContact (final Contact contact) throws ContactAlreadyAddedException { // Trace message this.getLogger().trace(MessageFormat.format("contact={0} - CALLED!", contact)); //NOI18N @@ -117,7 +98,7 @@ public class ContactManager extends BaseManager implements ManageableContact { } // Add it - this.contacts.add(contact); + this.getContactDatabase().addContact(contact); // Trace message this.getLogger().trace("EXIT!"); //NOI18N @@ -159,9 +140,6 @@ public class ContactManager extends BaseManager implements ManageableContact { throw new UnsupportedOperationException("Changing contact entries not finished."); //NOI18N } - // Flush whole list - this.flush(); - // Trace message this.getLogger().trace("EXIT!"); //NOI18N } @@ -194,8 +172,6 @@ public class ContactManager extends BaseManager implements ManageableContact { throw new UnsupportedOperationException("Changing contact entries not finished."); //NOI18N } - // Flush whole list - this.flush(); // Trace message this.getLogger().trace("EXIT!"); //NOI18N } @@ -237,9 +213,6 @@ public class ContactManager extends BaseManager implements ManageableContact { throw new UnsupportedOperationException("Changing contact entries not finished."); //NOI18N } - // Flush whole list - this.flush(); - // Trace message this.getLogger().trace("EXIT!"); //NOI18N } @@ -296,10 +269,16 @@ public class ContactManager extends BaseManager implements ManageableContact { * Asks user for own data */ @Override - public void doEnterOwnData () { + public void doEnterOwnData () throws ContactAlreadyAddedException { // Trace message this.getLogger().trace("CALLED!"); //NOI18N + // Is own contact already added? + if (this.isOwnContactAdded()) { + // Don't continue here + throw new ContactAlreadyAddedException(); + } + // Deligate this call to the client Contact contact = this.getClient().doEnterOwnData(); @@ -528,17 +507,6 @@ public class ContactManager extends BaseManager implements ManageableContact { return this.columnNames.get(columnIndex); } - /** - * Getter for whole contact list - * - * @return List of all contacts - */ - @Override - public List getList () { - assert (this.contacts instanceof List) : "this.contacts is not initialized"; //NOI18N - return Collections.unmodifiableList(this.contacts); - } - /** * Checks whether own contact is already added by checking all entries for * isOwnContact flag @@ -550,31 +518,8 @@ public class ContactManager extends BaseManager implements ManageableContact { // Trace message this.getLogger().trace("CALLED!"); //NOI18N - assert (this.contacts instanceof List) : "this.contacts is not initialized"; //NOI18N - - // Default is not added - boolean isAdded = false; - - // Now get it back from address book, first get an iterator - Iterator iterator = this.contacts.iterator(); - - // Check entries - while (iterator.hasNext()) { - // Get next entry - Contact contact = iterator.next(); - - // Is it valid? - if (contact instanceof Contact) { - // Get flag - isAdded = contact.isOwnContact(); - - // Is this own contact? - if (isAdded) { - // Then abort loop - break; - } - } - } + // Deligate this call to frontend + boolean isAdded = this.getContactDatabase().isOwnContactFound(); // Trace message this.getLogger().trace(MessageFormat.format("isAdded={0} : EXIT!", isAdded)); //NOI18N @@ -594,35 +539,36 @@ public class ContactManager extends BaseManager implements ManageableContact { // Trace message this.getLogger().trace(MessageFormat.format("contact={0} CALLED!", contact)); //NOI18N - // Contact must not be null - if (contact == null) { - // Abort here - throw new NullPointerException("contact is null"); //NOI18N - } - // Sanity check if (contact == null) { // Abort here throw new NullPointerException("contact is null"); //NOI18N } - // Check if contact is found - if (this.isContactAlreadyAdded(contact)) { - // Contact already added - // @todo Do something here - } else if ((contact.isOwnContact()) && (this.isOwnContactAdded())) { - // Own contact already added - // @todo Do something - } - // Debug message /* NOISY-DEBUG: */ this.getLogger().debug(MessageFormat.format("Adding '{0}' '{1}' at pos '{2}' ...", contact.getSurname(), contact.getFamilyName(), this.size())); //NOI18N + try { + // Check if contact is found + if (this.getContactDatabase().isContactFound(contact)) { + // Contact already added + // @todo Do something here + } else if ((contact.isOwnContact()) && (this.isOwnContactAdded())) { + // Own contact already added + // @todo Do something + } - // Add contact to internal list - this.addContact(contact); + // Add contact to internal list + this.addContact(contact); + } catch (final ContactAlreadyAddedException ex) { + // Abort here + this.abortProgramWithException(ex); + } catch (final BadTokenException ex) { + // Abort here + this.abortProgramWithException(ex); + } - // Flush whole list - this.flush(); + // Trace message + this.getLogger().trace("EXIT!"); //NOI18N } /** @@ -632,8 +578,7 @@ public class ContactManager extends BaseManager implements ManageableContact { */ @Override public final int size () { - assert (this.contacts instanceof List) : "this.contacts is not initialized"; //NOI18N - return this.contacts.size(); + return this.getContactDatabase().getContactsCount(); } /** @@ -667,20 +612,6 @@ public class ContactManager extends BaseManager implements ManageableContact { this.getLogger().trace(MessageFormat.format("getColumnCount()={0}: EXIT!", this.getColumnCount())); //NOI18N } - /** - * Flushes all entries by calling database backend - */ - private void flush () { - // Trace message - this.getLogger().trace("CALLED!"); //NOI18N - - // Flusgh all - this.getContactDatabase().flushAllContacts(); - - // Trace message - this.getLogger().trace("EXIT!"); //NOI18N - } - /** * A ContactWrapper instance * @@ -696,30 +627,11 @@ public class ContactManager extends BaseManager implements ManageableContact { * @return Contact instance or null */ private Contact getOwnContact () { - assert (this.contacts instanceof List) : "this.contacts is not initialized"; //NOI18N - // Trace message this.getLogger().trace("CALLED!"); //NOI18N - // Now get it back from address book, first get an iterator - Iterator iterator = this.contacts.iterator(); - - // Init instance - Contact contact = null; - - // Search all contact - while (iterator.hasNext()) { - // Get next instance - Contact next = iterator.next(); - - // Is this own contact? - if (next.isOwnContact()) { - // Found it - contact = next; - break; - - } - } + // Deligate this call to database frontend + Contact contact = this.getContactDatabase().getOwnContact(); // Trace message this.getLogger().trace(MessageFormat.format("contact={0} - EXIT!", contact)); //NOI18N @@ -727,52 +639,4 @@ public class ContactManager extends BaseManager implements ManageableContact { // Return instance or null return contact; } - - /** - * Checks whether given contact was found in "address book" - * - * @param checkContact Contact to be checked - * @return TRUE if found, FALSE if not found - */ - private boolean isContactAlreadyAdded (final Contact checkContact) throws NullPointerException { - assert (this.contacts instanceof List) : "this.contacts is not initialized"; //NOI18N - - // Trace message - this.getLogger().trace(MessageFormat.format("checkContact={0} - CALLED!", checkContact)); //NOI18N - - // Contact instance must not be null - if (checkContact == null) { - // Abort here - throw new NullPointerException("checkContact is null"); - } - - // Default is not found - boolean isFound = false; - - // Debug message - //* NOISY-DEBUG: */ this.getLogger().debug("Checking '" + this.contacts.length + "' entries..."); - // Now get it back from address book, first get an iterator - Iterator iterator = this.contacts.iterator(); - - // Check entries - while (iterator.hasNext()) { - // Get next entry - Contact contact = iterator.next(); - - // Debug message - //* NOISY-DEBUG: */ this.getLogger().debug("contact=" + contact + ",checkContent=" + checkContact); - // Is it valid? - if ((contact instanceof Contact) && ((contact.equals(checkContact)))) { - // Found matching entry - isFound = true; - break; - } - } - - // Trace message - this.getLogger().trace(MessageFormat.format("isFound={0} - EXIT!", isFound)); //NOI18N - - // Return result - return isFound; - } } diff --git a/Addressbook/src/org/mxchange/addressbook/manager/contact/ManageableContact.java b/Addressbook/src/org/mxchange/addressbook/manager/contact/ManageableContact.java index 6c4ff93..8343ffa 100644 --- a/Addressbook/src/org/mxchange/addressbook/manager/contact/ManageableContact.java +++ b/Addressbook/src/org/mxchange/addressbook/manager/contact/ManageableContact.java @@ -16,9 +16,9 @@ */ package org.mxchange.addressbook.manager.contact; -import java.util.List; import org.mxchange.addressbook.contact.Contact; import org.mxchange.addressbook.contact.Gender; +import org.mxchange.addressbook.exceptions.ContactAlreadyAddedException; import org.mxchange.addressbook.manager.Manageable; /** @@ -155,8 +155,9 @@ public interface ManageableContact extends Manageable { * Adds given Contact instance to list * * @param contact Contact instance to add + * @throws org.mxchange.addressbook.exceptions.ContactAlreadyAddedException If the contact is already added */ - public void addContact (final Contact contact); + public void addContact (final Contact contact) throws ContactAlreadyAddedException; /** * Let the user add a new other address @@ -203,15 +204,9 @@ public interface ManageableContact extends Manageable { /** * Asks user for own data + * @throws org.mxchange.addressbook.exceptions.ContactAlreadyAddedException If own contact is already added */ - public void doEnterOwnData (); - - /** - * Getter for whole list - * - * @return List of all contacts - */ - public List getList (); + public void doEnterOwnData () throws ContactAlreadyAddedException; /** * Searches address book for a contact diff --git a/Addressbook/src/org/mxchange/addressbook/menu/BaseMenu.java b/Addressbook/src/org/mxchange/addressbook/menu/BaseMenu.java index de12ad4..5d1785d 100644 --- a/Addressbook/src/org/mxchange/addressbook/menu/BaseMenu.java +++ b/Addressbook/src/org/mxchange/addressbook/menu/BaseMenu.java @@ -39,7 +39,6 @@ public class BaseMenu extends BaseFrameworkSystem { * No instance from this object */ protected BaseMenu () { - super(); } /** diff --git a/Addressbook/src/org/mxchange/addressbook/model/contact/ContactTableModel.java b/Addressbook/src/org/mxchange/addressbook/model/contact/ContactTableModel.java index 30307c6..c9ad5bd 100644 --- a/Addressbook/src/org/mxchange/addressbook/model/contact/ContactTableModel.java +++ b/Addressbook/src/org/mxchange/addressbook/model/contact/ContactTableModel.java @@ -34,9 +34,6 @@ public class ContactTableModel extends BaseModel implements TableModel { * @param client Client instance */ public ContactTableModel (final Client client) { - // Parent super constructor - super(); - // Trace message this.getLogger().trace(MessageFormat.format("client={1} - CALLED!", client)); //NOI18N -- 2.39.2