Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update delete contact functionality #32

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
53ab114
Add factory method for DeleteCommand
CJ-Lee01 Oct 10, 2023
ead20a1
Add subclass for DeleteCommand
CJ-Lee01 Oct 10, 2023
5f132cf
Add tasks in comments
CJ-Lee01 Oct 10, 2023
ed10bab
Add getChildren method for Contact
CJ-Lee01 Oct 10, 2023
e9f6f02
Add addChild method for Contact
CJ-Lee01 Oct 10, 2023
b077f23
Add new exception for illegal operations
CJ-Lee01 Oct 10, 2023
ff7ae08
Add exception thrown when calling addChild
CJ-Lee01 Oct 10, 2023
2805ec6
Add javadocs to delete commands
CJ-Lee01 Oct 12, 2023
1ad1b59
Add javadocs for Contact methods
CJ-Lee01 Oct 12, 2023
5722054
Fix style issues in DeleteCommand
CJ-Lee01 Oct 12, 2023
8ef6769
Add ContactId
CJ-Lee01 Oct 12, 2023
5033786
Add DeleteByIdCommand
CJ-Lee01 Oct 12, 2023
26f4670
Add DeleteByIdWithChildrenCommand
CJ-Lee01 Oct 12, 2023
538c16d
Update javadocs of delete commands
CJ-Lee01 Oct 12, 2023
f87453f
Add select ID for delete command
CJ-Lee01 Oct 12, 2023
4dfabe6
Add functionality to delete child contacts
CJ-Lee01 Oct 12, 2023
5a14f7b
Merge branch 'master' into branch-delete-contacts
CJ-Lee01 Oct 12, 2023
8a35390
Add hashcode function to ContactId
CJ-Lee01 Oct 12, 2023
f66a7ff
Add regex to ContactId
CJ-Lee01 Oct 12, 2023
79db31c
Add functionality to get contact by id
CJ-Lee01 Oct 16, 2023
93add45
Add javadocs to AddressBook
CJ-Lee01 Oct 16, 2023
6e99018
Add functionality to get contact by id in Model
CJ-Lee01 Oct 16, 2023
ee662e9
Implement delete by id commands
CJ-Lee01 Oct 16, 2023
ea0c0d3
Fix formatting and spelling errors
CJ-Lee01 Oct 16, 2023
a9b73c1
Fix checkstyle issues
CJ-Lee01 Oct 16, 2023
83126be
Implement new model method in test
CJ-Lee01 Oct 16, 2023
ad8194f
Nuke delete by id commands
CJ-Lee01 Oct 17, 2023
6b30a6e
Add no such contact exception message
CJ-Lee01 Oct 17, 2023
74baba9
Implement delete by id in DeleteCommand classes
CJ-Lee01 Oct 17, 2023
59cc772
Update javadocs for DeleteCommand classes
CJ-Lee01 Oct 17, 2023
70d7ca0
Add parseContactId method
CJ-Lee01 Oct 17, 2023
7fbe9a7
Merge branch 'master' into branch-delete-contacts
CJ-Lee01 Oct 17, 2023
fc915f9
Change ContactId to Id
CJ-Lee01 Oct 17, 2023
667451d
Add recursive flag to CliSyntax
CJ-Lee01 Oct 17, 2023
91d7f6f
Update DeleteCommandParser to delete id
CJ-Lee01 Oct 17, 2023
df0eeea
Fix wrong recursive delete message
CJ-Lee01 Oct 17, 2023
39aa1a6
Merge branch 'master' into branch-delete-contacts
CJ-Lee01 Oct 17, 2023
8dc9d58
Remove unncessary comment
CJ-Lee01 Oct 17, 2023
2e72dc4
Fix name for static field in Contact
CJ-Lee01 Oct 17, 2023
91974fe
Add todo for Organization
CJ-Lee01 Oct 17, 2023
3503f6e
Merge branch 'master' into branch-delete-contacts
CJ-Lee01 Oct 17, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package seedu.address.commons.exceptions;

