Skip to content

Commit

Permalink
Merge pull request #51 from muller317/Branch-DeleteByName
Browse files Browse the repository at this point in the history
Enable deleting customers' contacts based on their names
  • Loading branch information
RuijianLu authored Oct 10, 2024
2 parents 6addafa + af283cf commit 9e9dc42
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 37 deletions.
48 changes: 39 additions & 9 deletions src/main/java/seedu/address/logic/commands/DeleteCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static java.util.Objects.requireNonNull;

import java.util.List;
import java.util.Optional;

import seedu.address.commons.core.index.Index;
import seedu.address.commons.util.ToStringBuilder;
Expand All @@ -12,35 +13,63 @@
import seedu.address.model.person.Person;

/**
* Deletes a person identified using it's displayed index from the address book.
* Deletes a person identified using its displayed index or name from the address book.
*/
public class DeleteCommand extends Command {

public static final String COMMAND_WORD = "delete";

public static final String MESSAGE_USAGE = COMMAND_WORD
+ ": Deletes the person identified by the index number used in the displayed person list.\n"
+ "Parameters: INDEX (must be a positive integer)\n"
+ "Example: " + COMMAND_WORD + " 1";
+ ": Deletes the person identified by the index number or the full name used in the person list.\n"
+ "Parameters: INDEX (must be a positive integer) or NAME (must match an existing person name exactly)\n"
+ "Example: " + COMMAND_WORD + " 1 or " + COMMAND_WORD + " John Doe";

public static final String MESSAGE_DELETE_PERSON_SUCCESS = "Deleted Person: %1$s";
public static final String MESSAGE_PERSON_NOT_FOUND = "No person found with the name: %1$s";

private final Index targetIndex;
private final String targetName;

/**
* Creates a DeleteCommand for deleting by index.
*/
public DeleteCommand(Index targetIndex) {
this.targetIndex = targetIndex;
this.targetName = null;
}

/**
* Creates a DeleteCommand for deleting by name.
*/
public DeleteCommand(String targetName) {
this.targetName = targetName;
this.targetIndex = null;
}

@Override
public CommandResult execute(Model model) throws CommandException {
requireNonNull(model);
List<Person> lastShownList = model.getFilteredPersonList();

if (targetIndex.getZeroBased() >= lastShownList.size()) {
throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
Person personToDelete;
if (targetIndex != null) {
// Deletion by index
if (targetIndex.getZeroBased() >= lastShownList.size()) {
throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
}
personToDelete = lastShownList.get(targetIndex.getZeroBased());
} else {
// Deletion by name
Optional<Person> personOptional = lastShownList.stream()
.filter(person -> person.getName().fullName.equalsIgnoreCase(targetName))
.findFirst();

if (personOptional.isEmpty()) {
throw new CommandException(String.format(MESSAGE_PERSON_NOT_FOUND, targetName));
}
personToDelete = personOptional.get();
}

Person personToDelete = lastShownList.get(targetIndex.getZeroBased());
model.deletePerson(personToDelete);
return new CommandResult(String.format(MESSAGE_DELETE_PERSON_SUCCESS, Messages.format(personToDelete)));
}
Expand All @@ -51,19 +80,20 @@ public boolean equals(Object other) {
return true;
}

// instanceof handles nulls
if (!(other instanceof DeleteCommand)) {
return false;
}

DeleteCommand otherDeleteCommand = (DeleteCommand) other;
return targetIndex.equals(otherDeleteCommand.targetIndex);
return (targetIndex != null && targetIndex.equals(otherDeleteCommand.targetIndex))
|| (targetName != null && targetName.equals(otherDeleteCommand.targetName));
}

@Override
public String toString() {
return new ToStringBuilder(this)
.add("targetIndex", targetIndex)
.add("targetName", targetName)
.toString();
}
}
21 changes: 15 additions & 6 deletions src/main/java/seedu/address/logic/parser/DeleteCommandParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,32 @@
import seedu.address.logic.parser.exceptions.ParseException;

