From 12b7bc7862095e355d6434b8b24016fde2f7899f Mon Sep 17 00:00:00 2001 From: Xue-Chenyang Date: Tue, 29 Jan 2019 02:13:42 +0800 Subject: [PATCH 1/3] Added a new "update" command which allows users to update phone or email about one person --- src/seedu/addressbook/AddressBook.java | 176 +++++++++++++++++++++---- 1 file changed, 152 insertions(+), 24 deletions(-) diff --git a/src/seedu/addressbook/AddressBook.java b/src/seedu/addressbook/AddressBook.java index 5a158b67..dbfe49ec 100644 --- a/src/seedu/addressbook/AddressBook.java +++ b/src/seedu/addressbook/AddressBook.java @@ -14,14 +14,7 @@ import java.nio.file.InvalidPathException; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.Optional; -import java.util.Scanner; -import java.util.Set; +import java.util.*; /* * NOTE : ============================================================= @@ -71,6 +64,7 @@ public class AddressBook { private static final String MESSAGE_COMMAND_HELP_PARAMETERS = "\tParameters: %1$s"; private static final String MESSAGE_COMMAND_HELP_EXAMPLE = "\tExample: %1$s"; private static final String MESSAGE_DELETE_PERSON_SUCCESS = "Deleted Person: %1$s"; + private static final String MESSAGE_UPDATE_PERSON_SUCCESS = "Updated person: %1$s"; private static final String MESSAGE_DISPLAY_PERSON_DATA = "%1$s Phone Number: %2$s Email: %3$s"; private static final String MESSAGE_DISPLAY_LIST_ELEMENT_INDEX = "%1$d. "; private static final String MESSAGE_GOODBYE = "Exiting Address Book... Good bye!"; @@ -105,6 +99,13 @@ public class AddressBook { + PERSON_DATA_PREFIX_EMAIL + "EMAIL"; private static final String COMMAND_ADD_EXAMPLE = COMMAND_ADD_WORD + " John Doe p/98765432 e/johnd@gmail.com"; + private static final String COMMAND_UPDATE_WORD = "update"; + private static final String COMMAND_UPDATE_DESC = "Update a person's phone number or email address"; + private static final String COMMAND_UPDATE_PARAMETERS = "INDEX (Optional)" + + PERSON_DATA_PREFIX_PHONE + "NEW PHONE NUMBER (Optional)" + + PERSON_DATA_PREFIX_EMAIL + "NEW EMAIL"; + private static final String COMMAND_UPDATE_EXAMPLE = COMMAND_UPDATE_WORD + "1 p/12345678"; + private static final String COMMAND_FIND_WORD = "find"; private static final String COMMAND_FIND_DESC = "Finds all persons whose names contain any of the specified " + "keywords (case-sensitive) and displays them as a list with index numbers."; @@ -369,22 +370,24 @@ private static String executeCommand(String userInputString) { final String commandType = commandTypeAndParams[0]; final String commandArgs = commandTypeAndParams[1]; switch (commandType) { - case COMMAND_ADD_WORD: - return executeAddPerson(commandArgs); - case COMMAND_FIND_WORD: - return executeFindPersons(commandArgs); - case COMMAND_LIST_WORD: - return executeListAllPersonsInAddressBook(); - case COMMAND_DELETE_WORD: - return executeDeletePerson(commandArgs); - case COMMAND_CLEAR_WORD: - return executeClearAddressBook(); - case COMMAND_HELP_WORD: - return getUsageInfoForAllCommands(); - case COMMAND_EXIT_WORD: - executeExitProgramRequest(); - default: - return getMessageForInvalidCommandInput(commandType, getUsageInfoForAllCommands()); + case COMMAND_ADD_WORD: + return executeAddPerson(commandArgs); + case COMMAND_FIND_WORD: + return executeFindPersons(commandArgs); + case COMMAND_LIST_WORD: + return executeListAllPersonsInAddressBook(); + case COMMAND_DELETE_WORD: + return executeDeletePerson(commandArgs); + case COMMAND_CLEAR_WORD: + return executeClearAddressBook(); + case COMMAND_HELP_WORD: + return getUsageInfoForAllCommands(); + case COMMAND_EXIT_WORD: + executeExitProgramRequest(); + case COMMAND_UPDATE_WORD: + return executeUpdatePerson(commandArgs); + default: + return getMessageForInvalidCommandInput(commandType, getUsageInfoForAllCommands()); } } @@ -558,6 +561,123 @@ private static String getMessageForSuccessfulDelete(String[] deletedPerson) { return String.format(MESSAGE_DELETE_PERSON_SUCCESS, getMessageForFormattedPersonData(deletedPerson)); } + /** + * Updates person identified using last displayed index. + * + * @param commandArgs full command args string from the user + * @return feedback display message for the operation result + */ + private static String executeUpdatePerson(String commandArgs) { + if (!isUpdatePersonArgsValid(commandArgs)) { + return getMessageForInvalidCommandInput(COMMAND_DELETE_WORD, getUsageInfoForDeleteCommand()); + } + final int targetVisibleIndex = extractTargetIndexFromUpdatePersonArgs(commandArgs); + if (!isDisplayIndexValidForLastPersonListingView(targetVisibleIndex)) { + return MESSAGE_INVALID_PERSON_DISPLAYED_INDEX; + } + final String[] targetInModel = getPersonByLastVisibleIndex(targetVisibleIndex); + if (isPhoneChanging(commandArgs)){ + String newPhone = getNewPhone(commandArgs); + if (!updatePersonFromAddressbook(targetInModel, PERSON_DATA_INDEX_PHONE, newPhone)){ + return MESSAGE_PERSON_NOT_IN_ADDRESSBOOK; + } + } + if (isEmailChanging(commandArgs)){ + String newEmail = getNewEmail(commandArgs); + if (!updatePersonFromAddressbook(targetInModel, PERSON_DATA_INDEX_EMAIL, newEmail)){ + return MESSAGE_PERSON_NOT_IN_ADDRESSBOOK; + } + } + return getMessageForSuccessfulUpdate(targetInModel); // success + } + + private static boolean isUpdatePersonArgsValid(String rawArgs) { + final ArrayList indexsOfPrefixs = extractPrefixIndexFromUpdatePersonArgs(rawArgs); + if (!indexsOfPrefixs.get(0).isPresent()){ + return false; + } + final int indexOfFirstPrefix = indexsOfPrefixs.get(0).getAsInt(); + try { + final int extractedIndex = Integer.parseInt(rawArgs.substring(0, indexOfFirstPrefix).trim()); // use standard libraries to parse + return extractedIndex >= DISPLAYED_INDEX_OFFSET; + } catch (NumberFormatException nfe) { + return false; + } + } + + public static ArrayList extractPrefixIndexFromUpdatePersonArgs(String rawArgs){ + int indexOfFirstPrefix = -1; + ArrayList indexOfPrefixs = new ArrayList<>(); + final int indexOfPhonePrefix = rawArgs.indexOf(PERSON_DATA_PREFIX_PHONE); + if (indexOfPhonePrefix != -1){ + indexOfFirstPrefix = indexOfPhonePrefix; + } + final int indexOfEmailPrefix = rawArgs.indexOf(PERSON_DATA_PREFIX_EMAIL); + if (indexOfEmailPrefix != -1 && indexOfEmailPrefix < indexOfFirstPrefix){ + indexOfFirstPrefix = indexOfEmailPrefix; + } + if (indexOfFirstPrefix == -1){ + indexOfPrefixs.add(OptionalInt.empty()); + indexOfPrefixs.add(OptionalInt.empty()); + } else { + indexOfPrefixs.add(OptionalInt.of(indexOfFirstPrefix)); + if (indexOfEmailPrefix == -1 || indexOfPhonePrefix == -1){ + indexOfPrefixs.add(OptionalInt.empty()); + } else { + indexOfPrefixs.add(OptionalInt.of(Math.max(indexOfEmailPrefix, indexOfPhonePrefix))); + } + } + return indexOfPrefixs; + } + + private static int extractTargetIndexFromUpdatePersonArgs(String rawArgs) { + final ArrayList indexsOfPrefixs = extractPrefixIndexFromUpdatePersonArgs(rawArgs); + final int indexOfFirstPrefix = indexsOfPrefixs.get(0).getAsInt(); + return Integer.parseInt(rawArgs.substring(0, indexOfFirstPrefix).trim()); + } + + private static boolean isPhoneChanging(String rawArgs){ + final int indexOfPhonePrefix = rawArgs.indexOf(PERSON_DATA_PREFIX_PHONE); + return (indexOfPhonePrefix != -1); + } + + private static String getNewPhone(String rawArgs){ + final int indexOfPhonePrefix = rawArgs.indexOf(PERSON_DATA_PREFIX_PHONE); + if (!isEmailChanging(rawArgs)){ + return removePrefixSign(rawArgs.substring(indexOfPhonePrefix).trim(), PERSON_DATA_PREFIX_PHONE); + } else { + final int indexOfEmailPrefix = rawArgs.indexOf(PERSON_DATA_PREFIX_EMAIL); + if (indexOfEmailPrefix < indexOfPhonePrefix){ + return removePrefixSign(rawArgs.substring(indexOfPhonePrefix).trim(), PERSON_DATA_PREFIX_PHONE); + } else { + return removePrefixSign(rawArgs.substring(indexOfPhonePrefix, indexOfEmailPrefix).trim(), PERSON_DATA_PREFIX_PHONE); + } + } + } + + private static boolean isEmailChanging(String rawArgs){ + final int indexOfEmailPrefix = rawArgs.indexOf(PERSON_DATA_PREFIX_EMAIL); + return indexOfEmailPrefix != -1; + } + + private static String getNewEmail(String rawArgs){ + final int indexOfEmailPrefix = rawArgs.indexOf(PERSON_DATA_PREFIX_EMAIL); + if (!isPhoneChanging(rawArgs)){ + return removePrefixSign(rawArgs.substring(indexOfEmailPrefix).trim(), PERSON_DATA_PREFIX_EMAIL); + } else { + final int indexOfPhonePrefix = rawArgs.indexOf(PERSON_DATA_PREFIX_PHONE); + if (indexOfEmailPrefix > indexOfPhonePrefix){ + return removePrefixSign(rawArgs.substring(indexOfEmailPrefix).trim(), PERSON_DATA_PREFIX_PHONE); + } else { + return removePrefixSign(rawArgs.substring(indexOfEmailPrefix, indexOfPhonePrefix).trim(), PERSON_DATA_PREFIX_PHONE); + } + } + } + + private static String getMessageForSuccessfulUpdate(String[] updatedPerson) { + return String.format(MESSAGE_UPDATE_PERSON_SUCCESS, getMessageForFormattedPersonData(updatedPerson)); + } + /** * Clears all persons in the address book. * @@ -801,6 +921,14 @@ private static boolean deletePersonFromAddressBook(String[] exactPerson) { return changed; } + private static boolean updatePersonFromAddressbook(String[] exactPerson, int index, String content){ + final boolean deleted = deletePersonFromAddressBook(exactPerson); + if (! deleted){ return false;} + exactPerson[index] = content; + addPersonToAddressBook(exactPerson); + return true; + } + /** * Returns all persons in the address book */ From 6fe4304db9bdca20d40b917178742af10d7a7b21 Mon Sep 17 00:00:00 2001 From: Xue-Chenyang Date: Tue, 29 Jan 2019 12:46:18 +0800 Subject: [PATCH 2/3] Entered comments for new methods, fixed bugs, requires phone number and email address to be valid for successful update --- src/seedu/addressbook/AddressBook.java | 100 +++++++++++++++++++++---- 1 file changed, 87 insertions(+), 13 deletions(-) diff --git a/src/seedu/addressbook/AddressBook.java b/src/seedu/addressbook/AddressBook.java index dbfe49ec..da1df504 100644 --- a/src/seedu/addressbook/AddressBook.java +++ b/src/seedu/addressbook/AddressBook.java @@ -577,20 +577,31 @@ private static String executeUpdatePerson(String commandArgs) { } final String[] targetInModel = getPersonByLastVisibleIndex(targetVisibleIndex); if (isPhoneChanging(commandArgs)){ - String newPhone = getNewPhone(commandArgs); - if (!updatePersonFromAddressbook(targetInModel, PERSON_DATA_INDEX_PHONE, newPhone)){ + Optional newPhone = getNewPhone(commandArgs); + if (!newPhone.isPresent()){ + return getMessageForInvalidCommandInput(COMMAND_UPDATE_WORD, getUsageInfoForUpdateCommand()); + } + if (!updatePersonFromAddressbook(targetInModel, PERSON_DATA_INDEX_PHONE, newPhone.get())){ return MESSAGE_PERSON_NOT_IN_ADDRESSBOOK; } } if (isEmailChanging(commandArgs)){ - String newEmail = getNewEmail(commandArgs); - if (!updatePersonFromAddressbook(targetInModel, PERSON_DATA_INDEX_EMAIL, newEmail)){ + Optional newEmail = getNewEmail(commandArgs); + if (!newEmail.isPresent()){ + return getMessageForInvalidCommandInput(COMMAND_UPDATE_WORD, getUsageInfoForUpdateCommand()); + } + if (!updatePersonFromAddressbook(targetInModel, PERSON_DATA_INDEX_EMAIL, newEmail.get())){ return MESSAGE_PERSON_NOT_IN_ADDRESSBOOK; } } return getMessageForSuccessfulUpdate(targetInModel); // success } + /** + * Checks if the index of person to update is valid and there is at least one field to update + * @param rawArgs full command from the user + * @return whether the command is valid + */ private static boolean isUpdatePersonArgsValid(String rawArgs) { final ArrayList indexsOfPrefixs = extractPrefixIndexFromUpdatePersonArgs(rawArgs); if (!indexsOfPrefixs.get(0).isPresent()){ @@ -605,6 +616,11 @@ private static boolean isUpdatePersonArgsValid(String rawArgs) { } } + /** + * Extracts the indexes of prefix_phone and prefix_email + * @param rawArgs full command from the user + * @return An Arraylist of OptionalInt describing the indexes of prefixes + */ public static ArrayList extractPrefixIndexFromUpdatePersonArgs(String rawArgs){ int indexOfFirstPrefix = -1; ArrayList indexOfPrefixs = new ArrayList<>(); @@ -613,7 +629,7 @@ public static ArrayList extractPrefixIndexFromUpdatePersonArgs(Stri indexOfFirstPrefix = indexOfPhonePrefix; } final int indexOfEmailPrefix = rawArgs.indexOf(PERSON_DATA_PREFIX_EMAIL); - if (indexOfEmailPrefix != -1 && indexOfEmailPrefix < indexOfFirstPrefix){ + if (indexOfEmailPrefix != -1 && (indexOfEmailPrefix < indexOfFirstPrefix || indexOfFirstPrefix == -1)){ indexOfFirstPrefix = indexOfEmailPrefix; } if (indexOfFirstPrefix == -1){ @@ -630,50 +646,92 @@ public static ArrayList extractPrefixIndexFromUpdatePersonArgs(Stri return indexOfPrefixs; } + /** + * Extract the index of person to update + * @param rawArgs full command from the user + * @return the index of person to update + */ private static int extractTargetIndexFromUpdatePersonArgs(String rawArgs) { final ArrayList indexsOfPrefixs = extractPrefixIndexFromUpdatePersonArgs(rawArgs); final int indexOfFirstPrefix = indexsOfPrefixs.get(0).getAsInt(); return Integer.parseInt(rawArgs.substring(0, indexOfFirstPrefix).trim()); } + /** + * Check if the command requires phone number to be changed + * @param rawArgs full command from the user + * @return whether phont number is to be changed + */ private static boolean isPhoneChanging(String rawArgs){ final int indexOfPhonePrefix = rawArgs.indexOf(PERSON_DATA_PREFIX_PHONE); return (indexOfPhonePrefix != -1); } - private static String getNewPhone(String rawArgs){ + /** + * Extract the new phone number + * @param rawArgs full command from the user + * @return Optional.empty() if the phone number is invalid, else Optional.of(new phone number) + */ + private static Optional getNewPhone(String rawArgs){ final int indexOfPhonePrefix = rawArgs.indexOf(PERSON_DATA_PREFIX_PHONE); + String newPhone; if (!isEmailChanging(rawArgs)){ - return removePrefixSign(rawArgs.substring(indexOfPhonePrefix).trim(), PERSON_DATA_PREFIX_PHONE); + newPhone = removePrefixSign(rawArgs.substring(indexOfPhonePrefix).trim(), PERSON_DATA_PREFIX_PHONE); } else { final int indexOfEmailPrefix = rawArgs.indexOf(PERSON_DATA_PREFIX_EMAIL); if (indexOfEmailPrefix < indexOfPhonePrefix){ - return removePrefixSign(rawArgs.substring(indexOfPhonePrefix).trim(), PERSON_DATA_PREFIX_PHONE); + newPhone = removePrefixSign(rawArgs.substring(indexOfPhonePrefix).trim(), PERSON_DATA_PREFIX_PHONE); } else { - return removePrefixSign(rawArgs.substring(indexOfPhonePrefix, indexOfEmailPrefix).trim(), PERSON_DATA_PREFIX_PHONE); + newPhone = removePrefixSign(rawArgs.substring(indexOfPhonePrefix, indexOfEmailPrefix).trim(), PERSON_DATA_PREFIX_PHONE); } } + if (isPersonPhoneValid(newPhone)){ + return Optional.of(newPhone); + } else { + return Optional.empty(); + } } + /** + * Checks if the command requires email to be changed + * @param rawArgs full command from the user + * @return whether email is to be changed + */ private static boolean isEmailChanging(String rawArgs){ final int indexOfEmailPrefix = rawArgs.indexOf(PERSON_DATA_PREFIX_EMAIL); return indexOfEmailPrefix != -1; } - private static String getNewEmail(String rawArgs){ + /** + * Extracts the new email + * @param rawArgs full command from the user + * @return Optional.empty() if the email is invalid, else optional.of(new email) + */ + private static Optional getNewEmail(String rawArgs){ final int indexOfEmailPrefix = rawArgs.indexOf(PERSON_DATA_PREFIX_EMAIL); + String newEmail; if (!isPhoneChanging(rawArgs)){ - return removePrefixSign(rawArgs.substring(indexOfEmailPrefix).trim(), PERSON_DATA_PREFIX_EMAIL); + newEmail = removePrefixSign(rawArgs.substring(indexOfEmailPrefix).trim(), PERSON_DATA_PREFIX_EMAIL); } else { final int indexOfPhonePrefix = rawArgs.indexOf(PERSON_DATA_PREFIX_PHONE); if (indexOfEmailPrefix > indexOfPhonePrefix){ - return removePrefixSign(rawArgs.substring(indexOfEmailPrefix).trim(), PERSON_DATA_PREFIX_PHONE); + newEmail = removePrefixSign(rawArgs.substring(indexOfEmailPrefix).trim(), PERSON_DATA_PREFIX_PHONE); } else { - return removePrefixSign(rawArgs.substring(indexOfEmailPrefix, indexOfPhonePrefix).trim(), PERSON_DATA_PREFIX_PHONE); + newEmail = removePrefixSign(rawArgs.substring(indexOfEmailPrefix, indexOfPhonePrefix).trim(), PERSON_DATA_PREFIX_PHONE); } } + if (isPersonEmailValid(newEmail)){ + return Optional.of(newEmail); + } else { + return Optional.empty(); + } } + /** + * Get message for a successful update + * @param updatedPerson String[] describing the person after updating + * @return message for a successful update + */ private static String getMessageForSuccessfulUpdate(String[] updatedPerson) { return String.format(MESSAGE_UPDATE_PERSON_SUCCESS, getMessageForFormattedPersonData(updatedPerson)); } @@ -921,6 +979,14 @@ private static boolean deletePersonFromAddressBook(String[] exactPerson) { return changed; } + /** + * Update the specified person from the addressbook if it is inside. Save changes to storage file. + * + * @param exactPerson the actual person inside the address book + * @param index the index of field to update + * @param content the new content to replace the old content + * @return true if the update process is successful + */ private static boolean updatePersonFromAddressbook(String[] exactPerson, int index, String content){ final boolean deleted = deletePersonFromAddressBook(exactPerson); if (! deleted){ return false;} @@ -1216,6 +1282,7 @@ private static String getUsageInfoForAllCommands() { + getUsageInfoForDeleteCommand() + LS + getUsageInfoForClearCommand() + LS + getUsageInfoForExitCommand() + LS + + getUsageInfoForUpdateCommand() + LS + getUsageInfoForHelpCommand(); } @@ -1240,6 +1307,13 @@ private static String getUsageInfoForDeleteCommand() { + String.format(MESSAGE_COMMAND_HELP_EXAMPLE, COMMAND_DELETE_EXAMPLE) + LS; } + /** Returns the String for showing 'update' command usage instruction */ + private static String getUsageInfoForUpdateCommand() { + return String.format(MESSAGE_COMMAND_HELP, COMMAND_UPDATE_WORD, COMMAND_UPDATE_DESC) + LS + + String.format(MESSAGE_COMMAND_HELP_PARAMETERS, COMMAND_UPDATE_PARAMETERS) + LS + + String.format(MESSAGE_COMMAND_HELP_EXAMPLE, COMMAND_UPDATE_EXAMPLE) + LS; + } + /** Returns string for showing 'clear' command usage instruction */ private static String getUsageInfoForClearCommand() { return String.format(MESSAGE_COMMAND_HELP, COMMAND_CLEAR_WORD, COMMAND_CLEAR_DESC) + LS From 8e79cab73e76ea2c76d79f0539bfeaa2cb200922 Mon Sep 17 00:00:00 2001 From: Xue-Chenyang Date: Tue, 29 Jan 2019 13:03:40 +0800 Subject: [PATCH 3/3] Updated the expected test result --- src/seedu/addressbook/AddressBook.java | 2 +- test/expected.txt | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/seedu/addressbook/AddressBook.java b/src/seedu/addressbook/AddressBook.java index da1df504..6b8cfdcb 100644 --- a/src/seedu/addressbook/AddressBook.java +++ b/src/seedu/addressbook/AddressBook.java @@ -1280,9 +1280,9 @@ private static String getUsageInfoForAllCommands() { + getUsageInfoForFindCommand() + LS + getUsageInfoForViewCommand() + LS + getUsageInfoForDeleteCommand() + LS + + getUsageInfoForUpdateCommand() + LS + getUsageInfoForClearCommand() + LS + getUsageInfoForExitCommand() + LS - + getUsageInfoForUpdateCommand() + LS + getUsageInfoForHelpCommand(); } diff --git a/test/expected.txt b/test/expected.txt index f18922ac..9ec7977e 100644 --- a/test/expected.txt +++ b/test/expected.txt @@ -66,6 +66,10 @@ || Parameters: INDEX || Example: delete 1 || +|| update: Update a person's phone number or email address +|| Parameters: INDEX (Optional)p/NEW PHONE NUMBER (Optional)e/NEW EMAIL +|| Example: update1 p/12345678 +|| || clear: Clears address book permanently. || Example: clear ||