/**
* Exception thrown when attempting to make illegal.
*/
public class IllegalOperationException extends Exception {
/**
* @param message that informs the user that it has attempted an illegal operation.
*/
public IllegalOperationException(String message) {
super(message);
}

/**
* @param message that informs the user that it has attempted an illegal operation.
* @param cause of the main exception.
*/
public IllegalOperationException(String message, Throwable cause) {
super(message, cause);
}
}
1 change: 1 addition & 0 deletions src/main/java/seedu/address/logic/Messages.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public class Messages {
public static final String MESSAGE_UNKNOWN_COMMAND = "Unknown command";
public static final String MESSAGE_INVALID_COMMAND_FORMAT = "Invalid command format! \n%1$s";
public static final String MESSAGE_INVALID_CONTACT_DISPLAYED_INDEX = "The contact index provided is invalid";
public static final String MESSAGE_NO_SUCH_CONTACT = "No such contact";
public static final String MESSAGE_CONTACTS_LISTED_OVERVIEW = "%1$d contacts listed!";
public static final String MESSAGE_DUPLICATE_FIELDS =
"Multiple values specified for the following single-valued field(s): ";
Expand Down
87 changes: 76 additions & 11 deletions src/main/java/seedu/address/logic/commands/DeleteCommand.java
CJ-Lee01 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,18 @@
import static java.util.Objects.requireNonNull;

import java.util.List;
import java.util.function.Function;

import seedu.address.commons.core.index.Index;
import seedu.address.commons.util.ToStringBuilder;
import seedu.address.logic.Messages;
import seedu.address.logic.commands.exceptions.CommandException;
import seedu.address.model.Model;
import seedu.address.model.person.Contact;
import seedu.address.model.person.Id;

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

Expand All @@ -25,22 +27,75 @@ public class DeleteCommand extends Command {

public static final String MESSAGE_DELETE_CONTACT_SUCCESS = "Deleted Contact: %1$s";

private final Index targetIndex;
private final Object selector; // TODO: This is very sus but this will only be used for equals comparison
CJ-Lee01 marked this conversation as resolved.
Show resolved Hide resolved

private final Function<Model, Contact> contactFunction;

private final CommandException commandException;

/**
* @param targetIndex of the contact to be deleted
*/
public DeleteCommand(Index targetIndex) {
this.targetIndex = targetIndex;
this.selector = targetIndex;
this.contactFunction = (Model model) -> {
List<Contact> lastShownList = model.getFilteredContactList();

if (targetIndex.getZeroBased() >= lastShownList.size()) {
return null;
}

return lastShownList.get(targetIndex.getZeroBased());
};
this.commandException = new CommandException(Messages.MESSAGE_INVALID_CONTACT_DISPLAYED_INDEX);
}

/**
* @param targetId of the contact to be deleted
*/
public DeleteCommand(Id targetId) {
this.selector = targetId;
this.contactFunction = (Model model) -> model.getContactById(targetId);
this.commandException = new CommandException(Messages.MESSAGE_NO_SUCH_CONTACT);
}

/**
* Creates an executable DeleteCommand based on whether to delete recursively.
*
* @param targetIndex of the contact to delete in the current list
* @param shouldDeleteChildren specifies if child contacts should be deleted
*/
public static DeleteCommand selectIndex(Index targetIndex, boolean shouldDeleteChildren) {
// TODO: Add documentation to DG
requireNonNull(targetIndex);
if (shouldDeleteChildren) {
return new DeleteWithChildrenCommand(targetIndex);
}
return new DeleteCommand(targetIndex);
}

/**
* Creates an executable DeleteCommand based on whether to delete recursively.
*
* @param id of the contact to delete in the current list
* @param shouldDeleteChildren specifies if child contacts should be deleted
*/
public static DeleteCommand selectId(Id id, boolean shouldDeleteChildren) {
// TODO: Add documentation to DG
requireNonNull(id);
if (shouldDeleteChildren) {
return new DeleteWithChildrenCommand(id);
}
return new DeleteCommand(id);
}

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

if (targetIndex.getZeroBased() >= lastShownList.size()) {
throw new CommandException(Messages.MESSAGE_INVALID_CONTACT_DISPLAYED_INDEX);
Contact contactToDelete = this.contactFunction.apply(model);
if (contactToDelete == null) {
throw commandException;
}

Contact contactToDelete = lastShownList.get(targetIndex.getZeroBased());
model.deleteContact(contactToDelete);
return new CommandResult(String.format(MESSAGE_DELETE_CONTACT_SUCCESS, Messages.format(contactToDelete)));
}
Expand All @@ -57,13 +112,23 @@ public boolean equals(Object other) {
}

DeleteCommand otherDeleteCommand = (DeleteCommand) other;
return targetIndex.equals(otherDeleteCommand.targetIndex);
return selector.equals(otherDeleteCommand.selector);
}

@Override
public String toString() {
// TODO: replace this toString method with sth better than targetIndex
// To not replace yet until we do the tests
return new ToStringBuilder(this)
.add("targetIndex", targetIndex)
.add("targetIndex", selector)
.toString();
}

/**
* Gives the contact that the DeleteCommand is going to delete if a model is given.
* If such a contact does not exist, gives null.
*/
protected Contact getContact(Model model) {
return contactFunction.apply(model);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package seedu.address.logic.commands;

import static java.util.Objects.requireNonNull;

import java.util.Arrays;

import seedu.address.commons.core.index.Index;
import seedu.address.logic.Messages;
import seedu.address.logic.commands.exceptions.CommandException;
import seedu.address.model.Model;
import seedu.address.model.person.Contact;
import seedu.address.model.person.Id;

/**
* Deletes a contact and also deletes its child contacts.
*/
public class DeleteWithChildrenCommand extends DeleteCommand {

public static final String MESSAGE_DELETE_CONTACT_SUCCESS = DeleteCommand.MESSAGE_DELETE_CONTACT_SUCCESS + " with"
+ ":\n%2$s";


/**
* @param targetIndex of the contact to be deleted in the current contact list
*/
public DeleteWithChildrenCommand(Index targetIndex) {
// TODO add documentation in DG
super(targetIndex);
}

public DeleteWithChildrenCommand(Id targetId) {
super(targetId);
}

@Override
public CommandResult execute(Model model) throws CommandException {
requireNonNull(model);
Contact contactToDelete = super.getContact(model);
super.execute(model);
// At this point if the contact is null, the superclass would have thrown exception.
// Superclass would have also deleted the contact from the list.
assert contactToDelete != null;
Contact[] childContacts = contactToDelete.getChildren();
Arrays.stream(childContacts).forEach(contact -> {
model.deleteContact(contactToDelete);
});
return new CommandResult(String.format(
MESSAGE_DELETE_CONTACT_SUCCESS,
Messages.format(contactToDelete),
Arrays.stream(childContacts)
.map(c -> Messages.format(c) + "\n")
.reduce((c1, c2) -> c1 + c2)
.orElse("No other contacts found") // I can't find a better method.
));
}
}
3 changes: 1 addition & 2 deletions src/main/java/seedu/address/logic/parser/CliSyntax.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ public class CliSyntax {
public static final Flag FLAG_STATUS = new Flag("stat");
public static final Flag FLAG_POSITION = new Flag("pos");
public static final Flag FLAG_ID = new Flag("id");
public static final Flag FLAG_RECURSIVE = new Flag("recursive");
public static final Flag FLAG_ORGANIZATION_ID = new Flag("oid");



}
38 changes: 36 additions & 2 deletions src/main/java/seedu/address/logic/parser/DeleteCommandParser.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package seedu.address.logic.parser;

import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
import static seedu.address.logic.parser.CliSyntax.FLAG_ID;
import static seedu.address.logic.parser.CliSyntax.FLAG_RECURSIVE;

import seedu.address.commons.core.index.Index;
import seedu.address.logic.commands.DeleteCommand;
import seedu.address.logic.parser.exceptions.ParseException;
import seedu.address.model.person.Id;

/**
* Parses input arguments and creates a new DeleteCommand object
Expand All @@ -17,13 +20,44 @@ public class DeleteCommandParser implements Parser<DeleteCommand> {
* @throws ParseException if the user input does not conform the expected format
*/
public DeleteCommand parse(String args) throws ParseException {
ArgumentMultimap argumentMultimap =
ArgumentTokenizer.tokenize(args,
FLAG_ID, FLAG_RECURSIVE);

boolean hasIndex = !argumentMultimap.getPreamble().isEmpty();
boolean hasId = argumentMultimap.getValue(FLAG_ID).isPresent();
boolean isRecursive = argumentMultimap.getValue(FLAG_RECURSIVE).isPresent();

if (hasIndex) {
return parseDeleteIndexCommand(argumentMultimap.getPreamble(), isRecursive);
}

if (hasId) {
return parseDeleteIdCommand(argumentMultimap.getValue(FLAG_ID).get(), isRecursive);
}
throw new ParseException(
String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE));
}

private static DeleteCommand parseDeleteIdCommand(String idString, boolean isRecursive) throws ParseException {
Id id;
try {
Index index = ParserUtil.parseIndex(args);
return new DeleteCommand(index);
id = ParserUtil.parseId(idString);
return DeleteCommand.selectId(id, isRecursive);
} catch (ParseException pe) {
throw new ParseException(
String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE), pe);
}
}

