diff --git a/README.md b/README.md
index 13f5c77403f..0aed6c7dafe 100644
--- a/README.md
+++ b/README.md
@@ -1,14 +1,17 @@
-[](https://github.com/se-edu/addressbook-level3/actions)
+[](https://github.com/AY2021S2-CS2103T-W14-3/tp/actions/workflows/gradle.yml)

-* This is **a sample project for Software Engineering (SE) students**.
- Example usages:
- * as a starting point of a course project (as opposed to writing everything from scratch)
- * as a case study
-* The project simulates an ongoing software project for a desktop application (called _AddressBook_) used for managing contact details.
- * It is **written in OOP fashion**. It provides a **reasonably well-written** code base **bigger** (around 6 KLoC) than what students usually write in beginner-level SE modules, without being overwhelmingly big.
- * It comes with a **reasonable level of user and developer documentation**.
-* It is named `AddressBook Level 3` (`AB3` for short) because it was initially created as a part of a series of `AddressBook` projects (`Level 1`, `Level 2`, `Level 3` ...).
-* For the detailed documentation of this project, see the **[Address Book Product Website](https://se-education.org/addressbook-level3)**.
-* This project is a **part of the se-education.org** initiative. If you would like to contribute code to this project, see [se-education.org](https://se-education.org#https://se-education.org/#contributing) for more info.
+Are you a CCA leader that has to keep track of multiple CCA members, tasks and upcoming deadlines but can't seem to remember everything? Well HEY MATEz is the solution for you!
+
+## About Us
+Refer to the [About Us](https://github.com/AY2021S2-CS2103T-W14-3/tp/blob/master/docs/AboutUs.md) section
+
+## Developer Guide
+Refer to the [Developer Guide](https://github.com/AY2021S2-CS2103T-W14-3/tp/blob/master/docs/DeveloperGuide.md) section
+
+## User Guide
+Refer to the [User Guide](https://github.com/AY2021S2-CS2103T-W14-3/tp/blob/master/docs/UserGuide.md) section
+
+## Source Code
+This project is based off the AddressBook-Level3 project created by the [SE-EDU initiative](https://se-education.org).
diff --git a/build.gradle b/build.gradle
index be2d2905dde..cdd8917bef1 100644
--- a/build.gradle
+++ b/build.gradle
@@ -6,7 +6,7 @@ plugins {
id 'jacoco'
}
-mainClassName = 'seedu.address.Main'
+mainClassName = 'seedu.heymatez.Main'
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
@@ -66,7 +66,11 @@ dependencies {
}
shadowJar {
- archiveName = 'addressbook.jar'
+ archiveName = 'HEYMATEz.jar'
+}
+
+run {
+ enableAssertions = true
}
defaultTasks 'clean', 'test'
diff --git a/docs/AboutUs.md b/docs/AboutUs.md
index 1c9514e966a..decb9fb7c89 100644
--- a/docs/AboutUs.md
+++ b/docs/AboutUs.md
@@ -5,55 +5,50 @@ title: About Us
We are a team based in the [School of Computing, National University of Singapore](http://www.comp.nus.edu.sg).
-You can reach us at the email `seer[at]comp.nus.edu.sg`
+You can reach us at the respective emails:
+* `dylan.ghee@u.nus.edu`
+* `chee.erynne@u.nus.edu`
+* `rachel.limjt@u.nus.edu`
+* `e0424909@u.nus.edu`
## Project team
-### John Doe
+### Dylan Ghee Shao Kang
-
+
-[[homepage](http://www.comp.nus.edu.sg/~damithch)]
-[[github](https://github.com/johndoe)]
-[[portfolio](team/johndoe.md)]
-
-* Role: Project Advisor
-
-### Jane Doe
-
-
-
-[[github](http://github.com/johndoe)]
-[[portfolio](team/johndoe.md)]
+[[github](https://github.com/zatkiller)]
+[[portfolio](team/zatkiller.md)]
* Role: Team Lead
-* Responsibilities: UI
+* Responsibilities: Project Management and Code Quality
-### Johnny Doe
+### Chee Erynne
-
+
-[[github](http://github.com/johndoe)] [[portfolio](team/johndoe.md)]
+[[github](http://github.com/cheeerynne)]
+[[portfolio](team/cheeerynne.md)]
-* Role: Developer
-* Responsibilities: Data
+* Role: Software Developer
+* Responsibilities: Documentation, Testing
-### Jean Doe
+### Lim Jean Tong, Rachel
-
+
-[[github](http://github.com/johndoe)]
-[[portfolio](team/johndoe.md)]
+[[github](http://github.com/rachelljt)]
+[[portfolio](team/rachelljt.md)]
-* Role: Developer
-* Responsibilities: Dev Ops + Threading
+* Role: Software Developer
+* Responsibilities: UI
-### James Doe
+### Tasha Marion Wan hui lin
-
+
-[[github](http://github.com/johndoe)]
-[[portfolio](team/johndoe.md)]
+[[github](https://github.com/tashawan23)]
+[[portfolio](team/tashawan23.md)]
-* Role: Developer
-* Responsibilities: UI
+* Role: Software Developer
+* Responsibilities: Documentation, Integration
diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md
index 4829fe43011..434b4a4f18d 100644
--- a/docs/DeveloperGuide.md
+++ b/docs/DeveloperGuide.md
@@ -2,17 +2,22 @@
layout: page
title: Developer Guide
---
+## Table of Contents
* Table of Contents
{:toc}
--------------------------------------------------------------------------------------------------------------------
+
+
## **Setting up, getting started**
Refer to the guide [_Setting up and getting started_](SettingUp.md).
--------------------------------------------------------------------------------------------------------------------
+
+
## **Design**
### Architecture
@@ -23,11 +28,12 @@ The ***Architecture Diagram*** given above explains the high-level design of the
-:bulb: **Tip:** The `.puml` files used to create diagrams in this document can be found in the [diagrams](https://github.com/se-edu/addressbook-level3/tree/master/docs/diagrams/) folder. Refer to the [_PlantUML Tutorial_ at se-edu/guides](https://se-education.org/guides/tutorials/plantUml.html) to learn how to create and edit diagrams.
+:bulb: **Tip:** The `.puml` files used to create diagrams in this document can be found in the [diagrams](https://github.com/AY2021S2-CS2103T-W14-3/tp/tree/master/docs/diagrams) folder. Refer to the [_PlantUML Tutorial_ at se-edu/guides](https://se-education.org/guides/tutorials/plantUml.html) to learn how to create and edit diagrams.
-**`Main`** has two classes called [`Main`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/Main.java) and [`MainApp`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/MainApp.java). It is responsible for,
+**`Main`** has two classes called [`Main`](https://github.com/AY2021S2-CS2103T-W14-3/tp/blob/master/src/main/java/seedu/heymatez/Main.java)
+and [`MainApp`](https://github.com/AY2021S2-CS2103T-W14-3/tp/blob/master/src/main/java/seedu/heymatez/MainApp.java). It is responsible for,
* At app launch: Initializes the components in the correct sequence, and connects them up with each other.
* At shut down: Shuts down the components and invokes cleanup methods where necessary.
@@ -51,175 +57,297 @@ For example, the `Logic` component (see the class diagram given below) defines i
**How the architecture components interact with each other**
-The *Sequence Diagram* below shows how the components interact with each other for the scenario where the user issues the command `delete 1`.
+The *Sequence Diagram* below shows how the components interact with each other for the scenario where the user issues the command `deleteTask 1`.
The sections below give more details of each component.
+
+
### UI component

**API** :
-[`Ui.java`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/ui/Ui.java)
+[`Ui.java`](https://github.com/AY2021S2-CS2103T-W14-3/tp/blob/master/src/main/java/seedu/heymatez/ui/Ui.java)
-The UI consists of a `MainWindow` that is made up of parts e.g.`CommandBox`, `ResultDisplay`, `PersonListPanel`, `StatusBarFooter` etc. All these, including the `MainWindow`, inherit from the abstract `UiPart` class.
+The UI consists of a `MainWindow` that is made up of parts e.g.`CommandBox`, `ResultDisplay`, `PersonListPanel`, `TaskListPanel`, `StatusBarFooter` etc. All these, including the `MainWindow`, inherit from the abstract `UiPart` class.
-The `UI` component uses JavaFx UI framework. The layout of these UI parts are defined in matching `.fxml` files that are in the `src/main/resources/view` folder. For example, the layout of the [`MainWindow`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/ui/MainWindow.java) is specified in [`MainWindow.fxml`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/resources/view/MainWindow.fxml)
+The `UI` component uses JavaFx UI framework. The layout of these UI parts are defined in matching `.fxml` files that are in the `src/main/resources/view` folder. For example, the layout of the [`MainWindow`](https://github.com/AY2021S2-CS2103T-W14-3/tp/blob/master/src/main/java/seedu/heymatez/ui/MainWindow.java) is specified in [`MainWindow.fxml`](https://github.com/AY2021S2-CS2103T-W14-3/tp/blob/master/src/main/resources/view/MainWindow.fxml)
The `UI` component,
* Executes user commands using the `Logic` component.
* Listens for changes to `Model` data so that the UI can be updated with the modified data.
+
+
### Logic component

**API** :
-[`Logic.java`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/logic/Logic.java)
+[`Logic.java`](https://github.com/AY2021S2-CS2103T-W14-3/tp/blob/master/src/main/java/seedu/heymatez/logic/Logic.java)
-1. `Logic` uses the `AddressBookParser` class to parse the user command.
+1. `Logic` uses the `HeyMatezParser` class to parse the user command.
1. This results in a `Command` object which is executed by the `LogicManager`.
-1. The command execution can affect the `Model` (e.g. adding a person).
+1. The command execution can affect the `Model` (e.g. adding a task).
1. The result of the command execution is encapsulated as a `CommandResult` object which is passed back to the `Ui`.
1. In addition, the `CommandResult` object can also instruct the `Ui` to perform certain actions, such as displaying help to the user.
-Given below is the Sequence Diagram for interactions within the `Logic` component for the `execute("delete 1")` API call.
+Given below is the Sequence Diagram for interactions within the `Logic` component for the `execute("deleteTask 1")` API call.
-
+
-
:information_source: **Note:** The lifeline for `DeleteCommandParser` should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
+
:information_source: **Note:** The lifeline for `DeleteTaskCommandParser` should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
+
+
### Model component

-**API** : [`Model.java`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/model/Model.java)
+**API** : [`Model.java`](https://github.com/AY2021S2-CS2103T-W14-3/tp/blob/master/src/main/java/seedu/heymatez/model/Model.java)
The `Model`,
* stores a `UserPref` object that represents the user’s preferences.
-* stores the address book data.
-* exposes an unmodifiable `ObservableList` that can be 'observed' e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list change.
+* stores the HEY MATEz data.
+* exposes an unmodifiable `ObservableList` and `ObservableList` that can be 'observed' e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list change.
* does not depend on any of the other three components.
-
-
:information_source: **Note:** An alternative (arguably, a more OOP) model is given below. It has a `Tag` list in the `AddressBook`, which `Person` references. This allows `AddressBook` to only require one `Tag` object per unique `Tag`, instead of each `Person` needing their own `Tag` object.
-
-
-
-
+
### Storage component

-**API** : [`Storage.java`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/storage/Storage.java)
+**API** : [`Storage.java`](https://github.com/AY2021S2-CS2103T-W14-3/tp/blob/master/src/main/java/seedu/heymatez/storage/Storage.java)
The `Storage` component,
* can save `UserPref` objects in json format and read it back.
-* can save the address book data in json format and read it back.
+* can save the HEY MATEz data in json format and read it back.
### Common classes
-Classes used by multiple components are in the `seedu.addressbook.commons` package.
+Classes used by multiple components are in the `seedu.heymatez.commons` package.
--------------------------------------------------------------------------------------------------------------------
+
+
## **Implementation**
+This section documents some of the noteworthy details on how certain features are implemented
-This section describes some noteworthy details on how certain features are implemented.
+### Mark Task as completed / uncompleted feature
-### \[Proposed\] Undo/redo feature
+The implementation of the mark task as completed and uncompleted features are facilitated by the `DoneTaskCommand` and `UndoTaskCommand`
+classes respectively, both of which extends from the Command abstract class.
-#### Proposed Implementation
+The execution of the command is also facilitated by the following Parser Classes:
+* `DoneTaskCommandParser`
+* `UndoTaskCommandParser`
-The proposed undo/redo mechanism is facilitated by `VersionedAddressBook`. It extends `AddressBook` with an undo/redo history, stored internally as an `addressBookStateList` and `currentStatePointer`. Additionally, it implements the following operations:
+The above mentioned Parser classes inherit the `#parse` method from the `Parser` interface.
-* `VersionedAddressBook#commit()` — Saves the current address book state in its history.
-* `VersionedAddressBook#undo()` — Restores the previous address book state from its history.
-* `VersionedAddressBook#redo()` — Restores a previously undone address book state from its history.
+* `DoneTaskCommandParser#parse` - checks if the arguments passed to the current DoneTaskCommand is valid and creates an DoneTaskCommand instance if it is.
+* `UndoTaskCommandParser#parse` - checks if the arguments passed to the current UndoTaskCommand is valid and creates an UndoTaskCommand instance if it is.
-These operations are exposed in the `Model` interface as `Model#commitAddressBook()`, `Model#undoAddressBook()` and `Model#redoAddressBook()` respectively.
+Subsequently, the created `DoneTaskCommand` / `UndoTaskCommand` object contains an `#execute` method which is responsible for
+updating the status of the task to `completed` or `uncompleted`. This is achieved by creating a new `Task` object with the
+same fields and values but updating the `TaskStatus` field depending on which command is being executed.
-Given below is an example usage scenario and how the undo/redo mechanism behaves at each step.
+Below is the usage scenario and how the mark task as completed mechanism behaves.
-Step 1. The user launches the application for the first time. The `VersionedAddressBook` will be initialized with the initial address book state, and the `currentStatePointer` pointing to that single address book state.
+Assumptions:
+1. User has already launched the app
+2. HEY MATEz application has an existing task whose status is `uncompleted`
-
+Step 1. User executes the `done 1` command to mark the task with index number 1 in the task list of HEY MATEz as `completed`.
+ A `DoneTaskCommandParser` object is created and it calls `DoneTaskCommandParser#parse` on the arguments given.
-Step 2. The user executes `delete 5` command to delete the 5th person in the address book. The `delete` command calls `Model#commitAddressBook()`, causing the modified state of the address book after the `delete 5` command executes to be saved in the `addressBookStateList`, and the `currentStatePointer` is shifted to the newly inserted address book state.
+Step 2. The `DoneTaskCommandParser#parse` method will check the validity of the argument given for a `DoneTaskCommand`. If it
+is valid, it will create a new `DoneTaskCommand` instance by calling the constructor of `DoneTaskCommand`.
-
+Step 3. The `DoneTaskCommand#execute` method is then called by the `LogicManager`. The task with the same `Index` is retrieved and
+a copy of the task is created with the same attribute values. However, the `TaskStatus` value is updated to `completed`. The task copy
+with the updated status replaces the old task in the `Model`.
-Step 3. The user executes `add n/David …` to add a new person. The `add` command also calls `Model#commitAddressBook()`, causing another modified address book state to be saved into the `addressBookStateList`.
+Step 4. Once the execution is completed, the message `MESSAGE_DONE_TASK_SUCCESS` is used to return a new Command Result
+with the attached message.
-
+
-
:information_source: **Note:** If a command fails its execution, it will not call `Model#commitAddressBook()`, so the address book state will not be saved into the `addressBookStateList`.
+Below is the sequence diagram to show how the mark task as completed mechanism works:
+
+
:information_source: **Note:** The lifeline for `DoneTaskCommandParser` and `DoneTaskCommand` should end at the destroy marker (X)
+but due to the limitation of PlantUML, the lifeline reaches the end of the sequence diagram.
+
-Step 4. The user now decides that adding the person was a mistake, and decides to undo that action by executing the `undo` command. The `undo` command will call `Model#undoAddressBook()`, which will shift the `currentStatePointer` once to the left, pointing it to the previous address book state, and restores the address book to that state.
+The following activity diagram summarizes what happens when a user executes the mark task as completed command:
-
+
-
:information_source: **Note:** If the `currentStatePointer` is at index 0, pointing to the initial AddressBook state, then there are no previous AddressBook states to restore. The `undo` command uses `Model#canUndoAddressBook()` to check if this is the case. If so, it will return an error to the user rather
-than attempting to perform the undo.
+
-
+
+
+### Find Tasks with deadline before a selected date feature
+
+The implementation of the finding of tasks with deadlines before a selected date is facilitated by the `FindTasksBeforeCommand`
+class, which extends from the Command abstract class.
+
+It is also facilitated by the following Parser Class:
+* `FindTasksBeforeCommandParser`
+
+The above mentioned Parser class inherits the `#parse` method from the Parser interface.
-The following sequence diagram shows how the undo operation works:
+* `FindTasksBeforeParser#parse` - checks if the deadline passed to the current FindTasksBeforeCommand is in the correct format and is valid, then creates a FindTasksBeforeCommand instance if it is.
-
-
:information_source: **Note:** The lifeline for `UndoCommand` should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
+Subsequently, the created `FindTasksBeforeCommand` object contains an `#execute` method which is responsible for
+updating the task list to contain the tasks with deadlines before the selected date. This is achieved by calling on `Model#updateFilteredTaskList`
+with the DeadlineBeforeDatePredicate which updates the task list with tasks that match the given predicate.
+Below is the usage scenario and how the finding of tasks due before a selected date mechanism behaves.
+
+Assumptions:
+1. User has already launched the app
+2. HEY MATEz application has existing tasks with their corresponding deadlines
+
+Step 1. User executes the `findBefore 2021-04-04` command to show the tasks in the task list of HEY MATEz with deadlines before 2021-04-04. A
+`FindTasksBeforeCommandParser` is created and it calls `FindTasksBeforeParser#parse` on the arguments
+
+Step 2. The `FindTasksBeforeCommandParser#parse` method will check the validity of the deadline argument for a `FindTasksBeforeCommand`. If it is
+valid, it will create a new `FindTasksBeforeCommand` instance by calling the constructor with the DeadlineBeforeDatePredicate.
+
+Step 3. The `FindTasksBeforeCommand#execute` method is then called by the `LogicManager`. The tasks with deadline before 2021-04-04 are selected by the
+DeadlineBeforeDatePredicate.
+
+Step 4. Once the execution is completed, the message `MESSAGE_TASKS_LISTED_OVERVIEW,` is used to return a new Command Result
+with the attached message.
+
+Below is the sequence diagram:
+
+
+
+
:information_source: **Note:** The lifeline for `FindTasksBeforeCommandParser` and `FindTasksBeforeCommand` should end at the destroy marker (X)
+but due to the limitation of PlantUML, the lifeline reaches the end of the sequence diagram.
+
+
+The following activity diagram summarizes what happens when a user executes the find tasks with deadline before a selected date command:
+
+
+
+
+
+### Delete a Task feature
+
+The implementation of the delete a task feature is facilitated by the DeleteTaskCommand, which extends from the Command abstract class.
+
+It is also enabled by the following Parser class:
+* `DeleteTaskCommandParser`
+
+The above mentioned Parser class inherits the `#parse method` from the Parser interface.
-The `redo` command does the opposite — it calls `Model#redoAddressBook()`, which shifts the `currentStatePointer` once to the right, pointing to the previously undone state, and restores the address book to that state.
+* `DeleteTaskCommandParser#parse` - checks if the arguments passed to the current DeleteTaskCommand is valid.
+ If the arguments are valid, it creates a DeleteTaskCommand instance.
-
:information_source: **Note:** If the `currentStatePointer` is at index `addressBookStateList.size() - 1`, pointing to the latest address book state, then there are no undone AddressBook states to restore. The `redo` command uses `Model#canRedoAddressBook()` to check if this is the case. If so, it will return an error to the user rather than attempting to perform the redo.
+Subsequently, the created `DeleteTaskCommand` object contains an `#execute` method which
+is responsible for deleting the given Task with respect to the index. This is achieved by calling on
+`Model#deleteTask` with the task to be deleted where it will be removed from the list of tasks.
+Below is the usage scenario of how delete task mechanism behaves.
+
+Assumptions:
+1. User has already launched the app
+2. HEY MATEz application has an existing task
+
+Step 1. User executes the `deleteTask 1` command to delete the task at the 1st index in the task list of HEY MATEz.
+A `DeleteTaskCommandParser` object is created and calls the `DeleteTaskCommandParser#parse` on the arguments.
+
+Step 2. The `DeleteTaskCommandParser#parse` method then checks on the validity of the arguments given for a `DeleteTaskCommand`.
+If it is valid, it will create a new `DeleteTaskCommand` instance by calling the constructor along with the task `Index`.
+
+Step 3. The `DeleteTaskCommand#execute` method is then called by `Logic Manager`. The task with the same `Index` is retrieved
+and deleted from the task list when `Model#deleteTask` is called.
+
+Step 4. Once the execution is completed, the message `MESSAGE_DELETE_TASK_SUCCESS` is used to return a
+new Command Result with the attached message.
+
+Below is the sequence diagram:
+
+
+
+
:information_source: **Note:** The lifeline for `DeleteTaskCommandParser` and `DeleteTaskCommand` should end at the destroy marker (X)
+but due to the limitation of PlantUML, the lifeline reaches the end of the sequence diagram.
+
-Step 5. The user then decides to execute the command `list`. Commands that do not modify the address book, such as `list`, will usually not call `Model#commitAddressBook()`, `Model#undoAddressBook()` or `Model#redoAddressBook()`. Thus, the `addressBookStateList` remains unchanged.
+The following activity diagram below summarizes what happens when a user executes the `deleteTask` command:
-
+
-Step 6. The user executes `clear`, which calls `Model#commitAddressBook()`. Since the `currentStatePointer` is not pointing at the end of the `addressBookStateList`, all address book states after the `currentStatePointer` will be purged. Reason: It no longer makes sense to redo the `add n/David …` command. This is the behavior that most modern desktop applications follow.
+
-
+### Clear all assignees of a Task feature
-The following activity diagram summarizes what happens when a user executes a new command:
+The implementation of the clear all assignees of a task feature is facilitated by the `ClearAssigneeCommand`
+class which extends from the Command abstract class.
-
+It is also facilitated by the following Parser Classes:
+* `ClearAssigneesCommandParser`
-#### Design consideration:
+The above mentioned Parser class inherits the `#parse` method from the Parser interface.
-##### Aspect: How undo & redo executes
+* `ClearAssigneesCommandParser#parse` - checks if the arguments passed to the current ClearAssigneeCommand is valid.
+ If the arguments are valid, it creates a ClearAssigneeCommand instance.
-* **Alternative 1 (current choice):** Saves the entire address book.
- * Pros: Easy to implement.
- * Cons: May have performance issues in terms of memory usage.
+Subsequently, the created `ClearAssigneeCommand` object contains an `#execute` method which is responsible for
+clearing all assignees of the given task, with respect to its index. This is achieved by creating a new
+`Task` object with the same fields and values as before but with the assignees field set to be a new empty HashSet.
-* **Alternative 2:** Individual command knows how to undo/redo by
- itself.
- * Pros: Will use less memory (e.g. for `delete`, just save the person being deleted).
- * Cons: We must ensure that the implementation of each individual command are correct.
+Below is the usage scenario of how the clear all assignees of a task mechanism behaves.
-_{more aspects and alternatives to be added}_
+Assumptions:
+1. User has already launched the app
+2. HEY MATEz application has an existing task with **assignees**
-### \[Proposed\] Data archiving
+Step 1. User executes the `clearAssignees 1` command to clear all the assignees of the task at index 1 in the task list of
+HEY MATEz. A ` ClearAssigneesCommandParser` object is created and it calls `ClearAssigneesCommandParser#parse` on the arguments.
+
+Step 2. The `ClearAssigneesCommandParser#parse` method will check on the validity of the arguments given for a `ClearAssigneesCommand`.
+If it is valid, it will create a new `ClearAssigneesCommand` instance by calling the constructor of `ClearAssigneesCommand`.
+
+Step 3. The `ClearAssigneesCommand#execute` method is then called by the `LogicManager`. The task with the same `Index`
+is retrieved and a copy of the task is created with the same attribute values but with the assignees field updated to be a
+new empty HashSet. The copy of the task with the updated assignees field replaces the old task in the `Model`.
+
+Step 4. Once the execution is completed, the message `MESSAGE_CLEARED_ASSIGNEES_SUCCESS` is used to return a new Command Result
+with the attached message.
+
+The following sequence diagram shows how the clear all assignees of a task mechanism works:
+
+
+
+
:information_source: **Note:** The lifeline for `ClearAssigneesCommandParser` and `ClearAssigneesCommand` should end at the destroy marker (X)
+but due to the limitation of PlantUML, the lifeline reaches the end of the sequence diagram.
+
+
-_{Explain here how the data archiving feature will be implemented}_
+The following activity diagram summarizes what happens when a user executes the `clearAssignees` command:
+
--------------------------------------------------------------------------------------------------------------------
+
+
## **Documentation, logging, testing, configuration, dev-ops**
* [Documentation guide](Documentation.md)
@@ -230,19 +358,20 @@ _{Explain here how the data archiving feature will be implemented}_
--------------------------------------------------------------------------------------------------------------------
+
+
## **Appendix: Requirements**
### Product scope
**Target user profile**:
-* has a need to manage a significant number of contacts
-* prefer desktop apps over other types
-* can type fast
-* prefers typing to mouse interactions
-* is reasonably comfortable using CLI apps
+* CCA / Club head who is managing many members and tasks
+* Needs an efficient and organised method to assign tasks to these members
+* Prefer desktop apps over other types
+* Prefers typing to mouse interactions
-**Value proposition**: manage contacts faster than a typical mouse/GUI driven app
+**Value proposition**: Manage the members and tasks of a club quickly and efficiently.
### User stories
@@ -251,106 +380,651 @@ Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unli
| Priority | As a … | I want to … | So that I can… |
| -------- | ------------------------------------------ | ------------------------------ | ---------------------------------------------------------------------- |
-| `* * *` | new user | see usage instructions | refer to instructions when I forget how to use the App |
-| `* * *` | user | add a new person | |
-| `* * *` | user | delete a person | remove entries that I no longer need |
-| `* * *` | user | find a person by name | locate details of persons without having to go through the entire list |
-| `* *` | user | hide private contact details | minimize chance of someone else seeing them by accident |
-| `*` | user with many persons in the address book | sort persons by name | locate a person easily |
-
-*{More to be added}*
+| `* * *` | user starting to use the app| be able to add in the contacts of my CCA members | have a better overview of the members in my CCA and access their information easily|
+| `* * *` | forgetful CCA leader | be able to view who have been added into my contacts | retrieve their information and add the remaining members too |
+| `* * *` | CCA leader with many tasks to be done | be able to add the tasks of our CCA | better manage the tasks |
+| `* * *` | CCA leader whose tasks' details need to be updated constantly | be able to edit the details of the tasks accordingly | keep the tasks' details updated |
+| `* * *` | CCA leader with tasks that are no longer relevant | be able to delete tasks that are either completed or unnecessary | keep the list organized and clear |
+| `* * *` | CCA leader with projects and tasks piling up | be able to view a list of tasks that is to be completed by members of the CCA | be updated with what needs to be done |
+| `* * *` | CCA leader who has members leaving the CCA | be able to remove details of the members from the application | better manage my members |
+| `* * *` | CCA leader whose members’ details have changed | be able to edit the details of the members in the application | keep my contacts up-to-date |
+| `* * *` | CCA leader with many deadlines to meet | be able to set deadlines for specific tasks | keep track of the tasks' deadlines |
+| `* * *` | CCA leader with tasks to be distributed | be able to assign tasks to students | track the distribution of tasks to certain members|
+| `* * ` | CCA leader with tasks that are being completed every other week | be able to mark tasks as ‘completed’ | track which tasks are completed |
+| `* * ` | CCA leader | be able to change the assignee of a task | easily update the member assigned to the task |
+| `* * ` | CCA leader | be able to assign a priority to a task | take note of the tasks that are more important and need to be completed first |
+| `* * ` | CCA leader who has many tasks to supervise | be able to search for tasks of a certain priority | better manage tasks of different priorities |
+| `* * ` | CCA leader whose members have different roles | be able to assign roles to the members | be aware of the members' roles |
+| `* * ` | CCA leader whose members have different roles | be able to edit the roles to the members | update the members' roles when there is a change in their roles |
+| `* ` | CCA leader who is very forgetful | be notified if I have accidentally added duplicate tasks | prevent repeated tasks from being added |
+| `* ` | CCA leader who has a lot of tasks to manage | search for tasks which contain a particular word | find tasks more efficiently and quickly |
+| `* ` | forgetful CCA leader who has forgotten which tasks have not been assigned | be able to get a list of tasks that have not been assigned | distribute tasks more efficiently |
+| `* ` | CCA leader | be able to get a list of tasks that have not been completed | check on the progress of the tasks |
+| `* ` | CCA leader | be able to get a list of tasks with deadlines that are prior to a certain date | make sure I do not miss those deadlines |
+| `* ` | CCA leader | be able to get a list of tasks assigned to a particular member | check on the workload of a particular member |
+
+
### Use cases
-(For all use cases below, the **System** is the `AddressBook` and the **Actor** is the `user`, unless specified otherwise)
+(For all use cases below, the **System** is the `HEY MATEz` and the **Actor** is the `user`, unless specified otherwise)
-**Use case: Delete a person**
+:pencil2: **Use case: UC01 - Add a Member**
**MSS**
-1. User requests to list persons
-2. AddressBook shows a list of persons
-3. User requests to delete a specific person in the list
-4. AddressBook deletes the person
+1. User requests to add a member
+2. HEY MATEz adds the member to the list of members
- Use case ends.
+Use case ends.
**Extensions**
-* 2a. The list is empty.
+* 1a. Member already exists (Matching Name) in the list
+ * 1a1. HEY MATEz shows an error message
+* 1b. The name, phone number, email or role provided for the member is invalid
+ * 1b1. HEY MATEz shows an error message
+
+Use case ends.
- Use case ends.
+:pencil2: **Use case: UC02 - View Members**
-* 3a. The given index is invalid.
+**MSS**
- * 3a1. AddressBook shows an error message.
+1. User requests to view the members
+2. HEY MATEz lists the members and their details
+
+Use case ends.
- Use case resumes at step 2.
+:pencil2: **Use case: UC03 - Delete a Member**
-*{More to be added}*
+**MSS**
-### Non-Functional Requirements
+1. User requests to delete a member by specifying the member's name
+2. HEY MATEz searches for the member's name in the currently displayed list of members
+3. HEY MATEz deletes the specified member from the members list
+
+Use case ends.
-1. Should work on any _mainstream OS_ as long as it has Java `11` or above installed.
-2. Should be able to hold up to 1000 persons without a noticeable sluggishness in performance for typical usage.
-3. A user with above average typing speed for regular English text (i.e. not code, not system admin commands) should be able to accomplish most of the tasks faster using commands than using the mouse.
+**Extensions**
-*{More to be added}*
+* 2a. Member name provided by user does not exist in the currently displayed list of members
+ * 2a1. HEY MATEz shows an error message
+
+Use case ends.
-### Glossary
+:pencil2: **Use case: UC04 -Edit Member's details**
+
+**MSS**
+
+1. User requests to edit the details of a member by specifying the member's name
+2. HEY MATEz searches for the member's name in the currently displayed list of members
+3. HEY MATEz edits the corresponding member with the new details
+
+Use case ends.
+
+**Extensions**
+
+* 1a. The new name, phone number, email or role provided for the member is invalid
+ * 1a1. HEY MATEz shows an error message
+* 2a. Member name provided by user does not exist in the currently displayed list of members
+ * 2a1. HEY MATEz shows an error message
+
+Use case ends.
+:pencil2: **Use case: UC05 - Find Members with keywords**
+
+**MSS**
+
+1. User requests to find members using the keywords specified
+2. HEY MATEz searches through each member's details (i.e. name, phone number, email, role)
+3. HEY MATEz lists members whose details matches any of the keywords
+
+Use case ends.
+
+:pencil2: **Use case: UC06 - Add a Task**
+
+**MSS**
+
+1. User requests to add a task
+2. HEY MATEz adds the task to the task list
+
+Use case ends.
+
+**Extensions**
+
+* 1a. Task already exists (Matching Title) in the list
+ * 1a1. HEY MATEz shows an error message
+* 1b. The title, description, deadline, status or priority provided for the task is invalid
+ * 1b1. HEY MATEz shows an error message
+
+Use case ends.
+
+:pencil2: **Use case: UC07 - View Tasks**
+
+**MSS**
+
+1. User requests to view the list of tasks
+2. HEY MATEz lists all the tasks along with its details
+
+Use case ends.
+
+:pencil2: **Use case: UC08 - Delete a Task**
+
+**MSS**
+
+Similar to deleting a member (UC03) but user specifies task index instead of name
+
+**Extensions**
+
+* 2a. Task index does not exist in the current displayed list of tasks
+ * 2a1. HEY MATEz shows an error message
+
+Use case ends.
+
+:pencil2: **Use case: UC09 - Edit a Task**
+
+**MSS**
+
+Similar to editing a member (UC04) except that the user specifies task index instead of name
+
+**Extensions**
+
+* 1a. The new title, description, deadline, status or priority provided for the task is invalid
+ * 1a1. HEY MATEz shows an error message
+* 2a. Task index does not exist in the currently displayed list of tasks
+ * 2a1. HEY MATEz shows an error message
+
+Use case ends.
+
+:pencil2: **Use case: UC10 - Find Tasks with keywords**
+
+**MSS**
+
+Similar to finding members with keywords (UC05) except that HEY MATEz
+lists tasks with its title or description matching any of the keywords specified
+
+:pencil2: **Use case: Find tasks with deadline before a specified date**
+
+**MSS**
+
+1. User requests to find tasks which deadlines before their specified date
+2. HEY MATEz searches through tasks' deadline
+3. HEY MATEz lists tasks with deadlines before the specified date
+
+Use case ends.
+
+Extensions
+* 1a. The deadline provided by user is not in the correct format or is invalid
+ * 1a1. HEY MATEz shows an error message
+
+Use case ends.
+
+:pencil2: **Use case: UC11 - Find Tasks with Priority**
+
+**MSS**
+
+1. User requests to find tasks of a certain priority
+2. HEY MATEz searches through each task
+3. HEY MATEz lists tasks with a matching priority
+
+Use case ends.
+
+**Extensions**
+* 1a. The priority input provided by the user is not a valid priority
+ * 1a1. HEY MATEz shows an error message
+
+Use case ends.
+
+:pencil2: **Use case: UC12 - Mark a Task as Completed**
+
+**MSS**
+
+1. User requests to mark a task as completed using the task's index
+2. HEY MATEz searches for the task index
+3. HEY MATEz changes the status of the task in the list to **completed**
+
+Use case ends.
+
+**Extensions**
+* 2a. Task index does not exist in the currently displayed list of tasks
+ * 2a1. HEY MATEz shows an error message
+* 3a. The task has a status of **completed**
+ * 3a1. HEY MATEz shows an error message
+
+Use case ends.
+
+:pencil2: **Use case: UC13 - Mark a Task as Uncompleted**
+
+**MSS**
+
+1. User requests to mark a task as uncompleted using the task's index
+2. HEY MATEz searches for the task index
+3. HEY MATEz changes the status of the task in the list to **uncompleted**
+
+Use case ends.
+
+**Extensions**
+* 2a. Task index does not exist in the currently displayed list of tasks
+ * 2a1. HEY MATEz shows an error message
+* 3a. The task has a status of **uncompleted**
+ * 3a1. HEY MATEz shows an error message
+
+Use case ends.
+
+:pencil2: **Use case: UC14 - Clear all Members Assigned to a Task**
+
+**MSS**
+
+1. User requests to clear all assignees from a task using the task's index
+2. HEY MATEz searches for the task index
+3. HEY MATEz clears all members assigned to the task
+
+**Extensions**
+* 2a. Task index does not exist in the currently displayed list of tasks
+ * 2a1. HEY MATEz shows an error message
+* 2b. No members assigned to the task
+ * 2b1. HEY MATEz shows a 'nothing to clear' message
+
+Use case ends.
+
+:pencil2: **Use case: UC15 - View Uncompleted Tasks**
+
+**MSS**
+
+1. User requests to view the list of uncompleted tasks
+2. HEY MATEz lists the uncompleted tasks
+
+Use case ends.
+
+:pencil2: **Use case: UC16 - View Unassigned Tasks**
+
+**MSS**
+
+Similar to viewing a list of uncompleted tasks (UC15) but a list of unassigned task is displayed instead.
+
+:pencil2: **Use case: UC17 - Find all Tasks assigned to a particular Member**
+
+**MSS**
+
+1. User requests to find tasks assigned to a member using the member's name
+2. HEY MATEz searches through each task and checks the assignees of the task
+3. HEY MATEz lists tasks which has the specified name as an assignee
+
+Use case ends.
+
+
+### Non-Functional Requirements
+1. Should work on any _mainstream OS_ as long as it has Java `11` or above installed.
+2. Should be able to hold up to 100 members and tasks without a noticeable sluggishness in performance for typical usage.
+3. Application data should be saved locally.
+4. Application should be able to run normally without an internet connection.
+
+### Glossary
* **Mainstream OS**: Windows, Linux, Unix, OS-X
-* **Private contact detail**: A contact detail that is not meant to be shared with others
+* **CCA**: Co-curricular activities
+* **CCA / Club head**: A person who has a position in a Club / CCA and is required to manage the tasks and members within the club
--------------------------------------------------------------------------------------------------------------------
+
+
## **Appendix: Instructions for manual testing**
Given below are instructions to test the app manually.
:information_source: **Note:** These instructions only provide a starting point for testers to work on;
testers are expected to do more *exploratory* testing.
-
-### Launch and shutdown
+### Launch and Shutdown
1. Initial launch
- 1. Download the jar file and copy into an empty folder
+ 1. Download the jar file and copy into an empty folder.
- 1. Double-click the jar file Expected: Shows the GUI with a set of sample contacts. The window size may not be optimum.
+ 2. Double-click the jar file Expected: Shows the GUI with a set of sample contacts and tasks. The window size may not be optimum.
-1. Saving window preferences
+2. Saving window preferences
1. Resize the window to an optimum size. Move the window to a different location. Close the window.
- 1. Re-launch the app by double-clicking the jar file.
+ 2. Re-launch the app by double-clicking the jar file.
Expected: The most recent window size and location is retained.
-1. _{ more test cases … }_
+3. Shutting down
+ 1. Launch the help window using the `help` command.
+
+ 2. Close the app using the `exit` command.
+ Expected: Both the help and main window should be closed.
+
+### Adding a member
+
+1. Adding a member
+
+ 1. Prerequisites: No duplicate members exist.
+
+ 1. Test case: `addMember Alice p/12345678 e/Alice@gmail.com`
+ Expected: Member is successfully added, with the details of the member displayed in the status bar.
+
+ 1. Test case: `addMember Bryan p/45678910 e/Bryan@gmail.com r/President`
+ Expected: Member is successfully added, with the details of the member displayed in the status bar.
+
+ 1. Test case: `addMember Charlie p/12345678 e/Charlie.com `
+ Expected: No member is added since the email given is invalid. Error details shown in the status bar.
+
+ 1. Test case: `addMember Charlie p/12 e/Charlie@gmail.com`
+ Expected: No member is added since the phone number given is invalid. Error details shown in the status bar.
+
+ 1. Other incorrect commands to try: `addMember`, `addMember Alice`, `addMember Alice p/12345678`, `addMember Alice e/Alice@gmail.com`
+ Expected: Similar to previous test case.
+
+
+
+### Viewing Members
+
+1. Viewing all members
+
+ 1. Test case: `viewMembers`
+ Expected: Lists all members within HEY MATEz.
+
+### Deleting a Member
+
+1. Deleting a member
+
+ 1. Prerequisites: List all members using the `viewMembers` command. A member with the name of 'Rachel' exists in the members list
+ while no members with the name of 'John' exists.
+
+ 2. Test case: `deleteMember Rachel`
+ Expected: Member with the name 'Rachel' is deleted from the members list. Details of the deleted member is shown in the
+ status message.
+
+ 3. Test case: `deleteMember John`
+ Expected: No member is deleted. Error details is shown in the status message.
+
+ 4. Other incorrect delete commands to try: `delete`, `deleteMember x` (where x is a name which does not exist in the members list)
+ Expected: Similar to previous test case.
+
+### Editing a Member
+
+1. Editing a member
+
+ 1. Prerequisites: List all members using the `viewMembers` command. Members with the name of 'Alice' and 'Timothy' exists
+ in the members list while no members with the name of 'Dylan' exists.
+
+ 2. Test case: `editMember Alice n/Allyson`
+ Expected: Member with the name 'Alice' is edited to have a new name of 'Allyson'. Details of the edited member is shown
+ in the status message.
+
+ 3. Test case: `editMember Alice n/Timothy`
+ Expected: No member is edited since a member with the name 'Timothy' already exists. Error details is shown in the status
+ message.
+
+ 4. Test case: `editMember Alice n/Alice Tan p/98887777 e/aliceTan@gmail.com`
+ Expected: Member with the name 'Alice' is edited to have the new details as specified. Details of the edited member is shown
+ in the status message.
+
+ 5. Test case: `editMember Dylan`
+ Expected: No member is edited. Error details is shown in the status message.
+
+ 6. Other incorrect delete commands to try: `edit`, `editMember x` (where x is a name which does not exist in the members list)
+ Expected: Similar to previous test case.
+
+
+
+### Finding Members by keywords
+
+1. Finding members whose details (i.e. name, phone number, email, role) contain any of the specified keywords
+
+ 1. Prerequisites: HEY MATEz contains 2 members with the following details:
+ * 1. Name: Alice, Phone Number: 98887777, Email: alice@gmail.com, Role: Secretary
+ * 2. Name: Bryan, Phone Number: 89996666, Email: bryan@gmail.com, Role: Secretary
+
+ 2. Test case: `findMembers Alice`
+ Expected: Alice is listed in the members list.
+
+ 3. Test case: `findMembers alice@gmail.com 89996666`
+ Expected: Both Alice and Bryan are listed in the members list.
+
+ 4. Test case: `findMembers secretary`
+ Expected: Both Alice and Bryan are listed in the members list since keywords specified are case-insensitive.
+
+ 5. Test case: `findMembers President`
+ Expected: Both Alice and Bryan are not listed since none of their details matches the specified keyword.
+
+ 6. Test case: `findMembers`
+ Expected: Invalid command format, error details is shown in the status message.
+
+
+### Add a Task
+
+1. Adding a task
+
+ 1. Prerequisites: No duplicate tasks with same title exists.
+
+ 1. Test case: `addTask Book Rooms d/Book seminar rooms for exco meeting b/2021-05-04`
+ Expected: Task is successfully added, with the details of the task displayed in the status bar.
+
+ 1. Test case: `addTask Book Rooms d/Book seminar rooms for exco meeting b/2021-05-04 p/high`
+ Expected: Task is successfully added, with the details of the task displayed in the status bar.
+
+ 1. Test case: `addTask Book Rooms d/Book seminar rooms for exco meeting b/2021-05-04 s/completed p/high`
+ Expected: Task is successfully added, with the details of the task displayed in the status bar.
+
+ 1. Test case: `addTask CCA roster d/Plan roster for May b/2021/04/21`
+ Expected: No task is added since the deadline format is incorrect. Error details shown in the status bar.
+
+ 1. Test case: `addTask CCA roster d/Plan roster for May b/2021-13-21`
+ Expected: No task is added since the deadline provided is invalid. Error details shown in the status bar.
+
+ 1. Test case: `addTask CCA roster d/Plan roster for May b/2021-05-21 p/HIGH`
+ Expected: No task is added since the priority provided is invalid. Error details shown in the status bar.
+
+ 1. Other incorrect commands to try: `addTask`, `addTask Roster`, `addTask Roster d/Plan roster`
+ Expected: No task is added since compulsory fields are not provided. Error details shown in the status bar.
+
+
+
+### Editing a Task
+
+1. Editing a task
+
+ 1. Prerequisites: List all tasks using the `viewTasks` command. Tasks with the title of 'Meeting' and 'Draft roster' exist
+ in the task list with the index of 1 and 2 while no task with the title of 'Plan meeting' exists.
+
+ 2. Test case: `editTask 1 n/Plan meeting`
+ Expected: Task with index 1 in the task list is edited to have a new title of 'Plan meeting'. Details of the edited task is shown
+ in the status message.
+
+ 3. Test case: `editTask 1 n/Plan meeting d/Plan board meeting b/2021-04-04`
+ Expected: Task with index 1 in the task list is edited to have the new details as specified. Details of the edited task is shown
+ in the status message.
+
+ 4. Test case: `editTask 1 n/Draft roster`
+ Expected: No task is edited since a task with the same title already exists. Error details is shown in the status message.
+
+ 5. Test case: `editTask 1`
+ Expected: No Task is edited since none of the optional fields are provided. Error details is shown in the status message.
+
+ 6. Other incorrect delete commands to try: `edit`, `editTask 0`, `editTask -1`
+ Expected: Similar to previous test case.
+
+
+### Viewing Tasks
+
+1. Viewing all tasks
+
+ 1. Test case: `viewTasks`
+ Expected: Lists all tasks within the HEY MATEz.
+
+### Deleting a Task
+
+1. Deleting a Task
+
+ 1. Prerequisites: List all tasks using the `viewTasks` command. 3 different tasks in the list.
+ All 3 tasks have different indexes(1, 2, 3).
+
+ 2. Test case: `deleteTask 1`
+ Expected: Task with the index `1` is deleted from the list. Details of the deleted task shown in the status message.
+
+ 3. Test case: `deleteTask 4`
+ Expected: No task is deleted. Error details shown in the status message.
+
+ 4. Other incorrect commands to try: `deleteTask`, `deleteTask abc`, `deleteTask -1`
+ Expected: Similar to previous test case.
+
+
+
+### Marking a Task as completed
+
+1. Marking a task as completed
+
+ 1. Prerequisites: List all tasks with the `viewTasks` command. There exists a task at index 1 whose task status
+ is uncompleted. There also exists a task at index 2 whose task status is completed.
+
+ 1. Test case: `done 1`
+ Expected: Status of task at index 1 is updated to completed. Successful task status update message is shown in the status bar.
+
+ 1. Test case: `done 0`
+ Expected: No task marked as completed. Error details is shown in the status bar.
+
+ 1. Test case: `done 2`
+ Expected: Since the task already has a status of completed, an error message is shown in the status bar.
+
+ 1. Other incorrect commands to try: `done`, `done -1`
+ Expected: Similar to previous test case.
+
+### Marking a Task as uncompleted
+
+1. Marking a task as uncompleted
+
+ 1. Prerequisites: List all tasks with the `viewTasks` command. There exists a task at index 1 whose task status
+ is completed. There also exists a task at index 2 whose task status is uncompleted.
+
+ 1. Test case: `undo 1`
+ Expected: Status of task at index 1 is updated to uncompleted. Successful task status update message is shown in the status bar.
+
+ 1. Test case: `undo 0`
+ Expected: No task marked as uncompleted. Error details is shown in the status bar.
+
+ 1. Test case: `undo 2`
+ Expected: Since the task already has a status of uncompleted, an error message is shown in the status bar.
+
+ 1. Other incorrect commands to try: `undo`, `undo -1`
+ Expected: Similar to previous test case.
+
+### Viewing a list of unassigned Tasks
+
+1. Viewing all unassigned tasks
+
+ 1. Test case: `viewUnassignedTasks`
+ Expected: Lists all tasks that are unassigned within the HEY MATEz.
+
+### Viewing a list of uncompleted Tasks
+
+1. Viewing all uncompleted tasks
+
+ 1. Test case: `viewUncompletedTasks`
+ Expected: Lists all tasks that are uncompleted within the HEY MATEz.
+
+
+
+### Finding Tasks by priority
+
+1. Finding tasks by priority
+
+ 1. Test case: `findPriority high`
+ Expected: Lists all tasks within HEY MATEz whose priority is **high**.
+
+ 1. Test case: `findPriority medium`
+ Expected: Lists all tasks within HEY MATEz whose priority is **medium**.
+
+ 1. Test case: `findPriority low`
+ Expected: Lists all tasks within HEY MATEz whose priority is **low**.
+
+ 1. Test case: `findPriority unassigned`
+ Expected: Lists all tasks within HEY MATEz whose priority is **unassigned**.
+
+ 1. Test case: `findPriority unsure`
+ Expected: Error message displayed in the status bar.
+
+ 1. Test case: `findPriority HIGH`
+ Expected: Error message displayed in the status bar.
+
+ 1. Other incorrect commands to try: `findPriority, findPriority LOW`, `findPriority MeDIum`, etc.
+ Expected: Similar to previous test case.
+
+### Finding Tasks due before a certain date
+
+1. Finding all tasks with deadlines before the provided date
+
+ 1. Test case: `findBefore 2021-05-04`
+ Expected: Lists all tasks within HEY MATEz whose deadline is before 2021-05-04.
+
+ 1. Test case: `findBefore 2021/05/04`
+ Expected: Error occurred since the deadline provided is not in the correct format. Error details is shown in the status bar.
+
+ 1. Test case: `findBefore 2021-13-12`
+ Expected: Error occurred since the deadline provided is invalid. Error details is shown in the status bar.
+
+ 1. Other incorrect commands to try: `findBefore`, `findBefore 2021-03/21`, etc.
+ Expected: Similar to previous test case.
+
+
+### Finding Tasks assigned to a member
+
+1. Finding all tasks assigned to a member
+
+ 1. Prerequisites: There exists a member with the name of Alice and a task assigned to Alice within HEY MATEz.
+
+ 1. Test case: `findTasksFor Alice`
+ Expected: Lists the task which is assigned to Alice.
+
+ 1. Test case: `findTasksFor`
+ Expected: Error message displayed in the status bar.
+
+
+
+### Finding Tasks by keywords
-### Deleting a person
+1. Finding all tasks whose title or description contain any of the specified keywords
-1. Deleting a person while all persons are being shown
+ 1. Prerequisites: HEY MATEz contains 2 tasks, T1 and T2, with the following details:
+ * T1. Title: Community outreach proposal, Description: Write detailed proposal for MINDS outreach
+ * T2. Title: Proposal for EXCO event, Description: Plan and discuss timeline
+
+ 2. Test case: `findTasks Community`
+ Expected: Task T1 is listed in the task list.
- 1. Prerequisites: List all persons using the `list` command. Multiple persons in the list.
+ 3. Test case: `findTasks Community EXCO`
+ Expected: Both task T1 and T2 are listed in the task list.
- 1. Test case: `delete 1`
- Expected: First contact is deleted from the list. Details of the deleted contact shown in the status message. Timestamp in the status bar is updated.
+ 4. Test case: `findTasks proposal`
+ Expected: Both task T1 and T2 are listed in the task list since keywords specified are case-insensitive.
- 1. Test case: `delete 0`
- Expected: No person is deleted. Error details shown in the status message. Status bar remains the same.
+ 5. Test case: `findTasks Pitch`
+ Expected: Both task T1 and T2 are not listed since their title and description does not contain the specified keyword.
+
+ 6. Test case: `findTasks`
+ Expected: Invalid command format, error details is shown in the status message.
- 1. Other incorrect delete commands to try: `delete`, `delete x`, `...` (where x is larger than the list size)
- Expected: Similar to previous.
+### Clearing all assignees of a Task
-1. _{ more test cases … }_
+1. Clearing all Assignees of a Task
-### Saving data
+ 1. Prerequisites: List all tasks using the `viewTasks` command. There exists a task at index 1 with at least 1 member
+ assigned to it.
-1. Dealing with missing/corrupted data files
+ 2. Test case: `clearAssignees 1`
+ Expected: All members assigned to the task at index 1 is cleared. Details of the task being cleared is shown
+ in the status message.
+
+ 3. Test case: `clearAssignees 0`
+ Expected: No task is being cleared. Error details is shown in the status bar.
- 1. _{explain how to simulate a missing/corrupted file, and the expected behavior}_
+ 1. Other incorrect commands to try: `clearAssignees`, `clearAssignees -1`
+ Expected: Similar to previous test case.
-1. _{ more test cases … }_
+
+
+
diff --git a/docs/Gemfile.lock b/docs/Gemfile.lock
index 4caff5b900c..36e9e768be4 100644
--- a/docs/Gemfile.lock
+++ b/docs/Gemfile.lock
@@ -49,7 +49,7 @@ GEM
jekyll-relative-links (= 0.6.1)
jekyll-remote-theme (= 0.4.1)
jekyll-sass-converter (= 1.5.2)
- jekyll-seo-tag (= 2.6.1)
+ jekyll-seo-assignee (= 2.6.1)
jekyll-sitemap (= 1.4.0)
jekyll-swiss (= 1.0.0)
jekyll-theme-architect (= 0.1.1)
@@ -138,51 +138,51 @@ GEM
rubyzip (>= 1.3.0)
jekyll-sass-converter (1.5.2)
sass (~> 3.4)
- jekyll-seo-tag (2.6.1)
+ jekyll-seo-assignee (2.6.1)
jekyll (>= 3.3, < 5.0)
jekyll-sitemap (1.4.0)
jekyll (>= 3.7, < 5.0)
jekyll-swiss (1.0.0)
jekyll-theme-architect (0.1.1)
jekyll (~> 3.5)
- jekyll-seo-tag (~> 2.0)
+ jekyll-seo-assignee (~> 2.0)
jekyll-theme-cayman (0.1.1)
jekyll (~> 3.5)
- jekyll-seo-tag (~> 2.0)
+ jekyll-seo-assignee (~> 2.0)
jekyll-theme-dinky (0.1.1)
jekyll (~> 3.5)
- jekyll-seo-tag (~> 2.0)
+ jekyll-seo-assignee (~> 2.0)
jekyll-theme-hacker (0.1.1)
jekyll (~> 3.5)
- jekyll-seo-tag (~> 2.0)
+ jekyll-seo-assignee (~> 2.0)
jekyll-theme-leap-day (0.1.1)
jekyll (~> 3.5)
- jekyll-seo-tag (~> 2.0)
+ jekyll-seo-assignee (~> 2.0)
jekyll-theme-merlot (0.1.1)
jekyll (~> 3.5)
- jekyll-seo-tag (~> 2.0)
+ jekyll-seo-assignee (~> 2.0)
jekyll-theme-midnight (0.1.1)
jekyll (~> 3.5)
- jekyll-seo-tag (~> 2.0)
+ jekyll-seo-assignee (~> 2.0)
jekyll-theme-minimal (0.1.1)
jekyll (~> 3.5)
- jekyll-seo-tag (~> 2.0)
+ jekyll-seo-assignee (~> 2.0)
jekyll-theme-modernist (0.1.1)
jekyll (~> 3.5)
- jekyll-seo-tag (~> 2.0)
+ jekyll-seo-assignee (~> 2.0)
jekyll-theme-primer (0.5.4)
jekyll (> 3.5, < 5.0)
jekyll-github-metadata (~> 2.9)
- jekyll-seo-tag (~> 2.0)
+ jekyll-seo-assignee (~> 2.0)
jekyll-theme-slate (0.1.1)
jekyll (~> 3.5)
- jekyll-seo-tag (~> 2.0)
+ jekyll-seo-assignee (~> 2.0)
jekyll-theme-tactile (0.1.1)
jekyll (~> 3.5)
- jekyll-seo-tag (~> 2.0)
+ jekyll-seo-assignee (~> 2.0)
jekyll-theme-time-machine (0.1.1)
jekyll (~> 3.5)
- jekyll-seo-tag (~> 2.0)
+ jekyll-seo-assignee (~> 2.0)
jekyll-titles-from-headings (0.5.3)
jekyll (>= 3.3, < 5.0)
jekyll-watch (2.2.1)
@@ -201,7 +201,7 @@ GEM
minima (2.5.1)
jekyll (>= 3.5, < 5.0)
jekyll-feed (~> 0.9)
- jekyll-seo-tag (~> 2.1)
+ jekyll-seo-assignee (~> 2.1)
minitest (5.14.1)
multipart-post (2.1.1)
nokogiri (1.10.9-x64-mingw32)
diff --git a/docs/SettingUp.md b/docs/SettingUp.md
index 77667c6d581..d8ded1ab0d9 100644
--- a/docs/SettingUp.md
+++ b/docs/SettingUp.md
@@ -23,7 +23,7 @@ If you plan to use Intellij IDEA (highly recommended):
1. **Import the project as a Gradle project**: Follow the guide [_[se-edu/guides] IDEA: Importing a Gradle project_](https://se-education.org/guides/tutorials/intellijImportGradleProject.html) to import the project into IDEA.
:exclamation: Note: Importing a Gradle project is slightly different from importing a normal Java project.
1. **Verify the setup**:
- 1. Run the `seedu.address.Main` and try a few commands.
+ 1. Run the `seedu.heymatez.Main` and try a few commands.
1. [Run the tests](Testing.md) to ensure they all pass.
--------------------------------------------------------------------------------------------------------------------
@@ -45,11 +45,4 @@ If you plan to use Intellij IDEA (highly recommended):
1. **Learn the design**
- When you are ready to start coding, we recommend that you get some sense of the overall design by reading about [AddressBook’s architecture](DeveloperGuide.md#architecture).
-
-1. **Do the tutorials**
- These tutorials will help you get acquainted with the codebase.
-
- * [Tracing code](tutorials/TracingCode.md)
- * [Removing fields](tutorials/RemovingFields.md)
- * [Adding a new command](tutorials/AddRemark.md)
+ When you are ready to start coding, we recommend that you get some sense of the overall design by reading about [HEY MATEz’s architecture](DeveloperGuide.md#architecture).
diff --git a/docs/Testing.md b/docs/Testing.md
index 8a99e82438a..f5db7e19d92 100644
--- a/docs/Testing.md
+++ b/docs/Testing.md
@@ -29,8 +29,8 @@ There are two ways to run tests.
This project has three types of tests:
1. *Unit tests* targeting the lowest level methods/classes.
- e.g. `seedu.address.commons.StringUtilTest`
+ e.g. `seedu.heymatez.commons.StringUtilTest`
1. *Integration tests* that are checking the integration of multiple code units (those code units are assumed to be working).
- e.g. `seedu.address.storage.StorageManagerTest`
+ e.g. `seedu.heymatez.storage.StorageManagerTest`
1. Hybrids of unit and integration tests. These test are checking multiple code units as well as how the are connected together.
- e.g. `seedu.address.logic.LogicManagerTest`
+ e.g. `seedu.heymatez.logic.LogicManagerTest`
diff --git a/docs/UserGuide.md b/docs/UserGuide.md
index 3716f3ca8a4..0ec2dab9600 100644
--- a/docs/UserGuide.md
+++ b/docs/UserGuide.md
@@ -2,35 +2,87 @@
layout: page
title: User Guide
---
-
-AddressBook Level 3 (AB3) is a **desktop app for managing contacts, optimized for use via a Command Line Interface** (CLI) while still having the benefits of a Graphical User Interface (GUI). If you can type fast, AB3 can get your contact management tasks done faster than traditional GUI apps.
-
-* Table of Contents
-{:toc}
+## Table of Contents
+
+* [Welcome to HEY MATEz](#introduction)
+* [About this User Guide](#about)
+* [Quick Start](#quick-start)
+* [Features](#features)
+ + [General Features](#general)
+ - [1. View Help: `help`](#help)
+ - [2. Clear all data in HEY MATEz: `clear`](#clear)
+ - [3. Exit Program: `exit`](#exit)
+ + [Member Related Features](#members)
+ - [1. Add Member: `addMember`](#addMember)
+ - [2. Delete Member: `deleteMember`](#deleteMember)
+ - [3. View Members: `viewMembers`](#viewMembers)
+ - [4. Edit Member: `editMember`](#editMember)
+ - [5. Find Members by Keywords: `findMembers`](#findMember)
+ + [Task Related Features](#tasks)
+ - [1. Add Task: `addTask`](#addTask)
+ - [2. Delete Task: `deleteTask`](#deleteTask)
+ - [3. View Tasks: `viewTasks`](#viewTasks)
+ - [4. Edit Task: `editTask`](#editTask)
+ - [5. Mark Task as Completed: `done`](#doneTask)
+ - [6. Mark Task as Uncompleted: `undo`](#undoTask)
+ - [7. Find Tasks by Keywords: `findTasks`](#findTask)
+ - [8. Find Tasks by Deadline: `findBefore`](#findBefore)
+ - [9. Find Tasks by Priority: `findPriority`](#findPriority)
+ - [10. Clear all Members Assigned to a Task: `clearAssignees`](#clearAssignees)
+ - [11. View List of Unassigned Tasks: `viewUnassignedTasks`](#findUnassigned)
+ - [12. View List of Uncompleted Tasks: `viewUncompletedTasks`](#findUncompleted)
+ - [13. Find Tasks Assigned to a Single Member: `findTasksFor`](#findTasksFor)
+* [Data Storage](#dataStorage)
+ + [Saving the data](#savingData)
+ + [Editing the data file](#editData)
+* [FAQ](#faq)
+* [Command Summary](#summary)
+
+
+## Welcome to HEY MATEz
+As a CCA / club leader, are you struggling to **keep track of the ever-changing members** of your club as well as **manage
+the mountain of tasks** that have to be completed? Or perhaps it is a challenge to **keep track of the increasing
+number of deadlines** and be able to **assign tasks to members efficiently**.
+
+HEY MATEz is a desktop application to get rid of your woes by allowing you to **track
+members** and **tasks** within the club **efficiently and easily**! It is
+a Command Line Interface (CLI) application which handles user requests that are typed into the input box as commands.
+
+With HEY MATEz, managing and distributing tasks will never be a headache again! :smile:
+
+
+## About this User Guide
+This user guide includes information on the **features** of HEY MATEz as well as a walkthrough on how to use them. The features
+are further divided into 3 sections which include the **General features**, **Member related features** as well as the **Task related features**.
+Member related features allow you to manage a list of members and find members. On the other hand, Task related features allow you
+to manage tasks which can be identified by their unique list indexes.
--------------------------------------------------------------------------------------------------------------------
-## Quick start
+
-1. Ensure you have Java `11` or above installed in your Computer.
+
+## Quick Start
-1. Download the latest `addressbook.jar` from [here](https://github.com/se-edu/addressbook-level3/releases).
+1. Ensure you have Java `11` or above installed in your Computer. You can install Java `11` [here](https://www.oracle.com/sg/java/technologies/javase-jdk11-downloads.html).
-1. Copy the file to the folder you want to use as the _home folder_ for your AddressBook.
+1. Download the latest `heymatez.jar` from [here](https://github.com/AY2021S2-CS2103T-W14-3/tp/releases).
-1. Double-click the file to start the app. The GUI similar to the below should appear in a few seconds. Note how the app contains some sample data.
+1. Copy the file to the folder you want to use as the _home folder_ for your HEY MATEz.
+
+1. Double-click the file to start the app. The GUI similar to the picture below should appear in a few seconds. Note how the app contains some sample tasks and members.

1. Type the command in the command box and press Enter to execute it. e.g. typing **`help`** and pressing Enter will open the help window.
Some example commands you can try:
- * **`list`** : Lists all contacts.
-
- * **`add`**`n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01` : Adds a contact named `John Doe` to the Address Book.
+ * **`viewMembers`** : Lists all members.
- * **`delete`**`3` : Deletes the 3rd contact shown in the current list.
+ * **`addTask`**`Proposal d/Write out detailed proposal plan for CCA timeline b/2021-04-22` : Adds a task named `Proposal` to HEY MATEz.
+
+ * **`deleteTask`**`3` : Deletes the 3rd task shown in the list.
- * **`clear`** : Deletes all contacts.
+ * **`clear`** : Deletes all tasks and members.
* **`exit`** : Exits the app.
@@ -38,155 +90,450 @@ AddressBook Level 3 (AB3) is a **desktop app for managing contacts, optimized fo
--------------------------------------------------------------------------------------------------------------------
+
+
+
## Features
-**:information_source: Notes about the command format:**
+**:bookmark_tabs: Notes about the command format:**
* Words in `UPPER_CASE` are the parameters to be supplied by the user.
- e.g. in `add n/NAME`, `NAME` is a parameter which can be used as `add n/John Doe`.
+ e.g. in `addMember NAME`, `NAME` is a parameter which can be used as `addMember John Lim`.
* Items in square brackets are optional.
- e.g `n/NAME [t/TAG]` can be used as `n/John Doe t/friend` or as `n/John Doe`.
-
+ e.g `d/DESCRIPTION [p/PRIORITY]` can be used as `d/Meeting p/high` or as `d/Meeting`.
+
* Items with `…` after them can be used multiple times including zero times.
- e.g. `[t/TAG]…` can be used as ` ` (i.e. 0 times), `t/friend`, `t/friend t/family` etc.
-
-* Parameters can be in any order.
- e.g. if the command specifies `n/NAME p/PHONE_NUMBER`, `p/PHONE_NUMBER n/NAME` is also acceptable.
-
-* If a parameter is expected only once in the command but you specified it multiple times, only the last occurrence of the parameter will be taken.
- e.g. if you specify `p/12341234 p/56785678`, only `p/56785678` will be taken.
-
-* Extraneous parameters for commands that do not take in parameters (such as `help`, `list`, `exit` and `clear`) will be ignored.
+ e.g. `[a/ASSIGNEE]…` can be used as ` ` (i.e. 0 times), `a/Duncan`, `a/Daniel a/Benson` etc.
+
+* Parameters with prefixes can be in any order.
+ e.g. if the command specifies `e/EMAIL p/PHONE_NUMBER`, `p/PHONE_NUMBER e/EMAIL` is also acceptable.
+
+* If a parameter with a prefix is expected only once in the command, but you specified it multiple times, only the last occurrence of the parameter will be taken.
+ e.g. if you specify `p/98562545 p/88885555`, only `p/88885555` will be taken.
+
+* Extraneous parameters for commands that do not take in parameters (such as `help`, `exit` and `clear`) will be ignored.
e.g. if the command specifies `help 123`, it will be interpreted as `help`.
+* For features which use the INDEX field, the INDEX you specify must be a valid number in the currently displayed list of tasks.
+
+* The NAME, NEW_NAME, ASSIGNEE and NEW_ASSIGNEE fields are case-sensitive and format-sensitive across all features which uses it.
+ e.g. "Alex Yeoh" and "Alex Yeoh" are not the same.
+
-### Viewing help : `help`
+
-Shows a message explaning how to access the help page.
+
+## General Features
-
+
+### 1. View Help: `help`
+Shows a message explaining how to access the help page.
Format: `help`
+Example: `help`
-### Adding a person: `add`
+
+### 2. Clear all data in application: `clear`
+Clears all entries from the application.
-Adds a person to the address book.
+Format: `clear`
-Format: `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]…`
+Example: `clear`
-
:bulb: **Tip:**
-A person can have any number of tags (including 0)
+
+### 3. Exiting the programme: `exit`
+Exits the program.
+
+Format: `exit`
+
+Example: `exit`
+
+--------------------------------------------------------------------------------------------------------------------
+
+
+
+
+## Member Related Features
+
+
+### 1. Add Member: `addMember`
+
+With new members joining the club, you can add a new member along with his/her contact number and email to the members list.
+
+Format: `addMember NAME p/PHONE_NUMBER e/EMAIL [r/ROLE]`
+
+* NAME and ROLE fields can take on any values with alphanumeric characters.
+* PHONE_NUMBER field has to have a minimum length of 3 digits and maximum length of 15 digits.
+* If ROLE field is not specified, person will be assigned a default role of `Member`.
+
+Assumptions:
+* Every member in the CCA has a different name. An error will be prompted when you add a member with the same name but with
+a different phone number, email or role.
+
+Examples:
+* `addMember Dylan p/64529356 e/dylan@gmail.com`
+* `addMember Dylan p/64529356 e/dylan@gmail.com r/President`
+
+
+
+Using the following addMember command, `addMember Erynne p/96398428 e/erynne@gmail.com`, the addMember command
+can be used as shown below:
+
+1. Key in the addMember command and its parameters
+
+
+
+2. Press enter and view the result of the addMember command
+
+
+
+
+
+
+
+### 2. Delete Member: `deleteMember`
+
+As members leave the club, you can delete a member along with all of his/her contact details from the members list.
+
+Format: `deleteMember NAME`
+
+
:exclamation: **Caution:**
+The NAME specified must appear in the currently displayed list of members in order for it to be valid.
Examples:
-* `add n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01`
-* `add n/Betsy Crowe t/friend e/betsycrowe@example.com a/Newgate Prison p/1234567 t/criminal`
+* `deleteMember Rachel`
+
+
+### 3. View Members: `viewMembers`
-### Listing all persons : `list`
+Displays the list of members that you have added into HEY MATEz.
-Shows a list of all persons in the address book.
+Format: `viewMembers `
-Format: `list`
+Examples:
+* `viewMembers`
-### Editing a person : `edit`
+
-Edits an existing person in the address book.
+
+### 4. Edit Member: `editMember`
+Club members may change their emails or phone numbers after a while. This feature allows you to edit the details of an
+existing member in the application with the name you specify.
-Format: `edit INDEX [n/NAME] [p/PHONE] [e/EMAIL] [a/ADDRESS] [t/TAG]…`
+Format: `editMember NAME [n/NEW_NAME] [p/NEW_PHONE_NUMBER] [e/NEW_EMAIL] [r/NEW_ROLE]`
-* Edits the person at the specified `INDEX`. The index refers to the index number shown in the displayed person list. The index **must be a positive integer** 1, 2, 3, …
+* Edits the member with the specified NAME.
+* At least one of the optional fields must be provided.
+* NEW_NAME and NEW_ROLE fields can take on any values with alphanumeric characters.
+* Existing values will be updated to the input values.
+
+
:exclamation: **Caution:**
+The NAME specified must appear in the currently displayed list of members in order for it to be valid.
+
+
+Examples:
+* `editMember Alice n/Alice Tan`
+* `editMember Alice n/Alice Tan p/98154155 e/aliceTan@gmail.com`
+* `editMember Alice n/Alice Tan p/98154155 e/aliceTan@gmail.com r/Events head`
+
+
+### 5. Find Members by Keywords: `findMembers`
+
+With so many members in the club, you may want to find a particular member's details quickly.
+This feature allows you to find all members whose NAME, PHONE_NUMBER, EMAIL or ROLE contain
+any of the specified keywords.
+
+Format: `findMembers KEYWORD [MORE_KEYWORDS]...`
+
+* KEYWORD must match an entire word in order for the particular member to be found.
+ * e.g. `Rachel` will not match with `Rach`.
+* The search using KEYWORD is case-insensitive
+ * e.g. `Rachel` will match with `rachel`.
+
+Examples:
+* `findMembers Rachel`
+* `findMembers Rachel 98562154 john@gmail.com`
+* `findMembers Rachel 98562154 john@gmail.com President`
+
+--------------------------------------------------------------------------------------------------------------------
+
+
+
+
+## Task Related Features
+
+
+### 1. Add Task: `addTask`
+
+With new tasks that needs to be completed within the club every week, you can add a task, with its description and
+deadline to the task list.
+
+Format: `addTask TITLE d/DESCRIPTION b/DEADLINE [s/STATUS] [p/PRIORITY] [a/ASSIGNEE]...`
+
+* If you did not specify a value for STATUS, the Task will be assigned a default status value of **uncompleted**.
+* STATUS field can only take on the values **completed** or **uncompleted** (Values are case-sensitive).
+* If you did not specify a value for PRIORITY, the Task will be assigned a default priority of **unassigned**.
+* PRIORITY field can only take on the values **high**, **medium**, **low** or **unassigned** (Values are case-sensitive).
+
+
:bulb: **Tip:**
+A task can have any number of assignees (including 0). To add multiple assignees, simply use multiple assignee prefixes.
+
+
+Examples:
+* `addTask CCA Timeline d/Plan semester's timeline b/2021-04-04 s/completed p/high a/Rachel`
+* `addTask CCA Timeline d/Plan semester's timeline b/2021-04-04 a/Rachel a/James`
+
+
+
+Using the following addTask command, `addTask CCA Timeline d/Plan semester's timeline b/2021-04-04 a/Alex Yeoh a/Bernice Yu`, the
+addTask command can be used as shown below:
+
+1. Key in the addTask command and its parameters
+
+
+
+2. Press enter and view the result of the addTask command
+
+
+
+
+
+
+
+### 2. Delete Task: `deleteTask`
+If a task is no longer relevant, you can delete the task along with its details from the list with the task index you specified.
+
+Format: `deleteTask INDEX`
+
+Examples:
+* `deleteTask 1`
+
+
+### 3. View Tasks: `viewTasks`
+Displays the list of tasks that you have added into HEY MATEz.
+
+Format: `viewTasks`
+
+Examples:
+* `viewTasks`
+
+
+
+
+### 4. Edit Task: `editTask`
+With ever-changing task requirements, you can edit an existing task at the task index specified with the new details
+you key in.
+
+Format: `editTask INDEX [n/NEW_TITLE] [d/NEW_DESCRIPTION] [b/NEW_DEADLINE] [s/NEW_STATUS] [p/NEW_PRIORITY] [a/NEW_ASSIGNEE]...`
+
+* Edits the task at the specified INDEX.
* At least one of the optional fields must be provided.
* Existing values will be updated to the input values.
-* When editing tags, the existing tags of the person will be removed i.e adding of tags is not cumulative.
-* You can remove all the person’s tags by typing `t/` without
- specifying any tags after it.
+* When editing assignees, the existing assignees of the task will be removed i.e adding of assignees is not cumulative.
-Examples:
-* `edit 1 p/91234567 e/johndoe@example.com` Edits the phone number and email address of the 1st person to be `91234567` and `johndoe@example.com` respectively.
-* `edit 2 n/Betsy Crower t/` Edits the name of the 2nd person to be `Betsy Crower` and clears all existing tags.
+
:bulb: **Tip:**
+Any number of assignees can be specified here (including 0). To have multiple assignees, simply use multiple assignee prefixes.
+
-### Locating persons by name: `find`
+Examples:
+* `editTask 1 n/Plan meeting d/Plan board meeting`
+* `editTask 1 n/Plan meeting d/Plan board meeting b/2021-04-04`
+* `editTask 1 n/Plan meeting d/Plan board meeting b/2021-04-04 a/Samuel a/Christian`
-Finds persons whose names contain any of the given keywords.
+
+
+
+### 5. Mark Task as Completed: `done`
-Format: `find KEYWORD [MORE_KEYWORDS]`
+Upon completion of a task, you can change the status of a task with the task index you specify from **uncompleted**
+to **completed**.
-* The search is case-insensitive. e.g `hans` will match `Hans`
-* The order of the keywords does not matter. e.g. `Hans Bo` will match `Bo Hans`
-* Only the name is searched.
-* Only full words will be matched e.g. `Han` will not match `Hans`
-* Persons matching at least one keyword will be returned (i.e. `OR` search).
- e.g. `Hans Bo` will return `Hans Gruber`, `Bo Yang`
+Format: `done INDEX`
-Examples:
-* `find John` returns `john` and `John Doe`
-* `find alex david` returns `Alex Yeoh`, `David Li`
- 
+Examples:
+* `done 1`
+
+
+### 6. Mark Task as Uncompleted: `undo`
+
+Changes the status of a task with the task index you specify from **completed** to **uncompleted**.
+
+Format: `undo INDEX`
+
+Examples:
+* `undo 1`
+
+
+### 7. Find Tasks by Keywords: `findTasks`
+
+With so many tasks, you may want to find tasks quickly using some keywords.
+This feature allows you to find all tasks which contain any of the specified keywords in its TITLE or DESCRIPTION.
+
+Format: `findTasks KEYWORD [MORE_KEYWORDS]...`
+
+* KEYWORD must match an entire word in order for the particular task to be found.
+ * e.g. `Meeting` will not match with `Meet`.
+* The search using KEYWORD is case-insensitive.
+ * e.g. `Meeting` will match with `meeting`.
+
+Examples:
+* `findTasks Meeting`
+* `findTasks Meeting Proposal Draft`
+
+
+
+
+### 8. Find Tasks due before certain date: `findBefore`
+
+With so many tasks that need to be completed at different times, you may want to find tasks which are due before a certain date.
+This feature allows you to find all tasks with deadlines before the date you have specified.
+
+Format: `findBefore DATE`
+
+
:bulb: **Tip:**
+The DATE specified must follow the format `YYYY-MM-DD`and be a valid date in the calendar.
+
+
+Examples:
+* `findBefore 2021-05-04`
+
+
+### 9. Find Tasks by Priority: `findPriority`
-### Deleting a person : `delete`
+With so many tasks that are of different priority, this feature allows you to find all tasks containing the priority that
+you have specified.
-Deletes the specified person from the address book.
+* The valid input values for `findPriority` are **high**, **medium**, **low** and **unassigned**.
-Format: `delete INDEX`
+
:bulb: **Tip:**
+The input values are case-sensitive.
+
-* Deletes the person at the specified `INDEX`.
-* The index refers to the index number shown in the displayed person list.
-* The index **must be a positive integer** 1, 2, 3, …
+Format: `findPriority PRIORITY`
Examples:
-* `list` followed by `delete 2` deletes the 2nd person in the address book.
-* `find Betsy` followed by `delete 1` deletes the 1st person in the results of the `find` command.
+* `findPriority high`
-### Clearing all entries : `clear`
+
+### 10. Clear all Members Assigned to a Task: `clearAssignees`
-Clears all entries from the address book.
+If you have accidentally assigned a task to the wrong group of members,
+you can easily clear all members assigned to that task with the task index you specified.
-Format: `clear`
+Format: `clearAssignees INDEX`
-### Exiting the program : `exit`
+Examples:
+* `clearAssignees 2`
-Exits the program.
+
-Format: `exit`
+
+### 11. View List of Unassigned Tasks: `viewUnassignedTasks`
+
+In order to efficiently distribute tasks to members, you may want to view tasks which have yet to be assigned to any member.
+This feature allows you to view the list of unassigned tasks.
+
+Format: `viewUnassignedTasks`
+
+Examples:
+* `viewUnassignedTasks`
+
+
+### 12. View List of Uncompleted Tasks: `viewUncompletedTasks`
+
+In order to be on track with work, you may want to view tasks which have not been completed.
+This feature allows you to view the list of uncompleted tasks.
+
+Format: `viewUncompletedTasks`
+Examples:
+* `viewUncompletedTasks`
+
+
+### 13. Find Tasks Assigned to a Single Member: `findTasksFor`
+
+In order to manage members efficiently, you may want to track the tasks that are assigned to each member.
+This feature allows you to find all tasks assigned to a single member.
+
+Format: `findTasksFor NAME`
+
+* The search using NAME is case-sensitive.
+ * e.g. `David Li` will only match with `David Li`.
+* NAME must match an entire member's name exactly in order for the tasks assigned to that member to be found.
+ * e.g. `David` will not match with `David Li`
+
+
:bulb: **Tip:**
+A NAME that does not belong to a member inside HEY MATEz will return no tasks listed.
+
+
+Examples:
+* `findTasksFor Alex Yeoh`
+* `findTasksFor Bernice Teo Hui Min`
+
+--------------------------------------------------------------------------------------------------------------------
+
+
+
+
+## Data Storage
+
+
### Saving the data
-AddressBook data are saved in the hard disk automatically after any command that changes the data. There is no need to save manually.
+HEY MATEz data is saved in the hard disk automatically after any command that changes the data. There is no need to save manually.
+
### Editing the data file
-AddressBook data are saved as a JSON file `[JAR file location]/data/addressbook.json`. Advanced users are welcome to update data directly by editing that data file.
+HEY MATEz data is saved as a JSON file `[JAR file location]/data/heymatez.json`. Advanced users are welcome to update data directly by editing that data file.
:exclamation: **Caution:**
-If your changes to the data file makes its format invalid, AddressBook will discard all data and start with an empty data file at the next run.
+If your changes to the data file makes its format invalid, HEY MATEz will discard all data and start with an empty data file at the next run.
-### Archiving data files `[coming in v2.0]`
-
-_Details coming soon ..._
-
--------------------------------------------------------------------------------------------------------------------
+
## FAQ
**Q**: How do I transfer my data to another Computer?
-**A**: Install the app in the other computer and overwrite the empty data file it creates with the file that contains the data of your previous AddressBook home folder.
+**A**: Install the app in the other computer and overwrite the empty data file it creates with the file that contains the data of your previous HEY MATEz home folder.
--------------------------------------------------------------------------------------------------------------------
+
+
+
## Command summary
Action | Format, Examples
--------|------------------
-**Add** | `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]…` e.g., `add n/James Ho p/22224444 e/jamesho@example.com a/123, Clementi Rd, 1234665 t/friend t/colleague`
-**Clear** | `clear`
-**Delete** | `delete INDEX` e.g., `delete 3`
-**Edit** | `edit INDEX [n/NAME] [p/PHONE_NUMBER] [e/EMAIL] [a/ADDRESS] [t/TAG]…` e.g.,`edit 2 n/James Lee e/jameslee@example.com`
-**Find** | `find KEYWORD [MORE_KEYWORDS]` e.g., `find James Jake`
-**List** | `list`
-**Help** | `help`
+**View Help** | `help`
+**Clear Data** | `clear`
+**Exit Program** | `exit`
+||
+**Add Member** | `addMember NAME p/PHONE_NUMBER e/EMAIL [r/ROLE]` e.g., `addMember Dylan p/64529356 e/dylan@gmail.com r/Member`
+**Delete Member** | `deleteMember NAME` e.g., `deleteMember Rachel`
+**View Members** | `viewMembers` e.g., `viewMembers`
+**Edit Member** | `editMember NAME [n/NEW_NAME] [p/NEW_PHONE_NUMBER] [e/NEW_EMAIL] [r/NEW_ROLE]` e.g.,`editMember Alice e/newAlice@gmail.com r/Events head`
+**Find Members by Keywords** | `find KEYWORD [MORE_KEYWORDS]...` e.g., `findMembers Rachel 98562154 john@gmail.com`
+||
+**Add Task** | `addTask TITLE d/DESCRIPTION b/DEADLINE [s/STATUS] [p/PRIORITY] [a/ASSIGNEE]...` e.g.,`addTask CCA Timeline d/Plan semester's timeline b/2021-04-04 s/completed p/high a/Rachel`
+**Delete Task** | `deleteTask INDEX` e.g., `deleteTask 1`
+**View Tasks** | `viewTasks` e.g., `viewTasks`
+**Edit Task** | `editTask INDEX [n/NEW_TITLE] [d/NEW_DESCRIPTION] [b/NEW_DEADLINE] [s/NEW_STATUS] [p/NEW_PRIORITY] [a/NEW_ASSIGNEE]...` e.g.,`editTask 1 n/Plan meeting d/Plan board meeting b/2021-04-04`
+**Mark Task as Completed** | `done INDEX` e.g., `done 1`
+**Mark Task as Uncompleted** | `undo INDEX` e.g., `undo 1`
+**Find Tasks by Keywords** | `findTasks KEYWORD [MORE_KEYWORDS]...` e.g., `findTasks Meeting Proposal Draft`
+**Find Tasks by Deadline** | `findBefore DATE` e.g., `findBefore 2021-04-05`
+**Find Tasks by Priority** | `findPriority PRIORITY` e.g., `findPriority high`
+**Clear all Members Assigned to a Task** | `clearAssignees INDEX` e.g., `clearAssignees 2`
+**View Unassigned Tasks** | `viewUnassignedTasks` e.g., `viewUnassignedTasks`
+**View Uncompleted Tasks** | `viewUncompletedTasks` e.g., `viewUncompletedTasks`
+**Find Member's Tasks** | `findTasksFor NAME` e.g., `findTasksFor Alice Tay`
diff --git a/docs/_config.yml b/docs/_config.yml
index 6bd245d8f4e..4b8d0fb3278 100644
--- a/docs/_config.yml
+++ b/docs/_config.yml
@@ -1,4 +1,4 @@
-title: "AB-3"
+title: "HEY MATEz"
theme: minima
header_pages:
@@ -8,7 +8,7 @@ header_pages:
markdown: kramdown
-repository: "se-edu/addressbook-level3"
+repository: "AY2021S2-CS2103T-W14-3/tp"
github_icon: "images/github-icon.png"
plugins:
diff --git a/docs/_sass/minima/_base.scss b/docs/_sass/minima/_base.scss
index 0d3f6e80ced..9f267b503b9 100644
--- a/docs/_sass/minima/_base.scss
+++ b/docs/_sass/minima/_base.scss
@@ -288,7 +288,7 @@ table {
text-align: center;
}
.site-header:before {
- content: "AB-3";
+ content: "HEY MATEz";
font-size: 32px;
}
}
diff --git a/docs/diagrams/ArchitectureSequenceDiagram.puml b/docs/diagrams/ArchitectureSequenceDiagram.puml
index ef81d18c337..ef7e56a0c8a 100644
--- a/docs/diagrams/ArchitectureSequenceDiagram.puml
+++ b/docs/diagrams/ArchitectureSequenceDiagram.puml
@@ -7,19 +7,19 @@ Participant ":Logic" as logic LOGIC_COLOR
Participant ":Model" as model MODEL_COLOR
Participant ":Storage" as storage STORAGE_COLOR
-user -[USER_COLOR]> ui : "delete 1"
+user -[USER_COLOR]> ui : "deleteTask 1"
activate ui UI_COLOR
-ui -[UI_COLOR]> logic : execute("delete 1")
+ui -[UI_COLOR]> logic : execute("deleteTask 1")
activate logic LOGIC_COLOR
-logic -[LOGIC_COLOR]> model : deletePerson(p)
+logic -[LOGIC_COLOR]> model : deleteTask(task)
activate model MODEL_COLOR
model -[MODEL_COLOR]-> logic
deactivate model
-logic -[LOGIC_COLOR]> storage : saveAddressBook(addressBook)
+logic -[LOGIC_COLOR]> storage : saveHeyMatez(heyMatez)
activate storage STORAGE_COLOR
storage -[STORAGE_COLOR]> storage : Save to file
diff --git a/docs/diagrams/BetterModelClassDiagram.puml b/docs/diagrams/BetterModelClassDiagram.puml
index 29076104af3..047270c6749 100644
--- a/docs/diagrams/BetterModelClassDiagram.puml
+++ b/docs/diagrams/BetterModelClassDiagram.puml
@@ -4,18 +4,24 @@ skinparam arrowThickness 1.1
skinparam arrowColor MODEL_COLOR
skinparam classBackgroundColor MODEL_COLOR
-AddressBook *-right-> "1" UniquePersonList
-AddressBook *-right-> "1" UniqueTagList
-UniqueTagList -[hidden]down- UniquePersonList
-UniqueTagList -[hidden]down- UniquePersonList
+HeyMatez *-right-> "1" UniquePersonList
+HeyMatez *-right-> "1" TaskList
+TaskList -[hidden]down- UniquePersonList
+TaskList -[hidden]down- UniquePersonList
-UniqueTagList *-right-> "*" Tag
-UniquePersonList o-right-> Person
+TaskList *-right-> "*" Task
+UniquePersonList o-down-> Person
-Person -up-> "*" Tag
-Person *--> Name
-Person *--> Phone
-Person *--> Email
-Person *--> Address
+
+Person *--> "1"Name
+Person *--> "1"Phone
+Person *--> "1"Email
+Person *--> "1"Role
+
+Task *--> "1" Title
+Task *--> "1" Description
+Task *--> "1" Deadline
+Task *--> Priority
+Task *--> "1" TaskStatus
@enduml
diff --git a/docs/diagrams/ClearAssigneeSequenceDiagram.puml b/docs/diagrams/ClearAssigneeSequenceDiagram.puml
new file mode 100644
index 00000000000..b8b9b040434
--- /dev/null
+++ b/docs/diagrams/ClearAssigneeSequenceDiagram.puml
@@ -0,0 +1,78 @@
+@startuml
+!include style.puml
+
+box Logic LOGIC_COLOR_T1
+participant ":LogicManager" as LogicManager LOGIC_COLOR
+participant ":HeyMatezParser" as HeyMatezParser LOGIC_COLOR
+participant ":ClearAssigneesCommandParser" as ClearAssigneesCommandParser LOGIC_COLOR
+participant "c:ClearAssigneesCommand" as ClearAssigneesCommand LOGIC_COLOR
+participant ":CommandResult" as CommandResult LOGIC_COLOR
+end box
+
+box Model MODEL_COLOR_T1
+participant ":Model" as Model MODEL_COLOR
+end box
+
+[-> LogicManager : execute("clearAssignees 1")
+activate LogicManager
+
+LogicManager -> HeyMatezParser : parseCommand("clearAssignees 1")
+activate HeyMatezParser
+
+create ClearAssigneesCommandParser
+HeyMatezParser -> ClearAssigneesCommandParser
+activate ClearAssigneesCommandParser
+
+ClearAssigneesCommandParser --> HeyMatezParser
+deactivate ClearAssigneesCommandParser
+
+HeyMatezParser -> ClearAssigneesCommandParser : parse("1")
+activate ClearAssigneesCommandParser
+
+create ClearAssigneesCommand
+ClearAssigneesCommandParser -> ClearAssigneesCommand
+activate ClearAssigneesCommand
+
+ClearAssigneesCommand --> ClearAssigneesCommandParser : c
+deactivate ClearAssigneesCommand
+
+ClearAssigneesCommandParser --> HeyMatezParser : c
+deactivate ClearAssigneesCommandParser
+'Hidden arrow to position the destroy marker below the end of the activation bar.
+ClearAssigneesCommandParser -[hidden]-> HeyMatezParser
+destroy ClearAssigneesCommandParser
+
+HeyMatezParser --> LogicManager : c
+deactivate HeyMatezParser
+
+LogicManager -> ClearAssigneesCommand : execute()
+activate ClearAssigneesCommand
+
+ClearAssigneesCommand -> ClearAssigneesCommand : createModifiedTask(taskToClear)
+activate ClearAssigneesCommand
+
+ClearAssigneesCommand --> ClearAssigneesCommand : clearedTask
+deactivate ClearAssigneesCommand
+
+ClearAssigneesCommand -> Model : setTask(taskToClear, clearedTask)
+activate Model
+
+Model --> ClearAssigneesCommand
+deactivate Model
+
+create CommandResult
+ClearAssigneesCommand -> CommandResult
+activate CommandResult
+
+CommandResult --> ClearAssigneesCommand
+deactivate CommandResult
+
+ClearAssigneesCommand --> LogicManager
+deactivate ClearAssigneesCommand
+
+ClearAssigneesCommand -[hidden]-> LogicManager
+destroy ClearAssigneesCommand
+
+[<--LogicManager
+deactivate LogicManager
+@enduml
diff --git a/docs/diagrams/ClearAssigneesActivityDiagram.puml b/docs/diagrams/ClearAssigneesActivityDiagram.puml
new file mode 100644
index 00000000000..7468c23969f
--- /dev/null
+++ b/docs/diagrams/ClearAssigneesActivityDiagram.puml
@@ -0,0 +1,26 @@
+@startuml
+start
+:User executes clearAssignees command;
+
+if () then ([valid command input])
+ :Fetch task with the given
+ index from the task list;
+ if () then ([target task has 1 or more assignees])
+ : Create a copy of the fetched
+ task with its assignees
+ updated to be cleared;
+ : Update task list with the
+ updated copy of the
+ fetched task;
+ : Output cleared assignees
+ success message;
+ else([else])
+ : Output no assignees
+ to clear message;
+ endif
+else ([else])
+ : Output invalid command
+ input error message;
+endif
+stop
+@enduml
diff --git a/docs/diagrams/DeleteSequenceDiagram.puml b/docs/diagrams/DeleteSequenceDiagram.puml
deleted file mode 100644
index 1dc2311b245..00000000000
--- a/docs/diagrams/DeleteSequenceDiagram.puml
+++ /dev/null
@@ -1,69 +0,0 @@
-@startuml
-!include style.puml
-
-box Logic LOGIC_COLOR_T1
-participant ":LogicManager" as LogicManager LOGIC_COLOR
-participant ":AddressBookParser" as AddressBookParser LOGIC_COLOR
-participant ":DeleteCommandParser" as DeleteCommandParser LOGIC_COLOR
-participant "d:DeleteCommand" as DeleteCommand LOGIC_COLOR
-participant ":CommandResult" as CommandResult LOGIC_COLOR
-end box
-
-box Model MODEL_COLOR_T1
-participant ":Model" as Model MODEL_COLOR
-end box
-
-[-> LogicManager : execute("delete 1")
-activate LogicManager
-
-LogicManager -> AddressBookParser : parseCommand("delete 1")
-activate AddressBookParser
-
-create DeleteCommandParser
-AddressBookParser -> DeleteCommandParser
-activate DeleteCommandParser
-
-DeleteCommandParser --> AddressBookParser
-deactivate DeleteCommandParser
-
-AddressBookParser -> DeleteCommandParser : parse("1")
-activate DeleteCommandParser
-
-create DeleteCommand
-DeleteCommandParser -> DeleteCommand
-activate DeleteCommand
-
-DeleteCommand --> DeleteCommandParser : d
-deactivate DeleteCommand
-
-DeleteCommandParser --> AddressBookParser : d
-deactivate DeleteCommandParser
-'Hidden arrow to position the destroy marker below the end of the activation bar.
-DeleteCommandParser -[hidden]-> AddressBookParser
-destroy DeleteCommandParser
-
-AddressBookParser --> LogicManager : d
-deactivate AddressBookParser
-
-LogicManager -> DeleteCommand : execute()
-activate DeleteCommand
-
-DeleteCommand -> Model : deletePerson(1)
-activate Model
-
-Model --> DeleteCommand
-deactivate Model
-
-create CommandResult
-DeleteCommand -> CommandResult
-activate CommandResult
-
-CommandResult --> DeleteCommand
-deactivate CommandResult
-
-DeleteCommand --> LogicManager : result
-deactivate DeleteCommand
-
-[<--LogicManager
-deactivate LogicManager
-@enduml
diff --git a/docs/diagrams/DeleteTaskActivityDiagram.puml b/docs/diagrams/DeleteTaskActivityDiagram.puml
new file mode 100644
index 00000000000..9cf27494977
--- /dev/null
+++ b/docs/diagrams/DeleteTaskActivityDiagram.puml
@@ -0,0 +1,16 @@
+@startuml
+'https://plantuml.com/activity-diagram-beta
+
+start
+:User executes deleteTask command;
+if () then ([Index input is valid])
+ :Fetch task with the given index from task list;
+ :Delete the fetched task from task list;
+ :Update user interface with the updated task list;
+else ([Else])
+ :Output error message;
+
+ endif
+ stop
+
+@enduml
diff --git a/docs/diagrams/DeleteTaskSequenceDiagram.puml b/docs/diagrams/DeleteTaskSequenceDiagram.puml
new file mode 100644
index 00000000000..fbebf32dc4b
--- /dev/null
+++ b/docs/diagrams/DeleteTaskSequenceDiagram.puml
@@ -0,0 +1,69 @@
+@startuml
+!include style.puml
+
+box Logic LOGIC_COLOR_T1
+participant ":LogicManager" as LogicManager LOGIC_COLOR
+participant ":HeyMatezParser" as HeyMatezParser LOGIC_COLOR
+participant ":DeleteTaskCommandParser" as DeleteTaskCommandParser LOGIC_COLOR
+participant "d:DeleteTaskCommand" as DeleteTaskCommand LOGIC_COLOR
+participant ":CommandResult" as CommandResult LOGIC_COLOR
+end box
+
+box Model MODEL_COLOR_T1
+participant ":Model" as Model MODEL_COLOR
+end box
+
+[-> LogicManager : execute("deleteTask 1")
+activate LogicManager
+
+LogicManager -> HeyMatezParser : parseCommand("deleteTask 1")
+activate HeyMatezParser
+
+create DeleteTaskCommandParser
+HeyMatezParser -> DeleteTaskCommandParser
+activate DeleteTaskCommandParser
+
+DeleteTaskCommandParser --> HeyMatezParser
+deactivate DeleteTaskCommandParser
+
+HeyMatezParser -> DeleteTaskCommandParser : parse("1")
+activate DeleteTaskCommandParser
+
+create DeleteTaskCommand
+DeleteTaskCommandParser -> DeleteTaskCommand
+activate DeleteTaskCommand
+
+DeleteTaskCommand --> DeleteTaskCommandParser : d
+deactivate DeleteTaskCommand
+
+DeleteTaskCommandParser --> HeyMatezParser : d
+deactivate DeleteTaskCommandParser
+'Hidden arrow to position the destroy marker below the end of the activation bar.
+DeleteTaskCommandParser -[hidden]-> HeyMatezParser
+destroy DeleteTaskCommandParser
+
+HeyMatezParser --> LogicManager : d
+deactivate HeyMatezParser
+
+LogicManager -> DeleteTaskCommand : execute()
+activate DeleteTaskCommand
+
+DeleteTaskCommand -> Model : deleteTask(1)
+activate Model
+
+Model --> DeleteTaskCommand
+deactivate Model
+
+create CommandResult
+DeleteTaskCommand -> CommandResult
+activate CommandResult
+
+CommandResult --> DeleteTaskCommand
+deactivate CommandResult
+
+DeleteTaskCommand --> LogicManager :
+destroy DeleteTaskCommand
+
+[<--LogicManager
+deactivate LogicManager
+@enduml
diff --git a/docs/diagrams/DoneTaskActivityDiagram.puml b/docs/diagrams/DoneTaskActivityDiagram.puml
new file mode 100644
index 00000000000..aad733127e7
--- /dev/null
+++ b/docs/diagrams/DoneTaskActivityDiagram.puml
@@ -0,0 +1,20 @@
+@startuml
+start
+:User executes mark task as completed command;
+
+if () then ([input is valid])
+ :Fetch target task from task list;
+ if () then ([task status is uncompleted])
+ : Create a copy of the target task with
+ the status updated to completed;
+ : Update Task List with target task copy;
+ : Update User Interface;
+ else([else])
+ : Output task is already marked
+ as completed error;
+ endif
+else ([else])
+ : Output error message;
+endif
+stop
+@enduml
diff --git a/docs/diagrams/DoneTaskSeqeuenceDiagram.puml b/docs/diagrams/DoneTaskSeqeuenceDiagram.puml
new file mode 100644
index 00000000000..42685f97fa3
--- /dev/null
+++ b/docs/diagrams/DoneTaskSeqeuenceDiagram.puml
@@ -0,0 +1,77 @@
+@startuml
+!include style.puml
+
+box Logic LOGIC_COLOR_T1
+participant ":LogicManager" as LogicManager LOGIC_COLOR
+participant ":HeyMatezParser" as HeyMatezParser LOGIC_COLOR
+participant ":DoneTaskCommandParser" as DoneTaskCommandParser LOGIC_COLOR
+participant "d:DoneTaskCommand" as DoneTaskCommand LOGIC_COLOR
+participant ":CommandResult" as CommandResult LOGIC_COLOR
+end box
+
+box Model MODEL_COLOR_T1
+participant ":Model" as Model MODEL_COLOR
+end box
+
+[-> LogicManager : execute("done 1")
+activate LogicManager
+
+LogicManager -> HeyMatezParser : parseCommand("done 1")
+activate HeyMatezParser
+
+create DoneTaskCommandParser
+HeyMatezParser -> DoneTaskCommandParser
+activate DoneTaskCommandParser
+
+DoneTaskCommandParser --> HeyMatezParser
+deactivate DoneTaskCommandParser
+
+HeyMatezParser -> DoneTaskCommandParser : parse("1")
+activate DoneTaskCommandParser
+
+create DoneTaskCommand
+DoneTaskCommandParser -> DoneTaskCommand
+activate DoneTaskCommand
+
+DoneTaskCommand --> DoneTaskCommandParser : d
+deactivate DoneTaskCommand
+
+DoneTaskCommandParser --> HeyMatezParser : d
+deactivate DoneTaskCommandParser
+'Hidden arrow to position the destroy marker below the end of the activation bar.
+DoneTaskCommandParser -[hidden]-> HeyMatezParser
+destroy DoneTaskCommandParser
+
+HeyMatezParser --> LogicManager : d
+deactivate HeyMatezParser
+
+LogicManager -> DoneTaskCommand : execute()
+activate DoneTaskCommand
+
+DoneTaskCommand -> DoneTaskCommand : createDoneTask(taskToMarkDone)
+activate DoneTaskCommand
+
+DoneTaskCommand --> DoneTaskCommand : doneTask
+deactivate DoneTaskCommand
+
+DoneTaskCommand -> Model : setTask(taskToMarkDone, doneTask)
+activate Model
+
+Model --> DoneTaskCommand
+deactivate Model
+
+create CommandResult
+DoneTaskCommand -> CommandResult
+activate CommandResult
+
+CommandResult --> DoneTaskCommand
+deactivate CommandResult
+
+DoneTaskCommand --> LogicManager
+deactivate DoneTaskCommand
+DoneTaskCommand -[hidden]-> LogicManager
+destroy DoneTaskCommand
+
+[<--LogicManager
+deactivate LogicManager
+@enduml
diff --git a/docs/diagrams/FindBeforeActivityDiagram.puml b/docs/diagrams/FindBeforeActivityDiagram.puml
new file mode 100644
index 00000000000..6d76ad3dcb7
--- /dev/null
+++ b/docs/diagrams/FindBeforeActivityDiagram.puml
@@ -0,0 +1,12 @@
+@startuml
+start
+:User executes find task before command;
+
+if () then ([deadline input is valid and in correct format])
+ :Fetch tasks with deadline that matches predicate from task list;
+ : Update User Interface with updated task list;
+else ([else])
+ : Output error message;
+endif
+stop
+@enduml
diff --git a/docs/diagrams/FindBeforeSequenceDiagram.puml b/docs/diagrams/FindBeforeSequenceDiagram.puml
new file mode 100644
index 00000000000..597319e212a
--- /dev/null
+++ b/docs/diagrams/FindBeforeSequenceDiagram.puml
@@ -0,0 +1,78 @@
+@startuml
+!include style.puml
+
+box Logic LOGIC_COLOR_T1
+participant ":LogicManager" as LogicManager LOGIC_COLOR
+participant ":HeyMatezParser" as HeyMatezParser LOGIC_COLOR
+participant ":FindTaskBeforeCommandParser" as FindTaskBeforeCommandParser LOGIC_COLOR
+participant "p:DeadlineBeforeDatePredicate" as DeadlineBeforeDatePredicate LOGIC_COLOR
+participant "f:FindTaskBeforeCommand" as FindTaskBeforeCommand LOGIC_COLOR
+participant ":CommandResult" as CommandResult LOGIC_COLOR
+end box
+
+box Model MODEL_COLOR_T1
+participant ":Model" as Model MODEL_COLOR
+end box
+
+[-> LogicManager : execute("findBefore 2021-04-04")
+activate LogicManager
+
+LogicManager -> HeyMatezParser : parseCommand("findBefore 2021-04-04")
+activate HeyMatezParser
+
+create FindTaskBeforeCommandParser
+HeyMatezParser -> FindTaskBeforeCommandParser
+activate FindTaskBeforeCommandParser
+
+FindTaskBeforeCommandParser --> HeyMatezParser
+deactivate FindTaskBeforeCommandParser
+
+HeyMatezParser -> FindTaskBeforeCommandParser : parse("2021-04-04")
+activate FindTaskBeforeCommandParser
+
+create DeadlineBeforeDatePredicate
+FindTaskBeforeCommandParser -> DeadlineBeforeDatePredicate : DeadlineBeforeDatePredicate("2021-04-04")
+activate DeadlineBeforeDatePredicate
+
+
+DeadlineBeforeDatePredicate --> FindTaskBeforeCommandParser : p
+deactivate DeadlineBeforeDatePredicate
+create FindTaskBeforeCommand
+FindTaskBeforeCommandParser -> FindTaskBeforeCommand
+activate FindTaskBeforeCommand
+
+FindTaskBeforeCommand --> FindTaskBeforeCommandParser : f
+
+deactivate FindTaskBeforeCommand
+
+FindTaskBeforeCommandParser --> HeyMatezParser : f
+deactivate FindTaskBeforeCommandParser
+'Hidden arrow to position the destroy marker below the end of the activation bar.
+FindTaskBeforeCommandParser -[hidden]-> HeyMatezParser
+destroy FindTaskBeforeCommandParser
+
+HeyMatezParser --> LogicManager : f
+deactivate HeyMatezParser
+
+LogicManager -> FindTaskBeforeCommand : execute()
+activate FindTaskBeforeCommand
+
+FindTaskBeforeCommand -> Model : updateFilteredTaskList(p)
+activate Model
+
+Model --> FindTaskBeforeCommand
+deactivate Model
+
+create CommandResult
+FindTaskBeforeCommand -> CommandResult
+activate CommandResult
+
+CommandResult --> FindTaskBeforeCommand
+deactivate CommandResult
+
+FindTaskBeforeCommand --> LogicManager
+destroy FindTaskBeforeCommand
+
+[<--LogicManager
+deactivate LogicManager
+@enduml
diff --git a/docs/diagrams/LogicClassDiagram.puml b/docs/diagrams/LogicClassDiagram.puml
index 016ef33e2e2..02a61748086 100644
--- a/docs/diagrams/LogicClassDiagram.puml
+++ b/docs/diagrams/LogicClassDiagram.puml
@@ -8,7 +8,7 @@ package Logic {
package Parser {
Interface Parser <>
-Class AddressBookParser
+Class HeyMatezParser
Class XYZCommandParser
Class CliSyntax
Class ParserUtil
@@ -31,15 +31,19 @@ package Model{
Class HiddenModel #FFFFFF
}
+package Storage{
+Class HiddenModel #FFFFFF
+}
+
Class HiddenOutside #FFFFFF
HiddenOutside ..> Logic
LogicManager .up.|> Logic
-LogicManager -->"1" AddressBookParser
-AddressBookParser .left.> XYZCommandParser: creates >
+LogicManager -->"1" HeyMatezParser
+HeyMatezParser .left.> XYZCommandParser: creates >
XYZCommandParser ..> XYZCommand : creates >
-XYZCommandParser ..|> Parser
+XYZCommandParser .left.|> Parser
XYZCommandParser ..> ArgumentMultimap
XYZCommandParser ..> ArgumentTokenizer
ArgumentTokenizer .left.> ArgumentMultimap
@@ -52,8 +56,11 @@ XYZCommand -up-|> Command
LogicManager .left.> Command : executes >
LogicManager --> Model
+LogicManager --> Storage
+Storage --[hidden] Model
+Command .[hidden]up.> Storage
Command .right.> Model
-note right of XYZCommand: XYZCommand = AddCommand, \nFindCommand, etc
+note right of XYZCommand: XYZCommand = AddTaskCommand, \nFindTasksCommand, etc
Logic ..> CommandResult
LogicManager .down.> CommandResult
diff --git a/docs/diagrams/ModelClassDiagram.puml b/docs/diagrams/ModelClassDiagram.puml
index 3eae5326a82..61e85ae040a 100644
--- a/docs/diagrams/ModelClassDiagram.puml
+++ b/docs/diagrams/ModelClassDiagram.puml
@@ -5,11 +5,11 @@ skinparam arrowColor MODEL_COLOR
skinparam classBackgroundColor MODEL_COLOR
Package Model <>{
-Interface ReadOnlyAddressBook <>
+Interface ReadOnlyHeyMatez <>
Interface Model <>
Interface ObservableList <>
-Class AddressBook
-Class ReadOnlyAddressBook
+Class HeyMatez
+Class ReadOnlyHeyMatez
Class Model
Class ModelManager
Class UserPrefs
@@ -17,40 +17,55 @@ Class ReadOnlyUserPrefs
Package Person {
Class Person
-Class Address
Class Email
Class Name
Class Phone
+Class Role
Class UniquePersonList
}
-Package Tag {
-Class Tag
+Package Task {
+Class Task
+Class Title
+Class Description
+Class Deadline
+Enum Priority
+Enum TaskStatus
+Class UniqueTaskList
+}
+
+Package Assignee {
+Class Assignee
}
}
Class HiddenOutside #FFFFFF
HiddenOutside ..> Model
-AddressBook .up.|> ReadOnlyAddressBook
+HeyMatez .up.|> ReadOnlyHeyMatez
ModelManager .up.|> Model
Model .right.> ObservableList
-ModelManager o--> "1" AddressBook
+ModelManager o--> "1" HeyMatez
ModelManager o-left-> "1" UserPrefs
UserPrefs .up.|> ReadOnlyUserPrefs
-AddressBook *--> "1" UniquePersonList
+HeyMatez *--> "1" UniquePersonList
UniquePersonList o--> "*" Person
Person *--> Name
Person *--> Phone
Person *--> Email
-Person *--> Address
-Person *--> "*" Tag
+Person *--> Role
-Name -[hidden]right-> Phone
-Phone -[hidden]right-> Address
-Address -[hidden]right-> Email
+HeyMatez *--> "1" UniqueTaskList
+UniqueTaskList o--> "*" Task
+Task *--> Title
+Task *--> Description
+Task *--> Deadline
+Task *--> TaskStatus
+Task *--> Priority
+Task *--> "*" Assignee
ModelManager ----->" ~* filtered list" Person
+ModelManager ----->" \n\n\n~* filtered list" Task
@enduml
diff --git a/docs/diagrams/StorageClassDiagram.puml b/docs/diagrams/StorageClassDiagram.puml
index 6adb2e156bf..1fcc24ab94d 100644
--- a/docs/diagrams/StorageClassDiagram.puml
+++ b/docs/diagrams/StorageClassDiagram.puml
@@ -6,19 +6,23 @@ skinparam classBackgroundColor STORAGE_COLOR
Interface Storage <>
Interface UserPrefsStorage <>
-Interface AddressBookStorage <>
+Interface HeyMatezStorage <>
Class StorageManager
Class JsonUserPrefsStorage
-Class JsonAddressBookStorage
+Class JsonHeyMatezStorage
+
+Storage -|> HeyMatezStorage
+Storage -|> UserPrefsStorage
StorageManager .left.|> Storage
StorageManager o-right-> UserPrefsStorage
-StorageManager o--> AddressBookStorage
+StorageManager o--> HeyMatezStorage
JsonUserPrefsStorage .left.|> UserPrefsStorage
-JsonAddressBookStorage .left.|> AddressBookStorage
-JsonAddressBookStorage .down.> JsonSerializableAddressBookStorage
-JsonSerializableAddressBookStorage .right.> JsonSerializablePerson
-JsonSerializablePerson .right.> JsonAdaptedTag
+JsonHeyMatezStorage .left.|> HeyMatezStorage
+JsonHeyMatezStorage .down.> JsonSerializableHeyMatez
+JsonSerializableHeyMatez .left.> JsonAdaptedPerson
+JsonSerializableHeyMatez .right.> JsonAdaptedTask
+JsonAdaptedTask .right.> JsonAdaptedAssignee
@enduml
diff --git a/docs/diagrams/UiClassDiagram.puml b/docs/diagrams/UiClassDiagram.puml
index 92746f9fcf7..4f77df03f50 100644
--- a/docs/diagrams/UiClassDiagram.puml
+++ b/docs/diagrams/UiClassDiagram.puml
@@ -11,6 +11,8 @@ Class UiManager
Class MainWindow
Class HelpWindow
Class ResultDisplay
+class TaskListPanel
+class TaskCard
Class PersonListPanel
Class PersonCard
Class StatusBarFooter
@@ -34,9 +36,11 @@ MainWindow --> HelpWindow
MainWindow *-down-> CommandBox
MainWindow *-down-> ResultDisplay
MainWindow *-down-> PersonListPanel
+MainWindow *-down-> TaskListPanel
MainWindow *-down-> StatusBarFooter
PersonListPanel -down-> PersonCard
+TaskListPanel -down-> TaskCard
MainWindow -left-|> UiPart
@@ -44,13 +48,17 @@ ResultDisplay --|> UiPart
CommandBox --|> UiPart
PersonListPanel --|> UiPart
PersonCard --|> UiPart
+TaskListPanel --|> UiPart
+TaskCard --|> UiPart
StatusBarFooter --|> UiPart
HelpWindow -down-|> UiPart
PersonCard ..> Model
+TaskCard ..> Model
UiManager -right-> Logic
MainWindow -left-> Logic
+TaskListPanel -[hidden]left- HelpWindow
PersonListPanel -[hidden]left- HelpWindow
HelpWindow -[hidden]left- CommandBox
CommandBox -[hidden]left- ResultDisplay
diff --git a/docs/diagrams/tracing/LogicSequenceDiagram.puml b/docs/diagrams/tracing/LogicSequenceDiagram.puml
index fdcbe1c0ccc..b443490cea7 100644
--- a/docs/diagrams/tracing/LogicSequenceDiagram.puml
+++ b/docs/diagrams/tracing/LogicSequenceDiagram.puml
@@ -13,7 +13,7 @@ create ecp
abp -> ecp
abp -> ecp ++: parse(arguments)
create ec
-ecp -> ec ++: index, editPersonDescriptor
+ecp -> ec ++: index, editMemberDescriptor
ec --> ecp --
ecp --> abp --: command
abp --> logic --: command
diff --git a/docs/images/ArchitectureSequenceDiagram.png b/docs/images/ArchitectureSequenceDiagram.png
index 2f1346869d0..0c1235ade4e 100644
Binary files a/docs/images/ArchitectureSequenceDiagram.png and b/docs/images/ArchitectureSequenceDiagram.png differ
diff --git a/docs/images/ClearAssigneeSequenceDiagram.png b/docs/images/ClearAssigneeSequenceDiagram.png
new file mode 100644
index 00000000000..64954ab07c0
Binary files /dev/null and b/docs/images/ClearAssigneeSequenceDiagram.png differ
diff --git a/docs/images/ClearAssigneesActivityDiagram.png b/docs/images/ClearAssigneesActivityDiagram.png
new file mode 100644
index 00000000000..15433b19630
Binary files /dev/null and b/docs/images/ClearAssigneesActivityDiagram.png differ
diff --git a/docs/images/DeleteSequenceDiagram.png b/docs/images/DeleteSequenceDiagram.png
deleted file mode 100644
index fa327b39618..00000000000
Binary files a/docs/images/DeleteSequenceDiagram.png and /dev/null differ
diff --git a/docs/images/DeleteTaskActivityDiagram.png b/docs/images/DeleteTaskActivityDiagram.png
new file mode 100644
index 00000000000..b687e4eaf15
Binary files /dev/null and b/docs/images/DeleteTaskActivityDiagram.png differ
diff --git a/docs/images/DeleteTaskSequenceDiagram.png b/docs/images/DeleteTaskSequenceDiagram.png
new file mode 100644
index 00000000000..04431395b4e
Binary files /dev/null and b/docs/images/DeleteTaskSequenceDiagram.png differ
diff --git a/docs/images/DoneTaskActivityDiagram.png b/docs/images/DoneTaskActivityDiagram.png
new file mode 100644
index 00000000000..b3f72f8db2b
Binary files /dev/null and b/docs/images/DoneTaskActivityDiagram.png differ
diff --git a/docs/images/DoneTaskSequenceDiagram.png b/docs/images/DoneTaskSequenceDiagram.png
new file mode 100644
index 00000000000..6de0609d762
Binary files /dev/null and b/docs/images/DoneTaskSequenceDiagram.png differ
diff --git a/docs/images/FindBeforeActivityDiagram.png b/docs/images/FindBeforeActivityDiagram.png
new file mode 100644
index 00000000000..1294521d04c
Binary files /dev/null and b/docs/images/FindBeforeActivityDiagram.png differ
diff --git a/docs/images/FindBeforeSequenceDiagram.png b/docs/images/FindBeforeSequenceDiagram.png
new file mode 100644
index 00000000000..d67e48d6919
Binary files /dev/null and b/docs/images/FindBeforeSequenceDiagram.png differ
diff --git a/docs/images/LogicClassDiagram.png b/docs/images/LogicClassDiagram.png
index b9e853cef12..04c52c661fd 100644
Binary files a/docs/images/LogicClassDiagram.png and b/docs/images/LogicClassDiagram.png differ
diff --git a/docs/images/ModelClassDiagram.png b/docs/images/ModelClassDiagram.png
index ffd17662d41..70ce17d693e 100644
Binary files a/docs/images/ModelClassDiagram.png and b/docs/images/ModelClassDiagram.png differ
diff --git a/docs/images/StorageClassDiagram.png b/docs/images/StorageClassDiagram.png
index d87c1216820..bf91eb8b598 100644
Binary files a/docs/images/StorageClassDiagram.png and b/docs/images/StorageClassDiagram.png differ
diff --git a/docs/images/UG-examples/addMember-cmd.png b/docs/images/UG-examples/addMember-cmd.png
new file mode 100644
index 00000000000..c27923c9c42
Binary files /dev/null and b/docs/images/UG-examples/addMember-cmd.png differ
diff --git a/docs/images/UG-examples/addMember-result.png b/docs/images/UG-examples/addMember-result.png
new file mode 100644
index 00000000000..8bd33ce9f04
Binary files /dev/null and b/docs/images/UG-examples/addMember-result.png differ
diff --git a/docs/images/UG-examples/addTask-cmd.png b/docs/images/UG-examples/addTask-cmd.png
new file mode 100644
index 00000000000..c087d1b176b
Binary files /dev/null and b/docs/images/UG-examples/addTask-cmd.png differ
diff --git a/docs/images/UG-examples/addTask-result.png b/docs/images/UG-examples/addTask-result.png
new file mode 100644
index 00000000000..237c06f5ac4
Binary files /dev/null and b/docs/images/UG-examples/addTask-result.png differ
diff --git a/docs/images/Ui.png b/docs/images/Ui.png
index 5bd77847aa2..99c5d3d5c2a 100644
Binary files a/docs/images/Ui.png and b/docs/images/Ui.png differ
diff --git a/docs/images/UiClassDiagram.png b/docs/images/UiClassDiagram.png
index 7b4b3dbea45..4bd23340e7c 100644
Binary files a/docs/images/UiClassDiagram.png and b/docs/images/UiClassDiagram.png differ
diff --git a/docs/images/cheeerynne.png b/docs/images/cheeerynne.png
new file mode 100644
index 00000000000..84a9c90ecaf
Binary files /dev/null and b/docs/images/cheeerynne.png differ
diff --git a/docs/images/findAlexDavidResult.png b/docs/images/findAlexDavidResult.png
deleted file mode 100644
index 235da1c273e..00000000000
Binary files a/docs/images/findAlexDavidResult.png and /dev/null differ
diff --git a/docs/images/johndoe.png b/docs/images/johndoe.png
deleted file mode 100644
index 1ce7ce16dc8..00000000000
Binary files a/docs/images/johndoe.png and /dev/null differ
diff --git a/docs/images/rachelljt.png b/docs/images/rachelljt.png
new file mode 100644
index 00000000000..88e1614233d
Binary files /dev/null and b/docs/images/rachelljt.png differ
diff --git a/docs/images/tashawan23.png b/docs/images/tashawan23.png
new file mode 100644
index 00000000000..187c79fe642
Binary files /dev/null and b/docs/images/tashawan23.png differ
diff --git a/docs/images/zatkiller.png b/docs/images/zatkiller.png
new file mode 100644
index 00000000000..675753cf7ac
Binary files /dev/null and b/docs/images/zatkiller.png differ
diff --git a/docs/index.md b/docs/index.md
index 7601dbaad0d..fc6f8183596 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -1,17 +1,19 @@
---
layout: page
-title: AddressBook Level-3
+title: HEY MATEz
---
-[](https://github.com/se-edu/addressbook-level3/actions)
-[](https://codecov.io/gh/se-edu/addressbook-level3)
+[](https://github.com/AY2021S2-CS2103T-W14-3/tp/actions/workflows/gradle.yml)
+[](https://codecov.io/gh/AY2021S2-CS2103T-W14-3/tp)

-**AddressBook is a desktop application for managing your contact details.** While it has a GUI, most of the user interactions happen using a CLI (Command Line Interface).
+**HEY MATEz is a desktop application for managing your Club members and tasks to be completed.** While it has a GUI, most of the user interactions happen using a CLI (Command Line Interface).
+With HEY MATEz, planning and distributing tasks among your members will never give you a headache again! :smile:
-* If you are interested in using AddressBook, head over to the [_Quick Start_ section of the **User Guide**](UserGuide.html#quick-start).
-* If you are interested about developing AddressBook, the [**Developer Guide**](DeveloperGuide.html) is a good place to start.
+
+* If you are interested in using HEY MATEz, head over to the [_Quick Start_ section of the **User Guide**](UserGuide.html#quick-start).
+* If you are interested about developing HEY MATEz, the [**Developer Guide**](DeveloperGuide.html) is a good place to start.
**Acknowledgements**
diff --git a/docs/team/cheeerynne.md b/docs/team/cheeerynne.md
new file mode 100644
index 00000000000..c71960cf253
--- /dev/null
+++ b/docs/team/cheeerynne.md
@@ -0,0 +1,74 @@
+---
+layout: page
+title: Chee Erynne's Project Portfolio Page
+---
+
+## Project: HEY MATEz
+
+HEY MATEz is a desktop application to get rid of your woes by allowing you to track members and tasks within
+a club efficiently and easily! It is a Command Line Interface (CLI) application which handles user requests
+that are typed into the input box as commands and it has a GUI created with JavaFX. It is written in Java, and has about 10 kLoC.
+
+Given below are my contributions to the project.
+
+* **New Feature**: Added the ability to assign members to a task. (Pull Requests: [\#161](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/161), [\#163](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/163))
+ * What it does: Allows the user to assign members and edit assignees to a task.
+ * Justification: This feature improves the product significantly as a user can conveniently track which members are assigned to a task.
+ Also, users can easily modify the assignees to a task should there be any changes in the assignment of a task.
+ * Highlights: The implementation was challenging as I had to check whether the specified member's name exists in the
+ members' list before allowing assignment to a task. I decided to implement an Assignee class, along with a checkAssignees
+ method within the ModelManager class. The checkAssignees method checks the validity of the specified member's name by
+ calling the hasPerson method within the ModelManager class. With the checkAssignees method, I was able to check
+ the validity of the specified names while not creating any unnecessary dependency between the Task and Person classes.
+
+* **New Feature**: Added the ability to find tasks with keywords. (Pull Requests: [\#133](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/133))
+ * What it does: Allows the user to find all tasks which contain any of the specified keywords in its title or description.
+ * Justification: This feature improves the product significantly because a user can easily filter and find tasks based on specific
+ keywords. With this easy filtering, there is no need for users to scroll through the entire list just to find a specific task.
+ * Highlights: The implementation was challenging as I had to check through the title and description fields of all the tasks
+ in the task list. I decided to implement a predicate, TaskContainsKeywordPredicate, which compares the title and description of
+ a task to the list of keywords specified. The task list is then updated with the predicate, displaying tasks whose title or
+ description contain any of the specified keywords.
+
+* **New Feature**: Added the ability to find members with keywords. (Pull Requests: [\#130](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/130))
+ * What it does: Allows the user to find all members whose name, phone number, email or role contain any of the specified keywords.
+ * Justification: This feature improves the product significantly because a user can easily filter and find members based on specific
+ keywords. With this easy filtering, there is no need for users to scroll through the entire list just to find a specific member.
+ * Highlights: The implementation was challenging as I had to check through all the fields of the members in the list.
+ I decided to implement a predicate, DetailsContainsKeywordsPredicate, which compares all the fields of a member to the list of keywords specified.
+ The members list is then updated with the predicate, displaying members whose details contain any of the specified keywords.
+
+* **New Feature**: Added the ability to clear all members assigned to a task. (Pull Requests: [\#163](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/163), [\#174](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/174))
+ * What it does: Allows the user to clear all members assigned to a task.
+ * Justification: This feature improves the product significantly because should the user accidentally assigned a task to
+ the wrong group of members, the user can easily clear all members assigned to the task instead of removing one member at a time.
+ * Highlights: The implementation was challenging as I had to create a copy of the task at the given index and update
+ the assignees field accordingly, before updating the task list with the updated task copy.
+
+* **Code contributed**: [RepoSense link](https://nus-cs2103-ay2021s2.github.io/tp-dashboard/?search=&sort=groupTitle&sortWithin=title&since=&timeframe=commit&mergegroup=&groupSelect=groupByRepos&breakdown=false&tabOpen=true&tabType=authorship&tabAuthor=cheeerynne&tabRepo=AY2021S2-CS2103T-W14-3%2Ftp%5Bmaster%5D&authorshipIsMergeGroup=false&authorshipFileTypes=docs~functional-code~test-code&authorshipIsBinaryFileTypeChecked=false)
+
+* **Project management**:
+ * Created issues
+ * Managed milestones and issues
+
+* **Enhancements to existing features**:
+ * Updated the deleteMember and editMember commands to delete/edit by name instead of index. (Pull Requests: [\#70](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/70), [\#85](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/85))
+ * Added JavaDoc comments to existing classes for better documentation. (Pull Requests: [\#187](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/187))
+
+* **Documentation**:
+ * User Guide:
+ * Added documentation for the commands `findTasks`, `findMembers` and `clearAssignees`. (Pull Requests: [\#137](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/137), [\#166](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/166))
+ * Categorized and organized the User Guide. (Pull Requests: [\#166](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/166))
+ * Added introduction and mockup of application. (Pull Requests: [\#23](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/23))
+
+ * Developer Guide:
+ * Updated the Storage UML Diagram in the DG. (Pull Requests: [\#191](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/191), [\#273](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/273))
+ * Added implementation explanation for `clearAssignees` command. (Pull Requests: [\#191](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/191), [\#291](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/291))
+ * Added and updated use cases in the Developer Guide. (Pull Requests: [\#143](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/143), [\#171](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/171))
+ * Added manual testing instructions for various commands. (Pull Requests: [\#284](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/284))
+
+* **Community**:
+ * PRs reviewed (Pull requests: [\#246](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/246), [\#276](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/276), [\#283](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/283))
+ * Reported bugs and suggestions for other teams in the class (Examples: [1](https://github.com/cheeerynne/ped/issues/11), [2](https://github.com/cheeerynne/ped/issues/12), [3](https://github.com/cheeerynne/ped/issues/9))
+
+
diff --git a/docs/team/johndoe.md b/docs/team/johndoe.md
deleted file mode 100644
index 1f1e9e6f6db..00000000000
--- a/docs/team/johndoe.md
+++ /dev/null
@@ -1,46 +0,0 @@
----
-layout: page
-title: John Doe's Project Portfolio Page
----
-
-## Project: AddressBook Level 3
-
-AddressBook - Level 3 is a desktop address book application used for teaching Software Engineering principles. The user interacts with it using a CLI, and it has a GUI created with JavaFX. It is written in Java, and has about 10 kLoC.
-
-Given below are my contributions to the project.
-
-* **New Feature**: Added the ability to undo/redo previous commands.
- * What it does: allows the user to undo all previous commands one at a time. Preceding undo commands can be reversed by using the redo command.
- * Justification: This feature improves the product significantly because a user can make mistakes in commands and the app should provide a convenient way to rectify them.
- * Highlights: This enhancement affects existing commands and commands to be added in future. It required an in-depth analysis of design alternatives. The implementation too was challenging as it required changes to existing commands.
- * Credits: *{mention here if you reused any code/ideas from elsewhere or if a third-party library is heavily used in the feature so that a reader can make a more accurate judgement of how much effort went into the feature}*
-
-* **New Feature**: Added a history command that allows the user to navigate to previous commands using up/down keys.
-
-* **Code contributed**: [RepoSense link]()
-
-* **Project management**:
- * Managed releases `v1.3` - `v1.5rc` (3 releases) on GitHub
-
-* **Enhancements to existing features**:
- * Updated the GUI color scheme (Pull requests [\#33](), [\#34]())
- * Wrote additional tests for existing features to increase coverage from 88% to 92% (Pull requests [\#36](), [\#38]())
-
-* **Documentation**:
- * User Guide:
- * Added documentation for the features `delete` and `find` [\#72]()
- * Did cosmetic tweaks to existing documentation of features `clear`, `exit`: [\#74]()
- * Developer Guide:
- * Added implementation details of the `delete` feature.
-
-* **Community**:
- * PRs reviewed (with non-trivial review comments): [\#12](), [\#32](), [\#19](), [\#42]()
- * Contributed to forum discussions (examples: [1](), [2](), [3](), [4]())
- * Reported bugs and suggestions for other teams in the class (examples: [1](), [2](), [3]())
- * Some parts of the history feature I added was adopted by several other class mates ([1](), [2]())
-
-* **Tools**:
- * Integrated a third party library (Natty) to the project ([\#42]())
- * Integrated a new Github plugin (CircleCI) to the team repo
-
-* _{you can add/remove categories in the list above}_
diff --git a/docs/team/rachelljt.md b/docs/team/rachelljt.md
new file mode 100644
index 00000000000..7dd643b86c7
--- /dev/null
+++ b/docs/team/rachelljt.md
@@ -0,0 +1,81 @@
+---
+layout: page
+title: Rachel Lim's Project Portfolio Page
+---
+
+## Project: HEY MATEz
+
+HEY MATEz is a desktop application to get rid of your woes by allowing you to track members and tasks within a club efficiently and easily!
+It is a Command Line Interface (CLI) application which handles user requests that are typed into the input box as commands and
+it has a GUI created with JavaFX. It is written in Java, and has about 10 kLoC.
+
+Given below are my contributions to the project.
+
+* **New Feature**: Added the ability to delete tasks. (Pull Requests: [\#67](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/67), [\#106](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/106), [\#246](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/246))
+ * What it does: Allows the user to delete a specific task given a valid index.
+ * Justification: This feature allows the user to delete an existing task in the list based on a given index.
+ Should the user accidentally add a task, they can delete it easily just by using the `deleteTask` command.
+ * Highlights: The implementation was challenging as it required changes to existing commands. When the index is parsed, I had to take into account of the different scenarios.
+ For instance, I had to change the function of isNonZeroUnsignedInteger in StringUtil.java from a boolean function to an
+ int function so that '1' will be returned if the index is a valid integer(positive integer),
+ '2' for an invalid integer(non-positive integer) and '3' for an invalid input(spaces, alphanumeric) such that different error messages would be thrown
+ should the index differ from the format.
+
+
+* **New Feature**: Added the ability to view a list of uncompleted tasks. (Pull Requests: [\#117](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/117), [\#252](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/252))
+ * What it does: Allows the user to view a list of tasks that have not been completed.
+ * Justification: This feature improves the product significantly because a user can easily view a list of uncompleted tasks upon inputting the command
+ which greatly saves the time of the user, instead of manually searching for a list uncompleted tasks.
+ * Highlights: The implementation was challenging as it required me to create another predicate to filter a list of
+ uncompleted tasks. Furthermore, I had to create a boolean function `isCompleted` in the `Task` class instead of calling `task.taskStatus` to prevent breaking the abstraction barrier in
+ order to filter the list of uncompleted tasks.
+ Also, I had to take into account of the different messages displayed in different situations such as when there are no uncompleted tasks found.
+ Lastly, I had to do heavy testing to account for the different scenarios of usage which was quite tedious as some commands
+ have to be modified.
+
+
+* **New Feature**: Added the ability to view a list of unassigned tasks. (Pull Requests [\#162](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/162), [\#252](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/252))
+ * What it does: Allows the user to view a list of tasks that have not been assigned to any member.
+ * Justification: This feature improves the product significantly because a user can easily view a list of unassigned tasks upon inputting the command
+ which greatly saves the time of the user, instead of manually searching for a list of unassigned tasks.
+ * Highlights: The implementation was challenging as it required me to create another predicate to filter a list of
+ unassigned tasks. Furthermore, I had to create a boolean function `isAssigned` in `Task` class instead of calling `task.assignees.isEmpty()` to prevent breaking the abstraction barrier in
+ order to filter the list of unassigned tasks.
+ Also, I had to take into account of the different messages displayed in different situations such as when there are no unassigned tasks found.
+ Finally, I had to do heavy testing to account for the different scenarios of usage which was quite challenging as some commands
+ have to be changed.
+
+
+* **Code contributed**: [RepoSense link](https://nus-cs2103-ay2021s2.github.io/tp-dashboard/?search=&sort=groupTitle&sortWithin=title&since=&timeframe=commit&mergegroup=&groupSelect=groupByRepos&breakdown=false&tabOpen=true&tabType=authorship&zFR=false&tabAuthor=rachelljt&tabRepo=AY2021S2-CS2103T-W14-3%2Ftp%5Bmaster%5D&authorshipIsMergeGroup=false&authorshipFileTypes=docs~functional-code~test-code&authorshipIsBinaryFileTypeChecked=false)
+
+
+* **Project management**:
+ * Create issues
+ * Set up unit testing for tasks
+ * Managed milestones and issues
+
+
+* **Enhancements to existing features**:
+ * Change the User Interface of the app (Pull requests: [\#110](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/110), [\#128](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/128), [\#238](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/238))
+
+
+* **Documentation**:
+ * User Guide:
+ * Added documentation for the commands `deleteTask`, `viewTasks`, `viewUncompletedTasks`, `viewUnassignedTasks` (Pull requests: [\#117](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/117), [\#160](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/160))
+ * Embedded a link to download Java 11 at the Quick Start section (Pull Requests: [\#189](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/189))
+
+ * Developer Guide:
+ * Updated the user stories in the Developer Guide (Pull requests: [\#138](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/138), [\#169](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/169), [\#274](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/274))
+ * Updated the User Interface UML Diagram, Sequence Diagram in the Developer Guide (Pull requests: [\#185](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/185))
+ * Updated the Architecture Sequence Diagram in the Developer Guide (Pull requests: [\#189](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/189))
+ * Added the implementation explanation for `deleteTask` (Pull requests: [\#185](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/185))
+ * Added activity diagram for `deleteTask` (Pull requests: [\#290](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/290))
+ * Added manual testing instructions for `viewTasks`, `deleteTask`, `viewUnassignedTasks`, `viewUncompletedTasks` (Pull requests: [\#285](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/285))
+
+
+* **Community**:
+ * PRs reviewed (Pull requests: [\#247](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/247), [\#268](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/268))
+ * Contributed to forum discussions (Examples: [1](https://github.com/nus-cs2103-AY2021S2/forum/issues/182))
+ * Reported bugs and suggestions for other teams in the class (Examples: [1](https://github.com/rachelljt/ped/issues/4), [2](https://github.com/rachelljt/ped/issues/1), [3](https://github.com/rachelljt/ped/issues/6))
+
+
diff --git a/docs/team/tashawan23.md b/docs/team/tashawan23.md
new file mode 100644
index 00000000000..67a8ac5b768
--- /dev/null
+++ b/docs/team/tashawan23.md
@@ -0,0 +1,67 @@
+---
+layout: page
+title: Tasha Wan's Project Portfolio Page
+---
+
+## Project: HEY MATEz
+
+HEY MATEz is a desktop application to get rid of your woes by allowing you to track members and tasks within a club efficiently and easily!
+It is a Command Line Interface (CLI) application which handles user requests that are typed into the input box as commands and
+it has a GUI created with JavaFX. It is written in Java, and has about 10 kLoC.
+
+Given below are my contributions to the project.
+
+* **New Feature**: Added the ability to add and edit tasks.
+ * What it does: Allows the user to add a task with a title, and description as well as edit these details.
+ (Pull Requests: [\#62](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/62), [\#63](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/63))
+ * Justification: This feature allows the user to add a task to the task list and edit the task based on its index.
+ Should the user need to update the details of a task, they can edit it easily.
+ * Highlights: The implementation was challenging as it involved creating a task list to store added tasks that had to be included in the storage as well.
+ I represented each task as a JsonAdaptedTask to be added into the HeyMatez storage along with the members.
+
+* **New Feature**: Added the ability to add a deadline to tasks. (Pull Requests: [\#107](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/107), [\#116](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/116))
+ * What it does: Allows the user to add a deadline to tasks.
+ * Justification: This feature improves the ability to track tasks based on their deadlines so that users can ensure tasks are completed on time.
+ * Highlights: The implementation was challenging as it required me to implement a deadline parser which could parse a valid deadline provided in the
+ correct format. I had to handle the errors of incorrect deadline format by comparing it to the required format as well as invalid dates which are not
+ found in the calendar. This is so that the user can be notified correctly by the corresponding error messages when the deadline cannot be parsed.
+
+* **New Feature**: Added the ability to add a role to members and edit a member's role.
+ * What it does: Allows the user to add a role to any member and edit this role. (Pull Requests: [\#109](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/109), [\#111](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/111))
+ * Justification: This feature allows users to add the member's role so that they can better manage members, and assign tasks to them correspondingly.
+ * Highlights: The implementation was challenging as the member role is an optional field. I had to take into account the situation where the user does not
+ specify a member role while adding a member and assign a default value to the field. I decided to assign a default value of member to all members added
+ unless specified by the user.
+
+* **New Feature**: Added the ability to find tasks due before a certain deadline.
+ * What it does: Allows the user to view list of tasks with deadlines before the provided date. (Pull Requests: [\#153](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/153))
+ * Justification: This feature improves the product significantly because a user can conveniently search for tasks that are due soon or due before a specified
+ date to ensure that these tasks are completed on time.
+ * Highlights: The implementation was challenging as task deadlines have to be compared using a predicate that compares deadlines as a LocalDate.
+
+* **Code contributed**: [RepoSense link](https://nus-cs2103-ay2021s2.github.io/tp-dashboard/?search=w14&sort=groupTitle&sortWithin=title&since=2021-02-19&timeframe=commit&mergegroup=&groupSelect=groupByRepos&breakdown=false&tabOpen=true&tabType=authorship&zFR=false&tabAuthor=tashawan23&tabRepo=AY2021S2-CS2103T-W14-3%2Ftp%5Bmaster%5D&authorshipIsMergeGroup=false&authorshipFileTypes=docs~functional-code~test-code~other&authorshipIsBinaryFileTypeChecked=false)
+
+* **Project management**:
+ * Create issues.
+ * Managed milestones and issues.
+ * Set up Github repository.
+
+* **Enhancements to existing features**:
+ * Reorganise project structure by renaming directories and files to our product. (Pull requests: [\#181](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/181))
+
+* **Documentation**:
+ * User Guide:
+ * Added documentation for the commands `addTask`, `editTask`, `findTasksBefore` (Pull requests: [\#108](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/108), [\#119](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/119))
+ * Wrote the introduction and purpose of the user guide as well as use case scenarios for each command (Pull Requests: [\#196](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/196), [\#190](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/190))
+
+ * Developer Guide:
+ * Update the use cases in the Developer Guide (Pull requests: [\#139](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/139), [\#155](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/155))
+ * Update the Logic and Model UML Diagrams in the Developer Guide (Pull requests: [\#173](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/173))
+ * Update FindBefore Sequence Diagram in the Developer Guide (Pull requests: [\#186](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/186))
+ * Add implementation explanation for `findBefore` command (Pull requests: [\#186](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/186))
+
+* **Community**:
+ * PRs reviewed (Example pull requests: [\#185](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/185))
+ * Reported bugs and suggestions for other teams in the class (examples: [1](https://github.com/tashawan23/ped/issues/3), [2](https://github.com/tashawan23/ped/issues/9), [3](https://github.com/tashawan23/ped/issues/5))
+
+
diff --git a/docs/team/zatkiller.md b/docs/team/zatkiller.md
new file mode 100644
index 00000000000..bfa1010e2e6
--- /dev/null
+++ b/docs/team/zatkiller.md
@@ -0,0 +1,75 @@
+---
+layout: page
+title: Dylan Ghee's Project Portfolio Page
+---
+
+## Project: HEY MATEz
+
+HEY MATEz is a desktop application to get rid of your woes by allowing you to track members and tasks within a club efficiently and easily!
+It is a Command Line Interface (CLI) application which handles user requests that are typed into the input box as commands and
+it has a GUI created with JavaFX. It is written in Java, and has about 10 kLoC.
+
+Given below are my contributions to the project.
+
+* **New Feature**: Added the ability to mark a task as completed or uncompleted. (Pull Requests: [\#96](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/101), [\#101](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/101))
+
+ * What it does: allows the user to change the status of a task from completed or uncompleted.
+
+ * Justification: This feature improves the product significantly because a user can indicate whether a task is completed or uncompleted. With this indication, users
+ are able to focus on tasks that are not completed yet.
+
+ * Highlights: The implementation was challenging as I had to design the feature such that it was only restricted to 2 values - completed and uncompleted. After taking into account design
+ considerations, I decided to implement an Enum class named TaskStatus, with UNCOMPLETED and COMPLETED as the enum constants. Using this, I was able to add an additional attribute
+ to the Task Class, status, while being able to restrict the allowed values of a task's status to completed and uncompleted.
+
+* **New Feature**: Added the ability to prioritize a task. (Pull Requests: [\#114](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/114))
+
+ * What it does: allows the user to assign a task a certain priority.
+
+ * Justification: This feature improves the product significantly because a user can indicate the priority of a task - high, medium, low or unassigned. With this priority value, users
+ will be to focus on tasks which are of higher priority.
+
+ * Highlights: The implementation was challenging as I had to design the feature such that it was only restricted to 4 values - high, medium, low and unassigned. After taking into account design
+ considerations, I decided to implement an Enum class named PRIORITY, with HIGH, MEDIUM, LOW and UNASSIGNED as the enum constants. Using this, I was able to add an additional attribute
+ to the Task Class, priority, while being able to restrict the allowed values of a task's priority to high, medium, low or unassigned.
+
+* **New Feature**: Added the ability to find tasks assigned to a particular member. (Pull Requests: [\#168](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/168))
+
+ * What it does: allows the user to find all tasks assigned to a particular member.
+
+ * Justification: This feature improves the product significantly because a user can conveniently search what tasks has been assigned to a particular member.
+
+ * Highlights: The implementation was challenging as I had to think of a way to check which tasks have been assigned to a particular member. After considering the current software architecture,
+ I made a decision to implement a predicate, TaskContainsAssigneePredicate. When the Task List is updated with the predicate, the predicate calls the `hasAssignee` method of the Task class to check
+ if the name specified in the command exists as an assignee and updates the Task List accordingly.
+
+* **Code contributed**: [RepoSense link](https://nus-cs2103-ay2021s2.github.io/tp-dashboard/?search=&sort=groupTitle&sortWithin=title&since=&timeframe=commit&mergegroup=&groupSelect=groupByRepos&breakdown=false&tabOpen=true&tabType=zoom&zA=zatkiller&zR=AY2021S2-CS2103T-W14-3%2Ftp%5Bmaster%5D&zACS=233.65598705501617&zS=2021-02-19&zFS=&zU=2021-04-05&zMG=undefined&zFTF=commit&zFGS=groupByRepos&zFR=false)
+
+* **Project management**:
+ * Responsible for project direction and task delegation
+ * Managed releases `v1.1, v1.2, v1.2.1, v1.3` (4 releases) on GitHub
+ * Set up github organization and repository
+ * Set up continuous integration
+ * Create milestones and issues
+
+* **Enhancements to existing features**:
+ * Updated add and list commands to addMember and viewMember commands (Pull requests: [\#66](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/66), [\#68](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/68), [\#71](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/71))
+ * Remove redundant Address class and instances (Pull requests [\#65](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/65), [\#151](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/151))
+ * Add sample tasks to existing sample data which only contains sample persons (Pull requests [\#125](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/125))
+
+* **Documentation**:
+ * User Guide:
+ * Added documentation for the commands `done` and `undo` (Pull requests: [\#101](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/101))
+ * Added Introduction, Summary and List of Content (Pull requests: [\#154](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/154), [\#179](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/179))
+
+ * Developer Guide:
+ * Update the user stories in the Developer Guide (Pull requests: [\#105](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/105))
+ * Update the Model Diagram in the Developer Guide (Pull requests: [\#188](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/188))
+ * Add implementation documentation for done and undo command (Pull requests: [\#134](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/134))
+
+* **Community**:
+ * PRs reviewed (with non-trivial review comments) (Pull requests: [\#187](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/187), [\#67](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/67), [\#70](https://github.com/AY2021S2-CS2103T-W14-3/tp/pull/70))
+ * Contributed to forum discussions (examples: [1](https://github.com/nus-cs2103-AY2021S2/forum/issues/117))
+ * Reported bugs and suggestions for other teams in the class (examples: [1](https://github.com/zatkiller/ped/issues/4), [2](https://github.com/zatkiller/ped/issues/2), [3](https://github.com/zatkiller/ped/issues/7))
+
+
diff --git a/docs/tutorials/AddRemark.md b/docs/tutorials/AddRemark.md
deleted file mode 100644
index 64c9b1f91de..00000000000
--- a/docs/tutorials/AddRemark.md
+++ /dev/null
@@ -1,394 +0,0 @@
----
-layout: page
-title: "Tutorial: Adding a command"
----
-
-Let's walk you through the implementation of a new command — `remark`.
-
-This command allows users of the AddressBook application to add optional remarks to people in their address book and edit it if required. The command should have the following format:
-
-`remark INDEX r/REMARK` (e.g., `remark 2 r/Likes baseball`)
-
-We’ll assume that you have already set up the development environment as outlined in the Developer’s Guide.
-
-
-## Create a new `remark` command
-
-Looking in the `logic.command` package, you will notice that each existing command have their own class. All the commands inherit from the abstract class `Command` which means that they must override `execute()`. Each `Command` returns an instance of `CommandResult` upon success and `CommandResult#feedbackToUser` is printed to the `ResultDisplay`.
-
-Let’s start by creating a new `RemarkCommand` class in the `src/main/java/seedu/address/logic/command` directory.
-
-For now, let’s keep `RemarkCommand` as simple as possible and print some output. We accomplish that by returning a `CommandResult` with an accompanying message.
-
-**`RemarkCommand.java`:**
-
-``` java
-package seedu.address.logic.commands;
-
-import seedu.address.model.Model;
-
-/**
- * Changes the remark of an existing person in the address book.
- */
-public class RemarkCommand extends Command {
-
- public static final String COMMAND_WORD = "remark";
-
- @Override
- public CommandResult execute(Model model) {
- return new CommandResult("Hello from remark");
- }
-}
-```
-
-### Hook `RemarkCommand` into the application
-
-Now that we have our `RemarkCommand` ready to be executed, we need to update `AddressBookParser#parseCommand()` to recognize the `remark` keyword. Add the new command to the `switch` block by creating a new `case` that returns a new instance of `RemarkCommand`.
-
-You can refer to the changes in this [diff](https://github.com/se-edu/addressbook-level3/commit/35eb7286f18a029d39cb7a29df8f172a001e4fd8#diff-34ace715a8a8d2e5a66e71289f017b47).
-
-### Run the application
-
-Run `Main#main` and try out your new `RemarkCommand`. If everything went well, you should see something like this:
-
-
-
-## Change `RemarkCommand` to throw an exception
-
-While we have successfully printed a message to `ResultDisplay`, the command does not do what it is supposed to do. Let’s change the command to throw a `CommandException` to accurately reflect that our command is still a work in progress.
-
-
-
-Following the convention in other commands, we add relevant messages as constants and use them.
-
-**`RemarkCommand.java`:**
-
-``` java
- public static final String MESSAGE_USAGE = COMMAND_WORD + ": Edits the remark of the person identified "
- + "by the index number used in the last person listing. "
- + "Existing remark will be overwritten by the input.\n"
- + "Parameters: INDEX (must be a positive integer) "
- + "r/ [REMARK]\n"
- + "Example: " + COMMAND_WORD + " 1 "
- + "r/ Likes to swim.";
-
- public static final String MESSAGE_NOT_IMPLEMENTED_YET = "Remark command not implemented yet";
-
- @Override
- public CommandResult execute(Model model) throws CommandException {
- throw new CommandException(MESSAGE_NOT_IMPLEMENTED_YET);
- }
-```
-
-## Enhancing `RemarkCommand`
-
-Let’s change `RemarkCommand` to parse input from the user.
-
-### Make the command accept parameters
-
-We start by modifying the constructor of `RemarkCommand` to accept an `Index` and a `String`. While we are at it, let’s change the error message to echo the values. While this is not a replacement for tests, it is an obvious way to tell if our code is functioning as intended.
-
-``` java
-import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
-//...
-public class RemarkCommand extends Command {
- //...
- public static final String MESSAGE_ARGUMENTS = "Index: %1$d, Remark: %2$s";
-
- private final Index index;
- private final String remark;
-
- /**
- * @param index of the person in the filtered person list to edit the remark
- * @param remark of the person to be updated to
- */
- public RemarkCommand(Index index, String remark) {
- requireAllNonNull(index, remark);
-
- this.index = index;
- this.remark = remark;
- }
- @Override
- public CommandResult execute(Model model) throws CommandException {
- throw new CommandException(String.format(MESSAGE_ARGUMENTS, index.getOneBased(), remark));
- }
-
- @Override
- public boolean equals(Object other) {
- // short circuit if same object
- if (other == this) {
- return true;
- }
-
- // instanceof handles nulls
- if (!(other instanceof RemarkCommand)) {
- return false;
- }
-
- // state check
- RemarkCommand e = (RemarkCommand) other;
- return index.equals(e.index)
- && remark.equals(e.remark);
- }
-}
-```
-
-Your code should look something like [this](https://github.com/se-edu/addressbook-level3/commit/35eb7286f18a029d39cb7a29df8f172a001e4fd8#diff-34ace715a8a8d2e5a66e71289f017b47) after you are done.
-
-### Parse user input
-
-Now let’s move on to writing a parser that will extract the index and remark from the input provided by the user.
-
-Create a `RemarkCommandParser` class in the `seedu.address.logic.parser` package. The class must extend the `Parser` interface.
-
-
-
-Thankfully, `ArgumentTokenizer#tokenize()` makes it trivial to parse user input. Let’s take a look at the JavaDoc provided for the function to understand what it does.
-
-**`ArgumentTokenizer.java`:**
-
-``` java
-/**
- * Tokenizes an arguments string and returns an {@code ArgumentMultimap}
- * object that maps prefixes to their respective argument values. Only the
- * given prefixes will be recognized in the arguments string.
- *
- * @param argsString Arguments string of the form:
- * {@code preamble value value ...}
- * @param prefixes Prefixes to tokenize the arguments string with
- * @return ArgumentMultimap object that maps prefixes to their
- * arguments
- */
-```
-
-We can tell `ArgumentTokenizer#tokenize()` to look out for our new prefix `r/` and it will return us an instance of `ArgumentMultimap`. Now let’s find out what we need to do in order to obtain the Index and String that we need. Let’s look through `ArgumentMultimap` :
-
-**`ArgumentMultimap.java`:**
-
-``` java
-/**
- * Returns the last value of {@code prefix}.
- */
-public Optional getValue(Prefix prefix) {
- List values = getAllValues(prefix);
- return values.isEmpty() ? Optional.empty() :
- Optional.of(values.get(values.size() - 1));
-}
-```
-
-This appears to be what we need to get a String of the remark. But what about the Index? Let's take a quick peek at existing `Command` that uses an index to see how it is done.
-
-**`DeleteCommandParser.java`:**
-
-``` java
-Index index = ParserUtil.parseIndex(args);
-return new DeleteCommand(index);
-```
-
-There appears to be another utility class that obtains an `Index` from the input provided by the user.
-
-Now that we have the know-how to extract the data that we need from the user’s input, we can parse the user command and create a new instance of `RemarkCommand`, as given below.
-
-**`RemarkCommandParser.java`:**
-
-``` java
-public RemarkCommand parse(String args) throws ParseException {
- requireNonNull(args);
- ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args,
- PREFIX_REMARK);
-
- Index index;
- try {
- index = ParserUtil.parseIndex(argMultimap.getPreamble());
- } catch (IllegalValueException ive) {
- throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT,
- RemarkCommand.MESSAGE_USAGE), ive);
- }
-
- String remark = argMultimap.getValue(PREFIX_REMARK).orElse("");
-
- return new RemarkCommand(index, remark);
-}
-```
-
-
-
-:information_source: Don’t forget to update `AddressBookParser` to use our new `RemarkCommandParser`!
-
-
-
-If you are stuck, check out the sample
-[here](https://github.com/se-edu/addressbook-level3/commit/dc6d5139d08f6403da0ec624ea32bd79a2ae0cbf#diff-fc19ecee89c3732a62fbc8c840250508).
-
-## Add `Remark` to the model
-
-Now that we have all the information that we need, let’s lay the groundwork for propagating the remarks added into the in-memory storage of person data. We achieve that by working with the `Person` model. Each field in a Person is implemented as a separate class (e.g. a `Name` object represents the person’s name). That means we should add a `Remark` class so that we can use a `Remark` object to represent a remark given to a person.
-
-### Add a new `Remark` class
-
-Create a new `Remark` in `seedu.address.model.person`. Since a `Remark` is a field that is similar to `Address`, we can reuse a significant bit of code.
-
-A copy-paste and search-replace later, you should have something like [this](https://github.com/se-edu/addressbook-level3/commit/4516e099699baa9e2d51801bd26f016d812dedcc#diff-af2f075d24dfcd333876f0fbce321f25). Note how `Remark` has no constrains and thus does not require input
-validation.
-
-### Make use of `Remark`
-
-Let’s change `RemarkCommand` and `RemarkCommandParser` to use the new `Remark` class instead of plain `String`. These should be relatively simple changes.
-
-## Add a placeholder element for remark to the UI
-
-Without getting too deep into `fxml`, let’s go on a 5 minute adventure to get some placeholder text to show up for each person.
-
-Simply add the following to [`seedu.address.ui.PersonCard`](https://github.com/se-edu/addressbook-level3/commit/850b78879582f38accb05dd20c245963c65ea599#diff-0c6b6abcfac8c205e075294f25e851fe).
-
-**`PersonCard.java`:**
-
-``` java
-@FXML
-private Label remark;
-```
-
-
-`@FXML` is an annotation that marks a private or protected field and makes it accessible to FXML. It might sound like Greek to you right now, don’t worry — we will get back to it later.
-
-Then insert the following into [`main/resources/view/PersonListCard.fxml`](https://github.com/se-edu/addressbook-level3/commit/850b78879582f38accb05dd20c245963c65ea599#diff-12580431f55d7880578aa4c16f249e71).
-
-**`PersonListCard.fxml`:**
-
-``` xml
-
-```
-
-That’s it! Fire up the application again and you should see something like this:
-
-
-
-## Modify `Person` to support a `Remark` field
-
-Since `PersonCard` displays data from a `Person`, we need to update `Person` to get our `Remark` displayed!
-
-### Modify `Person`
-
-We change the constructor of `Person` to take a `Remark`. We will also need to define new fields and accessors accordingly to store our new addition.
-
-### Update other usages of `Person`
-
-Unfortunately, a change to `Person` will cause other commands to break, you will have to modify these commands to use the updated `Person`!
-
-
-
-:bulb: Use the `Find Usages` feature in IntelliJ IDEA on the `Person` class to find these commands.
-
-
-
-Refer to [this commit](https://github.com/se-edu/addressbook-level3/commit/ce998c37e65b92d35c91d28c7822cd139c2c0a5c) and check that you have got everything in order!
-
-
-## Updating Storage
-
-AddressBook stores data by serializing `JsonAdaptedPerson` into `json` with the help of an external library — Jackson. Let’s update `JsonAdaptedPerson` to work with our new `Person`!
-
-While the changes to code may be minimal, the test data will have to be updated as well.
-
-
-
-:exclamation: You must delete AddressBook’s storage file located at `/data/addressbook.json` before running it! Not doing so will cause AddressBook to default to an empty address book!
-
-
-
-Check out [this commit](https://github.com/se-edu/addressbook-level3/commit/556cbd0e03ff224d7a68afba171ad2eb0ce56bbf)
-to see what the changes entail.
-
-## Finalizing the UI
-
-Now that we have finalized the `Person` class and its dependencies, we can now bind the `Remark` field to the UI.
-
-Just add [this one line of code!](https://github.com/se-edu/addressbook-level3/commit/5b98fee11b6b3f5749b6b943c4f3bd3aa049b692)
-
-**`PersonCard.java`:**
-
-``` java
-public PersonCard(Person person, int displayedIndex) {
- //...
- remark.setText(person.getRemark().value);
-}
-```
-
-
-
-## Putting everything together
-
-After the previous step, we notice a peculiar regression — we went from displaying something to nothing at all. However, this is expected behavior as we are yet to update the `RemarkCommand` to make use of the code we've been adding in the last few steps.
-
-### Update `RemarkCommand` and `RemarkCommandParser`
-
-In this last step, we modify `RemarkCommand#execute()` to change the `Remark` of a `Person`. Since all fields in a `Person` are immutable, we create a new instance of a `Person` with the values that we want and
-save it with `Model#setPerson()`.
-
-**`RemarkCommand.java`:**
-
-``` java
-//...
- public static final String MESSAGE_ADD_REMARK_SUCCESS = "Added remark to Person: %1$s";
- public static final String MESSAGE_DELETE_REMARK_SUCCESS = "Removed remark from Person: %1$s";
-//...
- @Override
- public CommandResult execute(Model model) throws CommandException {
- List lastShownList = model.getFilteredPersonList();
-
- if (index.getZeroBased() >= lastShownList.size()) {
- throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
- }
-
- Person personToEdit = lastShownList.get(index.getZeroBased());
- Person editedPerson = new Person(personToEdit.getName(), personToEdit.getPhone(), personToEdit.getEmail(),
- personToEdit.getAddress(), remark, personToEdit.getTags());
-
- model.setPerson(personToEdit, editedPerson);
- model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
-
- return new CommandResult(generateSuccessMessage(editedPerson));
- }
-
- /**
- * Generates a command execution success message based on whether the remark is added to or removed from
- * {@code personToEdit}.
- */
- private String generateSuccessMessage(Person personToEdit) {
- String message = !remark.value.isEmpty() ? MESSAGE_ADD_REMARK_SUCCESS : MESSAGE_DELETE_REMARK_SUCCESS;
- return String.format(message, personToEdit);
- }
-```
-
-
-
-## Writing tests
-
-Tests are crucial to ensuring that bugs don’t slip into the codebase unnoticed. This is especially true for large code bases where a change might lead to unintended behavior.
-
-Let’s verify the correctness of our code by writing some tests!
-
-### Automatically generating tests
-
-The goal is to write effective and efficient tests to ensure that `RemarkCommand#execute()` behaves as expected.
-
-The convention for test names is `methodName_testScenario_expectedResult`. An example would be
-`execute_filteredList_success`.
-
-Let’s create a test for `RemarkCommand#execute()` to test that adding a remark works. On `IntelliJ IDEA` you can bring up the context menu and choose to `Go To` \> `Test` or use the appropriate keyboard shortcut.
-
-
-
-Then, create a test for the `execute` method.
-
-
-
-Following convention, let’s change the name of the generated method to `execute_addRemarkUnfilteredList_success`.
-
-Let’s use the utility functions provided in `CommandTestUtil`. The functions ensure that commands produce the expected `CommandResult` and output the correct message. In this case, `CommandTestUtil#assertCommandSuccess` is the best fit as we are testing that a `RemarkCommand` will successfully add a `Remark`.
-
-You should end up with a test that looks something like [this](https://github.com/se-edu/addressbook-level3/commit/fac8f3fd855d55831ca0cc73313b5943d49d4d6e#diff-d749de38392f7ea504da7824641ba8d9).
-
-## Conclusion
-
-This concludes the tutorial for adding a new `Command` to AddressBook.
diff --git a/docs/tutorials/RemovingFields.md b/docs/tutorials/RemovingFields.md
deleted file mode 100644
index aa8e0baaad9..00000000000
--- a/docs/tutorials/RemovingFields.md
+++ /dev/null
@@ -1,103 +0,0 @@
----
-layout: page
-title: "Tutorial: Removing Fields"
----
-
-> Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.
->
-> — Antoine de Saint-Exupery
-
-When working on AddressBook, you will most likely find that some features and fields that are no longer necessary. In scenarios like this, you can consider refactoring the existing `Person` model to suit your use case.
-
-In this tutorial, we’ll do exactly just that and remove the `address` field from `Person`.
-
-* Table of Contents
-{:toc}
-
-## Safely deleting `Address`
-
-Fortunately, IntelliJ IDEA provides a robust refactoring tool that can identify *most* usages. Let’s try to use it as much as we can.
-
-### Assisted refactoring
-
-The `address` field in `Person` is actually an instance of the `seedu.address.model.person.Address` class. Since removing the `Address` class will break the application, we start by identifying `Address`'s usages. This allows us to see code that depends on `Address` to function properly and edit them on a case-by-case basis. Right-click the `Address` class and select `Refactor` \> `Safe Delete` through the menu.
-
-
-
-Choose to `View Usages` and you should be presented with a list of `Safe Delete Conflicts`. These conflicts describe locations in which the `Address` class is used.
-
-
-
-Remove usages of `Address` by performing `Safe Delete`s on each entry. You will need to exercise discretion when removing usages of `Address`. Functions like `ParserUtil#parseAddress()` can be safely removed but its usages must be removed as well. Other usages like in `EditPersonDescriptor` may require more careful inspection.
-
-Let’s try removing references to `Address` in `EditPersonDescriptor`.
-
-1. Safe delete the field `address` in `EditPersonDescriptor`.
-
-1. Select `Yes` when prompted to remove getters and setters.
-
-1. Select `View Usages` again.
- 
-
-1. Remove the usages of `address` and select `Do refactor` when you are done.
-
-
-
- :bulb: **Tip:** Removing usages may result in errors. Exercise discretion and fix them. For example, removing the `address` field from the `Person` class will require you to modify its constructor.
-
-
-1. Repeat the steps for the remaining usages of `Address`
-
-After you are done, verify that the application still works by compiling and running it again.
-
-### Manual refactoring
-
-Unfortunately, there are usages of `Address` that IntelliJ IDEA cannot identify. You can find them by searching for instances of the word `address` in your code (`Edit` \> `Find` \> `Find in path`).
-
-Places of interest to look out for would be resources used by the application. `main/resources` contains images and `fxml` files used by the application and `test/resources` contains test data. For example, there is a `$address` in each `PersonCard` that has not been removed nor identified.
-
-
-
-A quick look at the `PersonCard` class and its `fxml` file quickly reveals why it slipped past the automated refactoring.
-
-**`PersonCard.java`**
-
-``` java
-...
-@FXML
-private Label address;
-...
-```
-
-**`PersonCard.fxml`**
-
-``` xml
-...
-
-
-
-...
-```
-
-After removing the `Label`, we can proceed to formally test our code. If everything went well, you should have most of your tests pass. Fix any remaining errors until the tests all pass.
-
-## Tidying up
-
-At this point, your application is working as intended and all your tests are passing. What’s left to do is to clean up references to `Address` in test data and documentation.
-
-In `src/test/data/`, data meant for testing purposes are stored. While keeping the `address` field in the json files does not cause the tests to fail, it is not good practice to let cruft from old features accumulate.
-
-**`invalidPersonAddressBook.json`:**
-
-```json
-{
- "persons": [ {
- "name": "Person with invalid name field: Ha!ns Mu@ster",
- "phone": "9482424",
- "email": "hans@example.com",
- "address": "4th street"
- } ]
-}
-```
-
-You can go through each individual `json` file and manually remove the `address` field.
diff --git a/docs/tutorials/TracingCode.md b/docs/tutorials/TracingCode.md
deleted file mode 100644
index bd34ed498cd..00000000000
--- a/docs/tutorials/TracingCode.md
+++ /dev/null
@@ -1,250 +0,0 @@
----
-layout: page
-title: "Tutorial: Tracing code"
----
-
-> Indeed, the ratio of time spent reading versus writing is well over 10 to 1. We are constantly reading old code as part of the effort to write new code. …\[Therefore,\] making it easy to read makes it easier to write.
->
-> — Robert C. Martin Clean Code: A Handbook of Agile Software Craftsmanship
-
-When trying to understand an unfamiliar code base, one common strategy used is to trace some representative execution path through the code base. One easy way to trace an execution path is to use a debugger to step through the code. In this tutorial, you will be using the IntelliJ IDEA’s debugger to trace the execution path of a specific user command.
-
-* Table of Contents
-{:toc}
-
-## Before we start
-
-Before we jump into the code, it is useful to get an idea of the overall structure and the high-level behavior of the application. This is provided in the 'Architecture' section of the developer guide. In particular, the architecture diagram (reproduced below), tells us that the App consists of several components.
-
-
-
-It also has a sequence diagram (reproduced below) that tells us how a command propagates through the App.
-
-
-
-Note how the diagram shows only how the execution flows *between* the main components. That is, it does not show details of the execution path *inside* each component. By hiding those details, the diagram succeeds in informing the reader about the overall execution path of a command without overwhelming the reader with too much details. In this tutorial, you aim to find those omitted details so that you get a more in-depth understanding of the code base.
-
-Before we proceed, ensure that you have done the following:
-1. Read the [*Architecture* section of the DG](../DeveloperGuide.md#architecture)
-1. Set up the project in Intellij IDEA
-1. Learn basic debugging features of Intellij IDEA
-
-## Setting a break point
-
-As you know, the first step of debugging is to put in a breakpoint where you want the debugger to pause the execution. For example, if you are trying to understand how the App starts up, you would put a breakpoint in the first statement of the `main` method. In our case, we would want to begin the tracing at the very point where the App start processing user input (i.e., somewhere in the UI component), and then trace through how the execution proceeds through the UI component. However, the execution path through a GUI is often somewhat obscure due to various *event-driven mechanisms* used by GUI frameworks, which happens to be the case here too. Therefore, let us put the breakpoint where the UI transfers control to the Logic component. According to the sequence diagram, the UI component yields control to the Logic component through a method named `execute`. Searching through the code base for `execute()` yields a promising candidate in `seedu.address.ui.CommandBox.CommandExecutor`.
-
-
-
-A quick look at the class confirms that this is indeed close to what we’re looking for. However, it is just an `Interface`. Let’s delve further and find the implementation of the interface by using the `Find Usages` feature in IntelliJ IDEA.
-
-
-
-Bingo\! `MainWindow#executeCommand()` seems to be exactly what we’re looking for\!
-
-Now let’s set the breakpoint. First, double-click the item to reach the corresponding code. Once there, click on the left gutter to set a breakpoint, as shown below.
- 
-
-## Tracing the execution path
-
-Recall from the User Guide that the `edit` command has the format: `edit INDEX [n/NAME] [p/PHONE] [e/EMAIL] [a/ADDRESS] [t/TAG]…` For this tutorial we will be issuing the command `edit 1 n/Alice Yeoh`.
-
-
-
-:bulb: **Tip:** Over the course of the debugging session, you will encounter every major component in the application. Try to jot down what happens inside the component and where the execution transfers to another component.
-
-
-1. To start the debugging session, simply `Run` \> `Debug Main`
-
-1. Enter `edit 1 n/Alice Yeoh` into the command box and press `Enter`.
-
-1. The Debugger tool window should show up and look something like this:
- 
-
-1. Use the `Show execution point` feature to jump to the line of code that we stopped at:
- 
-
-1. `CommandResult commandResult = logic.execute(commandText);` is the line that you end up at.
-
-1. We are interested in the `logic.execute(commandText)` portion of that line so let’s `Step in` into that method call:
- 
-
-1. We end up in `LogicManager#execute()`. Let’s take a look at the body of the method and annotate what we can deduce.
-
- **LogicManager\#execute().**
-
- ``` java
- @Override
- public CommandResult execute(String commandText)
- throws CommandException, ParseException {
-
- //Logging, safe to ignore
- logger.info("----------------[USER COMMAND][" + commandText + "]");
-
- CommandResult commandResult;
- //Parse user input from String to a Command
- Command command = addressBookParser.parseCommand(commandText);
- //Executes the Command and stores the result
- commandResult = command.execute(model);
-
- try {
- //We can deduce that the previous line of code modifies model in some way
- // since it's being stored here.
- storage.saveAddressBook(model.getAddressBook());
- } catch (IOException ioe) {
- throw new CommandException(FILE_OPS_ERROR_MESSAGE + ioe, ioe);
- }
-
- return commandResult;
- }
- ```
-
-1. `LogicManager#execute()` appears to delegate most of the heavy lifting to other components. Let’s take a closer look at each one.
-
-1. `Step over` the logging code since it is of no interest to us now. 
-
-1. `Step into` the line where user input in parsed from a String to a Command.
-
- **`AddressBookParser\#parseCommand()`**
-
- ``` java
- public Command parseCommand(String userInput) throws ParseException {
- ...
- final String commandWord = matcher.group("commandWord");
- final String arguments = matcher.group("arguments");
- ...
- ```
-
-1. `Step over` until you reach the `switch` statement. The `Variables` window now shows the value of both `commandWord` and `arguments`:
- 
-
-1. We see that the value of `commandWord` is now `edit` but `arguments` is still not processed in any meaningful way.
-
-1. Stepping into the `switch`, we obviously stop at **`AddressBookParser\#parseCommand()`.**
-
- ``` java
- ...
- case EditCommand.COMMAND_WORD:
- return new EditCommandParser().parse(arguments);
- ...
- ```
-
-1. Let’s see what `EditCommandParser#parse()` does by stepping into it.
-
-1. Stepping through the method shows that it calls `ArgumentTokenizer#tokenize()` and `ParserUtil#parseIndex()` to obtain the arguments and index required.
-
-
:bulb: **Tip:** Sometimes you might end up stepping into functions that are not of interest. Simply `step out` of them\!
-
-
-1. The rest of the method seems to exhaustively check for the existence of each possible parameter of the `edit` command and store any possible changes in an `EditPersonDescriptor`. Recall that we can verify the contents of `editPersonDesciptor` through the `Variable` tool window.
- 
-
-1. Let’s continue stepping through until we return to `LogicManager#execute()`.
-
- The sequence diagram below shows the details of the execution path through the Logic component. Does the execution path you traced in the code so far matches with the diagram?
- 
-
-1. Now let’s see what happens when we call `command#execute()`\!
-
- **`EditCommand\#execute()`:**
-
- ``` java
- @Override
- public CommandResult execute(Model model) throws CommandException {
- ...
- Person personToEdit = lastShownList.get(index.getZeroBased());
- Person editedPerson = createEditedPerson(personToEdit, editPersonDescriptor);
- if (!personToEdit.isSamePerson(editedPerson) && model.hasPerson(editedPerson)) {
- throw new CommandException(MESSAGE_DUPLICATE_PERSON);
- }
- model.setPerson(personToEdit, editedPerson);
- model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
- return new CommandResult(String.format(MESSAGE_EDIT_PERSON_SUCCESS, editedPerson));
- }
- ```
-
-1. As suspected, `command#execute()` does indeed make changes to `model`.
-
-1. We can a closer look at how storage works by repeatedly stepping into the code until we arrive at
- `JsonAddressBook#saveAddressBook()`.
-
-1. Again, it appears that the heavy lifting is delegated. Let’s take a look at `JsonSerializableAddressBook`'s constructor.
-
- **`JsonSerializableAddressBook\#JsonSerializableAddressBook()`:**
-
- ``` java
- /**
- * Converts a given {@code ReadOnlyAddressBook} into this class for Jackson use.
- *
- * @param source future changes to this will not affect the created
- * {@code JsonSerializableAddressBook}.
- */
- public JsonSerializableAddressBook(ReadOnlyAddressBook source) {
- persons.addAll(
- source.getPersonList()
- .stream()
- .map(JsonAdaptedPerson::new)
- .collect(Collectors.toList()));
- }
- ```
-
-1. It appears that a `JsonAdaptedPerson` is created for each `Person` and then added to the `JsonSerializableAddressBook`.
-
-1. We can continue to step through until we return to `MainWindow#executeCommand()`.
-
-1. Stepping into `resultDisplay.setFeedbackToUser(commandResult.getFeedbackToUser());`, we end up in:
-
- **`ResultDisplay\#setFeedbackToUser()`**
-
- ``` java
- public void setFeedbackToUser(String feedbackToUser) {
- requireNonNull(feedbackToUser);
- resultDisplay.setText(feedbackToUser);
- }
- ```
-
-1. Finally, we step through until we reach the end of
- `MainWindow#executeCommand()`.
-
-## Conclusion
-
-In this tutorial, we traced a valid edit command from raw user input to
-the result being displayed to the user. From this tutorial, you learned
-more about the inner workings of AddressBook and how the various
-components mesh together to form one cohesive product.
-
-Here are some quick questions you can try to answer based on your
-execution path tracing. In some cases, you can do further tracing for
-the given commands to find exactly what happens.
-
-1. In this tutorial, we traced the "happy path" (i.e., no errors). What
- do you think will happen if we traced the following commands
- instead? What exceptions do you think will be thrown(if any), where
- will the exceptions be thrown and where will they be handled?
-
- 1. `redit 1 n/Alice Yu`
-
- 2. `edit 0 n/Alice Yu`
-
- 3. `edit 1 n/Alex Yeoh`
-
- 4. `edit 1`
-
- 5. `edit 1 n/アリス ユー`
-
- 6. `edit 1 t/one t/two t/three t/one`
-
-2. What components will you have to modify to perform the following
- enhancements to the application?
-
- 1. Make command words case-insensitive
-
- 2. Allow `delete` to remove more than one index at a time
-
- 3. Save the address book in the CSV format instead
-
- 4. Add a new command
-
- 5. Add a new field to `Person`
-
- 6. Add a new entity to the address book
diff --git a/src/main/java/seedu - Shortcut.lnk b/src/main/java/seedu - Shortcut.lnk
new file mode 100644
index 00000000000..4a015461add
Binary files /dev/null and b/src/main/java/seedu - Shortcut.lnk differ
diff --git a/src/main/java/seedu/address/commons/core/Messages.java b/src/main/java/seedu/address/commons/core/Messages.java
deleted file mode 100644
index 1deb3a1e469..00000000000
--- a/src/main/java/seedu/address/commons/core/Messages.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package seedu.address.commons.core;
-
-/**
- * Container for user visible messages.
- */
-public class Messages {
-
- public static final String MESSAGE_UNKNOWN_COMMAND = "Unknown command";
- public static final String MESSAGE_INVALID_COMMAND_FORMAT = "Invalid command format! \n%1$s";
- public static final String MESSAGE_INVALID_PERSON_DISPLAYED_INDEX = "The person index provided is invalid";
- public static final String MESSAGE_PERSONS_LISTED_OVERVIEW = "%1$d persons listed!";
-
-}
diff --git a/src/main/java/seedu/address/logic/commands/AddCommand.java b/src/main/java/seedu/address/logic/commands/AddCommand.java
deleted file mode 100644
index 71656d7c5c8..00000000000
--- a/src/main/java/seedu/address/logic/commands/AddCommand.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package seedu.address.logic.commands;
-
-import static java.util.Objects.requireNonNull;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
-
-import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.model.Model;
-import seedu.address.model.person.Person;
-
-/**
- * Adds a person to the address book.
- */
-public class AddCommand extends Command {
-
- public static final String COMMAND_WORD = "add";
-
- public static final String MESSAGE_USAGE = COMMAND_WORD + ": Adds a person to the address book. "
- + "Parameters: "
- + PREFIX_NAME + "NAME "
- + PREFIX_PHONE + "PHONE "
- + PREFIX_EMAIL + "EMAIL "
- + PREFIX_ADDRESS + "ADDRESS "
- + "[" + PREFIX_TAG + "TAG]...\n"
- + "Example: " + COMMAND_WORD + " "
- + PREFIX_NAME + "John Doe "
- + PREFIX_PHONE + "98765432 "
- + PREFIX_EMAIL + "johnd@example.com "
- + PREFIX_ADDRESS + "311, Clementi Ave 2, #02-25 "
- + PREFIX_TAG + "friends "
- + PREFIX_TAG + "owesMoney";
-
- public static final String MESSAGE_SUCCESS = "New person added: %1$s";
- public static final String MESSAGE_DUPLICATE_PERSON = "This person already exists in the address book";
-
- private final Person toAdd;
-
- /**
- * Creates an AddCommand to add the specified {@code Person}
- */
- public AddCommand(Person person) {
- requireNonNull(person);
- toAdd = person;
- }
-
- @Override
- public CommandResult execute(Model model) throws CommandException {
- requireNonNull(model);
-
- if (model.hasPerson(toAdd)) {
- throw new CommandException(MESSAGE_DUPLICATE_PERSON);
- }
-
- model.addPerson(toAdd);
- return new CommandResult(String.format(MESSAGE_SUCCESS, toAdd));
- }
-
- @Override
- public boolean equals(Object other) {
- return other == this // short circuit if same object
- || (other instanceof AddCommand // instanceof handles nulls
- && toAdd.equals(((AddCommand) other).toAdd));
- }
-}
diff --git a/src/main/java/seedu/address/logic/commands/DeleteCommand.java b/src/main/java/seedu/address/logic/commands/DeleteCommand.java
deleted file mode 100644
index 02fd256acba..00000000000
--- a/src/main/java/seedu/address/logic/commands/DeleteCommand.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package seedu.address.logic.commands;
-
-import static java.util.Objects.requireNonNull;
-
-import java.util.List;
-
-import seedu.address.commons.core.Messages;
-import seedu.address.commons.core.index.Index;
-import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.model.Model;
-import seedu.address.model.person.Person;
-
-/**
- * Deletes a person identified using it's displayed index from the address book.
- */
-public class DeleteCommand extends Command {
-
- public static final String COMMAND_WORD = "delete";
-
- public static final String MESSAGE_USAGE = COMMAND_WORD
- + ": Deletes the person identified by the index number used in the displayed person list.\n"
- + "Parameters: INDEX (must be a positive integer)\n"
- + "Example: " + COMMAND_WORD + " 1";
-
- public static final String MESSAGE_DELETE_PERSON_SUCCESS = "Deleted Person: %1$s";
-
- private final Index targetIndex;
-
- public DeleteCommand(Index targetIndex) {
- this.targetIndex = targetIndex;
- }
-
- @Override
- public CommandResult execute(Model model) throws CommandException {
- requireNonNull(model);
- List lastShownList = model.getFilteredPersonList();
-
- if (targetIndex.getZeroBased() >= lastShownList.size()) {
- throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
- }
-
- Person personToDelete = lastShownList.get(targetIndex.getZeroBased());
- model.deletePerson(personToDelete);
- return new CommandResult(String.format(MESSAGE_DELETE_PERSON_SUCCESS, personToDelete));
- }
-
- @Override
- public boolean equals(Object other) {
- return other == this // short circuit if same object
- || (other instanceof DeleteCommand // instanceof handles nulls
- && targetIndex.equals(((DeleteCommand) other).targetIndex)); // state check
- }
-}
diff --git a/src/main/java/seedu/address/logic/commands/EditCommand.java b/src/main/java/seedu/address/logic/commands/EditCommand.java
deleted file mode 100644
index 7e36114902f..00000000000
--- a/src/main/java/seedu/address/logic/commands/EditCommand.java
+++ /dev/null
@@ -1,226 +0,0 @@
-package seedu.address.logic.commands;
-
-import static java.util.Objects.requireNonNull;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
-import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS;
-
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Optional;
-import java.util.Set;
-
-import seedu.address.commons.core.Messages;
-import seedu.address.commons.core.index.Index;
-import seedu.address.commons.util.CollectionUtil;
-import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.model.Model;
-import seedu.address.model.person.Address;
-import seedu.address.model.person.Email;
-import seedu.address.model.person.Name;
-import seedu.address.model.person.Person;
-import seedu.address.model.person.Phone;
-import seedu.address.model.tag.Tag;
-
-/**
- * Edits the details of an existing person in the address book.
- */
-public class EditCommand extends Command {
-
- public static final String COMMAND_WORD = "edit";
-
- public static final String MESSAGE_USAGE = COMMAND_WORD + ": Edits the details of the person identified "
- + "by the index number used in the displayed person list. "
- + "Existing values will be overwritten by the input values.\n"
- + "Parameters: INDEX (must be a positive integer) "
- + "[" + PREFIX_NAME + "NAME] "
- + "[" + PREFIX_PHONE + "PHONE] "
- + "[" + PREFIX_EMAIL + "EMAIL] "
- + "[" + PREFIX_ADDRESS + "ADDRESS] "
- + "[" + PREFIX_TAG + "TAG]...\n"
- + "Example: " + COMMAND_WORD + " 1 "
- + PREFIX_PHONE + "91234567 "
- + PREFIX_EMAIL + "johndoe@example.com";
-
- public static final String MESSAGE_EDIT_PERSON_SUCCESS = "Edited Person: %1$s";
- public static final String MESSAGE_NOT_EDITED = "At least one field to edit must be provided.";
- public static final String MESSAGE_DUPLICATE_PERSON = "This person already exists in the address book.";
-
- private final Index index;
- private final EditPersonDescriptor editPersonDescriptor;
-
- /**
- * @param index of the person in the filtered person list to edit
- * @param editPersonDescriptor details to edit the person with
- */
- public EditCommand(Index index, EditPersonDescriptor editPersonDescriptor) {
- requireNonNull(index);
- requireNonNull(editPersonDescriptor);
-
- this.index = index;
- this.editPersonDescriptor = new EditPersonDescriptor(editPersonDescriptor);
- }
-
- @Override
- public CommandResult execute(Model model) throws CommandException {
- requireNonNull(model);
- List lastShownList = model.getFilteredPersonList();
-
- if (index.getZeroBased() >= lastShownList.size()) {
- throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
- }
-
- Person personToEdit = lastShownList.get(index.getZeroBased());
- Person editedPerson = createEditedPerson(personToEdit, editPersonDescriptor);
-
- if (!personToEdit.isSamePerson(editedPerson) && model.hasPerson(editedPerson)) {
- throw new CommandException(MESSAGE_DUPLICATE_PERSON);
- }
-
- model.setPerson(personToEdit, editedPerson);
- model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
- return new CommandResult(String.format(MESSAGE_EDIT_PERSON_SUCCESS, editedPerson));
- }
-
- /**
- * Creates and returns a {@code Person} with the details of {@code personToEdit}
- * edited with {@code editPersonDescriptor}.
- */
- private static Person createEditedPerson(Person personToEdit, EditPersonDescriptor editPersonDescriptor) {
- assert personToEdit != null;
-
- Name updatedName = editPersonDescriptor.getName().orElse(personToEdit.getName());
- Phone updatedPhone = editPersonDescriptor.getPhone().orElse(personToEdit.getPhone());
- Email updatedEmail = editPersonDescriptor.getEmail().orElse(personToEdit.getEmail());
- Address updatedAddress = editPersonDescriptor.getAddress().orElse(personToEdit.getAddress());
- Set updatedTags = editPersonDescriptor.getTags().orElse(personToEdit.getTags());
-
- return new Person(updatedName, updatedPhone, updatedEmail, updatedAddress, updatedTags);
- }
-
- @Override
- public boolean equals(Object other) {
- // short circuit if same object
- if (other == this) {
- return true;
- }
-
- // instanceof handles nulls
- if (!(other instanceof EditCommand)) {
- return false;
- }
-
- // state check
- EditCommand e = (EditCommand) other;
- return index.equals(e.index)
- && editPersonDescriptor.equals(e.editPersonDescriptor);
- }
-
- /**
- * Stores the details to edit the person with. Each non-empty field value will replace the
- * corresponding field value of the person.
- */
- public static class EditPersonDescriptor {
- private Name name;
- private Phone phone;
- private Email email;
- private Address address;
- private Set tags;
-
- public EditPersonDescriptor() {}
-
- /**
- * Copy constructor.
- * A defensive copy of {@code tags} is used internally.
- */
- public EditPersonDescriptor(EditPersonDescriptor toCopy) {
- setName(toCopy.name);
- setPhone(toCopy.phone);
- setEmail(toCopy.email);
- setAddress(toCopy.address);
- setTags(toCopy.tags);
- }
-
- /**
- * Returns true if at least one field is edited.
- */
- public boolean isAnyFieldEdited() {
- return CollectionUtil.isAnyNonNull(name, phone, email, address, tags);
- }
-
- public void setName(Name name) {
- this.name = name;
- }
-
- public Optional getName() {
- return Optional.ofNullable(name);
- }
-
- public void setPhone(Phone phone) {
- this.phone = phone;
- }
-
- public Optional getPhone() {
- return Optional.ofNullable(phone);
- }
-
- public void setEmail(Email email) {
- this.email = email;
- }
-
- public Optional getEmail() {
- return Optional.ofNullable(email);
- }
-
- public void setAddress(Address address) {
- this.address = address;
- }
-
- public Optional getAddress() {
- return Optional.ofNullable(address);
- }
-
- /**
- * Sets {@code tags} to this object's {@code tags}.
- * A defensive copy of {@code tags} is used internally.
- */
- public void setTags(Set tags) {
- this.tags = (tags != null) ? new HashSet<>(tags) : null;
- }
-
- /**
- * Returns an unmodifiable tag set, which throws {@code UnsupportedOperationException}
- * if modification is attempted.
- * Returns {@code Optional#empty()} if {@code tags} is null.
- */
- public Optional> getTags() {
- return (tags != null) ? Optional.of(Collections.unmodifiableSet(tags)) : Optional.empty();
- }
-
- @Override
- public boolean equals(Object other) {
- // short circuit if same object
- if (other == this) {
- return true;
- }
-
- // instanceof handles nulls
- if (!(other instanceof EditPersonDescriptor)) {
- return false;
- }
-
- // state check
- EditPersonDescriptor e = (EditPersonDescriptor) other;
-
- return getName().equals(e.getName())
- && getPhone().equals(e.getPhone())
- && getEmail().equals(e.getEmail())
- && getAddress().equals(e.getAddress())
- && getTags().equals(e.getTags());
- }
- }
-}
diff --git a/src/main/java/seedu/address/logic/commands/FindCommand.java b/src/main/java/seedu/address/logic/commands/FindCommand.java
deleted file mode 100644
index d6b19b0a0de..00000000000
--- a/src/main/java/seedu/address/logic/commands/FindCommand.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package seedu.address.logic.commands;
-
-import static java.util.Objects.requireNonNull;
-
-import seedu.address.commons.core.Messages;
-import seedu.address.model.Model;
-import seedu.address.model.person.NameContainsKeywordsPredicate;
-
-/**
- * Finds and lists all persons in address book whose name contains any of the argument keywords.
- * Keyword matching is case insensitive.
- */
-public class FindCommand extends Command {
-
- public static final String COMMAND_WORD = "find";
-
- public static final String MESSAGE_USAGE = COMMAND_WORD + ": Finds all persons whose names contain any of "
- + "the specified keywords (case-insensitive) and displays them as a list with index numbers.\n"
- + "Parameters: KEYWORD [MORE_KEYWORDS]...\n"
- + "Example: " + COMMAND_WORD + " alice bob charlie";
-
- private final NameContainsKeywordsPredicate predicate;
-
- public FindCommand(NameContainsKeywordsPredicate predicate) {
- this.predicate = predicate;
- }
-
- @Override
- public CommandResult execute(Model model) {
- requireNonNull(model);
- model.updateFilteredPersonList(predicate);
- return new CommandResult(
- String.format(Messages.MESSAGE_PERSONS_LISTED_OVERVIEW, model.getFilteredPersonList().size()));
- }
-
- @Override
- public boolean equals(Object other) {
- return other == this // short circuit if same object
- || (other instanceof FindCommand // instanceof handles nulls
- && predicate.equals(((FindCommand) other).predicate)); // state check
- }
-}
diff --git a/src/main/java/seedu/address/logic/commands/ListCommand.java b/src/main/java/seedu/address/logic/commands/ListCommand.java
deleted file mode 100644
index 84be6ad2596..00000000000
--- a/src/main/java/seedu/address/logic/commands/ListCommand.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package seedu.address.logic.commands;
-
-import static java.util.Objects.requireNonNull;
-import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS;
-
-import seedu.address.model.Model;
-
-/**
- * Lists all persons in the address book to the user.
- */
-public class ListCommand extends Command {
-
- public static final String COMMAND_WORD = "list";
-
- public static final String MESSAGE_SUCCESS = "Listed all persons";
-
-
- @Override
- public CommandResult execute(Model model) {
- requireNonNull(model);
- model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
- return new CommandResult(MESSAGE_SUCCESS);
- }
-}
diff --git a/src/main/java/seedu/address/logic/parser/AddCommandParser.java b/src/main/java/seedu/address/logic/parser/AddCommandParser.java
deleted file mode 100644
index 3b8bfa035e8..00000000000
--- a/src/main/java/seedu/address/logic/parser/AddCommandParser.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package seedu.address.logic.parser;
-
-import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
-
-import java.util.Set;
-import java.util.stream.Stream;
-
-import seedu.address.logic.commands.AddCommand;
-import seedu.address.logic.parser.exceptions.ParseException;
-import seedu.address.model.person.Address;
-import seedu.address.model.person.Email;
-import seedu.address.model.person.Name;
-import seedu.address.model.person.Person;
-import seedu.address.model.person.Phone;
-import seedu.address.model.tag.Tag;
-
-/**
- * Parses input arguments and creates a new AddCommand object
- */
-public class AddCommandParser implements Parser {
-
- /**
- * Parses the given {@code String} of arguments in the context of the AddCommand
- * and returns an AddCommand object for execution.
- * @throws ParseException if the user input does not conform the expected format
- */
- public AddCommand parse(String args) throws ParseException {
- ArgumentMultimap argMultimap =
- ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, PREFIX_TAG);
-
- if (!arePrefixesPresent(argMultimap, PREFIX_NAME, PREFIX_ADDRESS, PREFIX_PHONE, PREFIX_EMAIL)
- || !argMultimap.getPreamble().isEmpty()) {
- throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE));
- }
-
- Name name = ParserUtil.parseName(argMultimap.getValue(PREFIX_NAME).get());
- Phone phone = ParserUtil.parsePhone(argMultimap.getValue(PREFIX_PHONE).get());
- Email email = ParserUtil.parseEmail(argMultimap.getValue(PREFIX_EMAIL).get());
- Address address = ParserUtil.parseAddress(argMultimap.getValue(PREFIX_ADDRESS).get());
- Set tagList = ParserUtil.parseTags(argMultimap.getAllValues(PREFIX_TAG));
-
- Person person = new Person(name, phone, email, address, tagList);
-
- return new AddCommand(person);
- }
-
- /**
- * Returns true if none of the prefixes contains empty {@code Optional} values in the given
- * {@code ArgumentMultimap}.
- */
- private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) {
- return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent());
- }
-
-}
diff --git a/src/main/java/seedu/address/logic/parser/AddressBookParser.java b/src/main/java/seedu/address/logic/parser/AddressBookParser.java
deleted file mode 100644
index 1e466792b46..00000000000
--- a/src/main/java/seedu/address/logic/parser/AddressBookParser.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package seedu.address.logic.parser;
-
-import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
-import static seedu.address.commons.core.Messages.MESSAGE_UNKNOWN_COMMAND;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import seedu.address.logic.commands.AddCommand;
-import seedu.address.logic.commands.ClearCommand;
-import seedu.address.logic.commands.Command;
-import seedu.address.logic.commands.DeleteCommand;
-import seedu.address.logic.commands.EditCommand;
-import seedu.address.logic.commands.ExitCommand;
-import seedu.address.logic.commands.FindCommand;
-import seedu.address.logic.commands.HelpCommand;
-import seedu.address.logic.commands.ListCommand;
-import seedu.address.logic.parser.exceptions.ParseException;
-
-/**
- * Parses user input.
- */
-public class AddressBookParser {
-
- /**
- * Used for initial separation of command word and args.
- */
- private static final Pattern BASIC_COMMAND_FORMAT = Pattern.compile("(?\\S+)(?.*)");
-
- /**
- * Parses user input into command for execution.
- *
- * @param userInput full user input string
- * @return the command based on the user input
- * @throws ParseException if the user input does not conform the expected format
- */
- public Command parseCommand(String userInput) throws ParseException {
- final Matcher matcher = BASIC_COMMAND_FORMAT.matcher(userInput.trim());
- if (!matcher.matches()) {
- throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, HelpCommand.MESSAGE_USAGE));
- }
-
- final String commandWord = matcher.group("commandWord");
- final String arguments = matcher.group("arguments");
- switch (commandWord) {
-
- case AddCommand.COMMAND_WORD:
- return new AddCommandParser().parse(arguments);
-
- case EditCommand.COMMAND_WORD:
- return new EditCommandParser().parse(arguments);
-
- case DeleteCommand.COMMAND_WORD:
- return new DeleteCommandParser().parse(arguments);
-
- case ClearCommand.COMMAND_WORD:
- return new ClearCommand();
-
- case FindCommand.COMMAND_WORD:
- return new FindCommandParser().parse(arguments);
-
- case ListCommand.COMMAND_WORD:
- return new ListCommand();
-
- case ExitCommand.COMMAND_WORD:
- return new ExitCommand();
-
- case HelpCommand.COMMAND_WORD:
- return new HelpCommand();
-
- default:
- throw new ParseException(MESSAGE_UNKNOWN_COMMAND);
- }
- }
-
-}
diff --git a/src/main/java/seedu/address/logic/parser/CliSyntax.java b/src/main/java/seedu/address/logic/parser/CliSyntax.java
deleted file mode 100644
index 75b1a9bf119..00000000000
--- a/src/main/java/seedu/address/logic/parser/CliSyntax.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package seedu.address.logic.parser;
-
-/**
- * Contains Command Line Interface (CLI) syntax definitions common to multiple commands
- */
-public class CliSyntax {
-
- /* Prefix definitions */
- public static final Prefix PREFIX_NAME = new Prefix("n/");
- public static final Prefix PREFIX_PHONE = new Prefix("p/");
- public static final Prefix PREFIX_EMAIL = new Prefix("e/");
- public static final Prefix PREFIX_ADDRESS = new Prefix("a/");
- public static final Prefix PREFIX_TAG = new Prefix("t/");
-
-}
diff --git a/src/main/java/seedu/address/logic/parser/DeleteCommandParser.java b/src/main/java/seedu/address/logic/parser/DeleteCommandParser.java
deleted file mode 100644
index 522b93081cc..00000000000
--- a/src/main/java/seedu/address/logic/parser/DeleteCommandParser.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package seedu.address.logic.parser;
-
-import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
-
-import seedu.address.commons.core.index.Index;
-import seedu.address.logic.commands.DeleteCommand;
-import seedu.address.logic.parser.exceptions.ParseException;
-
-/**
- * Parses input arguments and creates a new DeleteCommand object
- */
-public class DeleteCommandParser implements Parser {
-
- /**
- * Parses the given {@code String} of arguments in the context of the DeleteCommand
- * and returns a DeleteCommand object for execution.
- * @throws ParseException if the user input does not conform the expected format
- */
- public DeleteCommand parse(String args) throws ParseException {
- try {
- Index index = ParserUtil.parseIndex(args);
- return new DeleteCommand(index);
- } catch (ParseException pe) {
- throw new ParseException(
- String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE), pe);
- }
- }
-
-}
diff --git a/src/main/java/seedu/address/logic/parser/EditCommandParser.java b/src/main/java/seedu/address/logic/parser/EditCommandParser.java
deleted file mode 100644
index 845644b7dea..00000000000
--- a/src/main/java/seedu/address/logic/parser/EditCommandParser.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package seedu.address.logic.parser;
-
-import static java.util.Objects.requireNonNull;
-import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Optional;
-import java.util.Set;
-
-import seedu.address.commons.core.index.Index;
-import seedu.address.logic.commands.EditCommand;
-import seedu.address.logic.commands.EditCommand.EditPersonDescriptor;
-import seedu.address.logic.parser.exceptions.ParseException;
-import seedu.address.model.tag.Tag;
-
-/**
- * Parses input arguments and creates a new EditCommand object
- */
-public class EditCommandParser implements Parser {
-
- /**
- * Parses the given {@code String} of arguments in the context of the EditCommand
- * and returns an EditCommand object for execution.
- * @throws ParseException if the user input does not conform the expected format
- */
- public EditCommand parse(String args) throws ParseException {
- requireNonNull(args);
- ArgumentMultimap argMultimap =
- ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, PREFIX_TAG);
-
- Index index;
-
- try {
- index = ParserUtil.parseIndex(argMultimap.getPreamble());
- } catch (ParseException pe) {
- throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditCommand.MESSAGE_USAGE), pe);
- }
-
- EditPersonDescriptor editPersonDescriptor = new EditPersonDescriptor();
- if (argMultimap.getValue(PREFIX_NAME).isPresent()) {
- editPersonDescriptor.setName(ParserUtil.parseName(argMultimap.getValue(PREFIX_NAME).get()));
- }
- if (argMultimap.getValue(PREFIX_PHONE).isPresent()) {
- editPersonDescriptor.setPhone(ParserUtil.parsePhone(argMultimap.getValue(PREFIX_PHONE).get()));
- }
- if (argMultimap.getValue(PREFIX_EMAIL).isPresent()) {
- editPersonDescriptor.setEmail(ParserUtil.parseEmail(argMultimap.getValue(PREFIX_EMAIL).get()));
- }
- if (argMultimap.getValue(PREFIX_ADDRESS).isPresent()) {
- editPersonDescriptor.setAddress(ParserUtil.parseAddress(argMultimap.getValue(PREFIX_ADDRESS).get()));
- }
- parseTagsForEdit(argMultimap.getAllValues(PREFIX_TAG)).ifPresent(editPersonDescriptor::setTags);
-
- if (!editPersonDescriptor.isAnyFieldEdited()) {
- throw new ParseException(EditCommand.MESSAGE_NOT_EDITED);
- }
-
- return new EditCommand(index, editPersonDescriptor);
- }
-
- /**
- * Parses {@code Collection tags} into a {@code Set} if {@code tags} is non-empty.
- * If {@code tags} contain only one element which is an empty string, it will be parsed into a
- * {@code Set} containing zero tags.
- */
- private Optional> parseTagsForEdit(Collection tags) throws ParseException {
- assert tags != null;
-
- if (tags.isEmpty()) {
- return Optional.empty();
- }
- Collection tagSet = tags.size() == 1 && tags.contains("") ? Collections.emptySet() : tags;
- return Optional.of(ParserUtil.parseTags(tagSet));
- }
-
-}
diff --git a/src/main/java/seedu/address/logic/parser/FindCommandParser.java b/src/main/java/seedu/address/logic/parser/FindCommandParser.java
deleted file mode 100644
index 4fb71f23103..00000000000
--- a/src/main/java/seedu/address/logic/parser/FindCommandParser.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package seedu.address.logic.parser;
-
-import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
-
-import java.util.Arrays;
-
-import seedu.address.logic.commands.FindCommand;
-import seedu.address.logic.parser.exceptions.ParseException;
-import seedu.address.model.person.NameContainsKeywordsPredicate;
-
-/**
- * Parses input arguments and creates a new FindCommand object
- */
-public class FindCommandParser implements Parser {
-
- /**
- * Parses the given {@code String} of arguments in the context of the FindCommand
- * and returns a FindCommand object for execution.
- * @throws ParseException if the user input does not conform the expected format
- */
- public FindCommand parse(String args) throws ParseException {
- String trimmedArgs = args.trim();
- if (trimmedArgs.isEmpty()) {
- throw new ParseException(
- String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_USAGE));
- }
-
- String[] nameKeywords = trimmedArgs.split("\\s+");
-
- return new FindCommand(new NameContainsKeywordsPredicate(Arrays.asList(nameKeywords)));
- }
-
-}
diff --git a/src/main/java/seedu/address/logic/parser/ParserUtil.java b/src/main/java/seedu/address/logic/parser/ParserUtil.java
deleted file mode 100644
index b117acb9c55..00000000000
--- a/src/main/java/seedu/address/logic/parser/ParserUtil.java
+++ /dev/null
@@ -1,124 +0,0 @@
-package seedu.address.logic.parser;
-
-import static java.util.Objects.requireNonNull;
-
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Set;
-
-import seedu.address.commons.core.index.Index;
-import seedu.address.commons.util.StringUtil;
-import seedu.address.logic.parser.exceptions.ParseException;
-import seedu.address.model.person.Address;
-import seedu.address.model.person.Email;
-import seedu.address.model.person.Name;
-import seedu.address.model.person.Phone;
-import seedu.address.model.tag.Tag;
-
-/**
- * Contains utility methods used for parsing strings in the various *Parser classes.
- */
-public class ParserUtil {
-
- public static final String MESSAGE_INVALID_INDEX = "Index is not a non-zero unsigned integer.";
-
- /**
- * Parses {@code oneBasedIndex} into an {@code Index} and returns it. Leading and trailing whitespaces will be
- * trimmed.
- * @throws ParseException if the specified index is invalid (not non-zero unsigned integer).
- */
- public static Index parseIndex(String oneBasedIndex) throws ParseException {
- String trimmedIndex = oneBasedIndex.trim();
- if (!StringUtil.isNonZeroUnsignedInteger(trimmedIndex)) {
- throw new ParseException(MESSAGE_INVALID_INDEX);
- }
- return Index.fromOneBased(Integer.parseInt(trimmedIndex));
- }
-
- /**
- * Parses a {@code String name} into a {@code Name}.
- * Leading and trailing whitespaces will be trimmed.
- *
- * @throws ParseException if the given {@code name} is invalid.
- */
- public static Name parseName(String name) throws ParseException {
- requireNonNull(name);
- String trimmedName = name.trim();
- if (!Name.isValidName(trimmedName)) {
- throw new ParseException(Name.MESSAGE_CONSTRAINTS);
- }
- return new Name(trimmedName);
- }
-
- /**
- * Parses a {@code String phone} into a {@code Phone}.
- * Leading and trailing whitespaces will be trimmed.
- *
- * @throws ParseException if the given {@code phone} is invalid.
- */
- public static Phone parsePhone(String phone) throws ParseException {
- requireNonNull(phone);
- String trimmedPhone = phone.trim();
- if (!Phone.isValidPhone(trimmedPhone)) {
- throw new ParseException(Phone.MESSAGE_CONSTRAINTS);
- }
- return new Phone(trimmedPhone);
- }
-
- /**
- * Parses a {@code String address} into an {@code Address}.
- * Leading and trailing whitespaces will be trimmed.
- *
- * @throws ParseException if the given {@code address} is invalid.
- */
- public static Address parseAddress(String address) throws ParseException {
- requireNonNull(address);
- String trimmedAddress = address.trim();
- if (!Address.isValidAddress(trimmedAddress)) {
- throw new ParseException(Address.MESSAGE_CONSTRAINTS);
- }
- return new Address(trimmedAddress);
- }
-
- /**
- * Parses a {@code String email} into an {@code Email}.
- * Leading and trailing whitespaces will be trimmed.
- *
- * @throws ParseException if the given {@code email} is invalid.
- */
- public static Email parseEmail(String email) throws ParseException {
- requireNonNull(email);
- String trimmedEmail = email.trim();
- if (!Email.isValidEmail(trimmedEmail)) {
- throw new ParseException(Email.MESSAGE_CONSTRAINTS);
- }
- return new Email(trimmedEmail);
- }
-
- /**
- * Parses a {@code String tag} into a {@code Tag}.
- * Leading and trailing whitespaces will be trimmed.
- *
- * @throws ParseException if the given {@code tag} is invalid.
- */
- public static Tag parseTag(String tag) throws ParseException {
- requireNonNull(tag);
- String trimmedTag = tag.trim();
- if (!Tag.isValidTagName(trimmedTag)) {
- throw new ParseException(Tag.MESSAGE_CONSTRAINTS);
- }
- return new Tag(trimmedTag);
- }
-
- /**
- * Parses {@code Collection tags} into a {@code Set}.
- */
- public static Set parseTags(Collection tags) throws ParseException {
- requireNonNull(tags);
- final Set tagSet = new HashSet<>();
- for (String tagName : tags) {
- tagSet.add(parseTag(tagName));
- }
- return tagSet;
- }
-}
diff --git a/src/main/java/seedu/address/model/AddressBook.java b/src/main/java/seedu/address/model/AddressBook.java
deleted file mode 100644
index 1a943a0781a..00000000000
--- a/src/main/java/seedu/address/model/AddressBook.java
+++ /dev/null
@@ -1,120 +0,0 @@
-package seedu.address.model;
-
-import static java.util.Objects.requireNonNull;
-
-import java.util.List;
-
-import javafx.collections.ObservableList;
-import seedu.address.model.person.Person;
-import seedu.address.model.person.UniquePersonList;
-
-/**
- * Wraps all data at the address-book level
- * Duplicates are not allowed (by .isSamePerson comparison)
- */
-public class AddressBook implements ReadOnlyAddressBook {
-
- private final UniquePersonList persons;
-
- /*
- * The 'unusual' code block below is a non-static initialization block, sometimes used to avoid duplication
- * between constructors. See https://docs.oracle.com/javase/tutorial/java/javaOO/initial.html
- *
- * Note that non-static init blocks are not recommended to use. There are other ways to avoid duplication
- * among constructors.
- */
- {
- persons = new UniquePersonList();
- }
-
- public AddressBook() {}
-
- /**
- * Creates an AddressBook using the Persons in the {@code toBeCopied}
- */
- public AddressBook(ReadOnlyAddressBook toBeCopied) {
- this();
- resetData(toBeCopied);
- }
-
- //// list overwrite operations
-
- /**
- * Replaces the contents of the person list with {@code persons}.
- * {@code persons} must not contain duplicate persons.
- */
- public void setPersons(List persons) {
- this.persons.setPersons(persons);
- }
-
- /**
- * Resets the existing data of this {@code AddressBook} with {@code newData}.
- */
- public void resetData(ReadOnlyAddressBook newData) {
- requireNonNull(newData);
-
- setPersons(newData.getPersonList());
- }
-
- //// person-level operations
-
- /**
- * Returns true if a person with the same identity as {@code person} exists in the address book.
- */
- public boolean hasPerson(Person person) {
- requireNonNull(person);
- return persons.contains(person);
- }
-
- /**
- * Adds a person to the address book.
- * The person must not already exist in the address book.
- */
- public void addPerson(Person p) {
- persons.add(p);
- }
-
- /**
- * Replaces the given person {@code target} in the list with {@code editedPerson}.
- * {@code target} must exist in the address book.
- * The person identity of {@code editedPerson} must not be the same as another existing person in the address book.
- */
- public void setPerson(Person target, Person editedPerson) {
- requireNonNull(editedPerson);
-
- persons.setPerson(target, editedPerson);
- }
-
- /**
- * Removes {@code key} from this {@code AddressBook}.
- * {@code key} must exist in the address book.
- */
- public void removePerson(Person key) {
- persons.remove(key);
- }
-
- //// util methods
-
- @Override
- public String toString() {
- return persons.asUnmodifiableObservableList().size() + " persons";
- // TODO: refine later
- }
-
- @Override
- public ObservableList getPersonList() {
- return persons.asUnmodifiableObservableList();
- }
-
- @Override
- public boolean equals(Object other) {
- return other == this // short circuit if same object
- || (other instanceof AddressBook // instanceof handles nulls
- && persons.equals(((AddressBook) other).persons));
- }
-
- @Override
- public int hashCode() {
- return persons.hashCode();
- }
-}
diff --git a/src/main/java/seedu/address/model/Model.java b/src/main/java/seedu/address/model/Model.java
deleted file mode 100644
index d54df471c1f..00000000000
--- a/src/main/java/seedu/address/model/Model.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package seedu.address.model;
-
-import java.nio.file.Path;
-import java.util.function.Predicate;
-
-import javafx.collections.ObservableList;
-import seedu.address.commons.core.GuiSettings;
-import seedu.address.model.person.Person;
-
-/**
- * The API of the Model component.
- */
-public interface Model {
- /** {@code Predicate} that always evaluate to true */
- Predicate PREDICATE_SHOW_ALL_PERSONS = unused -> true;
-
- /**
- * Replaces user prefs data with the data in {@code userPrefs}.
- */
- void setUserPrefs(ReadOnlyUserPrefs userPrefs);
-
- /**
- * Returns the user prefs.
- */
- ReadOnlyUserPrefs getUserPrefs();
-
- /**
- * Returns the user prefs' GUI settings.
- */
- GuiSettings getGuiSettings();
-
- /**
- * Sets the user prefs' GUI settings.
- */
- void setGuiSettings(GuiSettings guiSettings);
-
- /**
- * Returns the user prefs' address book file path.
- */
- Path getAddressBookFilePath();
-
- /**
- * Sets the user prefs' address book file path.
- */
- void setAddressBookFilePath(Path addressBookFilePath);
-
- /**
- * Replaces address book data with the data in {@code addressBook}.
- */
- void setAddressBook(ReadOnlyAddressBook addressBook);
-
- /** Returns the AddressBook */
- ReadOnlyAddressBook getAddressBook();
-
- /**
- * Returns true if a person with the same identity as {@code person} exists in the address book.
- */
- boolean hasPerson(Person person);
-
- /**
- * Deletes the given person.
- * The person must exist in the address book.
- */
- void deletePerson(Person target);
-
- /**
- * Adds the given person.
- * {@code person} must not already exist in the address book.
- */
- void addPerson(Person person);
-
- /**
- * Replaces the given person {@code target} with {@code editedPerson}.
- * {@code target} must exist in the address book.
- * The person identity of {@code editedPerson} must not be the same as another existing person in the address book.
- */
- void setPerson(Person target, Person editedPerson);
-
- /** Returns an unmodifiable view of the filtered person list */
- ObservableList getFilteredPersonList();
-
- /**
- * Updates the filter of the filtered person list to filter by the given {@code predicate}.
- * @throws NullPointerException if {@code predicate} is null.
- */
- void updateFilteredPersonList(Predicate predicate);
-}
diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java
deleted file mode 100644
index 0650c954f5c..00000000000
--- a/src/main/java/seedu/address/model/ModelManager.java
+++ /dev/null
@@ -1,151 +0,0 @@
-package seedu.address.model;
-
-import static java.util.Objects.requireNonNull;
-import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
-
-import java.nio.file.Path;
-import java.util.function.Predicate;
-import java.util.logging.Logger;
-
-import javafx.collections.ObservableList;
-import javafx.collections.transformation.FilteredList;
-import seedu.address.commons.core.GuiSettings;
-import seedu.address.commons.core.LogsCenter;
-import seedu.address.model.person.Person;
-
-/**
- * Represents the in-memory model of the address book data.
- */
-public class ModelManager implements Model {
- private static final Logger logger = LogsCenter.getLogger(ModelManager.class);
-
- private final AddressBook addressBook;
- private final UserPrefs userPrefs;
- private final FilteredList filteredPersons;
-
- /**
- * Initializes a ModelManager with the given addressBook and userPrefs.
- */
- public ModelManager(ReadOnlyAddressBook addressBook, ReadOnlyUserPrefs userPrefs) {
- super();
- requireAllNonNull(addressBook, userPrefs);
-
- logger.fine("Initializing with address book: " + addressBook + " and user prefs " + userPrefs);
-
- this.addressBook = new AddressBook(addressBook);
- this.userPrefs = new UserPrefs(userPrefs);
- filteredPersons = new FilteredList<>(this.addressBook.getPersonList());
- }
-
- public ModelManager() {
- this(new AddressBook(), new UserPrefs());
- }
-
- //=========== UserPrefs ==================================================================================
-
- @Override
- public void setUserPrefs(ReadOnlyUserPrefs userPrefs) {
- requireNonNull(userPrefs);
- this.userPrefs.resetData(userPrefs);
- }
-
- @Override
- public ReadOnlyUserPrefs getUserPrefs() {
- return userPrefs;
- }
-
- @Override
- public GuiSettings getGuiSettings() {
- return userPrefs.getGuiSettings();
- }
-
- @Override
- public void setGuiSettings(GuiSettings guiSettings) {
- requireNonNull(guiSettings);
- userPrefs.setGuiSettings(guiSettings);
- }
-
- @Override
- public Path getAddressBookFilePath() {
- return userPrefs.getAddressBookFilePath();
- }
-
- @Override
- public void setAddressBookFilePath(Path addressBookFilePath) {
- requireNonNull(addressBookFilePath);
- userPrefs.setAddressBookFilePath(addressBookFilePath);
- }
-
- //=========== AddressBook ================================================================================
-
- @Override
- public void setAddressBook(ReadOnlyAddressBook addressBook) {
- this.addressBook.resetData(addressBook);
- }
-
- @Override
- public ReadOnlyAddressBook getAddressBook() {
- return addressBook;
- }
-
- @Override
- public boolean hasPerson(Person person) {
- requireNonNull(person);
- return addressBook.hasPerson(person);
- }
-
- @Override
- public void deletePerson(Person target) {
- addressBook.removePerson(target);
- }
-
- @Override
- public void addPerson(Person person) {
- addressBook.addPerson(person);
- updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
- }
-
- @Override
- public void setPerson(Person target, Person editedPerson) {
- requireAllNonNull(target, editedPerson);
-
- addressBook.setPerson(target, editedPerson);
- }
-
- //=========== Filtered Person List Accessors =============================================================
-
- /**
- * Returns an unmodifiable view of the list of {@code Person} backed by the internal list of
- * {@code versionedAddressBook}
- */
- @Override
- public ObservableList getFilteredPersonList() {
- return filteredPersons;
- }
-
- @Override
- public void updateFilteredPersonList(Predicate predicate) {
- requireNonNull(predicate);
- filteredPersons.setPredicate(predicate);
- }
-
- @Override
- public boolean equals(Object obj) {
- // short circuit if same object
- if (obj == this) {
- return true;
- }
-
- // instanceof handles nulls
- if (!(obj instanceof ModelManager)) {
- return false;
- }
-
- // state check
- ModelManager other = (ModelManager) obj;
- return addressBook.equals(other.addressBook)
- && userPrefs.equals(other.userPrefs)
- && filteredPersons.equals(other.filteredPersons);
- }
-
-}
diff --git a/src/main/java/seedu/address/model/person/Address.java b/src/main/java/seedu/address/model/person/Address.java
deleted file mode 100644
index 60472ca22a0..00000000000
--- a/src/main/java/seedu/address/model/person/Address.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package seedu.address.model.person;
-
-import static java.util.Objects.requireNonNull;
-import static seedu.address.commons.util.AppUtil.checkArgument;
-
-/**
- * Represents a Person's address in the address book.
- * Guarantees: immutable; is valid as declared in {@link #isValidAddress(String)}
- */
-public class Address {
-
- public static final String MESSAGE_CONSTRAINTS = "Addresses can take any values, and it should not be blank";
-
- /*
- * The first character of the address must not be a whitespace,
- * otherwise " " (a blank string) becomes a valid input.
- */
- public static final String VALIDATION_REGEX = "[^\\s].*";
-
- public final String value;
-
- /**
- * Constructs an {@code Address}.
- *
- * @param address A valid address.
- */
- public Address(String address) {
- requireNonNull(address);
- checkArgument(isValidAddress(address), MESSAGE_CONSTRAINTS);
- value = address;
- }
-
- /**
- * Returns true if a given string is a valid email.
- */
- public static boolean isValidAddress(String test) {
- return test.matches(VALIDATION_REGEX);
- }
-
- @Override
- public String toString() {
- return value;
- }
-
- @Override
- public boolean equals(Object other) {
- return other == this // short circuit if same object
- || (other instanceof Address // instanceof handles nulls
- && value.equals(((Address) other).value)); // state check
- }
-
- @Override
- public int hashCode() {
- return value.hashCode();
- }
-
-}
diff --git a/src/main/java/seedu/address/model/tag/Tag.java b/src/main/java/seedu/address/model/tag/Tag.java
deleted file mode 100644
index b0ea7e7dad7..00000000000
--- a/src/main/java/seedu/address/model/tag/Tag.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package seedu.address.model.tag;
-
-import static java.util.Objects.requireNonNull;
-import static seedu.address.commons.util.AppUtil.checkArgument;
-
-/**
- * Represents a Tag in the address book.
- * Guarantees: immutable; name is valid as declared in {@link #isValidTagName(String)}
- */
-public class Tag {
-
- public static final String MESSAGE_CONSTRAINTS = "Tags names should be alphanumeric";
- public static final String VALIDATION_REGEX = "\\p{Alnum}+";
-
- public final String tagName;
-
- /**
- * Constructs a {@code Tag}.
- *
- * @param tagName A valid tag name.
- */
- public Tag(String tagName) {
- requireNonNull(tagName);
- checkArgument(isValidTagName(tagName), MESSAGE_CONSTRAINTS);
- this.tagName = tagName;
- }
-
- /**
- * Returns true if a given string is a valid tag name.
- */
- public static boolean isValidTagName(String test) {
- return test.matches(VALIDATION_REGEX);
- }
-
- @Override
- public boolean equals(Object other) {
- return other == this // short circuit if same object
- || (other instanceof Tag // instanceof handles nulls
- && tagName.equals(((Tag) other).tagName)); // state check
- }
-
- @Override
- public int hashCode() {
- return tagName.hashCode();
- }
-
- /**
- * Format state as text for viewing.
- */
- public String toString() {
- return '[' + tagName + ']';
- }
-
-}
diff --git a/src/main/java/seedu/address/model/util/SampleDataUtil.java b/src/main/java/seedu/address/model/util/SampleDataUtil.java
deleted file mode 100644
index 1806da4facf..00000000000
--- a/src/main/java/seedu/address/model/util/SampleDataUtil.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package seedu.address.model.util;
-
-import java.util.Arrays;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import seedu.address.model.AddressBook;
-import seedu.address.model.ReadOnlyAddressBook;
-import seedu.address.model.person.Address;
-import seedu.address.model.person.Email;
-import seedu.address.model.person.Name;
-import seedu.address.model.person.Person;
-import seedu.address.model.person.Phone;
-import seedu.address.model.tag.Tag;
-
-/**
- * Contains utility methods for populating {@code AddressBook} with sample data.
- */
-public class SampleDataUtil {
- public static Person[] getSamplePersons() {
- return new Person[] {
- new Person(new Name("Alex Yeoh"), new Phone("87438807"), new Email("alexyeoh@example.com"),
- new Address("Blk 30 Geylang Street 29, #06-40"),
- getTagSet("friends")),
- new Person(new Name("Bernice Yu"), new Phone("99272758"), new Email("berniceyu@example.com"),
- new Address("Blk 30 Lorong 3 Serangoon Gardens, #07-18"),
- getTagSet("colleagues", "friends")),
- new Person(new Name("Charlotte Oliveiro"), new Phone("93210283"), new Email("charlotte@example.com"),
- new Address("Blk 11 Ang Mo Kio Street 74, #11-04"),
- getTagSet("neighbours")),
- new Person(new Name("David Li"), new Phone("91031282"), new Email("lidavid@example.com"),
- new Address("Blk 436 Serangoon Gardens Street 26, #16-43"),
- getTagSet("family")),
- new Person(new Name("Irfan Ibrahim"), new Phone("92492021"), new Email("irfan@example.com"),
- new Address("Blk 47 Tampines Street 20, #17-35"),
- getTagSet("classmates")),
- new Person(new Name("Roy Balakrishnan"), new Phone("92624417"), new Email("royb@example.com"),
- new Address("Blk 45 Aljunied Street 85, #11-31"),
- getTagSet("colleagues"))
- };
- }
-
- public static ReadOnlyAddressBook getSampleAddressBook() {
- AddressBook sampleAb = new AddressBook();
- for (Person samplePerson : getSamplePersons()) {
- sampleAb.addPerson(samplePerson);
- }
- return sampleAb;
- }
-
- /**
- * Returns a tag set containing the list of strings given.
- */
- public static Set getTagSet(String... strings) {
- return Arrays.stream(strings)
- .map(Tag::new)
- .collect(Collectors.toSet());
- }
-
-}
diff --git a/src/main/java/seedu/address/storage/AddressBookStorage.java b/src/main/java/seedu/address/storage/AddressBookStorage.java
deleted file mode 100644
index 4599182b3f9..00000000000
--- a/src/main/java/seedu/address/storage/AddressBookStorage.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package seedu.address.storage;
-
-import java.io.IOException;
-import java.nio.file.Path;
-import java.util.Optional;
-
-import seedu.address.commons.exceptions.DataConversionException;
-import seedu.address.model.ReadOnlyAddressBook;
-
-/**
- * Represents a storage for {@link seedu.address.model.AddressBook}.
- */
-public interface AddressBookStorage {
-
- /**
- * Returns the file path of the data file.
- */
- Path getAddressBookFilePath();
-
- /**
- * Returns AddressBook data as a {@link ReadOnlyAddressBook}.
- * Returns {@code Optional.empty()} if storage file is not found.
- * @throws DataConversionException if the data in storage is not in the expected format.
- * @throws IOException if there was any problem when reading from the storage.
- */
- Optional readAddressBook() throws DataConversionException, IOException;
-
- /**
- * @see #getAddressBookFilePath()
- */
- Optional readAddressBook(Path filePath) throws DataConversionException, IOException;
-
- /**
- * Saves the given {@link ReadOnlyAddressBook} to the storage.
- * @param addressBook cannot be null.
- * @throws IOException if there was any problem writing to the file.
- */
- void saveAddressBook(ReadOnlyAddressBook addressBook) throws IOException;
-
- /**
- * @see #saveAddressBook(ReadOnlyAddressBook)
- */
- void saveAddressBook(ReadOnlyAddressBook addressBook, Path filePath) throws IOException;
-
-}
diff --git a/src/main/java/seedu/address/storage/JsonAdaptedTag.java b/src/main/java/seedu/address/storage/JsonAdaptedTag.java
deleted file mode 100644
index 0df22bdb754..00000000000
--- a/src/main/java/seedu/address/storage/JsonAdaptedTag.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package seedu.address.storage;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonValue;
-
-import seedu.address.commons.exceptions.IllegalValueException;
-import seedu.address.model.tag.Tag;
-
-/**
- * Jackson-friendly version of {@link Tag}.
- */
-class JsonAdaptedTag {
-
- private final String tagName;
-
- /**
- * Constructs a {@code JsonAdaptedTag} with the given {@code tagName}.
- */
- @JsonCreator
- public JsonAdaptedTag(String tagName) {
- this.tagName = tagName;
- }
-
- /**
- * Converts a given {@code Tag} into this class for Jackson use.
- */
- public JsonAdaptedTag(Tag source) {
- tagName = source.tagName;
- }
-
- @JsonValue
- public String getTagName() {
- return tagName;
- }
-
- /**
- * Converts this Jackson-friendly adapted tag object into the model's {@code Tag} object.
- *
- * @throws IllegalValueException if there were any data constraints violated in the adapted tag.
- */
- public Tag toModelType() throws IllegalValueException {
- if (!Tag.isValidTagName(tagName)) {
- throw new IllegalValueException(Tag.MESSAGE_CONSTRAINTS);
- }
- return new Tag(tagName);
- }
-
-}
diff --git a/src/main/java/seedu/address/storage/JsonAddressBookStorage.java b/src/main/java/seedu/address/storage/JsonAddressBookStorage.java
deleted file mode 100644
index dfab9daaa0d..00000000000
--- a/src/main/java/seedu/address/storage/JsonAddressBookStorage.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package seedu.address.storage;
-
-import static java.util.Objects.requireNonNull;
-
-import java.io.IOException;
-import java.nio.file.Path;
-import java.util.Optional;
-import java.util.logging.Logger;
-
-import seedu.address.commons.core.LogsCenter;
-import seedu.address.commons.exceptions.DataConversionException;
-import seedu.address.commons.exceptions.IllegalValueException;
-import seedu.address.commons.util.FileUtil;
-import seedu.address.commons.util.JsonUtil;
-import seedu.address.model.ReadOnlyAddressBook;
-
-/**
- * A class to access AddressBook data stored as a json file on the hard disk.
- */
-public class JsonAddressBookStorage implements AddressBookStorage {
-
- private static final Logger logger = LogsCenter.getLogger(JsonAddressBookStorage.class);
-
- private Path filePath;
-
- public JsonAddressBookStorage(Path filePath) {
- this.filePath = filePath;
- }
-
- public Path getAddressBookFilePath() {
- return filePath;
- }
-
- @Override
- public Optional readAddressBook() throws DataConversionException {
- return readAddressBook(filePath);
- }
-
- /**
- * Similar to {@link #readAddressBook()}.
- *
- * @param filePath location of the data. Cannot be null.
- * @throws DataConversionException if the file is not in the correct format.
- */
- public Optional readAddressBook(Path filePath) throws DataConversionException {
- requireNonNull(filePath);
-
- Optional jsonAddressBook = JsonUtil.readJsonFile(
- filePath, JsonSerializableAddressBook.class);
- if (!jsonAddressBook.isPresent()) {
- return Optional.empty();
- }
-
- try {
- return Optional.of(jsonAddressBook.get().toModelType());
- } catch (IllegalValueException ive) {
- logger.info("Illegal values found in " + filePath + ": " + ive.getMessage());
- throw new DataConversionException(ive);
- }
- }
-
- @Override
- public void saveAddressBook(ReadOnlyAddressBook addressBook) throws IOException {
- saveAddressBook(addressBook, filePath);
- }
-
- /**
- * Similar to {@link #saveAddressBook(ReadOnlyAddressBook)}.
- *
- * @param filePath location of the data. Cannot be null.
- */
- public void saveAddressBook(ReadOnlyAddressBook addressBook, Path filePath) throws IOException {
- requireNonNull(addressBook);
- requireNonNull(filePath);
-
- FileUtil.createIfMissing(filePath);
- JsonUtil.saveJsonFile(new JsonSerializableAddressBook(addressBook), filePath);
- }
-
-}
diff --git a/src/main/java/seedu/address/storage/JsonSerializableAddressBook.java b/src/main/java/seedu/address/storage/JsonSerializableAddressBook.java
deleted file mode 100644
index 5efd834091d..00000000000
--- a/src/main/java/seedu/address/storage/JsonSerializableAddressBook.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package seedu.address.storage;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.stream.Collectors;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.annotation.JsonRootName;
-
-import seedu.address.commons.exceptions.IllegalValueException;
-import seedu.address.model.AddressBook;
-import seedu.address.model.ReadOnlyAddressBook;
-import seedu.address.model.person.Person;
-
-/**
- * An Immutable AddressBook that is serializable to JSON format.
- */
-@JsonRootName(value = "addressbook")
-class JsonSerializableAddressBook {
-
- public static final String MESSAGE_DUPLICATE_PERSON = "Persons list contains duplicate person(s).";
-
- private final List persons = new ArrayList<>();
-
- /**
- * Constructs a {@code JsonSerializableAddressBook} with the given persons.
- */
- @JsonCreator
- public JsonSerializableAddressBook(@JsonProperty("persons") List persons) {
- this.persons.addAll(persons);
- }
-
- /**
- * Converts a given {@code ReadOnlyAddressBook} into this class for Jackson use.
- *
- * @param source future changes to this will not affect the created {@code JsonSerializableAddressBook}.
- */
- public JsonSerializableAddressBook(ReadOnlyAddressBook source) {
- persons.addAll(source.getPersonList().stream().map(JsonAdaptedPerson::new).collect(Collectors.toList()));
- }
-
- /**
- * Converts this address book into the model's {@code AddressBook} object.
- *
- * @throws IllegalValueException if there were any data constraints violated.
- */
- public AddressBook toModelType() throws IllegalValueException {
- AddressBook addressBook = new AddressBook();
- for (JsonAdaptedPerson jsonAdaptedPerson : persons) {
- Person person = jsonAdaptedPerson.toModelType();
- if (addressBook.hasPerson(person)) {
- throw new IllegalValueException(MESSAGE_DUPLICATE_PERSON);
- }
- addressBook.addPerson(person);
- }
- return addressBook;
- }
-
-}
diff --git a/src/main/java/seedu/address/storage/Storage.java b/src/main/java/seedu/address/storage/Storage.java
deleted file mode 100644
index beda8bd9f11..00000000000
--- a/src/main/java/seedu/address/storage/Storage.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package seedu.address.storage;
-
-import java.io.IOException;
-import java.nio.file.Path;
-import java.util.Optional;
-
-import seedu.address.commons.exceptions.DataConversionException;
-import seedu.address.model.ReadOnlyAddressBook;
-import seedu.address.model.ReadOnlyUserPrefs;
-import seedu.address.model.UserPrefs;
-
-/**
- * API of the Storage component
- */
-public interface Storage extends AddressBookStorage, UserPrefsStorage {
-
- @Override
- Optional readUserPrefs() throws DataConversionException, IOException;
-
- @Override
- void saveUserPrefs(ReadOnlyUserPrefs userPrefs) throws IOException;
-
- @Override
- Path getAddressBookFilePath();
-
- @Override
- Optional readAddressBook() throws DataConversionException, IOException;
-
- @Override
- void saveAddressBook(ReadOnlyAddressBook addressBook) throws IOException;
-
-}
diff --git a/src/main/java/seedu/address/storage/StorageManager.java b/src/main/java/seedu/address/storage/StorageManager.java
deleted file mode 100644
index 79868290974..00000000000
--- a/src/main/java/seedu/address/storage/StorageManager.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package seedu.address.storage;
-
-import java.io.IOException;
-import java.nio.file.Path;
-import java.util.Optional;
-import java.util.logging.Logger;
-
-import seedu.address.commons.core.LogsCenter;
-import seedu.address.commons.exceptions.DataConversionException;
-import seedu.address.model.ReadOnlyAddressBook;
-import seedu.address.model.ReadOnlyUserPrefs;
-import seedu.address.model.UserPrefs;
-
-/**
- * Manages storage of AddressBook data in local storage.
- */
-public class StorageManager implements Storage {
-
- private static final Logger logger = LogsCenter.getLogger(StorageManager.class);
- private AddressBookStorage addressBookStorage;
- private UserPrefsStorage userPrefsStorage;
-
- /**
- * Creates a {@code StorageManager} with the given {@code AddressBookStorage} and {@code UserPrefStorage}.
- */
- public StorageManager(AddressBookStorage addressBookStorage, UserPrefsStorage userPrefsStorage) {
- super();
- this.addressBookStorage = addressBookStorage;
- this.userPrefsStorage = userPrefsStorage;
- }
-
- // ================ UserPrefs methods ==============================
-
- @Override
- public Path getUserPrefsFilePath() {
- return userPrefsStorage.getUserPrefsFilePath();
- }
-
- @Override
- public Optional readUserPrefs() throws DataConversionException, IOException {
- return userPrefsStorage.readUserPrefs();
- }
-
- @Override
- public void saveUserPrefs(ReadOnlyUserPrefs userPrefs) throws IOException {
- userPrefsStorage.saveUserPrefs(userPrefs);
- }
-
-
- // ================ AddressBook methods ==============================
-
- @Override
- public Path getAddressBookFilePath() {
- return addressBookStorage.getAddressBookFilePath();
- }
-
- @Override
- public Optional readAddressBook() throws DataConversionException, IOException {
- return readAddressBook(addressBookStorage.getAddressBookFilePath());
- }
-
- @Override
- public Optional readAddressBook(Path filePath) throws DataConversionException, IOException {
- logger.fine("Attempting to read data from file: " + filePath);
- return addressBookStorage.readAddressBook(filePath);
- }
-
- @Override
- public void saveAddressBook(ReadOnlyAddressBook addressBook) throws IOException {
- saveAddressBook(addressBook, addressBookStorage.getAddressBookFilePath());
- }
-
- @Override
- public void saveAddressBook(ReadOnlyAddressBook addressBook, Path filePath) throws IOException {
- logger.fine("Attempting to write to data file: " + filePath);
- addressBookStorage.saveAddressBook(addressBook, filePath);
- }
-
-}
diff --git a/src/main/java/seedu/address/AppParameters.java b/src/main/java/seedu/heymatez/AppParameters.java
similarity index 93%
rename from src/main/java/seedu/address/AppParameters.java
rename to src/main/java/seedu/heymatez/AppParameters.java
index ab552c398f3..5518d92bf13 100644
--- a/src/main/java/seedu/address/AppParameters.java
+++ b/src/main/java/seedu/heymatez/AppParameters.java
@@ -1,4 +1,4 @@
-package seedu.address;
+package seedu.heymatez;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -7,8 +7,8 @@
import java.util.logging.Logger;
import javafx.application.Application;
-import seedu.address.commons.core.LogsCenter;
-import seedu.address.commons.util.FileUtil;
+import seedu.heymatez.commons.core.LogsCenter;
+import seedu.heymatez.commons.util.FileUtil;
/**
* Represents the parsed command-line parameters given to the application.
diff --git a/src/main/java/seedu/address/Main.java b/src/main/java/seedu/heymatez/Main.java
similarity index 97%
rename from src/main/java/seedu/address/Main.java
rename to src/main/java/seedu/heymatez/Main.java
index 052a5068631..472f70ff13f 100644
--- a/src/main/java/seedu/address/Main.java
+++ b/src/main/java/seedu/heymatez/Main.java
@@ -1,4 +1,4 @@
-package seedu.address;
+package seedu.heymatez;
import javafx.application.Application;
diff --git a/src/main/java/seedu/address/MainApp.java b/src/main/java/seedu/heymatez/MainApp.java
similarity index 68%
rename from src/main/java/seedu/address/MainApp.java
rename to src/main/java/seedu/heymatez/MainApp.java
index e5cfb161b73..1f8aecc4811 100644
--- a/src/main/java/seedu/address/MainApp.java
+++ b/src/main/java/seedu/heymatez/MainApp.java
@@ -1,4 +1,4 @@
-package seedu.address;
+package seedu.heymatez;
import java.io.IOException;
import java.nio.file.Path;
@@ -7,36 +7,36 @@
import javafx.application.Application;
import javafx.stage.Stage;
-import seedu.address.commons.core.Config;
-import seedu.address.commons.core.LogsCenter;
-import seedu.address.commons.core.Version;
-import seedu.address.commons.exceptions.DataConversionException;
-import seedu.address.commons.util.ConfigUtil;
-import seedu.address.commons.util.StringUtil;
-import seedu.address.logic.Logic;
-import seedu.address.logic.LogicManager;
-import seedu.address.model.AddressBook;
-import seedu.address.model.Model;
-import seedu.address.model.ModelManager;
-import seedu.address.model.ReadOnlyAddressBook;
-import seedu.address.model.ReadOnlyUserPrefs;
-import seedu.address.model.UserPrefs;
-import seedu.address.model.util.SampleDataUtil;
-import seedu.address.storage.AddressBookStorage;
-import seedu.address.storage.JsonAddressBookStorage;
-import seedu.address.storage.JsonUserPrefsStorage;
-import seedu.address.storage.Storage;
-import seedu.address.storage.StorageManager;
-import seedu.address.storage.UserPrefsStorage;
-import seedu.address.ui.Ui;
-import seedu.address.ui.UiManager;
+import seedu.heymatez.commons.core.Config;
+import seedu.heymatez.commons.core.LogsCenter;
+import seedu.heymatez.commons.core.Version;
+import seedu.heymatez.commons.exceptions.DataConversionException;
+import seedu.heymatez.commons.util.ConfigUtil;
+import seedu.heymatez.commons.util.StringUtil;
+import seedu.heymatez.logic.Logic;
+import seedu.heymatez.logic.LogicManager;
+import seedu.heymatez.model.HeyMatez;
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.ModelManager;
+import seedu.heymatez.model.ReadOnlyHeyMatez;
+import seedu.heymatez.model.ReadOnlyUserPrefs;
+import seedu.heymatez.model.UserPrefs;
+import seedu.heymatez.model.util.SampleDataUtil;
+import seedu.heymatez.storage.HeyMatezStorage;
+import seedu.heymatez.storage.JsonHeyMatezStorage;
+import seedu.heymatez.storage.JsonUserPrefsStorage;
+import seedu.heymatez.storage.Storage;
+import seedu.heymatez.storage.StorageManager;
+import seedu.heymatez.storage.UserPrefsStorage;
+import seedu.heymatez.ui.Ui;
+import seedu.heymatez.ui.UiManager;
/**
* Runs the application.
*/
public class MainApp extends Application {
- public static final Version VERSION = new Version(0, 6, 0, true);
+ public static final Version VERSION = new Version(1, 4, 0, true);
private static final Logger logger = LogsCenter.getLogger(MainApp.class);
@@ -48,7 +48,7 @@ public class MainApp extends Application {
@Override
public void init() throws Exception {
- logger.info("=============================[ Initializing AddressBook ]===========================");
+ logger.info("=============================[ Initializing HeyMatez ]===========================");
super.init();
AppParameters appParameters = AppParameters.parse(getParameters());
@@ -56,8 +56,8 @@ public void init() throws Exception {
UserPrefsStorage userPrefsStorage = new JsonUserPrefsStorage(config.getUserPrefsFilePath());
UserPrefs userPrefs = initPrefs(userPrefsStorage);
- AddressBookStorage addressBookStorage = new JsonAddressBookStorage(userPrefs.getAddressBookFilePath());
- storage = new StorageManager(addressBookStorage, userPrefsStorage);
+ HeyMatezStorage heyMatezStorage = new JsonHeyMatezStorage(userPrefs.getHeyMatezFilePath());
+ storage = new StorageManager(heyMatezStorage, userPrefsStorage);
initLogging(config);
@@ -69,25 +69,25 @@ public void init() throws Exception {
}
/**
- * Returns a {@code ModelManager} with the data from {@code storage}'s address book and {@code userPrefs}.
- * The data from the sample address book will be used instead if {@code storage}'s address book is not found,
- * or an empty address book will be used instead if errors occur when reading {@code storage}'s address book.
+ * Returns a {@code ModelManager} with the data from {@code storage}'s Hey Matez and {@code userPrefs}.
+ * The data from the sample Hey Matez will be used instead if {@code storage}'s Hey Matez is not found,
+ * or an empty address book will be used instead if errors occur when reading {@code storage}'s Hey Matez .
*/
private Model initModelManager(Storage storage, ReadOnlyUserPrefs userPrefs) {
- Optional addressBookOptional;
- ReadOnlyAddressBook initialData;
+ Optional heyMatezOptional;
+ ReadOnlyHeyMatez initialData;
try {
- addressBookOptional = storage.readAddressBook();
- if (!addressBookOptional.isPresent()) {
- logger.info("Data file not found. Will be starting with a sample AddressBook");
+ heyMatezOptional = storage.readHeyMatez();
+ if (!heyMatezOptional.isPresent()) {
+ logger.info("Data file not found. Will be starting with a sample HeyMatez");
}
- initialData = addressBookOptional.orElseGet(SampleDataUtil::getSampleAddressBook);
+ initialData = heyMatezOptional.orElseGet(SampleDataUtil::getSampleHeyMatez);
} catch (DataConversionException e) {
- logger.warning("Data file not in the correct format. Will be starting with an empty AddressBook");
- initialData = new AddressBook();
+ logger.warning("Data file not in the correct format. Will be starting with an empty HeyMatez");
+ initialData = new HeyMatez();
} catch (IOException e) {
- logger.warning("Problem while reading from the file. Will be starting with an empty AddressBook");
- initialData = new AddressBook();
+ logger.warning("Problem while reading from the file. Will be starting with an empty HeyMatez");
+ initialData = new HeyMatez();
}
return new ModelManager(initialData, userPrefs);
@@ -151,7 +151,7 @@ protected UserPrefs initPrefs(UserPrefsStorage storage) {
+ "Using default user prefs");
initializedPrefs = new UserPrefs();
} catch (IOException e) {
- logger.warning("Problem while reading from the file. Will be starting with an empty AddressBook");
+ logger.warning("Problem while reading from the file. Will be starting with an empty HeyMatez");
initializedPrefs = new UserPrefs();
}
@@ -167,13 +167,13 @@ protected UserPrefs initPrefs(UserPrefsStorage storage) {
@Override
public void start(Stage primaryStage) {
- logger.info("Starting AddressBook " + MainApp.VERSION);
+ logger.info("Starting HeyMatez " + MainApp.VERSION);
ui.start(primaryStage);
}
@Override
public void stop() {
- logger.info("============================ [ Stopping Address Book ] =============================");
+ logger.info("============================ [ Stopping HeyMatez ] =============================");
try {
storage.saveUserPrefs(model.getUserPrefs());
} catch (IOException e) {
diff --git a/src/main/java/seedu/address/commons/core/Config.java b/src/main/java/seedu/heymatez/commons/core/Config.java
similarity index 97%
rename from src/main/java/seedu/address/commons/core/Config.java
rename to src/main/java/seedu/heymatez/commons/core/Config.java
index 91145745521..a139cd5e373 100644
--- a/src/main/java/seedu/address/commons/core/Config.java
+++ b/src/main/java/seedu/heymatez/commons/core/Config.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.core;
+package seedu.heymatez.commons.core;
import java.nio.file.Path;
import java.nio.file.Paths;
diff --git a/src/main/java/seedu/address/commons/core/GuiSettings.java b/src/main/java/seedu/heymatez/commons/core/GuiSettings.java
similarity index 98%
rename from src/main/java/seedu/address/commons/core/GuiSettings.java
rename to src/main/java/seedu/heymatez/commons/core/GuiSettings.java
index ba33653be67..a2d1a8386d6 100644
--- a/src/main/java/seedu/address/commons/core/GuiSettings.java
+++ b/src/main/java/seedu/heymatez/commons/core/GuiSettings.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.core;
+package seedu.heymatez.commons.core;
import java.awt.Point;
import java.io.Serializable;
diff --git a/src/main/java/seedu/address/commons/core/LogsCenter.java b/src/main/java/seedu/heymatez/commons/core/LogsCenter.java
similarity index 97%
rename from src/main/java/seedu/address/commons/core/LogsCenter.java
rename to src/main/java/seedu/heymatez/commons/core/LogsCenter.java
index 431e7185e76..2008418b5c0 100644
--- a/src/main/java/seedu/address/commons/core/LogsCenter.java
+++ b/src/main/java/seedu/heymatez/commons/core/LogsCenter.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.core;
+package seedu.heymatez.commons.core;
import java.io.IOException;
import java.util.Arrays;
@@ -18,7 +18,7 @@
public class LogsCenter {
private static final int MAX_FILE_COUNT = 5;
private static final int MAX_FILE_SIZE_IN_BYTES = (int) (Math.pow(2, 20) * 5); // 5MB
- private static final String LOG_FILE = "addressbook.log";
+ private static final String LOG_FILE = "HEYMATEz.log";
private static Level currentLogLevel = Level.INFO;
private static final Logger logger = LogsCenter.getLogger(LogsCenter.class);
private static FileHandler fileHandler;
diff --git a/src/main/java/seedu/heymatez/commons/core/Messages.java b/src/main/java/seedu/heymatez/commons/core/Messages.java
new file mode 100644
index 00000000000..0efa6502484
--- /dev/null
+++ b/src/main/java/seedu/heymatez/commons/core/Messages.java
@@ -0,0 +1,27 @@
+package seedu.heymatez.commons.core;
+
+/**
+ * Container for user visible messages.
+ */
+public class Messages {
+
+ public static final String MESSAGE_UNKNOWN_COMMAND = "Unknown command";
+ public static final String MESSAGE_INVALID_COMMAND_FORMAT = "Invalid command format! \n%1$s";
+ public static final String MESSAGE_INVALID_PERSON_DISPLAYED_NAME = "The member name provided is invalid! \n";
+ public static final String MESSAGE_INVALID_PERSON_PHONE = "The member phone number provided is invalid! \n";
+ public static final String MESSAGE_INVALID_PERSON_EMAIL = "The member email provided is invalid! \n";
+ public static final String MESSAGE_INVALID_PERSON_ROLE = "The member role provided is invalid! \n";
+ public static final String MESSAGE_PERSONS_LISTED_OVERVIEW = "%1$d members listed!";
+ public static final String MESSAGE_EMPTY_PERSON_LIST = "No members found!";
+ public static final String MESSAGE_INVALID_TASK_DISPLAYED_INDEX = "The task index provided is invalid! \n";
+ public static final String MESSAGE_INVALID_TASK_DESCRIPTION = "The task description provided is invalid! \n";
+ public static final String MESSAGE_INVALID_TASK_TITLE = "The task title provided is invalid! \n";
+ public static final String MESSAGE_INVALID_TASK_STATUS = "The task status provided is invalid! \n";
+ public static final String MESSAGE_INVALID_TASK_PRIORITY = "The task priority provided is invalid! \n";
+ public static final String MESSAGE_INVALID_TASK_ASSIGNEE = "The task assignee provided is invalid! \n";
+ public static final String MESSAGE_INVALID_TASK_DEADLINE = "The task deadline value provided is invalid! \n";
+ public static final String MESSAGE_INVALID_TASK_DEADLINE_FORMAT = "The task deadline format provided is "
+ + "incorrect! \n";
+ public static final String MESSAGE_EMPTY_TASK_LIST = "There are no tasks found!";
+ public static final String MESSAGE_TASKS_LISTED_OVERVIEW = "%1$d tasks listed!";
+}
diff --git a/src/main/java/seedu/address/commons/core/Version.java b/src/main/java/seedu/heymatez/commons/core/Version.java
similarity index 98%
rename from src/main/java/seedu/address/commons/core/Version.java
rename to src/main/java/seedu/heymatez/commons/core/Version.java
index 12142ec1e32..9279e278b23 100644
--- a/src/main/java/seedu/address/commons/core/Version.java
+++ b/src/main/java/seedu/heymatez/commons/core/Version.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.core;
+package seedu.heymatez.commons.core;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
diff --git a/src/main/java/seedu/address/commons/core/index/Index.java b/src/main/java/seedu/heymatez/commons/core/index/Index.java
similarity index 97%
rename from src/main/java/seedu/address/commons/core/index/Index.java
rename to src/main/java/seedu/heymatez/commons/core/index/Index.java
index 19536439c09..7ea2013f56d 100644
--- a/src/main/java/seedu/address/commons/core/index/Index.java
+++ b/src/main/java/seedu/heymatez/commons/core/index/Index.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.core.index;
+package seedu.heymatez.commons.core.index;
/**
* Represents a zero-based or one-based index.
diff --git a/src/main/java/seedu/address/commons/exceptions/DataConversionException.java b/src/main/java/seedu/heymatez/commons/exceptions/DataConversionException.java
similarity index 84%
rename from src/main/java/seedu/address/commons/exceptions/DataConversionException.java
rename to src/main/java/seedu/heymatez/commons/exceptions/DataConversionException.java
index 1f689bd8e3f..961cccf627f 100644
--- a/src/main/java/seedu/address/commons/exceptions/DataConversionException.java
+++ b/src/main/java/seedu/heymatez/commons/exceptions/DataConversionException.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.exceptions;
+package seedu.heymatez.commons.exceptions;
/**
* Represents an error during conversion of data from one format to another
diff --git a/src/main/java/seedu/address/commons/exceptions/IllegalValueException.java b/src/main/java/seedu/heymatez/commons/exceptions/IllegalValueException.java
similarity index 92%
rename from src/main/java/seedu/address/commons/exceptions/IllegalValueException.java
rename to src/main/java/seedu/heymatez/commons/exceptions/IllegalValueException.java
index 19124db485c..1079bd5b08f 100644
--- a/src/main/java/seedu/address/commons/exceptions/IllegalValueException.java
+++ b/src/main/java/seedu/heymatez/commons/exceptions/IllegalValueException.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.exceptions;
+package seedu.heymatez.commons.exceptions;
/**
* Signals that some given data does not fulfill some constraints.
diff --git a/src/main/java/seedu/address/commons/util/AppUtil.java b/src/main/java/seedu/heymatez/commons/util/AppUtil.java
similarity index 94%
rename from src/main/java/seedu/address/commons/util/AppUtil.java
rename to src/main/java/seedu/heymatez/commons/util/AppUtil.java
index 87aa89c0326..b1fc3bdf3dc 100644
--- a/src/main/java/seedu/address/commons/util/AppUtil.java
+++ b/src/main/java/seedu/heymatez/commons/util/AppUtil.java
@@ -1,9 +1,9 @@
-package seedu.address.commons.util;
+package seedu.heymatez.commons.util;
import static java.util.Objects.requireNonNull;
import javafx.scene.image.Image;
-import seedu.address.MainApp;
+import seedu.heymatez.MainApp;
/**
* A container for App specific utility functions
diff --git a/src/main/java/seedu/address/commons/util/CollectionUtil.java b/src/main/java/seedu/heymatez/commons/util/CollectionUtil.java
similarity index 96%
rename from src/main/java/seedu/address/commons/util/CollectionUtil.java
rename to src/main/java/seedu/heymatez/commons/util/CollectionUtil.java
index eafe4dfd681..937150a14e4 100644
--- a/src/main/java/seedu/address/commons/util/CollectionUtil.java
+++ b/src/main/java/seedu/heymatez/commons/util/CollectionUtil.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.util;
+package seedu.heymatez.commons.util;
import static java.util.Objects.requireNonNull;
diff --git a/src/main/java/seedu/address/commons/util/ConfigUtil.java b/src/main/java/seedu/heymatez/commons/util/ConfigUtil.java
similarity index 77%
rename from src/main/java/seedu/address/commons/util/ConfigUtil.java
rename to src/main/java/seedu/heymatez/commons/util/ConfigUtil.java
index f7f8a2bd44c..ce992aaae15 100644
--- a/src/main/java/seedu/address/commons/util/ConfigUtil.java
+++ b/src/main/java/seedu/heymatez/commons/util/ConfigUtil.java
@@ -1,11 +1,11 @@
-package seedu.address.commons.util;
+package seedu.heymatez.commons.util;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Optional;
-import seedu.address.commons.core.Config;
-import seedu.address.commons.exceptions.DataConversionException;
+import seedu.heymatez.commons.core.Config;
+import seedu.heymatez.commons.exceptions.DataConversionException;
/**
* A class for accessing the Config File.
diff --git a/src/main/java/seedu/address/commons/util/FileUtil.java b/src/main/java/seedu/heymatez/commons/util/FileUtil.java
similarity index 98%
rename from src/main/java/seedu/address/commons/util/FileUtil.java
rename to src/main/java/seedu/heymatez/commons/util/FileUtil.java
index b1e2767cdd9..110c3633eed 100644
--- a/src/main/java/seedu/address/commons/util/FileUtil.java
+++ b/src/main/java/seedu/heymatez/commons/util/FileUtil.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.util;
+package seedu.heymatez.commons.util;
import java.io.IOException;
import java.nio.file.Files;
diff --git a/src/main/java/seedu/address/commons/util/JsonUtil.java b/src/main/java/seedu/heymatez/commons/util/JsonUtil.java
similarity index 97%
rename from src/main/java/seedu/address/commons/util/JsonUtil.java
rename to src/main/java/seedu/heymatez/commons/util/JsonUtil.java
index 8ef609f055d..c997a97be98 100644
--- a/src/main/java/seedu/address/commons/util/JsonUtil.java
+++ b/src/main/java/seedu/heymatez/commons/util/JsonUtil.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.util;
+package seedu.heymatez.commons.util;
import static java.util.Objects.requireNonNull;
@@ -20,8 +20,8 @@
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
-import seedu.address.commons.core.LogsCenter;
-import seedu.address.commons.exceptions.DataConversionException;
+import seedu.heymatez.commons.core.LogsCenter;
+import seedu.heymatez.commons.exceptions.DataConversionException;
/**
* Converts a Java object instance to JSON and vice versa
diff --git a/src/main/java/seedu/address/commons/util/StringUtil.java b/src/main/java/seedu/heymatez/commons/util/StringUtil.java
similarity index 68%
rename from src/main/java/seedu/address/commons/util/StringUtil.java
rename to src/main/java/seedu/heymatez/commons/util/StringUtil.java
index 61cc8c9a1cb..e0fc6091a56 100644
--- a/src/main/java/seedu/address/commons/util/StringUtil.java
+++ b/src/main/java/seedu/heymatez/commons/util/StringUtil.java
@@ -1,7 +1,7 @@
-package seedu.address.commons.util;
+package seedu.heymatez.commons.util;
import static java.util.Objects.requireNonNull;
-import static seedu.address.commons.util.AppUtil.checkArgument;
+import static seedu.heymatez.commons.util.AppUtil.checkArgument;
import java.io.PrintWriter;
import java.io.StringWriter;
@@ -12,6 +12,12 @@
*/
public class StringUtil {
+ public static final int VALID_INTEGER = 1;
+
+ public static final int INVALID_INTEGER = 2;
+
+ public static final int INVALID_INPUT = 3;
+
/**
* Returns true if the {@code sentence} contains the {@code word}.
* Ignores case, but a full word match is required.
@@ -49,20 +55,28 @@ public static String getDetails(Throwable t) {
}
/**
- * Returns true if {@code s} represents a non-zero unsigned integer
+ * Returns an integer (1) VALID if {@code s} represents a non-zero unsigned integer or
* e.g. 1, 2, 3, ..., {@code Integer.MAX_VALUE}
- * Will return false for any other non-null string input
+ * an integer (2) INVALID_INTEGER if {@code s} represents a non-positive integer.
+ * e.g. 0, -1, -2, ..., {@code Integer.MIN_VALUE}
+ * Will return an integer (3) INVALID_INPUT for any other non-null string input
* e.g. empty string, "-1", "0", "+1", and " 2 " (untrimmed), "3 0" (contains whitespace), "1 a" (contains letters)
* @throws NullPointerException if {@code s} is null.
*/
- public static boolean isNonZeroUnsignedInteger(String s) {
+ public static int checkIndexValidity(String s) {
requireNonNull(s);
try {
int value = Integer.parseInt(s);
- return value > 0 && !s.startsWith("+"); // "+1" is successfully parsed by Integer#parseInt(String)
+ if (value > 0 && !s.startsWith("+")) { // "+1" is successfully parsed by Integer#parseInt(String)
+ return VALID_INTEGER;
+ } else if (value <= 0) {
+ return INVALID_INTEGER;
+ }
+ return INVALID_INPUT;
} catch (NumberFormatException nfe) {
- return false;
+ return INVALID_INPUT;
}
}
+
}
diff --git a/src/main/java/seedu/address/logic/Logic.java b/src/main/java/seedu/heymatez/logic/Logic.java
similarity index 56%
rename from src/main/java/seedu/address/logic/Logic.java
rename to src/main/java/seedu/heymatez/logic/Logic.java
index 92cd8fa605a..61627158750 100644
--- a/src/main/java/seedu/address/logic/Logic.java
+++ b/src/main/java/seedu/heymatez/logic/Logic.java
@@ -1,14 +1,16 @@
-package seedu.address.logic;
+package seedu.heymatez.logic;
import java.nio.file.Path;
import javafx.collections.ObservableList;
-import seedu.address.commons.core.GuiSettings;
-import seedu.address.logic.commands.CommandResult;
-import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.logic.parser.exceptions.ParseException;
-import seedu.address.model.ReadOnlyAddressBook;
-import seedu.address.model.person.Person;
+import seedu.heymatez.commons.core.GuiSettings;
+import seedu.heymatez.logic.commands.CommandResult;
+import seedu.heymatez.logic.commands.exceptions.CommandException;
+import seedu.heymatez.logic.parser.exceptions.ParseException;
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.ReadOnlyHeyMatez;
+import seedu.heymatez.model.person.Person;
+import seedu.heymatez.model.task.Task;
/**
* API of the Logic component
@@ -24,19 +26,22 @@ public interface Logic {
CommandResult execute(String commandText) throws CommandException, ParseException;
/**
- * Returns the AddressBook.
+ * Returns the HeyMatez.
*
- * @see seedu.address.model.Model#getAddressBook()
+ * @see Model#getHeyMatez()
*/
- ReadOnlyAddressBook getAddressBook();
+ ReadOnlyHeyMatez getHeyMatez();
/** Returns an unmodifiable view of the filtered list of persons */
ObservableList getFilteredPersonList();
+ /** Returns an unmodifiable view of the filtered list of tasks */
+ ObservableList getFilteredTaskList();
+
/**
- * Returns the user prefs' address book file path.
+ * Returns the user prefs' hey matez file path.
*/
- Path getAddressBookFilePath();
+ Path getHeyMatezFilePath();
/**
* Returns the user prefs' GUI settings.
diff --git a/src/main/java/seedu/address/logic/LogicManager.java b/src/main/java/seedu/heymatez/logic/LogicManager.java
similarity index 57%
rename from src/main/java/seedu/address/logic/LogicManager.java
rename to src/main/java/seedu/heymatez/logic/LogicManager.java
index 9d9c6d15bdc..8f8e02c1af4 100644
--- a/src/main/java/seedu/address/logic/LogicManager.java
+++ b/src/main/java/seedu/heymatez/logic/LogicManager.java
@@ -1,21 +1,22 @@
-package seedu.address.logic;
+package seedu.heymatez.logic;
import java.io.IOException;
import java.nio.file.Path;
import java.util.logging.Logger;
import javafx.collections.ObservableList;
-import seedu.address.commons.core.GuiSettings;
-import seedu.address.commons.core.LogsCenter;
-import seedu.address.logic.commands.Command;
-import seedu.address.logic.commands.CommandResult;
-import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.logic.parser.AddressBookParser;
-import seedu.address.logic.parser.exceptions.ParseException;
-import seedu.address.model.Model;
-import seedu.address.model.ReadOnlyAddressBook;
-import seedu.address.model.person.Person;
-import seedu.address.storage.Storage;
+import seedu.heymatez.commons.core.GuiSettings;
+import seedu.heymatez.commons.core.LogsCenter;
+import seedu.heymatez.logic.commands.Command;
+import seedu.heymatez.logic.commands.CommandResult;
+import seedu.heymatez.logic.commands.exceptions.CommandException;
+import seedu.heymatez.logic.parser.HeyMatezParser;
+import seedu.heymatez.logic.parser.exceptions.ParseException;
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.ReadOnlyHeyMatez;
+import seedu.heymatez.model.person.Person;
+import seedu.heymatez.model.task.Task;
+import seedu.heymatez.storage.Storage;
/**
* The main LogicManager of the app.
@@ -26,7 +27,7 @@ public class LogicManager implements Logic {
private final Model model;
private final Storage storage;
- private final AddressBookParser addressBookParser;
+ private final HeyMatezParser heyMatezParser;
/**
* Constructs a {@code LogicManager} with the given {@code Model} and {@code Storage}.
@@ -34,7 +35,7 @@ public class LogicManager implements Logic {
public LogicManager(Model model, Storage storage) {
this.model = model;
this.storage = storage;
- addressBookParser = new AddressBookParser();
+ heyMatezParser = new HeyMatezParser();
}
@Override
@@ -42,11 +43,10 @@ public CommandResult execute(String commandText) throws CommandException, ParseE
logger.info("----------------[USER COMMAND][" + commandText + "]");
CommandResult commandResult;
- Command command = addressBookParser.parseCommand(commandText);
+ Command command = heyMatezParser.parseCommand(commandText);
commandResult = command.execute(model);
-
try {
- storage.saveAddressBook(model.getAddressBook());
+ storage.saveHeyMatez(model.getHeyMatez());
} catch (IOException ioe) {
throw new CommandException(FILE_OPS_ERROR_MESSAGE + ioe, ioe);
}
@@ -55,8 +55,8 @@ public CommandResult execute(String commandText) throws CommandException, ParseE
}
@Override
- public ReadOnlyAddressBook getAddressBook() {
- return model.getAddressBook();
+ public ReadOnlyHeyMatez getHeyMatez() {
+ return model.getHeyMatez();
}
@Override
@@ -65,8 +65,13 @@ public ObservableList getFilteredPersonList() {
}
@Override
- public Path getAddressBookFilePath() {
- return model.getAddressBookFilePath();
+ public ObservableList getFilteredTaskList() {
+ return model.getFilteredTaskList();
+ }
+
+ @Override
+ public Path getHeyMatezFilePath() {
+ return model.getHeyMatezFilePath();
}
@Override
diff --git a/src/main/java/seedu/heymatez/logic/commands/AddMemberCommand.java b/src/main/java/seedu/heymatez/logic/commands/AddMemberCommand.java
new file mode 100644
index 00000000000..a4bd9df1e9d
--- /dev/null
+++ b/src/main/java/seedu/heymatez/logic/commands/AddMemberCommand.java
@@ -0,0 +1,62 @@
+package seedu.heymatez.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.heymatez.logic.parser.CliSyntax.PREFIX_EMAIL;
+import static seedu.heymatez.logic.parser.CliSyntax.PREFIX_PHONE;
+import static seedu.heymatez.logic.parser.CliSyntax.PREFIX_ROLE;
+
+import seedu.heymatez.logic.commands.exceptions.CommandException;
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.person.Person;
+
+/**
+ * Adds a person to HeyMatez.
+ */
+public class AddMemberCommand extends Command {
+
+ public static final String COMMAND_WORD = "addMember";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Adds a member to HeyMatez. \n"
+ + "Parameters: "
+ + "NAME "
+ + PREFIX_PHONE + "PHONE "
+ + PREFIX_EMAIL + "EMAIL "
+ + "[ " + PREFIX_ROLE + "ROLE ] \n"
+ + "Example: " + COMMAND_WORD
+ + " John Doe "
+ + PREFIX_PHONE + "98765432 "
+ + PREFIX_EMAIL + "johnd@example.com "
+ + PREFIX_ROLE + "Vice president";
+
+ public static final String MESSAGE_SUCCESS = "New Member Added: %1$s";
+ public static final String MESSAGE_DUPLICATE_PERSON = "This member already exists in HeyMatez!";
+
+ private final Person toAdd;
+
+ /**
+ * Creates an AddCommand to add the specified {@code Person}
+ */
+ public AddMemberCommand(Person person) {
+ requireNonNull(person);
+ toAdd = person;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+
+ if (model.hasPerson(toAdd)) {
+ throw new CommandException(MESSAGE_DUPLICATE_PERSON);
+ }
+
+ model.addPerson(toAdd);
+ return new CommandResult(String.format(MESSAGE_SUCCESS, toAdd));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof AddMemberCommand // instanceof handles nulls
+ && toAdd.equals(((AddMemberCommand) other).toAdd));
+ }
+}
diff --git a/src/main/java/seedu/heymatez/logic/commands/AddTaskCommand.java b/src/main/java/seedu/heymatez/logic/commands/AddTaskCommand.java
new file mode 100644
index 00000000000..7cfbc604ade
--- /dev/null
+++ b/src/main/java/seedu/heymatez/logic/commands/AddTaskCommand.java
@@ -0,0 +1,74 @@
+package seedu.heymatez.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.heymatez.logic.parser.CliSyntax.PREFIX_ASSIGNEE;
+import static seedu.heymatez.logic.parser.CliSyntax.PREFIX_DEADLINE;
+import static seedu.heymatez.logic.parser.CliSyntax.PREFIX_DESCRIPTION;
+import static seedu.heymatez.logic.parser.CliSyntax.PREFIX_PRIORITY;
+import static seedu.heymatez.logic.parser.CliSyntax.PREFIX_STATUS;
+
+import seedu.heymatez.logic.commands.exceptions.CommandException;
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.assignee.Assignee;
+import seedu.heymatez.model.task.Task;
+
+/**
+ * Adds a task to HeyMatez.
+ */
+public class AddTaskCommand extends Command {
+
+ public static final String COMMAND_WORD = "addTask";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Adds a new task to HeyMatez dashboard.\n"
+ + "Parameters: "
+ + "TITLE "
+ + PREFIX_DESCRIPTION + "DESCRIPTION "
+ + PREFIX_DEADLINE + "DEADLINE "
+ + PREFIX_STATUS + "TASK STATUS "
+ + PREFIX_PRIORITY + "PRIORITY "
+ + "[" + PREFIX_ASSIGNEE + "ASSIGNEE]...\n"
+ + "Example: " + COMMAND_WORD + " "
+ + "Plan board meeting "
+ + PREFIX_DESCRIPTION + "Draft meeting agenda and proposal for board meeting "
+ + PREFIX_DEADLINE + "2021-05-02 "
+ + PREFIX_STATUS + "completed "
+ + PREFIX_PRIORITY + "high "
+ + PREFIX_ASSIGNEE + "Rachel";
+
+ public static final String MESSAGE_SUCCESS = "New Task added: %1$s";
+ public static final String MESSAGE_DUPLICATE_TASK = "A task with the same title already exists in the HeyMatez "
+ + "task board! Pick another Task title.";
+
+ private final Task toAddTask;
+
+ /**
+ * Creates an AddTaskCommand to add the specified {@code Task}
+ */
+ public AddTaskCommand(Task task) {
+ requireNonNull(task);
+ toAddTask = task;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+
+ if (model.hasTask(toAddTask)) {
+ throw new CommandException(MESSAGE_DUPLICATE_TASK);
+ }
+
+ if (!model.checkAssignees(toAddTask)) {
+ throw new CommandException(Assignee.MESSAGE_CONSTRAINTS);
+ }
+
+ model.addTask(toAddTask);
+ return new CommandResult(String.format(MESSAGE_SUCCESS, toAddTask));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof AddTaskCommand // instanceof handles nulls
+ && toAddTask.equals(((AddTaskCommand) other).toAddTask));
+ }
+}
diff --git a/src/main/java/seedu/heymatez/logic/commands/ClearAssigneesCommand.java b/src/main/java/seedu/heymatez/logic/commands/ClearAssigneesCommand.java
new file mode 100644
index 00000000000..f6ef565bf07
--- /dev/null
+++ b/src/main/java/seedu/heymatez/logic/commands/ClearAssigneesCommand.java
@@ -0,0 +1,90 @@
+package seedu.heymatez.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX;
+import static seedu.heymatez.model.Model.PREDICATE_SHOW_ALL_TASKS;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import seedu.heymatez.commons.core.index.Index;
+import seedu.heymatez.logic.commands.exceptions.CommandException;
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.assignee.Assignee;
+import seedu.heymatez.model.task.Deadline;
+import seedu.heymatez.model.task.Description;
+import seedu.heymatez.model.task.Priority;
+import seedu.heymatez.model.task.Task;
+import seedu.heymatez.model.task.TaskStatus;
+import seedu.heymatez.model.task.Title;
+
+/**
+ * Remove all members assigned to a task, identified by the task's index in the task list.
+ */
+public class ClearAssigneesCommand extends Command {
+ public static final String COMMAND_WORD = "clearAssignees";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Clears all members assigned to a task, identified by the task's index number "
+ + " used in the displayed task list.\n"
+ + "Parameters: INDEX (must be a positive integer)\n"
+ + "Example: " + COMMAND_WORD + " 1";
+
+ public static final String MESSAGE_CLEARED_ASSIGNEES_SUCCESS = "Cleared all Members Assigned to Task: %1$s";
+
+
+ public static final String MESSAGE_ASSIGNEES_SET_IS_EMPTY = "There are no members assigned to this task, "
+ + "nothing to clear!";
+
+ private final Index targetIndex;
+
+ public ClearAssigneesCommand(Index targetIndex) {
+ this.targetIndex = targetIndex;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ List lastShownList = model.getFilteredTaskList();
+
+ if (targetIndex.getZeroBased() >= lastShownList.size()) {
+ throw new CommandException(MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+
+ Task taskToClear = lastShownList.get(targetIndex.getZeroBased());
+ Task clearedTask = createModifiedTask(taskToClear);
+
+ if (!taskToClear.hasAnyAssignees()) {
+ return new CommandResult(MESSAGE_ASSIGNEES_SET_IS_EMPTY);
+ }
+
+ model.setTask(taskToClear, clearedTask);
+ model.updateFilteredTaskList(PREDICATE_SHOW_ALL_TASKS);
+ return new CommandResult(String.format(MESSAGE_CLEARED_ASSIGNEES_SUCCESS, clearedTask));
+ }
+
+ /**
+ * Creates and returns a {@code Task} with its assignees cleared.
+ */
+ private static Task createModifiedTask(Task taskToClear) {
+ assert taskToClear != null;
+
+ Title updatedTitle = taskToClear.getTitle();
+ Description updatedDescription = taskToClear.getDescription();
+ Deadline updatedDeadline = taskToClear.getDeadline();
+ TaskStatus updatedStatus = taskToClear.getTaskStatus();
+ Priority updatedPriority = taskToClear.getPriority();
+ Set updatedAssignees = new HashSet<>();
+
+ return new Task(updatedTitle, updatedDescription, updatedDeadline, updatedStatus, updatedPriority,
+ updatedAssignees);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof ClearAssigneesCommand // instanceof handles nulls
+ && targetIndex.equals(((ClearAssigneesCommand) other).targetIndex));
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/ClearCommand.java b/src/main/java/seedu/heymatez/logic/commands/ClearCommand.java
similarity index 53%
rename from src/main/java/seedu/address/logic/commands/ClearCommand.java
rename to src/main/java/seedu/heymatez/logic/commands/ClearCommand.java
index 9c86b1fa6e4..f36fe8a8ef9 100644
--- a/src/main/java/seedu/address/logic/commands/ClearCommand.java
+++ b/src/main/java/seedu/heymatez/logic/commands/ClearCommand.java
@@ -1,23 +1,23 @@
-package seedu.address.logic.commands;
+package seedu.heymatez.logic.commands;
import static java.util.Objects.requireNonNull;
-import seedu.address.model.AddressBook;
-import seedu.address.model.Model;
+import seedu.heymatez.model.HeyMatez;
+import seedu.heymatez.model.Model;
/**
- * Clears the address book.
+ * Clears HeyMatez.
*/
public class ClearCommand extends Command {
public static final String COMMAND_WORD = "clear";
- public static final String MESSAGE_SUCCESS = "Address book has been cleared!";
+ public static final String MESSAGE_SUCCESS = "HEY MATEz has been cleared!";
@Override
public CommandResult execute(Model model) {
requireNonNull(model);
- model.setAddressBook(new AddressBook());
+ model.setHeyMatez(new HeyMatez());
return new CommandResult(MESSAGE_SUCCESS);
}
}
diff --git a/src/main/java/seedu/address/logic/commands/Command.java b/src/main/java/seedu/heymatez/logic/commands/Command.java
similarity index 78%
rename from src/main/java/seedu/address/logic/commands/Command.java
rename to src/main/java/seedu/heymatez/logic/commands/Command.java
index 64f18992160..804ebcdbd74 100644
--- a/src/main/java/seedu/address/logic/commands/Command.java
+++ b/src/main/java/seedu/heymatez/logic/commands/Command.java
@@ -1,7 +1,7 @@
-package seedu.address.logic.commands;
+package seedu.heymatez.logic.commands;
-import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.model.Model;
+import seedu.heymatez.logic.commands.exceptions.CommandException;
+import seedu.heymatez.model.Model;
/**
* Represents a command with hidden internal logic and the ability to be executed.
diff --git a/src/main/java/seedu/address/logic/commands/CommandResult.java b/src/main/java/seedu/heymatez/logic/commands/CommandResult.java
similarity index 97%
rename from src/main/java/seedu/address/logic/commands/CommandResult.java
rename to src/main/java/seedu/heymatez/logic/commands/CommandResult.java
index 92f900b7916..856ea02a1d4 100644
--- a/src/main/java/seedu/address/logic/commands/CommandResult.java
+++ b/src/main/java/seedu/heymatez/logic/commands/CommandResult.java
@@ -1,4 +1,4 @@
-package seedu.address.logic.commands;
+package seedu.heymatez.logic.commands;
import static java.util.Objects.requireNonNull;
@@ -67,5 +67,4 @@ public boolean equals(Object other) {
public int hashCode() {
return Objects.hash(feedbackToUser, showHelp, exit);
}
-
}
diff --git a/src/main/java/seedu/heymatez/logic/commands/DeleteMemberCommand.java b/src/main/java/seedu/heymatez/logic/commands/DeleteMemberCommand.java
new file mode 100644
index 00000000000..6d3dd6b8c67
--- /dev/null
+++ b/src/main/java/seedu/heymatez/logic/commands/DeleteMemberCommand.java
@@ -0,0 +1,64 @@
+package seedu.heymatez.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_PERSON_DISPLAYED_NAME;
+
+import java.util.List;
+
+import seedu.heymatez.logic.commands.exceptions.CommandException;
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.person.Name;
+import seedu.heymatez.model.person.Person;
+
+/**
+ * Deletes a person identified using its displayed name in HeyMatez.
+ */
+public class DeleteMemberCommand extends Command {
+
+ public static final String COMMAND_WORD = "deleteMember";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Deletes the member identified by the exact name (case-sensitive and format-sensitive) used in the "
+ + "displayed members list.\n"
+ + "Parameters: NAME (must be a valid name)\n"
+ + "Example: " + COMMAND_WORD + " John";
+
+ public static final String MESSAGE_DELETE_PERSON_SUCCESS = "Deleted Member: %1$s";
+
+ private final Name name;
+
+ public DeleteMemberCommand(Name name) {
+ this.name = name;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ List lastShownList = model.getFilteredPersonList();
+ Person personToDelete = null;
+
+ for (Person person : lastShownList) {
+ Name currentName = person.getName();
+
+ if (name.equals(currentName)) {
+ personToDelete = person;
+ break;
+ }
+ }
+
+ if (personToDelete == null) {
+ throw new CommandException(MESSAGE_INVALID_PERSON_DISPLAYED_NAME);
+ }
+
+ model.deletePerson(personToDelete);
+ model.removeAssignee(personToDelete);
+ return new CommandResult(String.format(MESSAGE_DELETE_PERSON_SUCCESS, personToDelete));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof DeleteMemberCommand // instanceof handles nulls
+ && name.equals(((DeleteMemberCommand) other).name)); // state check
+ }
+}
diff --git a/src/main/java/seedu/heymatez/logic/commands/DeleteTaskCommand.java b/src/main/java/seedu/heymatez/logic/commands/DeleteTaskCommand.java
new file mode 100644
index 00000000000..26080c54161
--- /dev/null
+++ b/src/main/java/seedu/heymatez/logic/commands/DeleteTaskCommand.java
@@ -0,0 +1,54 @@
+package seedu.heymatez.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX;
+
+import java.util.List;
+
+import seedu.heymatez.commons.core.index.Index;
+import seedu.heymatez.logic.commands.exceptions.CommandException;
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.task.Task;
+
+/**
+ * Deletes a task identified using it's displayed index from HeyMatez.
+ */
+public class DeleteTaskCommand extends Command {
+
+ public static final String COMMAND_WORD = "deleteTask";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Deletes the task identified by the index number used in the displayed task list.\n"
+ + "Parameters: INDEX (must be a positive integer)\n"
+ + "Example: " + COMMAND_WORD + " 1";
+
+ public static final String MESSAGE_DELETE_TASK_SUCCESS = "Deleted Task: %1$s";
+
+
+ private final Index targetIndex;
+
+ public DeleteTaskCommand(Index targetIndex) {
+ this.targetIndex = targetIndex;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ List lastShownList = model.getFilteredTaskList();
+
+ if (targetIndex.getZeroBased() >= lastShownList.size()) {
+ throw new CommandException(MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+
+ Task taskToDelete = lastShownList.get(targetIndex.getZeroBased());
+ model.deleteTask(taskToDelete);
+ return new CommandResult(String.format(MESSAGE_DELETE_TASK_SUCCESS, taskToDelete));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof DeleteTaskCommand // instanceof handles nulls
+ && targetIndex.equals(((DeleteTaskCommand) other).targetIndex)); // state check
+ }
+}
diff --git a/src/main/java/seedu/heymatez/logic/commands/DoneTaskCommand.java b/src/main/java/seedu/heymatez/logic/commands/DoneTaskCommand.java
new file mode 100644
index 00000000000..aacd4c89c04
--- /dev/null
+++ b/src/main/java/seedu/heymatez/logic/commands/DoneTaskCommand.java
@@ -0,0 +1,111 @@
+package seedu.heymatez.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX;
+
+import java.util.List;
+import java.util.Set;
+
+import seedu.heymatez.commons.core.index.Index;
+import seedu.heymatez.logic.commands.exceptions.CommandException;
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.assignee.Assignee;
+import seedu.heymatez.model.task.Deadline;
+import seedu.heymatez.model.task.Description;
+import seedu.heymatez.model.task.Priority;
+import seedu.heymatez.model.task.Task;
+import seedu.heymatez.model.task.TaskStatus;
+import seedu.heymatez.model.task.Title;
+
+/**
+ * Represents a DoneTaskCommand.
+ * Changes the status of existing task in HeyMatez to completed.
+ */
+public class DoneTaskCommand extends Command {
+ public static final String COMMAND_WORD = "done";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Changes the status of a task with the task index "
+ + "you specify from uncompleted to completed. \n"
+ + "Parameters: INDEX (must be a positive integer)\n"
+ + "Example: " + COMMAND_WORD + " 1 ";
+
+ public static final String MESSAGE_DONE_TASK_SUCCESS = "Task has been marked as completed.";
+
+ public static final String MESSAGE_TASK_ALREADY_MARKED_DONE = "Task has already been marked completed!";
+
+ private final Index index;
+
+ /**
+ * @param index of the task in the filtered task list to mark as completed.
+ */
+ public DoneTaskCommand(Index index) {
+ requireNonNull(index);
+
+ this.index = index;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ List lastShownList = model.getFilteredTaskList();
+
+ if (index.getZeroBased() >= lastShownList.size()) {
+ throw new CommandException(MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+
+ Task taskToMarkDone = lastShownList.get(index.getZeroBased());
+ Task doneTask = createDoneTask(taskToMarkDone);
+
+ assert doneTask != null;
+
+ model.setTask(taskToMarkDone, doneTask);
+ return new CommandResult(MESSAGE_DONE_TASK_SUCCESS);
+ }
+
+ /**
+ * Creates and returns a {@code Task} with the details of {@code taskToUndo}
+ *
+ * @params taskToUndo task to be marked as completed
+ * @return A Task with the updated completed status
+ */
+ public static Task createDoneTask(Task taskToDone) throws CommandException {
+ assert taskToDone != null;
+
+ Title updatedTitle = taskToDone.getTitle();
+ Description updatedDescription = taskToDone.getDescription();
+ Deadline updatedDeadline = taskToDone.getDeadline();
+
+ TaskStatus current = taskToDone.getTaskStatus();
+
+ if (current == TaskStatus.COMPLETED) {
+ throw new CommandException(MESSAGE_TASK_ALREADY_MARKED_DONE);
+ }
+
+ TaskStatus updatedStatus = TaskStatus.COMPLETED;
+
+ Priority updatedPriority = taskToDone.getPriority();
+ Set updatedAssignees = taskToDone.getAssignees();
+
+ return new Task(updatedTitle, updatedDescription, updatedDeadline, updatedStatus, updatedPriority,
+ updatedAssignees);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ // short circuit if same object
+ if (other == this) {
+ return true;
+ }
+
+ // instanceof handles nulls
+ if (!(other instanceof DoneTaskCommand)) {
+ return false;
+ }
+
+ // state check
+ DoneTaskCommand e = (DoneTaskCommand) other;
+ System.out.println(index);
+ System.out.println(e.index);
+ return index.equals(e.index);
+ }
+}
diff --git a/src/main/java/seedu/heymatez/logic/commands/EditMemberCommand.java b/src/main/java/seedu/heymatez/logic/commands/EditMemberCommand.java
new file mode 100644
index 00000000000..68591705173
--- /dev/null
+++ b/src/main/java/seedu/heymatez/logic/commands/EditMemberCommand.java
@@ -0,0 +1,209 @@
+package seedu.heymatez.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_PERSON_DISPLAYED_NAME;
+import static seedu.heymatez.logic.parser.CliSyntax.PREFIX_EMAIL;
+import static seedu.heymatez.logic.parser.CliSyntax.PREFIX_NEW_NAME;
+import static seedu.heymatez.logic.parser.CliSyntax.PREFIX_PHONE;
+import static seedu.heymatez.logic.parser.CliSyntax.PREFIX_ROLE;
+import static seedu.heymatez.model.Model.PREDICATE_SHOW_ALL_PERSONS;
+
+import java.util.List;
+import java.util.Optional;
+
+import seedu.heymatez.commons.util.CollectionUtil;
+import seedu.heymatez.logic.commands.exceptions.CommandException;
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.person.Email;
+import seedu.heymatez.model.person.Name;
+import seedu.heymatez.model.person.Person;
+import seedu.heymatez.model.person.Phone;
+import seedu.heymatez.model.person.Role;
+
+/**
+ * Edits the details of an existing person in HeyMatez.
+ */
+public class EditMemberCommand extends Command {
+
+ public static final String COMMAND_WORD = "editMember";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Edits the details of the member identified "
+ + "by the exact name (case-sensitive and format-sensitive) used in the displayed members list. "
+ + "Existing details will be overwritten by the input details.\n"
+ + "Parameters: NAME_IN_LIST "
+ + "[" + PREFIX_NEW_NAME + "NEW_NAME] "
+ + "[" + PREFIX_PHONE + "NEW_PHONE] "
+ + "[" + PREFIX_EMAIL + "NEW_EMAIL] "
+ + "[" + PREFIX_ROLE + "NEW_ROLE] "
+ + "Example: " + COMMAND_WORD + "John "
+ + PREFIX_NEW_NAME + "John Lim "
+ + PREFIX_PHONE + "91234567 "
+ + PREFIX_EMAIL + "john@example.com "
+ + PREFIX_ROLE + "Assistant treasurer";
+
+ public static final String MESSAGE_EDIT_PERSON_SUCCESS = "Edited Member: %1$s";
+ public static final String MESSAGE_NOT_EDITED = "At least one field to edit must be provided.";
+ public static final String MESSAGE_DUPLICATE_PERSON = "This member already exists in HeyMatez!";
+
+ private final Name name;
+ private final EditMemberDescriptor editMemberDescriptor;
+
+ /**
+ * @param name of the person in the filtered person list to edit
+ * @param editMemberDescriptor details to edit the person with
+ */
+ public EditMemberCommand(Name name, EditMemberDescriptor editMemberDescriptor) {
+ requireNonNull(editMemberDescriptor);
+
+ this.name = name;
+ this.editMemberDescriptor = new EditMemberDescriptor(editMemberDescriptor);
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ List lastShownList = model.getFilteredPersonList();
+ Person personToEdit = null;
+
+ for (Person person : lastShownList) {
+ Name currentName = person.getName();
+
+ if (name.equals(currentName)) {
+ personToEdit = person;
+ break;
+ }
+ }
+
+ if (personToEdit == null) {
+ throw new CommandException(MESSAGE_INVALID_PERSON_DISPLAYED_NAME);
+ }
+
+ Person editedPerson = createEditedPerson(personToEdit, editMemberDescriptor);
+
+ if (!personToEdit.isSamePerson(editedPerson) && model.hasPerson(editedPerson)) {
+ throw new CommandException(MESSAGE_DUPLICATE_PERSON);
+ }
+
+ model.setPerson(personToEdit, editedPerson);
+ model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
+ model.editAssignee(personToEdit, editedPerson);
+ return new CommandResult(String.format(MESSAGE_EDIT_PERSON_SUCCESS, editedPerson));
+ }
+
+ /**
+ * Creates and returns a {@code Person} with the details of {@code personToEdit}
+ * edited with {@code editPersonDescriptor}.
+ */
+ private static Person createEditedPerson(Person personToEdit, EditMemberDescriptor editMemberDescriptor) {
+ assert personToEdit != null;
+
+ Name updatedName = editMemberDescriptor.getName().orElse(personToEdit.getName());
+ Phone updatedPhone = editMemberDescriptor.getPhone().orElse(personToEdit.getPhone());
+ Email updatedEmail = editMemberDescriptor.getEmail().orElse(personToEdit.getEmail());
+ Role updatedRole = editMemberDescriptor.getRole().orElse(personToEdit.getRole());
+
+ return new Person(updatedName, updatedPhone, updatedEmail, updatedRole);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ // short circuit if same object
+ if (other == this) {
+ return true;
+ }
+
+ // instanceof handles nulls
+ if (!(other instanceof EditMemberCommand)) {
+ return false;
+ }
+
+ // state check
+ EditMemberCommand e = (EditMemberCommand) other;
+ return name.equals(e.name)
+ && editMemberDescriptor.equals(e.editMemberDescriptor);
+ }
+
+ /**
+ * Stores the details to edit the person with. Each non-empty field value will replace the
+ * corresponding field value of the person.
+ */
+ public static class EditMemberDescriptor {
+ private Name name;
+ private Phone phone;
+ private Email email;
+ private Role role;
+
+ public EditMemberDescriptor() {}
+
+ /**
+ * Copy constructor.
+ * A defensive copy of {@code assignees} is used internally.
+ */
+ public EditMemberDescriptor(EditMemberDescriptor toCopy) {
+ setName(toCopy.name);
+ setPhone(toCopy.phone);
+ setEmail(toCopy.email);
+ setRole(toCopy.role);
+ }
+
+ /**
+ * Returns true if at least one field is edited.
+ */
+ public boolean isAnyFieldEdited() {
+ return CollectionUtil.isAnyNonNull(name, phone, email, role);
+ }
+
+ public void setName(Name name) {
+ this.name = name;
+ }
+
+ public Optional getName() {
+ return Optional.ofNullable(name);
+ }
+
+ public void setPhone(Phone phone) {
+ this.phone = phone;
+ }
+
+ public Optional getPhone() {
+ return Optional.ofNullable(phone);
+ }
+
+ public void setEmail(Email email) {
+ this.email = email;
+ }
+
+ public Optional getEmail() {
+ return Optional.ofNullable(email);
+ }
+
+ public void setRole(Role role) {
+ this.role = role;
+ }
+
+ public Optional getRole() {
+ return Optional.ofNullable(role);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ // short circuit if same object
+ if (other == this) {
+ return true;
+ }
+
+ // instanceof handles nulls
+ if (!(other instanceof EditMemberDescriptor)) {
+ return false;
+ }
+
+ // state check
+ EditMemberDescriptor e = (EditMemberDescriptor) other;
+
+ return getName().equals(e.getName())
+ && getPhone().equals(e.getPhone())
+ && getEmail().equals(e.getEmail())
+ && getRole().equals(e.getRole());
+ }
+ }
+}
diff --git a/src/main/java/seedu/heymatez/logic/commands/EditTaskCommand.java b/src/main/java/seedu/heymatez/logic/commands/EditTaskCommand.java
new file mode 100644
index 00000000000..f10889b0c3b
--- /dev/null
+++ b/src/main/java/seedu/heymatez/logic/commands/EditTaskCommand.java
@@ -0,0 +1,249 @@
+package seedu.heymatez.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX;
+import static seedu.heymatez.logic.parser.CliSyntax.PREFIX_ASSIGNEE;
+import static seedu.heymatez.logic.parser.CliSyntax.PREFIX_DEADLINE;
+import static seedu.heymatez.logic.parser.CliSyntax.PREFIX_DESCRIPTION;
+import static seedu.heymatez.logic.parser.CliSyntax.PREFIX_PRIORITY;
+import static seedu.heymatez.logic.parser.CliSyntax.PREFIX_STATUS;
+import static seedu.heymatez.logic.parser.CliSyntax.PREFIX_TITLE;
+import static seedu.heymatez.model.Model.PREDICATE_SHOW_ALL_TASKS;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+
+import seedu.heymatez.commons.core.index.Index;
+import seedu.heymatez.commons.util.CollectionUtil;
+import seedu.heymatez.logic.commands.exceptions.CommandException;
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.assignee.Assignee;
+import seedu.heymatez.model.task.Deadline;
+import seedu.heymatez.model.task.Description;
+import seedu.heymatez.model.task.Priority;
+import seedu.heymatez.model.task.Task;
+import seedu.heymatez.model.task.TaskStatus;
+import seedu.heymatez.model.task.Title;
+
+/**
+ * Edits the details of an existing task in HeyMatez.
+ */
+public class EditTaskCommand extends Command {
+ public static final String COMMAND_WORD = "editTask";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Edits the details of the task identified "
+ + "by the index number used in the displayed task board. "
+ + "Existing values will be overwritten by the input values.\n"
+ + "Parameters: INDEX (must be a positive integer) "
+ + "[" + PREFIX_TITLE + "NEW_TITLE] "
+ + "[" + PREFIX_DESCRIPTION + "NEW_DESCRIPTION] "
+ + "[" + PREFIX_DEADLINE + "NEW_DEADLINE] "
+ + "[" + PREFIX_STATUS + "NEW_STATUS] "
+ + "[" + PREFIX_PRIORITY + "NEW_PRIORITY] "
+ + "[" + PREFIX_ASSIGNEE + "NEW_ASSIGNEE]...\n"
+ + "Example: " + COMMAND_WORD + " 1 "
+ + PREFIX_TITLE + "Plan open house meeting "
+ + PREFIX_STATUS + "completed";
+
+ public static final String MESSAGE_EDIT_TASK_SUCCESS = "Edited Task: %1$s";
+
+ public static final String MESSAGE_NOT_EDITED = "At least one field to edit must be provided.";
+
+ public static final String MESSAGE_DUPLICATE_TASK = "This task already exists in HeyMatez!";
+
+ private final Index index;
+ private final EditTaskCommand.EditTaskDescriptor editTaskDescriptor;
+
+ /**
+ * @param index of the task in the filtered task list to edit
+ * @param editTaskDescriptor details to edit the task with
+ */
+ public EditTaskCommand(Index index, EditTaskCommand.EditTaskDescriptor editTaskDescriptor) {
+ requireNonNull(index);
+ requireNonNull(editTaskDescriptor);
+
+ this.index = index;
+ this.editTaskDescriptor = new EditTaskCommand.EditTaskDescriptor(editTaskDescriptor);
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ List lastShownList = model.getFilteredTaskList();
+
+ if (index.getZeroBased() >= lastShownList.size()) {
+ throw new CommandException(MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+
+ Task taskToEdit = lastShownList.get(index.getZeroBased());
+ Task editedTask = createEditedTask(taskToEdit, editTaskDescriptor);
+
+ if (!model.checkAssignees(editedTask)) {
+ throw new CommandException(Assignee.MESSAGE_CONSTRAINTS);
+ }
+
+ if (!taskToEdit.isSameTask(editedTask) && model.hasTask(editedTask)) {
+ throw new CommandException(MESSAGE_DUPLICATE_TASK);
+ }
+
+ model.setTask(taskToEdit, editedTask);
+ model.updateFilteredTaskList(PREDICATE_SHOW_ALL_TASKS);
+ return new CommandResult(String.format(MESSAGE_EDIT_TASK_SUCCESS, editedTask));
+ }
+
+ /**
+ * Creates and returns a {@code Task} with the details of {@code taskToEdit}
+ * edited with {@code editTaskDescriptor}.
+ */
+ private static Task createEditedTask(Task taskToEdit, EditTaskCommand.EditTaskDescriptor editTaskDescriptor) {
+ assert taskToEdit != null;
+
+ Title updatedTitle = editTaskDescriptor.getTitle().orElse(taskToEdit.getTitle());
+ Description updatedDescription = editTaskDescriptor.getDescription().orElse(taskToEdit.getDescription());
+ Deadline updatedDeadline = editTaskDescriptor.getDeadline().orElse(taskToEdit.getDeadline());
+ TaskStatus updatedStatus = editTaskDescriptor.getStatus().orElse(taskToEdit.getTaskStatus());
+ Priority updatedPriority = editTaskDescriptor.getPriority().orElse(taskToEdit.getPriority());
+ Set updatedAssignees = editTaskDescriptor.getAssignees().orElse(taskToEdit.getAssignees());
+
+ return new Task(updatedTitle, updatedDescription, updatedDeadline, updatedStatus, updatedPriority,
+ updatedAssignees);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ // short circuit if same object
+ if (other == this) {
+ return true;
+ }
+
+ // instanceof handles nulls
+ if (!(other instanceof EditTaskCommand)) {
+ return false;
+ }
+
+ // state check
+ EditTaskCommand e = (EditTaskCommand) other;
+ System.out.println(index);
+ System.out.println(e.index);
+ return index.equals(e.index)
+ && editTaskDescriptor.equals(e.editTaskDescriptor);
+ }
+
+ /**
+ * Stores the details to edit the person with. Each non-empty field value will replace the
+ * corresponding field value of the person.
+ */
+ public static class EditTaskDescriptor {
+ private Title title;
+ private Description description;
+ private TaskStatus status;
+ private Deadline deadline;
+ private Priority priority;
+ private Set assignees;
+
+ public EditTaskDescriptor() {}
+
+ /**
+ * Copy constructor.
+ * A defensive copy of {@code assignees} is used internally.
+ */
+ public EditTaskDescriptor(EditTaskCommand.EditTaskDescriptor toCopy) {
+ setTitle(toCopy.title);
+ setDescription(toCopy.description);
+ setStatus(toCopy.status);
+ setDeadline(toCopy.deadline);
+ setPriority(toCopy.priority);
+ setAssignees(toCopy.assignees);
+ }
+
+ /**
+ * Returns true if at least one field is edited.
+ */
+ public boolean isAnyFieldEdited() {
+ return CollectionUtil.isAnyNonNull(title, description, status, deadline, priority, assignees);
+ }
+
+ public void setTitle(Title title) {
+ this.title = title;
+ }
+
+ public Optional getTitle() {
+ return Optional.ofNullable(title);
+ }
+
+ public void setDescription(Description description) {
+ this.description = description;
+ }
+
+ public Optional getDescription() {
+ return Optional.ofNullable(description);
+ }
+
+ public void setStatus(TaskStatus status) {
+ this.status = status;
+ }
+
+ public Optional getStatus() {
+ return Optional.ofNullable(status);
+ }
+
+ public void setDeadline(Deadline date) {
+ this.deadline = date;
+ }
+
+ public Optional getDeadline() {
+ return Optional.ofNullable(deadline);
+ }
+
+ public void setPriority(Priority priority) {
+ this.priority = priority;
+ }
+
+ public Optional getPriority() {
+ return Optional.ofNullable(priority);
+ }
+
+ /**
+ * Sets {@code assignees} to this object's {@code assignees}.
+ * A defensive copy of {@code assignees} is used internally.
+ */
+ public void setAssignees(Set assignees) {
+ this.assignees = (assignees != null) ? new HashSet<>(assignees) : null;
+ }
+
+ /**
+ * Returns an unmodifiable assignees set, which throws {@code UnsupportedOperationException}
+ * if modification is attempted.
+ * Returns {@code Optional#empty()} if {@code assignees} is null.
+ */
+ public Optional> getAssignees() {
+ return (assignees != null) ? Optional.of(Collections.unmodifiableSet(assignees)) : Optional.empty();
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ // short circuit if same object
+ if (other == this) {
+ return true;
+ }
+
+ // instanceof handles nulls
+ if (!(other instanceof EditTaskCommand.EditTaskDescriptor)) {
+ return false;
+ }
+
+ // state check
+ EditTaskCommand.EditTaskDescriptor e = (EditTaskCommand.EditTaskDescriptor) other;
+
+ return getTitle().equals(e.getTitle())
+ && getDescription().equals(e.getDescription())
+ && getStatus().equals(e.getStatus())
+ && getDeadline().equals(e.getDeadline())
+ && getPriority().equals(e.getPriority())
+ && getAssignees().equals(e.getAssignees());
+ }
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/ExitCommand.java b/src/main/java/seedu/heymatez/logic/commands/ExitCommand.java
similarity index 69%
rename from src/main/java/seedu/address/logic/commands/ExitCommand.java
rename to src/main/java/seedu/heymatez/logic/commands/ExitCommand.java
index 3dd85a8ba90..c7e00c1a9a1 100644
--- a/src/main/java/seedu/address/logic/commands/ExitCommand.java
+++ b/src/main/java/seedu/heymatez/logic/commands/ExitCommand.java
@@ -1,15 +1,15 @@
-package seedu.address.logic.commands;
+package seedu.heymatez.logic.commands;
-import seedu.address.model.Model;
+import seedu.heymatez.model.Model;
/**
- * Terminates the program.
+ * Terminates HeyMatez.
*/
public class ExitCommand extends Command {
public static final String COMMAND_WORD = "exit";
- public static final String MESSAGE_EXIT_ACKNOWLEDGEMENT = "Exiting Address Book as requested ...";
+ public static final String MESSAGE_EXIT_ACKNOWLEDGEMENT = "Exiting HEY MATEz as requested ... Goodbye";
@Override
public CommandResult execute(Model model) {
diff --git a/src/main/java/seedu/heymatez/logic/commands/FindByPriorityCommand.java b/src/main/java/seedu/heymatez/logic/commands/FindByPriorityCommand.java
new file mode 100644
index 00000000000..6dfd40867a2
--- /dev/null
+++ b/src/main/java/seedu/heymatez/logic/commands/FindByPriorityCommand.java
@@ -0,0 +1,49 @@
+package seedu.heymatez.logic.commands;
+
+
+import static java.util.Objects.requireNonNull;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_EMPTY_TASK_LIST;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_TASKS_LISTED_OVERVIEW;
+
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.task.PriorityContainsKeywordPredicate;
+
+/**
+ * Represents a FindByPriorityCommand.
+ * It displays tasks that are only of the specified priority value.
+ */
+public class FindByPriorityCommand extends Command {
+
+ public static final String COMMAND_WORD = "findPriority";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Finds all tasks with the specified priority "
+ + "and displays them as a list with index numbers\n "
+ + "Parameters: PRIORITY \n"
+ + "Example: " + COMMAND_WORD + " high";
+
+ private final PriorityContainsKeywordPredicate predicate;
+
+ public FindByPriorityCommand(PriorityContainsKeywordPredicate predicate) {
+ this.predicate = predicate;
+ }
+
+ @Override
+ public CommandResult execute(Model model) {
+ requireNonNull(model);
+ model.updateFilteredTaskList(predicate);
+
+ if (model.isTaskListEmpty()) {
+ return new CommandResult(MESSAGE_EMPTY_TASK_LIST);
+ }
+
+ return new CommandResult(
+ String.format(MESSAGE_TASKS_LISTED_OVERVIEW, model.getFilteredTaskList().size()));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof FindByPriorityCommand // instanceof handles nulls
+ && predicate.equals(((FindByPriorityCommand) other).predicate)); // state check
+ }
+}
diff --git a/src/main/java/seedu/heymatez/logic/commands/FindMemberTasksCommand.java b/src/main/java/seedu/heymatez/logic/commands/FindMemberTasksCommand.java
new file mode 100644
index 00000000000..cbec4aaf161
--- /dev/null
+++ b/src/main/java/seedu/heymatez/logic/commands/FindMemberTasksCommand.java
@@ -0,0 +1,47 @@
+package seedu.heymatez.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+
+import seedu.heymatez.commons.core.Messages;
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.task.TaskContainsAssigneePredicate;
+
+/**
+ * Finds and lists all tasks in HeyMatez who contains the assignee with the given name.
+ */
+public class FindMemberTasksCommand extends Command {
+
+ public static final String COMMAND_WORD = "findTasksFor";
+
+ public static final String MESSAGE_SUCCESS = "Listed all Tasks belonging to specified name.";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Find all tasks assigned to a single Member.\n"
+ + "Parameters: " + "NAME \n"
+ + "Example: " + COMMAND_WORD + " Rachel Tan";
+
+ private final TaskContainsAssigneePredicate predicate;
+
+ public FindMemberTasksCommand(TaskContainsAssigneePredicate predicate) {
+ this.predicate = predicate;
+ }
+
+ @Override
+ public CommandResult execute(Model model) {
+ requireNonNull(model);
+ model.updateFilteredTaskList(predicate);
+
+ if (model.isTaskListEmpty()) {
+ return new CommandResult(Messages.MESSAGE_EMPTY_TASK_LIST);
+ }
+
+ return new CommandResult(MESSAGE_SUCCESS);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof FindMemberTasksCommand // instanceof handles nulls
+ && predicate.equals(((FindMemberTasksCommand) other).predicate)); // state check
+ }
+}
+
diff --git a/src/main/java/seedu/heymatez/logic/commands/FindMembersCommand.java b/src/main/java/seedu/heymatez/logic/commands/FindMembersCommand.java
new file mode 100644
index 00000000000..8b40e5b7bd2
--- /dev/null
+++ b/src/main/java/seedu/heymatez/logic/commands/FindMembersCommand.java
@@ -0,0 +1,49 @@
+package seedu.heymatez.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_EMPTY_PERSON_LIST;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_PERSONS_LISTED_OVERVIEW;
+
+import seedu.heymatez.logic.commands.exceptions.CommandException;
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.person.DetailsContainsKeywordsPredicate;
+
+/**
+ * Finds and lists all persons in HeyMatez whose details contains any of the argument keywords.
+ * Keyword matching is case insensitive.
+ */
+public class FindMembersCommand extends Command {
+
+ public static final String COMMAND_WORD = "findMembers";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Finds all members whose name, phone number, "
+ + "email or role contain any of the specified keywords (case-insensitive) and displays them as a list.\n"
+ + "Parameters: KEYWORD [MORE_KEYWORDS]...\n"
+ + "Example: " + COMMAND_WORD + " alice 97574218 rachel@example.com";
+
+ private final DetailsContainsKeywordsPredicate predicate;
+
+ public FindMembersCommand(DetailsContainsKeywordsPredicate predicate) {
+ this.predicate = predicate;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ model.updateFilteredPersonList(predicate);
+
+ if (model.isPersonListEmpty()) {
+ return new CommandResult(MESSAGE_EMPTY_PERSON_LIST);
+ }
+
+ return new CommandResult(
+ String.format(MESSAGE_PERSONS_LISTED_OVERVIEW, model.getFilteredPersonList().size()));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof FindMembersCommand // instanceof handles nulls
+ && predicate.equals(((FindMembersCommand) other).predicate)); // state check
+ }
+}
diff --git a/src/main/java/seedu/heymatez/logic/commands/FindTasksBeforeCommand.java b/src/main/java/seedu/heymatez/logic/commands/FindTasksBeforeCommand.java
new file mode 100644
index 00000000000..52752488469
--- /dev/null
+++ b/src/main/java/seedu/heymatez/logic/commands/FindTasksBeforeCommand.java
@@ -0,0 +1,48 @@
+package seedu.heymatez.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_EMPTY_TASK_LIST;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_TASKS_LISTED_OVERVIEW;
+
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.task.DeadlineBeforeDatePredicate;
+
+/**
+ * Finds and lists all tasks in HeyMatez with deadline before a specified date.
+ */
+public class FindTasksBeforeCommand extends Command {
+ public static final String COMMAND_WORD = "findBefore";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Finds all tasks with deadline before the specified date "
+ + " and displays them as a list with index numbers.\n "
+ + "Parameters: DEADLINE \n"
+ + "Example: " + COMMAND_WORD + " 2021-03-26";
+
+ private final DeadlineBeforeDatePredicate predicate;
+
+ public FindTasksBeforeCommand(DeadlineBeforeDatePredicate predicate) {
+ this.predicate = predicate;
+ }
+
+ @Override
+ public CommandResult execute(Model model) {
+ requireNonNull(model);
+
+ model.updateFilteredTaskList(predicate);
+
+ if (model.isTaskListEmpty()) {
+ return new CommandResult(MESSAGE_EMPTY_TASK_LIST);
+ }
+
+ return new CommandResult(
+ String.format(MESSAGE_TASKS_LISTED_OVERVIEW, model.getFilteredTaskList().size()));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof FindTasksBeforeCommand // instanceof handles nulls
+ && predicate.equals(((FindTasksBeforeCommand) other).predicate)); // state check
+ }
+}
diff --git a/src/main/java/seedu/heymatez/logic/commands/FindTasksCommand.java b/src/main/java/seedu/heymatez/logic/commands/FindTasksCommand.java
new file mode 100644
index 00000000000..5e0b52d30a8
--- /dev/null
+++ b/src/main/java/seedu/heymatez/logic/commands/FindTasksCommand.java
@@ -0,0 +1,47 @@
+package seedu.heymatez.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_EMPTY_TASK_LIST;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_TASKS_LISTED_OVERVIEW;
+
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.task.TaskContainsKeywordPredicate;
+
+/**
+ * Finds and lists all tasks in HeyMatez with its title or description containing any of the argument keywords.
+ * Keyword matching is case insensitive.
+ */
+public class FindTasksCommand extends Command {
+ public static final String COMMAND_WORD = "findTasks";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Finds all tasks which contains any of the "
+ + "specified keywords (case-insensitive) in its title or description and displays them as a list. \n"
+ + "Parameters: KEYWORD [MORE_KEYWORDS]...\n"
+ + "Example: " + COMMAND_WORD + " plan meeting proposal";
+
+ private final TaskContainsKeywordPredicate predicate;
+
+ public FindTasksCommand(TaskContainsKeywordPredicate predicate) {
+ this.predicate = predicate;
+ }
+
+ @Override
+ public CommandResult execute(Model model) {
+ requireNonNull(model);
+
+ model.updateFilteredTaskList(predicate);
+
+ if (model.isTaskListEmpty()) {
+ return new CommandResult(MESSAGE_EMPTY_TASK_LIST);
+ }
+
+ return new CommandResult(String.format(MESSAGE_TASKS_LISTED_OVERVIEW, model.getFilteredTaskList().size()));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof FindTasksCommand // instanceof handles nulls
+ && predicate.equals(((FindTasksCommand) other).predicate)); // state check
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/HelpCommand.java b/src/main/java/seedu/heymatez/logic/commands/HelpCommand.java
similarity index 87%
rename from src/main/java/seedu/address/logic/commands/HelpCommand.java
rename to src/main/java/seedu/heymatez/logic/commands/HelpCommand.java
index bf824f91bd0..3c1ae9dab79 100644
--- a/src/main/java/seedu/address/logic/commands/HelpCommand.java
+++ b/src/main/java/seedu/heymatez/logic/commands/HelpCommand.java
@@ -1,6 +1,6 @@
-package seedu.address.logic.commands;
+package seedu.heymatez.logic.commands;
-import seedu.address.model.Model;
+import seedu.heymatez.model.Model;
/**
* Format full help instructions for every command for display.
diff --git a/src/main/java/seedu/heymatez/logic/commands/UndoTaskCommand.java b/src/main/java/seedu/heymatez/logic/commands/UndoTaskCommand.java
new file mode 100644
index 00000000000..f287663098d
--- /dev/null
+++ b/src/main/java/seedu/heymatez/logic/commands/UndoTaskCommand.java
@@ -0,0 +1,112 @@
+package seedu.heymatez.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX;
+
+import java.util.List;
+import java.util.Set;
+
+import seedu.heymatez.commons.core.index.Index;
+import seedu.heymatez.logic.commands.exceptions.CommandException;
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.assignee.Assignee;
+import seedu.heymatez.model.task.Deadline;
+import seedu.heymatez.model.task.Description;
+import seedu.heymatez.model.task.Priority;
+import seedu.heymatez.model.task.Task;
+import seedu.heymatez.model.task.TaskStatus;
+import seedu.heymatez.model.task.Title;
+
+/**
+ * Represents an Undo Task Command.
+ * Changes the status of existing task in HeyMatez to uncompleted.
+ */
+public class UndoTaskCommand extends Command {
+ public static final String COMMAND_WORD = "undo";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Changes the status of a task with the task index "
+ + "you specify from completed to uncompleted. \n"
+ + "Parameters: INDEX (must be a positive integer) \n"
+ + "Example: " + COMMAND_WORD + " 1 ";
+
+ public static final String MESSAGE_UNDO_TASK_SUCCESS = "Task has been marked as uncompleted.";
+
+ public static final String MESSAGE_TASK_ALREADY_MARKED_UNCOMPLETED = "Task has already been marked as uncompleted!";
+
+ private final Index index;
+
+ /**
+ * @param index of the task in the filtered task list to marked as uncompleted
+ */
+ public UndoTaskCommand(Index index) {
+ requireNonNull(index);
+
+ this.index = index;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ List lastShownList = model.getFilteredTaskList();
+
+ if (index.getZeroBased() >= lastShownList.size()) {
+ throw new CommandException(MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+
+ Task taskToMarkUndo = lastShownList.get(index.getZeroBased());
+ Task undoTask = createUndoTask(taskToMarkUndo);
+
+ assert undoTask != null;
+
+ model.setTask(taskToMarkUndo, undoTask);
+
+ return new CommandResult(MESSAGE_UNDO_TASK_SUCCESS);
+ }
+
+ /**
+ * Creates and returns a {@code Task} with the details of {@code taskToUndo}.
+ *
+ * @params taskToUndo task to be marked as uncompleted
+ * @return A Task with the updated uncompleted status
+ */
+ private static Task createUndoTask(Task taskToUndo) throws CommandException {
+ assert taskToUndo != null;
+
+ Title updatedTitle = taskToUndo.getTitle();
+ Description updatedDescription = taskToUndo.getDescription();
+ Deadline updatedDeadline = taskToUndo.getDeadline();
+
+ TaskStatus current = taskToUndo.getTaskStatus();
+
+ if (current == TaskStatus.UNCOMPLETED) {
+ throw new CommandException(MESSAGE_TASK_ALREADY_MARKED_UNCOMPLETED);
+ }
+
+ TaskStatus updatedStatus = TaskStatus.UNCOMPLETED;
+
+ Priority updatedPriority = taskToUndo.getPriority();
+ Set updatedAssignees = taskToUndo.getAssignees();
+
+ return new Task(updatedTitle, updatedDescription, updatedDeadline, updatedStatus, updatedPriority,
+ updatedAssignees);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ // short circuit if same object
+ if (other == this) {
+ return true;
+ }
+
+ // instanceof handles nulls
+ if (!(other instanceof UndoTaskCommand)) {
+ return false;
+ }
+
+ // state check
+ UndoTaskCommand e = (UndoTaskCommand) other;
+ System.out.println(index);
+ System.out.println(e.index);
+ return index.equals(e.index);
+ }
+}
diff --git a/src/main/java/seedu/heymatez/logic/commands/ViewMembersCommand.java b/src/main/java/seedu/heymatez/logic/commands/ViewMembersCommand.java
new file mode 100644
index 00000000000..e54b004b814
--- /dev/null
+++ b/src/main/java/seedu/heymatez/logic/commands/ViewMembersCommand.java
@@ -0,0 +1,30 @@
+package seedu.heymatez.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_EMPTY_PERSON_LIST;
+import static seedu.heymatez.model.Model.PREDICATE_SHOW_ALL_PERSONS;
+
+import seedu.heymatez.logic.commands.exceptions.CommandException;
+import seedu.heymatez.model.Model;
+
+/**
+ * Lists all persons in HeyMatez to the user.
+ */
+public class ViewMembersCommand extends Command {
+
+ public static final String COMMAND_WORD = "viewMembers";
+
+ public static final String MESSAGE_SUCCESS = "Listed all members in this Club.";
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
+
+ if (model.isPersonListEmpty()) {
+ return new CommandResult(MESSAGE_EMPTY_PERSON_LIST);
+ }
+
+ return new CommandResult(MESSAGE_SUCCESS);
+ }
+}
diff --git a/src/main/java/seedu/heymatez/logic/commands/ViewTasksCommand.java b/src/main/java/seedu/heymatez/logic/commands/ViewTasksCommand.java
new file mode 100644
index 00000000000..cdbd92da881
--- /dev/null
+++ b/src/main/java/seedu/heymatez/logic/commands/ViewTasksCommand.java
@@ -0,0 +1,29 @@
+package seedu.heymatez.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_EMPTY_TASK_LIST;
+import static seedu.heymatez.model.Model.PREDICATE_SHOW_ALL_TASKS;
+
+import seedu.heymatez.logic.commands.exceptions.CommandException;
+import seedu.heymatez.model.Model;
+
+/**
+ * Lists all tasks in HeyMatez to the user.
+ */
+public class ViewTasksCommand extends Command {
+
+ public static final String COMMAND_WORD = "viewTasks";
+
+ public static final String MESSAGE_SUCCESS = "Listed all Tasks.";
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ model.updateFilteredTaskList(PREDICATE_SHOW_ALL_TASKS);
+
+ if (model.isTaskListEmpty()) {
+ return new CommandResult(MESSAGE_EMPTY_TASK_LIST);
+ }
+ return new CommandResult(MESSAGE_SUCCESS);
+ }
+}
diff --git a/src/main/java/seedu/heymatez/logic/commands/ViewUnassignedTasksCommand.java b/src/main/java/seedu/heymatez/logic/commands/ViewUnassignedTasksCommand.java
new file mode 100644
index 00000000000..ad2532a363c
--- /dev/null
+++ b/src/main/java/seedu/heymatez/logic/commands/ViewUnassignedTasksCommand.java
@@ -0,0 +1,32 @@
+package seedu.heymatez.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.heymatez.model.Model.PREDICATE_SHOW_ALL_UNASSIGNED_TASKS;
+
+import seedu.heymatez.logic.commands.exceptions.CommandException;
+import seedu.heymatez.model.Model;
+
+/**
+ * Lists all unassigned tasks in HeyMatez to the user.
+ */
+public class ViewUnassignedTasksCommand extends Command {
+
+ public static final String COMMAND_WORD = "viewUnassignedTasks";
+
+ public static final String MESSAGE_SUCCESS = "Listed all Unassigned Tasks.";
+
+ public static final String MESSAGE_NO_UNASSIGNED_TASKS = "There are no unassigned tasks found!";
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+
+ model.updateFilteredTaskList(PREDICATE_SHOW_ALL_UNASSIGNED_TASKS);
+
+ if (model.isTaskListEmpty()) {
+ return new CommandResult(MESSAGE_NO_UNASSIGNED_TASKS);
+ }
+
+ return new CommandResult(MESSAGE_SUCCESS);
+ }
+}
diff --git a/src/main/java/seedu/heymatez/logic/commands/ViewUncompletedTasksCommand.java b/src/main/java/seedu/heymatez/logic/commands/ViewUncompletedTasksCommand.java
new file mode 100644
index 00000000000..d2b014ef4c8
--- /dev/null
+++ b/src/main/java/seedu/heymatez/logic/commands/ViewUncompletedTasksCommand.java
@@ -0,0 +1,32 @@
+package seedu.heymatez.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.heymatez.model.Model.PREDICATE_SHOW_ALL_UNCOMPLETED_TASKS;
+
+import seedu.heymatez.logic.commands.exceptions.CommandException;
+import seedu.heymatez.model.Model;
+
+/**
+ * Lists all uncompleted tasks in HeyMatez to the user.
+ */
+public class ViewUncompletedTasksCommand extends Command {
+
+ public static final String COMMAND_WORD = "viewUncompletedTasks";
+
+ public static final String MESSAGE_SUCCESS = "Listed all Uncompleted Tasks.";
+
+ public static final String MESSAGE_NO_UNCOMPLETED_TASKS = "There are no uncompleted tasks found!";
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+
+ model.updateFilteredTaskList(PREDICATE_SHOW_ALL_UNCOMPLETED_TASKS);
+
+ if (model.isTaskListEmpty()) {
+ return new CommandResult(MESSAGE_NO_UNCOMPLETED_TASKS);
+ }
+
+ return new CommandResult(MESSAGE_SUCCESS);
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/exceptions/CommandException.java b/src/main/java/seedu/heymatez/logic/commands/exceptions/CommandException.java
similarity index 89%
rename from src/main/java/seedu/address/logic/commands/exceptions/CommandException.java
rename to src/main/java/seedu/heymatez/logic/commands/exceptions/CommandException.java
index a16bd14f2cd..e2485e6ff64 100644
--- a/src/main/java/seedu/address/logic/commands/exceptions/CommandException.java
+++ b/src/main/java/seedu/heymatez/logic/commands/exceptions/CommandException.java
@@ -1,4 +1,4 @@
-package seedu.address.logic.commands.exceptions;
+package seedu.heymatez.logic.commands.exceptions;
/**
* Represents an error which occurs during execution of a {@link Command}.
diff --git a/src/main/java/seedu/heymatez/logic/parser/AddMemberCommandParser.java b/src/main/java/seedu/heymatez/logic/parser/AddMemberCommandParser.java
new file mode 100644
index 00000000000..0d41bd8eb0b
--- /dev/null
+++ b/src/main/java/seedu/heymatez/logic/parser/AddMemberCommandParser.java
@@ -0,0 +1,57 @@
+package seedu.heymatez.logic.parser;
+
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.heymatez.logic.parser.CliSyntax.PREFIX_EMAIL;
+import static seedu.heymatez.logic.parser.CliSyntax.PREFIX_PHONE;
+import static seedu.heymatez.logic.parser.CliSyntax.PREFIX_ROLE;
+
+import java.util.stream.Stream;
+
+import seedu.heymatez.logic.commands.AddMemberCommand;
+import seedu.heymatez.logic.parser.exceptions.ParseException;
+import seedu.heymatez.model.person.Email;
+import seedu.heymatez.model.person.Name;
+import seedu.heymatez.model.person.Person;
+import seedu.heymatez.model.person.Phone;
+import seedu.heymatez.model.person.Role;
+
+/**
+ * Parses input arguments and creates a new AddMemberCommand object
+ */
+public class AddMemberCommandParser implements Parser {
+
+ /**
+ * Parses the given {@code String} of arguments in the context of the AddMemberCommand
+ * and returns an AddMemberCommand object for execution.
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public AddMemberCommand parse(String args) throws ParseException {
+ ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ROLE);
+
+ if (!arePrefixesPresent(argMultimap, PREFIX_PHONE, PREFIX_EMAIL)) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddMemberCommand.MESSAGE_USAGE));
+ }
+
+ Name name = ParserUtil.parseName(argMultimap.getPreamble());
+ Phone phone = ParserUtil.parsePhone(argMultimap.getValue(PREFIX_PHONE).get());
+ Email email = ParserUtil.parseEmail(argMultimap.getValue(PREFIX_EMAIL).get());
+
+ Person person = new Person(name, phone, email);
+
+ Role role;
+ if (arePrefixesPresent(argMultimap, PREFIX_ROLE)) {
+ role = ParserUtil.parseRole(argMultimap.getValue(PREFIX_ROLE).get());
+ person = new Person(name, phone, email, role);
+ }
+ return new AddMemberCommand(person);
+ }
+
+ /**
+ * Returns true if none of the prefixes contains empty {@code Optional} values in the given
+ * {@code ArgumentMultimap}.
+ */
+ private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) {
+ return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent());
+ }
+
+}
diff --git a/src/main/java/seedu/heymatez/logic/parser/AddTaskCommandParser.java b/src/main/java/seedu/heymatez/logic/parser/AddTaskCommandParser.java
new file mode 100644
index 00000000000..b9b5d673c7e
--- /dev/null
+++ b/src/main/java/seedu/heymatez/logic/parser/AddTaskCommandParser.java
@@ -0,0 +1,83 @@
+package seedu.heymatez.logic.parser;
+
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_TASK_PRIORITY;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_TASK_STATUS;
+import static seedu.heymatez.logic.parser.CliSyntax.PREFIX_ASSIGNEE;
+import static seedu.heymatez.logic.parser.CliSyntax.PREFIX_DEADLINE;
+import static seedu.heymatez.logic.parser.CliSyntax.PREFIX_DESCRIPTION;
+import static seedu.heymatez.logic.parser.CliSyntax.PREFIX_PRIORITY;
+import static seedu.heymatez.logic.parser.CliSyntax.PREFIX_STATUS;
+
+import java.util.Set;
+import java.util.stream.Stream;
+
+import seedu.heymatez.logic.commands.AddTaskCommand;
+import seedu.heymatez.logic.parser.exceptions.ParseException;
+import seedu.heymatez.model.assignee.Assignee;
+import seedu.heymatez.model.task.Deadline;
+import seedu.heymatez.model.task.Description;
+import seedu.heymatez.model.task.Priority;
+import seedu.heymatez.model.task.Task;
+import seedu.heymatez.model.task.TaskStatus;
+import seedu.heymatez.model.task.Title;
+
+/**
+ * Parses input arguments and creates a new AddTaskCommand object
+ */
+public class AddTaskCommandParser implements Parser {
+ /**
+ * Parses the given {@code String} of arguments in the context of the AddTaskCommand
+ * and returns an AddTaskCommand object for execution.
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public AddTaskCommand parse(String args) throws ParseException {
+ ArgumentMultimap argMultimap =
+ ArgumentTokenizer.tokenize(args, PREFIX_DESCRIPTION, PREFIX_DEADLINE, PREFIX_STATUS,
+ PREFIX_PRIORITY, PREFIX_ASSIGNEE);
+
+ if (!arePrefixesPresent(argMultimap, PREFIX_DESCRIPTION, PREFIX_DEADLINE)) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddTaskCommand.MESSAGE_USAGE));
+ }
+
+ Title title = ParserUtil.parseTitle(argMultimap.getPreamble());
+ Description description = ParserUtil.parseDescription(argMultimap.getValue(PREFIX_DESCRIPTION).get());
+ Deadline deadline = ParserUtil.parseDeadline(argMultimap.getValue(PREFIX_DEADLINE).get());
+
+ TaskStatus status = TaskStatus.UNCOMPLETED;
+
+ if (arePrefixesPresent(argMultimap, PREFIX_STATUS)) {
+ try {
+ status = ParserUtil.parseStatus(argMultimap.getValue(PREFIX_STATUS).get());
+ } catch (ParseException pe) {
+ throw new ParseException(MESSAGE_INVALID_TASK_STATUS + TaskStatus.MESSAGE_CONSTRAINTS,
+ pe);
+ }
+ }
+
+ Priority priority = Priority.UNASSIGNED;
+
+ if (arePrefixesPresent(argMultimap, PREFIX_PRIORITY)) {
+ try {
+ priority = ParserUtil.parsePriority(argMultimap.getValue(PREFIX_PRIORITY).get());
+ } catch (ParseException pe) {
+ throw new ParseException(MESSAGE_INVALID_TASK_PRIORITY + Priority.MESSAGE_CONSTRAINTS,
+ pe);
+ }
+ }
+
+ Set assigneeList = ParserUtil.parseAssignees(argMultimap.getAllValues(PREFIX_ASSIGNEE));
+
+ Task task = new Task(title, description, deadline, status, priority, assigneeList);
+
+ return new AddTaskCommand(task);
+ }
+
+ /**
+ * Returns true if none of the prefixes contains empty {@code Optional} values in the given
+ * {@code ArgumentMultimap}.
+ */
+ private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) {
+ return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent());
+ }
+}
diff --git a/src/main/java/seedu/address/logic/parser/ArgumentMultimap.java b/src/main/java/seedu/heymatez/logic/parser/ArgumentMultimap.java
similarity index 98%
rename from src/main/java/seedu/address/logic/parser/ArgumentMultimap.java
rename to src/main/java/seedu/heymatez/logic/parser/ArgumentMultimap.java
index 954c8e18f8e..3751490a313 100644
--- a/src/main/java/seedu/address/logic/parser/ArgumentMultimap.java
+++ b/src/main/java/seedu/heymatez/logic/parser/ArgumentMultimap.java
@@ -1,4 +1,4 @@
-package seedu.address.logic.parser;
+package seedu.heymatez.logic.parser;
import java.util.ArrayList;
import java.util.HashMap;
@@ -57,4 +57,5 @@ public List getAllValues(Prefix prefix) {
public String getPreamble() {
return getValue(new Prefix("")).orElse("");
}
+
}
diff --git a/src/main/java/seedu/address/logic/parser/ArgumentTokenizer.java b/src/main/java/seedu/heymatez/logic/parser/ArgumentTokenizer.java
similarity index 99%
rename from src/main/java/seedu/address/logic/parser/ArgumentTokenizer.java
rename to src/main/java/seedu/heymatez/logic/parser/ArgumentTokenizer.java
index 5c9aebfa488..7557d2d67c9 100644
--- a/src/main/java/seedu/address/logic/parser/ArgumentTokenizer.java
+++ b/src/main/java/seedu/heymatez/logic/parser/ArgumentTokenizer.java
@@ -1,4 +1,4 @@
-package seedu.address.logic.parser;
+package seedu.heymatez.logic.parser;
import java.util.ArrayList;
import java.util.Arrays;
@@ -99,6 +99,7 @@ private static ArgumentMultimap extractArguments(String argsString, List {
+
+ /**
+ * Parses the given {@code String} of arguments in the context of the ClearAssigneesCommand
+ * and returns a ClearAssigneesCommand object for execution.
+ *
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public ClearAssigneesCommand parse(String args) throws ParseException {
+ try {
+ Index index = ParserUtil.parseIndex(args);
+ return new ClearAssigneesCommand(index);
+ } catch (ParseException pe) {
+ if (pe.getMessage().equals(MESSAGE_NON_POSITIVE_INDEX)) {
+ throw new ParseException(MESSAGE_INVALID_TASK_DISPLAYED_INDEX, pe);
+ }
+ throw new ParseException(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, ClearAssigneesCommand.MESSAGE_USAGE), pe);
+ }
+ }
+}
diff --git a/src/main/java/seedu/heymatez/logic/parser/CliSyntax.java b/src/main/java/seedu/heymatez/logic/parser/CliSyntax.java
new file mode 100644
index 00000000000..24a884a4423
--- /dev/null
+++ b/src/main/java/seedu/heymatez/logic/parser/CliSyntax.java
@@ -0,0 +1,20 @@
+package seedu.heymatez.logic.parser;
+
+/**
+ * Contains Command Line Interface (CLI) syntax definitions common to multiple commands
+ */
+public class CliSyntax {
+
+ /* Prefix definitions for member*/
+ public static final Prefix PREFIX_NEW_NAME = new Prefix("n/");
+ public static final Prefix PREFIX_PHONE = new Prefix("p/");
+ public static final Prefix PREFIX_EMAIL = new Prefix("e/");
+ public static final Prefix PREFIX_ROLE = new Prefix("r/");
+ /* Prefix definitions for task */
+ public static final Prefix PREFIX_TITLE = new Prefix("n/");
+ public static final Prefix PREFIX_DESCRIPTION = new Prefix("d/");
+ public static final Prefix PREFIX_STATUS = new Prefix("s/");
+ public static final Prefix PREFIX_DEADLINE = new Prefix("b/");
+ public static final Prefix PREFIX_PRIORITY = new Prefix("p/");
+ public static final Prefix PREFIX_ASSIGNEE = new Prefix("a/");
+}
diff --git a/src/main/java/seedu/heymatez/logic/parser/DeleteMemberCommandParser.java b/src/main/java/seedu/heymatez/logic/parser/DeleteMemberCommandParser.java
new file mode 100644
index 00000000000..9981ed3b065
--- /dev/null
+++ b/src/main/java/seedu/heymatez/logic/parser/DeleteMemberCommandParser.java
@@ -0,0 +1,29 @@
+package seedu.heymatez.logic.parser;
+
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+
+import seedu.heymatez.logic.commands.DeleteMemberCommand;
+import seedu.heymatez.logic.parser.exceptions.ParseException;
+import seedu.heymatez.model.person.Name;
+
+/**
+ * Parses input arguments and creates a new DeleteMemberCommand object
+ */
+public class DeleteMemberCommandParser implements Parser {
+
+ /**
+ * Parses the given {@code String} of arguments in the context of the DeleteMemberCommand
+ * and returns a DeleteMemberCommand object for execution.
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public DeleteMemberCommand parse(String args) throws ParseException {
+ try {
+ Name name = ParserUtil.parseName(args);
+ return new DeleteMemberCommand(name);
+ } catch (ParseException pe) {
+ throw new ParseException(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteMemberCommand.MESSAGE_USAGE), pe);
+ }
+ }
+
+}
diff --git a/src/main/java/seedu/heymatez/logic/parser/DeleteTaskCommandParser.java b/src/main/java/seedu/heymatez/logic/parser/DeleteTaskCommandParser.java
new file mode 100644
index 00000000000..35ed8b4b196
--- /dev/null
+++ b/src/main/java/seedu/heymatez/logic/parser/DeleteTaskCommandParser.java
@@ -0,0 +1,33 @@
+package seedu.heymatez.logic.parser;
+
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX;
+import static seedu.heymatez.logic.parser.ParserUtil.MESSAGE_NON_POSITIVE_INDEX;
+
+import seedu.heymatez.commons.core.index.Index;
+import seedu.heymatez.logic.commands.DeleteTaskCommand;
+import seedu.heymatez.logic.parser.exceptions.ParseException;
+
+/**
+ * Parses input arguments and creates a new DeleteTaskCommand object
+ */
+public class DeleteTaskCommandParser implements Parser {
+ /**
+ * Parses the given {@code String} of arguments in the context of the DeleteTaskCommand
+ * and returns a DeleteTaskCommand object for execution.
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public DeleteTaskCommand parse(String args) throws ParseException {
+ try {
+ Index index = ParserUtil.parseIndex(args);
+ return new DeleteTaskCommand(index);
+ } catch (ParseException pe) {
+ if (pe.getMessage().equals(MESSAGE_NON_POSITIVE_INDEX)) {
+ throw new ParseException(MESSAGE_INVALID_TASK_DISPLAYED_INDEX, pe);
+ } else {
+ throw new ParseException(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteTaskCommand.MESSAGE_USAGE), pe);
+ }
+ }
+ }
+}
diff --git a/src/main/java/seedu/heymatez/logic/parser/DoneTaskCommandParser.java b/src/main/java/seedu/heymatez/logic/parser/DoneTaskCommandParser.java
new file mode 100644
index 00000000000..717525e9ced
--- /dev/null
+++ b/src/main/java/seedu/heymatez/logic/parser/DoneTaskCommandParser.java
@@ -0,0 +1,41 @@
+package seedu.heymatez.logic.parser;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX;
+import static seedu.heymatez.logic.parser.ParserUtil.MESSAGE_NON_POSITIVE_INDEX;
+
+import seedu.heymatez.commons.core.index.Index;
+import seedu.heymatez.logic.commands.DoneTaskCommand;
+import seedu.heymatez.logic.parser.exceptions.ParseException;
+
+/**
+ * Parses input arguments and creates a new DoneTaskCommand object
+ */
+public class DoneTaskCommandParser implements Parser {
+ /**
+ * Parses the given {@code String} of arguments in the context of the DoneTaskCommand
+ * and returns an DoneTaskCommand object for execution.
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public DoneTaskCommand parse(String args) throws ParseException {
+ requireNonNull(args);
+ ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args);
+
+ Index index;
+
+ try {
+ index = ParserUtil.parseIndex(argMultimap.getPreamble());
+ } catch (ParseException pe) {
+ if (pe.getMessage().equals(MESSAGE_NON_POSITIVE_INDEX)) {
+ throw new ParseException(MESSAGE_INVALID_TASK_DISPLAYED_INDEX, pe);
+ }
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT,
+ DoneTaskCommand.MESSAGE_USAGE), pe);
+ }
+
+ return new DoneTaskCommand(index);
+ }
+
+
+}
diff --git a/src/main/java/seedu/heymatez/logic/parser/EditMemberCommandParser.java b/src/main/java/seedu/heymatez/logic/parser/EditMemberCommandParser.java
new file mode 100644
index 00000000000..979b6954e28
--- /dev/null
+++ b/src/main/java/seedu/heymatez/logic/parser/EditMemberCommandParser.java
@@ -0,0 +1,58 @@
+package seedu.heymatez.logic.parser;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.heymatez.logic.parser.CliSyntax.PREFIX_EMAIL;
+import static seedu.heymatez.logic.parser.CliSyntax.PREFIX_NEW_NAME;
+import static seedu.heymatez.logic.parser.CliSyntax.PREFIX_PHONE;
+import static seedu.heymatez.logic.parser.CliSyntax.PREFIX_ROLE;
+
+import seedu.heymatez.logic.commands.EditMemberCommand;
+import seedu.heymatez.logic.commands.EditMemberCommand.EditMemberDescriptor;
+import seedu.heymatez.logic.parser.exceptions.ParseException;
+import seedu.heymatez.model.person.Name;
+
+/**
+ * Parses input arguments and creates a new EditMemberCommand object
+ */
+public class EditMemberCommandParser implements Parser {
+
+ /**
+ * Parses the given {@code String} of arguments in the context of the EditMemberCommand
+ * and returns an EditMemberCommand object for execution.
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public EditMemberCommand parse(String args) throws ParseException {
+ requireNonNull(args);
+ ArgumentMultimap argMultimap =
+ ArgumentTokenizer.tokenize(args, PREFIX_NEW_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ROLE);
+
+ Name name;
+
+ try {
+ name = ParserUtil.parseName(argMultimap.getPreamble());
+ } catch (ParseException pe) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT,
+ EditMemberCommand.MESSAGE_USAGE), pe);
+ }
+
+ EditMemberCommand.EditMemberDescriptor editMemberDescriptor = new EditMemberDescriptor();
+ if (argMultimap.getValue(PREFIX_NEW_NAME).isPresent()) {
+ editMemberDescriptor.setName(ParserUtil.parseName(argMultimap.getValue(PREFIX_NEW_NAME).get()));
+ }
+ if (argMultimap.getValue(PREFIX_PHONE).isPresent()) {
+ editMemberDescriptor.setPhone(ParserUtil.parsePhone(argMultimap.getValue(PREFIX_PHONE).get()));
+ }
+ if (argMultimap.getValue(PREFIX_EMAIL).isPresent()) {
+ editMemberDescriptor.setEmail(ParserUtil.parseEmail(argMultimap.getValue(PREFIX_EMAIL).get()));
+ }
+ if (argMultimap.getValue(PREFIX_ROLE).isPresent()) {
+ editMemberDescriptor.setRole(ParserUtil.parseRole(argMultimap.getValue(PREFIX_ROLE).get()));
+ }
+ if (!editMemberDescriptor.isAnyFieldEdited()) {
+ throw new ParseException(EditMemberCommand.MESSAGE_NOT_EDITED);
+ }
+
+ return new EditMemberCommand(name, editMemberDescriptor);
+ }
+}
diff --git a/src/main/java/seedu/heymatez/logic/parser/EditTaskCommandParser.java b/src/main/java/seedu/heymatez/logic/parser/EditTaskCommandParser.java
new file mode 100644
index 00000000000..33a8cb5fb0e
--- /dev/null
+++ b/src/main/java/seedu/heymatez/logic/parser/EditTaskCommandParser.java
@@ -0,0 +1,97 @@
+package seedu.heymatez.logic.parser;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX;
+import static seedu.heymatez.logic.parser.CliSyntax.PREFIX_ASSIGNEE;
+import static seedu.heymatez.logic.parser.CliSyntax.PREFIX_DEADLINE;
+import static seedu.heymatez.logic.parser.CliSyntax.PREFIX_DESCRIPTION;
+import static seedu.heymatez.logic.parser.CliSyntax.PREFIX_PRIORITY;
+import static seedu.heymatez.logic.parser.CliSyntax.PREFIX_STATUS;
+import static seedu.heymatez.logic.parser.CliSyntax.PREFIX_TITLE;
+import static seedu.heymatez.logic.parser.ParserUtil.MESSAGE_NON_POSITIVE_INDEX;
+
+import java.util.Collection;
+import java.util.Optional;
+import java.util.Set;
+
+import seedu.heymatez.commons.core.index.Index;
+import seedu.heymatez.logic.commands.EditTaskCommand;
+import seedu.heymatez.logic.parser.exceptions.ParseException;
+import seedu.heymatez.model.assignee.Assignee;
+
+/**
+ * Parses input arguments and creates a new EditTaskCommand object
+ */
+public class EditTaskCommandParser implements Parser {
+ /**
+ * Parses the given {@code String} of arguments in the context of the EditTaskCommand
+ * and returns an EditTaskCommand object for execution.
+ * @throws ParseException if the user input does not conform to the expected format
+ */
+ public EditTaskCommand parse(String args) throws ParseException {
+ requireNonNull(args);
+ ArgumentMultimap argMultimap =
+ ArgumentTokenizer.tokenize(args, PREFIX_TITLE, PREFIX_DESCRIPTION, PREFIX_STATUS, PREFIX_DEADLINE,
+ PREFIX_PRIORITY, PREFIX_ASSIGNEE);
+
+ Index index;
+
+ try {
+ index = ParserUtil.parseIndex(argMultimap.getPreamble());
+ } catch (ParseException pe) {
+ if (pe.getMessage().equals(MESSAGE_NON_POSITIVE_INDEX)) {
+ throw new ParseException(MESSAGE_INVALID_TASK_DISPLAYED_INDEX, pe);
+ }
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT,
+ EditTaskCommand.MESSAGE_USAGE), pe);
+ }
+
+ EditTaskCommand.EditTaskDescriptor editTaskDescriptor = new EditTaskCommand.EditTaskDescriptor();
+ if (argMultimap.getValue(PREFIX_TITLE).isPresent()) {
+ editTaskDescriptor.setTitle(ParserUtil.parseTitle(argMultimap.getValue(PREFIX_TITLE).get()));
+ }
+ if (argMultimap.getValue(PREFIX_DESCRIPTION).isPresent()) {
+ editTaskDescriptor.setDescription(ParserUtil.parseDescription(argMultimap
+ .getValue(PREFIX_DESCRIPTION).get()));
+ }
+
+ if (argMultimap.getValue(PREFIX_STATUS).isPresent()) {
+ editTaskDescriptor.setStatus(ParserUtil.parseStatus(argMultimap
+ .getValue(PREFIX_STATUS).get()));
+ }
+
+ if (argMultimap.getValue(PREFIX_DEADLINE).isPresent()) {
+ editTaskDescriptor.setDeadline(ParserUtil.parseDeadline(argMultimap
+ .getValue(PREFIX_DEADLINE).get()));
+ }
+
+ if (argMultimap.getValue(PREFIX_PRIORITY).isPresent()) {
+ editTaskDescriptor.setPriority(ParserUtil.parsePriority(argMultimap
+ .getValue(PREFIX_PRIORITY).get()));
+ }
+
+ parseAssigneesForEdit(argMultimap.getAllValues(PREFIX_ASSIGNEE)).ifPresent(editTaskDescriptor::setAssignees);
+
+ if (!editTaskDescriptor.isAnyFieldEdited()) {
+ throw new ParseException(EditTaskCommand.MESSAGE_NOT_EDITED);
+ }
+
+ return new EditTaskCommand(index, editTaskDescriptor);
+ }
+
+ /**
+ * Parses {@code Collection assignees} into a {@code Set} if {@code assignees} is non-empty.
+ * If {@code assignees} contain only one element which is an empty string, it will be parsed into a
+ * {@code Set} containing zero assignees.
+ */
+ private Optional> parseAssigneesForEdit(Collection assignees) throws ParseException {
+ assert assignees != null;
+
+ if (assignees.isEmpty()) {
+ return Optional.empty();
+ }
+
+ return Optional.of(ParserUtil.parseAssignees(assignees));
+ }
+}
diff --git a/src/main/java/seedu/heymatez/logic/parser/FindByPriorityCommandParser.java b/src/main/java/seedu/heymatez/logic/parser/FindByPriorityCommandParser.java
new file mode 100644
index 00000000000..0e24a64d829
--- /dev/null
+++ b/src/main/java/seedu/heymatez/logic/parser/FindByPriorityCommandParser.java
@@ -0,0 +1,40 @@
+package seedu.heymatez.logic.parser;
+
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+
+import java.util.Arrays;
+
+import seedu.heymatez.logic.commands.FindByPriorityCommand;
+import seedu.heymatez.logic.parser.exceptions.ParseException;
+import seedu.heymatez.model.task.PriorityContainsKeywordPredicate;
+
+/**
+ * Parses input arguments and creates a new FindByPriorityCommand object
+ */
+public class FindByPriorityCommandParser implements Parser {
+
+ /**
+ * Parses the given {@code String} of arguments in the context of the FindByPriorityCommand
+ * and returns a FindByPriorityCommand object for execution.
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public FindByPriorityCommand parse(String args) throws ParseException {
+ String trimmedArgs = args.trim();
+ String[] parsedArgs = trimmedArgs.split(" ");
+
+ if (parsedArgs.length != 1 || parsedArgs[0].equals("")) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT,
+ FindByPriorityCommand.MESSAGE_USAGE));
+ }
+
+ String keyword = parsedArgs[0];
+
+ // Used to check if priority is valid
+ ParserUtil.parsePriority(keyword);
+
+ String[] nameKeywords = {keyword};
+
+ return new FindByPriorityCommand(new PriorityContainsKeywordPredicate(Arrays.asList(nameKeywords)));
+ }
+
+}
diff --git a/src/main/java/seedu/heymatez/logic/parser/FindMemberCommandParser.java b/src/main/java/seedu/heymatez/logic/parser/FindMemberCommandParser.java
new file mode 100644
index 00000000000..4a4d09e8224
--- /dev/null
+++ b/src/main/java/seedu/heymatez/logic/parser/FindMemberCommandParser.java
@@ -0,0 +1,32 @@
+package seedu.heymatez.logic.parser;
+
+import java.util.Arrays;
+
+import seedu.heymatez.commons.core.Messages;
+import seedu.heymatez.logic.commands.FindMembersCommand;
+import seedu.heymatez.logic.parser.exceptions.ParseException;
+import seedu.heymatez.model.person.DetailsContainsKeywordsPredicate;
+
+/**
+ * Parses input arguments and creates a new FindMemberCommand object
+ */
+public class FindMemberCommandParser implements Parser {
+
+ /**
+ * Parses the given {@code String} of arguments in the context of the FindMemberCommand
+ * and returns a FindMemberCommand object for execution.
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public FindMembersCommand parse(String args) throws ParseException {
+ String trimmedArgs = args.trim();
+ if (trimmedArgs.isEmpty()) {
+ throw new ParseException(
+ String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, FindMembersCommand.MESSAGE_USAGE));
+ }
+
+ String[] nameKeywords = trimmedArgs.split("\\s+");
+
+ return new FindMembersCommand(new DetailsContainsKeywordsPredicate(Arrays.asList(nameKeywords)));
+ }
+
+}
diff --git a/src/main/java/seedu/heymatez/logic/parser/FindMemberTasksCommandParser.java b/src/main/java/seedu/heymatez/logic/parser/FindMemberTasksCommandParser.java
new file mode 100644
index 00000000000..5acc1bb0786
--- /dev/null
+++ b/src/main/java/seedu/heymatez/logic/parser/FindMemberTasksCommandParser.java
@@ -0,0 +1,38 @@
+package seedu.heymatez.logic.parser;
+
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+
+import seedu.heymatez.logic.commands.FindMemberTasksCommand;
+import seedu.heymatez.logic.parser.exceptions.ParseException;
+import seedu.heymatez.model.assignee.Assignee;
+import seedu.heymatez.model.task.TaskContainsAssigneePredicate;
+
+/**
+ * Parses input arguments and creates a new FindMemberTasksCommand object
+ */
+public class FindMemberTasksCommandParser implements Parser {
+
+ /**
+ * Parses the given {@code String} of arguments in the context of the FindMemberTasksCommand
+ * and returns a FindMemberTasksCommand object for execution.
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public FindMemberTasksCommand parse(String args) throws ParseException {
+ String trimmedArgs = args.trim();
+
+ if (trimmedArgs.equals("")) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT,
+ FindMemberTasksCommand.MESSAGE_USAGE));
+ }
+
+ // Check if name is valid
+ try {
+ ParserUtil.parseAssignee(trimmedArgs);
+ } catch (ParseException e) {
+ throw new ParseException(Assignee.MESSAGE_SEARCH_TASKS_CONSTRAINTS);
+ }
+
+ return new FindMemberTasksCommand(new TaskContainsAssigneePredicate(trimmedArgs));
+ }
+
+}
diff --git a/src/main/java/seedu/heymatez/logic/parser/FindTasksBeforeCommandParser.java b/src/main/java/seedu/heymatez/logic/parser/FindTasksBeforeCommandParser.java
new file mode 100644
index 00000000000..b6b789c9dee
--- /dev/null
+++ b/src/main/java/seedu/heymatez/logic/parser/FindTasksBeforeCommandParser.java
@@ -0,0 +1,36 @@
+package seedu.heymatez.logic.parser;
+
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_TASK_DEADLINE;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_TASK_DEADLINE_FORMAT;
+
+import seedu.heymatez.logic.commands.FindTasksBeforeCommand;
+import seedu.heymatez.logic.parser.exceptions.ParseException;
+import seedu.heymatez.model.task.Deadline;
+import seedu.heymatez.model.task.DeadlineBeforeDatePredicate;
+
+/**
+ * Parses input arguments and creates a new FindTasksBeforeCommand object
+ */
+public class FindTasksBeforeCommandParser implements Parser {
+ /**
+ * Parses the given {@code String} deadline in the context of the FindTasksBeforeCommand
+ * and returns a FindTasksBefore Command object for execution.
+ *
+ * @throws ParseException if the user input does not conform to the expected format
+ */
+ public FindTasksBeforeCommand parse(String args) throws ParseException {
+ String trimmedArgs = args.trim();
+ if (trimmedArgs.isEmpty()) {
+ throw new ParseException(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindTasksBeforeCommand.MESSAGE_USAGE));
+ }
+ if (!Deadline.isValidFormat(trimmedArgs)) {
+ throw new ParseException(MESSAGE_INVALID_TASK_DEADLINE_FORMAT + Deadline.MESSAGE_CONSTRAINTS);
+ }
+ if (!Deadline.isValidDeadline(trimmedArgs)) {
+ throw new ParseException(MESSAGE_INVALID_TASK_DEADLINE + Deadline.MESSAGE_CONSTRAINTS);
+ }
+ return new FindTasksBeforeCommand(new DeadlineBeforeDatePredicate(trimmedArgs));
+ }
+}
diff --git a/src/main/java/seedu/heymatez/logic/parser/FindTasksCommandParser.java b/src/main/java/seedu/heymatez/logic/parser/FindTasksCommandParser.java
new file mode 100644
index 00000000000..1307476a812
--- /dev/null
+++ b/src/main/java/seedu/heymatez/logic/parser/FindTasksCommandParser.java
@@ -0,0 +1,31 @@
+package seedu.heymatez.logic.parser;
+
+import java.util.Arrays;
+
+import seedu.heymatez.commons.core.Messages;
+import seedu.heymatez.logic.commands.FindTasksCommand;
+import seedu.heymatez.logic.parser.exceptions.ParseException;
+import seedu.heymatez.model.task.TaskContainsKeywordPredicate;
+
+/**
+ * Parses input arguments and creates a new FindTasksCommand object
+ */
+public class FindTasksCommandParser implements Parser {
+ /**
+ * Parses the given {@code String} of arguments in the context of the FindTasksCommand
+ * and returns a FindTasksCommand object for execution.
+ *
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public FindTasksCommand parse(String args) throws ParseException {
+ String trimmedArgs = args.trim();
+ if (trimmedArgs.isEmpty()) {
+ throw new ParseException(
+ String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, FindTasksCommand.MESSAGE_USAGE));
+ }
+
+ String[] keywords = trimmedArgs.split("\\s+");
+
+ return new FindTasksCommand(new TaskContainsKeywordPredicate(Arrays.asList(keywords)));
+ }
+}
diff --git a/src/main/java/seedu/heymatez/logic/parser/HeyMatezParser.java b/src/main/java/seedu/heymatez/logic/parser/HeyMatezParser.java
new file mode 100644
index 00000000000..70794d166bf
--- /dev/null
+++ b/src/main/java/seedu/heymatez/logic/parser/HeyMatezParser.java
@@ -0,0 +1,126 @@
+package seedu.heymatez.logic.parser;
+
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_UNKNOWN_COMMAND;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import seedu.heymatez.logic.commands.AddMemberCommand;
+import seedu.heymatez.logic.commands.AddTaskCommand;
+import seedu.heymatez.logic.commands.ClearAssigneesCommand;
+import seedu.heymatez.logic.commands.ClearCommand;
+import seedu.heymatez.logic.commands.Command;
+import seedu.heymatez.logic.commands.DeleteMemberCommand;
+import seedu.heymatez.logic.commands.DeleteTaskCommand;
+import seedu.heymatez.logic.commands.DoneTaskCommand;
+import seedu.heymatez.logic.commands.EditMemberCommand;
+import seedu.heymatez.logic.commands.EditTaskCommand;
+import seedu.heymatez.logic.commands.ExitCommand;
+import seedu.heymatez.logic.commands.FindByPriorityCommand;
+import seedu.heymatez.logic.commands.FindMemberTasksCommand;
+import seedu.heymatez.logic.commands.FindMembersCommand;
+import seedu.heymatez.logic.commands.FindTasksBeforeCommand;
+import seedu.heymatez.logic.commands.FindTasksCommand;
+import seedu.heymatez.logic.commands.HelpCommand;
+import seedu.heymatez.logic.commands.UndoTaskCommand;
+import seedu.heymatez.logic.commands.ViewMembersCommand;
+import seedu.heymatez.logic.commands.ViewTasksCommand;
+import seedu.heymatez.logic.commands.ViewUnassignedTasksCommand;
+import seedu.heymatez.logic.commands.ViewUncompletedTasksCommand;
+import seedu.heymatez.logic.parser.exceptions.ParseException;
+
+/**
+ * Parses user input.
+ */
+public class HeyMatezParser {
+
+ /**
+ * Used for initial separation of command word and args.
+ */
+ private static final Pattern BASIC_COMMAND_FORMAT = Pattern.compile("(?\\S+)(?.*)");
+
+ /**
+ * Parses user input into command for execution.
+ *
+ * @param userInput full user input string
+ * @return the command based on the user input
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public Command parseCommand(String userInput) throws ParseException {
+ final Matcher matcher = BASIC_COMMAND_FORMAT.matcher(userInput.trim());
+ if (!matcher.matches()) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, HelpCommand.MESSAGE_USAGE));
+ }
+ final String commandWord = matcher.group("commandWord");
+ final String arguments = matcher.group("arguments");
+ switch (commandWord) {
+
+ case AddMemberCommand.COMMAND_WORD:
+ return new AddMemberCommandParser().parse(arguments);
+
+ case AddTaskCommand.COMMAND_WORD:
+ return new AddTaskCommandParser().parse(arguments);
+
+ case ClearAssigneesCommand.COMMAND_WORD:
+ return new ClearAssigneesCommandParser().parse(arguments);
+
+ case EditMemberCommand.COMMAND_WORD:
+ return new EditMemberCommandParser().parse(arguments);
+
+ case EditTaskCommand.COMMAND_WORD:
+ return new EditTaskCommandParser().parse(arguments);
+
+ case DeleteMemberCommand.COMMAND_WORD:
+ return new DeleteMemberCommandParser().parse(arguments);
+
+ case DeleteTaskCommand.COMMAND_WORD:
+ return new DeleteTaskCommandParser().parse(arguments);
+
+ case DoneTaskCommand.COMMAND_WORD:
+ return new DoneTaskCommandParser().parse(arguments);
+
+ case UndoTaskCommand.COMMAND_WORD:
+ return new UndoTaskCommandParser().parse(arguments);
+
+ case ClearCommand.COMMAND_WORD:
+ return new ClearCommand();
+
+ case FindMembersCommand.COMMAND_WORD:
+ return new FindMemberCommandParser().parse(arguments);
+
+ case FindMemberTasksCommand.COMMAND_WORD:
+ return new FindMemberTasksCommandParser().parse(arguments);
+
+ case FindByPriorityCommand.COMMAND_WORD:
+ return new FindByPriorityCommandParser().parse(arguments);
+
+ case FindTasksCommand.COMMAND_WORD:
+ return new FindTasksCommandParser().parse(arguments);
+
+ case FindTasksBeforeCommand.COMMAND_WORD:
+ return new FindTasksBeforeCommandParser().parse(arguments);
+
+ case ViewMembersCommand.COMMAND_WORD:
+ return new ViewMembersCommand();
+
+ case ViewTasksCommand.COMMAND_WORD:
+ return new ViewTasksCommand();
+
+ case ViewUnassignedTasksCommand.COMMAND_WORD:
+ return new ViewUnassignedTasksCommand();
+
+ case ViewUncompletedTasksCommand.COMMAND_WORD:
+ return new ViewUncompletedTasksCommand();
+
+ case ExitCommand.COMMAND_WORD:
+ return new ExitCommand();
+
+ case HelpCommand.COMMAND_WORD:
+ return new HelpCommand();
+
+ default:
+ throw new ParseException(MESSAGE_UNKNOWN_COMMAND);
+ }
+ }
+}
diff --git a/src/main/java/seedu/address/logic/parser/Parser.java b/src/main/java/seedu/heymatez/logic/parser/Parser.java
similarity index 72%
rename from src/main/java/seedu/address/logic/parser/Parser.java
rename to src/main/java/seedu/heymatez/logic/parser/Parser.java
index d6551ad8e3f..3144b6571ae 100644
--- a/src/main/java/seedu/address/logic/parser/Parser.java
+++ b/src/main/java/seedu/heymatez/logic/parser/Parser.java
@@ -1,7 +1,7 @@
-package seedu.address.logic.parser;
+package seedu.heymatez.logic.parser;
-import seedu.address.logic.commands.Command;
-import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.heymatez.logic.commands.Command;
+import seedu.heymatez.logic.parser.exceptions.ParseException;
/**
* Represents a Parser that is able to parse user input into a {@code Command} of type {@code T}.
diff --git a/src/main/java/seedu/heymatez/logic/parser/ParserUtil.java b/src/main/java/seedu/heymatez/logic/parser/ParserUtil.java
new file mode 100644
index 00000000000..edd0b581920
--- /dev/null
+++ b/src/main/java/seedu/heymatez/logic/parser/ParserUtil.java
@@ -0,0 +1,267 @@
+package seedu.heymatez.logic.parser;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_PERSON_DISPLAYED_NAME;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_PERSON_EMAIL;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_PERSON_PHONE;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_PERSON_ROLE;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_TASK_ASSIGNEE;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_TASK_DEADLINE;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_TASK_DEADLINE_FORMAT;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_TASK_DESCRIPTION;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_TASK_PRIORITY;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_TASK_STATUS;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_TASK_TITLE;
+import static seedu.heymatez.commons.util.StringUtil.INVALID_INPUT;
+import static seedu.heymatez.commons.util.StringUtil.INVALID_INTEGER;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+import seedu.heymatez.commons.core.index.Index;
+import seedu.heymatez.commons.util.StringUtil;
+import seedu.heymatez.logic.parser.exceptions.ParseException;
+import seedu.heymatez.model.assignee.Assignee;
+import seedu.heymatez.model.person.Email;
+import seedu.heymatez.model.person.Name;
+import seedu.heymatez.model.person.Phone;
+import seedu.heymatez.model.person.Role;
+import seedu.heymatez.model.task.Deadline;
+import seedu.heymatez.model.task.Description;
+import seedu.heymatez.model.task.Priority;
+import seedu.heymatez.model.task.TaskStatus;
+import seedu.heymatez.model.task.Title;
+
+/**
+ * Contains utility methods used for parsing strings in the various *Parser classes.
+ */
+public class ParserUtil {
+
+ public static final String MESSAGE_INVALID_INDEX = "Index is not a non-zero unsigned integer.";
+
+ public static final String MESSAGE_NON_POSITIVE_INDEX = "Index is a non positive integer.";
+
+ /**
+ * Parses {@code oneBasedIndex} into an {@code Index} and returns it. Leading and trailing whitespaces will be
+ * trimmed.
+ * @throws ParseException if the specified index is invalid (not non-zero unsigned integer).
+ */
+ public static Index parseIndex(String oneBasedIndex) throws ParseException {
+ String trimmedIndex = oneBasedIndex.trim();
+ System.out.println(trimmedIndex);
+ if (StringUtil.checkIndexValidity(trimmedIndex) == INVALID_INPUT) {
+ throw new ParseException(MESSAGE_INVALID_INDEX);
+ } else if (StringUtil.checkIndexValidity(trimmedIndex) == INVALID_INTEGER) {
+ throw new ParseException(MESSAGE_NON_POSITIVE_INDEX);
+ } else {
+ return Index.fromOneBased(Integer.parseInt(trimmedIndex));
+ }
+ }
+
+ /**
+ * Parses a {@code String name} into a {@code Name}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given {@code name} is invalid.
+ */
+ public static Name parseName(String name) throws ParseException {
+ requireNonNull(name);
+ String trimmedName = name.trim();
+ if (!Name.isValidName(trimmedName)) {
+ throw new ParseException(MESSAGE_INVALID_PERSON_DISPLAYED_NAME + Name.MESSAGE_CONSTRAINTS);
+ }
+ return new Name(trimmedName);
+ }
+
+ /**
+ * Parses a {@code String phone} into a {@code Phone}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given {@code phone} is invalid.
+ */
+ public static Phone parsePhone(String phone) throws ParseException {
+ requireNonNull(phone);
+ String trimmedPhone = phone.trim();
+ if (!Phone.isValidPhone(trimmedPhone)) {
+ throw new ParseException(MESSAGE_INVALID_PERSON_PHONE + Phone.MESSAGE_CONSTRAINTS);
+ }
+ if (!Phone.isValidLength(trimmedPhone)) {
+ throw new ParseException(MESSAGE_INVALID_PERSON_PHONE + Phone.MESSAGE_CONSTRAINTS);
+ }
+
+ return new Phone(trimmedPhone);
+ }
+
+ /**
+ * Parses a {@code String email} into an {@code Email}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given {@code email} is invalid.
+ */
+ public static Email parseEmail(String email) throws ParseException {
+ requireNonNull(email);
+ String trimmedEmail = email.trim();
+
+ if (!Email.isValidLength(trimmedEmail) || !Email.isValidEmail(trimmedEmail)) {
+ throw new ParseException(MESSAGE_INVALID_PERSON_EMAIL + Email.MESSAGE_CONSTRAINTS);
+ }
+ return new Email(trimmedEmail);
+ }
+
+ /**
+ * Parses a {@code String role} into an {@code Role}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given {@code role} is invalid.
+ */
+ public static Role parseRole(String role) throws ParseException {
+ requireNonNull(role);
+ String trimmedRole = role.trim();
+ if (!Role.isValidRole(trimmedRole)) {
+ throw new ParseException(MESSAGE_INVALID_PERSON_ROLE + Role.MESSAGE_CONSTRAINTS);
+ }
+ return new Role(trimmedRole);
+ }
+
+ /**
+ * Parses a {@code String assignee} into a {@code Assignee}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given {@code assignee} is invalid.
+ */
+ public static Assignee parseAssignee(String assignee) throws ParseException {
+ requireNonNull(assignee);
+ String trimmedAssignee = assignee.trim();
+ if (!Assignee.isValidAssigneeName(trimmedAssignee)) {
+ throw new ParseException(MESSAGE_INVALID_TASK_ASSIGNEE + Assignee.MESSAGE_CONSTRAINTS);
+ }
+ return new Assignee(trimmedAssignee);
+ }
+
+ /**
+ * Parses {@code Collection assignees} into a {@code Set}.
+ */
+ public static Set parseAssignees(Collection assignees) throws ParseException {
+ requireNonNull(assignees);
+ final Set assigneeSet = new HashSet<>();
+ for (String assigneeName : assignees) {
+ assigneeSet.add(parseAssignee(assigneeName));
+ }
+ return assigneeSet;
+ }
+
+ /**
+ * Parses a {@code String title} into a {@code title}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given {@code title} is invalid.
+ */
+ public static Title parseTitle(String title) throws ParseException {
+ requireNonNull(title);
+ String trimmedTitle = title.trim();
+
+ try {
+ assert Title.isValidTitle(trimmedTitle) : "You have to input a task Title";
+ } catch (AssertionError e) {
+ throw new ParseException(MESSAGE_INVALID_TASK_TITLE + Title.MESSAGE_CONSTRAINTS);
+ }
+
+ if (!Title.isValidTitle(trimmedTitle)) {
+ throw new ParseException(MESSAGE_INVALID_TASK_TITLE + Title.MESSAGE_CONSTRAINTS);
+ }
+ return new Title(trimmedTitle);
+ }
+
+ /**
+ * Parses a {@code String description} into a {@code Description}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given {@code description} is invalid.
+ */
+ public static Description parseDescription(String description) throws ParseException {
+ requireNonNull(description);
+ String trimmedDesc = description.trim();
+
+ try {
+ assert Description.isValidDescription(trimmedDesc) : "You have to input a task description";
+ } catch (AssertionError e) {
+ throw new ParseException(MESSAGE_INVALID_TASK_DESCRIPTION + Description.MESSAGE_CONSTRAINTS);
+ }
+
+ if (!Description.isValidDescription(trimmedDesc)) {
+ throw new ParseException(MESSAGE_INVALID_TASK_DESCRIPTION + Description.MESSAGE_CONSTRAINTS);
+ }
+ return new Description(trimmedDesc);
+ }
+
+ /**
+ * Parses a {@code String status} into a {@code TaskStatus}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given {@code status} is invalid.
+ */
+ public static TaskStatus parseStatus(String status) throws ParseException {
+ requireNonNull(status);
+ String trimmedStatus = status.trim();
+
+ try {
+ assert TaskStatus.isValidValue(trimmedStatus) : "You have to input a valid status";
+ } catch (AssertionError e) {
+ throw new ParseException(MESSAGE_INVALID_TASK_STATUS + TaskStatus.MESSAGE_CONSTRAINTS);
+ }
+
+ if (!TaskStatus.isValidValue(trimmedStatus)) {
+ throw new ParseException(MESSAGE_INVALID_TASK_STATUS + TaskStatus.MESSAGE_CONSTRAINTS);
+ }
+ return TaskStatus.valueOf(trimmedStatus.toUpperCase());
+ }
+
+ /**
+ * Parses a {@code String deadline} into a {@code Deadline}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given {@code deadline} is invalid.
+ */
+ public static Deadline parseDeadline(String deadline) throws ParseException {
+ requireNonNull(deadline);
+ String trimmedDeadline = deadline.trim();
+ DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+ sdf.setLenient(false);
+ try {
+ assert Deadline.isValidFormat(trimmedDeadline) : " You have to input a deadline with the correct format!";
+ } catch (AssertionError e) {
+ throw new ParseException(MESSAGE_INVALID_TASK_DEADLINE_FORMAT + Deadline.MESSAGE_CONSTRAINTS);
+ }
+ try {
+ assert Deadline.isValidDeadline(trimmedDeadline) : "You have to input a valid deadline!";
+ } catch (AssertionError e) {
+ throw new ParseException(MESSAGE_INVALID_TASK_DEADLINE + Deadline.MESSAGE_CONSTRAINTS);
+ }
+ if (!Deadline.isValidFormat(trimmedDeadline)) {
+ throw new ParseException(MESSAGE_INVALID_TASK_DEADLINE_FORMAT + Deadline.MESSAGE_CONSTRAINTS);
+ }
+ if (!Deadline.isValidDeadline(trimmedDeadline)) {
+ throw new ParseException(MESSAGE_INVALID_TASK_DEADLINE + Deadline.MESSAGE_CONSTRAINTS);
+ }
+ return new Deadline(trimmedDeadline);
+ }
+
+ /**
+ * Parses a {@code String priorty} into a {@code Priority}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given {@code priority} is invalid.
+ */
+ public static Priority parsePriority(String priority) throws ParseException {
+ requireNonNull(priority);
+ String trimmedPriority = priority.trim();
+
+ if (!Priority.isValidValue(trimmedPriority)) {
+ throw new ParseException(MESSAGE_INVALID_TASK_PRIORITY + Priority.MESSAGE_CONSTRAINTS);
+ }
+ return Priority.valueOf(trimmedPriority.toUpperCase());
+ }
+}
diff --git a/src/main/java/seedu/address/logic/parser/Prefix.java b/src/main/java/seedu/heymatez/logic/parser/Prefix.java
similarity index 95%
rename from src/main/java/seedu/address/logic/parser/Prefix.java
rename to src/main/java/seedu/heymatez/logic/parser/Prefix.java
index c859d5fa5db..7bd1b777122 100644
--- a/src/main/java/seedu/address/logic/parser/Prefix.java
+++ b/src/main/java/seedu/heymatez/logic/parser/Prefix.java
@@ -1,4 +1,4 @@
-package seedu.address.logic.parser;
+package seedu.heymatez.logic.parser;
/**
* A prefix that marks the beginning of an argument in an arguments string.
diff --git a/src/main/java/seedu/heymatez/logic/parser/UndoTaskCommandParser.java b/src/main/java/seedu/heymatez/logic/parser/UndoTaskCommandParser.java
new file mode 100644
index 00000000000..3b0d1ca9a34
--- /dev/null
+++ b/src/main/java/seedu/heymatez/logic/parser/UndoTaskCommandParser.java
@@ -0,0 +1,40 @@
+package seedu.heymatez.logic.parser;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX;
+import static seedu.heymatez.logic.parser.ParserUtil.MESSAGE_NON_POSITIVE_INDEX;
+
+import seedu.heymatez.commons.core.index.Index;
+import seedu.heymatez.logic.commands.UndoTaskCommand;
+import seedu.heymatez.logic.parser.exceptions.ParseException;
+
+/**
+ * Parses input arguments and creates a new UndoTaskCommand object
+ */
+public class UndoTaskCommandParser implements Parser {
+ /**
+ * Parses the given {@code String} of arguments in the context of the UndoTaskCommand
+ * and returns an UndoTaskCommand object for execution.
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public UndoTaskCommand parse(String args) throws ParseException {
+ requireNonNull(args);
+ ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args);
+
+ Index index;
+
+ try {
+ index = ParserUtil.parseIndex(argMultimap.getPreamble());
+ } catch (ParseException pe) {
+ if (pe.getMessage().equals(MESSAGE_NON_POSITIVE_INDEX)) {
+ throw new ParseException(MESSAGE_INVALID_TASK_DISPLAYED_INDEX, pe);
+ }
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, UndoTaskCommand.MESSAGE_USAGE), pe);
+ }
+
+ return new UndoTaskCommand(index);
+ }
+
+
+}
diff --git a/src/main/java/seedu/address/logic/parser/exceptions/ParseException.java b/src/main/java/seedu/heymatez/logic/parser/exceptions/ParseException.java
similarity index 72%
rename from src/main/java/seedu/address/logic/parser/exceptions/ParseException.java
rename to src/main/java/seedu/heymatez/logic/parser/exceptions/ParseException.java
index 158a1a54c1c..c65696db24b 100644
--- a/src/main/java/seedu/address/logic/parser/exceptions/ParseException.java
+++ b/src/main/java/seedu/heymatez/logic/parser/exceptions/ParseException.java
@@ -1,6 +1,6 @@
-package seedu.address.logic.parser.exceptions;
+package seedu.heymatez.logic.parser.exceptions;
-import seedu.address.commons.exceptions.IllegalValueException;
+import seedu.heymatez.commons.exceptions.IllegalValueException;
/**
* Represents a parse error encountered by a parser.
diff --git a/src/main/java/seedu/heymatez/model/HeyMatez.java b/src/main/java/seedu/heymatez/model/HeyMatez.java
new file mode 100644
index 00000000000..52e8287bfa8
--- /dev/null
+++ b/src/main/java/seedu/heymatez/model/HeyMatez.java
@@ -0,0 +1,189 @@
+package seedu.heymatez.model;
+
+import static java.util.Objects.requireNonNull;
+
+import java.util.List;
+
+import javafx.collections.ObservableList;
+import seedu.heymatez.model.person.Name;
+import seedu.heymatez.model.person.Person;
+import seedu.heymatez.model.person.UniquePersonList;
+import seedu.heymatez.model.task.Task;
+import seedu.heymatez.model.task.UniqueTaskList;
+
+
+/**
+ * Wraps all data at Hey Matez level.
+ * Duplicates are not allowed (by .isSamePerson comparison).
+ */
+public class HeyMatez implements ReadOnlyHeyMatez {
+
+ private final UniquePersonList persons;
+ private final UniqueTaskList tasks;
+
+ /*
+ * The 'unusual' code block below is a non-static initialization block, sometimes used to avoid duplication
+ * between constructors. See https://docs.oracle.com/javase/tutorial/java/javaOO/initial.html
+ *
+ * Note that non-static init blocks are not recommended to use. There are other ways to avoid duplication
+ * among constructors.
+ */
+ {
+ persons = new UniquePersonList();
+ tasks = new UniqueTaskList();
+ }
+
+ public HeyMatez() {}
+
+ /**
+ * Creates HeyMatez using the Persons in the {@code toBeCopied}.
+ */
+ public HeyMatez(ReadOnlyHeyMatez toBeCopied) {
+ this();
+ resetData(toBeCopied);
+ }
+
+ //// list overwrite operations
+
+ /**
+ * Replaces the contents of the person list with {@code persons}.
+ * {@code persons} must not contain duplicate persons.
+ */
+ public void setPersons(List persons) {
+ this.persons.setPersons(persons);
+ }
+
+ /**
+ * Resets the existing data of {@code HeyMatez} with {@code newData}.
+ */
+ public void resetData(ReadOnlyHeyMatez newData) {
+ requireNonNull(newData);
+
+ setTasks(newData.getTaskList());
+ setPersons(newData.getPersonList());
+ }
+
+ //// person-level operations
+
+ /**
+ * Returns true if a person with the same identity as {@code person} exists in HEY MATEz.
+ */
+ public boolean hasPerson(Person person) {
+ requireNonNull(person);
+ return persons.contains(person);
+ }
+
+ /**
+ * Adds a person to HEY MATEz.
+ * The person must not already exist in HEY MATEz.
+ */
+ public void addPerson(Person p) {
+ persons.add(p);
+ }
+
+ /**
+ * Replaces the given person {@code target} in the list with {@code editedPerson}.
+ * {@code target} must exist in HEY MATEz.
+ * The person identity of {@code editedPerson} must not be the same as another existing person in HEY MATEz.
+ */
+ public void setPerson(Person target, Person editedPerson) {
+ requireNonNull(editedPerson);
+
+ persons.setPerson(target, editedPerson);
+ }
+
+ /**
+ * Removes {@code key} from HEY MATEz.
+ * {@code key} must exist in HEY MATEz.
+ */
+ public void removePerson(Person key) {
+ persons.remove(key);
+ }
+
+ //// util methods
+
+ /**
+ * Replaces the contents of the task list with {@code tasks}.
+ */
+ public void setTasks(List tasks) {
+ this.tasks.setTasks(tasks);
+ }
+
+ /**
+ * Returns true if a task with the same identity as {@code task} exists in HEY MATEz.
+ */
+ public boolean hasTask(Task task) {
+ requireNonNull(task);
+ return tasks.contains(task);
+ }
+
+ /**
+ * Adds a task to HEY MATEz.
+ */
+ public void addTask(Task t) {
+ tasks.addTask(t);
+ }
+
+ /**
+ * Replaces the given task {@code target} in the list with {@code editedTask}.
+ * {@code target} must exist in HEY MATEz.
+ */
+ public void setTask(Task target, Task editedTask) {
+ requireNonNull(editedTask);
+
+ tasks.setTask(target, editedTask);
+ }
+
+ /**
+ * Removes {@code key} from this {@code UniqueTaskList}.
+ * {@code key} must exist in the task list.
+ */
+ public void removeTask(Task key) {
+ tasks.remove(key);
+ }
+
+ /**
+ * Removes the Assignee with the given name from the Assignee sets of the current task list
+ */
+ public void removeAssignee(Name name) {
+ tasks.removeAssignee(name);
+ }
+
+ /**
+ * Replaces the given Assignee {@code targetName} with {@code editedName} in tasks from the task list.
+ * {@code targetName} must exist in HEY MATEz.
+ */
+ public void editAssignee(Name targetName, Name editedName) {
+ tasks.editAssignee(targetName, editedName);
+ }
+
+ @Override
+ public ObservableList getTaskList() {
+ return tasks.asUnmodifiableObservableList();
+ }
+
+ @Override
+ public String toString() {
+ return persons.asUnmodifiableObservableList().size() + " persons";
+ // TODO: refine later
+ }
+
+ @Override
+ public ObservableList getPersonList() {
+ return persons.asUnmodifiableObservableList();
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof HeyMatez // instanceof handles nulls
+ && persons.equals(((HeyMatez) other).persons)
+ && tasks.equals(((HeyMatez) other).tasks));
+ }
+
+ @Override
+ public int hashCode() {
+ return persons.hashCode();
+ }
+
+}
diff --git a/src/main/java/seedu/heymatez/model/Model.java b/src/main/java/seedu/heymatez/model/Model.java
new file mode 100644
index 00000000000..6929450281e
--- /dev/null
+++ b/src/main/java/seedu/heymatez/model/Model.java
@@ -0,0 +1,147 @@
+package seedu.heymatez.model;
+
+import java.nio.file.Path;
+import java.util.function.Predicate;
+
+import javafx.collections.ObservableList;
+import seedu.heymatez.commons.core.GuiSettings;
+import seedu.heymatez.model.person.Person;
+import seedu.heymatez.model.task.Task;
+
+/**
+ * The API of the Model component.
+ */
+public interface Model {
+ /** {@code Predicate} that always evaluate to true */
+ Predicate PREDICATE_SHOW_ALL_TASKS = unused -> true;
+ Predicate PREDICATE_SHOW_ALL_PERSONS = unused -> true;
+ Predicate PREDICATE_SHOW_ALL_UNCOMPLETED_TASKS = Task::isUncompleted;
+ Predicate PREDICATE_SHOW_ALL_UNASSIGNED_TASKS = Task::isUnassigned;
+
+ /**
+ * Replaces user prefs data with the data in {@code userPrefs}.
+ */
+ void setUserPrefs(ReadOnlyUserPrefs userPrefs);
+
+ /**
+ * Returns the user prefs.
+ */
+ ReadOnlyUserPrefs getUserPrefs();
+
+ /**
+ * Returns the user prefs' GUI settings.
+ */
+ GuiSettings getGuiSettings();
+
+ /**
+ * Sets the user prefs' GUI settings.
+ */
+ void setGuiSettings(GuiSettings guiSettings);
+
+ /**
+ * Returns the user prefs' Hey Matez file path.
+ */
+ Path getHeyMatezFilePath();
+
+ /**
+ * Sets the user prefs' Hey Matez file path.
+ */
+ void setHeyMatezFilePath(Path heyMatezFilePath);
+
+ /**
+ * Replaces hay matez data with the data in {@code HeyMatez}.
+ */
+ void setHeyMatez(ReadOnlyHeyMatez heyMatez);
+
+ /** Returns hey matez */
+ ReadOnlyHeyMatez getHeyMatez();
+
+ /**
+ * Returns true if a person with the same identity as {@code person} exists in Hey Matez .
+ */
+ boolean hasPerson(Person person);
+
+ /**
+ * Deletes the given person.
+ * The person must exist in Hey Matez.
+ */
+ void deletePerson(Person target);
+
+ /**
+ * Adds the given person.
+ * {@code person} must not already exist in Hey Matez .
+ */
+ void addPerson(Person person);
+
+ /**
+ * Replaces the given person {@code target} with {@code editedPerson}.
+ * {@code target} must exist in Hey Matez.
+ * The person identity of {@code editedPerson} must not be the same as another existing person in Hey Matez.
+ */
+ void setPerson(Person target, Person editedPerson);
+
+ /** Returns an unmodifiable view of the filtered person list */
+ ObservableList getFilteredPersonList();
+
+ /**
+ * Updates the filter of the filtered person list to filter by the given {@code predicate}.
+ * @throws NullPointerException if {@code predicate} is null.
+ */
+ void updateFilteredPersonList(Predicate predicate);
+
+ /**
+ * Adds the given task.
+ */
+ void addTask(Task newTask);
+
+ /**
+ * Replaces the given task {@code target} with {@code editedTask}.
+ * {@code target} must exist in Hey Matez.
+ */
+ void setTask(Task target, Task editedTask);
+
+ /**
+ * Returns true if a person with the same identity as {@code person} exists in Hey Matez.
+ */
+ boolean hasTask(Task task);
+
+ /**
+ * Deletes the given task.
+ * The task must exist in Hey Matez.
+ */
+ void deleteTask(Task target);
+
+ /** Returns an unmodifiable view of the filtered task list */
+ ObservableList getFilteredTaskList();
+
+ /**
+ * Deletes the given Person if he is the Assignee of any task.
+ * The person must exist in Hey Matez.
+ */
+ void removeAssignee(Person target);
+
+ /**
+ * Edits the given person {@code target} with {@code editedPerson} in the Assignees of any task.
+ * {@code target} must exist in Hey Matez.
+ * The person identity of {@code editedPerson} must not be the same as another existing person in Hey Matez.
+ */
+ void editAssignee(Person target, Person editedPerson);
+
+ /**
+ * Updates the filter of the filtered task list to filter by the given {@code predicate}.
+ * @throws NullPointerException if {@code predicate} is null.
+ */
+ void updateFilteredTaskList(Predicate predicate);
+
+ boolean checkAssignees(Task task);
+
+ /**
+ * Returns true if the filtered person list is empty.
+ */
+ boolean isPersonListEmpty();
+
+ /**
+ * Returns true if the filtered task list is empty.
+ */
+ boolean isTaskListEmpty();
+}
diff --git a/src/main/java/seedu/heymatez/model/ModelManager.java b/src/main/java/seedu/heymatez/model/ModelManager.java
new file mode 100644
index 00000000000..18b9ec7ef67
--- /dev/null
+++ b/src/main/java/seedu/heymatez/model/ModelManager.java
@@ -0,0 +1,230 @@
+package seedu.heymatez.model;
+
+import static java.util.Objects.requireNonNull;
+
+import java.nio.file.Path;
+import java.util.Set;
+import java.util.function.Predicate;
+import java.util.logging.Logger;
+
+import javafx.collections.ObservableList;
+import javafx.collections.transformation.FilteredList;
+import seedu.heymatez.commons.core.GuiSettings;
+import seedu.heymatez.commons.core.LogsCenter;
+import seedu.heymatez.commons.util.CollectionUtil;
+import seedu.heymatez.model.assignee.Assignee;
+import seedu.heymatez.model.person.Name;
+import seedu.heymatez.model.person.Person;
+import seedu.heymatez.model.task.Task;
+
+/**
+ * Represents the in-memory model of the HeyMatez data.
+ */
+public class ModelManager implements Model {
+ private static final Logger logger = LogsCenter.getLogger(ModelManager.class);
+
+ private final HeyMatez heyMatez;
+ private final UserPrefs userPrefs;
+ private final FilteredList filteredPersons;
+ private final FilteredList filteredTasks;
+
+ /**
+ * Initializes a ModelManager with the given HeyMatez and userPrefs.
+ */
+ public ModelManager(ReadOnlyHeyMatez heyMatez, ReadOnlyUserPrefs userPrefs) {
+ super();
+ CollectionUtil.requireAllNonNull(heyMatez, userPrefs);
+
+ logger.fine("Initializing with HEY MATEz: " + heyMatez + " and user prefs " + userPrefs);
+
+ this.heyMatez = new HeyMatez(heyMatez);
+ this.userPrefs = new UserPrefs(userPrefs);
+ filteredPersons = new FilteredList<>(this.heyMatez.getPersonList());
+ filteredTasks = new FilteredList<>(this.heyMatez.getTaskList());
+ }
+
+ public ModelManager() {
+ this(new HeyMatez(), new UserPrefs());
+ }
+
+ //=========== UserPrefs ==================================================================================
+
+ @Override
+ public void setUserPrefs(ReadOnlyUserPrefs userPrefs) {
+ requireNonNull(userPrefs);
+ this.userPrefs.resetData(userPrefs);
+ }
+
+ @Override
+ public ReadOnlyUserPrefs getUserPrefs() {
+ return userPrefs;
+ }
+
+ @Override
+ public GuiSettings getGuiSettings() {
+ return userPrefs.getGuiSettings();
+ }
+
+ @Override
+ public void setGuiSettings(GuiSettings guiSettings) {
+ requireNonNull(guiSettings);
+ userPrefs.setGuiSettings(guiSettings);
+ }
+
+ @Override
+ public Path getHeyMatezFilePath() {
+ return userPrefs.getHeyMatezFilePath();
+ }
+
+ @Override
+ public void setHeyMatezFilePath(Path heyMatezFilePath) {
+ requireNonNull(heyMatezFilePath);
+ userPrefs.setHeyMatezFilePath(heyMatezFilePath);
+ }
+
+ //=========== HeyMatez ================================================================================
+
+ @Override
+ public void setHeyMatez(ReadOnlyHeyMatez heyMatez) {
+ this.heyMatez.resetData(heyMatez);
+ }
+
+ @Override
+ public ReadOnlyHeyMatez getHeyMatez() {
+ return heyMatez;
+ }
+
+ @Override
+ public boolean hasPerson(Person person) {
+ requireNonNull(person);
+ return heyMatez.hasPerson(person);
+ }
+
+ @Override
+ public void deletePerson(Person target) {
+ heyMatez.removePerson(target);
+ }
+
+ @Override
+ public void addPerson(Person person) {
+ heyMatez.addPerson(person);
+ updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
+ }
+
+ @Override
+ public void setPerson(Person target, Person editedPerson) {
+ CollectionUtil.requireAllNonNull(target, editedPerson);
+
+ heyMatez.setPerson(target, editedPerson);
+ }
+
+ @Override
+ public void addTask(Task task) {
+ heyMatez.addTask(task);
+ updateFilteredTaskList(PREDICATE_SHOW_ALL_TASKS);
+ }
+
+ @Override
+ public void setTask(Task target, Task editedTask) {
+ CollectionUtil.requireAllNonNull(target, editedTask);
+
+ heyMatez.setTask(target, editedTask);
+ }
+
+ @Override
+ public boolean hasTask(Task task) {
+ requireNonNull(task);
+ return heyMatez.hasTask(task);
+ }
+
+ @Override
+ public void deleteTask(Task target) {
+ heyMatez.removeTask(target);
+ }
+
+ @Override
+ public boolean checkAssignees(Task task) {
+ Set assignees = task.getAssignees();
+
+ for (Assignee assignee : assignees) {
+ Name tempName = new Name(assignee.assigneeName);
+ Person tempPerson = new Person(tempName);
+ if (!hasPerson(tempPerson)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean isTaskListEmpty() {
+ return this.filteredTasks.isEmpty();
+ }
+
+ @Override
+ public void removeAssignee(Person target) {
+ heyMatez.removeAssignee(target.getName());
+ updateFilteredTaskList(PREDICATE_SHOW_ALL_TASKS);
+ }
+
+ @Override
+ public void editAssignee(Person target, Person editedPerson) {
+ CollectionUtil.requireAllNonNull(target, editedPerson);
+
+ heyMatez.editAssignee(target.getName(), editedPerson.getName());
+ updateFilteredTaskList(PREDICATE_SHOW_ALL_TASKS);
+ }
+
+ @Override
+ public boolean isPersonListEmpty() {
+ return filteredPersons.isEmpty();
+ }
+
+ //=========== Filtered Person List Accessors =============================================================
+
+ /**
+ * Returns an unmodifiable view of the list of {@code Person} backed by the internal list of
+ * {@code versionedHeyMatez}
+ */
+ @Override
+ public ObservableList getFilteredPersonList() {
+ return filteredPersons;
+ }
+
+ @Override
+ public ObservableList getFilteredTaskList() {
+ return filteredTasks;
+ }
+
+ @Override
+ public void updateFilteredPersonList(Predicate predicate) {
+ requireNonNull(predicate);
+ filteredPersons.setPredicate(predicate);
+ }
+
+ @Override
+ public void updateFilteredTaskList(Predicate predicate) {
+ requireNonNull(predicate);
+ filteredTasks.setPredicate(predicate);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ // short circuit if same object
+ if (obj == this) {
+ return true;
+ }
+
+ // instanceof handles nulls
+ if (!(obj instanceof ModelManager)) {
+ return false;
+ }
+
+ // state check
+ ModelManager other = (ModelManager) obj;
+ return heyMatez.equals(other.heyMatez)
+ && userPrefs.equals(other.userPrefs)
+ && filteredPersons.equals(other.filteredPersons);
+ }
+}
diff --git a/src/main/java/seedu/address/model/ReadOnlyAddressBook.java b/src/main/java/seedu/heymatez/model/ReadOnlyHeyMatez.java
similarity index 50%
rename from src/main/java/seedu/address/model/ReadOnlyAddressBook.java
rename to src/main/java/seedu/heymatez/model/ReadOnlyHeyMatez.java
index 6ddc2cd9a29..bf19f4d4cf7 100644
--- a/src/main/java/seedu/address/model/ReadOnlyAddressBook.java
+++ b/src/main/java/seedu/heymatez/model/ReadOnlyHeyMatez.java
@@ -1,17 +1,19 @@
-package seedu.address.model;
+package seedu.heymatez.model;
import javafx.collections.ObservableList;
-import seedu.address.model.person.Person;
+import seedu.heymatez.model.person.Person;
+import seedu.heymatez.model.task.Task;
/**
- * Unmodifiable view of an address book
+ * Unmodifiable view of HEY MATEz
*/
-public interface ReadOnlyAddressBook {
+public interface ReadOnlyHeyMatez {
/**
* Returns an unmodifiable view of the persons list.
* This list will not contain any duplicate persons.
*/
ObservableList getPersonList();
+ ObservableList getTaskList();
}
diff --git a/src/main/java/seedu/address/model/ReadOnlyUserPrefs.java b/src/main/java/seedu/heymatez/model/ReadOnlyUserPrefs.java
similarity index 57%
rename from src/main/java/seedu/address/model/ReadOnlyUserPrefs.java
rename to src/main/java/seedu/heymatez/model/ReadOnlyUserPrefs.java
index befd58a4c73..d3cebaf0c62 100644
--- a/src/main/java/seedu/address/model/ReadOnlyUserPrefs.java
+++ b/src/main/java/seedu/heymatez/model/ReadOnlyUserPrefs.java
@@ -1,8 +1,8 @@
-package seedu.address.model;
+package seedu.heymatez.model;
import java.nio.file.Path;
-import seedu.address.commons.core.GuiSettings;
+import seedu.heymatez.commons.core.GuiSettings;
/**
* Unmodifiable view of user prefs.
@@ -11,6 +11,6 @@ public interface ReadOnlyUserPrefs {
GuiSettings getGuiSettings();
- Path getAddressBookFilePath();
+ Path getHeyMatezFilePath();
}
diff --git a/src/main/java/seedu/address/model/UserPrefs.java b/src/main/java/seedu/heymatez/model/UserPrefs.java
similarity index 70%
rename from src/main/java/seedu/address/model/UserPrefs.java
rename to src/main/java/seedu/heymatez/model/UserPrefs.java
index 25a5fd6eab9..eb8297eb04f 100644
--- a/src/main/java/seedu/address/model/UserPrefs.java
+++ b/src/main/java/seedu/heymatez/model/UserPrefs.java
@@ -1,4 +1,4 @@
-package seedu.address.model;
+package seedu.heymatez.model;
import static java.util.Objects.requireNonNull;
@@ -6,7 +6,7 @@
import java.nio.file.Paths;
import java.util.Objects;
-import seedu.address.commons.core.GuiSettings;
+import seedu.heymatez.commons.core.GuiSettings;
/**
* Represents User's preferences.
@@ -14,7 +14,7 @@
public class UserPrefs implements ReadOnlyUserPrefs {
private GuiSettings guiSettings = new GuiSettings();
- private Path addressBookFilePath = Paths.get("data" , "addressbook.json");
+ private Path heyMatezFilePath = Paths.get("data" , "heymatez.json");
/**
* Creates a {@code UserPrefs} with default values.
@@ -35,7 +35,7 @@ public UserPrefs(ReadOnlyUserPrefs userPrefs) {
public void resetData(ReadOnlyUserPrefs newUserPrefs) {
requireNonNull(newUserPrefs);
setGuiSettings(newUserPrefs.getGuiSettings());
- setAddressBookFilePath(newUserPrefs.getAddressBookFilePath());
+ setHeyMatezFilePath(newUserPrefs.getHeyMatezFilePath());
}
public GuiSettings getGuiSettings() {
@@ -47,13 +47,13 @@ public void setGuiSettings(GuiSettings guiSettings) {
this.guiSettings = guiSettings;
}
- public Path getAddressBookFilePath() {
- return addressBookFilePath;
+ public Path getHeyMatezFilePath() {
+ return heyMatezFilePath;
}
- public void setAddressBookFilePath(Path addressBookFilePath) {
- requireNonNull(addressBookFilePath);
- this.addressBookFilePath = addressBookFilePath;
+ public void setHeyMatezFilePath(Path heyMatezFilePath) {
+ requireNonNull(heyMatezFilePath);
+ this.heyMatezFilePath = heyMatezFilePath;
}
@Override
@@ -68,19 +68,19 @@ public boolean equals(Object other) {
UserPrefs o = (UserPrefs) other;
return guiSettings.equals(o.guiSettings)
- && addressBookFilePath.equals(o.addressBookFilePath);
+ && heyMatezFilePath.equals(o.heyMatezFilePath);
}
@Override
public int hashCode() {
- return Objects.hash(guiSettings, addressBookFilePath);
+ return Objects.hash(guiSettings, heyMatezFilePath);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("Gui Settings : " + guiSettings);
- sb.append("\nLocal data file location : " + addressBookFilePath);
+ sb.append("\nLocal data file location : " + heyMatezFilePath);
return sb.toString();
}
diff --git a/src/main/java/seedu/heymatez/model/assignee/Assignee.java b/src/main/java/seedu/heymatez/model/assignee/Assignee.java
new file mode 100644
index 00000000000..8a6ad3cfa12
--- /dev/null
+++ b/src/main/java/seedu/heymatez/model/assignee/Assignee.java
@@ -0,0 +1,58 @@
+package seedu.heymatez.model.assignee;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.heymatez.commons.util.AppUtil.checkArgument;
+
+/**
+ * Represents an Assignee in the address book.
+ * Guarantees: immutable; name is valid as declared in {@link #isValidAssigneeName(String)}
+ */
+public class Assignee {
+ public static final String MESSAGE_SEARCH_TASKS_CONSTRAINTS = "Please check that the name you have typed in is a "
+ + "proper name";
+
+ public static final String MESSAGE_CONSTRAINTS = "Assignee specified must be an existing member "
+ + "HEY MATEz, with the exact name (case-sensitive and format-sensitive) and name should not "
+ + "have extra spaces or characters between words.";
+
+ public static final String VALIDATION_REGEX = "[\\p{Alnum}][\\p{Alnum} ]*";
+
+ public final String assigneeName;
+
+ /**
+ * Constructs an {@code Assignee}.
+ *
+ * @param assigneeName A valid assignee name.
+ */
+ public Assignee(String assigneeName) {
+ requireNonNull(assigneeName);
+ checkArgument(isValidAssigneeName(assigneeName), MESSAGE_CONSTRAINTS);
+ this.assigneeName = assigneeName;
+ }
+
+ /**
+ * Returns true if a given string is a valid assignee name.
+ */
+ public static boolean isValidAssigneeName(String test) {
+ return test.matches(VALIDATION_REGEX);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof Assignee // instanceof handles nulls
+ && assigneeName.equals(((Assignee) other).assigneeName)); // state check
+ }
+
+ @Override
+ public int hashCode() {
+ return assigneeName.hashCode();
+ }
+
+ /**
+ * Format state as text for viewing.
+ */
+ public String toString() {
+ return '[' + assigneeName + ']';
+ }
+}
diff --git a/src/main/java/seedu/heymatez/model/person/DetailsContainsKeywordsPredicate.java b/src/main/java/seedu/heymatez/model/person/DetailsContainsKeywordsPredicate.java
new file mode 100644
index 00000000000..1640faa63c6
--- /dev/null
+++ b/src/main/java/seedu/heymatez/model/person/DetailsContainsKeywordsPredicate.java
@@ -0,0 +1,30 @@
+package seedu.heymatez.model.person;
+
+import java.util.List;
+import java.util.function.Predicate;
+
+import seedu.heymatez.commons.util.StringUtil;
+
+/**
+ * Tests that a {@code Person}'s details matches any of the keywords given.
+ */
+public class DetailsContainsKeywordsPredicate implements Predicate {
+ private final List keywords;
+
+ public DetailsContainsKeywordsPredicate(List keywords) {
+ this.keywords = keywords;
+ }
+
+ @Override
+ public boolean test(Person person) {
+ return keywords.stream()
+ .anyMatch(keyword -> StringUtil.containsWordIgnoreCase(person.getAllFields(), keyword));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof DetailsContainsKeywordsPredicate // instanceof handles nulls
+ && keywords.equals(((DetailsContainsKeywordsPredicate) other).keywords)); // state check
+ }
+}
diff --git a/src/main/java/seedu/address/model/person/Email.java b/src/main/java/seedu/heymatez/model/person/Email.java
similarity index 56%
rename from src/main/java/seedu/address/model/person/Email.java
rename to src/main/java/seedu/heymatez/model/person/Email.java
index a5bbe0b6a5f..b7e5fbd806c 100644
--- a/src/main/java/seedu/address/model/person/Email.java
+++ b/src/main/java/seedu/heymatez/model/person/Email.java
@@ -1,7 +1,8 @@
-package seedu.address.model.person;
+package seedu.heymatez.model.person;
import static java.util.Objects.requireNonNull;
-import static seedu.address.commons.util.AppUtil.checkArgument;
+
+import seedu.heymatez.commons.util.AppUtil;
/**
* Represents a Person's email in the address book.
@@ -11,21 +12,37 @@ public class Email {
private static final String SPECIAL_CHARACTERS = "!#$%&'*+/=?`{|}~^.-";
public static final String MESSAGE_CONSTRAINTS = "Emails should be of the format local-part@domain "
- + "and adhere to the following constraints:\n"
- + "1. The local-part should only contain alphanumeric characters and these special characters, excluding "
- + "the parentheses, (" + SPECIAL_CHARACTERS + ") .\n"
- + "2. This is followed by a '@' and then a domain name. "
+ + "and adhere to the following constraints:\n\n"
+
+ + "1. The entire email address should have a maximum length of 254 characters.\n\n"
+
+ + "2. The local-part should: \n"
+ + " - be at least 2 character long \n"
+ + " - only contain alphanumeric characters and these special characters, excluding "
+ + "the parentheses, (" + SPECIAL_CHARACTERS + ").\n\n"
+
+ + "3. This is followed by a '@' and then a domain name. "
+ "The domain name must:\n"
- + " - be at least 2 characters long\n"
+ + " - be at least 2 characters long \n"
+ " - start and end with alphanumeric characters\n"
- + " - consist of alphanumeric characters, a period or a hyphen for the characters in between, if any.";
+ + " - consist of alphanumeric characters, a period or a hyphen for the characters in between, "
+ + "if any.\n\n"
+
+ + "4. Lastly, a top-level domain (e.g. '.com') follows after the domain name. "
+ + "The top-level domain must: \n"
+ + " - be at least 2 character long with a maximum length of 24 characters\n"
+ + " - start with a period and consist of alphanumeric character only. ";
+
// alphanumeric and special characters
- private static final String LOCAL_PART_REGEX = "^[\\w" + SPECIAL_CHARACTERS + "]+";
+ private static final String LOCAL_PART_REGEX = "^[\\w" + SPECIAL_CHARACTERS + "]{2,}+";
private static final String DOMAIN_FIRST_CHARACTER_REGEX = "[^\\W_]"; // alphanumeric characters except underscore
private static final String DOMAIN_MIDDLE_REGEX = "[a-zA-Z0-9.-]*"; // alphanumeric, period and hyphen
- private static final String DOMAIN_LAST_CHARACTER_REGEX = "[^\\W_]$";
+ private static final String DOMAIN_LAST_CHARACTER_REGEX = "[^\\W_]";
+ private static final String TOP_LEVEL_DOMAIN_REGEX = "[^\\W]{2,24}$";
+
public static final String VALIDATION_REGEX = LOCAL_PART_REGEX + "@"
- + DOMAIN_FIRST_CHARACTER_REGEX + DOMAIN_MIDDLE_REGEX + DOMAIN_LAST_CHARACTER_REGEX;
+ + DOMAIN_FIRST_CHARACTER_REGEX + DOMAIN_MIDDLE_REGEX + DOMAIN_LAST_CHARACTER_REGEX
+ + "\\." + TOP_LEVEL_DOMAIN_REGEX;
public final String value;
@@ -36,7 +53,7 @@ public class Email {
*/
public Email(String email) {
requireNonNull(email);
- checkArgument(isValidEmail(email), MESSAGE_CONSTRAINTS);
+ AppUtil.checkArgument(isValidEmail(email), MESSAGE_CONSTRAINTS);
value = email;
}
@@ -47,6 +64,13 @@ public static boolean isValidEmail(String test) {
return test.matches(VALIDATION_REGEX);
}
+ /**
+ * Returns if a given string is within the maximum length of .
+ */
+ public static boolean isValidLength(String test) {
+ return test.length() <= 254;
+ }
+
@Override
public String toString() {
return value;
@@ -63,5 +87,4 @@ public boolean equals(Object other) {
public int hashCode() {
return value.hashCode();
}
-
}
diff --git a/src/main/java/seedu/address/model/person/Name.java b/src/main/java/seedu/heymatez/model/person/Name.java
similarity index 89%
rename from src/main/java/seedu/address/model/person/Name.java
rename to src/main/java/seedu/heymatez/model/person/Name.java
index 79244d71cf7..86943990b0d 100644
--- a/src/main/java/seedu/address/model/person/Name.java
+++ b/src/main/java/seedu/heymatez/model/person/Name.java
@@ -1,7 +1,9 @@
-package seedu.address.model.person;
+package seedu.heymatez.model.person;
import static java.util.Objects.requireNonNull;
-import static seedu.address.commons.util.AppUtil.checkArgument;
+
+import seedu.heymatez.commons.util.AppUtil;
+
/**
* Represents a Person's name in the address book.
@@ -27,7 +29,7 @@ public class Name {
*/
public Name(String name) {
requireNonNull(name);
- checkArgument(isValidName(name), MESSAGE_CONSTRAINTS);
+ AppUtil.checkArgument(isValidName(name), MESSAGE_CONSTRAINTS);
fullName = name;
}
@@ -55,5 +57,4 @@ public boolean equals(Object other) {
public int hashCode() {
return fullName.hashCode();
}
-
}
diff --git a/src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java b/src/main/java/seedu/heymatez/model/person/NameContainsKeywordsPredicate.java
similarity index 91%
rename from src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java
rename to src/main/java/seedu/heymatez/model/person/NameContainsKeywordsPredicate.java
index c9b5868427c..1a5e560c456 100644
--- a/src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java
+++ b/src/main/java/seedu/heymatez/model/person/NameContainsKeywordsPredicate.java
@@ -1,9 +1,9 @@
-package seedu.address.model.person;
+package seedu.heymatez.model.person;
import java.util.List;
import java.util.function.Predicate;
-import seedu.address.commons.util.StringUtil;
+import seedu.heymatez.commons.util.StringUtil;
/**
* Tests that a {@code Person}'s {@code Name} matches any of the keywords given.
@@ -27,5 +27,4 @@ public boolean equals(Object other) {
|| (other instanceof NameContainsKeywordsPredicate // instanceof handles nulls
&& keywords.equals(((NameContainsKeywordsPredicate) other).keywords)); // state check
}
-
}
diff --git a/src/main/java/seedu/address/model/person/Person.java b/src/main/java/seedu/heymatez/model/person/Person.java
similarity index 58%
rename from src/main/java/seedu/address/model/person/Person.java
rename to src/main/java/seedu/heymatez/model/person/Person.java
index 8ff1d83fe89..d0ba220c314 100644
--- a/src/main/java/seedu/address/model/person/Person.java
+++ b/src/main/java/seedu/heymatez/model/person/Person.java
@@ -1,13 +1,10 @@
-package seedu.address.model.person;
+package seedu.heymatez.model.person;
-import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
+import static seedu.heymatez.commons.util.CollectionUtil.requireAllNonNull;
-import java.util.Collections;
-import java.util.HashSet;
import java.util.Objects;
-import java.util.Set;
-import seedu.address.model.tag.Tag;
+import seedu.heymatez.commons.util.CollectionUtil;
/**
* Represents a Person in the address book.
@@ -19,21 +16,39 @@ public class Person {
private final Name name;
private final Phone phone;
private final Email email;
-
- // Data fields
- private final Address address;
- private final Set tags = new HashSet<>();
+ private final Role role;
/**
* Every field must be present and not null.
*/
- public Person(Name name, Phone phone, Email email, Address address, Set tags) {
- requireAllNonNull(name, phone, email, address, tags);
+ public Person(Name name, Phone phone, Email email, Role role) {
+ CollectionUtil.requireAllNonNull(name, phone, email);
+ this.name = name;
+ this.phone = phone;
+ this.email = email;
+ this.role = role;
+ }
+
+ /**
+ * Overloaded constructor which sets role to member as default.
+ */
+ public Person(Name name, Phone phone, Email email) {
+ CollectionUtil.requireAllNonNull(name, phone, email);
this.name = name;
this.phone = phone;
this.email = email;
- this.address = address;
- this.tags.addAll(tags);
+ this.role = new Role("Member");
+ }
+
+ /**
+ * Overloaded constructor which sets phone, email and role of member as null.
+ */
+ public Person(Name name) {
+ requireAllNonNull(name);
+ this.name = name;
+ this.phone = null;
+ this.email = null;
+ this.role = null;
}
public Name getName() {
@@ -48,16 +63,18 @@ public Email getEmail() {
return email;
}
- public Address getAddress() {
- return address;
+ public Role getRole() {
+ return role;
}
- /**
- * Returns an immutable tag set, which throws {@code UnsupportedOperationException}
- * if modification is attempted.
- */
- public Set getTags() {
- return Collections.unmodifiableSet(tags);
+ public String getAllFields() {
+ StringBuilder builder = new StringBuilder();
+ builder.append(name.fullName).append(" ")
+ .append(phone.value).append(" ")
+ .append(email.value).append(" ")
+ .append(role.memberRole);
+
+ return builder.toString();
}
/**
@@ -91,14 +108,13 @@ public boolean equals(Object other) {
return otherPerson.getName().equals(getName())
&& otherPerson.getPhone().equals(getPhone())
&& otherPerson.getEmail().equals(getEmail())
- && otherPerson.getAddress().equals(getAddress())
- && otherPerson.getTags().equals(getTags());
+ && otherPerson.getRole().equals(getRole());
}
@Override
public int hashCode() {
// use this method for custom fields hashing instead of implementing your own
- return Objects.hash(name, phone, email, address, tags);
+ return Objects.hash(name, phone, email, role);
}
@Override
@@ -109,15 +125,9 @@ public String toString() {
.append(getPhone())
.append("; Email: ")
.append(getEmail())
- .append("; Address: ")
- .append(getAddress());
+ .append("; Role:")
+ .append(getRole());
- Set tags = getTags();
- if (!tags.isEmpty()) {
- builder.append("; Tags: ");
- tags.forEach(builder::append);
- }
return builder.toString();
}
-
}
diff --git a/src/main/java/seedu/address/model/person/Phone.java b/src/main/java/seedu/heymatez/model/person/Phone.java
similarity index 62%
rename from src/main/java/seedu/address/model/person/Phone.java
rename to src/main/java/seedu/heymatez/model/person/Phone.java
index 872c76b382f..60649dbd364 100644
--- a/src/main/java/seedu/address/model/person/Phone.java
+++ b/src/main/java/seedu/heymatez/model/person/Phone.java
@@ -1,17 +1,17 @@
-package seedu.address.model.person;
+package seedu.heymatez.model.person;
import static java.util.Objects.requireNonNull;
-import static seedu.address.commons.util.AppUtil.checkArgument;
+
+import seedu.heymatez.commons.util.AppUtil;
/**
* Represents a Person's phone number in the address book.
* Guarantees: immutable; is valid as declared in {@link #isValidPhone(String)}
*/
public class Phone {
+ public static final String MESSAGE_CONSTRAINTS = "Phone numbers should only contain positive numbers, and it should"
+ + " be at least 3 digits long with a maximum length of 15 digits";
-
- public static final String MESSAGE_CONSTRAINTS =
- "Phone numbers should only contain numbers, and it should be at least 3 digits long";
public static final String VALIDATION_REGEX = "\\d{3,}";
public final String value;
@@ -22,17 +22,24 @@ public class Phone {
*/
public Phone(String phone) {
requireNonNull(phone);
- checkArgument(isValidPhone(phone), MESSAGE_CONSTRAINTS);
+ AppUtil.checkArgument(isValidPhone(phone), MESSAGE_CONSTRAINTS);
value = phone;
}
/**
- * Returns true if a given string is a valid phone number.
+ * Returns true if a given string is a valid phone number with 3 digits.
*/
public static boolean isValidPhone(String test) {
return test.matches(VALIDATION_REGEX);
}
+ /**
+ * Returns true if a given string is a valid phone number with a maximum of 15 digits.
+ */
+ public static boolean isValidLength(String test) {
+ return test.length() <= 15;
+ }
+
@Override
public String toString() {
return value;
@@ -49,5 +56,4 @@ public boolean equals(Object other) {
public int hashCode() {
return value.hashCode();
}
-
}
diff --git a/src/main/java/seedu/heymatez/model/person/Role.java b/src/main/java/seedu/heymatez/model/person/Role.java
new file mode 100644
index 00000000000..99ebbf45021
--- /dev/null
+++ b/src/main/java/seedu/heymatez/model/person/Role.java
@@ -0,0 +1,53 @@
+package seedu.heymatez.model.person;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.heymatez.commons.util.AppUtil.checkArgument;
+
+/**
+ * Represents a Person's role in Hey Matez.
+ * Guarantees: immutable; is valid as declared in {@link #isValidRole(String)}
+ */
+public class Role {
+ public static final String MESSAGE_CONSTRAINTS =
+ "Member roles can only take any alphanumeric characters, and it should not be blank ";
+ public static final String VALIDATION_REGEX = "[\\p{Alnum}][\\p{Alnum} ]*";
+ public final String memberRole;
+
+ /**
+ * Constructs a {@code Role}.
+ *
+ * @param role A valid member role as a string.
+ */
+ public Role(String role) {
+ requireNonNull(role);
+ checkArgument(isValidRole(role), MESSAGE_CONSTRAINTS);
+ memberRole = role;
+ }
+
+ /**
+ * Returns true if a given string is a valid member role.
+ *
+ * @return a boolean value
+ */
+ public static boolean isValidRole(String test) {
+ return test.matches(VALIDATION_REGEX);
+ }
+
+ @Override
+ public String toString() {
+ return memberRole;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof Role // instanceof handles nulls
+ && memberRole.equals(((Role) other).memberRole)); // state check
+ }
+
+ @Override
+ public int hashCode() {
+ return memberRole.hashCode();
+ }
+}
+
diff --git a/src/main/java/seedu/address/model/person/UniquePersonList.java b/src/main/java/seedu/heymatez/model/person/UniquePersonList.java
similarity index 92%
rename from src/main/java/seedu/address/model/person/UniquePersonList.java
rename to src/main/java/seedu/heymatez/model/person/UniquePersonList.java
index 0fee4fe57e6..d57272373b3 100644
--- a/src/main/java/seedu/address/model/person/UniquePersonList.java
+++ b/src/main/java/seedu/heymatez/model/person/UniquePersonList.java
@@ -1,15 +1,15 @@
-package seedu.address.model.person;
+package seedu.heymatez.model.person;
import static java.util.Objects.requireNonNull;
-import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
import java.util.Iterator;
import java.util.List;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
-import seedu.address.model.person.exceptions.DuplicatePersonException;
-import seedu.address.model.person.exceptions.PersonNotFoundException;
+import seedu.heymatez.commons.util.CollectionUtil;
+import seedu.heymatez.model.person.exceptions.DuplicatePersonException;
+import seedu.heymatez.model.person.exceptions.PersonNotFoundException;
/**
* A list of persons that enforces uniqueness between its elements and does not allow nulls.
@@ -54,7 +54,7 @@ public void add(Person toAdd) {
* The person identity of {@code editedPerson} must not be the same as another existing person in the list.
*/
public void setPerson(Person target, Person editedPerson) {
- requireAllNonNull(target, editedPerson);
+ CollectionUtil.requireAllNonNull(target, editedPerson);
int index = internalList.indexOf(target);
if (index == -1) {
@@ -89,7 +89,7 @@ public void setPersons(UniquePersonList replacement) {
* {@code persons} must not contain duplicate persons.
*/
public void setPersons(List persons) {
- requireAllNonNull(persons);
+ CollectionUtil.requireAllNonNull(persons);
if (!personsAreUnique(persons)) {
throw new DuplicatePersonException();
}
diff --git a/src/main/java/seedu/address/model/person/exceptions/DuplicatePersonException.java b/src/main/java/seedu/heymatez/model/person/exceptions/DuplicatePersonException.java
similarity index 86%
rename from src/main/java/seedu/address/model/person/exceptions/DuplicatePersonException.java
rename to src/main/java/seedu/heymatez/model/person/exceptions/DuplicatePersonException.java
index d7290f59442..c34d86f0cb9 100644
--- a/src/main/java/seedu/address/model/person/exceptions/DuplicatePersonException.java
+++ b/src/main/java/seedu/heymatez/model/person/exceptions/DuplicatePersonException.java
@@ -1,4 +1,4 @@
-package seedu.address.model.person.exceptions;
+package seedu.heymatez.model.person.exceptions;
/**
* Signals that the operation will result in duplicate Persons (Persons are considered duplicates if they have the same
diff --git a/src/main/java/seedu/address/model/person/exceptions/PersonNotFoundException.java b/src/main/java/seedu/heymatez/model/person/exceptions/PersonNotFoundException.java
similarity index 75%
rename from src/main/java/seedu/address/model/person/exceptions/PersonNotFoundException.java
rename to src/main/java/seedu/heymatez/model/person/exceptions/PersonNotFoundException.java
index fa764426ca7..bbcc8a4c1cd 100644
--- a/src/main/java/seedu/address/model/person/exceptions/PersonNotFoundException.java
+++ b/src/main/java/seedu/heymatez/model/person/exceptions/PersonNotFoundException.java
@@ -1,4 +1,4 @@
-package seedu.address.model.person.exceptions;
+package seedu.heymatez.model.person.exceptions;
/**
* Signals that the operation is unable to find the specified person.
diff --git a/src/main/java/seedu/heymatez/model/task/Deadline.java b/src/main/java/seedu/heymatez/model/task/Deadline.java
new file mode 100644
index 00000000000..b59843d8287
--- /dev/null
+++ b/src/main/java/seedu/heymatez/model/task/Deadline.java
@@ -0,0 +1,83 @@
+package seedu.heymatez.model.task;
+
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
+
+/**
+ * Represents Deadline for Task in HEY MATEz.
+ * Guarantees: deadline not empty and in the format YYYY-MM-DD.
+ */
+public class Deadline {
+ public static final String MESSAGE_CONSTRAINTS = "Deadlines should be in the format "
+ + "YYYY-MM-DD and should be a valid date";
+
+ public static final String VALIDATION_REGEX = "\\d{4}-\\d{2}-\\d{2}";
+ public final LocalDate date;
+ public final String dateString;
+ public final String unformattedDate;
+
+ /**
+ * Constructs a {@code Deadline}.
+ *
+ * @param date A valid date.
+ */
+ public Deadline(String date) {
+ this.unformattedDate = date;
+ this.date = LocalDate.parse(date);
+ this.dateString = this.date.format(DateTimeFormatter.ofPattern("MMM d yyyy"));
+ }
+
+ /**
+ * Returns a String value of unformatted deadline.
+ *
+ * @return a String value of unformatted deadline
+ */
+ public String getUnformattedDate() {
+ return unformattedDate;
+ }
+
+ /**
+ * Returns a parsed deadline.
+ *
+ * @return a LocalDate object of the parsed deadline
+ */
+ public LocalDate getDeadline() {
+ return this.date;
+ }
+
+ /**
+ * Returns true if a given string is a valid deadline.
+ *
+ * @return a boolean value
+ */
+ public static boolean isValidDeadline(String test) {
+ try {
+ LocalDate.parse(test);
+ } catch (DateTimeParseException e) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Returns true if a given string has a valid deadline format.
+ *
+ * @return a boolean value
+ */
+ public static boolean isValidFormat(String test) {
+ return test.matches(VALIDATION_REGEX);
+ }
+
+ @Override
+ public String toString() {
+ return this.date.format(DateTimeFormatter.ofPattern("MMM d yyyy"));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof Deadline // instanceof handles nulls
+ && dateString.equals(((Deadline) other).dateString)); // state check
+ }
+}
diff --git a/src/main/java/seedu/heymatez/model/task/DeadlineBeforeDatePredicate.java b/src/main/java/seedu/heymatez/model/task/DeadlineBeforeDatePredicate.java
new file mode 100644
index 00000000000..526182063bc
--- /dev/null
+++ b/src/main/java/seedu/heymatez/model/task/DeadlineBeforeDatePredicate.java
@@ -0,0 +1,27 @@
+package seedu.heymatez.model.task;
+
+import java.time.LocalDate;
+import java.util.function.Predicate;
+
+/**
+ * Tests that a {@code Task}'s {@code Deadline} is before a specified date.
+ */
+public class DeadlineBeforeDatePredicate implements Predicate {
+ private final String date;
+
+ public DeadlineBeforeDatePredicate(String date) {
+ this.date = date;
+ }
+
+ @Override
+ public boolean test(Task task) {
+ return task.getDeadline().getDeadline().compareTo(LocalDate.parse(this.date)) < 0;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof DeadlineBeforeDatePredicate// instanceof handles nulls
+ && date.equals(((DeadlineBeforeDatePredicate) other).date)); // state check
+ }
+}
diff --git a/src/main/java/seedu/heymatez/model/task/Description.java b/src/main/java/seedu/heymatez/model/task/Description.java
new file mode 100644
index 00000000000..a44c1ae75e7
--- /dev/null
+++ b/src/main/java/seedu/heymatez/model/task/Description.java
@@ -0,0 +1,56 @@
+package seedu.heymatez.model.task;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.heymatez.commons.util.AppUtil.checkArgument;
+
+/**
+ * Represents a Task's description.
+ */
+public class Description {
+ public static final String MESSAGE_CONSTRAINTS = "Descriptions can take any values, and it should not be blank";
+
+ /**
+ * The first character of the description must not be a whitespace,
+ * otherwise " " (a blank string) becomes a valid input.
+ */
+ public static final String VALIDATION_REGEX = "[^\\s].*";
+
+ public final String desc;
+
+ /**
+ * Constructs an {@code Description}.
+ *
+ * @param description A valid description.
+ */
+ public Description(String description) {
+ requireNonNull(description);
+ checkArgument(isValidDescription(description), MESSAGE_CONSTRAINTS);
+ desc = description;
+ }
+
+ /**
+ * Returns true if a given string is a valid description.
+ *
+ * @return a boolean value
+ */
+ public static boolean isValidDescription(String test) {
+ return test.matches(VALIDATION_REGEX);
+ }
+
+ @Override
+ public String toString() {
+ return desc;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof Description // instanceof handles nulls
+ && desc.equals(((Description) other).desc)); // state check
+ }
+
+ @Override
+ public int hashCode() {
+ return desc.hashCode();
+ }
+}
diff --git a/src/main/java/seedu/heymatez/model/task/Priority.java b/src/main/java/seedu/heymatez/model/task/Priority.java
new file mode 100644
index 00000000000..223ddcd3dcf
--- /dev/null
+++ b/src/main/java/seedu/heymatez/model/task/Priority.java
@@ -0,0 +1,74 @@
+package seedu.heymatez.model.task;
+
+/**
+ * Enum for the priority values
+ * Priority can take on the values, LOW, MEDIUM, HIGH, UNASSIGNED and is used to signify the priority of a task
+ * UNASSIGNED is the value that is set if there is no user input for priority
+ * */
+public enum Priority {
+ HIGH("high"),
+ MEDIUM("medium"),
+ LOW("low"),
+ UNASSIGNED("unassigned");
+
+ public static final String MESSAGE_CONSTRAINTS = "Task Priority should take one of the predefined values: "
+ + "high, medium, low or unassigned (case-sensitive)";
+
+ public final String priority;
+
+ Priority(String priority) {
+ this.priority = priority;
+ }
+
+ /**
+ * Returns a String value by of the Enum name to use for UI.
+ *
+ * @return a string value of the enum name to us for the UI
+ */
+ public static String getEnumName() {
+ return "Priority";
+ }
+
+ /**
+ * Returns a boolean value if the str input is "unasssigned".
+ *
+ * @return a boolean value
+ */
+ public static boolean isUnassigned(String str) {
+ return str.equals("unassigned");
+ }
+
+ /**
+ * Returns a boolean value by check if the String value is a
+ * value within this enum and is not unassigned value.
+ *
+ * @param value value for the Task Status enum
+ * @return a boolean value, whether the it is a value inside this enum
+ */
+ public static boolean isValidValue(String value) {
+ for (Priority c : Priority.values()) {
+
+ boolean match = c.name().toLowerCase().equals(value);
+
+ if (match) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns a string value of the priority casted to lower cast
+ *
+ * @return a string value representing the priority
+ */
+ public String getPriority() {
+ return this.priority.toLowerCase();
+ }
+
+ @Override
+ public String toString() {
+ return this.priority;
+ }
+}
diff --git a/src/main/java/seedu/heymatez/model/task/PriorityContainsKeywordPredicate.java b/src/main/java/seedu/heymatez/model/task/PriorityContainsKeywordPredicate.java
new file mode 100644
index 00000000000..b3269d6bc44
--- /dev/null
+++ b/src/main/java/seedu/heymatez/model/task/PriorityContainsKeywordPredicate.java
@@ -0,0 +1,30 @@
+package seedu.heymatez.model.task;
+
+import java.util.List;
+import java.util.function.Predicate;
+
+import seedu.heymatez.commons.util.StringUtil;
+
+/**
+ * Tests that a {@code Task}'s {@code Priority} matches any of the keywords given.
+ */
+public class PriorityContainsKeywordPredicate implements Predicate {
+ private final List keywords;
+
+ public PriorityContainsKeywordPredicate(List keywords) {
+ this.keywords = keywords;
+ }
+
+ @Override
+ public boolean test(Task task) {
+ return keywords.stream()
+ .anyMatch(keyword -> StringUtil.containsWordIgnoreCase(task.getPriority().getPriority(), keyword));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof PriorityContainsKeywordPredicate // instanceof handles nulls
+ && keywords.equals(((PriorityContainsKeywordPredicate) other).keywords)); // state check
+ }
+}
diff --git a/src/main/java/seedu/heymatez/model/task/Task.java b/src/main/java/seedu/heymatez/model/task/Task.java
new file mode 100644
index 00000000000..ff55f07bfb5
--- /dev/null
+++ b/src/main/java/seedu/heymatez/model/task/Task.java
@@ -0,0 +1,218 @@
+package seedu.heymatez.model.task;
+
+import static seedu.heymatez.commons.util.CollectionUtil.requireAllNonNull;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Objects;
+import java.util.Set;
+
+import seedu.heymatez.model.assignee.Assignee;
+
+/**
+ * Represents a Task in HEY MATEz.
+ * Guarantees: details are present and not null, field values are validated, immutable.
+ */
+public class Task {
+ // Identity fields
+ private final Title title;
+
+ // Data fields
+ private final Description description;
+ private final TaskStatus taskStatus;
+ private final Deadline deadline;
+ private final Priority priority;
+
+ private final Set assignees = new HashSet<>();
+
+ /**
+ * Overloaded constructor which sets taskStatus to uncompleted and PRIORITY to unassigned by default.
+ */
+ public Task(Title title, Description description, Deadline deadline) {
+ requireAllNonNull(title, description, deadline);
+ this.title = title;
+ this.description = description;
+ this.taskStatus = TaskStatus.UNCOMPLETED;
+ this.deadline = deadline;
+ this.priority = Priority.UNASSIGNED;
+ }
+
+ /**
+ * Overloaded constructor where every field must be present and not null. Priority here is default to unassigned.
+ */
+ public Task(Title title, Description description, Deadline deadline, TaskStatus taskStatus) {
+ requireAllNonNull(title, description, deadline, taskStatus);
+ this.title = title;
+ this.description = description;
+ this.taskStatus = taskStatus;
+ this.deadline = deadline;
+ this.priority = Priority.UNASSIGNED;
+ }
+
+ /**
+ * Overloaded constructor where every field must be present and not null.
+ * Overloaded constructor where every field must be present and not null. Status set to default of UNCOMPLETED
+ */
+ public Task(Title title, Description description, Deadline deadline, TaskStatus taskStatus, Priority priority) {
+ requireAllNonNull(title, description, deadline, taskStatus, priority);
+ this.title = title;
+ this.description = description;
+ this.taskStatus = taskStatus;
+ this.deadline = deadline;
+ this.priority = priority;
+ }
+
+ /**
+ * Overloaded constructor where every field must be present and not null
+ */
+ public Task(Title title, Description description, Deadline deadline, TaskStatus taskStatus,
+ Priority priority, Set assignees) {
+ requireAllNonNull(title, description, deadline, taskStatus, priority);
+ this.title = title;
+ this.description = description;
+ this.taskStatus = taskStatus;
+ this.deadline = deadline;
+ this.priority = priority;
+ this.assignees.addAll(assignees);
+ }
+
+ public Title getTitle() {
+ return title;
+ }
+
+ public Description getDescription() {
+ return description;
+ }
+
+ public TaskStatus getTaskStatus() {
+ return taskStatus;
+ }
+
+ public Deadline getDeadline() {
+ return deadline;
+ }
+
+ public Priority getPriority() {
+ return this.priority;
+ }
+
+ public Set getAssignees() {
+ return Collections.unmodifiableSet(assignees);
+ }
+
+ public boolean hasAssignee(Assignee assignee) {
+ return assignees.contains(assignee);
+ }
+
+ /**
+ * Returns true if the set of assignees to this task is not empty.
+ * Returns false if the set of assignees to this task is empty.
+ *
+ * @return a boolean value.
+ */
+ public boolean hasAnyAssignees() {
+ if (assignees.isEmpty()) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Returns an updated task with the assignee specified removed from the set of
+ * assignees to this task.
+ *
+ * @param assignee that is about to be removed.
+ * @return Task that is updated without the specified assignee.
+ */
+ public Task removeAssignee(Assignee assignee) {
+ Set copyAssignees = new HashSet<>();
+ copyAssignees.addAll(this.assignees);
+ copyAssignees.remove(assignee);
+
+ return new Task(title, description, deadline, taskStatus, priority, copyAssignees);
+ }
+
+ /**
+ * Returns an updated task with {@code assignee} edited from the set of assignees to this task.
+ *
+ * @param targetAssignee Assignee that is to be edited.
+ * @param editedAssignee Edited assignee.
+ * @return Task that is updated with the edited assignee.
+ */
+ public Task editAssignee(Assignee targetAssignee, Assignee editedAssignee) {
+ Set newAssignees = new HashSet<>(this.assignees);
+ newAssignees.remove(targetAssignee);
+ newAssignees.add(editedAssignee);
+
+ return new Task(title, description, deadline, taskStatus, priority, newAssignees);
+ }
+
+ public boolean isUnassigned() {
+ return assignees.isEmpty();
+ }
+
+ public boolean isUncompleted() {
+ return this.taskStatus.equals(TaskStatus.UNCOMPLETED);
+ }
+
+ /**
+ * Returns true if both tasks have the same title.
+ * This defines a weaker notion of equality between two tasks.
+ */
+ public boolean isSameTask(Task otherTask) {
+ if (otherTask == this) {
+ return true;
+ }
+
+ return otherTask != null
+ && otherTask.getTitle().equals(getTitle());
+ }
+
+ /**
+ * Returns true if both tasks have the same identity and data fields.
+ * This defines a stronger notion of equality between two tasks.
+ */
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ }
+
+ if (!(other instanceof Task)) {
+ return false;
+ }
+
+ Task otherTask = (Task) other;
+ return otherTask.getTitle().equals(getTitle())
+ && otherTask.getDescription().equals(getDescription())
+ && otherTask.getDeadline().equals(getDeadline());
+ }
+
+ @Override
+ public int hashCode() {
+ // use this method for custom fields hashing instead of implementing your own
+ return Objects.hash(title, description, deadline);
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append(getTitle())
+ .append("; Description: ")
+ .append(getDescription())
+ .append("; Deadline: ")
+ .append(getDeadline())
+ .append("; Task Status: ")
+ .append(getTaskStatus())
+ .append("; Priority: ")
+ .append(getPriority());
+
+ Set assignees = getAssignees();
+ if (!assignees.isEmpty()) {
+ builder.append("; Assignees: ");
+ assignees.forEach(builder::append);
+ }
+
+ return builder.toString();
+ }
+}
diff --git a/src/main/java/seedu/heymatez/model/task/TaskContainsAssigneePredicate.java b/src/main/java/seedu/heymatez/model/task/TaskContainsAssigneePredicate.java
new file mode 100644
index 00000000000..bc1387619bd
--- /dev/null
+++ b/src/main/java/seedu/heymatez/model/task/TaskContainsAssigneePredicate.java
@@ -0,0 +1,28 @@
+package seedu.heymatez.model.task;
+
+import java.util.function.Predicate;
+
+import seedu.heymatez.model.assignee.Assignee;
+
+/**
+ * Tests that a {@code Task}'s {@code Assignee} matches the keyword given.
+ */
+public class TaskContainsAssigneePredicate implements Predicate {
+ private final String keyword;
+
+ public TaskContainsAssigneePredicate(String keyword) {
+ this.keyword = keyword;
+ }
+
+ @Override
+ public boolean test(Task task) {
+ return task.hasAssignee(new Assignee(keyword));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof TaskContainsAssigneePredicate // instanceof handles nulls
+ && keyword.equals(((TaskContainsAssigneePredicate) other).keyword)); // state check
+ }
+}
diff --git a/src/main/java/seedu/heymatez/model/task/TaskContainsKeywordPredicate.java b/src/main/java/seedu/heymatez/model/task/TaskContainsKeywordPredicate.java
new file mode 100644
index 00000000000..083ff1c0425
--- /dev/null
+++ b/src/main/java/seedu/heymatez/model/task/TaskContainsKeywordPredicate.java
@@ -0,0 +1,35 @@
+package seedu.heymatez.model.task;
+
+import java.util.List;
+import java.util.function.Predicate;
+
+import seedu.heymatez.commons.util.StringUtil;
+
+/**
+ * Tests that a {@code Task}'s {@code Title} or {@code Description} matches any of the keywords given.
+ */
+public class TaskContainsKeywordPredicate implements Predicate {
+ private final List keywords;
+
+ public TaskContainsKeywordPredicate(List keywords) {
+ this.keywords = keywords;
+ }
+
+ @Override
+ public boolean test(Task task) {
+ boolean title = keywords.stream()
+ .anyMatch(keyword -> StringUtil.containsWordIgnoreCase(task.getTitle().taskTitle, keyword));
+
+ boolean description = keywords.stream()
+ .anyMatch(keyword -> StringUtil.containsWordIgnoreCase(task.getDescription().desc, keyword));
+
+ return title || description;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof TaskContainsKeywordPredicate // instanceof handles nulls
+ && keywords.equals(((TaskContainsKeywordPredicate) other).keywords)); // state check
+ }
+}
diff --git a/src/main/java/seedu/heymatez/model/task/TaskStatus.java b/src/main/java/seedu/heymatez/model/task/TaskStatus.java
new file mode 100644
index 00000000000..35db770a3c7
--- /dev/null
+++ b/src/main/java/seedu/heymatez/model/task/TaskStatus.java
@@ -0,0 +1,60 @@
+package seedu.heymatez.model.task;
+
+/**
+ * Enum for the Task status values.
+ * It is used to signify whether a task has been completed or uncompleted.
+ * Task Status can take on the values, UNCOMPLETED or COMPLETED.
+ * */
+public enum TaskStatus {
+ UNCOMPLETED("uncompleted"),
+ COMPLETED("completed");
+
+ public static final String MESSAGE_CONSTRAINTS = "Task Status should take one of the predefined values: completed "
+ + "or uncompleted (case-sensitive)";
+
+ public final String status;
+
+ TaskStatus(String status) {
+ this.status = status;
+ }
+
+ /**
+ * Returns a String value by of the Enum name to use for UI.
+ *
+ * @return a string value of the enum name to us for the UI
+ */
+ public static String getEnumName() {
+ return "Task Status";
+ }
+
+ /**
+ * Returns a boolean value by check if the String value is a
+ * value within this enum.
+ *
+ * @param value value for the Task Status enum
+ * @return a boolean value, whether the it is a value inside this enum
+ */
+ public static boolean isValidValue(String value) {
+ for (TaskStatus c : TaskStatus.values()) {
+ if (c.name().toLowerCase().equals(value)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns a string value of the TaskStatus casted to lower cast
+ *
+ * @return a string value representing the TaskStatus
+ */
+ public String getStatus() {
+ return this.status.toLowerCase();
+ }
+
+ @Override
+ public String toString() {
+ return this.status;
+ }
+}
diff --git a/src/main/java/seedu/heymatez/model/task/Title.java b/src/main/java/seedu/heymatez/model/task/Title.java
new file mode 100644
index 00000000000..2278172dd5f
--- /dev/null
+++ b/src/main/java/seedu/heymatez/model/task/Title.java
@@ -0,0 +1,57 @@
+package seedu.heymatez.model.task;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.heymatez.commons.util.AppUtil.checkArgument;
+
+/**
+ * Represents a Task's title in HEY MATEz.
+ */
+public class Title {
+ public static final String MESSAGE_CONSTRAINTS =
+ "Titles should only contain alphanumeric characters and spaces, and it should not be blank";
+
+ /*
+ * The first character of the title must not be a whitespace,
+ * otherwise " " (a blank string) becomes a valid input.
+ */
+ public static final String VALIDATION_REGEX = "[\\p{Alnum}][\\p{Alnum} ]*";
+
+ public final String taskTitle;
+
+ /**
+ * Constructs a {@code Title}.
+ *
+ * @param title A valid title.
+ */
+ public Title(String title) {
+ requireNonNull(title);
+ checkArgument(isValidTitle(title), MESSAGE_CONSTRAINTS);
+ taskTitle = title;
+ }
+
+ /**
+ * Returns true if a given string is a valid name.
+ *
+ * @return a boolean value
+ */
+ public static boolean isValidTitle(String test) {
+ return test.matches(VALIDATION_REGEX);
+ }
+
+ @Override
+ public String toString() {
+ return taskTitle;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof Title // instanceof handles nulls
+ && taskTitle.equals(((Title) other).taskTitle)); // state check
+ }
+
+ @Override
+ public int hashCode() {
+ return taskTitle.hashCode();
+ }
+}
diff --git a/src/main/java/seedu/heymatez/model/task/TitleContainsKeywordPredicate.java b/src/main/java/seedu/heymatez/model/task/TitleContainsKeywordPredicate.java
new file mode 100644
index 00000000000..f90cdbdcbb6
--- /dev/null
+++ b/src/main/java/seedu/heymatez/model/task/TitleContainsKeywordPredicate.java
@@ -0,0 +1,30 @@
+package seedu.heymatez.model.task;
+
+import java.util.List;
+import java.util.function.Predicate;
+
+import seedu.heymatez.commons.util.StringUtil;
+
+/**
+ * Tests that a {@code Task}'s {@code Title} matches any of the keywords given.
+ */
+public class TitleContainsKeywordPredicate implements Predicate {
+ private final List keywords;
+
+ public TitleContainsKeywordPredicate(List keywords) {
+ this.keywords = keywords;
+ }
+
+ @Override
+ public boolean test(Task task) {
+ return keywords.stream()
+ .anyMatch(keyword -> StringUtil.containsWordIgnoreCase(task.getTitle().taskTitle, keyword));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof TitleContainsKeywordPredicate // instanceof handles nulls
+ && keywords.equals(((TitleContainsKeywordPredicate) other).keywords)); // state check
+ }
+}
diff --git a/src/main/java/seedu/heymatez/model/task/UniqueTaskList.java b/src/main/java/seedu/heymatez/model/task/UniqueTaskList.java
new file mode 100644
index 00000000000..f6d080a0ac1
--- /dev/null
+++ b/src/main/java/seedu/heymatez/model/task/UniqueTaskList.java
@@ -0,0 +1,146 @@
+package seedu.heymatez.model.task;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.heymatez.commons.util.CollectionUtil.requireAllNonNull;
+
+import java.util.Iterator;
+import java.util.List;
+
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
+import seedu.heymatez.model.assignee.Assignee;
+import seedu.heymatez.model.person.Name;
+import seedu.heymatez.model.task.exceptions.TaskNotFoundException;
+
+/**
+ * A list of task that enforces uniqueness between its elements and does not allow nulls.
+ * A Task is considered unique by comparing using {@code Task#isSameTask(Task)}. As such, adding and updating of
+ * persons uses Task#isSameTask) for equality so as to ensure that the Task being added or updated is
+ * unique in terms of identity in the UniqueTaskList. However, the removal of a task uses Task#equals(Object) so
+ * as to ensure that the Task with exactly the same fields will be removed.
+ *
+ * Supports a minimal set of list operations.
+ *
+ * @see Task#isSameTask(Task)
+ */
+public class UniqueTaskList implements Iterable {
+ private final ObservableList internalList = FXCollections.observableArrayList();
+ private final ObservableList internalUnmodifiableList =
+ FXCollections.unmodifiableObservableList(internalList);
+
+ /**
+ * Returns true if the list contains an equivalent task as the given argument.
+ */
+ public boolean contains(Task toCheck) {
+ requireNonNull(toCheck);
+ return internalList.stream().anyMatch(toCheck::isSameTask);
+ }
+
+ /**
+ * Adds a task to the list.
+ * Task may be a duplicate.
+ */
+ public void addTask(Task toAdd) {
+ requireNonNull(toAdd);
+ internalList.add(toAdd);
+ }
+
+ /**
+ * Replaces the task {@code target} in the list with {@code editedTask}.
+ * {@code target} must exist in the list.
+ */
+ public void setTask(Task target, Task editedTask) {
+ requireAllNonNull(target, editedTask);
+
+ int index = internalList.indexOf(target);
+ if (index == -1) {
+ throw new TaskNotFoundException();
+ }
+ internalList.set(index, editedTask);
+ }
+
+ public void setTasks(UniqueTaskList replacement) {
+ requireNonNull(replacement);
+ internalList.setAll(replacement.internalList);
+ }
+
+ /**
+ * Replaces the contents of this list with {@code tasks}.
+ * {@code tasks} may contain duplicate tasks.
+ */
+ public void setTasks(List tasks) {
+ requireAllNonNull(tasks);
+
+ internalList.setAll(tasks);
+ }
+
+ /**
+ * Removes the equivalent task from the list.
+ * The task must exist in the list.
+ */
+ public void remove(Task toRemove) {
+ requireNonNull(toRemove);
+ if (!internalList.remove(toRemove)) {
+ throw new TaskNotFoundException();
+ }
+ }
+
+ /**
+ * Removes the Assignees from tasks in the current task list
+ */
+ public void removeAssignee(Name name) {
+ requireNonNull(name);
+ Assignee assignee = new Assignee(name.fullName);
+
+ for (int i = 0; i < internalList.size(); i++) {
+ Task task = internalList.get(i);
+ if (task.hasAssignee(assignee)) {
+ Task updated = task.removeAssignee(assignee);
+ internalList.set(i, updated);
+ }
+ }
+
+ }
+
+ /**
+ * Replaces the given Assignee {@code targetName} with {@code editedName} in tasks from the task list.
+ */
+ public void editAssignee(Name targetName, Name editedName) {
+ requireAllNonNull(targetName, editedName);
+ Assignee targetAssignee = new Assignee(targetName.fullName);
+ Assignee editedAssignee = new Assignee(editedName.fullName);
+
+ for (int i = 0; i < internalList.size(); i++) {
+ Task task = internalList.get(i);
+
+ if (task.hasAssignee(targetAssignee)) {
+ Task updatedTask = task.editAssignee(targetAssignee, editedAssignee);
+ internalList.set(i, updatedTask);
+ }
+ }
+ }
+
+ /**
+ * Returns the backing list as an unmodifiable {@code ObservableList}.
+ */
+ public ObservableList asUnmodifiableObservableList() {
+ return internalUnmodifiableList;
+ }
+
+ @Override
+ public Iterator iterator() {
+ return internalList.iterator();
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof UniqueTaskList // instanceof handles nulls
+ && internalList.equals(((UniqueTaskList) other).internalList));
+ }
+
+ @Override
+ public int hashCode() {
+ return internalList.hashCode();
+ }
+}
diff --git a/src/main/java/seedu/heymatez/model/task/exceptions/TaskNotFoundException.java b/src/main/java/seedu/heymatez/model/task/exceptions/TaskNotFoundException.java
new file mode 100644
index 00000000000..3ac2e1f76a8
--- /dev/null
+++ b/src/main/java/seedu/heymatez/model/task/exceptions/TaskNotFoundException.java
@@ -0,0 +1,6 @@
+package seedu.heymatez.model.task.exceptions;
+
+/**
+ * Signals that the operation is unable to find the specified task.
+ */
+public class TaskNotFoundException extends RuntimeException {}
diff --git a/src/main/java/seedu/heymatez/model/util/SampleDataUtil.java b/src/main/java/seedu/heymatez/model/util/SampleDataUtil.java
new file mode 100644
index 00000000000..9030ecd7c3d
--- /dev/null
+++ b/src/main/java/seedu/heymatez/model/util/SampleDataUtil.java
@@ -0,0 +1,91 @@
+package seedu.heymatez.model.util;
+
+import java.util.Arrays;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import seedu.heymatez.model.HeyMatez;
+import seedu.heymatez.model.ReadOnlyHeyMatez;
+import seedu.heymatez.model.assignee.Assignee;
+import seedu.heymatez.model.person.Email;
+import seedu.heymatez.model.person.Name;
+import seedu.heymatez.model.person.Person;
+import seedu.heymatez.model.person.Phone;
+import seedu.heymatez.model.person.Role;
+import seedu.heymatez.model.task.Deadline;
+import seedu.heymatez.model.task.Description;
+import seedu.heymatez.model.task.Priority;
+import seedu.heymatez.model.task.Task;
+import seedu.heymatez.model.task.TaskStatus;
+import seedu.heymatez.model.task.Title;
+
+/**
+ * Contains utility methods for populating {@code HeyMatez} with sample data.
+ */
+public class SampleDataUtil {
+ public static Person[] getSamplePersons() {
+ return new Person[] {
+ new Person(new Name("Alex Yeoh"), new Phone("87438807"), new Email("alexyeoh@example.com"),
+ new Role("Member")),
+ new Person(new Name("Bernice Yu"), new Phone("99272758"), new Email("berniceyu@example.com"),
+ new Role("Member")),
+ new Person(new Name("Charlotte Oliveiro"), new Phone("93210283"), new Email("charlotte@example.com"),
+ new Role("Member")),
+ new Person(new Name("David Li"), new Phone("91031282"), new Email("lidavid@example.com"),
+ new Role("Member")),
+ new Person(new Name("Irfan Ibrahim"), new Phone("92492021"), new Email("irfan@example.com"),
+ new Role("Member")),
+ new Person(new Name("Roy Balakrishnan"), new Phone("92624417"), new Email("royb@example.com"),
+ new Role("Member")),
+ };
+ }
+
+ public static Task[] getSampleTasks() {
+ return new Task[] {
+ new Task(new Title("End of Year Club Performance Review"),
+ new Description("End of Year Club Performance Review with the other EXCO member"),
+ new Deadline("2020-12-13"), TaskStatus.valueOf("COMPLETED"), Priority.valueOf("MEDIUM"),
+ getAssigneeSet("Alex Yeoh")),
+ new Task(new Title("Meeting with EXCO"), new Description("Meeting to discuss about club budget"),
+ new Deadline("2021-04-01"), TaskStatus.valueOf("UNCOMPLETED"), Priority.valueOf("HIGH"),
+ getAssigneeSet("Bernice Yu")),
+ new Task(new Title("Meeting with MINDS stakeholders"),
+ new Description("Meeting with stakeholders to discuss about planning of charity event"),
+ new Deadline("2021-02-23"), TaskStatus.valueOf("COMPLETED"), Priority.valueOf("MEDIUM"),
+ getAssigneeSet("Alex Yeoh")),
+ new Task(new Title("Cohesion Planning"),
+ new Description("Plan for Club cohesion. Decide on logistic and games"),
+ new Deadline("2021-08-30"), TaskStatus.valueOf("UNCOMPLETED"), Priority.valueOf("LOW"),
+ getAssigneeSet("Alex Yeoh")),
+ new Task(new Title("Buy materials for upcoming Cohesion"),
+ new Description("Buy N95 masks, alcohol wipes for participants to use"),
+ new Deadline("2021-05-15"), TaskStatus.valueOf("UNCOMPLETED"), Priority.valueOf("UNASSIGNED"),
+ getAssigneeSet("Bernice Yu")),
+ new Task(new Title("NUSSU Hackathon"),
+ new Description("Hackathon event day"),
+ new Deadline("2021-09-01"), TaskStatus.valueOf("UNCOMPLETED"), Priority.valueOf("HIGH"),
+ getAssigneeSet("Bernice Yu")),
+ };
+ }
+
+ public static ReadOnlyHeyMatez getSampleHeyMatez() {
+ HeyMatez sampleHm = new HeyMatez();
+ for (Person samplePerson : getSamplePersons()) {
+ sampleHm.addPerson(samplePerson);
+ }
+
+ for (Task sampleTask : getSampleTasks()) {
+ sampleHm.addTask(sampleTask);
+ }
+ return sampleHm;
+ }
+
+ /**
+ * Returns an assignee set containing the list of strings given.
+ */
+ public static Set getAssigneeSet(String... strings) {
+ return Arrays.stream(strings)
+ .map(Assignee::new)
+ .collect(Collectors.toSet());
+ }
+}
diff --git a/src/main/java/seedu/heymatez/storage/HeyMatezStorage.java b/src/main/java/seedu/heymatez/storage/HeyMatezStorage.java
new file mode 100644
index 00000000000..f88747ef7e0
--- /dev/null
+++ b/src/main/java/seedu/heymatez/storage/HeyMatezStorage.java
@@ -0,0 +1,45 @@
+package seedu.heymatez.storage;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.Optional;
+
+import seedu.heymatez.commons.exceptions.DataConversionException;
+import seedu.heymatez.model.HeyMatez;
+import seedu.heymatez.model.ReadOnlyHeyMatez;
+
+/**
+ * Represents a storage for {@link HeyMatez}.
+ */
+public interface HeyMatezStorage {
+
+ /**
+ * Returns the file path of the data file.
+ */
+ Path getHeyMatezFilePath();
+
+ /**
+ * Returns HeyMatez data as a {@link ReadOnlyHeyMatez}.
+ * Returns {@code Optional.empty()} if storage file is not found.
+ * @throws DataConversionException if the data in storage is not in the expected format.
+ * @throws IOException if there was any problem when reading from the storage.
+ */
+ Optional readHeyMatez() throws DataConversionException, IOException;
+
+ /**
+ * @see #getHeyMatezFilePath()
+ */
+ Optional readHeyMatez(Path filePath) throws DataConversionException, IOException;
+
+ /**
+ * Saves the given {@link ReadOnlyHeyMatez} to the storage.
+ * @param heyMatez cannot be null.
+ * @throws IOException if there was any problem writing to the file.
+ */
+ void saveHeyMatez(ReadOnlyHeyMatez heyMatez) throws IOException;
+
+ /**
+ * @see #saveHeyMatez(ReadOnlyHeyMatez)
+ */
+ void saveHeyMatez(ReadOnlyHeyMatez heyMatez, Path filePath) throws IOException;
+}
diff --git a/src/main/java/seedu/heymatez/storage/JsonAdaptedAssignee.java b/src/main/java/seedu/heymatez/storage/JsonAdaptedAssignee.java
new file mode 100644
index 00000000000..331ee4184e3
--- /dev/null
+++ b/src/main/java/seedu/heymatez/storage/JsonAdaptedAssignee.java
@@ -0,0 +1,47 @@
+package seedu.heymatez.storage;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonValue;
+
+import seedu.heymatez.commons.exceptions.IllegalValueException;
+import seedu.heymatez.model.assignee.Assignee;
+
+/**
+ * Jackson-friendly version of {@link Assignee}.
+ */
+class JsonAdaptedAssignee {
+
+ private final String assigneeName;
+
+ /**
+ * Constructs a {@code JsonAdaptedAssignee} with the given {@code assigneeName}.
+ */
+ @JsonCreator
+ public JsonAdaptedAssignee(String assigneeName) {
+ this.assigneeName = assigneeName;
+ }
+
+ /**
+ * Converts a given {@code Assignee} into this class for Jackson use.
+ */
+ public JsonAdaptedAssignee(Assignee source) {
+ assigneeName = source.assigneeName;
+ }
+
+ @JsonValue
+ public String getAssigneeName() {
+ return assigneeName;
+ }
+
+ /**
+ * Converts this Jackson-friendly adapted assignee object into the model's {@code Assignee} object.
+ *
+ * @throws IllegalValueException if there were any data constraints violated in the adapted assignee.
+ */
+ public Assignee toModelType() throws IllegalValueException {
+ if (!Assignee.isValidAssigneeName(assigneeName)) {
+ throw new IllegalValueException(Assignee.MESSAGE_CONSTRAINTS);
+ }
+ return new Assignee(assigneeName);
+ }
+}
diff --git a/src/main/java/seedu/address/storage/JsonAdaptedPerson.java b/src/main/java/seedu/heymatez/storage/JsonAdaptedPerson.java
similarity index 60%
rename from src/main/java/seedu/address/storage/JsonAdaptedPerson.java
rename to src/main/java/seedu/heymatez/storage/JsonAdaptedPerson.java
index a6321cec2ea..c97c0ee3e5c 100644
--- a/src/main/java/seedu/address/storage/JsonAdaptedPerson.java
+++ b/src/main/java/seedu/heymatez/storage/JsonAdaptedPerson.java
@@ -1,62 +1,49 @@
-package seedu.address.storage;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.stream.Collectors;
+package seedu.heymatez.storage;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
-import seedu.address.commons.exceptions.IllegalValueException;
-import seedu.address.model.person.Address;
-import seedu.address.model.person.Email;
-import seedu.address.model.person.Name;
-import seedu.address.model.person.Person;
-import seedu.address.model.person.Phone;
-import seedu.address.model.tag.Tag;
+import seedu.heymatez.commons.exceptions.IllegalValueException;
+import seedu.heymatez.model.person.Email;
+import seedu.heymatez.model.person.Name;
+import seedu.heymatez.model.person.Person;
+import seedu.heymatez.model.person.Phone;
+import seedu.heymatez.model.person.Role;
/**
* Jackson-friendly version of {@link Person}.
*/
class JsonAdaptedPerson {
- public static final String MISSING_FIELD_MESSAGE_FORMAT = "Person's %s field is missing!";
+ public static final String MISSING_FIELD_MESSAGE_FORMAT = "Member's %s field is missing!";
private final String name;
private final String phone;
private final String email;
- private final String address;
- private final List tagged = new ArrayList<>();
+ private final String role;
/**
* Constructs a {@code JsonAdaptedPerson} with the given person details.
*/
@JsonCreator
public JsonAdaptedPerson(@JsonProperty("name") String name, @JsonProperty("phone") String phone,
- @JsonProperty("email") String email, @JsonProperty("address") String address,
- @JsonProperty("tagged") List tagged) {
+ @JsonProperty("email") String email, @JsonProperty("role") String role) {
this.name = name;
this.phone = phone;
this.email = email;
- this.address = address;
- if (tagged != null) {
- this.tagged.addAll(tagged);
- }
+ this.role = role;
}
/**
* Converts a given {@code Person} into this class for Jackson use.
*/
public JsonAdaptedPerson(Person source) {
+ assert source != null : "person source should not be null";
+
name = source.getName().fullName;
phone = source.getPhone().value;
email = source.getEmail().value;
- address = source.getAddress().value;
- tagged.addAll(source.getTags().stream()
- .map(JsonAdaptedTag::new)
- .collect(Collectors.toList()));
+ role = source.getRole().memberRole;
}
/**
@@ -65,10 +52,6 @@ public JsonAdaptedPerson(Person source) {
* @throws IllegalValueException if there were any data constraints violated in the adapted person.
*/
public Person toModelType() throws IllegalValueException {
- final List personTags = new ArrayList<>();
- for (JsonAdaptedTag tag : tagged) {
- personTags.add(tag.toModelType());
- }
if (name == null) {
throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Name.class.getSimpleName()));
@@ -94,16 +77,14 @@ public Person toModelType() throws IllegalValueException {
}
final Email modelEmail = new Email(email);
- if (address == null) {
- throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Address.class.getSimpleName()));
+ if (role == null) {
+ throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Role.class.getSimpleName()));
}
- if (!Address.isValidAddress(address)) {
- throw new IllegalValueException(Address.MESSAGE_CONSTRAINTS);
+ if (!Role.isValidRole(role)) {
+ throw new IllegalValueException(Role.MESSAGE_CONSTRAINTS);
}
- final Address modelAddress = new Address(address);
+ final Role modelRole = new Role(role);
- final Set modelTags = new HashSet<>(personTags);
- return new Person(modelName, modelPhone, modelEmail, modelAddress, modelTags);
+ return new Person(modelName, modelPhone, modelEmail, modelRole);
}
-
}
diff --git a/src/main/java/seedu/heymatez/storage/JsonAdaptedTask.java b/src/main/java/seedu/heymatez/storage/JsonAdaptedTask.java
new file mode 100644
index 00000000000..3c0242e2b1b
--- /dev/null
+++ b/src/main/java/seedu/heymatez/storage/JsonAdaptedTask.java
@@ -0,0 +1,127 @@
+package seedu.heymatez.storage;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import seedu.heymatez.commons.exceptions.IllegalValueException;
+import seedu.heymatez.model.assignee.Assignee;
+import seedu.heymatez.model.task.Deadline;
+import seedu.heymatez.model.task.Description;
+import seedu.heymatez.model.task.Priority;
+import seedu.heymatez.model.task.Task;
+import seedu.heymatez.model.task.TaskStatus;
+import seedu.heymatez.model.task.Title;
+
+/**
+ * Jackson-friendly version of {@link Task}.
+ */
+public class JsonAdaptedTask {
+ public static final String MISSING_FIELD_MESSAGE_FORMAT = "Task's %s field is missing!";
+
+ private final String title;
+ private final String description;
+ private final String status;
+ private final String deadline;
+ private final String priority;
+ private final List assignee = new ArrayList<>();
+
+ /**
+ * Constructs a {@code JsonAdaptedtask} with the given task details.
+ */
+ @JsonCreator
+ public JsonAdaptedTask(@JsonProperty("title") String title, @JsonProperty("description") String description,
+ @JsonProperty("deadline") String deadline, @JsonProperty("status") String status,
+ @JsonProperty("priority") String priority,
+ @JsonProperty("assignee") List assignee) {
+ this.title = title;
+ this.description = description;
+ this.deadline = deadline;
+ this.status = status;
+ this.priority = priority;
+ if (assignee != null) {
+ this.assignee.addAll(assignee);
+ }
+ }
+
+ /**
+ * Converts a given {@code Task} into this class for Jackson use.
+ */
+ public JsonAdaptedTask(Task source) {
+ assert source != null;
+ title = source.getTitle().taskTitle;
+ description = source.getDescription().desc;
+ deadline = source.getDeadline().getUnformattedDate();
+ status = source.getTaskStatus().getStatus();
+ priority = source.getPriority().getPriority();
+ assignee.addAll(source.getAssignees().stream()
+ .map(JsonAdaptedAssignee::new)
+ .collect(Collectors.toList()));
+ }
+
+ /**
+ * Converts this Jackson-friendly adapted task object into the model's {@code Task} object.
+ *
+ * @throws IllegalValueException if there were any data constraints violated in the adapted task.
+ */
+ public Task toModelType() throws IllegalValueException {
+ final List personAssignees = new ArrayList<>();
+ for (JsonAdaptedAssignee currentAssignee : assignee) {
+ personAssignees.add(currentAssignee.toModelType());
+ }
+
+ if (title == null) {
+ throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Title.class.getSimpleName()));
+ }
+ if (!Title.isValidTitle(title)) {
+ throw new IllegalValueException(Title.MESSAGE_CONSTRAINTS);
+ }
+ final Title modelTitle = new Title(title);
+
+ if (description == null) {
+ throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT,
+ Description.class.getSimpleName()));
+ }
+ if (!Description.isValidDescription(description)) {
+ throw new IllegalValueException(Description.MESSAGE_CONSTRAINTS);
+ }
+ final Description modelDescription = new Description(description);
+
+ if (deadline == null) {
+ throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT,
+ Deadline.class.getSimpleName()));
+ }
+ if (!Deadline.isValidDeadline(deadline)) {
+ throw new IllegalValueException(Deadline.MESSAGE_CONSTRAINTS);
+ }
+ final Deadline modelDeadline = new Deadline(deadline);
+
+ if (status == null) {
+ throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT,
+ TaskStatus.getEnumName()));
+ }
+ if (!TaskStatus.isValidValue(status)) {
+ throw new IllegalValueException(TaskStatus.MESSAGE_CONSTRAINTS);
+ }
+
+ final TaskStatus modelTaskStatus = TaskStatus.valueOf(status.toUpperCase());
+
+ if (priority == null) {
+ throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT,
+ Priority.getEnumName()));
+ }
+ if (!Priority.isValidValue(priority)) {
+ throw new IllegalValueException(Priority.MESSAGE_CONSTRAINTS);
+ }
+
+ final Priority modelPriority = Priority.valueOf(priority.toUpperCase());
+
+ final Set modelAssignees = new HashSet<>(personAssignees);
+ return new Task(modelTitle, modelDescription, modelDeadline, modelTaskStatus, modelPriority, modelAssignees);
+ }
+}
diff --git a/src/main/java/seedu/heymatez/storage/JsonHeyMatezStorage.java b/src/main/java/seedu/heymatez/storage/JsonHeyMatezStorage.java
new file mode 100644
index 00000000000..aabb05e09cc
--- /dev/null
+++ b/src/main/java/seedu/heymatez/storage/JsonHeyMatezStorage.java
@@ -0,0 +1,80 @@
+package seedu.heymatez.storage;
+
+import static java.util.Objects.requireNonNull;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.Optional;
+import java.util.logging.Logger;
+
+import seedu.heymatez.commons.core.LogsCenter;
+import seedu.heymatez.commons.exceptions.DataConversionException;
+import seedu.heymatez.commons.exceptions.IllegalValueException;
+import seedu.heymatez.commons.util.FileUtil;
+import seedu.heymatez.commons.util.JsonUtil;
+import seedu.heymatez.model.ReadOnlyHeyMatez;
+
+/**
+ * A class to access HeyMatez data stored as a json file on the hard disk.
+ */
+public class JsonHeyMatezStorage implements HeyMatezStorage {
+
+ private static final Logger logger = LogsCenter.getLogger(JsonHeyMatezStorage.class);
+
+ private Path filePath;
+
+ public JsonHeyMatezStorage(Path filePath) {
+ this.filePath = filePath;
+ }
+
+ public Path getHeyMatezFilePath() {
+ return filePath;
+ }
+
+ @Override
+ public Optional readHeyMatez() throws DataConversionException {
+ return readHeyMatez(filePath);
+ }
+
+ /**
+ * Similar to {@link #readHeyMatez()}.
+ *
+ * @param filePath location of the data. Cannot be null.
+ * @throws DataConversionException if the file is not in the correct format.
+ */
+ public Optional readHeyMatez(Path filePath) throws DataConversionException {
+ requireNonNull(filePath);
+
+ Optional jsonHeyMatez = JsonUtil.readJsonFile(
+ filePath, JsonSerializableHeyMatez.class);
+ if (!jsonHeyMatez.isPresent()) {
+ return Optional.empty();
+ }
+
+ try {
+ return Optional.of(jsonHeyMatez.get().toModelType());
+ } catch (IllegalValueException ive) {
+ logger.info("Illegal values found in " + filePath + ": " + ive.getMessage());
+ throw new DataConversionException(ive);
+ }
+ }
+
+ @Override
+ public void saveHeyMatez(ReadOnlyHeyMatez heyMatez) throws IOException {
+ saveHeyMatez(heyMatez, filePath);
+ }
+
+ /**
+ * Similar to {@link #saveHeyMatez(ReadOnlyHeyMatez)}.
+ *
+ * @param filePath location of the data. Cannot be null.
+ */
+ public void saveHeyMatez(ReadOnlyHeyMatez heyMatez, Path filePath) throws IOException {
+ requireNonNull(heyMatez);
+ requireNonNull(filePath);
+
+ FileUtil.createIfMissing(filePath);
+ JsonUtil.saveJsonFile(new JsonSerializableHeyMatez(heyMatez), filePath);
+ }
+
+}
diff --git a/src/main/java/seedu/heymatez/storage/JsonSerializableHeyMatez.java b/src/main/java/seedu/heymatez/storage/JsonSerializableHeyMatez.java
new file mode 100644
index 00000000000..c350da737f1
--- /dev/null
+++ b/src/main/java/seedu/heymatez/storage/JsonSerializableHeyMatez.java
@@ -0,0 +1,83 @@
+package seedu.heymatez.storage;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonRootName;
+
+import seedu.heymatez.commons.exceptions.IllegalValueException;
+import seedu.heymatez.model.HeyMatez;
+import seedu.heymatez.model.ReadOnlyHeyMatez;
+import seedu.heymatez.model.assignee.Assignee;
+import seedu.heymatez.model.person.Name;
+import seedu.heymatez.model.person.Person;
+import seedu.heymatez.model.task.Task;
+
+/**
+ * An Immutable HeyMatez that is serializable to JSON format.
+ */
+@JsonRootName(value = "heymatez")
+class JsonSerializableHeyMatez {
+
+ public static final String MESSAGE_DUPLICATE_PERSON = "Persons list contains duplicate person(s).";
+
+ private final List persons = new ArrayList<>();
+ private final List tasks = new ArrayList<>();
+
+ /**
+ * Constructs a {@code JsonSerializableHeyMatez} with the given persons.
+ */
+ @JsonCreator
+ public JsonSerializableHeyMatez(@JsonProperty("persons") List persons,
+ @JsonProperty("tasks") List tasks) {
+ this.persons.addAll(persons);
+ this.tasks.addAll(tasks);
+ }
+
+ /**
+ * Converts a given {@code ReadOnlyHeyMatez} into this class for Jackson use.
+ *
+ * @param source future changes to this will not affect the created {@code JsonSerializableHeyMatez}.
+ */
+ public JsonSerializableHeyMatez(ReadOnlyHeyMatez source) {
+ persons.addAll(source.getPersonList().stream().map(JsonAdaptedPerson::new).collect(Collectors.toList()));
+ tasks.addAll(source.getTaskList().stream().map(JsonAdaptedTask::new).collect(Collectors.toList()));
+ }
+
+ /**
+ * Converts HeyMatez into the model's {@code HeyMatez} object.
+ *
+ * @throws IllegalValueException if there were any data constraints violated.
+ */
+ public HeyMatez toModelType() throws IllegalValueException {
+ HeyMatez heyMatez = new HeyMatez();
+
+ for (JsonAdaptedPerson jsonAdaptedPerson : persons) {
+ Person person = jsonAdaptedPerson.toModelType();
+ if (heyMatez.hasPerson(person)) {
+ throw new IllegalValueException(MESSAGE_DUPLICATE_PERSON);
+ }
+ heyMatez.addPerson(person);
+ }
+
+ for (JsonAdaptedTask jsonAdaptedTask : tasks) {
+ Task task = jsonAdaptedTask.toModelType();
+
+ for (Assignee assignee : task.getAssignees()) {
+
+ Person person = new Person(new Name(assignee.assigneeName));
+ if (!heyMatez.hasPerson(person)) {
+ throw new IllegalValueException("No such member in the displayed member's list!");
+ }
+ }
+
+ heyMatez.addTask(task);
+ }
+
+ return heyMatez;
+ }
+
+}
diff --git a/src/main/java/seedu/address/storage/JsonUserPrefsStorage.java b/src/main/java/seedu/heymatez/storage/JsonUserPrefsStorage.java
similarity index 82%
rename from src/main/java/seedu/address/storage/JsonUserPrefsStorage.java
rename to src/main/java/seedu/heymatez/storage/JsonUserPrefsStorage.java
index bc2bbad84aa..dab8b95ebfd 100644
--- a/src/main/java/seedu/address/storage/JsonUserPrefsStorage.java
+++ b/src/main/java/seedu/heymatez/storage/JsonUserPrefsStorage.java
@@ -1,13 +1,13 @@
-package seedu.address.storage;
+package seedu.heymatez.storage;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Optional;
-import seedu.address.commons.exceptions.DataConversionException;
-import seedu.address.commons.util.JsonUtil;
-import seedu.address.model.ReadOnlyUserPrefs;
-import seedu.address.model.UserPrefs;
+import seedu.heymatez.commons.exceptions.DataConversionException;
+import seedu.heymatez.commons.util.JsonUtil;
+import seedu.heymatez.model.ReadOnlyUserPrefs;
+import seedu.heymatez.model.UserPrefs;
/**
* A class to access UserPrefs stored in the hard disk as a json file
diff --git a/src/main/java/seedu/heymatez/storage/Storage.java b/src/main/java/seedu/heymatez/storage/Storage.java
new file mode 100644
index 00000000000..dd56f42aceb
--- /dev/null
+++ b/src/main/java/seedu/heymatez/storage/Storage.java
@@ -0,0 +1,32 @@
+package seedu.heymatez.storage;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.Optional;
+
+import seedu.heymatez.commons.exceptions.DataConversionException;
+import seedu.heymatez.model.ReadOnlyHeyMatez;
+import seedu.heymatez.model.ReadOnlyUserPrefs;
+import seedu.heymatez.model.UserPrefs;
+
+/**
+ * API of the Storage component
+ */
+public interface Storage extends HeyMatezStorage, UserPrefsStorage {
+
+ @Override
+ Optional readUserPrefs() throws DataConversionException, IOException;
+
+ @Override
+ void saveUserPrefs(ReadOnlyUserPrefs userPrefs) throws IOException;
+
+ @Override
+ Path getHeyMatezFilePath();
+
+ @Override
+ Optional readHeyMatez() throws DataConversionException, IOException;
+
+ @Override
+ void saveHeyMatez(ReadOnlyHeyMatez heyMatez) throws IOException;
+
+}
diff --git a/src/main/java/seedu/heymatez/storage/StorageManager.java b/src/main/java/seedu/heymatez/storage/StorageManager.java
new file mode 100644
index 00000000000..a1b357f8568
--- /dev/null
+++ b/src/main/java/seedu/heymatez/storage/StorageManager.java
@@ -0,0 +1,78 @@
+package seedu.heymatez.storage;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.Optional;
+import java.util.logging.Logger;
+
+import seedu.heymatez.commons.core.LogsCenter;
+import seedu.heymatez.commons.exceptions.DataConversionException;
+import seedu.heymatez.model.ReadOnlyHeyMatez;
+import seedu.heymatez.model.ReadOnlyUserPrefs;
+import seedu.heymatez.model.UserPrefs;
+
+/**
+ * Manages storage of HeyMatez data in local storage.
+ */
+public class StorageManager implements Storage {
+
+ private static final Logger logger = LogsCenter.getLogger(StorageManager.class);
+ private HeyMatezStorage heyMatezStorage;
+ private UserPrefsStorage userPrefsStorage;
+
+ /**
+ * Creates a {@code StorageManager} with the given {@code HeyMatezStorage} and {@code UserPrefStorage}.
+ */
+ public StorageManager(HeyMatezStorage heyMatezStorage, UserPrefsStorage userPrefsStorage) {
+ super();
+ this.heyMatezStorage = heyMatezStorage;
+ this.userPrefsStorage = userPrefsStorage;
+ }
+
+ // ================ UserPrefs methods ==============================
+
+ @Override
+ public Path getUserPrefsFilePath() {
+ return userPrefsStorage.getUserPrefsFilePath();
+ }
+
+ @Override
+ public Optional readUserPrefs() throws DataConversionException, IOException {
+ return userPrefsStorage.readUserPrefs();
+ }
+
+ @Override
+ public void saveUserPrefs(ReadOnlyUserPrefs userPrefs) throws IOException {
+ userPrefsStorage.saveUserPrefs(userPrefs);
+ }
+
+
+ // ================ HeyMatez methods ==============================
+
+ @Override
+ public Path getHeyMatezFilePath() {
+ return heyMatezStorage.getHeyMatezFilePath();
+ }
+
+ @Override
+ public Optional readHeyMatez() throws DataConversionException, IOException {
+ return readHeyMatez(heyMatezStorage.getHeyMatezFilePath());
+ }
+
+ @Override
+ public Optional readHeyMatez(Path filePath) throws DataConversionException, IOException {
+ logger.fine("Attempting to read data from file: " + filePath);
+ return heyMatezStorage.readHeyMatez(filePath);
+ }
+
+ @Override
+ public void saveHeyMatez(ReadOnlyHeyMatez heyMatez) throws IOException {
+ saveHeyMatez(heyMatez, heyMatezStorage.getHeyMatezFilePath());
+ }
+
+ @Override
+ public void saveHeyMatez(ReadOnlyHeyMatez heyMatez, Path filePath) throws IOException {
+ logger.fine("Attempting to write to data file: " + filePath);
+ heyMatezStorage.saveHeyMatez(heyMatez, filePath);
+ }
+}
diff --git a/src/main/java/seedu/address/storage/UserPrefsStorage.java b/src/main/java/seedu/heymatez/storage/UserPrefsStorage.java
similarity index 71%
rename from src/main/java/seedu/address/storage/UserPrefsStorage.java
rename to src/main/java/seedu/heymatez/storage/UserPrefsStorage.java
index 29eef178dbc..e6dde880e31 100644
--- a/src/main/java/seedu/address/storage/UserPrefsStorage.java
+++ b/src/main/java/seedu/heymatez/storage/UserPrefsStorage.java
@@ -1,15 +1,15 @@
-package seedu.address.storage;
+package seedu.heymatez.storage;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Optional;
-import seedu.address.commons.exceptions.DataConversionException;
-import seedu.address.model.ReadOnlyUserPrefs;
-import seedu.address.model.UserPrefs;
+import seedu.heymatez.commons.exceptions.DataConversionException;
+import seedu.heymatez.model.ReadOnlyUserPrefs;
+import seedu.heymatez.model.UserPrefs;
/**
- * Represents a storage for {@link seedu.address.model.UserPrefs}.
+ * Represents a storage for {@link UserPrefs}.
*/
public interface UserPrefsStorage {
@@ -27,7 +27,7 @@ public interface UserPrefsStorage {
Optional readUserPrefs() throws DataConversionException, IOException;
/**
- * Saves the given {@link seedu.address.model.ReadOnlyUserPrefs} to the storage.
+ * Saves the given {@link ReadOnlyUserPrefs} to the storage.
* @param userPrefs cannot be null.
* @throws IOException if there was any problem writing to the file.
*/
diff --git a/src/main/java/seedu/address/ui/CommandBox.java b/src/main/java/seedu/heymatez/ui/CommandBox.java
similarity index 88%
rename from src/main/java/seedu/address/ui/CommandBox.java
rename to src/main/java/seedu/heymatez/ui/CommandBox.java
index 9e75478664b..3eb16e47b1e 100644
--- a/src/main/java/seedu/address/ui/CommandBox.java
+++ b/src/main/java/seedu/heymatez/ui/CommandBox.java
@@ -1,12 +1,13 @@
-package seedu.address.ui;
+package seedu.heymatez.ui;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.TextField;
import javafx.scene.layout.Region;
-import seedu.address.logic.commands.CommandResult;
-import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.heymatez.logic.Logic;
+import seedu.heymatez.logic.commands.CommandResult;
+import seedu.heymatez.logic.commands.exceptions.CommandException;
+import seedu.heymatez.logic.parser.exceptions.ParseException;
/**
* The UI component that is responsible for receiving user command inputs.
@@ -77,7 +78,7 @@ public interface CommandExecutor {
/**
* Executes the command and returns the result.
*
- * @see seedu.address.logic.Logic#execute(String)
+ * @see Logic#execute(String)
*/
CommandResult execute(String commandText) throws CommandException, ParseException;
}
diff --git a/src/main/java/seedu/address/ui/HelpWindow.java b/src/main/java/seedu/heymatez/ui/HelpWindow.java
similarity index 92%
rename from src/main/java/seedu/address/ui/HelpWindow.java
rename to src/main/java/seedu/heymatez/ui/HelpWindow.java
index 9a665915949..e898f400264 100644
--- a/src/main/java/seedu/address/ui/HelpWindow.java
+++ b/src/main/java/seedu/heymatez/ui/HelpWindow.java
@@ -1,4 +1,4 @@
-package seedu.address.ui;
+package seedu.heymatez.ui;
import java.util.logging.Logger;
@@ -8,14 +8,14 @@
import javafx.scene.input.Clipboard;
import javafx.scene.input.ClipboardContent;
import javafx.stage.Stage;
-import seedu.address.commons.core.LogsCenter;
+import seedu.heymatez.commons.core.LogsCenter;
/**
* Controller for a help page
*/
public class HelpWindow extends UiPart {
- public static final String USERGUIDE_URL = "https://se-education.org/addressbook-level3/UserGuide.html";
+ public static final String USERGUIDE_URL = "https://ay2021s2-cs2103t-w14-3.github.io/tp/UserGuide.html";
public static final String HELP_MESSAGE = "Refer to the user guide: " + USERGUIDE_URL;
private static final Logger logger = LogsCenter.getLogger(HelpWindow.class);
diff --git a/src/main/java/seedu/address/ui/MainWindow.java b/src/main/java/seedu/heymatez/ui/MainWindow.java
similarity index 89%
rename from src/main/java/seedu/address/ui/MainWindow.java
rename to src/main/java/seedu/heymatez/ui/MainWindow.java
index 9106c3aa6e5..4e06f5ec0f3 100644
--- a/src/main/java/seedu/address/ui/MainWindow.java
+++ b/src/main/java/seedu/heymatez/ui/MainWindow.java
@@ -1,4 +1,4 @@
-package seedu.address.ui;
+package seedu.heymatez.ui;
import java.util.logging.Logger;
@@ -10,12 +10,12 @@
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
-import seedu.address.commons.core.GuiSettings;
-import seedu.address.commons.core.LogsCenter;
-import seedu.address.logic.Logic;
-import seedu.address.logic.commands.CommandResult;
-import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.heymatez.commons.core.GuiSettings;
+import seedu.heymatez.commons.core.LogsCenter;
+import seedu.heymatez.logic.Logic;
+import seedu.heymatez.logic.commands.CommandResult;
+import seedu.heymatez.logic.commands.exceptions.CommandException;
+import seedu.heymatez.logic.parser.exceptions.ParseException;
/**
* The Main Window. Provides the basic application layout containing
@@ -32,6 +32,7 @@ public class MainWindow extends UiPart {
// Independent Ui parts residing in this Ui container
private PersonListPanel personListPanel;
+ private TaskListPanel taskListPanel;
private ResultDisplay resultDisplay;
private HelpWindow helpWindow;
@@ -44,6 +45,9 @@ public class MainWindow extends UiPart {
@FXML
private StackPane personListPanelPlaceholder;
+ @FXML
+ private StackPane taskListPanelPlaceholder;
+
@FXML
private StackPane resultDisplayPlaceholder;
@@ -113,10 +117,13 @@ void fillInnerParts() {
personListPanel = new PersonListPanel(logic.getFilteredPersonList());
personListPanelPlaceholder.getChildren().add(personListPanel.getRoot());
+ taskListPanel = new TaskListPanel(logic.getFilteredTaskList());
+ taskListPanelPlaceholder.getChildren().add(taskListPanel.getRoot());
+
resultDisplay = new ResultDisplay();
resultDisplayPlaceholder.getChildren().add(resultDisplay.getRoot());
- StatusBarFooter statusBarFooter = new StatusBarFooter(logic.getAddressBookFilePath());
+ StatusBarFooter statusBarFooter = new StatusBarFooter(logic.getHeyMatezFilePath());
statusbarPlaceholder.getChildren().add(statusBarFooter.getRoot());
CommandBox commandBox = new CommandBox(this::executeCommand);
@@ -167,10 +174,14 @@ public PersonListPanel getPersonListPanel() {
return personListPanel;
}
+ public TaskListPanel getTaskListPanel() {
+ return taskListPanel;
+ }
+
/**
* Executes the command and returns the result.
*
- * @see seedu.address.logic.Logic#execute(String)
+ * @see Logic#execute(String)
*/
private CommandResult executeCommand(String commandText) throws CommandException, ParseException {
try {
diff --git a/src/main/java/seedu/address/ui/PersonCard.java b/src/main/java/seedu/heymatez/ui/PersonCard.java
similarity index 76%
rename from src/main/java/seedu/address/ui/PersonCard.java
rename to src/main/java/seedu/heymatez/ui/PersonCard.java
index 7fc927bc5d9..4e7e93ad712 100644
--- a/src/main/java/seedu/address/ui/PersonCard.java
+++ b/src/main/java/seedu/heymatez/ui/PersonCard.java
@@ -1,13 +1,10 @@
-package seedu.address.ui;
-
-import java.util.Comparator;
+package seedu.heymatez.ui;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
-import javafx.scene.layout.FlowPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Region;
-import seedu.address.model.person.Person;
+import seedu.heymatez.model.person.Person;
/**
* An UI component that displays information of a {@code Person}.
@@ -35,11 +32,10 @@ public class PersonCard extends UiPart {
@FXML
private Label phone;
@FXML
- private Label address;
- @FXML
private Label email;
@FXML
- private FlowPane tags;
+ private Label role;
+
/**
* Creates a {@code PersonCode} with the given {@code Person} and index to display.
@@ -49,12 +45,9 @@ public PersonCard(Person person, int displayedIndex) {
this.person = person;
id.setText(displayedIndex + ". ");
name.setText(person.getName().fullName);
- phone.setText(person.getPhone().value);
- address.setText(person.getAddress().value);
- email.setText(person.getEmail().value);
- person.getTags().stream()
- .sorted(Comparator.comparing(tag -> tag.tagName))
- .forEach(tag -> tags.getChildren().add(new Label(tag.tagName)));
+ phone.setText("Phone Number: " + person.getPhone().value);
+ email.setText("Email: " + person.getEmail().value);
+ role.setText("Role: " + person.getRole().memberRole);
}
@Override
diff --git a/src/main/java/seedu/address/ui/PersonListPanel.java b/src/main/java/seedu/heymatez/ui/PersonListPanel.java
similarity index 92%
rename from src/main/java/seedu/address/ui/PersonListPanel.java
rename to src/main/java/seedu/heymatez/ui/PersonListPanel.java
index f4c501a897b..64458f6386a 100644
--- a/src/main/java/seedu/address/ui/PersonListPanel.java
+++ b/src/main/java/seedu/heymatez/ui/PersonListPanel.java
@@ -1,4 +1,4 @@
-package seedu.address.ui;
+package seedu.heymatez.ui;
import java.util.logging.Logger;
@@ -7,8 +7,8 @@
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.layout.Region;
-import seedu.address.commons.core.LogsCenter;
-import seedu.address.model.person.Person;
+import seedu.heymatez.commons.core.LogsCenter;
+import seedu.heymatez.model.person.Person;
/**
* Panel containing the list of persons.
diff --git a/src/main/java/seedu/address/ui/ResultDisplay.java b/src/main/java/seedu/heymatez/ui/ResultDisplay.java
similarity index 95%
rename from src/main/java/seedu/address/ui/ResultDisplay.java
rename to src/main/java/seedu/heymatez/ui/ResultDisplay.java
index 7d98e84eedf..8bff60b7c35 100644
--- a/src/main/java/seedu/address/ui/ResultDisplay.java
+++ b/src/main/java/seedu/heymatez/ui/ResultDisplay.java
@@ -1,4 +1,4 @@
-package seedu.address.ui;
+package seedu.heymatez.ui;
import static java.util.Objects.requireNonNull;
diff --git a/src/main/java/seedu/address/ui/StatusBarFooter.java b/src/main/java/seedu/heymatez/ui/StatusBarFooter.java
similarity index 96%
rename from src/main/java/seedu/address/ui/StatusBarFooter.java
rename to src/main/java/seedu/heymatez/ui/StatusBarFooter.java
index b577f829423..18291dafb99 100644
--- a/src/main/java/seedu/address/ui/StatusBarFooter.java
+++ b/src/main/java/seedu/heymatez/ui/StatusBarFooter.java
@@ -1,4 +1,4 @@
-package seedu.address.ui;
+package seedu.heymatez.ui;
import java.nio.file.Path;
import java.nio.file.Paths;
diff --git a/src/main/java/seedu/heymatez/ui/TaskCard.java b/src/main/java/seedu/heymatez/ui/TaskCard.java
new file mode 100644
index 00000000000..4153ab8a9bb
--- /dev/null
+++ b/src/main/java/seedu/heymatez/ui/TaskCard.java
@@ -0,0 +1,72 @@
+package seedu.heymatez.ui;
+
+import java.util.Comparator;
+
+import javafx.fxml.FXML;
+import javafx.scene.control.Label;
+import javafx.scene.layout.FlowPane;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.Region;
+import seedu.heymatez.model.task.Task;
+
+/**
+ * An UI component that displays information of a {@code Task}.
+ */
+public class TaskCard extends UiPart {
+ private static final String FXML = "TaskListCard.fxml";
+
+ public final Task task;
+
+ @FXML
+ private HBox cardPane;
+ @FXML
+ private Label title;
+ @FXML
+ private Label id;
+ @FXML
+ private Label description;
+ @FXML
+ private Label deadline;
+ @FXML
+ private Label taskStatus;
+ @FXML
+ private Label priority;
+ @FXML
+ private FlowPane assignees;
+
+ /**
+ * Creates a {@code TaskCode} with the given {@code Task} and index to display.
+ */
+ public TaskCard(Task task, int displayedIndex) {
+ super(FXML);
+ this.task = task;
+ id.setText(displayedIndex + ". ");
+ title.setText(task.getTitle().taskTitle);
+ description.setText("Description: " + task.getDescription().desc);
+ deadline.setText("Deadline: " + task.getDeadline().dateString);
+ taskStatus.setText("Status: " + task.getTaskStatus().getStatus());
+ priority.setText("Priority: " + task.getPriority().getPriority());
+ task.getAssignees().stream()
+ .sorted(Comparator.comparing(assignee -> assignee.assigneeName))
+ .forEach(assignee -> assignees.getChildren().add(new Label(assignee.assigneeName)));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ // short circuit if same object
+ if (other == this) {
+ return true;
+ }
+
+ // instanceof handles nulls
+ if (!(other instanceof TaskCard)) {
+ return false;
+ }
+
+ // state check
+ TaskCard card = (TaskCard) other;
+ return id.getText().equals(card.id.getText())
+ && task.equals(card.task);
+ }
+
+}
diff --git a/src/main/java/seedu/heymatez/ui/TaskListPanel.java b/src/main/java/seedu/heymatez/ui/TaskListPanel.java
new file mode 100644
index 00000000000..23b230bd5d8
--- /dev/null
+++ b/src/main/java/seedu/heymatez/ui/TaskListPanel.java
@@ -0,0 +1,49 @@
+package seedu.heymatez.ui;
+
+import java.util.logging.Logger;
+
+import javafx.collections.ObservableList;
+import javafx.fxml.FXML;
+import javafx.scene.control.ListCell;
+import javafx.scene.control.ListView;
+import javafx.scene.layout.Region;
+import seedu.heymatez.commons.core.LogsCenter;
+import seedu.heymatez.model.task.Task;
+
+/**
+ * Panel containing the list of tasks.
+ */
+public class TaskListPanel extends UiPart {
+ private static final String FXML = "TaskListPanel.fxml";
+ private final Logger logger = LogsCenter.getLogger(TaskListPanel.class);
+
+ @FXML
+ private ListView taskListView;
+
+ /**
+ * Creates a {@code TaskListPanel} with the given {@code ObservableList}.
+ */
+ public TaskListPanel(ObservableList taskList) {
+ super(FXML);
+ taskListView.setItems(taskList);
+ taskListView.setCellFactory(listView -> new TaskListViewCell());
+ }
+
+ /**
+ * Custom {@code ListCell} that displays the graphics of a {@code Task} using a {@code TaskCard}.
+ */
+ class TaskListViewCell extends ListCell {
+ @Override
+ protected void updateItem(Task task, boolean empty) {
+ super.updateItem(task, empty);
+
+ if (empty || task == null) {
+ setGraphic(null);
+ setText(null);
+ } else {
+ setGraphic(new TaskCard(task, getIndex() + 1).getRoot());
+ }
+ }
+ }
+
+}
diff --git a/src/main/java/seedu/address/ui/Ui.java b/src/main/java/seedu/heymatez/ui/Ui.java
similarity index 85%
rename from src/main/java/seedu/address/ui/Ui.java
rename to src/main/java/seedu/heymatez/ui/Ui.java
index 17aa0b494fe..464008febab 100644
--- a/src/main/java/seedu/address/ui/Ui.java
+++ b/src/main/java/seedu/heymatez/ui/Ui.java
@@ -1,4 +1,4 @@
-package seedu.address.ui;
+package seedu.heymatez.ui;
import javafx.stage.Stage;
diff --git a/src/main/java/seedu/address/ui/UiManager.java b/src/main/java/seedu/heymatez/ui/UiManager.java
similarity index 93%
rename from src/main/java/seedu/address/ui/UiManager.java
rename to src/main/java/seedu/heymatez/ui/UiManager.java
index 882027e4537..602e6e3ce1e 100644
--- a/src/main/java/seedu/address/ui/UiManager.java
+++ b/src/main/java/seedu/heymatez/ui/UiManager.java
@@ -1,4 +1,4 @@
-package seedu.address.ui;
+package seedu.heymatez.ui;
import java.util.logging.Logger;
@@ -7,10 +7,10 @@
import javafx.scene.control.Alert.AlertType;
import javafx.scene.image.Image;
import javafx.stage.Stage;
-import seedu.address.MainApp;
-import seedu.address.commons.core.LogsCenter;
-import seedu.address.commons.util.StringUtil;
-import seedu.address.logic.Logic;
+import seedu.heymatez.MainApp;
+import seedu.heymatez.commons.core.LogsCenter;
+import seedu.heymatez.commons.util.StringUtil;
+import seedu.heymatez.logic.Logic;
/**
* The manager of the UI component.
diff --git a/src/main/java/seedu/address/ui/UiPart.java b/src/main/java/seedu/heymatez/ui/UiPart.java
similarity index 97%
rename from src/main/java/seedu/address/ui/UiPart.java
rename to src/main/java/seedu/heymatez/ui/UiPart.java
index fc820e01a9c..9f00abce2fe 100644
--- a/src/main/java/seedu/address/ui/UiPart.java
+++ b/src/main/java/seedu/heymatez/ui/UiPart.java
@@ -1,4 +1,4 @@
-package seedu.address.ui;
+package seedu.heymatez.ui;
import static java.util.Objects.requireNonNull;
@@ -6,7 +6,7 @@
import java.net.URL;
import javafx.fxml.FXMLLoader;
-import seedu.address.MainApp;
+import seedu.heymatez.MainApp;
/**
* Represents a distinct part of the UI. e.g. Windows, dialogs, panels, status bars, etc.
diff --git a/src/main/resources/view/Extensions.css b/src/main/resources/view/Extensions.css
deleted file mode 100644
index bfe82a85964..00000000000
--- a/src/main/resources/view/Extensions.css
+++ /dev/null
@@ -1,20 +0,0 @@
-
-.error {
- -fx-text-fill: #d06651 !important; /* The error class should always override the default text-fill style */
-}
-
-.list-cell:empty {
- /* Empty cells will not have alternating colours */
- -fx-background: #383838;
-}
-
-.tag-selector {
- -fx-border-width: 1;
- -fx-border-color: white;
- -fx-border-radius: 3;
- -fx-background-radius: 3;
-}
-
-.tooltip-text {
- -fx-text-fill: white;
-}
diff --git a/src/main/resources/view/HelpWindow.fxml b/src/main/resources/view/HelpWindow.fxml
index fa0fb54d9f4..a1f86f58403 100644
--- a/src/main/resources/view/HelpWindow.fxml
+++ b/src/main/resources/view/HelpWindow.fxml
@@ -8,7 +8,7 @@
-
+
diff --git a/src/main/resources/view/HeyMatez.css b/src/main/resources/view/HeyMatez.css
new file mode 100644
index 00000000000..28514380279
--- /dev/null
+++ b/src/main/resources/view/HeyMatez.css
@@ -0,0 +1,116 @@
+
+.error {
+ -fx-text-fill: #d06651 !important; /* The error class should always override the default text-fill style */
+}
+
+.list-cell:filled:selected {
+ -fx-background-color: #acd8e8;
+ -fx-border-color: #acd8e8;
+ -fx-border-width: 1;
+}
+
+.list-cell:filled:selected .label {
+ -fx-text-fill: #283754;
+}
+
+.tag-selector {
+ -fx-border-width: 1;
+ -fx-border-color: black;
+ -fx-border-radius: 3;
+ -fx-background-radius: 3;
+}
+
+.tooltip-text {
+ -fx-text-fill: black;
+}
+
+.cell_big_label {
+ -fx-font-family: "Arial";
+ -fx-font-size: 16px;
+ -fx-text-fill: #010504;
+}
+
+.cell_small_label {
+ -fx-font-family: "Arial";
+ -fx-font-size: 13px;
+ -fx-text-fill: #010504;
+}
+
+.column-header-background {
+ -fx-font-family: "Arial Rounded MT Bold";
+ -fx-font-size: 18px;
+ -fx-text-fill: #010504;
+}
+
+#personCardPane {
+ -fx-background-color: #EEBCF3;
+ -fx-background-radius: 15;
+}
+
+#taskCardPane {
+ -fx-background-color: #F7C06F;
+ -fx-background-radius: 15;
+}
+
+#resultDisplay .content {
+ -fx-background-color: white;
+ -fx-background-radius: 0;
+}
+
+#headerName {
+ -fx-background-color: #E6DFE7;
+}
+
+#headerName .label {
+ -fx-font-family: "Andale Mono";
+ -fx-font-size: 23;
+ -fx-alignment: center;
+ -fx-text-alignment: center;
+ -fx-content-display: center;
+}
+
+#taskList {
+ -fx-background-color: #F0D5AF;
+ -fx-padding: 10, 10, 10, 10;
+}
+
+#taskAndMemberListHeader {
+ -fx-background-color: #EAE5E0;
+}
+
+#taskAndMemberListHeader .label {
+ -fx-background-color: #EAE5E0;
+ -fx-text-alignment: center;
+ -fx-content-display: center;
+ -fx-alignment: center;
+ -fx-font-family: "Arial Rounded MT Bold";
+ -fx-font-size: 18;
+ -fx-label-padding: 10, 10, 10, 10;
+}
+
+#memberList {
+ -fx-background-color: #E0A6D3;
+ -fx-padding: 10, 10, 10, 10;
+}
+
+#resultDisplayPlaceholder {
+ -fx-padding: 5, 10, 10, 5;
+}
+
+#commandBoxPlaceholder {
+ -fx-padding: 5, 10, 10, 5;
+}
+
+#assigneesTag {
+ -fx-hgap: 7;
+ -fx-vgap: 3;
+ -fx-padding: 5, 5, 5, 5;
+}
+
+#assigneesTag .label{
+ -fx-padding: 5, 6, 6, 5;
+ -fx-text-fill: black;
+ -fx-background-color: #9DC5E1;
+ -fx-background-radius: 5;
+ -fx-font-size: 11;
+}
diff --git a/src/main/resources/view/MainWindow.fxml b/src/main/resources/view/MainWindow.fxml
index a431648f6c0..9ff6bc7a422 100644
--- a/src/main/resources/view/MainWindow.fxml
+++ b/src/main/resources/view/MainWindow.fxml
@@ -1,60 +1,70 @@
-
+
-
+
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
diff --git a/src/main/resources/view/PersonListCard.fxml b/src/main/resources/view/PersonListCard.fxml
index f08ea32ad55..7b9970a5311 100644
--- a/src/main/resources/view/PersonListCard.fxml
+++ b/src/main/resources/view/PersonListCard.fxml
@@ -7,30 +7,34 @@
+
-
+
-
+
-
+
-
+
-
-
-
-
+
+
+
+
+
+
+
diff --git a/src/main/resources/view/ResultDisplay.fxml b/src/main/resources/view/ResultDisplay.fxml
index 58d5ad3dc56..688c06db2b0 100644
--- a/src/main/resources/view/ResultDisplay.fxml
+++ b/src/main/resources/view/ResultDisplay.fxml
@@ -3,7 +3,6 @@
-
-
+
+
diff --git a/src/main/resources/view/TaskListCard.fxml b/src/main/resources/view/TaskListCard.fxml
new file mode 100644
index 00000000000..8dfe8e6d620
--- /dev/null
+++ b/src/main/resources/view/TaskListCard.fxml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/view/TaskListPanel.fxml b/src/main/resources/view/TaskListPanel.fxml
new file mode 100644
index 00000000000..a58887c89d1
--- /dev/null
+++ b/src/main/resources/view/TaskListPanel.fxml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/src/test/data/JsonAddressBookStorageTest/invalidAndValidPersonAddressBook.json b/src/test/data/JsonHeyMatezStorageTest/invalidAndValidPersonHeyMatez.json
similarity index 100%
rename from src/test/data/JsonAddressBookStorageTest/invalidAndValidPersonAddressBook.json
rename to src/test/data/JsonHeyMatezStorageTest/invalidAndValidPersonHeyMatez.json
diff --git a/src/test/data/JsonAddressBookStorageTest/invalidPersonAddressBook.json b/src/test/data/JsonHeyMatezStorageTest/invalidPersonHeyMatez.json
similarity index 100%
rename from src/test/data/JsonAddressBookStorageTest/invalidPersonAddressBook.json
rename to src/test/data/JsonHeyMatezStorageTest/invalidPersonHeyMatez.json
diff --git a/src/test/data/JsonAddressBookStorageTest/notJsonFormatAddressBook.json b/src/test/data/JsonHeyMatezStorageTest/notJsonFormatHeyMatez.json
similarity index 100%
rename from src/test/data/JsonAddressBookStorageTest/notJsonFormatAddressBook.json
rename to src/test/data/JsonHeyMatezStorageTest/notJsonFormatHeyMatez.json
diff --git a/src/test/data/JsonSerializableAddressBookTest/invalidPersonAddressBook.json b/src/test/data/JsonSerializableAddressBookTest/invalidPersonAddressBook.json
deleted file mode 100644
index ad3f135ae42..00000000000
--- a/src/test/data/JsonSerializableAddressBookTest/invalidPersonAddressBook.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "persons": [ {
- "name": "Hans Muster",
- "phone": "9482424",
- "email": "invalid@email!3e",
- "address": "4th street"
- } ]
-}
diff --git a/src/test/data/JsonSerializableAddressBookTest/duplicatePersonAddressBook.json b/src/test/data/JsonSerializableHeyMatezTest/duplicatePersonHeyMatez.json
similarity index 55%
rename from src/test/data/JsonSerializableAddressBookTest/duplicatePersonAddressBook.json
rename to src/test/data/JsonSerializableHeyMatezTest/duplicatePersonHeyMatez.json
index 48831cc7674..5dc79e2a4fb 100644
--- a/src/test/data/JsonSerializableAddressBookTest/duplicatePersonAddressBook.json
+++ b/src/test/data/JsonSerializableHeyMatezTest/duplicatePersonHeyMatez.json
@@ -3,12 +3,16 @@
"name": "Alice Pauline",
"phone": "94351253",
"email": "alice@example.com",
- "address": "123, Jurong West Ave 6, #08-111",
- "tagged": [ "friends" ]
+ "role" : "Member"
}, {
"name": "Alice Pauline",
"phone": "94351253",
"email": "pauline@example.com",
- "address": "4th street"
- } ]
+ "role" : "Member"
+ } ],
+ "tasks": [
+ {
+ "title": "Plan meeting",
+ "description": "Draft agenda for board meeting"
+ } ]
}
diff --git a/src/test/data/JsonSerializableHeyMatezTest/invalidPersonHeyMatez.json b/src/test/data/JsonSerializableHeyMatezTest/invalidPersonHeyMatez.json
new file mode 100644
index 00000000000..f3fcb051d28
--- /dev/null
+++ b/src/test/data/JsonSerializableHeyMatezTest/invalidPersonHeyMatez.json
@@ -0,0 +1,13 @@
+{
+ "persons": [ {
+ "name": "Hans Muster",
+ "phone": "9482424",
+ "email": "invalid@email!3e",
+ "role" : "Member"
+ } ],
+ "tasks": [
+ {
+ "title": "Plan meeting",
+ "description": "Draft agenda for board meeting"
+ } ]
+}
diff --git a/src/test/data/JsonSerializableAddressBookTest/typicalPersonsAddressBook.json b/src/test/data/JsonSerializableHeyMatezTest/typicalPersonsHeyMatez.json
similarity index 55%
rename from src/test/data/JsonSerializableAddressBookTest/typicalPersonsAddressBook.json
rename to src/test/data/JsonSerializableHeyMatezTest/typicalPersonsHeyMatez.json
index f10eddee12e..8d2c48707da 100644
--- a/src/test/data/JsonSerializableAddressBookTest/typicalPersonsAddressBook.json
+++ b/src/test/data/JsonSerializableHeyMatezTest/typicalPersonsHeyMatez.json
@@ -1,46 +1,40 @@
{
- "_comment": "AddressBook save file which contains the same Person values as in TypicalPersons#getTypicalAddressBook()",
+ "_comment": "HeyMatez save file which contains the same Person values as in TypicalPersons#getTypicalAddressBook()",
"persons" : [ {
"name" : "Alice Pauline",
"phone" : "94351253",
"email" : "alice@example.com",
- "address" : "123, Jurong West Ave 6, #08-111",
- "tagged" : [ "friends" ]
+ "role" : "Member"
}, {
"name" : "Benson Meier",
"phone" : "98765432",
"email" : "johnd@example.com",
- "address" : "311, Clementi Ave 2, #02-25",
- "tagged" : [ "owesMoney", "friends" ]
+ "role" : "Member"
}, {
"name" : "Carl Kurz",
"phone" : "95352563",
"email" : "heinz@example.com",
- "address" : "wall street",
- "tagged" : [ ]
+ "role" : "President"
}, {
"name" : "Daniel Meier",
"phone" : "87652533",
"email" : "cornelia@example.com",
- "address" : "10th street",
- "tagged" : [ "friends" ]
+ "role" : "Secretary"
}, {
"name" : "Elle Meyer",
"phone" : "9482224",
"email" : "werner@example.com",
- "address" : "michegan ave",
- "tagged" : [ ]
+ "role" : "Treasurer"
}, {
"name" : "Fiona Kunz",
"phone" : "9482427",
"email" : "lydia@example.com",
- "address" : "little tokyo",
- "tagged" : [ ]
+ "role" : "Member"
}, {
"name" : "George Best",
"phone" : "9482442",
"email" : "anna@example.com",
- "address" : "4th street",
- "tagged" : [ ]
- } ]
+ "role" : "Assistant Secretary"
+ } ],
+ "tasks": []
}
diff --git a/src/test/data/JsonUserPrefsStorageTest/ExtraValuesUserPref.json b/src/test/data/JsonUserPrefsStorageTest/ExtraValuesUserPref.json
index 1037548a9cd..db2d1be03ce 100644
--- a/src/test/data/JsonUserPrefsStorageTest/ExtraValuesUserPref.json
+++ b/src/test/data/JsonUserPrefsStorageTest/ExtraValuesUserPref.json
@@ -9,5 +9,5 @@
"z" : 99
}
},
- "addressBookFilePath" : "addressbook.json"
+ "heyMatezFilePath" : "heymatez.json"
}
diff --git a/src/test/data/JsonUserPrefsStorageTest/TypicalUserPref.json b/src/test/data/JsonUserPrefsStorageTest/TypicalUserPref.json
index b819bed900a..1d0c14c770e 100644
--- a/src/test/data/JsonUserPrefsStorageTest/TypicalUserPref.json
+++ b/src/test/data/JsonUserPrefsStorageTest/TypicalUserPref.json
@@ -7,5 +7,5 @@
"y" : 100
}
},
- "addressBookFilePath" : "addressbook.json"
+ "heyMatezFilePath" : "heymatez.json"
}
diff --git a/src/test/java/seedu/address/logic/commands/AddCommandIntegrationTest.java b/src/test/java/seedu/address/logic/commands/AddCommandIntegrationTest.java
deleted file mode 100644
index cb8714bb055..00000000000
--- a/src/test/java/seedu/address/logic/commands/AddCommandIntegrationTest.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package seedu.address.logic.commands;
-
-import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure;
-import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
-import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import seedu.address.model.Model;
-import seedu.address.model.ModelManager;
-import seedu.address.model.UserPrefs;
-import seedu.address.model.person.Person;
-import seedu.address.testutil.PersonBuilder;
-
-/**
- * Contains integration tests (interaction with the Model) for {@code AddCommand}.
- */
-public class AddCommandIntegrationTest {
-
- private Model model;
-
- @BeforeEach
- public void setUp() {
- model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
- }
-
- @Test
- public void execute_newPerson_success() {
- Person validPerson = new PersonBuilder().build();
-
- Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs());
- expectedModel.addPerson(validPerson);
-
- assertCommandSuccess(new AddCommand(validPerson), model,
- String.format(AddCommand.MESSAGE_SUCCESS, validPerson), expectedModel);
- }
-
- @Test
- public void execute_duplicatePerson_throwsCommandException() {
- Person personInList = model.getAddressBook().getPersonList().get(0);
- assertCommandFailure(new AddCommand(personInList), model, AddCommand.MESSAGE_DUPLICATE_PERSON);
- }
-
-}
diff --git a/src/test/java/seedu/address/logic/commands/ClearCommandTest.java b/src/test/java/seedu/address/logic/commands/ClearCommandTest.java
deleted file mode 100644
index 80d9110c03a..00000000000
--- a/src/test/java/seedu/address/logic/commands/ClearCommandTest.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package seedu.address.logic.commands;
-
-import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
-import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;
-
-import org.junit.jupiter.api.Test;
-
-import seedu.address.model.AddressBook;
-import seedu.address.model.Model;
-import seedu.address.model.ModelManager;
-import seedu.address.model.UserPrefs;
-
-public class ClearCommandTest {
-
- @Test
- public void execute_emptyAddressBook_success() {
- Model model = new ModelManager();
- Model expectedModel = new ModelManager();
-
- assertCommandSuccess(new ClearCommand(), model, ClearCommand.MESSAGE_SUCCESS, expectedModel);
- }
-
- @Test
- public void execute_nonEmptyAddressBook_success() {
- Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
- Model expectedModel = new ModelManager(getTypicalAddressBook(), new UserPrefs());
- expectedModel.setAddressBook(new AddressBook());
-
- assertCommandSuccess(new ClearCommand(), model, ClearCommand.MESSAGE_SUCCESS, expectedModel);
- }
-
-}
diff --git a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java b/src/test/java/seedu/address/logic/commands/CommandTestUtil.java
deleted file mode 100644
index 643a1d08069..00000000000
--- a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java
+++ /dev/null
@@ -1,128 +0,0 @@
-package seedu.address.logic.commands;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
-import static seedu.address.testutil.Assert.assertThrows;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import seedu.address.commons.core.index.Index;
-import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.model.AddressBook;
-import seedu.address.model.Model;
-import seedu.address.model.person.NameContainsKeywordsPredicate;
-import seedu.address.model.person.Person;
-import seedu.address.testutil.EditPersonDescriptorBuilder;
-
-/**
- * Contains helper methods for testing commands.
- */
-public class CommandTestUtil {
-
- public static final String VALID_NAME_AMY = "Amy Bee";
- public static final String VALID_NAME_BOB = "Bob Choo";
- public static final String VALID_PHONE_AMY = "11111111";
- public static final String VALID_PHONE_BOB = "22222222";
- public static final String VALID_EMAIL_AMY = "amy@example.com";
- public static final String VALID_EMAIL_BOB = "bob@example.com";
- public static final String VALID_ADDRESS_AMY = "Block 312, Amy Street 1";
- public static final String VALID_ADDRESS_BOB = "Block 123, Bobby Street 3";
- public static final String VALID_TAG_HUSBAND = "husband";
- public static final String VALID_TAG_FRIEND = "friend";
-
- public static final String NAME_DESC_AMY = " " + PREFIX_NAME + VALID_NAME_AMY;
- public static final String NAME_DESC_BOB = " " + PREFIX_NAME + VALID_NAME_BOB;
- public static final String PHONE_DESC_AMY = " " + PREFIX_PHONE + VALID_PHONE_AMY;
- public static final String PHONE_DESC_BOB = " " + PREFIX_PHONE + VALID_PHONE_BOB;
- public static final String EMAIL_DESC_AMY = " " + PREFIX_EMAIL + VALID_EMAIL_AMY;
- public static final String EMAIL_DESC_BOB = " " + PREFIX_EMAIL + VALID_EMAIL_BOB;
- public static final String ADDRESS_DESC_AMY = " " + PREFIX_ADDRESS + VALID_ADDRESS_AMY;
- public static final String ADDRESS_DESC_BOB = " " + PREFIX_ADDRESS + VALID_ADDRESS_BOB;
- public static final String TAG_DESC_FRIEND = " " + PREFIX_TAG + VALID_TAG_FRIEND;
- public static final String TAG_DESC_HUSBAND = " " + PREFIX_TAG + VALID_TAG_HUSBAND;
-
- public static final String INVALID_NAME_DESC = " " + PREFIX_NAME + "James&"; // '&' not allowed in names
- public static final String INVALID_PHONE_DESC = " " + PREFIX_PHONE + "911a"; // 'a' not allowed in phones
- public static final String INVALID_EMAIL_DESC = " " + PREFIX_EMAIL + "bob!yahoo"; // missing '@' symbol
- public static final String INVALID_ADDRESS_DESC = " " + PREFIX_ADDRESS; // empty string not allowed for addresses
- public static final String INVALID_TAG_DESC = " " + PREFIX_TAG + "hubby*"; // '*' not allowed in tags
-
- public static final String PREAMBLE_WHITESPACE = "\t \r \n";
- public static final String PREAMBLE_NON_EMPTY = "NonEmptyPreamble";
-
- public static final EditCommand.EditPersonDescriptor DESC_AMY;
- public static final EditCommand.EditPersonDescriptor DESC_BOB;
-
- static {
- DESC_AMY = new EditPersonDescriptorBuilder().withName(VALID_NAME_AMY)
- .withPhone(VALID_PHONE_AMY).withEmail(VALID_EMAIL_AMY).withAddress(VALID_ADDRESS_AMY)
- .withTags(VALID_TAG_FRIEND).build();
- DESC_BOB = new EditPersonDescriptorBuilder().withName(VALID_NAME_BOB)
- .withPhone(VALID_PHONE_BOB).withEmail(VALID_EMAIL_BOB).withAddress(VALID_ADDRESS_BOB)
- .withTags(VALID_TAG_HUSBAND, VALID_TAG_FRIEND).build();
- }
-
- /**
- * Executes the given {@code command}, confirms that
- * - the returned {@link CommandResult} matches {@code expectedCommandResult}
- * - the {@code actualModel} matches {@code expectedModel}
- */
- public static void assertCommandSuccess(Command command, Model actualModel, CommandResult expectedCommandResult,
- Model expectedModel) {
- try {
- CommandResult result = command.execute(actualModel);
- assertEquals(expectedCommandResult, result);
- assertEquals(expectedModel, actualModel);
- } catch (CommandException ce) {
- throw new AssertionError("Execution of command should not fail.", ce);
- }
- }
-
- /**
- * Convenience wrapper to {@link #assertCommandSuccess(Command, Model, CommandResult, Model)}
- * that takes a string {@code expectedMessage}.
- */
- public static void assertCommandSuccess(Command command, Model actualModel, String expectedMessage,
- Model expectedModel) {
- CommandResult expectedCommandResult = new CommandResult(expectedMessage);
- assertCommandSuccess(command, actualModel, expectedCommandResult, expectedModel);
- }
-
- /**
- * Executes the given {@code command}, confirms that
- * - a {@code CommandException} is thrown
- * - the CommandException message matches {@code expectedMessage}
- * - the address book, filtered person list and selected person in {@code actualModel} remain unchanged
- */
- public static void assertCommandFailure(Command command, Model actualModel, String expectedMessage) {
- // we are unable to defensively copy the model for comparison later, so we can
- // only do so by copying its components.
- AddressBook expectedAddressBook = new AddressBook(actualModel.getAddressBook());
- List expectedFilteredList = new ArrayList<>(actualModel.getFilteredPersonList());
-
- assertThrows(CommandException.class, expectedMessage, () -> command.execute(actualModel));
- assertEquals(expectedAddressBook, actualModel.getAddressBook());
- assertEquals(expectedFilteredList, actualModel.getFilteredPersonList());
- }
- /**
- * Updates {@code model}'s filtered list to show only the person at the given {@code targetIndex} in the
- * {@code model}'s address book.
- */
- public static void showPersonAtIndex(Model model, Index targetIndex) {
- assertTrue(targetIndex.getZeroBased() < model.getFilteredPersonList().size());
-
- Person person = model.getFilteredPersonList().get(targetIndex.getZeroBased());
- final String[] splitName = person.getName().fullName.split("\\s+");
- model.updateFilteredPersonList(new NameContainsKeywordsPredicate(Arrays.asList(splitName[0])));
-
- assertEquals(1, model.getFilteredPersonList().size());
- }
-
-}
diff --git a/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java b/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java
deleted file mode 100644
index 45a8c910ba1..00000000000
--- a/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java
+++ /dev/null
@@ -1,109 +0,0 @@
-package seedu.address.logic.commands;
-
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure;
-import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
-import static seedu.address.logic.commands.CommandTestUtil.showPersonAtIndex;
-import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
-import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PERSON;
-import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;
-
-import org.junit.jupiter.api.Test;
-
-import seedu.address.commons.core.Messages;
-import seedu.address.commons.core.index.Index;
-import seedu.address.model.Model;
-import seedu.address.model.ModelManager;
-import seedu.address.model.UserPrefs;
-import seedu.address.model.person.Person;
-
-/**
- * Contains integration tests (interaction with the Model) and unit tests for
- * {@code DeleteCommand}.
- */
-public class DeleteCommandTest {
-
- private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
-
- @Test
- public void execute_validIndexUnfilteredList_success() {
- Person personToDelete = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased());
- DeleteCommand deleteCommand = new DeleteCommand(INDEX_FIRST_PERSON);
-
- String expectedMessage = String.format(DeleteCommand.MESSAGE_DELETE_PERSON_SUCCESS, personToDelete);
-
- ModelManager expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs());
- expectedModel.deletePerson(personToDelete);
-
- assertCommandSuccess(deleteCommand, model, expectedMessage, expectedModel);
- }
-
- @Test
- public void execute_invalidIndexUnfilteredList_throwsCommandException() {
- Index outOfBoundIndex = Index.fromOneBased(model.getFilteredPersonList().size() + 1);
- DeleteCommand deleteCommand = new DeleteCommand(outOfBoundIndex);
-
- assertCommandFailure(deleteCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
- }
-
- @Test
- public void execute_validIndexFilteredList_success() {
- showPersonAtIndex(model, INDEX_FIRST_PERSON);
-
- Person personToDelete = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased());
- DeleteCommand deleteCommand = new DeleteCommand(INDEX_FIRST_PERSON);
-
- String expectedMessage = String.format(DeleteCommand.MESSAGE_DELETE_PERSON_SUCCESS, personToDelete);
-
- Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs());
- expectedModel.deletePerson(personToDelete);
- showNoPerson(expectedModel);
-
- assertCommandSuccess(deleteCommand, model, expectedMessage, expectedModel);
- }
-
- @Test
- public void execute_invalidIndexFilteredList_throwsCommandException() {
- showPersonAtIndex(model, INDEX_FIRST_PERSON);
-
- Index outOfBoundIndex = INDEX_SECOND_PERSON;
- // ensures that outOfBoundIndex is still in bounds of address book list
- assertTrue(outOfBoundIndex.getZeroBased() < model.getAddressBook().getPersonList().size());
-
- DeleteCommand deleteCommand = new DeleteCommand(outOfBoundIndex);
-
- assertCommandFailure(deleteCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
- }
-
- @Test
- public void equals() {
- DeleteCommand deleteFirstCommand = new DeleteCommand(INDEX_FIRST_PERSON);
- DeleteCommand deleteSecondCommand = new DeleteCommand(INDEX_SECOND_PERSON);
-
- // same object -> returns true
- assertTrue(deleteFirstCommand.equals(deleteFirstCommand));
-
- // same values -> returns true
- DeleteCommand deleteFirstCommandCopy = new DeleteCommand(INDEX_FIRST_PERSON);
- assertTrue(deleteFirstCommand.equals(deleteFirstCommandCopy));
-
- // different types -> returns false
- assertFalse(deleteFirstCommand.equals(1));
-
- // null -> returns false
- assertFalse(deleteFirstCommand.equals(null));
-
- // different person -> returns false
- assertFalse(deleteFirstCommand.equals(deleteSecondCommand));
- }
-
- /**
- * Updates {@code model}'s filtered list to show no one.
- */
- private void showNoPerson(Model model) {
- model.updateFilteredPersonList(p -> false);
-
- assertTrue(model.getFilteredPersonList().isEmpty());
- }
-}
diff --git a/src/test/java/seedu/address/logic/commands/EditCommandTest.java b/src/test/java/seedu/address/logic/commands/EditCommandTest.java
deleted file mode 100644
index 214c6c2507b..00000000000
--- a/src/test/java/seedu/address/logic/commands/EditCommandTest.java
+++ /dev/null
@@ -1,173 +0,0 @@
-package seedu.address.logic.commands;
-
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.logic.commands.CommandTestUtil.DESC_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.DESC_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND;
-import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure;
-import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
-import static seedu.address.logic.commands.CommandTestUtil.showPersonAtIndex;
-import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
-import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PERSON;
-import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;
-
-import org.junit.jupiter.api.Test;
-
-import seedu.address.commons.core.Messages;
-import seedu.address.commons.core.index.Index;
-import seedu.address.logic.commands.EditCommand.EditPersonDescriptor;
-import seedu.address.model.AddressBook;
-import seedu.address.model.Model;
-import seedu.address.model.ModelManager;
-import seedu.address.model.UserPrefs;
-import seedu.address.model.person.Person;
-import seedu.address.testutil.EditPersonDescriptorBuilder;
-import seedu.address.testutil.PersonBuilder;
-
-/**
- * Contains integration tests (interaction with the Model) and unit tests for EditCommand.
- */
-public class EditCommandTest {
-
- private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
-
- @Test
- public void execute_allFieldsSpecifiedUnfilteredList_success() {
- Person editedPerson = new PersonBuilder().build();
- EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(editedPerson).build();
- EditCommand editCommand = new EditCommand(INDEX_FIRST_PERSON, descriptor);
-
- String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedPerson);
-
- Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs());
- expectedModel.setPerson(model.getFilteredPersonList().get(0), editedPerson);
-
- assertCommandSuccess(editCommand, model, expectedMessage, expectedModel);
- }
-
- @Test
- public void execute_someFieldsSpecifiedUnfilteredList_success() {
- Index indexLastPerson = Index.fromOneBased(model.getFilteredPersonList().size());
- Person lastPerson = model.getFilteredPersonList().get(indexLastPerson.getZeroBased());
-
- PersonBuilder personInList = new PersonBuilder(lastPerson);
- Person editedPerson = personInList.withName(VALID_NAME_BOB).withPhone(VALID_PHONE_BOB)
- .withTags(VALID_TAG_HUSBAND).build();
-
- EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withName(VALID_NAME_BOB)
- .withPhone(VALID_PHONE_BOB).withTags(VALID_TAG_HUSBAND).build();
- EditCommand editCommand = new EditCommand(indexLastPerson, descriptor);
-
- String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedPerson);
-
- Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs());
- expectedModel.setPerson(lastPerson, editedPerson);
-
- assertCommandSuccess(editCommand, model, expectedMessage, expectedModel);
- }
-
- @Test
- public void execute_noFieldSpecifiedUnfilteredList_success() {
- EditCommand editCommand = new EditCommand(INDEX_FIRST_PERSON, new EditPersonDescriptor());
- Person editedPerson = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased());
-
- String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedPerson);
-
- Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs());
-
- assertCommandSuccess(editCommand, model, expectedMessage, expectedModel);
- }
-
- @Test
- public void execute_filteredList_success() {
- showPersonAtIndex(model, INDEX_FIRST_PERSON);
-
- Person personInFilteredList = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased());
- Person editedPerson = new PersonBuilder(personInFilteredList).withName(VALID_NAME_BOB).build();
- EditCommand editCommand = new EditCommand(INDEX_FIRST_PERSON,
- new EditPersonDescriptorBuilder().withName(VALID_NAME_BOB).build());
-
- String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedPerson);
-
- Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs());
- expectedModel.setPerson(model.getFilteredPersonList().get(0), editedPerson);
-
- assertCommandSuccess(editCommand, model, expectedMessage, expectedModel);
- }
-
- @Test
- public void execute_duplicatePersonUnfilteredList_failure() {
- Person firstPerson = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased());
- EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(firstPerson).build();
- EditCommand editCommand = new EditCommand(INDEX_SECOND_PERSON, descriptor);
-
- assertCommandFailure(editCommand, model, EditCommand.MESSAGE_DUPLICATE_PERSON);
- }
-
- @Test
- public void execute_duplicatePersonFilteredList_failure() {
- showPersonAtIndex(model, INDEX_FIRST_PERSON);
-
- // edit person in filtered list into a duplicate in address book
- Person personInList = model.getAddressBook().getPersonList().get(INDEX_SECOND_PERSON.getZeroBased());
- EditCommand editCommand = new EditCommand(INDEX_FIRST_PERSON,
- new EditPersonDescriptorBuilder(personInList).build());
-
- assertCommandFailure(editCommand, model, EditCommand.MESSAGE_DUPLICATE_PERSON);
- }
-
- @Test
- public void execute_invalidPersonIndexUnfilteredList_failure() {
- Index outOfBoundIndex = Index.fromOneBased(model.getFilteredPersonList().size() + 1);
- EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withName(VALID_NAME_BOB).build();
- EditCommand editCommand = new EditCommand(outOfBoundIndex, descriptor);
-
- assertCommandFailure(editCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
- }
-
- /**
- * Edit filtered list where index is larger than size of filtered list,
- * but smaller than size of address book
- */
- @Test
- public void execute_invalidPersonIndexFilteredList_failure() {
- showPersonAtIndex(model, INDEX_FIRST_PERSON);
- Index outOfBoundIndex = INDEX_SECOND_PERSON;
- // ensures that outOfBoundIndex is still in bounds of address book list
- assertTrue(outOfBoundIndex.getZeroBased() < model.getAddressBook().getPersonList().size());
-
- EditCommand editCommand = new EditCommand(outOfBoundIndex,
- new EditPersonDescriptorBuilder().withName(VALID_NAME_BOB).build());
-
- assertCommandFailure(editCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
- }
-
- @Test
- public void equals() {
- final EditCommand standardCommand = new EditCommand(INDEX_FIRST_PERSON, DESC_AMY);
-
- // same values -> returns true
- EditPersonDescriptor copyDescriptor = new EditPersonDescriptor(DESC_AMY);
- EditCommand commandWithSameValues = new EditCommand(INDEX_FIRST_PERSON, copyDescriptor);
- assertTrue(standardCommand.equals(commandWithSameValues));
-
- // same object -> returns true
- assertTrue(standardCommand.equals(standardCommand));
-
- // null -> returns false
- assertFalse(standardCommand.equals(null));
-
- // different types -> returns false
- assertFalse(standardCommand.equals(new ClearCommand()));
-
- // different index -> returns false
- assertFalse(standardCommand.equals(new EditCommand(INDEX_SECOND_PERSON, DESC_AMY)));
-
- // different descriptor -> returns false
- assertFalse(standardCommand.equals(new EditCommand(INDEX_FIRST_PERSON, DESC_BOB)));
- }
-
-}
diff --git a/src/test/java/seedu/address/logic/commands/EditPersonDescriptorTest.java b/src/test/java/seedu/address/logic/commands/EditPersonDescriptorTest.java
deleted file mode 100644
index e0288792e72..00000000000
--- a/src/test/java/seedu/address/logic/commands/EditPersonDescriptorTest.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package seedu.address.logic.commands;
-
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.logic.commands.CommandTestUtil.DESC_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.DESC_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND;
-
-import org.junit.jupiter.api.Test;
-
-import seedu.address.logic.commands.EditCommand.EditPersonDescriptor;
-import seedu.address.testutil.EditPersonDescriptorBuilder;
-
-public class EditPersonDescriptorTest {
-
- @Test
- public void equals() {
- // same values -> returns true
- EditPersonDescriptor descriptorWithSameValues = new EditPersonDescriptor(DESC_AMY);
- assertTrue(DESC_AMY.equals(descriptorWithSameValues));
-
- // same object -> returns true
- assertTrue(DESC_AMY.equals(DESC_AMY));
-
- // null -> returns false
- assertFalse(DESC_AMY.equals(null));
-
- // different types -> returns false
- assertFalse(DESC_AMY.equals(5));
-
- // different values -> returns false
- assertFalse(DESC_AMY.equals(DESC_BOB));
-
- // different name -> returns false
- EditPersonDescriptor editedAmy = new EditPersonDescriptorBuilder(DESC_AMY).withName(VALID_NAME_BOB).build();
- assertFalse(DESC_AMY.equals(editedAmy));
-
- // different phone -> returns false
- editedAmy = new EditPersonDescriptorBuilder(DESC_AMY).withPhone(VALID_PHONE_BOB).build();
- assertFalse(DESC_AMY.equals(editedAmy));
-
- // different email -> returns false
- editedAmy = new EditPersonDescriptorBuilder(DESC_AMY).withEmail(VALID_EMAIL_BOB).build();
- assertFalse(DESC_AMY.equals(editedAmy));
-
- // different address -> returns false
- editedAmy = new EditPersonDescriptorBuilder(DESC_AMY).withAddress(VALID_ADDRESS_BOB).build();
- assertFalse(DESC_AMY.equals(editedAmy));
-
- // different tags -> returns false
- editedAmy = new EditPersonDescriptorBuilder(DESC_AMY).withTags(VALID_TAG_HUSBAND).build();
- assertFalse(DESC_AMY.equals(editedAmy));
- }
-}
diff --git a/src/test/java/seedu/address/logic/commands/FindCommandTest.java b/src/test/java/seedu/address/logic/commands/FindCommandTest.java
deleted file mode 100644
index 9b15db28bbb..00000000000
--- a/src/test/java/seedu/address/logic/commands/FindCommandTest.java
+++ /dev/null
@@ -1,83 +0,0 @@
-package seedu.address.logic.commands;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.commons.core.Messages.MESSAGE_PERSONS_LISTED_OVERVIEW;
-import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
-import static seedu.address.testutil.TypicalPersons.CARL;
-import static seedu.address.testutil.TypicalPersons.ELLE;
-import static seedu.address.testutil.TypicalPersons.FIONA;
-import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;
-
-import java.util.Arrays;
-import java.util.Collections;
-
-import org.junit.jupiter.api.Test;
-
-import seedu.address.model.Model;
-import seedu.address.model.ModelManager;
-import seedu.address.model.UserPrefs;
-import seedu.address.model.person.NameContainsKeywordsPredicate;
-
-/**
- * Contains integration tests (interaction with the Model) for {@code FindCommand}.
- */
-public class FindCommandTest {
- private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
- private Model expectedModel = new ModelManager(getTypicalAddressBook(), new UserPrefs());
-
- @Test
- public void equals() {
- NameContainsKeywordsPredicate firstPredicate =
- new NameContainsKeywordsPredicate(Collections.singletonList("first"));
- NameContainsKeywordsPredicate secondPredicate =
- new NameContainsKeywordsPredicate(Collections.singletonList("second"));
-
- FindCommand findFirstCommand = new FindCommand(firstPredicate);
- FindCommand findSecondCommand = new FindCommand(secondPredicate);
-
- // same object -> returns true
- assertTrue(findFirstCommand.equals(findFirstCommand));
-
- // same values -> returns true
- FindCommand findFirstCommandCopy = new FindCommand(firstPredicate);
- assertTrue(findFirstCommand.equals(findFirstCommandCopy));
-
- // different types -> returns false
- assertFalse(findFirstCommand.equals(1));
-
- // null -> returns false
- assertFalse(findFirstCommand.equals(null));
-
- // different person -> returns false
- assertFalse(findFirstCommand.equals(findSecondCommand));
- }
-
- @Test
- public void execute_zeroKeywords_noPersonFound() {
- String expectedMessage = String.format(MESSAGE_PERSONS_LISTED_OVERVIEW, 0);
- NameContainsKeywordsPredicate predicate = preparePredicate(" ");
- FindCommand command = new FindCommand(predicate);
- expectedModel.updateFilteredPersonList(predicate);
- assertCommandSuccess(command, model, expectedMessage, expectedModel);
- assertEquals(Collections.emptyList(), model.getFilteredPersonList());
- }
-
- @Test
- public void execute_multipleKeywords_multiplePersonsFound() {
- String expectedMessage = String.format(MESSAGE_PERSONS_LISTED_OVERVIEW, 3);
- NameContainsKeywordsPredicate predicate = preparePredicate("Kurz Elle Kunz");
- FindCommand command = new FindCommand(predicate);
- expectedModel.updateFilteredPersonList(predicate);
- assertCommandSuccess(command, model, expectedMessage, expectedModel);
- assertEquals(Arrays.asList(CARL, ELLE, FIONA), model.getFilteredPersonList());
- }
-
- /**
- * Parses {@code userInput} into a {@code NameContainsKeywordsPredicate}.
- */
- private NameContainsKeywordsPredicate preparePredicate(String userInput) {
- return new NameContainsKeywordsPredicate(Arrays.asList(userInput.split("\\s+")));
- }
-}
diff --git a/src/test/java/seedu/address/logic/commands/ListCommandTest.java b/src/test/java/seedu/address/logic/commands/ListCommandTest.java
deleted file mode 100644
index 435ff1f7275..00000000000
--- a/src/test/java/seedu/address/logic/commands/ListCommandTest.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package seedu.address.logic.commands;
-
-import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
-import static seedu.address.logic.commands.CommandTestUtil.showPersonAtIndex;
-import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
-import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import seedu.address.model.Model;
-import seedu.address.model.ModelManager;
-import seedu.address.model.UserPrefs;
-
-/**
- * Contains integration tests (interaction with the Model) and unit tests for ListCommand.
- */
-public class ListCommandTest {
-
- private Model model;
- private Model expectedModel;
-
- @BeforeEach
- public void setUp() {
- model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
- expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs());
- }
-
- @Test
- public void execute_listIsNotFiltered_showsSameList() {
- assertCommandSuccess(new ListCommand(), model, ListCommand.MESSAGE_SUCCESS, expectedModel);
- }
-
- @Test
- public void execute_listIsFiltered_showsEverything() {
- showPersonAtIndex(model, INDEX_FIRST_PERSON);
- assertCommandSuccess(new ListCommand(), model, ListCommand.MESSAGE_SUCCESS, expectedModel);
- }
-}
diff --git a/src/test/java/seedu/address/logic/parser/AddCommandParserTest.java b/src/test/java/seedu/address/logic/parser/AddCommandParserTest.java
deleted file mode 100644
index 5cf487d7ebb..00000000000
--- a/src/test/java/seedu/address/logic/parser/AddCommandParserTest.java
+++ /dev/null
@@ -1,141 +0,0 @@
-package seedu.address.logic.parser;
-
-import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
-import static seedu.address.logic.commands.CommandTestUtil.ADDRESS_DESC_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.ADDRESS_DESC_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.EMAIL_DESC_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.EMAIL_DESC_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.INVALID_ADDRESS_DESC;
-import static seedu.address.logic.commands.CommandTestUtil.INVALID_EMAIL_DESC;
-import static seedu.address.logic.commands.CommandTestUtil.INVALID_NAME_DESC;
-import static seedu.address.logic.commands.CommandTestUtil.INVALID_PHONE_DESC;
-import static seedu.address.logic.commands.CommandTestUtil.INVALID_TAG_DESC;
-import static seedu.address.logic.commands.CommandTestUtil.NAME_DESC_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.NAME_DESC_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.PHONE_DESC_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.PHONE_DESC_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.PREAMBLE_NON_EMPTY;
-import static seedu.address.logic.commands.CommandTestUtil.PREAMBLE_WHITESPACE;
-import static seedu.address.logic.commands.CommandTestUtil.TAG_DESC_FRIEND;
-import static seedu.address.logic.commands.CommandTestUtil.TAG_DESC_HUSBAND;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_FRIEND;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND;
-import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure;
-import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess;
-import static seedu.address.testutil.TypicalPersons.AMY;
-import static seedu.address.testutil.TypicalPersons.BOB;
-
-import org.junit.jupiter.api.Test;
-
-import seedu.address.logic.commands.AddCommand;
-import seedu.address.model.person.Address;
-import seedu.address.model.person.Email;
-import seedu.address.model.person.Name;
-import seedu.address.model.person.Person;
-import seedu.address.model.person.Phone;
-import seedu.address.model.tag.Tag;
-import seedu.address.testutil.PersonBuilder;
-
-public class AddCommandParserTest {
- private AddCommandParser parser = new AddCommandParser();
-
- @Test
- public void parse_allFieldsPresent_success() {
- Person expectedPerson = new PersonBuilder(BOB).withTags(VALID_TAG_FRIEND).build();
-
- // whitespace only preamble
- assertParseSuccess(parser, PREAMBLE_WHITESPACE + NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB
- + ADDRESS_DESC_BOB + TAG_DESC_FRIEND, new AddCommand(expectedPerson));
-
- // multiple names - last name accepted
- assertParseSuccess(parser, NAME_DESC_AMY + NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB
- + ADDRESS_DESC_BOB + TAG_DESC_FRIEND, new AddCommand(expectedPerson));
-
- // multiple phones - last phone accepted
- assertParseSuccess(parser, NAME_DESC_BOB + PHONE_DESC_AMY + PHONE_DESC_BOB + EMAIL_DESC_BOB
- + ADDRESS_DESC_BOB + TAG_DESC_FRIEND, new AddCommand(expectedPerson));
-
- // multiple emails - last email accepted
- assertParseSuccess(parser, NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_AMY + EMAIL_DESC_BOB
- + ADDRESS_DESC_BOB + TAG_DESC_FRIEND, new AddCommand(expectedPerson));
-
- // multiple addresses - last address accepted
- assertParseSuccess(parser, NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_AMY
- + ADDRESS_DESC_BOB + TAG_DESC_FRIEND, new AddCommand(expectedPerson));
-
- // multiple tags - all accepted
- Person expectedPersonMultipleTags = new PersonBuilder(BOB).withTags(VALID_TAG_FRIEND, VALID_TAG_HUSBAND)
- .build();
- assertParseSuccess(parser, NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB
- + TAG_DESC_HUSBAND + TAG_DESC_FRIEND, new AddCommand(expectedPersonMultipleTags));
- }
-
- @Test
- public void parse_optionalFieldsMissing_success() {
- // zero tags
- Person expectedPerson = new PersonBuilder(AMY).withTags().build();
- assertParseSuccess(parser, NAME_DESC_AMY + PHONE_DESC_AMY + EMAIL_DESC_AMY + ADDRESS_DESC_AMY,
- new AddCommand(expectedPerson));
- }
-
- @Test
- public void parse_compulsoryFieldMissing_failure() {
- String expectedMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE);
-
- // missing name prefix
- assertParseFailure(parser, VALID_NAME_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB,
- expectedMessage);
-
- // missing phone prefix
- assertParseFailure(parser, NAME_DESC_BOB + VALID_PHONE_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB,
- expectedMessage);
-
- // missing email prefix
- assertParseFailure(parser, NAME_DESC_BOB + PHONE_DESC_BOB + VALID_EMAIL_BOB + ADDRESS_DESC_BOB,
- expectedMessage);
-
- // missing address prefix
- assertParseFailure(parser, NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + VALID_ADDRESS_BOB,
- expectedMessage);
-
- // all prefixes missing
- assertParseFailure(parser, VALID_NAME_BOB + VALID_PHONE_BOB + VALID_EMAIL_BOB + VALID_ADDRESS_BOB,
- expectedMessage);
- }
-
- @Test
- public void parse_invalidValue_failure() {
- // invalid name
- assertParseFailure(parser, INVALID_NAME_DESC + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB
- + TAG_DESC_HUSBAND + TAG_DESC_FRIEND, Name.MESSAGE_CONSTRAINTS);
-
- // invalid phone
- assertParseFailure(parser, NAME_DESC_BOB + INVALID_PHONE_DESC + EMAIL_DESC_BOB + ADDRESS_DESC_BOB
- + TAG_DESC_HUSBAND + TAG_DESC_FRIEND, Phone.MESSAGE_CONSTRAINTS);
-
- // invalid email
- assertParseFailure(parser, NAME_DESC_BOB + PHONE_DESC_BOB + INVALID_EMAIL_DESC + ADDRESS_DESC_BOB
- + TAG_DESC_HUSBAND + TAG_DESC_FRIEND, Email.MESSAGE_CONSTRAINTS);
-
- // invalid address
- assertParseFailure(parser, NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + INVALID_ADDRESS_DESC
- + TAG_DESC_HUSBAND + TAG_DESC_FRIEND, Address.MESSAGE_CONSTRAINTS);
-
- // invalid tag
- assertParseFailure(parser, NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB
- + INVALID_TAG_DESC + VALID_TAG_FRIEND, Tag.MESSAGE_CONSTRAINTS);
-
- // two invalid values, only first invalid value reported
- assertParseFailure(parser, INVALID_NAME_DESC + PHONE_DESC_BOB + EMAIL_DESC_BOB + INVALID_ADDRESS_DESC,
- Name.MESSAGE_CONSTRAINTS);
-
- // non-empty preamble
- assertParseFailure(parser, PREAMBLE_NON_EMPTY + NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB
- + ADDRESS_DESC_BOB + TAG_DESC_HUSBAND + TAG_DESC_FRIEND,
- String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE));
- }
-}
diff --git a/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java b/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java
deleted file mode 100644
index d9659205b57..00000000000
--- a/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java
+++ /dev/null
@@ -1,101 +0,0 @@
-package seedu.address.logic.parser;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
-import static seedu.address.commons.core.Messages.MESSAGE_UNKNOWN_COMMAND;
-import static seedu.address.testutil.Assert.assertThrows;
-import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.stream.Collectors;
-
-import org.junit.jupiter.api.Test;
-
-import seedu.address.logic.commands.AddCommand;
-import seedu.address.logic.commands.ClearCommand;
-import seedu.address.logic.commands.DeleteCommand;
-import seedu.address.logic.commands.EditCommand;
-import seedu.address.logic.commands.EditCommand.EditPersonDescriptor;
-import seedu.address.logic.commands.ExitCommand;
-import seedu.address.logic.commands.FindCommand;
-import seedu.address.logic.commands.HelpCommand;
-import seedu.address.logic.commands.ListCommand;
-import seedu.address.logic.parser.exceptions.ParseException;
-import seedu.address.model.person.NameContainsKeywordsPredicate;
-import seedu.address.model.person.Person;
-import seedu.address.testutil.EditPersonDescriptorBuilder;
-import seedu.address.testutil.PersonBuilder;
-import seedu.address.testutil.PersonUtil;
-
-public class AddressBookParserTest {
-
- private final AddressBookParser parser = new AddressBookParser();
-
- @Test
- public void parseCommand_add() throws Exception {
- Person person = new PersonBuilder().build();
- AddCommand command = (AddCommand) parser.parseCommand(PersonUtil.getAddCommand(person));
- assertEquals(new AddCommand(person), command);
- }
-
- @Test
- public void parseCommand_clear() throws Exception {
- assertTrue(parser.parseCommand(ClearCommand.COMMAND_WORD) instanceof ClearCommand);
- assertTrue(parser.parseCommand(ClearCommand.COMMAND_WORD + " 3") instanceof ClearCommand);
- }
-
- @Test
- public void parseCommand_delete() throws Exception {
- DeleteCommand command = (DeleteCommand) parser.parseCommand(
- DeleteCommand.COMMAND_WORD + " " + INDEX_FIRST_PERSON.getOneBased());
- assertEquals(new DeleteCommand(INDEX_FIRST_PERSON), command);
- }
-
- @Test
- public void parseCommand_edit() throws Exception {
- Person person = new PersonBuilder().build();
- EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(person).build();
- EditCommand command = (EditCommand) parser.parseCommand(EditCommand.COMMAND_WORD + " "
- + INDEX_FIRST_PERSON.getOneBased() + " " + PersonUtil.getEditPersonDescriptorDetails(descriptor));
- assertEquals(new EditCommand(INDEX_FIRST_PERSON, descriptor), command);
- }
-
- @Test
- public void parseCommand_exit() throws Exception {
- assertTrue(parser.parseCommand(ExitCommand.COMMAND_WORD) instanceof ExitCommand);
- assertTrue(parser.parseCommand(ExitCommand.COMMAND_WORD + " 3") instanceof ExitCommand);
- }
-
- @Test
- public void parseCommand_find() throws Exception {
- List keywords = Arrays.asList("foo", "bar", "baz");
- FindCommand command = (FindCommand) parser.parseCommand(
- FindCommand.COMMAND_WORD + " " + keywords.stream().collect(Collectors.joining(" ")));
- assertEquals(new FindCommand(new NameContainsKeywordsPredicate(keywords)), command);
- }
-
- @Test
- public void parseCommand_help() throws Exception {
- assertTrue(parser.parseCommand(HelpCommand.COMMAND_WORD) instanceof HelpCommand);
- assertTrue(parser.parseCommand(HelpCommand.COMMAND_WORD + " 3") instanceof HelpCommand);
- }
-
- @Test
- public void parseCommand_list() throws Exception {
- assertTrue(parser.parseCommand(ListCommand.COMMAND_WORD) instanceof ListCommand);
- assertTrue(parser.parseCommand(ListCommand.COMMAND_WORD + " 3") instanceof ListCommand);
- }
-
- @Test
- public void parseCommand_unrecognisedInput_throwsParseException() {
- assertThrows(ParseException.class, String.format(MESSAGE_INVALID_COMMAND_FORMAT, HelpCommand.MESSAGE_USAGE), ()
- -> parser.parseCommand(""));
- }
-
- @Test
- public void parseCommand_unknownCommand_throwsParseException() {
- assertThrows(ParseException.class, MESSAGE_UNKNOWN_COMMAND, () -> parser.parseCommand("unknownCommand"));
- }
-}
diff --git a/src/test/java/seedu/address/logic/parser/DeleteCommandParserTest.java b/src/test/java/seedu/address/logic/parser/DeleteCommandParserTest.java
deleted file mode 100644
index 27eaec84450..00000000000
--- a/src/test/java/seedu/address/logic/parser/DeleteCommandParserTest.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package seedu.address.logic.parser;
-
-import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
-import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure;
-import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess;
-import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
-
-import org.junit.jupiter.api.Test;
-
-import seedu.address.logic.commands.DeleteCommand;
-
-/**
- * As we are only doing white-box testing, our test cases do not cover path variations
- * outside of the DeleteCommand code. For example, inputs "1" and "1 abc" take the
- * same path through the DeleteCommand, and therefore we test only one of them.
- * The path variation for those two cases occur inside the ParserUtil, and
- * therefore should be covered by the ParserUtilTest.
- */
-public class DeleteCommandParserTest {
-
- private DeleteCommandParser parser = new DeleteCommandParser();
-
- @Test
- public void parse_validArgs_returnsDeleteCommand() {
- assertParseSuccess(parser, "1", new DeleteCommand(INDEX_FIRST_PERSON));
- }
-
- @Test
- public void parse_invalidArgs_throwsParseException() {
- assertParseFailure(parser, "a", String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE));
- }
-}
diff --git a/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java b/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java
deleted file mode 100644
index 2ff31522486..00000000000
--- a/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java
+++ /dev/null
@@ -1,211 +0,0 @@
-package seedu.address.logic.parser;
-
-import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
-import static seedu.address.logic.commands.CommandTestUtil.ADDRESS_DESC_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.ADDRESS_DESC_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.EMAIL_DESC_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.EMAIL_DESC_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.INVALID_ADDRESS_DESC;
-import static seedu.address.logic.commands.CommandTestUtil.INVALID_EMAIL_DESC;
-import static seedu.address.logic.commands.CommandTestUtil.INVALID_NAME_DESC;
-import static seedu.address.logic.commands.CommandTestUtil.INVALID_PHONE_DESC;
-import static seedu.address.logic.commands.CommandTestUtil.INVALID_TAG_DESC;
-import static seedu.address.logic.commands.CommandTestUtil.NAME_DESC_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.PHONE_DESC_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.PHONE_DESC_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.TAG_DESC_FRIEND;
-import static seedu.address.logic.commands.CommandTestUtil.TAG_DESC_HUSBAND;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_FRIEND;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
-import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure;
-import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess;
-import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
-import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PERSON;
-import static seedu.address.testutil.TypicalIndexes.INDEX_THIRD_PERSON;
-
-import org.junit.jupiter.api.Test;
-
-import seedu.address.commons.core.index.Index;
-import seedu.address.logic.commands.EditCommand;
-import seedu.address.logic.commands.EditCommand.EditPersonDescriptor;
-import seedu.address.model.person.Address;
-import seedu.address.model.person.Email;
-import seedu.address.model.person.Name;
-import seedu.address.model.person.Phone;
-import seedu.address.model.tag.Tag;
-import seedu.address.testutil.EditPersonDescriptorBuilder;
-
-public class EditCommandParserTest {
-
- private static final String TAG_EMPTY = " " + PREFIX_TAG;
-
- private static final String MESSAGE_INVALID_FORMAT =
- String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditCommand.MESSAGE_USAGE);
-
- private EditCommandParser parser = new EditCommandParser();
-
- @Test
- public void parse_missingParts_failure() {
- // no index specified
- assertParseFailure(parser, VALID_NAME_AMY, MESSAGE_INVALID_FORMAT);
-
- // no field specified
- assertParseFailure(parser, "1", EditCommand.MESSAGE_NOT_EDITED);
-
- // no index and no field specified
- assertParseFailure(parser, "", MESSAGE_INVALID_FORMAT);
- }
-
- @Test
- public void parse_invalidPreamble_failure() {
- // negative index
- assertParseFailure(parser, "-5" + NAME_DESC_AMY, MESSAGE_INVALID_FORMAT);
-
- // zero index
- assertParseFailure(parser, "0" + NAME_DESC_AMY, MESSAGE_INVALID_FORMAT);
-
- // invalid arguments being parsed as preamble
- assertParseFailure(parser, "1 some random string", MESSAGE_INVALID_FORMAT);
-
- // invalid prefix being parsed as preamble
- assertParseFailure(parser, "1 i/ string", MESSAGE_INVALID_FORMAT);
- }
-
- @Test
- public void parse_invalidValue_failure() {
- assertParseFailure(parser, "1" + INVALID_NAME_DESC, Name.MESSAGE_CONSTRAINTS); // invalid name
- assertParseFailure(parser, "1" + INVALID_PHONE_DESC, Phone.MESSAGE_CONSTRAINTS); // invalid phone
- assertParseFailure(parser, "1" + INVALID_EMAIL_DESC, Email.MESSAGE_CONSTRAINTS); // invalid email
- assertParseFailure(parser, "1" + INVALID_ADDRESS_DESC, Address.MESSAGE_CONSTRAINTS); // invalid address
- assertParseFailure(parser, "1" + INVALID_TAG_DESC, Tag.MESSAGE_CONSTRAINTS); // invalid tag
-
- // invalid phone followed by valid email
- assertParseFailure(parser, "1" + INVALID_PHONE_DESC + EMAIL_DESC_AMY, Phone.MESSAGE_CONSTRAINTS);
-
- // valid phone followed by invalid phone. The test case for invalid phone followed by valid phone
- // is tested at {@code parse_invalidValueFollowedByValidValue_success()}
- assertParseFailure(parser, "1" + PHONE_DESC_BOB + INVALID_PHONE_DESC, Phone.MESSAGE_CONSTRAINTS);
-
- // while parsing {@code PREFIX_TAG} alone will reset the tags of the {@code Person} being edited,
- // parsing it together with a valid tag results in error
- assertParseFailure(parser, "1" + TAG_DESC_FRIEND + TAG_DESC_HUSBAND + TAG_EMPTY, Tag.MESSAGE_CONSTRAINTS);
- assertParseFailure(parser, "1" + TAG_DESC_FRIEND + TAG_EMPTY + TAG_DESC_HUSBAND, Tag.MESSAGE_CONSTRAINTS);
- assertParseFailure(parser, "1" + TAG_EMPTY + TAG_DESC_FRIEND + TAG_DESC_HUSBAND, Tag.MESSAGE_CONSTRAINTS);
-
- // multiple invalid values, but only the first invalid value is captured
- assertParseFailure(parser, "1" + INVALID_NAME_DESC + INVALID_EMAIL_DESC + VALID_ADDRESS_AMY + VALID_PHONE_AMY,
- Name.MESSAGE_CONSTRAINTS);
- }
-
- @Test
- public void parse_allFieldsSpecified_success() {
- Index targetIndex = INDEX_SECOND_PERSON;
- String userInput = targetIndex.getOneBased() + PHONE_DESC_BOB + TAG_DESC_HUSBAND
- + EMAIL_DESC_AMY + ADDRESS_DESC_AMY + NAME_DESC_AMY + TAG_DESC_FRIEND;
-
- EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withName(VALID_NAME_AMY)
- .withPhone(VALID_PHONE_BOB).withEmail(VALID_EMAIL_AMY).withAddress(VALID_ADDRESS_AMY)
- .withTags(VALID_TAG_HUSBAND, VALID_TAG_FRIEND).build();
- EditCommand expectedCommand = new EditCommand(targetIndex, descriptor);
-
- assertParseSuccess(parser, userInput, expectedCommand);
- }
-
- @Test
- public void parse_someFieldsSpecified_success() {
- Index targetIndex = INDEX_FIRST_PERSON;
- String userInput = targetIndex.getOneBased() + PHONE_DESC_BOB + EMAIL_DESC_AMY;
-
- EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withPhone(VALID_PHONE_BOB)
- .withEmail(VALID_EMAIL_AMY).build();
- EditCommand expectedCommand = new EditCommand(targetIndex, descriptor);
-
- assertParseSuccess(parser, userInput, expectedCommand);
- }
-
- @Test
- public void parse_oneFieldSpecified_success() {
- // name
- Index targetIndex = INDEX_THIRD_PERSON;
- String userInput = targetIndex.getOneBased() + NAME_DESC_AMY;
- EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withName(VALID_NAME_AMY).build();
- EditCommand expectedCommand = new EditCommand(targetIndex, descriptor);
- assertParseSuccess(parser, userInput, expectedCommand);
-
- // phone
- userInput = targetIndex.getOneBased() + PHONE_DESC_AMY;
- descriptor = new EditPersonDescriptorBuilder().withPhone(VALID_PHONE_AMY).build();
- expectedCommand = new EditCommand(targetIndex, descriptor);
- assertParseSuccess(parser, userInput, expectedCommand);
-
- // email
- userInput = targetIndex.getOneBased() + EMAIL_DESC_AMY;
- descriptor = new EditPersonDescriptorBuilder().withEmail(VALID_EMAIL_AMY).build();
- expectedCommand = new EditCommand(targetIndex, descriptor);
- assertParseSuccess(parser, userInput, expectedCommand);
-
- // address
- userInput = targetIndex.getOneBased() + ADDRESS_DESC_AMY;
- descriptor = new EditPersonDescriptorBuilder().withAddress(VALID_ADDRESS_AMY).build();
- expectedCommand = new EditCommand(targetIndex, descriptor);
- assertParseSuccess(parser, userInput, expectedCommand);
-
- // tags
- userInput = targetIndex.getOneBased() + TAG_DESC_FRIEND;
- descriptor = new EditPersonDescriptorBuilder().withTags(VALID_TAG_FRIEND).build();
- expectedCommand = new EditCommand(targetIndex, descriptor);
- assertParseSuccess(parser, userInput, expectedCommand);
- }
-
- @Test
- public void parse_multipleRepeatedFields_acceptsLast() {
- Index targetIndex = INDEX_FIRST_PERSON;
- String userInput = targetIndex.getOneBased() + PHONE_DESC_AMY + ADDRESS_DESC_AMY + EMAIL_DESC_AMY
- + TAG_DESC_FRIEND + PHONE_DESC_AMY + ADDRESS_DESC_AMY + EMAIL_DESC_AMY + TAG_DESC_FRIEND
- + PHONE_DESC_BOB + ADDRESS_DESC_BOB + EMAIL_DESC_BOB + TAG_DESC_HUSBAND;
-
- EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withPhone(VALID_PHONE_BOB)
- .withEmail(VALID_EMAIL_BOB).withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_FRIEND, VALID_TAG_HUSBAND)
- .build();
- EditCommand expectedCommand = new EditCommand(targetIndex, descriptor);
-
- assertParseSuccess(parser, userInput, expectedCommand);
- }
-
- @Test
- public void parse_invalidValueFollowedByValidValue_success() {
- // no other valid values specified
- Index targetIndex = INDEX_FIRST_PERSON;
- String userInput = targetIndex.getOneBased() + INVALID_PHONE_DESC + PHONE_DESC_BOB;
- EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withPhone(VALID_PHONE_BOB).build();
- EditCommand expectedCommand = new EditCommand(targetIndex, descriptor);
- assertParseSuccess(parser, userInput, expectedCommand);
-
- // other valid values specified
- userInput = targetIndex.getOneBased() + EMAIL_DESC_BOB + INVALID_PHONE_DESC + ADDRESS_DESC_BOB
- + PHONE_DESC_BOB;
- descriptor = new EditPersonDescriptorBuilder().withPhone(VALID_PHONE_BOB).withEmail(VALID_EMAIL_BOB)
- .withAddress(VALID_ADDRESS_BOB).build();
- expectedCommand = new EditCommand(targetIndex, descriptor);
- assertParseSuccess(parser, userInput, expectedCommand);
- }
-
- @Test
- public void parse_resetTags_success() {
- Index targetIndex = INDEX_THIRD_PERSON;
- String userInput = targetIndex.getOneBased() + TAG_EMPTY;
-
- EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withTags().build();
- EditCommand expectedCommand = new EditCommand(targetIndex, descriptor);
-
- assertParseSuccess(parser, userInput, expectedCommand);
- }
-}
diff --git a/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java b/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java
deleted file mode 100644
index 70f4f0e79c4..00000000000
--- a/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package seedu.address.logic.parser;
-
-import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
-import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure;
-import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess;
-
-import java.util.Arrays;
-
-import org.junit.jupiter.api.Test;
-
-import seedu.address.logic.commands.FindCommand;
-import seedu.address.model.person.NameContainsKeywordsPredicate;
-
-public class FindCommandParserTest {
-
- private FindCommandParser parser = new FindCommandParser();
-
- @Test
- public void parse_emptyArg_throwsParseException() {
- assertParseFailure(parser, " ", String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_USAGE));
- }
-
- @Test
- public void parse_validArgs_returnsFindCommand() {
- // no leading and trailing whitespaces
- FindCommand expectedFindCommand =
- new FindCommand(new NameContainsKeywordsPredicate(Arrays.asList("Alice", "Bob")));
- assertParseSuccess(parser, "Alice Bob", expectedFindCommand);
-
- // multiple whitespaces between keywords
- assertParseSuccess(parser, " \n Alice \n \t Bob \t", expectedFindCommand);
- }
-
-}
diff --git a/src/test/java/seedu/address/logic/parser/ParserUtilTest.java b/src/test/java/seedu/address/logic/parser/ParserUtilTest.java
deleted file mode 100644
index 4256788b1a7..00000000000
--- a/src/test/java/seedu/address/logic/parser/ParserUtilTest.java
+++ /dev/null
@@ -1,196 +0,0 @@
-package seedu.address.logic.parser;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.logic.parser.ParserUtil.MESSAGE_INVALID_INDEX;
-import static seedu.address.testutil.Assert.assertThrows;
-import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
-import org.junit.jupiter.api.Test;
-
-import seedu.address.logic.parser.exceptions.ParseException;
-import seedu.address.model.person.Address;
-import seedu.address.model.person.Email;
-import seedu.address.model.person.Name;
-import seedu.address.model.person.Phone;
-import seedu.address.model.tag.Tag;
-
-public class ParserUtilTest {
- private static final String INVALID_NAME = "R@chel";
- private static final String INVALID_PHONE = "+651234";
- private static final String INVALID_ADDRESS = " ";
- private static final String INVALID_EMAIL = "example.com";
- private static final String INVALID_TAG = "#friend";
-
- private static final String VALID_NAME = "Rachel Walker";
- private static final String VALID_PHONE = "123456";
- private static final String VALID_ADDRESS = "123 Main Street #0505";
- private static final String VALID_EMAIL = "rachel@example.com";
- private static final String VALID_TAG_1 = "friend";
- private static final String VALID_TAG_2 = "neighbour";
-
- private static final String WHITESPACE = " \t\r\n";
-
- @Test
- public void parseIndex_invalidInput_throwsParseException() {
- assertThrows(ParseException.class, () -> ParserUtil.parseIndex("10 a"));
- }
-
- @Test
- public void parseIndex_outOfRangeInput_throwsParseException() {
- assertThrows(ParseException.class, MESSAGE_INVALID_INDEX, ()
- -> ParserUtil.parseIndex(Long.toString(Integer.MAX_VALUE + 1)));
- }
-
- @Test
- public void parseIndex_validInput_success() throws Exception {
- // No whitespaces
- assertEquals(INDEX_FIRST_PERSON, ParserUtil.parseIndex("1"));
-
- // Leading and trailing whitespaces
- assertEquals(INDEX_FIRST_PERSON, ParserUtil.parseIndex(" 1 "));
- }
-
- @Test
- public void parseName_null_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> ParserUtil.parseName((String) null));
- }
-
- @Test
- public void parseName_invalidValue_throwsParseException() {
- assertThrows(ParseException.class, () -> ParserUtil.parseName(INVALID_NAME));
- }
-
- @Test
- public void parseName_validValueWithoutWhitespace_returnsName() throws Exception {
- Name expectedName = new Name(VALID_NAME);
- assertEquals(expectedName, ParserUtil.parseName(VALID_NAME));
- }
-
- @Test
- public void parseName_validValueWithWhitespace_returnsTrimmedName() throws Exception {
- String nameWithWhitespace = WHITESPACE + VALID_NAME + WHITESPACE;
- Name expectedName = new Name(VALID_NAME);
- assertEquals(expectedName, ParserUtil.parseName(nameWithWhitespace));
- }
-
- @Test
- public void parsePhone_null_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> ParserUtil.parsePhone((String) null));
- }
-
- @Test
- public void parsePhone_invalidValue_throwsParseException() {
- assertThrows(ParseException.class, () -> ParserUtil.parsePhone(INVALID_PHONE));
- }
-
- @Test
- public void parsePhone_validValueWithoutWhitespace_returnsPhone() throws Exception {
- Phone expectedPhone = new Phone(VALID_PHONE);
- assertEquals(expectedPhone, ParserUtil.parsePhone(VALID_PHONE));
- }
-
- @Test
- public void parsePhone_validValueWithWhitespace_returnsTrimmedPhone() throws Exception {
- String phoneWithWhitespace = WHITESPACE + VALID_PHONE + WHITESPACE;
- Phone expectedPhone = new Phone(VALID_PHONE);
- assertEquals(expectedPhone, ParserUtil.parsePhone(phoneWithWhitespace));
- }
-
- @Test
- public void parseAddress_null_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> ParserUtil.parseAddress((String) null));
- }
-
- @Test
- public void parseAddress_invalidValue_throwsParseException() {
- assertThrows(ParseException.class, () -> ParserUtil.parseAddress(INVALID_ADDRESS));
- }
-
- @Test
- public void parseAddress_validValueWithoutWhitespace_returnsAddress() throws Exception {
- Address expectedAddress = new Address(VALID_ADDRESS);
- assertEquals(expectedAddress, ParserUtil.parseAddress(VALID_ADDRESS));
- }
-
- @Test
- public void parseAddress_validValueWithWhitespace_returnsTrimmedAddress() throws Exception {
- String addressWithWhitespace = WHITESPACE + VALID_ADDRESS + WHITESPACE;
- Address expectedAddress = new Address(VALID_ADDRESS);
- assertEquals(expectedAddress, ParserUtil.parseAddress(addressWithWhitespace));
- }
-
- @Test
- public void parseEmail_null_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> ParserUtil.parseEmail((String) null));
- }
-
- @Test
- public void parseEmail_invalidValue_throwsParseException() {
- assertThrows(ParseException.class, () -> ParserUtil.parseEmail(INVALID_EMAIL));
- }
-
- @Test
- public void parseEmail_validValueWithoutWhitespace_returnsEmail() throws Exception {
- Email expectedEmail = new Email(VALID_EMAIL);
- assertEquals(expectedEmail, ParserUtil.parseEmail(VALID_EMAIL));
- }
-
- @Test
- public void parseEmail_validValueWithWhitespace_returnsTrimmedEmail() throws Exception {
- String emailWithWhitespace = WHITESPACE + VALID_EMAIL + WHITESPACE;
- Email expectedEmail = new Email(VALID_EMAIL);
- assertEquals(expectedEmail, ParserUtil.parseEmail(emailWithWhitespace));
- }
-
- @Test
- public void parseTag_null_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> ParserUtil.parseTag(null));
- }
-
- @Test
- public void parseTag_invalidValue_throwsParseException() {
- assertThrows(ParseException.class, () -> ParserUtil.parseTag(INVALID_TAG));
- }
-
- @Test
- public void parseTag_validValueWithoutWhitespace_returnsTag() throws Exception {
- Tag expectedTag = new Tag(VALID_TAG_1);
- assertEquals(expectedTag, ParserUtil.parseTag(VALID_TAG_1));
- }
-
- @Test
- public void parseTag_validValueWithWhitespace_returnsTrimmedTag() throws Exception {
- String tagWithWhitespace = WHITESPACE + VALID_TAG_1 + WHITESPACE;
- Tag expectedTag = new Tag(VALID_TAG_1);
- assertEquals(expectedTag, ParserUtil.parseTag(tagWithWhitespace));
- }
-
- @Test
- public void parseTags_null_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> ParserUtil.parseTags(null));
- }
-
- @Test
- public void parseTags_collectionWithInvalidTags_throwsParseException() {
- assertThrows(ParseException.class, () -> ParserUtil.parseTags(Arrays.asList(VALID_TAG_1, INVALID_TAG)));
- }
-
- @Test
- public void parseTags_emptyCollection_returnsEmptySet() throws Exception {
- assertTrue(ParserUtil.parseTags(Collections.emptyList()).isEmpty());
- }
-
- @Test
- public void parseTags_collectionWithValidTags_returnsTagSet() throws Exception {
- Set actualTagSet = ParserUtil.parseTags(Arrays.asList(VALID_TAG_1, VALID_TAG_2));
- Set expectedTagSet = new HashSet(Arrays.asList(new Tag(VALID_TAG_1), new Tag(VALID_TAG_2)));
-
- assertEquals(expectedTagSet, actualTagSet);
- }
-}
diff --git a/src/test/java/seedu/address/model/AddressBookTest.java b/src/test/java/seedu/address/model/AddressBookTest.java
deleted file mode 100644
index 87782528ecd..00000000000
--- a/src/test/java/seedu/address/model/AddressBookTest.java
+++ /dev/null
@@ -1,102 +0,0 @@
-package seedu.address.model;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND;
-import static seedu.address.testutil.Assert.assertThrows;
-import static seedu.address.testutil.TypicalPersons.ALICE;
-import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
-import org.junit.jupiter.api.Test;
-
-import javafx.collections.FXCollections;
-import javafx.collections.ObservableList;
-import seedu.address.model.person.Person;
-import seedu.address.model.person.exceptions.DuplicatePersonException;
-import seedu.address.testutil.PersonBuilder;
-
-public class AddressBookTest {
-
- private final AddressBook addressBook = new AddressBook();
-
- @Test
- public void constructor() {
- assertEquals(Collections.emptyList(), addressBook.getPersonList());
- }
-
- @Test
- public void resetData_null_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> addressBook.resetData(null));
- }
-
- @Test
- public void resetData_withValidReadOnlyAddressBook_replacesData() {
- AddressBook newData = getTypicalAddressBook();
- addressBook.resetData(newData);
- assertEquals(newData, addressBook);
- }
-
- @Test
- public void resetData_withDuplicatePersons_throwsDuplicatePersonException() {
- // Two persons with the same identity fields
- Person editedAlice = new PersonBuilder(ALICE).withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND)
- .build();
- List newPersons = Arrays.asList(ALICE, editedAlice);
- AddressBookStub newData = new AddressBookStub(newPersons);
-
- assertThrows(DuplicatePersonException.class, () -> addressBook.resetData(newData));
- }
-
- @Test
- public void hasPerson_nullPerson_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> addressBook.hasPerson(null));
- }
-
- @Test
- public void hasPerson_personNotInAddressBook_returnsFalse() {
- assertFalse(addressBook.hasPerson(ALICE));
- }
-
- @Test
- public void hasPerson_personInAddressBook_returnsTrue() {
- addressBook.addPerson(ALICE);
- assertTrue(addressBook.hasPerson(ALICE));
- }
-
- @Test
- public void hasPerson_personWithSameIdentityFieldsInAddressBook_returnsTrue() {
- addressBook.addPerson(ALICE);
- Person editedAlice = new PersonBuilder(ALICE).withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND)
- .build();
- assertTrue(addressBook.hasPerson(editedAlice));
- }
-
- @Test
- public void getPersonList_modifyList_throwsUnsupportedOperationException() {
- assertThrows(UnsupportedOperationException.class, () -> addressBook.getPersonList().remove(0));
- }
-
- /**
- * A stub ReadOnlyAddressBook whose persons list can violate interface constraints.
- */
- private static class AddressBookStub implements ReadOnlyAddressBook {
- private final ObservableList persons = FXCollections.observableArrayList();
-
- AddressBookStub(Collection persons) {
- this.persons.setAll(persons);
- }
-
- @Override
- public ObservableList getPersonList() {
- return persons;
- }
- }
-
-}
diff --git a/src/test/java/seedu/address/model/person/AddressTest.java b/src/test/java/seedu/address/model/person/AddressTest.java
deleted file mode 100644
index dcd3be87b3a..00000000000
--- a/src/test/java/seedu/address/model/person/AddressTest.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package seedu.address.model.person;
-
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.testutil.Assert.assertThrows;
-
-import org.junit.jupiter.api.Test;
-
-public class AddressTest {
-
- @Test
- public void constructor_null_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> new Address(null));
- }
-
- @Test
- public void constructor_invalidAddress_throwsIllegalArgumentException() {
- String invalidAddress = "";
- assertThrows(IllegalArgumentException.class, () -> new Address(invalidAddress));
- }
-
- @Test
- public void isValidAddress() {
- // null address
- assertThrows(NullPointerException.class, () -> Address.isValidAddress(null));
-
- // invalid addresses
- assertFalse(Address.isValidAddress("")); // empty string
- assertFalse(Address.isValidAddress(" ")); // spaces only
-
- // valid addresses
- assertTrue(Address.isValidAddress("Blk 456, Den Road, #01-355"));
- assertTrue(Address.isValidAddress("-")); // one character
- assertTrue(Address.isValidAddress("Leng Inc; 1234 Market St; San Francisco CA 2349879; USA")); // long address
- }
-}
diff --git a/src/test/java/seedu/address/model/tag/TagTest.java b/src/test/java/seedu/address/model/tag/TagTest.java
deleted file mode 100644
index 64d07d79ee2..00000000000
--- a/src/test/java/seedu/address/model/tag/TagTest.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package seedu.address.model.tag;
-
-import static seedu.address.testutil.Assert.assertThrows;
-
-import org.junit.jupiter.api.Test;
-
-public class TagTest {
-
- @Test
- public void constructor_null_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> new Tag(null));
- }
-
- @Test
- public void constructor_invalidTagName_throwsIllegalArgumentException() {
- String invalidTagName = "";
- assertThrows(IllegalArgumentException.class, () -> new Tag(invalidTagName));
- }
-
- @Test
- public void isValidTagName() {
- // null tag name
- assertThrows(NullPointerException.class, () -> Tag.isValidTagName(null));
- }
-
-}
diff --git a/src/test/java/seedu/address/storage/JsonAddressBookStorageTest.java b/src/test/java/seedu/address/storage/JsonAddressBookStorageTest.java
deleted file mode 100644
index ac3c3af9566..00000000000
--- a/src/test/java/seedu/address/storage/JsonAddressBookStorageTest.java
+++ /dev/null
@@ -1,110 +0,0 @@
-package seedu.address.storage;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static seedu.address.testutil.Assert.assertThrows;
-import static seedu.address.testutil.TypicalPersons.ALICE;
-import static seedu.address.testutil.TypicalPersons.HOON;
-import static seedu.address.testutil.TypicalPersons.IDA;
-import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;
-
-import java.io.IOException;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.io.TempDir;
-
-import seedu.address.commons.exceptions.DataConversionException;
-import seedu.address.model.AddressBook;
-import seedu.address.model.ReadOnlyAddressBook;
-
-public class JsonAddressBookStorageTest {
- private static final Path TEST_DATA_FOLDER = Paths.get("src", "test", "data", "JsonAddressBookStorageTest");
-
- @TempDir
- public Path testFolder;
-
- @Test
- public void readAddressBook_nullFilePath_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> readAddressBook(null));
- }
-
- private java.util.Optional readAddressBook(String filePath) throws Exception {
- return new JsonAddressBookStorage(Paths.get(filePath)).readAddressBook(addToTestDataPathIfNotNull(filePath));
- }
-
- private Path addToTestDataPathIfNotNull(String prefsFileInTestDataFolder) {
- return prefsFileInTestDataFolder != null
- ? TEST_DATA_FOLDER.resolve(prefsFileInTestDataFolder)
- : null;
- }
-
- @Test
- public void read_missingFile_emptyResult() throws Exception {
- assertFalse(readAddressBook("NonExistentFile.json").isPresent());
- }
-
- @Test
- public void read_notJsonFormat_exceptionThrown() {
- assertThrows(DataConversionException.class, () -> readAddressBook("notJsonFormatAddressBook.json"));
- }
-
- @Test
- public void readAddressBook_invalidPersonAddressBook_throwDataConversionException() {
- assertThrows(DataConversionException.class, () -> readAddressBook("invalidPersonAddressBook.json"));
- }
-
- @Test
- public void readAddressBook_invalidAndValidPersonAddressBook_throwDataConversionException() {
- assertThrows(DataConversionException.class, () -> readAddressBook("invalidAndValidPersonAddressBook.json"));
- }
-
- @Test
- public void readAndSaveAddressBook_allInOrder_success() throws Exception {
- Path filePath = testFolder.resolve("TempAddressBook.json");
- AddressBook original = getTypicalAddressBook();
- JsonAddressBookStorage jsonAddressBookStorage = new JsonAddressBookStorage(filePath);
-
- // Save in new file and read back
- jsonAddressBookStorage.saveAddressBook(original, filePath);
- ReadOnlyAddressBook readBack = jsonAddressBookStorage.readAddressBook(filePath).get();
- assertEquals(original, new AddressBook(readBack));
-
- // Modify data, overwrite exiting file, and read back
- original.addPerson(HOON);
- original.removePerson(ALICE);
- jsonAddressBookStorage.saveAddressBook(original, filePath);
- readBack = jsonAddressBookStorage.readAddressBook(filePath).get();
- assertEquals(original, new AddressBook(readBack));
-
- // Save and read without specifying file path
- original.addPerson(IDA);
- jsonAddressBookStorage.saveAddressBook(original); // file path not specified
- readBack = jsonAddressBookStorage.readAddressBook().get(); // file path not specified
- assertEquals(original, new AddressBook(readBack));
-
- }
-
- @Test
- public void saveAddressBook_nullAddressBook_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> saveAddressBook(null, "SomeFile.json"));
- }
-
- /**
- * Saves {@code addressBook} at the specified {@code filePath}.
- */
- private void saveAddressBook(ReadOnlyAddressBook addressBook, String filePath) {
- try {
- new JsonAddressBookStorage(Paths.get(filePath))
- .saveAddressBook(addressBook, addToTestDataPathIfNotNull(filePath));
- } catch (IOException ioe) {
- throw new AssertionError("There should not be an error writing to the file.", ioe);
- }
- }
-
- @Test
- public void saveAddressBook_nullFilePath_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> saveAddressBook(new AddressBook(), null));
- }
-}
diff --git a/src/test/java/seedu/address/storage/JsonSerializableAddressBookTest.java b/src/test/java/seedu/address/storage/JsonSerializableAddressBookTest.java
deleted file mode 100644
index 188c9058d20..00000000000
--- a/src/test/java/seedu/address/storage/JsonSerializableAddressBookTest.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package seedu.address.storage;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static seedu.address.testutil.Assert.assertThrows;
-
-import java.nio.file.Path;
-import java.nio.file.Paths;
-
-import org.junit.jupiter.api.Test;
-
-import seedu.address.commons.exceptions.IllegalValueException;
-import seedu.address.commons.util.JsonUtil;
-import seedu.address.model.AddressBook;
-import seedu.address.testutil.TypicalPersons;
-
-public class JsonSerializableAddressBookTest {
-
- private static final Path TEST_DATA_FOLDER = Paths.get("src", "test", "data", "JsonSerializableAddressBookTest");
- private static final Path TYPICAL_PERSONS_FILE = TEST_DATA_FOLDER.resolve("typicalPersonsAddressBook.json");
- private static final Path INVALID_PERSON_FILE = TEST_DATA_FOLDER.resolve("invalidPersonAddressBook.json");
- private static final Path DUPLICATE_PERSON_FILE = TEST_DATA_FOLDER.resolve("duplicatePersonAddressBook.json");
-
- @Test
- public void toModelType_typicalPersonsFile_success() throws Exception {
- JsonSerializableAddressBook dataFromFile = JsonUtil.readJsonFile(TYPICAL_PERSONS_FILE,
- JsonSerializableAddressBook.class).get();
- AddressBook addressBookFromFile = dataFromFile.toModelType();
- AddressBook typicalPersonsAddressBook = TypicalPersons.getTypicalAddressBook();
- assertEquals(addressBookFromFile, typicalPersonsAddressBook);
- }
-
- @Test
- public void toModelType_invalidPersonFile_throwsIllegalValueException() throws Exception {
- JsonSerializableAddressBook dataFromFile = JsonUtil.readJsonFile(INVALID_PERSON_FILE,
- JsonSerializableAddressBook.class).get();
- assertThrows(IllegalValueException.class, dataFromFile::toModelType);
- }
-
- @Test
- public void toModelType_duplicatePersons_throwsIllegalValueException() throws Exception {
- JsonSerializableAddressBook dataFromFile = JsonUtil.readJsonFile(DUPLICATE_PERSON_FILE,
- JsonSerializableAddressBook.class).get();
- assertThrows(IllegalValueException.class, JsonSerializableAddressBook.MESSAGE_DUPLICATE_PERSON,
- dataFromFile::toModelType);
- }
-
-}
diff --git a/src/test/java/seedu/address/testutil/AddressBookBuilder.java b/src/test/java/seedu/address/testutil/AddressBookBuilder.java
deleted file mode 100644
index d53799fd110..00000000000
--- a/src/test/java/seedu/address/testutil/AddressBookBuilder.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package seedu.address.testutil;
-
-import seedu.address.model.AddressBook;
-import seedu.address.model.person.Person;
-
-/**
- * A utility class to help with building Addressbook objects.
- * Example usage:
- * {@code AddressBook ab = new AddressBookBuilder().withPerson("John", "Doe").build();}
- */
-public class AddressBookBuilder {
-
- private AddressBook addressBook;
-
- public AddressBookBuilder() {
- addressBook = new AddressBook();
- }
-
- public AddressBookBuilder(AddressBook addressBook) {
- this.addressBook = addressBook;
- }
-
- /**
- * Adds a new {@code Person} to the {@code AddressBook} that we are building.
- */
- public AddressBookBuilder withPerson(Person person) {
- addressBook.addPerson(person);
- return this;
- }
-
- public AddressBook build() {
- return addressBook;
- }
-}
diff --git a/src/test/java/seedu/address/testutil/EditPersonDescriptorBuilder.java b/src/test/java/seedu/address/testutil/EditPersonDescriptorBuilder.java
deleted file mode 100644
index 4584bd5044e..00000000000
--- a/src/test/java/seedu/address/testutil/EditPersonDescriptorBuilder.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package seedu.address.testutil;
-
-import java.util.Set;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import seedu.address.logic.commands.EditCommand.EditPersonDescriptor;
-import seedu.address.model.person.Address;
-import seedu.address.model.person.Email;
-import seedu.address.model.person.Name;
-import seedu.address.model.person.Person;
-import seedu.address.model.person.Phone;
-import seedu.address.model.tag.Tag;
-
-/**
- * A utility class to help with building EditPersonDescriptor objects.
- */
-public class EditPersonDescriptorBuilder {
-
- private EditPersonDescriptor descriptor;
-
- public EditPersonDescriptorBuilder() {
- descriptor = new EditPersonDescriptor();
- }
-
- public EditPersonDescriptorBuilder(EditPersonDescriptor descriptor) {
- this.descriptor = new EditPersonDescriptor(descriptor);
- }
-
- /**
- * Returns an {@code EditPersonDescriptor} with fields containing {@code person}'s details
- */
- public EditPersonDescriptorBuilder(Person person) {
- descriptor = new EditPersonDescriptor();
- descriptor.setName(person.getName());
- descriptor.setPhone(person.getPhone());
- descriptor.setEmail(person.getEmail());
- descriptor.setAddress(person.getAddress());
- descriptor.setTags(person.getTags());
- }
-
- /**
- * Sets the {@code Name} of the {@code EditPersonDescriptor} that we are building.
- */
- public EditPersonDescriptorBuilder withName(String name) {
- descriptor.setName(new Name(name));
- return this;
- }
-
- /**
- * Sets the {@code Phone} of the {@code EditPersonDescriptor} that we are building.
- */
- public EditPersonDescriptorBuilder withPhone(String phone) {
- descriptor.setPhone(new Phone(phone));
- return this;
- }
-
- /**
- * Sets the {@code Email} of the {@code EditPersonDescriptor} that we are building.
- */
- public EditPersonDescriptorBuilder withEmail(String email) {
- descriptor.setEmail(new Email(email));
- return this;
- }
-
- /**
- * Sets the {@code Address} of the {@code EditPersonDescriptor} that we are building.
- */
- public EditPersonDescriptorBuilder withAddress(String address) {
- descriptor.setAddress(new Address(address));
- return this;
- }
-
- /**
- * Parses the {@code tags} into a {@code Set} and set it to the {@code EditPersonDescriptor}
- * that we are building.
- */
- public EditPersonDescriptorBuilder withTags(String... tags) {
- Set tagSet = Stream.of(tags).map(Tag::new).collect(Collectors.toSet());
- descriptor.setTags(tagSet);
- return this;
- }
-
- public EditPersonDescriptor build() {
- return descriptor;
- }
-}
diff --git a/src/test/java/seedu/address/testutil/PersonUtil.java b/src/test/java/seedu/address/testutil/PersonUtil.java
deleted file mode 100644
index 90849945183..00000000000
--- a/src/test/java/seedu/address/testutil/PersonUtil.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package seedu.address.testutil;
-
-import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
-
-import java.util.Set;
-
-import seedu.address.logic.commands.AddCommand;
-import seedu.address.logic.commands.EditCommand.EditPersonDescriptor;
-import seedu.address.model.person.Person;
-import seedu.address.model.tag.Tag;
-
-/**
- * A utility class for Person.
- */
-public class PersonUtil {
-
- /**
- * Returns an add command string for adding the {@code person}.
- */
- public static String getAddCommand(Person person) {
- return AddCommand.COMMAND_WORD + " " + getPersonDetails(person);
- }
-
- /**
- * Returns the part of command string for the given {@code person}'s details.
- */
- public static String getPersonDetails(Person person) {
- StringBuilder sb = new StringBuilder();
- sb.append(PREFIX_NAME + person.getName().fullName + " ");
- sb.append(PREFIX_PHONE + person.getPhone().value + " ");
- sb.append(PREFIX_EMAIL + person.getEmail().value + " ");
- sb.append(PREFIX_ADDRESS + person.getAddress().value + " ");
- person.getTags().stream().forEach(
- s -> sb.append(PREFIX_TAG + s.tagName + " ")
- );
- return sb.toString();
- }
-
- /**
- * Returns the part of command string for the given {@code EditPersonDescriptor}'s details.
- */
- public static String getEditPersonDescriptorDetails(EditPersonDescriptor descriptor) {
- StringBuilder sb = new StringBuilder();
- descriptor.getName().ifPresent(name -> sb.append(PREFIX_NAME).append(name.fullName).append(" "));
- descriptor.getPhone().ifPresent(phone -> sb.append(PREFIX_PHONE).append(phone.value).append(" "));
- descriptor.getEmail().ifPresent(email -> sb.append(PREFIX_EMAIL).append(email.value).append(" "));
- descriptor.getAddress().ifPresent(address -> sb.append(PREFIX_ADDRESS).append(address.value).append(" "));
- if (descriptor.getTags().isPresent()) {
- Set tags = descriptor.getTags().get();
- if (tags.isEmpty()) {
- sb.append(PREFIX_TAG);
- } else {
- tags.forEach(s -> sb.append(PREFIX_TAG).append(s.tagName).append(" "));
- }
- }
- return sb.toString();
- }
-}
diff --git a/src/test/java/seedu/address/testutil/TypicalPersons.java b/src/test/java/seedu/address/testutil/TypicalPersons.java
deleted file mode 100644
index fec76fb7129..00000000000
--- a/src/test/java/seedu/address/testutil/TypicalPersons.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package seedu.address.testutil;
-
-import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_FRIEND;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import seedu.address.model.AddressBook;
-import seedu.address.model.person.Person;
-
-/**
- * A utility class containing a list of {@code Person} objects to be used in tests.
- */
-public class TypicalPersons {
-
- public static final Person ALICE = new PersonBuilder().withName("Alice Pauline")
- .withAddress("123, Jurong West Ave 6, #08-111").withEmail("alice@example.com")
- .withPhone("94351253")
- .withTags("friends").build();
- public static final Person BENSON = new PersonBuilder().withName("Benson Meier")
- .withAddress("311, Clementi Ave 2, #02-25")
- .withEmail("johnd@example.com").withPhone("98765432")
- .withTags("owesMoney", "friends").build();
- public static final Person CARL = new PersonBuilder().withName("Carl Kurz").withPhone("95352563")
- .withEmail("heinz@example.com").withAddress("wall street").build();
- public static final Person DANIEL = new PersonBuilder().withName("Daniel Meier").withPhone("87652533")
- .withEmail("cornelia@example.com").withAddress("10th street").withTags("friends").build();
- public static final Person ELLE = new PersonBuilder().withName("Elle Meyer").withPhone("9482224")
- .withEmail("werner@example.com").withAddress("michegan ave").build();
- public static final Person FIONA = new PersonBuilder().withName("Fiona Kunz").withPhone("9482427")
- .withEmail("lydia@example.com").withAddress("little tokyo").build();
- public static final Person GEORGE = new PersonBuilder().withName("George Best").withPhone("9482442")
- .withEmail("anna@example.com").withAddress("4th street").build();
-
- // Manually added
- public static final Person HOON = new PersonBuilder().withName("Hoon Meier").withPhone("8482424")
- .withEmail("stefan@example.com").withAddress("little india").build();
- public static final Person IDA = new PersonBuilder().withName("Ida Mueller").withPhone("8482131")
- .withEmail("hans@example.com").withAddress("chicago ave").build();
-
- // Manually added - Person's details found in {@code CommandTestUtil}
- public static final Person AMY = new PersonBuilder().withName(VALID_NAME_AMY).withPhone(VALID_PHONE_AMY)
- .withEmail(VALID_EMAIL_AMY).withAddress(VALID_ADDRESS_AMY).withTags(VALID_TAG_FRIEND).build();
- public static final Person BOB = new PersonBuilder().withName(VALID_NAME_BOB).withPhone(VALID_PHONE_BOB)
- .withEmail(VALID_EMAIL_BOB).withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND, VALID_TAG_FRIEND)
- .build();
-
- public static final String KEYWORD_MATCHING_MEIER = "Meier"; // A keyword that matches MEIER
-
- private TypicalPersons() {} // prevents instantiation
-
- /**
- * Returns an {@code AddressBook} with all the typical persons.
- */
- public static AddressBook getTypicalAddressBook() {
- AddressBook ab = new AddressBook();
- for (Person person : getTypicalPersons()) {
- ab.addPerson(person);
- }
- return ab;
- }
-
- public static List getTypicalPersons() {
- return new ArrayList<>(Arrays.asList(ALICE, BENSON, CARL, DANIEL, ELLE, FIONA, GEORGE));
- }
-}
diff --git a/src/test/java/seedu/address/AppParametersTest.java b/src/test/java/seedu/heymatez/AppParametersTest.java
similarity index 98%
rename from src/test/java/seedu/address/AppParametersTest.java
rename to src/test/java/seedu/heymatez/AppParametersTest.java
index 61326b2d31a..373aedab4a2 100644
--- a/src/test/java/seedu/address/AppParametersTest.java
+++ b/src/test/java/seedu/heymatez/AppParametersTest.java
@@ -1,4 +1,4 @@
-package seedu.address;
+package seedu.heymatez;
import static org.junit.jupiter.api.Assertions.assertEquals;
diff --git a/src/test/java/seedu/address/commons/core/ConfigTest.java b/src/test/java/seedu/heymatez/commons/core/ConfigTest.java
similarity index 95%
rename from src/test/java/seedu/address/commons/core/ConfigTest.java
rename to src/test/java/seedu/heymatez/commons/core/ConfigTest.java
index 07cd7f73d53..501078e7f1e 100644
--- a/src/test/java/seedu/address/commons/core/ConfigTest.java
+++ b/src/test/java/seedu/heymatez/commons/core/ConfigTest.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.core;
+package seedu.heymatez.commons.core;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
diff --git a/src/test/java/seedu/address/commons/core/VersionTest.java b/src/test/java/seedu/heymatez/commons/core/VersionTest.java
similarity index 98%
rename from src/test/java/seedu/address/commons/core/VersionTest.java
rename to src/test/java/seedu/heymatez/commons/core/VersionTest.java
index 495cd231554..31a55731e08 100644
--- a/src/test/java/seedu/address/commons/core/VersionTest.java
+++ b/src/test/java/seedu/heymatez/commons/core/VersionTest.java
@@ -1,8 +1,8 @@
-package seedu.address.commons.core;
+package seedu.heymatez.commons.core;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.testutil.Assert.assertThrows;
+import static seedu.heymatez.testutil.Assert.assertThrows;
import org.junit.jupiter.api.Test;
diff --git a/src/test/java/seedu/address/commons/core/index/IndexTest.java b/src/test/java/seedu/heymatez/commons/core/index/IndexTest.java
similarity index 95%
rename from src/test/java/seedu/address/commons/core/index/IndexTest.java
rename to src/test/java/seedu/heymatez/commons/core/index/IndexTest.java
index a3ec6f8e747..f3b5d96bb93 100644
--- a/src/test/java/seedu/address/commons/core/index/IndexTest.java
+++ b/src/test/java/seedu/heymatez/commons/core/index/IndexTest.java
@@ -1,9 +1,9 @@
-package seedu.address.commons.core.index;
+package seedu.heymatez.commons.core.index;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.testutil.Assert.assertThrows;
+import static seedu.heymatez.testutil.Assert.assertThrows;
import org.junit.jupiter.api.Test;
diff --git a/src/test/java/seedu/address/commons/util/AppUtilTest.java b/src/test/java/seedu/heymatez/commons/util/AppUtilTest.java
similarity index 91%
rename from src/test/java/seedu/address/commons/util/AppUtilTest.java
rename to src/test/java/seedu/heymatez/commons/util/AppUtilTest.java
index 594de1e6365..787f3951997 100644
--- a/src/test/java/seedu/address/commons/util/AppUtilTest.java
+++ b/src/test/java/seedu/heymatez/commons/util/AppUtilTest.java
@@ -1,7 +1,7 @@
-package seedu.address.commons.util;
+package seedu.heymatez.commons.util;
import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static seedu.address.testutil.Assert.assertThrows;
+import static seedu.heymatez.testutil.Assert.assertThrows;
import org.junit.jupiter.api.Test;
diff --git a/src/test/java/seedu/address/commons/util/CollectionUtilTest.java b/src/test/java/seedu/heymatez/commons/util/CollectionUtilTest.java
similarity index 96%
rename from src/test/java/seedu/address/commons/util/CollectionUtilTest.java
rename to src/test/java/seedu/heymatez/commons/util/CollectionUtilTest.java
index b467a3dc025..65d97ae471c 100644
--- a/src/test/java/seedu/address/commons/util/CollectionUtilTest.java
+++ b/src/test/java/seedu/heymatez/commons/util/CollectionUtilTest.java
@@ -1,9 +1,9 @@
-package seedu.address.commons.util;
+package seedu.heymatez.commons.util;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
-import static seedu.address.testutil.Assert.assertThrows;
+import static seedu.heymatez.commons.util.CollectionUtil.requireAllNonNull;
+import static seedu.heymatez.testutil.Assert.assertThrows;
import java.util.Arrays;
import java.util.Collection;
diff --git a/src/test/java/seedu/address/commons/util/ConfigUtilTest.java b/src/test/java/seedu/heymatez/commons/util/ConfigUtilTest.java
similarity index 94%
rename from src/test/java/seedu/address/commons/util/ConfigUtilTest.java
rename to src/test/java/seedu/heymatez/commons/util/ConfigUtilTest.java
index d2ab2839a52..e55a944d6b0 100644
--- a/src/test/java/seedu/address/commons/util/ConfigUtilTest.java
+++ b/src/test/java/seedu/heymatez/commons/util/ConfigUtilTest.java
@@ -1,8 +1,8 @@
-package seedu.address.commons.util;
+package seedu.heymatez.commons.util;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
-import static seedu.address.testutil.Assert.assertThrows;
+import static seedu.heymatez.testutil.Assert.assertThrows;
import java.io.IOException;
import java.nio.file.Path;
@@ -13,8 +13,8 @@
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
-import seedu.address.commons.core.Config;
-import seedu.address.commons.exceptions.DataConversionException;
+import seedu.heymatez.commons.core.Config;
+import seedu.heymatez.commons.exceptions.DataConversionException;
public class ConfigUtilTest {
diff --git a/src/test/java/seedu/address/commons/util/FileUtilTest.java b/src/test/java/seedu/heymatez/commons/util/FileUtilTest.java
similarity index 84%
rename from src/test/java/seedu/address/commons/util/FileUtilTest.java
rename to src/test/java/seedu/heymatez/commons/util/FileUtilTest.java
index 1fe5478c756..56871f152e3 100644
--- a/src/test/java/seedu/address/commons/util/FileUtilTest.java
+++ b/src/test/java/seedu/heymatez/commons/util/FileUtilTest.java
@@ -1,8 +1,8 @@
-package seedu.address.commons.util;
+package seedu.heymatez.commons.util;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.testutil.Assert.assertThrows;
+import static seedu.heymatez.testutil.Assert.assertThrows;
import org.junit.jupiter.api.Test;
diff --git a/src/test/java/seedu/address/commons/util/JsonUtilTest.java b/src/test/java/seedu/heymatez/commons/util/JsonUtilTest.java
similarity index 92%
rename from src/test/java/seedu/address/commons/util/JsonUtilTest.java
rename to src/test/java/seedu/heymatez/commons/util/JsonUtilTest.java
index d4907539dee..509c3120642 100644
--- a/src/test/java/seedu/address/commons/util/JsonUtilTest.java
+++ b/src/test/java/seedu/heymatez/commons/util/JsonUtilTest.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.util;
+package seedu.heymatez.commons.util;
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -7,8 +7,8 @@
import org.junit.jupiter.api.Test;
-import seedu.address.testutil.SerializableTestClass;
-import seedu.address.testutil.TestUtil;
+import seedu.heymatez.testutil.SerializableTestClass;
+import seedu.heymatez.testutil.TestUtil;
/**
* Tests JSON Read and Write
diff --git a/src/test/java/seedu/address/commons/util/StringUtilTest.java b/src/test/java/seedu/heymatez/commons/util/StringUtilTest.java
similarity index 72%
rename from src/test/java/seedu/address/commons/util/StringUtilTest.java
rename to src/test/java/seedu/heymatez/commons/util/StringUtilTest.java
index c56d407bf3f..cac07e3dc93 100644
--- a/src/test/java/seedu/address/commons/util/StringUtilTest.java
+++ b/src/test/java/seedu/heymatez/commons/util/StringUtilTest.java
@@ -1,8 +1,13 @@
-package seedu.address.commons.util;
+package seedu.heymatez.commons.util;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.testutil.Assert.assertThrows;
+import static seedu.heymatez.commons.util.StringUtil.INVALID_INPUT;
+import static seedu.heymatez.commons.util.StringUtil.INVALID_INTEGER;
+import static seedu.heymatez.commons.util.StringUtil.VALID_INTEGER;
+import static seedu.heymatez.testutil.Assert.assertThrows;
import java.io.FileNotFoundException;
@@ -13,36 +18,38 @@ public class StringUtilTest {
//---------------- Tests for isNonZeroUnsignedInteger --------------------------------------
@Test
- public void isNonZeroUnsignedInteger() {
+ public void checkIndexValidity() {
// EP: empty strings
- assertFalse(StringUtil.isNonZeroUnsignedInteger("")); // Boundary value
- assertFalse(StringUtil.isNonZeroUnsignedInteger(" "));
+ assertEquals(INVALID_INPUT, StringUtil.checkIndexValidity("")); // Boundary value
+ assertNotEquals(VALID_INTEGER, StringUtil.checkIndexValidity(""));
+ assertEquals(INVALID_INPUT, StringUtil.checkIndexValidity(" "));
+ assertNotEquals(VALID_INTEGER, StringUtil.checkIndexValidity(" "));
// EP: not a number
- assertFalse(StringUtil.isNonZeroUnsignedInteger("a"));
- assertFalse(StringUtil.isNonZeroUnsignedInteger("aaa"));
+ assertEquals(INVALID_INPUT, StringUtil.checkIndexValidity("a"));
+ assertEquals(INVALID_INPUT, StringUtil.checkIndexValidity("aaa"));
// EP: zero
- assertFalse(StringUtil.isNonZeroUnsignedInteger("0"));
+ assertEquals(INVALID_INTEGER, StringUtil.checkIndexValidity("0"));
// EP: zero as prefix
- assertTrue(StringUtil.isNonZeroUnsignedInteger("01"));
+ assertEquals(VALID_INTEGER, StringUtil.checkIndexValidity("01"));
// EP: signed numbers
- assertFalse(StringUtil.isNonZeroUnsignedInteger("-1"));
- assertFalse(StringUtil.isNonZeroUnsignedInteger("+1"));
+ assertEquals(INVALID_INTEGER, StringUtil.checkIndexValidity("-1"));
+ assertEquals(INVALID_INPUT, StringUtil.checkIndexValidity("+1"));
// EP: numbers with white space
- assertFalse(StringUtil.isNonZeroUnsignedInteger(" 10 ")); // Leading/trailing spaces
- assertFalse(StringUtil.isNonZeroUnsignedInteger("1 0")); // Spaces in the middle
+ assertEquals(INVALID_INPUT, StringUtil.checkIndexValidity(" 10 ")); // Leading/trailing spaces
+ assertEquals(INVALID_INPUT, StringUtil.checkIndexValidity("1 0")); // Spaces in the middle
// EP: number larger than Integer.MAX_VALUE
- assertFalse(StringUtil.isNonZeroUnsignedInteger(Long.toString(Integer.MAX_VALUE + 1)));
+ assertNotEquals(VALID_INTEGER, StringUtil.checkIndexValidity(Long.toString(Integer.MAX_VALUE + 1)));
// EP: valid numbers, should return true
- assertTrue(StringUtil.isNonZeroUnsignedInteger("1")); // Boundary value
- assertTrue(StringUtil.isNonZeroUnsignedInteger("10"));
+ assertEquals(VALID_INTEGER, StringUtil.checkIndexValidity("1")); // Boundary value
+ assertEquals(VALID_INTEGER, StringUtil.checkIndexValidity("10"));
}
diff --git a/src/test/java/seedu/address/logic/LogicManagerTest.java b/src/test/java/seedu/heymatez/logic/LogicManagerTest.java
similarity index 62%
rename from src/test/java/seedu/address/logic/LogicManagerTest.java
rename to src/test/java/seedu/heymatez/logic/LogicManagerTest.java
index ad923ac249a..4f938b00ad4 100644
--- a/src/test/java/seedu/address/logic/LogicManagerTest.java
+++ b/src/test/java/seedu/heymatez/logic/LogicManagerTest.java
@@ -1,14 +1,13 @@
-package seedu.address.logic;
+package seedu.heymatez.logic;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static seedu.address.commons.core.Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX;
-import static seedu.address.commons.core.Messages.MESSAGE_UNKNOWN_COMMAND;
-import static seedu.address.logic.commands.CommandTestUtil.ADDRESS_DESC_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.EMAIL_DESC_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.NAME_DESC_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.PHONE_DESC_AMY;
-import static seedu.address.testutil.Assert.assertThrows;
-import static seedu.address.testutil.TypicalPersons.AMY;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_EMPTY_PERSON_LIST;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_UNKNOWN_COMMAND;
+import static seedu.heymatez.logic.commands.CommandTestUtil.EMAIL_DESC_AMY;
+import static seedu.heymatez.logic.commands.CommandTestUtil.NAME_DESC_AMY;
+import static seedu.heymatez.logic.commands.CommandTestUtil.PHONE_DESC_AMY;
+import static seedu.heymatez.testutil.Assert.assertThrows;
+import static seedu.heymatez.testutil.TypicalPersons.AMY;
import java.io.IOException;
import java.nio.file.Path;
@@ -17,20 +16,20 @@
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
-import seedu.address.logic.commands.AddCommand;
-import seedu.address.logic.commands.CommandResult;
-import seedu.address.logic.commands.ListCommand;
-import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.logic.parser.exceptions.ParseException;
-import seedu.address.model.Model;
-import seedu.address.model.ModelManager;
-import seedu.address.model.ReadOnlyAddressBook;
-import seedu.address.model.UserPrefs;
-import seedu.address.model.person.Person;
-import seedu.address.storage.JsonAddressBookStorage;
-import seedu.address.storage.JsonUserPrefsStorage;
-import seedu.address.storage.StorageManager;
-import seedu.address.testutil.PersonBuilder;
+import seedu.heymatez.logic.commands.AddMemberCommand;
+import seedu.heymatez.logic.commands.CommandResult;
+import seedu.heymatez.logic.commands.ViewMembersCommand;
+import seedu.heymatez.logic.commands.exceptions.CommandException;
+import seedu.heymatez.logic.parser.exceptions.ParseException;
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.ModelManager;
+import seedu.heymatez.model.ReadOnlyHeyMatez;
+import seedu.heymatez.model.UserPrefs;
+import seedu.heymatez.model.person.Person;
+import seedu.heymatez.storage.JsonHeyMatezStorage;
+import seedu.heymatez.storage.JsonUserPrefsStorage;
+import seedu.heymatez.storage.StorageManager;
+import seedu.heymatez.testutil.PersonBuilder;
public class LogicManagerTest {
private static final IOException DUMMY_IO_EXCEPTION = new IOException("dummy exception");
@@ -43,10 +42,10 @@ public class LogicManagerTest {
@BeforeEach
public void setUp() {
- JsonAddressBookStorage addressBookStorage =
- new JsonAddressBookStorage(temporaryFolder.resolve("addressBook.json"));
+ JsonHeyMatezStorage heyMatezStorage =
+ new JsonHeyMatezStorage(temporaryFolder.resolve("heymatez.json"));
JsonUserPrefsStorage userPrefsStorage = new JsonUserPrefsStorage(temporaryFolder.resolve("userPrefs.json"));
- StorageManager storage = new StorageManager(addressBookStorage, userPrefsStorage);
+ StorageManager storage = new StorageManager(heyMatezStorage, userPrefsStorage);
logic = new LogicManager(model, storage);
}
@@ -56,32 +55,25 @@ public void execute_invalidCommandFormat_throwsParseException() {
assertParseException(invalidCommand, MESSAGE_UNKNOWN_COMMAND);
}
- @Test
- public void execute_commandExecutionError_throwsCommandException() {
- String deleteCommand = "delete 9";
- assertCommandException(deleteCommand, MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
- }
-
@Test
public void execute_validCommand_success() throws Exception {
- String listCommand = ListCommand.COMMAND_WORD;
- assertCommandSuccess(listCommand, ListCommand.MESSAGE_SUCCESS, model);
+ String listCommand = ViewMembersCommand.COMMAND_WORD;
+ assertCommandSuccess(listCommand, MESSAGE_EMPTY_PERSON_LIST, model);
}
@Test
public void execute_storageThrowsIoException_throwsCommandException() {
- // Setup LogicManager with JsonAddressBookIoExceptionThrowingStub
- JsonAddressBookStorage addressBookStorage =
- new JsonAddressBookIoExceptionThrowingStub(temporaryFolder.resolve("ioExceptionAddressBook.json"));
+ // Setup LogicManager with JsonHeyMatezIoExceptionThrowingStub
+ JsonHeyMatezStorage heyMatezStorage =
+ new JsonHeyMatezIoExceptionThrowingStub(temporaryFolder.resolve("ioExceptionHeyMatez.json"));
JsonUserPrefsStorage userPrefsStorage =
new JsonUserPrefsStorage(temporaryFolder.resolve("ioExceptionUserPrefs.json"));
- StorageManager storage = new StorageManager(addressBookStorage, userPrefsStorage);
+ StorageManager storage = new StorageManager(heyMatezStorage, userPrefsStorage);
logic = new LogicManager(model, storage);
// Execute add command
- String addCommand = AddCommand.COMMAND_WORD + NAME_DESC_AMY + PHONE_DESC_AMY + EMAIL_DESC_AMY
- + ADDRESS_DESC_AMY;
- Person expectedPerson = new PersonBuilder(AMY).withTags().build();
+ String addCommand = AddMemberCommand.COMMAND_WORD + NAME_DESC_AMY + PHONE_DESC_AMY + EMAIL_DESC_AMY;
+ Person expectedPerson = new PersonBuilder(AMY).build();
ModelManager expectedModel = new ModelManager();
expectedModel.addPerson(expectedPerson);
String expectedMessage = LogicManager.FILE_OPS_ERROR_MESSAGE + DUMMY_IO_EXCEPTION;
@@ -129,7 +121,7 @@ private void assertCommandException(String inputCommand, String expectedMessage)
*/
private void assertCommandFailure(String inputCommand, Class extends Throwable> expectedException,
String expectedMessage) {
- Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs());
+ Model expectedModel = new ModelManager(model.getHeyMatez(), new UserPrefs());
assertCommandFailure(inputCommand, expectedException, expectedMessage, expectedModel);
}
@@ -149,13 +141,13 @@ private void assertCommandFailure(String inputCommand, Class extends Throwable
/**
* A stub class to throw an {@code IOException} when the save method is called.
*/
- private static class JsonAddressBookIoExceptionThrowingStub extends JsonAddressBookStorage {
- private JsonAddressBookIoExceptionThrowingStub(Path filePath) {
+ private static class JsonHeyMatezIoExceptionThrowingStub extends JsonHeyMatezStorage {
+ private JsonHeyMatezIoExceptionThrowingStub(Path filePath) {
super(filePath);
}
@Override
- public void saveAddressBook(ReadOnlyAddressBook addressBook, Path filePath) throws IOException {
+ public void saveHeyMatez(ReadOnlyHeyMatez heyMatez, Path filePath) throws IOException {
throw DUMMY_IO_EXCEPTION;
}
}
diff --git a/src/test/java/seedu/heymatez/logic/commands/AddMemberCommandIntegrationTest.java b/src/test/java/seedu/heymatez/logic/commands/AddMemberCommandIntegrationTest.java
new file mode 100644
index 00000000000..571c658a03e
--- /dev/null
+++ b/src/test/java/seedu/heymatez/logic/commands/AddMemberCommandIntegrationTest.java
@@ -0,0 +1,44 @@
+package seedu.heymatez.logic.commands;
+
+import static seedu.heymatez.logic.commands.CommandTestUtil.assertCommandFailure;
+import static seedu.heymatez.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.heymatez.testutil.TypicalPersons.getTypicalHeyMatez;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.ModelManager;
+import seedu.heymatez.model.UserPrefs;
+import seedu.heymatez.model.person.Person;
+import seedu.heymatez.testutil.PersonBuilder;
+
+/**
+ * Contains integration tests (interaction with the Model) for {@code AddMemberCommand}.
+ */
+public class AddMemberCommandIntegrationTest {
+
+ private Model model;
+
+ @BeforeEach
+ public void setUp() {
+ model = new ModelManager(getTypicalHeyMatez(), new UserPrefs());
+ }
+
+ @Test
+ public void execute_newPerson_success() {
+ Person validPerson = new PersonBuilder().build();
+ Model expectedModel = new ModelManager(model.getHeyMatez(), new UserPrefs());
+ expectedModel.addPerson(validPerson);
+
+ assertCommandSuccess(new AddMemberCommand(validPerson), model,
+ String.format(AddMemberCommand.MESSAGE_SUCCESS, validPerson), expectedModel);
+ }
+
+ @Test
+ public void execute_duplicatePerson_throwsCommandException() {
+ Person personInList = model.getHeyMatez().getPersonList().get(0);
+ assertCommandFailure(new AddMemberCommand(personInList), model, AddMemberCommand.MESSAGE_DUPLICATE_PERSON);
+ }
+
+}
diff --git a/src/test/java/seedu/address/logic/commands/AddCommandTest.java b/src/test/java/seedu/heymatez/logic/commands/AddMemberCommandTest.java
similarity index 59%
rename from src/test/java/seedu/address/logic/commands/AddCommandTest.java
rename to src/test/java/seedu/heymatez/logic/commands/AddMemberCommandTest.java
index 5865713d5dd..49e06307770 100644
--- a/src/test/java/seedu/address/logic/commands/AddCommandTest.java
+++ b/src/test/java/seedu/heymatez/logic/commands/AddMemberCommandTest.java
@@ -1,10 +1,10 @@
-package seedu.address.logic.commands;
+package seedu.heymatez.logic.commands;
import static java.util.Objects.requireNonNull;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.testutil.Assert.assertThrows;
+import static seedu.heymatez.testutil.Assert.assertThrows;
import java.nio.file.Path;
import java.util.ArrayList;
@@ -14,20 +14,25 @@
import org.junit.jupiter.api.Test;
import javafx.collections.ObservableList;
-import seedu.address.commons.core.GuiSettings;
-import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.model.AddressBook;
-import seedu.address.model.Model;
-import seedu.address.model.ReadOnlyAddressBook;
-import seedu.address.model.ReadOnlyUserPrefs;
-import seedu.address.model.person.Person;
-import seedu.address.testutil.PersonBuilder;
-
-public class AddCommandTest {
+import seedu.heymatez.commons.core.GuiSettings;
+import seedu.heymatez.logic.commands.exceptions.CommandException;
+import seedu.heymatez.model.HeyMatez;
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.ReadOnlyHeyMatez;
+import seedu.heymatez.model.ReadOnlyUserPrefs;
+import seedu.heymatez.model.person.Person;
+import seedu.heymatez.model.task.Task;
+import seedu.heymatez.testutil.PersonBuilder;
+
+/**
+ * Contains integration tests (interaction with the Model) and unit tests for
+ * {@code AddMemberCommand}.
+ */
+public class AddMemberCommandTest {
@Test
public void constructor_nullPerson_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> new AddCommand(null));
+ assertThrows(NullPointerException.class, () -> new AddMemberCommand(null));
}
@Test
@@ -35,33 +40,34 @@ public void execute_personAcceptedByModel_addSuccessful() throws Exception {
ModelStubAcceptingPersonAdded modelStub = new ModelStubAcceptingPersonAdded();
Person validPerson = new PersonBuilder().build();
- CommandResult commandResult = new AddCommand(validPerson).execute(modelStub);
+ CommandResult commandResult = new AddMemberCommand(validPerson).execute(modelStub);
- assertEquals(String.format(AddCommand.MESSAGE_SUCCESS, validPerson), commandResult.getFeedbackToUser());
+ assertEquals(String.format(AddMemberCommand.MESSAGE_SUCCESS, validPerson), commandResult.getFeedbackToUser());
assertEquals(Arrays.asList(validPerson), modelStub.personsAdded);
}
@Test
public void execute_duplicatePerson_throwsCommandException() {
Person validPerson = new PersonBuilder().build();
- AddCommand addCommand = new AddCommand(validPerson);
+ AddMemberCommand addPersonCommand = new AddMemberCommand(validPerson);
ModelStub modelStub = new ModelStubWithPerson(validPerson);
- assertThrows(CommandException.class, AddCommand.MESSAGE_DUPLICATE_PERSON, () -> addCommand.execute(modelStub));
+ assertThrows(CommandException.class, AddMemberCommand.MESSAGE_DUPLICATE_PERSON, () ->
+ addPersonCommand.execute(modelStub));
}
@Test
public void equals() {
Person alice = new PersonBuilder().withName("Alice").build();
Person bob = new PersonBuilder().withName("Bob").build();
- AddCommand addAliceCommand = new AddCommand(alice);
- AddCommand addBobCommand = new AddCommand(bob);
+ AddMemberCommand addAliceCommand = new AddMemberCommand(alice);
+ AddMemberCommand addBobCommand = new AddMemberCommand(bob);
// same object -> returns true
assertTrue(addAliceCommand.equals(addAliceCommand));
// same values -> returns true
- AddCommand addAliceCommandCopy = new AddCommand(alice);
+ AddMemberCommand addAliceCommandCopy = new AddMemberCommand(alice);
assertTrue(addAliceCommand.equals(addAliceCommandCopy));
// different types -> returns false
@@ -99,12 +105,12 @@ public void setGuiSettings(GuiSettings guiSettings) {
}
@Override
- public Path getAddressBookFilePath() {
+ public Path getHeyMatezFilePath() {
throw new AssertionError("This method should not be called.");
}
@Override
- public void setAddressBookFilePath(Path addressBookFilePath) {
+ public void setHeyMatezFilePath(Path heyMatezFilePath) {
throw new AssertionError("This method should not be called.");
}
@@ -114,12 +120,18 @@ public void addPerson(Person person) {
}
@Override
- public void setAddressBook(ReadOnlyAddressBook newData) {
+ public void addTask(Task task) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+
+ @Override
+ public void setHeyMatez(ReadOnlyHeyMatez newData) {
throw new AssertionError("This method should not be called.");
}
@Override
- public ReadOnlyAddressBook getAddressBook() {
+ public ReadOnlyHeyMatez getHeyMatez() {
throw new AssertionError("This method should not be called.");
}
@@ -133,6 +145,11 @@ public void deletePerson(Person target) {
throw new AssertionError("This method should not be called.");
}
+ @Override
+ public void deleteTask(Task target) {
+ throw new AssertionError("This method should not be called.");
+ }
+
@Override
public void setPerson(Person target, Person editedPerson) {
throw new AssertionError("This method should not be called.");
@@ -147,6 +164,51 @@ public ObservableList getFilteredPersonList() {
public void updateFilteredPersonList(Predicate predicate) {
throw new AssertionError("This method should not be called.");
}
+
+ @Override
+ public boolean isTaskListEmpty() {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public boolean hasTask(Task task) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void setTask(Task target, Task editedTask) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public ObservableList getFilteredTaskList() {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void updateFilteredTaskList(Predicate predicate) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public boolean checkAssignees(Task task) {
+ throw new AssertionError("This method should not be called.");
+ };
+
+ @Override
+ public void removeAssignee(Person person) {
+ throw new AssertionError("This method should not be called.");
+ };
+
+ @Override
+ public void editAssignee(Person target, Person editedPerson) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public boolean isPersonListEmpty() {
+ throw new AssertionError("This method should not be called.");
+ }
}
/**
@@ -186,9 +248,8 @@ public void addPerson(Person person) {
}
@Override
- public ReadOnlyAddressBook getAddressBook() {
- return new AddressBook();
+ public ReadOnlyHeyMatez getHeyMatez() {
+ return new HeyMatez();
}
}
-
}
diff --git a/src/test/java/seedu/heymatez/logic/commands/AddTaskCommandIntegrationTest.java b/src/test/java/seedu/heymatez/logic/commands/AddTaskCommandIntegrationTest.java
new file mode 100644
index 00000000000..4abea8b1f82
--- /dev/null
+++ b/src/test/java/seedu/heymatez/logic/commands/AddTaskCommandIntegrationTest.java
@@ -0,0 +1,44 @@
+package seedu.heymatez.logic.commands;
+
+import static seedu.heymatez.logic.commands.CommandTestUtil.assertCommandFailure;
+import static seedu.heymatez.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.heymatez.testutil.TypicalTasks.getTypicalHeyMatez;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.ModelManager;
+import seedu.heymatez.model.UserPrefs;
+import seedu.heymatez.model.task.Task;
+import seedu.heymatez.testutil.TaskBuilder;
+
+/**
+ * Contains integration tests (interaction with the Model) for {@code AddTaskCommand}.
+ */
+public class AddTaskCommandIntegrationTest {
+
+ private Model model;
+
+ @BeforeEach
+ public void setUp() {
+ model = new ModelManager(getTypicalHeyMatez(), new UserPrefs());
+ }
+
+ @Test
+ public void execute_newTask_success() {
+ Task validTask = new TaskBuilder().build();
+ Model expectedModel = new ModelManager(model.getHeyMatez(), new UserPrefs());
+ expectedModel.addTask(validTask);
+
+ assertCommandSuccess(new AddTaskCommand(validTask), model,
+ String.format(AddTaskCommand.MESSAGE_SUCCESS, validTask), expectedModel);
+ }
+
+ @Test
+ public void execute_duplicateTask_throwsCommandException() {
+ Task taskInList = model.getHeyMatez().getTaskList().get(0);
+ assertCommandFailure(new AddTaskCommand(taskInList), model, AddTaskCommand.MESSAGE_DUPLICATE_TASK);
+ }
+
+}
diff --git a/src/test/java/seedu/heymatez/logic/commands/AddTaskCommandTest.java b/src/test/java/seedu/heymatez/logic/commands/AddTaskCommandTest.java
new file mode 100644
index 00000000000..0fd0ea81a12
--- /dev/null
+++ b/src/test/java/seedu/heymatez/logic/commands/AddTaskCommandTest.java
@@ -0,0 +1,259 @@
+package seedu.heymatez.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.heymatez.testutil.Assert.assertThrows;
+
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Set;
+import java.util.function.Predicate;
+
+import org.junit.jupiter.api.Test;
+
+import javafx.collections.ObservableList;
+import seedu.heymatez.commons.core.GuiSettings;
+import seedu.heymatez.model.HeyMatez;
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.ReadOnlyHeyMatez;
+import seedu.heymatez.model.ReadOnlyUserPrefs;
+import seedu.heymatez.model.assignee.Assignee;
+import seedu.heymatez.model.person.Name;
+import seedu.heymatez.model.person.Person;
+import seedu.heymatez.model.task.Task;
+import seedu.heymatez.testutil.TaskBuilder;
+
+public class AddTaskCommandTest {
+ @Test
+ public void constructor_nullTask_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> new AddTaskCommand(null));
+ }
+
+ @Test
+ public void execute_taskAcceptedByModel_addSuccessful() throws Exception {
+ AddTaskCommandTest.ModelStubAcceptingTaskAdded modelStub = new AddTaskCommandTest
+ .ModelStubAcceptingTaskAdded();
+ Task validTask = new TaskBuilder().build();
+
+ CommandResult commandResult = new AddTaskCommand(validTask).execute(modelStub);
+
+ assertEquals(String.format(AddTaskCommand.MESSAGE_SUCCESS, validTask), commandResult.getFeedbackToUser());
+ assertEquals(Arrays.asList(validTask), modelStub.tasksAdded);
+ }
+
+ @Test
+ public void equals() {
+ Task planMeeting = new TaskBuilder().withTitle("Plan meeting").build();
+ Task bookVenue = new TaskBuilder().withTitle("Book venue").build();
+ AddTaskCommand addPlanMeetingCommand = new AddTaskCommand(planMeeting);
+ AddTaskCommand addBookVenueCommand = new AddTaskCommand(bookVenue);
+
+
+ // same object -> returns true
+ assertTrue(addPlanMeetingCommand.equals(addPlanMeetingCommand));
+
+ // same values -> returns true
+ AddTaskCommand addPlanMeetingCommandCopy = new AddTaskCommand(planMeeting);
+ assertTrue(addPlanMeetingCommand.equals(addPlanMeetingCommandCopy));
+
+ // different types -> returns false
+ assertFalse(addPlanMeetingCommand.equals(1));
+
+ // null -> returns false
+ assertFalse(addPlanMeetingCommand.equals(null));
+
+ // different person -> returns false
+ assertFalse(addPlanMeetingCommand.equals(addBookVenueCommand));
+ }
+
+ /**
+ * A default model stub that have all of the methods failing.
+ */
+ private class ModelStub implements Model {
+ @Override
+ public void setUserPrefs(ReadOnlyUserPrefs userPrefs) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public ReadOnlyUserPrefs getUserPrefs() {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public GuiSettings getGuiSettings() {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void setGuiSettings(GuiSettings guiSettings) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public Path getHeyMatezFilePath() {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void setHeyMatezFilePath(Path heyMatezFilePath) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void addPerson(Person person) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void addTask(Task task) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+
+ @Override
+ public void setHeyMatez(ReadOnlyHeyMatez newData) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public ReadOnlyHeyMatez getHeyMatez() {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public boolean hasPerson(Person person) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public boolean hasTask(Task task) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void deletePerson(Person target) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void deleteTask(Task target) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void setPerson(Person target, Person editedPerson) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public ObservableList getFilteredPersonList() {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void updateFilteredPersonList(Predicate predicate) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void setTask(Task target, Task editedTask) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public ObservableList getFilteredTaskList() {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void updateFilteredTaskList(Predicate predicate) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public boolean isTaskListEmpty() {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public boolean checkAssignees(Task task) {
+ throw new AssertionError("This method should not be called.");
+ };
+
+ @Override
+ public void removeAssignee(Person person) {
+ throw new AssertionError("This method should not be called.");
+ };
+
+ @Override
+ public void editAssignee(Person target, Person editedPerson) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public boolean isPersonListEmpty() {
+ throw new AssertionError("This method should not be called.");
+ }
+ }
+
+ /**
+ * A Model stub that contains a single task.
+ */
+ private class ModelStubWithTask extends AddTaskCommandTest.ModelStub {
+ private final Task task;
+
+ ModelStubWithTask(Task task) {
+ requireNonNull(task);
+ this.task = task;
+ }
+
+ @Override
+ public boolean hasTask(Task task) {
+ requireNonNull(task);
+ return this.task.isSameTask(task);
+ }
+ }
+
+ /**
+ * A Model stub that always accept the task being added.
+ */
+ private class ModelStubAcceptingTaskAdded extends AddTaskCommandTest.ModelStub {
+ final ArrayList tasksAdded = new ArrayList<>();
+
+ @Override
+ public boolean hasTask(Task task) {
+ requireNonNull(task);
+ return tasksAdded.stream().anyMatch(task::isSameTask);
+ }
+
+ @Override
+ public void addTask(Task task) {
+ requireNonNull(task);
+ tasksAdded.add(task);
+ }
+
+ @Override
+ public ReadOnlyHeyMatez getHeyMatez() {
+ return new HeyMatez();
+ }
+
+ @Override
+ public boolean checkAssignees(Task task) {
+ Set assignees = task.getAssignees();
+
+ for (Assignee assignee : assignees) {
+ Name tempName = new Name(assignee.assigneeName);
+ Person tempPerson = new Person(tempName);
+ if (!hasPerson(tempPerson)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/src/test/java/seedu/heymatez/logic/commands/ClearAssigneesCommandTest.java b/src/test/java/seedu/heymatez/logic/commands/ClearAssigneesCommandTest.java
new file mode 100644
index 00000000000..6f6d7ba585e
--- /dev/null
+++ b/src/test/java/seedu/heymatez/logic/commands/ClearAssigneesCommandTest.java
@@ -0,0 +1,139 @@
+package seedu.heymatez.logic.commands;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.heymatez.logic.commands.CommandTestUtil.assertCommandFailure;
+import static seedu.heymatez.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.heymatez.logic.commands.CommandTestUtil.showTaskAtIndex;
+import static seedu.heymatez.testutil.TypicalIndexes.INDEX_FIRST_TASK;
+import static seedu.heymatez.testutil.TypicalIndexes.INDEX_SECOND_TASK;
+import static seedu.heymatez.testutil.TypicalTasks.getTypicalHeyMatez;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.heymatez.commons.core.Messages;
+import seedu.heymatez.commons.core.index.Index;
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.ModelManager;
+import seedu.heymatez.model.UserPrefs;
+import seedu.heymatez.model.task.Task;
+import seedu.heymatez.testutil.TaskBuilder;
+
+/**
+ * Contains integration tests (interaction with the Model) and unit tests for
+ * {@code ClearAssigneesCommand}.
+ */
+public class ClearAssigneesCommandTest {
+ private Model model = new ModelManager(getTypicalHeyMatez(), new UserPrefs());
+
+ @Test
+ public void execute_validIndexUnfilteredList_success() {
+ Task taskToClear = model.getFilteredTaskList().get(INDEX_FIRST_TASK.getZeroBased());
+
+ Task clearedTask = new TaskBuilder()
+ .withTitle(taskToClear.getTitle().taskTitle)
+ .withDescription(taskToClear.getDescription().desc)
+ .withDeadline(taskToClear.getDeadline().unformattedDate)
+ .withTaskStatus(taskToClear.getTaskStatus().status)
+ .withPriority(taskToClear.getPriority().priority)
+ .build();
+
+ ClearAssigneesCommand clearAssigneesCommand = new ClearAssigneesCommand(INDEX_FIRST_TASK);
+
+ String expectedMessage = String.format(clearAssigneesCommand.MESSAGE_ASSIGNEES_SET_IS_EMPTY,
+ clearedTask);
+
+ ModelManager expectedModel = new ModelManager(model.getHeyMatez(), new UserPrefs());
+ expectedModel.setTask(taskToClear, clearedTask);
+
+ assertCommandSuccess(clearAssigneesCommand, model, expectedMessage, expectedModel);
+ }
+
+
+ @Test
+ public void execute_invalidIndexUnfilteredList_throwsCommandException() {
+ Index outOfBoundIndex = Index.fromOneBased(model.getFilteredTaskList().size() + 1);
+ ClearAssigneesCommand clearAssigneesCommand = new ClearAssigneesCommand(outOfBoundIndex);
+
+ assertCommandFailure(clearAssigneesCommand, model, Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+
+ @Test
+ public void execute_invalidIntegerUnfilteredList_throwsCommandException() {
+ Index outOfBoundIndex = Index.fromOneBased(Integer.MAX_VALUE + 1);
+ ClearAssigneesCommand clearAssigneesCommand = new ClearAssigneesCommand(outOfBoundIndex);
+
+ assertCommandFailure(clearAssigneesCommand, model, Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+
+ @Test
+ public void execute_validIndexFilteredList_success() {
+ showTaskAtIndex(model, INDEX_FIRST_TASK);
+
+ Task taskToClear = model.getFilteredTaskList().get(INDEX_FIRST_TASK.getZeroBased());
+
+ Task clearedTask = new TaskBuilder()
+ .withTitle(taskToClear.getTitle().taskTitle)
+ .withDescription(taskToClear.getDescription().desc)
+ .withDeadline(taskToClear.getDeadline().unformattedDate)
+ .withTaskStatus(taskToClear.getTaskStatus().status)
+ .withPriority(taskToClear.getPriority().priority)
+ .build();
+
+ ClearAssigneesCommand clearAssigneesCommand = new ClearAssigneesCommand(INDEX_FIRST_TASK);
+
+ String expectedMessage = String.format(ClearAssigneesCommand.MESSAGE_ASSIGNEES_SET_IS_EMPTY,
+ clearedTask);
+
+ Model expectedModel = new ModelManager(model.getHeyMatez(), new UserPrefs());
+
+ expectedModel.setTask(taskToClear, clearedTask);
+ showNoTask(expectedModel);
+
+ assertCommandSuccess(clearAssigneesCommand, model, expectedMessage, expectedModel);
+ }
+
+ @Test
+ public void execute_invalidIndexFilteredList_throwsCommandException() {
+ showTaskAtIndex(model, INDEX_FIRST_TASK);
+
+ Index outOfBoundIndex = INDEX_SECOND_TASK;
+ // ensures that outOfBoundIndex is still in bounds of HeyMatez task list
+ assertTrue(outOfBoundIndex.getZeroBased() < model.getHeyMatez().getTaskList().size());
+
+ ClearAssigneesCommand clearAssigneesCommand = new ClearAssigneesCommand(outOfBoundIndex);
+
+ assertCommandFailure(clearAssigneesCommand, model, Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+
+ /**
+ * Updates {@code model}'s filtered list to show no one.
+ */
+ private void showNoTask(Model model) {
+ model.updateFilteredTaskList(p -> false);
+
+ assertTrue(model.getFilteredTaskList().isEmpty());
+ }
+
+ @Test
+ public void equals() {
+ ClearAssigneesCommand firstClearCommand = new ClearAssigneesCommand(INDEX_FIRST_TASK);
+ ClearAssigneesCommand secondClearCommand = new ClearAssigneesCommand(INDEX_SECOND_TASK);
+
+ // same object -> returns true
+ assertTrue(firstClearCommand.equals(firstClearCommand));
+
+ // same values -> returns true
+ ClearAssigneesCommand firstClearCommandCopy = new ClearAssigneesCommand(INDEX_FIRST_TASK);
+ assertTrue(firstClearCommand.equals(firstClearCommandCopy));
+
+ // different types -> returns false
+ assertFalse(firstClearCommand.equals(1));
+
+ // null -> returns false
+ assertFalse(firstClearCommand.equals(null));
+
+ // different person -> returns false
+ assertFalse(firstClearCommand.equals(secondClearCommand));
+ }
+}
diff --git a/src/test/java/seedu/heymatez/logic/commands/ClearCommandTest.java b/src/test/java/seedu/heymatez/logic/commands/ClearCommandTest.java
new file mode 100644
index 00000000000..f4d42a110b8
--- /dev/null
+++ b/src/test/java/seedu/heymatez/logic/commands/ClearCommandTest.java
@@ -0,0 +1,36 @@
+package seedu.heymatez.logic.commands;
+
+import static seedu.heymatez.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.heymatez.testutil.TypicalPersons.getTypicalHeyMatez;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.heymatez.model.HeyMatez;
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.ModelManager;
+import seedu.heymatez.model.UserPrefs;
+
+/**
+ * Contains integration tests (interaction with the Model) and unit tests for
+ * {@code ClearCommand}.
+ */
+public class ClearCommandTest {
+
+ @Test
+ public void execute_emptyHeyMatez_success() {
+ Model model = new ModelManager();
+ Model expectedModel = new ModelManager();
+
+ assertCommandSuccess(new ClearCommand(), model, ClearCommand.MESSAGE_SUCCESS, expectedModel);
+ }
+
+ @Test
+ public void execute_nonEmptyHeyMatez_success() {
+ Model model = new ModelManager(getTypicalHeyMatez(), new UserPrefs());
+ Model expectedModel = new ModelManager(getTypicalHeyMatez(), new UserPrefs());
+ expectedModel.setHeyMatez(new HeyMatez());
+
+ assertCommandSuccess(new ClearCommand(), model, ClearCommand.MESSAGE_SUCCESS, expectedModel);
+ }
+
+}
diff --git a/src/test/java/seedu/address/logic/commands/CommandResultTest.java b/src/test/java/seedu/heymatez/logic/commands/CommandResultTest.java
similarity index 95%
rename from src/test/java/seedu/address/logic/commands/CommandResultTest.java
rename to src/test/java/seedu/heymatez/logic/commands/CommandResultTest.java
index 4f3eb46e9ef..9c991a394f3 100644
--- a/src/test/java/seedu/address/logic/commands/CommandResultTest.java
+++ b/src/test/java/seedu/heymatez/logic/commands/CommandResultTest.java
@@ -1,4 +1,4 @@
-package seedu.address.logic.commands;
+package seedu.heymatez.logic.commands;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
@@ -7,6 +7,9 @@
import org.junit.jupiter.api.Test;
+/**
+ * Contains unit tests for {@code CommandResult}.
+ */
public class CommandResultTest {
@Test
public void equals() {
diff --git a/src/test/java/seedu/heymatez/logic/commands/CommandTestUtil.java b/src/test/java/seedu/heymatez/logic/commands/CommandTestUtil.java
new file mode 100644
index 00000000000..1d582dde5c3
--- /dev/null
+++ b/src/test/java/seedu/heymatez/logic/commands/CommandTestUtil.java
@@ -0,0 +1,202 @@
+package seedu.heymatez.logic.commands;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.heymatez.logic.parser.CliSyntax.PREFIX_ASSIGNEE;
+import static seedu.heymatez.logic.parser.CliSyntax.PREFIX_DEADLINE;
+import static seedu.heymatez.logic.parser.CliSyntax.PREFIX_DESCRIPTION;
+import static seedu.heymatez.logic.parser.CliSyntax.PREFIX_EMAIL;
+import static seedu.heymatez.logic.parser.CliSyntax.PREFIX_NEW_NAME;
+import static seedu.heymatez.logic.parser.CliSyntax.PREFIX_PHONE;
+import static seedu.heymatez.logic.parser.CliSyntax.PREFIX_PRIORITY;
+import static seedu.heymatez.logic.parser.CliSyntax.PREFIX_ROLE;
+import static seedu.heymatez.logic.parser.CliSyntax.PREFIX_TITLE;
+import static seedu.heymatez.testutil.Assert.assertThrows;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import seedu.heymatez.commons.core.index.Index;
+import seedu.heymatez.logic.commands.exceptions.CommandException;
+import seedu.heymatez.model.HeyMatez;
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.person.Name;
+import seedu.heymatez.model.person.NameContainsKeywordsPredicate;
+import seedu.heymatez.model.person.Person;
+import seedu.heymatez.model.task.Task;
+import seedu.heymatez.model.task.TitleContainsKeywordPredicate;
+import seedu.heymatez.testutil.EditMemberDescriptorBuilder;
+import seedu.heymatez.testutil.EditTaskDescriptorBuilder;
+
+/**
+ * Contains helper methods for testing commands.
+ */
+public class CommandTestUtil {
+
+ public static final String VALID_NAME_AMY = "Amy Bee";
+ public static final String VALID_NAME_BOB = "Bob Choo";
+ public static final String VALID_PHONE_AMY = "11111111";
+ public static final String VALID_PHONE_BOB = "22222222";
+ public static final String VALID_EMAIL_AMY = "amy@example.com";
+ public static final String VALID_EMAIL_BOB = "bob@example.com";
+ public static final String VALID_ROLE_AMY = "Events Head";
+ public static final String VALID_ROLE_BOB = "Member";
+
+ public static final String VALID_TITLE_MARATHON = "MARATHON";
+ public static final String VALID_DESCRIPTION_MARATHON = "At east coast park";
+ public static final String VALID_DEADLINE_MARATHON = "2021-05-06";
+ public static final String VALID_STATUS_MARATHON = "completed";
+ public static final String VALID_PRIORITY_MARATHON = "low";
+ public static final String VALID_ASSIGNEE_MARATHON = "Alice Pauline";
+
+ public static final String VALID_TITLE_MEETING = "MEETING";
+ public static final String VALID_DESCRIPTION_MEETING = "Board meeting";
+ public static final String VALID_DEADLINE_MEETING = "2021-07-02";
+ public static final String VALID_PRIORITY_MEETING = "high";
+ public static final String VALID_ASSIGNEE_MEETING = "Benson Meier";
+
+ public static final String NEW_NAME_DESC_AMY = " " + PREFIX_NEW_NAME + VALID_NAME_AMY;
+ public static final String TITLE_DESC_TASK1 = " " + PREFIX_TITLE + VALID_TITLE_MARATHON;
+ public static final String TITLE_DESC_TASK2 = " " + PREFIX_TITLE + VALID_TITLE_MEETING;
+ public static final String DESCRIPTION_TASK1 = " " + PREFIX_DESCRIPTION + VALID_DESCRIPTION_MARATHON;
+ public static final String DESCRIPTION_TASK2 = " " + PREFIX_DESCRIPTION + VALID_DESCRIPTION_MEETING;
+ public static final String DEADLINE_TASK1 = " " + PREFIX_DEADLINE + VALID_DEADLINE_MARATHON;
+ public static final String DEADLINE_TASK2 = " " + PREFIX_DEADLINE + VALID_DEADLINE_MEETING;
+ public static final String PRIORITY_TASK1 = " " + PREFIX_PRIORITY + VALID_PRIORITY_MARATHON;
+ public static final String PRIORITY_TASK2 = " " + PREFIX_PRIORITY + VALID_PRIORITY_MEETING;
+ public static final String ASSIGNEE_TASK2 = " " + PREFIX_ASSIGNEE + VALID_ASSIGNEE_MEETING;
+ public static final String NAME_DESC_AMY = " " + VALID_NAME_AMY;
+ public static final String NAME_DESC_BOB = VALID_NAME_BOB;
+
+ public static final String PHONE_DESC_AMY = " " + PREFIX_PHONE + VALID_PHONE_AMY;
+ public static final String PHONE_DESC_BOB = " " + PREFIX_PHONE + VALID_PHONE_BOB;
+ public static final String EMAIL_DESC_AMY = " " + PREFIX_EMAIL + VALID_EMAIL_AMY;
+ public static final String EMAIL_DESC_BOB = " " + PREFIX_EMAIL + VALID_EMAIL_BOB;
+ public static final String ROLE_DESC_BOB = " " + PREFIX_ROLE + VALID_ROLE_BOB;
+
+ public static final String INVALID_NAME_DESC = " " + "James&"; // '&' not allowed in names
+ public static final String INVALID_NEW_NAME_DESC = " " + PREFIX_NEW_NAME + "James&"; // '&' not allowed in new names
+ public static final String INVALID_PHONE_DESC = " " + PREFIX_PHONE + "911a"; // 'a' not allowed in phones
+ public static final String INVALID_EMAIL_DESC = " " + PREFIX_EMAIL + "bob!yahoo"; // missing '@' symbol
+
+ public static final String INVALID_DEADLINE_DESC = " " + PREFIX_DEADLINE + "20 March 2021"; // only allow dates in
+ // the format "YYYY-MM-DD"
+ public static final String INVALID_PRIORITY_DESC = " " + PREFIX_PRIORITY + "very high";
+
+ public static final String PREAMBLE_WHITESPACE = "\t \r \n";
+ public static final String PREAMBLE_NON_EMPTY = "NonEmptyPreamble";
+
+ public static final EditMemberCommand.EditMemberDescriptor DESC_AMY;
+ public static final EditMemberCommand.EditMemberDescriptor DESC_BOB;
+ public static final EditTaskCommand.EditTaskDescriptor DESC_TASK1;
+ public static final EditTaskCommand.EditTaskDescriptor DESC_TASK2;
+
+
+ static {
+ DESC_AMY = new EditMemberDescriptorBuilder().withName(VALID_NAME_AMY)
+ .withPhone(VALID_PHONE_AMY).withEmail(VALID_EMAIL_AMY).build();
+ DESC_BOB = new EditMemberDescriptorBuilder().withName(VALID_NAME_BOB)
+ .withPhone(VALID_PHONE_BOB).withEmail(VALID_EMAIL_BOB).build();
+ DESC_TASK1 = new EditTaskDescriptorBuilder().withTitle(VALID_DESCRIPTION_MARATHON)
+ .withDescription(VALID_DESCRIPTION_MARATHON).withDeadline(VALID_DEADLINE_MARATHON)
+ .withAssignees(VALID_ASSIGNEE_MARATHON).build();
+ DESC_TASK2 = new EditTaskDescriptorBuilder().withTitle(VALID_DESCRIPTION_MEETING)
+ .withDescription(VALID_DESCRIPTION_MEETING).withPriority("high")
+ .withAssignees(VALID_ASSIGNEE_MEETING).build();
+ }
+
+ /**
+ * Executes the given {@code command}, confirms that
+ * - the returned {@link CommandResult} matches {@code expectedCommandResult}
+ * - the {@code actualModel} matches {@code expectedModel}
+ */
+ public static void assertCommandSuccess(Command command, Model actualModel, CommandResult expectedCommandResult,
+ Model expectedModel) {
+ try {
+ CommandResult result = command.execute(actualModel);
+ assertEquals(expectedCommandResult, result);
+ assertEquals(expectedModel, actualModel);
+ } catch (CommandException ce) {
+ throw new AssertionError("Execution of command should not fail.", ce);
+ }
+ }
+
+ /**
+ * Convenience wrapper to {@link #assertCommandSuccess(Command, Model, CommandResult, Model)}
+ * that takes a string {@code expectedMessage}.
+ */
+ public static void assertCommandSuccess(Command command, Model actualModel, String expectedMessage,
+ Model expectedModel) {
+ CommandResult expectedCommandResult = new CommandResult(expectedMessage);
+ assertCommandSuccess(command, actualModel, expectedCommandResult, expectedModel);
+ }
+
+ /**
+ * Executes the given {@code command}, confirms that
+ * - a {@code CommandException} is thrown
+ * - the CommandException message matches {@code expectedMessage}
+ * - the address book, filtered person list and selected person in {@code actualModel} remain unchanged
+ */
+ public static void assertCommandFailure(Command command, Model actualModel, String expectedMessage) {
+ // we are unable to defensively copy the model for comparison later, so we can
+ // only do so by copying its components.
+ HeyMatez expectedAddressBook = new HeyMatez(actualModel.getHeyMatez());
+ List expectedFilteredList = new ArrayList<>(actualModel.getFilteredPersonList());
+ List expectedFilteredTaskList = new ArrayList<>(actualModel.getFilteredTaskList());
+
+ assertThrows(CommandException.class, expectedMessage, () -> command.execute(actualModel));
+ assertEquals(expectedAddressBook, actualModel.getHeyMatez());
+ assertEquals(expectedFilteredList, actualModel.getFilteredPersonList());
+ assertEquals(expectedFilteredTaskList, actualModel.getFilteredTaskList());
+ }
+
+
+ /**
+ * Updates {@code model}'s filtered list to show only the person at the given {@code targetIndex} in the
+ * {@code model}'s address book.
+ */
+ public static void showPersonAtIndex(Model model, Index targetIndex) {
+ assertTrue(targetIndex.getZeroBased() < model.getFilteredPersonList().size());
+
+ Person person = model.getFilteredPersonList().get(targetIndex.getZeroBased());
+ final String[] splitName = person.getName().fullName.split("\\s+");
+ model.updateFilteredPersonList(new NameContainsKeywordsPredicate(Arrays.asList(splitName[0])));
+
+ assertEquals(1, model.getFilteredPersonList().size());
+ }
+
+ /**
+ * Updates {@code model}'s filtered list to show only the task at the given {@code targetIndex} in the
+ * {@code model}'s address book.
+ */
+ public static void showTaskAtIndex(Model model, Index targetIndex) {
+ assertTrue(targetIndex.getZeroBased() < model.getFilteredTaskList().size());
+
+ Task task = model.getFilteredTaskList().get(targetIndex.getZeroBased());
+ model.updateFilteredTaskList(new TitleContainsKeywordPredicate(Arrays.asList(task.getTitle().taskTitle)));
+
+ assertEquals(1, model.getFilteredTaskList().size());
+ }
+ /**
+ * Updates {@code model}'s filtered list to show only the person at the given {@code name} in the
+ * {@code model}'s address book.
+ */
+ public static void showPersonAtName(Model model, Name name) {
+ Person person = null;
+
+ for (Person currentPerson : model.getFilteredPersonList()) {
+ Name currentName = currentPerson.getName();
+
+ if (currentName.equals(name)) {
+ person = currentPerson;
+ break;
+ }
+ }
+
+ final String[] splitName = person.getName().fullName.split("\\s+");
+ model.updateFilteredPersonList(new NameContainsKeywordsPredicate(Arrays.asList(splitName[0])));
+
+ assertEquals(1, model.getFilteredPersonList().size());
+ }
+}
diff --git a/src/test/java/seedu/heymatez/logic/commands/DeleteMemberCommandIntegrationTest.java b/src/test/java/seedu/heymatez/logic/commands/DeleteMemberCommandIntegrationTest.java
new file mode 100644
index 00000000000..86e2bbba21b
--- /dev/null
+++ b/src/test/java/seedu/heymatez/logic/commands/DeleteMemberCommandIntegrationTest.java
@@ -0,0 +1,46 @@
+package seedu.heymatez.logic.commands;
+
+import static seedu.heymatez.logic.commands.CommandTestUtil.assertCommandFailure;
+import static seedu.heymatez.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.heymatez.testutil.TypicalPersons.getTypicalHeyMatez;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import seedu.heymatez.commons.core.Messages;
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.ModelManager;
+import seedu.heymatez.model.UserPrefs;
+import seedu.heymatez.model.person.Name;
+import seedu.heymatez.model.person.Person;
+import seedu.heymatez.testutil.PersonBuilder;
+
+/**
+ * Contains integration tests (interaction with the Model) for {@code DeleteMemberCommand}.
+ */
+public class DeleteMemberCommandIntegrationTest {
+
+ private Model model;
+
+ @BeforeEach
+ public void setUp() {
+ model = new ModelManager(getTypicalHeyMatez(), new UserPrefs());
+ }
+
+ @Test
+ public void execute_deletePerson_success() {
+ Person validPerson = model.getHeyMatez().getPersonList().get(0);
+ Model expectedModel = new ModelManager(model.getHeyMatez(), new UserPrefs());
+ expectedModel.deletePerson(validPerson);
+
+ assertCommandSuccess(new DeleteMemberCommand(validPerson.getName()), model,
+ String.format(DeleteMemberCommand.MESSAGE_DELETE_PERSON_SUCCESS, validPerson), expectedModel);
+ }
+
+ @Test
+ public void execute_deletePerson_throwsNameNotValid() {
+ Name name = new PersonBuilder().withName("Not a name").build().getName();
+ assertCommandFailure(new DeleteMemberCommand(name), model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_NAME);
+ }
+
+}
diff --git a/src/test/java/seedu/heymatez/logic/commands/DeleteMemberCommandTest.java b/src/test/java/seedu/heymatez/logic/commands/DeleteMemberCommandTest.java
new file mode 100644
index 00000000000..ba0578295f3
--- /dev/null
+++ b/src/test/java/seedu/heymatez/logic/commands/DeleteMemberCommandTest.java
@@ -0,0 +1,159 @@
+package seedu.heymatez.logic.commands;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.heymatez.logic.commands.CommandTestUtil.assertCommandFailure;
+import static seedu.heymatez.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.heymatez.logic.commands.CommandTestUtil.showPersonAtName;
+import static seedu.heymatez.testutil.TypicalPersons.getTypicalHeyMatez;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.heymatez.commons.core.Messages;
+import seedu.heymatez.logic.parser.exceptions.ParseException;
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.ModelManager;
+import seedu.heymatez.model.UserPrefs;
+import seedu.heymatez.model.person.Name;
+import seedu.heymatez.model.person.Person;
+import seedu.heymatez.model.task.Task;
+import seedu.heymatez.testutil.TaskBuilder;
+import seedu.heymatez.testutil.TypicalPersons;
+
+/**
+ * Contains integration tests (interaction with the Model) and unit tests for
+ * {@code DeleteMemberCommand}.
+ */
+public class DeleteMemberCommandTest {
+ private Model model = new ModelManager(getTypicalHeyMatez(), new UserPrefs());
+
+ @Test
+ public void execute_validNameUnfilteredList_success() throws ParseException {
+ Person personToDelete = null;
+ Name parsedNameAlice = TypicalPersons.ALICE.getName();
+ DeleteMemberCommand deleteCommand = new DeleteMemberCommand(parsedNameAlice);
+
+ for (Person person : model.getFilteredPersonList()) {
+ Name currentName = person.getName();
+
+ if (currentName.equals(parsedNameAlice)) {
+ personToDelete = person;
+ break;
+ }
+ }
+
+ String expectedMessage = String.format(DeleteMemberCommand.MESSAGE_DELETE_PERSON_SUCCESS, personToDelete);
+
+ ModelManager expectedModel = new ModelManager(model.getHeyMatez(), new UserPrefs());
+ expectedModel.deletePerson(personToDelete);
+
+ assertCommandSuccess(deleteCommand, model, expectedMessage, expectedModel);
+ }
+
+ @Test
+ public void execute_invalidNameUnfilteredList_throwsCommandException() {
+ Name invalidName = new Name("John");
+ DeleteMemberCommand deleteCommand = new DeleteMemberCommand(invalidName);
+
+ assertCommandFailure(deleteCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_NAME);
+ }
+
+ @Test
+ public void execute_validNameFilteredList_success() throws ParseException {
+ Name parsedNameAlice = TypicalPersons.ALICE.getName();
+ showPersonAtName(model, parsedNameAlice);
+ Person personToDelete = null;
+
+ for (Person person : model.getFilteredPersonList()) {
+ Name currentName = person.getName();
+
+ if (currentName.equals(parsedNameAlice)) {
+ personToDelete = person;
+ break;
+ }
+ }
+
+ DeleteMemberCommand deleteCommand = new DeleteMemberCommand(parsedNameAlice);
+ String expectedMessage = String.format(DeleteMemberCommand.MESSAGE_DELETE_PERSON_SUCCESS, personToDelete);
+
+ Model expectedModel = new ModelManager(model.getHeyMatez(), new UserPrefs());
+ expectedModel.deletePerson(personToDelete);
+ showNoPerson(expectedModel);
+
+ assertCommandSuccess(deleteCommand, model, expectedMessage, expectedModel);
+ }
+
+ @Test
+ public void execute_invalidNameFilteredList_throwsCommandException() throws ParseException {
+ Name parsedNameAlice = TypicalPersons.ALICE.getName();
+ showPersonAtName(model, parsedNameAlice);
+
+ Name invalidName = TypicalPersons.BENSON.getName();
+ DeleteMemberCommand deleteCommand = new DeleteMemberCommand(invalidName);
+
+ assertCommandFailure(deleteCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_NAME);
+ }
+
+ @Test
+ public void execute_removePersonAsAssigneeFilteredPersonList_onDeleteSuccess() throws ParseException {
+ Person personToDelete = null;
+ Name parsedNameAlice = TypicalPersons.ALICE.getName();
+ DeleteMemberCommand deleteCommand = new DeleteMemberCommand(parsedNameAlice);
+
+ Task dummyTaskWithAssigned = new TaskBuilder().withAssignees(parsedNameAlice.fullName).build();
+
+ model.addTask(dummyTaskWithAssigned);
+
+ for (Person person : model.getFilteredPersonList()) {
+ Name currentName = person.getName();
+
+ if (currentName.equals(parsedNameAlice)) {
+ personToDelete = person;
+ break;
+ }
+ }
+
+ String expectedMessage = String.format(DeleteMemberCommand.MESSAGE_DELETE_PERSON_SUCCESS, personToDelete);
+
+ ModelManager expectedModel = new ModelManager(model.getHeyMatez(), new UserPrefs());
+
+ expectedModel.deletePerson(personToDelete);
+ expectedModel.removeAssignee(personToDelete);
+
+ assertCommandSuccess(deleteCommand, model, expectedMessage, expectedModel);
+ }
+
+ @Test
+ public void equals() throws ParseException {
+ Name parsedNameAlice = TypicalPersons.ALICE.getName();
+ Name parsedNameBenson = TypicalPersons.BENSON.getName();
+
+ DeleteMemberCommand deleteFirstCommand = new DeleteMemberCommand(parsedNameAlice);
+ DeleteMemberCommand deleteSecondCommand = new DeleteMemberCommand(parsedNameBenson);
+
+ // same object -> returns true
+ assertTrue(deleteFirstCommand.equals(deleteFirstCommand));
+
+ // same values -> returns true
+ DeleteMemberCommand deleteFirstCommandCopy = new DeleteMemberCommand(parsedNameAlice);
+ assertTrue(deleteFirstCommand.equals(deleteFirstCommandCopy));
+
+ // different types -> returns false
+ assertFalse(deleteFirstCommand.equals(1));
+
+ // null -> returns false
+ assertFalse(deleteFirstCommand.equals(null));
+
+ // different person -> returns false
+ assertFalse(deleteFirstCommand.equals(deleteSecondCommand));
+ }
+
+ /**
+ * Updates {@code model}'s filtered list to show no one.
+ */
+ private void showNoPerson(Model model) {
+ model.updateFilteredPersonList(p -> false);
+
+ assertTrue(model.getFilteredPersonList().isEmpty());
+ }
+}
diff --git a/src/test/java/seedu/heymatez/logic/commands/DeleteTaskCommandIntegrationTest.java b/src/test/java/seedu/heymatez/logic/commands/DeleteTaskCommandIntegrationTest.java
new file mode 100644
index 00000000000..7bf9f82f3db
--- /dev/null
+++ b/src/test/java/seedu/heymatez/logic/commands/DeleteTaskCommandIntegrationTest.java
@@ -0,0 +1,46 @@
+package seedu.heymatez.logic.commands;
+
+import static seedu.heymatez.logic.commands.CommandTestUtil.assertCommandFailure;
+import static seedu.heymatez.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.heymatez.testutil.TypicalTasks.getTypicalHeyMatez;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import seedu.heymatez.commons.core.Messages;
+import seedu.heymatez.commons.core.index.Index;
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.ModelManager;
+import seedu.heymatez.model.UserPrefs;
+import seedu.heymatez.model.task.Task;
+
+/**
+ * Contains integration tests (interaction with the Model) for {@code DeleteTaskCommand}.
+ */
+public class DeleteTaskCommandIntegrationTest {
+
+ private Model model;
+
+ @BeforeEach
+ public void setUp() {
+ model = new ModelManager(getTypicalHeyMatez(), new UserPrefs());
+ }
+
+ @Test
+ public void execute_deleteTask_success() {
+ Task validTask = model.getHeyMatez().getTaskList().get(0);
+ Model expectedModel = new ModelManager(model.getHeyMatez(), new UserPrefs());
+ expectedModel.deleteTask(validTask);
+
+ Index index = Index.fromOneBased(1);
+ assertCommandSuccess(new DeleteTaskCommand(index), model,
+ String.format(DeleteTaskCommand.MESSAGE_DELETE_TASK_SUCCESS, validTask), expectedModel);
+ }
+
+ @Test
+ public void execute_deleteTask_throwsIndexNotValid() {
+ Index index = Index.fromOneBased(model.getHeyMatez().getTaskList().size() + 1);
+ assertCommandFailure(new DeleteTaskCommand(index), model, Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+
+}
diff --git a/src/test/java/seedu/heymatez/logic/commands/DeleteTaskCommandTest.java b/src/test/java/seedu/heymatez/logic/commands/DeleteTaskCommandTest.java
new file mode 100644
index 00000000000..aa99f54d0b5
--- /dev/null
+++ b/src/test/java/seedu/heymatez/logic/commands/DeleteTaskCommandTest.java
@@ -0,0 +1,108 @@
+package seedu.heymatez.logic.commands;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.heymatez.logic.commands.CommandTestUtil.assertCommandFailure;
+import static seedu.heymatez.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.heymatez.logic.commands.CommandTestUtil.showTaskAtIndex;
+import static seedu.heymatez.testutil.TypicalIndexes.INDEX_FIRST_TASK;
+import static seedu.heymatez.testutil.TypicalIndexes.INDEX_SECOND_TASK;
+import static seedu.heymatez.testutil.TypicalTasks.getTypicalHeyMatez;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.heymatez.commons.core.Messages;
+import seedu.heymatez.commons.core.index.Index;
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.ModelManager;
+import seedu.heymatez.model.UserPrefs;
+import seedu.heymatez.model.task.Task;
+
+/**
+ * Contains integration tests (interaction with the Model) and unit tests for
+ * {@code DeleteTaskCommand}.
+ */
+public class DeleteTaskCommandTest {
+ private Model model = new ModelManager(getTypicalHeyMatez(), new UserPrefs());
+
+ @Test
+ public void execute_validIndexUnfilteredList_success() {
+ Task taskToDelete = model.getFilteredTaskList().get(INDEX_FIRST_TASK.getZeroBased());
+ DeleteTaskCommand deleteCommand = new DeleteTaskCommand(INDEX_FIRST_TASK);
+
+ String expectedMessage = String.format(DeleteTaskCommand.MESSAGE_DELETE_TASK_SUCCESS, taskToDelete);
+
+ ModelManager expectedModel = new ModelManager(model.getHeyMatez(), new UserPrefs());
+ expectedModel.deleteTask(taskToDelete);
+
+ assertCommandSuccess(deleteCommand, model, expectedMessage, expectedModel);
+ }
+
+ @Test
+ public void execute_invalidIndexUnfilteredList_throwsCommandException() {
+ Index outOfBoundIndex = Index.fromOneBased(model.getFilteredTaskList().size() + 1);
+ DeleteTaskCommand deleteCommand = new DeleteTaskCommand(outOfBoundIndex);
+
+ assertCommandFailure(deleteCommand, model, Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+
+ @Test
+ public void execute_validIndexFilteredList_success() {
+ showTaskAtIndex(model, INDEX_FIRST_TASK);
+
+ Task taskToDelete = model.getFilteredTaskList().get(INDEX_FIRST_TASK.getZeroBased());
+ DeleteTaskCommand deleteCommand = new DeleteTaskCommand(INDEX_FIRST_TASK);
+
+ String expectedMessage = String.format(DeleteTaskCommand.MESSAGE_DELETE_TASK_SUCCESS, taskToDelete);
+
+ Model expectedModel = new ModelManager(model.getHeyMatez(), new UserPrefs());
+ expectedModel.deleteTask(taskToDelete);
+ showNoTask(expectedModel);
+
+ assertCommandSuccess(deleteCommand, model, expectedMessage, expectedModel);
+ }
+
+ @Test
+ public void execute_invalidIndexFilteredList_throwsCommandException() {
+ showTaskAtIndex(model, INDEX_FIRST_TASK);
+
+ Index outOfBoundIndex = INDEX_SECOND_TASK;
+ // ensures that outOfBoundIndex is still in bounds of address book list
+ assertTrue(outOfBoundIndex.getZeroBased() < model.getHeyMatez().getTaskList().size());
+
+ DeleteTaskCommand deleteCommand = new DeleteTaskCommand(outOfBoundIndex);
+
+ assertCommandFailure(deleteCommand, model, Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+
+ @Test
+ public void equals() {
+ DeleteTaskCommand deleteFirstCommand = new DeleteTaskCommand(INDEX_FIRST_TASK);
+ DeleteTaskCommand deleteSecondCommand = new DeleteTaskCommand(INDEX_SECOND_TASK);
+
+ // same object -> returns true
+ assertTrue(deleteFirstCommand.equals(deleteFirstCommand));
+
+ // same values -> returns true
+ DeleteTaskCommand deleteFirstCommandCopy = new DeleteTaskCommand(INDEX_FIRST_TASK);
+ assertTrue(deleteFirstCommand.equals(deleteFirstCommandCopy));
+
+ // different types -> returns false
+ assertFalse(deleteFirstCommand.equals(1));
+
+ // null -> returns false
+ assertFalse(deleteFirstCommand.equals(null));
+
+ // different person -> returns false
+ assertFalse(deleteFirstCommand.equals(deleteSecondCommand));
+ }
+
+ /**
+ * Updates {@code model}'s filtered list to show no one.
+ */
+ private void showNoTask(Model model) {
+ model.updateFilteredTaskList(p -> false);
+
+ assertTrue(model.getFilteredTaskList().isEmpty());
+ }
+}
diff --git a/src/test/java/seedu/heymatez/logic/commands/DoneTaskCommandIntegrationTest.java b/src/test/java/seedu/heymatez/logic/commands/DoneTaskCommandIntegrationTest.java
new file mode 100644
index 00000000000..0a60e48a3bd
--- /dev/null
+++ b/src/test/java/seedu/heymatez/logic/commands/DoneTaskCommandIntegrationTest.java
@@ -0,0 +1,56 @@
+package seedu.heymatez.logic.commands;
+
+import static seedu.heymatez.logic.commands.CommandTestUtil.assertCommandFailure;
+import static seedu.heymatez.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.heymatez.testutil.TypicalIndexes.INDEX_FIRST_TASK;
+import static seedu.heymatez.testutil.TypicalIndexes.INDEX_THIRD_TASK;
+import static seedu.heymatez.testutil.TypicalTasks.getTypicalHeyMatez;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import seedu.heymatez.commons.core.Messages;
+import seedu.heymatez.commons.core.index.Index;
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.ModelManager;
+import seedu.heymatez.model.UserPrefs;
+import seedu.heymatez.model.task.Task;
+import seedu.heymatez.testutil.TaskBuilder;
+
+/**
+ * Contains integration tests (interaction with the Model) for {@code DoneTaskCommand}.
+ */
+public class DoneTaskCommandIntegrationTest {
+
+ private Model model;
+
+ @BeforeEach
+ public void setUp() {
+ model = new ModelManager(getTypicalHeyMatez(), new UserPrefs());
+ }
+
+ @Test
+ public void execute_doneTask_success() {
+ Task validTask = model.getHeyMatez().getTaskList().get(0);
+ Task doneTask = new TaskBuilder(validTask).withTaskStatus(TaskBuilder.COMPLETED_STATUS).build();
+
+ Model expectedModel = new ModelManager(model.getHeyMatez(), new UserPrefs());
+ model.setTask(validTask, doneTask);
+
+ assertCommandSuccess(new DoneTaskCommand(INDEX_FIRST_TASK), model, DoneTaskCommand.MESSAGE_DONE_TASK_SUCCESS,
+ expectedModel);
+ }
+
+ @Test
+ public void execute_done_throwsIndexNotValid() {
+ Index index = Index.fromOneBased(model.getHeyMatez().getTaskList().size() + 1);
+ assertCommandFailure(new DoneTaskCommand(index), model, Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+
+ @Test
+ public void execute_done_throwsTaskIsAlreadyCompleted() {
+ Index index = Index.fromOneBased(3);
+ assertCommandFailure(new DoneTaskCommand(INDEX_THIRD_TASK), model,
+ DoneTaskCommand.MESSAGE_TASK_ALREADY_MARKED_DONE);
+ }
+}
diff --git a/src/test/java/seedu/heymatez/logic/commands/DoneTaskCommandTest.java b/src/test/java/seedu/heymatez/logic/commands/DoneTaskCommandTest.java
new file mode 100644
index 00000000000..3d9ee7bfbf2
--- /dev/null
+++ b/src/test/java/seedu/heymatez/logic/commands/DoneTaskCommandTest.java
@@ -0,0 +1,123 @@
+package seedu.heymatez.logic.commands;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.heymatez.logic.commands.CommandTestUtil.assertCommandFailure;
+import static seedu.heymatez.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.heymatez.logic.commands.CommandTestUtil.showTaskAtIndex;
+import static seedu.heymatez.testutil.TypicalIndexes.INDEX_FIRST_TASK;
+import static seedu.heymatez.testutil.TypicalIndexes.INDEX_SECOND_TASK;
+import static seedu.heymatez.testutil.TypicalIndexes.INDEX_THIRD_TASK;
+import static seedu.heymatez.testutil.TypicalTasks.getTypicalHeyMatez;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.heymatez.commons.core.Messages;
+import seedu.heymatez.commons.core.index.Index;
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.ModelManager;
+import seedu.heymatez.model.UserPrefs;
+import seedu.heymatez.model.task.Task;
+import seedu.heymatez.testutil.TaskBuilder;
+
+/**
+ * Contains integration tests (interaction with the Model) and unit tests for
+ * {@code DoneTaskCommand}.
+ */
+public class DoneTaskCommandTest {
+ private Model model = new ModelManager(getTypicalHeyMatez(), new UserPrefs());
+
+ @Test
+ public void execute_validIndexUnfilteredList_success() {
+ Task taskToMarkDone = model.getFilteredTaskList().get(INDEX_FIRST_TASK.getZeroBased());
+
+ Task doneTask = new TaskBuilder(taskToMarkDone).withTaskStatus(TaskBuilder.COMPLETED_STATUS).build();
+
+ DoneTaskCommand doneCommand = new DoneTaskCommand(INDEX_FIRST_TASK);
+
+ String expectedMessage = DoneTaskCommand.MESSAGE_DONE_TASK_SUCCESS;
+
+ ModelManager expectedModel = new ModelManager(model.getHeyMatez(), new UserPrefs());
+ expectedModel.setTask(taskToMarkDone, doneTask);
+
+ assertCommandSuccess(doneCommand, model, expectedMessage, expectedModel);
+ }
+
+ @Test
+ public void execute_invalidIndexUnfilteredList_throwsCommandException() {
+ Index outOfBoundIndex = Index.fromOneBased(model.getFilteredTaskList().size() + 1);
+ DoneTaskCommand doneCommand = new DoneTaskCommand(outOfBoundIndex);
+
+ assertCommandFailure(doneCommand, model, Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+
+ @Test
+ public void execute_validIndexFilteredList_success() {
+ showTaskAtIndex(model, INDEX_FIRST_TASK);
+
+ Task taskToMarkDone = model.getFilteredTaskList().get(INDEX_FIRST_TASK.getZeroBased());
+ Task doneTask = new TaskBuilder(taskToMarkDone).withTaskStatus(TaskBuilder.COMPLETED_STATUS).build();
+
+ DoneTaskCommand doneCommand = new DoneTaskCommand(INDEX_FIRST_TASK);
+
+ String expectedMessage = DoneTaskCommand.MESSAGE_DONE_TASK_SUCCESS;
+
+ Model expectedModel = new ModelManager(model.getHeyMatez(), new UserPrefs());
+
+ expectedModel.setTask(taskToMarkDone, doneTask);
+ showNoTask(expectedModel);
+
+ assertCommandSuccess(doneCommand, model, expectedMessage, expectedModel);
+ }
+
+ @Test
+ public void task_already_markedCompleted() {
+ DoneTaskCommand doneCommand = new DoneTaskCommand(INDEX_THIRD_TASK);
+
+ assertCommandFailure(doneCommand, model, DoneTaskCommand.MESSAGE_TASK_ALREADY_MARKED_DONE);
+ }
+
+ @Test
+ public void execute_invalidIndexFilteredList_throwsCommandException() {
+ showTaskAtIndex(model, INDEX_FIRST_TASK);
+
+ Index outOfBoundIndex = INDEX_SECOND_TASK;
+ // ensures that outOfBoundIndex is still in bounds of task list
+ assertTrue(outOfBoundIndex.getZeroBased() < model.getHeyMatez().getTaskList().size());
+
+ DoneTaskCommand doneCommand = new DoneTaskCommand(outOfBoundIndex);
+
+ assertCommandFailure(doneCommand, model, Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+
+ @Test
+ public void equals() {
+ DoneTaskCommand doneFirstCommand = new DoneTaskCommand(INDEX_FIRST_TASK);
+ DoneTaskCommand doneSecondCommand = new DoneTaskCommand(INDEX_SECOND_TASK);
+
+ // same object -> returns true
+ assertTrue(doneFirstCommand.equals(doneFirstCommand));
+
+ // same values -> returns true
+ DoneTaskCommand doneFirstCommandCopy = new DoneTaskCommand(INDEX_FIRST_TASK);
+ assertTrue(doneFirstCommand.equals(doneFirstCommandCopy));
+
+ // different types -> returns false
+ assertFalse(doneFirstCommand.equals(1));
+
+ // null -> returns false
+ assertFalse(doneFirstCommand.equals(null));
+
+ // different person -> returns false
+ assertFalse(doneFirstCommand.equals(doneSecondCommand));
+ }
+
+ /**
+ * Updates {@code model}'s filtered list to show no one.
+ */
+ private void showNoTask(Model model) {
+ model.updateFilteredTaskList(p -> false);
+
+ assertTrue(model.getFilteredTaskList().isEmpty());
+ }
+}
diff --git a/src/test/java/seedu/heymatez/logic/commands/EditMemberCommandTest.java b/src/test/java/seedu/heymatez/logic/commands/EditMemberCommandTest.java
new file mode 100644
index 00000000000..0091e6b560a
--- /dev/null
+++ b/src/test/java/seedu/heymatez/logic/commands/EditMemberCommandTest.java
@@ -0,0 +1,216 @@
+package seedu.heymatez.logic.commands;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.heymatez.logic.commands.CommandTestUtil.DESC_AMY;
+import static seedu.heymatez.logic.commands.CommandTestUtil.DESC_BOB;
+import static seedu.heymatez.logic.commands.CommandTestUtil.VALID_NAME_BOB;
+import static seedu.heymatez.logic.commands.CommandTestUtil.VALID_PHONE_BOB;
+import static seedu.heymatez.logic.commands.CommandTestUtil.assertCommandFailure;
+import static seedu.heymatez.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.heymatez.logic.commands.CommandTestUtil.showPersonAtName;
+import static seedu.heymatez.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
+import static seedu.heymatez.testutil.TypicalPersons.getTypicalHeyMatez;
+
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.heymatez.commons.core.Messages;
+import seedu.heymatez.logic.commands.EditMemberCommand.EditMemberDescriptor;
+import seedu.heymatez.logic.parser.exceptions.ParseException;
+import seedu.heymatez.model.HeyMatez;
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.ModelManager;
+import seedu.heymatez.model.UserPrefs;
+import seedu.heymatez.model.person.Name;
+import seedu.heymatez.model.person.Person;
+import seedu.heymatez.model.task.Task;
+import seedu.heymatez.testutil.EditMemberDescriptorBuilder;
+import seedu.heymatez.testutil.PersonBuilder;
+import seedu.heymatez.testutil.TaskBuilder;
+import seedu.heymatez.testutil.TypicalPersons;
+
+/**
+ * Contains integration tests (interaction with the Model) and unit tests for EditMemberCommand.
+ */
+public class EditMemberCommandTest {
+
+ private Model model = new ModelManager(getTypicalHeyMatez(), new UserPrefs());
+
+ @Test
+ public void execute_allFieldsSpecifiedUnfilteredList_success() throws ParseException {
+ Name parsedNameAlice = TypicalPersons.ALICE.getName();
+
+ Person editedPerson = new PersonBuilder().build();
+ EditMemberCommand.EditMemberDescriptor descriptor = new EditMemberDescriptorBuilder(editedPerson).build();
+ EditMemberCommand editMemberCommand = new EditMemberCommand(parsedNameAlice, descriptor);
+
+ String expectedMessage = String.format(EditMemberCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedPerson);
+
+ Model expectedModel = new ModelManager(new HeyMatez(model.getHeyMatez()), new UserPrefs());
+ expectedModel.setPerson(model.getFilteredPersonList().get(0), editedPerson);
+
+ assertCommandSuccess(editMemberCommand, model, expectedMessage, expectedModel);
+ }
+
+ @Test
+ public void execute_someFieldsSpecifiedUnfilteredList_success() {
+ List personList = model.getFilteredPersonList();
+ Person lastPerson = personList.get(personList.size() - 1);
+ Name nameLastPerson = lastPerson.getName();
+
+ PersonBuilder personInList = new PersonBuilder(lastPerson);
+ Person editedPerson = personInList.withName(VALID_NAME_BOB).withPhone(VALID_PHONE_BOB).build();
+
+ EditMemberCommand.EditMemberDescriptor descriptor = new EditMemberDescriptorBuilder().withName(VALID_NAME_BOB)
+ .withPhone(VALID_PHONE_BOB).build();
+ EditMemberCommand editMemberCommand = new EditMemberCommand(nameLastPerson, descriptor);
+
+ String expectedMessage = String.format(EditMemberCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedPerson);
+
+ Model expectedModel = new ModelManager(new HeyMatez(model.getHeyMatez()), new UserPrefs());
+ expectedModel.setPerson(lastPerson, editedPerson);
+
+ assertCommandSuccess(editMemberCommand, model, expectedMessage, expectedModel);
+ }
+
+ @Test
+ public void execute_noFieldSpecifiedUnfilteredList_success() throws ParseException {
+ Name parsedNameAlice = TypicalPersons.ALICE.getName();
+
+ EditMemberCommand editMemberCommand = new EditMemberCommand(parsedNameAlice,
+ new EditMemberCommand.EditMemberDescriptor());
+ Person editedPerson = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased());
+
+ String expectedMessage = String.format(EditMemberCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedPerson);
+
+ Model expectedModel = new ModelManager(new HeyMatez(model.getHeyMatez()), new UserPrefs());
+
+ assertCommandSuccess(editMemberCommand, model, expectedMessage, expectedModel);
+ }
+
+ @Test
+ public void execute_duplicatePersonUnfilteredList_failure() {
+ Person firstPerson = TypicalPersons.ALICE;
+ Name secondPerson = TypicalPersons.BENSON.getName();
+
+ EditMemberDescriptor descriptor = new EditMemberDescriptorBuilder(firstPerson).build();
+ EditMemberCommand editMemberCommand = new EditMemberCommand(secondPerson, descriptor);
+
+ assertCommandFailure(editMemberCommand, model, EditMemberCommand.MESSAGE_DUPLICATE_PERSON);
+ }
+
+ @Test
+ public void execute_duplicatePersonFilteredList_failure() throws ParseException {
+ Name parsedNameAlice = TypicalPersons.ALICE.getName();
+ Name parsedNameBenson = TypicalPersons.BENSON.getName();
+ showPersonAtName(model, parsedNameAlice);
+
+ Person personInList = null;
+
+ // edit person in filtered list into a duplicate in address book
+ for (Person person : model.getHeyMatez().getPersonList()) {
+ Name currentName = person.getName();
+
+ if (currentName.equals(parsedNameBenson)) {
+ personInList = person;
+ break;
+ }
+ }
+
+ EditMemberCommand editMemberCommand = new EditMemberCommand(parsedNameAlice,
+ new EditMemberDescriptorBuilder(personInList).build());
+
+ assertCommandFailure(editMemberCommand, model, EditMemberCommand.MESSAGE_DUPLICATE_PERSON);
+ }
+
+ @Test
+ public void execute_invalidPersonNameUnfilteredList_failure() {
+ Name invalidName = new Name("John");
+ EditMemberCommand.EditMemberDescriptor descriptor =
+ new EditMemberDescriptorBuilder().withName(VALID_NAME_BOB).build();
+ EditMemberCommand editMemberCommand = new EditMemberCommand(invalidName, descriptor);
+
+ assertCommandFailure(editMemberCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_NAME);
+ }
+
+ /**
+ * Edit filtered list where the input name is invalid.
+ */
+ @Test
+ public void execute_invalidPersonNameFilteredList_failure() throws ParseException {
+ Name parsedNameAlice = TypicalPersons.ALICE.getName();
+ Name invalidName = TypicalPersons.BENSON.getName();
+ showPersonAtName(model, parsedNameAlice);
+
+ EditMemberCommand editMemberCommand = new EditMemberCommand(invalidName,
+ new EditMemberDescriptorBuilder().withName(VALID_NAME_BOB).build());
+
+ assertCommandFailure(editMemberCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_NAME);
+ }
+
+ @Test
+ public void execute_editAssigneeName_filteredListSuccess() throws ParseException {
+ Name parsedNameAlice = TypicalPersons.ALICE.getName();
+ showPersonAtName(model, parsedNameAlice);
+
+ Person personInFilteredList = null;
+
+ Task dummyTaskWithAssigned = new TaskBuilder().withAssignees(parsedNameAlice.fullName).build();
+
+ for (Person person : model.getFilteredPersonList()) {
+ Name currentName = person.getName();
+
+ if (currentName.equals(parsedNameAlice)) {
+ personInFilteredList = person;
+ break;
+ }
+ }
+
+ model.addTask(dummyTaskWithAssigned);
+
+ Person editedPerson = new PersonBuilder(personInFilteredList).withName(VALID_NAME_BOB).build();
+
+ EditMemberCommand editMemberCommand = new EditMemberCommand(parsedNameAlice,
+ new EditMemberDescriptorBuilder().withName(VALID_NAME_BOB).build());
+
+ String expectedMessage = String.format(EditMemberCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedPerson);
+
+ Model expectedModel = new ModelManager(new HeyMatez(model.getHeyMatez()), new UserPrefs());
+ expectedModel.setPerson(model.getFilteredPersonList().get(0), editedPerson);
+ expectedModel.editAssignee(personInFilteredList, editedPerson);
+
+ assertCommandSuccess(editMemberCommand, model, expectedMessage, expectedModel);
+ }
+
+
+ @Test
+ public void equals() throws ParseException {
+ Name parsedNameAlice = TypicalPersons.ALICE.getName();
+ Name parsedNameBenson = TypicalPersons.BENSON.getName();
+
+ final EditMemberCommand standardCommand = new EditMemberCommand(parsedNameAlice, DESC_AMY);
+
+ // same values -> returns true
+ EditMemberCommand.EditMemberDescriptor copyDescriptor = new EditMemberCommand.EditMemberDescriptor(DESC_AMY);
+ EditMemberCommand commandWithSameValues = new EditMemberCommand(parsedNameAlice, copyDescriptor);
+ assertTrue(standardCommand.equals(commandWithSameValues));
+
+ // same object -> returns true
+ assertTrue(standardCommand.equals(standardCommand));
+
+ // null -> returns false
+ assertFalse(standardCommand.equals(null));
+
+ // different types -> returns false
+ assertFalse(standardCommand.equals(new ClearCommand()));
+
+ // different index -> returns false
+ assertFalse(standardCommand.equals(new EditMemberCommand(parsedNameBenson, DESC_AMY)));
+
+ // different descriptor -> returns false
+ assertFalse(standardCommand.equals(new EditMemberCommand(parsedNameAlice, DESC_BOB)));
+ }
+
+}
diff --git a/src/test/java/seedu/heymatez/logic/commands/EditMemberDescriptorTest.java b/src/test/java/seedu/heymatez/logic/commands/EditMemberDescriptorTest.java
new file mode 100644
index 00000000000..d1c7fb50ffd
--- /dev/null
+++ b/src/test/java/seedu/heymatez/logic/commands/EditMemberDescriptorTest.java
@@ -0,0 +1,52 @@
+package seedu.heymatez.logic.commands;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.heymatez.logic.commands.CommandTestUtil.DESC_AMY;
+import static seedu.heymatez.logic.commands.CommandTestUtil.DESC_BOB;
+import static seedu.heymatez.logic.commands.CommandTestUtil.VALID_EMAIL_BOB;
+import static seedu.heymatez.logic.commands.CommandTestUtil.VALID_NAME_BOB;
+import static seedu.heymatez.logic.commands.CommandTestUtil.VALID_PHONE_BOB;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.heymatez.logic.commands.EditMemberCommand.EditMemberDescriptor;
+import seedu.heymatez.testutil.EditMemberDescriptorBuilder;
+
+/**
+ * Contains unit tests for {@code EditMemberDescriptor}.
+ */
+public class EditMemberDescriptorTest {
+
+ @Test
+ public void equals() {
+ // same values -> returns true
+ EditMemberDescriptor descriptorWithSameValues = new EditMemberDescriptor(DESC_AMY);
+ assertTrue(DESC_AMY.equals(descriptorWithSameValues));
+
+ // same object -> returns true
+ assertTrue(DESC_AMY.equals(DESC_AMY));
+
+ // null -> returns false
+ assertFalse(DESC_AMY.equals(null));
+
+ // different types -> returns false
+ assertFalse(DESC_AMY.equals(5));
+
+ // different values -> returns false
+ assertFalse(DESC_AMY.equals(DESC_BOB));
+
+ // different name -> returns false
+ EditMemberDescriptor editedAmy = new EditMemberDescriptorBuilder(DESC_AMY).withName(VALID_NAME_BOB).build();
+ assertFalse(DESC_AMY.equals(editedAmy));
+
+ // different phone -> returns false
+ editedAmy = new EditMemberDescriptorBuilder(DESC_AMY).withPhone(VALID_PHONE_BOB).build();
+ assertFalse(DESC_AMY.equals(editedAmy));
+
+ // different email -> returns false
+ editedAmy = new EditMemberDescriptorBuilder(DESC_AMY).withEmail(VALID_EMAIL_BOB).build();
+ assertFalse(DESC_AMY.equals(editedAmy));
+
+ }
+}
diff --git a/src/test/java/seedu/heymatez/logic/commands/EditTaskCommandTest.java b/src/test/java/seedu/heymatez/logic/commands/EditTaskCommandTest.java
new file mode 100644
index 00000000000..616fe67996e
--- /dev/null
+++ b/src/test/java/seedu/heymatez/logic/commands/EditTaskCommandTest.java
@@ -0,0 +1,161 @@
+package seedu.heymatez.logic.commands;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.heymatez.logic.commands.CommandTestUtil.DESC_TASK1;
+import static seedu.heymatez.logic.commands.CommandTestUtil.DESC_TASK2;
+import static seedu.heymatez.logic.commands.CommandTestUtil.VALID_DEADLINE_MARATHON;
+import static seedu.heymatez.logic.commands.CommandTestUtil.VALID_DESCRIPTION_MARATHON;
+import static seedu.heymatez.logic.commands.CommandTestUtil.VALID_TITLE_MARATHON;
+import static seedu.heymatez.logic.commands.CommandTestUtil.VALID_TITLE_MEETING;
+import static seedu.heymatez.logic.commands.CommandTestUtil.assertCommandFailure;
+import static seedu.heymatez.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.heymatez.logic.commands.CommandTestUtil.showTaskAtIndex;
+import static seedu.heymatez.testutil.TypicalIndexes.INDEX_FIRST_TASK;
+import static seedu.heymatez.testutil.TypicalIndexes.INDEX_SECOND_TASK;
+import static seedu.heymatez.testutil.TypicalTasks.getTypicalHeyMatez;
+
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.heymatez.commons.core.Messages;
+import seedu.heymatez.commons.core.index.Index;
+import seedu.heymatez.logic.parser.exceptions.ParseException;
+import seedu.heymatez.model.HeyMatez;
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.ModelManager;
+import seedu.heymatez.model.UserPrefs;
+import seedu.heymatez.model.task.Task;
+import seedu.heymatez.testutil.EditTaskDescriptorBuilder;
+import seedu.heymatez.testutil.TaskBuilder;
+
+/**
+ * Contains integration tests (interaction with the Model) and unit tests for EditTaskCommand.
+ */
+public class EditTaskCommandTest {
+
+ private Model model = new ModelManager(getTypicalHeyMatez(), new UserPrefs());
+
+ @Test
+ public void execute_allFieldsSpecifiedUnfilteredList_success() {
+ Task editedTask = new TaskBuilder().build();
+ EditTaskCommand.EditTaskDescriptor descriptor = new EditTaskDescriptorBuilder(editedTask).build();
+ EditTaskCommand editTaskCommand = new EditTaskCommand(INDEX_FIRST_TASK, descriptor);
+
+ String expectedMessage = String.format(EditTaskCommand.MESSAGE_EDIT_TASK_SUCCESS, editedTask);
+
+ Model expectedModel = new ModelManager(model.getHeyMatez(), new UserPrefs());
+ expectedModel.setTask(model.getFilteredTaskList().get(0), editedTask);
+
+ assertCommandSuccess(editTaskCommand, model, expectedMessage, expectedModel);
+ }
+
+ @Test
+ public void execute_someFieldsSpecifiedUnfilteredList_success() {
+ List taskList = model.getFilteredTaskList();
+ Index indexLastTask = Index.fromOneBased(taskList.size());
+ Task lastTask = taskList.get(indexLastTask.getZeroBased());
+
+ TaskBuilder taskInList = new TaskBuilder(lastTask);
+ Task editedTask = taskInList.withTitle(VALID_TITLE_MARATHON)
+ .withDescription(VALID_DESCRIPTION_MARATHON).withDeadline(VALID_DEADLINE_MARATHON).build();
+
+ EditTaskCommand.EditTaskDescriptor descriptor = new EditTaskDescriptorBuilder().withTitle(VALID_TITLE_MARATHON)
+ .withDescription(VALID_DESCRIPTION_MARATHON).withDeadline(VALID_DEADLINE_MARATHON).build();
+ EditTaskCommand editTaskCommand = new EditTaskCommand(indexLastTask, descriptor);
+
+ String expectedMessage = String.format(EditTaskCommand.MESSAGE_EDIT_TASK_SUCCESS, editedTask);
+
+ Model expectedModel = new ModelManager(new HeyMatez(model.getHeyMatez()), new UserPrefs());
+ expectedModel.setTask(lastTask, editedTask);
+
+ assertCommandSuccess(editTaskCommand, model, expectedMessage, expectedModel);
+ }
+
+ @Test
+ public void execute_noFieldSpecifiedUnfilteredList_success() {
+ EditTaskCommand editTaskCommand = new EditTaskCommand(INDEX_FIRST_TASK,
+ new EditTaskCommand.EditTaskDescriptor());
+ Task editedTask = model.getFilteredTaskList().get(INDEX_FIRST_TASK.getZeroBased());
+
+ String expectedMessage = String.format(EditTaskCommand.MESSAGE_EDIT_TASK_SUCCESS, editedTask);
+
+ Model expectedModel = new ModelManager(model.getHeyMatez(), new UserPrefs());
+
+ assertCommandSuccess(editTaskCommand, model, expectedMessage, expectedModel);
+ }
+
+
+ @Test
+ public void execute_filteredList_success() {
+ showTaskAtIndex(model, INDEX_FIRST_TASK);
+
+ Task taskInFilteredList = model.getFilteredTaskList().get(INDEX_FIRST_TASK.getZeroBased());
+ Task editedTask = new TaskBuilder(taskInFilteredList).withTitle(VALID_TITLE_MEETING).build();
+
+ EditTaskCommand editTaskCommand = new EditTaskCommand(INDEX_FIRST_TASK,
+ new EditTaskDescriptorBuilder().withTitle(VALID_TITLE_MEETING).build());
+
+ String expectedMessage = String.format(EditTaskCommand.MESSAGE_EDIT_TASK_SUCCESS, editedTask);
+
+ Model expectedModel = new ModelManager(new HeyMatez(model.getHeyMatez()), new UserPrefs());
+ expectedModel.setTask(model.getFilteredTaskList().get(0), editedTask);
+
+ assertCommandSuccess(editTaskCommand, model, expectedMessage, expectedModel);
+ }
+
+ @Test
+ public void execute_invalidTaskIndexUnfilteredList_failure() {
+ showTaskAtIndex(model, INDEX_FIRST_TASK);
+ Index outOfBound = INDEX_SECOND_TASK;
+ assertTrue(outOfBound.getZeroBased() < model.getHeyMatez().getTaskList().size());
+
+ EditTaskCommand editTaskCommand = new EditTaskCommand(outOfBound,
+ new EditTaskDescriptorBuilder().withTitle(VALID_TITLE_MARATHON).build());
+
+ assertCommandFailure(editTaskCommand, model, Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+
+ /**
+ * Edit filtered list where index is larger than size of filtered list,
+ * but smaller than size of HeyMatez.
+ */
+ @Test
+ public void execute_invalidTaskIndexFilteredList_failure() {
+ showTaskAtIndex(model, INDEX_FIRST_TASK);
+ Index outOfBound = INDEX_SECOND_TASK;
+
+ assertTrue(outOfBound.getZeroBased() < model.getHeyMatez().getTaskList().size());
+
+ EditTaskCommand editTaskCommand = new EditTaskCommand(outOfBound,
+ new EditTaskDescriptorBuilder().withTitle(VALID_TITLE_MARATHON).build());
+
+ assertCommandFailure(editTaskCommand, model, Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+
+ @Test
+ public void equals() throws ParseException {
+ final EditTaskCommand standardCommand = new EditTaskCommand(INDEX_FIRST_TASK, DESC_TASK1);
+ // same values -> returns true
+ EditTaskCommand.EditTaskDescriptor copyDescriptor = new EditTaskCommand.EditTaskDescriptor(DESC_TASK1);
+ EditTaskCommand commandWithSameValues = new EditTaskCommand(INDEX_FIRST_TASK, copyDescriptor);
+ assertTrue(standardCommand.equals(commandWithSameValues));
+
+ // same object -> returns true
+ assertTrue(standardCommand.equals(standardCommand));
+
+ // null -> returns false
+ assertFalse(standardCommand.equals(null));
+
+ // different types -> returns false
+ assertFalse(standardCommand.equals(new ClearCommand()));
+
+ // different index -> returns false
+ assertFalse(standardCommand.equals(new EditTaskCommand(INDEX_SECOND_TASK, DESC_TASK1)));
+
+ // different descriptor -> returns false
+ assertFalse(standardCommand.equals(new EditTaskCommand(INDEX_FIRST_TASK, DESC_TASK2)));
+ }
+
+}
diff --git a/src/test/java/seedu/heymatez/logic/commands/EditTaskDescriptorTest.java b/src/test/java/seedu/heymatez/logic/commands/EditTaskDescriptorTest.java
new file mode 100644
index 00000000000..475b75cc4de
--- /dev/null
+++ b/src/test/java/seedu/heymatez/logic/commands/EditTaskDescriptorTest.java
@@ -0,0 +1,61 @@
+package seedu.heymatez.logic.commands;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.heymatez.logic.commands.CommandTestUtil.DESC_TASK1;
+import static seedu.heymatez.logic.commands.CommandTestUtil.DESC_TASK2;
+import static seedu.heymatez.logic.commands.CommandTestUtil.TITLE_DESC_TASK1;
+import static seedu.heymatez.logic.commands.CommandTestUtil.VALID_ASSIGNEE_MARATHON;
+import static seedu.heymatez.logic.commands.CommandTestUtil.VALID_DEADLINE_MEETING;
+import static seedu.heymatez.logic.commands.CommandTestUtil.VALID_DESCRIPTION_MEETING;
+import static seedu.heymatez.logic.commands.CommandTestUtil.VALID_TITLE_MEETING;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.heymatez.testutil.EditTaskDescriptorBuilder;
+
+/**
+ * Contains unit tests for EditTaskDescriptorCommand.
+ */
+public class EditTaskDescriptorTest {
+ @Test
+ public void equals() {
+ // same values -> returns true
+ EditTaskCommand.EditTaskDescriptor descriptorWithSameValues = new EditTaskCommand
+ .EditTaskDescriptor(DESC_TASK1);
+ assertTrue(DESC_TASK1.equals(descriptorWithSameValues));
+
+ // same object -> returns true
+ assertTrue(DESC_TASK1.equals(DESC_TASK1));
+
+ // null -> returns false
+ assertFalse(DESC_TASK1.equals(null));
+
+ // different types -> returns false
+ assertFalse(DESC_TASK1.equals(TITLE_DESC_TASK1));
+
+ // different values -> returns false
+ assertFalse(DESC_TASK1.equals(DESC_TASK2));
+
+ // different title -> returns false
+ EditTaskCommand.EditTaskDescriptor editedTask = new EditTaskDescriptorBuilder(DESC_TASK1)
+ .withTitle(VALID_TITLE_MEETING).build();
+ assertFalse(DESC_TASK1.equals(editedTask));
+
+ // different description -> returns false
+ editedTask = new EditTaskDescriptorBuilder(DESC_TASK1).withDescription(VALID_DESCRIPTION_MEETING).build();
+ assertFalse(DESC_TASK1.equals(editedTask));
+
+ // different deadline -> returns false
+ editedTask = new EditTaskDescriptorBuilder(DESC_TASK1).withDeadline(VALID_DEADLINE_MEETING).build();
+ assertFalse(DESC_TASK1.equals(editedTask));
+
+ // different priority -> returns false
+ editedTask = new EditTaskDescriptorBuilder(DESC_TASK2).withPriority("low").build();
+ assertFalse(DESC_TASK2.equals(editedTask));
+
+ // different assignee -> returns false
+ editedTask = new EditTaskDescriptorBuilder(DESC_TASK2).withAssignees(VALID_ASSIGNEE_MARATHON).build();
+ assertFalse(DESC_TASK2.equals(editedTask));
+ }
+}
diff --git a/src/test/java/seedu/address/logic/commands/ExitCommandTest.java b/src/test/java/seedu/heymatez/logic/commands/ExitCommandTest.java
similarity index 53%
rename from src/test/java/seedu/address/logic/commands/ExitCommandTest.java
rename to src/test/java/seedu/heymatez/logic/commands/ExitCommandTest.java
index 9533c473875..eace65c7b5e 100644
--- a/src/test/java/seedu/address/logic/commands/ExitCommandTest.java
+++ b/src/test/java/seedu/heymatez/logic/commands/ExitCommandTest.java
@@ -1,13 +1,16 @@
-package seedu.address.logic.commands;
+package seedu.heymatez.logic.commands;
-import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
-import static seedu.address.logic.commands.ExitCommand.MESSAGE_EXIT_ACKNOWLEDGEMENT;
+import static seedu.heymatez.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.heymatez.logic.commands.ExitCommand.MESSAGE_EXIT_ACKNOWLEDGEMENT;
import org.junit.jupiter.api.Test;
-import seedu.address.model.Model;
-import seedu.address.model.ModelManager;
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.ModelManager;
+/**
+ * Contains integration tests (interaction with Model) and unit tests for ExitCommand.
+ */
public class ExitCommandTest {
private Model model = new ModelManager();
private Model expectedModel = new ModelManager();
diff --git a/src/test/java/seedu/heymatez/logic/commands/FindByPriorityCommandIntegrationTest.java b/src/test/java/seedu/heymatez/logic/commands/FindByPriorityCommandIntegrationTest.java
new file mode 100644
index 00000000000..8805d6c3521
--- /dev/null
+++ b/src/test/java/seedu/heymatez/logic/commands/FindByPriorityCommandIntegrationTest.java
@@ -0,0 +1,57 @@
+package seedu.heymatez.logic.commands;
+
+import static seedu.heymatez.commons.core.Messages.MESSAGE_EMPTY_TASK_LIST;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_TASKS_LISTED_OVERVIEW;
+import static seedu.heymatez.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.heymatez.testutil.TypicalTasks.getTypicalHeyMatez;
+
+import java.util.ArrayList;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.ModelManager;
+import seedu.heymatez.model.UserPrefs;
+import seedu.heymatez.model.task.PriorityContainsKeywordPredicate;
+
+/**
+ * Contains integration tests (interaction with the Model) for {@code FindByPriorityCommand}.
+ */
+public class FindByPriorityCommandIntegrationTest {
+
+ private Model model = new ModelManager(getTypicalHeyMatez(), new UserPrefs());
+
+ @Test
+ public void checkSuccessfulFinding() {
+
+ Model expectedModel = new ModelManager(getTypicalHeyMatez(), new UserPrefs());
+
+ ArrayList newList = new ArrayList<>();
+ newList.add("low");
+
+ PriorityContainsKeywordPredicate predicate = new PriorityContainsKeywordPredicate(newList);
+ expectedModel.updateFilteredTaskList(predicate);
+
+ String expectedMessage = String.format(MESSAGE_TASKS_LISTED_OVERVIEW,
+ expectedModel.getFilteredTaskList().size());
+
+ assertCommandSuccess(new FindByPriorityCommand(predicate), model, expectedMessage, expectedModel);
+ }
+
+ @Test
+ public void checkNoTasksFound() {
+
+ Model expectedModel = new ModelManager(getTypicalHeyMatez(), new UserPrefs());
+
+ ArrayList newList = new ArrayList<>();
+ newList.add("high");
+
+ PriorityContainsKeywordPredicate predicate = new PriorityContainsKeywordPredicate(newList);
+ expectedModel.updateFilteredTaskList(predicate);
+
+ String expectedMessage = MESSAGE_EMPTY_TASK_LIST;
+
+ assertCommandSuccess(new FindByPriorityCommand(predicate), model, expectedMessage, expectedModel);
+ }
+
+}
diff --git a/src/test/java/seedu/heymatez/logic/commands/FindByPriorityCommandTest.java b/src/test/java/seedu/heymatez/logic/commands/FindByPriorityCommandTest.java
new file mode 100644
index 00000000000..9ea27a85f34
--- /dev/null
+++ b/src/test/java/seedu/heymatez/logic/commands/FindByPriorityCommandTest.java
@@ -0,0 +1,108 @@
+package seedu.heymatez.logic.commands;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_EMPTY_TASK_LIST;
+import static seedu.heymatez.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.heymatez.testutil.TypicalPersons.getTypicalHeyMatez;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.ModelManager;
+import seedu.heymatez.model.UserPrefs;
+import seedu.heymatez.model.task.PriorityContainsKeywordPredicate;
+
+/**
+ * Contains integration tests (interaction with the Model) and unit tests for {@code FindByPriorityCommand}.
+ */
+public class FindByPriorityCommandTest {
+ private Model model = new ModelManager(getTypicalHeyMatez(), new UserPrefs());
+ private Model expectedModel = new ModelManager(getTypicalHeyMatez(), new UserPrefs());
+
+ @Test
+ public void equals() {
+ PriorityContainsKeywordPredicate firstPredicate =
+ new PriorityContainsKeywordPredicate(Collections.singletonList("first"));
+ PriorityContainsKeywordPredicate secondPredicate =
+ new PriorityContainsKeywordPredicate(Collections.singletonList("second"));
+
+ FindByPriorityCommand findFirstCommand = new FindByPriorityCommand(firstPredicate);
+ FindByPriorityCommand findSecondCommand = new FindByPriorityCommand(secondPredicate);
+
+ // same object -> returns true
+ assertTrue(findFirstCommand.equals(findFirstCommand));
+
+ // same values -> returns true
+ FindByPriorityCommand findFirstCommandCopy = new FindByPriorityCommand(firstPredicate);
+ assertTrue(findFirstCommand.equals(findFirstCommandCopy));
+
+ // different types -> returns false
+ assertFalse(findFirstCommand.equals(1));
+
+ // null -> returns false
+ assertFalse(findFirstCommand.equals(null));
+
+ // different person -> returns false
+ assertFalse(findFirstCommand.equals(findSecondCommand));
+ }
+
+ @Test
+ public void execute_zeroKeywords_noTaskFound() {
+ String expectedMessage = MESSAGE_EMPTY_TASK_LIST;
+
+ PriorityContainsKeywordPredicate predicate = preparePredicate(" ");
+
+ FindByPriorityCommand command = new FindByPriorityCommand(predicate);
+ expectedModel.updateFilteredTaskList(predicate);
+
+ assertCommandSuccess(command, model, expectedMessage, expectedModel);
+ assertEquals(Collections.emptyList(), model.getFilteredTaskList());
+ }
+
+ @Test
+ public void execute_singleKeywords_taskFound() {
+ String expectedMessage = MESSAGE_EMPTY_TASK_LIST;
+
+ PriorityContainsKeywordPredicate highPredicate = preparePredicate("high");
+ FindByPriorityCommand highCommand = new FindByPriorityCommand(highPredicate);
+ expectedModel.updateFilteredTaskList(highPredicate);
+
+ assertCommandSuccess(highCommand, model, expectedMessage, expectedModel);
+ assertEquals(Collections.emptyList(), model.getFilteredTaskList());
+
+
+ PriorityContainsKeywordPredicate mediumPredicate = preparePredicate("medium");
+ FindByPriorityCommand medCommand = new FindByPriorityCommand(mediumPredicate);
+
+ expectedModel.updateFilteredTaskList(mediumPredicate);
+ assertCommandSuccess(medCommand, model, expectedMessage, expectedModel);
+ assertEquals(Collections.emptyList(), model.getFilteredTaskList());
+
+
+ PriorityContainsKeywordPredicate lowPredicate = preparePredicate("low");
+ FindByPriorityCommand command = new FindByPriorityCommand(lowPredicate);
+ expectedModel.updateFilteredTaskList(lowPredicate);
+
+ assertCommandSuccess(command, model, expectedMessage, expectedModel);
+ assertEquals(Collections.emptyList(), model.getFilteredTaskList());
+
+ PriorityContainsKeywordPredicate unassignedPredicate = preparePredicate("unassigned");
+ FindByPriorityCommand unassCommand = new FindByPriorityCommand(unassignedPredicate);
+
+ expectedModel.updateFilteredTaskList(unassignedPredicate);
+ assertCommandSuccess(unassCommand, model, expectedMessage, expectedModel);
+ assertEquals(Collections.emptyList(), model.getFilteredTaskList());
+ }
+
+ /**
+ * Parses {@code userInput} into a {@code DetailsContainsKeywordsPredicate}.
+ */
+ private PriorityContainsKeywordPredicate preparePredicate(String userInput) {
+ return new PriorityContainsKeywordPredicate(Arrays.asList(userInput.split("\\s+")));
+ }
+}
diff --git a/src/test/java/seedu/heymatez/logic/commands/FindMemberTasksCommandTest.java b/src/test/java/seedu/heymatez/logic/commands/FindMemberTasksCommandTest.java
new file mode 100644
index 00000000000..1f70cef510e
--- /dev/null
+++ b/src/test/java/seedu/heymatez/logic/commands/FindMemberTasksCommandTest.java
@@ -0,0 +1,107 @@
+package seedu.heymatez.logic.commands;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.heymatez.logic.commands.CommandTestUtil.VALID_ASSIGNEE_MARATHON;
+import static seedu.heymatez.logic.commands.CommandTestUtil.VALID_ASSIGNEE_MEETING;
+import static seedu.heymatez.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.heymatez.testutil.TypicalTasks.getTypicalHeyMatez;
+
+import java.util.Collections;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.heymatez.commons.core.Messages;
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.ModelManager;
+import seedu.heymatez.model.UserPrefs;
+import seedu.heymatez.model.task.TaskContainsAssigneePredicate;
+
+/**
+ * Contains integration tests (interaction with the Model) for {@code FindMemberTasksCommand}.
+ */
+public class FindMemberTasksCommandTest {
+ private Model model = new ModelManager(getTypicalHeyMatez(), new UserPrefs());
+ private Model expectedModel = new ModelManager(getTypicalHeyMatez(), new UserPrefs());
+
+ @Test
+ public void equals() {
+ TaskContainsAssigneePredicate firstPredicate =
+ new TaskContainsAssigneePredicate("first");
+ TaskContainsAssigneePredicate secondPredicate =
+ new TaskContainsAssigneePredicate("second");
+
+ FindMemberTasksCommand findFirstCommand = new FindMemberTasksCommand(firstPredicate);
+ FindMemberTasksCommand findSecondCommand = new FindMemberTasksCommand(secondPredicate);
+
+ // same object -> returns true
+ assertTrue(findFirstCommand.equals(findFirstCommand));
+
+ // same values -> returns true
+ FindMemberTasksCommand findFirstCommandCopy = new FindMemberTasksCommand(firstPredicate);
+ assertTrue(findFirstCommand.equals(findFirstCommandCopy));
+
+ // different types -> returns false
+ assertFalse(findFirstCommand.equals(1));
+
+ // null -> returns false
+ assertFalse(findFirstCommand.equals(null));
+
+ // different person -> returns false
+ assertFalse(findFirstCommand.equals(findSecondCommand));
+ }
+
+ @Test
+ public void execute_zeroKeywords_illegalArgumentException() {
+ TaskContainsAssigneePredicate predicate = preparePredicate(" ");
+ assertThrows(IllegalArgumentException.class, () -> expectedModel.updateFilteredTaskList(predicate));
+ }
+
+ @Test
+ public void execute_singleKeyword_nonExistentMemberSuccess() {
+ String expectedMessage = Messages.MESSAGE_EMPTY_TASK_LIST;
+
+ // Does not exist in list
+ TaskContainsAssigneePredicate predicate = preparePredicate("Alex Yeoh");
+ FindMemberTasksCommand command = new FindMemberTasksCommand(predicate);
+ expectedModel.updateFilteredTaskList(predicate);
+
+ assertCommandSuccess(command, model, expectedMessage, expectedModel);
+ assertEquals(Collections.emptyList(), model.getFilteredTaskList());
+ }
+
+ @Test
+ public void execute_singleKeywordExistingMember_tasksFound() {
+ String expectedMessage = FindMemberTasksCommand.MESSAGE_SUCCESS;
+
+ //Exists in list
+ TaskContainsAssigneePredicate predicate = preparePredicate(VALID_ASSIGNEE_MARATHON);
+ FindMemberTasksCommand command = new FindMemberTasksCommand(predicate);
+ expectedModel.updateFilteredTaskList(predicate);
+
+ assertCommandSuccess(command, model, expectedMessage, expectedModel);
+ }
+
+ @Test
+ public void execute_multipleKeywordsExistingMember_noTasksFound() {
+ String expectedMessage = Messages.MESSAGE_EMPTY_TASK_LIST;
+
+ // Does not exist in list
+ TaskContainsAssigneePredicate predicate = preparePredicate(VALID_ASSIGNEE_MARATHON + " "
+ + VALID_ASSIGNEE_MEETING);
+ FindMemberTasksCommand command = new FindMemberTasksCommand(predicate);
+ expectedModel.updateFilteredTaskList(predicate);
+
+ assertCommandSuccess(command, model, expectedMessage, expectedModel);
+ assertEquals(Collections.emptyList(), model.getFilteredTaskList());
+ }
+
+ /**
+ * Parses {@code userInput} into a {@code DetailsContainsKeywordsPredicate}.
+ */
+ private TaskContainsAssigneePredicate preparePredicate(String userInput) {
+ return new TaskContainsAssigneePredicate(userInput);
+ }
+}
diff --git a/src/test/java/seedu/heymatez/logic/commands/FindMembersCommandTest.java b/src/test/java/seedu/heymatez/logic/commands/FindMembersCommandTest.java
new file mode 100644
index 00000000000..5295dd587fc
--- /dev/null
+++ b/src/test/java/seedu/heymatez/logic/commands/FindMembersCommandTest.java
@@ -0,0 +1,99 @@
+package seedu.heymatez.logic.commands;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_EMPTY_PERSON_LIST;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_PERSONS_LISTED_OVERVIEW;
+import static seedu.heymatez.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.heymatez.testutil.TypicalPersons.BENSON;
+import static seedu.heymatez.testutil.TypicalPersons.CARL;
+import static seedu.heymatez.testutil.TypicalPersons.DANIEL;
+import static seedu.heymatez.testutil.TypicalPersons.ELLE;
+import static seedu.heymatez.testutil.TypicalPersons.FIONA;
+import static seedu.heymatez.testutil.TypicalPersons.GEORGE;
+import static seedu.heymatez.testutil.TypicalPersons.getTypicalHeyMatez;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.ModelManager;
+import seedu.heymatez.model.UserPrefs;
+import seedu.heymatez.model.person.DetailsContainsKeywordsPredicate;
+
+/**
+ * Contains integration tests (interaction with the Model) for {@code FindMembersCommand}.
+ */
+public class FindMembersCommandTest {
+ private Model model = new ModelManager(getTypicalHeyMatez(), new UserPrefs());
+ private Model expectedModel = new ModelManager(getTypicalHeyMatez(), new UserPrefs());
+
+ @Test
+ public void equals() {
+ DetailsContainsKeywordsPredicate firstPredicate =
+ new DetailsContainsKeywordsPredicate(Collections.singletonList("first"));
+ DetailsContainsKeywordsPredicate secondPredicate =
+ new DetailsContainsKeywordsPredicate(Collections.singletonList("second"));
+
+ FindMembersCommand findFirstCommand = new FindMembersCommand(firstPredicate);
+ FindMembersCommand findSecondCommand = new FindMembersCommand(secondPredicate);
+
+ // same object -> returns true
+ assertTrue(findFirstCommand.equals(findFirstCommand));
+
+ // same values -> returns true
+ FindMembersCommand findFirstCommandCopy = new FindMembersCommand(firstPredicate);
+ assertTrue(findFirstCommand.equals(findFirstCommandCopy));
+
+ // different types -> returns false
+ assertFalse(findFirstCommand.equals(1));
+
+ // null -> returns false
+ assertFalse(findFirstCommand.equals(null));
+
+ // different person -> returns false
+ assertFalse(findFirstCommand.equals(findSecondCommand));
+ }
+
+ @Test
+ public void execute_zeroKeywords_noPersonFound() {
+ String expectedMessage = MESSAGE_EMPTY_PERSON_LIST;
+ DetailsContainsKeywordsPredicate predicate = preparePredicate(" ");
+ FindMembersCommand command = new FindMembersCommand(predicate);
+ expectedModel.updateFilteredPersonList(predicate);
+ assertCommandSuccess(command, model, expectedMessage, expectedModel);
+ assertEquals(Collections.emptyList(), model.getFilteredPersonList());
+ }
+
+ @Test
+ public void execute_multipleKeywords_multiplePersonsFound() {
+ String expectedMessage = String.format(MESSAGE_PERSONS_LISTED_OVERVIEW, 6);
+ DetailsContainsKeywordsPredicate predicate =
+ preparePredicate("Kurz Elle Kunz 98765432 secretary anna@example.com");
+ FindMembersCommand command = new FindMembersCommand(predicate);
+ expectedModel.updateFilteredPersonList(predicate);
+ assertCommandSuccess(command, model, expectedMessage, expectedModel);
+ assertEquals(Arrays.asList(BENSON, CARL, DANIEL, ELLE, FIONA, GEORGE), model.getFilteredPersonList());
+ }
+
+ @Test
+ public void execute_multipleKeywords_noPersonsFound() {
+ String expectedMessage = MESSAGE_EMPTY_PERSON_LIST;
+ DetailsContainsKeywordsPredicate predicate =
+ preparePredicate("Michelle Joelle Tim 98755432 vicePresident tim@example.com");
+ FindMembersCommand command = new FindMembersCommand(predicate);
+ expectedModel.updateFilteredPersonList(predicate);
+ assertCommandSuccess(command, model, expectedMessage, expectedModel);
+ assertEquals(Collections.emptyList(), model.getFilteredPersonList());
+ }
+
+ /**
+ * Parses {@code userInput} into a {@code DetailsContainsKeywordsPredicate}.
+ */
+ private DetailsContainsKeywordsPredicate preparePredicate(String userInput) {
+ return new DetailsContainsKeywordsPredicate(Arrays.asList(userInput.split("\\s+")));
+ }
+}
diff --git a/src/test/java/seedu/heymatez/logic/commands/FindTasksBeforeCommandTest.java b/src/test/java/seedu/heymatez/logic/commands/FindTasksBeforeCommandTest.java
new file mode 100644
index 00000000000..b31172d7e6c
--- /dev/null
+++ b/src/test/java/seedu/heymatez/logic/commands/FindTasksBeforeCommandTest.java
@@ -0,0 +1,100 @@
+package seedu.heymatez.logic.commands;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_EMPTY_TASK_LIST;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_TASKS_LISTED_OVERVIEW;
+import static seedu.heymatez.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.heymatez.testutil.TypicalTasks.HOMEWORK;
+import static seedu.heymatez.testutil.TypicalTasks.MARATHON;
+import static seedu.heymatez.testutil.TypicalTasks.RETURNBOOK;
+import static seedu.heymatez.testutil.TypicalTasks.getTypicalHeyMatez;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.heymatez.model.HeyMatez;
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.ModelManager;
+import seedu.heymatez.model.UserPrefs;
+import seedu.heymatez.model.task.DeadlineBeforeDatePredicate;
+
+/**
+ * Contains integration tests (interaction with the Model) for {@code FindTasksBeforeCommand}.
+ */
+public class FindTasksBeforeCommandTest {
+ private Model model = new ModelManager(getTypicalHeyMatez(), new UserPrefs());
+ private Model expectedModel = new ModelManager(getTypicalHeyMatez(), new UserPrefs());
+
+ @Test
+ public void equals() {
+ DeadlineBeforeDatePredicate firstPredicate =
+ new DeadlineBeforeDatePredicate("2021-04-13");
+ DeadlineBeforeDatePredicate secondPredicate =
+ new DeadlineBeforeDatePredicate("2021-05-06");
+
+ FindTasksBeforeCommand findFirstCommand = new FindTasksBeforeCommand(firstPredicate);
+ FindTasksBeforeCommand findSecondCommand = new FindTasksBeforeCommand(secondPredicate);
+
+ // same object -> returns true
+ assertTrue(findFirstCommand.equals(findFirstCommand));
+
+ // same values -> returns true
+ FindTasksBeforeCommand findFirstCommandCopy = new FindTasksBeforeCommand(firstPredicate);
+ assertTrue(findFirstCommand.equals(findFirstCommandCopy));
+
+ // different types -> returns false
+ assertFalse(findFirstCommand.equals(1));
+
+ // null -> returns false
+ assertFalse(findFirstCommand.equals(null));
+
+ // different deadline -> returns false
+ assertFalse(findFirstCommand.equals(findSecondCommand));
+ }
+
+ @Test
+ public void execute_deadline_noTaskFound() {
+ String expectedMessage = MESSAGE_EMPTY_TASK_LIST;
+ DeadlineBeforeDatePredicate predicate = new DeadlineBeforeDatePredicate("2021-02-03");
+ FindTasksBeforeCommand command = new FindTasksBeforeCommand(predicate);
+ expectedModel.updateFilteredTaskList(predicate);
+ assertCommandSuccess(command, model, expectedMessage, expectedModel);
+ assertEquals(Collections.emptyList(), model.getFilteredTaskList());
+ }
+
+ @Test
+ public void execute_deadline_multipleTasksFound() {
+ String expectedMessage = String.format(MESSAGE_TASKS_LISTED_OVERVIEW, 3);
+ DeadlineBeforeDatePredicate predicate = new DeadlineBeforeDatePredicate("2021-06-05");
+ FindTasksBeforeCommand command = new FindTasksBeforeCommand(predicate);
+ expectedModel.updateFilteredTaskList(predicate);
+ assertCommandSuccess(command, model, expectedMessage, expectedModel);
+ assertEquals(Arrays.asList(HOMEWORK, RETURNBOOK, MARATHON), model.getFilteredTaskList());
+ }
+
+ @Test
+ public void execute_deadline_taskFound() {
+ String expectedMessage = String.format(MESSAGE_TASKS_LISTED_OVERVIEW, 1);
+ DeadlineBeforeDatePredicate predicate = new DeadlineBeforeDatePredicate("2021-02-05");
+ FindTasksBeforeCommand command = new FindTasksBeforeCommand(predicate);
+ expectedModel.updateFilteredTaskList(predicate);
+ assertCommandSuccess(command, model, expectedMessage, expectedModel);
+ assertEquals(Arrays.asList(HOMEWORK), model.getFilteredTaskList());
+ }
+
+ @Test
+ public void execute_emptyFilteredList_success() {
+ HeyMatez heyMatez = new HeyMatez();
+ model = new ModelManager(heyMatez, new UserPrefs());
+ Model expectedModel = new ModelManager(model.getHeyMatez(), new UserPrefs());
+ DeadlineBeforeDatePredicate predicate = new DeadlineBeforeDatePredicate("2021-02-05");
+ FindTasksBeforeCommand findTasksCommand = new FindTasksBeforeCommand(predicate);
+ expectedModel.updateFilteredTaskList(predicate);
+ assertCommandSuccess(findTasksCommand, model, MESSAGE_EMPTY_TASK_LIST, expectedModel);
+ }
+
+}
diff --git a/src/test/java/seedu/heymatez/logic/commands/FindTasksCommandTest.java b/src/test/java/seedu/heymatez/logic/commands/FindTasksCommandTest.java
new file mode 100644
index 00000000000..0e277d1fce7
--- /dev/null
+++ b/src/test/java/seedu/heymatez/logic/commands/FindTasksCommandTest.java
@@ -0,0 +1,95 @@
+package seedu.heymatez.logic.commands;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_EMPTY_TASK_LIST;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_TASKS_LISTED_OVERVIEW;
+import static seedu.heymatez.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.heymatez.testutil.TypicalTasks.HOMEWORK;
+import static seedu.heymatez.testutil.TypicalTasks.RETURNBOOK;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.heymatez.model.HeyMatez;
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.ModelManager;
+import seedu.heymatez.model.UserPrefs;
+import seedu.heymatez.model.task.TaskContainsKeywordPredicate;
+import seedu.heymatez.testutil.TypicalTasks;
+
+/**
+ * Contains integration tests (interaction with the Model) for {@code FindTasksCommand}.
+ */
+public class FindTasksCommandTest {
+ private Model model = new ModelManager(TypicalTasks.getTypicalHeyMatez(), new UserPrefs());
+ private Model expectedModel = new ModelManager(model.getHeyMatez(), new UserPrefs());
+
+ @Test
+ public void equals() {
+ TaskContainsKeywordPredicate firstPredicate =
+ new TaskContainsKeywordPredicate(Collections.singletonList("first"));
+ TaskContainsKeywordPredicate secondPredicate =
+ new TaskContainsKeywordPredicate(Collections.singletonList("second"));
+
+ FindTasksCommand findFirstCommand = new FindTasksCommand(firstPredicate);
+ FindTasksCommand findSecondCommand = new FindTasksCommand(secondPredicate);
+
+ // same object -> returns true
+ assertTrue(findFirstCommand.equals(findFirstCommand));
+
+ // same values -> returns true
+ FindTasksCommand findFirstCommandCopy = new FindTasksCommand(firstPredicate);
+ assertTrue(findFirstCommand.equals(findFirstCommandCopy));
+
+ // different types -> returns false
+ assertFalse(findFirstCommand.equals(1));
+
+ // null -> returns false
+ assertFalse(findFirstCommand.equals(null));
+
+ // different person -> returns false
+ assertFalse(findFirstCommand.equals(findSecondCommand));
+ }
+
+ @Test
+ public void execute_zeroKeywords_noTaskFound() {
+ String expectedMessage = MESSAGE_EMPTY_TASK_LIST;
+ TaskContainsKeywordPredicate predicate = preparePredicate(" ");
+ FindTasksCommand command = new FindTasksCommand(predicate);
+ expectedModel.updateFilteredTaskList(predicate);
+ assertCommandSuccess(command, model, expectedMessage, expectedModel);
+ assertEquals(Collections.emptyList(), model.getFilteredTaskList());
+ }
+
+ @Test
+ public void execute_multipleKeywords_multipleTasksFound() {
+ String expectedMessage = String.format(MESSAGE_TASKS_LISTED_OVERVIEW, 2);
+ TaskContainsKeywordPredicate predicate = preparePredicate("Homework national Library");
+ FindTasksCommand command = new FindTasksCommand(predicate);
+ expectedModel.updateFilteredTaskList(predicate);
+ assertCommandSuccess(command, model, expectedMessage, expectedModel);
+ assertEquals(Arrays.asList(HOMEWORK, RETURNBOOK), model.getFilteredTaskList());
+ }
+
+ @Test
+ public void execute_emptyFilteredList_success() {
+ HeyMatez heyMatez = new HeyMatez();
+ model = new ModelManager(heyMatez, new UserPrefs());
+ Model expectedModel = new ModelManager(model.getHeyMatez(), new UserPrefs());
+ TaskContainsKeywordPredicate predicate = preparePredicate("Homework national Library");
+ FindTasksCommand findTasksCommand = new FindTasksCommand(predicate);
+ expectedModel.updateFilteredTaskList(predicate);
+ assertCommandSuccess(findTasksCommand, model, MESSAGE_EMPTY_TASK_LIST, expectedModel);
+ }
+
+ /**
+ * Parses {@code userInput} into a {@code TaskContainsKeywordPredicate}.
+ */
+ private TaskContainsKeywordPredicate preparePredicate(String userInput) {
+ return new TaskContainsKeywordPredicate(Arrays.asList(userInput.split("\\s+")));
+ }
+}
diff --git a/src/test/java/seedu/address/logic/commands/HelpCommandTest.java b/src/test/java/seedu/heymatez/logic/commands/HelpCommandTest.java
similarity index 53%
rename from src/test/java/seedu/address/logic/commands/HelpCommandTest.java
rename to src/test/java/seedu/heymatez/logic/commands/HelpCommandTest.java
index 4904fc4352e..5f3c637a442 100644
--- a/src/test/java/seedu/address/logic/commands/HelpCommandTest.java
+++ b/src/test/java/seedu/heymatez/logic/commands/HelpCommandTest.java
@@ -1,13 +1,16 @@
-package seedu.address.logic.commands;
+package seedu.heymatez.logic.commands;
-import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
-import static seedu.address.logic.commands.HelpCommand.SHOWING_HELP_MESSAGE;
+import static seedu.heymatez.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.heymatez.logic.commands.HelpCommand.SHOWING_HELP_MESSAGE;
import org.junit.jupiter.api.Test;
-import seedu.address.model.Model;
-import seedu.address.model.ModelManager;
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.ModelManager;
+/**
+ * Contains integration tests (interaction with the Model) for {@code HelpCommand}.
+ */
public class HelpCommandTest {
private Model model = new ModelManager();
private Model expectedModel = new ModelManager();
diff --git a/src/test/java/seedu/heymatez/logic/commands/UndoTaskCommandIntegrationTest.java b/src/test/java/seedu/heymatez/logic/commands/UndoTaskCommandIntegrationTest.java
new file mode 100644
index 00000000000..d202ac599be
--- /dev/null
+++ b/src/test/java/seedu/heymatez/logic/commands/UndoTaskCommandIntegrationTest.java
@@ -0,0 +1,55 @@
+package seedu.heymatez.logic.commands;
+
+import static seedu.heymatez.logic.commands.CommandTestUtil.assertCommandFailure;
+import static seedu.heymatez.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.heymatez.testutil.TypicalIndexes.INDEX_THIRD_TASK;
+import static seedu.heymatez.testutil.TypicalTasks.getTypicalHeyMatez;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import seedu.heymatez.commons.core.Messages;
+import seedu.heymatez.commons.core.index.Index;
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.ModelManager;
+import seedu.heymatez.model.UserPrefs;
+import seedu.heymatez.model.task.Task;
+import seedu.heymatez.testutil.TaskBuilder;
+
+/**
+ * Contains integration tests (interaction with the Model) for {@code UndoTaskCommand}.
+ */
+public class UndoTaskCommandIntegrationTest {
+
+ private Model model;
+
+ @BeforeEach
+ public void setUp() {
+ model = new ModelManager(getTypicalHeyMatez(), new UserPrefs());
+ }
+
+ @Test
+ public void execute_undoTask_success() {
+ Task validTask = model.getHeyMatez().getTaskList().get(0);
+ Task undoTask = new TaskBuilder(validTask).withTaskStatus(TaskBuilder.COMPLETED_STATUS).build();
+
+ Model expectedModel = new ModelManager(model.getHeyMatez(), new UserPrefs());
+ model.setTask(validTask, undoTask);
+
+ assertCommandSuccess(new UndoTaskCommand(INDEX_THIRD_TASK), model,
+ UndoTaskCommand.MESSAGE_UNDO_TASK_SUCCESS, expectedModel);
+ }
+
+ @Test
+ public void execute_undo_throwsIndexNotValid() {
+ Index index = Index.fromOneBased(model.getHeyMatez().getTaskList().size() + 1);
+ assertCommandFailure(new UndoTaskCommand(index), model, Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+
+ @Test
+ public void execute_undo_throwsTaskIsAlreadyCompleted() {
+ Index index = Index.fromOneBased(1);
+ assertCommandFailure(new UndoTaskCommand(index), model,
+ UndoTaskCommand.MESSAGE_TASK_ALREADY_MARKED_UNCOMPLETED);
+ }
+}
diff --git a/src/test/java/seedu/heymatez/logic/commands/UndoTaskCommandTest.java b/src/test/java/seedu/heymatez/logic/commands/UndoTaskCommandTest.java
new file mode 100644
index 00000000000..59fe4a72df0
--- /dev/null
+++ b/src/test/java/seedu/heymatez/logic/commands/UndoTaskCommandTest.java
@@ -0,0 +1,124 @@
+package seedu.heymatez.logic.commands;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.heymatez.logic.commands.CommandTestUtil.assertCommandFailure;
+import static seedu.heymatez.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.heymatez.logic.commands.CommandTestUtil.showTaskAtIndex;
+import static seedu.heymatez.testutil.TypicalIndexes.INDEX_FIRST_TASK;
+import static seedu.heymatez.testutil.TypicalIndexes.INDEX_SECOND_TASK;
+import static seedu.heymatez.testutil.TypicalIndexes.INDEX_THIRD_TASK;
+import static seedu.heymatez.testutil.TypicalTasks.getTypicalHeyMatez;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.heymatez.commons.core.Messages;
+import seedu.heymatez.commons.core.index.Index;
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.ModelManager;
+import seedu.heymatez.model.UserPrefs;
+import seedu.heymatez.model.task.Task;
+import seedu.heymatez.testutil.TaskBuilder;
+
+
+/**
+ * Contains integration tests (interaction with the Model) and unit tests for
+ * {@code UndoTaskCommand}.
+ */
+public class UndoTaskCommandTest {
+ private Model model = new ModelManager(getTypicalHeyMatez(), new UserPrefs());
+
+ @Test
+ public void execute_validIndexUnfilteredList_success() {
+ Task taskToMarkUncompleted = model.getFilteredTaskList().get(INDEX_THIRD_TASK.getZeroBased());
+
+ Task undoTask = new TaskBuilder(taskToMarkUncompleted).withTaskStatus(TaskBuilder.DEFAULT_STATUS).build();
+
+ UndoTaskCommand undoTaskCommand = new UndoTaskCommand(INDEX_THIRD_TASK);
+
+ String expectedMessage = UndoTaskCommand.MESSAGE_UNDO_TASK_SUCCESS;
+
+ ModelManager expectedModel = new ModelManager(model.getHeyMatez(), new UserPrefs());
+ expectedModel.setTask(taskToMarkUncompleted, undoTask);
+
+ assertCommandSuccess(undoTaskCommand, model, expectedMessage, expectedModel);
+ }
+
+ @Test
+ public void execute_invalidIndexUnfilteredList_throwsCommandException() {
+ Index outOfBoundIndex = Index.fromOneBased(model.getFilteredTaskList().size() + 1);
+ UndoTaskCommand undoTaskCommand = new UndoTaskCommand(outOfBoundIndex);
+
+ assertCommandFailure(undoTaskCommand, model, Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+
+ @Test
+ public void execute_validIndexFilteredList_success() {
+ showTaskAtIndex(model, INDEX_THIRD_TASK);
+
+ Task taskToMarkUncompleted = model.getFilteredTaskList().get(INDEX_FIRST_TASK.getZeroBased());
+ Task doneTask = new TaskBuilder(taskToMarkUncompleted).withTaskStatus(TaskBuilder.COMPLETED_STATUS).build();
+
+ UndoTaskCommand undoCommand = new UndoTaskCommand(INDEX_FIRST_TASK);
+
+ String expectedMessage = UndoTaskCommand.MESSAGE_UNDO_TASK_SUCCESS;
+
+ Model expectedModel = new ModelManager(model.getHeyMatez(), new UserPrefs());
+
+ expectedModel.setTask(taskToMarkUncompleted, doneTask);
+ showNoTask(expectedModel);
+
+ assertCommandSuccess(undoCommand, model, expectedMessage, expectedModel);
+ }
+
+ @Test
+ public void task_already_markedUncompleted() {
+ UndoTaskCommand undoTaskCommand = new UndoTaskCommand(INDEX_FIRST_TASK);
+
+ assertCommandFailure(undoTaskCommand, model, UndoTaskCommand.MESSAGE_TASK_ALREADY_MARKED_UNCOMPLETED);
+ }
+
+ @Test
+ public void execute_invalidIndexFilteredList_throwsCommandException() {
+ showTaskAtIndex(model, INDEX_FIRST_TASK);
+
+ Index outOfBoundIndex = INDEX_SECOND_TASK;
+ // ensures that outOfBoundIndex is still in bounds of task list
+ assertTrue(outOfBoundIndex.getZeroBased() < model.getHeyMatez().getTaskList().size());
+
+ UndoTaskCommand undoTaskCommand = new UndoTaskCommand(outOfBoundIndex);
+
+ assertCommandFailure(undoTaskCommand, model, Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+
+ @Test
+ public void equals() {
+ UndoTaskCommand undoFirstCommand = new UndoTaskCommand(INDEX_FIRST_TASK);
+ UndoTaskCommand undoSecondCommand = new UndoTaskCommand(INDEX_SECOND_TASK);
+
+ // same object -> returns true
+ assertTrue(undoFirstCommand.equals(undoFirstCommand));
+
+ // same values -> returns true
+ UndoTaskCommand undoFirstCommandCopy = new UndoTaskCommand(INDEX_FIRST_TASK);
+ assertTrue(undoFirstCommand.equals(undoFirstCommandCopy));
+
+ // different types -> returns false
+ assertFalse(undoFirstCommand.equals(1));
+
+ // null -> returns false
+ assertFalse(undoFirstCommand.equals(null));
+
+ // different person -> returns false
+ assertFalse(undoFirstCommand.equals(undoSecondCommand));
+ }
+
+ /**
+ * Updates {@code model}'s filtered list to show no one.
+ */
+ private void showNoTask(Model model) {
+ model.updateFilteredTaskList(p -> false);
+
+ assertTrue(model.getFilteredTaskList().isEmpty());
+ }
+}
diff --git a/src/test/java/seedu/heymatez/logic/commands/ViewMembersCommandTest.java b/src/test/java/seedu/heymatez/logic/commands/ViewMembersCommandTest.java
new file mode 100644
index 00000000000..604f31bd4e6
--- /dev/null
+++ b/src/test/java/seedu/heymatez/logic/commands/ViewMembersCommandTest.java
@@ -0,0 +1,49 @@
+package seedu.heymatez.logic.commands;
+
+import static seedu.heymatez.commons.core.Messages.MESSAGE_EMPTY_PERSON_LIST;
+import static seedu.heymatez.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.heymatez.logic.commands.CommandTestUtil.showPersonAtIndex;
+import static seedu.heymatez.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
+import static seedu.heymatez.testutil.TypicalPersons.getTypicalHeyMatez;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import seedu.heymatez.model.HeyMatez;
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.ModelManager;
+import seedu.heymatez.model.UserPrefs;
+
+/**
+ * Contains integration tests (interaction with the Model) and unit tests for {@code ViewMembersCommand}.
+ */
+public class ViewMembersCommandTest {
+
+ private Model model;
+ private Model expectedModel;
+
+ @BeforeEach
+ public void setUp() {
+ model = new ModelManager(getTypicalHeyMatez(), new UserPrefs());
+ expectedModel = new ModelManager(model.getHeyMatez(), new UserPrefs());
+ }
+
+ @Test
+ public void execute_listIsNotFiltered_showsSameList() {
+ assertCommandSuccess(new ViewMembersCommand(), model, ViewMembersCommand.MESSAGE_SUCCESS, expectedModel);
+ }
+
+ @Test
+ public void execute_listIsFiltered_showsEverything() {
+ showPersonAtIndex(model, INDEX_FIRST_PERSON);
+ assertCommandSuccess(new ViewMembersCommand(), model, ViewMembersCommand.MESSAGE_SUCCESS, expectedModel);
+ }
+
+ @Test
+ public void execute_emptyFilteredList_success() {
+ HeyMatez heyMatez = new HeyMatez();
+ model = new ModelManager(heyMatez, new UserPrefs());
+ expectedModel = new ModelManager(model.getHeyMatez(), new UserPrefs());
+ assertCommandSuccess(new ViewMembersCommand(), model, MESSAGE_EMPTY_PERSON_LIST, expectedModel);
+ }
+}
diff --git a/src/test/java/seedu/heymatez/logic/commands/ViewTasksCommandTest.java b/src/test/java/seedu/heymatez/logic/commands/ViewTasksCommandTest.java
new file mode 100644
index 00000000000..3d99130f58e
--- /dev/null
+++ b/src/test/java/seedu/heymatez/logic/commands/ViewTasksCommandTest.java
@@ -0,0 +1,48 @@
+package seedu.heymatez.logic.commands;
+
+import static seedu.heymatez.commons.core.Messages.MESSAGE_EMPTY_TASK_LIST;
+import static seedu.heymatez.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.heymatez.logic.commands.CommandTestUtil.showTaskAtIndex;
+import static seedu.heymatez.testutil.TypicalIndexes.INDEX_FIRST_TASK;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import seedu.heymatez.model.HeyMatez;
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.ModelManager;
+import seedu.heymatez.model.UserPrefs;
+import seedu.heymatez.testutil.TypicalTasks;
+
+/**
+ * Contains integration tests (interaction with the Model) and unit tests for {@code ViewTasksCommand}.
+ */
+public class ViewTasksCommandTest {
+ private Model model;
+ private Model expectedModel;
+
+ @BeforeEach
+ public void setUp() {
+ model = new ModelManager(TypicalTasks.getTypicalHeyMatez(), new UserPrefs());
+ expectedModel = new ModelManager(model.getHeyMatez(), new UserPrefs());
+ }
+
+ @Test
+ public void execute_listIsNotFiltered_showsSameList() {
+ assertCommandSuccess(new ViewTasksCommand(), model, ViewTasksCommand.MESSAGE_SUCCESS, expectedModel);
+ }
+
+ @Test
+ public void execute_listIsFiltered_showsEverything() {
+ showTaskAtIndex(model, INDEX_FIRST_TASK);
+ assertCommandSuccess(new ViewTasksCommand(), model, ViewTasksCommand.MESSAGE_SUCCESS, expectedModel);
+ }
+
+ @Test
+ public void execute_emptyFilteredList_success() {
+ HeyMatez heyMatez = new HeyMatez();
+ model = new ModelManager(heyMatez, new UserPrefs());
+ expectedModel = new ModelManager(model.getHeyMatez(), new UserPrefs());
+ assertCommandSuccess(new ViewTasksCommand(), model, MESSAGE_EMPTY_TASK_LIST, expectedModel);
+ }
+}
diff --git a/src/test/java/seedu/heymatez/logic/commands/ViewUnassignedTasksCommandTest.java b/src/test/java/seedu/heymatez/logic/commands/ViewUnassignedTasksCommandTest.java
new file mode 100644
index 00000000000..3c807b152ae
--- /dev/null
+++ b/src/test/java/seedu/heymatez/logic/commands/ViewUnassignedTasksCommandTest.java
@@ -0,0 +1,66 @@
+package seedu.heymatez.logic.commands;
+
+import static seedu.heymatez.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.heymatez.logic.commands.CommandTestUtil.showTaskAtIndex;
+import static seedu.heymatez.testutil.TypicalIndexes.INDEX_FIRST_TASK;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import seedu.heymatez.model.HeyMatez;
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.ModelManager;
+import seedu.heymatez.model.UserPrefs;
+import seedu.heymatez.model.task.Task;
+import seedu.heymatez.testutil.TaskBuilder;
+import seedu.heymatez.testutil.TypicalTasks;
+
+
+/**
+ * Contains integration tests (interaction with the Model) and unit tests for {@code ViewUnassignedTasksCommand}.
+ */
+public class ViewUnassignedTasksCommandTest {
+ private Model model;
+ private Model expectedModel;
+
+ @BeforeEach
+ public void setUp() {
+ model = new ModelManager(TypicalTasks.getTypicalHeyMatez(), new UserPrefs());
+ expectedModel = new ModelManager(model.getHeyMatez(), new UserPrefs());
+ }
+
+ @Test
+ public void execute_listIsNotFiltered_showsSameList() {
+ assertCommandSuccess(new ViewUnassignedTasksCommand(), model,
+ ViewUnassignedTasksCommand.MESSAGE_SUCCESS, expectedModel);
+ }
+
+ @Test
+ public void execute_listIsFiltered_showsEverything() {
+ showTaskAtIndex(model, INDEX_FIRST_TASK);
+ assertCommandSuccess(new ViewUnassignedTasksCommand(), model,
+ ViewUnassignedTasksCommand.MESSAGE_SUCCESS, expectedModel);
+ }
+
+ @Test
+ public void execute_emptyFilteredList_showsNoTask() {
+ HeyMatez hm = new HeyMatez();
+ assertCommandSuccess(new ViewUnassignedTasksCommand(), new ModelManager(hm, new UserPrefs()),
+ ViewUnassignedTasksCommand.MESSAGE_NO_UNASSIGNED_TASKS,
+ new ModelManager(hm, new UserPrefs()));
+ }
+
+ @Test
+ public void executed_noUnassignedTaskFilteredList_showsNoTask() {
+ Task homework = new TaskBuilder().withTitle("Homework").withDescription("do CS2103tp")
+ .withDeadline("2021-02-04").withTaskStatus("completed").withPriority("unassigned")
+ .withAssignees("Rachel").build();
+ HeyMatez hm = new HeyMatez();
+ hm.addTask(homework);
+ Model newModel = new ModelManager(hm, new UserPrefs());
+ Model myExpectedModel = new ModelManager(hm, new UserPrefs());
+ assertCommandSuccess(new ViewUnassignedTasksCommand(), newModel,
+ ViewUnassignedTasksCommand.MESSAGE_NO_UNASSIGNED_TASKS,
+ myExpectedModel);
+ }
+}
diff --git a/src/test/java/seedu/heymatez/logic/commands/ViewUncompletedTasksCommandTest.java b/src/test/java/seedu/heymatez/logic/commands/ViewUncompletedTasksCommandTest.java
new file mode 100644
index 00000000000..5a03323ab0b
--- /dev/null
+++ b/src/test/java/seedu/heymatez/logic/commands/ViewUncompletedTasksCommandTest.java
@@ -0,0 +1,66 @@
+package seedu.heymatez.logic.commands;
+
+import static seedu.heymatez.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.heymatez.logic.commands.CommandTestUtil.showTaskAtIndex;
+import static seedu.heymatez.testutil.TypicalIndexes.INDEX_FIRST_TASK;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import seedu.heymatez.model.HeyMatez;
+import seedu.heymatez.model.Model;
+import seedu.heymatez.model.ModelManager;
+import seedu.heymatez.model.UserPrefs;
+import seedu.heymatez.model.task.Task;
+import seedu.heymatez.testutil.TaskBuilder;
+import seedu.heymatez.testutil.TypicalTasks;
+
+
+/**
+ * Contains integration tests (interaction with the Model) and unit tests for {@code ViewUncompletedTasksCommand}.
+ */
+public class ViewUncompletedTasksCommandTest {
+ private Model model;
+ private Model expectedModel;
+
+ @BeforeEach
+ public void setUp() {
+ model = new ModelManager(TypicalTasks.getTypicalHeyMatez(), new UserPrefs());
+ expectedModel = new ModelManager(model.getHeyMatez(), new UserPrefs());
+ }
+
+ @Test
+ public void execute_listIsNotFiltered_showsSameList() {
+ assertCommandSuccess(new ViewUncompletedTasksCommand(), model,
+ ViewUncompletedTasksCommand.MESSAGE_SUCCESS, expectedModel);
+ }
+
+ @Test
+ public void execute_listIsFiltered_showsEverything() {
+ showTaskAtIndex(model, INDEX_FIRST_TASK);
+ assertCommandSuccess(new ViewUncompletedTasksCommand(), model,
+ ViewUncompletedTasksCommand.MESSAGE_SUCCESS, expectedModel);
+ }
+
+ @Test
+ public void execute_emptyFilteredList_showsNoTask() {
+ HeyMatez hm = new HeyMatez();
+ assertCommandSuccess(new ViewUncompletedTasksCommand(), new ModelManager(hm, new UserPrefs()),
+ ViewUncompletedTasksCommand.MESSAGE_NO_UNCOMPLETED_TASKS,
+ new ModelManager(hm, new UserPrefs()));
+ }
+
+ @Test
+ public void executed_noUncompletedTaskFilteredList_showsNoTask() {
+ Task homework = new TaskBuilder().withTitle("Homework").withDescription("do CS2103tp")
+ .withDeadline("2021-02-04").withTaskStatus("completed").withPriority("unassigned").build();
+ HeyMatez hm = new HeyMatez();
+ hm.addTask(homework);
+ Model newModel = new ModelManager(hm, new UserPrefs());
+ Model myExpectedModel = new ModelManager(hm, new UserPrefs());
+ assertCommandSuccess(new ViewUncompletedTasksCommand(), newModel,
+ ViewUncompletedTasksCommand.MESSAGE_NO_UNCOMPLETED_TASKS,
+ myExpectedModel);
+ }
+
+}
diff --git a/src/test/java/seedu/heymatez/logic/parser/AddMemberCommandParserTest.java b/src/test/java/seedu/heymatez/logic/parser/AddMemberCommandParserTest.java
new file mode 100644
index 00000000000..2253ab2ee37
--- /dev/null
+++ b/src/test/java/seedu/heymatez/logic/parser/AddMemberCommandParserTest.java
@@ -0,0 +1,90 @@
+package seedu.heymatez.logic.parser;
+
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_PERSON_DISPLAYED_NAME;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_PERSON_EMAIL;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_PERSON_PHONE;
+import static seedu.heymatez.logic.commands.CommandTestUtil.EMAIL_DESC_AMY;
+import static seedu.heymatez.logic.commands.CommandTestUtil.EMAIL_DESC_BOB;
+import static seedu.heymatez.logic.commands.CommandTestUtil.INVALID_EMAIL_DESC;
+import static seedu.heymatez.logic.commands.CommandTestUtil.INVALID_NAME_DESC;
+import static seedu.heymatez.logic.commands.CommandTestUtil.INVALID_PHONE_DESC;
+import static seedu.heymatez.logic.commands.CommandTestUtil.NAME_DESC_BOB;
+import static seedu.heymatez.logic.commands.CommandTestUtil.PHONE_DESC_AMY;
+import static seedu.heymatez.logic.commands.CommandTestUtil.PHONE_DESC_BOB;
+import static seedu.heymatez.logic.commands.CommandTestUtil.PREAMBLE_WHITESPACE;
+import static seedu.heymatez.logic.commands.CommandTestUtil.ROLE_DESC_BOB;
+import static seedu.heymatez.logic.commands.CommandTestUtil.VALID_EMAIL_BOB;
+import static seedu.heymatez.logic.commands.CommandTestUtil.VALID_NAME_BOB;
+import static seedu.heymatez.logic.commands.CommandTestUtil.VALID_PHONE_BOB;
+import static seedu.heymatez.logic.parser.CommandParserTestUtil.assertParseFailure;
+import static seedu.heymatez.logic.parser.CommandParserTestUtil.assertParseSuccess;
+import static seedu.heymatez.testutil.TypicalPersons.BOB;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.heymatez.logic.commands.AddMemberCommand;
+import seedu.heymatez.model.person.Email;
+import seedu.heymatez.model.person.Name;
+import seedu.heymatez.model.person.Person;
+import seedu.heymatez.model.person.Phone;
+import seedu.heymatez.testutil.PersonBuilder;
+
+/**
+ * Contains unit tests for {@code AddMemberCommandParser}.
+ */
+public class AddMemberCommandParserTest {
+ private AddMemberCommandParser parser = new AddMemberCommandParser();
+
+ @Test
+ public void parse_allFieldsPresent_success() {
+ Person expectedPerson = new PersonBuilder(BOB).build();
+
+ // whitespace only preamble
+ assertParseSuccess(parser, PREAMBLE_WHITESPACE + VALID_NAME_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB
+ + ROLE_DESC_BOB, new AddMemberCommand(expectedPerson));
+
+ // multiple phones - last phone accepted
+ assertParseSuccess(parser, NAME_DESC_BOB + PHONE_DESC_AMY + PHONE_DESC_BOB + EMAIL_DESC_BOB
+ + ROLE_DESC_BOB, new AddMemberCommand(expectedPerson));
+
+ // multiple emails - last email accepted
+ assertParseSuccess(parser, NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_AMY + EMAIL_DESC_BOB
+ + ROLE_DESC_BOB, new AddMemberCommand(expectedPerson));
+
+ }
+
+ @Test
+ public void parse_compulsoryFieldMissing_failure() {
+ String expectedMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddMemberCommand.MESSAGE_USAGE);
+
+ // missing phone prefix
+ assertParseFailure(parser, NAME_DESC_BOB + VALID_PHONE_BOB + EMAIL_DESC_BOB, expectedMessage);
+
+ // missing email prefix
+ assertParseFailure(parser, NAME_DESC_BOB + PHONE_DESC_BOB + VALID_EMAIL_BOB, expectedMessage);
+
+ // all prefixes missing
+ assertParseFailure(parser, VALID_NAME_BOB + VALID_PHONE_BOB + VALID_EMAIL_BOB, expectedMessage);
+ }
+
+ @Test
+ public void parse_invalidValue_failure() {
+ // invalid name
+ assertParseFailure(parser, INVALID_NAME_DESC + PHONE_DESC_BOB + EMAIL_DESC_BOB,
+ MESSAGE_INVALID_PERSON_DISPLAYED_NAME + Name.MESSAGE_CONSTRAINTS);
+
+ // invalid phone
+ assertParseFailure(parser, NAME_DESC_BOB + INVALID_PHONE_DESC + EMAIL_DESC_BOB ,
+ MESSAGE_INVALID_PERSON_PHONE + Phone.MESSAGE_CONSTRAINTS);
+
+ // invalid email
+ assertParseFailure(parser, NAME_DESC_BOB + PHONE_DESC_BOB + INVALID_EMAIL_DESC ,
+ MESSAGE_INVALID_PERSON_EMAIL + Email.MESSAGE_CONSTRAINTS);
+
+ // two invalid values, only first invalid value reported
+ assertParseFailure(parser, INVALID_NAME_DESC + PHONE_DESC_BOB + EMAIL_DESC_BOB,
+ MESSAGE_INVALID_PERSON_DISPLAYED_NAME + Name.MESSAGE_CONSTRAINTS);
+
+ }
+}
diff --git a/src/test/java/seedu/heymatez/logic/parser/AddTaskCommandParserTest.java b/src/test/java/seedu/heymatez/logic/parser/AddTaskCommandParserTest.java
new file mode 100644
index 00000000000..c75aa3be137
--- /dev/null
+++ b/src/test/java/seedu/heymatez/logic/parser/AddTaskCommandParserTest.java
@@ -0,0 +1,60 @@
+package seedu.heymatez.logic.parser;
+
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.heymatez.logic.commands.CommandTestUtil.DEADLINE_TASK1;
+import static seedu.heymatez.logic.commands.CommandTestUtil.DESCRIPTION_TASK1;
+import static seedu.heymatez.logic.commands.CommandTestUtil.INVALID_DEADLINE_DESC;
+import static seedu.heymatez.logic.commands.CommandTestUtil.PREAMBLE_WHITESPACE;
+import static seedu.heymatez.logic.commands.CommandTestUtil.TITLE_DESC_TASK1;
+import static seedu.heymatez.logic.commands.CommandTestUtil.VALID_DEADLINE_MARATHON;
+import static seedu.heymatez.logic.commands.CommandTestUtil.VALID_DESCRIPTION_MARATHON;
+import static seedu.heymatez.logic.commands.CommandTestUtil.VALID_TITLE_MARATHON;
+import static seedu.heymatez.logic.parser.CommandParserTestUtil.assertParseFailure;
+import static seedu.heymatez.logic.parser.CommandParserTestUtil.assertParseSuccess;
+import static seedu.heymatez.testutil.TypicalTasks.MARATHON;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.heymatez.logic.commands.AddTaskCommand;
+import seedu.heymatez.model.task.Task;
+import seedu.heymatez.testutil.TaskBuilder;
+
+/**
+ * Contains unit tests for {@code AddTaskCommandParser}.
+ */
+public class AddTaskCommandParserTest {
+ private AddTaskCommandParser parser = new AddTaskCommandParser();
+
+ @Test
+ public void parse_allFieldsPresent_success() {
+ Task expectedTask = new TaskBuilder(MARATHON).build();
+
+ // whitespace only preamble
+ assertParseSuccess(parser, PREAMBLE_WHITESPACE + VALID_TITLE_MARATHON + DESCRIPTION_TASK1
+ + DEADLINE_TASK1, new AddTaskCommand(expectedTask));
+ }
+
+ @Test
+ public void parse_compulsoryFieldMissing_failure() {
+ String expectedMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddTaskCommand.MESSAGE_USAGE);
+
+ // missing description prefix
+ assertParseFailure(parser, TITLE_DESC_TASK1 + VALID_DESCRIPTION_MARATHON + DEADLINE_TASK1,
+ expectedMessage);
+
+ // missing deadline prefix
+ assertParseFailure(parser, TITLE_DESC_TASK1 + DESCRIPTION_TASK1 + VALID_DEADLINE_MARATHON,
+ expectedMessage);
+
+ // all prefixes missing
+ assertParseFailure(parser, VALID_TITLE_MARATHON + VALID_DESCRIPTION_MARATHON + VALID_DEADLINE_MARATHON,
+ expectedMessage);
+ }
+
+ @Test
+ public void parse_invalidValue_failure() {
+ // invalid deadline
+ assertParseFailure(parser, VALID_TITLE_MARATHON + VALID_DESCRIPTION_MARATHON + INVALID_DEADLINE_DESC,
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddTaskCommand.MESSAGE_USAGE));
+ }
+}
diff --git a/src/test/java/seedu/address/logic/parser/ArgumentTokenizerTest.java b/src/test/java/seedu/heymatez/logic/parser/ArgumentTokenizerTest.java
similarity index 98%
rename from src/test/java/seedu/address/logic/parser/ArgumentTokenizerTest.java
rename to src/test/java/seedu/heymatez/logic/parser/ArgumentTokenizerTest.java
index c97308935f5..db0cfd4d1fd 100644
--- a/src/test/java/seedu/address/logic/parser/ArgumentTokenizerTest.java
+++ b/src/test/java/seedu/heymatez/logic/parser/ArgumentTokenizerTest.java
@@ -1,4 +1,4 @@
-package seedu.address.logic.parser;
+package seedu.heymatez.logic.parser;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
@@ -7,6 +7,9 @@
import org.junit.jupiter.api.Test;
+/**
+ * Contains unit tests for {@code ArgumentTokenizer}.
+ */
public class ArgumentTokenizerTest {
private final Prefix unknownPrefix = new Prefix("--u");
diff --git a/src/test/java/seedu/heymatez/logic/parser/ClearAssigneesCommandParserTest.java b/src/test/java/seedu/heymatez/logic/parser/ClearAssigneesCommandParserTest.java
new file mode 100644
index 00000000000..c3023a12f61
--- /dev/null
+++ b/src/test/java/seedu/heymatez/logic/parser/ClearAssigneesCommandParserTest.java
@@ -0,0 +1,43 @@
+package seedu.heymatez.logic.parser;
+
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX;
+import static seedu.heymatez.logic.parser.CommandParserTestUtil.assertParseFailure;
+import static seedu.heymatez.logic.parser.CommandParserTestUtil.assertParseSuccess;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.heymatez.logic.commands.ClearAssigneesCommand;
+import seedu.heymatez.logic.parser.exceptions.ParseException;
+
+/**
+ * Contains unit tests for {@code ClearAssigneeCommandParser}.
+ */
+public class ClearAssigneesCommandParserTest {
+ private ClearAssigneesCommandParser parser = new ClearAssigneesCommandParser();
+
+ @Test
+ public void parse_validArgs_returnsClearedTaskCommand() throws ParseException {
+ assertParseSuccess(parser, "1", new ClearAssigneesCommand(ParserUtil.parseIndex("1")));
+ }
+
+ @Test
+ public void parse_invalidArgs_throwsParseException() {
+ assertParseFailure(parser, " ", String.format(MESSAGE_INVALID_COMMAND_FORMAT,
+ ClearAssigneesCommand.MESSAGE_USAGE));
+
+ assertParseFailure(parser, "1 2", String.format(MESSAGE_INVALID_COMMAND_FORMAT,
+ ClearAssigneesCommand.MESSAGE_USAGE));
+
+ assertParseFailure(parser, "1, 2 ", String.format(MESSAGE_INVALID_COMMAND_FORMAT,
+ ClearAssigneesCommand.MESSAGE_USAGE));
+ }
+
+ @Test
+ public void parse_invalidInteger_throwsParseException() {
+
+ assertParseFailure(parser, "0", MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+
+ assertParseFailure(parser, "-1", MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+}
diff --git a/src/test/java/seedu/address/logic/parser/CommandParserTestUtil.java b/src/test/java/seedu/heymatez/logic/parser/CommandParserTestUtil.java
similarity index 89%
rename from src/test/java/seedu/address/logic/parser/CommandParserTestUtil.java
rename to src/test/java/seedu/heymatez/logic/parser/CommandParserTestUtil.java
index e4c33515768..6e52c64d479 100644
--- a/src/test/java/seedu/address/logic/parser/CommandParserTestUtil.java
+++ b/src/test/java/seedu/heymatez/logic/parser/CommandParserTestUtil.java
@@ -1,9 +1,9 @@
-package seedu.address.logic.parser;
+package seedu.heymatez.logic.parser;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import seedu.address.logic.commands.Command;
-import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.heymatez.logic.commands.Command;
+import seedu.heymatez.logic.parser.exceptions.ParseException;
/**
* Contains helper methods for testing command parsers.
diff --git a/src/test/java/seedu/heymatez/logic/parser/DeleteMemberCommandParserTest.java b/src/test/java/seedu/heymatez/logic/parser/DeleteMemberCommandParserTest.java
new file mode 100644
index 00000000000..4fd0b9337ec
--- /dev/null
+++ b/src/test/java/seedu/heymatez/logic/parser/DeleteMemberCommandParserTest.java
@@ -0,0 +1,31 @@
+package seedu.heymatez.logic.parser;
+
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.heymatez.logic.commands.CommandTestUtil.VALID_NAME_AMY;
+import static seedu.heymatez.logic.parser.CommandParserTestUtil.assertParseFailure;
+import static seedu.heymatez.logic.parser.CommandParserTestUtil.assertParseSuccess;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.heymatez.logic.commands.DeleteMemberCommand;
+import seedu.heymatez.logic.parser.exceptions.ParseException;
+
+/**
+ * Contains unit tests for {@code DeleteMemberCommandParser}.
+ */
+public class DeleteMemberCommandParserTest {
+
+ private DeleteMemberCommandParser parser = new DeleteMemberCommandParser();
+
+ @Test
+ public void parse_validArgs_returnsDeleteCommand() throws ParseException {
+ assertParseSuccess(parser, "Amy Bee",
+ new DeleteMemberCommand(ParserUtil.parseName(VALID_NAME_AMY)));
+ }
+
+ @Test
+ public void parse_invalidArgs_throwsParseException() {
+ assertParseFailure(parser, " ", String.format(MESSAGE_INVALID_COMMAND_FORMAT,
+ DeleteMemberCommand.MESSAGE_USAGE));
+ }
+}
diff --git a/src/test/java/seedu/heymatez/logic/parser/DeleteTaskCommandParserTest.java b/src/test/java/seedu/heymatez/logic/parser/DeleteTaskCommandParserTest.java
new file mode 100644
index 00000000000..b023453e183
--- /dev/null
+++ b/src/test/java/seedu/heymatez/logic/parser/DeleteTaskCommandParserTest.java
@@ -0,0 +1,40 @@
+package seedu.heymatez.logic.parser;
+
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX;
+import static seedu.heymatez.logic.parser.CommandParserTestUtil.assertParseFailure;
+import static seedu.heymatez.logic.parser.CommandParserTestUtil.assertParseSuccess;
+import static seedu.heymatez.testutil.TypicalIndexes.INDEX_FIRST_TASK;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.heymatez.logic.commands.DeleteTaskCommand;
+import seedu.heymatez.logic.parser.exceptions.ParseException;
+
+/**
+ * As we are only doing white-box testing, our test cases do not cover path variations
+ * outside of the DeleteTaskCommand code. For example, inputs "1" and "1 abc" take the
+ * same path through the DeleteTaskCommand, and therefore we test only one of them.
+ * The path variation for those two cases occur inside the ParserUtil, and
+ * therefore should be covered by the ParserUtilTest.
+ */
+public class DeleteTaskCommandParserTest {
+ private DeleteTaskCommandParser parser = new DeleteTaskCommandParser();
+
+ @Test
+ public void parse_validArgs_returnsDeleteTaskCommand() throws ParseException {
+ assertParseSuccess(parser, "1",
+ new DeleteTaskCommand(INDEX_FIRST_TASK));
+ }
+
+ @Test
+ public void parse_invalidInteger_returnsDeleteTaskCommand() throws ParseException {
+ assertParseFailure(parser, "-1", MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+
+ @Test
+ public void parse_invalidArgs_throwsParseException() {
+ assertParseFailure(parser, " ", String.format(MESSAGE_INVALID_COMMAND_FORMAT,
+ DeleteTaskCommand.MESSAGE_USAGE));
+ }
+}
diff --git a/src/test/java/seedu/heymatez/logic/parser/DoneTaskParserCommandTest.java b/src/test/java/seedu/heymatez/logic/parser/DoneTaskParserCommandTest.java
new file mode 100644
index 00000000000..bb677d831d5
--- /dev/null
+++ b/src/test/java/seedu/heymatez/logic/parser/DoneTaskParserCommandTest.java
@@ -0,0 +1,44 @@
+package seedu.heymatez.logic.parser;
+
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX;
+import static seedu.heymatez.logic.parser.CommandParserTestUtil.assertParseFailure;
+import static seedu.heymatez.logic.parser.CommandParserTestUtil.assertParseSuccess;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.heymatez.logic.commands.DoneTaskCommand;
+import seedu.heymatez.logic.parser.exceptions.ParseException;
+
+/**
+ * Contains unit tests for {@code DoneTaskCommand}.
+ */
+public class DoneTaskParserCommandTest {
+
+ private DoneTaskCommandParser parser = new DoneTaskCommandParser();
+
+ @Test
+ public void parse_validArgs_returnsDoneTaskCommand() throws ParseException {
+ assertParseSuccess(parser, "1", new DoneTaskCommand(ParserUtil.parseIndex("1")));
+ }
+
+ @Test
+ public void parse_invalidArgs_throwsParseException() {
+ assertParseFailure(parser, " ", String.format(MESSAGE_INVALID_COMMAND_FORMAT,
+ DoneTaskCommand.MESSAGE_USAGE));
+
+ assertParseFailure(parser, "1 2", String.format(MESSAGE_INVALID_COMMAND_FORMAT,
+ DoneTaskCommand.MESSAGE_USAGE));
+
+ assertParseFailure(parser, "1, 2 ", String.format(MESSAGE_INVALID_COMMAND_FORMAT,
+ DoneTaskCommand.MESSAGE_USAGE));
+ }
+
+ @Test
+ public void parse_invalidInteger_throwsParseException() {
+ assertParseFailure(parser, "0", MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+
+ assertParseFailure(parser, "-1", MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+
+ }
+}
diff --git a/src/test/java/seedu/heymatez/logic/parser/EditMemberCommandParserTest.java b/src/test/java/seedu/heymatez/logic/parser/EditMemberCommandParserTest.java
new file mode 100644
index 00000000000..25b6c155081
--- /dev/null
+++ b/src/test/java/seedu/heymatez/logic/parser/EditMemberCommandParserTest.java
@@ -0,0 +1,165 @@
+package seedu.heymatez.logic.parser;
+
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_PERSON_DISPLAYED_NAME;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_PERSON_EMAIL;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_PERSON_PHONE;
+import static seedu.heymatez.logic.commands.CommandTestUtil.EMAIL_DESC_AMY;
+import static seedu.heymatez.logic.commands.CommandTestUtil.EMAIL_DESC_BOB;
+import static seedu.heymatez.logic.commands.CommandTestUtil.INVALID_EMAIL_DESC;
+import static seedu.heymatez.logic.commands.CommandTestUtil.INVALID_NEW_NAME_DESC;
+import static seedu.heymatez.logic.commands.CommandTestUtil.INVALID_PHONE_DESC;
+import static seedu.heymatez.logic.commands.CommandTestUtil.NEW_NAME_DESC_AMY;
+import static seedu.heymatez.logic.commands.CommandTestUtil.PHONE_DESC_AMY;
+import static seedu.heymatez.logic.commands.CommandTestUtil.PHONE_DESC_BOB;
+import static seedu.heymatez.logic.commands.CommandTestUtil.VALID_EMAIL_AMY;
+import static seedu.heymatez.logic.commands.CommandTestUtil.VALID_EMAIL_BOB;
+import static seedu.heymatez.logic.commands.CommandTestUtil.VALID_NAME_AMY;
+import static seedu.heymatez.logic.commands.CommandTestUtil.VALID_NAME_BOB;
+import static seedu.heymatez.logic.commands.CommandTestUtil.VALID_PHONE_AMY;
+import static seedu.heymatez.logic.commands.CommandTestUtil.VALID_PHONE_BOB;
+import static seedu.heymatez.logic.parser.CommandParserTestUtil.assertParseFailure;
+import static seedu.heymatez.logic.parser.CommandParserTestUtil.assertParseSuccess;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.heymatez.logic.commands.EditMemberCommand;
+import seedu.heymatez.logic.commands.EditMemberCommand.EditMemberDescriptor;
+import seedu.heymatez.logic.parser.exceptions.ParseException;
+import seedu.heymatez.model.person.Email;
+import seedu.heymatez.model.person.Name;
+import seedu.heymatez.model.person.Phone;
+import seedu.heymatez.testutil.EditMemberDescriptorBuilder;
+
+/**
+ * Contains unit tests for {@code EditMemberCommandParser}.
+ */
+public class EditMemberCommandParserTest {
+
+ private static final String MESSAGE_INVALID_FORMAT =
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditMemberCommand.MESSAGE_USAGE);
+
+ private EditMemberCommandParser parser = new EditMemberCommandParser();
+
+ @Test
+ public void parse_missingParts_failure() {
+ // no name specified
+ assertParseFailure(parser, "p/93451122", MESSAGE_INVALID_FORMAT);
+
+ // no field specified
+ assertParseFailure(parser, VALID_NAME_AMY, EditMemberCommand.MESSAGE_NOT_EDITED);
+
+ // no name and no field specified
+ assertParseFailure(parser, "", MESSAGE_INVALID_FORMAT);
+ }
+
+ @Test
+ public void parse_invalidPreamble_failure() {
+ // invalid arguments being parsed as preamble
+ assertParseFailure(parser, "N@ME", MESSAGE_INVALID_FORMAT);
+
+ // invalid prefix being parsed as preamble
+ assertParseFailure(parser, "h/", MESSAGE_INVALID_FORMAT);
+ }
+
+ @Test
+ public void parse_invalidValue_failure() {
+ assertParseFailure(parser, "1" + INVALID_NEW_NAME_DESC,
+ MESSAGE_INVALID_PERSON_DISPLAYED_NAME + Name.MESSAGE_CONSTRAINTS); // invalid name
+ assertParseFailure(parser, "1" + INVALID_PHONE_DESC,
+ MESSAGE_INVALID_PERSON_PHONE + Phone.MESSAGE_CONSTRAINTS); // invalid phone
+ assertParseFailure(parser, "1" + INVALID_EMAIL_DESC,
+ MESSAGE_INVALID_PERSON_EMAIL + Email.MESSAGE_CONSTRAINTS); // invalid email
+
+ // invalid phone followed by valid email
+ assertParseFailure(parser, "1" + INVALID_PHONE_DESC + EMAIL_DESC_AMY,
+ MESSAGE_INVALID_PERSON_PHONE + Phone.MESSAGE_CONSTRAINTS);
+
+ // valid phone followed by invalid phone. The test case for invalid phone followed by valid phone
+ // is tested at {@code parse_invalidValueFollowedByValidValue_success()}
+ assertParseFailure(parser, "1" + PHONE_DESC_BOB + INVALID_PHONE_DESC,
+ MESSAGE_INVALID_PERSON_PHONE + Phone.MESSAGE_CONSTRAINTS);
+
+ // multiple invalid values, but only the first invalid value is captured
+ assertParseFailure(parser, "1" + INVALID_NEW_NAME_DESC + INVALID_EMAIL_DESC + VALID_PHONE_AMY,
+ MESSAGE_INVALID_PERSON_DISPLAYED_NAME + Name.MESSAGE_CONSTRAINTS);
+ }
+
+ @Test
+ public void parse_allFieldsSpecified_success() throws ParseException {
+ Name targetName = ParserUtil.parseName(VALID_NAME_BOB);
+ String userInput = VALID_NAME_BOB + NEW_NAME_DESC_AMY + PHONE_DESC_BOB + EMAIL_DESC_AMY;
+
+ EditMemberDescriptor descriptor = new EditMemberDescriptorBuilder().withName(VALID_NAME_AMY)
+ .withPhone(VALID_PHONE_BOB).withEmail(VALID_EMAIL_AMY).build();
+ EditMemberCommand expectedCommand = new EditMemberCommand(targetName, descriptor);
+
+ assertParseSuccess(parser, userInput, expectedCommand);
+ }
+
+ @Test
+ public void parse_someFieldsSpecified_success() throws ParseException {
+ Name targetName = ParserUtil.parseName(VALID_NAME_AMY);
+ String userInput = VALID_NAME_AMY + PHONE_DESC_BOB + EMAIL_DESC_AMY;
+
+ EditMemberDescriptor descriptor = new EditMemberDescriptorBuilder().withPhone(VALID_PHONE_BOB)
+ .withEmail(VALID_EMAIL_AMY).build();
+ EditMemberCommand expectedCommand = new EditMemberCommand(targetName, descriptor);
+
+ assertParseSuccess(parser, userInput, expectedCommand);
+ }
+
+ @Test
+ public void parse_oneFieldSpecified_success() throws ParseException {
+ // name
+ Name targetName = ParserUtil.parseName(VALID_NAME_BOB);
+ String userInput = VALID_NAME_BOB + NEW_NAME_DESC_AMY;
+ EditMemberCommand.EditMemberDescriptor descriptor =
+ new EditMemberDescriptorBuilder().withName(VALID_NAME_AMY).build();
+ EditMemberCommand expectedCommand = new EditMemberCommand(targetName, descriptor);
+ assertParseSuccess(parser, userInput, expectedCommand);
+
+ // phone
+ userInput = VALID_NAME_BOB + PHONE_DESC_AMY;
+ descriptor = new EditMemberDescriptorBuilder().withPhone(VALID_PHONE_AMY).build();
+ expectedCommand = new EditMemberCommand(targetName, descriptor);
+ assertParseSuccess(parser, userInput, expectedCommand);
+
+ // email
+ userInput = VALID_NAME_BOB + EMAIL_DESC_AMY;
+ descriptor = new EditMemberDescriptorBuilder().withEmail(VALID_EMAIL_AMY).build();
+ expectedCommand = new EditMemberCommand(targetName, descriptor);
+ assertParseSuccess(parser, userInput, expectedCommand);
+ }
+
+ @Test
+ public void parse_multipleRepeatedFields_acceptsLast() throws ParseException {
+ Name targetName = ParserUtil.parseName(VALID_NAME_AMY);
+ String userInput = VALID_NAME_AMY + PHONE_DESC_AMY + EMAIL_DESC_AMY + PHONE_DESC_AMY + EMAIL_DESC_AMY
+ + PHONE_DESC_BOB + EMAIL_DESC_BOB;
+
+ EditMemberCommand.EditMemberDescriptor descriptor = new EditMemberDescriptorBuilder()
+ .withPhone(VALID_PHONE_BOB).withEmail(VALID_EMAIL_BOB).build();
+ EditMemberCommand expectedCommand = new EditMemberCommand(targetName, descriptor);
+
+ assertParseSuccess(parser, userInput, expectedCommand);
+ }
+
+ @Test
+ public void parse_invalidValueFollowedByValidValue_success() throws ParseException {
+ // no other valid values specified
+ Name targetName = ParserUtil.parseName(VALID_NAME_AMY);
+ String userInput = VALID_NAME_AMY + INVALID_PHONE_DESC + PHONE_DESC_BOB;
+ EditMemberCommand.EditMemberDescriptor descriptor =
+ new EditMemberDescriptorBuilder().withPhone(VALID_PHONE_BOB).build();
+ EditMemberCommand expectedCommand = new EditMemberCommand(targetName, descriptor);
+ assertParseSuccess(parser, userInput, expectedCommand);
+
+ // other valid values specified
+ userInput = VALID_NAME_AMY + EMAIL_DESC_BOB + INVALID_PHONE_DESC + PHONE_DESC_BOB;
+ descriptor = new EditMemberDescriptorBuilder().withPhone(VALID_PHONE_BOB).withEmail(VALID_EMAIL_BOB)
+ .build();
+ expectedCommand = new EditMemberCommand(targetName, descriptor);
+ assertParseSuccess(parser, userInput, expectedCommand);
+ }
+}
diff --git a/src/test/java/seedu/heymatez/logic/parser/EditTaskCommandParserTest.java b/src/test/java/seedu/heymatez/logic/parser/EditTaskCommandParserTest.java
new file mode 100644
index 00000000000..c20a88e19dc
--- /dev/null
+++ b/src/test/java/seedu/heymatez/logic/parser/EditTaskCommandParserTest.java
@@ -0,0 +1,177 @@
+package seedu.heymatez.logic.parser;
+
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_TASK_DEADLINE_FORMAT;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_TASK_PRIORITY;
+import static seedu.heymatez.logic.commands.CommandTestUtil.ASSIGNEE_TASK2;
+import static seedu.heymatez.logic.commands.CommandTestUtil.DEADLINE_TASK1;
+import static seedu.heymatez.logic.commands.CommandTestUtil.DEADLINE_TASK2;
+import static seedu.heymatez.logic.commands.CommandTestUtil.DESCRIPTION_TASK1;
+import static seedu.heymatez.logic.commands.CommandTestUtil.DESCRIPTION_TASK2;
+import static seedu.heymatez.logic.commands.CommandTestUtil.INVALID_DEADLINE_DESC;
+import static seedu.heymatez.logic.commands.CommandTestUtil.INVALID_PRIORITY_DESC;
+import static seedu.heymatez.logic.commands.CommandTestUtil.PRIORITY_TASK1;
+import static seedu.heymatez.logic.commands.CommandTestUtil.PRIORITY_TASK2;
+import static seedu.heymatez.logic.commands.CommandTestUtil.TITLE_DESC_TASK1;
+import static seedu.heymatez.logic.commands.CommandTestUtil.TITLE_DESC_TASK2;
+import static seedu.heymatez.logic.commands.CommandTestUtil.VALID_ASSIGNEE_MEETING;
+import static seedu.heymatez.logic.commands.CommandTestUtil.VALID_DEADLINE_MARATHON;
+import static seedu.heymatez.logic.commands.CommandTestUtil.VALID_DEADLINE_MEETING;
+import static seedu.heymatez.logic.commands.CommandTestUtil.VALID_DESCRIPTION_MARATHON;
+import static seedu.heymatez.logic.commands.CommandTestUtil.VALID_DESCRIPTION_MEETING;
+import static seedu.heymatez.logic.commands.CommandTestUtil.VALID_PRIORITY_MARATHON;
+import static seedu.heymatez.logic.commands.CommandTestUtil.VALID_PRIORITY_MEETING;
+import static seedu.heymatez.logic.commands.CommandTestUtil.VALID_TITLE_MARATHON;
+import static seedu.heymatez.logic.commands.CommandTestUtil.VALID_TITLE_MEETING;
+import static seedu.heymatez.logic.parser.CommandParserTestUtil.assertParseFailure;
+import static seedu.heymatez.logic.parser.CommandParserTestUtil.assertParseSuccess;
+import static seedu.heymatez.testutil.TypicalIndexes.INDEX_FIRST_TASK;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.heymatez.commons.core.index.Index;
+import seedu.heymatez.logic.commands.EditTaskCommand;
+import seedu.heymatez.logic.parser.exceptions.ParseException;
+import seedu.heymatez.model.task.Deadline;
+import seedu.heymatez.model.task.Priority;
+import seedu.heymatez.testutil.EditTaskDescriptorBuilder;
+
+/**
+ * Contains unit tests for {@code EditTaskCommandParser}.
+ */
+public class EditTaskCommandParserTest {
+ private static final String MESSAGE_INVALID_FORMAT =
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditTaskCommand.MESSAGE_USAGE);
+
+ private EditTaskCommandParser parser = new EditTaskCommandParser();
+
+ @Test
+ public void parse_missingParts_failure() {
+ // no index specified
+ assertParseFailure(parser, "d/This is my new description",
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditTaskCommand.MESSAGE_USAGE));
+
+ // no field specified
+ assertParseFailure(parser, "1", EditTaskCommand.MESSAGE_NOT_EDITED);
+
+ // no index and no field specified
+ assertParseFailure(parser, "", MESSAGE_INVALID_FORMAT);
+ }
+
+ @Test
+ public void parse_invalidPreamble_failure() {
+ // invalid arguments being parsed as preamble
+ assertParseFailure(parser, "N", MESSAGE_INVALID_FORMAT);
+
+ // invalid prefix being parsed as preamble
+ assertParseFailure(parser, "h/", MESSAGE_INVALID_FORMAT);
+
+ assertParseFailure(parser, "0", MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+
+ assertParseFailure(parser, "-1", MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+
+ @Test
+ public void parse_invalidInteger_failure() {
+ // invalid index
+ assertParseFailure(parser, "0", MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+
+ assertParseFailure(parser, "-1", MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+
+ @Test
+ public void parse_invalidValue_failure() {
+ // invalid deadline
+ assertParseFailure(parser, "1" + INVALID_DEADLINE_DESC, MESSAGE_INVALID_TASK_DEADLINE_FORMAT
+ + Deadline.MESSAGE_CONSTRAINTS);
+
+ //invalid priority
+ assertParseFailure(parser, "1" + INVALID_PRIORITY_DESC, MESSAGE_INVALID_TASK_PRIORITY
+ + Priority.MESSAGE_CONSTRAINTS);
+ }
+
+ @Test
+ public void parse_allFieldsSpecified_success() {
+ Index targetIndex = INDEX_FIRST_TASK;
+ String userInput = targetIndex.getOneBased() + TITLE_DESC_TASK1 + DESCRIPTION_TASK1 + DEADLINE_TASK1
+ + PRIORITY_TASK1;
+
+ EditTaskCommand.EditTaskDescriptor descriptor = new EditTaskDescriptorBuilder().withTitle(VALID_TITLE_MARATHON)
+ .withDescription(VALID_DESCRIPTION_MARATHON).withDeadline(VALID_DEADLINE_MARATHON)
+ .withPriority(VALID_PRIORITY_MARATHON).build();
+ EditTaskCommand expectedCommand = new EditTaskCommand(targetIndex, descriptor);
+
+ assertParseSuccess(parser, userInput, expectedCommand);
+ }
+
+ @Test
+ public void parse_someFieldsSpecified_success() {
+ Index targetIndex = INDEX_FIRST_TASK;
+ String userInput = targetIndex.getOneBased() + TITLE_DESC_TASK2 + DESCRIPTION_TASK2;
+
+ EditTaskCommand.EditTaskDescriptor descriptor = new EditTaskDescriptorBuilder().withTitle(VALID_TITLE_MEETING)
+ .withDescription(VALID_DESCRIPTION_MEETING).build();
+ EditTaskCommand expectedCommand = new EditTaskCommand(targetIndex, descriptor);
+
+ assertParseSuccess(parser, userInput, expectedCommand);
+ }
+
+ @Test
+ public void parse_oneFieldSpecified_success() {
+ // title
+ Index targetIndex = INDEX_FIRST_TASK;
+ String userInput = targetIndex.getOneBased() + TITLE_DESC_TASK2;
+ EditTaskCommand.EditTaskDescriptor descriptor =
+ new EditTaskDescriptorBuilder().withTitle(VALID_TITLE_MEETING).build();
+ EditTaskCommand expectedCommand = new EditTaskCommand(targetIndex, descriptor);
+ assertParseSuccess(parser, userInput, expectedCommand);
+
+ // description
+ userInput = targetIndex.getOneBased() + DESCRIPTION_TASK2;
+ descriptor = new EditTaskDescriptorBuilder().withDescription(VALID_DESCRIPTION_MEETING).build();
+ expectedCommand = new EditTaskCommand(targetIndex, descriptor);
+ assertParseSuccess(parser, userInput, expectedCommand);
+
+ // deadline
+ userInput = targetIndex.getOneBased() + DEADLINE_TASK2;
+ descriptor = new EditTaskDescriptorBuilder().withDeadline(VALID_DEADLINE_MEETING).build();
+ expectedCommand = new EditTaskCommand(targetIndex, descriptor);
+ assertParseSuccess(parser, userInput, expectedCommand);
+
+ // priority
+ userInput = targetIndex.getOneBased() + PRIORITY_TASK2;
+ descriptor = new EditTaskDescriptorBuilder().withPriority(VALID_PRIORITY_MEETING).build();
+ expectedCommand = new EditTaskCommand(targetIndex, descriptor);
+ assertParseSuccess(parser, userInput, expectedCommand);
+
+ // assignee
+ userInput = targetIndex.getOneBased() + ASSIGNEE_TASK2;
+ descriptor = new EditTaskDescriptorBuilder().withAssignees(VALID_ASSIGNEE_MEETING).build();
+ expectedCommand = new EditTaskCommand(targetIndex, descriptor);
+ assertParseSuccess(parser, userInput, expectedCommand);
+ }
+
+ @Test
+ public void parse_multipleRepeatedFields_acceptsLast() throws ParseException {
+ Index targetIndex = INDEX_FIRST_TASK;
+ String userInput = targetIndex.getOneBased() + DESCRIPTION_TASK1 + DEADLINE_TASK1
+ + DESCRIPTION_TASK1 + DEADLINE_TASK1 + DESCRIPTION_TASK2 + DEADLINE_TASK2;
+
+ EditTaskCommand.EditTaskDescriptor descriptor = new EditTaskDescriptorBuilder()
+ .withDescription(VALID_DESCRIPTION_MEETING).withDeadline(VALID_DEADLINE_MEETING).build();
+ EditTaskCommand expectedCommand = new EditTaskCommand(targetIndex, descriptor);
+ assertParseSuccess(parser, userInput, expectedCommand);
+ }
+
+ @Test
+ public void parse_invalidValueFollowedByValidValue_success() {
+ // no other valid values specified
+ Index targetIndex = INDEX_FIRST_TASK;
+ String userInput = targetIndex.getOneBased() + INVALID_DEADLINE_DESC + DEADLINE_TASK1;
+ EditTaskCommand.EditTaskDescriptor descriptor = new EditTaskDescriptorBuilder()
+ .withDeadline(VALID_DEADLINE_MARATHON).build();
+ EditTaskCommand expectedCommand = new EditTaskCommand(targetIndex, descriptor);
+ assertParseSuccess(parser, userInput, expectedCommand);
+ }
+}
diff --git a/src/test/java/seedu/heymatez/logic/parser/FindByPriorityCommandParserTest.java b/src/test/java/seedu/heymatez/logic/parser/FindByPriorityCommandParserTest.java
new file mode 100644
index 00000000000..154af8d473c
--- /dev/null
+++ b/src/test/java/seedu/heymatez/logic/parser/FindByPriorityCommandParserTest.java
@@ -0,0 +1,61 @@
+package seedu.heymatez.logic.parser;
+
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_TASK_PRIORITY;
+import static seedu.heymatez.logic.parser.CommandParserTestUtil.assertParseFailure;
+import static seedu.heymatez.logic.parser.CommandParserTestUtil.assertParseSuccess;
+
+import java.util.Arrays;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.heymatez.logic.commands.FindByPriorityCommand;
+import seedu.heymatez.model.task.Priority;
+import seedu.heymatez.model.task.PriorityContainsKeywordPredicate;
+
+/**
+ * Contains unit tests for {@code FindByPriorityCommandParser}.
+ */
+public class FindByPriorityCommandParserTest {
+ private FindByPriorityCommandParser parser = new FindByPriorityCommandParser();
+
+ @Test
+ public void parse_emptyArg_throwsParseException() {
+ assertParseFailure(parser, "", String.format(MESSAGE_INVALID_COMMAND_FORMAT,
+ FindByPriorityCommand.MESSAGE_USAGE));
+ }
+
+ @Test
+ public void parse_validArgs_returnsFindTasksCommand() {
+ // no leading and trailing whitespaces
+ FindByPriorityCommand expectedTasksByPriorityCommand =
+ new FindByPriorityCommand(new PriorityContainsKeywordPredicate(Arrays.asList("high")));
+
+ assertParseSuccess(parser, "high", expectedTasksByPriorityCommand);
+
+ expectedTasksByPriorityCommand =
+ new FindByPriorityCommand(new PriorityContainsKeywordPredicate(Arrays.asList("low")));
+
+ assertParseSuccess(parser, "low", expectedTasksByPriorityCommand);
+
+ expectedTasksByPriorityCommand =
+ new FindByPriorityCommand(new PriorityContainsKeywordPredicate(Arrays.asList("medium")));
+
+ assertParseSuccess(parser, "medium", expectedTasksByPriorityCommand);
+
+ expectedTasksByPriorityCommand =
+ new FindByPriorityCommand(new PriorityContainsKeywordPredicate(Arrays.asList("unassigned")));
+
+ assertParseSuccess(parser, "unassigned", expectedTasksByPriorityCommand);
+ }
+
+ @Test
+ public void parse_invalidArgs_returnsFindTasksCommand() {
+
+ assertParseFailure(parser, "low high", String.format(MESSAGE_INVALID_COMMAND_FORMAT,
+ FindByPriorityCommand.MESSAGE_USAGE));
+
+ assertParseFailure(parser, "extreme", MESSAGE_INVALID_TASK_PRIORITY
+ + Priority.MESSAGE_CONSTRAINTS);
+ }
+}
diff --git a/src/test/java/seedu/heymatez/logic/parser/FindMemberTasksCommandParserTest.java b/src/test/java/seedu/heymatez/logic/parser/FindMemberTasksCommandParserTest.java
new file mode 100644
index 00000000000..4415c5b85e6
--- /dev/null
+++ b/src/test/java/seedu/heymatez/logic/parser/FindMemberTasksCommandParserTest.java
@@ -0,0 +1,35 @@
+package seedu.heymatez.logic.parser;
+
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.heymatez.logic.parser.CommandParserTestUtil.assertParseFailure;
+import static seedu.heymatez.logic.parser.CommandParserTestUtil.assertParseSuccess;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.heymatez.logic.commands.FindMemberTasksCommand;
+import seedu.heymatez.model.assignee.Assignee;
+import seedu.heymatez.model.task.TaskContainsAssigneePredicate;
+
+/**
+ * Contains unit tests for {@code FindMemberTasksCommandParser}.
+ */
+public class FindMemberTasksCommandParserTest {
+ private FindMemberTasksCommandParser parser = new FindMemberTasksCommandParser();
+
+ @Test
+ public void parse_emptyArg_throwsParseException() {
+ assertParseFailure(parser, " ", String.format(MESSAGE_INVALID_COMMAND_FORMAT,
+ FindMemberTasksCommand.MESSAGE_USAGE));
+ }
+
+ @Test
+ public void parse_validArg_returnsFindMemberTasksCommand() {
+ // no leading and trailing whitespaces
+ FindMemberTasksCommand expectedFindMemberTasksCommand =
+ new FindMemberTasksCommand(new TaskContainsAssigneePredicate("Alice"));
+ assertParseSuccess(parser, "Alice", expectedFindMemberTasksCommand);
+
+ // multiple whitespaces between keywords
+ assertParseFailure(parser, "Alex Yeoh /t", Assignee.MESSAGE_SEARCH_TASKS_CONSTRAINTS);
+ }
+}
diff --git a/src/test/java/seedu/heymatez/logic/parser/FindMembersCommandParserTest.java b/src/test/java/seedu/heymatez/logic/parser/FindMembersCommandParserTest.java
new file mode 100644
index 00000000000..d55dcef72ad
--- /dev/null
+++ b/src/test/java/seedu/heymatez/logic/parser/FindMembersCommandParserTest.java
@@ -0,0 +1,41 @@
+package seedu.heymatez.logic.parser;
+
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.heymatez.logic.parser.CommandParserTestUtil.assertParseFailure;
+import static seedu.heymatez.logic.parser.CommandParserTestUtil.assertParseSuccess;
+
+import java.util.Arrays;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.heymatez.logic.commands.FindMembersCommand;
+import seedu.heymatez.model.person.DetailsContainsKeywordsPredicate;
+
+/**
+ * Contains unit tests for {@code FindMembersCommandParser}.
+ */
+public class FindMembersCommandParserTest {
+
+ private FindMemberCommandParser parser = new FindMemberCommandParser();
+
+ @Test
+ public void parse_emptyArg_throwsParseException() {
+ assertParseFailure(parser, "",
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindMembersCommand.MESSAGE_USAGE));
+
+ assertParseFailure(parser, " ",
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindMembersCommand.MESSAGE_USAGE));
+ }
+
+ @Test
+ public void parse_validArgs_returnsFindCommand() {
+ // no leading and trailing whitespaces
+ FindMembersCommand expectedFindMembersCommand =
+ new FindMembersCommand(new DetailsContainsKeywordsPredicate(Arrays.asList("Alice", "Bob")));
+ assertParseSuccess(parser, "Alice Bob", expectedFindMembersCommand);
+
+ // multiple whitespaces between keywords
+ assertParseSuccess(parser, " \n Alice \n \t Bob \t", expectedFindMembersCommand);
+ }
+
+}
diff --git a/src/test/java/seedu/heymatez/logic/parser/FindTasksBeforeCommandParserTest.java b/src/test/java/seedu/heymatez/logic/parser/FindTasksBeforeCommandParserTest.java
new file mode 100644
index 00000000000..5dc20f2e3a1
--- /dev/null
+++ b/src/test/java/seedu/heymatez/logic/parser/FindTasksBeforeCommandParserTest.java
@@ -0,0 +1,34 @@
+package seedu.heymatez.logic.parser;
+
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.heymatez.logic.parser.CommandParserTestUtil.assertParseFailure;
+import static seedu.heymatez.logic.parser.CommandParserTestUtil.assertParseSuccess;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.heymatez.logic.commands.FindTasksBeforeCommand;
+import seedu.heymatez.model.task.DeadlineBeforeDatePredicate;
+
+/**
+ * Contains unit tests for {@code FindTasksBeforeCommandParser}.
+ */
+public class FindTasksBeforeCommandParserTest {
+ private FindTasksBeforeCommandParser parser = new FindTasksBeforeCommandParser();
+
+ @Test
+ public void parse_emptyArg_throwsParseException() {
+ assertParseFailure(parser, " ", String.format(MESSAGE_INVALID_COMMAND_FORMAT,
+ FindTasksBeforeCommand.MESSAGE_USAGE));
+ }
+
+ @Test
+ public void parse_validArgs_returnsFindTasksBeforeCommand() {
+ // no leading and trailing whitespaces
+ FindTasksBeforeCommand expectedFindTasksBeforeCommand =
+ new FindTasksBeforeCommand(new DeadlineBeforeDatePredicate("2021-05-06"));
+ assertParseSuccess(parser, "2021-05-06", expectedFindTasksBeforeCommand);
+
+ // multiple whitespaces
+ assertParseSuccess(parser, " 2021-05-06 ", expectedFindTasksBeforeCommand);
+ }
+}
diff --git a/src/test/java/seedu/heymatez/logic/parser/FindTasksCommandParserTest.java b/src/test/java/seedu/heymatez/logic/parser/FindTasksCommandParserTest.java
new file mode 100644
index 00000000000..75b02a88a07
--- /dev/null
+++ b/src/test/java/seedu/heymatez/logic/parser/FindTasksCommandParserTest.java
@@ -0,0 +1,36 @@
+package seedu.heymatez.logic.parser;
+
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.heymatez.logic.parser.CommandParserTestUtil.assertParseFailure;
+import static seedu.heymatez.logic.parser.CommandParserTestUtil.assertParseSuccess;
+
+import java.util.Arrays;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.heymatez.logic.commands.FindTasksCommand;
+import seedu.heymatez.model.task.TaskContainsKeywordPredicate;
+
+/**
+ * Contains unit tests for {@code FindTasksCommandParser}.
+ */
+public class FindTasksCommandParserTest {
+ private FindTasksCommandParser parser = new FindTasksCommandParser();
+
+ @Test
+ public void parse_emptyArg_throwsParseException() {
+ assertParseFailure(parser, " ", String.format(MESSAGE_INVALID_COMMAND_FORMAT,
+ FindTasksCommand.MESSAGE_USAGE));
+ }
+
+ @Test
+ public void parse_validArgs_returnsFindTasksCommand() {
+ // no leading and trailing whitespaces
+ FindTasksCommand expectedFindTasksCommand =
+ new FindTasksCommand(new TaskContainsKeywordPredicate(Arrays.asList("book", "CS2103tp")));
+ assertParseSuccess(parser, "book CS2103tp", expectedFindTasksCommand);
+
+ // multiple whitespaces between keywords
+ assertParseSuccess(parser, " \n book \n \t CS2103tp \t", expectedFindTasksCommand);
+ }
+}
diff --git a/src/test/java/seedu/heymatez/logic/parser/HeyMatezParserTest.java b/src/test/java/seedu/heymatez/logic/parser/HeyMatezParserTest.java
new file mode 100644
index 00000000000..267ea2cc0cc
--- /dev/null
+++ b/src/test/java/seedu/heymatez/logic/parser/HeyMatezParserTest.java
@@ -0,0 +1,103 @@
+package seedu.heymatez.logic.parser;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_UNKNOWN_COMMAND;
+import static seedu.heymatez.logic.commands.CommandTestUtil.VALID_NAME_AMY;
+import static seedu.heymatez.testutil.Assert.assertThrows;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.heymatez.logic.commands.AddMemberCommand;
+import seedu.heymatez.logic.commands.ClearCommand;
+import seedu.heymatez.logic.commands.DeleteMemberCommand;
+import seedu.heymatez.logic.commands.EditMemberCommand;
+import seedu.heymatez.logic.commands.ExitCommand;
+import seedu.heymatez.logic.commands.FindMembersCommand;
+import seedu.heymatez.logic.commands.HelpCommand;
+import seedu.heymatez.logic.commands.ViewMembersCommand;
+import seedu.heymatez.logic.parser.exceptions.ParseException;
+import seedu.heymatez.model.person.DetailsContainsKeywordsPredicate;
+import seedu.heymatez.model.person.Person;
+import seedu.heymatez.testutil.EditMemberDescriptorBuilder;
+import seedu.heymatez.testutil.PersonBuilder;
+import seedu.heymatez.testutil.PersonUtil;
+
+/**
+ * Contains unit tests for {@code HeyMatezParser}.
+ */
+public class HeyMatezParserTest {
+
+ private final HeyMatezParser parser = new HeyMatezParser();
+
+ @Test
+ public void parseCommand_add() throws Exception {
+ Person person = new PersonBuilder().build();
+ AddMemberCommand command = (AddMemberCommand) parser.parseCommand(PersonUtil.getAddCommand(person));
+ assertEquals(new AddMemberCommand(person), command);
+ }
+
+ @Test
+ public void parseCommand_clear() throws Exception {
+ assertTrue(parser.parseCommand(ClearCommand.COMMAND_WORD) instanceof ClearCommand);
+ assertTrue(parser.parseCommand(ClearCommand.COMMAND_WORD + " 3") instanceof ClearCommand);
+ }
+
+ @Test
+ public void parseCommand_delete() throws Exception {
+ DeleteMemberCommand command = (DeleteMemberCommand) parser.parseCommand(
+ DeleteMemberCommand.COMMAND_WORD + " " + VALID_NAME_AMY);
+ assertEquals(new DeleteMemberCommand(ParserUtil.parseName(VALID_NAME_AMY)), command);
+ }
+
+ @Test
+ public void parseCommand_edit() throws Exception {
+ Person person = new PersonBuilder().build();
+ EditMemberCommand.EditMemberDescriptor descriptor = new EditMemberDescriptorBuilder(person).build();
+ EditMemberCommand command = (EditMemberCommand) parser.parseCommand(EditMemberCommand.COMMAND_WORD + " "
+ + VALID_NAME_AMY + " " + PersonUtil.getEditPersonDescriptorDetails(descriptor));
+ assertEquals(new EditMemberCommand(ParserUtil.parseName(VALID_NAME_AMY), descriptor), command);
+ }
+
+ @Test
+ public void parseCommand_exit() throws Exception {
+ assertTrue(parser.parseCommand(ExitCommand.COMMAND_WORD) instanceof ExitCommand);
+ assertTrue(parser.parseCommand(ExitCommand.COMMAND_WORD + " 3") instanceof ExitCommand);
+ }
+
+ @Test
+ public void parseCommand_find() throws Exception {
+ List keywords = Arrays.asList("foo", "bar", "baz");
+ FindMembersCommand command = (FindMembersCommand) parser.parseCommand(
+ FindMembersCommand.COMMAND_WORD + " " + keywords.stream().collect(Collectors.joining(" ")));
+ assertEquals(new FindMembersCommand(new DetailsContainsKeywordsPredicate(keywords)), command);
+ }
+
+ @Test
+ public void parseCommand_help() throws Exception {
+ assertTrue(parser.parseCommand(HelpCommand.COMMAND_WORD) instanceof HelpCommand);
+ assertTrue(parser.parseCommand(HelpCommand.COMMAND_WORD + " 3") instanceof HelpCommand);
+ }
+
+ @Test
+ public void parseCommand_list() throws Exception {
+ assertTrue(parser.parseCommand(ViewMembersCommand.COMMAND_WORD) instanceof ViewMembersCommand);
+ assertTrue(parser.parseCommand(ViewMembersCommand.COMMAND_WORD + " 3") instanceof ViewMembersCommand);
+ }
+
+ @Test
+ public void parseCommand_unrecognisedInput_throwsParseException() {
+ assertThrows(ParseException.class, String.format(MESSAGE_INVALID_COMMAND_FORMAT, HelpCommand.MESSAGE_USAGE), ()
+ -> parser.parseCommand(""));
+ }
+
+ @Test
+ public void parseCommand_unknownCommand_throwsParseException() {
+ assertThrows(ParseException.class, MESSAGE_UNKNOWN_COMMAND, () -> parser.parseCommand("unknownCommand"));
+ }
+}
diff --git a/src/test/java/seedu/heymatez/logic/parser/ParserUtilTest.java b/src/test/java/seedu/heymatez/logic/parser/ParserUtilTest.java
new file mode 100644
index 00000000000..839f28c263f
--- /dev/null
+++ b/src/test/java/seedu/heymatez/logic/parser/ParserUtilTest.java
@@ -0,0 +1,292 @@
+package seedu.heymatez.logic.parser;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static seedu.heymatez.logic.parser.ParserUtil.MESSAGE_INVALID_INDEX;
+import static seedu.heymatez.logic.parser.ParserUtil.MESSAGE_NON_POSITIVE_INDEX;
+import static seedu.heymatez.testutil.Assert.assertThrows;
+import static seedu.heymatez.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.heymatez.logic.parser.exceptions.ParseException;
+import seedu.heymatez.model.person.Email;
+import seedu.heymatez.model.person.Name;
+import seedu.heymatez.model.person.Phone;
+import seedu.heymatez.model.task.Deadline;
+import seedu.heymatez.model.task.Description;
+import seedu.heymatez.model.task.Priority;
+import seedu.heymatez.model.task.TaskStatus;
+import seedu.heymatez.model.task.Title;
+
+/**
+ * Contains unit tests for {@code ParserUtil}.
+ */
+public class ParserUtilTest {
+ private static final String INVALID_NAME = "R@chel";
+ private static final String INVALID_PHONE = "+651234";
+ private static final String INVALID_EMAIL = "example.com";
+ private static final String INVALID_TITLE = "";
+ private static final String INVALID_DESCRIPTION = "";
+ private static final String INVALID_DEADLINE = "25 Mar 2021";
+ private static final String INVALID_STATUS = "Uncompleted";
+ private static final String INVALID_PRIORITY = "Low";
+ private static final String INVALID_ASSIGNEE = "#rachel";
+
+ private static final String VALID_NAME = "Rachel Walker";
+ private static final String VALID_PHONE = "123456";
+ private static final String VALID_EMAIL = "rachel@example.com";
+ private static final String VALID_TITLE = "EXCO Meeting";
+ private static final String VALID_DESCRIPTION = "Meeting for hackathon";
+ private static final String VALID_DEADLINE = "2021-03-04";
+ private static final String VALID_STATUS = "uncompleted";
+ private static final String VALID_PRIORITY = "low";
+
+ private static final String WHITESPACE = " \t\r\n";
+
+ @Test
+ public void parseIndex_invalidInput_throwsParseException() {
+ assertThrows(ParseException.class, () -> ParserUtil.parseIndex("10 a"));
+
+ assertThrows(ParseException.class, () -> ParserUtil.parseIndex("abc"));
+
+ assertThrows(ParseException.class, () -> ParserUtil.parseIndex("a a a"));
+ }
+
+ @Test
+ public void parseIndex_outOfRangeInput_throwsParseException() {
+ assertThrows(ParseException.class, MESSAGE_NON_POSITIVE_INDEX, ()
+ -> ParserUtil.parseIndex(Long.toString(Integer.MAX_VALUE + 1)));
+ }
+
+ @Test
+ public void parseIndex_invalidIntegerInput_throwsParseException() {
+ assertThrows(ParseException.class, MESSAGE_NON_POSITIVE_INDEX, ()
+ -> ParserUtil.parseIndex("-1"));
+
+ assertThrows(ParseException.class, MESSAGE_NON_POSITIVE_INDEX, ()
+ -> ParserUtil.parseIndex("0"));
+ }
+
+ @Test
+ public void parseIndex_invalidIntegerWithPositiveSigns_throwsParseException() {
+ assertThrows(ParseException.class, MESSAGE_INVALID_INDEX, ()
+ -> ParserUtil.parseIndex(" +1 "));
+
+ assertThrows(ParseException.class, MESSAGE_INVALID_INDEX, ()
+ -> ParserUtil.parseIndex(" +3 "));
+
+ assertThrows(ParseException.class, MESSAGE_INVALID_INDEX, ()
+ -> ParserUtil.parseIndex("+2"));
+
+ assertThrows(ParseException.class, MESSAGE_INVALID_INDEX, ()
+ -> ParserUtil.parseIndex(" + 8 "));
+ }
+
+ @Test
+ public void parseIndex_validInput_success() throws Exception {
+ // No whitespaces
+ assertEquals(INDEX_FIRST_PERSON, ParserUtil.parseIndex("1"));
+
+ // Leading and trailing whitespaces
+ assertEquals(INDEX_FIRST_PERSON, ParserUtil.parseIndex(" 1 "));
+ }
+
+ @Test
+ public void parseName_null_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> ParserUtil.parseName((String) null));
+ }
+
+ @Test
+ public void parseName_invalidValue_throwsParseException() {
+ assertThrows(ParseException.class, () -> ParserUtil.parseName(INVALID_NAME));
+ }
+
+ @Test
+ public void parseName_validValueWithoutWhitespace_returnsName() throws Exception {
+ Name expectedName = new Name(VALID_NAME);
+ assertEquals(expectedName, ParserUtil.parseName(VALID_NAME));
+ }
+
+ @Test
+ public void parseName_validValueWithWhitespace_returnsTrimmedName() throws Exception {
+ String nameWithWhitespace = WHITESPACE + VALID_NAME + WHITESPACE;
+ Name expectedName = new Name(VALID_NAME);
+ assertEquals(expectedName, ParserUtil.parseName(nameWithWhitespace));
+ }
+
+ @Test
+ public void parsePhone_null_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> ParserUtil.parsePhone((String) null));
+ }
+
+ @Test
+ public void parsePhone_invalidValue_throwsParseException() {
+ assertThrows(ParseException.class, () -> ParserUtil.parsePhone(INVALID_PHONE));
+ }
+
+ @Test
+ public void parsePhone_validValueWithoutWhitespace_returnsPhone() throws Exception {
+ Phone expectedPhone = new Phone(VALID_PHONE);
+ assertEquals(expectedPhone, ParserUtil.parsePhone(VALID_PHONE));
+ }
+
+ @Test
+ public void parsePhone_validValueWithWhitespace_returnsTrimmedPhone() throws Exception {
+ String phoneWithWhitespace = WHITESPACE + VALID_PHONE + WHITESPACE;
+ Phone expectedPhone = new Phone(VALID_PHONE);
+ assertEquals(expectedPhone, ParserUtil.parsePhone(phoneWithWhitespace));
+ }
+
+ @Test
+ public void parseEmail_null_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> ParserUtil.parseEmail((String) null));
+ }
+
+ @Test
+ public void parseEmail_invalidValue_throwsParseException() {
+ assertThrows(ParseException.class, () -> ParserUtil.parseEmail(INVALID_EMAIL));
+ }
+
+ @Test
+ public void parseEmail_validValueWithoutWhitespace_returnsEmail() throws Exception {
+ Email expectedEmail = new Email(VALID_EMAIL);
+ assertEquals(expectedEmail, ParserUtil.parseEmail(VALID_EMAIL));
+ }
+
+ @Test
+ public void parseEmail_validValueWithWhitespace_returnsTrimmedEmail() throws Exception {
+ String emailWithWhitespace = WHITESPACE + VALID_EMAIL + WHITESPACE;
+ Email expectedEmail = new Email(VALID_EMAIL);
+ assertEquals(expectedEmail, ParserUtil.parseEmail(emailWithWhitespace));
+ }
+
+ @Test
+ public void parseTitle_null_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> ParserUtil.parseTitle((String) null));
+ }
+
+ @Test
+ public void parseTitle_invalidValue_throwsParseException() {
+ assertThrows(ParseException.class, () -> ParserUtil.parseTitle(INVALID_TITLE));
+ }
+
+ @Test
+ public void parseTitle_validValueWithoutWhitespace_returnsTitle() throws Exception {
+ Title expectedTitle = new Title(VALID_TITLE);
+ assertEquals(expectedTitle, ParserUtil.parseTitle(VALID_TITLE));
+ }
+
+ @Test
+ public void parseTitle_validValueWithWhitespace_returnsTrimmedTitle() throws Exception {
+ String titleWithWhitespace = WHITESPACE + VALID_TITLE + WHITESPACE;
+ Title expectedTitle = new Title(VALID_TITLE);
+ assertEquals(expectedTitle, ParserUtil.parseTitle(titleWithWhitespace));
+ }
+
+ @Test
+ public void parseDescription_null_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> ParserUtil.parseDescription((String) null));
+ }
+
+ @Test
+ public void parseDescription_invalidValue_throwsParseException() {
+ assertThrows(ParseException.class, () -> ParserUtil.parseDescription(INVALID_DESCRIPTION));
+ }
+
+ @Test
+ public void parseDescription_validValueWithoutWhitespace_returnsDescription() throws Exception {
+ Description expectedDescription = new Description(VALID_DESCRIPTION);
+ assertEquals(expectedDescription, ParserUtil.parseDescription(VALID_DESCRIPTION));
+ }
+
+ @Test
+ public void parseDescription_validValueWithWhitespace_returnsTrimmedDescription() throws Exception {
+ String descriptionWithWhitespace = WHITESPACE + VALID_DESCRIPTION + WHITESPACE;
+ Description expectedDescription = new Description(VALID_DESCRIPTION);
+ assertEquals(expectedDescription, ParserUtil.parseDescription(descriptionWithWhitespace));
+ }
+
+ @Test
+ public void parseDeadline_null_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> ParserUtil.parseDeadline((String) null));
+ }
+
+ @Test
+ public void parseDeadline_invalidValue_throwsParseException() {
+ assertThrows(ParseException.class, () -> ParserUtil.parseDeadline(INVALID_DEADLINE));
+ }
+
+ @Test
+ public void parseDeadline_validValueWithoutWhitespace_returnsDeadline() throws Exception {
+ Deadline expectedDeadline = new Deadline(VALID_DEADLINE);
+ assertEquals(expectedDeadline, ParserUtil.parseDeadline(VALID_DEADLINE));
+ }
+
+ @Test
+ public void parseDeadline_validValueWithWhitespace_returnsTrimmedDeadline() throws Exception {
+ String deadlineWithWhitespace = WHITESPACE + VALID_DEADLINE + WHITESPACE;
+ Deadline expectedDeadline = new Deadline(VALID_DEADLINE);
+ assertEquals(expectedDeadline, ParserUtil.parseDeadline(deadlineWithWhitespace));
+ }
+
+ @Test
+ public void parseStatus_null_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> ParserUtil.parseStatus((String) null));
+ }
+
+ @Test
+ public void parseStatus_invalidValue_throwsParseException() {
+ assertThrows(ParseException.class, () -> ParserUtil.parseStatus(INVALID_STATUS));
+ }
+
+ @Test
+ public void parseStatus_validValueWithoutWhitespace_returnsStatus() throws Exception {
+ TaskStatus expectedStatus = TaskStatus.valueOf(VALID_STATUS.toUpperCase());
+ assertEquals(expectedStatus, ParserUtil.parseStatus(VALID_STATUS));
+ }
+
+ @Test
+ public void parseStatus_validValueWithWhitespace_returnsTrimmedStatus() throws Exception {
+ String statusWithWhiteSpace = WHITESPACE + VALID_STATUS + WHITESPACE;
+ TaskStatus expectedStatus = TaskStatus.valueOf(VALID_STATUS.toUpperCase());
+ assertEquals(expectedStatus, ParserUtil.parseStatus(statusWithWhiteSpace));
+ }
+
+ @Test
+ public void parsePriority_null_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> ParserUtil.parsePriority((String) null));
+ }
+
+ @Test
+ public void parsePriority_invalidValue_throwsParseException() {
+ assertThrows(ParseException.class, () -> ParserUtil.parsePriority(INVALID_PRIORITY));
+ }
+
+ @Test
+ public void parsePriority_validValueWithoutWhitespace_returnsPriority() throws Exception {
+ Priority expectedPriority = Priority.valueOf(VALID_PRIORITY.toUpperCase());
+ assertEquals(expectedPriority, ParserUtil.parsePriority(VALID_PRIORITY));
+ }
+
+ @Test
+ public void parsePriority_validValueWithWhitespace_returnsTrimmedPriority() throws Exception {
+ String priorityWithWhiteSpace = WHITESPACE + VALID_PRIORITY + WHITESPACE;
+ Priority expectedPriority = Priority.valueOf(VALID_PRIORITY.toUpperCase());
+ assertEquals(expectedPriority, ParserUtil.parsePriority(priorityWithWhiteSpace));
+ }
+
+ @Test
+ public void parseAssignee_null_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> ParserUtil.parseAssignee(null));
+ }
+
+ @Test
+ public void parseAssignee_invalidValue_throwsParseException() {
+ assertThrows(ParseException.class, () -> ParserUtil.parseAssignee(INVALID_ASSIGNEE));
+ }
+
+ @Test
+ public void parseAssignees_null_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> ParserUtil.parseAssignees(null));
+ }
+}
diff --git a/src/test/java/seedu/heymatez/logic/parser/UndoTaskParserCommandTest.java b/src/test/java/seedu/heymatez/logic/parser/UndoTaskParserCommandTest.java
new file mode 100644
index 00000000000..641c33b9278
--- /dev/null
+++ b/src/test/java/seedu/heymatez/logic/parser/UndoTaskParserCommandTest.java
@@ -0,0 +1,44 @@
+package seedu.heymatez.logic.parser;
+
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.heymatez.commons.core.Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX;
+import static seedu.heymatez.logic.parser.CommandParserTestUtil.assertParseFailure;
+import static seedu.heymatez.logic.parser.CommandParserTestUtil.assertParseSuccess;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.heymatez.logic.commands.UndoTaskCommand;
+import seedu.heymatez.logic.parser.exceptions.ParseException;
+
+/**
+ * Contains unit tests for {@code UndoTaskCommandParser}.
+ */
+public class UndoTaskParserCommandTest {
+
+ private UndoTaskCommandParser parser = new UndoTaskCommandParser();
+
+ @Test
+ public void parse_validArgs_returnsUndoTaskCommand() throws ParseException {
+ assertParseSuccess(parser, "1", new UndoTaskCommand(ParserUtil.parseIndex("1")));
+ }
+
+ @Test
+ public void parse_invalidArgs_throwsParseException() {
+ assertParseFailure(parser, " ", String.format(MESSAGE_INVALID_COMMAND_FORMAT,
+ UndoTaskCommand.MESSAGE_USAGE));
+
+ assertParseFailure(parser, "1 2", String.format(MESSAGE_INVALID_COMMAND_FORMAT,
+ UndoTaskCommand.MESSAGE_USAGE));
+
+ assertParseFailure(parser, "1, 2 ", String.format(MESSAGE_INVALID_COMMAND_FORMAT,
+ UndoTaskCommand.MESSAGE_USAGE));
+ }
+
+ @Test
+ public void parse_invalidInteger_throwsParseException() {
+ assertParseFailure(parser, "0", MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+
+ assertParseFailure(parser, "-1", MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+
+ }
+}
diff --git a/src/test/java/seedu/heymatez/model/HeyMatezTest.java b/src/test/java/seedu/heymatez/model/HeyMatezTest.java
new file mode 100644
index 00000000000..63be84519d1
--- /dev/null
+++ b/src/test/java/seedu/heymatez/model/HeyMatezTest.java
@@ -0,0 +1,111 @@
+package seedu.heymatez.model;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.heymatez.testutil.Assert.assertThrows;
+import static seedu.heymatez.testutil.TypicalPersons.ALICE;
+import static seedu.heymatez.testutil.TypicalPersons.getTypicalHeyMatez;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
+import seedu.heymatez.model.person.Person;
+import seedu.heymatez.model.person.exceptions.DuplicatePersonException;
+import seedu.heymatez.model.task.Deadline;
+import seedu.heymatez.model.task.Description;
+import seedu.heymatez.model.task.Task;
+import seedu.heymatez.model.task.Title;
+import seedu.heymatez.testutil.PersonBuilder;
+import seedu.heymatez.testutil.TaskBuilder;
+
+public class HeyMatezTest {
+
+ private final HeyMatez heyMatez = new HeyMatez();
+
+ @Test
+ public void constructor() {
+ assertEquals(Collections.emptyList(), heyMatez.getPersonList());
+ }
+
+ @Test
+ public void resetData_null_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> heyMatez.resetData(null));
+ }
+
+ @Test
+ public void resetData_withValidReadOnlyHeyMatez_replacesData() {
+ HeyMatez newData = getTypicalHeyMatez();
+ heyMatez.resetData(newData);
+ assertEquals(newData, heyMatez);
+ }
+
+ @Test
+ public void resetData_withDuplicatePersons_throwsDuplicatePersonException() {
+ // Two persons with the same identity fields
+ Person editedAlice = new PersonBuilder(ALICE).build();
+ Task dummyTask = new TaskBuilder(new Task(new Title("Task1"), new Description("Some Description"),
+ new Deadline("2021-04-04"))).build();
+ List newPersons = Arrays.asList(ALICE, editedAlice);
+ List tasks = Arrays.asList(dummyTask);
+ HeyMatezStub newData = new HeyMatezStub(newPersons, tasks);
+
+ assertThrows(DuplicatePersonException.class, () -> heyMatez.resetData(newData));
+ }
+
+ @Test
+ public void hasPerson_nullPerson_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> heyMatez.hasPerson(null));
+ }
+
+ @Test
+ public void hasPerson_personNotInHeyMatez_returnsFalse() {
+ assertFalse(heyMatez.hasPerson(ALICE));
+ }
+
+ @Test
+ public void hasPerson_personInHeyMatez_returnsTrue() {
+ heyMatez.addPerson(ALICE);
+ assertTrue(heyMatez.hasPerson(ALICE));
+ }
+
+ @Test
+ public void hasPerson_personWithSameIdentityFieldsInHeyMatez_returnsTrue() {
+ heyMatez.addPerson(ALICE);
+ Person editedAlice = new PersonBuilder(ALICE).build();
+ assertTrue(heyMatez.hasPerson(editedAlice));
+ }
+
+ @Test
+ public void getPersonList_modifyList_throwsUnsupportedOperationException() {
+ assertThrows(UnsupportedOperationException.class, () -> heyMatez.getPersonList().remove(0));
+ }
+
+ /**
+ * A stub ReadOnlyAddressBook whose persons list can violate interface constraints.
+ */
+ private static class HeyMatezStub implements ReadOnlyHeyMatez {
+ private final ObservableList persons = FXCollections.observableArrayList();
+ private final ObservableList tasks = FXCollections.observableArrayList();
+
+ HeyMatezStub(Collection persons, Collection