diff --git a/src/main/java/seedu/address/commons/core/Messages.java b/src/main/java/seedu/address/commons/core/Messages.java index 507f0711042..d3f56fcced9 100644 --- a/src/main/java/seedu/address/commons/core/Messages.java +++ b/src/main/java/seedu/address/commons/core/Messages.java @@ -12,4 +12,7 @@ public class Messages { public static final String MESSAGE_MODULE_DETAILS_LISTED = "The details of %s are listed"; public static final String MESSAGE_MODULE_NOT_FOUND = "%s does not exist in the ModBook!"; + public static final String MESSAGE_INVALID_MODULE_DISPLAYED_INDEX = "The module index provided is invalid"; + public static final String MESSAGE_INVALID_LESSON_DISPLAYED_INDEX = "The lesson index provided is invalid"; + public static final String MESSAGE_INVALID_EXAM_DISPLAYED_INDEX = "The exam index provided is invalid"; } diff --git a/src/main/java/seedu/address/logic/commands/DeleteCommand.java b/src/main/java/seedu/address/logic/commands/DeleteCommand.java deleted file mode 100644 index 02fd256acba..00000000000 --- a/src/main/java/seedu/address/logic/commands/DeleteCommand.java +++ /dev/null @@ -1,53 +0,0 @@ -package seedu.address.logic.commands; - -import static java.util.Objects.requireNonNull; - -import java.util.List; - -import seedu.address.commons.core.Messages; -import seedu.address.commons.core.index.Index; -import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.model.Model; -import seedu.address.model.person.Person; - -/** - * Deletes a person identified using it's displayed index 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"; - - public static final String MESSAGE_DELETE_PERSON_SUCCESS = "Deleted Person: %1$s"; - - private final Index targetIndex; - - public DeleteCommand(Index targetIndex) { - this.targetIndex = targetIndex; - } - - @Override - public CommandResult execute(Model model) throws CommandException { - requireNonNull(model); - List lastShownList = model.getFilteredPersonList(); - - if (targetIndex.getZeroBased() >= lastShownList.size()) { - throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); - } - - Person personToDelete = lastShownList.get(targetIndex.getZeroBased()); - model.deletePerson(personToDelete); - return new CommandResult(String.format(MESSAGE_DELETE_PERSON_SUCCESS, personToDelete)); - } - - @Override - public boolean equals(Object other) { - return other == this // short circuit if same object - || (other instanceof DeleteCommand // instanceof handles nulls - && targetIndex.equals(((DeleteCommand) other).targetIndex)); // state check - } -} diff --git a/src/main/java/seedu/address/logic/commands/delete/DeleteCommand.java b/src/main/java/seedu/address/logic/commands/delete/DeleteCommand.java new file mode 100644 index 00000000000..5516bab9c6f --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/delete/DeleteCommand.java @@ -0,0 +1,12 @@ +package seedu.address.logic.commands.delete; + +import seedu.address.logic.commands.Command; + +public abstract class DeleteCommand extends Command { + public static final String COMMAND_WORD = "delete"; + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Deletes a mod/lesson/exam from the mod book. " + + "Please specify what you would like to delete\n" + + "Example:\n" + COMMAND_WORD + " mod \n" + + COMMAND_WORD + " lesson \n" + + COMMAND_WORD + " exam \n"; +} diff --git a/src/main/java/seedu/address/logic/commands/delete/DeleteExamCommand.java b/src/main/java/seedu/address/logic/commands/delete/DeleteExamCommand.java new file mode 100644 index 00000000000..6568b044f82 --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/delete/DeleteExamCommand.java @@ -0,0 +1,62 @@ +package seedu.address.logic.commands.delete; + +import static java.util.Objects.requireNonNull; +import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; +import static seedu.address.logic.parser.CliSyntax.PREFIX_CODE; + +import java.util.List; + +import seedu.address.commons.core.Messages; +import seedu.address.commons.core.index.Index; +import seedu.address.logic.commands.CommandResult; +import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.model.Model; +import seedu.address.model.module.Module; +import seedu.address.model.module.ModuleCode; +import seedu.address.model.module.exam.Exam; + +public class DeleteExamCommand extends DeleteCommand { + public static final String MESSAGE_DELETE_EXAM_SUCCESS = "Deleted Exam %s from Module %s"; + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Deletes an Exam from a " + + "specified Module from the Mod book." + + "\nParameters: Index " + + PREFIX_CODE + "MOD_CODE" + + "\nExample: " + COMMAND_WORD + " exam 1 " + + PREFIX_CODE + "CS2103T"; + private final Index targetIndex; + private final ModuleCode targetModuleCode; + + /** + * Creates an DeleteExamCommand to delete the Exam at specified {@code Index} of the specified {@code Module}. + */ + public DeleteExamCommand(Index targetIndex, ModuleCode targetModuleCode) { + requireAllNonNull(targetIndex, targetModuleCode); + this.targetIndex = targetIndex; + this.targetModuleCode = targetModuleCode; + } + + @Override + public CommandResult execute(Model model) throws CommandException { + requireNonNull(model); + Module module = model.getModule(targetModuleCode); + List exams = module.getExams(); + if (targetIndex.getZeroBased() >= exams.size()) { + throw new CommandException(Messages.MESSAGE_INVALID_EXAM_DISPLAYED_INDEX); + } + Exam examToDelete = exams.get(targetIndex.getZeroBased()); + model.deleteExam(module, examToDelete); + return new CommandResult(String.format(MESSAGE_DELETE_EXAM_SUCCESS, examToDelete.getName(), targetModuleCode)); + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + if (!(other instanceof DeleteExamCommand)) { + return false; + } + return targetIndex.equals(((DeleteExamCommand) other).targetIndex) + && targetModuleCode.equals(((DeleteExamCommand) other).targetModuleCode); + } +} diff --git a/src/main/java/seedu/address/logic/commands/delete/DeleteLessonCommand.java b/src/main/java/seedu/address/logic/commands/delete/DeleteLessonCommand.java new file mode 100644 index 00000000000..e31f7fe0b3f --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/delete/DeleteLessonCommand.java @@ -0,0 +1,63 @@ +package seedu.address.logic.commands.delete; + +import static java.util.Objects.requireNonNull; +import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; +import static seedu.address.logic.parser.CliSyntax.PREFIX_CODE; + +import java.util.List; + +import seedu.address.commons.core.Messages; +import seedu.address.commons.core.index.Index; +import seedu.address.logic.commands.CommandResult; +import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.model.Model; +import seedu.address.model.module.Module; +import seedu.address.model.module.ModuleCode; +import seedu.address.model.module.lesson.Lesson; + +public class DeleteLessonCommand extends DeleteCommand { + public static final String MESSAGE_DELETE_LESSON_SUCCESS = "Deleted Lesson %s from Module %s"; + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Deletes a Lesson from a " + + "specified Module from the Mod book." + + "\nParameters: Index " + + PREFIX_CODE + "MOD_CODE" + + "\nExample: " + COMMAND_WORD + " lesson 1 " + + PREFIX_CODE + "CS1231S"; + private final Index targetIndex; + private final ModuleCode targetModuleCode; + + /** + * Creates an DeleteLessonCommand to delete the Lesson at specified {@code Index} of the specified {@code Module}. + */ + public DeleteLessonCommand(Index targetIndex, ModuleCode targetModuleCode) { + requireAllNonNull(targetIndex, targetModuleCode); + this.targetIndex = targetIndex; + this.targetModuleCode = targetModuleCode; + } + + @Override + public CommandResult execute(Model model) throws CommandException { + requireNonNull(model); + Module module = model.getModule(targetModuleCode); + List lessons = module.getLessons(); + if (targetIndex.getZeroBased() >= lessons.size()) { + throw new CommandException(Messages.MESSAGE_INVALID_LESSON_DISPLAYED_INDEX); + } + Lesson lessonToDelete = lessons.get(targetIndex.getZeroBased()); + model.deleteLesson(module, lessonToDelete); + return new CommandResult(String.format(MESSAGE_DELETE_LESSON_SUCCESS, + lessonToDelete.getName(), targetModuleCode)); + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + if (!(other instanceof DeleteLessonCommand)) { + return false; + } + return targetIndex.equals(((DeleteLessonCommand) other).targetIndex) + && targetModuleCode.equals(((DeleteLessonCommand) other).targetModuleCode); + } +} diff --git a/src/main/java/seedu/address/logic/commands/delete/DeleteModCommand.java b/src/main/java/seedu/address/logic/commands/delete/DeleteModCommand.java new file mode 100644 index 00000000000..01e140e4cb9 --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/delete/DeleteModCommand.java @@ -0,0 +1,51 @@ +package seedu.address.logic.commands.delete; + +import static java.util.Objects.requireNonNull; + +import java.util.List; + +import seedu.address.commons.core.Messages; +import seedu.address.commons.core.index.Index; +import seedu.address.logic.commands.CommandResult; +import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.model.Model; +import seedu.address.model.module.Module; + +public class DeleteModCommand extends DeleteCommand { + public static final String MESSAGE_DELETE_MODULE_SUCCESS = "Deleted Module: %1$s"; + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Deletes a module from the Mod book. " + + "\nParameters: Index" + + "\nExample: " + COMMAND_WORD + " mod 1"; + private final Index targetIndex; + + /** + * Creates an DeleteModCommand to delete the module at specified {@code Index} + */ + public DeleteModCommand(Index targetIndex) { + requireNonNull(targetIndex); + this.targetIndex = targetIndex; + } + + @Override + public CommandResult execute(Model model) throws CommandException { + requireNonNull(model); + List lastShownList = model.getFilteredModuleList(); + if (targetIndex.getZeroBased() >= lastShownList.size()) { + throw new CommandException(Messages.MESSAGE_INVALID_MODULE_DISPLAYED_INDEX); + } + Module moduleToDelete = lastShownList.get(targetIndex.getZeroBased()); + model.deleteModule(moduleToDelete); + return new CommandResult(String.format(MESSAGE_DELETE_MODULE_SUCCESS, moduleToDelete)); + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + if (!(other instanceof DeleteModCommand)) { + return false; + } + return targetIndex.equals(((DeleteModCommand) other).targetIndex); + } +} diff --git a/src/main/java/seedu/address/logic/parser/AddressBookParser.java b/src/main/java/seedu/address/logic/parser/AddressBookParser.java index c65fcbddb54..fc866bf21d5 100644 --- a/src/main/java/seedu/address/logic/parser/AddressBookParser.java +++ b/src/main/java/seedu/address/logic/parser/AddressBookParser.java @@ -8,7 +8,6 @@ import seedu.address.logic.commands.ClearCommand; import seedu.address.logic.commands.Command; -import seedu.address.logic.commands.DeleteCommand; import seedu.address.logic.commands.DetailCommand; import seedu.address.logic.commands.EditCommand; import seedu.address.logic.commands.ExitCommand; @@ -16,6 +15,7 @@ import seedu.address.logic.commands.GuiState; import seedu.address.logic.commands.HelpCommand; import seedu.address.logic.commands.add.AddCommand; +import seedu.address.logic.commands.delete.DeleteCommand; import seedu.address.logic.commands.list.ListCommand; import seedu.address.logic.parser.exceptions.ParseException; diff --git a/src/main/java/seedu/address/logic/parser/DeleteCommandParser.java b/src/main/java/seedu/address/logic/parser/DeleteCommandParser.java index e4e46bb2fab..dc091db65cd 100644 --- a/src/main/java/seedu/address/logic/parser/DeleteCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/DeleteCommandParser.java @@ -1,16 +1,25 @@ package seedu.address.logic.parser; import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static seedu.address.logic.parser.CliSyntax.PREFIX_CODE; +import static seedu.address.logic.parser.ParserUtil.arePrefixesPresent; import seedu.address.commons.core.index.Index; -import seedu.address.logic.commands.DeleteCommand; import seedu.address.logic.commands.GuiState; +import seedu.address.logic.commands.delete.DeleteCommand; +import seedu.address.logic.commands.delete.DeleteExamCommand; +import seedu.address.logic.commands.delete.DeleteLessonCommand; +import seedu.address.logic.commands.delete.DeleteModCommand; +import seedu.address.logic.parser.exceptions.GuiStateException; import seedu.address.logic.parser.exceptions.ParseException; +import seedu.address.model.module.ModuleCode; /** * Parses input arguments and creates a new DeleteCommand object */ public class DeleteCommandParser implements Parser { + public static final String MESSAGE_WRONG_VIEW_DETAILS = "Please execute the \"detail\" command first!"; + public static final String MESSAGE_WRONG_VIEW_SUMMARY = "Please execute \"list mod\" first!"; /** * Parses the given {@code String} of arguments in the context of the DeleteCommand @@ -18,13 +27,66 @@ public class DeleteCommandParser implements Parser { * @throws ParseException if the user input does not conform the expected format */ public DeleteCommand parse(String args, GuiState guiState) throws ParseException { - try { - Index index = ParserUtil.parseIndex(args); - return new DeleteCommand(index); - } catch (ParseException pe) { - throw new ParseException( - String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE), pe); + Type type = ParserUtil.parseFirstArg(args, String.format(MESSAGE_INVALID_COMMAND_FORMAT, + DeleteCommand.MESSAGE_USAGE)); + switch(type) { + case MOD: + return parseDeleteMod(args, guiState); + case LESSON: + return parseDeleteLesson(args, guiState); + case EXAM: + return parseDeleteExam(args, guiState); + default: + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE)); } } + /** + * Parses the given {@code String} of arguments in the context of the DeleteModCommand + * and returns a DeleteModCommand object for execution. + * @throws ParseException if the user input does not conform the expected format. + */ + public DeleteModCommand parseDeleteMod(String args, GuiState guiState) throws ParseException { + if (guiState != GuiState.SUMMARY) { + throw new GuiStateException(MESSAGE_WRONG_VIEW_SUMMARY); + } + Index index = ParserUtil.parseFirstIndex(args); + return new DeleteModCommand(index); + } + + /** + * Parses the given {@code String} of arguments in the context of the DeleteLessonCommand + * and returns a DeleteLessonCommand object for execution. + * @throws ParseException if the user input does not conform the expected format. + */ + public DeleteLessonCommand parseDeleteLesson(String args, GuiState guiState) throws ParseException { + if (guiState != GuiState.DETAILS) { + throw new GuiStateException(MESSAGE_WRONG_VIEW_DETAILS); + } + ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, PREFIX_CODE); + if (!arePrefixesPresent(argMultimap, PREFIX_CODE)) { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteLessonCommand.MESSAGE_USAGE)); + } + Index index = ParserUtil.parseFirstIndex(args); + ModuleCode modCode = ParserUtil.parseModuleCode(argMultimap.getValue(PREFIX_CODE).get()); + return new DeleteLessonCommand(index, modCode); + } + + /** + * Parses the given {@code String} of arguments in the context of the DeleteExamCommand + * and returns a DeleteExamCommand object for execution. + * @throws ParseException if the user input does not conform the expected format. + */ + public DeleteExamCommand parseDeleteExam(String args, GuiState guiState) throws ParseException { + if (guiState != GuiState.DETAILS) { + throw new GuiStateException(MESSAGE_WRONG_VIEW_DETAILS); + } + ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, PREFIX_CODE); + if (!arePrefixesPresent(argMultimap, PREFIX_CODE)) { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteExamCommand.MESSAGE_USAGE)); + } + Index index = ParserUtil.parseFirstIndex(args); + ModuleCode modCode = ParserUtil.parseModuleCode(argMultimap.getValue(PREFIX_CODE).get()); + return new DeleteExamCommand(index, modCode); + } } diff --git a/src/main/java/seedu/address/logic/parser/ParserUtil.java b/src/main/java/seedu/address/logic/parser/ParserUtil.java index 4e18cd11472..df20a7b9167 100644 --- a/src/main/java/seedu/address/logic/parser/ParserUtil.java +++ b/src/main/java/seedu/address/logic/parser/ParserUtil.java @@ -36,6 +36,7 @@ public class ParserUtil { public static final String MESSAGE_INVALID_INDEX = "Index is not a non-zero unsigned integer."; + public static final String MESSAGE_NO_INDEXES_FOUND = "Index not found in command."; /** * Parses {@code oneBasedIndex} into an {@code Index} and returns it. Leading and trailing whitespaces will be @@ -51,6 +52,22 @@ public static Index parseIndex(String oneBasedIndex) throws ParseException { return Index.fromOneBased(Integer.parseInt(trimmedIndex)); } + /** + * Parses the first integer seen in {@code args} (split by " ") into an {@code Index} and returns it. + * Leading and trailing whitespaces will be trimmed. + * + * @throws ParseException if no indexes found in args (no non-zero unsigned integer). + */ + public static Index parseFirstIndex(String args) throws ParseException { + String trimmedArgs = args.trim(); + for (String arg : trimmedArgs.split(" ")) { + if (StringUtil.isNonZeroUnsignedInteger(arg)) { + return Index.fromOneBased(Integer.parseInt(arg)); + } + } + throw new ParseException(MESSAGE_NO_INDEXES_FOUND); + } + /** * Parses a {@code String name} into a {@code Name}. * Leading and trailing whitespaces will be trimmed. diff --git a/src/main/java/seedu/address/model/ModBook.java b/src/main/java/seedu/address/model/ModBook.java index 47239f23bd7..d81e8ecf7af 100644 --- a/src/main/java/seedu/address/model/ModBook.java +++ b/src/main/java/seedu/address/model/ModBook.java @@ -7,6 +7,8 @@ import javafx.collections.ObservableList; import seedu.address.model.module.Module; import seedu.address.model.module.UniqueModuleList; +import seedu.address.model.module.exam.Exam; +import seedu.address.model.module.lesson.Lesson; /** * Wraps all data at the address-book level @@ -92,6 +94,22 @@ public void removeModule(Module key) { modules.remove(key); } + /** + * Removes Exam {@code target} from the Module {@code module}. + * {@code target} must exist in {@code module}'s exams list. + */ + public void removeExam(Module module, Exam target) { + module.getExams().remove(target); + } + + /** + * Removes Lesson {@code target} from the Module {@code module}. + * {@code target} must exist in {@code module}'s lessons list. + */ + public void removeLesson(Module module, Lesson target) { + module.getLessons().remove(target); + } + //// util methods @Override diff --git a/src/main/java/seedu/address/model/Model.java b/src/main/java/seedu/address/model/Model.java index 2f203d443d2..1ab1ae4cb9c 100644 --- a/src/main/java/seedu/address/model/Model.java +++ b/src/main/java/seedu/address/model/Model.java @@ -136,6 +136,16 @@ public interface Model { */ Module getModule(ModuleCode modCode) throws CommandException; + /** + * Deletes the Exam from the specified module's lessons list. + */ + void deleteExam(Module module, Exam target); + + /** + * Deletes the Lesson from the specified module's lessons list. + */ + void deleteLesson(Module module, Lesson target); + /** * Checks if a module has the lesson */ diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java index e6014b3bb83..2d4decd1b7b 100644 --- a/src/main/java/seedu/address/model/ModelManager.java +++ b/src/main/java/seedu/address/model/ModelManager.java @@ -217,6 +217,16 @@ public Module getModule(ModuleCode modCode) throws CommandException { return module.get(); } + @Override + public void deleteExam(Module module, Exam target) { + modBook.removeExam(module, target); + } + + @Override + public void deleteLesson(Module module, Lesson target) { + modBook.removeLesson(module, target); + } + @Override public boolean moduleHasLesson(Module module, Lesson lesson) { List lessons = module.getLessons(); diff --git a/src/main/java/seedu/address/model/module/Link.java b/src/main/java/seedu/address/model/module/Link.java index 368da13e6e1..b0abb02a0b5 100644 --- a/src/main/java/seedu/address/model/module/Link.java +++ b/src/main/java/seedu/address/model/module/Link.java @@ -30,6 +30,10 @@ public Link(String link) { this.link = link; } + public String getLink() { + return link; + } + /** * Returns true if a given string is a valid link. */ diff --git a/src/main/java/seedu/address/model/module/ModBookDate.java b/src/main/java/seedu/address/model/module/ModBookDate.java index f0ca62e821b..d9602e311cc 100644 --- a/src/main/java/seedu/address/model/module/ModBookDate.java +++ b/src/main/java/seedu/address/model/module/ModBookDate.java @@ -29,6 +29,14 @@ public ModBookDate(String date) { this.date = LocalDate.parse(date, PARSE_FORMATTER); } + private ModBookDate(LocalDate date) { + this.date = date; + } + + public ModBookDate deepCopy() { + return new ModBookDate(date); + } + /** * Returns true if a given string is a valid date */ diff --git a/src/main/java/seedu/address/model/module/ModBookTime.java b/src/main/java/seedu/address/model/module/ModBookTime.java index 5fd8ac588cc..8f93185def4 100644 --- a/src/main/java/seedu/address/model/module/ModBookTime.java +++ b/src/main/java/seedu/address/model/module/ModBookTime.java @@ -29,6 +29,14 @@ public ModBookTime(String time) { this.time = LocalTime.parse(time, PARSE_FORMATTER); } + private ModBookTime(LocalTime time) { + this.time = time; + } + + public ModBookTime deepCopy() { + return new ModBookTime(time); + } + /** * Returns true if a given string is a valid time */ diff --git a/src/main/java/seedu/address/model/module/Module.java b/src/main/java/seedu/address/model/module/Module.java index 060cd3b2833..1326263f8ab 100644 --- a/src/main/java/seedu/address/model/module/Module.java +++ b/src/main/java/seedu/address/model/module/Module.java @@ -7,6 +7,7 @@ import java.util.List; import java.util.Objects; import java.util.Optional; +import java.util.stream.Collectors; import seedu.address.model.module.exam.Exam; import seedu.address.model.module.lesson.Lesson; @@ -90,6 +91,17 @@ public Exam getNextExam() { return Collections.min(exams); } + /** + * Returns a deepCopy of the Module object. + */ + public Module deepCopy() { + ModuleCode newModCode = new ModuleCode(moduleCode.moduleCode); + Optional newModName = moduleName.map(modName -> new ModuleName(modName.getModuleName())); + List newLessons = lessons.stream().map(Lesson::deepCopy).collect(Collectors.toList()); + List newExams = exams.stream().map(Exam::deepCopy).collect(Collectors.toList()); + return new Module(newModCode, newModName, newLessons, newExams); + } + /** * Returns true if both modules have the same identity and attributes. * This defines a stronger notion of equality between two modules. diff --git a/src/main/java/seedu/address/model/module/ModuleCode.java b/src/main/java/seedu/address/model/module/ModuleCode.java index ea68c55ac4a..552eec9fea2 100644 --- a/src/main/java/seedu/address/model/module/ModuleCode.java +++ b/src/main/java/seedu/address/model/module/ModuleCode.java @@ -33,6 +33,10 @@ public ModuleCode(String moduleCode) { this.moduleCode = moduleCode.toUpperCase(); } + public String getModuleCode() { + return moduleCode; + } + /** * Returns true if a given string is a valid code. * diff --git a/src/main/java/seedu/address/model/module/ModuleName.java b/src/main/java/seedu/address/model/module/ModuleName.java index 6db50c38450..95f9986b9a5 100644 --- a/src/main/java/seedu/address/model/module/ModuleName.java +++ b/src/main/java/seedu/address/model/module/ModuleName.java @@ -36,6 +36,10 @@ public static boolean isValidModuleName(String test) { return test.matches(VALIDATION_REGEX); } + public String getModuleName() { + return moduleName; + } + @Override public String toString() { return moduleName; diff --git a/src/main/java/seedu/address/model/module/Timeslot.java b/src/main/java/seedu/address/model/module/Timeslot.java index d941be2ab2e..33065551a53 100644 --- a/src/main/java/seedu/address/model/module/Timeslot.java +++ b/src/main/java/seedu/address/model/module/Timeslot.java @@ -28,6 +28,10 @@ public Timeslot(ModBookTime startTime, ModBookTime endTime) { this.endTime = endTime; } + public Timeslot deepCopy() { + return new Timeslot(startTime.deepCopy(), endTime.deepCopy()); + } + /** * Returns true if the given startTime is before the given endTime. */ diff --git a/src/main/java/seedu/address/model/module/Venue.java b/src/main/java/seedu/address/model/module/Venue.java index db39fd88911..c574c7e5663 100644 --- a/src/main/java/seedu/address/model/module/Venue.java +++ b/src/main/java/seedu/address/model/module/Venue.java @@ -31,6 +31,10 @@ public Venue(String venue) { fullVenue = venue; } + public String getFullVenue() { + return fullVenue; + } + /** * Returns true if a given string is a valid venue. */ diff --git a/src/main/java/seedu/address/model/module/exam/Exam.java b/src/main/java/seedu/address/model/module/exam/Exam.java index 21940cfb10d..0a0ff7d358b 100644 --- a/src/main/java/seedu/address/model/module/exam/Exam.java +++ b/src/main/java/seedu/address/model/module/exam/Exam.java @@ -59,6 +59,17 @@ public Optional getLink() { return link; } + /** + * Returns a deepCopy of the Exam object. + */ + public Exam deepCopy() { + ExamName newExamName = new ExamName(name.getFullExamName()); + ModBookDate newModBookDate = date.deepCopy(); + Timeslot newTimeslot = timeslot.deepCopy(); + Optional newVenue = venue.map(venue -> new Venue(venue.getFullVenue())); + Optional newLink = link.map(link -> new Link(link.getLink())); + return new Exam(newExamName, newModBookDate, newTimeslot, newVenue, newLink); + } /** * Returns true if both exams have the same name. diff --git a/src/main/java/seedu/address/model/module/exam/ExamName.java b/src/main/java/seedu/address/model/module/exam/ExamName.java index 16dac9227b1..9791de09618 100644 --- a/src/main/java/seedu/address/model/module/exam/ExamName.java +++ b/src/main/java/seedu/address/model/module/exam/ExamName.java @@ -10,12 +10,10 @@ public class ExamName { public static final String MESSAGE_CONSTRAINTS = "Exam name should not be blank"; - /* * The first character of the exam must not be a whitespace. */ public static final String VALIDATION_REGEX = "^\\S.*$"; - public final String fullExamName; /** @@ -29,6 +27,10 @@ public ExamName(String examName) { fullExamName = examName; } + public String getFullExamName() { + return fullExamName; + } + /** * Returns true if a given string is a valid name. */ diff --git a/src/main/java/seedu/address/model/module/lesson/Lesson.java b/src/main/java/seedu/address/model/module/lesson/Lesson.java index 699975f5782..02c9fa40c16 100644 --- a/src/main/java/seedu/address/model/module/lesson/Lesson.java +++ b/src/main/java/seedu/address/model/module/lesson/Lesson.java @@ -68,6 +68,18 @@ public boolean isSameLesson(Lesson otherLesson) { && otherLesson.getName().equals(getName()); } + /** + * Returns a deepCopy of the Lesson object. + */ + public Lesson deepCopy() { + LessonName newLessonName = new LessonName(name.getLessonName()); + Timeslot newTimeslot = timeslot.deepCopy(); + Optional newVenue = venue.map(venue -> new Venue(venue.getFullVenue())); + Optional newLink = link.map(link -> new Link(link.getLink())); + // day is enum, no clone method + return new Lesson(newLessonName, day, newTimeslot, newVenue, newLink); + } + /** * Returns true if both Lessons have the same identity and data fields. * This defines a stronger notion of equality between two Lessons. diff --git a/src/main/java/seedu/address/model/module/lesson/LessonName.java b/src/main/java/seedu/address/model/module/lesson/LessonName.java index 89711a42d38..47462c16f06 100644 --- a/src/main/java/seedu/address/model/module/lesson/LessonName.java +++ b/src/main/java/seedu/address/model/module/lesson/LessonName.java @@ -10,12 +10,10 @@ public class LessonName { public static final String MESSAGE_CONSTRAINTS = "Lesson name should not be blank"; - /* * The first character of the exam must not be a whitespace. */ public static final String VALIDATION_REGEX = "^\\S.*$"; - public final String fullLessonName; /** @@ -29,6 +27,10 @@ public LessonName(String lessonName) { fullLessonName = lessonName; } + public String getLessonName() { + return fullLessonName; + } + /** * Returns true if a given string is a valid name. */ diff --git a/src/test/java/seedu/address/logic/LogicManagerTest.java b/src/test/java/seedu/address/logic/LogicManagerTest.java index 3d5533d61f5..947eac2c790 100644 --- a/src/test/java/seedu/address/logic/LogicManagerTest.java +++ b/src/test/java/seedu/address/logic/LogicManagerTest.java @@ -1,7 +1,7 @@ package seedu.address.logic; import static org.junit.jupiter.api.Assertions.assertEquals; -import static seedu.address.commons.core.Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX; +import static seedu.address.commons.core.Messages.MESSAGE_INVALID_MODULE_DISPLAYED_INDEX; import static seedu.address.commons.core.Messages.MESSAGE_UNKNOWN_COMMAND; import static seedu.address.logic.commands.CommandTestUtil.VALID_MODULE_CODE; import static seedu.address.logic.parser.CliSyntax.PREFIX_CODE; @@ -61,8 +61,8 @@ public void execute_invalidCommandFormat_throwsParseException() { @Test public void execute_commandExecutionError_throwsCommandException() { - String deleteCommand = "delete 9"; - assertCommandException(deleteCommand, MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); + String deleteCommand = "delete mod 9"; + assertCommandException(deleteCommand, MESSAGE_INVALID_MODULE_DISPLAYED_INDEX); } @Test diff --git a/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java b/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java deleted file mode 100644 index e86b14e6e0f..00000000000 --- a/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java +++ /dev/null @@ -1,110 +0,0 @@ -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.logic.commands.CommandTestUtil.showPersonAtIndex; -import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; -import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PERSON; -import static seedu.address.testutil.TypicalModules.getTypicalModBook; -import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; - -import org.junit.jupiter.api.Test; - -import seedu.address.commons.core.Messages; -import seedu.address.commons.core.index.Index; -import seedu.address.model.Model; -import seedu.address.model.ModelManager; -import seedu.address.model.UserPrefs; -import seedu.address.model.person.Person; - -/** - * Contains integration tests (interaction with the Model) and unit tests for - * {@code DeleteCommand}. - */ -public class DeleteCommandTest { - - private Model model = new ModelManager(getTypicalAddressBook(), getTypicalModBook(), new UserPrefs()); - - @Test - public void execute_validIndexUnfilteredList_success() { - Person personToDelete = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); - DeleteCommand deleteCommand = new DeleteCommand(INDEX_FIRST_PERSON); - - String expectedMessage = String.format(DeleteCommand.MESSAGE_DELETE_PERSON_SUCCESS, personToDelete); - - ModelManager expectedModel = new ModelManager(model.getAddressBook(), model.getModBook(), new UserPrefs()); - expectedModel.deletePerson(personToDelete); - - assertCommandSuccess(deleteCommand, model, expectedMessage, expectedModel); - } - - @Test - public void execute_invalidIndexUnfilteredList_throwsCommandException() { - Index outOfBoundIndex = Index.fromOneBased(model.getFilteredPersonList().size() + 1); - DeleteCommand deleteCommand = new DeleteCommand(outOfBoundIndex); - - assertCommandFailure(deleteCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); - } - - @Test - public void execute_validIndexFilteredList_success() { - showPersonAtIndex(model, INDEX_FIRST_PERSON); - - Person personToDelete = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); - DeleteCommand deleteCommand = new DeleteCommand(INDEX_FIRST_PERSON); - - String expectedMessage = String.format(DeleteCommand.MESSAGE_DELETE_PERSON_SUCCESS, personToDelete); - - Model expectedModel = new ModelManager(model.getAddressBook(), model.getModBook(), new UserPrefs()); - expectedModel.deletePerson(personToDelete); - showNoPerson(expectedModel); - - assertCommandSuccess(deleteCommand, model, expectedMessage, expectedModel); - } - - @Test - public void execute_invalidIndexFilteredList_throwsCommandException() { - 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()); - - DeleteCommand deleteCommand = new DeleteCommand(outOfBoundIndex); - - assertCommandFailure(deleteCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); - } - - @Test - public void equals() { - DeleteCommand deleteFirstCommand = new DeleteCommand(INDEX_FIRST_PERSON); - DeleteCommand deleteSecondCommand = new DeleteCommand(INDEX_SECOND_PERSON); - - // same object -> returns true - assertTrue(deleteFirstCommand.equals(deleteFirstCommand)); - - // same values -> returns true - DeleteCommand deleteFirstCommandCopy = new DeleteCommand(INDEX_FIRST_PERSON); - assertTrue(deleteFirstCommand.equals(deleteFirstCommandCopy)); - - // different types -> returns false - assertFalse(deleteFirstCommand.equals(1)); - - // null -> returns false - assertFalse(deleteFirstCommand.equals(null)); - - // different person -> returns false - assertFalse(deleteFirstCommand.equals(deleteSecondCommand)); - } - - /** - * Updates {@code model}'s filtered list to show no one. - */ - private void showNoPerson(Model model) { - model.updateFilteredPersonList(p -> false); - - assertTrue(model.getFilteredPersonList().isEmpty()); - } -} diff --git a/src/test/java/seedu/address/logic/commands/add/AddExamCommandTest.java b/src/test/java/seedu/address/logic/commands/add/AddExamCommandTest.java index 7963c2f6533..e028395e2e9 100644 --- a/src/test/java/seedu/address/logic/commands/add/AddExamCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/add/AddExamCommandTest.java @@ -237,6 +237,15 @@ public ReadOnlyModBook getModBook() { throw new AssertionError("This method should not be called."); } + @Override + public void deleteExam(Module module, Exam target) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void deleteLesson(Module module, Lesson target) { + throw new AssertionError("This method should not be called."); + } } /** diff --git a/src/test/java/seedu/address/logic/commands/add/AddLessonCommandTest.java b/src/test/java/seedu/address/logic/commands/add/AddLessonCommandTest.java index 903570e14ac..0300171d1ed 100644 --- a/src/test/java/seedu/address/logic/commands/add/AddLessonCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/add/AddLessonCommandTest.java @@ -236,6 +236,16 @@ public void setModBook(ReadOnlyModBook newData) { public ReadOnlyModBook getModBook() { throw new AssertionError("This method should not be called."); } + + @Override + public void deleteExam(Module module, Exam target) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void deleteLesson(Module module, Lesson target) { + throw new AssertionError("This method should not be called."); + } } /** diff --git a/src/test/java/seedu/address/logic/commands/add/AddModCommandTest.java b/src/test/java/seedu/address/logic/commands/add/AddModCommandTest.java index 499bcfcf3cd..527ea8dd03c 100644 --- a/src/test/java/seedu/address/logic/commands/add/AddModCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/add/AddModCommandTest.java @@ -229,6 +229,15 @@ public ReadOnlyModBook getModBook() { throw new AssertionError("This method should not be called."); } + @Override + public void deleteExam(Module module, Exam target) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void deleteLesson(Module module, Lesson target) { + throw new AssertionError("This method should not be called."); + } } /** diff --git a/src/test/java/seedu/address/logic/commands/delete/DeleteExamCommandTest.java b/src/test/java/seedu/address/logic/commands/delete/DeleteExamCommandTest.java new file mode 100644 index 00000000000..e850a64efd4 --- /dev/null +++ b/src/test/java/seedu/address/logic/commands/delete/DeleteExamCommandTest.java @@ -0,0 +1,106 @@ +package seedu.address.logic.commands.delete; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +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.logic.commands.CommandTestUtil.showModuleAtIndex; +import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_EXAM; +import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_MODULE; +import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_EXAM; +import static seedu.address.testutil.TypicalModules.CS2103T; +import static seedu.address.testutil.TypicalModules.getTypicalModBook; +import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; + +import org.junit.jupiter.api.Test; + +import seedu.address.commons.core.Messages; +import seedu.address.commons.core.index.Index; +import seedu.address.model.Model; +import seedu.address.model.ModelManager; +import seedu.address.model.UserPrefs; +import seedu.address.model.module.Module; +import seedu.address.model.module.exam.Exam; + +/** + * Contains integration tests (interaction with the Model) and unit tests for + * {@code DeleteExamCommand}. + */ +public class DeleteExamCommandTest { + private Model model = new ModelManager(getTypicalAddressBook(), getTypicalModBook(), new UserPrefs()); + + @Test + public void execute_validIndexUnfilteredList_success() { + // using a CS2103T clone for tests to prevent double deletions (both by command and tests) + Module targetModule = CS2103T.deepCopy(); + Exam examToDelete = targetModule.getExams().get(INDEX_FIRST_EXAM.getZeroBased()); + DeleteCommand deleteExamCommand = new DeleteExamCommand(INDEX_FIRST_EXAM, targetModule.getCode()); + String expectedMessage = String.format(DeleteExamCommand.MESSAGE_DELETE_EXAM_SUCCESS, + examToDelete.getName(), targetModule.getCode()); + ModelManager expectedModel = new ModelManager(model.getAddressBook(), model.getModBook(), new UserPrefs()); + expectedModel.deleteExam(targetModule, examToDelete); + assertCommandSuccess(deleteExamCommand, model, expectedMessage, expectedModel); + } + + @Test + public void execute_invalidIndexUnfilteredList_throwsCommandException() { + Module targetModule = model.getFilteredModuleList().get(INDEX_FIRST_MODULE.getZeroBased()); + Index outOfBoundIndex = Index.fromZeroBased(targetModule.getExams().size() + 1); + DeleteCommand deleteExamCommand = new DeleteExamCommand(outOfBoundIndex, targetModule.getCode()); + assertCommandFailure(deleteExamCommand, model, Messages.MESSAGE_INVALID_EXAM_DISPLAYED_INDEX); + } + + @Test + public void execute_validIndexFilteredList_success() { + showModuleAtIndex(model, INDEX_FIRST_MODULE); + Module targetModule = CS2103T.deepCopy(); + Exam examToDelete = targetModule.getExams().get(INDEX_FIRST_EXAM.getZeroBased()); + DeleteCommand deleteExamCommand = new DeleteExamCommand(INDEX_FIRST_EXAM, targetModule.getCode()); + String expectedMessage = String.format(DeleteExamCommand.MESSAGE_DELETE_EXAM_SUCCESS, examToDelete.getName(), + targetModule.getCode()); + Model expectedModel = new ModelManager(model.getAddressBook(), model.getModBook(), new UserPrefs()); + expectedModel.deleteExam(targetModule, examToDelete); + showNoModule(expectedModel); + assertCommandSuccess(deleteExamCommand, model, expectedMessage, expectedModel); + } + + @Test + public void execute_invalidIndexFilteredList_throwsCommandException() { + showModuleAtIndex(model, INDEX_FIRST_MODULE); + Module targetModule = model.getFilteredModuleList().get(INDEX_FIRST_MODULE.getZeroBased()); + Index outOfBoundIndex = Index.fromZeroBased(targetModule.getExams().size() + 1); + DeleteCommand deleteExamCommand = new DeleteExamCommand(outOfBoundIndex, targetModule.getCode()); + assertCommandFailure(deleteExamCommand, model, Messages.MESSAGE_INVALID_EXAM_DISPLAYED_INDEX); + } + + @Test + public void equals() { + DeleteCommand deleteExamFirstCommand = new DeleteExamCommand(INDEX_FIRST_EXAM, CS2103T.getCode()); + DeleteCommand deleteExamSecondCommand = new DeleteExamCommand(INDEX_SECOND_EXAM, CS2103T.getCode()); + + // same object -> returns true + assertEquals(deleteExamFirstCommand, deleteExamFirstCommand); + + // same values -> returns true + DeleteCommand deleteExamFirstCommandCopy = new DeleteExamCommand(INDEX_FIRST_EXAM, CS2103T.getCode()); + assertEquals(deleteExamFirstCommand, deleteExamFirstCommandCopy); + + // different types -> returns false + assertNotEquals(deleteExamFirstCommand, 1); + + // null -> returns false + assertNotEquals(deleteExamFirstCommand, null); + + // different module command -> returns false + assertNotEquals(deleteExamFirstCommand, deleteExamSecondCommand); + } + + /** + * Updates {@code model}'s filtered list to show no one. + */ + private void showNoModule(Model model) { + model.updateFilteredModuleList(m -> false); + assertTrue(model.getFilteredModuleList().isEmpty()); + } +} diff --git a/src/test/java/seedu/address/logic/commands/delete/DeleteLessonCommandTest.java b/src/test/java/seedu/address/logic/commands/delete/DeleteLessonCommandTest.java new file mode 100644 index 00000000000..a731ea44f3d --- /dev/null +++ b/src/test/java/seedu/address/logic/commands/delete/DeleteLessonCommandTest.java @@ -0,0 +1,104 @@ +package seedu.address.logic.commands.delete; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +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.logic.commands.CommandTestUtil.showModuleAtIndex; +import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_LESSON; +import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_MODULE; +import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_LESSON; +import static seedu.address.testutil.TypicalModules.CS2103T; +import static seedu.address.testutil.TypicalModules.getTypicalModBook; +import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; + +import org.junit.jupiter.api.Test; + +import seedu.address.commons.core.Messages; +import seedu.address.commons.core.index.Index; +import seedu.address.model.Model; +import seedu.address.model.ModelManager; +import seedu.address.model.UserPrefs; +import seedu.address.model.module.Module; +import seedu.address.model.module.lesson.Lesson; + +/** + * Contains integration tests (interaction with the Model) and unit tests for + * {@code DeleteLessonCommand}. + */ +public class DeleteLessonCommandTest { + private Model model = new ModelManager(getTypicalAddressBook(), getTypicalModBook(), new UserPrefs()); + + @Test + public void execute_validIndexUnfilteredList_success() { + Module targetModule = CS2103T.deepCopy(); + Lesson lessonToDelete = targetModule.getLessons().get(INDEX_FIRST_LESSON.getZeroBased()); + DeleteCommand deleteLessonCommand = new DeleteLessonCommand(INDEX_FIRST_LESSON, targetModule.getCode()); + String expectedMessage = String.format(DeleteLessonCommand.MESSAGE_DELETE_LESSON_SUCCESS, + lessonToDelete.getName(), targetModule.getCode()); + ModelManager expectedModel = new ModelManager(model.getAddressBook(), model.getModBook(), new UserPrefs()); + expectedModel.deleteLesson(targetModule, lessonToDelete); + assertCommandSuccess(deleteLessonCommand, model, expectedMessage, expectedModel); + } + + @Test + public void execute_invalidIndexUnfilteredList_throwsCommandException() { + Module targetModule = model.getFilteredModuleList().get(INDEX_FIRST_MODULE.getZeroBased()); + Index outOfBoundIndex = Index.fromZeroBased(targetModule.getLessons().size() + 1); + DeleteCommand deleteLessonCommand = new DeleteLessonCommand(outOfBoundIndex, targetModule.getCode()); + assertCommandFailure(deleteLessonCommand, model, Messages.MESSAGE_INVALID_LESSON_DISPLAYED_INDEX); + } + + @Test + public void execute_validIndexFilteredList_success() { + showModuleAtIndex(model, INDEX_FIRST_MODULE); + Module targetModule = CS2103T.deepCopy(); + Lesson lessonToDelete = targetModule.getLessons().get(INDEX_FIRST_LESSON.getZeroBased()); + DeleteCommand deleteLessonCommand = new DeleteLessonCommand(INDEX_FIRST_LESSON, targetModule.getCode()); + String expectedMessage = String.format(DeleteLessonCommand.MESSAGE_DELETE_LESSON_SUCCESS, + lessonToDelete.getName(), targetModule.getCode()); + Model expectedModel = new ModelManager(model.getAddressBook(), model.getModBook(), new UserPrefs()); + expectedModel.deleteLesson(targetModule, lessonToDelete); + assertCommandSuccess(deleteLessonCommand, model, expectedMessage, expectedModel); + } + + @Test + public void execute_invalidIndexFilteredList_throwsCommandException() { + showModuleAtIndex(model, INDEX_FIRST_MODULE); + Module targetModule = model.getFilteredModuleList().get(INDEX_FIRST_MODULE.getZeroBased()); + Index outOfBoundIndex = Index.fromZeroBased(targetModule.getLessons().size() + 1); + DeleteCommand deleteLessonCommand = new DeleteLessonCommand(outOfBoundIndex, targetModule.getCode()); + assertCommandFailure(deleteLessonCommand, model, Messages.MESSAGE_INVALID_LESSON_DISPLAYED_INDEX); + } + + @Test + public void equals() { + DeleteCommand deleteLessonFirstCommand = new DeleteLessonCommand(INDEX_FIRST_LESSON, CS2103T.getCode()); + DeleteCommand deleteLessonSecondCommand = new DeleteLessonCommand(INDEX_SECOND_LESSON, CS2103T.getCode()); + + // same object -> returns true + assertEquals(deleteLessonFirstCommand, deleteLessonFirstCommand); + + // same values -> returns true + DeleteCommand deleteLessonFirstCommandCopy = new DeleteLessonCommand(INDEX_FIRST_LESSON, CS2103T.getCode()); + assertEquals(deleteLessonFirstCommand, deleteLessonFirstCommandCopy); + + // different types -> returns false + assertNotEquals(deleteLessonFirstCommand, 1); + + // null -> returns false + assertNotEquals(deleteLessonFirstCommand, null); + + // different module command -> returns false + assertNotEquals(deleteLessonFirstCommand, deleteLessonSecondCommand); + } + + /** + * Updates {@code model}'s filtered list to show no one. + */ + private void showNoModule(Model model) { + model.updateFilteredModuleList(m -> false); + assertTrue(model.getFilteredModuleList().isEmpty()); + } +} diff --git a/src/test/java/seedu/address/logic/commands/delete/DeleteModCommandTest.java b/src/test/java/seedu/address/logic/commands/delete/DeleteModCommandTest.java new file mode 100644 index 00000000000..eb7ff6494c7 --- /dev/null +++ b/src/test/java/seedu/address/logic/commands/delete/DeleteModCommandTest.java @@ -0,0 +1,98 @@ +package seedu.address.logic.commands.delete; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +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.logic.commands.CommandTestUtil.showModuleAtIndex; +import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_MODULE; +import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_MODULE; +import static seedu.address.testutil.TypicalModules.getTypicalModBook; +import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; + +import org.junit.jupiter.api.Test; + +import seedu.address.commons.core.Messages; +import seedu.address.commons.core.index.Index; +import seedu.address.model.Model; +import seedu.address.model.ModelManager; +import seedu.address.model.UserPrefs; +import seedu.address.model.module.Module; + +/** + * Contains integration tests (interaction with the Model) and unit tests for + * {@code DeleteModCommand}. + */ +public class DeleteModCommandTest { + private Model model = new ModelManager(getTypicalAddressBook(), getTypicalModBook(), new UserPrefs()); + + @Test + public void execute_validIndexUnfilteredList_success() { + Module moduleToDelete = model.getFilteredModuleList().get(INDEX_FIRST_MODULE.getZeroBased()); + DeleteCommand deleteCommand = new DeleteModCommand(INDEX_FIRST_MODULE); + String expectedMessage = String.format(DeleteModCommand.MESSAGE_DELETE_MODULE_SUCCESS, moduleToDelete); + ModelManager expectedModel = new ModelManager(model.getAddressBook(), model.getModBook(), new UserPrefs()); + expectedModel.deleteModule(moduleToDelete); + assertCommandSuccess(deleteCommand, model, expectedMessage, expectedModel); + } + + @Test + public void execute_invalidIndexUnfilteredList_throwsCommandException() { + Index outOfBoundIndex = Index.fromOneBased(model.getFilteredModuleList().size() + 1); + DeleteCommand deleteCommand = new DeleteModCommand(outOfBoundIndex); + assertCommandFailure(deleteCommand, model, Messages.MESSAGE_INVALID_MODULE_DISPLAYED_INDEX); + } + + @Test + public void execute_validIndexFilteredList_success() { + showModuleAtIndex(model, INDEX_FIRST_MODULE); + Module moduleToDelete = model.getFilteredModuleList().get(INDEX_FIRST_MODULE.getZeroBased()); + DeleteCommand deleteCommand = new DeleteModCommand(INDEX_FIRST_MODULE); + String expectedMessage = String.format(DeleteModCommand.MESSAGE_DELETE_MODULE_SUCCESS, moduleToDelete); + Model expectedModel = new ModelManager(model.getAddressBook(), model.getModBook(), new UserPrefs()); + expectedModel.deleteModule(moduleToDelete); + showNoModule(expectedModel); + assertCommandSuccess(deleteCommand, model, expectedMessage, expectedModel); + } + + @Test + public void execute_invalidIndexFilteredList_throwsCommandException() { + showModuleAtIndex(model, INDEX_FIRST_MODULE); + Index outOfBoundIndex = INDEX_SECOND_MODULE; + // ensures that outOfBoundIndex is still in bounds of ModBook module list + assertTrue(outOfBoundIndex.getZeroBased() < model.getModBook().getModuleList().size()); + DeleteCommand deleteCommand = new DeleteModCommand(outOfBoundIndex); + assertCommandFailure(deleteCommand, model, Messages.MESSAGE_INVALID_MODULE_DISPLAYED_INDEX); + } + + @Test + public void equals() { + DeleteCommand deleteModFirstCommand = new DeleteModCommand(INDEX_FIRST_MODULE); + DeleteCommand deleteModSecondCommand = new DeleteModCommand(INDEX_SECOND_MODULE); + + // same object -> returns true + assertEquals(deleteModFirstCommand, deleteModFirstCommand); + + // same values -> returns true + DeleteCommand deleteModFirstCommandCopy = new DeleteModCommand(INDEX_FIRST_MODULE); + assertEquals(deleteModFirstCommand, deleteModFirstCommandCopy); + + // different types -> returns false + assertNotEquals(deleteModFirstCommand, 1); + + // null -> returns false + assertNotEquals(deleteModFirstCommand, null); + + // different module command -> returns false + assertNotEquals(deleteModFirstCommand, deleteModSecondCommand); + } + + /** + * Updates {@code model}'s filtered list to show no one. + */ + private void showNoModule(Model model) { + model.updateFilteredModuleList(m -> false); + assertTrue(model.getFilteredModuleList().isEmpty()); + } +} diff --git a/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java b/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java index 91d5d25db4d..b88d0448a08 100644 --- a/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java +++ b/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java @@ -4,7 +4,11 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; import static seedu.address.commons.core.Messages.MESSAGE_UNKNOWN_COMMAND; +import static seedu.address.logic.parser.CliSyntax.PREFIX_CODE; import static seedu.address.testutil.Assert.assertThrows; +import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_EXAM; +import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_LESSON; +import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_MODULE; import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; import java.util.Arrays; @@ -14,7 +18,6 @@ import org.junit.jupiter.api.Test; import seedu.address.logic.commands.ClearCommand; -import seedu.address.logic.commands.DeleteCommand; import seedu.address.logic.commands.EditCommand; import seedu.address.logic.commands.EditCommand.EditPersonDescriptor; import seedu.address.logic.commands.ExitCommand; @@ -22,6 +25,10 @@ import seedu.address.logic.commands.GuiState; import seedu.address.logic.commands.HelpCommand; import seedu.address.logic.commands.add.AddModCommand; +import seedu.address.logic.commands.delete.DeleteCommand; +import seedu.address.logic.commands.delete.DeleteExamCommand; +import seedu.address.logic.commands.delete.DeleteLessonCommand; +import seedu.address.logic.commands.delete.DeleteModCommand; import seedu.address.logic.commands.list.ListCommand; import seedu.address.logic.parser.exceptions.ParseException; import seedu.address.model.module.Module; @@ -53,9 +60,22 @@ public void parseCommand_clear() throws Exception { @Test public void parseCommand_delete() throws Exception { - DeleteCommand command = (DeleteCommand) parser.parseCommand( - DeleteCommand.COMMAND_WORD + " " + INDEX_FIRST_PERSON.getOneBased(), DEFAULT_STATE); - assertEquals(new DeleteCommand(INDEX_FIRST_PERSON), command); + Module module = new ModuleBuilder().build(); + DeleteCommand deleteModCommand = (DeleteModCommand) parser.parseCommand( + DeleteCommand.COMMAND_WORD + " mod " + INDEX_FIRST_MODULE.getOneBased(), DEFAULT_STATE); + assertEquals(new DeleteModCommand(INDEX_FIRST_MODULE), deleteModCommand); + + DeleteCommand deleteLessonCommand = (DeleteLessonCommand) parser.parseCommand( + DeleteCommand.COMMAND_WORD + " lesson " + + INDEX_FIRST_LESSON.getOneBased() + " " + + PREFIX_CODE + module.getCode(), GuiState.DETAILS); + assertEquals(new DeleteLessonCommand(INDEX_FIRST_LESSON, module.getCode()), deleteLessonCommand); + + DeleteCommand deleteExamCommand = (DeleteExamCommand) parser.parseCommand( + DeleteCommand.COMMAND_WORD + " exam " + + INDEX_FIRST_EXAM.getOneBased() + " " + + PREFIX_CODE + module.getCode(), GuiState.DETAILS); + assertEquals(new DeleteExamCommand(INDEX_FIRST_EXAM, module.getCode()), deleteExamCommand); } @Test diff --git a/src/test/java/seedu/address/logic/parser/DeleteCommandParserTest.java b/src/test/java/seedu/address/logic/parser/DeleteCommandParserTest.java index 27eaec84450..ad65d14aeb8 100644 --- a/src/test/java/seedu/address/logic/parser/DeleteCommandParserTest.java +++ b/src/test/java/seedu/address/logic/parser/DeleteCommandParserTest.java @@ -1,13 +1,25 @@ package seedu.address.logic.parser; import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static seedu.address.logic.parser.CliSyntax.PREFIX_CODE; 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 static seedu.address.logic.parser.DeleteCommandParser.MESSAGE_WRONG_VIEW_DETAILS; +import static seedu.address.logic.parser.DeleteCommandParser.MESSAGE_WRONG_VIEW_SUMMARY; +import static seedu.address.logic.parser.ParserUtil.MESSAGE_NO_INDEXES_FOUND; +import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_EXAM; +import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_LESSON; +import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_MODULE; import org.junit.jupiter.api.Test; -import seedu.address.logic.commands.DeleteCommand; +import seedu.address.logic.commands.GuiState; +import seedu.address.logic.commands.delete.DeleteCommand; +import seedu.address.logic.commands.delete.DeleteExamCommand; +import seedu.address.logic.commands.delete.DeleteLessonCommand; +import seedu.address.logic.commands.delete.DeleteModCommand; +import seedu.address.model.module.Module; +import seedu.address.testutil.builders.ModuleBuilder; /** * As we are only doing white-box testing, our test cases do not cover path variations @@ -17,16 +29,71 @@ * therefore should be covered by the ParserUtilTest. */ public class DeleteCommandParserTest { - private DeleteCommandParser parser = new DeleteCommandParser(); @Test - public void parse_validArgs_returnsDeleteCommand() { - assertParseSuccess(parser, "1", new DeleteCommand(INDEX_FIRST_PERSON)); + public void parse_emptyArg_throwsParseException() { + assertParseFailure(parser, " ", + String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE)); + } + + @Test + public void parse_missingKeyword_throwsParseException() { + assertParseFailure(parser, "venue", + String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE)); + } + + @Test + public void parse_missingIndex_throwsParseException() { + assertParseFailure(parser, "mod lesson", MESSAGE_NO_INDEXES_FOUND); } @Test - public void parse_invalidArgs_throwsParseException() { - assertParseFailure(parser, "a", String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE)); + public void parse_validArgs_returnsDeleteCommand() { + Module module = new ModuleBuilder().build(); + // no leading and trailing whitespaces + DeleteCommand expectedDeleteModCommand = new DeleteModCommand(INDEX_FIRST_MODULE); + assertParseSuccess(parser, " mod " + INDEX_FIRST_MODULE.getOneBased(), expectedDeleteModCommand); + + DeleteCommand expectedDeleteLessonCommand = new DeleteLessonCommand(INDEX_FIRST_LESSON, module.getCode()); + assertParseSuccess(parser, " lesson " + INDEX_FIRST_LESSON.getOneBased() + + " " + PREFIX_CODE + module.getCode(), GuiState.DETAILS, expectedDeleteLessonCommand); + + DeleteCommand expectedDeleteExamCommand = new DeleteExamCommand(INDEX_FIRST_EXAM, module.getCode()); + assertParseSuccess(parser, " exam " + INDEX_FIRST_EXAM.getOneBased() + + " " + PREFIX_CODE + module.getCode(), GuiState.DETAILS, expectedDeleteExamCommand); + + // leading and trailing whitespaces + assertParseSuccess(parser, " mod " + INDEX_FIRST_MODULE.getOneBased() + + " \n \t ", expectedDeleteModCommand); + + // delete mod command must only work in the summary gui state + assertParseSuccess(parser, " mod " + INDEX_FIRST_MODULE.getOneBased(), + GuiState.SUMMARY, expectedDeleteModCommand); + assertParseFailure(parser, " mod " + INDEX_FIRST_MODULE.getOneBased(), + GuiState.LESSONS, MESSAGE_WRONG_VIEW_SUMMARY); + assertParseFailure(parser, " mod " + INDEX_FIRST_MODULE.getOneBased(), + GuiState.EXAMS, MESSAGE_WRONG_VIEW_SUMMARY); + assertParseFailure(parser, " mod " + INDEX_FIRST_MODULE.getOneBased(), + GuiState.DETAILS, MESSAGE_WRONG_VIEW_SUMMARY); + + // delete exam command must only work in the details gui state + assertParseSuccess(parser, " exam " + INDEX_FIRST_EXAM.getOneBased() + + " " + PREFIX_CODE + module.getCode(), GuiState.DETAILS, expectedDeleteExamCommand); + assertParseFailure(parser, " exam " + INDEX_FIRST_EXAM.getOneBased() + + " " + PREFIX_CODE + module.getCode(), GuiState.SUMMARY, MESSAGE_WRONG_VIEW_DETAILS); + assertParseFailure(parser, " exam " + INDEX_FIRST_EXAM.getOneBased() + + " " + PREFIX_CODE + module.getCode(), GuiState.LESSONS, MESSAGE_WRONG_VIEW_DETAILS); + assertParseFailure(parser, " exam " + INDEX_FIRST_EXAM.getOneBased() + + " " + PREFIX_CODE + module.getCode(), GuiState.EXAMS, MESSAGE_WRONG_VIEW_DETAILS); + + assertParseSuccess(parser, " lesson " + INDEX_FIRST_MODULE.getOneBased() + + " " + PREFIX_CODE + module.getCode(), GuiState.DETAILS, expectedDeleteLessonCommand); + assertParseFailure(parser, " lesson " + INDEX_FIRST_LESSON.getOneBased() + + " " + PREFIX_CODE + module.getCode(), GuiState.SUMMARY, MESSAGE_WRONG_VIEW_DETAILS); + assertParseFailure(parser, " lesson " + INDEX_FIRST_LESSON.getOneBased() + + " " + PREFIX_CODE + module.getCode(), GuiState.LESSONS, MESSAGE_WRONG_VIEW_DETAILS); + assertParseFailure(parser, " lesson " + INDEX_FIRST_LESSON.getOneBased() + + " " + PREFIX_CODE + module.getCode(), GuiState.EXAMS, MESSAGE_WRONG_VIEW_DETAILS); } } diff --git a/src/test/java/seedu/address/storage/JsonSerializableModBookTest.java b/src/test/java/seedu/address/storage/JsonSerializableModBookTest.java index 71534067298..b55c041d5e2 100644 --- a/src/test/java/seedu/address/storage/JsonSerializableModBookTest.java +++ b/src/test/java/seedu/address/storage/JsonSerializableModBookTest.java @@ -1,6 +1,6 @@ package seedu.address.storage; -//import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import static seedu.address.testutil.Assert.assertThrows; import java.nio.file.Path; @@ -10,8 +10,8 @@ import seedu.address.commons.exceptions.IllegalValueException; import seedu.address.commons.util.JsonUtil; -//import seedu.address.model.ModBook; -//import seedu.address.testutil.TypicalModules; +import seedu.address.model.ModBook; +import seedu.address.testutil.TypicalModules; public class JsonSerializableModBookTest { @@ -20,7 +20,6 @@ public class JsonSerializableModBookTest { private static final Path INVALID_MODULE_FILE = TEST_DATA_FOLDER.resolve("invalidModuleModBook.json"); private static final Path DUPLICATE_MODULE_FILE = TEST_DATA_FOLDER.resolve("duplicateModuleModBook.json"); - /* @Test public void toModelType_typicalModulesFile_success() throws Exception { JsonSerializableModBook dataFromFile = JsonUtil.readJsonFile(TYPICAL_MODULES_FILE, @@ -29,7 +28,6 @@ public void toModelType_typicalModulesFile_success() throws Exception { ModBook typicalModulesModBook = TypicalModules.getTypicalModBook(); assertEquals(modBookFromFile, typicalModulesModBook); } - */ @Test public void toModelType_invalidPersonFile_throwsIllegalValueException() throws Exception { diff --git a/src/test/java/seedu/address/testutil/TypicalIndexes.java b/src/test/java/seedu/address/testutil/TypicalIndexes.java index ef50f7afe6e..1f1942abcd6 100644 --- a/src/test/java/seedu/address/testutil/TypicalIndexes.java +++ b/src/test/java/seedu/address/testutil/TypicalIndexes.java @@ -12,4 +12,8 @@ public class TypicalIndexes { public static final Index INDEX_FIRST_MODULE = Index.fromOneBased(1); public static final Index INDEX_SECOND_MODULE = Index.fromOneBased(2); public static final Index INDEX_THIRD_MODULE = Index.fromOneBased(3); + public static final Index INDEX_FIRST_LESSON = Index.fromOneBased(1); + public static final Index INDEX_SECOND_LESSON = Index.fromOneBased(2); + public static final Index INDEX_FIRST_EXAM = Index.fromOneBased(1); + public static final Index INDEX_SECOND_EXAM = Index.fromOneBased(2); } diff --git a/src/test/java/seedu/address/testutil/TypicalModules.java b/src/test/java/seedu/address/testutil/TypicalModules.java index 9752d2aecb6..482162ccce6 100644 --- a/src/test/java/seedu/address/testutil/TypicalModules.java +++ b/src/test/java/seedu/address/testutil/TypicalModules.java @@ -3,6 +3,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; import seedu.address.model.ModBook; import seedu.address.model.module.Module; @@ -52,6 +53,8 @@ public static ModBook getTypicalModBook() { } public static List getTypicalModules() { - return new ArrayList<>(Arrays.asList(CS2103T, CS2040S, CS1231S)); + return new ArrayList<>(Arrays.asList(CS2103T, CS2040S, CS1231S)) + .stream().map(Module::deepCopy) + .collect(Collectors.toList()); } }