private static DeleteCommand parseDeleteIndexCommand(String indexStr, boolean isRecursive) throws ParseException {
Index index;
try {
index = ParserUtil.parseIndex(indexStr);
return DeleteCommand.selectIndex(index, isRecursive);
} catch (ParseException pe) {
throw new ParseException(
String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE), pe);
}
}
}
16 changes: 16 additions & 0 deletions src/main/java/seedu/address/model/AddressBook.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import javafx.collections.ObservableList;
import seedu.address.commons.util.ToStringBuilder;
import seedu.address.model.person.Contact;
import seedu.address.model.person.Id;
import seedu.address.model.person.UniqueContactList;

/**
Expand Down Expand Up @@ -94,6 +95,21 @@ public void removeContact(Contact key) {
contacts.remove(key);
}

/**
* Gives a contact which id matches the given id.
* Gives null if a contact with such id does not exist.
* Given id must not be null.
*/
public Contact getContactById(Id id) {
requireNonNull(id);
for (Contact c: contacts) {
if (id.equals(c.getId())) {
return c;
}
}
return null;
}

//// util methods

@Override
Expand Down
8 changes: 8 additions & 0 deletions src/main/java/seedu/address/model/Model.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import javafx.collections.ObservableList;
import seedu.address.commons.core.GuiSettings;
import seedu.address.model.person.Contact;
import seedu.address.model.person.Id;
import seedu.address.model.person.Type;

/**
Expand Down Expand Up @@ -80,6 +81,13 @@ public interface Model {
*/
void setContact(Contact target, Contact editedContact);

/**
* Gives a contact which matches the given id.
* Gives null if no such contact is found.
* Given id must not be null.
*/
Contact getContactById(Id id);

/** Returns an unmodifiable view of the filtered contact list */
ObservableList<Contact> getFilteredContactList();

Expand Down
6 changes: 6 additions & 0 deletions src/main/java/seedu/address/model/ModelManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import seedu.address.commons.core.GuiSettings;
import seedu.address.commons.core.LogsCenter;
import seedu.address.model.person.Contact;
import seedu.address.model.person.Id;

/**
* Represents the in-memory model of the address book data.
Expand Down Expand Up @@ -111,6 +112,11 @@ public void setContact(Contact target, Contact editedContact) {
addressBook.setContact(target, editedContact);
}

@Override
public Contact getContactById(Id id) {
return addressBook.getContactById(id);
}

//=========== Filtered Contact List Accessors =============================================================

/**
Expand Down
Loading