Skip to content

Commit

Permalink
Merge pull request #105 from CYX22222003/delete-tag
Browse files Browse the repository at this point in the history
Implement command to delete tag
  • Loading branch information
KrashKart authored Oct 22, 2024
2 parents d41e651 + 480077e commit ca486c8
Show file tree
Hide file tree
Showing 18 changed files with 322 additions and 8 deletions.
4 changes: 3 additions & 1 deletion src/main/java/seedu/address/logic/Messages.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ public class Messages {
public static final String MESSAGE_PERSONS_LISTED_OVERVIEW = "%1$d persons listed!";
public static final String MESSAGE_DUPLICATE_FIELDS =
"Multiple values specified for the following single-valued field(s): ";

public static final String MESSAGE_NO_TAG = "The person does not contain the tag";
public static final String MESSAGE_TAG_NOT_FOUND = "There is no tag presented in the command!";
public static final String MESSAGE_DELETE_TAG_SUCCESS = "Tag %1$s is deleted from student %2$s";
/**
* Returns an error message indicating the duplicate prefixes.
*/
Expand Down
78 changes: 78 additions & 0 deletions src/main/java/seedu/address/logic/commands/DeleteTagCommand.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package seedu.address.logic.commands;

import static java.util.Objects.requireNonNull;

import java.util.List;

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.Person;
import seedu.address.model.tag.Tag;

/**
* Implements command to delete a tag from a person
* format: deletetag [INDEX] t/[TAG NAME]
*/
public class DeleteTagCommand extends Command {
public static final String COMMAND_WORD = "deletetag";

public static final String MESSAGE_USAGE = COMMAND_WORD
+ ": Deletes tag from the person identified by the index number used in the displayed person list.\n"
+ "Parameters: INDEX (must be a positive integer) [TAG NAME]\n"
+ "Example: " + COMMAND_WORD + " 1 " + " hello_world";

private final Index targetIndex;
private final Tag targetTag;

/**
* Constructs new DeleteTag command.
* @param targetIndex the index of the person in the list.
* @param target the tag the user wants to delete.
*/
public DeleteTagCommand(Index targetIndex, Tag target) {
assert targetIndex != null;
assert target != null;
this.targetIndex = targetIndex;
this.targetTag = target;
}

/**
* Executes the command and delete a tag from a specific person.
*/
@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 personToEdit = lastShownList.get(targetIndex.getZeroBased());
assert personToEdit != null;
if (!personToEdit.hasTag(this.targetTag)) {
throw new CommandException(Messages.MESSAGE_NO_TAG);
}

model.deletePersonTag(personToEdit, targetTag);
return new CommandResult(String.format(Messages.MESSAGE_DELETE_TAG_SUCCESS,
this.targetTag, personToEdit.getName()));
}

@Override
public boolean equals(Object other) {
if (other == this) {
return true;
}

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

DeleteTagCommand otherDeleteTagCommand = (DeleteTagCommand) other;
return targetIndex.equals(otherDeleteTagCommand.targetIndex)
&& targetTag.equals(otherDeleteTagCommand.targetTag);
}
}
4 changes: 1 addition & 3 deletions src/main/java/seedu/address/logic/commands/EditCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,7 @@ public CommandResult execute(Model model) throws CommandException {
Person personToEdit = lastShownList.get(index.getZeroBased());
Person editedPerson = createEditedPerson(personToEdit, editPersonDescriptor);

// if (!personToEdit.isSamePerson(editedPerson) && model.hasPerson(editedPerson)) {
// throw new CommandException(MESSAGE_DUPLICATE_PERSON);
// }

model.deletePerson(personToEdit);
if (model.hasPerson(editedPerson)) {
model.insertPerson(personToEdit, index.getZeroBased());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import seedu.address.logic.commands.ClearCommand;
import seedu.address.logic.commands.Command;
import seedu.address.logic.commands.DeleteCommand;
import seedu.address.logic.commands.DeleteTagCommand;
import seedu.address.logic.commands.EditCommand;
import seedu.address.logic.commands.ExitCommand;
import seedu.address.logic.commands.HelpCommand;
Expand Down Expand Up @@ -77,10 +78,13 @@ public Command parseCommand(String userInput) throws ParseException {

case HelpCommand.COMMAND_WORD:
return new HelpCommand();


case DeleteTagCommand.COMMAND_WORD:
return new DeleteTagCommandParser().parse(arguments);

case UndoCommand.COMMAND_WORD:
return new UndoCommand();

default:
logger.finer("This user input caused a ParseException: " + userInput);
throw new ParseException(MESSAGE_UNKNOWN_COMMAND);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package seedu.address.logic.parser;

import static java.util.Objects.requireNonNull;
import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
import static seedu.address.logic.Messages.MESSAGE_TAG_NOT_FOUND;
import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;

import seedu.address.commons.core.index.Index;
import seedu.address.logic.commands.DeleteTagCommand;
import seedu.address.logic.parser.exceptions.ParseException;
import seedu.address.model.tag.Tag;

/**
* Parse the delete tag command.
*/
public class DeleteTagCommandParser implements Parser<DeleteTagCommand> {
/**
* Parses the given string of arguments in the context of Delete tag command.
* and returns DeleteTagCommand object for execution.
* @throws ParseException if user input does not conform the expected input
*/
public DeleteTagCommand parse(String args) throws ParseException {
requireNonNull(args);
assert !args.isEmpty();
ArgumentMultimap argMultiMap = ArgumentTokenizer.tokenize(args, PREFIX_TAG);
Index index;

try {
index = ParserUtil.parseIndex(argMultiMap.getPreamble());
} catch (ParseException pe) {
throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteTagCommand.MESSAGE_USAGE), pe);
}

argMultiMap.verifyNoDuplicatePrefixesFor(PREFIX_TAG);
if (argMultiMap.getValue(PREFIX_TAG).isEmpty()) {
throw new ParseException(MESSAGE_TAG_NOT_FOUND);
}

Tag target = ParserUtil.parseTag(argMultiMap.getValue(PREFIX_TAG).get());
return new DeleteTagCommand(index, target);
}
}
7 changes: 7 additions & 0 deletions src/main/java/seedu/address/model/CampusConnect.java
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,13 @@ public void removePerson(Person key) {
persons.remove(key);
}

/**
* Delete a tag from a person.
*/
public void removePersonTag(Person p, Tag t) {
persons.deletePersonTag(p, t);
}

//// util methods

@Override
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/seedu/address/model/Model.java
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@ public interface Model {
*/
void deletePerson(Person target);

/**
* Delete a tag from a person.
* The person must exist as well as the tag
*/
void deletePersonTag(Person p, Tag tag);

/**
* Adds the given person.
* {@code person} must not already exist in the address book.
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/seedu/address/model/ModelManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ public void deletePerson(Person target) {
refreshTagList();
}

@Override
public void deletePersonTag(Person p, Tag t) {
campusConnect.removePersonTag(p, t);
}

@Override
public void addPerson(Person person) {
campusConnect.addPerson(person);
Expand Down
17 changes: 17 additions & 0 deletions src/main/java/seedu/address/model/person/Person.java
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,23 @@ public boolean hasDuplicateInfo(Person otherPerson) {
|| this.hasSamePhoneNumber(otherPerson);
}

/**
* Checks whether the person has the tags
*/
public boolean hasTag(Tag t) {
return this.getTags().contains(t);
}

/**
* Remove a tag from a person
*/
public Person removeTag(Tag t) {
Set<Tag> newTagSet = new HashSet<>();
newTagSet.addAll(this.getTags());
newTagSet.remove(t);
return new Person(this.name, this.phone, this.email, newTagSet);
}

/**
* Returns true if both persons have the same identity and data fields.
* This defines a stronger notion of equality between two persons.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,15 @@ public void setPersons(List<Person> persons) {
internalList.setAll(persons);
}

/**
* Delete a tag from a person
*/
public void deletePersonTag(Person p, Tag t) {
requireNonNull(p);
Person replace = p.removeTag(t);
setPerson(p, replace);
}

/**
* Returns the backing list as an unmodifiable {@code ObservableList}.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,11 @@ public void deletePerson(Person target) {
throw new AssertionError("This method should not be called.");
}

@Override
public void deletePersonTag(Person p, Tag tag) {
throw new AssertionError("This method should not be called.");
}

@Override
public void setPerson(Person target, Person editedPerson) {
throw new AssertionError("This method should not be called.");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package seedu.address.logic.commands;

import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure;
import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PERSON;
import static seedu.address.testutil.TypicalPersons.FRIEND_TAG;
import static seedu.address.testutil.TypicalPersons.OWES_MONEY_TAG;
import static seedu.address.testutil.TypicalPersons.getTypicalCampusConnect;

import org.junit.jupiter.api.Test;

import seedu.address.commons.core.index.Index;
import seedu.address.logic.Messages;
import seedu.address.model.Model;
import seedu.address.model.ModelManager;
import seedu.address.model.UserPrefs;
import seedu.address.model.person.Person;
import seedu.address.model.tag.Tag;
import seedu.address.testutil.PersonBuilder;

public class DeleteTagCommandTest {
private static final Model model = new ModelManager(getTypicalCampusConnect(), new UserPrefs());
private static final String DEFAULT_TAG = "test";
private static final String DEFAULT_TAG_SECOND = "test2";
private static final String TEST_EMAIL = "test@test";
private static final String TEST_PHONE = "84209817";
private static final String TEST_USER = "test user";
@Test
public void execute_validIndexPersonList_success() {
Person firstPerson = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased());
Person p = new PersonBuilder(firstPerson).withName(TEST_USER).withEmail(TEST_EMAIL)
.withPhone(TEST_PHONE).withTags(FRIEND_TAG, OWES_MONEY_TAG).build();
model.setPerson(firstPerson, p);

Person expectedPerson = new PersonBuilder(firstPerson).withName(TEST_USER).withEmail(TEST_EMAIL)
.withPhone(TEST_PHONE).withTags(OWES_MONEY_TAG).build();

Model expectedModel = new ModelManager(getTypicalCampusConnect(), new UserPrefs());
expectedModel.setPerson(firstPerson, expectedPerson);

DeleteTagCommand deleteTagCommand = new DeleteTagCommand(INDEX_FIRST_PERSON, new Tag(FRIEND_TAG));
String expectedMessage = String.format(Messages.MESSAGE_DELETE_TAG_SUCCESS,
new Tag(FRIEND_TAG), p.getName());
assertCommandSuccess(deleteTagCommand, model, expectedMessage, expectedModel);
}

@Test
public void execute_invalidIndexPersonList_throwsCommandException() {
Index outOfBoundIndex = Index.fromOneBased(model.getFilteredPersonList().size() + 1);
DeleteTagCommand deleteTagCommand = new DeleteTagCommand(outOfBoundIndex, new Tag(DEFAULT_TAG));
assertCommandFailure(deleteTagCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
}

@Test
public void execute_personHasNoTag_throwsCommandException() {
Index lastIndex = Index.fromOneBased(model.getFilteredPersonList().size());
DeleteTagCommand deleteTagCommand = new DeleteTagCommand(lastIndex, new Tag(DEFAULT_TAG));
assertCommandFailure(deleteTagCommand, model, Messages.MESSAGE_NO_TAG);
}

@Test
public void equals() {
DeleteTagCommand deleteTagCommandA = new DeleteTagCommand(INDEX_FIRST_PERSON, new Tag(DEFAULT_TAG));
DeleteTagCommand deleteTagCommandB = new DeleteTagCommand(INDEX_SECOND_PERSON, new Tag(DEFAULT_TAG));
DeleteTagCommand deleteTagCommandC = new DeleteTagCommand(INDEX_FIRST_PERSON, new Tag(DEFAULT_TAG_SECOND));
DeleteTagCommand deleteTagCommandD = new DeleteTagCommand(INDEX_FIRST_PERSON, new Tag(DEFAULT_TAG));

assertTrue(deleteTagCommandA.equals(deleteTagCommandD));
assertTrue(deleteTagCommandA.equals(deleteTagCommandA));
assertFalse(deleteTagCommandA.equals(deleteTagCommandB));
assertFalse(deleteTagCommandA.equals(deleteTagCommandC));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public void parse_validArgs_returnsDeleteCommand() {

@Test
public void parse_invalidArgs_throwsParseException() {
assertParseFailure(parser, "a", String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE));
assertParseFailure(parser, "a",
String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package seedu.address.logic.parser;

import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure;
import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess;
import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON;

import org.junit.jupiter.api.Test;

import seedu.address.logic.commands.DeleteTagCommand;
import seedu.address.model.tag.Tag;

public class DeleteTagCommandParserTest {
private DeleteTagCommandParser parser = new DeleteTagCommandParser();

@Test
public void parse_validArgs_returnsDeleteTagCommand() {
assertParseSuccess(parser, "1 t/hello",
new DeleteTagCommand(INDEX_FIRST_PERSON, new Tag("hello")));
}

@Test
public void parse_invalidArgs_throwsParseException() {
assertParseFailure(parser, "a",
String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteTagCommand.MESSAGE_USAGE));
}

}
Loading

0 comments on commit ca486c8

Please sign in to comment.