/**
* Parses input arguments and creates a new DeleteCommand object
* Parses input arguments and creates a new DeleteCommand object.
*/
public class DeleteCommandParser implements Parser<DeleteCommand> {

/**
* Parses the given {@code String} of arguments in the context of the DeleteCommand
* and returns a DeleteCommand object for execution.
* @throws ParseException if the user input does not conform the expected format
* @throws ParseException if the user input does not conform to the expected format.
*/
public DeleteCommand parse(String args) throws ParseException {
String trimmedArgs = args.trim();

// Check if the argument is empty
if (trimmedArgs.isEmpty()) {
throw new ParseException(
String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE));
}

try {
Index index = ParserUtil.parseIndex(args);
// Attempt to parse the input as an index
Index index = ParserUtil.parseIndex(trimmedArgs);
return new DeleteCommand(index);
} catch (ParseException pe) {
throw new ParseException(
String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE), pe);
// If it fails to parse as an index, assume it's a name and proceed to create DeleteCommand with name
return new DeleteCommand(trimmedArgs);
}
}

}

90 changes: 71 additions & 19 deletions src/test/java/seedu/address/logic/commands/DeleteCommandTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public class DeleteCommandTest {

private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs());

// Test for valid index-based deletion in an unfiltered list
@Test
public void execute_validIndexUnfilteredList_success() {
Person personToDelete = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased());
Expand All @@ -41,14 +42,32 @@ public void execute_validIndexUnfilteredList_success() {
assertCommandSuccess(deleteCommand, model, expectedMessage, expectedModel);
}

// Test for valid name-based deletion in an unfiltered list
@Test
public void execute_invalidIndexUnfilteredList_throwsCommandException() {
Index outOfBoundIndex = Index.fromOneBased(model.getFilteredPersonList().size() + 1);
DeleteCommand deleteCommand = new DeleteCommand(outOfBoundIndex);
public void execute_validNameUnfilteredList_success() {
Person personToDelete = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased());
String nameToDelete = personToDelete.getName().fullName;
DeleteCommand deleteCommand = new DeleteCommand(nameToDelete);

String expectedMessage = String.format(DeleteCommand.MESSAGE_DELETE_PERSON_SUCCESS,
Messages.format(personToDelete));

ModelManager expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs());
expectedModel.deletePerson(personToDelete);

assertCommandSuccess(deleteCommand, model, expectedMessage, expectedModel);
}

