forked from AY2425S1-CS2103T-T08-2/tp
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
409 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
113 changes: 113 additions & 0 deletions
113
src/main/java/keycontacts/logic/commands/UnassignPiecesCommand.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
package keycontacts.logic.commands; | ||
|
||
import static java.util.Objects.requireNonNull; | ||
import static keycontacts.commons.util.CollectionUtil.requireAllNonNull; | ||
import static keycontacts.logic.parser.CliSyntax.PREFIX_PIECE_NAME; | ||
|
||
import java.util.List; | ||
import java.util.Set; | ||
|
||
import keycontacts.commons.core.index.Index; | ||
import keycontacts.commons.util.ToStringBuilder; | ||
import keycontacts.logic.Messages; | ||
import keycontacts.logic.commands.exceptions.CommandException; | ||
import keycontacts.model.Model; | ||
import keycontacts.model.pianopiece.PianoPiece; | ||
import keycontacts.model.student.Student; | ||
|
||
/** | ||
* Adds a student to the student directory. | ||
*/ | ||
public class UnassignPiecesCommand extends Command { | ||
|
||
public static final String COMMAND_WORD = "unassign"; | ||
|
||
public static final String MESSAGE_USAGE = COMMAND_WORD | ||
+ ": Unassigns one or more piano pieces from the student identified " | ||
+ "by the index number used in the displayed student list\n" | ||
+ "All piano pieces will be unassigned if none are given as argument\n" | ||
+ "Parameters: INDEX (must be a positive integer) " | ||
+ PREFIX_PIECE_NAME + "[PIECE_NAME]...\n" | ||
+ "Example: " + COMMAND_WORD + " 1 " | ||
+ PREFIX_PIECE_NAME + "Für Elise " | ||
+ PREFIX_PIECE_NAME + "Moonlight Sonata"; | ||
|
||
public static final String MESSAGE_SUCCESS = "Piano piece(s): %1$s\nRemoved from student: %2$s"; | ||
public static final String MESSAGE_PIANO_PIECE_NOT_FOUND = "The student does not have" | ||
+ " the piano piece(s) %1$s assigned."; | ||
public static final String MESSAGE_NO_PIANO_PIECE_FOUND = "The student does not have any" | ||
+ " piano pieces assigned"; | ||
private final Index index; | ||
private final Set<PianoPiece> pianoPieces; | ||
|
||
/** | ||
* @param index of the student in the filtered student list to edit | ||
* @param pianoPieces the names of the pieces to be removed | ||
*/ | ||
public UnassignPiecesCommand(Index index, Set<PianoPiece> pianoPieces) { | ||
requireAllNonNull(index, pianoPieces); | ||
|
||
this.index = index; | ||
this.pianoPieces = pianoPieces; | ||
} | ||
|
||
@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 studentToUpdate = lastShownList.get(index.getZeroBased()); | ||
|
||
if (studentToUpdate.getPianoPieces().isEmpty()) { | ||
throw new CommandException(MESSAGE_NO_PIANO_PIECE_FOUND); | ||
} | ||
|
||
Set<PianoPiece> piecesToRemove = pianoPieces; | ||
if (piecesToRemove.isEmpty()) { | ||
piecesToRemove = studentToUpdate.getPianoPieces(); | ||
} | ||
|
||
List<PianoPiece> piecesNotInStudent = piecesToRemove.stream() | ||
.filter(pianoPiece -> !studentToUpdate.getPianoPieces().contains(pianoPiece)).toList(); | ||
if (!piecesNotInStudent.isEmpty()) { | ||
throw new CommandException(String.format(MESSAGE_PIANO_PIECE_NOT_FOUND, | ||
Messages.format(piecesNotInStudent))); | ||
} | ||
|
||
Student updatedStudent = studentToUpdate.withRemovedPianoPieces(piecesToRemove); | ||
|
||
model.setStudent(studentToUpdate, updatedStudent); | ||
|
||
return new CommandResult(String.format(MESSAGE_SUCCESS, | ||
Messages.format(piecesToRemove), Messages.format(updatedStudent))); | ||
} | ||
|
||
@Override | ||
public boolean equals(Object other) { | ||
if (other == this) { | ||
return true; | ||
} | ||
|
||
// instanceof handles nulls | ||
if (!(other instanceof UnassignPiecesCommand)) { | ||
return false; | ||
} | ||
|
||
UnassignPiecesCommand otherUnassignPiecesCommand = (UnassignPiecesCommand) other; | ||
return index.equals(otherUnassignPiecesCommand.index) | ||
&& pianoPieces.equals(otherUnassignPiecesCommand.pianoPieces); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return new ToStringBuilder(this) | ||
.add("index", index) | ||
.add("pianoPieces", pianoPieces) | ||
.toString(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
40 changes: 40 additions & 0 deletions
40
src/main/java/keycontacts/logic/parser/UnassignPiecesCommandParser.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package keycontacts.logic.parser; | ||
|
||
import static keycontacts.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; | ||
import static keycontacts.logic.parser.CliSyntax.PREFIX_PIECE_NAME; | ||
|
||
import java.util.Set; | ||
|
||
import keycontacts.commons.core.index.Index; | ||
import keycontacts.logic.commands.UnassignPiecesCommand; | ||
import keycontacts.logic.parser.exceptions.ParseException; | ||
import keycontacts.model.pianopiece.PianoPiece; | ||
|
||
|
||
/** | ||
* Parses input arguments and creates a new UnassignPieceCommand object | ||
*/ | ||
public class UnassignPiecesCommandParser implements Parser<UnassignPiecesCommand> { | ||
/** | ||
* Parses the given {@code String} of arguments in the context of the UnassignPieceCommand | ||
* and returns a UnassignPieceCommand object for execution. | ||
* @throws ParseException if the user input does not conform the expected format | ||
*/ | ||
public UnassignPiecesCommand parse(String args) throws ParseException { | ||
ArgumentMultimap argMultimap = | ||
ArgumentTokenizer.tokenize(args, PREFIX_PIECE_NAME); | ||
|
||
Index index; | ||
try { | ||
index = ParserUtil.parseIndex(argMultimap.getPreamble()); | ||
} catch (ParseException pe) { | ||
throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, | ||
UnassignPiecesCommand.MESSAGE_USAGE), pe); | ||
} | ||
|
||
Set<PianoPiece> pianoPieces = ParserUtil.parsePianoPieces(argMultimap.getAllValues(PREFIX_PIECE_NAME)); | ||
|
||
return new UnassignPiecesCommand(index, pianoPieces); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
137 changes: 137 additions & 0 deletions
137
src/test/java/keycontacts/logic/commands/UnassignPiecesCommandTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
package keycontacts.logic.commands; | ||
|
||
import static keycontacts.logic.commands.CommandTestUtil.VALID_PIANO_PIECE_BEETHOVEN; | ||
import static keycontacts.logic.commands.CommandTestUtil.VALID_PIANO_PIECE_PACHELBEL; | ||
import static keycontacts.logic.commands.CommandTestUtil.assertCommandFailure; | ||
import static keycontacts.logic.commands.CommandTestUtil.assertCommandSuccess; | ||
import static keycontacts.testutil.Assert.assertThrows; | ||
import static keycontacts.testutil.TypicalIndexes.INDEX_FIRST_STUDENT; | ||
import static keycontacts.testutil.TypicalIndexes.INDEX_SECOND_STUDENT; | ||
import static keycontacts.testutil.TypicalStudents.ALICE; | ||
import static keycontacts.testutil.TypicalStudents.BENSON; | ||
import static keycontacts.testutil.TypicalStudents.getTypicalStudentDirectory; | ||
import static org.junit.jupiter.api.Assertions.assertEquals; | ||
import static org.junit.jupiter.api.Assertions.assertFalse; | ||
import static org.junit.jupiter.api.Assertions.assertTrue; | ||
|
||
import java.util.HashSet; | ||
import java.util.Set; | ||
import java.util.stream.Collectors; | ||
|
||
import org.junit.jupiter.api.Test; | ||
|
||
import keycontacts.commons.core.index.Index; | ||
import keycontacts.logic.Messages; | ||
import keycontacts.model.Model; | ||
import keycontacts.model.ModelManager; | ||
import keycontacts.model.StudentDirectory; | ||
import keycontacts.model.UserPrefs; | ||
import keycontacts.model.pianopiece.PianoPiece; | ||
import keycontacts.model.student.Student; | ||
|
||
public class UnassignPiecesCommandTest { | ||
|
||
private final Set<PianoPiece> validPianoPieces = PianoPiece.getPianoPieceSet(VALID_PIANO_PIECE_BEETHOVEN, | ||
VALID_PIANO_PIECE_PACHELBEL); | ||
|
||
private final Model model = new ModelManager(getTypicalStudentDirectory(), new UserPrefs()); | ||
|
||
@Test | ||
public void constructor_nullIndex_throwsNullPointerException() { | ||
assertThrows(NullPointerException.class, () -> new UnassignPiecesCommand(null, validPianoPieces)); | ||
} | ||
@Test | ||
public void constructor_nullPianoPieces_throwsNullPointerException() { | ||
assertThrows(NullPointerException.class, () -> new UnassignPiecesCommand(INDEX_FIRST_STUDENT, null)); | ||
} | ||
|
||
@Test | ||
public void execute_validIndexAndPianoPiece_success() { | ||
Student student = model.getFilteredStudentList().get(INDEX_FIRST_STUDENT.getZeroBased()); | ||
Set<PianoPiece> studentFirstPianoPiece = student.getPianoPieces().stream() | ||
.limit(1).collect(Collectors.toSet()); | ||
|
||
UnassignPiecesCommand command = new UnassignPiecesCommand(INDEX_FIRST_STUDENT, studentFirstPianoPiece); | ||
|
||
Student updatedStudent = student.withRemovedPianoPieces(studentFirstPianoPiece); | ||
Model expectedModel = new ModelManager(new StudentDirectory(model.getStudentDirectory()), new UserPrefs()); | ||
expectedModel.setStudent(model.getFilteredStudentList().get(0), updatedStudent); | ||
|
||
CommandResult commandResult = new CommandResult(String.format(UnassignPiecesCommand.MESSAGE_SUCCESS, | ||
Messages.format(studentFirstPianoPiece), | ||
Messages.format(student))); | ||
|
||
assertCommandSuccess(command, model, commandResult, expectedModel); | ||
} | ||
@Test | ||
public void execute_indexOutOfBounds_failure() { | ||
Index outOfBoundsIndex = Index.fromOneBased(model.getFilteredStudentList().size() + 1); | ||
UnassignPiecesCommand command = new UnassignPiecesCommand(outOfBoundsIndex, validPianoPieces); | ||
|
||
assertCommandFailure(command, model, Messages.MESSAGE_INVALID_STUDENT_DISPLAYED_INDEX); | ||
} | ||
@Test | ||
public void execute_studentNoPianoPiece_throwsCommandException() { | ||
UnassignPiecesCommand command = new UnassignPiecesCommand(INDEX_FIRST_STUDENT, validPianoPieces); | ||
Student student = model.getFilteredStudentList().get(0); | ||
model.setStudent(model.getFilteredStudentList().get(0), | ||
student.withRemovedPianoPieces(student.getPianoPieces())); | ||
assertCommandFailure(command, model, UnassignPiecesCommand.MESSAGE_NO_PIANO_PIECE_FOUND); | ||
} | ||
@Test | ||
public void execute_allPianoPiecesNotOnStudent_throwsCommandException() { | ||
model.setStudent(model.getFilteredStudentList().get(0), ALICE); | ||
Set<PianoPiece> piecesToRemove = BENSON.getPianoPieces(); | ||
UnassignPiecesCommand command = new UnassignPiecesCommand(INDEX_FIRST_STUDENT, piecesToRemove); | ||
|
||
assertCommandFailure(command, model, String.format(UnassignPiecesCommand.MESSAGE_PIANO_PIECE_NOT_FOUND, | ||
Messages.format(piecesToRemove))); | ||
} | ||
@Test | ||
public void execute_subsetOfPianoPiecesNotOnStudent_throwsCommandException() { | ||
model.setStudent(model.getFilteredStudentList().get(0), ALICE); | ||
Set<PianoPiece> subsetNotPresent = BENSON.getPianoPieces(); | ||
Set<PianoPiece> piecesToRemove = new HashSet<>(subsetNotPresent); | ||
piecesToRemove.addAll(ALICE.getPianoPieces()); | ||
|
||
UnassignPiecesCommand command = new UnassignPiecesCommand(INDEX_FIRST_STUDENT, piecesToRemove); | ||
|
||
assertCommandFailure(command, model, String.format(UnassignPiecesCommand.MESSAGE_PIANO_PIECE_NOT_FOUND, | ||
Messages.format(subsetNotPresent))); | ||
} | ||
@Test | ||
public void equals() { | ||
Set<PianoPiece> bensonPianoPieces = BENSON.getPianoPieces(); | ||
Set<PianoPiece> alicePianoPieces = ALICE.getPianoPieces(); | ||
|
||
UnassignPiecesCommand baseCommand = new UnassignPiecesCommand(INDEX_FIRST_STUDENT, bensonPianoPieces); | ||
|
||
// same object -> returns true | ||
assertTrue(baseCommand.equals(baseCommand)); | ||
|
||
// same values -> returns true | ||
UnassignPiecesCommand identicalCommand = new UnassignPiecesCommand(INDEX_FIRST_STUDENT, bensonPianoPieces); | ||
assertTrue(baseCommand.equals(identicalCommand)); | ||
assertTrue(identicalCommand.equals(baseCommand)); | ||
|
||
// different values -> returns false | ||
UnassignPiecesCommand differentIndexCommand = new UnassignPiecesCommand(INDEX_SECOND_STUDENT, bensonPianoPieces); | ||
assertFalse(baseCommand.equals(differentIndexCommand)); | ||
|
||
UnassignPiecesCommand differentPianoPiecesCommand = new UnassignPiecesCommand(INDEX_FIRST_STUDENT, | ||
alicePianoPieces); | ||
assertFalse(baseCommand.equals(differentPianoPiecesCommand)); | ||
|
||
// null -> returns false | ||
assertFalse(baseCommand.equals(null)); | ||
|
||
} | ||
|
||
@Test | ||
public void toStringMethod() { | ||
UnassignPiecesCommand unassignPiecesCommand = new UnassignPiecesCommand(INDEX_FIRST_STUDENT, validPianoPieces); | ||
String expected = UnassignPiecesCommand.class.getCanonicalName() + "{index=" + INDEX_FIRST_STUDENT + ", " | ||
+ "pianoPieces=" + validPianoPieces + "}"; | ||
assertEquals(expected, unassignPiecesCommand.toString()); | ||
} | ||
} |
Oops, something went wrong.