diff --git a/collated/functional/Kyomian.md b/collated/functional/Kyomian.md new file mode 100644 index 000000000000..f600f48f9057 --- /dev/null +++ b/collated/functional/Kyomian.md @@ -0,0 +1,679 @@ +# Kyomian +###### \java\seedu\address\logic\commands\EventCommand.java +``` java +/** + * Adds an event to the desk board + */ +public class EventCommand extends UndoableCommand { + + public static final String COMMAND_WORD = "event"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Adds an event to the desk board. " + + "Parameters: " + + PREFIX_NAME + "NAME " + + PREFIX_START_DATETIME + " START DATETIME " + + PREFIX_END_DATETIME + "END DATETIME " + + PREFIX_LOCATION + "LOCATION " + + "[" + PREFIX_REMARK + "REMARK]" + + "[" + PREFIX_TAG + "TAG]\n" + + "Example: " + COMMAND_WORD + " " + + PREFIX_NAME + "Software Project " + + PREFIX_START_DATETIME + "01/05/2018 08:00 " + + PREFIX_END_DATETIME + "01/08/2018 08:00 " + + PREFIX_LOCATION + "School of Computing " + + PREFIX_REMARK + "Bring laptop charger " + + PREFIX_TAG + "Important"; + + public static final String MESSAGE_SUCCESS = "New event added: %1$s"; + public static final String MESSAGE_DUPLICATE_EVENT = "This event already exists in the desk board"; + + private final Event toAdd; + + /** + * Creates a EventCommand to add the specified {@code Event} + */ + public EventCommand(Event event) { + requireNonNull(event); + toAdd = event; + } + + @Override + public CommandResult executeUndoableCommand() throws CommandException { + requireNonNull(model); + try { + model.addActivity(toAdd); + return new CommandResult(String.format(MESSAGE_SUCCESS, toAdd)); + } catch (DuplicateActivityException e) { + throw new CommandException(MESSAGE_DUPLICATE_EVENT); + } + + } + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof EventCommand // instanceof handles nulls + && toAdd.equals(((EventCommand) other).toAdd)); + } +} +``` +###### \java\seedu\address\logic\commands\RemoveCommand.java +``` java +/** + * Removes an activity based on its last displayed index in the desk board. + */ +public class RemoveCommand extends UndoableCommand { + + public static final String COMMAND_WORD = "rm"; + public static final String MESSAGE_USAGE = COMMAND_WORD + + ": Removes task/event identified by the index number in the last displayed task/event listing.\n" + + "Parameters: task/event INDEX (INDEX must be a positive integer)\n" + + "Example: " + COMMAND_WORD + " task 1" + " OR " + + COMMAND_WORD + " event 1"; + + public static final String MESSAGE_REMOVE_TASK_SUCCESS = "Removed task: %1$s"; + public static final String MESSAGE_REMOVE_EVENT_SUCCESS = "Removed event: %1$s"; + + private final Index targetIndex; + private Activity activityToDelete; + private final String activityOption; + + public RemoveCommand(String activityOption, Index targetIndex) { + this.activityOption = activityOption; + this.targetIndex = targetIndex; + } + + @Override + public CommandResult executeUndoableCommand() { + requireNonNull(activityToDelete); + try { + model.deleteActivity(activityToDelete); + } catch (ActivityNotFoundException pnfe) { + throw new AssertionError("The target activity cannot be missing"); + } + + if (activityOption.equals("task")) { + return new CommandResult(String.format(MESSAGE_REMOVE_TASK_SUCCESS, activityToDelete)); + } else { + return new CommandResult(String.format(MESSAGE_REMOVE_EVENT_SUCCESS, activityToDelete)); + } + } + + @Override + protected void preprocessUndoableCommand() throws CommandException { + + if (activityOption.equals("task")) { + List lastShownTaskList = model.getFilteredTaskList(); + if (targetIndex.getZeroBased() >= lastShownTaskList.size()) { + throw new CommandException(Messages.MESSAGE_INVALID_ACTIVITY_DISPLAYED_INDEX); + } + activityToDelete = lastShownTaskList.get(targetIndex.getZeroBased()); + } else if (activityOption.equals("event")) { + List lastShownEventList = model.getFilteredEventList(); + if (targetIndex.getZeroBased() >= lastShownEventList.size()) { + throw new CommandException(Messages.MESSAGE_INVALID_ACTIVITY_DISPLAYED_INDEX); + } + activityToDelete = lastShownEventList.get(targetIndex.getZeroBased()); + } + } + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof RemoveCommand // instanceof handles nulls + && this.targetIndex.equals(((RemoveCommand) other).targetIndex) // state check + && Objects.equals(this.activityToDelete, ((RemoveCommand) other).activityToDelete)); + } +} +``` +###### \java\seedu\address\logic\commands\TaskCommand.java +``` java +/** + * Adds a task to the desk board. + */ +public class TaskCommand extends UndoableCommand { + + public static final String COMMAND_WORD = "task"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Adds a task to the desk board. " + + "Parameters: " + + PREFIX_NAME + "NAME " + + PREFIX_DATE_TIME + "DATETIME " + + "[" + PREFIX_REMARK + "REMARK] " + + "[" + PREFIX_TAG + "TAG]\n" + + "Example: " + COMMAND_WORD + " " + + PREFIX_NAME + "Software Engineering Milestone 1 " + + PREFIX_DATE_TIME + "01/08/2018 17:00 " + + PREFIX_REMARK + "Enhance major component " + + PREFIX_TAG + "CS2103T"; + + public static final String MESSAGE_SUCCESS = "New task added: %1$s"; + public static final String MESSAGE_DUPLICATE_TASK = "This task already exists in the desk board"; + + private final Task toAdd; + + /** + * Creates a TaskCommand to add the specified {@code Task} + */ + public TaskCommand(Task task) { + requireNonNull(task); + toAdd = task; + } + + @Override + public CommandResult executeUndoableCommand() throws CommandException { + requireNonNull(model); + try { + model.addActivity(toAdd); + return new CommandResult(String.format(MESSAGE_SUCCESS, toAdd)); + } catch (DuplicateActivityException e) { + throw new CommandException(MESSAGE_DUPLICATE_TASK); + } + + } + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof TaskCommand // instanceof handles nulls + && toAdd.equals(((TaskCommand) other).toAdd)); + } +} +``` +###### \java\seedu\address\logic\parser\CliSyntax.java +``` java +/** + * Contains Command Line Interface (CLI) syntax definitions common to multiple commands + */ +public class CliSyntax { + + /* Prefix definitions */ + public static final Prefix PREFIX_NAME = new Prefix("n/"); + public static final Prefix PREFIX_DATE_TIME = new Prefix("d/"); + public static final Prefix PREFIX_REMARK = new Prefix("r/"); + public static final Prefix PREFIX_TAG = new Prefix("t/"); + public static final Prefix PREFIX_START_DATETIME = new Prefix("s/"); + public static final Prefix PREFIX_END_DATETIME = new Prefix("e/"); + public static final Prefix PREFIX_LOCATION = new Prefix("l/"); + + // To be deleted soon + public static final Prefix PREFIX_ADDRESS = new Prefix("a/"); + public static final Prefix PREFIX_EMAIL = new Prefix("em/"); + public static final Prefix PREFIX_PHONE = new Prefix("p/"); +} +``` +###### \java\seedu\address\logic\parser\DeskBoardParser.java +``` java +/** + * Parses user input. + */ +public class DeskBoardParser { + + /** + * 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 + * @throws ParseException if the user input does not conform the expected format + */ + public Command parseCommand(String userInput) throws ParseException { + final Matcher matcher = BASIC_COMMAND_FORMAT.matcher(userInput.trim()); + if (!matcher.matches()) { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, HelpCommand.MESSAGE_USAGE)); + } + + final String commandWord = matcher.group("commandWord"); + final String arguments = matcher.group("arguments"); + switch (commandWord) { + + case TaskCommand.COMMAND_WORD: + return new TaskCommandParser().parse(arguments); + + case CompleteCommand.COMMAND_WORD: + return new CompleteCommandParser().parse(arguments); + + case EventCommand.COMMAND_WORD: + return new EventCommandParser().parse(arguments); + + //case EditCommand.COMMAND_WORD: + //return new EditCommandParser().parse(arguments); + + //case SelectCommand.COMMAND_WORD: + //return new SelectCommandParser().parse(arguments); + + case RemoveCommand.COMMAND_WORD: + return new RemoveCommandParser().parse(arguments); + + case ClearCommand.COMMAND_WORD: + return new ClearCommand(); + + case ClearCommand.COMMAND_ALIAS: + return new ClearCommand(); + + //case FindCommand.COMMAND_WORD: + //return new FindCommandParser().parse(arguments); + + case ListCommand.COMMAND_WORD: + return new ListCommandParser().parse(arguments); + + case ListCommand.COMMAND_ALIAS: + return new ListCommandParser().parse(arguments); + + //case HistoryCommand.COMMAND_WORD: + //return new HistoryCommand(); + + //case ExitCommand.COMMAND_WORD: + //return new ExitCommand(); + + case HelpCommand.COMMAND_WORD: + return new HelpCommandParser().parse(arguments); + + case HelpCommand.COMMAND_ALIAS: + return new HelpCommandParser().parse(arguments); + + //case UndoCommand.COMMAND_WORD: + //return new UndoCommand(); + + //case RedoCommand.COMMAND_WORD: + //return new RedoCommand(); + + default: + throw new ParseException(MESSAGE_UNKNOWN_COMMAND); + } + } + +} +``` +###### \java\seedu\address\logic\parser\EventCommandParser.java +``` java + +/** + * Parses input arguments and creates a new EventCommand object + */ +public class EventCommandParser implements Parser { + /** + * Parses the given {@code String} of arguments in the context of the EventCommand + * and returns a EventCommand object for execution. + * @throws ParseException if the user input does not conform the expected format + */ + public EventCommand parse(String args) throws ParseException { + ArgumentMultimap argMultimap = + ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_START_DATETIME, PREFIX_END_DATETIME, + PREFIX_LOCATION, PREFIX_REMARK, PREFIX_TAG); + + if (!arePrefixesPresent(argMultimap, PREFIX_NAME, PREFIX_START_DATETIME, PREFIX_END_DATETIME) + || !argMultimap.getPreamble().isEmpty()) { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, EventCommand.MESSAGE_USAGE)); + } + + try { + Name name = ParserUtil.parseName(argMultimap.getValue(PREFIX_NAME)).get(); + DateTime startDateTime = ParserUtil.parseDateTime(argMultimap.getValue(PREFIX_START_DATETIME)).get(); + DateTime endDateTime = ParserUtil.parseDateTime(argMultimap.getValue(PREFIX_END_DATETIME)).get(); + Location location = ParserUtil.parseLocation(argMultimap.getValue(PREFIX_LOCATION)).get(); + Remark remark = ParserUtil.parseRemark(argMultimap.getValue(PREFIX_REMARK)).get(); + Set tagList = ParserUtil.parseTags(argMultimap.getAllValues(PREFIX_TAG)); + + Event event = new Event(name, startDateTime, endDateTime, location, remark, tagList); + + return new EventCommand(event); + } catch (IllegalValueException ive) { + throw new ParseException(ive.getMessage(), ive); + } + } + + /** + * Returns true if none of the prefixes contains empty {@code Optional} values in the given + * {@code ArgumentMultimap}. + */ + private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) { + return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent()); + } +} +``` +###### \java\seedu\address\logic\parser\ParserUtil.java +``` java +/** + * Contains utility methods used for parsing strings in the various *Parser classes. + * {@code ParserUtil} contains methods that take in {@code Optional} as parameters. However, it goes against Java's + * convention (see https://stackoverflow.com/a/39005452) as {@code Optional} should only be used a return type. + * Justification: The methods in concern receive {@code Optional} return values from other methods as parameters and + * return {@code Optional} values based on whether the parameters were present. Therefore, it is redundant to unwrap the + * initial {@code Optional} before passing to {@code ParserUtil} as a parameter and then re-wrap it into an + * {@code Optional} return value inside {@code ParserUtil} methods. + */ +public class ParserUtil { + + public static final String MESSAGE_INVALID_INDEX = "Index is not a non-zero unsigned integer."; + public static final String MESSAGE_INSUFFICIENT_PARTS = "Number of parts must be more than 1."; + + /** + * Parses {@code oneBasedIndex} into an {@code Index} and returns it. Leading and trailing whitespaces will be + * trimmed. + * @throws IllegalValueException if the specified index is invalid (not non-zero unsigned integer). + */ + public static Index parseIndex(String oneBasedIndex) throws IllegalValueException { + String trimmedIndex = oneBasedIndex.trim(); + if (!StringUtil.isNonZeroUnsignedInteger(trimmedIndex)) { + throw new IllegalValueException(MESSAGE_INVALID_INDEX); + } + return Index.fromOneBased(Integer.parseInt(trimmedIndex)); + } + + /** + * Parses a {@code String name} into a {@code Name}. + * Leading and trailing whitespaces will be trimmed. + * + * @throws IllegalValueException if the given {@code name} is invalid. + */ + public static Name parseName(String name) throws IllegalValueException { + requireNonNull(name); + String trimmedName = name.trim(); + if (!Name.isValidName(trimmedName)) { + throw new IllegalValueException(Name.MESSAGE_NAME_CONSTRAINTS); + } + return new Name(trimmedName); + } + + /** + * Parses a {@code Optional name} into an {@code Optional} if {@code name} is present. + * See header comment of this class regarding the use of {@code Optional} parameters. + */ + public static Optional parseName(Optional name) throws IllegalValueException { + requireNonNull(name); + return name.isPresent() ? Optional.of(parseName(name.get())) : Optional.empty(); + } + + /** + * Parses a {@code String datetime} into a {@code DateTime}. + * Leading and trailing whitespaces will be trimmed. + * + * @throws IllegalValueException if the given {@code datetime} is invalid. + */ + + public static DateTime parseDateTime(String datetime) throws IllegalValueException { + requireNonNull(datetime); + String trimmedDateTime = datetime.trim(); + if (!DateTime.isValidDateTime(trimmedDateTime)) { + throw new IllegalValueException(DateTime.MESSAGE_DATETIME_CONSTRAINTS); + } + return new DateTime(trimmedDateTime); + } + + /** + * Parses a {@code Optional name} into an {@code Optional} if {@code datetime} is present. + * See header comment of this class regarding the use of {@code Optional} parameters. + */ + public static Optional parseDateTime(Optional datetime) throws IllegalValueException { + requireNonNull(datetime); + return datetime.isPresent() ? Optional.of(parseDateTime(datetime.get())) : Optional.empty(); + } + + + /** + * Parses a {@code String location} into a {@code Location}. + * Leading and trailing whitespaces will be trimmed. + * + * @throws IllegalValueException if the given {@code location} is invalid. + */ + + public static Location parseLocation(String location) throws IllegalValueException { + requireNonNull(location); + String trimmedLocation = location.trim(); + if (!Location.isValidLocation(trimmedLocation)) { + throw new IllegalValueException(Location.MESSAGE_LOCATION_CONSTRAINTS); + } + return new Location(trimmedLocation); + } + + /** + * Parses a {@code Optional location} into an {@code Optional} if {@code location} is present. + * See header comment of this class regarding the use of {@code Optional} parameters. + */ + public static Optional parseLocation(Optional location) throws IllegalValueException { + requireNonNull(location); + return location.isPresent() ? Optional.of(parseLocation(location.get())) : Optional.empty(); + } + + /** + * Parses a {@code String remark} into a {@code Remark}. + * Leading and trailing whitespaces will be trimmed. + * + * @throws IllegalValueException if the given {@code remark} is invalid. + */ + public static Remark parseRemark(String remark) throws IllegalValueException { + requireNonNull(remark); + String trimmedRemark = remark.trim(); + if (!Remark.isValidRemark(trimmedRemark)) { + throw new IllegalValueException(Remark.MESSAGE_REMARK_CONSTRAINTS); + } + return new Remark(trimmedRemark); + } + + /** + * Parses a {@code Optional remark} into an {@code Optional} if {@code remark} is present. + * See header comment of this class regarding the use of {@code Optional} parameters. + */ + public static Optional parseRemark(Optional remark) throws IllegalValueException { + requireNonNull(remark); + return remark.isPresent() ? Optional.of(parseRemark(remark.get())) : Optional.empty(); + } + + /** + * Parses a {@code String tag} into a {@code Tag}. + * Leading and trailing whitespaces will be trimmed. + * + * @throws IllegalValueException if the given {@code tag} is invalid. + */ + public static Tag parseTag(String tag) throws IllegalValueException { + requireNonNull(tag); + String trimmedTag = tag.trim(); + if (!Tag.isValidTagName(trimmedTag)) { + throw new IllegalValueException(Tag.MESSAGE_TAG_CONSTRAINTS); + } + return new Tag(trimmedTag); + } + + /** + * Parses {@code Collection tags} into a {@code Set}. + */ + public static Set parseTags(Collection tags) throws IllegalValueException { + requireNonNull(tags); + final Set tagSet = new HashSet<>(); + for (String tagName : tags) { + tagSet.add(parseTag(tagName)); + } + return tagSet; + } + +} +``` +###### \java\seedu\address\logic\parser\RemoveCommandParser.java +``` java +/** + * Parses input arguments and creates a new RemoveCommand object + */ +public class RemoveCommandParser implements Parser { + + /** + * Parses the given {@code String} of arguments in the context of the RemoveCommand + * and returns a RemoveCommand object for execution. + * @throws ParseException if the user input does not conform the expected format + */ + public RemoveCommand parse(String args) throws ParseException { + String[] argsParts = args.trim().split(" "); + + if (argsParts.length != 2 || !isValidActivityOption(argsParts[0])) { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, RemoveCommand.MESSAGE_USAGE)); + } + + try { + String activityOption = argsParts[0]; + Index index = ParserUtil.parseIndex(argsParts[1]); + return new RemoveCommand(activityOption, index); + } catch (IllegalValueException ive) { + throw new ParseException( + String.format(MESSAGE_INVALID_COMMAND_FORMAT, RemoveCommand.MESSAGE_USAGE)); + } + } + + private static boolean isValidActivityOption(String activityOption) { + return activityOption.equals("task") || activityOption.equals("event"); + } + +} +``` +###### \java\seedu\address\logic\parser\TaskCommandParser.java +``` java +/** + * Parses input arguments and creates a new TaskCommand object + */ + +public class TaskCommandParser implements Parser { + + /** + * Parses the given {@code String} of arguments in the context of the TaskCommand + * and returns a TaskCommand object for execution. + * @throws ParseException if the user input does not conform the expected format + */ + public TaskCommand parse(String args) throws ParseException { + ArgumentMultimap argMultimap = + ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_DATE_TIME, PREFIX_REMARK, PREFIX_TAG); + + if (!arePrefixesPresent(argMultimap, PREFIX_NAME, PREFIX_DATE_TIME) + || !argMultimap.getPreamble().isEmpty()) { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, TaskCommand.MESSAGE_USAGE)); + } + + try { + Name name = ParserUtil.parseName(argMultimap.getValue(PREFIX_NAME)).get(); + DateTime datetime = ParserUtil.parseDateTime(argMultimap.getValue(PREFIX_DATE_TIME)).get(); + Remark remark = ParserUtil.parseRemark(argMultimap.getValue(PREFIX_REMARK)).get(); + Set tagList = ParserUtil.parseTags(argMultimap.getAllValues(PREFIX_TAG)); + + Task task = new Task(name, datetime, remark, tagList); + + return new TaskCommand(task); + } catch (IllegalValueException ive) { + throw new ParseException(ive.getMessage(), ive); + } + } + + /** + * Returns true if none of the prefixes contains empty {@code Optional} values in the given + * {@code ArgumentMultimap}. + */ + private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) { + return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent()); + } + +} +``` +###### \java\seedu\address\model\activity\DateTime.java +``` java +/** + * Represents an Activity's datetime in the desk board. + * Guarantees: immutable; is valid as declared in {@link #isValidDateTime(String)} + */ +public class DateTime { + + public static final String DEFAULT_DATETIME_FORMAT = "d/M/y H:m"; + public static final String MESSAGE_DATETIME_CONSTRAINTS = + "Date and Time should be in the format of " + DEFAULT_DATETIME_FORMAT; + private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DEFAULT_DATETIME_FORMAT); + + private final LocalDateTime dateTime; + private final String dateTimeString; + + /** + * Constructs a {@code DateTime}. + * + * @param value A valid datetime. + */ + public DateTime(String value) { + requireNonNull(value); + checkArgument(isValidDateTime(value), MESSAGE_DATETIME_CONSTRAINTS); + this.dateTime = LocalDateTime.parse(value, formatter); + this.dateTimeString = value; + } + + /** + * Returns true if a given string is a valid datetime. + */ + public static boolean isValidDateTime(String value) { + try { + LocalDateTime.parse(value, formatter); + return true; + } catch (DateTimeParseException dtpe) { + dtpe.printStackTrace(); + return false; + } + } + + public LocalDateTime getLocalDateTime() { + return this.dateTime; + } + + @Override + public String toString() { + return this.dateTimeString; + } + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof DateTime // instanceof handles nulls + && this.dateTime.equals(((DateTime) other).dateTime)); // state check + } + + @Override + public int hashCode() { + return dateTime.hashCode(); + } + +} +``` +###### \java\seedu\address\ui\util\DateTimeUtil.java +``` java +/** + * Formats DateTime for display in UI + * Example: 01/08/2018 08:00 is displayed as 1 Aug 2018 08:00 in the UI + */ +public class DateTimeUtil { + + private static final String DISPLAYED_DATETIME_FORMAT = "d MMM y HH:mm"; + private static final DateTimeFormatter displayFormatter = DateTimeFormatter.ofPattern(DISPLAYED_DATETIME_FORMAT); + + /** + * Formats DateTime of task as day, name of month, year, hours and minutes + */ + public static String getDisplayedDateTime(Task task) throws DateTimeException { + DateTime dateTime = task.getDateTime(); + String displayedDateTime = displayFormatter.format(dateTime.getLocalDateTime()); + return displayedDateTime; + } + + /** + * Formats StartDateTime of event as day, name of month, year, hours and minutes + */ + public static String getDisplayedStartDateTime(Event event) throws DateTimeException { + DateTime dateTime = event.getStartDateTime(); + String displayedDateTime = displayFormatter.format(dateTime.getLocalDateTime()); + return displayedDateTime; + } + + /** + * Formats EndDateTime of event as day, name of month, year, hours and minutes + */ + public static String getDisplayedEndDateTime(Event event) throws DateTimeException { + DateTime dateTime = event.getEndDateTime(); + String displayedDateTime = displayFormatter.format(dateTime.getLocalDateTime()); + return displayedDateTime; + } +} +``` diff --git a/collated/functional/YuanQLLer.md b/collated/functional/YuanQLLer.md new file mode 100644 index 000000000000..540037c0f343 --- /dev/null +++ b/collated/functional/YuanQLLer.md @@ -0,0 +1,68 @@ +# YuanQLLer +###### \java\seedu\address\model\util\SampleDataUtil.java +``` java +/** + * Contains utility methods for populating {@code DeskBoard} with sample data. + */ +public class SampleDataUtil { + public static Activity[] getSampleActivity() { + return new Activity[] { + new Task(new Name("Task 1"), new DateTime("01/01/2018 23:59"), + new Remark("Submit through ivle"), getTagSet("Completed")), + new Task (new Name("Task 2"), new DateTime("02/02/2018 23:59"), + new Remark("Submit through ivle"), getTagSet("Completed")), + new Task (new Name("Task 3"), new DateTime("03/03/2018 23:59"), + new Remark("Submit through ivle"), getTagSet("Completed")), + new Task (new Name("Task 4"), new DateTime("04/04/2018 23:59"), + new Remark("Submit through ivle"), getTagSet("Uncompleted")), + new Task (new Name("Task 5"), new DateTime("05/05/2018 23:59"), + new Remark("Submit through ivle"), getTagSet("Unompleted")), + new Task (new Name("Task 6"), new DateTime("06/06/2018 23:59"), + new Remark("Submit through ivle"), getTagSet("Completed")), + new Event(new Name("Event 1"), new DateTime("01/01/2018 07:00"), + new DateTime("01/01/2018 08:00"), new Location("TBC"), new Remark("Remark"), + getTagSet("Finished")), + new Event (new Name("Event 2"), new DateTime("02/02/2018 07:00"), + new DateTime("02/02/2018 08:00"), new Location("TBC"), new Remark("Remark"), + getTagSet("Finished")), + new Event (new Name("Event 3"), new DateTime("03/03/2018 07:00"), + new DateTime("03/03/2018 08:00"), new Location("TBC"), new Remark("Remark"), + getTagSet("Cancelled")), + new Event (new Name("Event 4"), new DateTime("04/04/2018 07:00"), + new DateTime("04/04/2018 08:00"), new Location("TBC"), new Remark("Remark"), + getTagSet("Important")), + new Event (new Name("Event 5"), new DateTime("05/05/2018 07:00"), + new DateTime("05/05/2018 08:00"), new Location("TBC"), new Remark("Remark"), + getTagSet("Important")), + new Event (new Name("Event 6"), new DateTime("06/06/2018 07:00"), + new DateTime("06/06/2018 08:00"), new Location("TBC"), new Remark("Remark"), + getTagSet("Compulsory")) + }; + } + + public static ReadOnlyDeskBoard getSampleDeskBoard() { + try { + DeskBoard sampleAb = new DeskBoard(); + for (Activity sampleActivity : getSampleActivity()) { + sampleAb.addActivity(sampleActivity); + } + return sampleAb; + } catch (DuplicateActivityException e) { + throw new AssertionError("sample data cannot contain duplicate activities", e); + } + } + + /** + * Returns a tag set containing the list of strings given. + */ + public static Set getTagSet(String ... strings) { + HashSet tags = new HashSet<>(); + for (String s : strings) { + tags.add(new Tag(s)); + } + + return tags; + } + +} +``` diff --git a/collated/functional/YuanQQLer.md b/collated/functional/YuanQQLer.md new file mode 100644 index 000000000000..37242a6fbe29 --- /dev/null +++ b/collated/functional/YuanQQLer.md @@ -0,0 +1,825 @@ +# YuanQQLer +###### \java\seedu\address\commons\events\model\DeskBoardChangedEvent.java +``` java +/** Indicates the DeskBoard in the model has changed*/ +public class DeskBoardChangedEvent extends BaseEvent { + + public final ReadOnlyDeskBoard data; + + public DeskBoardChangedEvent(ReadOnlyDeskBoard data) { + this.data = data; + } + + @Override + public String toString() { + return "number of activities " + data.getActivityList().size() + ", number of tags " + data.getTagList().size(); + } +} +``` +###### \java\seedu\address\commons\events\ui\ActivityPanelSelectionChangedEvent.java +``` java +/** + * Represents a selection change in the Activity List Panel + */ +public class ActivityPanelSelectionChangedEvent extends BaseEvent { + + + private final ActivityCard newSelection; + + public ActivityPanelSelectionChangedEvent(ActivityCard newSelection) { + this.newSelection = newSelection; + } + + @Override + public String toString() { + return this.getClass().getSimpleName(); + } + + public ActivityCard getNewSelection() { + return newSelection; + } +} +``` +###### \java\seedu\address\model\activity\Activity.java +``` java +/** + * Represents a Activity in the desk board. + * Guarantees: details are present and not null, field values are validated, immutable. + */ +public abstract class Activity { + + private final Name name; + private final DateTime dateTime; + private final Remark remark; + + private final UniqueTagList tags; + private final boolean isCompleted; + + /** + * Every field must be present and not null. + */ + public Activity(Name name, DateTime dateTime, Remark remark, Set tags) { + requireAllNonNull(name, dateTime, tags); + this.name = name; + this.dateTime = dateTime; + this.remark = remark; + // protect internal tags from changes in the arg list + this.tags = new UniqueTagList(tags); + this.isCompleted = false; + } + + public Activity(Name name, DateTime dateTime, Remark remark, Set tags, boolean isCompleted) { + requireAllNonNull(name, dateTime, tags); + this.name = name; + this.dateTime = dateTime; + this.remark = remark; + // protect internal tags from changes in the arg list + this.tags = new UniqueTagList(tags); + this.isCompleted = isCompleted; + } + + public Name getName() { + return name; + } + + public DateTime getDateTime() { + return dateTime; + } + + public Remark getRemark() { + return remark; + } + + /** + * Returns an immutable tag set, which throws {@code UnsupportedOperationException} + * if modification is attempted. + */ + public Set getTags() { + return Collections.unmodifiableSet(tags.toSet()); + } + + public abstract String getActivityType(); + + public abstract Activity copy(Set tags); + + public boolean isCompleted() { + return isCompleted; + } + + public abstract Activity getCompletedCopy(); +} +``` +###### \java\seedu\address\model\activity\Event.java +``` java +/** + * Represents a Task in the desk board. + * The field contains 3 field, name, start date/time, end date/time and + * (Optional)location (Optional)remark. + * The following example would illustrate one example + * ******** Example ******************************* * + * NAME : CS2103 Exam + * START DATE/TIME: 21/03/2018 23:59 + * END DATE/TIME: + * LOCATION: TBC + * REMARK: Submit through a pull request in git hub. + * ************************************************ * + */ +public class Event extends Activity { + + private static final String ACTIVITY_TYPE = "EVENT"; + + private final DateTime endDateTime; + private final Location location; + + /** + * Every field must be present and not null. + */ + public Event( + Name name, DateTime startDateTime, DateTime endDateTime, Location location, Remark remark, Set tags) { + super(name, startDateTime, remark, tags); + requireAllNonNull(endDateTime); + this.endDateTime = endDateTime; + this.location = location; + } + + public Event( + Name name, DateTime startDateTime, DateTime endDateTime, Location location, Remark remark, Set tags, + boolean isComplete) { + super(name, startDateTime, remark, tags, isComplete); + requireAllNonNull(endDateTime); + this.endDateTime = endDateTime; + this.location = location; + } + + @Override + public Name getName() { + return super.getName(); + } + + public DateTime getStartDateTime() { + return super.getDateTime(); + } + + public DateTime getEndDateTime() { + return this.endDateTime; + } + + public Location getLocation() { + return this.location; + } + @Override + public Remark getRemark() { + return super.getRemark(); + } + + @Override + public String getActivityType() { + return ACTIVITY_TYPE; + } + + /** + * Returns an immutable tag set, which throws {@code UnsupportedOperationException} + * if modification is attempted. + */ + @Override + public Set getTags() { + return super.getTags(); + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + + if (!(other instanceof Event)) { + return false; + } + + Event otherEvent = (Event) other; + return otherEvent.getName().equals(this.getName()) + && otherEvent.getStartDateTime().equals(this.getStartDateTime()) + && otherEvent.getEndDateTime().equals(this.getEndDateTime()) + && (location == null ? otherEvent.location == null : location.equals(otherEvent.getLocation())) + && (getRemark() == null ? otherEvent.getRemark() == null : getRemark().equals(otherEvent.getRemark())) + && this.isCompleted() == otherEvent.isCompleted(); + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Event Name: ") + .append(getName()) + .append(" Start Date/Time: ") + .append(getDateTime()) + .append(" End Date/Time") + .append(getEndDateTime()) + .append(" Location: ") + .append(getLocation() == null ? "" : getLocation()) + .append(" Remark: ") + .append(getRemark() == null ? "" : getRemark()) + .append(" Tags: ") + .append(isCompleted() ? "Uncompleted" : "Completed"); + getTags().forEach(builder::append); + return builder.toString(); + } + + @Override + public Activity copy(Set tags) { + if (tags == null) { + return new Event(getName(), getStartDateTime(), getEndDateTime(), getLocation(), getRemark(), getTags(), + isCompleted()); + } + return new Event(getName(), getStartDateTime(), getEndDateTime(), getLocation(), getRemark(), tags, + isCompleted()); + } + + @Override + public Activity getCompletedCopy() { + return new Event( + getName(), getStartDateTime(), getEndDateTime(), getLocation(), getRemark(), getTags(), true); + } +} + +``` +###### \java\seedu\address\model\activity\EventOnlyPredicate.java +``` java +/** + * This class gives a predicate that returns only the event in a list. + */ +public class EventOnlyPredicate implements Predicate { + + public EventOnlyPredicate() { + ; + } + + @Override + public boolean test(Activity activity) { + return activity.getActivityType().equals("EVENT"); + } + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof EventOnlyPredicate); // instanceof handles nulls + } + +} +``` +###### \java\seedu\address\model\activity\exceptions\ActivityNotFoundException.java +``` java +/** + * Signals that the operation is unable to find the specified activity. + */ +public class ActivityNotFoundException extends Exception {} +``` +###### \java\seedu\address\model\activity\exceptions\DuplicateActivityException.java +``` java +/** + * Signals that the operation will result in duplicate Activity objects. + */ +public class DuplicateActivityException extends DuplicateDataException { + public DuplicateActivityException() { + super("Operation would result in duplicate activities"); + } +} +``` +###### \java\seedu\address\model\activity\Location.java +``` java +/** + * This class is to store location info in an event + */ +public class Location { + public static final String MESSAGE_LOCATION_CONSTRAINTS = + "Activity location should not be blank, or start with white space"; + + /* + * The first character of the address must not be a whitespace, + * otherwise " " (a blank string) becomes a valid input. + */ + public static final String LOCATION_VALIDATION_REGEX = "[^\\s].*"; + + public final String value; + + /** + * Constructs a {@code Name}. + * + * @param location A valid location. + */ + public Location(String location) { + requireNonNull(location); + checkArgument(isValidLocation(location), MESSAGE_LOCATION_CONSTRAINTS); + this.value = location; + } + + /** + * Returns true if a given string is a valid location. + */ + public static boolean isValidLocation(String test) { + return test.matches(LOCATION_VALIDATION_REGEX); + } + + + @Override + public String toString() { + return value; + } + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof Location // instanceof handles nulls + && this.value.equals(((Location) other).value)); // state check + } + + @Override + public int hashCode() { + return value.hashCode(); + } + +} +``` +###### \java\seedu\address\model\activity\Remark.java +``` java +/** + * Represents an Activity's remark in the desk board. + * Guarantees: immutable; is valid as declared in {@link #isValidRemark(String)} + */ +public class Remark { + + public static final String MESSAGE_REMARK_CONSTRAINTS = + "Activity remark can take any values, and it should not be blank."; + + public static final String REMARK_VALIDATION_REGEX = ".+"; + + public final String value; + + /** + * Constructs an {@code Remark}. + * + * @param remark A valid remark. + */ + public Remark(String remark) { + requireNonNull(remark); + checkArgument(isValidRemark(remark), MESSAGE_REMARK_CONSTRAINTS); + this.value = remark; + } + + /** + * Returns true if a given string is a valid activity remark. + */ + public static boolean isValidRemark(String test) { + return test.matches(REMARK_VALIDATION_REGEX); + } + + @Override + public String toString() { + return value; + } + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof Remark // instanceof handles nulls + && this.value.equals(((Remark) other).value)); // state check + } + + @Override + public int hashCode() { + return value.hashCode(); + } + +} +``` +###### \java\seedu\address\model\activity\Task.java +``` java +/** + * Represents a Task in the desk board. + * The field contains 3 field, name, due date and (Optional)remark. + * The following example would illustrate one example + * ******** Example ******************************* * + * NAME : CS2103 Project + * DUE DATE/TIME: 21/03/2018 23:59 + * REMARK: Submit through a pull request in git hub. + * ************************************************ * + */ +public class Task extends Activity { + + private static final String ACTIVITY_TYPE = "TASK"; + + /** + * Every field must be present and not null. + */ + public Task(Name name, DateTime dueDateTime, Remark remark, Set tags) { + super(name, dueDateTime, remark, tags); + + + } + + public Task(Name name, DateTime dueDateTime, Remark remark, Set tags, boolean isComplete) { + super(name, dueDateTime, remark, tags, isComplete); + + + } + @Override + public Name getName() { + return super.getName(); + } + + public DateTime getDueDateTime() { + return super.getDateTime(); + } + + @Override + public Remark getRemark() { + return super.getRemark(); + } + + @Override + public String getActivityType() { + return ACTIVITY_TYPE; + } + + /** + * Returns an immutable tag set, which throws {@code UnsupportedOperationException} + * if modification is attempted. + */ + @Override + public Set getTags() { + return super.getTags(); + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + + if (!(other instanceof Task)) { + return false; + } + + Task otherTask = (Task) other; + return otherTask.getName().equals(this.getName()) + && otherTask.getDueDateTime().equals(this.getDueDateTime()) + && (getRemark() == null ? otherTask.getRemark() == null : getRemark().equals(otherTask.getRemark())) + && this.isCompleted() == otherTask.isCompleted(); + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Task Name: ") + .append(getName()) + .append(" Due Date/Time: ") + .append(getDateTime()) + .append(" Remark: ") + .append(getRemark() == null ? "" : getRemark()) + .append(" Tags: ") + .append(isCompleted() ? "Uncompleted" : "Completed"); + getTags().forEach(builder::append); + return builder.toString(); + } + + @Override + public Activity copy(Set tags) { + if (tags == null) { + return new Task(getName(), getDueDateTime(), getRemark(), getTags(), isCompleted()); + } + return new Task(getName(), getDueDateTime(), getRemark(), tags, isCompleted()); + } + + @Override + public Activity getCompletedCopy() { + return new Task(getName(), getDueDateTime(), getRemark(), getTags(), true); + } +} +``` +###### \java\seedu\address\model\activity\TaskOnlyPredicate.java +``` java +/** + * This class gives a predicate that returns only the tasks in a list. + */ +public class TaskOnlyPredicate implements Predicate { + public TaskOnlyPredicate() { + ; + } + + @Override + public boolean test(Activity activity) { + return activity.getActivityType().equals("TASK"); + } + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof TaskOnlyPredicate); // instanceof handles nulls + } + +} +``` +###### \java\seedu\address\model\DeskBoard.java +``` java +/** + * Wraps all data at the address-book level + * Duplicates are not allowed (by .equals comparison) + */ +public class DeskBoard implements ReadOnlyDeskBoard { + + private final UniqueActivityList activities; + private final UniqueTagList tags; + + /* + * The 'unusual' code block below is an non-static initialization block, sometimes used to avoid duplication + * between constructors. See https://docs.oracle.com/javase/tutorial/java/javaOO/initial.html + * + * Note that non-static init blocks are not recommended to use. There are other ways to avoid duplication + * among constructors. + */ + { + activities = new UniqueActivityList(); + tags = new UniqueTagList(); + } + + public DeskBoard() {} + + /** + * Creates an DeskBoard using the Activities and Tags in the {@code toBeCopied} + */ + public DeskBoard(ReadOnlyDeskBoard toBeCopied) { + this(); + resetData(toBeCopied); + } + + //// list overwrite operations + + public void setActivities(List activities) throws DuplicateActivityException { + this.activities.setActivity(activities); + } + + public void setTags(Set tags) { + this.tags.setTags(tags); + } + + /** + * Resets the existing data of this {@code DeskBoard} with {@code newData}. + */ + public void resetData(ReadOnlyDeskBoard newData) { + requireNonNull(newData); + setTags(new HashSet<>(newData.getTagList())); + List syncedActivityList = newData.getActivityList().stream() + .map(this::syncWithMasterTagList) + .collect(Collectors.toList()); + + try { + setActivities(syncedActivityList); + } catch (DuplicateActivityException e) { + throw new AssertionError("DeskBoard should not have duplicate activities"); + } + } + + //// activity-level operations + + /** + * Adds an activity to the desk board. + * Also checks the new activity's tags and updates {@link #tags} with any new tags found, + * and updates the Tag objects in the activity to point to those in {@link #tags}. + * + * @throws DuplicateActivityException if an equivalent activity already exists. + */ + public void addActivity(Activity p) throws DuplicateActivityException { + Activity activity = syncWithMasterTagList(p); + // TODO: the tags master list will be updated even though the below line fails. + // This can cause the tags master list to have additional tags that are not tagged to any activity + // in the activity list. + activities.add(activity); + } + + /** + * Replaces the given activity {@code target} in the list with {@code editedActivity}. + * {@code DeskBoard}'s tag list will be updated with the tags of {@code editedActivity}. + * + * @throws DuplicateActivityException if updating the activity's details causes the activity to be equivalent to + * another existing activity in the list. + * @throws ActivityNotFoundException if {@code target} could not be found in the list. + * + * @see #syncWithMasterTagList(Activity) + */ + public void updateActivity(Activity target, Activity editedActivity) + throws DuplicateActivityException, ActivityNotFoundException { + requireNonNull(editedActivity); + + Activity syncedEditedActivity = syncWithMasterTagList(editedActivity); + // TODO: the tags master list will be updated even though the below line fails. + // This can cause the tags master list to have additional tags that are not tagged to any activity + // in the activity list. + activities.setActivity(target, syncedEditedActivity); + } + + /** + * Updates the master tag list to include tags in {@code activity} that are not in the list. + * @return a copy of this {@code activity} such that every tag in this activity points to + * a Tag object in the master list. + */ + private Activity syncWithMasterTagList(Activity activity) { + final UniqueTagList activityTags = new UniqueTagList(activity.getTags()); + tags.mergeFrom(activityTags); + + // Create map with values = tag object references in the master list + // used for checking activity tag references + final Map masterTagObjects = new HashMap<>(); + tags.forEach(tag -> masterTagObjects.put(tag, tag)); + + // Rebuild the list of activity tags to point to the relevant tags in the master tag list. + final Set correctTagReferences = new HashSet<>(); + activityTags.forEach(tag -> correctTagReferences.add(masterTagObjects.get(tag))); + return activity.copy(correctTagReferences); + } + + /** + * Removes {@code key} from this {@code DeskBoard}. + * @throws ActivityNotFoundException if the {@code key} is not in this {@code DeskBoard}. + */ + public boolean removeActivity(Activity key) throws ActivityNotFoundException { + if (activities.remove(key)) { + return true; + } else { + throw new ActivityNotFoundException(); + } + } + + //// tag-level operations + + public void addTag(Tag t) throws UniqueTagList.DuplicateTagException { + tags.add(t); + } + + //// util methods + + @Override + public String toString() { + return activities.internalListAsObservable().size() + " activities, " + + tags.internalListAsObservable().size() + " tags"; + // TODO: refine later + } + + @Override + public ObservableList getActivityList() { + return activities.internalListAsObservable(); + } + + + @Override + public ObservableList getTagList() { + return tags.internalListAsObservable(); + } + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof DeskBoard // instanceof handles nulls + && this.activities.equals(((DeskBoard) other).activities) + && this.tags.equalsOrderInsensitive(((DeskBoard) other).tags)); + } + + @Override + public int hashCode() { + // use this method for custom fields hashing instead of implementing your own + return Objects.hash(activities, tags); + } +} +``` +###### \java\seedu\address\model\Model.java +``` java +/** + * The API of the Model component. + */ +public interface Model { + /** {@code Predicate} that always evaluate to true */ + Predicate PREDICATE_SHOW_ALL_ACTIVITY = unused -> true; + + /** Clears existing backing model and replaces with the provided new data. */ + void resetData(ReadOnlyDeskBoard newData); + + /** Returns the DeskBoard */ + ReadOnlyDeskBoard getDeskBoard(); + + /** Deletes the given activity. */ + void deleteActivity(Activity target) throws ActivityNotFoundException; + + /** Adds the given activity */ + void addActivity(Activity activity) throws DuplicateActivityException; + + /** + * Replaces the given activity {@code target} with {@code editedActivity}. + * + * @throws DuplicateActivityException if updating the activity's details causes the activity to be equivalent to + * another existing activity in the list. + * @throws ActivityNotFoundException if {@code target} could not be found in the list. + */ + void updateActivity(Activity target, Activity editedActivity) + throws DuplicateActivityException, ActivityNotFoundException; + + /** Returns an unmodifiable view of the filtered activity list */ + ObservableList getFilteredActivityList(); + +``` +###### \java\seedu\address\model\ModelManager.java +``` java +/** + * Represents the in-memory model of the desk board data. + * All changes to any model should be synchronized. + */ +public class ModelManager extends ComponentManager implements Model { + private static final Logger logger = LogsCenter.getLogger(ModelManager.class); + + private final DeskBoard deskBoard; + private final FilteredList filteredActivities; + /** + * Initializes a ModelManager with the given deskBoard and userPrefs. + */ + public ModelManager(ReadOnlyDeskBoard deskBoard, UserPrefs userPrefs) { + super(); + requireAllNonNull(deskBoard, userPrefs); + + logger.fine("Initializing with desk board: " + deskBoard + " and user prefs " + userPrefs); + + this.deskBoard = new DeskBoard(deskBoard); + filteredActivities = new FilteredList<>(this.deskBoard.getActivityList()); + } + + public ModelManager() { + this(new DeskBoard(), new UserPrefs()); + } + + @Override + public void resetData(ReadOnlyDeskBoard newData) { + deskBoard.resetData(newData); + indicateAddressBookChanged(); + } + + @Override + public ReadOnlyDeskBoard getDeskBoard() { + return deskBoard; + } + + /** Raises an event to indicate the model has changed */ + private void indicateAddressBookChanged() { + raise(new DeskBoardChangedEvent(deskBoard)); + } + + @Override + public synchronized void deleteActivity(Activity target) throws ActivityNotFoundException { + deskBoard.removeActivity(target); + indicateAddressBookChanged(); + } + + @Override + public synchronized void addActivity(Activity activity) throws DuplicateActivityException { + deskBoard.addActivity(activity); + updateFilteredActivityList(PREDICATE_SHOW_ALL_ACTIVITY); + indicateAddressBookChanged(); + } + + @Override + public synchronized void updateActivity(Activity target, Activity editedActivity) + throws DuplicateActivityException, ActivityNotFoundException { + requireAllNonNull(target, editedActivity); + + deskBoard.updateActivity(target, editedActivity); + indicateAddressBookChanged(); + } + + //=========== Filtered Activity List Accessors ============================================================= + + /** + * Returns an unmodifiable view of the list of {@code Activity} backed by the internal list of + * {@code deskBoard} + */ + @Override + public ObservableList getFilteredActivityList() { + return FXCollections.unmodifiableObservableList(filteredActivities); + } + +``` +###### \java\seedu\address\model\ReadOnlyDeskBoard.java +``` java +/** + * Unmodifiable view of an desk board + */ +public interface ReadOnlyDeskBoard { + + /** + * Returns an unmodifiable view of the activities list. + * This list will not contain any duplicate activities.. + */ + ObservableList getActivityList(); + + /** + * Returns an unmodifiable view of the tags list. + * This list will not contain any duplicate tags. + */ + ObservableList getTagList(); + +} +``` diff --git a/collated/functional/jasmoon.md b/collated/functional/jasmoon.md new file mode 100644 index 000000000000..96ef8b1a4722 --- /dev/null +++ b/collated/functional/jasmoon.md @@ -0,0 +1,1019 @@ +# jasmoon +###### \java\seedu\address\commons\core\Messages.java +``` java + public static final String MESSAGE_INVALID_HELP_REQUEST = "Help for '%s' is unknown or not available."; + public static final String MESSAGE_INVALID_LIST_REQUEST = "List for '%s' is invalid"; + +} +``` +###### \java\seedu\address\commons\events\ui\PanelSelectionChangedEvent.java +``` java +package seedu.address.commons.events.ui; + +import seedu.address.commons.events.BaseEvent; + +/** + * Represents a selection change in the Panel + */ +public class PanelSelectionChangedEvent extends BaseEvent { + + + private final Object newSelection; + + public PanelSelectionChangedEvent(Object newSelection) { + this.newSelection = newSelection; + } + + @Override + public String toString() { + return this.getClass().getSimpleName(); + } + + public Object getNewSelection() { + return newSelection; + } + +} +``` +###### \java\seedu\address\logic\commands\HelpCommand.java +``` java + public HelpCommand() { + } + + public HelpCommand(String args) { + commandRequest = args.trim(); + } + + @Override + public CommandResult execute() throws CommandException { + if (commandRequest == null) { + EventsCenter.getInstance().post(new ShowHelpRequestEvent()); + return new CommandResult(SHOWING_HELP_MESSAGE); + } else { + switch(commandRequest) { + + case TaskCommand.COMMAND_WORD: + return new CommandResult(TaskCommand.MESSAGE_USAGE); + + case EventCommand.COMMAND_WORD: + return new CommandResult(EventCommand.MESSAGE_USAGE); + + case CompleteCommand.COMMAND_WORD: + return new CommandResult(CompleteCommand.MESSAGE_USAGE); + + //case EditCommand.COMMAND_WORD: + //return new CommandResult(EditCommand.MESSAGE_USAGE); + + //case SelectCommand.COMMAND_WORD: + //return new CommandResult(SelectCommand.MESSAGE_USAGE); + + case RemoveCommand.COMMAND_WORD: + return new CommandResult(RemoveCommand.MESSAGE_USAGE); + + //case FindCommand.COMMAND_WORD: + //return new CommandResult(FindCommand.MESSAGE_USAGE); + + default: + throw new CommandException(MESSAGE_USAGE); + } + } + } + + +} +``` +###### \java\seedu\address\logic\Logic.java +``` java + /** Returns an unmodifiable view of the filtered list of tasks */ + public ObservableList getFilteredTaskList(); + + /** Returns an unmodifiable view of the filtered list of events*/ + public ObservableList getFilteredEventList(); + +``` +###### \java\seedu\address\logic\LogicManager.java +``` java + public ObservableList getFilteredTaskList() { + return model.getFilteredTaskList(); + } + + public ObservableList getFilteredEventList() { + return model.getFilteredEventList(); + } + + @Override + public ListElementPointer getHistorySnapshot() { + return new ListElementPointer(history.getHistory()); + } +} +``` +###### \java\seedu\address\logic\parser\HelpCommandParser.java +``` java +/** + * Parses input arguments and create a new HelpCommand object. + */ +public class HelpCommandParser implements Parser { + + public final ArrayList availableCommands; + + /** + * HelpCommandParser constructor - creates an ArrayList which contains all commands open to the help function. + */ + public HelpCommandParser() { + availableCommands = new ArrayList<>(); + availableCommands.add(RemoveCommand.COMMAND_WORD); + availableCommands.add(EditCommand.COMMAND_WORD); + availableCommands.add(FindCommand.COMMAND_WORD); + availableCommands.add(SelectCommand.COMMAND_WORD); + availableCommands.add(TaskCommand.COMMAND_WORD); + availableCommands.add(EventCommand.COMMAND_WORD); + availableCommands.add(CompleteCommand.COMMAND_WORD); + availableCommands.add(HelpCommand.COMMAND_WORD); + availableCommands.add(HelpCommand.COMMAND_ALIAS); + } + + /** + * Parses the given {@code String} of arguments in the context of the HelpCommand + * and returns an HelpCommand object for execution. + * @throws ParseException if the user input does not conform the expected format + */ + + public HelpCommand parse(String args) throws ParseException { + + String commandRequest = args.trim(); + if (commandRequest.length() == 0) { + return new HelpCommand(); + } else { + if (availableCommands.contains(commandRequest)) { + return new HelpCommand(args); + } else { + throw new ParseException(String.format(Messages.MESSAGE_INVALID_HELP_REQUEST, commandRequest)); + } + } + } +} +``` +###### \java\seedu\address\logic\parser\ListCommandParser.java +``` java + +/** + * Parses input arguments and create a new ListCommand object. + */ +public class ListCommandParser implements Parser { + + public final ArrayList availableCommands; + + public ListCommandParser() { + availableCommands = new ArrayList(); + availableCommands.add("task"); + availableCommands.add("event"); + } + + /** + * Parses the given {@code String} of arguments in the context of the ListCommand + * and returns an ListCommand object for execution. + * @throws ParseException if the user input does not conform the expected format + */ + public ListCommand parse(String args) throws ParseException { + String commandRequest = args.trim(); + + if (commandRequest.length() == 0) { + return new ListCommand(); + } else { + if (availableCommands.contains(commandRequest)) { + return new ListCommand(commandRequest); + } else { + throw new ParseException(String.format(Messages.MESSAGE_INVALID_LIST_REQUEST, commandRequest)); + } + } + } + +} +``` +###### \java\seedu\address\model\activity\UniqueActivityList.java +``` java + } else { + internalList.remove(toRemove); + } + return activityFoundAndDeleted; + } + + /** + * Returns the backing list as an unmodifiable {@code ObservableList}. + */ + public ObservableList internalListAsObservable() { + return FXCollections.unmodifiableObservableList(internalList); + } + + + + @Override + public Iterator iterator() { + return internalList.iterator(); + } + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof UniqueActivityList // instanceof handles nulls + && this.internalList.equals(((UniqueActivityList) other).internalList)); + } + + @Override + public int hashCode() { + return internalList.hashCode(); + } +} +``` +###### \java\seedu\address\model\Model.java +``` java + /** Returns an unmodifiable view of the filtered task list */ + ObservableList getFilteredTaskList(); + + /** Returns an unmodifiable view of the filtered event list */ + ObservableList getFilteredEventList(); + + /** + * Updates the filter of the filtered activity list to filter by the given {@code predicate}. + * @throws NullPointerException if {@code predicate} is null. + */ + void updateFilteredActivityList(Predicate predicate); + +} +``` +###### \java\seedu\address\model\ModelManager.java +``` java + /** + * Returns an unmodifiable view of the list of {@code Task} backed by the task list of + * {@code deskBoard} + */ + @Override + public ObservableList getFilteredTaskList() { + FilteredList taskList = new FilteredList<>(filteredActivities, new TaskOnlyPredicate()); + ObservableList result = FXCollections.unmodifiableObservableList(taskList); + return result; + } + + /** + * Returns an unmodifiable view of the list of {@code Event} backed by the event list of + * {@code deskBoard} + */ + @Override + public ObservableList getFilteredEventList() { + FilteredList eventList = new FilteredList<>(filteredActivities, new EventOnlyPredicate()); + ObservableList result = FXCollections.unmodifiableObservableList(eventList); + return result; + } + + @Override + public void updateFilteredActivityList(Predicate predicate) { + requireNonNull(predicate); + filteredActivities.setPredicate(predicate); + } + + @Override + public boolean equals(Object obj) { + // short circuit if same object + if (obj == this) { + return true; + } + + // instanceof handles nulls + if (!(obj instanceof ModelManager)) { + return false; + } + + // state check + ModelManager other = (ModelManager) obj; + return deskBoard.equals(other.deskBoard) + && filteredActivities.equals(other.filteredActivities); + } + +} +``` +###### \java\seedu\address\ui\EventListPanel.java +``` java +package seedu.address.ui; + +import java.util.logging.Logger; + +import org.fxmisc.easybind.EasyBind; + +import com.google.common.eventbus.Subscribe; + +import javafx.application.Platform; +import javafx.collections.ObservableList; +import javafx.fxml.FXML; +import javafx.scene.control.Label; +import javafx.scene.control.ListCell; +import javafx.scene.control.ListView; +import javafx.scene.input.MouseEvent; +import javafx.scene.layout.Region; +import seedu.address.commons.core.LogsCenter; +import seedu.address.commons.events.ui.DeselectListCellEvent; +import seedu.address.commons.events.ui.JumpToListRequestEvent; +import seedu.address.commons.events.ui.PanelSelectionChangedEvent; +import seedu.address.model.activity.Activity; + +/** + * Panel containing the list of events. + */ +public class EventListPanel extends UiPart { + private static final String FXML = "EventListPanel.fxml"; + private final Logger logger = LogsCenter.getLogger(EventListPanel.class); + + @FXML + private ListView eventListView; + + private Label emptyLabel = new Label("Event List is empty!"); + + public EventListPanel(ObservableList eventList) { + super(FXML); + setConnections(eventList); + registerAsAnEventHandler(this); + setUpPlaceHolder(); + //maybe do not need this + //eventListView.managedProperty().bind(eventListView.visibleProperty()); + } + + private void setConnections(ObservableList eventList) { + ObservableList mappedList = EasyBind.map( + eventList, (event) -> new EventCard(event, eventList.indexOf(event) + 1)); + eventListView.setItems(mappedList); + linkCell(); + setEventHandlerForSelectionChangeEvent(); + } + + private void setUpPlaceHolder() { + eventListView.setPlaceholder(emptyLabel); + emptyLabel.setStyle("-fx-font-family: \"Open Sans\"; -fx-font-size: 25px; "); + } + + /** + * Links eventListView to eventListViewCell as its custom ListCell + */ + private void linkCell() { + eventListView.setCellFactory(listView -> { + EventListViewCell cell = new EventListViewCell(); + cell.addEventFilter(MouseEvent.MOUSE_PRESSED, event -> { + eventListView.requestFocus(); + if (!cell.isEmpty()) { + int index = cell.getIndex(); + if (eventListView.getSelectionModel().getSelectedIndices().contains(index)) { + logger.fine("Selection in event list panel with index '" + index + + "' has been deselected"); + raise(new DeselectListCellEvent(eventListView, index)); + } else { + eventListView.getSelectionModel().select(index); + } + event.consume(); + } + }); + return cell; + }); + } + + private void setEventHandlerForSelectionChangeEvent() { + eventListView.getSelectionModel().selectedItemProperty() + .addListener((observable, oldValue, newValue) -> { + if (newValue != null) { + logger.fine("Selection in event list panel changed to : '" + newValue + "'"); + raise(new PanelSelectionChangedEvent(newValue)); + } + }); + } + + /** + * Scrolls to the {@code EventCard} at the {@code index} and selects it. + */ + private void scrollTo(int index) { + Platform.runLater(() -> { + eventListView.scrollTo(index); + eventListView.getSelectionModel().clearAndSelect(index); + }); + } + + @Subscribe + private void handleJumpToListRequestEvent(JumpToListRequestEvent event) { + logger.info(LogsCenter.getEventHandlingLogMessage(event)); + scrollTo(event.targetIndex); + } + + /** + * Custom {@code ListCell} that displays the graphics of a {@code EventCard}. + */ + class EventListViewCell extends ListCell { + + @Override + protected void updateItem(EventCard event, boolean empty) { + super.updateItem(event, empty); + + if (empty || event == null) { + setGraphic(null); + setText(null); + } else { + setGraphic(event.getRoot()); + } + } + } + +``` +###### \java\seedu\address\ui\EventListPanel.java +``` java + /** + * Getter method for eventListView + * @return eventListView + */ + public ListView getEventListView() { + return eventListView; + } +} +``` +###### \java\seedu\address\ui\MainWindow.java +``` java + taskListPanel = new TaskListPanel(logic.getFilteredTaskList()); + taskListPanelPlaceholder.getChildren().add(taskListPanel.getRoot()); + + eventListPanel = new EventListPanel(logic.getFilteredEventList()); + eventListPanelPlaceholder.getChildren().add(eventListPanel.getRoot()); + +``` +###### \java\seedu\address\ui\MainWindow.java +``` java + @Subscribe + private void handleShowActivityRequestEvent(ShowActivityRequestEvent event) { + logger.info(LogsCenter.getEventHandlingLogMessage(event)); + taskListPanel.getTaskListView().setVisible(true); + eventListPanel.getEventListView().setVisible(true); + } + + @Subscribe + private void handleShowEventOnlyRequestEvent(ShowEventOnlyRequestEvent event) { + logger.info(LogsCenter.getEventHandlingLogMessage(event)); + taskListPanel.getTaskListView().setVisible(false); + eventListPanel.getEventListView().setVisible(true); + } + + @Subscribe + private void handleShowTaskOnlyRequestEvent(ShowTaskOnlyRequestEvent event) { + logger.info(LogsCenter.getEventHandlingLogMessage(event)); + taskListPanel.getTaskListView().setVisible(true); + eventListPanel.getEventListView().setVisible(false); + } +} +``` +###### \java\seedu\address\ui\TaskCard.java +``` java +package seedu.address.ui; + +import static seedu.address.ui.util.DateTimeUtil.getDisplayedDateTime; + +import javafx.fxml.FXML; +import javafx.scene.control.Label; +import javafx.scene.layout.FlowPane; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Region; +import seedu.address.model.activity.Activity; +import seedu.address.model.activity.Task; + +/** + * An UI component that displays information of a {@code Task}. + */ +public class TaskCard extends UiPart { + + private static final String FXML = "TaskListCard.fxml"; + + public final Task task; + + @FXML + private HBox cardPane; + @FXML + private Label name; + @FXML + private Label id; + @FXML + private Label dateTime; + @FXML + private Label remark; + @FXML + private FlowPane tags; + @FXML + private FlowPane status; + + public TaskCard(Activity task, int displayedIndex) { + super(FXML); + this.task = (Task) task; + id.setText(displayedIndex + ". "); + name.setText(this.task.getName().fullName); + dateTime.setText(getDisplayedDateTime(this.task)); + remark.setText(this.task.getRemark().value); + task.getTags().forEach(tag -> tags.getChildren().add(new Label(tag.tagName))); + if (task.isCompleted()) { + status.getChildren().add(new Label("Completed")); + } else { + status.getChildren().add(new Label("Uncompleted")); + } + } + + @Override + public boolean equals(Object other) { + // short circuit if same object + if (other == this) { + return true; + } + + // instanceof handles nulls + if (!(other instanceof TaskCard)) { + return false; + } + + // state check + TaskCard card = (TaskCard) other; + return id.getText().equals(card.id.getText()) + && task.equals(card.task); + } +} +``` +###### \java\seedu\address\ui\TaskListPanel.java +``` java +package seedu.address.ui; + +import java.util.logging.Logger; + +import org.fxmisc.easybind.EasyBind; + +import com.google.common.eventbus.Subscribe; + +import javafx.application.Platform; +import javafx.collections.ObservableList; +import javafx.fxml.FXML; +import javafx.scene.control.Label; +import javafx.scene.control.ListCell; +import javafx.scene.control.ListView; +import javafx.scene.input.MouseEvent; +import javafx.scene.layout.Region; +import seedu.address.commons.core.LogsCenter; +import seedu.address.commons.events.ui.DeselectListCellTask; +import seedu.address.commons.events.ui.JumpToListRequestEvent; +import seedu.address.commons.events.ui.PanelSelectionChangedEvent; +import seedu.address.model.activity.Activity; + +/** + * Panel containing the list of activities. + */ +public class TaskListPanel extends UiPart { + private static final String FXML = "TaskListPanel.fxml"; + private final Logger logger = LogsCenter.getLogger(TaskListPanel.class); + + @FXML + private ListView taskListView; + + private Label emptyLabel = new Label("Task List is empty!"); + + public TaskListPanel(ObservableList taskList) { + super(FXML); + setConnections(taskList); + registerAsAnEventHandler(this); + setUpPlaceholder(); + } + + private void setUpPlaceholder() { + taskListView.setPlaceholder(emptyLabel); + emptyLabel.setStyle("-fx-font-family: \"Open Sans\"; -fx-font-size: 25px; "); + } + + private void setConnections(ObservableList taskList) { + ObservableList mappedList = EasyBind.map( + taskList, (activity) -> new TaskCard(activity, taskList.indexOf(activity) + 1)); + taskListView.setItems(mappedList); + linkCell(); + setEventHandlerForSelectionChangeEvent(); + } + + /** + * Links taskListView to taskListViewCell as its custom ListCell + */ + private void linkCell() { + taskListView.setCellFactory(listView -> { + TaskListViewCell cell = new TaskListViewCell(); + cell.addEventFilter(MouseEvent.MOUSE_PRESSED, event -> { + taskListView.requestFocus(); + if (!cell.isEmpty()) { + int index = cell.getIndex(); + if (taskListView.getSelectionModel().getSelectedIndices().contains(index)) { + logger.fine("Selection in task list panel with index '" + index + + "' has been deselected"); + raise(new DeselectListCellTask(taskListView, index)); + } else { + taskListView.getSelectionModel().select(index); + } + event.consume(); + } + }); + return cell; + }); + } + + private void setEventHandlerForSelectionChangeEvent() { + taskListView.getSelectionModel().selectedItemProperty() + .addListener((observable, oldValue, newValue) -> { + if (newValue != null) { + logger.fine("Selection in task list panel changed to : '" + newValue + "'"); + raise(new PanelSelectionChangedEvent(newValue)); + } + }); + } + + /** + * Scrolls to the {@code TaskCard} at the {@code index} and selects it. + */ + private void scrollTo(int index) { + Platform.runLater(() -> { + taskListView.scrollTo(index); + taskListView.getSelectionModel().clearAndSelect(index); + }); + } + + @Subscribe + private void handleJumpToListRequestEvent(JumpToListRequestEvent event) { + logger.info(LogsCenter.getEventHandlingLogMessage(event)); + scrollTo(event.targetIndex); + } + + + + /** + * Custom {@code ListCell} that displays the graphics of a {@code TaskCard}. + */ + class TaskListViewCell extends ListCell { + + @Override + protected void updateItem(TaskCard activity, boolean empty) { + super.updateItem(activity, empty); + + if (empty || activity == null) { + setGraphic(null); + setText(null); + } else { + setGraphic(activity.getRoot()); + } + } + } + +``` +###### \java\seedu\address\ui\TaskListPanel.java +``` java + /** + * Getter method for taskListView + * @return taskListView + */ + public ListView getTaskListView() { + return taskListView; + } +} +``` +###### \resources\view\ClindarStyler.css +``` css +@font-face { + font-family: 'Open Sans Bold Italic'; + src: url('../fonts/open-sans/OpenSans-BoldItalic.ttf'); +} + +@font-face { + font-family: 'Open Sans Italic'; + src: url('../fonts/open-sans/OpenSans-Italic.ttf'); +} + +@font-face { + font-family: 'Open Sans'; + src: url('../fonts/open-sans/OpenSans-Regular.ttf'); +} + +@font-face { + font-family: 'Arvo'; + src: url('../fonts/arvo/Arvo-Regular.ttf'); +} + +@font-face { + font-family: 'Arvo Bold'; + src: url('../fonts/arvo/Arvo-Bold.ttf'); +} + +/* menu bar*/ +.menu-bar { + -fx-background-color: #f7e399; + -fx-padding: 0 2 0 2; + -fx-border-width: 0 0 2 0; + -fx-border-color: #dbdad9; +} + +.menu-bar .label { + -fx-font-size: 11pt; + -fx-font-family: "Segoe UI Light"; + -fx-text-fill: black; +} + +.context-menu { + -fx-background-color: #ffd177; + -fx-border-width: 2 0 0 0; + -fx-border-color: #969594; +} + +/* taskList and eventList */ + +.list-view { + -fx-background-color: transparent; + -fx-border-insets: 2 2 2 2; + -fx-background-insets: 2 2 2 2; + -fx-focus-color: transparent; + -fx-faint-focus-color: transparent; +} + +.list-cell:empty { + -fx-background-color: transparent; + -fx-border-color: transparent; +} + +.list-cell:filled:hover { + -fx-border-width: 1 1 1 1; + -fx-border-color: #2dc6c6; + -fx-border-insets: 0 0 0 1; + -fx-background-insets: 0 0 0 1; +} + +#taskListView .list-cell:filled:even { + -fx-background: linear-gradient(to right, #e8e8e8 0%, #e8e8e8 82.5%, #b2eaff 82.5%, #b2eaff 100%); +} + +#taskListView .list-cell:filled:odd { + -fx-background: linear-gradient(to right, #d1d1d1 0%, #d1d1d1 82.5%, #8ccef2 82.5%, #8ccef2 100%); +} + +#eventListView .list-cell:filled:even { + -fx-background: linear-gradient(to right, #e8e8e8 0%, #e8e8e8 82.5%, #ffd6d8 82.5%, #ffd6d8 100%); +} + +#eventListView .list-cell:filled:odd { + -fx-background: linear-gradient(to right, #d1d1d1 0%, #d1d1d1 82.5%, #ffb2b5 82.5%, #ffb2b5 100%); +} + +.list-cell .label { + -fx-text-fill: black; +} + +.cell_big_label { + -fx-font-family: "Open Sans Bold Italic"; + -fx-font-size: 14pt; + -fx-text-fill: #010504; +} + +.cell_small_label { + -fx-font-family: "Open Sans Italic"; + -fx-font-size: 10pt; + -fx-text-fill: #010504; +} + +#tags { + -fx-hgap: 7; + -fx-vgap: 3; +} + +#tags .label { + -fx-font-family: "Open Sans"; + -fx-text-fill: white; + -fx-background-color: #854c99; + -fx-padding: 1 3 1 3; + -fx-border-radius: 2; + -fx-background-radius: 2; + -fx-font-size: 11; +} + +.scroll-bar .thumb { + -fx-background-color: linear-gradient(to right, #f4f4f4, #bcbcbc); + -fx-background-insets: 2; +} + +.scroll-bar .increment-button, .scroll-bar .decrement-button { + -fx-background-color: transparent; + -fx-padding: 0 0 0 0; +} + +.scroll-bar .increment-arrow, .scroll-bar .decrement-arrow { + -fx-shape: "|"; +} + +.scroll-bar:vertical .increment-arrow, .scroll-bar:vertical .decrement-arrow { + -fx-padding: 1 8 1 8; +} + +.scroll-bar:horizontal .increment-arrow, .scroll-bar:horizontal .decrement-arrow { + -fx-padding: 8 1 8 1; +} + +/* resultBox */ +.text-area { + -fx-text-fill: black; +} + +#resultBox { + -fx-background-color: transparent; + -fx-opacity: 0.45; + -fx-background-radius: 2px 2px 2px 2px; +} + +/* commandBox */ + +#commandBoxPlaceholder { + -fx-background-color: white; + -fx-opacity: 0.45; + -fx-background-radius: 4px 4px 4px 4px; +} + +.text-field { + -fx-background-color: transparent; + -fx-border-width: 1 1 1 1; + -fx-border-color: grey; + -fx-border-radius: 4px 4px 4px 4px; + -fx-prompt-text-fill: black; + -fx-text-fill: black; +} + +/* statusBar */ + +#statusBarPlaceholder { + -fx-background-color: #f7e399 /*silver #d8d7d0*/; + -fx-font-color: black; + -fx-border-width: 1 0 0 0; + -fx-border-color: #dbdad9; + +} + +.status-bar .label { + -fx-font-family: "Segoe UI Light"; + -fx-text-fill: black; +} + +.grid-pane .anchor-pane { + -fx-background-color: #f7e399; + -fx-border-width: 1 0 0 0; + -fx-border-color: #dbdad9; +} + +/* miscs */ +.background { + -fx-background-image: url("../images/light-veneer.png"); + -fx-background-repeat: repeat; +} + +.split-pane-divider { + -fx-background-color: transparent; +} +``` +###### \resources\view\EventListCard.fxml +``` fxml + + + + + + + + + + + + + + + + +``` +###### \resources\view\EventListPanel.fxml +``` fxml + + + + +``` +###### \resources\view\MainWindow.fxml +``` fxml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` +###### \resources\view\TaskListCard.fxml +``` fxml + + + + + + + + + + + + + + + + + +``` +###### \resources\view\TaskListPanel.fxml +``` fxml + + + + +``` diff --git a/collated/functional/karenfrilya97.md b/collated/functional/karenfrilya97.md new file mode 100644 index 000000000000..98cc704897cc --- /dev/null +++ b/collated/functional/karenfrilya97.md @@ -0,0 +1,447 @@ +# karenfrilya97 +###### \java\seedu\address\model\activity\UniqueActivityList.java +``` java + private static Comparator dateTimeComparator = new Comparator() { + public int compare (Activity o1, Activity o2) { + DateTime dt1 = o1.getDateTime(); + DateTime dt2 = o2.getDateTime(); + return dt1.getLocalDateTime().compareTo(dt2.getLocalDateTime()); + } + }; + + private final ObservableList internalList = FXCollections.observableArrayList(); + + /** + * Returns true if the list contains an equivalent activity as the given argument. + */ + public boolean contains(Activity toCheck) { + requireNonNull(toCheck); + return internalList.contains(toCheck); + } + + + /** + * Adds a activity to the list. + * If activity is a task or an event, is added to its respective list. + * + * @throws DuplicateActivityException if the activity to add is a duplicate of an existing activity in the list. + */ + public void add(Activity toAdd) throws DuplicateActivityException { + requireNonNull(toAdd); + if (contains(toAdd)) { + throw new DuplicateActivityException(); + } + internalList.add(toAdd); +``` +###### \java\seedu\address\model\activity\UniqueActivityList.java +``` java + Collections.sort(internalList, dateTimeComparator); + } + + /** + * Replaces the activity {@code target} in the list with {@code editedActivity}. + * If activity is a task or an event, edited in its respective list. + * + * @throws DuplicateActivityException if the replacement is equivalent to another existing activity in the list. + * @throws ActivityNotFoundException if {@code target} could not be found in the list. + */ + public void setActivity(Activity target, Activity editedActivity) + throws DuplicateActivityException, ActivityNotFoundException { + requireNonNull(editedActivity); + + int index = internalList.indexOf(target); + int taskIndex; + int eventIndex; + + if (index == -1) { + throw new ActivityNotFoundException(); + } + + if (!target.equals(editedActivity) && internalList.contains(editedActivity)) { + throw new DuplicateActivityException(); + } + + internalList.set(index, editedActivity); + + } + + public void setActivity(UniqueActivityList replacement) { + this.internalList.setAll(replacement.internalList); + } + + public void setActivity(List activities) throws DuplicateActivityException { + requireAllNonNull(activities); + final UniqueActivityList replacement = new UniqueActivityList(); + for (final Activity activity : activities) { + replacement.add(activity); + } + setActivity(replacement); + } + + /** + * Removes the equivalent activity from the list and its respective task or event list. + * + * @throws ActivityNotFoundException if no such activity could be found in the list. + */ + public boolean remove(Activity toRemove) throws ActivityNotFoundException { + requireNonNull(toRemove); + final boolean activityFoundAndDeleted = internalList.remove(toRemove); + if (!activityFoundAndDeleted) { + throw new ActivityNotFoundException(); +``` +###### \java\seedu\address\storage\XmlAdaptedActivity.java +``` java +/** + * JAXB-friendly version of the Activity. + */ +public abstract class XmlAdaptedActivity { + + public static final String MISSING_FIELD_MESSAGE_FORMAT = "%s's %s field is missing!"; + + @XmlElement(required = true) + protected String name; + @XmlElement(required = true) + protected String dateTime; + @XmlElement(required = true) + protected String remark; + @XmlElement + protected boolean iscompleted; + @XmlElement + protected List tagged = new ArrayList<>(); + + /** + * Constructs an XmlAdaptedActivity. + * This is the no-arg constructor that is required by JAXB. + */ + public XmlAdaptedActivity() {} + + /** + * Constructs an {@code XmlAdaptedActivity} with the given activity details. + */ + public XmlAdaptedActivity(String name, String dateTime, String remark, List tagged) { + this.name = name; + this.dateTime = dateTime; + this.remark = remark; + if (tagged != null) { + this.tagged = new ArrayList<>(tagged); + } + iscompleted = false; + } + + /** + * Converts a given Activity into this class for JAXB use. + * + * @param source future changes to this will not affect the created XmlAdaptedActivity + */ + public XmlAdaptedActivity(Activity source) { + name = source.getName().fullName; + dateTime = source.getDateTime().toString(); + remark = source.getRemark().value; + tagged = new ArrayList<>(); + for (Tag tag : source.getTags()) { + tagged.add(new XmlAdaptedTag(tag)); + } + iscompleted = source.isCompleted(); + } + + /** + * Converts this jaxb-friendly adapted activity object into the model's Activity object. + * + * @throws IllegalValueException if there were any data constraints violated in the adapted activity + */ + public abstract Activity toModelType() throws IllegalValueException; + + public abstract String getActivityType(); + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + + if (!(other instanceof XmlAdaptedActivity)) { + return false; + } + + XmlAdaptedActivity otherActivity = (XmlAdaptedActivity) other; + return Objects.equals(name, otherActivity.name) + && Objects.equals(dateTime, otherActivity.dateTime) + && Objects.equals(remark, otherActivity.remark) + && tagged.equals(otherActivity.tagged) + && this.iscompleted == otherActivity.iscompleted; + } +} +``` +###### \java\seedu\address\storage\XmlAdaptedEvent.java +``` java +/** + * JAXB-friendly version of the Event. + */ +public class XmlAdaptedEvent extends XmlAdaptedActivity { + + private static final String ACTIVITY_TYPE = "Event"; + + @XmlElement(required = true) + private String endDateTime; + @XmlElement(required = true) + private String location; + + /** + * Constructs an XmlAdaptedEvent. + * This is the no-arg constructor that is required by JAXB. + */ + public XmlAdaptedEvent() {} + + /** + * Constructs an {@code XmlAdaptedEvent} with the given event details. + */ + public XmlAdaptedEvent(String name, String startDateTime, String endDateTime, + String location, String remark, List tagged) { + super(name, startDateTime, remark, tagged); + this.endDateTime = endDateTime; + this.location = location; + } + + /** + * Converts a given Event into this class for JAXB use. + * + * @param source future changes to this will not affect the created XmlAdaptedEvent + */ + public XmlAdaptedEvent(Event source) { + super((Activity) source); + endDateTime = source.getEndDateTime().toString(); + location = source.getLocation().toString(); + } + + /** + * Converts this jaxb-friendly adapted Event object into the model's Event object. + * + * @throws IllegalValueException if there were any data constraints violated in the adapted ectivity + */ + @Override + public Event toModelType() throws IllegalValueException { + final List personTags = new ArrayList<>(); + for (XmlAdaptedTag tag : tagged) { + personTags.add(tag.toModelType()); + } + + if (this.name == null) { + throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, + getActivityType(), "name")); + } + if (!Name.isValidName(this.name)) { + throw new IllegalValueException(Name.MESSAGE_NAME_CONSTRAINTS); + } + final Name name = new Name(this.name); + + if (this.dateTime == null) { + throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, + getActivityType(), "start date/time")); + } + if (!DateTime.isValidDateTime(this.dateTime)) { + throw new IllegalValueException(DateTime.MESSAGE_DATETIME_CONSTRAINTS); + } + final DateTime startDateTime = new DateTime(this.dateTime); + + if (this.endDateTime == null) { + throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, + getActivityType(), "end date/time")); + } + if (!DateTime.isValidDateTime(this.endDateTime)) { + throw new IllegalValueException(DateTime.MESSAGE_DATETIME_CONSTRAINTS); + } + final DateTime endDateTime = new DateTime(this.endDateTime); + + if (!Location.isValidLocation(this.location)) { + throw new IllegalValueException(Location.MESSAGE_LOCATION_CONSTRAINTS); + } + final Location location = new Location(this.location); + + if (!Remark.isValidRemark(this.remark)) { + throw new IllegalValueException(Remark.MESSAGE_REMARK_CONSTRAINTS); + } + final Remark remark = new Remark(this.remark); + + final Set tags = new HashSet<>(personTags); + return new Event(name, startDateTime, endDateTime, location, remark, tags, this.iscompleted); + } + + @Override + public String getActivityType() { + return ACTIVITY_TYPE; + } + + @Override + public boolean equals(Object other) { + if (!super.equals(other)) { + return false; + } + + if (!(other instanceof XmlAdaptedEvent)) { + return false; + } + + XmlAdaptedEvent otherEvent = (XmlAdaptedEvent) other; + return Objects.equals(endDateTime, otherEvent.endDateTime) + && Objects.equals(location, otherEvent.location); + } + +} +``` +###### \java\seedu\address\storage\XmlAdaptedTask.java +``` java +/** + * JAXB-friendly version of the Task. + */ +public class XmlAdaptedTask extends XmlAdaptedActivity { + + private static final String ACTIVITY_TYPE = "Task"; + + /** + * Constructs an XmlAdaptedTask. + * This is the no-arg constructor that is required by JAXB. + */ + public XmlAdaptedTask() {} + + /** + * Constructs an {@code XmlAdaptedTask} with the given task details. + */ + public XmlAdaptedTask(String name, String dueDateTime, String remark, List tagged) { + super(name, dueDateTime, remark, tagged); + } + + /** + * Converts a given Task into this class for JAXB use. + * + * @param source future changes to this will not affect the created XmlAdaptedTask + */ + public XmlAdaptedTask(Task source) { + super(source); + } + + /** + * Converts this jaxb-friendly adapted Task object into the model's Task object. + * + * @throws IllegalValueException if there were any data constraints violated in the adapted task + */ + public Task toModelType() throws IllegalValueException { + final List personTags = new ArrayList<>(); + for (XmlAdaptedTag tag : tagged) { + personTags.add(tag.toModelType()); + } + + if (this.name == null) { + throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, + getActivityType(), "name")); + } + if (!Name.isValidName(this.name)) { + throw new IllegalValueException(Name.MESSAGE_NAME_CONSTRAINTS); + } + final Name name = new Name(this.name); + + if (this.dateTime == null) { + throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, + getActivityType(), "due date/time")); + } + if (!DateTime.isValidDateTime(this.dateTime)) { + throw new IllegalValueException(DateTime.MESSAGE_DATETIME_CONSTRAINTS); + } + final DateTime dateTime = new DateTime(this.dateTime); + + if (!Remark.isValidRemark(this.remark)) { + throw new IllegalValueException(Remark.MESSAGE_REMARK_CONSTRAINTS); + } + final Remark remark = new Remark(this.remark); + + final Set tags = new HashSet<>(personTags); + + return new Task(name, dateTime, remark, tags, this.iscompleted); + } + + @Override + public String getActivityType() { + return ACTIVITY_TYPE; + } + + @Override + public boolean equals(Object other) { + return super.equals(other) && other instanceof XmlAdaptedTask; + } + +} +``` +###### \java\seedu\address\storage\XmlSerializableDeskBoard.java +``` java +/** + * An Immutable DeskBoard that is serializable to XML format + */ +@XmlRootElement(name = "deskboard") +public class XmlSerializableDeskBoard { + + @XmlElement + private List tasks; + @XmlElement + private List events; + @XmlElement + private List tags; + + /** + * Creates an empty XmlSerializableDeskBoard. + * This empty constructor is required for marshalling. + */ + public XmlSerializableDeskBoard() { + tasks = new ArrayList<>(); + events = new ArrayList<>(); + tags = new ArrayList<>(); + } + + /** + * Conversion + */ + public XmlSerializableDeskBoard(ReadOnlyDeskBoard src) { + this(); + for (Activity activity : src.getActivityList()) { + if (activity instanceof Task) { + tasks.add(new XmlAdaptedTask((Task) activity)); + } else if (activity instanceof Event) { + events.add(new XmlAdaptedEvent((Event) activity)); + } + } + tags.addAll(src.getTagList().stream().map(XmlAdaptedTag::new).collect(Collectors.toList())); + } + + /** + * Converts this addressbook into the model's {@code DeskBoard} object. + * + * @throws IllegalValueException if there were any data constraints violated or duplicates in the + * {@code XmlAdaptedActivity} or {@code XmlAdaptedTag}. + */ + public DeskBoard toModelType() throws IllegalValueException { + DeskBoard deskBoard = new DeskBoard(); + for (XmlAdaptedTag t : tags) { + deskBoard.addTag(t.toModelType()); + } + for (XmlAdaptedActivity a : tasks) { + deskBoard.addActivity(((XmlAdaptedTask) a).toModelType()); + } + for (XmlAdaptedActivity e : events) { + deskBoard.addActivity(((XmlAdaptedEvent) e).toModelType()); + } + return deskBoard; + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + + if (!(other instanceof XmlSerializableDeskBoard)) { + return false; + } + + XmlSerializableDeskBoard otherDb = (XmlSerializableDeskBoard) other; + return tasks.equals(otherDb.tasks) && events.equals(otherDb.events) && tags.equals(otherDb.tags); + } +} +``` diff --git a/collated/test/Kyomian.md b/collated/test/Kyomian.md new file mode 100644 index 000000000000..8dd408315961 --- /dev/null +++ b/collated/test/Kyomian.md @@ -0,0 +1,721 @@ +# Kyomian +###### \java\seedu\address\logic\commands\CommandTestUtil.java +``` java + public static final String VALID_TAG_URGENT = "Urgent"; + +``` +###### \java\seedu\address\logic\commands\CommandTestUtil.java +``` java + public static final String TAG_DESC_URGENT = " " + PREFIX_TAG + VALID_TAG_URGENT; + + public static final String INVALID_TASK_NAME_DESC = " " + PREFIX_NAME + "CS2106 Assignment&"; // '&' not allowed + public static final String INVALID_TASK_DATE_TIME_DESC = " " + PREFIX_DATE_TIME + "2018-03-04 17:00"; + public static final String INVALID_TASK_REMARK_DESC = " " + PREFIX_REMARK + "$"; // '$' not allowed + public static final String INVALID_TASK_TAG_DESC = " " + PREFIX_TAG + "CS2106*"; // '*' not allowed in tags + + // ============================= EVENT ============================================= + //TODO: Tedious + +``` +###### \java\seedu\address\logic\commands\CommandTestUtil.java +``` java + /** + * Removes the first activity in {@code model}'s filtered list from {@code model}'s desk board. + */ + public static void removeFirstActivity(Model model) { + Activity firstActivity = model.getFilteredActivityList().get(0); + try { + model.deleteActivity(firstActivity); + } catch (ActivityNotFoundException pnfe) { + throw new AssertionError("Activity in filtered list must exist in model.", pnfe); + } + } + +``` +###### \java\seedu\address\logic\commands\EventCommandIntegrationTest.java +``` java +/** + * Contains integration tests (interaction with the Model) for {@code EventCommand}. + */ +public class EventCommandIntegrationTest { + + private Model model; + + @Before + public void setUp() { + model = new ModelManager(getTypicalDeskBoard(), new UserPrefs()); + } + + @Test + public void execute_newEvent_success() throws Exception { + Event validEvent = new EventBuilder().build(); + + Model expectedModel = new ModelManager(model.getDeskBoard(), new UserPrefs()); + expectedModel.addActivity(validEvent); + + assertCommandSuccess(prepareCommand(validEvent, model), model, + String.format(EventCommand.MESSAGE_SUCCESS, validEvent), expectedModel); + } + + @Test + // Questionable - does the app check for duplicate? + public void execute_duplicateEvent_throwsCommandException() { + Activity activityInList = model.getDeskBoard().getActivityList().get(0); + assertCommandFailure(prepareCommand((Event) activityInList, model), model, + EventCommand.MESSAGE_DUPLICATE_EVENT); + } + + /** + * Generates a new {@code EventCommand} which upon execution, adds {@code event} into the {@code model}. + */ + private EventCommand prepareCommand(Event event, Model model) { + EventCommand command = new EventCommand(event); + command.setData(model, new CommandHistory(), new UndoRedoStack()); + return command; + } +} +``` +###### \java\seedu\address\logic\commands\EventCommandTest.java +``` java +public class EventCommandTest { + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Test + public void constructor_nullEvent_throwsNullPointerException() { + thrown.expect(NullPointerException.class); + new EventCommand(null); + } + + @Test + public void execute_eventAcceptedByModel_addSuccessful() throws Exception { + ModelStubAcceptingEventAdded modelStub = new ModelStubAcceptingEventAdded(); + Event validEvent = new EventBuilder().build(); + + CommandResult commandResult = getEventCommandForGivenEvent(validEvent, modelStub).execute(); + + assertEquals(String.format(EventCommand.MESSAGE_SUCCESS, validEvent), commandResult.feedbackToUser); + assertEquals(Arrays.asList(validEvent), modelStub.eventsAdded); + } + + @Test + public void execute_duplicateEvent_throwsCommandException() throws Exception { + ModelStub modelStub = new ModelStubThrowingDuplicateActivityException(); + Event validEvent = new EventBuilder().build(); + + thrown.expect(CommandException.class); + thrown.expectMessage(EventCommand.MESSAGE_DUPLICATE_EVENT); + + getEventCommandForGivenEvent(validEvent, modelStub).execute(); + } + + @Test + public void equals() { + Event cip = new EventBuilder().build(); + Event cca = new EventBuilder().withName("CCA").build(); + EventCommand addCipCommand = new EventCommand(cip); + EventCommand addCcaCommand = new EventCommand(cca); + + // same object -> returns true + assertTrue(addCipCommand.equals(addCipCommand)); + + // same values -> returns true + EventCommand addAssignmentCommandCopy = new EventCommand(cip); + assertTrue(addCipCommand.equals(addAssignmentCommandCopy)); + + // different types -> returns false + assertFalse(addCipCommand.equals(1)); + + // null -> returns false + assertFalse(addCipCommand.equals(null)); + + // different activity -> returns false + assertFalse(addCipCommand.equals(addCcaCommand)); + } + + /** + * Generates a new EventCommand with the details of the given event. + */ + private EventCommand getEventCommandForGivenEvent(Event event, Model model) { + EventCommand command = new EventCommand(event); + command.setData(model, new CommandHistory(), new UndoRedoStack()); + return command; + } + + /** + * A default model stub that have all of the methods failing. + */ + private class ModelStub implements Model { + @Override + public void addActivity(Activity activity) throws DuplicateActivityException { + fail("This method should not be called."); + } + + @Override + public void resetData(ReadOnlyDeskBoard newData) { + fail("This method should not be called."); + } + + @Override + public ReadOnlyDeskBoard getDeskBoard() { + fail("This method should not be called."); + return null; + } + + @Override + public void deleteActivity(Activity target) throws ActivityNotFoundException { + fail("This method should not be called."); + } + + @Override + public void updateActivity(Activity target, Activity editedActivity) + throws DuplicateActivityException { + fail("This method should not be called."); + } + + @Override + public ObservableList getFilteredActivityList() { + fail("This method should not be called."); + return null; + } + +``` +###### \java\seedu\address\logic\commands\RemoveCommandTest.java +``` java +/** + * Contains unit tests for {@code RemoveCommand} and integration tests (interactions with Model, UndoCommand + * and RedoCommand) + */ +public class RemoveCommandTest { + + private Model model = new ModelManager(getTypicalDeskBoard(), new UserPrefs()); + + @Test + public void execute_validTaskOptionValidIndex_success() throws Exception { + Activity activityToDelete = model.getFilteredTaskList().get(INDEX_FIRST_ACTIVITY.getZeroBased()); + RemoveCommand removeCommand = prepareCommand("task", INDEX_FIRST_ACTIVITY); + + String expectedMessage = String.format(RemoveCommand.MESSAGE_REMOVE_TASK_SUCCESS, activityToDelete); + + ModelManager expectedModel = new ModelManager(model.getDeskBoard(), new UserPrefs()); + expectedModel.deleteActivity(activityToDelete); + + assertCommandSuccess(removeCommand, model, expectedMessage, expectedModel); + } + + @Test + public void execute_validEventOptionValidIndex_success() throws Exception { + Activity activityToDelete = model.getFilteredEventList().get(INDEX_FIRST_ACTIVITY.getZeroBased()); + RemoveCommand removeCommand = prepareCommand("event", INDEX_FIRST_ACTIVITY); + + String expectedMessage = String.format(RemoveCommand.MESSAGE_REMOVE_EVENT_SUCCESS, activityToDelete); + + ModelManager expectedModel = new ModelManager(model.getDeskBoard(), new UserPrefs()); + expectedModel.deleteActivity(activityToDelete); + + assertCommandSuccess(removeCommand, model, expectedMessage, expectedModel); + } + + @Test + public void execute_validOptionInvalidIndex_throwsCommandException() throws Exception { + Index outOfBoundIndex = Index.fromOneBased(model.getFilteredTaskList().size() + 1); + RemoveCommand removeCommand = prepareCommand("task", outOfBoundIndex); + + assertCommandFailure(removeCommand, model, Messages.MESSAGE_INVALID_ACTIVITY_DISPLAYED_INDEX); + } + + @Test + public void executeUndoRedo_validOptionValidIndex_success() throws Exception { + UndoRedoStack undoRedoStack = new UndoRedoStack(); + UndoCommand undoCommand = prepareUndoCommand(model, undoRedoStack); + RedoCommand redoCommand = prepareRedoCommand(model, undoRedoStack); + Activity activityToDelete = model.getFilteredTaskList().get(INDEX_FIRST_ACTIVITY.getZeroBased()); + RemoveCommand removeCommand = prepareCommand("task", INDEX_FIRST_ACTIVITY); + Model expectedModel = new ModelManager(model.getDeskBoard(), new UserPrefs()); + + // delete -> first activity deleted + removeCommand.execute(); + undoRedoStack.push(removeCommand); + + // undo -> reverts desk board back to previous state + assertCommandSuccess(undoCommand, model, UndoCommand.MESSAGE_SUCCESS, expectedModel); + + // redo -> same first activity deleted again + expectedModel.deleteActivity(activityToDelete); + assertCommandSuccess(redoCommand, model, RedoCommand.MESSAGE_SUCCESS, expectedModel); + } + + @Test + public void executeUndoRedo_validOptionInvalidIndex_failure() { + UndoRedoStack undoRedoStack = new UndoRedoStack(); + UndoCommand undoCommand = prepareUndoCommand(model, undoRedoStack); + RedoCommand redoCommand = prepareRedoCommand(model, undoRedoStack); + Index outOfBoundIndex = Index.fromOneBased(model.getFilteredTaskList().size() + 1); + RemoveCommand removeCommand = prepareCommand("task", outOfBoundIndex); + + // execution failed -> deleteCommand not pushed into undoRedoStack + assertCommandFailure(removeCommand, model, Messages.MESSAGE_INVALID_ACTIVITY_DISPLAYED_INDEX); + + // no commands in undoRedoStack -> undoCommand and redoCommand fail + assertCommandFailure(undoCommand, model, UndoCommand.MESSAGE_FAILURE); + assertCommandFailure(redoCommand, model, RedoCommand.MESSAGE_FAILURE); + } + + @Test + public void equals() throws Exception { + RemoveCommand removeFirstCommand = prepareCommand("task", INDEX_FIRST_ACTIVITY); + RemoveCommand removeSecondCommand = prepareCommand("task", INDEX_SECOND_ACTIVITY); + + // same object -> returns true + assertTrue(removeFirstCommand.equals(removeFirstCommand)); + + // same values -> returns true + RemoveCommand removeFirstCommandCopy = prepareCommand("task", INDEX_FIRST_ACTIVITY); + assertTrue(removeFirstCommand.equals(removeFirstCommandCopy)); + + // one command preprocessed when previously equal -> returns false + removeFirstCommandCopy.preprocessUndoableCommand(); + assertFalse(removeFirstCommand.equals(removeFirstCommandCopy)); + + // different types -> returns false + assertFalse(removeFirstCommand.equals(1)); + + // null -> returns false + assertFalse(removeFirstCommand.equals(null)); + + // different activity -> returns false + assertFalse(removeFirstCommand.equals(removeSecondCommand)); + } + + private RemoveCommand prepareCommand(String activityOption, Index index) { + RemoveCommand removeCommand = new RemoveCommand(activityOption, index); + removeCommand.setData(model, new CommandHistory(), new UndoRedoStack()); + return removeCommand; + } +} +``` +###### \java\seedu\address\logic\commands\TaskCommandIntegrationTest.java +``` java +/** + * Contains integration tests (interaction with the Model) for {@code TaskCommand}. + */ +public class TaskCommandIntegrationTest { + + private Model model; + + @Before + public void setUp() { + model = new ModelManager(getTypicalDeskBoard(), new UserPrefs()); + } + + @Test + public void execute_newTask_success() throws Exception { + Task validTask = new TaskBuilder().build(); + + Model expectedModel = new ModelManager(model.getDeskBoard(), new UserPrefs()); + expectedModel.addActivity(validTask); + + assertCommandSuccess(prepareCommand(validTask, model), model, + String.format(TaskCommand.MESSAGE_SUCCESS, validTask), expectedModel); + } + + @Test + // Questionable - does the app check for duplicate task? + public void execute_duplicateTask_throwsCommandException() { + Activity activityInList = model.getDeskBoard().getActivityList().get(1); + assertCommandFailure(prepareCommand((Task) activityInList, model), model, TaskCommand.MESSAGE_DUPLICATE_TASK); + } + + /** + * Generates a new {@code TaskCommand} which upon execution, adds {@code task} into the {@code model}. + */ + private TaskCommand prepareCommand(Task task, Model model) { + TaskCommand command = new TaskCommand(task); + command.setData(model, new CommandHistory(), new UndoRedoStack()); + return command; + } +} +``` +###### \java\seedu\address\logic\commands\TaskCommandTest.java +``` java +public class TaskCommandTest { + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Test + public void constructor_nullTask_throwsNullPointerException() { + thrown.expect(NullPointerException.class); + new TaskCommand(null); + } + + @Test + public void execute_taskAcceptedByModel_addSuccessful() throws Exception { + ModelStubAcceptingTaskAdded modelStub = new ModelStubAcceptingTaskAdded(); + Task validTask = new TaskBuilder().build(); + + CommandResult commandResult = getTaskCommandForGivenTask(validTask, modelStub).execute(); + + assertEquals(String.format(TaskCommand.MESSAGE_SUCCESS, validTask), commandResult.feedbackToUser); + assertEquals(Arrays.asList(validTask), modelStub.tasksAdded); + } + + @Test + public void execute_duplicateTask_throwsCommandException() throws Exception { + ModelStub modelStub = new ModelStubThrowingDuplicateActivityException(); + Task validTask = new TaskBuilder().build(); + + thrown.expect(CommandException.class); + thrown.expectMessage(TaskCommand.MESSAGE_DUPLICATE_TASK); + + getTaskCommandForGivenTask(validTask, modelStub).execute(); + } + + @Test + public void equals() { + Task assignment = new TaskBuilder().build(); + Task project = new TaskBuilder().withName("Project").build(); + TaskCommand addAssignmentCommand = new TaskCommand(assignment); + TaskCommand addProjectCommand = new TaskCommand(project); + + // same object -> returns true + assertTrue(addAssignmentCommand.equals(addAssignmentCommand)); + + // same values -> returns true + TaskCommand addAssignmentCommandCopy = new TaskCommand(assignment); + assertTrue(addAssignmentCommand.equals(addAssignmentCommandCopy)); + + // different types -> returns false + assertFalse(addAssignmentCommand.equals(1)); + + // null -> returns false + assertFalse(addAssignmentCommand.equals(null)); + + // different activity -> returns false + assertFalse(addAssignmentCommand.equals(addProjectCommand)); + } + + /** + * Generates a new TaskCommand with the details of the given task. + */ + private TaskCommand getTaskCommandForGivenTask(Task task, Model model) { + TaskCommand command = new TaskCommand(task); + command.setData(model, new CommandHistory(), new UndoRedoStack()); + return command; + } + + /** + * A default model stub that have all of the methods failing. + */ + private class ModelStub implements Model { + @Override + public void addActivity(Activity activity) throws DuplicateActivityException { + fail("This method should not be called."); + } + + @Override + public void resetData(ReadOnlyDeskBoard newData) { + fail("This method should not be called."); + } + + @Override + public ReadOnlyDeskBoard getDeskBoard() { + fail("This method should not be called."); + return null; + } + + @Override + public void deleteActivity(Activity target) throws ActivityNotFoundException { + fail("This method should not be called."); + } + + @Override + public void updateActivity(Activity target, Activity editedActivity) + throws DuplicateActivityException { + fail("This method should not be called."); + } + + @Override + public ObservableList getFilteredActivityList() { + fail("This method should not be called."); + return null; + } + +``` +###### \java\seedu\address\logic\parser\DeskBoardParserTest.java +``` java +public class DeskBoardParserTest { + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + private final DeskBoardParser parser = new DeskBoardParser(); + + @Test + public void parseCommand_task() throws Exception { + Task task = new TaskBuilder().build(); + TaskCommand command = (TaskCommand) parser.parseCommand(TaskUtil.getTaskCommand(task)); + assertEquals(new TaskCommand(task), command); + } + +``` +###### \java\seedu\address\logic\parser\EventCommandParserTest.java +``` java +public class EventCommandParserTest { + //TODO: Tedious +} +``` +###### \java\seedu\address\logic\parser\RemoveCommandParserTest.java +``` java +public class RemoveCommandParserTest { + + private RemoveCommandParser parser = new RemoveCommandParser(); + + @Test + public void parse_validArgs_returnsDeleteCommand() { + assertParseSuccess(parser, "task 1", new RemoveCommand("task", INDEX_FIRST_ACTIVITY)); + } + + @Test + public void parse_invalidArgs_throwsParseException() { + // Invalid activity option + assertParseFailure(parser, "invalidOption 1", String.format(MESSAGE_INVALID_COMMAND_FORMAT, RemoveCommand + .MESSAGE_USAGE)); + + // Only one argument + assertParseFailure(parser, "task", String.format(MESSAGE_INVALID_COMMAND_FORMAT, RemoveCommand + .MESSAGE_USAGE)); + + } +} +``` +###### \java\seedu\address\logic\parser\TaskCommandParserTest.java +``` java +public class TaskCommandParserTest { + private TaskCommandParser parser = new TaskCommandParser(); + + @Test + public void parse_allFieldsPresent_success() { + Task expectedTask = new TaskBuilder().withName(VALID_NAME_CS2010_QUIZ).withDateTime(VALID_DATE_TIME_CS2010_QUIZ) + .withRemark(VALID_REMARK_CS2010_QUIZ).withTags(VALID_TAG_CS2010).build(); + + // whitespace only preamble + assertParseSuccess(parser, PREAMBLE_WHITESPACE + NAME_DESC_CS2010_QUIZ + DATE_TIME_DESC_CS2010_QUIZ + + REMARK_DESC_CS2010_QUIZ + TAG_DESC_CS2010, new TaskCommand(expectedTask)); + + // multiple names - last name accepted + assertParseSuccess(parser, NAME_DESC_MA2108_HOMEWORK + NAME_DESC_CS2010_QUIZ + + DATE_TIME_DESC_CS2010_QUIZ + REMARK_DESC_CS2010_QUIZ + TAG_DESC_CS2010, + new TaskCommand(expectedTask)); + + // multiple date times - last date time accepted + assertParseSuccess(parser, NAME_DESC_CS2010_QUIZ + DATE_TIME_DESC_MA2108_HOMEWORK + + DATE_TIME_DESC_CS2010_QUIZ + REMARK_DESC_CS2010_QUIZ + + TAG_DESC_CS2010, new TaskCommand(expectedTask)); + + // multiple remarks - last remark accepted + assertParseSuccess(parser, NAME_DESC_CS2010_QUIZ + DATE_TIME_DESC_CS2010_QUIZ + + REMARK_DESC_MA2108_HOMEWORK + REMARK_DESC_CS2010_QUIZ + TAG_DESC_CS2010, + new TaskCommand(expectedTask)); + + // multiple tags - all accepted + Task expectedTaskMultipleTags = new TaskBuilder().withName(VALID_NAME_CS2010_QUIZ) + .withDateTime(VALID_DATE_TIME_CS2010_QUIZ) + .withRemark(VALID_REMARK_CS2010_QUIZ) + .withTags(VALID_TAG_CS2010, VALID_TAG_URGENT).build(); + assertParseSuccess(parser, NAME_DESC_CS2010_QUIZ + DATE_TIME_DESC_CS2010_QUIZ + + REMARK_DESC_CS2010_QUIZ + TAG_DESC_URGENT + TAG_DESC_CS2010, + new TaskCommand(expectedTaskMultipleTags)); + } + + + //TODO: Is Remark optional? + public void parse_optionalRemarkMissing_success() { + + } + + @Test + public void parse_optionalTagsMissing_success() { + Task expectedTask = new TaskBuilder().withName(VALID_NAME_MA2108_HOMEWORK) + .withDateTime(VALID_DATE_TIME_MA2108_HOMEWORK) + .withRemark(VALID_REMARK_MA2108_HOMEWORK).withTags().build(); + assertParseSuccess(parser, NAME_DESC_MA2108_HOMEWORK + DATE_TIME_DESC_MA2108_HOMEWORK + + REMARK_DESC_MA2108_HOMEWORK, new TaskCommand(expectedTask)); + } + + @Test + public void parse_compulsoryFieldMissing_failure() { + String expectedMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, TaskCommand.MESSAGE_USAGE); + + // missing name prefix + assertParseFailure(parser, VALID_NAME_CS2010_QUIZ + DATE_TIME_DESC_CS2010_QUIZ + + REMARK_DESC_CS2010_QUIZ, expectedMessage); + + // missing date time prefix + assertParseFailure(parser, NAME_DESC_CS2010_QUIZ + VALID_DATE_TIME_CS2010_QUIZ + + REMARK_DESC_CS2010_QUIZ, expectedMessage); + +// // missing remark prefix +// assertParseFailure(parser, NAME_DESC_CS2010_QUIZ + DATE_TIME_DESC_CS2010_QUIZ + VALID_EMAIL_BOB + , +// expectedMessage); + +// // all prefixes missing +// assertParseFailure(parser, VALID_NAME_CS2010_QUIZ + VALID_DATE_TIME_CS2010_QUIZ + VALID_EMAIL_BOB +// + VALID_ADDRESS_BOB, expectedMessage); + } + + @Test + public void parse_invalidValue_failure() { + // invalid name + assertParseFailure(parser, INVALID_TASK_NAME_DESC + DATE_TIME_DESC_CS2010_QUIZ + + REMARK_DESC_CS2010_QUIZ + TAG_DESC_CS2010, Name.MESSAGE_NAME_CONSTRAINTS); + +// TODO: Got to do with DateTime Regex in Model +// // invalid date time +// assertParseFailure(parser, NAME_DESC_CS2010_QUIZ + INVALID_TASK_DATE_TIME_DESC +// + REMARK_DESC_CS2010_QUIZ + TAG_DESC_CS2010, DateTime.MESSAGE_DATETIME_CONSTRAINTS); + +// TODO: Not sure myself +// // invalid remark +// assertParseFailure(parser, NAME_DESC_CS2010_QUIZ + DATE_TIME_DESC_CS2010_QUIZ +// + INVALID_TASK_REMARK_DESC + TAG_DESC_CS2010, Remark.MESSAGE_REMARK_CONSTRAINTS); + + // invalid tag + assertParseFailure(parser, NAME_DESC_CS2010_QUIZ + DATE_TIME_DESC_CS2010_QUIZ + + REMARK_DESC_CS2010_QUIZ + INVALID_TASK_TAG_DESC, Tag.MESSAGE_TAG_CONSTRAINTS); + + // two invalid values, only first invalid value reported + assertParseFailure(parser, INVALID_TASK_NAME_DESC + DATE_TIME_DESC_CS2010_QUIZ + + REMARK_DESC_CS2010_QUIZ, + Name.MESSAGE_NAME_CONSTRAINTS); + + // non-empty preamble + assertParseFailure(parser, PREAMBLE_NON_EMPTY + NAME_DESC_CS2010_QUIZ + DATE_TIME_DESC_CS2010_QUIZ + + REMARK_DESC_CS2010_QUIZ + TAG_DESC_CS2010, + String.format(MESSAGE_INVALID_COMMAND_FORMAT, TaskCommand.MESSAGE_USAGE)); + } +} +``` +###### \java\seedu\address\model\activity\DateTimeTest.java +``` java +public class DateTimeTest { + + @Test + public void constructor_null_throwsNullPointerException() { + Assert.assertThrows(NullPointerException.class, () -> new DateTime(null)); + } + + @Test + public void constructor_invalidDateTime_throwsIllegalArgumentException() { + String invalidDateTime = ""; + Assert.assertThrows(IllegalArgumentException.class, () -> new DateTime(invalidDateTime)); + } + + @Test + public void isValidDateTime_null_throwsNullPointerException() { + Assert.assertThrows(NullPointerException.class, () -> DateTime.isValidDateTime(null)); + } + + @Test + public void isValidDateTime_validDateTime() { + assertTrue(DateTime.isValidDateTime("01/08/1995 12:00")); + assertTrue(DateTime.isValidDateTime("03/03/2019 12:00")); + assertTrue(DateTime.isValidDateTime("3/3/2019 00:00")); + assertTrue(DateTime.isValidDateTime("3/3/2019 23:59")); + + } + + @Test + public void isValidDateTime_invalidDateTime() { + assertFalse(DateTime.isValidDateTime("")); + assertFalse(DateTime.isValidDateTime(" ")); + assertFalse(DateTime.isValidDateTime("2019/03/03 12:00")); // YYMMDD + assertFalse(DateTime.isValidDateTime("12:00 03/03/2019")); // time before date + assertFalse(DateTime.isValidDateTime("03-03-2019 12:00")); // dash, instead of slash + assertFalse(DateTime.isValidDateTime("32/12/2018 12:00")); // wrong day + assertFalse(DateTime.isValidDateTime("1/13/2018 10:00")); // wrong month + assertFalse(DateTime.isValidDateTime("1/12/0000 12:00")); // wrong year + assertFalse(DateTime.isValidDateTime("1/8/1995 25:00")); // wrong time + } +} +``` +###### \java\seedu\address\testutil\ActivityBuilder.java +``` java + T build(); + +} +``` +###### \java\seedu\address\testutil\EventBuilder.java +``` java + public Event build() { + return new Event(name, startDateTime, endDateTime, location, remark, tags); + } + +} +``` +###### \java\seedu\address\testutil\EventUtil.java +``` java +/** + * A utility class for Event. + */ +public class EventUtil { + /** + * Returns an event command string for adding the {@code event}. + */ + public static String getEventCommand(Event event) { + return EventCommand.COMMAND_WORD + " " + getEventDetails(event); + } + + /** + * Returns the part of command string for the given {@code event}'s details. + */ + public static String getEventDetails(Event event) { + StringBuilder sb = new StringBuilder(); + sb.append(PREFIX_NAME + event.getName().fullName + " "); + sb.append(PREFIX_START_DATETIME + event.getStartDateTime().toString() + " "); + sb.append(PREFIX_END_DATETIME + event.getEndDateTime().toString() + " "); + sb.append(PREFIX_LOCATION + event.getLocation().toString() + " "); + sb.append(PREFIX_REMARK + event.getRemark().value + " "); + event.getTags().stream().forEach( + s -> sb.append(PREFIX_TAG + s.tagName + " ") + ); + return sb.toString(); + } +} +``` +###### \java\seedu\address\testutil\TaskBuilder.java +``` java + public Task build() { + return new Task(name, dateTime, remark, tags); + } +} +``` +###### \java\seedu\address\testutil\TaskUtil.java +``` java +/** + * A utility class for Task. + */ +public class TaskUtil { + /** + * Returns a task command string for adding the {@code task}. + */ + public static String getTaskCommand(Task task) { + return TaskCommand.COMMAND_WORD + " " + getTaskDetails(task); + } + + /** + * Returns the part of command string for the given {@code task}'s details. + */ + public static String getTaskDetails(Task task) { + StringBuilder sb = new StringBuilder(); + sb.append(PREFIX_NAME + task.getName().fullName + " "); + sb.append(PREFIX_DATE_TIME + task.getDueDateTime().toString() + " "); + sb.append(PREFIX_REMARK + task.getRemark().value + " "); + task.getTags().stream().forEach( + s -> sb.append(PREFIX_TAG + s.tagName + " ") + ); + return sb.toString(); + } +} +``` diff --git a/collated/test/YuanQQLer.md b/collated/test/YuanQQLer.md new file mode 100644 index 000000000000..9213e88cd016 --- /dev/null +++ b/collated/test/YuanQQLer.md @@ -0,0 +1,245 @@ +# YuanQQLer +###### \java\seedu\address\testutil\EventBuilder.java +``` java +/** + * This the class to build event + */ +public class EventBuilder implements ActivityBuilder { + + public static final String DEFAULT_NAME = "CIP"; + public static final String DEFAULT_START_DATETIME = "04/04/2018 08:10"; + public static final String DEFAULT_END_DATETIME = "04/04/2018 10:00"; + public static final String DEFAULT_LOCATION = "123, Jurong West Ave 6"; + public static final String DEFAULT_REMARK = "nil"; + public static final String DEFAULT_TAGS = "optional"; + + private Name name; + private DateTime startDateTime; + private DateTime endDateTime; + private Location location; + private Remark remark; + private Set tags; + + public EventBuilder() { + name = new Name(DEFAULT_NAME); + startDateTime = new DateTime(DEFAULT_START_DATETIME); + endDateTime = new DateTime(DEFAULT_END_DATETIME); + location = new Location(DEFAULT_LOCATION); + remark = new Remark(DEFAULT_REMARK); + tags = SampleDataUtil.getTagSet(DEFAULT_TAGS); + } + + /** + * Initializes the EventBuilder with the data of {@code activityToCopy}. + */ + public EventBuilder(Event eventToCopy) { + name = eventToCopy.getName(); + startDateTime = eventToCopy.getStartDateTime(); + endDateTime = eventToCopy.getEndDateTime(); + location = eventToCopy.getLocation(); + remark = eventToCopy.getRemark(); + tags = new HashSet<>(eventToCopy.getTags()); + } + + /** + * Sets the {@code Name} of the {@code Activity} that we are building. + */ + public EventBuilder withName(String name) { + this.name = new Name(name); + return this; + } + + /** + * Parses the {@code tags} into a {@code Set} and set it to the {@code Activity} that we are building. + */ + public EventBuilder withTags(String ... tags) { + this.tags = SampleDataUtil.getTagSet(tags); + return this; + } + + /** + * Sets the {@code Remark} of the {@code Activity} that we are building. + */ + public EventBuilder withRemark(String remark) { + this.remark = new Remark(remark); + return this; + } + + /** + * Sets the {@code DateTime} of the {@code Activity} that we are building. + */ + public EventBuilder withStartDateTime(String dateTime) { + this.startDateTime = new DateTime(dateTime); + return this; + } + + /** + * Sets the {@code DateTime} of the {@code Activity} that we are building. + */ + public EventBuilder withEndDateTime(String dateTime) { + this.endDateTime = new DateTime(dateTime); + return this; + } + + /** + * Sets the {@code Location} of the {@code Activity} that we are building. + */ + public EventBuilder withLocation (String location) { + this.location = new Location(location); + return this; + } + +``` +###### \java\seedu\address\testutil\TaskBuilder.java +``` java +/** + * Build task for testing + */ +public class TaskBuilder implements ActivityBuilder { + public static final String DEFAULT_NAME = "Assignment"; + public static final String DEFAULT_DATETIME = "04/04/2018 08:10"; + public static final String DEFAULT_REMARK = "Urgent"; + public static final String DEFAULT_TAGS = "Optional"; + + private Name name; + private DateTime dateTime; + private Remark remark; + private Set tags; + + public TaskBuilder() { + name = new Name(DEFAULT_NAME); + dateTime = new DateTime(DEFAULT_DATETIME); + remark = new Remark(DEFAULT_REMARK); + tags = SampleDataUtil.getTagSet(DEFAULT_TAGS); + } + + /** + * Initializes the ActivityBuilder with the data of {@code taskToCopy}. + */ + public TaskBuilder(Task taskToCopy) { + name = taskToCopy.getName(); + dateTime = taskToCopy.getDateTime(); + remark = taskToCopy.getRemark(); + tags = new HashSet<>(taskToCopy.getTags()); + } + + /** + * Initializes the ActivityBuilder with the data of {@code taskToCopy}. + */ + public TaskBuilder(Activity activityToCopy) { + name = activityToCopy.getName(); + dateTime = activityToCopy.getDateTime(); + remark = activityToCopy.getRemark(); + tags = new HashSet<>(activityToCopy.getTags()); + } + /** + * Sets the {@code Name} of the {@code Activity} that we are building. + */ + public TaskBuilder withName(String name) { + this.name = new Name(name); + return this; + } + + /** + * Parses the {@code tags} into a {@code Set} and set it to the {@code Activity} that we are building. + */ + public TaskBuilder withTags(String... tags) { + this.tags = SampleDataUtil.getTagSet(tags); + return this; + } + + /** + * Sets the {@code Remark} of the {@code Activity} that we are building. + */ + public TaskBuilder withRemark(String remark) { + this.remark = new Remark(remark); + return this; + } + + /** + * Sets the {@code DateTime} of the {@code Activity} that we are building. + */ + public TaskBuilder withDateTime(String dateTime) { + this.dateTime = new DateTime(dateTime); + return this; + } + +``` +###### \java\seedu\address\testutil\TypicalActivities.java +``` java +/** + * A utility class containing a list of {@code Activity} objects to be used in tests. + */ +public class TypicalActivities { + + public static final Task ASSIGNMENT1 = new TaskBuilder().withName("CS2101Assignment") + .withRemark(" ") + .withDateTime("04/03/2018 23:59") + .withTags("CS2101").build(); + public static final Task ASSIGNMENT2 = new TaskBuilder().withName("CS2102Assignment") + .withRemark(" ") + .withDateTime("15/03/2018 23:59") + .withTags("CS2102").build(); + public static final Task QUIZ = new TaskBuilder().withName("CS2101Quiz") + .withDateTime("19/03/2018 23:59") + .withRemark("IVLE Quiz").build(); + public static final Event CCA = new EventBuilder().withName("CCA") + .withStartDateTime("01/04/2018 20:00") + .withEndDateTime("01/04/2018 21:00") + .withLocation("Campus") + .withRemark("nil").build(); + public static final Event CIP = new EventBuilder().withName("CIP") + .withStartDateTime("02/04/2018 08:00") + .withEndDateTime("02/04/2018 12:00") + .withLocation("michegan ave") + .withRemark("nil") + .withTags("CIP").build(); + public static final Event EXAM1 = new EventBuilder().withName("CS2101Exam") + .withStartDateTime("28/04/2018 09:00") + .withEndDateTime("28/04/2018 11:00") + .withLocation("MPSH") + .withRemark("nil") + .withTags("CS2101").build(); + public static final Event IFG = new EventBuilder().withName("InterFacultyGame") + .withStartDateTime("04/01/2018 20:00") + .withEndDateTime("04/01/2018 22:00") + .withLocation("MPSH 1") + .withRemark("nil").build(); + + // Manually added + public static final Task ASSIGNMENT3 = new TaskBuilder().withName("CS2102Assignment") + .withDateTime("01/04/2018 20:00") + .withRemark("nil").build(); + public static final Event DEMO1 = new EventBuilder().withName("CS2102ProjectDemo") + .withStartDateTime("04/04/2018 09:00") + .withEndDateTime("04/04/2018 10:00") + .withRemark("FinalDemo").build(); + + public static final String KEYWORD_MATCHING_MEIER = "Meier"; // A keyword that matches MEIER + + private TypicalActivities() {} // prevents instantiation + + /** + * Returns an {@code DeskBoard} with all the typical activities. + */ + public static DeskBoard getTypicalDeskBoard() { + DeskBoard deskBoard = new DeskBoard(); + for (Activity activity : getTypicalActivities()) { + try { + deskBoard.addActivity(activity); + } catch (DuplicateActivityException e) { + throw new AssertionError("Not possible"); + } + } + return deskBoard; + } + + public static List getTypicalActivities() { + return new ArrayList<>(Arrays.asList(ASSIGNMENT1, ASSIGNMENT2, QUIZ, CCA, CIP, EXAM1, IFG)); + } + + public static List getTypicalTask() { + return new ArrayList<>(Arrays.asList(ASSIGNMENT1, ASSIGNMENT2, QUIZ)); + } +} +``` diff --git a/collated/test/jasmoon.md b/collated/test/jasmoon.md new file mode 100644 index 000000000000..a3bf2022f571 --- /dev/null +++ b/collated/test/jasmoon.md @@ -0,0 +1,314 @@ +# jasmoon +###### \java\seedu\address\logic\commands\CommandTestUtil.java +``` java + /** + * Executes the given {@code command}, confirms that
+ * - the result message matches {@code expectedMessage}
+ */ + public static void assertCommandSuccess(Command command, String expectedMessage) { + try { + CommandResult result = command.execute(); + assertEquals(expectedMessage, result.feedbackToUser); + } catch (CommandException ce) { + throw new AssertionError("Execution of command should not fail.", ce); + } + } + + /** + * Executes the given {@code command}, confirms that
+ * - a {@code CommandException} is thrown
+ * - the CommandException message matches {@code expectedMessage}
+ */ + public static void assertCommandFailure(Command command, String expectedMessage) { + try { + command.execute(); + fail("The expected CommandException was not thrown."); + } catch (CommandException e) { + assertEquals(expectedMessage, e.getMessage()); + } + } + +``` +###### \java\seedu\address\logic\commands\EventCommandTest.java +``` java + @Override + public ObservableList getFilteredTaskList() { + fail("This method should not be called."); + return null; + } + + @Override + public ObservableList getFilteredEventList() { + fail("This method should not be called."); + return null; + } + + @Override + public void updateFilteredActivityList(Predicate predicate) { + fail("This method should not be called."); + } + } + + /** + * A Model stub that always throw a DuplicateActivityException when trying to add a activity. + */ + private class ModelStubThrowingDuplicateActivityException extends ModelStub { + @Override + public void addActivity(Activity activity) throws DuplicateActivityException { + throw new DuplicateActivityException(); + } + + @Override + public ReadOnlyDeskBoard getDeskBoard() { + return new DeskBoard(); + } + } + + /** + * A Model stub that always accept the activity being added. + */ + private class ModelStubAcceptingEventAdded extends ModelStub { + final ArrayList eventsAdded = new ArrayList<>(); + + @Override + public void addActivity(Activity activity) throws DuplicateActivityException { + requireNonNull(activity); + eventsAdded.add(activity); + } + + @Override + public ReadOnlyDeskBoard getDeskBoard() { + return new DeskBoard(); + } + } +} +``` +###### \java\seedu\address\logic\commands\ListCommandTest.java +``` java + @Test + public void execute_listForTask_success() { + ListCommand command = new ListCommand("task"); + assertCommandSuccess(command, ListCommand.MESSAGE_SUCCESS_TASK); + assertTrue(eventsCollectorRule.eventsCollector.getMostRecent() instanceof ShowTaskOnlyRequestEvent); + assertTrue(eventsCollectorRule.eventsCollector.getSize() == 1); + } + + @Test + public void execute_listForEvent_success() { + ListCommand command = new ListCommand("event"); + assertCommandSuccess(command, ListCommand.MESSAGE_SUCCESS_EVENT); + assertTrue(eventsCollectorRule.eventsCollector.getMostRecent() instanceof ShowEventOnlyRequestEvent); + assertTrue(eventsCollectorRule.eventsCollector.getSize() == 1); + } + + @Test + public void execute_listForActivity_success() { + ListCommand command = new ListCommand(); + assertCommandSuccess(command, ListCommand.MESSAGE_SUCCESS); + assertTrue(eventsCollectorRule.eventsCollector.getMostRecent() instanceof ShowActivityRequestEvent); + assertTrue(eventsCollectorRule.eventsCollector.getSize() == 1); + } + + @Test + public void execute_invalidArgs_throwsCommandException() throws Exception { + ListCommand command = new ListCommand("hello"); + assertCommandFailure(command, String.format(Messages.MESSAGE_INVALID_LIST_REQUEST, "hello")); + } + +} +``` +###### \java\seedu\address\logic\commands\TaskCommandTest.java +``` java + @Override + public ObservableList getFilteredTaskList() { + fail("This method should not be called."); + return null; + } + + @Override + public ObservableList getFilteredEventList() { + fail("This method should not be called."); + return null; + } + + @Override + public void updateFilteredActivityList(Predicate predicate) { + fail("This method should not be called."); + } + } + + /** + * A Model stub that always throw a DuplicateActivityException when trying to add a activity. + */ + private class ModelStubThrowingDuplicateActivityException extends ModelStub { + @Override + public void addActivity(Activity activity) throws DuplicateActivityException { + throw new DuplicateActivityException(); + } + + @Override + public ReadOnlyDeskBoard getDeskBoard() { + return new DeskBoard(); + } + } + + /** + * A Model stub that always accept the activity being added. + */ + private class ModelStubAcceptingTaskAdded extends ModelStub { + final ArrayList tasksAdded = new ArrayList<>(); + + @Override + public void addActivity(Activity activity) throws DuplicateActivityException { + requireNonNull(activity); + tasksAdded.add(activity); + } + + @Override + public ReadOnlyDeskBoard getDeskBoard() { + return new DeskBoard(); + } + } + +} +``` +###### \java\seedu\address\logic\parser\DeskBoardParserTest.java +``` java + @Test + public void parseCommand_event() throws Exception { + Event event = new EventBuilder().build(); + EventCommand command = (EventCommand) parser.parseCommand(EventUtil.getEventCommand(event)); + assertTrue(command instanceof EventCommand); + } + + @Test + public void parseCommandPlusAlias_clear() throws Exception { + assertTrue(parser.parseCommand(ClearCommand.COMMAND_WORD) instanceof ClearCommand); + assertTrue(parser.parseCommand(ClearCommand.COMMAND_ALIAS + " 3") instanceof ClearCommand); + } + + /* @Test + public void parseCommand_remove() throws Exception { + RemoveCommand command = (RemoveCommand) parser.parseCommand( + RemoveCommand.COMMAND_WORD + " " + INDEX_FIRST_ACTIVITY.getOneBased()); + assertEquals(new RemoveCommand("task", INDEX_FIRST_ACTIVITY), command); + }*/ + +// +// public void parseCommand_edit() throws Exception { +// Person person = new PersonBuilder().build(); +// EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(person).build(); +// EditCommand command = (EditCommand) parser.parseCommand(EditCommand.COMMAND_WORD + " " +// + INDEX_FIRST_PERSON.getOneBased() + " " + PersonUtil.getPersonDetails(person)); +// assertEquals(new EditCommand(INDEX_FIRST_PERSON, descriptor), command); +// } +// +// +// public void parseCommand_exit() throws Exception { +// assertTrue(parser.parseCommand(ExitCommand.COMMAND_WORD) instanceof ExitCommand); +// assertTrue(parser.parseCommand(ExitCommand.COMMAND_WORD + " 3") instanceof ExitCommand); +// } +// +// +// public void parseCommand_find() throws Exception { +// List keywords = Arrays.asList("foo", "bar", "baz"); +// FindCommand command = (FindCommand) parser.parseCommand( +// FindCommand.COMMAND_WORD + " " + keywords.stream().collect(Collectors.joining(" "))); +// assertEquals(new FindCommand(new NameContainsKeywordsPredicate(keywords)), command); +// } +// +// +``` +###### \java\seedu\address\logic\parser\DeskBoardParserTest.java +``` java + @Test + public void parseCommandPlusAlias_help() throws Exception { + assertTrue(parser.parseCommand(HelpCommand.COMMAND_WORD) instanceof HelpCommand); + assertTrue(parser.parseCommand(HelpCommand.COMMAND_ALIAS + " task") instanceof HelpCommand); + try { + parser.parseCommand(HelpCommand.COMMAND_WORD + " 3"); + fail("The expected ParseException was not thrown."); + } catch (ParseException pe) { + assertEquals(String.format(Messages.MESSAGE_INVALID_HELP_REQUEST, "3"), pe.getMessage()); + } + } +// +// +// public void parseCommand_history() throws Exception { +// assertTrue(parser.parseCommand(HistoryCommand.COMMAND_WORD) instanceof HistoryCommand); +// assertTrue(parser.parseCommand(HistoryCommand.COMMAND_WORD + " 3") instanceof HistoryCommand); +// +// try { +// parser.parseCommand("histories"); +// fail("The expected ParseException was not thrown."); +// } catch (ParseException pe) { +// assertEquals(MESSAGE_UNKNOWN_COMMAND, pe.getMessage()); +// } +// } +// +// + @Test + public void parseCommandPlusAlias_list() throws Exception { + assertTrue(parser.parseCommand(ListCommand.COMMAND_WORD) instanceof ListCommand); + assertTrue(parser.parseCommand(ListCommand.COMMAND_ALIAS + " task") instanceof ListCommand); + } +// +// +// public void parseCommand_select() throws Exception { +// SelectCommand command = (SelectCommand) parser.parseCommand( +// SelectCommand.COMMAND_WORD + " " + INDEX_FIRST_PERSON.getOneBased()); +// assertEquals(new SelectCommand(INDEX_FIRST_PERSON), command); +// } +// +// +// public void parseCommand_redoCommandWord_returnsRedoCommand() throws Exception { +// assertTrue(parser.parseCommand(RedoCommand.COMMAND_WORD) instanceof RedoCommand); +// assertTrue(parser.parseCommand("redo 1") instanceof RedoCommand); +// } +// +// +// public void parseCommand_undoCommandWord_returnsUndoCommand() throws Exception { +// assertTrue(parser.parseCommand(UndoCommand.COMMAND_WORD) instanceof UndoCommand); +// assertTrue(parser.parseCommand("undo 3") instanceof UndoCommand); +// } +// + @Test + public void parseCommand_unrecognisedInput_throwsParseException() throws Exception { + thrown.expect(ParseException.class); + thrown.expectMessage(String.format(MESSAGE_INVALID_COMMAND_FORMAT, HelpCommand.MESSAGE_USAGE)); + parser.parseCommand(" "); + } + + @Test + public void parseCommand_unknownCommand_throwsParseException() throws Exception { + thrown.expect(ParseException.class); + thrown.expectMessage(MESSAGE_UNKNOWN_COMMAND); + parser.parseCommand("unknownCommand"); + } +} +``` +###### \java\seedu\address\logic\parser\HelpCommandParserTest.java +``` java +public class HelpCommandParserTest { + + private HelpCommandParser parser = new HelpCommandParser(); + + @Test + public void parse_invalidArgs_throwsParseException() { + assertParseFailure(parser, "a", String.format(Messages.MESSAGE_INVALID_HELP_REQUEST, "a")); + } +} +``` +###### \java\seedu\address\logic\parser\ListCommandParserTest.java +``` java +public class ListCommandParserTest { + + private ListCommandParser parser = new ListCommandParser(); + + @Test + public void parse_invalidArgs_throwsParseException() { + assertParseFailure(parser, "hello", + String.format(Messages.MESSAGE_INVALID_LIST_REQUEST, "hello")); + } +} +``` diff --git a/collated/test/karenfrilya97.md b/collated/test/karenfrilya97.md new file mode 100644 index 000000000000..26ef6f8463c5 --- /dev/null +++ b/collated/test/karenfrilya97.md @@ -0,0 +1,362 @@ +# karenfrilya97 +###### \java\seedu\address\commons\util\XmlUtilTest.java +``` java +/** + * Tests {@code XmlUtil} read and save methods + */ +public class XmlUtilTest { + + private static final String TEST_DATA_FOLDER = FileUtil.getPath("src/test/data/XmlUtilTest/"); + private static final File EMPTY_FILE = new File(TEST_DATA_FOLDER + "empty.xml"); + private static final File MISSING_FILE = new File(TEST_DATA_FOLDER + "missing.xml"); + private static final File VALID_FILE = new File(TEST_DATA_FOLDER + "validDeskBoard.xml"); + private static final File MISSING_TASK_FIELD_FILE = new File(TEST_DATA_FOLDER + "missingTaskField.xml"); + private static final File INVALID_TASK_FIELD_FILE = new File(TEST_DATA_FOLDER + "invalidTaskField.xml"); + private static final File VALID_TASK_FILE = new File(TEST_DATA_FOLDER + "validTask.xml"); + private static final File MISSING_EVENT_FIELD_FILE = new File(TEST_DATA_FOLDER + "missingEventField.xml"); + private static final File INVALID_EVENT_FIELD_FILE = new File(TEST_DATA_FOLDER + "invalidEventField.xml"); + private static final File VALID_EVENT_FILE = new File(TEST_DATA_FOLDER + "validEvent.xml"); + + private static final File TEMP_FILE = new File(TestUtil.getFilePathInSandboxFolder("tempDeskBoard.xml")); + + private static final String INVALID_DATE_TIME = "9482asf424"; + private static final String INVALID_LOCATION = " michegan ave"; + + private static final String VALID_TASK_NAME = "Hans Muster"; + private static final String VALID_TASK_DUE_DATE_TIME = "9482424"; + private static final String VALID_TASK_REMARK = "4th street"; + private static final List VALID_TASK_TAGS = Collections.singletonList(new XmlAdaptedTag("friends")); + + private static final String VALID_EVENT_NAME = "CIP"; + private static final String VALID_EVENT_START_DATE_TIME = "02/04/2018 08:00"; + private static final String VALID_EVENT_END_DATE_TIME = "02/04/2018 12:00"; + private static final String VALID_EVENT_LOCATION = "michegan ave"; + private static final List VALID_EVENT_TAGS = Collections.singletonList(new XmlAdaptedTag("CIP")); + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Test + public void getDataFromFile_nullFile_throwsNullPointerException() throws Exception { + thrown.expect(NullPointerException.class); + XmlUtil.getDataFromFile(null, DeskBoard.class); + } + + @Test + public void getDataFromFile_nullClass_throwsNullPointerException() throws Exception { + thrown.expect(NullPointerException.class); + XmlUtil.getDataFromFile(VALID_FILE, null); + } + + @Test + public void getDataFromFile_missingFile_fileNotFoundException() throws Exception { + thrown.expect(FileNotFoundException.class); + XmlUtil.getDataFromFile(MISSING_FILE, DeskBoard.class); + } + + @Test + public void getDataFromFile_emptyFile_dataFormatMismatchException() throws Exception { + thrown.expect(JAXBException.class); + XmlUtil.getDataFromFile(EMPTY_FILE, DeskBoard.class); + } + + //TODO: TEST + //@Test + public void getDataFromFile_validFile_validResult() throws Exception { + DeskBoard dataFromFile = XmlUtil.getDataFromFile(VALID_FILE, XmlSerializableDeskBoard.class).toModelType(); + assertEquals(7, dataFromFile.getActivityList().size()); + assertEquals(3, dataFromFile.getTagList().size()); + } + + @Test + public void xmlAdaptedTaskFromFile_fileWithMissingTaskField_validResult() throws Exception { + XmlAdaptedTask actualTask = XmlUtil.getDataFromFile( + MISSING_TASK_FIELD_FILE, XmlAdaptedTaskWithRootElement.class); + XmlAdaptedTask expectedTask = new XmlAdaptedTask( + null, VALID_TASK_DUE_DATE_TIME, VALID_TASK_REMARK, VALID_TASK_TAGS); + assertEquals(expectedTask, actualTask); + } + + @Test + public void xmlAdaptedTaskFromFile_fileWithInvalidTaskField_validResult() throws Exception { + XmlAdaptedTask actualTask = XmlUtil.getDataFromFile( + INVALID_TASK_FIELD_FILE, XmlAdaptedTaskWithRootElement.class); + XmlAdaptedTask expectedTask = new XmlAdaptedTask( + VALID_TASK_NAME, INVALID_DATE_TIME, VALID_TASK_REMARK, VALID_TASK_TAGS); + assertEquals(expectedTask, actualTask); + } + + @Test + public void xmlAdaptedTaskFromFile_fileWithValidTask_validResult() throws Exception { + XmlAdaptedTask actualTask = XmlUtil.getDataFromFile( + VALID_TASK_FILE, XmlAdaptedTaskWithRootElement.class); + XmlAdaptedTask expectedTask = new XmlAdaptedTask( + VALID_TASK_NAME, VALID_TASK_DUE_DATE_TIME, VALID_TASK_REMARK, VALID_TASK_TAGS); + assertEquals(expectedTask, actualTask); + } + + @Test + public void xmlAdaptedEventFromFile_fileWithMissingEventField_validResult() throws Exception { + XmlAdaptedEvent actualEvent = XmlUtil.getDataFromFile( + MISSING_EVENT_FIELD_FILE, XmlAdaptedEventWithRootElement.class); + XmlAdaptedEvent expectedEvent = new XmlAdaptedEvent(VALID_EVENT_NAME, VALID_EVENT_START_DATE_TIME, + null, VALID_EVENT_LOCATION, null, VALID_EVENT_TAGS); + assertEquals(expectedEvent, actualEvent); + } + + @Test + public void xmlAdaptedEventFromFile_fileWithInvalidEventField_validResult() throws Exception { + XmlAdaptedEvent actualEvent = XmlUtil.getDataFromFile( + INVALID_EVENT_FIELD_FILE, XmlAdaptedEventWithRootElement.class); + XmlAdaptedEvent expectedEvent = new XmlAdaptedEvent(VALID_EVENT_NAME, VALID_EVENT_START_DATE_TIME, + VALID_EVENT_END_DATE_TIME, INVALID_LOCATION, null, VALID_EVENT_TAGS); + assertEquals(expectedEvent, actualEvent); + } + + @Test + public void xmlAdaptedEventFromFile_fileWithValidEvent_validResult() throws Exception { + XmlAdaptedEvent actualEvent = XmlUtil.getDataFromFile( + VALID_EVENT_FILE, XmlAdaptedEventWithRootElement.class); + XmlAdaptedEvent expectedEvent = new XmlAdaptedEvent(VALID_EVENT_NAME, VALID_EVENT_START_DATE_TIME, + VALID_EVENT_END_DATE_TIME, VALID_EVENT_LOCATION, null, VALID_EVENT_TAGS); + assertEquals(expectedEvent, actualEvent); + } + + @Test + public void saveDataToFile_nullFile_throwsNullPointerException() throws Exception { + thrown.expect(NullPointerException.class); + XmlUtil.saveDataToFile(null, new DeskBoard()); + } + + @Test + public void saveDataToFile_nullClass_throwsNullPointerException() throws Exception { + thrown.expect(NullPointerException.class); + XmlUtil.saveDataToFile(VALID_FILE, null); + } + + @Test + public void saveDataToFile_missingFile_fileNotFoundException() throws Exception { + thrown.expect(FileNotFoundException.class); + XmlUtil.saveDataToFile(MISSING_FILE, new DeskBoard()); + } + + @Test + public void saveDataToFile_validFile_dataSaved() throws Exception { + TEMP_FILE.createNewFile(); + XmlSerializableDeskBoard dataToWrite = new XmlSerializableDeskBoard(new DeskBoard()); + XmlUtil.saveDataToFile(TEMP_FILE, dataToWrite); + XmlSerializableDeskBoard dataFromFile = XmlUtil.getDataFromFile(TEMP_FILE, XmlSerializableDeskBoard.class); + assertEquals(dataToWrite, dataFromFile); + + DeskBoardBuilder builder = new DeskBoardBuilder(new DeskBoard()); + dataToWrite = new XmlSerializableDeskBoard( + builder.withActivity(new TaskBuilder().build()).withTag("Friends").build()); + + XmlUtil.saveDataToFile(TEMP_FILE, dataToWrite); + dataFromFile = XmlUtil.getDataFromFile(TEMP_FILE, XmlSerializableDeskBoard.class); + assertEquals(dataToWrite, dataFromFile); + } + + /** + * Test class annotated with {@code XmlRootElement} to allow unmarshalling of .xml data + * to {@code XmlAdaptedTask} objects. + */ + @XmlRootElement(name = "task") + private static class XmlAdaptedTaskWithRootElement extends XmlAdaptedTask {} + + /** + * Test class annotated with {@code XmlRootElement} to allow unmarshalling of .xml data + * to {@code XmlAdaptedEvent} objects. + */ + @XmlRootElement(name = "event") + private static class XmlAdaptedEventWithRootElement extends XmlAdaptedEvent {} +} +``` +###### \java\seedu\address\model\UniqueActivityListTest.java +``` java + @Test + public void add_taskWithEarlierDateTimeThanExisting_sortsListAutomatically() throws DuplicateActivityException { + UniqueActivityList uniqueActivityList = new UniqueActivityList(); + Task earlierTask = ASSIGNMENT1; + Task laterTask = ASSIGNMENT2; + uniqueActivityList.add(laterTask); + uniqueActivityList.add(earlierTask); + Activity firstActivityOnTheList = uniqueActivityList.internalListAsObservable().get(0); + assertEquals(firstActivityOnTheList, earlierTask); + } + + @Test + public void add_eventWithEarlierStartDateTimeThanExisting_sortsListAutomatically() + throws DuplicateActivityException { + UniqueActivityList uniqueActivityList = new UniqueActivityList(); + Event earlierEvent = CCA; + Event laterEvent = CIP; + uniqueActivityList.add(laterEvent); + uniqueActivityList.add(earlierEvent); + Activity firstActivityOnTheList = uniqueActivityList.internalListAsObservable().get(0); + assertEquals(firstActivityOnTheList, earlierEvent); + } +} +``` +###### \java\seedu\address\storage\XmlAdaptedEventTest.java +``` java +public class XmlAdaptedEventTest { + + private static final Event CIP_EVENT = CIP; + + private static final String INVALID_NAME = "Rachel's Bday"; + private static final String INVALID_DATE_TIME = "23 April 2018"; + private static final String INVALID_LOCATION = " "; + private static final String INVALID_TAG = "#friend"; + + private static final String VALID_NAME = CIP_EVENT.getName().toString(); + private static final String VALID_START_DATE_TIME = CIP_EVENT.getStartDateTime().toString(); + private static final String VALID_END_DATE_TIME = CIP_EVENT.getEndDateTime().toString(); + private static final String VALID_LOCATION = CIP_EVENT.getLocation().toString(); + private static final String VALID_REMARK = CIP_EVENT.getRemark().toString(); + private static final List VALID_TAGS = CIP_EVENT.getTags().stream() + .map(XmlAdaptedTag::new) + .collect(Collectors.toList()); + + // TODO: 3/26/2018 fix bug + /** + * Test + */ + public void toModelType_validEventDetails_returnsEvent() throws Exception { + XmlAdaptedEvent event = new XmlAdaptedEvent(CIP_EVENT); + assertEquals(CIP_EVENT, event.toModelType()); + } + + @Test + public void toModelType_invalidName_throwsIllegalValueException() { + XmlAdaptedEvent event = new XmlAdaptedEvent(INVALID_NAME, VALID_START_DATE_TIME, VALID_END_DATE_TIME, + VALID_LOCATION, VALID_REMARK, VALID_TAGS); + String expectedMessage = Name.MESSAGE_NAME_CONSTRAINTS; + Assert.assertThrows(IllegalValueException.class, expectedMessage, event::toModelType); + } + + @Test + public void toModelType_nullName_throwsIllegalValueException() { + XmlAdaptedEvent event = new XmlAdaptedEvent(null, VALID_START_DATE_TIME, VALID_END_DATE_TIME, + VALID_LOCATION, VALID_REMARK, VALID_TAGS); + String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, event.getActivityType(), "name"); + Assert.assertThrows(IllegalValueException.class, expectedMessage, event::toModelType); + } + + @Test + public void toModelType_invalidStartDateTime_throwsIllegalValueException() { + XmlAdaptedEvent event = new XmlAdaptedEvent(VALID_NAME, INVALID_DATE_TIME, VALID_END_DATE_TIME, + VALID_LOCATION, VALID_REMARK, VALID_TAGS); + String expectedMessage = DateTime.MESSAGE_DATETIME_CONSTRAINTS; + Assert.assertThrows(IllegalValueException.class, expectedMessage, event::toModelType); + } + + @Test + public void toModelType_nullStartDateTime_throwsIllegalValueException() { + XmlAdaptedEvent event = new XmlAdaptedEvent(VALID_NAME, null, VALID_END_DATE_TIME, + VALID_LOCATION, VALID_REMARK, VALID_TAGS); + String expectedMessage = + String.format(MISSING_FIELD_MESSAGE_FORMAT, event.getActivityType(), "start date/time"); + Assert.assertThrows(IllegalValueException.class, expectedMessage, event::toModelType); + } + + @Test + public void toModelType_invalidEndDateTime_throwsIllegalValueException() { + XmlAdaptedEvent event = new XmlAdaptedEvent(VALID_NAME, VALID_START_DATE_TIME, INVALID_DATE_TIME, + VALID_LOCATION, VALID_REMARK, VALID_TAGS); + String expectedMessage = DateTime.MESSAGE_DATETIME_CONSTRAINTS; + Assert.assertThrows(IllegalValueException.class, expectedMessage, event::toModelType); + } + + @Test + public void toModelType_nullEndDateTime_throwsIllegalValueException() { + XmlAdaptedEvent event = new XmlAdaptedEvent(VALID_NAME, VALID_START_DATE_TIME, null, + VALID_LOCATION, VALID_REMARK, VALID_TAGS); + String expectedMessage = + String.format(MISSING_FIELD_MESSAGE_FORMAT, event.getActivityType(), "end date/time"); + Assert.assertThrows(IllegalValueException.class, expectedMessage, event::toModelType); + } + + @Test + public void toModelType_invalidLocation_throwsIllegalValueException() { + XmlAdaptedEvent event = new XmlAdaptedEvent(VALID_NAME, VALID_START_DATE_TIME, VALID_END_DATE_TIME, + INVALID_LOCATION, VALID_REMARK, VALID_TAGS); + String expectedMessage = Location.MESSAGE_LOCATION_CONSTRAINTS; + Assert.assertThrows(IllegalValueException.class, expectedMessage, event::toModelType); + } + + @Test + public void toModelType_invalidTags_throwsIllegalValueException() { + List invalidTags = new ArrayList<>(VALID_TAGS); + invalidTags.add(new XmlAdaptedTag(INVALID_TAG)); + XmlAdaptedEvent event = new XmlAdaptedEvent(VALID_NAME, VALID_START_DATE_TIME, VALID_END_DATE_TIME, + VALID_LOCATION, VALID_REMARK, invalidTags); + Assert.assertThrows(IllegalValueException.class, event::toModelType); + } + +} +``` +###### \java\seedu\address\storage\XmlAdaptedTaskTest.java +``` java +public class XmlAdaptedTaskTest { + + private static final Task ASSIGNMENT2_TASK = (Task) ASSIGNMENT2; + + private static final String INVALID_NAME = "Rachel's Bday"; + private static final String INVALID_DATE_TIME = "23 April 2018"; + private static final String INVALID_TAG = "#friend"; + + private static final String VALID_NAME = ASSIGNMENT2_TASK.getName().toString(); + private static final String VALID_DATE_TIME = ASSIGNMENT2_TASK.getDueDateTime().toString(); + private static final String VALID_REMARK = ASSIGNMENT2_TASK.getRemark().toString(); + private static final List VALID_TAGS = ASSIGNMENT2_TASK.getTags().stream() + .map(XmlAdaptedTag::new) + .collect(Collectors.toList()); + + @Test + public void toModelType_validTaskDetails_returnsTask() throws Exception { + XmlAdaptedTask task = new XmlAdaptedTask(ASSIGNMENT2_TASK); + assertEquals(ASSIGNMENT2_TASK, task.toModelType()); + } + + @Test + public void toModelType_invalidName_throwsIllegalValueException() { + XmlAdaptedTask task = + new XmlAdaptedTask(INVALID_NAME, VALID_DATE_TIME, VALID_REMARK, VALID_TAGS); + String expectedMessage = Name.MESSAGE_NAME_CONSTRAINTS; + Assert.assertThrows(IllegalValueException.class, expectedMessage, task::toModelType); + } + + @Test + public void toModelType_nullName_throwsIllegalValueException() { + XmlAdaptedTask task = new XmlAdaptedTask(null, VALID_DATE_TIME, VALID_REMARK, VALID_TAGS); + String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, task.getActivityType(), "name"); + Assert.assertThrows(IllegalValueException.class, expectedMessage, task::toModelType); + } + + @Test + public void toModelType_invalidDateTime_throwsIllegalValueException() { + XmlAdaptedTask task = + new XmlAdaptedTask(VALID_NAME, INVALID_DATE_TIME, VALID_REMARK, VALID_TAGS); + String expectedMessage = DateTime.MESSAGE_DATETIME_CONSTRAINTS; + Assert.assertThrows(IllegalValueException.class, expectedMessage, task::toModelType); + } + + @Test + public void toModelType_nullDateTime_throwsIllegalValueException() { + XmlAdaptedTask task = new XmlAdaptedTask(VALID_NAME, null, VALID_REMARK, VALID_TAGS); + String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, task.getActivityType(), "due date/time"); + Assert.assertThrows(IllegalValueException.class, expectedMessage, task::toModelType); + } + + @Test + public void toModelType_invalidTags_throwsIllegalValueException() { + List invalidTags = new ArrayList<>(VALID_TAGS); + invalidTags.add(new XmlAdaptedTag(INVALID_TAG)); + XmlAdaptedTask task = + new XmlAdaptedTask(VALID_NAME, VALID_DATE_TIME, VALID_REMARK, invalidTags); + Assert.assertThrows(IllegalValueException.class, task::toModelType); + } + +} +``` diff --git a/docs/images/App Interface.png b/docs/images/App Interface.png deleted file mode 100644 index 9084bf7a70ea..000000000000 Binary files a/docs/images/App Interface.png and /dev/null differ diff --git a/src/main/java/seedu/address/MainApp.java b/src/main/java/seedu/address/MainApp.java index 831ef9373c50..cdf94ba964fc 100644 --- a/src/main/java/seedu/address/MainApp.java +++ b/src/main/java/seedu/address/MainApp.java @@ -40,7 +40,7 @@ */ public class MainApp extends Application { - public static final Version VERSION = new Version(1, 3, 0, true); + public static final Version VERSION = new Version(1, 4, 0, true); private static final Logger logger = LogsCenter.getLogger(MainApp.class);