diff --git a/collated/docs/A0139922Y.md b/collated/docs/A0139922Y.md new file mode 100644 index 000000000000..a9a2db03363b --- /dev/null +++ b/collated/docs/A0139922Y.md @@ -0,0 +1,409 @@ +# A0139922Y +###### /DeveloperGuide.md +``` md +#### Use case : UC03 - Add Event + +**MSS** + +1. User requests to add new events with its details. +2. Application adds the events with specified details. +3. Application displays successful message. +Use case ends. + +**Extensions** + +1a. User specifies a start date and end date. + +> 1a1. User specifies an invalid date format. +Application shows an error message. +Use case ends. + +1b. User specifies a deadline. + +> 1b1. User specifies an invalid date deadline format. +Application shows an error message. +Use case ends. + +#### Use case : UC04 - Find with specific keyword + +**MSS** + +1. User requests to find tasks with specific keyword/specific keywords. +2. Application shows the list of tasks contains the specific keyword in its name or tag. +Use case ends. + +**Extensions** + +2a. The list is empty. +> 2a1. Application shows an error message. +Use case ends. + +2b. User did not provide any keyword +> 2b1. Application shows an error message. +Use case ends. + +2c. User specifies a start date and end date +> 2c1. User specifies an invalid date format for either start or end date. +Application shows an error message. +Use case ends. + +2d. User specifies a single date +> 2d1. User specifies invalid date format. +Application shows an error message. +Use case ends. + +2e. User did not follow command syntax +> 2e1. Application shows an error message. +Use case ends. + +``` +###### /DeveloperGuide.md +``` md + +#### Use case : UC06 - List by date + +**MSS** + +1. User requests to list all the tasks and events by date. +2. Application shows the list of tasks and events by the date with respective details. +Use case ends. + +**Extensions** + +2a. The list is empty. + +> 2a1. Application shows error message. +Use case ends. + +2b. User did not provide any date. +> Use case ends. + +2c. User provides a single date. +> 2c1. User specifies an invalid date format. +> Application shows error message. +> Use case ends. + +2d. User provide a start date and end date. +> 2c1. User specifies invalid date format for either start or end date. +> Application shows error message. +Use case ends. + +#### Use case : UC07 - List by status + +**MSS** + +1. User requests to list all the tasks and events by status. +2. Application shows the list of tasks or events by status with respective details. +Use case ends. + +**Extensions** + +2a. The list is empty. + +> 2a1. Application shows error message. +Use case ends. + +2b. User specifies status +>2b1. User specifies an invalid task/event status. +Use case ends. + +#### Use case: UC08 - Delete task/event + +**MSS** + +1. Application shows a list of tasks and events. +2. User requests to delete a specific task or event in the list by its respective index. +3. Application deletes the task or event. +4. Application shows a updated list of task and events. +Use case ends. + +**Extensions** + +2a. The list is empty. +> Use case ends. + +3a. The given index is invalid. +> 3a1. Application shows an error message. +Use case ends. + +#### Use case: UC10 - Update task + +**MSS** + +1. Application shows a list of tasks and events. +2. User requests to update a specific task in the list by respective index. +3. Application edits the task. +4. Application shows a updated list of tasks and events. +Use case ends. + +**Extensions** + +2a. The list is empty. +> Use case ends. + +3a. The given index is invalid. +> 3a1. Application shows an error message. +Use case ends. + +3b. The given details are invalid. +> 3b1. User specifies an invalid date format. +> Application shows an error message. +Use case ends. + +> 3b2. User specifies more than one date. +> Application shows an error message. +Use case ends. + +#### Use case: UC11 - Update Events + +**MSS** + +1. Application shows a list of tasks and events. +2. User requests to update a specific event in the list by respective index. +3. Application edits the event. +4. Application shows a updated list of tasks and events. +Use case ends. + +**Extensions** + +2a. The list is empty. +> Use case ends. + +3a. The given index is invalid. +> 3a1. Application shows an error message. +Use case ends. + +3b. The given details are invalid. +> 3b1. User specifies an invalid date format. +> Application shows an error message. +Use case ends. + +``` +###### /DeveloperGuide.md +``` md + +#### Use case: UC14 - Complete task + +**MSS** + +1. Application shows a list of tasks and events. +2. User requests to complete a specific task in the list by respective index. +3. Application completes the task. +4. Application shows a updated list of tasks and events. +Use case ends. + +**Extensions** + +2a. The list is empty. +> Use case ends. + +2a. The given index is invalid. + +> 2a1. The given index is out of range. +> Application shows an error message. +Use case ends. + +>2a2. The given index belongs to an event. +> Application shows an error message. +Use case ends. + +2b. Index is not specified. + +> 2b1. Application shows an error message. +Use case ends. + +#### Use case: UC15 - Uncomplete task + +**MSS** + +1. User requests a list of completed tasks or find completed task with keyword. +2. Application shows a list of completed tasks. +3. User requests to uncomplete a task by respective index. +4. Application uncompletes the task. +5. Application shows the updated list of tasks and events. +Use case ends. + +**Extensions** + +2a. The list is empty. +> Use case ends. + +3a. The given index is invalid. + +> 3a1. The given index is out of range. +> Application shows an error message. +Use case ends. + +3b. Index is not specified. + +> 3b1. Application shows an error message. +Use case ends. + +#### Use case: UC16 - Add tag to a task/event + +**MSS** + +1. Application shows a list of tasks and events. +2. User requests to tag a specific task/event in the list by respective index. +3. Application adds the tag and associated it with the task/event. +4. Application shows a updated list of tasks and events. +Use case ends. + +**Extensions** + +2a. The list is empty. +> Use case ends + +2a. The given index is invalid. + +> 2a1. The given index is out of range. +> Application shows an error message. +Use case ends. + +2b. Index is not specified. + +> 2b1. Application shows an error message. +Use case ends. + +2c. Invalid tag name +> 2c1. Tag name is not specified +> Application shows an error message. +Use case ends. + +> 2c2. Tag name specified is already associated to the task/event. +> Application shows an error message. +Use case ends. + +2d. Tag list size is full +> 2d1. Application shows an error message. +Use case ends. + +#### Use case: UC17 - Untag tag from a task/event + +**MSS** + +1. Application shows a list of tasks and events. +2. User requests to untag the tag of a specific task/event in the list by respective index. +3. Application deletes the tag that is associated to the task/event. +4. Application shows a updated list of tasks and events. +Use case ends. + +**Extensions** + +2a. The list is empty. +> Use case ends + +2a. The given index is invalid. + +> 2a1. The given index is out of range. +> Application shows an error message. +Use case ends. + +2b. Index is not specified. + +> 2b1. Application shows an error message. +Use case ends. + +2c. Invalid tag name +> 2c1. Tag name is not specified. +> Application shows an error message. +Use case ends. + +>2c2. Tag name specified does not belong to the task/event. +> Application shows and error message. +Use case ends. + +``` +###### /DeveloperGuide.md +``` md +5. Should be able to respond to any command within 3 seconds. +6. User-friendly interface +``` +###### /DeveloperGuide.md +``` md +#### Todoist: Strength and Weaknesses + +> Todoist is a task management application, with access to over ten different platforms and the ability to collaborate on tasks. The application is straightforward and quick in providing the user with easy access to the important details of the to-do item. It also encourages people to keep up the habit of clearing existing tasks with its Karma Mode. + +> Moreover, its ease of use and its integration with other services are its true strength. It can integrate with the latest technologies such as Trello and Amazon Echo to keep every to-do item in a single place. + +> However, one flaw with Todoist is that it does not possess any capabilities of having subproject hierarchy. Hence, it would make complex projects' task to be split among the team in an orderly fashion. +``` +###### /UserGuide.md +``` md + +#### Clearing the Database : `clear` + +Clear tasks/events by specific instruction from GetShitDone. + +Format: `clear [event/task] ([(by|on|at) DATE] | [from STARTDATE to ENDDATE])` + +Examples: + +* `clear task` + Clear all tasks in GetShitDone. + +* `clear event to yesterday` + Clear all events up to yesterday [inclusive]. + +#### Tagging an item : `tag` + +Adds a tag to the task. + +Format: `tag INDEX TAG_NAME` + +> Adds the tag for the task at the specified `INDEX`. + The index refers to the index number shown in the most recent listing. + +#### Untagging an item : `untag` + +Removes the specified tag of the task. + +Format: `untag INDEX TAG_NAME` + +> Removes the tag for the task at the specified `INDEX`. + The index refers to the index number shown in the most recent listing. + +Examples: + +* `untag 2 CS2103` + Untag the 2nd task/event of the tag name `CS2103` in GetShitDone. + +* `untag 1 CS2103` + Untag the 1st task/event of the tag name `CS2103` in GetShitDone. + +#### Completing a task : `complete` + +Completes the specified task from GetShitDone. + +Format: `complete INDEX` + +> completes the task at the specified `INDEX`. + The index refers to the index number shown in the most recent listing. + +Examples: + +* `complete 2` + Completes the 2nd task/event in GetShitDone. + +* `complete 1` + Completes the 1st task/event in GetShitDone. + +#### Uncompleting a task : `uncomplete` + +Uncompletes the specified task from GetShitDone. + +Format: `uncomplete INDEX` + +> uncompletes the task at the specified `INDEX`. + The index refers to the index number shown in the most recent listing. + +Examples: + +* `uncomplete 2` + Uncomplete the 2nd task in GetShitDone. + +* `uncomplete 1` + Uncomplete the 1st task in GetShitDone. + +``` diff --git a/collated/main/A0139922Yunused.md b/collated/main/A0139922Yunused.md new file mode 100644 index 000000000000..d2cffa9505a0 --- /dev/null +++ b/collated/main/A0139922Yunused.md @@ -0,0 +1,2288 @@ +# A0139922Yunused +###### /java/seedu/todo/commons/util/DateUtil.java +``` java + /** + * Performs a "ceiling" operation on a LocalDateTime, and returns a new LocalDateTime + * with time set to 23:59. + * + * @param dateTime LocalDateTime for operation to be performed on. + * @return "Ceiled" LocalDateTime. + */ + public static LocalDateTime ceilDate(LocalDateTime dateTime) { + if (dateTime == null) { + return null; + } + + return dateTime.toLocalDate().atTime(23, 59); + } +``` +###### /java/seedu/todo/commons/util/DateUtil.java +``` java + /* + * Check a LocalDateTime if the time is the same as the current time + * + * @param date + * @return true if it is not the same as current time, false if it is the same as current time + */ + public static boolean checkIfTimeExist(LocalDateTime date) { + LocalDateTime currentTime = LocalDateTime.now(); + return currentTime.getHour() != date.getHour() || currentTime.getMinute() != date.getMinute(); + } + +``` +###### /java/seedu/todo/commons/util/DateUtil.java +``` java + /* + * Check a LocalDateTime if the date is the same as the current date + * + * @param date + * @return true if it is not the same as current date, false if it is the same as current date + */ + public static boolean checkIfDateExist(LocalDateTime date) { + LocalDateTime currentDate = LocalDateTime.now(); + return currentDate.getDayOfYear() != date.getDayOfYear() || currentDate.getMonth() != date.getMonth() || + currentDate.getYear() != date.getYear(); + } + +``` +###### /java/seedu/todo/commons/util/DateUtil.java +``` java + /* + * To convert LocalDateTime to 00:00 or 23:59 if not specified + * @param actualDate + * is the date that that is require for checking + * @param checkedDate + * is the date to be used for checking + * @isDateFrom + * if true, actualDate is dateFrom, false if actualDate is dateTo + * + * @return the correct date format + */ + public static LocalDateTime parseTimeStamp(LocalDateTime actualDate, LocalDateTime checkedDate, boolean isDateFrom) { + // Check for date + if (checkedDate != null && actualDate != null && checkIfDateExist(checkedDate) && !checkIfDateExist(actualDate)) { + if (!isDateFrom) { + actualDate = checkedDate.toLocalDate().atTime(actualDate.getHour(), actualDate.getMinute()); + } + } + // Check for time + if (checkedDate != null && actualDate != null && checkIfTimeExist(checkedDate) && !checkIfTimeExist(actualDate)) { + actualDate = actualDate.toLocalDate().atTime(checkedDate.getHour(), checkedDate.getMinute()); + } + if (actualDate != null && !checkIfTimeExist(actualDate)) { + if (isDateFrom) { + actualDate = floorDate(actualDate); + } else { + actualDate = ceilDate(actualDate); + } + } + return actualDate; + } +} +``` +###### /java/seedu/todo/commons/util/FilterUtil.java +``` java +/** + * Helper function to help in filtering results + */ + +public class FilterUtil { + + /*==================== Filtering Methods for Tasks ======================*/ + + /* + * Use to filter out Task items from calendarItems + * + * @param calendarItems + * List of mixture of Task and Event + * @return filteredTasks + * List containing only Task + */ + public static List filterOutTask(List calendarItems) { + List filteredTasks = new ArrayList(); + for (int i = 0; i < calendarItems.size(); i ++) { + if (calendarItems.get(i) instanceof Task) { + filteredTasks.add((Task) calendarItems.get(i)); + } + } + return filteredTasks; + } + + /** + * Filter the task list based on matching task name list + * @param tasks + * Provided list for filtering + * @param namelist + * Search and filter based on the name list + * @return filteredTasks + * List containing only Task that filtered by the item name + */ + public static List filterTaskByNames(List tasks, HashSet nameList) { + // If search list size is 0 , user not searching based on name + List filteredTasks = new ArrayList(); + if (nameList.size() == 0) { + return filteredTasks; + } + + // Loop through all the tasks + for (int i = 0; i < tasks.size(); i ++) { + Task task = tasks.get(i); + + // For every task, loop through all the name list + Iterator nameListIterator = nameList.iterator(); + while (nameListIterator.hasNext()) { + String matchingName = nameListIterator.next(); + if (matchWithFullName(task, matchingName) || matchWithSubName(task, matchingName)) { + filteredTasks.add(task); // Once found, add and break + break; + } + } + // Reset the name list for other task + nameListIterator = nameList.iterator(); + } + return filteredTasks; + } + + /** + * Filter the task list based on matching tag name list + * @param tasks + * Provided list for filtering + * @param namelist + * Search and filter based on the name list + * @return filteredTasks + * List containing only Task that filtered by the tag names + */ + public static List filterTaskByTags(List tasks, HashSet nameList) { + // If no search list is provided, user not searching based on tags + List filteredTasks = new ArrayList(); + if (nameList.size() == 0) { + return filteredTasks; + } + + // Lopp through all the tasks + for (int i = 0; i < tasks.size(); i ++) { + // Get the task tag list + Task task = tasks.get(i); + ArrayList taskTagList = task.getTagList(); + + // Loop through the tag names list + Iterator nameListIterator = nameList.iterator(); + while (nameListIterator.hasNext()) { + String currentMatchingName = nameListIterator.next(); + if (taskTagList.contains(currentMatchingName)) { + filteredTasks.add(task); // Once found a matching tag, add and break; + break; + } + } + nameListIterator = nameList.iterator(); + } + return filteredTasks; + } + + /** + * Filter the task list based on incomplete status + * @param tasks + * Provided list for filtering + * @param taskStatus + * True if searching for is completed, false if search for incomplete. + * @return filteredTasks + * List containing only Task that filtered by status (e.g. complete or incomplete) + */ + public static List filterTasksByStatus(List tasks, boolean taskStatus) { + // If tasks is empty, return immediately + if (tasks.size() == 0) { + return tasks; + } + + List filteredTasks = new ArrayList(); + // Loop through all the tasks + for (int i = 0; i < tasks.size(); i ++) { + Task task = tasks.get(i); + // Check if it is the same as the required task status + if (task.isCompleted() == taskStatus) { + filteredTasks.add(task); //Add any task has the same task status + } + } + return filteredTasks; + } + + /** + * Filter the task list based on single date + * @param tasks + * Provided list for filtering + * @param date + * Search based on this date + * @return filteredTasks + * List containing only Task that filtered by a single date + */ + public static List filterTaskBySingleDate(List tasks, LocalDateTime date) { + // If tasks is empty, return immediately + if (tasks.size() == 0) { + return tasks; + } + + ArrayList filteredTasks = new ArrayList(); + // Loop through all the tasks + Iterator iterator = tasks.iterator(); + while (iterator.hasNext()) { + Task task = iterator.next(); + // Searched date should not be null, break out if it is. + assert date != null; + // Check if task start date is the same as the searched date + date = DateUtil.floorDate(date); + LocalDateTime taskDate = DateUtil.floorDate(task.getCalendarDateTime()); + + // May have floating tasks, skip floating tasks + if (taskDate != null && taskDate.equals(date)) { + filteredTasks.add(task); + } + } + return filteredTasks; + } + + /** + * Filter the task list with a date range + * @param tasks + * Provided list for filtering + * @param startDate + * Search based on this as starting date + * @param endDate + * Search based on this as ending date + * @return filteredTasks + * List containing only Task that filtered by a range of two dates + */ + public static List filterTaskWithDateRange(List tasks, LocalDateTime startDate, LocalDateTime endDate) { + // If tasks is empty, return immediately + if (tasks.size() == 0) { + return tasks; + } + + // If start date is null, set it to MIN dateTime, user could searched by "from today" + if (startDate == null) { + startDate = LocalDateTime.MIN; + } + + // If end date is null, set it to MAX dateTime, user could searched by "to today" + if (endDate == null) { + endDate = LocalDateTime.MAX; + } + + ArrayList filteredTasks = new ArrayList(); + // Loop through all the tasks + Iterator iterator = tasks.iterator(); + while (iterator.hasNext()) { + Task task = iterator.next(); + LocalDateTime taskDate = DateUtil.floorDate(task.getDueDate()); + // May have floating task, set the date to MIN dateTime, to avoid been filtered + if (taskDate == null) { + taskDate = LocalDateTime.MIN; + } + + // Set the searched date to its min and max value + startDate = DateUtil.floorDate(startDate); + endDate = DateUtil.ceilDate(endDate); + // Compare if the task date is within the range of start and end date + if (taskDate.compareTo(startDate) >= 0 && taskDate.compareTo(endDate) <= 0) { + filteredTasks.add(task); // Add if it is within the range + } + } + return filteredTasks; + } + + /*==================== Filtering Methods for Events ======================*/ + + /* + * Use to filter out Event items from calendarItems + * + * @param calendarItems + * List of mixture of Task and Event + * @return filteredTasks + * List containing only Event + */ + public static List filterOutEvent(List calendarItems) { + List filteredEvents = new ArrayList(); + for (int i = 0; i < calendarItems.size(); i ++) { + if (calendarItems.get(i) instanceof Event) { + filteredEvents.add((Event) calendarItems.get(i)); + } + } + return filteredEvents; + } + + /** + * Filter the event list based on event name list + * @param events + * Provided list for filtering + * @param namelist + * Search and filter based on the name list + * @return filteredEvents + * List containing only Event that event name matches with the item name + */ + public static List filterEventByNames(List events, HashSet nameList) { + List filteredEvents = new ArrayList(); + // If name list size is 0, means not searching by name list + if (nameList.size() == 0) { + return filteredEvents; + } + + // Lopp through all the events + for (int i = 0; i < events.size(); i ++) { + Event event = events.get(i); + // Loop through all the name list + Iterator nameListIterator = nameList.iterator(); + while (nameListIterator.hasNext()) { + String matchingName = nameListIterator.next().toLowerCase(); + // If found a match with its full name or sub names, break + if (matchWithFullName(event, matchingName) || matchWithSubName(event, matchingName)) { + filteredEvents.add(event); + break; + } + } + // Reset the nameList for the next event + nameListIterator = nameList.iterator(); + } + return filteredEvents; + } + + /** + * Filter the event list based on tag name list + * @param events + * Provided list for filtering + * @param namelist + * Search and filter based on the name list + * @return filteredEvents + * List containing only Event that tag names matches with the tag name + */ + public static List filterEventByTags(List events, HashSet nameList) { + List filteredEvents = new ArrayList(); + // If name list size is 0, means not searching by tags + if (nameList.size() == 0) { + return filteredEvents; + } + + // Loop through all the events + for (int i = 0; i < events.size(); i ++) { + Event event = events.get(i); + // Get the tag list of the event + ArrayList taskTagList = event.getTagList(); + Iterator nameListIterator = nameList.iterator(); + // Loop through the tag names list + while (nameListIterator.hasNext()) { + String currentMatchingName = nameListIterator.next(); + // If found a match, add and break + if (taskTagList.contains(currentMatchingName)) { + filteredEvents.add(event); + break; + } + } + // Reset the tag names list for the next event + nameListIterator = nameList.iterator(); + } + return filteredEvents; + } + + /** + * Filter the event list if the event date is over + * @param events + * Provided list for filtering + * @param isEventOver + * True if searching for event that are over, false if searching for current event + * @return filteredEvents + * List containing only Event that status matches with the status, For e.g. over or current + */ + public static List filterEventsByStatus(List events, boolean eventStatus) { + // If events is empty, return immediately + if (events.size() == 0) { + return events; + } + + List filteredEvents = new ArrayList(); + // Loop through the events + for (int i = 0; i < events.size(); i ++) { + Event event = events.get(i); + // Add into filteredEvents, once the status of the event matches + if (event.isOver() == eventStatus) { + filteredEvents.add(event); + } + } + return filteredEvents; + } + + /** + * Filter the event list based on single date + * @param events + * Provided list for filtering + * @param date + * Search based on this date + * @return filteredEvents + * List containing only Event date that matches with searched date + */ + public static List filterEventBySingleDate(List events, LocalDateTime date) { + // If events is empty, return immediately + if (events.size() == 0) { + return events; + } + + ArrayList filteredEvents = new ArrayList(); + // Loop through all the events + Iterator iterator = events.iterator(); + while (iterator.hasNext()) { + Event event = iterator.next(); + // Search dates cannot be null + assert date != null; + date = DateUtil.floorDate(date); + + // Event start date should not be null + assert event.getStartDate() != null; + LocalDateTime eventDate = DateUtil.floorDate(event.getStartDate()); + + // Check against start date, if equals add it in + if (eventDate.equals(date)) { + filteredEvents.add(event); + } + } + return filteredEvents; + } + + /** + * Filter the event list with range of dates + * @param events + * Provided list for filtering + * @param startDate + * Search based on this as starting date + * @param endDate + * Search based on this as ending date + * @return filteredEvents + * List containing only Event that date fall between startDate and endDate + */ + public static List filterEventWithDateRange(List events, LocalDateTime startDate, LocalDateTime endDate) { + // If events is empty, return immediately + if (events.size() == 0) { + return events; + } + + // Set startDate to MIN, user could search "from Today" + if (startDate == null) { + startDate = LocalDateTime.MIN; + } + + // Set endDate to MaX, user could search "to Today" + if (endDate == null) { + endDate = LocalDateTime.MAX; + } + + ArrayList filteredEvents = new ArrayList(); + Iterator iterator = events.iterator(); + // Loop through all the events + while (iterator.hasNext()) { + Event event = iterator.next(); + // Event dates should not be null + assert event.getStartDate() != null; + assert event.getEndDate() != null; + LocalDateTime eventStartDate = DateUtil.floorDate(event.getStartDate()); + LocalDateTime eventEndDate = DateUtil.floorDate(event.getEndDate()); + + // Check if the event start dates and end dates is within the search dates + startDate = DateUtil.floorDate(startDate); + endDate = DateUtil.ceilDate(endDate); + if (eventStartDate.compareTo(startDate) >= 0 && eventEndDate.compareTo(endDate) <= 0) { + filteredEvents.add(event); + } + } + return filteredEvents; + } + + /*==================== Helper Methods to Check Command Conflict ===================================*/ + + /* + * To be use to check if there are more than 1 event type entered by user + * + * @return true if more than 1 event type found, false, if only 1 or 0 event type found + */ + public static boolean isItemTypeConflict(String input) { + return input.contains("task") && input.contains("event"); + } + + /*==================== Helper Methods for filtering CalendarItem name ======================*/ + + /* + * Use to check if calendarItem name starts with the matching name + * + * @return true if it calendarItem's name starts with the matching name, + * false if calendarItem's name does not starts with matching name + */ + private static boolean matchWithFullName(CalendarItem calendarItem, String matchingName) { + String taskName = calendarItem.getName().toLowerCase(); + return taskName.startsWith(matchingName.toLowerCase()); + } + + /* + * Use to check if calendarItem name split by space starts with the matching name + * + * @return true if any of the calendarItem's name that is split by space that starts with the matching name, + * false if calendarItem's name that is split by space does not starts with matching name + */ + private static boolean matchWithSubName(CalendarItem calendarItem, String matchingName) { + String[] nameBySpace = StringUtil.splitStringBySpace(calendarItem.getName()); + for (int i = 0; i < nameBySpace.length; i ++) { + if (nameBySpace[i].toLowerCase().startsWith(matchingName.toLowerCase())) { + return true; + } + } + return false; + } + +} +``` +###### /java/seedu/todo/commons/util/ParseUtil.java +``` java +/** + * Helper functions for parsing. + */ +public class ParseUtil { + private static final int TOKEN_INDEX = 0; + private static final int TOKEN_RESULT_INDEX = 1; + + /* + * To be used to check if there exist an item tagged with the token + */ + public static boolean isTokenNull(Map parsedResult, String token) { + return parsedResult.get(token) == null || parsedResult.get(token)[TOKEN_INDEX] == null; + } + /* + * To check if parsedResult with the token containing the keyword provided + * + * @return true if keyword is found, false if it is not found + */ + public static boolean doesTokenContainKeyword(Map parsedResult, String token, String keyword) { + if (!isTokenNull(parsedResult, token)) { + return parsedResult.get(token)[TOKEN_INDEX].contains(keyword); + } + return false; + } + + /* + * To be used to get input from token + * + * @return the parsed result from tokenizer + */ + public static String getTokenResult(Map parsedResult, String token) { + if(!isTokenNull(parsedResult, token)) { + return parsedResult.get(token)[TOKEN_RESULT_INDEX]; + } + return null; + } + + /** + * Extracts the natural dates from parsedResult. + * + * @param parsedResult + * @return { numOfdateFound, naturalOn, naturalFrom, naturalTo } + */ + public static String[] parseDates(Map parsedResult) { + String naturalFrom = getTokenResult(parsedResult, "timeFrom"); + String naturalTo = getTokenResult(parsedResult, "timeTo"); + String naturalOn = getTokenResult(parsedResult, "time"); + int numOfDateFound = 0; + + String [] dateResult = { null, naturalOn, naturalFrom, naturalTo }; + for (int i = 0; i < dateResult.length; i ++) { + if (dateResult[i] != null) { + numOfDateFound ++; + } + } + + if (numOfDateFound == 0) { + return null; + } else { + dateResult[0] = Integer.toString(numOfDateFound); + } + + return dateResult; + } +} +``` +###### /java/seedu/todo/commons/util/StringUtil.java +``` java + /* + * Format the display message depending on the number of tasks and events + * + * @param numTasks + * the number of tasks found + * @param numEvents + * the number of events found + * + * @return the display message for console message output + */ + public static String displayNumberOfTaskAndEventFoundWithPuralizer (int numTasks, int numEvents) { + if (numTasks != 0 && numEvents != 0) { + return String.format("%s and %s", formatNumberOfTaskWithPuralizer(numTasks), formatNumberOfEventWithPuralizer(numEvents)); + } else if (numTasks != 0) { + return formatNumberOfTaskWithPuralizer(numTasks); + } else if (numEvents != 0){ + return formatNumberOfEventWithPuralizer(numEvents); + } else { + return "No item found!"; + } + } + + /* + * Format the number of events found based on the events found + * + * @param numEvents + * the number of events found + */ + public static String formatNumberOfEventWithPuralizer (int numEvents) { + return String.format("%d %s", numEvents, pluralizer(numEvents, "event", "events")); + } + + /* + * Format the number of tasks found based on the tasks found + * + * @param numTasks + * the number of tasks found + */ + public static String formatNumberOfTaskWithPuralizer (int numTasks) { + return String.format("%d %s", numTasks, pluralizer(numTasks, "task", "tasks")); + } +``` +###### /java/seedu/todo/commons/util/StringUtil.java +``` java + /* + * Convert input into individual input by splitting with space + */ + public static String[] splitStringBySpace(String input) { + return (input == null) ? null : input.trim().split(" "); + } +} +``` +###### /java/seedu/todo/controllers/ClearController.java +``` java +/** + * Controller to clear task/event by Type + */ +public class ClearController implements Controller { + + private static final String NAME = "Clear"; + private static final String DESCRIPTION = "Clear all tasks/events or by specify date."; + private static final String COMMAND_WORD = "clear"; + + // Syntax correction to console input + public static final String COMMAND_SYNTAX = "clear \"task/event\" on \"date\""; + public static final String CLEAR_DATE_SYNTAX = "clear \"date\" [or from \"date\" to \"date\"]"; + + // Message output to console text area + public static final String MESSAGE_CLEAR_SUCCESS_FORMAT = "A total of %s deleted!"; + public static final String MESSAGE_CLEAR_NO_ITEM_FOUND = "No item found!"; + public static final String MESSAGE_CLEAR_ALL_SUCCESS = "All tasks and events have been deleted!\n" + "To undo, type \"undo\"."; + public static final String MESSAGE_CLEAR_UNABLE_TO_SUPPORT = "Unable to clear!\nCannot clear by status!"; + public static final String MESSAGE_DATE_CONFLICT = "Unable to clear!\nMore than 1 date criteria is provided!"; + public static final String MESSAGE_NO_DATE_DETECTED = "Unable to clear!\nThe natural date entered is not supported."; + public static final String MESSAGE_ITEM_TYPE_CONFLICT = "Unable to clear!\nMore than 1 item type is provided!"; + + // Use to access parsing of dates + private static final int NUM_OF_DATES_FOUND_INDEX = 0; + private static final int COMMAND_INPUT_INDEX = 0; + private static final int DATE_CRITERIA_INDEX = 0; + private static final int DATE_ON_INDEX = 1; + private static final int DATE_FROM_INDEX = 2; + private static final int DATE_TO_INDEX = 3; + + private static CommandDefinition commandDefinition = + new CommandDefinition(NAME, DESCRIPTION, COMMAND_SYNTAX); + + public static CommandDefinition getCommandDefinition() { + return commandDefinition; + } + + @Override + public float inputConfidence(String input) { + return (StringUtil.splitStringBySpace(input.toLowerCase())[COMMAND_INPUT_INDEX]).equals(COMMAND_WORD) ? 1 : 0; + } + + /** + * Get the token definitions for use with tokenizer.
+ * This method exists primarily because Java does not support HashMap + * literals... + * + * @return tokenDefinitions + */ + private static Map getTokenDefinitions() { + Map tokenDefinitions = new HashMap(); + tokenDefinitions.put(Tokenizer.DEFAULT_TOKEN, new String[] { COMMAND_WORD }); + tokenDefinitions.put(Tokenizer.EVENT_TYPE_TOKEN, Tokenizer.EVENT_TYPE_DEFINITION); + tokenDefinitions.put(Tokenizer.TIME_TOKEN, Tokenizer.TIME_DEFINITION); + tokenDefinitions.put(Tokenizer.TASK_STATUS_TOKEN, Tokenizer.TASK_STATUS_DEFINITION); + tokenDefinitions.put(Tokenizer.EVENT_STATUS_TOKEN, Tokenizer.EVENT_STATUS_DEFINITION); + tokenDefinitions.put(Tokenizer.TIME_FROM_TOKEN, Tokenizer.TIME_FROM_DEFINITION); + tokenDefinitions.put(Tokenizer.TIME_TO_TOKEN, Tokenizer.TIME_TO_DEFINITION); + return tokenDefinitions; + } + + @Override + public void process(String input) throws ParseException { + Map parsedResult; + parsedResult = Tokenizer.tokenize(getTokenDefinitions(), input); + TodoListDB db = TodoListDB.getInstance(); + + if (input.trim().equals(COMMAND_WORD)) { + db.destroyAllTaskAndEvents(); + Renderer.renderIndex(db, MESSAGE_CLEAR_ALL_SUCCESS); + return; // Clear all + } + + boolean isItemTypeProvided = !ParseUtil.isTokenNull(parsedResult, Tokenizer.EVENT_TYPE_TOKEN); + boolean isTaskStatusProvided = !ParseUtil.isTokenNull(parsedResult, Tokenizer.TASK_STATUS_TOKEN); + boolean isEventStatusProvided = !ParseUtil.isTokenNull(parsedResult, Tokenizer.EVENT_STATUS_TOKEN); + + if (isErrorCommand(isTaskStatusProvided, isEventStatusProvided, input)) { + return; // Break out if found error + } + + boolean isTask = true; //default + if (isItemTypeProvided) { + isTask = ParseUtil.doesTokenContainKeyword(parsedResult, Tokenizer.EVENT_TYPE_TOKEN, "task"); + } + + LocalDateTime [] validDates = parsingDates(parsedResult); + if (validDates == null) { + return; // Break out when date conflict found + } + + // Setting up view + List tasks; //default + List events; //default + List calendarItems; + // Filter Task and Event by Type + if (!isItemTypeProvided) { + tasks = db.getAllTasks(); + events = db.getAllEvents(); + } else { + if (isTask) { + events = new ArrayList(); + tasks = db.getAllTasks(); + } else { + tasks = new ArrayList(); + events = db.getAllEvents(); + } + } + + // Filter Task and Event by date + calendarItems = filterTasksAndEventsByDate(tasks, events, parsedResult); + if (calendarItems == null) { + return; // Date conflict detected + } + tasks = FilterUtil.filterOutTask(calendarItems); + events = FilterUtil.filterOutEvent(calendarItems); + + // Show message if no items had been found + if (tasks.size() == 0 && events.size() == 0) { + Renderer.renderIndex(db, MESSAGE_CLEAR_NO_ITEM_FOUND); + return; + } + + deleteSelectedTasksAndEvents(tasks, events, db); + } + + /*====================== Helper Methods to check for Error/Syntax Command ===================*/ + + /* + * To be used to parsed dates and check for any dates conflict + * + * @return null if dates conflict detected, else return { dateCriteria, dateOn, dateFrom, dateTo } + */ + private LocalDateTime[] parsingDates(Map parsedResult) { + String[] parsedDates = ParseUtil.parseDates(parsedResult); + //date enter with COMMAND_WORD e.g list today + String date = ParseUtil.getTokenResult(parsedResult, Tokenizer.DEFAULT_TOKEN); + + if (date != null && parsedDates != null) { + Renderer.renderDisambiguation(CLEAR_DATE_SYNTAX, MESSAGE_DATE_CONFLICT); + return null; + } + + LocalDateTime dateCriteria = null; + LocalDateTime dateOn = null; + LocalDateTime dateFrom = null; + LocalDateTime dateTo = null; + + if (date != null) { + try { + dateCriteria = DateParser.parseNatural(date); + } catch (InvalidNaturalDateException e) { + Renderer.renderDisambiguation(CLEAR_DATE_SYNTAX, MESSAGE_NO_DATE_DETECTED); + return null; + } + } + + if (parsedDates != null) { + String naturalOn = parsedDates[DATE_ON_INDEX]; + String naturalFrom = parsedDates[DATE_FROM_INDEX]; + String naturalTo = parsedDates[DATE_TO_INDEX]; + if (naturalOn != null && Integer.parseInt(parsedDates[NUM_OF_DATES_FOUND_INDEX]) > 1) { + //date conflict detected + Renderer.renderDisambiguation(CLEAR_DATE_SYNTAX, MESSAGE_DATE_CONFLICT); + return null; + } + // Parse natural date using Natty. + try { + dateOn = naturalOn == null ? null : DateUtil.floorDate(DateParser.parseNatural(naturalOn)); + dateFrom = naturalFrom == null ? null : DateUtil.floorDate(DateParser.parseNatural(naturalFrom)); + dateTo = naturalTo == null ? null : DateUtil.floorDate(DateParser.parseNatural(naturalTo)); + } catch (InvalidNaturalDateException e) { + Renderer.renderDisambiguation(CLEAR_DATE_SYNTAX, MESSAGE_NO_DATE_DETECTED); + return null; + } + } + return new LocalDateTime[] { dateCriteria, dateOn, dateFrom, dateTo }; + } + + /* + * To be use to check if there are any command syntax error + * + * @return true, if there is error in command syntax, false if syntax is allowed + */ + private boolean isErrorCommand(boolean isTaskStatusProvided, boolean isEventStatusProvided, String input) { + // Check if any status is provided + if (isTaskStatusProvided || isEventStatusProvided) { + Renderer.renderDisambiguation(COMMAND_SYNTAX, MESSAGE_CLEAR_UNABLE_TO_SUPPORT); + return true; + } + // Check if more than 1 item type is provided + if (FilterUtil.isItemTypeConflict(input)) { + Renderer.renderDisambiguation(COMMAND_SYNTAX, MESSAGE_ITEM_TYPE_CONFLICT); + return true; + } + return false; + } + + /* =================== Helper methods to filter out Task and Events ==================*/ + + /* + * Filter out the selected tasks and events based on the dates + * and update tasks and events accordingly + * + * @param tasks + * List of Task items + * @param events + * List of Event items + * @param parsedResult + * parsedResult by Tokenizer + * @return + * tasks and events in a list form by date or null when date conflict found + */ + private List filterTasksAndEventsByDate(List tasks, List events, Map parsedResult) { + // Get dates from input + List calendarItems = new ArrayList(); + LocalDateTime [] validDates = parsingDates(parsedResult); + List filteredTasks = tasks; + List filteredEvents = events; + if (validDates == null) { + return null; // Break out when date conflict found + } + + // Set dates that are found, if not found value will be null + LocalDateTime dateCriteria = validDates[DATE_CRITERIA_INDEX]; + LocalDateTime dateOn = validDates[DATE_ON_INDEX]; + LocalDateTime dateFrom = validDates[DATE_FROM_INDEX]; + LocalDateTime dateTo = validDates[DATE_TO_INDEX]; + + if (dateCriteria != null) { + // Filter by single date + assert dateOn == null; + assert dateFrom == null; + assert dateTo == null; + filteredTasks = FilterUtil.filterTaskBySingleDate(tasks, dateCriteria); + filteredEvents = FilterUtil.filterEventBySingleDate(events, dateCriteria); + } + + if (dateOn != null) { + // Filter by single date + filteredTasks = FilterUtil.filterTaskBySingleDate(tasks, dateOn); + filteredEvents = FilterUtil.filterEventBySingleDate(events, dateOn); + } else if (dateFrom != null || dateTo != null) { + // Filter by range + filteredTasks = FilterUtil.filterTaskWithDateRange(tasks, dateFrom, dateTo); + filteredEvents =FilterUtil.filterEventWithDateRange(events, dateFrom, dateTo); + } + + calendarItems.addAll(filteredTasks); + calendarItems.addAll(filteredEvents); + return calendarItems; + } + + /* =============== Helper Methods to delete selected Tasks and Events ============*/ + + /* + * Delete the selected Tasks and Events , filtered out by helper methods + * + * @param tasks + * A list of Task that already been filtered for deletion + * @param events + * A list of Event that already been filtered for deletion + * @param db + * The same instance of db used to filtered out both tasks and events + */ + private void deleteSelectedTasksAndEvents(List tasks, List events, TodoListDB db) { + db.destroyAllTaskAndEventsByList(tasks, events); + String consoleMessage = String.format(MESSAGE_CLEAR_SUCCESS_FORMAT, + StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(tasks.size(), events.size())); + Renderer.renderIndex(db, consoleMessage); + } +} +``` +###### /java/seedu/todo/controllers/FindController.java +``` java +/** + * Controller to find task/event by keyword + */ +public class FindController implements Controller { + + private static final String NAME = "Find"; + private static final String DESCRIPTION = "Find all tasks and events based on the provided keywords.\n" + + "This command will be searching with non-case sensitive keywords."; + private static final String COMMAND_WORD = "find"; + + // Syntax correction to console input + public static final String COMMAND_SYNTAX = "find \"name\" tagName \"tag\" on \"date\" \"task/event\""; + public static final String FIND_TASK_SYNTAX = "find \"name\" task \"complete/incomplete\""; + public static final String FIND_EVENT_SYNTAX = "find \"name\" event \"over/ongoing\""; + + // Message output to console text area + public static final String MESSAGE_RESULT_FOUND_FORMAT = "A total of %s found!"; + public static final String MESSAGE_NO_RESULT_FOUND = "No task or event found!"; + public static final String MESSAGE_NO_KEYWORD_FOUND = "No keyword found!"; + public static final String MESSAGE_DATE_CONFLICT = "Unable to find!\nMore than 1 date criteria is provided!"; + public static final String MESSAGE_NO_DATE_DETECTED = "Unable to find!\nThe natural date entered is not supported."; + public static final String MESSAGE_INVALID_TASK_STATUS = "Unable to find!\nTry searching with complete or incomplete"; + public static final String MESSAGE_INVALID_EVENT_STATUS = "Unable to find!\nTry searching with over or current"; + public static final String MESSAGE_ITEM_TYPE_CONFLICT = "Unable to list!\nMore than 1 item type is provided!"; + + private static final int COMMAND_INPUT_INDEX = 0; + //use to access parsing of dates + private static final int NUM_OF_DATES_FOUND_INDEX = 0; + private static final int DATE_ON_INDEX = 1; + private static final int DATE_FROM_INDEX = 2; + private static final int DATE_TO_INDEX = 3; + + private static CommandDefinition commandDefinition = + new CommandDefinition(NAME, DESCRIPTION, COMMAND_SYNTAX); + + public static CommandDefinition getCommandDefinition() { + return commandDefinition; + } + + @Override + public float inputConfidence(String input) { + String command = StringUtil.splitStringBySpace(input.toLowerCase())[COMMAND_INPUT_INDEX]; + return (command).equals(COMMAND_WORD) ? 1 : 0; + } + + private static Map getTokenDefinitions() { + Map tokenDefinitions = new HashMap(); + tokenDefinitions.put(Tokenizer.DEFAULT_TOKEN, new String[] { COMMAND_WORD }); + tokenDefinitions.put(Tokenizer.EVENT_TYPE_TOKEN, Tokenizer.EVENT_TYPE_DEFINITION); + tokenDefinitions.put(Tokenizer.TIME_TOKEN, Tokenizer.TIME_DEFINITION); + tokenDefinitions.put(Tokenizer.TASK_STATUS_TOKEN, Tokenizer.TASK_STATUS_DEFINITION); + tokenDefinitions.put(Tokenizer.EVENT_STATUS_TOKEN, Tokenizer.EVENT_STATUS_DEFINITION); + tokenDefinitions.put(Tokenizer.TIME_FROM_TOKEN, Tokenizer.TIME_FROM_DEFINITION); + tokenDefinitions.put(Tokenizer.TIME_TO_TOKEN, Tokenizer.TIME_TO_DEFINITION); + tokenDefinitions.put(Tokenizer.ITEM_NAME_TOKEN, Tokenizer.ITEM_NAME_DEFINITION); + tokenDefinitions.put(Tokenizer.TAG_NAME_TOKEN, Tokenizer.TAG_NAME_DEFINITION); + return tokenDefinitions; + } + + @Override + public void process(String input) throws ParseException { + + Map parsedResult; + parsedResult = Tokenizer.tokenize(getTokenDefinitions(), input); + + HashSet itemNameList = new HashSet(); + HashSet tagNameList = new HashSet(); + HashSet keywordList = new HashSet(); + + // To be use to be filter out name and tag names + updateHashList(parsedResult, keywordList, Tokenizer.DEFAULT_TOKEN); + updateHashList(parsedResult, itemNameList, Tokenizer.ITEM_NAME_TOKEN); + updateHashList(parsedResult, tagNameList, Tokenizer.TAG_NAME_TOKEN); + itemNameList.addAll(keywordList); + tagNameList.addAll(keywordList); + + // Show console output message, since no keyword found + if (keywordList.size() == 0 && itemNameList.size() == 0 && tagNameList.size() == 0) { + //No keyword provided, display error + Renderer.renderDisambiguation(COMMAND_SYNTAX, MESSAGE_NO_KEYWORD_FOUND); + return; + } + + // Check if input includes itemType and itemStatus + boolean isItemTypeProvided = !ParseUtil.isTokenNull(parsedResult, Tokenizer.EVENT_TYPE_TOKEN); + boolean isTaskStatusProvided = !ParseUtil.isTokenNull(parsedResult, Tokenizer.TASK_STATUS_TOKEN); + boolean isEventStatusProvided = !ParseUtil.isTokenNull(parsedResult, Tokenizer.EVENT_STATUS_TOKEN); + + // Set item type + boolean isTask = true; //default + if (isItemTypeProvided) { + isTask = ParseUtil.doesTokenContainKeyword(parsedResult, Tokenizer.EVENT_TYPE_TOKEN, "task"); + } + + if (isErrorCommand(isTaskStatusProvided, isEventStatusProvided, isTask, isItemTypeProvided, input)) { + return; // Break out if found error + } + + // Setting up view + TodoListDB db = TodoListDB.getInstance(); + List tasks; //default + List events; //default + List calendarItems; + + // Filter out the tasks and events based on type and names + if (!isItemTypeProvided) { + tasks = filterByTaskNameAndTagName(itemNameList, tagNameList, db.getAllTasks()); + events = filterByEventNameAndTagName(itemNameList, tagNameList, db.getAllEvents()); + } else { + if (isTask) { + events = new ArrayList(); + tasks = filterByTaskNameAndTagName(itemNameList, tagNameList, db.getAllTasks()); + } else { + tasks = new ArrayList(); + events = filterByEventNameAndTagName(itemNameList, tagNameList, db.getAllEvents()); + } + } + + // Filter Task and Event by Status + calendarItems = filterTasksAndEventsByStatus(parsedResult, isTaskStatusProvided, isEventStatusProvided, tasks, events); + tasks = FilterUtil.filterOutTask(calendarItems); + events = FilterUtil.filterOutEvent(calendarItems); + + // Filter Task and Event by date + calendarItems = filterTasksAndEventsByDate(tasks, events, parsedResult); + if (calendarItems == null) { + return; // Date conflict detected + } + tasks = FilterUtil.filterOutTask(calendarItems); + events = FilterUtil.filterOutEvent(calendarItems); + + // Show message if no items had been found + if (tasks.size() == 0 && events.size() == 0) { + Renderer.renderIndex(db, MESSAGE_NO_RESULT_FOUND); + return; + } + + String consoleMessage = String.format(MESSAGE_RESULT_FOUND_FORMAT, + StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(tasks.size(), events.size())); + Renderer.renderSelectedIndex(db, consoleMessage, tasks, events); + } + + /*======================== Helper Methods to filter tasks and events ========================================*/ + + /* + * Filter out the selected tasks and events based on the status and update tasks and events accordingly + * + * @param parsedResult + * parsedResult by Tokenizer + * @param isTaskStatusProvided + * true if complete or incomplete is found, else false + * @param isEventStatusProvided + * true if over or current is found, else false + * @param tasks + * List of Task items + * @param events + * List of Event items + * @return + * tasks and events in a list form by status + */ + private List filterTasksAndEventsByStatus(Map parsedResult, boolean isTaskStatusProvided, + boolean isEventStatusProvided, List tasks, List events) { + List calendarItems = new ArrayList(); + // Set item status + boolean isCompleted = false; //default + boolean isOver = false; //default + List filteredTasks = tasks; + List filteredEvents = events; + + // Filter out by Task Status if provided + if (isTaskStatusProvided) { + isCompleted = !ParseUtil.doesTokenContainKeyword(parsedResult, Tokenizer.TASK_STATUS_TOKEN, "incomplete"); + filteredTasks = FilterUtil.filterTasksByStatus(tasks, isCompleted); + filteredEvents = new ArrayList(); + } + + // Filter out by Event Status if provided + if (isEventStatusProvided) { + isOver = ParseUtil.doesTokenContainKeyword(parsedResult, Tokenizer.EVENT_STATUS_TOKEN, "over"); + filteredEvents = FilterUtil.filterEventsByStatus(events, isOver); + filteredTasks = new ArrayList(); + } + calendarItems.addAll(filteredTasks); + calendarItems.addAll(filteredEvents); + return calendarItems; + } + + /* + * Filter out the selected tasks and events based on the dates + * and update tasks and events accordingly + * + * @param tasks + * List of Task items + * @param events + * List of Event items + * @param parsedResult + * parsedResult by Tokenizer + * @return + * tasks and events in a list form by date or null when date conflict found + */ + private List filterTasksAndEventsByDate(List tasks, List events, + Map parsedResult) { + // Get dates from input + List calendarItems = new ArrayList(); + LocalDateTime [] validDates = parsingDates(parsedResult); + List filteredTasks; + List filteredEvents; + if (validDates == null) { + return null; // Break out when date conflict found + } + + // Set dates that are found, if not found value will be null + LocalDateTime dateOn = validDates[DATE_ON_INDEX]; + LocalDateTime dateFrom = validDates[DATE_FROM_INDEX]; + LocalDateTime dateTo = validDates[DATE_TO_INDEX]; + + if (dateOn != null) { + // Filter by single date + filteredTasks = FilterUtil.filterTaskBySingleDate(tasks, dateOn); + filteredEvents = FilterUtil.filterEventBySingleDate(events, dateOn); + } else { + // Filter by range + filteredTasks = FilterUtil.filterTaskWithDateRange(tasks, dateFrom, dateTo); + filteredEvents = FilterUtil.filterEventWithDateRange(events, dateFrom, dateTo); + } + calendarItems.addAll(filteredTasks); + calendarItems.addAll(filteredEvents); + return calendarItems; + } + + /* + * Filter out all the events based on the name list that has been parsed. + * This method also ensure that no duplicate event will be return. + * + * @param itemNameList + * a list of item name that has been parsed from input + * @param tagNameList + * a List of tag name that has been parsed from input + * @param events + * all the events in the DB + * @return a list of Event which names or tag names is filtered with the list + */ + private List filterByEventNameAndTagName(HashSet itemNameList, HashSet tagNameList, + List events) { + HashSet mergedEvents = new HashSet(); + List eventsByNames = FilterUtil.filterEventByNames(events, itemNameList); + List eventsByTags = FilterUtil.filterEventByTags(events, tagNameList); + mergedEvents.addAll(eventsByNames); + mergedEvents.addAll(eventsByTags); + events = new ArrayList(mergedEvents); + return events; + } + + /* + * Filter out all the tasks based on the name list that has been parsed. + * This method also ensure that no duplicate task will be return. + * + * @param itemNameList + * a list of item name that has been parsed from input + * @param tagNameList + * a List of tag name that has been parsed from input + * @param tasks + * all the tasks in the DB + * @return a list of Task which names or tag names is filtered with the list + */ + private List filterByTaskNameAndTagName(HashSet itemNameList, HashSet tagNameList, + List tasks) { + HashSet mergedTasks = new HashSet(); + List tasksByNames = FilterUtil.filterTaskByNames(tasks, itemNameList); + List tasksByTags = FilterUtil.filterTaskByTags(tasks, tagNameList); + mergedTasks.addAll(tasksByNames); + mergedTasks.addAll(tasksByTags); + tasks = new ArrayList(mergedTasks); + return tasks; + } + + /** + * Extract the parsed result and update into the hashlist + * @param parsedResult + */ + private void updateHashList(Map parsedResult, HashSet hashList, + String token) { + String result = ParseUtil.getTokenResult(parsedResult, token); + // If found any matching , update list + if (result != null) { + hashList.add(result); + String[] resultArray = StringUtil.splitStringBySpace(result); + for (int i = 0; i < resultArray.length; i ++) { + hashList.add(resultArray[i]); + } + } + } + + /*============================ Helper Methods to check for Error/Syntax Command ===================*/ + + /* + * To be use to check if there are any command syntax error + * + * @return true, if there is an error in the command syntax, false if syntax is allowed + */ + private boolean isErrorCommand(boolean isTaskStatusProvided, boolean isEventStatusProvided, + boolean isTask, boolean isItemTypeProvided, String input) { + // Check if more than 1 item type is provided + if (FilterUtil.isItemTypeConflict(input)) { + Renderer.renderDisambiguation(COMMAND_SYNTAX, MESSAGE_ITEM_TYPE_CONFLICT); + return true; + } + if (isItemTypeProvided) { + // Task and Event Command Syntax detected + if (isTask && isEventStatusProvided) { + Renderer.renderDisambiguation(FIND_TASK_SYNTAX, MESSAGE_INVALID_TASK_STATUS); + return true; + } + if (!isTask && isTaskStatusProvided) { + Renderer.renderDisambiguation(FIND_EVENT_SYNTAX, MESSAGE_INVALID_EVENT_STATUS); + return true; + } + } + return false; + } + + /* + * To be used to parsed dates and check for any dates conflict + * + * @return null if dates conflict detected, else return { null, dateOn, dateFrom, dateTo } + */ + private LocalDateTime[] parsingDates(Map parsedResult) { + String[] parsedDates = ParseUtil.parseDates(parsedResult); + LocalDateTime dateOn = null; + LocalDateTime dateFrom = null; + LocalDateTime dateTo = null; + + if (parsedDates != null) { + String naturalOn = parsedDates[DATE_ON_INDEX]; + String naturalFrom = parsedDates[DATE_FROM_INDEX]; + String naturalTo = parsedDates[DATE_TO_INDEX]; + + if (naturalOn != null && Integer.parseInt(parsedDates[NUM_OF_DATES_FOUND_INDEX]) > 1) { + // Date conflict detected + Renderer.renderDisambiguation(COMMAND_SYNTAX, MESSAGE_DATE_CONFLICT); + return null; + } + // Parse natural date using Natty. + try { + dateOn = naturalOn == null ? null : DateUtil.floorDate(DateParser.parseNatural(naturalOn)); + dateFrom = naturalFrom == null ? null : DateUtil.floorDate(DateParser.parseNatural(naturalFrom)); + dateTo = naturalTo == null ? null : DateUtil.floorDate(DateParser.parseNatural(naturalTo)); + } catch (InvalidNaturalDateException e) { + Renderer.renderDisambiguation(COMMAND_SYNTAX, MESSAGE_NO_DATE_DETECTED); + return null; + } + } + return new LocalDateTime[] { null, dateOn, dateFrom, dateTo }; + } +} +``` +###### /java/seedu/todo/controllers/ListController.java +``` java +/** + * Controller to list CalendarItems + */ +public class ListController implements Controller { + + private static final String NAME = "List"; + private static final String DESCRIPTION = "List all tasks and events by type or status."; + private static final String COMMAND_SYNTAX = "list \"task complete/incomplete\" or \"event over/ongoing\"" + + "[on date] or [from date to date]"; + private static final String COMMAND_WORD = "list"; + + // Syntax correction to console input + public static final String LIST_TASK_SYNTAX = "list task \"complete/incomplete\""; + public static final String LIST_EVENT_SYNTAX = "list event \"over/current\""; + public static final String LIST_DATE_SYNTAX = "list \"date\" [or from \"date\" to \"date\"]"; + + // Message output to console text area + public static final String MESSAGE_RESULT_FOUND_FORMAT = "A total of %s found!"; + public static final String MESSAGE_NO_RESULT_FOUND = "No task or event found!"; + public static final String MESSAGE_LIST_SUCCESS = "Listing Today's, incompleted tasks and ongoing events"; + public static final String MESSAGE_INVALID_TASK_STATUS = "Unable to list!\nTry listing with complete or incomplete"; + public static final String MESSAGE_INVALID_EVENT_STATUS = "Unable to list!\nTry listing with over or current"; + public static final String MESSAGE_DATE_CONFLICT = "Unable to list!\nMore than 1 date criteria is provided!"; + public static final String MESSAGE_NO_DATE_DETECTED = "Unable to list!\nThe natural date entered is not supported."; + public static final String MESSAGE_ITEM_TYPE_CONFLICT = "Unable to list!\nMore than 1 item type is provided!"; + + // Use to access parsing of dates + private static final int NUM_OF_DATES_FOUND_INDEX = 0; + private static final int COMMAND_INPUT_INDEX = 0; + private static final int DATE_CRITERIA_INDEX = 0; + private static final int DATE_ON_INDEX = 1; + private static final int DATE_FROM_INDEX = 2; + private static final int DATE_TO_INDEX = 3; + + private static CommandDefinition commandDefinition = + new CommandDefinition(NAME, DESCRIPTION, COMMAND_SYNTAX); + + public static CommandDefinition getCommandDefinition() { + return commandDefinition; + } + + @Override + public float inputConfidence(String input) { + return (StringUtil.splitStringBySpace(input.toLowerCase())[COMMAND_INPUT_INDEX]).equals(COMMAND_WORD) ? 1 : 0; + } + + private static Map getTokenDefinitions() { + Map tokenDefinitions = new HashMap(); + tokenDefinitions.put(Tokenizer.DEFAULT_TOKEN, new String[] { COMMAND_WORD }); + tokenDefinitions.put(Tokenizer.EVENT_TYPE_TOKEN, Tokenizer.EVENT_TYPE_DEFINITION); + tokenDefinitions.put(Tokenizer.TIME_TOKEN, Tokenizer.TIME_DEFINITION); + tokenDefinitions.put(Tokenizer.TASK_STATUS_TOKEN, Tokenizer.TASK_STATUS_DEFINITION); + tokenDefinitions.put(Tokenizer.EVENT_STATUS_TOKEN, Tokenizer.EVENT_STATUS_DEFINITION); + tokenDefinitions.put(Tokenizer.TIME_FROM_TOKEN, Tokenizer.TIME_FROM_DEFINITION); + tokenDefinitions.put(Tokenizer.TIME_TO_TOKEN, Tokenizer.TIME_TO_DEFINITION); + return tokenDefinitions; + } + + @Override + public void process(String input) throws ParseException { + + Map parsedResult; + parsedResult = Tokenizer.tokenize(getTokenDefinitions(), input); + TodoListDB db = TodoListDB.getInstance(); + + // If input is just "list", invoke Renderer + if (input.trim().equals(COMMAND_WORD)) { + Renderer.renderIndex(db, MESSAGE_LIST_SUCCESS); + return; + } + + // Check if input includes itemType and itemStatus + boolean isItemTypeProvided = !ParseUtil.isTokenNull(parsedResult, Tokenizer.EVENT_TYPE_TOKEN); + boolean isTaskStatusProvided = !ParseUtil.isTokenNull(parsedResult, Tokenizer.TASK_STATUS_TOKEN); + boolean isEventStatusProvided = !ParseUtil.isTokenNull(parsedResult, Tokenizer.EVENT_STATUS_TOKEN); + + // Set item type + boolean isTask = true; //default + if (isItemTypeProvided) { + isTask = ParseUtil.doesTokenContainKeyword(parsedResult, Tokenizer.EVENT_TYPE_TOKEN, "task"); + } + + if (isErrorCommand(isTaskStatusProvided, isEventStatusProvided, isTask, isItemTypeProvided, input)) { + return; // Break out if found error + } + + // Setting up view + List tasks; //default + List events; //default + List calendarItems; + // Filter Task and Event by Type + if (!isItemTypeProvided) { + tasks = db.getAllTasks(); + events = db.getAllEvents(); + } else { + if (isTask) { + events = new ArrayList(); + tasks = db.getAllTasks(); + } else { + tasks = new ArrayList(); + events = db.getAllEvents(); + } + } + + // Filter Task and Event by Status + calendarItems = filterTasksAndEventsByStatus(parsedResult, isTaskStatusProvided, isEventStatusProvided, + tasks, events); + tasks = FilterUtil.filterOutTask(calendarItems); + events = FilterUtil.filterOutEvent(calendarItems); + + // Filter Task and Event by date + calendarItems = filterTasksAndEventsByDate(tasks, events, parsedResult); + if (calendarItems == null) { + return; // Date conflict detected + } + tasks = FilterUtil.filterOutTask(calendarItems); + events = FilterUtil.filterOutEvent(calendarItems); + + // Show message if no items had been found + if (tasks.size() == 0 && events.size() == 0) { + Renderer.renderIndex(db, MESSAGE_NO_RESULT_FOUND); + return; + } + + String consoleMessage = String.format(MESSAGE_RESULT_FOUND_FORMAT, + StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(tasks.size(), events.size())); + Renderer.renderSelectedIndex(db, consoleMessage, tasks, events); + } + + /* ============================== Helper methods to filter out by criterias ================================*/ + + /* + * Filter out the selected tasks and events based on the dates + * and update tasks and events accordingly + * + * @param tasks + * List of Task items + * @param events + * List of Event items + * @param parsedResult + * Parsed result by Tokenizer, in order to filter out the dates + * @return a List of CalendarItem that is been filtered by date(s) + */ + private List filterTasksAndEventsByDate(List tasks, List events, Map parsedResult) { + // Get dates from input + List calendarItems = new ArrayList(); + LocalDateTime [] validDates = parsingDates(parsedResult); + List filteredTasks = tasks; + List filteredEvents = events; + if (validDates == null) { + return null; // Break out when date conflict found + } + + // Set dates that are found, if not found value will be null + LocalDateTime dateCriteria = validDates[DATE_CRITERIA_INDEX]; + LocalDateTime dateOn = validDates[DATE_ON_INDEX]; + LocalDateTime dateFrom = validDates[DATE_FROM_INDEX]; + LocalDateTime dateTo = validDates[DATE_TO_INDEX]; + + if (dateCriteria != null) { + // Filter by single date + assert dateOn == null; + assert dateFrom == null; + assert dateTo == null; + filteredTasks = FilterUtil.filterTaskBySingleDate(tasks, dateCriteria); + filteredEvents = FilterUtil.filterEventBySingleDate(events, dateCriteria); + } + + if (dateOn != null) { + // Filter by single date + filteredTasks = FilterUtil.filterTaskBySingleDate(tasks, dateOn); + filteredEvents = FilterUtil.filterEventBySingleDate(events, dateOn); + } else if (dateFrom != null || dateTo != null) { + // Filter by range + filteredTasks = FilterUtil.filterTaskWithDateRange(tasks, dateFrom, dateTo); + filteredEvents =FilterUtil.filterEventWithDateRange(events, dateFrom, dateTo); + } + + calendarItems.addAll(filteredTasks); + calendarItems.addAll(filteredEvents); + return calendarItems; + } + + /* + * Filter out the selected tasks and events based on the status and update tasks and events accordingly + * + * @param parsedResult + * parsedResult by Tokenizer + * @param isTaskStatusProvided + * true if complete or incomplete is found, else false + * @param isEventStatusProvided + * true if over or current is found, else false + * @param tasks + * List of Task items + * @param events + * List of Event items + * @return + * tasks and events in a list form by status + */ + private List filterTasksAndEventsByStatus(Map parsedResult, boolean isTaskStatusProvided, + boolean isEventStatusProvided, List tasks, List events) { + List calendarItems = new ArrayList(); + List filteredTasks = tasks; + List filteredEvents = events; + + // Set item status + boolean isCompleted = false; //default + boolean isOver = false; //default + + // Filter out by Task Status if provided + if (isTaskStatusProvided) { + isCompleted = !ParseUtil.doesTokenContainKeyword(parsedResult, Tokenizer.TASK_STATUS_TOKEN, "incomplete"); + filteredTasks = FilterUtil.filterTasksByStatus(tasks, isCompleted); + filteredEvents = new ArrayList(); + } + + // Filter out by Event Status if provided + if (isEventStatusProvided) { + isOver = ParseUtil.doesTokenContainKeyword(parsedResult, Tokenizer.EVENT_STATUS_TOKEN, "over"); + filteredEvents = FilterUtil.filterEventsByStatus(events, isOver); + filteredTasks = new ArrayList(); + } + calendarItems.addAll(filteredTasks); + calendarItems.addAll(filteredEvents); + return calendarItems; + } + + /*====================== Helper Methods to check for Error/Syntax Command ===================*/ + + /* + * To be use to check if there are any command syntax error + * + * @return true, if there is an error in the command syntax, false if syntax is allowed + */ + private boolean isErrorCommand(boolean isTaskStatusProvided, boolean isEventStatusProvided, + boolean isTask, boolean isItemTypeProvided, String input) { + // Check if more than 1 item type is provided + if (FilterUtil.isItemTypeConflict(input)) { + Renderer.renderDisambiguation(COMMAND_SYNTAX, MESSAGE_ITEM_TYPE_CONFLICT); + return true; + } + if (isItemTypeProvided) { + // Task and Event Command Syntax detected + if (isTask && isEventStatusProvided) { + Renderer.renderDisambiguation(LIST_TASK_SYNTAX, MESSAGE_INVALID_TASK_STATUS); + return true; + } + + if (!isTask && isTaskStatusProvided) { + Renderer.renderDisambiguation(LIST_EVENT_SYNTAX, MESSAGE_INVALID_EVENT_STATUS); + return true; + } + } + return false; + } + + /* + * To be used to parsed dates and check for any dates conflict + * + * @return null if dates conflict detected, else return { dateCriteria, dateOn, dateFrom, dateTo } + */ + private LocalDateTime[] parsingDates(Map parsedResult) { + String[] parsedDates = ParseUtil.parseDates(parsedResult); + + // Date enter with COMMAND_WORD e.g list today + String date = ParseUtil.getTokenResult(parsedResult, Tokenizer.DEFAULT_TOKEN); + + // Check for more than 1 date + if (date != null && parsedDates != null) { + Renderer.renderDisambiguation(LIST_DATE_SYNTAX, MESSAGE_DATE_CONFLICT); + return null; + } + + LocalDateTime dateCriteria = null; + LocalDateTime dateOn = null; + LocalDateTime dateFrom = null; + LocalDateTime dateTo = null; + + // Setting of dates value + if (date != null) { + try { + dateCriteria = DateParser.parseNatural(date); + } catch (InvalidNaturalDateException e) { + Renderer.renderDisambiguation(LIST_DATE_SYNTAX, MESSAGE_NO_DATE_DETECTED); + return null; + } + } + + if (parsedDates != null) { + String naturalOn = parsedDates[DATE_ON_INDEX]; + String naturalFrom = parsedDates[DATE_FROM_INDEX]; + String naturalTo = parsedDates[DATE_TO_INDEX]; + + if (naturalOn != null && Integer.parseInt(parsedDates[NUM_OF_DATES_FOUND_INDEX]) > 1) { + //date conflict detected + Renderer.renderDisambiguation(LIST_DATE_SYNTAX, MESSAGE_DATE_CONFLICT); + return null; + } + // Parse natural date using Natty. + try { + dateOn = naturalOn == null ? null : DateUtil.floorDate(DateParser.parseNatural(naturalOn)); + dateFrom = naturalFrom == null ? null : DateUtil.floorDate(DateParser.parseNatural(naturalFrom)); + dateTo = naturalTo == null ? null : DateUtil.floorDate(DateParser.parseNatural(naturalTo)); + } catch (InvalidNaturalDateException e) { + Renderer.renderDisambiguation(LIST_DATE_SYNTAX, MESSAGE_NO_DATE_DETECTED); + return null; + } + } + + boolean isEventStatusProvided = !ParseUtil.isTokenNull(parsedResult, Tokenizer.EVENT_STATUS_TOKEN); + // Checking of date conflict with status, for e.g. list by today over + if ((parsedDates != null || dateCriteria != null) && isEventStatusProvided ) { + //detect date conflict + Renderer.renderDisambiguation(LIST_DATE_SYNTAX, MESSAGE_DATE_CONFLICT); + return null; + } + + return new LocalDateTime[] { dateCriteria, dateOn, dateFrom, dateTo }; + } +} +``` +###### /java/seedu/todo/controllers/TagController.java +``` java +/** + * Controller to Tag a CalendarItem. + */ +public class TagController implements Controller { + + private static final String NAME = "Tag"; + private static final String DESCRIPTION = "Tag a task/event by listed index"; + public static final String COMMAND_SYNTAX = "tag "; + private static final String COMMAND_WORD = "tag"; + + public static final String TAG_FORMAT = "tag %d"; + public static final String MESSAGE_TAG_SUCCESS = "Item has been tagged successfully."; + public static final String MESSAGE_INDEX_OUT_OF_RANGE = "Could not tag task/event: Invalid index provided!"; + public static final String MESSAGE_MISSING_INDEX_AND_TAG_NAME = "Please specify the index of the item and the tag name to tag."; + public static final String MESSAGE_INDEX_NOT_NUMBER = "Index has to be a number!"; + public static final String MESSAGE_TAG_NAME_NOT_FOUND = "Could not tag task/event: Tag name not provided!"; + public static final String MESSAGE_EXCEED_TAG_SIZE = "Could not tag task/event : Tag size exceed"; + public static final String MESSAGE_TAG_NAME_EXIST = "Could not tag task/event: Tag name already exist or Duplicate Tag Names!"; + + private static final int COMMAND_INPUT_INDEX = 0; + private static final int ITEM_INDEX = 0; + private static final int TOKENIZER_DEFAULT_INDEX = 1; + + private static CommandDefinition commandDefinition = + new CommandDefinition(NAME, DESCRIPTION, COMMAND_SYNTAX); + + public static CommandDefinition getCommandDefinition() { + return commandDefinition; + } + + @Override + public float inputConfidence(String input) { + return (StringUtil.splitStringBySpace(input.toLowerCase())[COMMAND_INPUT_INDEX]).equals(COMMAND_WORD) ? 1 : 0; + } + + /** + * Get the token definitions for use with tokenizer.
+ * This method exists primarily because Java does not support HashMap + * literals... + * + * @return tokenDefinitions + */ + private static Map getTokenDefinitions() { + Map tokenDefinitions = new HashMap(); + tokenDefinitions.put(Tokenizer.DEFAULT_TOKEN, new String[] { COMMAND_WORD }); + return tokenDefinitions; + } + + @Override + public void process(String input) throws ParseException { + + Map parsedResult; + parsedResult = Tokenizer.tokenize(getTokenDefinitions(), input); + String param = parsedResult.get(Tokenizer.DEFAULT_TOKEN)[TOKENIZER_DEFAULT_INDEX]; + + if (param == null) { + Renderer.renderDisambiguation(COMMAND_SYNTAX, MESSAGE_MISSING_INDEX_AND_TAG_NAME); + return; + } + + String[] parameters = StringUtil.splitStringBySpace(param); + + // Get index and tag names. + int index = 0; + String tagNames = null; + + try { + index = Integer.decode(parameters[ITEM_INDEX]); + tagNames = param.replaceFirst(parameters[ITEM_INDEX], "").trim(); + } catch (NumberFormatException e) { + Renderer.renderDisambiguation(COMMAND_SYNTAX, MESSAGE_INDEX_NOT_NUMBER); + return; + } + + // Get record + EphemeralDB edb = EphemeralDB.getInstance(); + CalendarItem calendarItem = edb.getCalendarItemsByDisplayedId(index); + TodoListDB db = TodoListDB.getInstance(); + + String[] parsedTagNames = parseTags(tagNames); + + if (isErrorCommand(parameters, index, calendarItem, parsedTagNames)) { + return; // Break out once error + } + + boolean resultOfTagging = addingTagNames(parsedTagNames, calendarItem); + + // Re-render + if (resultOfTagging) { + db.addIntoTagList(parsedTagNames); + db.save(); + Renderer.renderSelectedIndex(db, MESSAGE_TAG_SUCCESS, edb.getAllDisplayedTasks(), edb.getAllDisplayedEvents()); + } else { + Renderer.renderDisambiguation(COMMAND_SYNTAX, MESSAGE_EXCEED_TAG_SIZE); + } + } + + /* + * To be used to check if there are any command syntax errors + * + * @return true if error detected, else false. + */ + private boolean isErrorCommand(String[] parameters, int index, CalendarItem calendarItem, String[] parsedTagNames) { + // Check if index is out of range + if (calendarItem == null) { + Renderer.renderDisambiguation(String.format(TAG_FORMAT, index), MESSAGE_INDEX_OUT_OF_RANGE); + return true; + } + + // Check if tag name is provided + if (parameters.length <= 1) { + Renderer.renderDisambiguation(COMMAND_SYNTAX, MESSAGE_TAG_NAME_NOT_FOUND); + return true; + } + + // Check if tag name already exist + boolean isTagNameDuplicate = checkDuplicateTagName(parsedTagNames, calendarItem); + + if (isTagNameDuplicate) { + Renderer.renderDisambiguation(String.format(TAG_FORMAT, index), MESSAGE_TAG_NAME_EXIST); + return true; + } + + return false; + } + + /* + * To be used to add tag into the tag list that belong to the CalendarItem + * @param parsedTagNames + * tag names that are entered by user and not duplicate and do not belong to the calendarItem + * @param calendarItem + * can be task or event + * + * @return true if all tags have been added successfully, false if one of the tags is not added successfully + */ + private boolean addingTagNames(String[] parsedTagNames, CalendarItem calendarItem) { + + // If tag names parsed exceed the maximum tag list limit + if (calendarItem.getTagList().size() + parsedTagNames.length > calendarItem.getTagListLimit()) { + return false; + } + + boolean result = true; + for (int i = 0; i < parsedTagNames.length; i ++) { + result = calendarItem.addTag(parsedTagNames[i].trim()) & result; + } + return result; + } + + /* + * To be used to check if user enter any duplicate tag name and if calendarItem already has that tag name + * @param parsedTagNames + * tag names that has been split into an array + * @param calendarItem + * calendarItem that can be either a task or event + * + * @return true if tag name already exist or is entered more than once, false if it does not exist + */ + private boolean checkDuplicateTagName(String[] parsedTagNames, CalendarItem calendarItem) { + HashSet parsedTagNamesList = new HashSet(); + for (int i = 0; i < parsedTagNames.length; i ++) { + // Checking with overall tag list in db + if (calendarItem.getTagList().contains(parsedTagNames[i].trim())) { + return true; + } + // Checking with the current array, if there are duplicate tags + parsedTagNamesList.add(parsedTagNames[i]); + } + + if (parsedTagNamesList.size() != parsedTagNames.length) { + return true; + } + return false; + } + + /* + * To be used to split tag names by comma if more than one is entered + * @param tags + * tag names that is entered + * + * @return an array of tag name that is split by comma + */ + private String [] parseTags(String tags) { + return tags.split(","); + } + +} +``` +###### /java/seedu/todo/controllers/UntagController.java +``` java +/** + * Controller to untag a CalendarItem. + */ +public class UntagController implements Controller { + + private static final String NAME = "Untag"; + private static final String DESCRIPTION = "Untag a task/event by listed index"; + public static final String COMMAND_SYNTAX = "untag "; + private static final String COMMAND_WORD = "untag"; + + public static final String UNTAG_FORMAT = "untag %d"; + public static final String MESSAGE_UNTAG_SUCCESS = "Item has been untagged successfully."; + public static final String MESSAGE_INDEX_OUT_OF_RANGE = "Could not untag task/event: Invalid index provided!"; + public static final String MESSAGE_MISSING_INDEX_AND_TAG_NAME = "Please specify the index of the item and the tag name to untag."; + public static final String MESSAGE_INDEX_NOT_NUMBER = "Index has to be a number!"; + public static final String MESSAGE_TAG_NAME_NOT_FOUND = "Could not untag task/event: Tag name not provided!"; + public static final String MESSAGE_TAG_NAME_DOES_NOT_EXIST = "Could not untag task/event: Tag name does not exist!"; + public static final String MESSAGE_TAG_NAME_EXIST = "Could not untag task/event : Tag name does not exist or Duplicate Tag name detected!"; + + private static final int COMMAND_INPUT_INDEX = 0; + private static final int ITEM_INDEX = 0; + private static final int TOKENIZER_DEFAULT_INDEX = 1; + + private static CommandDefinition commandDefinition = + new CommandDefinition(NAME, DESCRIPTION, COMMAND_SYNTAX); + + public static CommandDefinition getCommandDefinition() { + return commandDefinition; + } + + @Override + public float inputConfidence(String input) { + return (StringUtil.splitStringBySpace(input.toLowerCase())[COMMAND_INPUT_INDEX]).equals(COMMAND_WORD) ? 1 : 0; + } + + /** + * Get the token definitions for use with tokenizer.
+ * This method exists primarily because Java does not support HashMap + * literals... + * + * @return tokenDefinitions + */ + private static Map getTokenDefinitions() { + Map tokenDefinitions = new HashMap(); + tokenDefinitions.put(Tokenizer.DEFAULT_TOKEN, new String[] { COMMAND_WORD }); + return tokenDefinitions; + } + + @Override + public void process(String input) throws ParseException { + + Map parsedResult; + parsedResult = Tokenizer.tokenize(getTokenDefinitions(), input); + + String param = parsedResult.get(Tokenizer.DEFAULT_TOKEN)[TOKENIZER_DEFAULT_INDEX]; + + if (param == null) { + Renderer.renderDisambiguation(COMMAND_SYNTAX, MESSAGE_MISSING_INDEX_AND_TAG_NAME); + return; + } + + String[] parameters = StringUtil.splitStringBySpace(param); + + // Get index. + int index = 0; + String tagNames = null; + try { + index = Integer.decode(parameters[ITEM_INDEX]); + tagNames = param.replaceFirst(parameters[ITEM_INDEX], "").trim(); + } catch (NumberFormatException e) { + Renderer.renderDisambiguation(COMMAND_SYNTAX, MESSAGE_INDEX_NOT_NUMBER); + return; + } + + // Get record + EphemeralDB edb = EphemeralDB.getInstance(); + CalendarItem calendarItem = edb.getCalendarItemsByDisplayedId(index); + TodoListDB db = TodoListDB.getInstance(); + + String[] parsedTagNames = parseTags(tagNames); + + if (isErrorCommand(parameters, index, calendarItem, parsedTagNames)) { + return; // Break out once error + } + + boolean resultOfUntagging = removingTagNames(parsedTagNames, calendarItem); + + // Re-render + if (resultOfUntagging) { + db.updateTagList(parsedTagNames); + db.save(); + Renderer.renderSelectedIndex(db, MESSAGE_UNTAG_SUCCESS, edb.getAllDisplayedTasks(), edb.getAllDisplayedEvents()); + } else { + Renderer.renderDisambiguation(String.format(UNTAG_FORMAT, index), MESSAGE_TAG_NAME_DOES_NOT_EXIST); + } + } + + /* + * To be used to check if there are any command syntax errors + * + * @return true if error detected, else false. + */ + private boolean isErrorCommand(String[] parameters, int index, CalendarItem calendarItem, String[] parsedTagNames) { + // Check if index is out of range + if (calendarItem == null) { + Renderer.renderDisambiguation(String.format(UNTAG_FORMAT, index), MESSAGE_INDEX_OUT_OF_RANGE); + return true; + } + + // Check if tag name is provided + if (parameters.length <= 1) { + Renderer.renderDisambiguation(COMMAND_SYNTAX, MESSAGE_TAG_NAME_NOT_FOUND); + return true; + } + + // Check if tag name exist + if (tagNameDoesNotExist(parsedTagNames, calendarItem)) { + Renderer.renderDisambiguation(String.format(UNTAG_FORMAT, index), MESSAGE_TAG_NAME_EXIST); + return true; + } + return false; + } + + /* + * To be used to remove tag from the tag list that belong to the CalendarItem + * @param parsedTagNames + * tag names that are entered by user and not duplicate and belong to the calendarItem + * @param calendarItem + * can be task or event + * + * @return true if all tags have been removed successfully, false if one of the tags its not removed successfully + * */ + private boolean removingTagNames(String[] parsedTagNames, CalendarItem calendarItem) { + assert parsedTagNames != null; + assert calendarItem != null; + + boolean result = true; + for (int i = 0; i < parsedTagNames.length; i ++) { + result = calendarItem.removeTag(parsedTagNames[i].trim()) & result; + } + return result; + } + + /* + * To be used to check if user enter any duplicate tag name and if calendarItem has the exact tag name + * @param parsedTagNames + * tag names that has been split into an array + * @param calendarItem + * calendarItem that can be either a task or event + * + * @return true if tag name does not exist or is entered more than once, false if it exist in the tag list + */ + private boolean tagNameDoesNotExist(String[] parsedTagNames, CalendarItem calendarItem) { + HashSet parsedTagNamesList = new HashSet(); + for (int i = 0; i < parsedTagNames.length; i ++) { + // Checking with overall tag list in db + if (!calendarItem.getTagList().contains(parsedTagNames[i].trim())) { + return true; + } + + // Checking with the current array, if there are any duplicate tag names + parsedTagNamesList.add(parsedTagNames[i]); + } + return parsedTagNamesList.size() != parsedTagNames.length; + } + + /* + * To be used to split tag names by comma if more than one is entered + * @param tags + * tag names that is entered + * + * @return an array of tag name that is split by comma + */ + private String [] parseTags(String tags) { + return tags.split(","); + } + +} +``` +###### /java/seedu/todo/models/CalendarItem.java +``` java + /** + * Returns the current tag list that belong to the CalendarItem, mainly for displaying purpose + * + * @return ArrayList tags + */ + public ArrayList getTagList(); + +``` +###### /java/seedu/todo/models/CalendarItem.java +``` java + /** + * Add a new tag in the list of tag of the calendar item. + * + * @param tagName + * @return true if it has not reached the max tag list size, false if tag list already reach the max size + */ + public boolean addTag(String tagName); + +``` +###### /java/seedu/todo/models/CalendarItem.java +``` java + /** + * Remove a existing tag in the tag list of tag of the calendar item. + * + * @param tagName + * @return true if tagName is removed successfully, false if failed to remove tagName due to unable to find + */ + public boolean removeTag(String tagName); + +``` +###### /java/seedu/todo/models/CalendarItem.java +``` java + /** + * Get the limit of the tag that is allowed for calendar item + * + * @return the limit of tag list + */ + public int getTagListLimit(); +} +``` +###### /java/seedu/todo/models/Event.java +``` java + /** + * Return the tag list that belong to the calendar item + */ + @Override + public ArrayList getTagList() { + return tagList; + } + +``` +###### /java/seedu/todo/models/Event.java +``` java + /** + * Adding the tag into the tag list that belong to the calendar item + * @param tagName + * name of the tag + * + * @return true tag name is successfully added, false if tag list if full + */ + @Override + public boolean addTag(String tagName) { + if(tagList.size() < MAX_TAG_LIST_SIZE) { + tagList.add(tagName); + return true; + } else { + return false; + } + } + +``` +###### /java/seedu/todo/models/Event.java +``` java + /** + * Removing the tag from the tag list that belong to the calendar item + * @param tagName + * name of the tag + * + * @return true tag name is successfully removed, false if tag name does not exist + */ + @Override + public boolean removeTag(String tagName) { + return tagList.remove(tagName); + } + + /** +``` +###### /java/seedu/todo/models/Event.java +``` java + /** + * Returning the maximum tag list size that is allowed + */ + @Override + public int getTagListLimit() { + return MAX_TAG_LIST_SIZE; + } + +} +``` +###### /java/seedu/todo/models/Task.java +``` java + /** + * Return the tag list that belong to the calendar item + */ + @Override + public ArrayList getTagList() { + return tagList; + } + +``` +###### /java/seedu/todo/models/Task.java +``` java + /** + * Adding the tag into the tag list that belong to the calendar item + * @param tagName + * name of the tag + * + * @return true tag name is successfully added, false if tag list if full + */ + @Override + public boolean addTag(String tagName) { + if(tagList.size() < MAX_TAG_LIST_SIZE) { + tagList.add(tagName); + return true; + } else { + return false; + } + } + +``` +###### /java/seedu/todo/models/Task.java +``` java + /** + * Removing the tag from the tag list that belong to the calendar item + * @param tagName + * name of the tag + * + * @return true tag name is successfully removed, false if tag name does not exist + */ + @Override + public boolean removeTag(String tagName) { + return tagList.remove(tagName); + } + + + /** +``` +###### /java/seedu/todo/models/Task.java +``` java + /** + * Returning the maximum tag list size that is allowed + */ + @Override + public int getTagListLimit() { + return MAX_TAG_LIST_SIZE; + } + +} +``` +###### /java/seedu/todo/models/TodoListDB.java +``` java + /** + * Add into the overall Tags in the DB. + */ + public void addIntoTagList(String[] parsedTagNames) { + assert parsedTagNames != null; + for (int i = 0; i < parsedTagNames.length; i ++) { + String tagName = parsedTagNames[i].trim(); + if (tagList.get(tagName) != null) { + int currentTagCount = tagList.get(tagName); + tagList.put(tagName, currentTagCount + 1); + } else { + tagList.put(tagName, 1); + } + } + } + +``` +###### /java/seedu/todo/models/TodoListDB.java +``` java + /** + * Remove from the overall Tags with a single tagName that exist in the DB. + */ + public void updateTagList(String[] parsedTagNames) { + assert parsedTagNames != null; + for (int i = 0; i < parsedTagNames.length; i ++) { + String tagName = parsedTagNames[i].trim(); + int currentTagCount = tagList.get(tagName); + + int newTagCount = currentTagCount - 1; + if (newTagCount == 0) { + tagList.remove(tagName); + } else { + tagList.put(tagName, newTagCount); + } + } + } + +``` +###### /java/seedu/todo/models/TodoListDB.java +``` java + /** + * Remove from the overall Tags with a given List of CalendarItem that exist in the DB. + * @param listOfItem of type CalendarItem + */ + public void removeFromTagList(List listOfCalendarItem) { + assert listOfCalendarItem != null; + + ArrayList selectedTagList = new ArrayList(); + for (int i = 0; i < listOfCalendarItem.size(); i ++) { + selectedTagList.addAll(((CalendarItem) listOfCalendarItem.get(i)).getTagList()); + } + + updateTagList(selectedTagList.toArray(new String[0])); + } + +``` +###### /java/seedu/todo/models/TodoListDB.java +``` java + /** + * Get a list of Tags in the DB. + * + * @return tagList + */ + public HashMap getTagList() { + return tagList; + } + +``` +###### /java/seedu/todo/models/TodoListDB.java +``` java + /** + * Count tags which are already inserted into the db + * + * @return Number of tags + */ + public int countTagList() { + return tagList.size(); + } +``` +###### /java/seedu/todo/models/TodoListDB.java +``` java + /** + * Destroys all Task and Events in the DB and persists the commit. + * + * @return true if the save was successful, false otherwise + */ + public boolean destroyAllTaskAndEvents() { + removeFromTagList(new ArrayList(tasks)); + removeFromTagList(new ArrayList(events)); + tasks = new LinkedHashSet(); + events = new LinkedHashSet(); + return save(); + } + +``` +###### /java/seedu/todo/models/TodoListDB.java +``` java + /** + * Destroys Task and Events based on list in the DB and persists the commit. + * @taskLists + * List of tasks to be destroyed + * @eventLists + * List of events to be destroyed + * + * @return true if the save was successful, false otherwise + */ + public boolean destroyAllTaskAndEventsByList(List tasksList , List eventsList) { + removeFromTagList(new ArrayList(tasksList)); + removeFromTagList(new ArrayList(eventsList)); + + //removing tasks and events + tasks.removeAll(tasksList); + events.removeAll(eventsList); + return save(); + } + +``` +###### /java/seedu/todo/models/TodoListDB.java +``` java + /** + * Destroys all Task in the DB and persists the commit. + * + * @return true if the save was successful, false otherwise + */ + public void destroyAllTask() { + removeFromTagList(new ArrayList(tasks)); + tasks = new LinkedHashSet(); + } +``` +###### /java/seedu/todo/models/TodoListDB.java +``` java + /** + * Destroys all Event in the DB and persists the commit. + */ + public void destroyAllEvent() { + removeFromTagList(new ArrayList(events)); + events = new LinkedHashSet(); + } +``` diff --git a/collated/test/A0139922Yreused.md b/collated/test/A0139922Yreused.md new file mode 100644 index 000000000000..057df6bcf5e6 --- /dev/null +++ b/collated/test/A0139922Yreused.md @@ -0,0 +1,235 @@ +# A0139922Yreused +###### /java/seedu/todo/guitests/FindCommandTest.java +``` java + // Date variables to be use to initialise DB + private static final LocalDateTime TODAY = LocalDateTime.now(); + private static final String TODAY_STRING = DateUtil.formatDate(TODAY); + private static final String TODAY_ISO_STRING = DateUtil.formatIsoDate(TODAY); + private static final LocalDateTime TOMORROW = LocalDateTime.now().plusDays(1); + private static final String TOMORROW_STRING = DateUtil.formatDate(TOMORROW); + private static final String TOMORROW_ISO_STRING = DateUtil.formatIsoDate(TOMORROW); + private static final LocalDateTime THE_DAY_AFTER_TOMORROW_ = LocalDateTime.now().plusDays(2); + private static final String THE_DAY_AFTER_TOMORROW_STRING = DateUtil.formatDate(THE_DAY_AFTER_TOMORROW_); + private static final String THE_DAY_AFTER_TOMORROW__ISO_STRING = DateUtil.formatIsoDate(THE_DAY_AFTER_TOMORROW_); + + // Command to be use to initialise DB + private String commandAdd1 = String.format("add task Buy Coco by \"%s 8pm\" tag personal", TODAY_STRING); + private Task task1 = new Task(); + private String commandAdd2 = String.format("add task Buy Milk by \"%s 9pm\" tag personal", TOMORROW_STRING); + private Task task2 = new Task(); + private String commandAdd3 = String.format("add event CS2103 V0.5 Demo from \"%s 4pm\" to \"%s 5pm\" tag event", + TOMORROW_STRING, TOMORROW_STRING); + private Event event3 = new Event(); + private String commandAdd4 = String.format("add event buying workshop from \"%s 8pm\" to \"%s 9pm\" tag buy", + THE_DAY_AFTER_TOMORROW_STRING, THE_DAY_AFTER_TOMORROW_STRING); + private Event event4 = new Event(); + + private int expectedNumOfTasks; + private int expectedNumOfEvents; + + // Set up DB + public FindCommandTest() { + task1.setName("Buy Coco"); + task1.setCalendarDateTime(DateUtil.parseDateTime( + String.format("%s 20:00:00", TODAY_ISO_STRING))); + task1.addTag("personal"); + task1.setCompleted(); + + task2.setName("Buy Milk"); + task2.setDueDate(DateUtil.parseDateTime( + String.format("%s 21:00:00", TOMORROW_ISO_STRING))); + task2.addTag("personal"); + + event3.setName("CS2103 V0.5 Demo"); + event3.setStartDate(DateUtil.parseDateTime( + String.format("%s 16:00:00", TOMORROW_ISO_STRING))); + event3.setEndDate(DateUtil.parseDateTime( + String.format("%s 17:00:00", TOMORROW_ISO_STRING))); + event3.addTag("event"); + + event4.setName("buying workshop"); + event4.setStartDate(DateUtil.parseDateTime( + String.format("%s 20:00:00", THE_DAY_AFTER_TOMORROW__ISO_STRING))); + event4.setEndDate(DateUtil.parseDateTime( + String.format("%s 21:00:00", THE_DAY_AFTER_TOMORROW__ISO_STRING))); + event4.addTag("buy"); + } + +``` +###### /java/seedu/todo/guitests/FindCommandTest.java +``` java + @Before + public void initFixtures() { + console.runCommand("clear"); + assertTaskVisibleAfterCmd(commandAdd1, task1); + assertTaskVisibleAfterCmd(commandAdd2, task2); + assertEventVisibleAfterCmd(commandAdd3, event3); + assertEventVisibleAfterCmd(commandAdd4, event4); + } + +``` +###### /java/seedu/todo/guitests/FindCommandTest.java +``` java + @Test + public void fixtures_test() { + console.runCommand("clear"); + assertTaskNotVisibleAfterCmd("list", task1); + assertTaskNotVisibleAfterCmd("list", task2); + assertEventNotVisibleAfterCmd("list", event3); + assertEventNotVisibleAfterCmd("list", event4); + } +``` +###### /java/seedu/todo/guitests/ListCommandTest.java +``` java + // Date variables to be use to initialise DB + private static final LocalDateTime TODAY = LocalDateTime.now(); + private static final String TODAY_STRING = DateUtil.formatDate(TODAY); + private static final String TODAY_ISO_STRING = DateUtil.formatIsoDate(TODAY); + private static final LocalDateTime TOMORROW = LocalDateTime.now().plusDays(1); + private static final String TOMORROW_STRING = DateUtil.formatDate(TOMORROW); + private static final String TOMORROW_ISO_STRING = DateUtil.formatIsoDate(TOMORROW); + private static final LocalDateTime THE_DAY_AFTER_TOMORROW_ = LocalDateTime.now().plusDays(2); + private static final String THE_DAY_AFTER_TOMORROW_STRING = DateUtil.formatDate(THE_DAY_AFTER_TOMORROW_); + private static final String THE_DAY_AFTER_TOMORROW__ISO_STRING = DateUtil.formatIsoDate(THE_DAY_AFTER_TOMORROW_); + + // Command to be use to initialise DB + private String commandAdd1 = String.format("add task Buy Coco by \"%s 8pm\"", TODAY_STRING); + private Task task1 = new Task(); + private String commandAdd2 = String.format("add task Buy Milk by \"%s 9pm\"", TOMORROW_STRING); + private Task task2 = new Task(); + private String commandAdd3 = String.format("add event CS2103 V0.5 Demo from \"%s 4pm\" to \"%s 5pm\"", + TOMORROW_STRING, TOMORROW_STRING); + private Event event3 = new Event(); + private String commandAdd4 = String.format("add event buying workshop from \"%s 8pm\" to \"%s 9pm\"", + THE_DAY_AFTER_TOMORROW_STRING, THE_DAY_AFTER_TOMORROW_STRING); + private Event event4 = new Event(); + private int expectedNumOfTasks; + private int expectedNumOfEvents; + + // Set up DB + public ListCommandTest() { + task1.setName("Buy Coco"); + task1.setCalendarDateTime(DateUtil.parseDateTime( + String.format("%s 20:00:00", TODAY_ISO_STRING))); + task1.setCompleted(); + + task2.setName("Buy Milk"); + task2.setDueDate(DateUtil.parseDateTime( + String.format("%s 21:00:00", TOMORROW_ISO_STRING))); + + event3.setName("CS2103 V0.5 Demo"); + event3.setStartDate(DateUtil.parseDateTime( + String.format("%s 16:00:00", TOMORROW_ISO_STRING))); + event3.setEndDate(DateUtil.parseDateTime( + String.format("%s 17:00:00", TOMORROW_ISO_STRING))); + + event4.setName("buying workshop"); + event4.setStartDate(DateUtil.parseDateTime( + String.format("%s 20:00:00", THE_DAY_AFTER_TOMORROW__ISO_STRING))); + event4.setEndDate(DateUtil.parseDateTime( + String.format("%s 21:00:00", THE_DAY_AFTER_TOMORROW__ISO_STRING))); + } + +``` +###### /java/seedu/todo/guitests/ListCommandTest.java +``` java + @Before + public void initFixtures() { + console.runCommand("clear"); + assertTaskVisibleAfterCmd(commandAdd1, task1); + assertTaskVisibleAfterCmd(commandAdd2, task2); + assertEventVisibleAfterCmd(commandAdd3, event3); + assertEventVisibleAfterCmd(commandAdd4, event4); + } + +``` +###### /java/seedu/todo/guitests/ListCommandTest.java +``` java + @Test + public void fixtures_test() { + console.runCommand("clear"); + assertTaskNotVisibleAfterCmd("list", task1); + assertTaskNotVisibleAfterCmd("list", task2); + assertEventNotVisibleAfterCmd("list", event3); + assertEventNotVisibleAfterCmd("list", event4); + } +``` +###### /java/seedu/todo/guitests/TagControllerTest.java +``` java + // Date variables to be use to initialise DB + private static final LocalDateTime TODAY = LocalDateTime.now(); + private static final String TODAY_STRING = DateUtil.formatDate(TODAY); + private static final String TODAY_ISO_STRING = DateUtil.formatIsoDate(TODAY); + + // Command to be use to initialise DB + private String commandAdd = String.format("add task Buy Coco by \"%s 8pm\"", TODAY_STRING); + private Task task = new Task(); + private Task taskWithoutTag = new Task(); + + // Set up DB + public TagControllerTest() { + task.setName("Buy Coco"); + task.setCalendarDateTime(DateUtil.parseDateTime( + String.format("%s 20:00:00", TODAY_ISO_STRING))); + task.addTag("personal"); + taskWithoutTag.setName("Buy Coco"); + taskWithoutTag.setCalendarDateTime(DateUtil.parseDateTime( + String.format("%s 20:00:00", TODAY_ISO_STRING))); + } + +``` +###### /java/seedu/todo/guitests/TagControllerTest.java +``` java + @Before + public void initFixtures() { + console.runCommand("clear"); + assertTaskVisibleAfterCmd(commandAdd, task); + } + + @Test + public void fixtures_test() { + console.runCommand("clear"); + assertTaskNotVisibleAfterCmd("list", task); + } +``` +###### /java/seedu/todo/guitests/UntagControllerTest.java +``` java + // Date variables to be use to initialise DB + private static final LocalDateTime TODAY = LocalDateTime.now(); + private static final String TODAY_STRING = DateUtil.formatDate(TODAY); + private static final String TODAY_ISO_STRING = DateUtil.formatIsoDate(TODAY); + + // Command to be use to initialise DB + private String commandAdd = String.format("add task Buy Coco by \"%s 8pm\"", TODAY_STRING); + private Task task = new Task(); + private Task taskWithoutTag = new Task(); + + // Set up DB + public UntagControllerTest() { + task.setName("Buy Coco"); + task.setCalendarDateTime(DateUtil.parseDateTime( + String.format("%s 20:00:00", TODAY_ISO_STRING))); + task.addTag("personal"); + taskWithoutTag.setName("Buy Coco"); + taskWithoutTag.setCalendarDateTime(DateUtil.parseDateTime( + String.format("%s 20:00:00", TODAY_ISO_STRING))); + } + +``` +###### /java/seedu/todo/guitests/UntagControllerTest.java +``` java + @Before + public void initFixtures() { + console.runCommand("clear"); + assertTaskVisibleAfterCmd(commandAdd, task); + } + +``` +###### /java/seedu/todo/guitests/UntagControllerTest.java +``` java + @Test + public void fixtures_test() { + console.runCommand("clear"); + assertTaskNotVisibleAfterCmd("list", task); + } +``` diff --git a/collated/test/A0139922Yunused.md b/collated/test/A0139922Yunused.md new file mode 100644 index 000000000000..76e5620e4647 --- /dev/null +++ b/collated/test/A0139922Yunused.md @@ -0,0 +1,2426 @@ +# A0139922Yunused +###### /java/seedu/todo/commons/util/DateUtilTest.java +``` java + @Test + public void ceilDate_sameDate_equals() { + LocalDateTime today = LocalDateTime.now().toLocalDate().atTime(10,0); + LocalDateTime todayPlusAnHour = today.plusHours(1); + assertEquals(DateUtil.ceilDate(today), DateUtil.ceilDate(todayPlusAnHour)); + } + +``` +###### /java/seedu/todo/commons/util/DateUtilTest.java +``` java + @Test + public void ceilDate_sameDate_not_null() { + LocalDateTime today = LocalDateTime.now().toLocalDate().atTime(10,0); + LocalDateTime todayPlusAnHour = today.plusHours(1); + assertNotNull(DateUtil.ceilDate(today)); + assertNotNull(DateUtil.ceilDate(todayPlusAnHour)); + assertEquals(DateUtil.ceilDate(today), DateUtil.ceilDate(todayPlusAnHour)); + } + +``` +###### /java/seedu/todo/commons/util/DateUtilTest.java +``` java + @Test + public void ceilDate_differentDate_not_equals() { + LocalDateTime today = LocalDateTime.now(); + LocalDateTime tmr = LocalDateTime.now().plusDays(1); + assertNotEquals(DateUtil.ceilDate(today), DateUtil.ceilDate(tmr)); + } + +``` +###### /java/seedu/todo/commons/util/DateUtilTest.java +``` java + @Test + public void ceilDate_differentDate_not_null() { + LocalDateTime today = LocalDateTime.now(); + LocalDateTime tmr = LocalDateTime.now().plusDays(1); + assertNotNull(DateUtil.ceilDate(today)); + assertNotNull(DateUtil.ceilDate(tmr)); + assertNotEquals(DateUtil.ceilDate(today), DateUtil.ceilDate(tmr)); + } + +``` +###### /java/seedu/todo/commons/util/DateUtilTest.java +``` java + public void ceilDate_nullDate_null() { + LocalDateTime nullDate = null; + assertEquals(null, DateUtil.ceilDate(nullDate)); + } +``` +###### /java/seedu/todo/commons/util/DateUtilTest.java +``` java + @Test + public void formatShortDateTests_null_test() { + assertNull(DateUtil.formatShortDate(null)); + assertNotNull(DateUtil.formatShortDate(LocalDateTime.now())); + } + +``` +###### /java/seedu/todo/commons/util/DateUtilTest.java +``` java + @Test + public void formatTime_null_test() { + assertNull(DateUtil.formatTime(null)); + assertNotNull(DateUtil.formatTime(LocalDateTime.now())); + } +``` +###### /java/seedu/todo/commons/util/DateUtilTest.java +``` java + @Test + public void testIfDateExist_false() { + LocalDateTime currentDate = LocalDateTime.now(); + assertNotNull(DateUtil.checkIfDateExist(currentDate)); + assertFalse(DateUtil.checkIfDateExist(currentDate)); + } + +``` +###### /java/seedu/todo/commons/util/DateUtilTest.java +``` java + @Test + public void testCheckIfDateExist_with_year_diff_true() { + LocalDateTime currentDate = LocalDateTime.now(); + assertNotNull(DateUtil.checkIfDateExist(currentDate)); + // Only year is different + assertTrue(DateUtil.checkIfDateExist(currentDate.plusYears(1))); + } + +``` +###### /java/seedu/todo/commons/util/DateUtilTest.java +``` java + @Test + public void testCheckIfDateExist_with_month_diff_true() { + LocalDateTime currentDate = LocalDateTime.now(); + assertNotNull(DateUtil.checkIfDateExist(currentDate)); + // Only month is different + assertTrue(DateUtil.checkIfDateExist(currentDate.plusMonths(1))); + assertTrue(DateUtil.checkIfDateExist(currentDate.plusMonths(12))); + } + +``` +###### /java/seedu/todo/commons/util/DateUtilTest.java +``` java + @Test + public void testCheckifDateExist_with_day_diff_true() { + LocalDateTime currentDate = LocalDateTime.now(); + assertNotNull(DateUtil.checkIfDateExist(currentDate)); + // Only day is different + assertTrue(DateUtil.checkIfDateExist(currentDate.plusDays(1))); + assertTrue(DateUtil.checkIfDateExist(currentDate.plusDays(365))); + } + +``` +###### /java/seedu/todo/commons/util/DateUtilTest.java +``` java + @Test + public void testCheckifDateExist_with_day_month_diff_true() { + LocalDateTime currentDate = LocalDateTime.now(); + assertNotNull(DateUtil.checkIfDateExist(currentDate)); + // Day and Month are different + currentDate = currentDate.plusDays(1); + currentDate = currentDate.plusMonths(1); + assertTrue(DateUtil.checkIfDateExist(currentDate)); + } + +``` +###### /java/seedu/todo/commons/util/DateUtilTest.java +``` java + @Test + public void testCheckifDateExist_with_day_year_diff_true() { + LocalDateTime currentDate = LocalDateTime.now(); + assertNotNull(DateUtil.checkIfDateExist(currentDate)); + // Day and Month are different + currentDate = currentDate.plusDays(1); + currentDate = currentDate.plusYears(1); + assertTrue(DateUtil.checkIfDateExist(currentDate)); + } + +``` +###### /java/seedu/todo/commons/util/DateUtilTest.java +``` java + @Test + public void testCheckifDateExist_with_month_year_diff_true() { + LocalDateTime currentDate = LocalDateTime.now(); + assertNotNull(DateUtil.checkIfDateExist(currentDate)); + // Day and Month are different + currentDate = currentDate.plusMonths(1); + currentDate = currentDate.plusYears(1); + assertTrue(DateUtil.checkIfDateExist(currentDate)); + } + +``` +###### /java/seedu/todo/commons/util/DateUtilTest.java +``` java + @Test + public void testCheckifDateExist_equals_false() { + LocalDateTime currentDate = LocalDateTime.now(); + assertNotNull(DateUtil.checkIfDateExist(currentDate)); + assertFalse(DateUtil.checkIfDateExist(currentDate)); + } + +``` +###### /java/seedu/todo/commons/util/DateUtilTest.java +``` java + @Test + public void testCheckIfTimeExist_false() { + LocalDateTime currentTime = LocalDateTime.now(); + assertNotNull(DateUtil.checkIfTimeExist(currentTime)); + assertFalse(DateUtil.checkIfTimeExist(currentTime)); + } + +``` +###### /java/seedu/todo/commons/util/DateUtilTest.java +``` java + @Test + public void testIfTimeExist_true() { + LocalDateTime currentTime = LocalDateTime.now().toLocalDate().atTime(10,0); + assertNotNull(DateUtil.checkIfTimeExist(currentTime)); + assertTrue(DateUtil.checkIfTimeExist(currentTime.toLocalDate().atTime(currentTime.getHour() - currentTime.getHour(), + currentTime.getMinute()))); + assertTrue(DateUtil.checkIfTimeExist(currentTime.toLocalDate().atTime(currentTime.getHour(), + currentTime.getMinute() - currentTime.getMinute()))); + assertTrue(DateUtil.checkIfTimeExist(currentTime.toLocalDate().atTime(currentTime.getHour() - currentTime.getHour(), + currentTime.getMinute() - currentTime.getMinute()))); + } + +``` +###### /java/seedu/todo/commons/util/DateUtilTest.java +``` java + @Test + public void testParseTimeStamp_task_setTimeToMin() { + //set the time to 00:00 for task + assertNotEquals(DateUtil.parseTimeStamp(currentDay, null, true), currentDay); + assertEquals(DateUtil.parseTimeStamp(currentDay, null, true), DateUtil.floorDate(currentDay)); + } + +``` +###### /java/seedu/todo/commons/util/DateUtilTest.java +``` java + @Test + public void testParseTimeStamp_event_setTimeToMin() { + //will set the time to 00:00 for event + assertNotEquals(DateUtil.parseTimeStamp(currentDay, nextDay, true), currentDay); + assertEquals(DateUtil.parseTimeStamp(currentDay, nextDay, true), DateUtil.floorDate(currentDay)); + } + +``` +###### /java/seedu/todo/commons/util/DateUtilTest.java +``` java + @Test + public void testParseTimeStamp_event_setTimeToMax() { + // will set the time to 23:59 + assertNotEquals(DateUtil.parseTimeStamp(nextDay, currentDay, false), nextDay); + assertEquals(DateUtil.parseTimeStamp(nextDay, currentDay, false), nextDayAt2359); + } + +``` +###### /java/seedu/todo/commons/util/DateUtilTest.java +``` java + @Test + public void testParseTimeStamp_event_followNextDayTime() { + // will set the time to follow the nextDay + assertNotEquals(DateUtil.parseTimeStamp(currentDay, nextDayAt2Pm, true), currentDay); + assertEquals(DateUtil.parseTimeStamp(currentDay, nextDayAt2Pm, true), currentDayAt2Pm); + } + +``` +###### /java/seedu/todo/commons/util/DateUtilTest.java +``` java + @Test + public void testParseTimeStamp_event_followCurrentDayTime() { + // will set the time to follow the currentDay + assertEquals(DateUtil.parseTimeStamp(currentDayAt2Pm, nextDay, true), currentDayAt2Pm); + assertNotEquals(DateUtil.parseTimeStamp(nextDay, currentDayAt2Pm, false), nextDay); + assertEquals(DateUtil.parseTimeStamp(nextDay, currentDayAt2Pm, false), nextDayAt2Pm); + } + +``` +###### /java/seedu/todo/commons/util/DateUtilTest.java +``` java + @Test + public void testParseTimeStamp_event_followGivenDateTime() { + // if date and time exist, will not overwrite it + assertEquals(DateUtil.parseTimeStamp(currentDayAt2Pm, nextDay, true), currentDayAt2Pm); + assertEquals(DateUtil.parseTimeStamp(currentDayAt2Pm, nextDayAt2Pm, true), currentDayAt2Pm); + assertEquals(DateUtil.parseTimeStamp(nextDayAt2Pm, currentDay, false), nextDayAt2Pm); + assertEquals(DateUtil.parseTimeStamp(nextDayAt2Pm, currentDayAt2Pm, false), nextDayAt2Pm); + } +} +``` +###### /java/seedu/todo/commons/util/FilterUtilTest.java +``` java +public class FilterUtilTest { + public static final LocalDateTime TODAY = LocalDateTime.now(); + public static final LocalDateTime TOMORROW = LocalDateTime.now().plusDays(1); + public static final LocalDateTime YESTERDAY = LocalDateTime.now().minusDays(1); + Task firstTestTask = getFirstTestTask(); + Task secondTestTask = getSecondTestTask(); + List overdueEvents = getOverdueEvents(); + List currentEvents = getCurrentEvents(); + + /* ======================== Test cases for Filtering Task Methods ========================== */ + + @Test + public void testFilterOutTask_equals() { + List calendarItems = new ArrayList(); + calendarItems.add(firstTestTask); + assertEquals(calendarItems, FilterUtil.filterOutTask(calendarItems)); + } + + @Test + public void testFilterOutTask_not_equals() { + List calendarItems = new ArrayList(); + calendarItems.add(firstTestTask); + calendarItems.addAll(overdueEvents); + assertNotEquals(calendarItems, FilterUtil.filterOutTask(calendarItems)); + } + + @Test + public void testFilterTaskByNames_filter_with_empty_taskList_equals() { + List tasks = getEmptyTaskList(); + HashSet nameList = new HashSet(); + // Empty task list with empty name list + assertEquals(tasks, FilterUtil.filterTaskByNames(tasks, nameList)); + // Empty task list with name list + nameList.add("Nothing"); + assertEquals(tasks, FilterUtil.filterTaskByNames(tasks, nameList)); + } + + @Test + public void testFilterTaskByNames_filter_by_fullname_equals() { + List tasks = getEmptyTaskList(); + HashSet nameList = new HashSet(); + + // Filter out first test task + nameList.add("Buy"); + tasks.add(firstTestTask); + assertEquals(tasks, FilterUtil.filterTaskByNames(tasks, nameList)); + + tasks.add(secondTestTask); + List filteredResult = getEmptyTaskList(); + filteredResult.add(firstTestTask); + assertEquals(filteredResult, (FilterUtil.filterTaskByNames(tasks, nameList))); + } + + @Test + public void testFilterTaskByNames_filter_by_fullname_not_equals() { + List tasks = getEmptyTaskList(); + HashSet nameList = new HashSet(); + List filteredResult = getEmptyTaskList(); + + nameList.add("Buy"); + tasks.add(firstTestTask); + tasks.add(secondTestTask); + filteredResult.add(firstTestTask); + filteredResult.add(secondTestTask); + assertNotEquals(filteredResult, (FilterUtil.filterTaskByNames(tasks, nameList))); + } + + @Test + public void testFilterTaskByNames_filter_by_subname_equals() { + List tasks = getEmptyTaskList(); + HashSet nameList = new HashSet(); + List filteredResult = getEmptyTaskList(); + + // Filter out first test task + tasks.add(firstTestTask); + tasks.add(secondTestTask); + filteredResult.add(firstTestTask); + nameList.add("Milk"); + assertEquals(filteredResult, FilterUtil.filterTaskByNames(tasks, nameList)); + } + + @Test + public void testFilterTaskByNames_filter_by_subname_not_equals() { + List tasks = getEmptyTaskList(); + HashSet nameList = new HashSet(); + List filteredResult = getEmptyTaskList(); + + tasks.add(firstTestTask); + tasks.add(secondTestTask); + filteredResult.add(firstTestTask); + filteredResult.add(secondTestTask); + nameList.add("Milk"); + assertNotEquals(filteredResult, FilterUtil.filterTaskByNames(tasks, nameList)); + } + + @Test + public void testFilterTaskByTags_with_empty_task_list_equals() { + List tasks = getEmptyTaskList(); + HashSet nameList = new HashSet(); + // Empty task list and name list + assertEquals(tasks, FilterUtil.filterTaskByTags(tasks, nameList)); + // Empty task list + nameList.add("Nothing"); + assertEquals(tasks, FilterUtil.filterTaskByTags(tasks, nameList)); + } + + @Test + public void testFilterTaskByTags_equals() { + List tasks = getEmptyTaskList(); + HashSet nameList = new HashSet(); + List filteredResult = getEmptyTaskList(); + + // Filter out first test task + nameList.add("personal"); + tasks.add(firstTestTask); + tasks.add(secondTestTask); + filteredResult.add(firstTestTask); + assertEquals(filteredResult, FilterUtil.filterTaskByTags(tasks, nameList)); + } + + @Test + public void testFilterTaskByTags_not_equals() { + List tasks = getEmptyTaskList(); + HashSet nameList = new HashSet(); + List filteredResult = getEmptyTaskList(); + + // Filter out first test task + nameList.add("Buy"); + tasks.add(firstTestTask); + tasks.add(secondTestTask); + filteredResult.add(firstTestTask); + assertNotEquals(filteredResult, FilterUtil.filterTaskByTags(tasks, nameList)); + } + + @Test + public void testFilterCompletedTaskList_equals() { + List tasks = getEmptyTaskList(); + // Check with empty tasks + assertEquals(tasks, FilterUtil.filterTasksByStatus(tasks, true)); + tasks.add(firstTestTask); + tasks.add(secondTestTask); + + // Filter out completed tasks + List filteredTasks = getEmptyTaskList(); + filteredTasks.add(firstTestTask); + assertEquals(filteredTasks, FilterUtil.filterTasksByStatus(tasks, true)); + } + + @Test + public void testFilterCompletedTaskList_not_equals() { + List tasks = getEmptyTaskList(); + List filteredResult = getEmptyTaskList(); + tasks.add(firstTestTask); + tasks.add(secondTestTask); + filteredResult.add(secondTestTask); + + // Filter out completed tasks + assertNotEquals(filteredResult, FilterUtil.filterTasksByStatus(tasks, true)); + } + + @Test + public void testFilterIncompletedTaskList_equals() { + List tasks = getEmptyTaskList(); + // Check with empty tasks + assertEquals(tasks, FilterUtil.filterTasksByStatus(tasks, false)); + tasks.add(firstTestTask); + tasks.add(secondTestTask); + + // Filter out incomplete tasks + List filteredTasks = getEmptyTaskList(); + filteredTasks.add(secondTestTask); + assertEquals(filteredTasks, FilterUtil.filterTasksByStatus(tasks, false)); + } + + @Test + public void testFilterIncompletedTaskList_not_equals() { + List tasks = getEmptyTaskList(); + tasks.add(firstTestTask); + tasks.add(secondTestTask); + + // Filter out incomplete tasks + List filteredTasks = getEmptyTaskList(); + filteredTasks.add(firstTestTask); + filteredTasks.add(secondTestTask); + assertNotEquals(filteredTasks, FilterUtil.filterTasksByStatus(tasks, false)); + } + + @Test + public void testFilterTaskBySingleDate_with_empty_tasks_equals() { + List tasks = getEmptyTaskList(); + assertEquals(tasks, FilterUtil.filterTaskBySingleDate(tasks, DateUtil.floorDate(TODAY))); + assertEquals(tasks, FilterUtil.filterTaskBySingleDate(tasks, null)); + } + + @Test + public void testFilterTaskBySingleDate_equals() { + List tasks = getEmptyTaskList(); + tasks.add(firstTestTask); + tasks.add(secondTestTask); + + // Filter out first task + List filteredTasks = getEmptyTaskList(); + filteredTasks.add(firstTestTask); + assertEquals(filteredTasks, FilterUtil.filterTaskBySingleDate(filteredTasks, DateUtil.floorDate(TODAY))); + } + + @Test + public void testFilterTaskBySingleDate_not_equals() { + List tasks = getEmptyTaskList(); + tasks.add(firstTestTask); + tasks.add(secondTestTask); + + List filteredTasks = getEmptyTaskList(); + filteredTasks.add(firstTestTask); + filteredTasks.add(firstTestTask); + assertNotEquals(filteredTasks, FilterUtil.filterTaskBySingleDate(tasks, TODAY)); + } + + @Test + public void testFilterTaskWithDateRange_with_empty_tasks_equals() { + List tasks = getEmptyTaskList(); + assertEquals(tasks, FilterUtil.filterTaskWithDateRange(tasks, + LocalDateTime.now().plusDays(3), LocalDateTime.now().plusDays(4))); + } + + @Test + public void testFilterTaskWithDateRange_out_of_range_equals() { + List tasks = getEmptyTaskList(); + tasks.add(firstTestTask); + // Filter out of range of test task + assertEquals(getEmptyTaskList(), FilterUtil.filterTaskWithDateRange(tasks, + LocalDateTime.now().plusDays(3), LocalDateTime.now().plusDays(4))); + } + + @Test + public void testFilterTaskWithDateRange_equals() { + List tasks = getEmptyTaskList(); + tasks.add(firstTestTask); + tasks.add(secondTestTask); + + // Filter out first task + List filteredTasks = getEmptyTaskList(); + filteredTasks.add(firstTestTask); + assertEquals(filteredTasks, FilterUtil.filterTaskWithDateRange(tasks, TODAY, TODAY)); + } + + @Test + public void testFilterTaskWithDateRange_with_null_dates_equals() { + List tasks = getEmptyTaskList(); + tasks.add(firstTestTask); + tasks.add(secondTestTask); + + List filteredTasks = getEmptyTaskList(); + filteredTasks.add(firstTestTask); + filteredTasks.add(secondTestTask); + // Filter out both task + assertEquals(filteredTasks, FilterUtil.filterTaskWithDateRange(tasks, null, TOMORROW)); + assertEquals(filteredTasks, FilterUtil.filterTaskWithDateRange(tasks, YESTERDAY, null)); + } + + /* ============================= Test cases for Event Filtering Methods ==================== */ + + @Test + public void testFilterOutEvent_equals() { + List calendarItems = new ArrayList(); + calendarItems.addAll(overdueEvents); + assertEquals(calendarItems, FilterUtil.filterOutEvent(calendarItems)); + } + + @Test + public void testFilterOutEvent_not_equals() { + List calendarItems = new ArrayList(); + calendarItems.add(firstTestTask); + calendarItems.addAll(overdueEvents); + assertNotEquals(calendarItems, FilterUtil.filterOutEvent(calendarItems)); + } + + @Test + public void testFilterEventByNames_filter_with_empty_eventList_equals() { + List events = getEmptyEventList(); + HashSet nameList = new HashSet(); + // Empty event list and name list + assertEquals(events, FilterUtil.filterEventByNames(events, nameList)); + // Empty event list + nameList.add("Nothing"); + assertEquals(events, FilterUtil.filterEventByNames(events, nameList)); + } + + @Test + public void testFilterEventByNames_filter_equals() { + List events = getEmptyEventList(); + HashSet nameList = new HashSet(); + List filteredResult = getEmptyEventList(); + + // Filter out overdue events + nameList.add("CS2103"); + nameList.add("Roadshow"); + events.addAll(overdueEvents); + events.addAll(currentEvents); + filteredResult.addAll(overdueEvents); + assertEquals(filteredResult, FilterUtil.filterEventByNames(events, nameList)); + } + + @Test + public void testFilterEventByNames_filter_not_equals() { + List events = getEmptyEventList(); + HashSet nameList = new HashSet(); + events.addAll(overdueEvents); + nameList.add("Nothing"); + assertNotEquals(events, FilterUtil.filterEventByNames(events, nameList)); + } + + @Test + public void testFilterEventByTags_with_empty_event_list_equals() { + List events = getEmptyEventList(); + HashSet nameList = new HashSet(); + // Empty event list and name list + assertEquals(events, FilterUtil.filterEventByTags(events, nameList)); + // Empty event list + nameList.add("Nothing"); + assertEquals(events, FilterUtil.filterEventByTags(events, nameList)); + } + + @Test + public void testFilterEventByTags_equals() { + List events = getEmptyEventList(); + HashSet nameList = new HashSet(); + List filteredResult = getEmptyEventList(); + + // Filter out overdue events + nameList.add("CS3216"); + nameList.add("CSIT"); + events.addAll(overdueEvents); + events.addAll(currentEvents); + filteredResult.addAll(overdueEvents); + assertEquals(filteredResult, FilterUtil.filterEventByTags(events, nameList)); + } + + @Test + public void testFilterEventByTags_not_equals() { + List events = getEmptyEventList(); + HashSet nameList = new HashSet(); + List filteredResult = getEmptyEventList(); + + // Filter out overdue events + nameList.add("test"); + events.addAll(overdueEvents); + filteredResult.addAll(overdueEvents); + assertNotEquals(filteredResult, FilterUtil.filterEventByTags(events, nameList)); + } + + @Test + public void testFilterIsOverEventList_with_empty_event_list_equals() { + List events = new ArrayList(); + // Filter with empty events list + assertEquals(events, FilterUtil.filterEventsByStatus(events, true)); + } + + @Test + public void testFilterIsOverEventList_equals() { + List events = new ArrayList(); + List filteredResult = getEmptyEventList(); + + // Filter out overdue events + events.addAll(overdueEvents); + events.addAll(currentEvents); + filteredResult.addAll(overdueEvents); + assertEquals(filteredResult, FilterUtil.filterEventsByStatus(events, true)); + } + + @Test + public void testFilterIsOverEventList_not_equals() { + List events = new ArrayList(); + List filteredResult = getEmptyEventList(); + events.addAll(overdueEvents); + events.addAll(currentEvents); + filteredResult.addAll(overdueEvents); + filteredResult.addAll(currentEvents); + assertNotEquals(filteredResult, FilterUtil.filterEventsByStatus(events, false)); + } + + @Test + public void testFilterCurrentEventList_with_empty_event_list_equals() { + List events = new ArrayList(); + // Filter with empty events list + assertEquals(events, FilterUtil.filterEventsByStatus(events, false)); + } + + @Test + public void testFilterCurrentEventList_equals() { + List events = new ArrayList(); + List filteredResult = getEmptyEventList(); + events.addAll(overdueEvents); + events.addAll(currentEvents); + filteredResult.addAll(currentEvents); + assertEquals(filteredResult, FilterUtil.filterEventsByStatus(events, false)); + } + + @Test + public void testFilterCurrentEventList_not_equals() { + List events = new ArrayList(); + List filteredResult = getEmptyEventList(); + events.addAll(overdueEvents); + events.addAll(currentEvents); + filteredResult.addAll(currentEvents); + filteredResult.addAll(overdueEvents); + assertNotEquals(filteredResult, FilterUtil.filterEventsByStatus(events, true)); + } + + @Test + public void testFilterEventsBySingleDate_with_empty_event_list_equals() { + List events = new ArrayList(); + // Events is empty + assertEquals(events, FilterUtil.filterEventBySingleDate(events, TODAY)); + } + + @Test + public void testFilterEventBySingleDate_equals() { + List events = new ArrayList(); + List filteredResult = getEmptyEventList(); + // Filter out overdue events + events.addAll(overdueEvents); + events.addAll(currentEvents); + filteredResult.addAll(overdueEvents); + assertEquals(filteredResult, FilterUtil.filterEventBySingleDate(events, DateUtil.floorDate(YESTERDAY))); + } + + @Test + public void testFilterEventBySingleDate_not_equals() { + List events = new ArrayList(); + List filteredResult = getEmptyEventList(); + + // Filter out current events + events.addAll(overdueEvents); + events.addAll(currentEvents); + filteredResult.addAll(currentEvents); + assertNotEquals(filteredResult, FilterUtil.filterEventBySingleDate(events, DateUtil.floorDate(YESTERDAY))); + } + + @Test + public void testFilterEventWithDateRange_empty_event_list_equals() { + List events = new ArrayList(); + // Events is empty + assertEquals(events, FilterUtil.filterEventWithDateRange(events, YESTERDAY, YESTERDAY)); + } + + @Test + public void testFilterEventWithDateRange_equals() { + List events = new ArrayList(); + List filteredResult = new ArrayList(); + // Filter out overdue events + events.addAll(overdueEvents); + events.addAll(currentEvents); + filteredResult.addAll(overdueEvents); + assertEquals(filteredResult, + FilterUtil.filterEventWithDateRange(events, DateUtil.floorDate(YESTERDAY), DateUtil.ceilDate(YESTERDAY))); + } + + @Test + public void testFilterEventWithDateRange_null_dates_equals() { + List events = new ArrayList(); + List filteredResult = new ArrayList(); + // Filter out both overdue and current events + events.addAll(overdueEvents); + events.addAll(currentEvents); + filteredResult.addAll(overdueEvents); + filteredResult.addAll(currentEvents); + assertEquals(events, FilterUtil.filterEventWithDateRange(events, null, DateUtil.ceilDate(TOMORROW))); + assertEquals(events, FilterUtil.filterEventWithDateRange(events, DateUtil.floorDate(YESTERDAY), null)); + assertEquals(events, FilterUtil.filterEventWithDateRange(events, null, null)); + } + + @Test + public void testFilterEventWithDateRange_not_equals() { + List events = new ArrayList(); + List filteredResult = new ArrayList(); + // Filter out overdue events + events.addAll(currentEvents); + events.addAll(overdueEvents); + filteredResult.addAll(currentEvents); + assertNotEquals(filteredResult, + FilterUtil.filterEventWithDateRange(events, DateUtil.floorDate(YESTERDAY), DateUtil.ceilDate(YESTERDAY))); + } + + /* =================== Helper methods to be use to generate Task and Event for testing =============== */ + + private Task getFirstTestTask() { + Task task = new Task(); + task.setName("Buy Milk"); + task.setCalendarDateTime(TODAY); + task.addTag("personal"); + task.setCompleted(); + return task; + } + + private Task getSecondTestTask() { + Task task = new Task(); + task.setName("CS2103"); + task.setCalendarDateTime(TOMORROW); + task.addTag("CS2103"); + return task; + } + + private List getEmptyTaskList() { + return new ArrayList(); + } + + private List getEmptyEventList() { + return new ArrayList(); + } + + private List getOverdueEvents() { + List events = new ArrayList(); + Event event = new Event(); + event.setStartDate(YESTERDAY); + event.setEndDate(YESTERDAY); + event.setName("CS2103 V0.5"); + event.addTag("CS2103"); + events.add(event); + event.removeTag("CS2103"); + event.setName("CSIT roadshow"); + event.addTag("CSIT"); + events.add(event); + return events; + } + + private List getCurrentEvents() { + List events = new ArrayList(); + Event event = new Event(); + event.setStartDate(TODAY); + event.setEndDate(TOMORROW); + event.setName("CS3216 9th Steps"); + event.addTag("CS3216"); + events.add(event); + event.removeTag("CS3216"); + event.setName("CS3217 9th Steps"); + event.addTag("CS3217"); + events.add(event); + return events; + } +} +``` +###### /java/seedu/todo/commons/util/ParseUtilTest.java +``` java +public class ParseUtilTest { + + Map parsedResult = new HashMap(); + public static final String EMPTY_TOKEN = ""; + public static final String [] NULL_TOKEN_RESULT = new String [] { null }; + public static final String [] TOKEN_RESULT = new String [] {"test", "test1, test2"}; + + public static final String TEST_TOKEN = "test"; + public static final String TOKEN_KEYWORD_DOES_NOT_EXIST = "random"; + + public static final int TOKEN_RESULT_INDEX_ONE = 0; + public static final int TOKEN_RESULT_INDEX_TWO = 1; + + public static final String CORRECT_NATURAL_DATE = "today"; + public static final String INCORRECT_NATURAL_DATE = "todar"; + + public static final String DATE_ON_FORMAT = Tokenizer.TIME_TOKEN; + public static final String DATE_FROM_FORMAT = Tokenizer.TIME_FROM_TOKEN; + public static final String DATE_TO_FORMAT = Tokenizer.TIME_TO_TOKEN; + + @Test + public void testIsTokenNull_true() { + parsedResult.put(TEST_TOKEN, NULL_TOKEN_RESULT); + assertTrue(ParseUtil.isTokenNull(parsedResult, TEST_TOKEN)); + } + + @Test + public void testIsTokenNull_false() { + parsedResult.put(TEST_TOKEN, TOKEN_RESULT); + assertFalse(ParseUtil.isTokenNull(parsedResult, TEST_TOKEN)); + } + + @Test + public void testDoesTokenContainKeyword_true() { + parsedResult.put(TEST_TOKEN, TOKEN_RESULT); + assertTrue(ParseUtil.doesTokenContainKeyword(parsedResult, TEST_TOKEN, TOKEN_RESULT[TOKEN_RESULT_INDEX_ONE])); + } + + @Test + public void testDoesTokenContainKeyword_false() { + parsedResult.put(TEST_TOKEN, TOKEN_RESULT); + assertFalse(ParseUtil.doesTokenContainKeyword(parsedResult, TEST_TOKEN, TOKEN_KEYWORD_DOES_NOT_EXIST)); + } + + @Test + public void testDoesTokenContainKeyword_with_empty_token_false() { + parsedResult.put(TEST_TOKEN, TOKEN_RESULT); + assertFalse(ParseUtil.doesTokenContainKeyword(parsedResult, EMPTY_TOKEN, TOKEN_RESULT[TOKEN_RESULT_INDEX_ONE])); + assertFalse(ParseUtil.doesTokenContainKeyword(parsedResult, EMPTY_TOKEN, NULL_TOKEN_RESULT[TOKEN_RESULT_INDEX_ONE])); + } + + @Test + public void testGetTokenResult_not_null() { + assertNotNull(ParseUtil.getTokenResult(parsedResult, TEST_TOKEN), TOKEN_RESULT[TOKEN_RESULT_INDEX_TWO]); + } + + @Test + public void testGetTokenResult_null() { + assertNull(ParseUtil.getTokenResult(parsedResult, EMPTY_TOKEN)); + } + + @Test + public void testGetTokenResult_equals() { + parsedResult.put(TEST_TOKEN, TOKEN_RESULT); + assertEquals(ParseUtil.getTokenResult(parsedResult, TEST_TOKEN), TOKEN_RESULT[TOKEN_RESULT_INDEX_TWO]); + } + + @Test + public void testGetTokenResult_not_equals() { + parsedResult.put(TEST_TOKEN, TOKEN_RESULT); + assertNotEquals(ParseUtil.getTokenResult(parsedResult, TEST_TOKEN), TOKEN_RESULT[TOKEN_RESULT_INDEX_ONE]); + } + + @Test + public void testParseDates_with_valid_dates_not_null() { + String [] date_on_result = { "time", "today" }; + String [] incorrect_date_result = { "" , null }; + + parsedResult.put(DATE_ON_FORMAT, date_on_result); + parsedResult.put(DATE_FROM_FORMAT, incorrect_date_result); + parsedResult.put(DATE_TO_FORMAT, incorrect_date_result); + assertNotNull(ParseUtil.parseDates(parsedResult)); + } + + @Test + public void testParseDates_null() { + String [] incorrect_date_result = { "" , null }; + parsedResult.put(DATE_ON_FORMAT, incorrect_date_result); + parsedResult.put(DATE_FROM_FORMAT, incorrect_date_result); + parsedResult.put(DATE_TO_FORMAT, incorrect_date_result); + assertNull(ParseUtil.parseDates(parsedResult)); + } + + @Test + public void testParseDates_equals() { + String[] test_result = { "3", "today" , "tuesday" , "wednesday" }; + String [] date_on_result = { "time", "today" }; + String [] date_from_result = { "timeFrom" , "tuesday" }; + String [] date_to_result = { "timeTo" , "wednesday" }; + + parsedResult.put(DATE_ON_FORMAT, date_on_result); + parsedResult.put(DATE_FROM_FORMAT, date_from_result); + parsedResult.put(DATE_TO_FORMAT, date_to_result); + assertArrayEquals(test_result, ParseUtil.parseDates(parsedResult)); + } +} +``` +###### /java/seedu/todo/commons/util/StringUtilTest.java +``` java + @Test + public void testSplitStringBySpace_null() { + assertNull(StringUtil.splitStringBySpace(null)); + } + +``` +###### /java/seedu/todo/commons/util/StringUtilTest.java +``` java + @Test + public void testSplitStringBySpace_not_null() { + String testcase1 = "TEST TEST"; + assertNotNull(StringUtil.splitStringBySpace(testcase1)); + } + +``` +###### /java/seedu/todo/commons/util/StringUtilTest.java +``` java + @Test + public void testSplitStringBySpace_equals() { + String testcase1 = "TEST"; + String testcase2 = "TEST TEST"; + assertArrayEquals(testcase1.split(" "), StringUtil.splitStringBySpace(testcase1)); + assertArrayEquals(testcase2.split(" "),StringUtil.splitStringBySpace(testcase2)); + } + +``` +###### /java/seedu/todo/commons/util/StringUtilTest.java +``` java + @Test + public void testFormatNumberOfTaskWithPuralizer_equals() { + int single = 1; + assertEquals(String.format("%d task", single), StringUtil.formatNumberOfTaskWithPuralizer(single)); + int pural = 2; + assertEquals(String.format("%d tasks", pural), StringUtil.formatNumberOfTaskWithPuralizer(pural)); + } + +``` +###### /java/seedu/todo/commons/util/StringUtilTest.java +``` java + @Test + public void testFormatNumberOfTaskWithPuralizer_not_equals() { + int single = 1; + assertNotEquals(String.format("%d tasks", single), StringUtil.formatNumberOfTaskWithPuralizer(single)); + int pural = 2; + assertNotEquals(String.format("%d task", pural), StringUtil.formatNumberOfTaskWithPuralizer(pural)); + } + +``` +###### /java/seedu/todo/commons/util/StringUtilTest.java +``` java + @Test + public void testFormatNumberOfEventWithPuralizer_equals() { + int single = 1; + assertEquals(String.format("%d event", single), StringUtil.formatNumberOfEventWithPuralizer(single)); + int pural = 2; + assertEquals(String.format("%d events", pural), StringUtil.formatNumberOfEventWithPuralizer(pural)); + } + +``` +###### /java/seedu/todo/commons/util/StringUtilTest.java +``` java + @Test + public void testFormatNumberOfEventWithPuralizer_not_equals() { + int single = 1; + assertNotEquals(String.format("%d events", single), StringUtil.formatNumberOfEventWithPuralizer(single)); + int pural = 2; + assertNotEquals(String.format("%d event", pural), StringUtil.formatNumberOfEventWithPuralizer(pural)); + } + +``` +###### /java/seedu/todo/commons/util/StringUtilTest.java +``` java + @Test + public void testDisplayNumberOfTaskAndEventFoundWithPuralizer_equals() { + int numTasks = 0; + int numEvents = 0; + assertEquals("No item found!", StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(numTasks, numEvents)); + numTasks = 1; + assertEquals("1 task", StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(numTasks, numEvents)); + numEvents = 1; + assertEquals("1 task and 1 event", StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(numTasks, numEvents)); + numTasks = 0; + assertEquals("1 event", StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(numTasks, numEvents)); + } +} +``` +###### /java/seedu/todo/guitests/ClearCommandTest.java +``` java + @Test + public void clear_tasks_by_single_date() { + console.runCommand("clear tasks on tmr"); + // For console text area to check output message + expectedNumOfTasks = 1; + expectedNumOfEvents = 0; + String expectedOutputMessage = String.format(ClearController.MESSAGE_CLEAR_SUCCESS_FORMAT, + StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(expectedNumOfTasks, expectedNumOfEvents)); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + + // Check if Tasks and Events still in the GUI + assertTaskNotVisibleAfterCmd("list", task1); + assertTaskVisibleAfterCmd("list", task2); + assertEventVisibleAfterCmd("list", event3); + assertEventVisibleAfterCmd("list", event4); + } + + @Test + public void clear_tasks_by_date_range() { + console.runCommand("clear tasks from today to tmr"); + // For console text area to check output message + expectedNumOfTasks = 1; + expectedNumOfEvents = 0; + String expectedOutputMessage = String.format(ClearController.MESSAGE_CLEAR_SUCCESS_FORMAT, + StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(expectedNumOfTasks, expectedNumOfEvents)); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + + // Check if Tasks and Events still in the GUI + assertTaskNotVisibleAfterCmd("list", task1); + assertTaskVisibleAfterCmd("list", task2); + assertEventVisibleAfterCmd("list", event3); + assertEventVisibleAfterCmd("list", event4); + } + + @Test + public void clear_tasks_by_date_range_with_single_date() { + console.runCommand("clear tasks from today"); + // For console text area to check output message + expectedNumOfTasks = 2; + expectedNumOfEvents = 0; + String expectedOutputMessage = String.format(ClearController.MESSAGE_CLEAR_SUCCESS_FORMAT, + StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(expectedNumOfTasks, expectedNumOfEvents)); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + + // Check if Tasks and Events still in the GUI + assertTaskNotVisibleAfterCmd("list", task1); + assertTaskNotVisibleAfterCmd("list", task2); + assertEventVisibleAfterCmd("list", event3); + assertEventVisibleAfterCmd("list", event4); + } + + @Test + public void clear_events_by_single_date() { + console.runCommand("clear events on tmr"); + // For console text area to check output message + expectedNumOfTasks = 0; + expectedNumOfEvents = 1; + String expectedOutputMessage = String.format(ClearController.MESSAGE_CLEAR_SUCCESS_FORMAT, + StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(expectedNumOfTasks, expectedNumOfEvents)); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + + // Check if Tasks and Events still in the GUI + assertTaskVisibleAfterCmd("list", task1); + assertTaskVisibleAfterCmd("list", task2); + assertEventNotVisibleAfterCmd("list", event3); + assertEventVisibleAfterCmd("list", event4); + } + + @Test + public void clear_events_by_date_range() { + console.runCommand("clear events from today to tmr"); + // For console text area to check output message + expectedNumOfTasks = 0; + expectedNumOfEvents = 1; + String expectedOutputMessage = String.format(ClearController.MESSAGE_CLEAR_SUCCESS_FORMAT, + StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(expectedNumOfTasks, expectedNumOfEvents)); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + + // Check if Tasks and Events still in the GUI + assertTaskVisibleAfterCmd("list", task1); + assertTaskVisibleAfterCmd("list", task2); + assertEventNotVisibleAfterCmd("list", event3); + assertEventVisibleAfterCmd("list", event4); + } + + @Test + public void clear_events_by_date_range_with_single_date() { + console.runCommand("clear events from today"); + // For console text area to check output message + expectedNumOfTasks = 0; + expectedNumOfEvents = 2; + String expectedOutputMessage = String.format(ClearController.MESSAGE_CLEAR_SUCCESS_FORMAT, + StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(expectedNumOfTasks, expectedNumOfEvents)); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + + // Check if Tasks and Events still in the GUI + assertTaskVisibleAfterCmd("list", task1); + assertTaskVisibleAfterCmd("list", task2); + assertEventNotVisibleAfterCmd("list", event3); + assertEventNotVisibleAfterCmd("list", event4); + } + + @Test + public void clear_by_single_date() { + console.runCommand("clear on tmr"); + // For console text area to check output message + expectedNumOfTasks = 1; + expectedNumOfEvents = 1; + String expectedOutputMessage = String.format(ClearController.MESSAGE_CLEAR_SUCCESS_FORMAT, + StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(expectedNumOfTasks, expectedNumOfEvents)); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + + // Check if Tasks and Events still in the GUI + assertTaskNotVisibleAfterCmd("list", task1); + assertTaskVisibleAfterCmd("list", task2); + assertEventNotVisibleAfterCmd("list", event3); + assertEventVisibleAfterCmd("list", event4); + } + + @Test + public void clear_by_date_range() { + console.runCommand("clear from today to tmr"); + // For console text area to check output message + expectedNumOfTasks = 1; + expectedNumOfEvents = 1; + String expectedOutputMessage = String.format(ClearController.MESSAGE_CLEAR_SUCCESS_FORMAT, + StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(expectedNumOfTasks, expectedNumOfEvents)); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + + // Check if Tasks and Events still in the GUI + assertTaskNotVisibleAfterCmd("list", task1); + assertTaskVisibleAfterCmd("list", task2); + assertEventNotVisibleAfterCmd("list", event3); + assertEventVisibleAfterCmd("list", event4); + } + + @Test + public void clear_by_date_range_with_single_date() { + console.runCommand("clear from today"); + // For console text area to check output message + expectedNumOfTasks = 2; + expectedNumOfEvents = 2; + String expectedOutputMessage = String.format(ClearController.MESSAGE_CLEAR_SUCCESS_FORMAT, + StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(expectedNumOfTasks, expectedNumOfEvents)); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + + // Check if Tasks and Events still in the GUI + assertTaskNotVisibleAfterCmd("list", task1); + assertTaskNotVisibleAfterCmd("list", task2); + assertEventNotVisibleAfterCmd("list", event3); + assertEventNotVisibleAfterCmd("list", event4); + } + + @Test + public void clear_with_invalid_date_syntax() { + console.runCommand("clear from todar"); + // For console text area to check error message + String expectedDisambiguation = ClearController.CLEAR_DATE_SYNTAX; + assertEquals(console.getConsoleInputText(), expectedDisambiguation); + String expectedOutputMessage = formatConsoleOutputTextArea(ClearController.MESSAGE_NO_DATE_DETECTED); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + + // Check if Tasks and Events still in the GUI + assertTaskVisibleAfterCmd("list", task1); + assertTaskVisibleAfterCmd("list", task2); + assertEventVisibleAfterCmd("list", event3); + assertEventVisibleAfterCmd("list", event4); + } + + @Test + public void clear_with_date_conflict() { + console.runCommand("clear by today to tmr"); + // For console text area to check error message + String expectedDisambiguation = ClearController.CLEAR_DATE_SYNTAX; + assertEquals(console.getConsoleInputText(), expectedDisambiguation); + String expectedOutputMessage = formatConsoleOutputTextArea(ClearController.MESSAGE_DATE_CONFLICT); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + + // Check if Tasks and Events still in the GUI + assertTaskVisibleAfterCmd("list", task1); + assertTaskVisibleAfterCmd("list", task2); + assertEventVisibleAfterCmd("list", event3); + assertEventVisibleAfterCmd("list", event4); + } + + @Test + public void clear_with_item_type_conflict() { + console.runCommand("clear tasks events"); + // For console text area to check error message + String expectedDisambiguation = ClearController.COMMAND_SYNTAX; + assertEquals(console.getConsoleInputText(), expectedDisambiguation); + String expectedOutputMessage = formatConsoleOutputTextArea(ClearController.MESSAGE_ITEM_TYPE_CONFLICT); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + + // Check if Tasks and Events still in the GUI + assertTaskVisibleAfterCmd("list", task1); + assertTaskVisibleAfterCmd("list", task2); + assertEventVisibleAfterCmd("list", event3); + assertEventVisibleAfterCmd("list", event4); + } + + @Test + public void clear_with_invalid_command_syntax_by_event_status() { + console.runCommand("clear current events"); + // For console text area to check error message + String expectedDisambiguation = ClearController.COMMAND_SYNTAX; + assertEquals(console.getConsoleInputText(), expectedDisambiguation); + String expectedOutputMessage = formatConsoleOutputTextArea(ClearController.MESSAGE_CLEAR_UNABLE_TO_SUPPORT); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + + // Check if Tasks and Events still in the GUI + assertTaskVisibleAfterCmd("list", task1); + assertTaskVisibleAfterCmd("list", task2); + assertEventVisibleAfterCmd("list", event3); + assertEventVisibleAfterCmd("list", event4); + } + + @Test + public void clear_with_invalid_command_syntax_by_task_status() { + console.runCommand("clear completed tasks"); + // For console text area to check error message + String expectedDisambiguation = ClearController.COMMAND_SYNTAX; + assertEquals(console.getConsoleInputText(), expectedDisambiguation); + String expectedOutputMessage = formatConsoleOutputTextArea(ClearController.MESSAGE_CLEAR_UNABLE_TO_SUPPORT); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + + // Check if Tasks and Events still in the GUI + assertTaskVisibleAfterCmd("list", task1); + assertTaskVisibleAfterCmd("list", task2); + assertEventVisibleAfterCmd("list", event3); + assertEventVisibleAfterCmd("list", event4); + } +} +``` +###### /java/seedu/todo/guitests/FindCommandTest.java +``` java + */ +public class FindCommandTest extends GuiTest { +``` +###### /java/seedu/todo/guitests/FindCommandTest.java +``` java + @Test + public void find_by_name() { + String command = "find name buy"; + // To check if the tasks and events are been filtered as expected + assertTaskVisibleAfterCmd(command, task1); + assertTaskVisibleAfterCmd(command, task2); + assertEventNotVisibleAfterCmd(command, event3); + assertEventVisibleAfterCmd(command, event4); + + // For console text area to check output message + expectedNumOfTasks = 2; + expectedNumOfEvents = 1; + String expectedOutputMessage = String.format(FindController.MESSAGE_RESULT_FOUND_FORMAT, + StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(expectedNumOfTasks, expectedNumOfEvents)); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + @Test + public void find_tasks_by_name() { + String command = "find name buy tasks"; + // To check if the tasks are been filtered as expected + assertTaskVisibleAfterCmd(command, task1); + assertTaskVisibleAfterCmd(command, task2); + assertEventNotVisibleAfterCmd(command, event3); + assertEventNotVisibleAfterCmd(command, event4); + + // For console text area to check output message + expectedNumOfTasks = 2; + expectedNumOfEvents = 0; + String expectedOutputMessage = String.format(FindController.MESSAGE_RESULT_FOUND_FORMAT, + StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(expectedNumOfTasks, expectedNumOfEvents)); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + @Test + public void find_events_by_name() { + String command = "find name buy events"; + // To check if the events are been filtered as expected + assertTaskNotVisibleAfterCmd(command, task1); + assertTaskNotVisibleAfterCmd(command, task2); + assertEventNotVisibleAfterCmd(command, event3); + assertEventVisibleAfterCmd(command, event4); + + // For console text area to check output message + expectedNumOfTasks = 0; + expectedNumOfEvents = 1; + String expectedOutputMessage = String.format(FindController.MESSAGE_RESULT_FOUND_FORMAT, + StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(expectedNumOfTasks, expectedNumOfEvents)); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + @Test + public void find_by_invalid_name() { + String command = "find name tester"; + // To check if the tasks and events are been filtered as expected + assertTaskVisibleAfterCmd(command, task1); + assertTaskVisibleAfterCmd(command, task2); + assertEventVisibleAfterCmd(command, event3); + assertEventVisibleAfterCmd(command, event4); + + // For console text area to check error message + assertEquals(console.getConsoleTextArea(), FindController.MESSAGE_NO_RESULT_FOUND); + } + + @Test + public void find_by_tag() { + String command = "find tagName buy"; + // To check if the tasks and events are been filtered as expected + assertTaskNotVisibleAfterCmd(command, task1); + assertTaskNotVisibleAfterCmd(command, task2); + assertEventNotVisibleAfterCmd(command, event3); + assertEventVisibleAfterCmd(command, event4); + + // For console text area to check output message + expectedNumOfTasks = 0; + expectedNumOfEvents = 1; + String expectedOutputMessage = String.format(FindController.MESSAGE_RESULT_FOUND_FORMAT, + StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(expectedNumOfTasks, expectedNumOfEvents)); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + @Test + public void find_tasks_by_tag() { + String command = "find tagName personal tasks"; + // To check if the tasks are been filtered as expected + assertTaskVisibleAfterCmd(command, task1); + assertTaskVisibleAfterCmd(command, task2); + assertEventNotVisibleAfterCmd(command, event3); + assertEventNotVisibleAfterCmd(command, event4); + + // For console text area to check output message + expectedNumOfTasks = 2; + expectedNumOfEvents = 0; + String expectedOutputMessage = String.format(FindController.MESSAGE_RESULT_FOUND_FORMAT, + StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(expectedNumOfTasks, expectedNumOfEvents)); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + @Test + public void find_events_by_tag() { + String command = "find tagName buy events"; + // To check if event 4 is been filtered as expected + assertTaskNotVisibleAfterCmd(command, task1); + assertTaskNotVisibleAfterCmd(command, task2); + assertEventNotVisibleAfterCmd(command, event3); + assertEventVisibleAfterCmd(command, event4); + + // For console text area to check output message + expectedNumOfTasks = 0; + expectedNumOfEvents = 1; + String expectedOutputMessage = String.format(FindController.MESSAGE_RESULT_FOUND_FORMAT, + StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(expectedNumOfTasks, expectedNumOfEvents)); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + @Test + public void find_by_invalid_tag() { + // To check if all tasks and events are still in the view + String command = "find tagName tester"; + assertTaskVisibleAfterCmd(command, task1); + assertTaskVisibleAfterCmd(command, task2); + assertEventVisibleAfterCmd(command, event3); + assertEventVisibleAfterCmd(command, event4); + + // For console text area to check output message + assertEquals(console.getConsoleTextArea(), FindController.MESSAGE_NO_RESULT_FOUND); + } + + @Test + public void find_by_keyword() { + String command = "find buy"; + // To check if tasks and events are been filtered as expected + assertTaskVisibleAfterCmd(command, task1); + assertTaskVisibleAfterCmd(command, task2); + assertEventNotVisibleAfterCmd(command, event3); + assertEventVisibleAfterCmd(command, event4); + + // For console text area to check output message + expectedNumOfTasks = 2; + expectedNumOfEvents = 1; + String expectedOutputMessage = String.format(FindController.MESSAGE_RESULT_FOUND_FORMAT, + StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(expectedNumOfTasks, expectedNumOfEvents)); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + @Test + public void find_tasks_by_keyword() { + String command = "find buy tasks"; + // To check if tasks are been filtered as expected + assertTaskVisibleAfterCmd(command, task1); + assertTaskVisibleAfterCmd(command, task2); + assertEventNotVisibleAfterCmd(command, event3); + assertEventNotVisibleAfterCmd(command, event4); + + // For console text area to check output message + expectedNumOfTasks = 2; + expectedNumOfEvents = 0; + String expectedOutputMessage = String.format(FindController.MESSAGE_RESULT_FOUND_FORMAT, + StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(expectedNumOfTasks, expectedNumOfEvents)); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + @Test + public void find_events_by_keyword() { + String command = "find buy events"; + // To check if event4 is been filtered + assertTaskNotVisibleAfterCmd(command, task1); + assertTaskNotVisibleAfterCmd(command, task2); + assertEventNotVisibleAfterCmd(command, event3); + assertEventVisibleAfterCmd(command, event4); + + // For console text area to check output message + expectedNumOfTasks = 0; + expectedNumOfEvents = 1; + String expectedOutputMessage = String.format(FindController.MESSAGE_RESULT_FOUND_FORMAT, + StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(expectedNumOfTasks, expectedNumOfEvents)); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + @Test + public void find_by_invalid_keyword() { + String command = "find tester"; + // To check if all tasks and events are still in the view + assertTaskVisibleAfterCmd(command, task1); + assertTaskVisibleAfterCmd(command, task2); + assertEventVisibleAfterCmd(command, event3); + assertEventVisibleAfterCmd(command, event4); + + // For console text area to check output message + assertEquals(console.getConsoleTextArea(), FindController.MESSAGE_NO_RESULT_FOUND); + } + + @Test + public void find_by_tasks_complete_status() { + console.runCommand("complete 1"); + String command = "find buy complete"; + // To check if task1 is been filtered as expected + assertTaskVisibleAfterCmd(command, task1); + assertTaskNotVisibleAfterCmd(command, task2); + assertEventNotVisibleAfterCmd(command, event3); + assertEventNotVisibleAfterCmd(command, event4); + + // For console text area to check output message + expectedNumOfTasks = 1; + expectedNumOfEvents = 0; + String expectedOutputMessage = String.format(FindController.MESSAGE_RESULT_FOUND_FORMAT, + StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(expectedNumOfTasks, expectedNumOfEvents)); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + @Test + public void find_by_tassk_incomplete_status() { + String command = "find buy incomplete"; + // To check if tasks are been filtered as expected + assertTaskVisibleAfterCmd(command, task1); + assertTaskVisibleAfterCmd(command, task2); + assertEventNotVisibleAfterCmd(command, event3); + assertEventNotVisibleAfterCmd(command, event4); + + // For console text area to check output message + expectedNumOfTasks = 2; + expectedNumOfEvents = 0; + String expectedOutputMessage = String.format(FindController.MESSAGE_RESULT_FOUND_FORMAT, + StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(expectedNumOfTasks, expectedNumOfEvents)); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + @Test + public void find_by_events_current_status() { + String command = "find buy current"; + // To check if event3 is been filtered as expected + assertTaskNotVisibleAfterCmd(command, task1); + assertTaskNotVisibleAfterCmd(command, task2); + assertEventNotVisibleAfterCmd(command, event3); + assertEventVisibleAfterCmd(command, event4); + + // For console text area to check output message + expectedNumOfTasks = 0; + expectedNumOfEvents = 1; + String expectedOutputMessage = String.format(FindController.MESSAGE_RESULT_FOUND_FORMAT, + StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(expectedNumOfTasks, expectedNumOfEvents)); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + @Test + public void find_by_events_over_status() { + String command = "find buy over"; + // To check if all tasks and events are still in the view + assertTaskVisibleAfterCmd(command, task1); + assertTaskVisibleAfterCmd(command, task2); + assertEventVisibleAfterCmd(command, event3); + assertEventVisibleAfterCmd(command, event4); + + // For console text area to check output message + assertEquals(console.getConsoleTextArea(), FindController.MESSAGE_NO_RESULT_FOUND); + } + + @Test + public void find_by_single_date() { + String command = "find buy on today"; + // To check if task1 is been filtered as expected + assertTaskVisibleAfterCmd(command, task1); + assertTaskNotVisibleAfterCmd(command, task2); + assertEventNotVisibleAfterCmd(command, event3); + assertEventNotVisibleAfterCmd(command, event4); + + // For console text area to check output message + expectedNumOfTasks = 1; + expectedNumOfEvents = 0; + String expectedOutputMessage = String.format(FindController.MESSAGE_RESULT_FOUND_FORMAT, + StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(expectedNumOfTasks, expectedNumOfEvents)); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + @Test + public void find_by_date_range() { + String command = "find buy from today"; + // To check if tasks and events are been filtered as expected + assertTaskVisibleAfterCmd(command, task1); + assertTaskVisibleAfterCmd(command, task2); + assertEventNotVisibleAfterCmd(command, event3); + assertEventVisibleAfterCmd(command, event4); + + // For console text area to check output message + expectedNumOfTasks = 2; + expectedNumOfEvents = 1; + String expectedOutputMessage = String.format(FindController.MESSAGE_RESULT_FOUND_FORMAT, + StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(expectedNumOfTasks, expectedNumOfEvents)); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + @Test + public void find_tasks_by_single_date() { + String command = "find buy tasks on today"; + + // To check if task1 is been filtered as expected + assertTaskVisibleAfterCmd(command, task1); + assertTaskNotVisibleAfterCmd(command, task2); + assertEventNotVisibleAfterCmd(command, event3); + assertEventNotVisibleAfterCmd(command, event4); + + // For console text area to check output message + expectedNumOfTasks = 1; + expectedNumOfEvents = 0; + String expectedOutputMessage = String.format(FindController.MESSAGE_RESULT_FOUND_FORMAT, + StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(expectedNumOfTasks, expectedNumOfEvents)); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + @Test + public void find_tasks_by_date_range() { + String command = "find buy tasks from today to tmr"; + + // To check if all tasks are been filtered as expected + assertTaskVisibleAfterCmd(command, task1); + assertTaskVisibleAfterCmd(command, task2); + assertEventNotVisibleAfterCmd(command, event3); + assertEventNotVisibleAfterCmd(command, event4); + + // For console text area to check output message + expectedNumOfTasks = 2; + expectedNumOfEvents = 0; + String expectedOutputMessage = String.format(FindController.MESSAGE_RESULT_FOUND_FORMAT, + StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(expectedNumOfTasks, expectedNumOfEvents)); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + @Test + public void find_tasks_by_date_range_with_single_date() { + String command = "find buy tasks from today"; + // To check if all tasks are been filtered as expected + assertTaskVisibleAfterCmd(command, task1); + assertTaskVisibleAfterCmd(command, task2); + assertEventNotVisibleAfterCmd(command, event3); + assertEventNotVisibleAfterCmd(command, event4); + + // For console text area to check output message + expectedNumOfTasks = 2; + expectedNumOfEvents = 0; + String expectedOutputMessage = String.format(FindController.MESSAGE_RESULT_FOUND_FORMAT, + StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(expectedNumOfTasks, expectedNumOfEvents)); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + @Test + public void find_events_by_single_date() { + String command = "find CS2103 events on tomorrow"; + // To check if event3 is been filtered as expected + assertTaskNotVisibleAfterCmd(command, task1); + assertTaskNotVisibleAfterCmd(command, task2); + assertEventVisibleAfterCmd(command, event3); + assertEventNotVisibleAfterCmd(command, event4); + + // For console text area to check output message + expectedNumOfTasks = 0; + expectedNumOfEvents = 1; + String expectedOutputMessage = String.format(FindController.MESSAGE_RESULT_FOUND_FORMAT, + StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(expectedNumOfTasks, expectedNumOfEvents)); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + @Test + public void find_events_by_date_range_with_single_date() { + String command = "find buy events from today"; + // To check if event4 is been filtered as expected + assertTaskNotVisibleAfterCmd(command, task1); + assertTaskNotVisibleAfterCmd(command, task2); + assertEventNotVisibleAfterCmd(command, event3); + assertEventVisibleAfterCmd(command, event4); + + // For console text area to check output message + expectedNumOfTasks = 0; + expectedNumOfEvents = 1; + String expectedOutputMessage = String.format(FindController.MESSAGE_RESULT_FOUND_FORMAT, + StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(expectedNumOfTasks, expectedNumOfEvents)); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + @Test + public void find_events_by_date_range() { + String command = "find CS2103 events from today to tmr"; + // To check if event3 is been filtered as expected + assertTaskNotVisibleAfterCmd(command, task1); + assertTaskNotVisibleAfterCmd(command, task2); + assertEventVisibleAfterCmd(command, event3); + assertEventNotVisibleAfterCmd(command, event4); + + // For console text area to check output message + expectedNumOfTasks = 0; + expectedNumOfEvents = 1; + String expectedOutputMessage = String.format(FindController.MESSAGE_RESULT_FOUND_FORMAT, + StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(expectedNumOfTasks, expectedNumOfEvents)); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + @Test + public void find_missingKeywords_disambiguate() { + String command = "find"; + console.runCommand(command); + + // To check if the consoleInputText matches the controller corrected syntax + String expectedDisambiguation = FindController.COMMAND_SYNTAX; + assertEquals(console.getConsoleInputText(), expectedDisambiguation); + + // For console text area to check error message + String expectedOutputMessage = formatConsoleOutputTextArea(FindController.MESSAGE_NO_KEYWORD_FOUND); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + @Test + public void find_invalidTaskSyntax_disambiguate() { + String command = "find buy task over"; + console.runCommand(command); + + // To check if the consoleInputText matches the controller corrected syntax + String expectedDisambiguation = FindController.FIND_TASK_SYNTAX; + assertEquals(console.getConsoleInputText(), expectedDisambiguation); + + // For console text area to check error message + String expectedOutputMessage = formatConsoleOutputTextArea(FindController.MESSAGE_INVALID_TASK_STATUS); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + @Test + public void find_invalidEventSyntax_disambiguate() { + String command = "find buy event complete"; + console.runCommand(command); + + // To check if the consoleInputText matches the controller corrected syntax + String expectedDisambiguation = FindController.FIND_EVENT_SYNTAX; + assertEquals(console.getConsoleInputText(), expectedDisambiguation); + + // For console text area to check error message + String expectedOutputMessage = formatConsoleOutputTextArea(FindController.MESSAGE_INVALID_EVENT_STATUS); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + @Test + public void find_with_invalid_single_date() { + String command = "find buy by todar"; + console.runCommand(command); + + // To check if the consoleInputText matches the controller corrected syntax + String expectedDisambiguation = FindController.COMMAND_SYNTAX; + assertEquals(console.getConsoleInputText(), expectedDisambiguation); + + // For console text area to check error message + String expectedOutputMessage = formatConsoleOutputTextArea(FindController.MESSAGE_NO_DATE_DETECTED); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + @Test + public void find_with_date_conflict() { + String command = "find buy by today from tmr"; + console.runCommand(command); + + // To check if the consoleInputText matches the controller corrected syntax + String expectedDisambiguation = FindController.COMMAND_SYNTAX; + assertEquals(console.getConsoleInputText(), expectedDisambiguation); + + // For console text area to check error message + String expectedOutputMessage = formatConsoleOutputTextArea(FindController.MESSAGE_DATE_CONFLICT); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + @Test + public void find_with_invalid_date_range() { + String command = "find buy from today to tml"; + console.runCommand(command); + + // To check if the consoleInputText matches the controller corrected syntax + String expectedDisambiguation = FindController.COMMAND_SYNTAX; + assertEquals(console.getConsoleInputText(), expectedDisambiguation); + + // For console text area to check error message + String expectedOutputMessage = formatConsoleOutputTextArea(FindController.MESSAGE_NO_DATE_DETECTED); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } +} +``` +###### /java/seedu/todo/guitests/guihandles/SideBarHandle.java +``` java + */ +public class SideBarHandle extends GuiHandle { + + private static final String TAGLIST = "#sidebarTagsPlaceholder"; + + public SideBarHandle(GuiRobot guiRobot, Stage primaryStage, String stageTitle) { + super(guiRobot, primaryStage, stageTitle); + } + + /** + * Returns a TaskListDateItemHandle that corresponds to the name specified. + * If it doesn't exist, it returns null. + */ + public TagListItemHandle getTagListItem(String tagName) { + Optional tagItemNode = guiRobot.lookup(TAGLIST).queryAll().stream() + .filter(node -> new TagListItemHandle(guiRobot, primaryStage, node).getName().equals(tagName)) + .findFirst(); + + if (tagItemNode.isPresent()) { + return new TagListItemHandle(guiRobot, primaryStage, tagItemNode.get()); + } else { + return null; + } + } +} +``` +###### /java/seedu/todo/guitests/guihandles/TagListItemHandle.java +``` java + */ +public class TagListItemHandle extends GuiHandle { + + private static final String TAGLISTITEM_LABEL = "#labelText"; + private Node node; + + public TagListItemHandle(GuiRobot guiRobot, Stage primaryStage, Node node){ + super(guiRobot, primaryStage, null); + this.node = node; + } + + public String getName() { + return getStringFromText(TAGLISTITEM_LABEL, node); + } + +} +``` +###### /java/seedu/todo/guitests/GuiTest.java +``` java + * Utility method for testing if tag has been successfully added to the GUI side panel. + * This runs a command and checks if TagList contains tag that matches + * the tag that was just added. + * + * Assumption : No tags can have the same name + * + */ + protected void assertTaskTagVisibleAfterCmd(String command, Task taskToAdd) { + // Run the command in the console. + console.runCommand(command); + int tag_index = 0; + + // Get the Tag List + ArrayList taskTagList = taskToAdd.getTagList(); + + // Assumption each task only got 1 tag + String tagName = taskTagList.get(tag_index); + + // Check if tag exist in the side panel tag list + TagListItemHandle tagItem = sidebar.getTagListItem(tagName); + assertNotNull(tagItem); + + // Check if the tag found is equal to the tag name of the task + String tagItemName = tagItem.getName(); + assertEquals(tagItemName, tagName); + } + + /** +``` +###### /java/seedu/todo/guitests/GuiTest.java +``` java + * Utility method for testing if tag has been successfully removed from the GUI side panel. + * This runs a command and checks if TagList contains tag that matches + * the tag that was just removed. + * + * Assumption : No tags can have the same name + * + */ + protected void assertTaskTagNotVisibleAfterCmd(String command, Task taskToAdd) { + // Get the Tag List + ArrayList taskTagList = taskToAdd.getTagList(); + + // Get the tag name with assumption each task only got 1 tag + String tagName = getTagNameFromCommand(command); + + // Run the command in the console. + console.runCommand(command); + + // Check if tag exist in the side panel tag list + TagListItemHandle tagItem = sidebar.getTagListItem(tagName); + assertNull(tagItem); + + // Check if tag has been removed + int expected_tag_list_size = 0; + assertEquals(taskTagList.size(), expected_tag_list_size); + } + + /** +``` +###### /java/seedu/todo/guitests/GuiTest.java +``` java + * Utility method for testing if tag is not successfully added into the GUI side panel. + * This runs a command and checks if TagList contains tag that matches + * the tag that is attempt to be added. + * + * Assumption : No tags can have the same name + * + */ + protected void assertTaskTagListFull(String command, Task taskToAdd) { + // Get the Tag List + ArrayList taskTagList = taskToAdd.getTagList(); + + // Get the next tag name from command + String tagName = getTagNameFromCommand(command); + + // Run the command in the console. + console.runCommand(command); + int expected_tag_list_size = 20; + + // Check if tag exist in the side panel tag list + TagListItemHandle tagItem = sidebar.getTagListItem(tagName); + assertNull(tagItem); + + assertEquals(expected_tag_list_size, taskTagList.size()); + } + + /* +``` +###### /java/seedu/todo/guitests/GuiTest.java +``` java + * Extract out the tag name that is been parsed in the command + * + * Assumption only 1 tag name is provided and tag name wil be provided + * @return tagName + */ + private String getTagNameFromCommand(String command) { + int tagName_index = 2; + String tagName = StringUtil.splitStringBySpace(command)[tagName_index]; + assert tagName != null; + return tagName; + } + + /* +``` +###### /java/seedu/todo/guitests/GuiTest.java +``` java + * To format disambiguate message at console output text area + * + * @return formatted output + */ + protected String formatConsoleOutputTextArea(String expectedDisambiguateMessage) { + return String.format(Renderer.MESSAGE_DISAMBIGUATE + "\n\n%s", expectedDisambiguateMessage); + } +} +``` +###### /java/seedu/todo/guitests/ListCommandTest.java +``` java + */ +public class ListCommandTest extends GuiTest { +``` +###### /java/seedu/todo/guitests/ListCommandTest.java +``` java + @Test + public void list_all() { + String command = "list"; + // To check if all tasks and events are still in the view + assertTaskVisibleAfterCmd(command, task1); + assertTaskVisibleAfterCmd(command, task2); + assertEventVisibleAfterCmd(command, event3); + assertEventVisibleAfterCmd(command, event4); + + // For console text area to check output message + String expectedOutputMessage = ListController.MESSAGE_LIST_SUCCESS; + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + @Test + public void list_tasks() { + String command = "list tasks"; + // To check if all tasks are been filtered out as expected + assertTaskVisibleAfterCmd(command, task1); + assertTaskVisibleAfterCmd(command, task2); + assertEventNotVisibleAfterCmd(command, event3); + assertEventNotVisibleAfterCmd(command, event4); + + // For console text area to check output message + expectedNumOfTasks = 2; + expectedNumOfEvents = 0; + String expectedOutputMessage = String.format(ListController.MESSAGE_RESULT_FOUND_FORMAT, + StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(expectedNumOfTasks, expectedNumOfEvents)); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + @Test + public void list_completed_tasks() { + console.runCommand("complete 1"); + String command = "list complete"; + // To check if task1 is been filtered out as expected + assertTaskVisibleAfterCmd(command, task1); + assertTaskNotVisibleAfterCmd(command, task2); + assertEventNotVisibleAfterCmd(command, event3); + assertEventNotVisibleAfterCmd(command, event4); + + // For console text area to check output message + expectedNumOfTasks = 1; + expectedNumOfEvents = 0; + String expectedOutputMessage = String.format(ListController.MESSAGE_RESULT_FOUND_FORMAT, + StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(expectedNumOfTasks, expectedNumOfEvents)); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + @Test + public void list_incomplete_tasks() { + String command = "list incomplete"; + // To check if all tasks are been filtered out as expected + assertTaskVisibleAfterCmd(command, task1); + assertTaskVisibleAfterCmd(command, task2); + assertEventNotVisibleAfterCmd(command, event3); + assertEventNotVisibleAfterCmd(command, event4); + + // For console text area to check output message + expectedNumOfTasks = 2; + expectedNumOfEvents = 0; + String expectedOutputMessage = String.format(ListController.MESSAGE_RESULT_FOUND_FORMAT, + StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(expectedNumOfTasks, expectedNumOfEvents)); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + @Test + public void list_events() { + String command = "list events"; + // To check if all events are been filtered out as expected + assertTaskNotVisibleAfterCmd(command, task1); + assertTaskNotVisibleAfterCmd(command, task2); + assertEventVisibleAfterCmd(command, event3); + assertEventVisibleAfterCmd(command, event4); + + // For console text area to check output message + expectedNumOfTasks = 0; + expectedNumOfEvents = 2; + String expectedOutputMessage = String.format(ListController.MESSAGE_RESULT_FOUND_FORMAT, + StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(expectedNumOfTasks, expectedNumOfEvents)); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + + @Test + public void list_over_events() { + String command = "list over"; + // To check if all tasks events are still in the view + assertTaskVisibleAfterCmd(command, task1); + assertTaskVisibleAfterCmd(command, task2); + assertEventVisibleAfterCmd(command, event3); + assertEventVisibleAfterCmd(command, event4); + + // For console text area to check output message + String expectedOutputMessage = ListController.MESSAGE_NO_RESULT_FOUND; + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + @Test + public void list_current_events() { + String command = "list current"; + // To check if all events are been filtered out as expected + assertTaskNotVisibleAfterCmd(command, task1); + assertTaskNotVisibleAfterCmd(command, task2); + assertEventVisibleAfterCmd(command, event3); + assertEventVisibleAfterCmd(command, event4); + + // For console text area to check output message + expectedNumOfTasks = 0; + expectedNumOfEvents = 2; + String expectedOutputMessage = String.format(ListController.MESSAGE_RESULT_FOUND_FORMAT, + StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(expectedNumOfTasks, expectedNumOfEvents)); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + @Test + public void list_by_single_date() { + String command = "list today"; + // To check if task1 is been filtered out as expected + assertTaskVisibleAfterCmd(command, task1); + assertTaskNotVisibleAfterCmd(command, task2); + assertEventNotVisibleAfterCmd(command, event3); + assertEventNotVisibleAfterCmd(command, event4); + + // For console text area to check output message + expectedNumOfTasks = 1; + expectedNumOfEvents = 0; + String expectedOutputMessage = String.format(ListController.MESSAGE_RESULT_FOUND_FORMAT, + StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(expectedNumOfTasks, expectedNumOfEvents)); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + @Test + public void list_by_date_range() { + String command = "list from today"; + // To check if all tasks and events are been filtered out as expected + assertTaskVisibleAfterCmd(command, task1); + assertTaskVisibleAfterCmd(command, task2); + assertEventVisibleAfterCmd(command, event3); + assertEventVisibleAfterCmd(command, event4); + + // For console text area to check output message + expectedNumOfTasks = 2; + expectedNumOfEvents = 2; + String expectedOutputMessage = String.format(ListController.MESSAGE_RESULT_FOUND_FORMAT, + StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(expectedNumOfTasks, expectedNumOfEvents)); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + @Test + public void list_tasks_by_single_date() { + String command = "list tasks on today"; + // To check if task1 is been filtered out as expected + assertTaskVisibleAfterCmd(command, task1); + assertTaskNotVisibleAfterCmd(command, task2); + assertEventNotVisibleAfterCmd(command, event3); + assertEventNotVisibleAfterCmd(command, event4); + + // For console text area to check output message + expectedNumOfTasks = 1; + expectedNumOfEvents = 0; + String expectedOutputMessage = String.format(ListController.MESSAGE_RESULT_FOUND_FORMAT, + StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(expectedNumOfTasks, expectedNumOfEvents)); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + @Test + public void list_tasks_by_date_range_with_single_date() { + String command = "list tasks from today"; + // To check if all tasks are been filtered out as expected + assertTaskVisibleAfterCmd(command, task1); + assertTaskVisibleAfterCmd(command, task2); + assertEventNotVisibleAfterCmd(command, event3); + assertEventNotVisibleAfterCmd(command, event4); + + // For console text area to check output message + expectedNumOfTasks = 2; + expectedNumOfEvents = 0; + String expectedOutputMessage = String.format(ListController.MESSAGE_RESULT_FOUND_FORMAT, + StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(expectedNumOfTasks, expectedNumOfEvents)); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + @Test + public void list_tasks_by_date_range() { + String command = "list tasks from today to tmr"; + // To check if all tasks are been filtered out as expected + assertTaskVisibleAfterCmd(command, task1); + assertTaskVisibleAfterCmd(command, task2); + assertEventNotVisibleAfterCmd(command, event3); + assertEventNotVisibleAfterCmd(command, event4); + + // For console text area to check output message + expectedNumOfTasks = 2; + expectedNumOfEvents = 0; + String expectedOutputMessage = String.format(ListController.MESSAGE_RESULT_FOUND_FORMAT, + StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(expectedNumOfTasks, expectedNumOfEvents)); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + @Test + public void list_events_by_single_date() { + String command = "list events on tomorrow"; + // To check if event3 is been filtered as expected + assertTaskNotVisibleAfterCmd(command, task1); + assertTaskNotVisibleAfterCmd(command, task2); + assertEventVisibleAfterCmd(command, event3); + assertEventNotVisibleAfterCmd(command, event4); + + // For console text area to check output message + expectedNumOfTasks = 0; + expectedNumOfEvents = 1; + String expectedOutputMessage = String.format(ListController.MESSAGE_RESULT_FOUND_FORMAT, + StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(expectedNumOfTasks, expectedNumOfEvents)); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + @Test + public void list_events_by_date_range_with_single_date() { + String command = "list events from today"; + // To check if all events are been filtered out as expected + assertTaskNotVisibleAfterCmd(command, task1); + assertTaskNotVisibleAfterCmd(command, task2); + assertEventVisibleAfterCmd(command, event3); + assertEventVisibleAfterCmd(command, event4); + + // For console text area to check output message + expectedNumOfTasks = 0; + expectedNumOfEvents = 2; + String expectedOutputMessage = String.format(ListController.MESSAGE_RESULT_FOUND_FORMAT, + StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(expectedNumOfTasks, expectedNumOfEvents)); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + @Test + public void list_events_by_date_range() { + String command = "list events from today to " + THE_DAY_AFTER_TOMORROW_STRING; + // To check if all events are been filtered out as expected + assertTaskNotVisibleAfterCmd(command, task1); + assertTaskNotVisibleAfterCmd(command, task2); + assertEventVisibleAfterCmd(command, event3); + assertEventVisibleAfterCmd(command, event4); + + // For console text area to check output message + expectedNumOfTasks = 0; + expectedNumOfEvents = 2; + String expectedOutputMessage = String.format(ListController.MESSAGE_RESULT_FOUND_FORMAT, + StringUtil.displayNumberOfTaskAndEventFoundWithPuralizer(expectedNumOfTasks, expectedNumOfEvents)); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + @Test + public void list_invalidTaskSyntax_disambiguate() { + String command = "list task over"; + console.runCommand(command); + // For console input text to check controller corrected syntax + String expectedDisambiguation = ListController.LIST_TASK_SYNTAX; + assertEquals(console.getConsoleInputText(), expectedDisambiguation); + + // For console text area to check error message + String expectedOutputMessage = formatConsoleOutputTextArea(ListController.MESSAGE_INVALID_TASK_STATUS); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + @Test + public void list_invalidEventSyntax_disambiguate() { + String command = "list event complete"; + console.runCommand(command); + // For console input text to check controller corrected syntax + String expectedDisambiguation = ListController.LIST_EVENT_SYNTAX; + assertEquals(console.getConsoleInputText(), expectedDisambiguation); + + // For console text area to check error message + String expectedOutputMessage = formatConsoleOutputTextArea(ListController.MESSAGE_INVALID_EVENT_STATUS); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + @Test + public void list_invalidDateSyntax_disambiguate_with_date_range() { + String command = "list by today to tml"; + console.runCommand(command); + // For console input text to check controller corrected syntax + String expectedDisambiguation = ListController.LIST_DATE_SYNTAX; + assertEquals(console.getConsoleInputText(), expectedDisambiguation); + + // For console text area to check error message + String expectedOutputMessage = formatConsoleOutputTextArea(ListController.MESSAGE_DATE_CONFLICT); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + @Test + public void list_invalidDateSyntax_disambiguate_with_single_date_by_keyword() { + String command = "list by todar"; + console.runCommand(command); + // For console input text to check controller corrected syntax + String expectedDisambiguation = ListController.LIST_DATE_SYNTAX; + assertEquals(console.getConsoleInputText(), expectedDisambiguation); + + // For console text area to check error message + String expectedOutputMessage = formatConsoleOutputTextArea(ListController.MESSAGE_NO_DATE_DETECTED); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + @Test + public void list_invalidDateSyntax_disambiguate_with_single_date() { + String command = "list todar"; + console.runCommand(command); + // For console input text to check controller corrected syntax + String expectedDisambiguation = ListController.LIST_DATE_SYNTAX; + assertEquals(console.getConsoleInputText(), expectedDisambiguation); + + // For console text area to check error message + String expectedOutputMessage = formatConsoleOutputTextArea(ListController.MESSAGE_NO_DATE_DETECTED); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + @Test + public void list_invalidDateSyntax_disambiguate_with_date_conflict() { + String command = "list today by tmr"; + console.runCommand(command); + // For console input text to check controller corrected syntax + String expectedDisambiguation = ListController.LIST_DATE_SYNTAX; + assertEquals(console.getConsoleInputText(), expectedDisambiguation); + + // For console text area to check error message + String expectedOutputMessage = formatConsoleOutputTextArea(ListController.MESSAGE_DATE_CONFLICT); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } + + @Test + public void list_invalidDateSyntax_disambiguate_with_date_conflict_by_status() { + String command = "list today over"; + console.runCommand(command); + // For console input text to check controller corrected syntax + String expectedDisambiguation = ListController.LIST_DATE_SYNTAX; + assertEquals(console.getConsoleInputText(), expectedDisambiguation); + + // For console text area to check error message + String expectedOutputMessage = formatConsoleOutputTextArea(ListController.MESSAGE_DATE_CONFLICT); + assertEquals(console.getConsoleTextArea(), expectedOutputMessage); + } +} +``` +###### /java/seedu/todo/guitests/TagControllerTest.java +``` java + */ +public class TagControllerTest extends GuiTest { +``` +###### /java/seedu/todo/guitests/TagControllerTest.java +``` java + @Test + public void tag_succcessfully() { + String command = "tag 1 personal"; + assertTaskTagVisibleAfterCmd(command, task); + assertEquals(console.getConsoleTextArea(), TagController.MESSAGE_TAG_SUCCESS); + } + + @Test + public void tag_with_duplicated_names() { + // To run the command + String command = "tag 1 personal"; + + assertTaskTagVisibleAfterCmd(command, task); + console.runCommand(command); + + // For console input + int tag_index = 1; + String expectedDisambiguationForConsoleInput = String.format(TagController.TAG_FORMAT, tag_index); + assertEquals(console.getConsoleInputText(), expectedDisambiguationForConsoleInput); + + // For console text area to check error message + String expectedDisambiguationForConsoleTextArea = formatConsoleOutputTextArea(TagController.MESSAGE_TAG_NAME_EXIST); + assertEquals(console.getConsoleTextArea(), expectedDisambiguationForConsoleTextArea); + } + + @Test + public void tag_when_tag_list_is_full() { + taskWithoutTag = generateTags(taskWithoutTag); + // To run Command + String command = "tag 1 personal"; + + assertTaskTagListFull(command, taskWithoutTag); + + // For console input + String expectedDisambiguationForConsoleInput = TagController.COMMAND_SYNTAX; + assertEquals(console.getConsoleInputText(), expectedDisambiguationForConsoleInput); + + // For console text area to check error message + String expectedDisambiguationForConsoleTextArea = formatConsoleOutputTextArea(TagController.MESSAGE_EXCEED_TAG_SIZE); + assertEquals(console.getConsoleTextArea(), expectedDisambiguationForConsoleTextArea); + } + + @Test + public void tag_without_index() { + // To run command + String command = "tag"; + console.runCommand(command); + + // For console input + String expectedDisambiguationForConsoleInput = TagController.COMMAND_SYNTAX; + assertEquals(console.getConsoleInputText(), expectedDisambiguationForConsoleInput); + + // For console text area to check error message + String expectedDisambiguationForConsoleTextArea = formatConsoleOutputTextArea(TagController.MESSAGE_MISSING_INDEX_AND_TAG_NAME); + assertEquals(console.getConsoleTextArea(), expectedDisambiguationForConsoleTextArea); + } + + @Test + public void tag_with_invalid_index_out_of_range() { + // To run command + String command = "tag 2"; + console.runCommand(command); + + // For console input + int tag_index_out_of_range = 2; + String expectedDisambiguationForConsoleInput = String.format(TagController.TAG_FORMAT, tag_index_out_of_range); + assertEquals(console.getConsoleInputText(), expectedDisambiguationForConsoleInput); + + // For console text area to check error message + String expectedDisambiguationForConsoleTextArea = formatConsoleOutputTextArea(TagController.MESSAGE_INDEX_OUT_OF_RANGE); + assertEquals(console.getConsoleTextArea(), expectedDisambiguationForConsoleTextArea); + } + + @Test + public void tag_with_invalid_index_as_alphabets() { + // To run command + String command = "tag personal"; + console.runCommand(command); + + // For console input + String expectedDisambiguationForConsoleInput = TagController.COMMAND_SYNTAX; + assertEquals(console.getConsoleInputText(), expectedDisambiguationForConsoleInput); + + // For console text area to check error message + String expectedDisambiguationForConsoleTextArea = formatConsoleOutputTextArea(TagController.MESSAGE_INDEX_NOT_NUMBER); + assertEquals(console.getConsoleTextArea(), expectedDisambiguationForConsoleTextArea); + } + + @Test + public void tag_without_name() { + // To run command + String command = "tag 1"; + console.runCommand(command); + + // For console input + String expectedDisambiguationForConsoleInput = TagController.COMMAND_SYNTAX; + assertEquals(console.getConsoleInputText(), expectedDisambiguationForConsoleInput); + + // For console text area to check error message + String expectedDisambiguationForConsoleTextArea = formatConsoleOutputTextArea(TagController.MESSAGE_TAG_NAME_NOT_FOUND); + assertEquals(console.getConsoleTextArea(), expectedDisambiguationForConsoleTextArea); + } + + private Task generateTags(Task task) { + for (int i = 0; i < task.getTagListLimit(); i ++) { + console.runCommand("tag 1 " + Integer.toString(i)); + task.addTag(Integer.toString(i)); + } + return task; + } +} +``` +###### /java/seedu/todo/guitests/UntagControllerTest.java +``` java + */ +public class UntagControllerTest extends GuiTest { +``` +###### /java/seedu/todo/guitests/UntagControllerTest.java +``` java + @Test + public void untag_succesfully() { + console.runCommand("tag 1 personal"); + String command = "untag 1 personal"; + assertTaskTagNotVisibleAfterCmd(command, taskWithoutTag); + } + + @Test + public void untag_task_with_invalid_name() { + // To run command + console.runCommand("tag 1 test"); + String command = "untag 1 personal"; + console.runCommand(command); + + // For console input + int tag_index = 1; + String expectedDisambiguationForConsoleInput = String.format(UntagController.UNTAG_FORMAT, tag_index); + assertEquals(console.getConsoleInputText(), expectedDisambiguationForConsoleInput); + + // For console text area to check error message + String expectedDisambiguationForConsoleTextArea = formatConsoleOutputTextArea(UntagController.MESSAGE_TAG_NAME_EXIST); + assertEquals(console.getConsoleTextArea(), expectedDisambiguationForConsoleTextArea); + } + + @Test + public void untag_without_name() { + // To run command + String command = "untag 1"; + console.runCommand(command); + + // For console input + String expectedDisambiguationForConsoleInput = UntagController.COMMAND_SYNTAX; + assertEquals(console.getConsoleInputText(), expectedDisambiguationForConsoleInput); + + // For console text area to check error message + String expectedDisambiguationForConsoleTextArea = formatConsoleOutputTextArea(UntagController.MESSAGE_TAG_NAME_NOT_FOUND); + assertEquals(console.getConsoleTextArea(), expectedDisambiguationForConsoleTextArea); + } + + @Test + public void untag_without_index() { + // To run command + String command = "untag"; + console.runCommand(command); + + // For console input + String expectedDisambiguationForConsoleInput = UntagController.COMMAND_SYNTAX; + assertEquals(console.getConsoleInputText(), expectedDisambiguationForConsoleInput); + + // For console text area to check error message + String expectedDisambiguationForConsoleTextArea = formatConsoleOutputTextArea(UntagController.MESSAGE_MISSING_INDEX_AND_TAG_NAME); + assertEquals(console.getConsoleTextArea(), expectedDisambiguationForConsoleTextArea); + } + + @Test + public void untag_with_invalid_index() { + // To run command + String command = "untag 2"; + console.runCommand(command); + + // For console input + int index_out_of_range = 2; + String expectedDisambiguationForConsoleInput = String.format(UntagController.UNTAG_FORMAT, index_out_of_range); + assertEquals(console.getConsoleInputText(), expectedDisambiguationForConsoleInput); + + // For console text area to check error message + String expectedDisambiguationForConsoleTextArea = formatConsoleOutputTextArea(UntagController.MESSAGE_INDEX_OUT_OF_RANGE); + assertEquals(console.getConsoleTextArea(), expectedDisambiguationForConsoleTextArea); + } +} +```