diff --git a/collated/main/A0139915W.md b/collated/main/A0139915W.md new file mode 100644 index 000000000000..773f4c1a3a22 --- /dev/null +++ b/collated/main/A0139915W.md @@ -0,0 +1,1430 @@ +# A0139915W +###### \java\seedu\savvytasker\commons\events\ui\TaskPanelSelectionChangedEvent.java +``` java + +/** + * Represents a selection change in the Task List Panel + */ +public class TaskPanelSelectionChangedEvent extends BaseEvent { + + + private final ReadOnlyTask newSelection; + + public TaskPanelSelectionChangedEvent(ReadOnlyTask newSelection){ + this.newSelection = newSelection; + } + + @Override + public String toString() { + return this.getClass().getSimpleName(); + } + + public ReadOnlyTask getNewSelection() { + return newSelection; + } +} +``` +###### \java\seedu\savvytasker\commons\util\SmartDefaultDates.java +``` java +/** + * Helper functions for handling dates. + * @author A0139915W + */ + +public class SmartDefaultDates { + + private Date startDateTime; + private Date endDateTime; + private final Calendar calendar; + private final Calendar today; + + /** + * + * @param startDateTime Starting date time + * @param endDateTime Ending date time + * @throws InvalidDateException If endDateTime is earlier than startDateTime + */ + public SmartDefaultDates(InferredDate startDateTime, InferredDate endDateTime) { + calendar = Calendar.getInstance(); + today = Calendar.getInstance(); + today.setTime(new Date()); + if (startDateTime == null && endDateTime == null) { + // dates not being supplied, nothing to parse + } else if (startDateTime == null && endDateTime != null) { + // apply smart default for endDateTime only + parseEnd(endDateTime); + } else if (startDateTime != null && endDateTime == null) { + // apply smart default for startDateTime only + parseStart(startDateTime); + } else { + parseStartAndEnd(startDateTime, endDateTime); + } + } + + /** + * Gets the smart default for end date + * @param today the time now + * @param endDateTime the end time to parse + * @return + */ + public Date getEnd(InferredDate endDateTime) { + if (endDateTime == null) return null; + calendar.setTime(endDateTime.getInferredDateTime()); + if (endDateTime.isDateInferred()) { + // date not supplied + // defaults to today + calendar.set(Calendar.DATE, today.get(Calendar.DATE)); + calendar.set(Calendar.MONTH, today.get(Calendar.MONTH)); + calendar.set(Calendar.YEAR, today.get(Calendar.YEAR)); + } else if (endDateTime.isTimeInferred()) { + // time not supplied + // defaults to 2359 + calendar.set(Calendar.HOUR_OF_DAY, 23); + calendar.set(Calendar.MINUTE, 59); + calendar.set(Calendar.SECOND, 59); + } + return calendar.getTime(); + } + + /** + * Sets the starting and ending date/time based on defaults for providing only + * the end time + * @param endDateTime end time supplied + */ + private void parseEnd(InferredDate endDateTime) { + assert endDateTime.getInferredDateTime() != null; + Date start = new Date(); + this.endDateTime = getEnd(endDateTime); + + // Since only end date is supplied, the task is considered to start at 12am today + calendar.setTime(start); + calendar.set(Calendar.HOUR_OF_DAY, 0); + calendar.set(Calendar.MINUTE, 0); + calendar.set(Calendar.SECOND, 0); + this.startDateTime = calendar.getTime(); + } + + + /** + * Gets the smart default for start date + * @param today the time now + * @param startDateTime the start time to parse + * @return + */ + public Date getStart(InferredDate startDateTime) { + if (startDateTime == null) return null; + calendar.setTime(startDateTime.getInferredDateTime()); + if (startDateTime.isDateInferred()) { + // date not supplied + // defaults to today + calendar.set(Calendar.DATE, today.get(Calendar.DATE)); + calendar.set(Calendar.MONTH, today.get(Calendar.MONTH)); + calendar.set(Calendar.YEAR, today.get(Calendar.YEAR)); + } else if (startDateTime.isTimeInferred()) { + // time not supplied + // defaults to 0000 + calendar.set(Calendar.HOUR_OF_DAY, 0); + calendar.set(Calendar.MINUTE, 0); + calendar.set(Calendar.SECOND, 0); + } + return calendar.getTime(); + } + + + /** + * Sets the starting and ending date/time based on defaults for providing only + * the start time + * @param startDateTime start time supplied + */ + private void parseStart(InferredDate startDateTime) { + assert startDateTime.getInferredDateTime() != null; + Date end = (Date)startDateTime.getInferredDateTime().clone(); + this.startDateTime = getStart(startDateTime); + + // Since only the start time is supplied, the task is considered to end today 2359 on the same day as start. + calendar.setTime(end); + calendar.set(Calendar.HOUR_OF_DAY, 23); + calendar.set(Calendar.MINUTE, 59); + calendar.set(Calendar.SECOND, 59); + this.endDateTime = calendar.getTime(); + } + + /** + * Sets the starting and ending date/time based on defaults for providing both + * start and end times + * @param startDateTime start time supplied + */ + private void parseStartAndEnd(InferredDate startDateTime, InferredDate endDateTime) { + assert endDateTime.getInferredDateTime() != null; + assert startDateTime.getInferredDateTime() != null; + Date start = getStart(startDateTime); + Date end = getEnd(endDateTime); + this.startDateTime = start; + this.endDateTime = end; + if (this.startDateTime.compareTo(this.endDateTime) > 0) { + calendar.setTime(this.endDateTime); + calendar.add(Calendar.DATE, 7); + this.endDateTime = calendar.getTime(); + } + } + + public Date getStartDate() { + return startDateTime; + } + + public Date getEndDate() { + return endDateTime; + } +} +``` +###### \java\seedu\savvytasker\commons\util\SmartDefaultDates.java +``` java + +``` +###### \java\seedu\savvytasker\commons\util\StringUtil.java +``` java + // reused original implementation of 'containsIgnoreCase' to find exact matches + public static boolean containsExactIgnoreCase(String source, String query) { + List strings = Arrays.asList(source); + return strings.stream().filter(s -> s.equalsIgnoreCase(query)).count() > 0; + } + + // reused original implementation of 'containsIgnoreCase' to find partial matches + public static boolean containsPartialIgnoreCase(String source, String query) { + if (source == null) return false; + String[] split = source.toLowerCase().split("\\s+"); + List strings = Arrays.asList(split); + return strings.stream().filter(s -> s.contains(query.toLowerCase())).count() > 0; + } +``` +###### \java\seedu\savvytasker\commons\util\StringUtil.java +``` java + + public static boolean containsIgnoreCase(String source, String query) { + String[] split = source.toLowerCase().split("\\s+"); + List strings = Arrays.asList(split); + return strings.stream().filter(s -> s.equals(query.toLowerCase())).count() > 0; + } + + /** + * Returns a detailed message of the t, including the stack trace. + */ + public static String getDetails(Throwable t){ + assert t != null; + StringWriter sw = new StringWriter(); + t.printStackTrace(new PrintWriter(sw)); + return t.getMessage() + "\n" + sw.toString(); + } + + /** + * Returns true if s represents an unsigned integer e.g. 1, 2, 3, ...
+ * Will return false for null, empty string, "-1", "0", "+1", and " 2 " (untrimmed) "3 0" (contains whitespace). + * @param s Should be trimmed. + */ + public static boolean isUnsignedInteger(String s){ + return s != null && s.matches("^0*[1-9]\\d*$"); + } +} +``` +###### \java\seedu\savvytasker\logic\commands\AddCommand.java +``` java + /** + * Creates an add command. + */ + public AddCommand(String taskName, InferredDate startDateTime, InferredDate endDateTime, + String location, PriorityLevel priority, RecurrenceType recurringType, + Integer numberOfRecurrence, String category, String description) { + this.taskName = taskName; + this.startDateTime = startDateTime; + this.endDateTime = endDateTime; + this.location = location; + this.priority = priority; + this.recurringType = recurringType; + this.numberOfRecurrence = numberOfRecurrence; + this.category = category; + this.description = description; + } + + private void createTask() { + final boolean isArchived = false; // all tasks are first added as active tasks + final int taskId = 0; // taskId to be assigned by ModelManager, leave as 0 + + SmartDefaultDates sdd = new SmartDefaultDates(startDateTime, endDateTime); + this.toAdd = new Task(taskId, taskName, sdd.getStartDate(), sdd.getEndDate(), + location, priority, recurringType, numberOfRecurrence, + category, description, isArchived); + } + + @Override + public CommandResult execute() { + assert model != null; + createTask(); + + try { + model.addTask(toAdd); + return new CommandResult(String.format(MESSAGE_SUCCESS, toAdd)); + } catch (DuplicateTaskException e) { + return new CommandResult(MESSAGE_DUPLICATE_TASK); + } catch (InvalidDateException ex) { + return new CommandResult(MESSAGE_INVALID_START_END); + } + + } +``` +###### \java\seedu\savvytasker\logic\commands\AddCommand.java +``` java + + /** + * Checks if a command can perform undo operations + * @return true if the command supports undo, false otherwise + */ + @Override + public boolean canUndo() { + return true; + } + + /** + * Redo the add command + * @return true if the operation completed successfully, false otherwise + */ + @Override + public boolean redo() { + execute(); + return false; + } + + /** + * Undo the add command + * @return true if the operation completed successfully, false otherwise + */ + @Override + public boolean undo() { + + UnmodifiableObservableList lastShownList = model.getFilteredTaskListTask(); + + for (int i = 0; i < lastShownList.size(); i++) { + if (lastShownList.get(i) == toAdd){ + ReadOnlyTask taskToDelete = lastShownList.get(i); + try { + model.deleteTask(taskToDelete); + } catch (TaskNotFoundException e) { + e.printStackTrace(); + } + } + } + return false; + } + + /** + * Check if command is an undo command + * @return true if the command is an undo operation, false otherwise + */ + @Override + public boolean isUndo() { + return false; + } + + /** + * Check if command is a redo command + * @return true if the command is a redo operation, false otherwise + */ + @Override + public boolean isRedo(){ + return false; + } +} +``` +###### \java\seedu\savvytasker\logic\commands\DeleteCommand.java +``` java + public DeleteCommand(int[] targetIndices) { + this.targetIndices = targetIndices; + } + + @Override + public CommandResult execute() { + + UnmodifiableObservableList lastShownList = model.getFilteredTaskList(); + + LinkedList tasksToDelete = new LinkedList(); + for(int targetIndex : this.targetIndices) { + if (lastShownList.size() < targetIndex || targetIndex <= 0) { + indicateAttemptToExecuteIncorrectCommand(); + return new CommandResult(Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX); + } + tasksToDelete.add(lastShownList.get(targetIndex - 1)); + } + + original = new SavvyTasker(model.getSavvyTasker()); + + StringBuilder resultSb = new StringBuilder(); + try { + for(ReadOnlyTask taskToDelete : tasksToDelete) { + model.deleteTask(taskToDelete); + //tasksToUndo.add((Task)taskToDelete); + resultSb.append(String.format(MESSAGE_DELETE_TASK_SUCCESS, taskToDelete)); + } + } catch (TaskNotFoundException pnfe) { + assert false : "The target task cannot be missing"; + } + + return new CommandResult(resultSb.toString()); + } +``` +###### \java\seedu\savvytasker\logic\commands\DeleteCommand.java +``` java + + /** + * Checks if a command can perform undo operations + * @return true if the command supports undo, false otherwise + */ + @Override + public boolean canUndo() { + return true; + } + + /** + * Redo the delete command + * @return true if the operation completed successfully, false otherwise + */ + @Override + public boolean redo() { + execute(); + + /* + * METHOD 2 + UnmodifiableObservableList lastShownList = model.getFilteredTaskListTask(); + + for(Task toUndo : tasksToUndo){ + for (int i = 0; i < lastShownList.size(); i++) { + if (lastShownList.get(i) == toUndo){ + ReadOnlyTask taskToDelete = lastShownList.get(i); + try { + model.deleteTask(taskToDelete); + } catch (TaskNotFoundException e) { + e.printStackTrace(); + } + } + } + } + */ + return true; + } + + /** + * Undo the delete command + * @return true if the operation completed successfully, false otherwise + */ + @Override + public boolean undo() { + + assert model != null; + model.resetData(original); + + /* + * METHOD 2 + assert model != null; + + for(Task deleted : tasksToUndo) + try { + model.addTask(deleted); + } catch (DuplicateTaskException e) { + e.printStackTrace(); + } + */ + return true; + } + + /** + * Check if command is an undo command + * @return true if the command is an undo operation, false otherwise + */ + @Override + public boolean isUndo() { + return false; + } + + /** + * Check if command is a redo command + * @return true if the command is a redo operation, false otherwise + */ + @Override + public boolean isRedo(){ + return false; + } +} +``` +###### \java\seedu\savvytasker\logic\commands\ListCommand.java +``` java + /** + * Creates the List command to list the specified tasks + * @author A0139915W + * @param commandModel Arguments for the List command, must not be null + */ + public ListCommand(ListType listType) { + this.listType = listType; + } + + @Override + public CommandResult execute() { + ListType _listType = listType; + if (listType == null) { + // use default, sort by due date + _listType = ListType.DueDate; + } + switch (_listType) + { + case DueDate: + model.updateFilteredListToShowActiveSortedByDueDate(); + break; + case PriorityLevel: + model.updateFilteredListToShowActiveSortedByPriorityLevel(); + break; + case Archived: + model.updateFilteredListToShowArchived(); + break; + default: + assert false; // should not reach here + } + return new CommandResult(getMessageForTaskListShownSummary(model.getFilteredTaskList().size())); + } +``` +###### \java\seedu\savvytasker\logic\commands\ListCommand.java +``` java + + /** + * Checks if a command can perform undo operations + * @return true if the command supports undo, false otherwise + */ + @Override + public boolean canUndo() { + return false; + } + + /** + * Redo the list command + * @return true if the operation completed successfully, false otherwise + */ + @Override + public boolean redo() { + // nothing required to be done + return false; + } + + + /** + * Undo the list command + * @return true if the operation completed successfully, false otherwise + */ + @Override + public boolean undo() { + // nothing required to be done + return false; + } + + /** + * Check if command is an undo command + * @return true if the command is an undo operation, false otherwise + */ + @Override + public boolean isUndo() { + return false; + } + + /** + * Check if command is a redo command + * @return true if the command is a redo operation, false otherwise + */ + @Override + public boolean isRedo(){ + return false; + } +} + +``` +###### \java\seedu\savvytasker\model\Model.java +``` java + /** Deletes the given Task. */ + void deleteTask(ReadOnlyTask target) throws TaskNotFoundException; + + /** Modifies the given Task. */ + void modifyTask(ReadOnlyTask target, Task replacement) throws TaskNotFoundException, InvalidDateException; + + /** Adds the given Task. + * @throws {@link DuplicateTaskException} if a duplicate is found + * */ + void addTask(Task task) throws DuplicateTaskException, InvalidDateException; + + /** Returns the filtered task list as an {@code UnmodifiableObservableList} */ + UnmodifiableObservableList getFilteredTaskList(); + + /** Returns the filtered task list as an {@code UnmodifiableObservableList} */ + UnmodifiableObservableList getFilteredTaskListTask(); + + /** Updates the filter of the filtered task list to show all active tasks sorted by due date */ + void updateFilteredListToShowActiveSortedByDueDate(); + + /** Updates the filter of the filtered task list to show all active tasks sorted by priority level */ + void updateFilteredListToShowActiveSortedByPriorityLevel(); + + /** Updates the filter of the filtered task list to show all active tasks */ + void updateFilteredListToShowActive(); + + /** Updates the filter of the filtered task list to show all archived tasks */ + void updateFilteredListToShowArchived(); + + /** Updates the filter of the filtered task list to filter by the given keywords*/ + void updateFilteredTaskList(FindType findType, String[] keywords); +``` +###### \java\seedu\savvytasker\model\Model.java +``` java + + /** Adds the given AliasSymbol */ + void addAliasSymbol(AliasSymbol symbol) throws DuplicateSymbolKeywordException; + + /** Removes an the given AliasSymbol. */ + void removeAliasSymbol(AliasSymbol symbol) throws SymbolKeywordNotFoundException; +} +``` +###### \java\seedu\savvytasker\model\ModelManager.java +``` java + private final SavvyTasker savvyTasker; + private final FilteredList filteredTasks; + private final SortedList sortedAndFilteredTasks; +``` +###### \java\seedu\savvytasker\model\ModelManager.java +``` java + +``` +###### \java\seedu\savvytasker\model\ModelManager.java +``` java + /** + * Initializes a ModelManager with the given SavvyTasker + * and its variables should not be null + */ + public ModelManager(SavvyTasker src) { + super(); + assert src != null; + + logger.fine("Initializing with savvy tasker: " + src); + + savvyTasker = new SavvyTasker(src); + filteredTasks = new FilteredList<>(savvyTasker.getTasks()); + sortedAndFilteredTasks = new SortedList<>(filteredTasks, new TaskSortedByDefault()); + updateFilteredListToShowActive(); // shows only active tasks on start + } + + public ModelManager() { + this(new SavvyTasker()); + } + + public ModelManager(ReadOnlySavvyTasker initialData) { + savvyTasker = new SavvyTasker(initialData); + filteredTasks = new FilteredList<>(savvyTasker.getTasks()); + sortedAndFilteredTasks = new SortedList<>(filteredTasks, new TaskSortedByDefault()); + updateFilteredListToShowActive(); // shows only active tasks on start + } + + @Override + public void resetData(ReadOnlySavvyTasker newData) { + savvyTasker.resetData(newData); + indicateSavvyTaskerChanged(); + } + + @Override + public ReadOnlySavvyTasker getSavvyTasker() { + return savvyTasker; + } + + /** Raises an event to indicate the model has changed */ + private void indicateSavvyTaskerChanged() { + raise(new SavvyTaskerChangedEvent(savvyTasker)); + } +``` +###### \java\seedu\savvytasker\model\ModelManager.java +``` java + + private void indicateAliasSymbolAdded(AliasSymbol symbol) { + raise(new AliasSymbolChangedEvent(symbol, AliasSymbolChangedEvent.Action.Added)); + } + + private void indicateAliasSymbolRemoved(AliasSymbol symbol) { + raise(new AliasSymbolChangedEvent(symbol, AliasSymbolChangedEvent.Action.Removed)); + } + + +``` +###### \java\seedu\savvytasker\model\ModelManager.java +``` java + @Override + public synchronized void deleteTask(ReadOnlyTask target) throws TaskNotFoundException { + savvyTasker.removeTask(target); + indicateSavvyTaskerChanged(); + } + + @Override + public void modifyTask(ReadOnlyTask target, Task replacement) throws TaskNotFoundException, InvalidDateException { + savvyTasker.replaceTask(target, replacement); + indicateSavvyTaskerChanged(); + } + + @Override + public synchronized void addTask(Task t) throws DuplicateTaskException, InvalidDateException { + t.setId(savvyTasker.getNextTaskId()); + savvyTasker.addTask(t); + updateFilteredListToShowActive(); + indicateSavvyTaskerChanged(); + } +``` +###### \java\seedu\savvytasker\model\ModelManager.java +``` java + + @Override + public synchronized void addAliasSymbol(AliasSymbol symbol) throws DuplicateSymbolKeywordException { + savvyTasker.addAliasSymbol(symbol); + indicateSavvyTaskerChanged(); + indicateAliasSymbolAdded(symbol); + } + + @Override + public synchronized void removeAliasSymbol(AliasSymbol symbol) throws SymbolKeywordNotFoundException { + savvyTasker.removeAliasSymbol(symbol); + indicateSavvyTaskerChanged(); + indicateAliasSymbolRemoved(symbol); + } + + //=========== Filtered/Sorted Task List Accessors =============================================================== + +``` +###### \java\seedu\savvytasker\model\ModelManager.java +``` java + @Override + public UnmodifiableObservableList getFilteredTaskList() { + return new UnmodifiableObservableList(sortedAndFilteredTasks); + } + + @Override + public UnmodifiableObservableList getFilteredTaskListTask() { + return new UnmodifiableObservableList(sortedAndFilteredTasks); + } + + @Override + public void updateFilteredListToShowActiveSortedByDueDate() { + updateFilteredListToShowActive(new TaskSortedByDueDate()); + } + + @Override + public void updateFilteredListToShowActiveSortedByPriorityLevel() { + updateFilteredListToShowActive(new TaskSortedByPriorityLevel()); + } + + @Override + public void updateFilteredListToShowActive() { + updateFilteredTaskList(new PredicateExpression(new TaskIsActiveQualifier())); + } + private void updateFilteredListToShowActive(Comparator comparator) { + updateFilteredTaskList( + new PredicateExpression(new TaskIsActiveQualifier()), + comparator); + } + + @Override + public void updateFilteredListToShowArchived() { + updateFilteredTaskList(new PredicateExpression(new TaskIsArchivedQualifier())); + } + + @Override + public void updateFilteredTaskList(FindType findType, String[] keywords) { + assert findType != null; + Qualifier qualifier = null; + switch (findType) + { + case Partial: + qualifier = new TaskNamePartialMatchQualifier(keywords); + break; + case Full: + qualifier = new TaskNameFullMatchQualifier(keywords); + break; + case Exact: + qualifier = new TaskNameExactMatchQualifier(keywords); + break; + case Category: + qualifier = new CategoryPartialMatchQualifier(keywords); + break; + default: + assert false; // should never get here. + } + updateFilteredTaskList(new PredicateExpression(qualifier)); + } + + private void updateFilteredTaskList(Expression expression) { + updateFilteredTaskList(expression, new TaskSortedByDefault()); + } + + private void updateFilteredTaskList(Expression expression, Comparator comparator) { + filteredTasks.setPredicate(expression::satisfies); + sortedAndFilteredTasks.setComparator(comparator); + } +``` +###### \java\seedu\savvytasker\model\ModelManager.java +``` java + + //========== Inner classes/interfaces used for filtering ================================================== + + interface Expression { + boolean satisfies(ReadOnlyTask task); + String toString(); + } + + private class PredicateExpression implements Expression { + + private final Qualifier qualifier; + + PredicateExpression(Qualifier qualifier) { + this.qualifier = qualifier; + } + + @Override + public boolean satisfies(ReadOnlyTask task) { + return qualifier.run(task); + } + + @Override + public String toString() { + return qualifier.toString(); + } + } + + interface Qualifier { + boolean run(ReadOnlyTask task); + String toString(); + + /** + * Helper method to build Set from String[] + * @param keywords list of keywords + */ + default Set createSet(String[] keywords) { + HashSet _keywords = new HashSet(); + for (String keyword : keywords) { + _keywords.add(keyword); + } + return _keywords; + } + } + +``` +###### \java\seedu\savvytasker\model\ModelManager.java +``` java + /** + * Qualifier matching a partial word from the set of keywords + * @author A0139915W + */ + private class CategoryPartialMatchQualifier implements Qualifier { + private Set keyWordsToMatch; + + CategoryPartialMatchQualifier(String[] keyWordsToMatch) { + this.keyWordsToMatch = createSet(keyWordsToMatch); + } + + @Override + public boolean run(ReadOnlyTask task) { + return keyWordsToMatch.stream() + .filter(keyword -> StringUtil.containsPartialIgnoreCase(task.getCategory(), keyword)) + .findAny() + .isPresent(); + } + + @Override + public String toString() { + return "category(PartialMatch)=" + String.join(", ", keyWordsToMatch); + } + } + + /** + * Qualifier matching a partial word from the set of keywords + * @author A0139915W + */ + private class TaskNamePartialMatchQualifier implements Qualifier { + private Set keyWordsToMatch; + + TaskNamePartialMatchQualifier(String[] keyWordsToMatch) { + this.keyWordsToMatch = createSet(keyWordsToMatch); + } + + @Override + public boolean run(ReadOnlyTask task) { + return keyWordsToMatch.stream() + .filter(keyword -> StringUtil.containsPartialIgnoreCase(task.getTaskName(), keyword)) + .findAny() + .isPresent(); + } + + @Override + public String toString() { + return "taskName(PartialMatch)=" + String.join(", ", keyWordsToMatch); + } + } + + /** + * Qualifier matching a full word from the set of keywords + * @author A0139915W + */ + private class TaskNameFullMatchQualifier implements Qualifier { + private Set keyWordsToMatch; + + TaskNameFullMatchQualifier(String[] keyWordsToMatch) { + this.keyWordsToMatch = createSet(keyWordsToMatch); + } + + @Override + public boolean run(ReadOnlyTask task) { + return keyWordsToMatch.stream() + .filter(keyword -> StringUtil.containsIgnoreCase(task.getTaskName(), keyword)) + .findAny() + .isPresent(); + } + + @Override + public String toString() { + return "taskName(FullMatch)=" + String.join(", ", keyWordsToMatch); + } + } + + /** + * Qualifier matching a exactly from the set of keywords + * @author A0139915W + */ + private class TaskNameExactMatchQualifier implements Qualifier { + private Set keyWordsToMatch; + + TaskNameExactMatchQualifier(String[] keyWordsToMatch) { + this.keyWordsToMatch = new HashSet(); + this.keyWordsToMatch.add(buildSingleString(keyWordsToMatch)); + } + + /** + * Builds a single string to be matched exactly against the task name. + * @param keyWordsToMatch list of keywords to match. + * @return A single string built from the list of keywords. + */ + private String buildSingleString(String[] keyWordsToMatch) { + StringBuilder sb = new StringBuilder(); + List keywords = Arrays.asList(keyWordsToMatch); + Iterator itr = keywords.iterator(); + while (itr.hasNext()) { + sb.append(itr.next()); + if (itr.hasNext()) { + sb.append(" "); + } + } + return sb.toString(); + } + + @Override + public boolean run(ReadOnlyTask task) { + return keyWordsToMatch.stream() + .filter(keyword -> StringUtil.containsExactIgnoreCase(task.getTaskName(), keyword)) + .findAny() + .isPresent(); + } + + @Override + public String toString() { + return "taskName(ExactMatch)=" + String.join(", ", keyWordsToMatch); + } + } + + /** + * Qualifier for checking if {@link Task} is active. Tasks that are not archived are active. + * @author A0139915W + * + */ + private class TaskIsActiveQualifier implements Qualifier { + + @Override + public boolean run(ReadOnlyTask task) { + return task.isArchived() == false; + } + + @Override + public String toString() { + return "isArchived=false"; + } + } + + /** + * Qualifier for checking if {@link Task} is archived + * @author A0139915W + * + */ + private class TaskIsArchivedQualifier implements Qualifier { + + @Override + public boolean run(ReadOnlyTask task) { + return task.isArchived() == true; + } + + @Override + public String toString() { + return "isArchived=true"; + } + } + + //========== Inner classes/interfaces used for sorting ================================================== + + /** + * Compares {@link Task} by their default field, id + * @author A0139915W + * + */ + private class TaskSortedByDefault implements Comparator { + + @Override + public int compare(Task task1, Task task2) { + if (task1 == null && task2 == null) return 0; + else if (task1 == null) return 1; + else if (task2 == null) return -1; + else return task1.getId() - task2.getId(); + } + + } + + /** + * Compares {@link Task} by their DueDate + * @author A0139915W + * + */ + private class TaskSortedByDueDate implements Comparator { + + @Override + public int compare(Task task1, Task task2) { + if (task1 == null && task2 == null) return 0; + else if (task1 == null) return 1; + else if (task2 == null) return -1; + else { + // End dates can be nulls (floating tasks) + // Check for existence of endDateTime before comparing + if (task1.getEndDateTime() == null && + task2.getEndDateTime() == null) { + return 0; + } else if (task1.getEndDateTime() == null) { + return 1; + } else if (task2.getEndDateTime() == null) { + return -1; + } else { + return task1.getEndDateTime().compareTo(task2.getEndDateTime()); + } + } + } + + } + + /** + * Compares {@link Task} by their PriorityLevel + * @author A0139915W + * + */ + private class TaskSortedByPriorityLevel implements Comparator { + + @Override + public int compare(Task task1, Task task2) { + if (task1 == null && task2 == null) return 0; + else if (task1 == null) return 1; + else if (task2 == null) return -1; + else { + // Priority Level can be nulls + // Check for existence of priorityLevel before comparing + if (task1.getPriority() == null && + task2.getPriority() == null) { + return 0; + } else if (task1.getPriority() == null) { + return 1; + } else if (task2.getPriority() == null) { + return -1; + } else { + return task2.getPriority().compareTo(task1.getPriority()); + } + } + } + + } +``` +###### \java\seedu\savvytasker\model\ModelManager.java +``` java + +} +``` +###### \java\seedu\savvytasker\model\ReadOnlySavvyTasker.java +``` java + /** + * Returns a defensively copied task list. + */ + TaskList getTaskList(); +``` +###### \java\seedu\savvytasker\model\ReadOnlySavvyTasker.java +``` java + + /** + * Returns a defensively copied alias symbol list. + */ + + AliasSymbolList getAliasSymbolList(); +``` +###### \java\seedu\savvytasker\model\ReadOnlySavvyTasker.java +``` java + /** + * Returns an unmodifiable view of task list + */ + List getReadOnlyListOfTasks(); +``` +###### \java\seedu\savvytasker\model\ReadOnlySavvyTasker.java +``` java + + /** + * Returns unmodifiable view of symbols list + */ + List getReadOnlyListOfAliasSymbols(); +} +``` +###### \java\seedu\savvytasker\model\SavvyTasker.java +``` java + private final TaskList tasks; +``` +###### \java\seedu\savvytasker\model\SavvyTasker.java +``` java + private final AliasSymbolList symbols; + +``` +###### \java\seedu\savvytasker\model\SavvyTasker.java +``` java + public SavvyTasker() { + this.tasks = new TaskList(); + this.symbols = new AliasSymbolList(); + } + + public SavvyTasker(ReadOnlySavvyTasker toBeCopied) { + this(toBeCopied.getTaskList(), toBeCopied.getAliasSymbolList()); + } + + public SavvyTasker(TaskList tasks, AliasSymbolList symbols) { + this(); + resetData(tasks.getInternalList()); + this.symbols.reset(symbols); + } + + public static ReadOnlySavvyTasker getEmptySavvyTasker() { + return new SavvyTasker(); + } + +//// task list overwrite operations + + public ObservableList getTasks() { + return tasks.getInternalList(); + } + + public void setTasks(List tasks) { + this.tasks.getInternalList().setAll(tasks); + } + + public void resetData(Collection newTasks) { + setTasks(newTasks.stream().map(Task::new).collect(Collectors.toList())); + } + + public void resetData(ReadOnlySavvyTasker newData) { + resetData(newData.getReadOnlyListOfTasks()); + } +``` +###### \java\seedu\savvytasker\model\SavvyTasker.java +``` java + +//// symbol/task-level operations + +``` +###### \java\seedu\savvytasker\model\SavvyTasker.java +``` java + /** + * Returns the next available id for use to uniquely identify a task. + * @author A0139915W + * @return The next available id. + */ + public int getNextTaskId() { + return tasks.getNextId(); + } + + /** + * Adds a task to savvy tasker. + * @throws TaskList.DuplicateTaskException if an equivalent task already exists. + */ + public void addTask(Task t) throws DuplicateTaskException, InvalidDateException { + tasks.add(t); + } + + /** + * Removes a task from savvy tasker. + * @param key the task to be removed + * @return true if the task is removed successfully + * @throws TaskNotFoundException if the task to be removed does not exist + */ + public boolean removeTask(ReadOnlyTask key) throws TaskNotFoundException { + return tasks.remove(key); + } + + /** + * Replaces a task from savvy tasker. + * @param key the task to be replaced + * @return true if the task is removed successfully + * @throws TaskNotFoundException if the task to be removed does not exist + */ + public boolean replaceTask(ReadOnlyTask key, Task replacement) throws TaskNotFoundException, InvalidDateException { + return tasks.replace(key, replacement); + } +``` +###### \java\seedu\savvytasker\model\SavvyTasker.java +``` java + + /** + * Adds an alias symbol to savvy tasker. + * @param symbol the symbol to add + * @throws DuplicateSymbolKeywordException if another symbol with the same keyword already exists + */ + public void addAliasSymbol(AliasSymbol symbol) throws DuplicateSymbolKeywordException { + symbols.addAliasSymbol(symbol); + } + + /** + * Removes an alias symbol from savvy tasker. + * @param symbol the symbol to remove + * @throws SymbolKeywordNotFoundException if there is no such symbol + */ + public void removeAliasSymbol(AliasSymbol symbol) throws SymbolKeywordNotFoundException { + symbols.removeAliasSymbol(symbol); + } + + +//// util methods + + @Override + public String toString() { + return tasks.getInternalList().size() + " tasks, " + symbols.size() + " symbols"; + // TODO: refine later + } + + @Override + public List getReadOnlyListOfTasks() { + return Collections.unmodifiableList(tasks.getInternalList()); + } + + @Override + public TaskList getTaskList() { + TaskList defensiveCopy = new TaskList(); + defensiveCopy.getInternalList().addAll(tasks.getInternalList()); + return defensiveCopy; + } + + @Override + public List getReadOnlyListOfAliasSymbols() { + return symbols.asReadonly(); + } + + @Override + public AliasSymbolList getAliasSymbolList() { + return new AliasSymbolList(symbols); + } + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof SavvyTasker // instanceof handles nulls + && this.tasks.equals(((SavvyTasker) other).tasks) + && this.symbols.equals(((SavvyTasker) other).symbols)); + } + + @Override + public int hashCode() { + // use this method for custom fields hashing instead of implementing your own + return Objects.hash(tasks, symbols); + } +} +``` +###### \java\seedu\savvytasker\model\task\TaskList.java +``` java +/** + * A list of tasks that enforces uniqueness between its elements and does not allow nulls. + * + * Supports a minimal set of list operations. + * + * @see Task#equals(Object) + */ +public class TaskList implements Iterable { + + /** + * Signals that an operation would have violated the 'end time earlier than start time' property of the list. + */ + public static class InvalidDateException extends IllegalValueException { + + /** + * Generated serial ID + */ + private static final long serialVersionUID = 8933810750762846403L; + + protected InvalidDateException() { + super("Operation would result in invalid start/end dates"); + } + } + + /** + * Signals that an operation would have violated the 'no duplicates' property of the list. + */ + public static class DuplicateTaskException extends DuplicateDataException { + + /** + * Generated serial ID + */ + private static final long serialVersionUID = 8933810750762846403L; + + protected DuplicateTaskException() { + super("Operation would result in duplicate tasks"); + } + } + + /** + * Signals that an operation targeting a specified task in the list would fail because + * there is no such matching task in the list. + */ + public static class TaskNotFoundException extends Exception { + + /** + * Generated serial ID + */ + private static final long serialVersionUID = -7591982407764643511L; + } + + private final ObservableList internalList = FXCollections.observableArrayList(); + private int nextId = 0; + private boolean isNextIdInitialized = false; + + /** + * Constructs empty TaskList. + */ + public TaskList() {} + + /** + * Gets the next available id for uniquely identifying a task in + * Savvy Tasker. + * @return The next available id; + */ + public int getNextId() { + if (!isNextIdInitialized) { + int nextLowest = -1; // first id to be used is 0. Start finding with -1 + LinkedList usedIds = new LinkedList(); + for (Task t : internalList) { + usedIds.add(t.getId()); + if (t.getId() > nextLowest) { + nextLowest = t.getId(); + } + } + // assumption that the number of tasks < 2^31 + // implementation will be buggy if nextId exceeds 2^31 + nextId = nextLowest; + assert nextId < Integer.MAX_VALUE; + isNextIdInitialized = true; + } + nextId++; + return nextId; + } + + /** + * Returns true if the list contains an equivalent task as the given argument. + */ + public boolean contains(ReadOnlyTask toCheck) { + assert toCheck != null; + return internalList.contains(toCheck); + } + + /** + * Returns true if the end time is not earlier than the start time. + */ + public boolean isValidStartEnd(ReadOnlyTask toCheck) { + assert toCheck != null; + if (toCheck.getStartDateTime() != null && toCheck.getEndDateTime() != null && + toCheck.getStartDateTime().compareTo(toCheck.getEndDateTime()) >= 0) { + return false; + } + return true; + } + + /** + * Adds a task to the list. + * + * @throws DuplicateTaskException if the person to add is a duplicate of an existing task in the list. + */ + public void add(Task toAdd) throws DuplicateTaskException, InvalidDateException { + assert toAdd != null; + if (contains(toAdd)) { + throw new DuplicateTaskException(); + } + if (!isValidStartEnd(toAdd)) { + throw new InvalidDateException(); + } + internalList.add(toAdd); + } + + /** + * Removes the equivalent task from the list. + * + * @throws TaskNotFoundException if no such task could be found in the list. + */ + public boolean remove(ReadOnlyTask toRemove) throws TaskNotFoundException { + assert toRemove != null; + final boolean taskFoundAndDeleted = internalList.remove(toRemove); + if (!taskFoundAndDeleted) { + throw new TaskNotFoundException(); + } + return taskFoundAndDeleted; + } + + /** + * Replaces the equivalent task from the list. + * + * @throws TaskNotFoundException if no such task could be found in the list. + */ + public boolean replace(ReadOnlyTask toReplace, Task replacement) throws TaskNotFoundException, InvalidDateException { + assert toReplace != null; + assert replacement != null; + if (internalList.contains(toReplace)) { + if (!isValidStartEnd(replacement)) { + throw new InvalidDateException(); + } + internalList.set(internalList.indexOf(toReplace), replacement); + return true; + } + else { + throw new TaskNotFoundException(); + } + } + + public ObservableList getInternalList() { + return internalList; + } + + @Override + public Iterator iterator() { + return internalList.iterator(); + } + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof TaskList // instanceof handles nulls + && this.internalList.equals( ((TaskList) other).internalList)); + } + + @Override + public int hashCode() { + return internalList.hashCode(); + } +} +``` +###### \java\seedu\savvytasker\model\task\TaskList.java +``` java + +``` diff --git a/collated/test/A0139915W.md b/collated/test/A0139915W.md new file mode 100644 index 000000000000..b023e9452f3e --- /dev/null +++ b/collated/test/A0139915W.md @@ -0,0 +1,660 @@ +# A0139915W +###### \java\guitests\AddCommandTest.java +``` java +public class AddCommandTest extends SavvyTaskerGuiTest { + + @Test + public void add() { + //add one task + TestTask[] currentList = td.getTypicalTasks(); + TestTask taskToAdd = td.happy; + assertAddSuccess(taskToAdd, currentList); + currentList = TestUtil.addTasksToList(currentList, taskToAdd); + + //add another task + taskToAdd = td.haloween; + assertAddSuccess(taskToAdd, currentList); + currentList = TestUtil.addTasksToList(currentList, taskToAdd); + + //add to empty list + commandBox.runCommand("clear"); + assertAddSuccess(td.highPriority); + + //invalid command + commandBox.runCommand("adds Bad Command Task"); + assertResultMessage(Messages.MESSAGE_UNKNOWN_COMMAND); + } + + private void assertAddSuccess(TestTask taskToAdd, TestTask... currentList) { + commandBox.runCommand(taskToAdd.getAddCommand()); + + //confirm the new card contains the right data + TaskCardHandle addedCard = taskListPanel.navigateToTask(taskToAdd.getTaskName()); + assertMatching(taskToAdd, addedCard); + + //confirm the list now contains all previous persons plus the new person + TestTask[] expectedList = TestUtil.addTasksToList(currentList, taskToAdd); + assertTrue(taskListPanel.isListMatching(expectedList)); + } + +} +``` +###### \java\guitests\AddCommandTest.java +``` java + +``` +###### \java\guitests\guihandles\TaskListPanelHandle.java +``` java +/** + * Provides a handle for the panel containing the person list. + */ +public class TaskListPanelHandle extends GuiHandle { + + public static final int NOT_FOUND = -1; + public static final String CARD_PANE_ID = "#cardPane"; + + private static final String TASK_LIST_VIEW_ID = "#taskListView"; + + public TaskListPanelHandle(GuiRobot guiRobot, Stage primaryStage) { + super(guiRobot, primaryStage, TestApp.APP_TITLE); + } + + public List getSelectedTasks() { + ListView taskList = getListView(); + return taskList.getSelectionModel().getSelectedItems(); + } + + @SuppressWarnings("unchecked") + public ListView getListView() { + // Should be a listview of readonlytask only. + return (ListView) getNode(TASK_LIST_VIEW_ID); + } + + /** + * Returns true if the list is showing the person details correctly and in correct order. + * @param persons A list of person in the correct order. + */ + public boolean isListMatching(ReadOnlyTask... tasks) { + return this.isListMatching(0, tasks); + } + + /** + * Clicks on the ListView. + */ + public void clickOnListView() { + Point2D point= TestUtil.getScreenMidPoint(getListView()); + guiRobot.clickOn(point.getX(), point.getY()); + } + + /** + * Returns true if the {@code persons} appear as the sub list (in that order) at position {@code startPosition}. + */ + public boolean containsInOrder(int startPosition, ReadOnlyTask... tasks) { + List tasksInList = getListView().getItems(); + + // Return false if the list in panel is too short to contain the given list + if (startPosition + tasks.length > tasksInList.size()){ + return false; + } + + // Return false if any of the persons doesn't match + for (int i = 0; i < tasks.length; i++) { + if (!tasksInList.get(startPosition + i).getTaskName().equals(tasks[i].getTaskName())){ + return false; + } + } + + return true; + } + + /** + * Returns true if the list is showing the person details correctly and in correct order. + * @param startPosition The starting position of the sub list. + * @param persons A list of person in the correct order. + */ + public boolean isListMatching(int startPosition, ReadOnlyTask... tasks) throws IllegalArgumentException { + if (tasks.length + startPosition != getListView().getItems().size()) { + throw new IllegalArgumentException("List size mismatched\n" + + "Expected " + (getListView().getItems().size()) + " tasks"); + } + assertTrue(this.containsInOrder(startPosition, tasks)); + for (int i = 0; i < tasks.length; i++) { + final int scrollTo = i + startPosition; + guiRobot.interact(() -> getListView().scrollTo(scrollTo)); + guiRobot.sleep(200); + if (!TestUtil.compareCardAndTask(getTaskCardHandle(startPosition + i), tasks[i])) { + return false; + } + } + return true; + } + + + public TaskCardHandle navigateToTask(String name) { + guiRobot.sleep(500); //Allow a bit of time for the list to be updated + final Optional task = getListView().getItems().stream().filter(p -> p.getTaskName().equals(name)).findAny(); + if (!task.isPresent()) { + throw new IllegalStateException("Name not found: " + name); + } + + return navigateToTask(task.get()); + } + + /** + * Navigates the listview to display and select the person. + */ + public TaskCardHandle navigateToTask(ReadOnlyTask task) { + int index = getTaskIndex(task); + + guiRobot.interact(() -> { + getListView().scrollTo(index); + guiRobot.sleep(150); + getListView().getSelectionModel().select(index); + }); + guiRobot.sleep(100); + return getTaskCardHandle(task); + } + + + /** + * Returns the position of the person given, {@code NOT_FOUND} if not found in the list. + */ + public int getTaskIndex(ReadOnlyTask targetTask) { + List tasksInList = getListView().getItems(); + for (int i = 0; i < tasksInList.size(); i++) { + if(tasksInList.get(i).getTaskName().equals(targetTask.getTaskName())){ + return i; + } + } + return NOT_FOUND; + } + + /** + * Gets a person from the list by index + */ + public ReadOnlyTask getTask(int index) { + return getListView().getItems().get(index); + } + + public TaskCardHandle getTaskCardHandle(int index) { + return getTaskCardHandle(new Task(getListView().getItems().get(index))); + } + + public TaskCardHandle getTaskCardHandle(ReadOnlyTask task) { + Set nodes = getAllCardNodes(); + Optional taskCardNode = nodes.stream() + .filter(n -> new TaskCardHandle(guiRobot, primaryStage, n).isSameTask(task)) + .findFirst(); + if (taskCardNode.isPresent()) { + return new TaskCardHandle(guiRobot, primaryStage, taskCardNode.get()); + } else { + return null; + } + } + + protected Set getAllCardNodes() { + return guiRobot.lookup(CARD_PANE_ID).queryAll(); + } + + public int getNumberOfTasks() { + return getListView().getItems().size(); + } +} +``` +###### \java\guitests\guihandles\TaskListPanelHandle.java +``` java + +``` +###### \java\seedu\savvytasker\testutil\SavvyTaskerBuilder.java +``` java +/** + * A utility class to help with building SavvyTasker objects. + * Example usage:
+ * {@code SavvyTasker st = new SavvyTaskerBuilder().withTask("Hello Task").build();} + */ +public class SavvyTaskerBuilder { + + private SavvyTasker savvyTasker; + + public SavvyTaskerBuilder(SavvyTasker savvyTasker){ + this.savvyTasker = savvyTasker; + } + + public SavvyTaskerBuilder withTask(Task task) throws DuplicateTaskException, InvalidDateException { + savvyTasker.addTask(task); + return this; + } + + public SavvyTasker build(){ + return savvyTasker; + } +} +``` +###### \java\seedu\savvytasker\testutil\SavvyTaskerBuilder.java +``` java + +``` +###### \java\seedu\savvytasker\testutil\TaskBuilder.java +``` java +/** + * Helper to build Task objects + */ +public class TaskBuilder { + + private TestTask task; + + public TaskBuilder() { + this.task = new TestTask(); + } + + public TaskBuilder withId(int id) { + this.task.setId(id); + return this; + } + + public TaskBuilder withTaskName(String taskName) throws IllegalValueException { + this.task.setTaskName(taskName); + return this; + } + + public TaskBuilder withStartDateTime(Date startDateTime) { + this.task.setStartDateTime(startDateTime); + return this; + } + + public TaskBuilder withEndDateTime(Date endDateTime) { + this.task.setEndDateTime(endDateTime); + return this; + } + + public TaskBuilder withLocation(String location) { + this.task.setLocation(location); + return this; + } + + public TaskBuilder withPriority(PriorityLevel priority) { + this.task.setPriority(priority); + return this; + } + + public TaskBuilder withRecurringType(RecurrenceType recurringType) { + this.task.setRecurringType(recurringType); + return this; + } + + public TaskBuilder withNumberOfRecurrence(int numberOfRecurrence) { + this.task.setNumberOfRecurrence(numberOfRecurrence); + return this; + } + + public TaskBuilder withCategory(String category) { + this.task.setCategory(category); + return this; + } + + public TaskBuilder withDescription(String description) { + this.task.setDescription(description); + return this; + } + + public TaskBuilder withArchived(boolean isArchived) { + this.task.setArchived(isArchived); + return this; + } + + public TestTask build() { + return this.task; + } + +} +``` +###### \java\seedu\savvytasker\testutil\TaskBuilder.java +``` java + +``` +###### \java\seedu\savvytasker\testutil\TestUtil.java +``` java + public static final Task[] sampleTaskData = getSampleTaskData(); + + private static Task[] getSampleTaskData() { + return new Task[]{ + new Task("Sample Task Leh"), + new Task("Sample Task La"), + new Task("Sample Task Lo"), + new Task("Sample Task Ah") + }; + } +``` +###### \java\seedu\savvytasker\testutil\TestUtil.java +``` java + + public static List generateSampleTaskData() { + return Arrays.asList(sampleTaskData); + } + + /** + * Appends the file name to the sandbox folder path. + * Creates the sandbox folder if it doesn't exist. + * @param fileName + * @return + */ + public static String getFilePathInSandboxFolder(String fileName) { + try { + FileUtil.createDirs(new File(SANDBOX_FOLDER)); + } catch (IOException e) { + throw new RuntimeException(e); + } + return SANDBOX_FOLDER + fileName; + } + + public static void createDataFileWithSampleData(String filePath) { + createDataFileWithData(generateSampleStorageSavvyTasker(), filePath); + } + + public static void createDataFileWithData(T data, String filePath) { + try { + File saveFileForTesting = new File(filePath); + FileUtil.createIfMissing(saveFileForTesting); + XmlUtil.saveDataToFile(saveFileForTesting, data); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static void main(String... s) { + createDataFileWithSampleData(TestApp.SAVE_LOCATION_FOR_TESTING); + } + + public static SavvyTasker generateEmptySavvyTasker() { + return new SavvyTasker(new TaskList(), new AliasSymbolList()); + } + + public static XmlSerializableSavvyTasker generateSampleStorageSavvyTasker() { + return new XmlSerializableSavvyTasker(generateEmptySavvyTasker()); + } + + /** + * Tweaks the {@code keyCodeCombination} to resolve the {@code KeyCode.SHORTCUT} to their + * respective platform-specific keycodes + */ + public static KeyCode[] scrub(KeyCodeCombination keyCodeCombination) { + List keys = new ArrayList<>(); + if (keyCodeCombination.getAlt() == KeyCombination.ModifierValue.DOWN) { + keys.add(KeyCode.ALT); + } + if (keyCodeCombination.getShift() == KeyCombination.ModifierValue.DOWN) { + keys.add(KeyCode.SHIFT); + } + if (keyCodeCombination.getMeta() == KeyCombination.ModifierValue.DOWN) { + keys.add(KeyCode.META); + } + if (keyCodeCombination.getControl() == KeyCombination.ModifierValue.DOWN) { + keys.add(KeyCode.CONTROL); + } + keys.add(keyCodeCombination.getCode()); + return keys.toArray(new KeyCode[]{}); + } + + public static boolean isHeadlessEnvironment() { + String headlessProperty = System.getProperty("testfx.headless"); + return headlessProperty != null && headlessProperty.equals("true"); + } + + public static void captureScreenShot(String fileName) { + File file = GuiTest.captureScreenshot(); + try { + Files.copy(file, new File(fileName + ".png")); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public static String descOnFail(Object... comparedObjects) { + return "Comparison failed \n" + + Arrays.asList(comparedObjects).stream() + .map(Object::toString) + .collect(Collectors.joining("\n")); + } + + public static void setFinalStatic(Field field, Object newValue) throws NoSuchFieldException, IllegalAccessException{ + field.setAccessible(true); + // remove final modifier from field + Field modifiersField = Field.class.getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + // ~Modifier.FINAL is used to remove the final modifier from field so that its value is no longer + // final and can be changed + modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); + field.set(null, newValue); + } + + public static void initRuntime() throws TimeoutException { + FxToolkit.registerPrimaryStage(); + FxToolkit.hideStage(); + } + + public static void tearDownRuntime() throws Exception { + FxToolkit.cleanupStages(); + } + + /** + * Gets private method of a class + * Invoke the method using method.invoke(objectInstance, params...) + * + * Caveat: only find method declared in the current Class, not inherited from supertypes + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + public static Method getPrivateMethod(Class objectClass, String methodName) throws NoSuchMethodException { + Method method = objectClass.getDeclaredMethod(methodName); + method.setAccessible(true); + return method; + } + + public static void renameFile(File file, String newFileName) { + try { + Files.copy(file, new File(newFileName)); + } catch (IOException e1) { + e1.printStackTrace(); + } + } + + /** + * Gets mid point of a node relative to the screen. + * @param node + * @return + */ + public static Point2D getScreenMidPoint(Node node) { + double x = getScreenPos(node).getMinX() + node.getLayoutBounds().getWidth() / 2; + double y = getScreenPos(node).getMinY() + node.getLayoutBounds().getHeight() / 2; + return new Point2D(x,y); + } + + /** + * Gets mid point of a node relative to its scene. + * @param node + * @return + */ + public static Point2D getSceneMidPoint(Node node) { + double x = getScenePos(node).getMinX() + node.getLayoutBounds().getWidth() / 2; + double y = getScenePos(node).getMinY() + node.getLayoutBounds().getHeight() / 2; + return new Point2D(x,y); + } + + /** + * Gets the bound of the node relative to the parent scene. + * @param node + * @return + */ + public static Bounds getScenePos(Node node) { + return node.localToScene(node.getBoundsInLocal()); + } + + public static Bounds getScreenPos(Node node) { + return node.localToScreen(node.getBoundsInLocal()); + } + + public static double getSceneMaxX(Scene scene) { + return scene.getX() + scene.getWidth(); + } + + public static double getSceneMaxY(Scene scene) { + return scene.getX() + scene.getHeight(); + } + + public static Object getLastElement(List list) { + return list.get(list.size() - 1); + } + +``` +###### \java\seedu\savvytasker\testutil\TestUtil.java +``` java + /** + * Removes a subset from the list of tasks. + * @param tasks The list of tasks + * @param tasksToRemove The subset of tasjs. + * @return The modified tasks after removal of the subset from tasks. + */ + public static TestTask[] removeTasksFromList(final TestTask[] tasks, TestTask... tasksToRemove) { + List listOfTasks = asList(tasks); + listOfTasks.removeAll(asList(tasksToRemove)); + return listOfTasks.toArray(new TestTask[listOfTasks.size()]); + } + + + /** + * Returns a copy of the list with the task at specified index removed. + * @param list original list to copy from + * @param targetIndexInOneIndexedFormat e.g. if the first element to be removed, 1 should be given as index. + */ + public static TestTask[] removeTaskFromList(final TestTask[] list, int targetIndexInOneIndexedFormat) { + return removeTasksFromList(list, list[targetIndexInOneIndexedFormat-1]); + } + + /** + * Replaces tasks[i] with a task. + * @param tasks The array of tasks. + * @param task The replacement task + * @param index The index of the task to be replaced. + * @return + */ + public static TestTask[] replaceTaskFromList(TestTask[] tasks, TestTask task, int index) { + tasks[index] = task; + return tasks; + } + + /** + * Appends tasks to the array of tasks. + * @param tasks A array of tasks. + * @param tasksToAdd The tasks that are to be appended behind the original array. + * @return The modified array of tasks. + */ + public static TestTask[] addTasksToList(final TestTask[] tasks, TestTask... tasksToAdd) { + List listOfTasks = asList(tasks); + listOfTasks.addAll(asList(tasksToAdd)); + return listOfTasks.toArray(new TestTask[listOfTasks.size()]); + } +``` +###### \java\seedu\savvytasker\testutil\TestUtil.java +``` java + + private static List asList(T[] objs) { + List list = new ArrayList<>(); + for(T obj : objs) { + list.add(obj); + } + return list; + } + +``` +###### \java\seedu\savvytasker\testutil\TestUtil.java +``` java + public static boolean compareCardAndTask(TaskCardHandle card, ReadOnlyTask task) { + return card.isSameTask(task); + } +``` +###### \java\seedu\savvytasker\testutil\TestUtil.java +``` java + +} +``` +###### \java\seedu\savvytasker\testutil\TypicalTestTasks.java +``` java +/** + * Test tasks used to test cases + */ +public class TypicalTestTasks { + + public TestTask highPriority, medPriority, lowPriority, furthestDue, + nearerDue, notSoNearerDue, earliestDue, longDue, happy, haloween; + private SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy"); + + public TypicalTestTasks() { + try { + highPriority = new TaskBuilder().withId(0).withTaskName("High Priority Task") + .withPriority(PriorityLevel.High).build(); + medPriority = new TaskBuilder().withId(1).withTaskName("Medium Priority Task") + .withPriority(PriorityLevel.Medium).build(); + lowPriority = new TaskBuilder().withId(2).withTaskName("Low Priority Task") + .withPriority(PriorityLevel.Low).build(); + furthestDue = new TaskBuilder().withId(3).withTaskName("Furthest Due Task") + .withEndDateTime(getDate("01/12/2016")).build(); + nearerDue = new TaskBuilder().withId(4).withTaskName("Nearer Due Task") + .withEndDateTime(getDate("01/11/2016")).build(); + notSoNearerDue = new TaskBuilder().withId(5).withTaskName("Not So Nearer Due Task") + .withEndDateTime(getDate("02/11/2016")).build(); + earliestDue = new TaskBuilder().withId(6).withTaskName("Earliest Due Task") + .withEndDateTime(getDate("01/10/2016")).build(); + longDue = new TaskBuilder().withId(7).withTaskName("Long Due Task") + .withEndDateTime(getDate("01/1/2016")).withArchived(true).build(); + + //Manually added + happy = new TaskBuilder().withId(8).withTaskName("Happy Task").build(); + haloween = new TaskBuilder().withId(9).withTaskName("Haloween Task").build(); + } catch (IllegalValueException e) { + e.printStackTrace(); + assert false : "not possible"; + } + } + + public static void loadSavvyTaskerWithSampleData(SavvyTasker st) { + TypicalTestTasks td = new TypicalTestTasks(); + try { + st.addTask(new Task(td.highPriority)); + st.addTask(new Task(td.medPriority)); + st.addTask(new Task(td.lowPriority)); + st.addTask(new Task(td.furthestDue)); + st.addTask(new Task(td.nearerDue)); + st.addTask(new Task(td.notSoNearerDue)); + st.addTask(new Task(td.earliestDue)); + st.addTask(new Task(td.longDue)); + } catch (DuplicateTaskException e) { + assert false : "not possible"; + } catch (InvalidDateException e) { + assert false : "not possible"; + } + } + + public TestTask[] getTypicalTasks() { + return new TestTask[]{ highPriority, medPriority, lowPriority, + furthestDue, nearerDue, notSoNearerDue, earliestDue }; + } + + public SavvyTasker getTypicalSavvyTasker(){ + SavvyTasker st = new SavvyTasker(); + loadSavvyTaskerWithSampleData(st); + return st; + } + + private Date getDate(String ddmmyyyy) { + try { + return format.parse(ddmmyyyy); + } catch (Exception e) { + assert false; //should not get an invalid date.... + } + return null; + } +} +``` +###### \java\seedu\savvytasker\testutil\TypicalTestTasks.java +``` java + +``` diff --git a/src/main/java/seedu/savvytasker/commons/events/ui/TaskPanelSelectionChangedEvent.java b/src/main/java/seedu/savvytasker/commons/events/ui/TaskPanelSelectionChangedEvent.java index 89caab54a44f..317fa9e493ba 100644 --- a/src/main/java/seedu/savvytasker/commons/events/ui/TaskPanelSelectionChangedEvent.java +++ b/src/main/java/seedu/savvytasker/commons/events/ui/TaskPanelSelectionChangedEvent.java @@ -3,8 +3,10 @@ import seedu.savvytasker.commons.events.BaseEvent; import seedu.savvytasker.model.task.ReadOnlyTask; +//@@author A0139915W + /** - * Represents a selection change in the Person List Panel + * Represents a selection change in the Task List Panel */ public class TaskPanelSelectionChangedEvent extends BaseEvent { @@ -24,3 +26,4 @@ public ReadOnlyTask getNewSelection() { return newSelection; } } +//@@author \ No newline at end of file diff --git a/src/main/java/seedu/savvytasker/commons/util/SmartDefaultDates.java b/src/main/java/seedu/savvytasker/commons/util/SmartDefaultDates.java index d23b4ed64516..2ca8133d63dd 100644 --- a/src/main/java/seedu/savvytasker/commons/util/SmartDefaultDates.java +++ b/src/main/java/seedu/savvytasker/commons/util/SmartDefaultDates.java @@ -5,6 +5,7 @@ import seedu.savvytasker.logic.parser.DateParser.InferredDate; +//@@author A0139915W /** * Helper functions for handling dates. * @author A0139915W @@ -127,7 +128,12 @@ private void parseStart(InferredDate startDateTime) { calendar.set(Calendar.SECOND, 59); this.endDateTime = calendar.getTime(); } - + + /** + * Sets the starting and ending date/time based on defaults for providing both + * start and end times + * @param startDateTime start time supplied + */ private void parseStartAndEnd(InferredDate startDateTime, InferredDate endDateTime) { assert endDateTime.getInferredDateTime() != null; assert startDateTime.getInferredDateTime() != null; @@ -149,4 +155,5 @@ public Date getStartDate() { public Date getEndDate() { return endDateTime; } -} \ No newline at end of file +} +//@@author A0139915W \ No newline at end of file diff --git a/src/main/java/seedu/savvytasker/commons/util/StringUtil.java b/src/main/java/seedu/savvytasker/commons/util/StringUtil.java index 8a7355cdec6b..d9345fe3a922 100644 --- a/src/main/java/seedu/savvytasker/commons/util/StringUtil.java +++ b/src/main/java/seedu/savvytasker/commons/util/StringUtil.java @@ -9,17 +9,21 @@ * Helper functions for handling strings. */ public class StringUtil { + //@@author A0139915W + // reused original implementation of 'containsIgnoreCase' to find exact matches public static boolean containsExactIgnoreCase(String source, String query) { List strings = Arrays.asList(source); return strings.stream().filter(s -> s.equalsIgnoreCase(query)).count() > 0; } - + + // reused original implementation of 'containsIgnoreCase' to find partial matches public static boolean containsPartialIgnoreCase(String source, String query) { if (source == null) return false; String[] split = source.toLowerCase().split("\\s+"); List strings = Arrays.asList(split); return strings.stream().filter(s -> s.contains(query.toLowerCase())).count() > 0; } + //@@author A0139915W public static boolean containsIgnoreCase(String source, String query) { String[] split = source.toLowerCase().split("\\s+"); diff --git a/src/main/java/seedu/savvytasker/logic/commands/AddCommand.java b/src/main/java/seedu/savvytasker/logic/commands/AddCommand.java index 07d16272c5d8..3c13f604c26d 100644 --- a/src/main/java/seedu/savvytasker/logic/commands/AddCommand.java +++ b/src/main/java/seedu/savvytasker/logic/commands/AddCommand.java @@ -40,6 +40,7 @@ public class AddCommand extends ModelRequiringCommand { private Task toAdd; + //@@author A0139915W /** * Creates an add command. */ @@ -61,7 +62,6 @@ private void createTask() { final boolean isArchived = false; // all tasks are first added as active tasks final int taskId = 0; // taskId to be assigned by ModelManager, leave as 0 - //TODO: Smart defaults for date SmartDefaultDates sdd = new SmartDefaultDates(startDateTime, endDateTime); this.toAdd = new Task(taskId, taskName, sdd.getStartDate(), sdd.getEndDate(), location, priority, recurringType, numberOfRecurrence, @@ -83,6 +83,7 @@ public CommandResult execute() { } } + //@@author A0139915W /** * Checks if a command can perform undo operations diff --git a/src/main/java/seedu/savvytasker/logic/commands/DeleteCommand.java b/src/main/java/seedu/savvytasker/logic/commands/DeleteCommand.java index a5161fc96845..acfefd6873d4 100644 --- a/src/main/java/seedu/savvytasker/logic/commands/DeleteCommand.java +++ b/src/main/java/seedu/savvytasker/logic/commands/DeleteCommand.java @@ -29,7 +29,8 @@ public class DeleteCommand extends ModelRequiringCommand { //private LinkedList tasksToUndo = new LinkedList(); private ReadOnlySavvyTasker original; private final int[] targetIndices; - + + //@@author A0139915W public DeleteCommand(int[] targetIndices) { this.targetIndices = targetIndices; } @@ -63,6 +64,7 @@ public CommandResult execute() { return new CommandResult(resultSb.toString()); } + //@@author A0139915W /** * Checks if a command can perform undo operations diff --git a/src/main/java/seedu/savvytasker/logic/commands/ListCommand.java b/src/main/java/seedu/savvytasker/logic/commands/ListCommand.java index ac5d7f0a675f..160f1630c047 100644 --- a/src/main/java/seedu/savvytasker/logic/commands/ListCommand.java +++ b/src/main/java/seedu/savvytasker/logic/commands/ListCommand.java @@ -17,7 +17,8 @@ public class ListCommand extends ModelRequiringCommand { public static final String MESSAGE_SUCCESS = "Listed all tasks"; private final ListType listType; - + + //@@author A0139915W /** * Creates the List command to list the specified tasks * @author A0139915W @@ -50,6 +51,7 @@ public CommandResult execute() { } return new CommandResult(getMessageForTaskListShownSummary(model.getFilteredTaskList().size())); } + //@@author A0139915W /** * Checks if a command can perform undo operations diff --git a/src/main/java/seedu/savvytasker/model/Model.java b/src/main/java/seedu/savvytasker/model/Model.java index 9eaef9cd7905..b5da015385a6 100644 --- a/src/main/java/seedu/savvytasker/model/Model.java +++ b/src/main/java/seedu/savvytasker/model/Model.java @@ -21,6 +21,7 @@ public interface Model { /** Returns Savvy Tasker */ ReadOnlySavvyTasker getSavvyTasker(); + //@@author A0139915W /** Deletes the given Task. */ void deleteTask(ReadOnlyTask target) throws TaskNotFoundException; @@ -52,6 +53,7 @@ public interface Model { /** Updates the filter of the filtered task list to filter by the given keywords*/ void updateFilteredTaskList(FindType findType, String[] keywords); + //@@author A0139915W /** Adds the given AliasSymbol */ void addAliasSymbol(AliasSymbol symbol) throws DuplicateSymbolKeywordException; diff --git a/src/main/java/seedu/savvytasker/model/ModelManager.java b/src/main/java/seedu/savvytasker/model/ModelManager.java index f7dd384fc7cf..41beb7878dc4 100644 --- a/src/main/java/seedu/savvytasker/model/ModelManager.java +++ b/src/main/java/seedu/savvytasker/model/ModelManager.java @@ -33,10 +33,13 @@ public class ModelManager extends ComponentManager implements Model { private static final Logger logger = LogsCenter.getLogger(ModelManager.class); + //@@author A0139915W private final SavvyTasker savvyTasker; private final FilteredList filteredTasks; private final SortedList sortedAndFilteredTasks; + //@@author A0139915W + //@@author A0139915W /** * Initializes a ModelManager with the given SavvyTasker * and its variables should not be null @@ -79,6 +82,7 @@ public ReadOnlySavvyTasker getSavvyTasker() { private void indicateSavvyTaskerChanged() { raise(new SavvyTaskerChangedEvent(savvyTasker)); } + //@@author A0139915W private void indicateAliasSymbolAdded(AliasSymbol symbol) { raise(new AliasSymbolChangedEvent(symbol, AliasSymbolChangedEvent.Action.Added)); @@ -89,6 +93,7 @@ private void indicateAliasSymbolRemoved(AliasSymbol symbol) { } + //@@author A0139915W @Override public synchronized void deleteTask(ReadOnlyTask target) throws TaskNotFoundException { savvyTasker.removeTask(target); @@ -108,6 +113,7 @@ public synchronized void addTask(Task t) throws DuplicateTaskException, InvalidD updateFilteredListToShowActive(); indicateSavvyTaskerChanged(); } + //@@author A0139915W @Override public synchronized void addAliasSymbol(AliasSymbol symbol) throws DuplicateSymbolKeywordException { @@ -125,6 +131,7 @@ public synchronized void removeAliasSymbol(AliasSymbol symbol) throws SymbolKeyw //=========== Filtered/Sorted Task List Accessors =============================================================== + //@@author A0139915W @Override public UnmodifiableObservableList getFilteredTaskList() { return new UnmodifiableObservableList(sortedAndFilteredTasks); @@ -144,12 +151,11 @@ public void updateFilteredListToShowActiveSortedByDueDate() { public void updateFilteredListToShowActiveSortedByPriorityLevel() { updateFilteredListToShowActive(new TaskSortedByPriorityLevel()); } - + @Override public void updateFilteredListToShowActive() { updateFilteredTaskList(new PredicateExpression(new TaskIsActiveQualifier())); } - private void updateFilteredListToShowActive(Comparator comparator) { updateFilteredTaskList( new PredicateExpression(new TaskIsActiveQualifier()), @@ -160,7 +166,7 @@ private void updateFilteredListToShowActive(Comparator comparator) { public void updateFilteredListToShowArchived() { updateFilteredTaskList(new PredicateExpression(new TaskIsArchivedQualifier())); } - + @Override public void updateFilteredTaskList(FindType findType, String[] keywords) { assert findType != null; @@ -193,6 +199,7 @@ private void updateFilteredTaskList(Expression expression, Comparator comp filteredTasks.setPredicate(expression::satisfies); sortedAndFilteredTasks.setComparator(comparator); } + //@@author A0139915W //========== Inner classes/interfaces used for filtering ================================================== @@ -237,6 +244,7 @@ default Set createSet(String[] keywords) { } } + //@@author A0139915W /** * Qualifier matching a partial word from the set of keywords * @author A0139915W @@ -470,5 +478,6 @@ public int compare(Task task1, Task task2) { } } + //@@author A0139915W } diff --git a/src/main/java/seedu/savvytasker/model/ReadOnlySavvyTasker.java b/src/main/java/seedu/savvytasker/model/ReadOnlySavvyTasker.java index 8b4a456b44b7..c9078435f4a6 100644 --- a/src/main/java/seedu/savvytasker/model/ReadOnlySavvyTasker.java +++ b/src/main/java/seedu/savvytasker/model/ReadOnlySavvyTasker.java @@ -11,20 +11,24 @@ * Unmodifiable view of a task list */ public interface ReadOnlySavvyTasker { + //@@author A0139915W /** * Returns a defensively copied task list. */ TaskList getTaskList(); + //@@author A0139915W /** * Returns a defensively copied alias symbol list. */ AliasSymbolList getAliasSymbolList(); + //@@author A0139915W /** * Returns an unmodifiable view of task list */ List getReadOnlyListOfTasks(); + //@@author A0139915W /** * Returns unmodifiable view of symbols list diff --git a/src/main/java/seedu/savvytasker/model/SavvyTasker.java b/src/main/java/seedu/savvytasker/model/SavvyTasker.java index d11aef04d442..5c03abca8623 100644 --- a/src/main/java/seedu/savvytasker/model/SavvyTasker.java +++ b/src/main/java/seedu/savvytasker/model/SavvyTasker.java @@ -24,9 +24,12 @@ */ public class SavvyTasker implements ReadOnlySavvyTasker { + //@@author A0139915W private final TaskList tasks; + //@@author A0139915W private final AliasSymbolList symbols; + //@@author A0139915W public SavvyTasker() { this.tasks = new TaskList(); this.symbols = new AliasSymbolList(); @@ -63,9 +66,11 @@ public void resetData(Collection newTasks) { public void resetData(ReadOnlySavvyTasker newData) { resetData(newData.getReadOnlyListOfTasks()); } + //@@author A0139915W //// symbol/task-level operations - + + //@@author A0139915W /** * Returns the next available id for use to uniquely identify a task. * @author A0139915W @@ -90,11 +95,7 @@ public void addTask(Task t) throws DuplicateTaskException, InvalidDateException * @throws TaskNotFoundException if the task to be removed does not exist */ public boolean removeTask(ReadOnlyTask key) throws TaskNotFoundException { - if (tasks.remove(key)) { - return true; - } else { - throw new TaskList.TaskNotFoundException(); - } + return tasks.remove(key); } /** @@ -104,12 +105,9 @@ public boolean removeTask(ReadOnlyTask key) throws TaskNotFoundException { * @throws TaskNotFoundException if the task to be removed does not exist */ public boolean replaceTask(ReadOnlyTask key, Task replacement) throws TaskNotFoundException, InvalidDateException { - if (tasks.contains(key)) { - return tasks.replace(key, replacement); - } else { - throw new TaskList.TaskNotFoundException(); - } + return tasks.replace(key, replacement); } + //@@author A0139915W /** * Adds an alias symbol to savvy tasker. diff --git a/src/main/java/seedu/savvytasker/model/task/TaskList.java b/src/main/java/seedu/savvytasker/model/task/TaskList.java index 61445730e98d..ad49ab128afc 100644 --- a/src/main/java/seedu/savvytasker/model/task/TaskList.java +++ b/src/main/java/seedu/savvytasker/model/task/TaskList.java @@ -8,6 +8,7 @@ import seedu.savvytasker.commons.exceptions.DuplicateDataException; import seedu.savvytasker.commons.exceptions.IllegalValueException; +//@@author A0139915W /** * A list of tasks that enforces uniqueness between its elements and does not allow nulls. * @@ -184,3 +185,4 @@ public int hashCode() { return internalList.hashCode(); } } +//@@author A0139915W diff --git a/src/test/java/guitests/AddCommandTest.java b/src/test/java/guitests/AddCommandTest.java index d845d6939c8d..b7025a837241 100644 --- a/src/test/java/guitests/AddCommandTest.java +++ b/src/test/java/guitests/AddCommandTest.java @@ -10,6 +10,7 @@ import static org.junit.Assert.assertTrue; +//@@author A0139915W public class AddCommandTest extends SavvyTaskerGuiTest { @Test @@ -47,3 +48,4 @@ private void assertAddSuccess(TestTask taskToAdd, TestTask... currentList) { } } +//@@author A0139915W diff --git a/src/test/java/guitests/guihandles/TaskListPanelHandle.java b/src/test/java/guitests/guihandles/TaskListPanelHandle.java index 787b7715a43e..b2cfeb50398e 100644 --- a/src/test/java/guitests/guihandles/TaskListPanelHandle.java +++ b/src/test/java/guitests/guihandles/TaskListPanelHandle.java @@ -17,6 +17,7 @@ import static org.junit.Assert.assertTrue; +//@@author A0139915W /** * Provides a handle for the panel containing the person list. */ @@ -172,3 +173,4 @@ public int getNumberOfTasks() { return getListView().getItems().size(); } } +//@@author A0139915W diff --git a/src/test/java/seedu/savvytasker/testutil/SavvyTaskerBuilder.java b/src/test/java/seedu/savvytasker/testutil/SavvyTaskerBuilder.java index db6af1cab618..f2c3c28fd268 100644 --- a/src/test/java/seedu/savvytasker/testutil/SavvyTaskerBuilder.java +++ b/src/test/java/seedu/savvytasker/testutil/SavvyTaskerBuilder.java @@ -5,6 +5,7 @@ import seedu.savvytasker.model.task.TaskList.DuplicateTaskException; import seedu.savvytasker.model.task.TaskList.InvalidDateException; +//@@author A0139915W /** * A utility class to help with building SavvyTasker objects. * Example usage:
@@ -27,3 +28,4 @@ public SavvyTasker build(){ return savvyTasker; } } +//@@author A0139915W diff --git a/src/test/java/seedu/savvytasker/testutil/TaskBuilder.java b/src/test/java/seedu/savvytasker/testutil/TaskBuilder.java index b964b46ff4c9..1934740e1622 100644 --- a/src/test/java/seedu/savvytasker/testutil/TaskBuilder.java +++ b/src/test/java/seedu/savvytasker/testutil/TaskBuilder.java @@ -6,8 +6,9 @@ import seedu.savvytasker.model.task.PriorityLevel; import seedu.savvytasker.model.task.RecurrenceType; +//@@author A0139915W /** - * + * Helper to build Task objects */ public class TaskBuilder { @@ -77,3 +78,4 @@ public TestTask build() { } } +//@@author A0139915W diff --git a/src/test/java/seedu/savvytasker/testutil/TestUtil.java b/src/test/java/seedu/savvytasker/testutil/TestUtil.java index 45fd0ba223cd..02b95a34ab2f 100644 --- a/src/test/java/seedu/savvytasker/testutil/TestUtil.java +++ b/src/test/java/seedu/savvytasker/testutil/TestUtil.java @@ -61,6 +61,7 @@ public static void assertThrows(Class expected, Runnable ex */ public static String SANDBOX_FOLDER = FileUtil.getPath("./src/test/data/sandbox/"); + //@@author A0139915W public static final Task[] sampleTaskData = getSampleTaskData(); private static Task[] getSampleTaskData() { @@ -71,6 +72,7 @@ private static Task[] getSampleTaskData() { new Task("Sample Task Ah") }; } + //@@author A0139915W public static List generateSampleTaskData() { return Arrays.asList(sampleTaskData); @@ -248,11 +250,12 @@ public static Object getLastElement(List list) { return list.get(list.size() - 1); } + //@@author A0139915W /** - * Removes a subset from the list of persons. - * @param persons The list of persons - * @param personsToRemove The subset of persons. - * @return The modified persons after removal of the subset from persons. + * Removes a subset from the list of tasks. + * @param tasks The list of tasks + * @param tasksToRemove The subset of tasjs. + * @return The modified tasks after removal of the subset from tasks. */ public static TestTask[] removeTasksFromList(final TestTask[] tasks, TestTask... tasksToRemove) { List listOfTasks = asList(tasks); @@ -262,7 +265,7 @@ public static TestTask[] removeTasksFromList(final TestTask[] tasks, TestTask... /** - * Returns a copy of the list with the person at specified index removed. + * Returns a copy of the list with the task at specified index removed. * @param list original list to copy from * @param targetIndexInOneIndexedFormat e.g. if the first element to be removed, 1 should be given as index. */ @@ -293,6 +296,7 @@ public static TestTask[] addTasksToList(final TestTask[] tasks, TestTask... task listOfTasks.addAll(asList(tasksToAdd)); return listOfTasks.toArray(new TestTask[listOfTasks.size()]); } + //@@author A0139915W private static List asList(T[] objs) { List list = new ArrayList<>(); @@ -302,8 +306,10 @@ private static List asList(T[] objs) { return list; } + //@@author A0139915W public static boolean compareCardAndTask(TaskCardHandle card, ReadOnlyTask task) { return card.isSameTask(task); } + //@@author A0139915W } diff --git a/src/test/java/seedu/savvytasker/testutil/TypicalTestTasks.java b/src/test/java/seedu/savvytasker/testutil/TypicalTestTasks.java index a89ccf000d95..9b49d7d50437 100644 --- a/src/test/java/seedu/savvytasker/testutil/TypicalTestTasks.java +++ b/src/test/java/seedu/savvytasker/testutil/TypicalTestTasks.java @@ -10,8 +10,9 @@ import seedu.savvytasker.model.task.TaskList.DuplicateTaskException; import seedu.savvytasker.model.task.TaskList.InvalidDateException; +//@@author A0139915W /** - * + * Test tasks used to test cases */ public class TypicalTestTasks { @@ -85,3 +86,4 @@ private Date getDate(String ddmmyyyy) { return null; } } +//@@author A0139915W