Skip to content

Commit

Permalink
Merge pull request #97 from cheweejia/tag-retrieve-command
Browse files Browse the repository at this point in the history
Implement Tag Command
  • Loading branch information
cheweejia authored Oct 21, 2021
2 parents 5e1617b + ba6aa5b commit 8791040
Show file tree
Hide file tree
Showing 7 changed files with 292 additions and 12 deletions.
4 changes: 4 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,7 @@ shadowJar {
}

defaultTasks 'clean', 'test'

run {
enableAssertions = true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package seedu.academydirectory.logic.commands;

import static java.util.Objects.requireNonNull;
import static seedu.academydirectory.commons.util.CollectionUtil.requireAllNonNull;
import static seedu.academydirectory.logic.parser.CliSyntax.PREFIX_TAG;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import seedu.academydirectory.commons.core.Messages;
import seedu.academydirectory.commons.core.index.Index;
import seedu.academydirectory.logic.commands.exceptions.CommandException;
import seedu.academydirectory.model.Model;
import seedu.academydirectory.model.student.Student;
import seedu.academydirectory.model.tag.Tag;

/**
* Represents a command that tags a student.
*/
public class TagCommand extends Command {
public static final String COMMAND_WORD = "tag";

public static final String HELP_MESSAGE = "### Assigns tag(s) to a student: `tag`\\\n"
+ "Tutors will be able to tag a student with relevant information.\\\n"
+ "Format: `tag INDEX t/tag`\\\n"
+ "Recommended use of tags:\n"
+ "- Set a reminder to mark the student's mission with a `mission` tag\n"
+ "- Note down the topics that the student needs help with\\\n"
+ "Multiple tags can be assigned in a single command.\n"
+ "Example:\n"
+ "tag 1 t/mission\n"
+ "tag 1 t/streams t/envModel";

public static final String MESSAGE_USAGE = COMMAND_WORD + ": Assigns tag(s) to a student.\n"
+ "Parameters: "
+ "INDEX "
+ PREFIX_TAG + "TAG...\n"
+ "Example: " + COMMAND_WORD + " "
+ "1 "
+ PREFIX_TAG + "mission "
+ PREFIX_TAG + "streams";

public static final String MESSAGE_SUCCESS = "%1$s's tag(s) updated!";

private final Index index;
private final Set<Tag> tag;

/**
* Creates a TagCommand to add the specified {@code Tag}
* @param tag The tag to be assigned.
*/
public TagCommand(Index index, Set<Tag> tag) {
requireAllNonNull(index, tag);
this.index = index;
this.tag = tag;
}

@Override
public CommandResult execute(Model model) throws CommandException {
requireNonNull(model);

List<Student> lastShownList = model.getFilteredStudentList();

if (index.getZeroBased() >= lastShownList.size()) {
throw new CommandException(Messages.MESSAGE_INVALID_STUDENT_DISPLAYED_INDEX);
}

Student studentToEdit = lastShownList.get(index.getZeroBased());
Set<Tag> editedTagSet = new HashSet<>(tag);
Student editedStudent = new Student(
studentToEdit.getName(), studentToEdit.getPhone(), studentToEdit.getEmail(),
studentToEdit.getTelegram(), studentToEdit.getStudioRecord(),
studentToEdit.getAssessment(), editedTagSet);
model.setStudent(studentToEdit, editedStudent);
model.updateFilteredStudentList(Model.PREDICATE_SHOW_ALL_STUDENTS);
return new CommandResult(String.format(MESSAGE_SUCCESS, studentToEdit.getName()));
}

@Override
public boolean equals(Object other) {
// short circuit if same object
if (other == this) {
return true;
}

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

// state check
TagCommand e = (TagCommand) other;
return index.equals(e.index)
&& tag.equals(e.tag);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import seedu.academydirectory.logic.commands.RetrieveCommand;
import seedu.academydirectory.logic.commands.ShowCommand;
import seedu.academydirectory.logic.commands.SortCommand;
import seedu.academydirectory.logic.commands.TagCommand;
import seedu.academydirectory.logic.parser.exceptions.ParseException;

/**
Expand Down Expand Up @@ -93,6 +94,9 @@ public Command parseCommand(String userInput) throws ParseException {
case SortCommand.COMMAND_WORD:
return new SortCommandParser().parse(arguments);

case TagCommand.COMMAND_WORD:
return new TagCommandParser().parse(arguments);

case ExitCommand.COMMAND_WORD:
return new ExitCommand();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package seedu.academydirectory.logic.parser;

import static java.util.Objects.requireNonNull;
import static seedu.academydirectory.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
import static seedu.academydirectory.logic.parser.CliSyntax.PREFIX_TAG;

import java.util.Set;
import java.util.stream.Stream;

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

public class TagCommandParser implements Parser<TagCommand> {

/**
* Parses the given {@code String} of arguments in the context of the TagCommand
* and returns an TagCommand object for execution.
* @throws ParseException if the user input does not conform the expected format
*/
public TagCommand parse(String args) throws ParseException {
requireNonNull(args);
ArgumentMultimap argMultimap =
ArgumentTokenizer.tokenize(args, PREFIX_TAG);
if (!arePrefixesPresent(argMultimap, PREFIX_TAG)
|| argMultimap.getPreamble().isEmpty()) {
throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, TagCommand.MESSAGE_USAGE));
}

Index index = ParserUtil.parseIndex(argMultimap.getPreamble());
Set<Tag> tagList = ParserUtil.parseTags(argMultimap.getAllValues(PREFIX_TAG));

return new TagCommand(index, tagList);
}

/**
* Returns true if none of the prefixes contains empty {@code Optional} values in the given
* {@code ArgumentMultimap}.
*/
private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) {
return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent());
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package seedu.academydirectory.logic.commands;