// Test for invalid name-based deletion in an unfiltered list
@Test
public void execute_invalidNameUnfilteredList_throwsCommandException() {
String invalidName = "Non Existent Person";
DeleteCommand deleteCommand = new DeleteCommand(invalidName);

assertCommandFailure(deleteCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
assertCommandFailure(deleteCommand, model, String.format(DeleteCommand.MESSAGE_PERSON_NOT_FOUND, invalidName));
}

// Test for valid index-based deletion in a filtered list
@Test
public void execute_validIndexFilteredList_success() {
showPersonAtIndex(model, INDEX_FIRST_PERSON);
Expand All @@ -66,46 +85,80 @@ public void execute_validIndexFilteredList_success() {
assertCommandSuccess(deleteCommand, model, expectedMessage, expectedModel);
}

// Test for valid name-based deletion in a filtered list
@Test
public void execute_invalidIndexFilteredList_throwsCommandException() {
public void execute_validNameFilteredList_success() {
showPersonAtIndex(model, INDEX_FIRST_PERSON);

Index outOfBoundIndex = INDEX_SECOND_PERSON;
// ensures that outOfBoundIndex is still in bounds of address book list
assertTrue(outOfBoundIndex.getZeroBased() < model.getAddressBook().getPersonList().size());
Person personToDelete = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased());
String nameToDelete = personToDelete.getName().fullName;
DeleteCommand deleteCommand = new DeleteCommand(nameToDelete);

DeleteCommand deleteCommand = new DeleteCommand(outOfBoundIndex);
String expectedMessage = String.format(DeleteCommand.MESSAGE_DELETE_PERSON_SUCCESS,
Messages.format(personToDelete));

assertCommandFailure(deleteCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs());
expectedModel.deletePerson(personToDelete);
showNoPerson(expectedModel);

assertCommandSuccess(deleteCommand, model, expectedMessage, expectedModel);
}

// Test for invalid name-based deletion in a filtered list
@Test
public void execute_invalidNameFilteredList_throwsCommandException() {
showPersonAtIndex(model, INDEX_FIRST_PERSON);

String invalidName = "Non Existent Person";
DeleteCommand deleteCommand = new DeleteCommand(invalidName);

assertCommandFailure(deleteCommand, model, String.format(DeleteCommand.MESSAGE_PERSON_NOT_FOUND, invalidName));
}

// Equality tests for both index-based and name-based commands
@Test
public void equals() {
DeleteCommand deleteFirstCommand = new DeleteCommand(INDEX_FIRST_PERSON);
DeleteCommand deleteSecondCommand = new DeleteCommand(INDEX_SECOND_PERSON);
DeleteCommand deleteNameCommand = new DeleteCommand("John Doe");

// same object -> returns true
// Same object -> returns true
assertTrue(deleteFirstCommand.equals(deleteFirstCommand));

// same values -> returns true
// Same values -> returns true
DeleteCommand deleteFirstCommandCopy = new DeleteCommand(INDEX_FIRST_PERSON);
assertTrue(deleteFirstCommand.equals(deleteFirstCommandCopy));

// different types -> returns false
// Different index -> returns false
assertFalse(deleteFirstCommand.equals(deleteSecondCommand));

// Different types -> returns false
assertFalse(deleteFirstCommand.equals(1));

// null -> returns false
// Null -> returns false
assertFalse(deleteFirstCommand.equals(null));

// different person -> returns false
assertFalse(deleteFirstCommand.equals(deleteSecondCommand));
// Different name -> returns false
assertFalse(deleteFirstCommand.equals(deleteNameCommand));

// Same name -> returns true
DeleteCommand deleteNameCommandCopy = new DeleteCommand("John Doe");
assertTrue(deleteNameCommand.equals(deleteNameCommandCopy));
}

@Test
public void toStringMethod() {
public void toString_indexBasedDeletion() {
Index targetIndex = Index.fromOneBased(1);
DeleteCommand deleteCommand = new DeleteCommand(targetIndex);
String expected = DeleteCommand.class.getCanonicalName() + "{targetIndex=" + targetIndex + "}";
String expected = DeleteCommand.class.getCanonicalName() + "{targetIndex=" + targetIndex + ", targetName=null}";
assertEquals(expected, deleteCommand.toString());
}

@Test
public void toString_nameBasedDeletion() {
String targetName = "John Doe";
DeleteCommand deleteCommand = new DeleteCommand(targetName);
String expected = DeleteCommand.class.getCanonicalName() + "{targetIndex=null, targetName=" + targetName + "}";
assertEquals(expected, deleteCommand.toString());
}

Expand All @@ -114,7 +167,6 @@ public void toStringMethod() {
*/
private void showNoPerson(Model model) {
model.updateFilteredPersonList(p -> false);

assertTrue(model.getFilteredPersonList().isEmpty());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,26 @@ public class DeleteCommandParserTest {
private DeleteCommandParser parser = new DeleteCommandParser();

@Test
public void parse_validArgs_returnsDeleteCommand() {
public void parse_validIndexArgs_returnsDeleteCommand() {
// Test for deletion using a valid index
assertParseSuccess(parser, "1", new DeleteCommand(INDEX_FIRST_PERSON));
}

@Test
public void parse_invalidArgs_throwsParseException() {
assertParseFailure(parser, "a", String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE));
public void parse_validNameArgs_returnsDeleteCommand() {
// Test for deletion using a valid name
assertParseSuccess(parser, "John Doe", new DeleteCommand("John Doe"));
}

@Test
public void parse_emptyNameArgs_throwsParseException() {
// Test for an empty string (invalid name input)
assertParseFailure(parser, "", String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE));
}

@Test
public void parse_whitespaceNameArgs_throwsParseException() {
// Test for whitespace-only string (invalid name input)
assertParseFailure(parser, " ", String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE));
}
}

0 comments on commit 9e9dc42

Please sign in to comment.