diff --git a/src/planmysem/Main.java b/src/planmysem/Main.java index 8417a34cf..986561074 100644 --- a/src/planmysem/Main.java +++ b/src/planmysem/Main.java @@ -4,7 +4,6 @@ import javafx.application.Platform; import javafx.stage.Stage; import planmysem.logic.Logic; -import planmysem.logic.LogicP; import planmysem.ui.Gui; import planmysem.ui.Stoppable; @@ -26,7 +25,7 @@ public static void main(String[] args) { @Override public void start(Stage primaryStage) throws Exception { - gui = new Gui(new Logic(), new LogicP(), VERSION); + gui = new Gui(new Logic(), VERSION); gui.start(primaryStage, this); } diff --git a/src/planmysem/commands/AddCommand.java b/src/planmysem/commands/AddCommand.java index e040f7961..a88ed9347 100644 --- a/src/planmysem/commands/AddCommand.java +++ b/src/planmysem/commands/AddCommand.java @@ -1,75 +1,103 @@ package planmysem.commands; -import java.util.HashSet; +import java.time.LocalDate; +import java.time.LocalTime; import java.util.Set; +import planmysem.common.Utils; import planmysem.data.exception.IllegalValueException; -import planmysem.data.person.Address; -import planmysem.data.person.Email; -import planmysem.data.person.Name; -import planmysem.data.person.Person; -import planmysem.data.person.Phone; -import planmysem.data.person.ReadOnlyPerson; -import planmysem.data.person.UniquePersonList; -import planmysem.data.tag.Tag; +import planmysem.data.recurrence.Recurrence; +import planmysem.data.semester.Semester; +import planmysem.data.slot.Description; +import planmysem.data.slot.Location; +import planmysem.data.slot.Name; +import planmysem.data.slot.Slot; /** - * Adds a person to the address book. + * Adds a person to the planner. */ public class AddCommand extends Command { - public static final String COMMAND_WORD = "add"; + public static final String COMMAND_WORD_SHORT = "a"; + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Add single or multiple slots to the Planner." + + "\n\tParameters: " + + "\n\t\tMandatory: n/NAME d/DATE_OR_DAY_OF_WEEK st/START_TIME et/END_TIME_OR_DURATION" + + "\n\t\tOptional: [l/LOCATION] [des/DESCRIPTION] [r/normal] [r/recess] [r/reading] [r/exam]" + + "[r/past] [t/TAG]..." + + "\n\tExample: " + COMMAND_WORD + + " n/CS2113T Tutorial d/mon st/08:00 et/09:00 des/Topic: Sequence Diagram t/CS2113T " + + "t/Tutorial r/normal"; - public static final String MESSAGE_USAGE = COMMAND_WORD + ":\n" + "Adds a person to the address book. " - + "Contact details can be marked private by prepending 'p' to the prefix.\n\t" - + "Parameters: NAME [p]p/PHONE [p]e/EMAIL [p]a/ADDRESS [t/TAG]...\n\t" - + "Example: " + COMMAND_WORD - + " John Doe p/98765432 e/johnd@gmail.com a/311, Clementi Ave 2, #02-25 t/friends t/owesMoney"; - - public static final String MESSAGE_SUCCESS = "New person added: %1$s"; - public static final String MESSAGE_DUPLICATE_PERSON = "This person already exists in the address book"; + public static final String MESSAGE_SUCCESS_NO_CHANGE = "No slots were added."; + public static final String MESSAGE_SUCCESS = "%1$s Slots added.\n\n%2$s"; + public static final String MESSAGE_FAIL_OUT_OF_BOUNDS = "Date specified is out of bounds."; - private final Person toAdd; + private final Slot slot; + private final Recurrence recurrence; /** * Convenience constructor using raw values. * * @throws IllegalValueException if any of the raw values are invalid */ - public AddCommand(String name, - String phone, boolean isPhonePrivate, - String email, boolean isEmailPrivate, - String address, boolean isAddressPrivate, - Set tags) throws IllegalValueException { - final Set tagSet = new HashSet<>(); - for (String tagName : tags) { - tagSet.add(new Tag(tagName)); - } - this.toAdd = new Person( - new Name(name), - new Phone(phone, isPhonePrivate), - new Email(email, isEmailPrivate), - new Address(address, isAddressPrivate), - tagSet - ); - } - - public AddCommand(Person toAdd) { - this.toAdd = toAdd; + public AddCommand(LocalDate date, String name, String location, String description, LocalTime startTime, + int duration, Set tags, Set recurrences) throws IllegalValueException { + slot = new Slot(new Name(name), new Location(location), new Description(description), + startTime, duration, Utils.parseTags(tags)); + recurrence = new Recurrence(recurrences, date); } - public ReadOnlyPerson getPerson() { - return toAdd; + /** + * Convenience constructor using raw values. + * + * @throws IllegalValueException if any of the raw values are invalid + */ + public AddCommand(int day, String name, String location, String description, LocalTime startTime, + int duration, Set tags, Set recurrences) throws IllegalValueException { + slot = new Slot(new Name(name), new Location(location), new Description(description), + startTime, duration, Utils.parseTags(tags)); + recurrence = new Recurrence(recurrences, day); } @Override public CommandResult execute() { - try { - addressBook.addPerson(toAdd); - return new CommandResult(String.format(MESSAGE_SUCCESS, toAdd)); - } catch (UniquePersonList.DuplicatePersonException dpe) { - return new CommandResult(MESSAGE_DUPLICATE_PERSON); + Set dates = recurrence.generateDates(planner.getSemester()); + + for (LocalDate date : dates) { + try { + planner.addSlot(date, slot); + } catch (Semester.DateNotFoundException dnfe) { + return new CommandResult(MESSAGE_FAIL_OUT_OF_BOUNDS); + } + } + + if (dates.size() == 0) { + return new CommandResult(MESSAGE_SUCCESS_NO_CHANGE); + } else { + return new CommandResult(String.format(MESSAGE_SUCCESS, dates.size(), + craftSuccessMessage(dates, slot))); } } + /** + * Craft success message. + */ + private String craftSuccessMessage(Set dates, Slot slot) { + StringBuilder sb = new StringBuilder(); + sb.append("On dates:"); + + for (LocalDate date : dates) { + sb.append("\n\t"); + sb.append(planner.getSemester().getDays().get(date).getType()); + sb.append(", "); + sb.append(date.toString()); + sb.append(", "); + sb.append(date.getDayOfWeek().toString()); + } + sb.append("\n\n"); + + sb.append(slot.toString()); + + return sb.toString(); + } } diff --git a/src/planmysem/commands/AddCommandP.java b/src/planmysem/commands/AddCommandP.java deleted file mode 100644 index d8923af08..000000000 --- a/src/planmysem/commands/AddCommandP.java +++ /dev/null @@ -1,103 +0,0 @@ -package planmysem.commands; - -import java.time.LocalDate; -import java.time.LocalTime; -import java.util.Set; - -import planmysem.common.Utils; -import planmysem.data.exception.IllegalValueException; -import planmysem.data.recurrence.Recurrence; -import planmysem.data.semester.Semester; -import planmysem.data.slot.Description; -import planmysem.data.slot.Location; -import planmysem.data.slot.Name; -import planmysem.data.slot.Slot; - -/** - * Adds a person to the planner. - */ -public class AddCommandP extends CommandP { - public static final String COMMAND_WORD = "add"; - public static final String COMMAND_WORD_SHORT = "a"; - public static final String MESSAGE_USAGE = COMMAND_WORD + ": Add single or multiple slots to the Planner." - + "\n\tParameters: " - + "\n\t\tMandatory: n/NAME d/DATE_OR_DAY_OF_WEEK st/START_TIME et/END_TIME_OR_DURATION" - + "\n\t\tOptional: [l/LOCATION] [des/DESCRIPTION] [r/normal] [r/recess] [r/reading] [r/exam]" - + "[r/past] [t/TAG]..." - + "\n\tExample: " + COMMAND_WORD - + " n/CS2113T Tutorial d/mon st/08:00 et/09:00 des/Topic: Sequence Diagram t/CS2113T " - + "t/Tutorial r/normal"; - - public static final String MESSAGE_SUCCESS_NO_CHANGE = "No slots were added."; - public static final String MESSAGE_SUCCESS = "%1$s Slots added.\n\n%2$s"; - public static final String MESSAGE_FAIL_OUT_OF_BOUNDS = "Date specified is out of bounds."; - - private final Slot slot; - private final Recurrence recurrence; - - /** - * Convenience constructor using raw values. - * - * @throws IllegalValueException if any of the raw values are invalid - */ - public AddCommandP(LocalDate date, String name, String location, String description, LocalTime startTime, - int duration, Set tags, Set recurrences) throws IllegalValueException { - slot = new Slot(new Name(name), new Location(location), new Description(description), - startTime, duration, Utils.parseTags(tags)); - recurrence = new Recurrence(recurrences, date); - } - - /** - * Convenience constructor using raw values. - * - * @throws IllegalValueException if any of the raw values are invalid - */ - public AddCommandP(int day, String name, String location, String description, LocalTime startTime, - int duration, Set tags, Set recurrences) throws IllegalValueException { - slot = new Slot(new Name(name), new Location(location), new Description(description), - startTime, duration, Utils.parseTags(tags)); - recurrence = new Recurrence(recurrences, day); - } - - @Override - public CommandResultP execute() { - Set dates = recurrence.generateDates(planner.getSemester()); - - for (LocalDate date : dates) { - try { - planner.addSlot(date, slot); - } catch (Semester.DateNotFoundException dnfe) { - return new CommandResultP(MESSAGE_FAIL_OUT_OF_BOUNDS); - } - } - - if (dates.size() == 0) { - return new CommandResultP(MESSAGE_SUCCESS_NO_CHANGE); - } else { - return new CommandResultP(String.format(MESSAGE_SUCCESS, dates.size(), - craftSuccessMessage(dates, slot))); - } - } - - /** - * Craft success message. - */ - private String craftSuccessMessage(Set dates, Slot slot) { - StringBuilder sb = new StringBuilder(); - sb.append("On dates:"); - - for (LocalDate date : dates) { - sb.append("\n\t"); - sb.append(planner.getSemester().getDays().get(date).getType()); - sb.append(", "); - sb.append(date.toString()); - sb.append(", "); - sb.append(date.getDayOfWeek().toString()); - } - sb.append("\n\n"); - - sb.append(slot.toString()); - - return sb.toString(); - } -} diff --git a/src/planmysem/commands/ClearCommand.java b/src/planmysem/commands/ClearCommand.java index 1fd562ae0..f93ca7e5e 100644 --- a/src/planmysem/commands/ClearCommand.java +++ b/src/planmysem/commands/ClearCommand.java @@ -1,19 +1,19 @@ package planmysem.commands; /** - * Clears the address book. + * Clears the planner. */ public class ClearCommand extends Command { public static final String COMMAND_WORD = "clear"; - public static final String MESSAGE_USAGE = COMMAND_WORD + ":\n" + "Clears address book permanently.\n\t" - + "Example: " + COMMAND_WORD; + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Clears the planner permanently." + + "\n\tExample: " + COMMAND_WORD; - public static final String MESSAGE_SUCCESS = "Address book has been cleared!"; + public static final String MESSAGE_SUCCESS = "The Planner has been cleared!"; @Override public CommandResult execute() { - addressBook.clear(); + planner.clearSlots(); return new CommandResult(MESSAGE_SUCCESS); } } diff --git a/src/planmysem/commands/ClearCommandP.java b/src/planmysem/commands/ClearCommandP.java deleted file mode 100644 index 0dd6e7f78..000000000 --- a/src/planmysem/commands/ClearCommandP.java +++ /dev/null @@ -1,19 +0,0 @@ -package planmysem.commands; - -/** - * Clears the planner. - */ -public class ClearCommandP extends CommandP { - - public static final String COMMAND_WORD = "clear"; - public static final String MESSAGE_USAGE = COMMAND_WORD + ": Clears the planner permanently." - + "\n\tExample: " + COMMAND_WORD; - - public static final String MESSAGE_SUCCESS = "The Planner has been cleared!"; - - @Override - public CommandResultP execute() { - planner.clearSlots(); - return new CommandResultP(MESSAGE_SUCCESS); - } -} diff --git a/src/planmysem/commands/Command.java b/src/planmysem/commands/Command.java index 925948b42..c8f0fd426 100644 --- a/src/planmysem/commands/Command.java +++ b/src/planmysem/commands/Command.java @@ -2,65 +2,77 @@ import static planmysem.ui.Gui.DISPLAYED_INDEX_OFFSET; +import java.time.LocalDate; import java.util.List; +import javafx.util.Pair; import planmysem.common.Messages; -import planmysem.data.AddressBook; -import planmysem.data.person.ReadOnlyPerson; +import planmysem.data.Planner; +import planmysem.data.slot.ReadOnlySlot; /** * Represents an executable command. */ public abstract class Command { - protected AddressBook addressBook; - protected List relevantPersons; + protected Planner planner; + protected List> relevantSlots; private int targetIndex = -1; + /** + * @param slots last visible listing index of the target person + */ + // public Command(List> slots) { + // this.relevantSlots = slots; + // } + /** * @param targetIndex last visible listing index of the target person */ public Command(int targetIndex) { - this.setTargetIndex(targetIndex); + this.targetIndex = targetIndex; } protected Command() { } /** - * Constructs a feedback message to summarise an operation that displayed a listing of persons. - * - * @param personsDisplayed used to generate summary - * @return summary message for persons displayed + * Executes the command and returns the result. */ - public static String getMessageForPersonListShownSummary(List personsDisplayed) { - return String.format(Messages.MESSAGE_PERSONS_LISTED_OVERVIEW, personsDisplayed.size()); - } + public abstract CommandResult execute(); /** - * Executes the command and returns the result. + * Constructs a feedback message to summarise an operation that displayed a listing of persons. + * + * @param slots used to generate summary + * @return summary message for persons displayed */ - public CommandResult execute() { - throw new UnsupportedOperationException("This method should be implement in child classes"); + public static String getMessageForSlotsListShownSummary(List> slots) { + return String.format(Messages.MESSAGE_PERSONS_LISTED_OVERVIEW, slots.size()); } - //Note: it is better to make the execute() method abstract, by replacing the above method with the line below: - //public abstract CommandResult execute(); - /** * Supplies the data the command will operate on. */ - public void setData(AddressBook addressBook, List relevantPersons) { - this.addressBook = addressBook; - this.relevantPersons = relevantPersons; + public void setData(Planner planner, List> slots) { + this.planner = planner; + this.relevantSlots = slots; } /** - * Extracts the the target person in the last shown list from the given arguments. + * Extracts the the target Day in the last shown list from the given arguments. * * @throws IndexOutOfBoundsException if the target index is out of bounds of the last viewed listing */ - protected ReadOnlyPerson getTargetPerson() throws IndexOutOfBoundsException { - return relevantPersons.get(getTargetIndex() - DISPLAYED_INDEX_OFFSET); + protected List> getTargetSlots() throws IndexOutOfBoundsException { + return relevantSlots; + } + + protected Pair getTargetSlot(int index) throws IndexOutOfBoundsException { + return relevantSlots.get(index); + } + + protected Pair getTargetSlot() throws IndexOutOfBoundsException { + return relevantSlots.get(targetIndex - DISPLAYED_INDEX_OFFSET); } public int getTargetIndex() { diff --git a/src/planmysem/commands/CommandP.java b/src/planmysem/commands/CommandP.java deleted file mode 100644 index a3c802365..000000000 --- a/src/planmysem/commands/CommandP.java +++ /dev/null @@ -1,85 +0,0 @@ -package planmysem.commands; - -import static planmysem.ui.Gui.DISPLAYED_INDEX_OFFSET; - -import java.time.LocalDate; -import java.util.List; - -import javafx.util.Pair; -import planmysem.common.Messages; -import planmysem.data.Planner; -import planmysem.data.slot.ReadOnlySlot; - -/** - * Represents an executable command. - */ -public abstract class CommandP { - protected Planner planner; - protected List> relevantSlots; - private int targetIndex = -1; - - /** - * @param slots last visible listing index of the target person - */ - // public CommandP(List> slots) { - // this.relevantSlots = slots; - // } - - /** - * @param targetIndex last visible listing index of the target person - */ - public CommandP(int targetIndex) { - this.targetIndex = targetIndex; - } - - protected CommandP() { - } - - /** - * Executes the command and returns the result. - */ - public abstract CommandResultP execute(); - - /** - * Constructs a feedback message to summarise an operation that displayed a listing of persons. - * - * @param slots used to generate summary - * @return summary message for persons displayed - */ - public static String getMessageForSlotsListShownSummary(List> slots) { - return String.format(Messages.MESSAGE_PERSONS_LISTED_OVERVIEW, slots.size()); - } - - /** - * Supplies the data the command will operate on. - */ - public void setData(Planner planner, List> slots) { - this.planner = planner; - this.relevantSlots = slots; - } - - /** - * Extracts the the target Day in the last shown list from the given arguments. - * - * @throws IndexOutOfBoundsException if the target index is out of bounds of the last viewed listing - */ - protected List> getTargetSlots() throws IndexOutOfBoundsException { - return relevantSlots; - } - - protected Pair getTargetSlot(int index) throws IndexOutOfBoundsException { - return relevantSlots.get(index); - } - - protected Pair getTargetSlot() throws IndexOutOfBoundsException { - return relevantSlots.get(targetIndex - DISPLAYED_INDEX_OFFSET); - } - - public int getTargetIndex() { - return targetIndex; - } - - public void setTargetIndex(int targetIndex) { - this.targetIndex = targetIndex; - } -} diff --git a/src/planmysem/commands/CommandResult.java b/src/planmysem/commands/CommandResult.java index 87063b52e..5da8160eb 100644 --- a/src/planmysem/commands/CommandResult.java +++ b/src/planmysem/commands/CommandResult.java @@ -1,9 +1,11 @@ package planmysem.commands; +import java.time.LocalDate; import java.util.List; import java.util.Optional; -import planmysem.data.person.ReadOnlyPerson; +import javafx.util.Pair; +import planmysem.data.slot.ReadOnlySlot; /** * Represents the result of a command execution. @@ -16,25 +18,25 @@ public class CommandResult { public final String feedbackToUser; /** - * The list of persons that was produced by the command + * The list of Slots that was produced by the command */ - private final List relevantPersons; + private final List> slots; public CommandResult(String feedbackToUser) { this.feedbackToUser = feedbackToUser; - relevantPersons = null; + slots = null; } - public CommandResult(String feedbackToUser, List relevantPersons) { + public CommandResult(String feedbackToUser, List> slots) { this.feedbackToUser = feedbackToUser; - this.relevantPersons = relevantPersons; + this.slots = slots; } /** - * Returns list of persons relevant to the command command result, if any. + * Returns list of Slots relevant to the command command result, if any. */ - public Optional> getRelevantPersons() { - return Optional.ofNullable(relevantPersons); + public Optional>> getRelevantSlots() { + return Optional.ofNullable(slots); } } diff --git a/src/planmysem/commands/CommandResultP.java b/src/planmysem/commands/CommandResultP.java deleted file mode 100644 index aea29c389..000000000 --- a/src/planmysem/commands/CommandResultP.java +++ /dev/null @@ -1,42 +0,0 @@ -package planmysem.commands; - -import java.time.LocalDate; -import java.util.List; -import java.util.Optional; - -import javafx.util.Pair; -import planmysem.data.slot.ReadOnlySlot; - -/** - * Represents the result of a command execution. - */ -public class CommandResultP { - - /** - * The feedback message to be shown to the user. Contains a description of the execution result - */ - public final String feedbackToUser; - - /** - * The list of Slots that was produced by the command - */ - private final List> slots; - - public CommandResultP(String feedbackToUser) { - this.feedbackToUser = feedbackToUser; - slots = null; - } - - public CommandResultP(String feedbackToUser, List> slots) { - this.feedbackToUser = feedbackToUser; - this.slots = slots; - } - - /** - * Returns list of Slots relevant to the command command result, if any. - */ - public Optional>> getRelevantSlots() { - return Optional.ofNullable(slots); - } - -} diff --git a/src/planmysem/commands/DeleteCommand.java b/src/planmysem/commands/DeleteCommand.java index 5db36613e..f09479393 100644 --- a/src/planmysem/commands/DeleteCommand.java +++ b/src/planmysem/commands/DeleteCommand.java @@ -1,42 +1,144 @@ package planmysem.commands; -import planmysem.common.Messages; -import planmysem.data.person.ReadOnlyPerson; -import planmysem.data.person.UniquePersonList.PersonNotFoundException; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import javafx.util.Pair; +import planmysem.common.Messages; +import planmysem.common.Utils; +import planmysem.data.exception.IllegalValueException; +import planmysem.data.semester.Day; +import planmysem.data.slot.ReadOnlySlot; +import planmysem.data.slot.Slot; +import planmysem.data.tag.TagP; /** - * Deletes a person identified using it's last displayed index from the address book. + * Adds a person to the address book. */ public class DeleteCommand extends Command { public static final String COMMAND_WORD = "delete"; + public static final String COMMAND_WORD_ALT = "del"; + public static final String COMMAND_WORD_SHORT = "d"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Delete single or multiple slots in the Planner." + + "\n\tParameters: " + + "\n\t\tMandatory: t/TAG... or INDEX" + + "\n\tExample 1: " + COMMAND_WORD + + " t/CS2113T t/Tutorial" + + "\n\tExample 2: " + COMMAND_WORD + + " 2"; - public static final String MESSAGE_USAGE = COMMAND_WORD + ":\n" - + "Deletes the person identified by the index number used in the last person listing.\n\t" - + "Parameters: INDEX\n\t" - + "Example: " + COMMAND_WORD + " 1"; - public static final String MESSAGE_DELETE_PERSON_SUCCESS = "Deleted Person: %1$s"; + public static final String MESSAGE_SUCCESS_NO_CHANGE = "No Slots were deleted.\n\n%1$s"; + public static final String MESSAGE_SUCCESS = "%1$s Slots deleted.\n\n%2$s\n%3$s"; + public static final String MESSAGE_FAIL_ILLEGAL_VALUE = MESSAGE_SUCCESS_NO_CHANGE + + " Illegal characters were detected."; + private final Set tags = new HashSet<>(); - public DeleteCommand(int targetVisibleIndex) { - super(targetVisibleIndex); + /** + * Convenience constructor using raw values. + * + * @throws IllegalValueException if any of the raw values are invalid + */ + public DeleteCommand(Set tags) throws IllegalValueException { + this.tags.addAll(Utils.parseTags(tags)); } + /** + * Convenience constructor using raw values. + */ + public DeleteCommand(int index) { + super(index); + } @Override public CommandResult execute() { - try { - final ReadOnlyPerson target = getTargetPerson(); - addressBook.removePerson(target); - return new CommandResult(String.format(MESSAGE_DELETE_PERSON_SUCCESS, target)); - - } catch (IndexOutOfBoundsException ie) { - return new CommandResult(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); - } catch (PersonNotFoundException pnfe) { - return new CommandResult(Messages.MESSAGE_PERSON_NOT_IN_ADDRESSBOOK); + Map selectedSlots = new TreeMap<>(); + + if (getTargetIndex() == -1) { + for (Map.Entry day : planner.getSemester().getDays().entrySet()) { + for (Slot slot : day.getValue().getSlots()) { + if (slot.getTags().containsAll(tags)) { + selectedSlots.put(LocalDateTime.of(day.getKey(), slot.getStartTime()), slot); + } + } + } + if (selectedSlots.size() == 0) { + return new CommandResult(String.format(MESSAGE_SUCCESS_NO_CHANGE, craftSelectedMessage())); + } + } else { + try { + final Pair target = getTargetSlot(); + selectedSlots.put(LocalDateTime.of(target.getKey(), + target.getValue().getStartTime()), target.getValue()); + + if (!planner.containsSlot(target.getKey(), target.getValue())) { + return new CommandResult(Messages.MESSAGE_SLOT_NOT_IN_PLANNER); + } + } catch (IndexOutOfBoundsException ie) { + return new CommandResult(Messages.MESSAGE_INVALID_SLOT_DISPLAYED_INDEX); + } + } + + // perform deletion of slots from the planner + for (Map.Entry slot: selectedSlots.entrySet()) { + planner.getSemester().getDays().get(slot.getKey().toLocalDate()).removeSlot(slot.getValue()); } + + return new CommandResult(String.format(MESSAGE_SUCCESS, selectedSlots.size(), + craftSelectedMessage(), craftSuccessMessage(selectedSlots))); } + /** + * Craft success message. + */ + private String craftSuccessMessage(Map selectedSlots) { + StringBuilder sb = new StringBuilder(); + + sb.append("Deleted Slots: "); + sb.append("\n"); + + int count = 1; + for (Map.Entry editedSlot : selectedSlots.entrySet()) { + sb.append("\tItem: "); + sb.append(count); + sb.append(": "); + sb.append("\n\t\t"); + sb.append(editedSlot.getValue().getName().toString()); + sb.append("\n\t\t"); + sb.append(editedSlot.getKey().toLocalDate().toString()); + sb.append(" "); + sb.append(editedSlot.getKey().toLocalTime().toString()); + sb.append(", "); + sb.append(planner.getSemester().getDays().get(editedSlot.getKey().toLocalDate()).getType()); + sb.append(", "); + sb.append(editedSlot.getKey().getDayOfWeek().toString()); + count++; + sb.append("\n\n"); + } + + return sb.toString(); + } + + /** + * Craft selected message. + */ + private String craftSelectedMessage() { + StringBuilder sb = new StringBuilder(); + sb.append("Selected Slots containing tags: \n"); + + for (TagP tag : tags) { + sb.append("\t"); + sb.append(tag.toString()); + sb.append("\n"); + } + + return sb.toString(); + } } diff --git a/src/planmysem/commands/DeleteCommandP.java b/src/planmysem/commands/DeleteCommandP.java deleted file mode 100644 index dc926223a..000000000 --- a/src/planmysem/commands/DeleteCommandP.java +++ /dev/null @@ -1,144 +0,0 @@ -package planmysem.commands; - -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; - -import javafx.util.Pair; -import planmysem.common.Messages; -import planmysem.common.Utils; -import planmysem.data.exception.IllegalValueException; -import planmysem.data.semester.Day; -import planmysem.data.slot.ReadOnlySlot; -import planmysem.data.slot.Slot; -import planmysem.data.tag.TagP; - -/** - * Adds a person to the address book. - */ -public class DeleteCommandP extends CommandP { - - public static final String COMMAND_WORD = "delete"; - public static final String COMMAND_WORD_ALT = "del"; - public static final String COMMAND_WORD_SHORT = "d"; - - public static final String MESSAGE_USAGE = COMMAND_WORD + ": Delete single or multiple slots in the Planner." - + "\n\tParameters: " - + "\n\t\tMandatory: t/TAG... or INDEX" - + "\n\tExample 1: " + COMMAND_WORD - + " t/CS2113T t/Tutorial" - + "\n\tExample 2: " + COMMAND_WORD - + " 2"; - - - public static final String MESSAGE_SUCCESS_NO_CHANGE = "No Slots were deleted.\n\n%1$s"; - public static final String MESSAGE_SUCCESS = "%1$s Slots deleted.\n\n%2$s\n%3$s"; - public static final String MESSAGE_FAIL_ILLEGAL_VALUE = MESSAGE_SUCCESS_NO_CHANGE - + " Illegal characters were detected."; - - private final Set tags = new HashSet<>(); - - /** - * Convenience constructor using raw values. - * - * @throws IllegalValueException if any of the raw values are invalid - */ - public DeleteCommandP(Set tags) throws IllegalValueException { - this.tags.addAll(Utils.parseTags(tags)); - } - - /** - * Convenience constructor using raw values. - */ - public DeleteCommandP(int index) { - super(index); - } - - @Override - public CommandResultP execute() { - Map selectedSlots = new TreeMap<>(); - - if (getTargetIndex() == -1) { - for (Map.Entry day : planner.getSemester().getDays().entrySet()) { - for (Slot slot : day.getValue().getSlots()) { - if (slot.getTags().containsAll(tags)) { - selectedSlots.put(LocalDateTime.of(day.getKey(), slot.getStartTime()), slot); - } - } - } - if (selectedSlots.size() == 0) { - return new CommandResultP(String.format(MESSAGE_SUCCESS_NO_CHANGE, craftSelectedMessage())); - } - } else { - try { - final Pair target = getTargetSlot(); - selectedSlots.put(LocalDateTime.of(target.getKey(), - target.getValue().getStartTime()), target.getValue()); - - if (!planner.containsSlot(target.getKey(), target.getValue())) { - return new CommandResultP(Messages.MESSAGE_SLOT_NOT_IN_PLANNER); - } - } catch (IndexOutOfBoundsException ie) { - return new CommandResultP(Messages.MESSAGE_INVALID_SLOT_DISPLAYED_INDEX); - } - } - - // perform deletion of slots from the planner - for (Map.Entry slot: selectedSlots.entrySet()) { - planner.getSemester().getDays().get(slot.getKey().toLocalDate()).removeSlot(slot.getValue()); - } - - return new CommandResultP(String.format(MESSAGE_SUCCESS, selectedSlots.size(), - craftSelectedMessage(), craftSuccessMessage(selectedSlots))); - } - - /** - * Craft success message. - */ - private String craftSuccessMessage(Map selectedSlots) { - StringBuilder sb = new StringBuilder(); - - sb.append("Deleted Slots: "); - sb.append("\n"); - - int count = 1; - for (Map.Entry editedSlot : selectedSlots.entrySet()) { - sb.append("\tItem: "); - sb.append(count); - sb.append(": "); - sb.append("\n\t\t"); - sb.append(editedSlot.getValue().getName().toString()); - sb.append("\n\t\t"); - sb.append(editedSlot.getKey().toLocalDate().toString()); - sb.append(" "); - sb.append(editedSlot.getKey().toLocalTime().toString()); - sb.append(", "); - sb.append(planner.getSemester().getDays().get(editedSlot.getKey().toLocalDate()).getType()); - sb.append(", "); - sb.append(editedSlot.getKey().getDayOfWeek().toString()); - count++; - sb.append("\n\n"); - } - - return sb.toString(); - } - - /** - * Craft selected message. - */ - private String craftSelectedMessage() { - StringBuilder sb = new StringBuilder(); - sb.append("Selected Slots containing tags: \n"); - - for (TagP tag : tags) { - sb.append("\t"); - sb.append(tag.toString()); - sb.append("\n"); - } - - return sb.toString(); - } -} diff --git a/src/planmysem/commands/EditCommandP.java b/src/planmysem/commands/EditCommand.java similarity index 87% rename from src/planmysem/commands/EditCommandP.java rename to src/planmysem/commands/EditCommand.java index 9b56306ba..436d4b8ed 100644 --- a/src/planmysem/commands/EditCommandP.java +++ b/src/planmysem/commands/EditCommand.java @@ -21,7 +21,7 @@ /** * Adds a person to the address book. */ -public class EditCommandP extends CommandP { +public class EditCommand extends Command { public static final String COMMAND_WORD = "edit"; public static final String COMMAND_WORD_SHORT = "e"; @@ -56,8 +56,8 @@ public class EditCommandP extends CommandP { * * @throws IllegalValueException if any of the raw values are invalid */ - public EditCommandP(String name, LocalTime startTime, int duration, String location, String description, - Set tags, Set newTags) throws IllegalValueException { + public EditCommand(String name, LocalTime startTime, int duration, String location, String description, + Set tags, Set newTags) throws IllegalValueException { this.date = null; this.startTime = startTime; this.duration = duration; @@ -73,8 +73,8 @@ public EditCommandP(String name, LocalTime startTime, int duration, String locat /** * Convenience constructor using raw values. */ - public EditCommandP(int index, String name, LocalDate date, LocalTime startTime, int duration, - String location, String description, Set newTags) + public EditCommand(int index, String name, LocalDate date, LocalTime startTime, int duration, + String location, String description, Set newTags) throws IllegalValueException { super(index); this.date = date; @@ -89,7 +89,7 @@ public EditCommandP(int index, String name, LocalDate date, LocalTime startTime, } @Override - public CommandResultP execute() { + public CommandResult execute() { Map selectedSlots = new TreeMap<>(); if (getTargetIndex() == -1) { @@ -101,7 +101,7 @@ public CommandResultP execute() { } } if (selectedSlots.size() == 0) { - return new CommandResultP(String.format(MESSAGE_SUCCESS_NO_CHANGE, craftSelectedMessage())); + return new CommandResult(String.format(MESSAGE_SUCCESS_NO_CHANGE, craftSelectedMessage())); } } else { try { @@ -109,10 +109,10 @@ public CommandResultP execute() { selectedSlots.put(LocalDateTime.of(target.getKey(), target.getValue().getStartTime()), target.getValue()); if (!planner.containsSlot(target.getKey(), target.getValue())) { - return new CommandResultP(Messages.MESSAGE_SLOT_NOT_IN_PLANNER); + return new CommandResult(Messages.MESSAGE_SLOT_NOT_IN_PLANNER); } } catch (IndexOutOfBoundsException ie) { - return new CommandResultP(Messages.MESSAGE_INVALID_SLOT_DISPLAYED_INDEX); + return new CommandResult(Messages.MESSAGE_INVALID_SLOT_DISPLAYED_INDEX); } } @@ -121,13 +121,13 @@ public CommandResultP execute() { planner.editSlot(entry.getKey().toLocalDate(), entry.getValue(), date, startTime, duration, name, location, description, newTags); } catch (IllegalValueException ive) { - return new CommandResultP(MESSAGE_FAIL_ILLEGAL_VALUE); + return new CommandResult(MESSAGE_FAIL_ILLEGAL_VALUE); } catch (Semester.DateNotFoundException dnfe) { - return new CommandResultP(Messages.MESSAGE_SLOT_NOT_IN_PLANNER); + return new CommandResult(Messages.MESSAGE_SLOT_NOT_IN_PLANNER); } } - return new CommandResultP(String.format(MESSAGE_SUCCESS, selectedSlots.size(), + return new CommandResult(String.format(MESSAGE_SUCCESS, selectedSlots.size(), craftSelectedMessage(), craftSuccessMessage(selectedSlots))); } diff --git a/src/planmysem/commands/ExitCommand.java b/src/planmysem/commands/ExitCommand.java index 36f9e4cf0..4d1c36079 100644 --- a/src/planmysem/commands/ExitCommand.java +++ b/src/planmysem/commands/ExitCommand.java @@ -9,7 +9,7 @@ public class ExitCommand extends Command { public static final String MESSAGE_USAGE = COMMAND_WORD + ":\n" + "Exits the program.\n\t" + "Example: " + COMMAND_WORD; - public static final String MESSAGE_EXIT_ACKNOWEDGEMENT = "Exiting Address Book as requested ..."; + public static final String MESSAGE_EXIT_ACKNOWEDGEMENT = "Exiting PlanMySem as requested ..."; @Override public CommandResult execute() { diff --git a/src/planmysem/commands/ExitCommandP.java b/src/planmysem/commands/ExitCommandP.java deleted file mode 100644 index 3dcba5263..000000000 --- a/src/planmysem/commands/ExitCommandP.java +++ /dev/null @@ -1,19 +0,0 @@ -package planmysem.commands; - -/** - * Terminates the program. - */ -public class ExitCommandP extends CommandP { - - public static final String COMMAND_WORD = "exit"; - - public static final String MESSAGE_USAGE = COMMAND_WORD + ":\n" + "Exits the program.\n\t" - + "Example: " + COMMAND_WORD; - public static final String MESSAGE_EXIT_ACKNOWEDGEMENT = "Exiting PlanMySem as requested ..."; - - @Override - public CommandResultP execute() { - return new CommandResultP(MESSAGE_EXIT_ACKNOWEDGEMENT); - } - -} diff --git a/src/planmysem/commands/ExportCommandP.java b/src/planmysem/commands/ExportCommand.java similarity index 85% rename from src/planmysem/commands/ExportCommandP.java rename to src/planmysem/commands/ExportCommand.java index 6754f01fb..06c5a1243 100644 --- a/src/planmysem/commands/ExportCommandP.java +++ b/src/planmysem/commands/ExportCommand.java @@ -9,7 +9,7 @@ /** * Exports the calendar into a .ics file. */ -public class ExportCommandP extends CommandP { +public class ExportCommand extends Command { public static final String COMMAND_WORD = "export"; public static final String MESSAGE_USAGE = COMMAND_WORD + ": Delete single or multiple slots in the Planner." @@ -17,7 +17,7 @@ public class ExportCommandP extends CommandP { public static final String MESSAGE_EXPORT_ACKNOWEDGEMENT = "Calendar exported"; @Override - public CommandResultP execute() { + public CommandResult execute() { AdaptedSemester semester = new AdaptedSemester(planner.getSemester()); System.out.println(semester.toString()); try { @@ -28,7 +28,7 @@ public CommandResultP execute() { e.printStackTrace(); } - return new CommandResultP(MESSAGE_EXPORT_ACKNOWEDGEMENT); + return new CommandResult(MESSAGE_EXPORT_ACKNOWEDGEMENT); } } diff --git a/src/planmysem/commands/FindCommand.java b/src/planmysem/commands/FindCommand.java index 1a54ae693..07a0f823d 100644 --- a/src/planmysem/commands/FindCommand.java +++ b/src/planmysem/commands/FindCommand.java @@ -1,25 +1,27 @@ package planmysem.commands; import java.util.ArrayList; -import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.stream.Collectors; + +import planmysem.data.semester.Day; +import planmysem.data.slot.Slot; -import planmysem.data.person.ReadOnlyPerson; /** - * Finds and lists all persons in address book whose name contains any of the argument keywords. + * Finds all slots and tags in planner whose name directly matches any of the argument keywords. * Keyword matching is case sensitive. */ public class FindCommand extends Command { public static final String COMMAND_WORD = "find"; - public static final String MESSAGE_USAGE = COMMAND_WORD + ":\n" + "Finds all persons whose names contain any of " - + "the specified keywords (case-sensitive) and displays them as a list with index numbers.\n\t" + public static final String MESSAGE_USAGE = COMMAND_WORD + ":\n" + "Finds all slots and tags which directly " + + "matches the specified keywords (case-sensitive).\n\t" + "Parameters: KEYWORD [MORE_KEYWORDS]...\n\t" - + "Example: " + COMMAND_WORD + " alice bob charlie"; + + "Example: " + COMMAND_WORD + " CS2113T"; private final Set keywords; @@ -36,25 +38,28 @@ public Set getKeywords() { @Override public CommandResult execute() { - final List personsFound = getPersonsWithNameContainingAnyKeyword(keywords); - return new CommandResult(getMessageForPersonListShownSummary(personsFound), personsFound); + String result = getSlotsWithTag(keywords).stream().map(Object::toString) + .collect(Collectors.joining(", ")); + return new CommandResult(result); } /** - * Retrieve all persons in the address book whose names contain some of the specified keywords. + * Retrieve all slot in the semesters of the planner whose slots contain some of the specified keywords. * * @param keywords for searching * @return list of persons found */ - private List getPersonsWithNameContainingAnyKeyword(Set keywords) { - final List matchedPersons = new ArrayList<>(); - for (ReadOnlyPerson person : addressBook.getAllPersons()) { - final Set wordsInName = new HashSet<>(person.getName().getWordsInName()); - if (!Collections.disjoint(wordsInName, keywords)) { - matchedPersons.add(person); + private List getSlotsWithTag(Set keywords) { + List test = new ArrayList<>(); + for (Day days : planner.getSemester().getDays().values()) { + for (Slot slots : days.getSlots()) { + for (String keyword : keywords) { + if (slots.getName().value.equalsIgnoreCase(keyword)) { + test.add(slots); + } + } } } - return matchedPersons; + return test; } - } diff --git a/src/planmysem/commands/FindCommandP.java b/src/planmysem/commands/FindCommandP.java deleted file mode 100644 index bacf05e61..000000000 --- a/src/planmysem/commands/FindCommandP.java +++ /dev/null @@ -1,65 +0,0 @@ -package planmysem.commands; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - -import planmysem.data.semester.Day; -import planmysem.data.slot.Slot; - - -/** - * Finds all slots and tags in planner whose name directly matches any of the argument keywords. - * Keyword matching is case sensitive. - */ -public class FindCommandP extends CommandP { - - public static final String COMMAND_WORD = "find"; - - public static final String MESSAGE_USAGE = COMMAND_WORD + ":\n" + "Finds all slots and tags which directly " - + "matches the specified keywords (case-sensitive).\n\t" - + "Parameters: KEYWORD [MORE_KEYWORDS]...\n\t" - + "Example: " + COMMAND_WORD + " CS2113T"; - - private final Set keywords; - - public FindCommandP(Set keywords) { - this.keywords = keywords; - } - - /** - * Returns copy of keywords in this command. - */ - public Set getKeywords() { - return new HashSet<>(keywords); - } - - @Override - public CommandResultP execute() { - String result = getSlotsWithTag(keywords).stream().map(Object::toString) - .collect(Collectors.joining(", ")); - return new CommandResultP(result); - } - - /** - * Retrieve all slot in the semesters of the planner whose slots contain some of the specified keywords. - * - * @param keywords for searching - * @return list of persons found - */ - private List getSlotsWithTag(Set keywords) { - List test = new ArrayList<>(); - for (Day days : planner.getSemester().getDays().values()) { - for (Slot slots : days.getSlots()) { - for (String keyword : keywords) { - if (slots.getName().value.equalsIgnoreCase(keyword)) { - test.add(slots); - } - } - } - } - return test; - } -} diff --git a/src/planmysem/commands/HelpCommand.java b/src/planmysem/commands/HelpCommand.java index f4555d76e..2d7471c4d 100644 --- a/src/planmysem/commands/HelpCommand.java +++ b/src/planmysem/commands/HelpCommand.java @@ -12,14 +12,15 @@ public class HelpCommand extends Command { + "Example: " + COMMAND_WORD; public static final String MESSAGE_ALL_USAGES = AddCommand.MESSAGE_USAGE - + "\n" + DeleteCommand.MESSAGE_USAGE - + "\n" + ClearCommand.MESSAGE_USAGE - + "\n" + FindCommand.MESSAGE_USAGE - + "\n" + ListCommand.MESSAGE_USAGE - + "\n" + ViewCommand.MESSAGE_USAGE - + "\n" + ViewAllCommand.MESSAGE_USAGE - + "\n" + HelpCommand.MESSAGE_USAGE - + "\n" + ExitCommand.MESSAGE_USAGE; + + "\n\n" + EditCommand.MESSAGE_USAGE + + "\n\n" + DeleteCommand.MESSAGE_USAGE + + "\n\n" + ListCommand.MESSAGE_USAGE + + "\n\n" + FindCommand.MESSAGE_USAGE + // + "\n\n" + ViewCommand.MESSAGE_USAGE + // + "\n\n" + ViewAllCommand.MESSAGE_USAGE + + "\n\n" + ClearCommand.MESSAGE_USAGE + + "\n\n" + HelpCommand.MESSAGE_USAGE + + "\n\n" + ExitCommand.MESSAGE_USAGE; @Override public CommandResult execute() { diff --git a/src/planmysem/commands/HelpCommandP.java b/src/planmysem/commands/HelpCommandP.java deleted file mode 100644 index 200f1d913..000000000 --- a/src/planmysem/commands/HelpCommandP.java +++ /dev/null @@ -1,29 +0,0 @@ -package planmysem.commands; - - -/** - * Shows help instructions. - */ -public class HelpCommandP extends CommandP { - - public static final String COMMAND_WORD = "help"; - - public static final String MESSAGE_USAGE = COMMAND_WORD + ":\n" + "Shows program usage instructions.\n\t" - + "Example: " + COMMAND_WORD; - - public static final String MESSAGE_ALL_USAGES = AddCommandP.MESSAGE_USAGE - + "\n\n" + EditCommandP.MESSAGE_USAGE - // + "\n\n" + DeleteCommand.MESSAGE_USAGE - + "\n\n" + ClearCommandP.MESSAGE_USAGE - + "\n\n" + FindCommand.MESSAGE_USAGE - + "\n\n" + ListCommandP.MESSAGE_USAGE - // + "\n\n" + ViewCommand.MESSAGE_USAGE - // + "\n\n" + ViewAllCommand.MESSAGE_USAGE - + "\n\n" + HelpCommandP.MESSAGE_USAGE - + "\n\n" + ExitCommandP.MESSAGE_USAGE; - - @Override - public CommandResultP execute() { - return new CommandResultP(MESSAGE_ALL_USAGES); - } -} diff --git a/src/planmysem/commands/HistoryCommand.java b/src/planmysem/commands/HistoryCommand.java index 573487261..393f14172 100644 --- a/src/planmysem/commands/HistoryCommand.java +++ b/src/planmysem/commands/HistoryCommand.java @@ -10,7 +10,7 @@ /** * Lists all the commands entered by user from the start of app launch. */ -public class HistoryCommand extends CommandP { +public class HistoryCommand extends Command { public static final String COMMAND_WORD = "history"; public static final String MESSAGE_SUCCESS = "Entered commands (from most recent to earliest):\n%1$s"; @@ -27,18 +27,18 @@ public HistoryCommand(CommandHistory commandHistory) { /** * TODO: description - * @return CommandResultP with a list of previousCommands + * @return CommandResult with a list of previousCommands */ - public CommandResultP execute() { + public CommandResult execute() { requireNonNull(commandHistory); ArrayList previousCommands = new ArrayList<>(commandHistory.getHistory()); if (previousCommands.isEmpty()) { - return new CommandResultP(MESSAGE_NO_HISTORY); + return new CommandResult(MESSAGE_NO_HISTORY); } Collections.reverse(previousCommands); - return new CommandResultP(String.format(MESSAGE_SUCCESS, String.join("\n", previousCommands))); + return new CommandResult(String.format(MESSAGE_SUCCESS, String.join("\n", previousCommands))); } } diff --git a/src/planmysem/commands/IncorrectCommand.java b/src/planmysem/commands/IncorrectCommand.java deleted file mode 100644 index d90bd4513..000000000 --- a/src/planmysem/commands/IncorrectCommand.java +++ /dev/null @@ -1,20 +0,0 @@ -package planmysem.commands; - - -/** - * Represents an incorrect command. Upon execution, produces some feedback to the user. - */ -public class IncorrectCommand extends Command { - - public final String feedbackToUser; - - public IncorrectCommand(String feedbackToUser) { - this.feedbackToUser = feedbackToUser; - } - - @Override - public CommandResult execute() { - return new CommandResult(feedbackToUser); - } - -} diff --git a/src/planmysem/commands/IncorrectCommandP.java b/src/planmysem/commands/IncorrectCommandP.java deleted file mode 100644 index f5dd0ef8a..000000000 --- a/src/planmysem/commands/IncorrectCommandP.java +++ /dev/null @@ -1,20 +0,0 @@ -package planmysem.commands; - - -/** - * Represents an incorrect command. Upon execution, produces some feedback to the user. - */ -public class IncorrectCommandP extends CommandP { - - public final String feedbackToUser; - - public IncorrectCommandP(String feedbackToUser) { - this.feedbackToUser = feedbackToUser; - } - - @Override - public CommandResultP execute() { - return new CommandResultP(feedbackToUser); - } - -} diff --git a/src/planmysem/commands/ListCommand.java b/src/planmysem/commands/ListCommand.java index 34975191d..9b40505af 100644 --- a/src/planmysem/commands/ListCommand.java +++ b/src/planmysem/commands/ListCommand.java @@ -1,25 +1,83 @@ package planmysem.commands; +import java.time.LocalDate; +import java.util.ArrayList; import java.util.List; +import java.util.Map; -import planmysem.data.person.ReadOnlyPerson; - +import javafx.util.Pair; +import planmysem.data.semester.Day; +import planmysem.data.slot.ReadOnlySlot; +import planmysem.data.slot.Slot; /** - * Lists all persons in the address book to the user. + * Finds and lists all slots in planner whose name contains any of the argument keywords. + * Keyword matching is case sensitive. */ public class ListCommand extends Command { public static final String COMMAND_WORD = "list"; + public static final String COMMAND_WORD_SHORT = "l"; + public static final String MESSAGE_SUCCESS = "%1$s Slots listed.\n%2$s"; + public static final String MESSAGE_SUCCESS_NONE = "0 Slots listed.\n"; + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Lists all slots." + + "\n\tOptional Parameters: [past] [next] [all]" + + "\n\tDefault: list all" + + "\n\tExample: " + COMMAND_WORD + " CS1010 tutorial lab"; - public static final String MESSAGE_USAGE = COMMAND_WORD + ":\n" - + "Displays all persons in the address book as a list with index numbers.\n\t" - + "Example: " + COMMAND_WORD; - + private final String name; + public ListCommand(String name) { + this.name = name; + } @Override public CommandResult execute() { - List allPersons = addressBook.getAllPersons().immutableListView(); - return new CommandResult(getMessageForPersonListShownSummary(allPersons), allPersons); + final List> relevantSlots = new ArrayList<>(); + List matchedSlots = new ArrayList<>(); + LocalDate date; + + for (Map.Entry entry : planner.getSemester().getDays().entrySet()) { + for (Slot slots : entry.getValue().getSlots()) { + if (slots.getName().value.equalsIgnoreCase(name)) { + matchedSlots.add(slots); + date = entry.getKey(); + relevantSlots.add(new Pair<>(date, slots)); + } + } + } + + if (matchedSlots.isEmpty()) { + return new CommandResult(MESSAGE_SUCCESS_NONE); + } + setData(this.planner, relevantSlots); + + return new CommandResult(String.format(MESSAGE_SUCCESS, matchedSlots.size(), + craftSuccessMessage(relevantSlots))); + } + + /** + * Craft success message. + */ + private String craftSuccessMessage(List> result) { + int count = 1; + StringBuilder sb = new StringBuilder(); + + for (Pair pair : result) { + sb.append("\n"); + sb.append(count + ".\t"); + sb.append("Name: "); + sb.append(pair.getValue().getName().toString()); + sb.append(",\n\t"); + sb.append("Date: "); + sb.append(pair.getKey().toString()); + sb.append(",\n\t"); + sb.append("Start Time: "); + sb.append(pair.getValue().getStartTime()); + sb.append("\n"); + count++; + } + return sb.toString(); } } + + diff --git a/src/planmysem/commands/ListCommandP.java b/src/planmysem/commands/ListCommandP.java deleted file mode 100644 index 05acff22c..000000000 --- a/src/planmysem/commands/ListCommandP.java +++ /dev/null @@ -1,84 +0,0 @@ -package planmysem.commands; - -import java.time.LocalDate; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import javafx.util.Pair; - -import planmysem.data.semester.Day; -import planmysem.data.slot.ReadOnlySlot; -import planmysem.data.slot.Slot; - -/** - * Finds and lists all slots in planner whose name contains any of the argument keywords. - * Keyword matching is case sensitive. - */ -public class ListCommandP extends CommandP { - - public static final String COMMAND_WORD = "list"; - public static final String COMMAND_WORD_SHORT = "l"; - public static final String MESSAGE_SUCCESS = "%1$s Slots listed.\n%2$s"; - public static final String MESSAGE_SUCCESS_NONE = "0 Slots listed.\n"; - public static final String MESSAGE_USAGE = COMMAND_WORD + ": Lists all slots." - + "\n\tOptional Parameters: [past] [next] [all]" - + "\n\tDefault: list all" - + "\n\tExample: " + COMMAND_WORD + " CS1010 tutorial lab"; - - private final String name; - - public ListCommandP(String name) { - this.name = name; - } - @Override - public CommandResultP execute() { - final List> relevantSlots = new ArrayList<>(); - List matchedSlots = new ArrayList<>(); - LocalDate date; - - for (Map.Entry entry : planner.getSemester().getDays().entrySet()) { - for (Slot slots : entry.getValue().getSlots()) { - if (slots.getName().value.equalsIgnoreCase(name)) { - matchedSlots.add(slots); - date = entry.getKey(); - relevantSlots.add(new Pair<>(date, slots)); - } - } - } - - if (matchedSlots.isEmpty()) { - return new CommandResultP(MESSAGE_SUCCESS_NONE); - } - setData(this.planner, relevantSlots); - - return new CommandResultP(String.format(MESSAGE_SUCCESS, matchedSlots.size(), - craftSuccessMessage(relevantSlots))); - } - - /** - * Craft success message. - */ - private String craftSuccessMessage(List> result) { - int count = 1; - StringBuilder sb = new StringBuilder(); - - for (Pair pair : result) { - sb.append("\n"); - sb.append(count + ".\t"); - sb.append("Name: "); - sb.append(pair.getValue().getName().toString()); - sb.append(",\n\t"); - sb.append("Date: "); - sb.append(pair.getKey().toString()); - sb.append(",\n\t"); - sb.append("Start Time: "); - sb.append(pair.getValue().getStartTime()); - sb.append("\n"); - count++; - } - return sb.toString(); - } -} - - diff --git a/src/planmysem/commands/ViewAllCommand.java b/src/planmysem/commands/ViewAllCommand.java deleted file mode 100644 index 1b77760d5..000000000 --- a/src/planmysem/commands/ViewAllCommand.java +++ /dev/null @@ -1,40 +0,0 @@ -package planmysem.commands; - -import planmysem.common.Messages; -import planmysem.data.person.ReadOnlyPerson; - - -/** - * Shows all details of the person identified using the last displayed index. - * Private contact details are shown. - */ -public class ViewAllCommand extends Command { - - public static final String COMMAND_WORD = "viewall"; - - public static final String MESSAGE_USAGE = COMMAND_WORD + ":\n" + "Shows all details of the person " - + "identified by the index number in the last shown person listing.\n\t" - + "Parameters: INDEX\n\t" - + "Example: " + COMMAND_WORD + " 1"; - - public static final String MESSAGE_VIEW_PERSON_DETAILS = "Viewing person: %1$s"; - - - public ViewAllCommand(int targetVisibleIndex) { - super(targetVisibleIndex); - } - - - @Override - public CommandResult execute() { - try { - final ReadOnlyPerson target = getTargetPerson(); - if (!addressBook.containsPerson(target)) { - return new CommandResult(Messages.MESSAGE_PERSON_NOT_IN_ADDRESSBOOK); - } - return new CommandResult(String.format(MESSAGE_VIEW_PERSON_DETAILS, target.getAsTextShowAll())); - } catch (IndexOutOfBoundsException ie) { - return new CommandResult(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); - } - } -} diff --git a/src/planmysem/commands/ViewCommand.java b/src/planmysem/commands/ViewCommand.java deleted file mode 100644 index e064b3057..000000000 --- a/src/planmysem/commands/ViewCommand.java +++ /dev/null @@ -1,41 +0,0 @@ -package planmysem.commands; - -import planmysem.common.Messages; -import planmysem.data.person.ReadOnlyPerson; - - -/** - * Shows details of the person identified using the last displayed index. - * Private contact details are not shown. - */ -public class ViewCommand extends Command { - - public static final String COMMAND_WORD = "view"; - - public static final String MESSAGE_USAGE = COMMAND_WORD + ":\n" + "Shows the non-private details of the person " - + "identified by the index number in the last shown person listing.\n\t" - + "Parameters: INDEX\n\t" - + "Example: " + COMMAND_WORD + " 1"; - - public static final String MESSAGE_VIEW_PERSON_DETAILS = "Viewing person: %1$s"; - - - public ViewCommand(int targetVisibleIndex) { - super(targetVisibleIndex); - } - - - @Override - public CommandResult execute() { - try { - final ReadOnlyPerson target = getTargetPerson(); - if (!addressBook.containsPerson(target)) { - return new CommandResult(Messages.MESSAGE_PERSON_NOT_IN_ADDRESSBOOK); - } - return new CommandResult(String.format(MESSAGE_VIEW_PERSON_DETAILS, target.getAsTextHidePrivate())); - } catch (IndexOutOfBoundsException ie) { - return new CommandResult(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); - } - } - -} diff --git a/src/planmysem/data/AddressBook.java b/src/planmysem/data/AddressBook.java deleted file mode 100644 index f95fc9509..000000000 --- a/src/planmysem/data/AddressBook.java +++ /dev/null @@ -1,85 +0,0 @@ -package planmysem.data; - -import planmysem.data.person.Person; -import planmysem.data.person.ReadOnlyPerson; -import planmysem.data.person.UniquePersonList; -import planmysem.data.person.UniquePersonList.DuplicatePersonException; -import planmysem.data.person.UniquePersonList.PersonNotFoundException; - -/** - * Represents the entire address book. Contains the data of the address book. - */ -public class AddressBook { - private final UniquePersonList allPersons; - - /** - * Creates an empty address book. - */ - public AddressBook() { - allPersons = new UniquePersonList(); - } - - /** - * Constructs an address book with the given data. - * - * @param persons external changes to this will not affect this address book - */ - public AddressBook(UniquePersonList persons) { - this.allPersons = new UniquePersonList(persons); - } - - public static AddressBook empty() { - return new AddressBook(); - } - - /** - * Adds a person to the address book. - * - * @throws DuplicatePersonException if an equivalent person already exists. - */ - public void addPerson(Person toAdd) throws DuplicatePersonException { - allPersons.add(toAdd); - } - - /** - * Checks if an equivalent person exists in the address book. - */ - public boolean containsPerson(ReadOnlyPerson key) { - return allPersons.contains(key); - } - - /** - * Removes the equivalent person from the address book. - * - * @throws PersonNotFoundException if no such Person could be found. - */ - public void removePerson(ReadOnlyPerson toRemove) throws PersonNotFoundException { - allPersons.remove(toRemove); - } - - /** - * Clears all persons from the address book. - */ - public void clear() { - allPersons.clear(); - } - - /** - * Defensively copied UniquePersonList of all persons in the address book at the time of the call. - */ - public UniquePersonList getAllPersons() { - return new UniquePersonList(allPersons); - } - - @Override - public boolean equals(Object other) { - return other == this // short circuit if same object - || (other instanceof AddressBook // instanceof handles nulls - && this.allPersons.equals(((AddressBook) other).allPersons)); - } - - @Override - public int hashCode() { - return allPersons.hashCode(); - } -} diff --git a/src/planmysem/data/person/Address.java b/src/planmysem/data/person/Address.java deleted file mode 100644 index a4839e0f0..000000000 --- a/src/planmysem/data/person/Address.java +++ /dev/null @@ -1,58 +0,0 @@ -package planmysem.data.person; - -import planmysem.data.exception.IllegalValueException; - -/** - * Represents a Person's address in the address book. - * Guarantees: immutable; is valid as declared in {@link #isValidAddress(String)} - */ -public class Address { - - public static final String EXAMPLE = "123, some street"; - public static final String MESSAGE_ADDRESS_CONSTRAINTS = "Person addresses can be in any format"; - public static final String ADDRESS_VALIDATION_REGEX = ".+"; - - public final String value; - private boolean isPrivate; - - /** - * Validates given address. - * - * @throws IllegalValueException if given address string is invalid. - */ - public Address(String address, boolean isPrivate) throws IllegalValueException { - this.isPrivate = isPrivate; - if (!isValidAddress(address)) { - throw new IllegalValueException(MESSAGE_ADDRESS_CONSTRAINTS); - } - this.value = address; - } - - /** - * Returns true if a given string is a valid person email. - */ - public static boolean isValidAddress(String test) { - return test.matches(ADDRESS_VALIDATION_REGEX); - } - - @Override - public String toString() { - return value; - } - - @Override - public boolean equals(Object other) { - return other == this // short circuit if same object - || (other instanceof Address // instanceof handles nulls - && this.value.equals(((Address) other).value)); // state check - } - - @Override - public int hashCode() { - return value.hashCode(); - } - - public boolean isPrivate() { - return isPrivate; - } -} diff --git a/src/planmysem/data/person/Email.java b/src/planmysem/data/person/Email.java deleted file mode 100644 index b24a87185..000000000 --- a/src/planmysem/data/person/Email.java +++ /dev/null @@ -1,60 +0,0 @@ -package planmysem.data.person; - -import planmysem.data.exception.IllegalValueException; - -/** - * Represents a Person's email in the address book. - * Guarantees: immutable; is valid as declared in {@link #isValidEmail(String)} - */ -public class Email { - - public static final String EXAMPLE = "valid@e.mail"; - public static final String MESSAGE_EMAIL_CONSTRAINTS = - "Person emails should be 2 alphanumeric/period strings separated by '@'"; - public static final String EMAIL_VALIDATION_REGEX = "[\\w\\.]+@[\\w\\.]+"; - - public final String value; - private boolean isPrivate; - - /** - * Validates given email. - * - * @throws IllegalValueException if given email address string is invalid. - */ - public Email(String email, boolean isPrivate) throws IllegalValueException { - this.isPrivate = isPrivate; - email = email.trim(); - if (!isValidEmail(email)) { - throw new IllegalValueException(MESSAGE_EMAIL_CONSTRAINTS); - } - this.value = email; - } - - /** - * Checks if a given string is a valid person email. - */ - public static boolean isValidEmail(String test) { - return test.matches(EMAIL_VALIDATION_REGEX); - } - - @Override - public String toString() { - return value; - } - - @Override - public boolean equals(Object other) { - return other == this // short circuit if same object - || (other instanceof Email // instanceof handles nulls - && this.value.equals(((Email) other).value)); // state check - } - - @Override - public int hashCode() { - return value.hashCode(); - } - - public boolean isPrivate() { - return isPrivate; - } -} diff --git a/src/planmysem/data/person/Name.java b/src/planmysem/data/person/Name.java deleted file mode 100644 index bb4e36f12..000000000 --- a/src/planmysem/data/person/Name.java +++ /dev/null @@ -1,64 +0,0 @@ -package planmysem.data.person; - -import java.util.Arrays; -import java.util.List; - -import planmysem.data.exception.IllegalValueException; - -/** - * Represents a Person's name in the address book. - * Guarantees: immutable; is valid as declared in {@link #isValidName(String)} - */ -public class Name { - - public static final String EXAMPLE = "John Doe"; - public static final String MESSAGE_NAME_CONSTRAINTS = "Person names should be spaces or alphanumeric characters"; - public static final String NAME_VALIDATION_REGEX = "[\\p{Alnum} ]+"; - - public final String fullName; - - /** - * Validates given name. - * - * @throws IllegalValueException if given name string is invalid. - */ - public Name(String name) throws IllegalValueException { - name = name.trim(); - if (!isValidName(name)) { - throw new IllegalValueException(MESSAGE_NAME_CONSTRAINTS); - } - this.fullName = name; - } - - /** - * Returns true if a given string is a valid person name. - */ - public static boolean isValidName(String test) { - return test.matches(NAME_VALIDATION_REGEX); - } - - /** - * Retrieves a listing of every word in the name, in order. - */ - public List getWordsInName() { - return Arrays.asList(fullName.split("\\s+")); - } - - @Override - public String toString() { - return fullName; - } - - @Override - public boolean equals(Object other) { - return other == this // short circuit if same object - || (other instanceof Name // instanceof handles nulls - && this.fullName.equals(((Name) other).fullName)); // state check - } - - @Override - public int hashCode() { - return fullName.hashCode(); - } - -} diff --git a/src/planmysem/data/person/Person.java b/src/planmysem/data/person/Person.java deleted file mode 100644 index 664cd747c..000000000 --- a/src/planmysem/data/person/Person.java +++ /dev/null @@ -1,89 +0,0 @@ -package planmysem.data.person; - -import java.util.HashSet; -import java.util.Objects; -import java.util.Set; - -import planmysem.data.tag.Tag; - -/** - * Represents a Person in the address book. - * Guarantees: details are present and not null, field values are validated. - */ -public class Person implements ReadOnlyPerson { - private final Set tags = new HashSet<>(); - private Name name; - private Phone phone; - private Email email; - private Address address; - - /** - * Assumption: Every field must be present and not null. - */ - public Person(Name name, Phone phone, Email email, Address address, Set tags) { - this.name = name; - this.phone = phone; - this.email = email; - this.address = address; - this.tags.addAll(tags); - } - - /** - * Copy constructor. - */ - public Person(ReadOnlyPerson source) { - this(source.getName(), source.getPhone(), source.getEmail(), source.getAddress(), source.getTags()); - } - - @Override - public Name getName() { - return name; - } - - @Override - public Phone getPhone() { - return phone; - } - - @Override - public Email getEmail() { - return email; - } - - @Override - public Address getAddress() { - return address; - } - - @Override - public Set getTags() { - return new HashSet<>(tags); - } - - /** - * Replaces this person's tags with the tags in {@code replacement}. - */ - public void setTags(Set replacement) { - tags.clear(); - tags.addAll(replacement); - } - - @Override - public boolean equals(Object other) { - return other == this // short circuit if same object - || (other instanceof ReadOnlyPerson // instanceof handles nulls - && this.isSameStateAs((ReadOnlyPerson) other)); - } - - @Override - public int hashCode() { - // use this method for custom fields hashing instead of implementing your own - return Objects.hash(name, phone, email, address, tags); - } - - @Override - public String toString() { - return getAsTextShowAll(); - } - -} diff --git a/src/planmysem/data/person/Phone.java b/src/planmysem/data/person/Phone.java deleted file mode 100644 index 128e49424..000000000 --- a/src/planmysem/data/person/Phone.java +++ /dev/null @@ -1,59 +0,0 @@ -package planmysem.data.person; - -import planmysem.data.exception.IllegalValueException; - -/** - * Represents a Person's phone number in the address book. - * Guarantees: immutable; is valid as declared in {@link #isValidPhone(String)} - */ -public class Phone { - - public static final String EXAMPLE = "123456789"; - public static final String MESSAGE_PHONE_CONSTRAINTS = "Person phone numbers should only contain numbers"; - public static final String PHONE_VALIDATION_REGEX = "\\d+"; - - public final String value; - private boolean isPrivate; - - /** - * Validates given phone number. - * - * @throws IllegalValueException if given phone string is invalid. - */ - public Phone(String phone, boolean isPrivate) throws IllegalValueException { - this.isPrivate = isPrivate; - phone = phone.trim(); - if (!isValidPhone(phone)) { - throw new IllegalValueException(MESSAGE_PHONE_CONSTRAINTS); - } - this.value = phone; - } - - /** - * Checks if a given string is a valid person phone number. - */ - public static boolean isValidPhone(String test) { - return test.matches(PHONE_VALIDATION_REGEX); - } - - @Override - public String toString() { - return value; - } - - @Override - public boolean equals(Object other) { - return other == this // short circuit if same object - || (other instanceof Phone // instanceof handles nulls - && this.value.equals(((Phone) other).value)); // state check - } - - @Override - public int hashCode() { - return value.hashCode(); - } - - public boolean isPrivate() { - return isPrivate; - } -} diff --git a/src/planmysem/data/person/ReadOnlyPerson.java b/src/planmysem/data/person/ReadOnlyPerson.java deleted file mode 100644 index 4ac7766e9..000000000 --- a/src/planmysem/data/person/ReadOnlyPerson.java +++ /dev/null @@ -1,90 +0,0 @@ -package planmysem.data.person; - -import java.util.Set; - -import planmysem.data.tag.Tag; - -/** - * A read-only immutable interface for a Person in the planmysem. - * Implementations should guarantee: details are present and not null, field values are validated. - */ -public interface ReadOnlyPerson { - - Name getName(); - - Phone getPhone(); - - Email getEmail(); - - Address getAddress(); - - /** - * The returned {@code Set} is a deep copy of the internal {@code Set}, - * changes on the returned list will not affect the person's internal tags. - */ - Set getTags(); - - /** - * Returns true if the values inside this object is same as - * those of the other (Note: interfaces cannot override .equals) - */ - default boolean isSameStateAs(ReadOnlyPerson other) { - return other == this // short circuit if same object - || (other != null // this is first to avoid NPE below - && other.getName().equals(this.getName()) // state checks here onwards - && other.getPhone().equals(this.getPhone()) - && other.getEmail().equals(this.getEmail()) - && other.getAddress().equals(this.getAddress())); - } - - /** - * Formats the person as text, showing all contact details. - */ - default String getAsTextShowAll() { - final StringBuilder builder = new StringBuilder(); - final String detailIsPrivate = "(private) "; - builder.append(getName()) - .append(" Phone: "); - if (getPhone().isPrivate()) { - builder.append(detailIsPrivate); - } - builder.append(getPhone()) - .append(" Email: "); - if (getEmail().isPrivate()) { - builder.append(detailIsPrivate); - } - builder.append(getEmail()) - .append(" Address: "); - if (getAddress().isPrivate()) { - builder.append(detailIsPrivate); - } - builder.append(getAddress()) - .append(" Tags: "); - for (Tag tag : getTags()) { - builder.append(tag); - } - return builder.toString(); - } - - /** - * Formats a person as text, showing only non-private contact details. - */ - default String getAsTextHidePrivate() { - final StringBuilder builder = new StringBuilder(); - builder.append(getName()); - if (!getPhone().isPrivate()) { - builder.append(" Phone: ").append(getPhone()); - } - if (!getEmail().isPrivate()) { - builder.append(" Email: ").append(getEmail()); - } - if (!getAddress().isPrivate()) { - builder.append(" Address: ").append(getAddress()); - } - builder.append(" Tags: "); - for (Tag tag : getTags()) { - builder.append(tag); - } - return builder.toString(); - } -} diff --git a/src/planmysem/data/person/UniquePersonList.java b/src/planmysem/data/person/UniquePersonList.java deleted file mode 100644 index 195f57372..000000000 --- a/src/planmysem/data/person/UniquePersonList.java +++ /dev/null @@ -1,140 +0,0 @@ -package planmysem.data.person; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; - -import planmysem.common.Utils; -import planmysem.data.exception.DuplicateDataException; - -/** - * A list of persons. Does not allow null elements or duplicates. - * - * @see Person#equals(Object) - * @see Utils#elementsAreUnique(Collection) - */ -public class UniquePersonList implements Iterable { - - private final List internalList = new ArrayList<>(); - - /** - * Constructs empty person list. - */ - public UniquePersonList() { - } - - /** - * Constructs a person list with the given persons. - */ - public UniquePersonList(Person... persons) throws DuplicatePersonException { - final List initialTags = Arrays.asList(persons); - if (!Utils.elementsAreUnique(initialTags)) { - throw new DuplicatePersonException(); - } - internalList.addAll(initialTags); - } - - /** - * Constructs a list from the items in the given collection. - * - * @param persons a collection of persons - * @throws DuplicatePersonException if the {@code persons} contains duplicate persons - */ - public UniquePersonList(Collection persons) throws DuplicatePersonException { - if (!Utils.elementsAreUnique(persons)) { - throw new DuplicatePersonException(); - } - internalList.addAll(persons); - } - - /** - * Constructs a shallow copy of the list. - */ - public UniquePersonList(UniquePersonList source) { - internalList.addAll(source.internalList); - } - - /** - * Unmodifiable java List view with elements cast as immutable {@link ReadOnlyPerson}s. - * For use with other methods/libraries. - * Any changes to the internal list/elements are immediately visible in the returned list. - */ - public List immutableListView() { - return Collections.unmodifiableList(internalList); - } - - /** - * Checks if the list contains an equivalent person as the given argument. - */ - public boolean contains(ReadOnlyPerson toCheck) { - return internalList.contains(toCheck); - } - - /** - * Adds a person to the list. - * - * @throws DuplicatePersonException if the person to addDay is a duplicate of an existing person in the list. - */ - public void add(Person toAdd) throws DuplicatePersonException { - if (contains(toAdd)) { - throw new DuplicatePersonException(); - } - internalList.add(toAdd); - } - - /** - * Removes the equivalent person from the list. - * - * @throws PersonNotFoundException if no such person could be found in the list. - */ - public void remove(ReadOnlyPerson toRemove) throws PersonNotFoundException { - final boolean personFoundAndDeleted = internalList.remove(toRemove); - if (!personFoundAndDeleted) { - throw new PersonNotFoundException(); - } - } - - /** - * Clears all persons in list. - */ - public void clear() { - internalList.clear(); - } - - @Override - public Iterator iterator() { - return internalList.iterator(); - } - - @Override - public boolean equals(Object other) { - return other == this // short circuit if same object - || (other instanceof UniquePersonList // instanceof handles nulls - && this.internalList.equals(((UniquePersonList) other).internalList)); - } - - @Override - public int hashCode() { - return internalList.hashCode(); - } - - /** - * Signals that an operation would have violated the 'no duplicates' property of the list. - */ - public static class DuplicatePersonException extends DuplicateDataException { - protected DuplicatePersonException() { - super("Operation would result in duplicate persons"); - } - } - - /** - * Signals that an operation targeting a specified person in the list would fail because - * there is no such matching person in the list. - */ - public static class PersonNotFoundException extends Exception { - } - -} diff --git a/src/planmysem/data/slot/Slot.java b/src/planmysem/data/slot/Slot.java index a55862340..f3d35e952 100644 --- a/src/planmysem/data/slot/Slot.java +++ b/src/planmysem/data/slot/Slot.java @@ -31,7 +31,9 @@ public Slot(Name name, Location location, Description description, this.description = description; this.startTime = startTime; this.duration = Utils.getDuration(startTime, endTime); - this.tags.addAll(tags); + if (tags != null) { + this.tags.addAll(tags); + } } /** @@ -44,7 +46,9 @@ public Slot(Name name, Location location, Description description, this.description = description; this.startTime = startTime; this.duration = duration; - this.tags.addAll(tags); + if (tags != null) { + this.tags.addAll(tags); + } } /** diff --git a/src/planmysem/logic/Logic.java b/src/planmysem/logic/Logic.java index 08c20d87a..9abf96982 100644 --- a/src/planmysem/logic/Logic.java +++ b/src/planmysem/logic/Logic.java @@ -1,53 +1,56 @@ package planmysem.logic; -import java.util.Collections; +import java.time.LocalDate; import java.util.List; import java.util.Optional; +import javax.xml.bind.JAXBException; + +import javafx.util.Pair; import planmysem.commands.Command; import planmysem.commands.CommandResult; -import planmysem.data.AddressBook; -import planmysem.data.person.ReadOnlyPerson; +import planmysem.data.Planner; +import planmysem.data.slot.ReadOnlySlot; import planmysem.parser.Parser; -import planmysem.storage.StorageFile; +import planmysem.storage.StorageFileP; /** * Represents the main Logic of the Planner. */ public class Logic { - private StorageFile storage; - private AddressBook addressBook; + private StorageFileP storage; + private Planner planner; /** - * The list of person shown to the user most recently. + * The list of Slots shown to the user most recently. */ - private List lastShownList = Collections.emptyList(); + private List> lastShownSlots; public Logic() throws Exception { setStorage(initializeStorage()); - setAddressBook(storage.load()); + setPlanner(storage.load()); } - public Logic(StorageFile storageFile, AddressBook addressBook) { + public Logic(StorageFileP storageFile, Planner planner) { setStorage(storageFile); - setAddressBook(addressBook); + setPlanner(planner); } - void setStorage(StorageFile storage) { + public void setStorage(StorageFileP storage) { this.storage = storage; } - void setAddressBook(AddressBook addressBook) { - this.addressBook = addressBook; + public void setPlanner(Planner planner) { + this.planner = planner; } /** * Creates the StorageFile object based on the user specified path (if any) or the default storage path. * - * @throws StorageFile.InvalidStorageFilePathException if the target file path is incorrect. + * @throws StorageFileP.InvalidStorageFilePathException if the target file path is incorrect. */ - private StorageFile initializeStorage() throws StorageFile.InvalidStorageFilePathException { - return new StorageFile(); + private StorageFileP initializeStorage() throws JAXBException, StorageFileP.InvalidStorageFilePathException { + return new StorageFileP(); } public String getStorageFilePath() { @@ -57,12 +60,12 @@ public String getStorageFilePath() { /** * Unmodifiable view of the current last shown list. */ - public List getLastShownList() { - return Collections.unmodifiableList(lastShownList); + public List> getLastShownSlots() { + return lastShownSlots; } - protected void setLastShownList(List newList) { - lastShownList = newList; + protected void setLastShownSlots(List> slots) { + lastShownSlots = slots; } /** @@ -85,19 +88,20 @@ public CommandResult execute(String userCommandText) throws Exception { * @throws Exception if there was any problem during command execution. */ private CommandResult execute(Command command) throws Exception { - command.setData(addressBook, lastShownList); + command.setData(planner, lastShownSlots); CommandResult result = command.execute(); - storage.save(addressBook); + storage.save(planner); return result; } /** - * Updates the {@link #lastShownList} if the result contains a list of Persons. + * Updates the {@link #lastShownSlots} if the result contains a list of Days. + * TODO: */ private void recordResult(CommandResult result) { - final Optional> personList = result.getRelevantPersons(); - if (personList.isPresent()) { - lastShownList = personList.get(); + final Optional>> slots = result.getRelevantSlots(); + if (slots.isPresent()) { + lastShownSlots = slots.get(); } } } diff --git a/src/planmysem/logic/LogicP.java b/src/planmysem/logic/LogicP.java deleted file mode 100644 index c3b7f961e..000000000 --- a/src/planmysem/logic/LogicP.java +++ /dev/null @@ -1,107 +0,0 @@ -package planmysem.logic; - -import java.time.LocalDate; -import java.util.List; -import java.util.Optional; - -import javax.xml.bind.JAXBException; - -import javafx.util.Pair; -import planmysem.commands.CommandP; -import planmysem.commands.CommandResultP; -import planmysem.data.Planner; -import planmysem.data.slot.ReadOnlySlot; -import planmysem.parser.ParserP; -import planmysem.storage.StorageFileP; - -/** - * Represents the main Logic of the Planner. - */ -public class LogicP { - private StorageFileP storage; - private Planner planner; - - /** - * The list of Slots shown to the user most recently. - */ - private List> lastShownSlots; - - public LogicP() throws Exception { - setStorage(initializeStorage()); - setPlanner(storage.load()); - } - - public LogicP(StorageFileP storageFile, Planner planner) { - setStorage(storageFile); - setPlanner(planner); - } - - public void setStorage(StorageFileP storage) { - this.storage = storage; - } - - public void setPlanner(Planner planner) { - this.planner = planner; - } - - /** - * Creates the StorageFile object based on the user specified path (if any) or the default storage path. - * - * @throws StorageFileP.InvalidStorageFilePathException if the target file path is incorrect. - */ - private StorageFileP initializeStorage() throws JAXBException, StorageFileP.InvalidStorageFilePathException { - return new StorageFileP(); - } - - public String getStorageFilePath() { - return storage.getPath(); - } - - /** - * Unmodifiable view of the current last shown list. - */ - public List> getLastShownSlots() { - return lastShownSlots; - } - - protected void setLastShownSlots(List> slots) { - lastShownSlots = slots; - } - - /** - * Parses the user command, executes it, and returns the result. - * - * @throws Exception if there was any problem during command execution. - */ - public CommandResultP execute(String userCommandText) throws Exception { - CommandP command = new ParserP().parseCommand(userCommandText); - CommandResultP result = execute(command); - recordResult(result); - return result; - } - - /** - * Executes the command, updates storage, and returns the result. - * - * @param command user command - * @return result of the command - * @throws Exception if there was any problem during command execution. - */ - private CommandResultP execute(CommandP command) throws Exception { - command.setData(planner, lastShownSlots); - CommandResultP result = command.execute(); - storage.save(planner); - return result; - } - - /** - * Updates the {@link #lastShownSlots} if the result contains a list of Days. - * TODO: - */ - private void recordResult(CommandResultP result) { - final Optional>> slots = result.getRelevantSlots(); - if (slots.isPresent()) { - lastShownSlots = slots.get(); - } - } -} diff --git a/src/planmysem/parser/Parser.java b/src/planmysem/parser/Parser.java index 5d371310d..3cdf637bd 100644 --- a/src/planmysem/parser/Parser.java +++ b/src/planmysem/parser/Parser.java @@ -2,9 +2,11 @@ import static planmysem.common.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import java.time.LocalDate; +import java.time.LocalTime; import java.util.Arrays; -import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.Set; import java.util.regex.Matcher; @@ -14,13 +16,13 @@ import planmysem.commands.ClearCommand; import planmysem.commands.Command; import planmysem.commands.DeleteCommand; +import planmysem.commands.EditCommand; import planmysem.commands.ExitCommand; import planmysem.commands.FindCommand; import planmysem.commands.HelpCommand; import planmysem.commands.IncorrectCommand; import planmysem.commands.ListCommand; -import planmysem.commands.ViewAllCommand; -import planmysem.commands.ViewCommand; +import planmysem.common.Utils; import planmysem.data.exception.IllegalValueException; /** @@ -33,40 +35,27 @@ public class Parser { public static final Pattern KEYWORDS_ARGS_FORMAT = Pattern.compile("(?\\S+(?:\\s+\\S+)*)"); // one or more keywords separated by whitespace - public static final Pattern PERSON_DATA_ARGS_FORMAT = // '/' forward slashes are reserved for delimiter prefixes - Pattern.compile("(?[^/]+)" - + " (?p?)p/(?[^/]+)" - + " (?p?)e/(?[^/]+)" - + " (?p?)a/(?
[^/]+)" - + "(?(?: t/[^/]+)*)"); // variable number of tags - /** - * Used for initial separation of command word and args. - */ - public static final Pattern BASIC_COMMAND_FORMAT = Pattern.compile("(?\\S+)(?.*)"); + private static final String PARAMETER_NAME = "n"; + private static final String PARAMETER_DATE_OR_DAY = "d"; + private static final String PARAMETER_START_TIME = "st"; + private static final String PARAMETER_END_TIME = "et"; + private static final String PARAMETER_RECURRENCE = "r"; + private static final String PARAMETER_LOCATION = "l"; + private static final String PARAMETER_DESCRIPTION = "des"; + private static final String PARAMETER_TAG = "t"; + private static final String PARAMETER_NEW_NAME = "nn"; + private static final String PARAMETER_NEW_DATE = "nd"; + private static final String PARAMETER_NEW_START_TIME = "nst"; + private static final String PARAMETER_NEW_END_TIME = "net"; + private static final String PARAMETER_NEW_LOCATION = "nl"; + private static final String PARAMETER_NEW_DESCRIPTION = "ndes"; + private static final String PARAMETER_NEW_TAG = "nt"; - /** - * Checks whether the private prefix of a contact detail in the - * add command's arguments string is present. - */ - private static boolean isPrivatePrefixPresent(String matchedPrefix) { - return matchedPrefix.equals("p"); - } /** - * Extracts the new person's tags from the addDay command's tag arguments string. - * Merges duplicate tag strings. + * Used for initial separation of command word and args. */ - private static Set getTagsFromArgs(String tagArguments) throws IllegalValueException { - // no tags - if (tagArguments.isEmpty()) { - return Collections.emptySet(); - } - // replace first delimiter prefix, then split - final Collection tagStrings = - Arrays.asList(tagArguments.replaceFirst( - " t/", "").split(" t/")); - return new HashSet<>(tagStrings); - } + private static final Pattern BASIC_COMMAND_FORMAT = Pattern.compile("(?\\S+)(?.*)"); /** * Parses user input into command for execution. @@ -82,119 +71,263 @@ public Command parseCommand(String userInput) { final String commandWord = matcher.group("commandWord"); final String arguments = matcher.group("arguments"); - switch (commandWord) { + switch (commandWord) { case AddCommand.COMMAND_WORD: + case AddCommand.COMMAND_WORD_SHORT: return prepareAdd(arguments); + case EditCommand.COMMAND_WORD: + case EditCommand.COMMAND_WORD_SHORT: + return prepareEdit(arguments); + case DeleteCommand.COMMAND_WORD: + case DeleteCommand.COMMAND_WORD_ALT: + case DeleteCommand.COMMAND_WORD_SHORT: return prepareDelete(arguments); - case ClearCommand.COMMAND_WORD: - return new ClearCommand(); - - case FindCommand.COMMAND_WORD: - return prepareFind(arguments); - case ListCommand.COMMAND_WORD: - return new ListCommand(); + case ListCommand.COMMAND_WORD_SHORT: + return prepareList(arguments); - case ViewCommand.COMMAND_WORD: - return prepareView(arguments); - - case ViewAllCommand.COMMAND_WORD: - return prepareViewAll(arguments); + case ClearCommand.COMMAND_WORD: + return new ClearCommand(); case ExitCommand.COMMAND_WORD: return new ExitCommand(); case HelpCommand.COMMAND_WORD: // Fallthrough + default: return new HelpCommand(); } } /** - * Parses arguments in the context of the addDay person command. + * Parses arguments in the context of the add command. * * @param args full command args string * @return the prepared command */ private Command prepareAdd(String args) { - final Matcher matcher = PERSON_DATA_ARGS_FORMAT.matcher(args.trim()); - // Validate arg string format - if (!matcher.matches()) { + HashMap> arguments = getParametersWithArguments(args); + + // Name is mandatory + String name = getFirstInSet(arguments.get(PARAMETER_NAME)); + + if ((arguments == null || arguments.isEmpty()) + || (name == null || name.isEmpty()) + || arguments.get(PARAMETER_DATE_OR_DAY) == null + || arguments.get(PARAMETER_START_TIME) == null + || arguments.get(PARAMETER_END_TIME) == null) { + return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE)); + } + + // Either date or day must be present + String dateOrDay = getFirstInSet(arguments.get(PARAMETER_DATE_OR_DAY)); + int day = Utils.parseDay(dateOrDay); + LocalDate date = null; + if (day == 0) { + date = Utils.parseDate(dateOrDay); + } + if (day == 0 && date == null) { + return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE)); + } + + // Start time is mandatory + String stringStartTime = getFirstInSet(arguments.get(PARAMETER_START_TIME)); + LocalTime startTime = Utils.parseTime(stringStartTime); + if (startTime == null) { return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE)); } - try { - return new AddCommand( - matcher.group("name"), - matcher.group("phone"), - isPrivatePrefixPresent(matcher.group("isPhonePrivate")), + // determine if "end time" is a duration or time + String stringEndTime = getFirstInSet(arguments.get(PARAMETER_END_TIME)); + int duration = Utils.parseInteger(stringEndTime); - matcher.group("email"), - isPrivatePrefixPresent(matcher.group("isEmailPrivate")), + if (duration == -1) { + LocalTime endTime = Utils.parseTime(stringEndTime); + if (endTime == null) { + return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE)); + } + duration = Utils.getDuration(startTime, endTime); + } + + // Description is not mandatory and can be null + String description = getFirstInSet(arguments.get(PARAMETER_DESCRIPTION)); + + // Location is not mandatory and can be null + String location = getFirstInSet(arguments.get(PARAMETER_LOCATION)); + + // Tags is not mandatory + Set tags = arguments.get(PARAMETER_TAG); + if (tags != null) { + for (String tag : tags) { + if (tag.length() == 0) { + return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT, + AddCommand.MESSAGE_USAGE)); + } + } + } - matcher.group("address"), - isPrivatePrefixPresent(matcher.group("isAddressPrivate")), + // Recurrences is not mandatory + Set recurrences = arguments.get(PARAMETER_RECURRENCE); - getTagsFromArgs(matcher.group("tagArguments")) - ); + try { + if (day != -1) { + return new AddCommand( + day, + name, + location, + description, + startTime, + duration, + tags, + recurrences + ); + } else { + return new AddCommand( + date, + name, + location, + description, + startTime, + duration, + tags, + recurrences + ); + } } catch (IllegalValueException ive) { return new IncorrectCommand(ive.getMessage()); } } /** - * Parses arguments in the context of the delete person command. + * Parses arguments in the context of the edit command. * * @param args full command args string * @return the prepared command */ - private Command prepareDelete(String args) { - try { - final int targetIndex = parseArgsAsDisplayedIndex(args); - return new DeleteCommand(targetIndex); - } catch (ParseException | NumberFormatException e) { - return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE)); + private Command prepareEdit(String args) { + HashMap> arguments = getParametersWithArguments(args); + String stringIndex = getStartingArgument(args); + int index = Utils.parseInteger(stringIndex); + Set tags = arguments.get(PARAMETER_TAG); + + if ((index == -1 && tags == null) || (index != -1 && tags != null)) { + return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditCommand.MESSAGE_USAGE)); + } + + String nst = getFirstInSet(arguments.get(PARAMETER_NEW_START_TIME)); + LocalTime startTime = null; + if (nst != null) { + startTime = Utils.parseTime(nst); + if (startTime == null) { + return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditCommand.MESSAGE_USAGE)); + } + } + + // determine if "end time" is a duration or time + String net = getFirstInSet(arguments.get(PARAMETER_NEW_END_TIME)); + int duration = -1; + if (net != null) { + duration = Utils.parseInteger(net); + if (duration == -1) { + LocalTime endTime = Utils.parseTime(net); + if (endTime == null) { + return new IncorrectCommand(String.format( + MESSAGE_INVALID_COMMAND_FORMAT, EditCommand.MESSAGE_USAGE)); + } else { + duration = Utils.getDuration(startTime, endTime); + } + } + } + + String name = getFirstInSet(arguments.get(PARAMETER_NEW_NAME)); + String location = getFirstInSet(arguments.get(PARAMETER_NEW_LOCATION)); + String description = getFirstInSet(arguments.get(PARAMETER_NEW_DESCRIPTION)); + Set newTags = arguments.get(PARAMETER_NEW_TAG); + + if (index == -1) { + try { + return new EditCommand(name, startTime, duration, location, description, tags, newTags); + } catch (IllegalValueException ive) { + return new IncorrectCommand(ive.getMessage()); + } + } else { + String nd = getFirstInSet(arguments.get(PARAMETER_NEW_DATE)); + LocalDate date = Utils.parseDate(nd); + if (date == null) { + return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditCommand.MESSAGE_USAGE)); + } + + try { + return new EditCommand(index, name, date, startTime, duration, location, description, newTags); + } catch (IllegalValueException ive) { + return new IncorrectCommand(ive.getMessage()); + } } } /** - * Parses arguments in the context of the view command. + * Parses arguments in the context of the delete command. * * @param args full command args string * @return the prepared command */ - private Command prepareView(String args) { + private Command prepareDelete(String args) { + HashMap> arguments = getParametersWithArguments(args); + String stringIndex = getStartingArgument(args); + int index = Utils.parseInteger(stringIndex); + Set tags = arguments.get(PARAMETER_TAG); - try { - final int targetIndex = parseArgsAsDisplayedIndex(args); - return new ViewCommand(targetIndex); - } catch (ParseException | NumberFormatException e) { - return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT, - ViewCommand.MESSAGE_USAGE)); + if ((index == -1 && tags == null) || (index != -1 && tags != null)) { + return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE)); + } + + if (index == -1) { + try { + return new DeleteCommand(tags); + } catch (IllegalValueException ive) { + return new IncorrectCommand(ive.getMessage()); + } + } else { + return new DeleteCommand(index); } } /** - * Parses arguments in the context of the view all command. + * Parses arguments in the context of the list command. * * @param args full command args string * @return the prepared command */ - private Command prepareViewAll(String args) { - - try { - final int targetIndex = parseArgsAsDisplayedIndex(args); - return new ViewAllCommand(targetIndex); - } catch (ParseException | NumberFormatException e) { - return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT, - ViewAllCommand.MESSAGE_USAGE)); + private Command prepareList(String args) { + HashMap> arguments = getParametersWithArguments(args); + String name = getFirstInSet(arguments.get(PARAMETER_NAME)); + if (name == null || name.trim().isEmpty()) { + return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT, ListCommand.MESSAGE_USAGE)); } + return new ListCommand(name); } + /** + * Parses arguments in the context of the view command. + * + * @param args full command args string + * @return the prepared command + */ + // private Command prepareView(String args) { + // + // try { + // final int targetIndex = parseArgsAsDisplayedIndex(args); + // return new ViewCommand(targetIndex); + // } catch (ParseException | NumberFormatException e) { + // return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT, + // ViewCommand.MESSAGE_USAGE)); + // } + // } + /** * Parses the given arguments string as a single index number. * @@ -214,8 +347,8 @@ private int parseArgsAsDisplayedIndex(String args) throws ParseException, Number /** * Parses arguments in the context of the find person command. * - * @param args full command args string - * @return the prepared command + * @param args partial args string + * @return the arguments sorted by its relevant options */ private Command prepareFind(String args) { final Matcher matcher = KEYWORDS_ARGS_FORMAT.matcher(args.trim()); @@ -230,6 +363,84 @@ private Command prepareFind(String args) { return new FindCommand(keywordSet); } + /** + * Parses arguments in the context of the add slots command. + * + * @return hashmap of parameter command with set of parameters. + */ + private static HashMap> getParametersWithArguments(String args) { + String parameters = args.trim(); + String parameter; + String option; + int buf; + HashMap> result = new HashMap<>(); + while (true) { + buf = parameters.indexOf('/'); + if (buf == -1) { + break; + } + + option = parameters.substring(0, buf).trim(); + if (option.contains(" ")) { + parameters = parameters.substring(option.lastIndexOf(" ")); + continue; + } + + parameters = parameters.substring(buf + 1); + + if (parameters.indexOf('/') != -1) { + parameter = parameters.substring(0, parameters.indexOf('/')); + if (parameter.indexOf(' ') != -1) { + parameter = parameter.substring(0, parameter.lastIndexOf(" ")); + } + } else { + parameter = parameters; + } + + if (result.get(option) == null) { + result.put(option, new HashSet<>(Collections.singletonList(parameter.trim()))); + } else { + Set ss = result.get(option); + ss.add(parameter.trim()); + result.replace(option, ss); + } + + if (parameters.length() == 0) { + break; + } + parameters = parameters.substring(parameter.length()); + } + + return result; + } + + /** + * Get the first argument. + */ + private String getStartingArgument(String args) { + String result = args; + + // test if firstArgument is present + if (result.trim().length() == 0) { + return null; + } else if (result.indexOf('/') != -1) { + result = result.substring(0, result.indexOf('/')); + return result.substring(0, result.lastIndexOf(" ")).trim(); + } else { + return result.trim(); + } + } + + /** + * Get the first string in a set. + */ + private String getFirstInSet(Set set) { + if (set == null || set.size() == 0) { + return null; + } + return set.stream().findFirst().get(); + } + /** * Signals that the user input could not be parsed. */ diff --git a/src/planmysem/parser/ParserP.java b/src/planmysem/parser/ParserP.java deleted file mode 100644 index b1c3c41cd..000000000 --- a/src/planmysem/parser/ParserP.java +++ /dev/null @@ -1,457 +0,0 @@ -package planmysem.parser; - -import static planmysem.common.Messages.MESSAGE_INVALID_COMMAND_FORMAT; - -import java.time.LocalDate; -import java.time.LocalTime; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import planmysem.commands.AddCommandP; -import planmysem.commands.ClearCommandP; -import planmysem.commands.Command; -import planmysem.commands.CommandP; -import planmysem.commands.DeleteCommandP; -import planmysem.commands.EditCommandP; -import planmysem.commands.ExitCommandP; -import planmysem.commands.ExportCommandP; -import planmysem.commands.FindCommand; -import planmysem.commands.HelpCommand; -import planmysem.commands.HelpCommandP; -import planmysem.commands.IncorrectCommand; -import planmysem.commands.IncorrectCommandP; -import planmysem.commands.ListCommandP; -import planmysem.commands.ViewCommand; -import planmysem.common.Utils; -import planmysem.data.exception.IllegalValueException; - -/** - * Parses user input. - */ -public class ParserP { - - public static final Pattern PERSON_INDEX_ARGS_FORMAT = Pattern.compile("(?.+)"); - - public static final Pattern KEYWORDS_ARGS_FORMAT = - Pattern.compile("(?\\S+(?:\\s+\\S+)*)"); // one or more keywords separated by whitespace - - private static final String PARAMETER_NAME = "n"; - private static final String PARAMETER_DATE_OR_DAY = "d"; - private static final String PARAMETER_START_TIME = "st"; - private static final String PARAMETER_END_TIME = "et"; - private static final String PARAMETER_RECURRENCE = "r"; - private static final String PARAMETER_LOCATION = "l"; - private static final String PARAMETER_DESCRIPTION = "des"; - private static final String PARAMETER_TAG = "t"; - private static final String PARAMETER_NEW_NAME = "nn"; - private static final String PARAMETER_NEW_DATE = "nd"; - private static final String PARAMETER_NEW_START_TIME = "nst"; - private static final String PARAMETER_NEW_END_TIME = "net"; - private static final String PARAMETER_NEW_LOCATION = "nl"; - private static final String PARAMETER_NEW_DESCRIPTION = "ndes"; - private static final String PARAMETER_NEW_TAG = "nt"; - - - /** - * Used for initial separation of command word and args. - */ - private static final Pattern BASIC_COMMAND_FORMAT = Pattern.compile("(?\\S+)(?.*)"); - - /** - * Parses user input into command for execution. - * - * @param userInput full user input string - * @return the command based on the user input - */ - public CommandP parseCommand(String userInput) { - final Matcher matcher = BASIC_COMMAND_FORMAT.matcher(userInput.trim()); - if (!matcher.matches()) { - return new IncorrectCommandP(String.format(MESSAGE_INVALID_COMMAND_FORMAT, HelpCommand.MESSAGE_USAGE)); - } - - final String commandWord = matcher.group("commandWord"); - final String arguments = matcher.group("arguments"); - - switch (commandWord) { - case AddCommandP.COMMAND_WORD: - case AddCommandP.COMMAND_WORD_SHORT: - return prepareAdd(arguments); - - case EditCommandP.COMMAND_WORD: - case EditCommandP.COMMAND_WORD_SHORT: - return prepareEdit(arguments); - - case ExportCommandP.COMMAND_WORD: - return new ExportCommandP(); - - case DeleteCommandP.COMMAND_WORD: - case DeleteCommandP.COMMAND_WORD_ALT: - case DeleteCommandP.COMMAND_WORD_SHORT: - return prepareDelete(arguments); - - case ListCommandP.COMMAND_WORD: - case ListCommandP.COMMAND_WORD_SHORT: - return prepareList(arguments); - - case ClearCommandP.COMMAND_WORD: - return new ClearCommandP(); - - case ExitCommandP.COMMAND_WORD: - return new ExitCommandP(); - - case HelpCommandP.COMMAND_WORD: // Fallthrough - - default: - return new HelpCommandP(); - } - } - - /** - * Parses arguments in the context of the add command. - * - * @param args full command args string - * @return the prepared command - */ - private CommandP prepareAdd(String args) { - HashMap> arguments = getParametersWithArguments(args); - - // Name is mandatory - String name = getFirstInSet(arguments.get(PARAMETER_NAME)); - - if (arguments.isEmpty() || name.isEmpty() || arguments.get(PARAMETER_DATE_OR_DAY) == null - || arguments.get(PARAMETER_START_TIME) == null || arguments.get(PARAMETER_END_TIME) == null) { - return new IncorrectCommandP(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommandP.MESSAGE_USAGE)); - } - - // Either date or day must be present - String dateOrDay = getFirstInSet(arguments.get(PARAMETER_DATE_OR_DAY)); - int day = Utils.parseDay(dateOrDay); - LocalDate date = null; - if (day == 0) { - date = Utils.parseDate(dateOrDay); - } - if (day == 0 && date == null) { - return new IncorrectCommandP(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommandP.MESSAGE_USAGE)); - } - - // Start time is mandatory - String stringStartTime = getFirstInSet(arguments.get(PARAMETER_START_TIME)); - LocalTime startTime = Utils.parseTime(stringStartTime); - if (startTime == null) { - return new IncorrectCommandP(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommandP.MESSAGE_USAGE)); - } - - // determine if "end time" is a duration or time - String stringEndTime = getFirstInSet(arguments.get(PARAMETER_END_TIME)); - int duration = Utils.parseInteger(stringEndTime); - - if (duration == -1) { - LocalTime endTime = Utils.parseTime(stringEndTime); - if (endTime == null) { - return new IncorrectCommandP(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommandP.MESSAGE_USAGE)); - } - duration = Utils.getDuration(startTime, endTime); - } - - // Description is not mandatory and can be null - String description = getFirstInSet(arguments.get(PARAMETER_DESCRIPTION)); - - // Location is not mandatory and can be null - String location = getFirstInSet(arguments.get(PARAMETER_LOCATION)); - - // Tags is not mandatory - Set tags = arguments.get(PARAMETER_TAG); - for (String tag : tags) { - if (tag.length() == 0) { - return new IncorrectCommandP(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommandP.MESSAGE_USAGE)); - } - } - - // Recurrences is not mandatory - Set recurrences = arguments.get(PARAMETER_RECURRENCE); - - try { - if (day != -1) { - return new AddCommandP( - day, - name, - location, - description, - startTime, - duration, - tags, - recurrences - ); - } else { - return new AddCommandP( - date, - name, - location, - description, - startTime, - duration, - tags, - recurrences - ); - } - } catch (IllegalValueException ive) { - return new IncorrectCommandP(ive.getMessage()); - } - } - - /** - * Parses arguments in the context of the edit command. - * - * @param args full command args string - * @return the prepared command - */ - private CommandP prepareEdit(String args) { - HashMap> arguments = getParametersWithArguments(args); - String stringIndex = getStartingArgument(args); - int index = Utils.parseInteger(stringIndex); - Set tags = arguments.get(PARAMETER_TAG); - - if ((index == -1 && tags == null) || (index != -1 && tags != null)) { - return new IncorrectCommandP(String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditCommandP.MESSAGE_USAGE)); - } - - String nst = getFirstInSet(arguments.get(PARAMETER_NEW_START_TIME)); - LocalTime startTime = null; - if (nst != null) { - startTime = Utils.parseTime(nst); - if (startTime == null) { - return new IncorrectCommandP(String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditCommandP.MESSAGE_USAGE)); - } - } - - // determine if "end time" is a duration or time - String net = getFirstInSet(arguments.get(PARAMETER_NEW_END_TIME)); - int duration = -1; - if (net != null) { - duration = Utils.parseInteger(net); - if (duration == -1) { - LocalTime endTime = Utils.parseTime(net); - if (endTime == null) { - return new IncorrectCommandP(String.format( - MESSAGE_INVALID_COMMAND_FORMAT, EditCommandP.MESSAGE_USAGE)); - } else { - duration = Utils.getDuration(startTime, endTime); - } - } - } - - String name = getFirstInSet(arguments.get(PARAMETER_NEW_NAME)); - String location = getFirstInSet(arguments.get(PARAMETER_NEW_LOCATION)); - String description = getFirstInSet(arguments.get(PARAMETER_NEW_DESCRIPTION)); - Set newTags = arguments.get(PARAMETER_NEW_TAG); - - if (index == -1) { - try { - return new EditCommandP(name, startTime, duration, location, description, tags, newTags); - } catch (IllegalValueException ive) { - return new IncorrectCommandP(ive.getMessage()); - } - } else { - String nd = getFirstInSet(arguments.get(PARAMETER_NEW_DATE)); - LocalDate date = Utils.parseDate(nd); - if (date == null) { - return new IncorrectCommandP(String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditCommandP.MESSAGE_USAGE)); - } - - try { - return new EditCommandP(index, name, date, startTime, duration, location, description, newTags); - } catch (IllegalValueException ive) { - return new IncorrectCommandP(ive.getMessage()); - } - } - } - - /** - * Parses arguments in the context of the delete command. - * - * @param args full command args string - * @return the prepared command - */ - private CommandP prepareDelete(String args) { - HashMap> arguments = getParametersWithArguments(args); - String stringIndex = getStartingArgument(args); - int index = Utils.parseInteger(stringIndex); - Set tags = arguments.get(PARAMETER_TAG); - - if ((index == -1 && tags == null) || (index != -1 && tags != null)) { - return new IncorrectCommandP(String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommandP.MESSAGE_USAGE)); - } - - if (index == -1) { - try { - return new DeleteCommandP(tags); - } catch (IllegalValueException ive) { - return new IncorrectCommandP(ive.getMessage()); - } - } else { - return new DeleteCommandP(index); - } - } - - /** - * Parses arguments in the context of the list command. - * - * @param args full command args string - * @return the prepared command - */ - private CommandP prepareList(String args) { - HashMap> arguments = getParametersWithArguments(args); - String name = getFirstInSet(arguments.get(PARAMETER_NAME)); - if (name == null || name.trim().isEmpty()) { - return new IncorrectCommandP(String.format(MESSAGE_INVALID_COMMAND_FORMAT, ListCommandP.MESSAGE_USAGE)); - } - // TODO: prepare list - // try { - // TODO: add exception handling - return new ListCommandP(name); - } - - /** - * Parses arguments in the context of the view command. - * - * @param args full command args string - * @return the prepared command - */ - private Command prepareView(String args) { - - try { - final int targetIndex = parseArgsAsDisplayedIndex(args); - return new ViewCommand(targetIndex); - } catch (ParseException | NumberFormatException e) { - return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT, - ViewCommand.MESSAGE_USAGE)); - } - } - - /** - * Parses the given arguments string as a single index number. - * - * @param args arguments string to parse as index number - * @return the parsed index number - * @throws ParseException if no region of the args string could be found for the index - * @throws NumberFormatException the args string region is not a valid number - */ - private int parseArgsAsDisplayedIndex(String args) throws ParseException, NumberFormatException { - final Matcher matcher = PERSON_INDEX_ARGS_FORMAT.matcher(args.trim()); - if (!matcher.matches()) { - throw new ParseException("Could not find index number to parse"); - } - return Integer.parseInt(matcher.group("targetIndex")); - } - - /** - * Parses arguments in the context of the find person command. - * - * @param args partial args string - * @return the arguments sorted by its relevant options - */ - private Command prepareFind(String args) { - final Matcher matcher = KEYWORDS_ARGS_FORMAT.matcher(args.trim()); - if (!matcher.matches()) { - return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT, - FindCommand.MESSAGE_USAGE)); - } - - // keywords delimited by whitespace - final String[] keywords = matcher.group("keywords").split("\\s+"); - final Set keywordSet = new HashSet<>(Arrays.asList(keywords)); - return new FindCommand(keywordSet); - } - - /** - * Parses arguments in the context of the add slots command. - * - * @return hashmap of parameter command with set of parameters. - */ - private static HashMap> getParametersWithArguments(String args) { - String parameters = args.trim(); - String parameter; - String option; - int buf; - HashMap> result = new HashMap<>(); - while (true) { - buf = parameters.indexOf('/'); - if (buf == -1) { - break; - } - - option = parameters.substring(0, buf).trim(); - if (option.contains(" ")) { - parameters = parameters.substring(option.lastIndexOf(" ")); - continue; - } - - parameters = parameters.substring(buf + 1); - - if (parameters.indexOf('/') != -1) { - parameter = parameters.substring(0, parameters.indexOf('/')); - if (parameter.indexOf(' ') != -1) { - parameter = parameter.substring(0, parameter.lastIndexOf(" ")); - } - } else { - parameter = parameters; - } - - if (result.get(option) == null) { - result.put(option, new HashSet<>(Collections.singletonList(parameter.trim()))); - } else { - Set ss = result.get(option); - ss.add(parameter.trim()); - result.replace(option, ss); - } - - if (parameters.length() == 0) { - break; - } - parameters = parameters.substring(parameter.length()); - } - - return result; - } - - /** - * Get the first argument. - */ - private String getStartingArgument(String args) { - String result = args; - - // test if firstArgument is present - if (result.trim().length() == 0) { - return null; - } else if (result.indexOf('/') != -1) { - result = result.substring(0, result.indexOf('/')); - return result.substring(0, result.lastIndexOf(" ")).trim(); - } else { - return result.trim(); - } - } - - /** - * Get the first string in a set. - */ - private String getFirstInSet(Set set) { - if (set == null || set.size() == 0) { - return null; - } - return set.stream().findFirst().get(); - } - - /** - * Signals that the user input could not be parsed. - */ - public static class ParseException extends Exception { - ParseException(String message) { - super(message); - } - } -} diff --git a/src/planmysem/storage/StorageFile.java b/src/planmysem/storage/StorageFile.java deleted file mode 100644 index d9dba4a09..000000000 --- a/src/planmysem/storage/StorageFile.java +++ /dev/null @@ -1,173 +0,0 @@ -package planmysem.storage; - -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.io.StringReader; -import java.io.StringWriter; -import java.io.Writer; -import java.nio.file.Path; -import java.nio.file.Paths; - -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBException; -import javax.xml.bind.Marshaller; -import javax.xml.bind.Unmarshaller; - -import planmysem.data.AddressBook; -import planmysem.data.exception.IllegalValueException; -import planmysem.storage.jaxb.AdaptedAddressBook; - - -/** - * Represents the file used to store address book data. - */ -public class StorageFile { - - /** - * Default file path used if the user doesn't provide the file name. - */ - public static final String DEFAULT_STORAGE_FILEPATH = "addressbook.txt"; - /* Note: Note the use of nested classes below. - * More info https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html - */ - public final Path path; - private final JAXBContext jaxbContext; - private final boolean isEncrypted = false; //set to true to encrypt data - - /** - * @throws InvalidStorageFilePathException if the default path is invalid - */ - public StorageFile() throws InvalidStorageFilePathException { - this(DEFAULT_STORAGE_FILEPATH); - } - - /** - * @throws InvalidStorageFilePathException if the given file path is invalid - */ - public StorageFile(String filePath) throws InvalidStorageFilePathException { - try { - jaxbContext = JAXBContext.newInstance(AdaptedAddressBook.class); - } catch (JAXBException jaxbe) { - throw new RuntimeException("jaxb initialisation error"); - } - - path = Paths.get(filePath); - if (!isValidPath(path)) { - throw new InvalidStorageFilePathException("Storage file should end with '.txt'"); - } - } - - /** - * Returns true if the given path is acceptable as a storage file. - * The file path is considered acceptable if it ends with '.txt' - */ - private static boolean isValidPath(Path filePath) { - return filePath.toString().endsWith(".txt"); - } - - /** - * Saves all data to this storage file. - * - * @throws StorageOperationException if there were errors converting and/or storing data to file. - */ - public void save(AddressBook addressBook) throws StorageOperationException { - - - /* Note: Note the 'try with resource' statement below. - * More info: https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html - */ - try (final Writer fileWriter = - new BufferedWriter(new FileWriter(path.toFile()))) { - - final AdaptedAddressBook toSave = new AdaptedAddressBook(addressBook); - final Marshaller marshaller = jaxbContext.createMarshaller(); - marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); - if (isEncrypted) { - StringWriter sw = new StringWriter(); - marshaller.marshal(toSave, sw); - fileWriter.write(Encryptor.encrypt(sw.toString())); - } else { - marshaller.marshal(toSave, fileWriter); - } - - } catch (IOException ioe) { - throw new StorageOperationException("Error writing to file: " + path + " error: " + ioe.getMessage()); - } catch (JAXBException jaxbe) { - throw new StorageOperationException("Error converting address book into storage format"); - } - } - - /** - * Loads data from this storage file. - * - * @throws StorageOperationException if there were errors reading and/or converting data from file. - */ - public AddressBook load() throws StorageOperationException { - try (final BufferedReader fileReader = - new BufferedReader(new FileReader(path.toFile()))) { - - final Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); - final AdaptedAddressBook loaded; - //decrypts - if (isEncrypted) { - StringReader decryptedData = new StringReader(Encryptor.decrypt(fileReader.readLine())); - loaded = (AdaptedAddressBook) unmarshaller.unmarshal(decryptedData); - } else { - loaded = (AdaptedAddressBook) unmarshaller.unmarshal(fileReader); - } - - // manual check for missing elements - if (loaded.isAnyRequiredFieldMissing()) { - throw new StorageOperationException("File data missing some elements"); - } - return loaded.toModelType(); - - /* Note: Here, we are using an exception to create the file if it is missing. However, we should minimize - * using exceptions to facilitate normal paths of execution. If we consider the missing file as a 'normal' - * situation (i.e. not truly exceptional) we should not use an exception to handle it. - */ - - // create empty file if not found - } catch (FileNotFoundException fnfe) { - final AddressBook empty = new AddressBook(); - save(empty); - return empty; - - // other errors - } catch (IOException ioe) { - throw new StorageOperationException("Error writing to file: " + path); - } catch (JAXBException jaxbe) { - throw new StorageOperationException("Error parsing file data format"); - } catch (IllegalValueException ive) { - throw new StorageOperationException("File contains illegal data values; data type constraints not met"); - } - } - - public String getPath() { - return path.toString(); - } - - /** - * Signals that the given file path does not fulfill the storage filepath constraints. - */ - public static class InvalidStorageFilePathException extends IllegalValueException { - public InvalidStorageFilePathException(String message) { - super(message); - } - } - - /** - * Signals that some error has occured while trying to convert and read/write data between the application - * and the storage file. - */ - public static class StorageOperationException extends Exception { - public StorageOperationException(String message) { - super(message); - } - } - -} diff --git a/src/planmysem/storage/jaxb/AdaptedAddressBook.java b/src/planmysem/storage/jaxb/AdaptedAddressBook.java deleted file mode 100644 index ff224d3a8..000000000 --- a/src/planmysem/storage/jaxb/AdaptedAddressBook.java +++ /dev/null @@ -1,63 +0,0 @@ -package planmysem.storage.jaxb; - -import java.util.ArrayList; -import java.util.List; - -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; - -import planmysem.data.AddressBook; -import planmysem.data.exception.IllegalValueException; -import planmysem.data.person.Person; -import planmysem.data.person.UniquePersonList; - -/** - * JAXB-friendly adapted address book data holder class. - */ -@XmlRootElement(name = "AddressBook") -public class AdaptedAddressBook { - - @XmlElement - private List persons = new ArrayList<>(); - - /** - * No-arg constructor for JAXB use. - */ - public AdaptedAddressBook() {} - - /** - * Converts a given AddressBook into this class for JAXB use. - * - * @param source future changes to this will not affect the created AdaptedAddressBook - */ - public AdaptedAddressBook(AddressBook source) { - persons = new ArrayList<>(); - source.getAllPersons().forEach(person -> persons.add(new AdaptedPerson(person))); - } - - - /** - * Returns true if any required field is missing. - * - * JAXB does not enforce (required = true) without a given XML schema. - * Since we do most of our validation using the data class constructors, the only extra logic we need - * is to ensure that every xml element in the document is present. JAXB sets missing elements as null, - * so we check for that. - */ - public boolean isAnyRequiredFieldMissing() { - return persons.stream().anyMatch(AdaptedPerson::isAnyRequiredFieldMissing); - } - - - /** - * Converts this jaxb-friendly {@code AdaptedAddressBook} object into the corresponding(@code AddressBook} object. - * @throws IllegalValueException if there were any data constraints violated in the adapted person - */ - public AddressBook toModelType() throws IllegalValueException { - final List personList = new ArrayList<>(); - for (AdaptedPerson person : persons) { - personList.add(person.toModelType()); - } - return new AddressBook(new UniquePersonList(personList)); - } -} diff --git a/src/planmysem/storage/jaxb/AdaptedPerson.java b/src/planmysem/storage/jaxb/AdaptedPerson.java deleted file mode 100644 index bb1cc1943..000000000 --- a/src/planmysem/storage/jaxb/AdaptedPerson.java +++ /dev/null @@ -1,115 +0,0 @@ -package planmysem.storage.jaxb; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlValue; - -import planmysem.common.Utils; -import planmysem.data.exception.IllegalValueException; -import planmysem.data.person.Address; -import planmysem.data.person.Email; -import planmysem.data.person.Name; -import planmysem.data.person.Person; -import planmysem.data.person.Phone; -import planmysem.data.person.ReadOnlyPerson; -import planmysem.data.tag.Tag; - -/** - * JAXB-friendly adapted person data holder class. - */ -public class AdaptedPerson { - @XmlElement(required = true) - private String name; - @XmlElement(required = true) - private AdaptedContactDetail phone; - @XmlElement(required = true) - private AdaptedContactDetail email; - @XmlElement(required = true) - private AdaptedContactDetail address; - @XmlElement - private List tagged = new ArrayList<>(); - - /** - * No-arg constructor for JAXB use. - */ - public AdaptedPerson() { - } - - /** - * Converts a given Person into this class for JAXB use. - * - * @param source future changes to this will not affect the created AdaptedPerson - */ - public AdaptedPerson(ReadOnlyPerson source) { - name = source.getName().fullName; - - phone = new AdaptedContactDetail(); - phone.isPrivate = source.getPhone().isPrivate(); - phone.value = source.getPhone().value; - - email = new AdaptedContactDetail(); - email.isPrivate = source.getEmail().isPrivate(); - email.value = source.getEmail().value; - - address = new AdaptedContactDetail(); - address.isPrivate = source.getAddress().isPrivate(); - address.value = source.getAddress().value; - - tagged = new ArrayList<>(); - for (Tag tag : source.getTags()) { - tagged.add(new AdaptedTag(tag)); - } - } - - /** - * Returns true if any required field is missing. - *

- * JAXB does not enforce (required = true) without a given XML schema. - * Since we do most of our validation using the data class constructors, the only extra logic we need - * is to ensure that every xml element in the document is present. JAXB sets missing elements as null, - * so we check for that. - */ - public boolean isAnyRequiredFieldMissing() { - for (AdaptedTag tag : tagged) { - if (tag.isAnyRequiredFieldMissing()) { - return true; - } - } - // second call only happens if phone/email/address are all not null - return Utils.isAnyNull(name, phone, email, address) - || Utils.isAnyNull(phone.value, email.value, address.value); - } - - /** - * Converts this jaxb-friendly adapted person object into the Person object. - * - * @throws IllegalValueException if there were any data constraints violated in the adapted person - */ - public Person toModelType() throws IllegalValueException { - final Set tags = new HashSet<>(); - for (AdaptedTag tag : tagged) { - tags.add(tag.toModelType()); - } - final Name name = new Name(this.name); - final Phone phone = new Phone(this.phone.value, this.phone.isPrivate); - final Email email = new Email(this.email.value, this.email.isPrivate); - final Address address = new Address(this.address.value, this.address.isPrivate); - return new Person(name, phone, email, address, tags); - } - - /** - * TODO: Add Javadoc comment. - * - */ - private static class AdaptedContactDetail { - @XmlValue - private String value; - @XmlAttribute(required = true) - private boolean isPrivate; - } -} diff --git a/src/planmysem/storage/jaxb/AdaptedSlot.java b/src/planmysem/storage/jaxb/AdaptedSlot.java index f36985d39..eff8c9405 100644 --- a/src/planmysem/storage/jaxb/AdaptedSlot.java +++ b/src/planmysem/storage/jaxb/AdaptedSlot.java @@ -32,7 +32,7 @@ public class AdaptedSlot { @XmlElement(required = true) private String startTime; @XmlElement(required = true) - private List tags = new ArrayList<>(); + private List tags = new ArrayList<>(); /** * No-arg constructor for JAXB use. @@ -54,7 +54,7 @@ public AdaptedSlot(ReadOnlySlot source) { tags = new ArrayList<>(); for (TagP tag : source.getTags()) { - tags.add(new AdaptedTagP(tag)); + tags.add(new AdaptedTag(tag)); } } @@ -62,7 +62,7 @@ public AdaptedSlot(ReadOnlySlot source) { * Returns true if any required field is missing. */ public boolean isAnyRequiredFieldMissing() { - for (AdaptedTagP tag : tags) { + for (AdaptedTag tag : tags) { if (tag.isAnyRequiredFieldMissing()) { return true; } @@ -84,7 +84,7 @@ public Slot toModelType() throws IllegalValueException { final int duration = this.duration; final Set tags = new HashSet<>(); - for (AdaptedTagP tag : this.tags) { + for (AdaptedTag tag : this.tags) { tags.add(tag.toModelType()); } diff --git a/src/planmysem/storage/jaxb/AdaptedTag.java b/src/planmysem/storage/jaxb/AdaptedTag.java index 88b07e3af..2da949bb2 100644 --- a/src/planmysem/storage/jaxb/AdaptedTag.java +++ b/src/planmysem/storage/jaxb/AdaptedTag.java @@ -4,14 +4,14 @@ import planmysem.common.Utils; import planmysem.data.exception.IllegalValueException; -import planmysem.data.tag.Tag; +import planmysem.data.tag.TagP; /** * JAXB-friendly adapted tag data holder class. */ public class AdaptedTag { @XmlValue - private String tagName; + private String value; /** * No-arg constructor for JAXB use. @@ -24,8 +24,8 @@ public AdaptedTag() { * * @param source future changes to this will not affect the created AdaptedTag */ - public AdaptedTag(Tag source) { - tagName = source.tagName; + public AdaptedTag(TagP source) { + value = source.value; } /** @@ -37,7 +37,7 @@ public AdaptedTag(Tag source) { * so we check for that. */ public boolean isAnyRequiredFieldMissing() { - return Utils.isAnyNull(tagName); + return Utils.isAnyNull(value); } /** @@ -45,7 +45,7 @@ public boolean isAnyRequiredFieldMissing() { * * @throws IllegalValueException if there were any data constraints violated in the adapted person */ - public Tag toModelType() throws IllegalValueException { - return new Tag(tagName); + public TagP toModelType() throws IllegalValueException { + return new TagP(value); } } diff --git a/src/planmysem/storage/jaxb/AdaptedTagP.java b/src/planmysem/storage/jaxb/AdaptedTagP.java deleted file mode 100644 index 7c1104085..000000000 --- a/src/planmysem/storage/jaxb/AdaptedTagP.java +++ /dev/null @@ -1,51 +0,0 @@ -package planmysem.storage.jaxb; - -import javax.xml.bind.annotation.XmlValue; - -import planmysem.common.Utils; -import planmysem.data.exception.IllegalValueException; -import planmysem.data.tag.TagP; - -/** - * JAXB-friendly adapted tag data holder class. - */ -public class AdaptedTagP { - @XmlValue - private String value; - - /** - * No-arg constructor for JAXB use. - */ - public AdaptedTagP() { - } - - /** - * Converts a given Tag into this class for JAXB use. - * - * @param source future changes to this will not affect the created AdaptedTag - */ - public AdaptedTagP(TagP source) { - value = source.value; - } - - /** - * Returns true if any required field is missing. - *

- * JAXB does not enforce (required = true) without a given XML schema. - * Since we do most of our validation using the data class constructors, the only extra logic we need - * is to ensure that every xml element in the document is present. JAXB sets missing elements as null, - * so we check for that. - */ - public boolean isAnyRequiredFieldMissing() { - return Utils.isAnyNull(value); - } - - /** - * Converts this jaxb-friendly adapted tag object into the Tag object. - * - * @throws IllegalValueException if there were any data constraints violated in the adapted person - */ - public TagP toModelType() throws IllegalValueException { - return new TagP(value); - } -} diff --git a/src/planmysem/ui/Formatter.java b/src/planmysem/ui/Formatter.java index cedaa139d..9c18f550f 100644 --- a/src/planmysem/ui/Formatter.java +++ b/src/planmysem/ui/Formatter.java @@ -5,7 +5,6 @@ import java.util.List; import javafx.util.Pair; -import planmysem.data.person.ReadOnlyPerson; import planmysem.data.slot.ReadOnlySlot; /** @@ -68,17 +67,6 @@ public String format(String... messages) { return sb.toString(); } - /** - * Formats the given list of persons for displaying to the user. - */ - public String format(List persons) { - final List formattedPersons = new ArrayList<>(); - for (ReadOnlyPerson person : persons) { - formattedPersons.add(person.getAsTextHidePrivate()); - } - return format(asIndexedList(formattedPersons)); - } - /** * Formats the given list of slots for displaying to the user. */ diff --git a/src/planmysem/ui/Gui.java b/src/planmysem/ui/Gui.java index 0ec5960bb..203a16986 100644 --- a/src/planmysem/ui/Gui.java +++ b/src/planmysem/ui/Gui.java @@ -7,7 +7,6 @@ import javafx.stage.Stage; import planmysem.Main; import planmysem.logic.Logic; -import planmysem.logic.LogicP; /** * The GUI of the App @@ -22,14 +21,11 @@ public class Gui { public static final int INITIAL_WINDOW_WIDTH = 800; public static final int INITIAL_WINDOW_HEIGHT = 600; private final Logic logic; - private final LogicP logicP; private MainWindow mainWindow; - private MainWindowP mainWindowP; private String version; - public Gui(Logic logic, LogicP logicP, String version) { - this.logicP = logicP; + public Gui(Logic logic, String version) { this.logic = logic; this.version = version; } @@ -38,48 +34,23 @@ public Gui(Logic logic, LogicP logicP, String version) { * TODO: Add Javadoc comment. */ public void start(Stage stage, Stoppable mainApp) throws IOException { - mainWindow = createMainWindow(stage, mainApp); - mainWindow.displayWelcomeMessage(version + " old Address Book", logic.getStorageFilePath()); - - Stage stage2 = new Stage(); - mainWindowP = createMainWindowP(stage2, mainApp); - mainWindowP.displayWelcomeMessage(version, logicP.getStorageFilePath()); + mainWindow = createMainWindowP(stage, mainApp); + mainWindow.displayWelcomeMessage(version, logic.getStorageFilePath()); } /** * TODO: Add Javadoc comment. */ - private MainWindow createMainWindow(Stage stage, Stoppable mainApp) throws IOException { + private MainWindow createMainWindowP(Stage stage, Stoppable mainApp) throws IOException { FXMLLoader loader = new FXMLLoader(); - - /* Note: When calling getResource(), use '/', instead of File.separator or '\\' - * More info: http://docs.oracle.com/javase/8/docs/technotes/guides/lang/resources.html#res_name_context - */ loader.setLocation(Main.class.getResource("ui/mainwindow.fxml")); stage.setTitle(version); stage.setScene(new Scene(loader.load(), INITIAL_WINDOW_WIDTH, INITIAL_WINDOW_HEIGHT)); stage.show(); - MainWindow mainWindow = loader.getController(); + mainWindow = loader.getController(); mainWindow.setLogic(logic); mainWindow.setMainApp(mainApp); return mainWindow; } - - /** - * TODO: Add Javadoc comment. - */ - private MainWindowP createMainWindowP(Stage stage, Stoppable mainApp) throws IOException { - FXMLLoader loader = new FXMLLoader(); - loader.setLocation(Main.class.getResource("ui/mainwindowP.fxml")); - - stage.setTitle(version); - stage.setScene(new Scene(loader.load(), INITIAL_WINDOW_WIDTH, INITIAL_WINDOW_HEIGHT)); - stage.show(); - MainWindowP mainWindowP = null; - mainWindowP = loader.getController(); - mainWindowP.setLogic(logicP); - mainWindowP.setMainApp(mainApp); - return mainWindowP; - } } diff --git a/src/planmysem/ui/MainWindow.java b/src/planmysem/ui/MainWindow.java deleted file mode 100644 index a203754a0..000000000 --- a/src/planmysem/ui/MainWindow.java +++ /dev/null @@ -1,121 +0,0 @@ -package planmysem.ui; - -import java.util.List; -import java.util.Optional; - -import javafx.event.ActionEvent; -import javafx.fxml.FXML; -import javafx.scene.control.TextArea; -import javafx.scene.control.TextField; - -import planmysem.commands.CommandResult; -import planmysem.commands.ExitCommand; -import planmysem.common.Messages; -import planmysem.data.person.ReadOnlyPerson; -import planmysem.logic.Logic; - -/** - * Main Window of the GUI. - */ -public class MainWindow { - - private Logic logic; - private Stoppable mainApp; - @FXML - private TextArea outputConsole; - @FXML - private TextField commandInput; - - public MainWindow() { - } - - public void setLogic(Logic logic) { - this.logic = logic; - } - - public void setMainApp(Stoppable mainApp) { - this.mainApp = mainApp; - } - - - /** - * TODO: Add Javadoc comment. - */ - @FXML - void onCommand(ActionEvent event) { - try { - String userCommandText = commandInput.getText(); - CommandResult result = logic.execute(userCommandText); - if (isExitCommand(result)) { - exitApp(); - return; - } - displayResult(result); - clearCommandInput(); - } catch (Exception e) { - display(e.getMessage()); - throw new RuntimeException(e); - } - } - - private void exitApp() throws Exception { - mainApp.stop(); - } - - /** - * Returns true of the result given is the result of an exit command - */ - private boolean isExitCommand(CommandResult result) { - return result.feedbackToUser.equals(ExitCommand.MESSAGE_EXIT_ACKNOWEDGEMENT); - } - - /** - * Clears the command input box - */ - private void clearCommandInput() { - commandInput.setText(""); - } - - /** - * Clears the output display area - */ - public void clearOutputConsole() { - outputConsole.clear(); - } - - /** - * Displays the result of a command execution to the user. - */ - public void displayResult(CommandResult result) { - clearOutputConsole(); - final Optional> resultPersons = result.getRelevantPersons(); - if (resultPersons.isPresent()) { - display(resultPersons.get()); - } - display(result.feedbackToUser); - } - - /** - * TODO: Add Javadoc comment. - */ - public void displayWelcomeMessage(String version, String storageFilePath) { - String storageFileInfo = String.format(Messages.MESSAGE_USING_STORAGE_FILE, storageFilePath); - display(Messages.MESSAGE_WELCOME, version, Messages.MESSAGE_PROGRAM_LAUNCH_ARGS_USAGE, storageFileInfo); - } - - /** - * Displays the list of persons in the output display area, formatted as an indexed list. - * Private contact details are hidden. - */ - private void display(List persons) { - display(new Formatter().format(persons)); - } - - /** - * Displays the given messages on the output display area, after formatting appropriately. - */ - private void display(String... messages) { - outputConsole.setText(outputConsole.getText() + new Formatter().format(messages)); - } - -} diff --git a/src/planmysem/ui/MainWindowP.java b/src/planmysem/ui/MainWindowP.java deleted file mode 100644 index 3c0599c1a..000000000 --- a/src/planmysem/ui/MainWindowP.java +++ /dev/null @@ -1,119 +0,0 @@ -package planmysem.ui; - -import java.time.LocalDate; -import java.util.List; -import java.util.Optional; - -import javafx.event.ActionEvent; -import javafx.fxml.FXML; -import javafx.scene.control.TextArea; -import javafx.scene.control.TextField; -import javafx.util.Pair; -import planmysem.commands.CommandResultP; -import planmysem.commands.ExitCommand; -import planmysem.common.Messages; -import planmysem.data.slot.ReadOnlySlot; -import planmysem.logic.LogicP; - -/** - * Main Window of the GUI. - */ -public class MainWindowP { - - private LogicP logic; - private Stoppable mainApp; - @FXML - private TextArea outputConsole; - @FXML - private TextField commandInput; - - public void setLogic(LogicP logic) { - this.logic = logic; - } - - public void setMainApp(Stoppable mainApp) { - this.mainApp = mainApp; - } - - /** - * TODO: Add Javadoc comment. - */ - @FXML - void onCommand(ActionEvent event) { - try { - String userCommandText = commandInput.getText(); - CommandResultP result = logic.execute(userCommandText); - if (isExitCommand(result)) { - exitApp(); - return; - } - displayResult(result); - clearCommandInput(); - } catch (Exception e) { - display(e.getMessage()); - throw new RuntimeException(e); - } - } - - private void exitApp() throws Exception { - mainApp.stop(); - } - - /** - * Returns true of the result given is the result of an exit command - */ - private boolean isExitCommand(CommandResultP result) { - return result.feedbackToUser.equals(ExitCommand.MESSAGE_EXIT_ACKNOWEDGEMENT); - } - - /** - * Clears the command input box - */ - private void clearCommandInput() { - commandInput.setText(""); - } - - /** - * Clears the output display area - */ - public void clearOutputConsole() { - outputConsole.clear(); - } - - /** - * Displays the result of a command execution to the user. - */ - public void displayResult(CommandResultP result) { - clearOutputConsole(); - final Optional>> resultDays = result.getRelevantSlots(); - if (resultDays.isPresent()) { - display(resultDays.get()); - } - display(result.feedbackToUser); - } - - /** - * TODO: Add Javadoc comment. - */ - public void displayWelcomeMessage(String version, String storageFilePath) { - String storageFileInfo = String.format(Messages.MESSAGE_USING_STORAGE_FILE, storageFilePath); - display(Messages.MESSAGE_WELCOME, version, Messages.MESSAGE_PROGRAM_LAUNCH_ARGS_USAGE, storageFileInfo); - } - - /** - * Displays the list of slots in the output display area, formatted as an indexed list. - * Private contact details are hidden. - */ - private void display(List> slots) { - // TODO: rename function call when AddressBook is fully removed from project - display(new Formatter().formatSlots(slots)); - } - - /** - * Displays the given messages on the output display area, after formatting appropriately. - */ - private void display(String... messages) { - outputConsole.setText(outputConsole.getText() + new Formatter().format(messages)); - } - -} diff --git a/src/planmysem/ui/mainwindowP.fxml b/src/planmysem/ui/mainwindowP.fxml deleted file mode 100644 index 97571ae87..000000000 --- a/src/planmysem/ui/mainwindowP.fxml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/test/java/planmysem/logic/LogicTest.java b/test/java/planmysem/logic/LogicTest.java index f1b7c3345..f51327d89 100644 --- a/test/java/planmysem/logic/LogicTest.java +++ b/test/java/planmysem/logic/LogicTest.java @@ -1,42 +1,12 @@ package planmysem.logic; -import static junit.framework.TestCase.assertEquals; -import static planmysem.common.Messages.MESSAGE_INVALID_COMMAND_FORMAT; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.StringJoiner; - import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; -import planmysem.commands.AddCommand; -import planmysem.commands.ClearCommand; -import planmysem.commands.Command; -import planmysem.commands.CommandResult; -import planmysem.commands.DeleteCommand; -import planmysem.commands.ExitCommand; -import planmysem.commands.FindCommand; -import planmysem.commands.HelpCommand; -import planmysem.commands.ViewAllCommand; -import planmysem.commands.ViewCommand; -import planmysem.common.Messages; -import planmysem.data.AddressBook; -import planmysem.data.person.Address; -import planmysem.data.person.Email; -import planmysem.data.person.Name; -import planmysem.data.person.Person; -import planmysem.data.person.Phone; -import planmysem.data.person.ReadOnlyPerson; -import planmysem.data.tag.Tag; -import planmysem.storage.StorageFile; - +import planmysem.data.Planner; +import planmysem.storage.StorageFileP; public class LogicTest { @@ -45,18 +15,18 @@ public class LogicTest { * See https://github.com/junit-team/junit4/wiki/rules#temporaryfolder-rule */ @Rule - public TemporaryFolder saveFolder = new TemporaryFolder(); + public TemporaryFolder temporaryFolder = new TemporaryFolder(); - private StorageFile saveFile; - private AddressBook addressBook; + private StorageFileP storgageFile; + private Planner planner; private Logic logic; @Before public void setup() throws Exception { - saveFile = new StorageFile(saveFolder.newFile("testSaveFile.txt").getPath()); - addressBook = new AddressBook(); - saveFile.save(addressBook); - logic = new Logic(saveFile, addressBook); + // saveFile = new StorageFile(saveFolder.newFile("testSaveFile.txt").getPath()); + // addressBook = new AddressBook(); + // saveFile.save(addressBook); + // logic = new Logic(saveFile, addressBook); } @Test @@ -64,547 +34,6 @@ public void constructor() { //Constructor is called in the setup() method which executes before every test, no need to call it here again. //Confirm the last shown list is empty - assertEquals(Collections.emptyList(), logic.getLastShownList()); - } - - @Test - public void execute_invalid() throws Exception { - String invalidCommand = " "; - assertCommandBehavior(invalidCommand, - String.format(MESSAGE_INVALID_COMMAND_FORMAT, HelpCommand.MESSAGE_USAGE)); - } - - /** - * Executes the command and confirms that the result message is correct. - * Both the 'address book' and the 'last shown list' are expected to be empty. - * @see #assertCommandBehavior(String, String, AddressBook, boolean, List) - */ - private void assertCommandBehavior(String inputCommand, String expectedMessage) throws Exception { - assertCommandBehavior(inputCommand, expectedMessage, AddressBook.empty(),false, Collections.emptyList()); - } - - /** - * Executes the command and confirms that the result message is correct and - * also confirms that the following three parts of the Logic object's state are as expected:
- * - the internal address book data are same as those in the {@code expectedAddressBook}
- * - the internal 'last shown list' matches the {@code expectedLastList}
- * - the storage file content matches data in {@code expectedAddressBook}
- */ - private void assertCommandBehavior(String inputCommand, - String expectedMessage, - AddressBook expectedAddressBook, - boolean isRelevantPersonsExpected, - List lastShownList) throws Exception { - - //Execute the command - CommandResult r = logic.execute(inputCommand); - - //Confirm the result contains the right data - assertEquals(expectedMessage, r.feedbackToUser); - assertEquals(r.getRelevantPersons().isPresent(), isRelevantPersonsExpected); - if(isRelevantPersonsExpected){ - assertEquals(lastShownList, r.getRelevantPersons().get()); - } - - //Confirm the state of data is as expected - assertEquals(expectedAddressBook, addressBook); - assertEquals(lastShownList, logic.getLastShownList()); - assertEquals(addressBook, saveFile.load()); - } - - - @Test - public void execute_unknownCommandWord() throws Exception { - String unknownCommand = "uicfhmowqewca"; - assertCommandBehavior(unknownCommand, HelpCommand.MESSAGE_ALL_USAGES); - } - - @Test - public void execute_help() throws Exception { - assertCommandBehavior("help", HelpCommand.MESSAGE_ALL_USAGES); - } - - @Test - public void execute_exit() throws Exception { - assertCommandBehavior("exit", ExitCommand.MESSAGE_EXIT_ACKNOWEDGEMENT); - } - - @Test - public void execute_clear() throws Exception { - TestDataHelper helper = new TestDataHelper(); - addressBook.addPerson(helper.generatePerson(1, true)); - addressBook.addPerson(helper.generatePerson(2, true)); - addressBook.addPerson(helper.generatePerson(3, true)); - - assertCommandBehavior("clear", ClearCommand.MESSAGE_SUCCESS, AddressBook.empty(), false, Collections.emptyList()); - } - - @Test - public void execute_add_invalidArgsFormat() throws Exception { - String expectedMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE); - assertCommandBehavior( - "add wrong args wrong args", expectedMessage); - assertCommandBehavior( - "add Valid Name 12345 e/valid@email.butNoPhonePrefix a/valid, address", expectedMessage); - assertCommandBehavior( - "add Valid Name p/12345 valid@email.butNoPrefix a/valid, address", expectedMessage); - assertCommandBehavior( - "add Valid Name p/12345 e/valid@email.butNoAddressPrefix valid, address", expectedMessage); - } - - @Test - public void execute_add_invalidPersonData() throws Exception { - assertCommandBehavior( - "add []\\[;] p/12345 e/valid@e.mail a/valid, address", Name.MESSAGE_NAME_CONSTRAINTS); - assertCommandBehavior( - "add Valid Name p/not_numbers e/valid@e.mail a/valid, address", Phone.MESSAGE_PHONE_CONSTRAINTS); - assertCommandBehavior( - "add Valid Name p/12345 e/notAnEmail a/valid, address", Email.MESSAGE_EMAIL_CONSTRAINTS); - assertCommandBehavior( - "add Valid Name p/12345 e/valid@e.mail a/valid, address t/invalid_-[.tag", Tag.MESSAGE_TAG_CONSTRAINTS); - + // assertEquals(Collections.emptyList(), logic.getLastShownList()); } - - @Test - public void execute_add_successful() throws Exception { - // setup expectations - TestDataHelper helper = new TestDataHelper(); - Person toBeAdded = helper.adam(); - AddressBook expectedAB = new AddressBook(); - expectedAB.addPerson(toBeAdded); - - // execute command and verify result - assertCommandBehavior(helper.generateAddCommand(toBeAdded), - String.format(AddCommand.MESSAGE_SUCCESS, toBeAdded), - expectedAB, - false, - Collections.emptyList()); - - } - - @Test - public void execute_addDuplicate_notAllowed() throws Exception { - // setup expectations - TestDataHelper helper = new TestDataHelper(); - Person toBeAdded = helper.adam(); - AddressBook expectedAB = new AddressBook(); - expectedAB.addPerson(toBeAdded); - - // setup starting state - addressBook.addPerson(toBeAdded); // person already in internal address book - - // execute command and verify result - assertCommandBehavior( - helper.generateAddCommand(toBeAdded), - AddCommand.MESSAGE_DUPLICATE_PERSON, - expectedAB, - false, - Collections.emptyList()); - - } - - @Test - public void execute_list_showsAllPersons() throws Exception { - // prepare expectations - TestDataHelper helper = new TestDataHelper(); - AddressBook expectedAB = helper.generateAddressBook(false, true); - List expectedList = expectedAB.getAllPersons().immutableListView(); - - // prepare address book state - helper.addToAddressBook(addressBook, false, true); - - assertCommandBehavior("list", - Command.getMessageForPersonListShownSummary(expectedList), - expectedAB, - true, - expectedList); - } - - @Test - public void execute_view_invalidArgsFormat() throws Exception { - String expectedMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, ViewCommand.MESSAGE_USAGE); - assertCommandBehavior("view ", expectedMessage); - assertCommandBehavior("view arg not number", expectedMessage); - } - - @Test - public void execute_view_invalidIndex() throws Exception { - assertInvalidIndexBehaviorForCommand("view"); - } - - /** - * Confirms the 'invalid argument index number behaviour' for the given command - * targeting a single person in the last shown list, using visible index. - * @param commandWord to test assuming it targets a single person in the last shown list based on visible index. - */ - private void assertInvalidIndexBehaviorForCommand(String commandWord) throws Exception { - String expectedMessage = Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX; - TestDataHelper helper = new TestDataHelper(); - List lastShownList = helper.generatePersonList(false, true); - - logic.setLastShownList(lastShownList); - - assertCommandBehavior(commandWord + " -1", expectedMessage, AddressBook.empty(), false, lastShownList); - assertCommandBehavior(commandWord + " 0", expectedMessage, AddressBook.empty(), false, lastShownList); - assertCommandBehavior(commandWord + " 3", expectedMessage, AddressBook.empty(), false, lastShownList); - - } - - @Test - public void execute_view_onlyShowsNonPrivate() throws Exception { - - TestDataHelper helper = new TestDataHelper(); - Person p1 = helper.generatePerson(1, true); - Person p2 = helper.generatePerson(2, false); - List lastShownList = helper.generatePersonList(p1, p2); - AddressBook expectedAB = helper.generateAddressBook(lastShownList); - helper.addToAddressBook(addressBook, lastShownList); - - logic.setLastShownList(lastShownList); - - assertCommandBehavior("view 1", - String.format(ViewCommand.MESSAGE_VIEW_PERSON_DETAILS, p1.getAsTextHidePrivate()), - expectedAB, - false, - lastShownList); - - assertCommandBehavior("view 2", - String.format(ViewCommand.MESSAGE_VIEW_PERSON_DETAILS, p2.getAsTextHidePrivate()), - expectedAB, - false, - lastShownList); - } - - @Test - public void execute_tryToViewMissingPerson_errorMessage() throws Exception { - TestDataHelper helper = new TestDataHelper(); - Person p1 = helper.generatePerson(1, false); - Person p2 = helper.generatePerson(2, false); - List lastShownList = helper.generatePersonList(p1, p2); - - AddressBook expectedAB = new AddressBook(); - expectedAB.addPerson(p2); - - addressBook.addPerson(p2); - logic.setLastShownList(lastShownList); - - assertCommandBehavior("view 1", - Messages.MESSAGE_PERSON_NOT_IN_ADDRESSBOOK, - expectedAB, - false, - lastShownList); - } - - @Test - public void execute_viewAll_invalidArgsFormat() throws Exception { - String expectedMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, ViewAllCommand.MESSAGE_USAGE); - assertCommandBehavior("viewall ", expectedMessage); - assertCommandBehavior("viewall arg not number", expectedMessage); - } - - @Test - public void execute_viewAll_invalidIndex() throws Exception { - assertInvalidIndexBehaviorForCommand("viewall"); - } - - @Test - public void execute_viewAll_alsoShowsPrivate() throws Exception { - TestDataHelper helper = new TestDataHelper(); - Person p1 = helper.generatePerson(1, true); - Person p2 = helper.generatePerson(2, false); - List lastShownList = helper.generatePersonList(p1, p2); - AddressBook expectedAB = helper.generateAddressBook(lastShownList); - helper.addToAddressBook(addressBook, lastShownList); - - logic.setLastShownList(lastShownList); - - assertCommandBehavior("viewall 1", - String.format(ViewCommand.MESSAGE_VIEW_PERSON_DETAILS, p1.getAsTextShowAll()), - expectedAB, - false, - lastShownList); - - assertCommandBehavior("viewall 2", - String.format(ViewCommand.MESSAGE_VIEW_PERSON_DETAILS, p2.getAsTextShowAll()), - expectedAB, - false, - lastShownList); - } - - @Test - public void execute_tryToViewAllPersonMissingInAddressBook_errorMessage() throws Exception { - TestDataHelper helper = new TestDataHelper(); - Person p1 = helper.generatePerson(1, false); - Person p2 = helper.generatePerson(2, false); - List lastShownList = helper.generatePersonList(p1, p2); - - AddressBook expectedAB = new AddressBook(); - expectedAB.addPerson(p1); - - addressBook.addPerson(p1); - logic.setLastShownList(lastShownList); - - assertCommandBehavior("viewall 2", - Messages.MESSAGE_PERSON_NOT_IN_ADDRESSBOOK, - expectedAB, - false, - lastShownList); - } - - @Test - public void execute_delete_invalidArgsFormat() throws Exception { - String expectedMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE); - assertCommandBehavior("delete ", expectedMessage); - assertCommandBehavior("delete arg not number", expectedMessage); - } - - @Test - public void execute_delete_invalidIndex() throws Exception { - assertInvalidIndexBehaviorForCommand("delete"); - } - - @Test - public void execute_delete_removesCorrectPerson() throws Exception { - TestDataHelper helper = new TestDataHelper(); - Person p1 = helper.generatePerson(1, false); - Person p2 = helper.generatePerson(2, true); - Person p3 = helper.generatePerson(3, true); - - List threePersons = helper.generatePersonList(p1, p2, p3); - - AddressBook expectedAB = helper.generateAddressBook(threePersons); - expectedAB.removePerson(p2); - - - helper.addToAddressBook(addressBook, threePersons); - logic.setLastShownList(threePersons); - - assertCommandBehavior("delete 2", - String.format(DeleteCommand.MESSAGE_DELETE_PERSON_SUCCESS, p2), - expectedAB, - false, - threePersons); - } - - @Test - public void execute_delete_missingInAddressBook() throws Exception { - - TestDataHelper helper = new TestDataHelper(); - Person p1 = helper.generatePerson(1, false); - Person p2 = helper.generatePerson(2, true); - Person p3 = helper.generatePerson(3, true); - - List threePersons = helper.generatePersonList(p1, p2, p3); - - AddressBook expectedAB = helper.generateAddressBook(threePersons); - expectedAB.removePerson(p2); - - helper.addToAddressBook(addressBook, threePersons); - addressBook.removePerson(p2); - logic.setLastShownList(threePersons); - - assertCommandBehavior("delete 2", - Messages.MESSAGE_PERSON_NOT_IN_ADDRESSBOOK, - expectedAB, - false, - threePersons); - } - - @Test - public void execute_find_invalidArgsFormat() throws Exception { - String expectedMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_USAGE); - assertCommandBehavior("find ", expectedMessage); - } - - @Test - public void execute_find_onlyMatchesFullWordsInNames() throws Exception { - TestDataHelper helper = new TestDataHelper(); - Person pTarget1 = helper.generatePersonWithName("bla bla KEY bla"); - Person pTarget2 = helper.generatePersonWithName("bla KEY bla bceofeia"); - Person p1 = helper.generatePersonWithName("KE Y"); - Person p2 = helper.generatePersonWithName("KEYKEYKEY sduauo"); - - List fourPersons = helper.generatePersonList(p1, pTarget1, p2, pTarget2); - AddressBook expectedAB = helper.generateAddressBook(fourPersons); - List expectedList = helper.generatePersonList(pTarget1, pTarget2); - helper.addToAddressBook(addressBook, fourPersons); - - assertCommandBehavior("find KEY", - Command.getMessageForPersonListShownSummary(expectedList), - expectedAB, - true, - expectedList); - } - - @Test - public void execute_find_isCaseSensitive() throws Exception { - TestDataHelper helper = new TestDataHelper(); - Person pTarget1 = helper.generatePersonWithName("bla bla KEY bla"); - Person pTarget2 = helper.generatePersonWithName("bla KEY bla bceofeia"); - Person p1 = helper.generatePersonWithName("key key"); - Person p2 = helper.generatePersonWithName("KEy sduauo"); - - List fourPersons = helper.generatePersonList(p1, pTarget1, p2, pTarget2); - AddressBook expectedAB = helper.generateAddressBook(fourPersons); - List expectedList = helper.generatePersonList(pTarget1, pTarget2); - helper.addToAddressBook(addressBook, fourPersons); - - assertCommandBehavior("find KEY", - Command.getMessageForPersonListShownSummary(expectedList), - expectedAB, - true, - expectedList); - } - - @Test - public void execute_find_matchesIfAnyKeywordPresent() throws Exception { - TestDataHelper helper = new TestDataHelper(); - Person pTarget1 = helper.generatePersonWithName("bla bla KEY bla"); - Person pTarget2 = helper.generatePersonWithName("bla rAnDoM bla bceofeia"); - Person p1 = helper.generatePersonWithName("key key"); - Person p2 = helper.generatePersonWithName("KEy sduauo"); - - List fourPersons = helper.generatePersonList(p1, pTarget1, p2, pTarget2); - AddressBook expectedAB = helper.generateAddressBook(fourPersons); - List expectedList = helper.generatePersonList(pTarget1, pTarget2); - helper.addToAddressBook(addressBook, fourPersons); - - assertCommandBehavior("find KEY rAnDoM", - Command.getMessageForPersonListShownSummary(expectedList), - expectedAB, - true, - expectedList); - } - - /** - * A utility class to generate test data. - */ - class TestDataHelper{ - - Person adam() throws Exception { - Name name = new Name("Adam Brown"); - Phone privatePhone = new Phone("111111", true); - Email email = new Email("adam@gmail.com", false); - Address privateAddress = new Address("111, alpha street", true); - Tag tag1 = new Tag("tag1"); - Tag tag2 = new Tag("tag2"); - Set tags = new HashSet<>(Arrays.asList(tag1, tag2)); - return new Person(name, privatePhone, email, privateAddress, tags); - } - - /** - * Generates a valid person using the given seed. - * Running this function with the same parameter values guarantees the returned person will have the same state. - * Each unique seed will generate a unique Person object. - * - * @param seed used to generate the person data field values - * @param isAllFieldsPrivate determines if private-able fields (phone, email, address) will be private - */ - Person generatePerson(int seed, boolean isAllFieldsPrivate) throws Exception { - return new Person( - new Name("Person " + seed), - new Phone("" + Math.abs(seed), isAllFieldsPrivate), - new Email(seed + "@email", isAllFieldsPrivate), - new Address("House of " + seed, isAllFieldsPrivate), - new HashSet<>(Arrays.asList(new Tag("tag" + Math.abs(seed)), new Tag("tag" + Math.abs(seed + 1)))) - ); - } - - /** Generates the correct add command based on the person given */ - String generateAddCommand(Person p) { - StringJoiner cmd = new StringJoiner(" "); - - cmd.add("add"); - - cmd.add(p.getName().toString()); - cmd.add((p.getPhone().isPrivate() ? "pp/" : "p/") + p.getPhone()); - cmd.add((p.getEmail().isPrivate() ? "pe/" : "e/") + p.getEmail()); - cmd.add((p.getAddress().isPrivate() ? "pa/" : "a/") + p.getAddress()); - - Set tags = p.getTags(); - for(Tag t: tags){ - cmd.add("t/" + t.tagName); - } - - return cmd.toString(); - } - - /** - * Generates an AddressBook with auto-generated persons. - * @param isPrivateStatuses flags to indicate if all contact details of respective persons should be set to - * private. - */ - AddressBook generateAddressBook(Boolean... isPrivateStatuses) throws Exception{ - AddressBook addressBook = new AddressBook(); - addToAddressBook(addressBook, isPrivateStatuses); - return addressBook; - } - - /** - * Generates an AddressBook based on the list of Persons given. - */ - AddressBook generateAddressBook(List persons) throws Exception{ - AddressBook addressBook = new AddressBook(); - addToAddressBook(addressBook, persons); - return addressBook; - } - - /** - * Adds auto-generated Person objects to the given AddressBook - * @param addressBook The AddressBook to which the Persons will be added - * @param isPrivateStatuses flags to indicate if all contact details of generated persons should be set to - * private. - */ - void addToAddressBook(AddressBook addressBook, Boolean... isPrivateStatuses) throws Exception{ - addToAddressBook(addressBook, generatePersonList(isPrivateStatuses)); - } - - /** - * Adds the given list of Persons to the given AddressBook - */ - void addToAddressBook(AddressBook addressBook, List personsToAdd) throws Exception{ - for(Person p: personsToAdd){ - addressBook.addPerson(p); - } - } - - /** - * Creates a list of Persons based on the give Person objects. - */ - List generatePersonList(Person... persons) throws Exception{ - List personList = new ArrayList<>(); - for(Person p: persons){ - personList.add(p); - } - return personList; - } - - /** - * Generates a list of Persons based on the flags. - * @param isPrivateStatuses flags to indicate if all contact details of respective persons should be set to - * private. - */ - List generatePersonList(Boolean... isPrivateStatuses) throws Exception{ - List persons = new ArrayList<>(); - int i = 1; - for(Boolean p: isPrivateStatuses){ - persons.add(generatePerson(i++, p)); - } - return persons; - } - - /** - * Generates a Person object with given name. Other fields will have some dummy values. - */ - Person generatePersonWithName(String name) throws Exception { - return new Person( - new Name(name), - new Phone("1", false), - new Email("1@email", false), - new Address("House of 1", false), - Collections.singleton(new Tag("tag")) - ); - } - } - } \ No newline at end of file diff --git a/test/java/planmysem/parser/ParserTest.java b/test/java/planmysem/parser/ParserTest.java index d6dc1cc24..29baea1a5 100644 --- a/test/java/planmysem/parser/ParserTest.java +++ b/test/java/planmysem/parser/ParserTest.java @@ -4,32 +4,11 @@ import static org.junit.Assert.assertTrue; import static planmysem.common.Messages.MESSAGE_INVALID_COMMAND_FORMAT; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - import org.junit.Before; import org.junit.Test; - -import planmysem.commands.AddCommand; -import planmysem.commands.ClearCommand; import planmysem.commands.Command; -import planmysem.commands.DeleteCommand; -import planmysem.commands.ExitCommand; -import planmysem.commands.FindCommand; import planmysem.commands.HelpCommand; import planmysem.commands.IncorrectCommand; -import planmysem.commands.ListCommand; -import planmysem.commands.ViewAllCommand; -import planmysem.commands.ViewCommand; -import planmysem.data.exception.IllegalValueException; -import planmysem.data.person.Address; -import planmysem.data.person.Email; -import planmysem.data.person.Name; -import planmysem.data.person.Person; -import planmysem.data.person.Phone; -import planmysem.data.person.ReadOnlyPerson; -import planmysem.data.tag.Tag; public class ParserTest { @@ -47,247 +26,6 @@ public void emptyInput_returnsIncorrect() { parseAndAssertIncorrectWithMessage(resultMessage, emptyInputs); } - @Test - public void unknownCommandWord_returnsHelp() { - final String input = "unknowncommandword arguments arguments"; - parseAndAssertCommandType(input, HelpCommand.class); - } - - /** - * Test 0-argument commands - */ - - @Test - public void helpCommand_parsedCorrectly() { - final String input = "help"; - parseAndAssertCommandType(input, HelpCommand.class); - } - - @Test - public void clearCommand_parsedCorrectly() { - final String input = "clear"; - parseAndAssertCommandType(input, ClearCommand.class); - } - - @Test - public void listCommand_parsedCorrectly() { - final String input = "list"; - parseAndAssertCommandType(input, ListCommand.class); - } - - @Test - public void exitCommand_parsedCorrectly() { - final String input = "exit"; - parseAndAssertCommandType(input, ExitCommand.class); - } - - /** - * Test ingle index argument commands - */ - - @Test - public void deleteCommand_noArgs() { - final String[] inputs = { "delete", "delete " }; - final String resultMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE); - parseAndAssertIncorrectWithMessage(resultMessage, inputs); - } - - @Test - public void deleteCommand_argsIsNotSingleNumber() { - final String[] inputs = { "delete notAnumber ", "delete 8*wh12", "delete 1 2 3 4 5" }; - final String resultMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE); - parseAndAssertIncorrectWithMessage(resultMessage, inputs); - } - - @Test - public void deleteCommand_numericArg_indexParsedCorrectly() { - final int testIndex = 1; - final String input = "delete " + testIndex; - final DeleteCommand result = parseAndAssertCommandType(input, DeleteCommand.class); - assertEquals(result.getTargetIndex(), testIndex); - } - - @Test - public void viewCommand_noArgs() { - final String[] inputs = { "view", "view " }; - final String resultMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, ViewCommand.MESSAGE_USAGE); - parseAndAssertIncorrectWithMessage(resultMessage, inputs); - } - - @Test - public void viewCommand_argsIsNotSingleNumber() { - final String[] inputs = { "view notAnumber ", "view 8*wh12", "view 1 2 3 4 5" }; - final String resultMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, ViewCommand.MESSAGE_USAGE); - parseAndAssertIncorrectWithMessage(resultMessage, inputs); - } - - @Test - public void viewCommand_numericArg_indexParsedCorrectly() { - final int testIndex = 2; - final String input = "view " + testIndex; - final ViewCommand result = parseAndAssertCommandType(input, ViewCommand.class); - assertEquals(result.getTargetIndex(), testIndex); - } - - @Test - public void viewAllCommand_noArgs() { - final String[] inputs = { "viewall", "viewall " }; - final String resultMessage = - String.format(MESSAGE_INVALID_COMMAND_FORMAT, ViewAllCommand.MESSAGE_USAGE); - parseAndAssertIncorrectWithMessage(resultMessage, inputs); - } - - @Test - public void viewAllCommand_argsIsNotSingleNumber() { - final String[] inputs = { "viewall notAnumber ", "viewall 8*wh12", "viewall 1 2 3 4 5" }; - final String resultMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, ViewAllCommand.MESSAGE_USAGE); - parseAndAssertIncorrectWithMessage(resultMessage, inputs); - } - - @Test - public void viewAllCommand_numericArg_indexParsedCorrectly() { - final int testIndex = 3; - final String input = "viewall " + testIndex; - final ViewAllCommand result = parseAndAssertCommandType(input, ViewAllCommand.class); - assertEquals(result.getTargetIndex(), testIndex); - } - - /** - * Test find persons by keyword in name command - */ - - @Test - public void findCommand_invalidArgs() { - // no keywords - final String[] inputs = { - "find", - "find " - }; - final String resultMessage = - String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_USAGE); - parseAndAssertIncorrectWithMessage(resultMessage, inputs); - } - - @Test - public void findCommand_validArgs_parsedCorrectly() { - final String[] keywords = { "key1", "key2", "key3" }; - final Set keySet = new HashSet<>(Arrays.asList(keywords)); - - final String input = "find " + String.join(" ", keySet); - final FindCommand result = - parseAndAssertCommandType(input, FindCommand.class); - assertEquals(keySet, result.getKeywords()); - } - - @Test - public void findCommand_duplicateKeys_parsedCorrectly() { - final String[] keywords = { "key1", "key2", "key3" }; - final Set keySet = new HashSet<>(Arrays.asList(keywords)); - - // duplicate every keyword - final String input = "find " + String.join(" ", keySet) + " " + String.join(" ", keySet); - final FindCommand result = - parseAndAssertCommandType(input, FindCommand.class); - assertEquals(keySet, result.getKeywords()); - } - - /** - * Test add person command - */ - - @Test - public void addCommand_invalidArgs() { - final String[] inputs = { - "add", - "add ", - "add wrong args format", - // no phone prefix - String.format("add $s $s e/$s a/$s", Name.EXAMPLE, Phone.EXAMPLE, Email.EXAMPLE, Address.EXAMPLE), - // no email prefix - String.format("add $s p/$s $s a/$s", Name.EXAMPLE, Phone.EXAMPLE, Email.EXAMPLE, Address.EXAMPLE), - // no address prefix - String.format("add $s p/$s e/$s $s", Name.EXAMPLE, Phone.EXAMPLE, Email.EXAMPLE, Address.EXAMPLE) - }; - final String resultMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE); - parseAndAssertIncorrectWithMessage(resultMessage, inputs); - } - - @Test - public void addCommand_invalidPersonDataInArgs() { - final String invalidName = "[]\\[;]"; - final String validName = Name.EXAMPLE; - final String invalidPhoneArg = "p/not__numbers"; - final String validPhoneArg = "p/" + Phone.EXAMPLE; - final String invalidEmailArg = "e/notAnEmail123"; - final String validEmailArg = "e/" + Email.EXAMPLE; - final String invalidTagArg = "t/invalid_-[.tag"; - - // address can be any string, so no invalid address - final String addCommandFormatString = "add $s $s $s a/" + Address.EXAMPLE; - - // test each incorrect person data field argument individually - final String[] inputs = { - // invalid name - String.format(addCommandFormatString, invalidName, validPhoneArg, validEmailArg), - // invalid phone - String.format(addCommandFormatString, validName, invalidPhoneArg, validEmailArg), - // invalid email - String.format(addCommandFormatString, validName, validPhoneArg, invalidEmailArg), - // invalid tag - String.format(addCommandFormatString, validName, validPhoneArg, validEmailArg) + " " + invalidTagArg - }; - for (String input : inputs) { - parseAndAssertCommandType(input, IncorrectCommand.class); - } - } - - @Test - public void addCommand_validPersonData_parsedCorrectly() { - final Person testPerson = generateTestPerson(); - final String input = convertPersonToAddCommandString(testPerson); - final AddCommand result = parseAndAssertCommandType(input, AddCommand.class); - assertEquals(result.getPerson(), testPerson); - } - - @Test - public void addCommand_duplicateTags_merged() throws IllegalValueException { - final Person testPerson = generateTestPerson(); - String input = convertPersonToAddCommandString(testPerson); - for (Tag tag : testPerson.getTags()) { - // create duplicates by doubling each tag - input += " t/" + tag.tagName; - } - - final AddCommand result = parseAndAssertCommandType(input, AddCommand.class); - assertEquals(result.getPerson(), testPerson); - } - - private static Person generateTestPerson() { - try { - return new Person( - new Name(Name.EXAMPLE), - new Phone(Phone.EXAMPLE, true), - new Email(Email.EXAMPLE, false), - new Address(Address.EXAMPLE, true), - new HashSet<>(Arrays.asList(new Tag("tag1"), new Tag("tag2"), new Tag("tag3"))) - ); - } catch (IllegalValueException ive) { - throw new RuntimeException("test person data should be valid by definition"); - } - } - - private static String convertPersonToAddCommandString(ReadOnlyPerson person) { - String addCommand = "add " - + person.getName().fullName - + (person.getPhone().isPrivate() ? " pp/" : " p/") + person.getPhone().value - + (person.getEmail().isPrivate() ? " pe/" : " e/") + person.getEmail().value - + (person.getAddress().isPrivate() ? " pa/" : " a/") + person.getAddress().value; - for (Tag tag : person.getTags()) { - addCommand += " t/" + tag.tagName; - } - return addCommand; - } - /** * Utility methods */ diff --git a/test/java/planmysem/storage/StorageFileTest.java b/test/java/planmysem/storage/StorageFileTest.java index 241794f1c..7e0415d38 100644 --- a/test/java/planmysem/storage/StorageFileTest.java +++ b/test/java/planmysem/storage/StorageFileTest.java @@ -1,26 +1,8 @@ package planmysem.storage; -import static org.junit.Assert.assertEquals; -import static planmysem.util.TestUtil.assertTextFilesEqual; - -import java.nio.file.Paths; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; - import org.junit.Rule; -import org.junit.Test; import org.junit.rules.ExpectedException; import org.junit.rules.TemporaryFolder; -import planmysem.data.AddressBook; -import planmysem.data.exception.IllegalValueException; -import planmysem.data.person.Address; -import planmysem.data.person.Email; -import planmysem.data.person.Name; -import planmysem.data.person.Person; -import planmysem.data.person.Phone; -import planmysem.data.tag.Tag; -import planmysem.storage.StorageFile.StorageOperationException; public class StorageFileTest { private static final String TEST_DATA_FOLDER = "test/data/StorageFileTest"; @@ -31,81 +13,81 @@ public class StorageFileTest { @Rule public TemporaryFolder testFolder = new TemporaryFolder(); - @Test - public void constructor_nullFilePath_exceptionThrown() throws Exception { - thrown.expect(NullPointerException.class); - new StorageFile(null); - } - - @Test - public void constructor_noTxtExtension_exceptionThrown() throws Exception { - thrown.expect(IllegalValueException.class); - new StorageFile(TEST_DATA_FOLDER + "/" + "InvalidfileName"); - } - - @Test - public void load_invalidFormat_exceptionThrown() throws Exception { - // The file contains valid xml data, but does not match the AddressBook class - StorageFile storage = getStorage("InvalidData.txt"); - thrown.expect(StorageOperationException.class); - storage.load(); - } - - @Test - public void load_validFormat() throws Exception { - AddressBook actualAB = getStorage("ValidData.txt").load(); - AddressBook expectedAB = getTestAddressBook(); - - // ensure loaded AddressBook is properly constructed with test data - // TODO: overwrite equals method in AddressBook class and replace with equals method below - assertEquals(actualAB.getAllPersons(), expectedAB.getAllPersons()); - } - - @Test - public void save_nullAddressBook_exceptionThrown() throws Exception { - StorageFile storage = getTempStorage(); - thrown.expect(NullPointerException.class); - storage.save(null); - } - - @Test - public void save_validAddressBook() throws Exception { - AddressBook ab = getTestAddressBook(); - StorageFile storage = getTempStorage(); - storage.save(ab); - - assertStorageFilesEqual(storage, getStorage("ValidData.txt")); - } - - // getPath() method in StorageFile class is trivial so it is not tested - - /** - * Asserts that the contents of two storage files are the same. - */ - private void assertStorageFilesEqual(StorageFile sf1, StorageFile sf2) throws Exception { - assertTextFilesEqual(Paths.get(sf1.getPath()), Paths.get(sf2.getPath())); - } - - private StorageFile getStorage(String fileName) throws Exception { - return new StorageFile(TEST_DATA_FOLDER + "/" + fileName); - } - - private StorageFile getTempStorage() throws Exception { - return new StorageFile(testFolder.getRoot().getPath() + "/" + "temp.txt"); - } - - private AddressBook getTestAddressBook() throws Exception { - AddressBook ab = new AddressBook(); - ab.addPerson(new Person(new Name("John Doe"), - new Phone("98765432", false), - new Email("johnd@gmail.com", false), - new Address("John street, block 123, #01-01", false), - Collections.emptySet())); - ab.addPerson(new Person(new Name("Betsy Crowe"), - new Phone("1234567", true), - new Email("betsycrowe@gmail.com", false), - new Address("Newgate Prison", true), - new HashSet<>(Arrays.asList(new Tag("friend"), new Tag("criminal"))))); - return ab; - } + // @Test + // public void constructor_nullFilePath_exceptionThrown() throws Exception { + // thrown.expect(NullPointerException.class); + // new StorageFile(null); + // } + // + // @Test + // public void constructor_noTxtExtension_exceptionThrown() throws Exception { + // thrown.expect(IllegalValueException.class); + // new StorageFile(TEST_DATA_FOLDER + "/" + "InvalidfileName"); + // } + // + // @Test + // public void load_invalidFormat_exceptionThrown() throws Exception { + // // The file contains valid xml data, but does not match the AddressBook class + // StorageFile storage = getStorage("InvalidData.txt"); + // thrown.expect(StorageOperationException.class); + // storage.load(); + // } + // + // @Test + // public void load_validFormat() throws Exception { + // AddressBook actualAB = getStorage("ValidData.txt").load(); + // AddressBook expectedAB = getTestAddressBook(); + // + // // ensure loaded AddressBook is properly constructed with test data + // // TODO: overwrite equals method in AddressBook class and replace with equals method below + // assertEquals(actualAB.getAllPersons(), expectedAB.getAllPersons()); + // } + // + // @Test + // public void save_nullAddressBook_exceptionThrown() throws Exception { + // StorageFile storage = getTempStorage(); + // thrown.expect(NullPointerException.class); + // storage.save(null); + // } + // + // @Test + // public void save_validAddressBook() throws Exception { + // AddressBook ab = getTestAddressBook(); + // StorageFile storage = getTempStorage(); + // storage.save(ab); + // + // assertStorageFilesEqual(storage, getStorage("ValidData.txt")); + // } + // + // // getPath() method in StorageFile class is trivial so it is not tested + // + // /** + // * Asserts that the contents of two storage files are the same. + // */ + // private void assertStorageFilesEqual(StorageFile sf1, StorageFile sf2) throws Exception { + // assertTextFilesEqual(Paths.get(sf1.getPath()), Paths.get(sf2.getPath())); + // } + // + // private StorageFile getStorage(String fileName) throws Exception { + // return new StorageFile(TEST_DATA_FOLDER + "/" + fileName); + // } + // + // private StorageFile getTempStorage() throws Exception { + // return new StorageFile(testFolder.getRoot().getPath() + "/" + "temp.txt"); + // } + // + // private AddressBook getTestAddressBook() throws Exception { + // AddressBook ab = new AddressBook(); + // ab.addPerson(new Person(new Name("John Doe"), + // new Phone("98765432", false), + // new Email("johnd@gmail.com", false), + // new Address("John street, block 123, #01-01", false), + // Collections.emptySet())); + // ab.addPerson(new Person(new Name("Betsy Crowe"), + // new Phone("1234567", true), + // new Email("betsycrowe@gmail.com", false), + // new Address("Newgate Prison", true), + // new HashSet<>(Arrays.asList(new Tag("friend"), new Tag("criminal"))))); + // return ab; + // } }