import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static seedu.academydirectory.logic.commands.CommandTestUtil.assertCommandFailure;
import static seedu.academydirectory.logic.commands.CommandTestUtil.assertCommandSuccess;
import static seedu.academydirectory.testutil.Assert.assertThrows;
Expand Down Expand Up @@ -71,28 +71,25 @@ public void equals() {
// same values -> returns true
GradeCommand commandWithSameValues =
new GradeCommand(INDEX_FIRST_STUDENT, validAssessmentName1, validGrade1);
assertTrue(standardCommand.equals(commandWithSameValues));
assertEquals(standardCommand, commandWithSameValues);

// same object -> returns true
assertTrue(standardCommand.equals(standardCommand));
assertEquals(standardCommand, standardCommand);

// null -> returns false
assertFalse(standardCommand.equals(null));
assertNotEquals(null, standardCommand);

// different types -> returns false
assertFalse(standardCommand.equals(new ClearCommand()));
assertNotEquals(standardCommand, new ClearCommand());

// different index -> returns false
assertFalse(standardCommand.equals(
new GradeCommand(INDEX_SECOND_STUDENT, validAssessmentName1, validGrade1)));
assertNotEquals(standardCommand, new GradeCommand(INDEX_SECOND_STUDENT, validAssessmentName1, validGrade1));

// different assessment -> returns false
assertFalse(standardCommand.equals(
new GradeCommand(INDEX_FIRST_STUDENT, validAssessmentName2, validGrade1)));
assertNotEquals(standardCommand, new GradeCommand(INDEX_FIRST_STUDENT, validAssessmentName2, validGrade1));

// different grade -> returns false
assertFalse(standardCommand.equals(
new GradeCommand(INDEX_FIRST_STUDENT, validAssessmentName1, validGrade2)));
assertNotEquals(standardCommand, new GradeCommand(INDEX_FIRST_STUDENT, validAssessmentName1, validGrade2));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package seedu.academydirectory.logic.commands;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static seedu.academydirectory.logic.commands.CommandTestUtil.assertCommandFailure;
import static seedu.academydirectory.logic.commands.CommandTestUtil.assertCommandSuccess;
import static seedu.academydirectory.testutil.Assert.assertThrows;
import static seedu.academydirectory.testutil.TypicalIndexes.INDEX_FIRST_STUDENT;
import static seedu.academydirectory.testutil.TypicalIndexes.INDEX_SECOND_STUDENT;
import static seedu.academydirectory.testutil.TypicalStudents.getTypicalAcademyDirectory;

import java.util.HashSet;
import java.util.Set;

import org.junit.jupiter.api.Test;

import seedu.academydirectory.commons.core.Messages;
import seedu.academydirectory.commons.core.index.Index;
import seedu.academydirectory.model.AcademyDirectory;
import seedu.academydirectory.model.Model;
import seedu.academydirectory.model.ModelManager;
import seedu.academydirectory.model.UserPrefs;
import seedu.academydirectory.model.student.Student;
import seedu.academydirectory.model.tag.Tag;
import seedu.academydirectory.testutil.StudentBuilder;

class TagCommandTest {

private final Model model = new ModelManager(getTypicalAcademyDirectory(), new UserPrefs());
private final Set<Tag> tagSet = new HashSet<>();
private final String validTagName1 = "mission";
private final String validTagName2 = "streams2";

@Test
public void constructor_nullStudent_throwsNullPointerException() {
assertThrows(NullPointerException.class, () -> new TagCommand(null, null));
}

@Test
void execute_addTag_success() {
Student firstStudent = model.getFilteredStudentList().get(0);

Student editedStudent = new StudentBuilder(firstStudent).withTags().build();
TagCommand addTagCommand =
new TagCommand(INDEX_FIRST_STUDENT, tagSet);
String expectedMessage =
String.format(TagCommand.MESSAGE_SUCCESS, editedStudent.getName());
Model expectedModel = new ModelManager(new AcademyDirectory(model.getAcademyDirectory()), new UserPrefs());
expectedModel.setStudent(firstStudent, editedStudent);
assertCommandSuccess(addTagCommand, model, expectedMessage, expectedModel);
}

@Test
public void execute_invalidPersonIndexUnfilteredList_failure() {
Index outOfBoundIndex = Index.fromOneBased(model.getFilteredStudentList().size() + 1);
TagCommand tagCommand = new TagCommand(outOfBoundIndex, tagSet);

assertCommandFailure(tagCommand, model, Messages.MESSAGE_INVALID_STUDENT_DISPLAYED_INDEX);
}

@Test
public void equals() {
Set<Tag> tagSet1 = new HashSet<>();
Set<Tag> tagSet2 = new HashSet<>();
tagSet1.add(new Tag(validTagName1));
tagSet2.add(new Tag(validTagName2));

final TagCommand standardCommand =
new TagCommand(INDEX_FIRST_STUDENT, tagSet1);

// same values -> returns true
TagCommand commandWithSameValues =
new TagCommand(INDEX_FIRST_STUDENT, tagSet1);
assertEquals(standardCommand, commandWithSameValues);

// same object -> returns true
assertEquals(standardCommand, standardCommand);

// null -> returns false
assertNotEquals(null, standardCommand);

// different types -> returns false
assertNotEquals(standardCommand, new ClearCommand());

// different index -> returns false
assertNotEquals(standardCommand, new TagCommand(INDEX_SECOND_STUDENT, tagSet1));

// different grade -> returns false
assertNotEquals(standardCommand, new TagCommand(INDEX_FIRST_STUDENT, tagSet2));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package seedu.academydirectory.logic.parser;

import static seedu.academydirectory.logic.parser.CliSyntax.PREFIX_TAG;
import static seedu.academydirectory.logic.parser.CommandParserTestUtil.assertParseFailure;
import static seedu.academydirectory.logic.parser.CommandParserTestUtil.assertParseSuccess;
import static seedu.academydirectory.testutil.TypicalIndexes.INDEX_FIRST_STUDENT;

import java.util.HashSet;
import java.util.Set;

import org.junit.jupiter.api.Test;

import seedu.academydirectory.logic.commands.TagCommand;
import seedu.academydirectory.model.tag.Tag;

public class TagCommandParserTest {
private final TagCommandParser parser = new TagCommandParser();
private final Set<Tag> tag = new HashSet<>();
private final String validTagName = "mission";
private final String invalidTagName = "!!!!!!";
private final String expectedInvalidTagMessage = Tag.MESSAGE_CONSTRAINTS;

@Test
public void parse_validArgument_success() {
String input = INDEX_FIRST_STUDENT.getOneBased() + " "
+ PREFIX_TAG + validTagName;
Tag validTag = new Tag(validTagName);
tag.clear();
tag.add(validTag);
TagCommand expectedCommand =
new TagCommand(INDEX_FIRST_STUDENT, tag);

assertParseSuccess(parser, input, expectedCommand);
}

@Test
public void parse_invalidArgument_failure() {
String inputInvalidTag = INDEX_FIRST_STUDENT.getOneBased() + " "
+ PREFIX_TAG + invalidTagName;

assertParseFailure(parser, inputInvalidTag, expectedInvalidTagMessage);
}
}

0 comments on commit 8791040

Please sign in to comment.