From bc3ac9b9e5e64c26aae1a9a94d305f26c683c7cb Mon Sep 17 00:00:00 2001 From: mingyuanc Date: Thu, 26 Oct 2023 00:26:51 +0800 Subject: [PATCH 1/7] Refactor state to model --- docs/DeveloperGuide.md | 221 +++++++++++------- docs/team/nereuswb922.md | 42 ++-- src/main/java/seedu/address/MainApp.java | 19 +- .../seedu/address/logic/LogicManager.java | 24 +- .../commands/ChangeDirectoryCommand.java | 11 +- .../seedu/address/logic/commands/Command.java | 4 +- .../logic/commands/CreateDeadlineCommand.java | 24 +- .../logic/commands/CreateGroupCommand.java | 14 +- .../logic/commands/CreateStudentCommand.java | 14 +- .../logic/commands/CreateTodoCommand.java | 30 +-- .../DeleteForStudentsAndGroupsCommand.java | 29 +-- .../logic/commands/DeleteTaskCommand.java | 16 +- .../address/logic/commands/EditCommand.java | 24 +- .../address/logic/commands/HelpCommand.java | 6 +- .../address/logic/commands/MarkCommand.java | 22 +- .../commands/MoveStudentToGroupCommand.java | 20 +- .../commands/ShowChildrenListCommand.java | 31 ++- .../logic/commands/ShowTaskListCommand.java | 33 ++- .../address/logic/commands/UnmarkCommand.java | 22 +- .../{statemanager => }/ChildOperation.java | 4 +- .../{statemanager => }/IChildOperation.java | 4 +- .../{statemanager => }/ITaskOperations.java | 7 +- .../{statemanager/State.java => Model.java} | 71 +++--- .../StateManager.java => ModelManager.java} | 20 +- .../{statemanager => }/TaskOperation.java | 2 +- .../address/model/path/AbsolutePath.java | 10 +- .../UnsupportedPathOperationException.java | 2 +- .../logic/commands/CommandTestUtil.java | 44 ++-- .../commands/CreateDeadlineCommandTest.java | 45 ++-- .../commands/CreateGroupCommandTest.java | 12 +- .../commands/CreateStudentCommandTest.java | 27 ++- .../logic/commands/CreateTodoCommandTest.java | 30 +-- ...DeleteForStudentsAndGroupsCommandTest.java | 49 ++-- .../logic/commands/DeleteTaskCommandTest.java | 45 ++-- .../logic/commands/EditCommandTest.java | 16 +- .../logic/commands/HelpCommandTest.java | 8 +- .../logic/commands/MarkCommandTest.java | 45 ++-- .../MoveStudentToGroupCommandTest.java | 8 +- .../logic/commands/UnmarkCommandTest.java | 45 ++-- .../statemanager/ChildOperationTest.java | 28 +-- .../statemanager/TaskOperationTest.java | 24 +- 41 files changed, 614 insertions(+), 538 deletions(-) rename src/main/java/seedu/address/model/{statemanager => }/ChildOperation.java (98%) rename src/main/java/seedu/address/model/{statemanager => }/IChildOperation.java (95%) rename src/main/java/seedu/address/model/{statemanager => }/ITaskOperations.java (95%) rename src/main/java/seedu/address/model/{statemanager/State.java => Model.java} (65%) rename src/main/java/seedu/address/model/{statemanager/StateManager.java => ModelManager.java} (94%) rename src/main/java/seedu/address/model/{statemanager => }/TaskOperation.java (98%) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 5843abf2d8e..90a3dc35993 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -1,7 +1,7 @@ --- - layout: default.md - title: "Developer Guide" - pageNav: 3 +layout: default.md +title: "Developer Guide" +pageNav: 3 --- # ProfBook Developer Guide @@ -13,7 +13,8 @@ ## **Acknowledgements** -_{ list here sources of all reused/adapted ideas, code, documentation, and third-party libraries -- include links to the original source as well }_ +_{ list here sources of all reused/adapted ideas, code, documentation, and third-party libraries -- include links to the +original source as well }_ -------------------------------------------------------------------------------------------------------------------- @@ -35,7 +36,11 @@ Given below is a quick overview of main components and how they interact with ea **Main components of the architecture** -**`Main`** (consisting of classes [`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)) is in charge of the app launch and shut down. +**`Main`** (consisting of +classes [`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)) is +in charge of the app launch and shut down. + * At app launch, it initializes the other components in the correct sequence, and connects them up with each other. * At shut down, it shuts down the other components and invokes cleanup methods where necessary. @@ -50,16 +55,21 @@ The bulk of the app's work is done by the following four components: **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 `delete 1`. Each of the four main components (also shown in the diagram above), * defines its *API* in an `interface` with the same name as the Component. -* implements its functionality using a concrete `{Component Name}Manager` class (which follows the corresponding API `interface` mentioned in the previous point. +* implements its functionality using a concrete `{Component Name}Manager` class (which follows the corresponding + API `interface` mentioned in the previous point. -For example, the `Logic` component defines its API in the `Logic.java` interface and implements its functionality using the `LogicManager.java` class which follows the `Logic` interface. Other components interact with a given component through its interface rather than the concrete class (reason: to prevent outside component's being coupled to the implementation of a component), as illustrated in the (partial) class diagram below. +For example, the `Logic` component defines its API in the `Logic.java` interface and implements its functionality using +the `LogicManager.java` class which follows the `Logic` interface. Other components interact with a given component +through its interface rather than the concrete class (reason: to prevent outside component's being coupled to the +implementation of a component), as illustrated in the (partial) class diagram below. @@ -67,13 +77,21 @@ The sections below give more details of each component. ### UI component -The **API** of this component is specified in [`Ui.java`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/ui/Ui.java) +The **API** of this component is specified +in [`Ui.java`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/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 which captures the commonalities between classes that represent parts of the visible GUI. +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 which captures the commonalities between classes that represent parts of the +visible GUI. -The `UI` component uses the 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 the 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, @@ -84,25 +102,30 @@ The `UI` component, ### Logic component -**API** : [`Logic.java`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/logic/Logic.java) +**API +** : [`Logic.java`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/logic/Logic.java) Here's a (partial) class diagram of the `Logic` component: -The sequence diagram below illustrates the interactions within the `Logic` component, taking `execute("delete 1")` API call as an example. +The sequence diagram below illustrates the interactions within the `Logic` component, taking `execute("delete 1")` API +call as an example. -**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. +**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. How the `Logic` component works: -1. When `Logic` is called upon to execute a command, it is passed to an `AddressBookParser` object which in turn creates a parser that matches the command (e.g., `DeleteCommandParser`) and uses it to parse the command. -1. This results in a `Command` object (more precisely, an object of one of its subclasses e.g., `DeleteCommand`) which is executed by the `LogicManager`. +1. When `Logic` is called upon to execute a command, it is passed to an `AddressBookParser` object which in turn creates + a parser that matches the command (e.g., `DeleteCommandParser`) and uses it to parse the command. +1. This results in a `Command` object (more precisely, an object of one of its subclasses e.g., `DeleteCommand`) which + is executed by the `LogicManager`. 1. The command can communicate with the `Model` when it is executed (e.g. to delete a person). 1. The result of the command execution is encapsulated as a `CommandResult` object which is returned back from `Logic`. @@ -111,11 +134,18 @@ Here are the other classes in `Logic` (omitted from the class diagram above) tha How the parsing works: -* When called upon to parse a user command, the `AddressBookParser` class creates an `XYZCommandParser` (`XYZ` is a placeholder for the specific command name e.g., `AddCommandParser`) which uses the other classes shown above to parse the user command and create a `XYZCommand` object (e.g., `AddCommand`) which the `AddressBookParser` returns back as a `Command` object. -* All `XYZCommandParser` classes (e.g., `AddCommandParser`, `DeleteCommandParser`, ...) inherit from the `Parser` interface so that they can be treated similarly where possible e.g, during testing. + +* When called upon to parse a user command, the `AddressBookParser` class creates an `XYZCommandParser` (`XYZ` is a + placeholder for the specific command name e.g., `AddCommandParser`) which uses the other classes shown above to parse + the user command and create a `XYZCommand` object (e.g., `AddCommand`) which the `AddressBookParser` returns back as + a `Command` object. +* All `XYZCommandParser` classes (e.g., `AddCommandParser`, `DeleteCommandParser`, ...) inherit from the `Parser` + interface so that they can be treated similarly where possible e.g, during testing. ### 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/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/model/Model.java) @@ -123,29 +153,39 @@ How the parsing works: The `Model` component, * stores the address book data i.e., all `Person` objects (which are contained in a `UniquePersonList` object). -* stores the currently 'selected' `Person` objects (e.g., results of a search query) as a separate _filtered_ list which is exposed to outsiders as 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 a `UserPref` object that represents the user’s preferences. This is exposed to the outside as a `ReadOnlyUserPref` objects. -* does not depend on any of the other three components (as the `Model` represents data entities of the domain, they should make sense on their own without depending on other components) +* stores the currently 'selected' `Person` objects (e.g., results of a search query) as a separate _filtered_ list which + is exposed to outsiders as 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 a `UserPref` object that represents the user’s preferences. This is exposed to the outside as + a `ReadOnlyUserPref` objects. +* does not depend on any of the other three components (as the `Model` represents data entities of the domain, they + should make sense on their own without depending on other components) -**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` objects.
+**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` objects.
- ### 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/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/storage/Storage.java) The `Storage` component, -* can save both address book data and user preference data in JSON format, and read them back into corresponding objects. -* inherits from both `AddressBookStorage` and `UserPrefStorage`, which means it can be treated as either one (if only the functionality of only one is needed). -* depends on some classes in the `Model` component (because the `Storage` component's job is to save/retrieve objects that belong to the `Model`) + +* can save both address book data and user preference data in JSON format, and read them back into corresponding + objects. +* inherits from both `AddressBookStorage` and `UserPrefStorage`, which means it can be treated as either one (if only + the functionality of only one is needed). +* depends on some classes in the `Model` component (because the `Storage` component's job is to save/retrieve objects + that belong to the `Model`) ### Common classes @@ -161,42 +201,56 @@ This section describes some noteworthy details on how certain features are imple #### Proposed Implementation -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 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: -* `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. +* `VersionedAddressBook#commit()`— Saves the current address book model in its history. +* `VersionedAddressBook#undo()`— Restores the previous address book model from its history. +* `VersionedAddressBook#redo()`— Restores a previously undone address book model from its history. -These operations are exposed in the `Model` interface as `Model#commitAddressBook()`, `Model#undoAddressBook()` and `Model#redoAddressBook()` respectively. +These operations are exposed in the `Model` interface as `Model#commitAddressBook()`, `Model#undoAddressBook()` +and `Model#redoAddressBook()` respectively. Given below is an example usage scenario and how the undo/redo mechanism behaves at each step. -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. +Step 1. The user launches the application for the first time. The `VersionedAddressBook` will be initialized with the +initial address book model, and the `currentStatePointer` pointing to that single address book model. -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 user executes `delete 5` command to delete the 5th person in the address book. The `delete` command +calls `Model#commitAddressBook()`, causing the modified model 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 +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 3. The user executes `add n/David …​` to add a new person. The `add` command also +calls `Model#commitAddressBook()`, causing another modified address book model to be saved into +the `addressBookStateList`. -**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`. +**Note:** If a command fails its execution, it will not call `Model#commitAddressBook()`, so the address book model will +not be saved into the `addressBookStateList`. -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. +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 model, and restores the address book to that model. -**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 +**Note:** If the `currentStatePointer` is at index 0, pointing to the initial AddressBook model, 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. @@ -207,23 +261,32 @@ The following sequence diagram shows how the undo operation works: -**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. +**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. -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. +The `redo` command does the opposite — it calls `Model#redoAddressBook()`, which shifts the `currentStatePointer` once +to the right, pointing to the previously undone model, and restores the address book to that model. -**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. +**Note:** If the `currentStatePointer` is at index `addressBookStateList.size() - 1`, pointing to the latest address +book model, 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. -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. +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. -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. +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. @@ -236,13 +299,13 @@ The following activity diagram summarizes what happens when a user executes a ne **Aspect: How undo & redo executes:** * **Alternative 1 (current choice):** Saves the entire address book. - * Pros: Easy to implement. - * Cons: May have performance issues in terms of memory usage. + * Pros: Easy to implement. + * Cons: May have performance issues in terms of memory usage. * **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. + * 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. _{more aspects and alternatives to be added}_ @@ -276,10 +339,8 @@ _{Explain here how the data archiving feature will be implemented}_ * can type fast * prefers typing to mouse interactions -**Value proposition**: Keep track of tutorial groups and students deadlines and tasks efficiently with an interface that will be faster than a typical mouse/GUI driven app - - - +**Value proposition**: Keep track of tutorial groups and students deadlines and tasks efficiently with an interface that +will be faster than a typical mouse/GUI driven app ### User stories @@ -292,7 +353,7 @@ Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unli | `* * *` | new user | delete a student | remove students that I no longer need | | `* * *` | new user | create deadlines for student | keep track of when assignments are due | | `* * *` | new user | create todo task for student | keep track of which label they are at | - | `* * *` | new user | create deadline for a group | keep track of when group specific assignments are due | +| `* * *` | new user | create deadline for a group | keep track of when group specific assignments are due | | `* * *` | new user | create todo for a group | keep track of the progress of each group relative to others | | `* * *` | new user | create deadline for a tutorial group | keep track of when tutorial specific assignments are due | | `* * *` | new user | create todo tasks for a tutorial group | keep track of the progress of each tutorial group relative to others | @@ -328,7 +389,8 @@ Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unli ### Use cases -(For all use cases below, the **System** is the `ProfBook` and the **Professor** is the `user`, unless specified otherwise) +(For all use cases below, the **System** is the `ProfBook` and the **Professor** is the `user`, unless specified +otherwise) **Use case: Delete a person** @@ -337,7 +399,7 @@ Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unli 1. User requests to delete a student/group/task with specific id for each one 2. AddressBook deletes the person - Use case ends. + Use case ends. **Extensions** @@ -346,23 +408,22 @@ Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unli * 2a1. ProfBook shows an error message. Use case resumes at step 1. - **Use case: Move student into/out of group** **MSS** -1. User requests to move a specific student from a source group to destination group with an id -2. AddressBook moves the student from a source group to destination group - - Use case ends. +1. User requests to move a specific student from a source group to destination group with an id +2. AddressBook moves the student from a source group to destination group + + Use case ends. **Extensions** * 2a. The given StudentID is invalid. - * 2a1. ProfBook shows an error message. - - Use case resumes at step 1. + * 2a1. ProfBook shows an error message. + + Use case resumes at step 1. * 3a. The given groupID is invalid. @@ -375,9 +436,11 @@ Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unli ### Non-Functional Requirements -1. The application should be platform-independent and should run on all major operating systems 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. +1. The application should be platform-independent and should run on all major operating systems 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. *{More to be added}* @@ -404,15 +467,16 @@ testers are expected to do more *exploratory* testing. 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. + 1. Double-click the jar file Expected: Shows the GUI with a set of sample contacts. The window size may not be + optimum. 1. Saving window preferences - 1. Resize the window to an optimum size. Move the window to a different location. Close the window. + 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.
+ 1. Re-launch the app by double-clicking the jar file.
Expected: The most recent window size and location is retained. 1. _{ more test cases …​ }_ @@ -421,16 +485,17 @@ testers are expected to do more *exploratory* testing. 1. Deleting a person while all persons are being shown - 1. Prerequisites: List all persons using the `list` command. Multiple persons in the list. + 1. Prerequisites: List all persons using the `list` command. Multiple persons in the 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. + 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. - 1. Test case: `delete 0`
- Expected: No person is deleted. Error details shown in the status message. Status bar remains the same. + 1. Test case: `delete 0`
+ Expected: No person is deleted. Error details shown in the status message. Status bar remains the same. - 1. Other incorrect delete commands to try: `delete`, `delete x`, `...` (where x is larger than the list size)
- Expected: Similar to previous. + 1. Other incorrect delete commands to try: `delete`, `delete x`, `...` (where x is larger than the list size)
+ Expected: Similar to previous. 1. _{ more test cases …​ }_ @@ -438,6 +503,6 @@ testers are expected to do more *exploratory* testing. 1. Dealing with missing/corrupted data files - 1. _{explain how to simulate a missing/corrupted file, and the expected behavior}_ + 1. _{explain how to simulate a missing/corrupted file, and the expected behavior}_ 1. _{ more test cases …​ }_ diff --git a/docs/team/nereuswb922.md b/docs/team/nereuswb922.md index 23871fe79c5..82e0bc72e8c 100644 --- a/docs/team/nereuswb922.md +++ b/docs/team/nereuswb922.md @@ -5,29 +5,34 @@ title: Nereus Ng Wei Bin's Project Portfolio Page # ProfBook -ProfBook is a desktop address book application used for easy management of tasks, group schedules, and notes for every tutorial slot and group. 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. +ProfBook is a desktop address book application used for easy management of tasks, group schedules, and notes for every +tutorial slot and group. 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. ## RepoSense Report -**Link to my RepoSense Report**: [Code Contributions](https://nus-cs2103-ay2324s1.github.io/tp-dashboard/?search=nereuswb922&breakdown=false&sort=groupTitle%20dsc&sortWithin=title&since=2023-09-22&timeframe=commit&mergegroup=&groupSelect=groupByRepos). +**Link to my RepoSense Report +**: [Code Contributions](https://nus-cs2103-ay2324s1.github.io/tp-dashboard/?search=nereuswb922&breakdown=false&sort=groupTitle%20dsc&sortWithin=title&since=2023-09-22&timeframe=commit&mergegroup=&groupSelect=groupByRepos). ## Code Contributions -In this section, I will outline the code contributions I made to the project. These contributions include enhancements and new features that I implemented. +In this section, I will outline the code contributions I made to the project. These contributions include enhancements +and new features that I implemented. ### Class Enhancements 1. **Introduced `Path` Class :** - Provided a structured way to manage and manipulate paths in our application. - - This addition assists other classes (e.g. `StateManager`, `Command`) in providing functionality such as navigating between directories and executing commands against specific paths. - - The `AbsolutePath` class represents a full path within our application. + - This addition assists other classes (e.g. `StateManager`, `Command`) in providing functionality such as navigating + between directories and executing commands against specific paths. + - The `AbsolutePath` class represents a full path within our application. - The `RelativePath` class represents a relative path in relation to the current path. 2. **Introduced `Id` class :** - - Represent unique id of group and student. + - Represent unique id of group and student. 2. **Introduced `Option` class :** - - Similar to the `Prefix` class in AB3. + - Similar to the `Prefix` class in AB3. - Enables the creation of command options with short-hand and long-hand names. 3. **Updated `ArgumentTokernizer` class :** @@ -35,6 +40,7 @@ In this section, I will outline the code contributions I made to the project. Th - e.g. User can pass in name option using `--name` or `-n`. ### New Features + 1. **`cd` Command :** - The `cd` command allows users to navigate between different directories. - For example, using `cd ../grp-001` will navigate to the `grp-001` directory. @@ -48,32 +54,38 @@ In this section, I will outline the code contributions I made to the project. Th - For example, `cat grp-001/stu-001` will show the task list of the student with ID `stu-001`. ### GUI Enhancements + 1. **Visual Improvements**: -Added a new icon and expanded the color palette to enhance the project's visual appeal. + Added a new icon and expanded the color palette to enhance the project's visual appeal. 2. **Current Directory Display**: -Added a working directory display, similar to a terminal, simplifying navigation and enhancing users' understanding of the application's state. + Added a working directory display, similar to a terminal, simplifying navigation and enhancing users' understanding + of the application's model. ## User Guide Contributions + coming soon ## Developer Guide Contributions + coming soon ## Team-Based Task Contributions 1. **Github Setup**: - - Established our team's **organization** and **repo** on GitHub. - - Setup **GitHub project** to manage issues related to user stories and tasks. - - Setup project **website deployment**. + - Established our team's **organization** and **repo** on GitHub. + - Setup **GitHub project** to manage issues related to user stories and tasks. + - Setup project **website deployment**. 3. **Integration of GitHub Plugins**: - - **Netifly :** Enables automatic deployments of our PR previews. - - **Codecov :** Automate code coverage assessment, ensuring that our project maintains high code quality and identifying areas for improvement. - + - **Netifly :** Enables automatic deployments of our PR previews. + - **Codecov :** Automate code coverage assessment, ensuring that our project maintains high code quality and + identifying areas for improvement. + ## Review and Mentoring Contributions Here are the pull requests I reviewed and provided valuable feedback and suggestions: + - **[Pull Request #71](https://github.com/AY2324S1-CS2103T-W15-2/tp/pull/71)** - **[Pull Request #91](https://github.com/AY2324S1-CS2103T-W15-2/tp/pull/91)** - **[Pull Request #100](https://github.com/AY2324S1-CS2103T-W15-2/tp/pull/100)** diff --git a/src/main/java/seedu/address/MainApp.java b/src/main/java/seedu/address/MainApp.java index c83fd98c71a..65fb2e06620 100644 --- a/src/main/java/seedu/address/MainApp.java +++ b/src/main/java/seedu/address/MainApp.java @@ -15,13 +15,13 @@ import seedu.address.commons.util.StringUtil; import seedu.address.logic.Logic; import seedu.address.logic.LogicManager; +import seedu.address.model.Model; +import seedu.address.model.ModelManager; import seedu.address.model.ReadOnlyUserPrefs; import seedu.address.model.UserPrefs; import seedu.address.model.path.AbsolutePath; import seedu.address.model.path.exceptions.InvalidPathException; import seedu.address.model.profbook.Root; -import seedu.address.model.statemanager.State; -import seedu.address.model.statemanager.StateManager; import seedu.address.model.util.SampleProfBook; import seedu.address.storage.JsonProfBookStorage; import seedu.address.storage.JsonUserPrefsStorage; @@ -43,7 +43,7 @@ public class MainApp extends Application { protected Ui ui; protected Logic logic; protected ProfBookStorage storage; - protected State state; + protected Model model; protected Config config; @Override @@ -60,8 +60,8 @@ public void init() throws Exception { ProfBookStorage profBookStorage = new JsonProfBookStorage(userPrefs.getProfBookFilePath()); storage = new ProfBookStorageManager(profBookStorage, userPrefsStorage); - state = initModelManager(userPrefs); - logic = new LogicManager(state, storage); + model = initModelManager(userPrefs); + logic = new LogicManager(model, storage); ui = new UiManager(logic); } @@ -70,7 +70,7 @@ public void init() throws Exception { * 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. */ - private State initModelManager(ReadOnlyUserPrefs userPrefs) throws InvalidPathException { + private Model initModelManager(ReadOnlyUserPrefs userPrefs) throws InvalidPathException { logger.info("Using data file : " + storage.getProfBookFilePath()); Optional profBookOptional; Root initialData; @@ -91,7 +91,7 @@ private State initModelManager(ReadOnlyUserPrefs userPrefs) throws InvalidPathEx } AbsolutePath currentPath = new AbsolutePath("~/"); - return new StateManager(currentPath, initialData, userPrefs); + return new ModelManager(currentPath, initialData, userPrefs); } private void initLogging(Config config) { @@ -167,6 +167,7 @@ protected UserPrefs initPrefs(UserPrefsStorage storage) { return initializedPrefs; } + @Override public void start(Stage primaryStage) { logger.info("Starting AddressBook " + MainApp.VERSION); @@ -177,8 +178,8 @@ public void start(Stage primaryStage) { public void stop() { logger.info("============================ [ Stopping Address Book ] ============================="); try { - storage.saveUserPrefs(state.getUserPrefs()); - storage.saveProfBook(state.getRoot()); + storage.saveUserPrefs(model.getUserPrefs()); + storage.saveProfBook(model.getRoot()); } catch (IOException e) { logger.severe("Failed to save preferences/ProfBook " + StringUtil.getDetails(e)); } diff --git a/src/main/java/seedu/address/logic/LogicManager.java b/src/main/java/seedu/address/logic/LogicManager.java index eab2f1bf2a8..d29d16e8496 100644 --- a/src/main/java/seedu/address/logic/LogicManager.java +++ b/src/main/java/seedu/address/logic/LogicManager.java @@ -13,7 +13,7 @@ import seedu.address.logic.commands.exceptions.CommandException; import seedu.address.logic.parser.ProfBookParser; import seedu.address.logic.parser.exceptions.ParseException; -import seedu.address.model.statemanager.State; +import seedu.address.model.Model; import seedu.address.storage.ProfBookStorage; import seedu.address.ui.Displayable; @@ -28,7 +28,7 @@ public class LogicManager implements Logic { private final Logger logger = LogsCenter.getLogger(LogicManager.class); - private final State state; + private final Model model; private final ProfBookStorage storage; private final ProfBookParser profBookParser; @@ -36,10 +36,10 @@ public class LogicManager implements Logic { /** * Constructs a {@code LogicManager} with the given {@code Model} and {@code Storage}. */ - public LogicManager(State state, ProfBookStorage storage) { + public LogicManager(Model model, ProfBookStorage storage) { //todo : storage; this.storage = storage; - this.state = state; + this.model = model; profBookParser = new ProfBookParser(); } @@ -48,11 +48,11 @@ public CommandResult execute(String commandText) throws CommandException, ParseE logger.info("----------------[USER COMMAND][" + commandText + "]"); CommandResult commandResult; - Command command = profBookParser.parseCommand(commandText, state.getCurrPath()); - commandResult = command.execute(state); + Command command = profBookParser.parseCommand(commandText, model.getCurrPath()); + commandResult = command.execute(model); try { - storage.saveProfBook(state.getRoot()); + storage.saveProfBook(model.getRoot()); } catch (AccessDeniedException e) { throw new CommandException(String.format(FILE_OPS_PERMISSION_ERROR_FORMAT, e.getMessage()), e); } catch (IOException ioe) { @@ -64,26 +64,26 @@ public CommandResult execute(String commandText) throws CommandException, ParseE @Override public ObservableList getDisplayList() { - return state.getDisplayList(); + return model.getDisplayList(); } @Override public String getCurrPath() { - return state.getCurrPath().toString(); + return model.getCurrPath().toString(); } @Override public Path getAddressBookFilePath() { - return state.getProfBookFilePath(); + return model.getProfBookFilePath(); } @Override public GuiSettings getGuiSettings() { - return state.getGuiSettings(); + return model.getGuiSettings(); } @Override public void setGuiSettings(GuiSettings guiSettings) { - state.setGuiSettings(guiSettings); + model.setGuiSettings(guiSettings); } } diff --git a/src/main/java/seedu/address/logic/commands/ChangeDirectoryCommand.java b/src/main/java/seedu/address/logic/commands/ChangeDirectoryCommand.java index bef23a8287a..9336cbb8ddb 100644 --- a/src/main/java/seedu/address/logic/commands/ChangeDirectoryCommand.java +++ b/src/main/java/seedu/address/logic/commands/ChangeDirectoryCommand.java @@ -4,8 +4,9 @@ import seedu.address.commons.util.ToStringBuilder; import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.model.Model; import seedu.address.model.path.AbsolutePath; -import seedu.address.model.statemanager.State; + /** * Change directory to target path. @@ -39,8 +40,8 @@ public ChangeDirectoryCommand(AbsolutePath dest) { * @throws CommandException If an error occurs during command execution. */ @Override - public CommandResult execute(State state) throws CommandException { - if (!state.hasPath(dest)) { + public CommandResult execute(Model model) throws CommandException { + if (!model.hasPath(dest)) { throw new CommandException(MESSAGE_PATH_NOT_FOUND); } @@ -48,9 +49,9 @@ public CommandResult execute(State state) throws CommandException { throw new CommandException(MESSAGE_INVALID_DEST); } - state.changeDirectory(dest); + model.changeDirectory(dest); - return new CommandResult(String.format(MESSAGE_SUCCESS, dest.toString())); + return new CommandResult(String.format(MESSAGE_SUCCESS, dest)); } /** diff --git a/src/main/java/seedu/address/logic/commands/Command.java b/src/main/java/seedu/address/logic/commands/Command.java index 5c4701b2ace..8d63fed8a3b 100644 --- a/src/main/java/seedu/address/logic/commands/Command.java +++ b/src/main/java/seedu/address/logic/commands/Command.java @@ -1,7 +1,7 @@ package seedu.address.logic.commands; import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.model.statemanager.State; +import seedu.address.model.Model; /** * Represents a command with hidden internal logic and the ability to be executed. @@ -14,5 +14,5 @@ public abstract class Command { * @return feedback message of the operation result for display * @throws CommandException If an error occurs during command execution. */ - public abstract CommandResult execute(State state) throws CommandException; + public abstract CommandResult execute(Model model) throws CommandException; } diff --git a/src/main/java/seedu/address/logic/commands/CreateDeadlineCommand.java b/src/main/java/seedu/address/logic/commands/CreateDeadlineCommand.java index 14dc7eedd51..b456f242b13 100644 --- a/src/main/java/seedu/address/logic/commands/CreateDeadlineCommand.java +++ b/src/main/java/seedu/address/logic/commands/CreateDeadlineCommand.java @@ -7,12 +7,12 @@ import seedu.address.commons.util.ToStringBuilder; import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.model.ChildOperation; +import seedu.address.model.Model; +import seedu.address.model.TaskOperation; import seedu.address.model.path.AbsolutePath; import seedu.address.model.profbook.Group; import seedu.address.model.profbook.Student; -import seedu.address.model.statemanager.ChildOperation; -import seedu.address.model.statemanager.State; -import seedu.address.model.statemanager.TaskOperation; import seedu.address.model.taskmanager.Deadline; /** @@ -76,19 +76,19 @@ public CreateDeadlineCommand(AbsolutePath path, Deadline deadline, String catego * @throws CommandException Exception thrown when error occurs during command execution. */ @Override - public CommandResult execute(State state) throws CommandException { + public CommandResult execute(Model model) throws CommandException { // Check path exists in ProfBook - if (!state.hasPath(path)) { + if (!model.hasPath(path)) { throw new CommandException(MESSAGE_PATH_NOT_FOUND); } if (this.category == null) { // Check target path is task manager - if (!state.hasTaskListInPath(path)) { + if (!model.hasTaskListInPath(path)) { throw new CommandException(MESSAGE_NOT_TASK_MANAGER); } - TaskOperation target = state.taskOperation(path); + TaskOperation target = model.taskOperation(path); // Check duplicate deadline if (target.hasTask(this.deadline)) { @@ -96,7 +96,7 @@ public CommandResult execute(State state) throws CommandException { } target.addTask(this.deadline); - state.updateList(); + model.updateList(); return new CommandResult(String.format(MESSAGE_SUCCESS, this.deadline)); } @@ -105,9 +105,9 @@ public CommandResult execute(State state) throws CommandException { if (!path.isGroupDirectory()) { throw new CommandException(MESSAGE_INVALID_PATH_FOR_ALL_STU); } - ChildOperation groupOper = state.groupChildOperation(path); + ChildOperation groupOper = model.groupChildOperation(path); groupOper.addTaskToAllChildren(deadline, 1); - state.updateList(); + model.updateList(); return new CommandResult(MESSAGE_SUCCESS_ALL_STUDENTS); } @@ -115,9 +115,9 @@ public CommandResult execute(State state) throws CommandException { throw new CommandException(MESSAGE_INVALID_PATH_FOR_ALL_GROUP); } - ChildOperation rootOper = state.rootChildOperation(); + ChildOperation rootOper = model.rootChildOperation(); rootOper.addTaskToAllChildren(deadline, 1); - state.updateList(); + model.updateList(); return new CommandResult(MESSAGE_SUCCESS_ALL_GROUPS); } diff --git a/src/main/java/seedu/address/logic/commands/CreateGroupCommand.java b/src/main/java/seedu/address/logic/commands/CreateGroupCommand.java index b2104e5f2a9..8f27892fdde 100644 --- a/src/main/java/seedu/address/logic/commands/CreateGroupCommand.java +++ b/src/main/java/seedu/address/logic/commands/CreateGroupCommand.java @@ -5,10 +5,10 @@ import seedu.address.commons.util.ToStringBuilder; import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.model.ChildOperation; +import seedu.address.model.Model; import seedu.address.model.path.AbsolutePath; import seedu.address.model.profbook.Group; -import seedu.address.model.statemanager.ChildOperation; -import seedu.address.model.statemanager.State; /** * Represents a command for creating a new group within ProfBook. @@ -43,15 +43,15 @@ public CreateGroupCommand(AbsolutePath dest, Group group) { /** * Executes the CreateGroupCommand to create a new group within ProfBook at the specified path. * - * @param state The current state of the application. + * @param model The current model of the application. * @return A CommandResult indicating the outcome of the execution. * @throws CommandException If an error occurs while executing the command. */ @Override - public CommandResult execute(State state) throws CommandException { - requireNonNull(state); + public CommandResult execute(Model model) throws CommandException { + requireNonNull(model); - ChildOperation rootOperation = state.rootChildOperation(); + ChildOperation rootOperation = model.rootChildOperation(); // Check duplicate group if (rootOperation.hasChild(dest.getGroupId().get())) { @@ -59,7 +59,7 @@ public CommandResult execute(State state) throws CommandException { } rootOperation.addChild(this.group.getId(), this.group); - state.updateList(); + model.updateList(); return new CommandResult(String.format(MESSAGE_SUCCESS, this.group)); } diff --git a/src/main/java/seedu/address/logic/commands/CreateStudentCommand.java b/src/main/java/seedu/address/logic/commands/CreateStudentCommand.java index 5509b777436..57a2026be5e 100644 --- a/src/main/java/seedu/address/logic/commands/CreateStudentCommand.java +++ b/src/main/java/seedu/address/logic/commands/CreateStudentCommand.java @@ -10,10 +10,10 @@ import seedu.address.commons.util.ToStringBuilder; import seedu.address.logic.Messages; import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.model.ChildOperation; +import seedu.address.model.Model; import seedu.address.model.path.AbsolutePath; import seedu.address.model.profbook.Student; -import seedu.address.model.statemanager.ChildOperation; -import seedu.address.model.statemanager.State; /** * Adds a student within the specific group. @@ -60,19 +60,19 @@ public CreateStudentCommand(AbsolutePath path, Student student) { * @throws CommandException Exception thrown when error occurs during command execution. */ @Override - public CommandResult execute(State state) throws CommandException { - requireNonNull(state); + public CommandResult execute(Model model) throws CommandException { + requireNonNull(model); if (!path.isStudentDirectory()) { throw new CommandException(MESSAGE_INVALID_PATH); } // Check group exists in ProfBook - if (!state.hasGroup(path)) { + if (!model.hasGroup(path)) { throw new CommandException(String.format(MESSAGE_GROUP_NOT_FOUND, path.getGroupId())); } - ChildOperation target = state.groupChildOperation(path); + ChildOperation target = model.groupChildOperation(path); // Check duplicate student if (target.hasChild(this.student.getId())) { @@ -80,7 +80,7 @@ public CommandResult execute(State state) throws CommandException { } target.addChild(this.student.getId(), this.student); - state.updateList(); + model.updateList(); return new CommandResult(String.format(MESSAGE_SUCCESS, Messages.format(student))); } diff --git a/src/main/java/seedu/address/logic/commands/CreateTodoCommand.java b/src/main/java/seedu/address/logic/commands/CreateTodoCommand.java index 361f0c1defd..2fe0668ab30 100644 --- a/src/main/java/seedu/address/logic/commands/CreateTodoCommand.java +++ b/src/main/java/seedu/address/logic/commands/CreateTodoCommand.java @@ -5,12 +5,12 @@ import seedu.address.commons.util.ToStringBuilder; import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.model.ChildOperation; +import seedu.address.model.Model; +import seedu.address.model.TaskOperation; import seedu.address.model.path.AbsolutePath; import seedu.address.model.profbook.Group; import seedu.address.model.profbook.Student; -import seedu.address.model.statemanager.ChildOperation; -import seedu.address.model.statemanager.State; -import seedu.address.model.statemanager.TaskOperation; import seedu.address.model.taskmanager.ToDo; /** @@ -59,9 +59,9 @@ public CreateTodoCommand(AbsolutePath target, ToDo todo) { /** * Constructs a {@code CreateTodoCommand} with the specified absolute path and "ToDo" task details. * - * @param target The absolute path to the group where the "ToDo" task will be added. - * @param todo The details of the "ToDo" task to be created. - * @param category The specific category of people to add ToDo task to each. + * @param target The absolute path to the group where the "ToDo" task will be added. + * @param todo The details of the "ToDo" task to be created. + * @param category The specific category of people to add ToDo task to each. */ public CreateTodoCommand(AbsolutePath target, ToDo todo, String category) { requireAllNonNull(target, todo, category); @@ -78,15 +78,15 @@ public CreateTodoCommand(AbsolutePath target, ToDo todo, String category) { * @throws CommandException If an error occurs during command execution. */ @Override - public CommandResult execute(State state) throws CommandException { - requireNonNull(state); + public CommandResult execute(Model model) throws CommandException { + requireNonNull(model); if (this.category == null) { - TaskOperation taskOperation = state.taskOperation(target); + TaskOperation taskOperation = model.taskOperation(target); if (taskOperation.hasTask(this.todo)) { throw new CommandException(MESSAGE_DUPLICATE_TODO_TASK_STUDENT); } taskOperation.addTask(this.todo); - state.updateList(); + model.updateList(); return new CommandResult(String.format(MESSAGE_SUCCESS, target)); } @@ -94,19 +94,19 @@ public CommandResult execute(State state) throws CommandException { if (!target.isGroupDirectory()) { throw new CommandException(MESSAGE_INVALID_PATH_FOR_ALL_STU); } - ChildOperation groupOper = state.groupChildOperation(target); + ChildOperation groupOper = model.groupChildOperation(target); groupOper.addTaskToAllChildren(todo, 1); - state.updateList(); + model.updateList(); return new CommandResult(MESSAGE_SUCCESS_ALL_STUDENTS); } if (!target.isRootDirectory()) { throw new CommandException(MESSAGE_INVALID_PATH_FOR_ALL_GROUP); } - ChildOperation rootOper = state.rootChildOperation(); - rootOper.addTaskToAllChildren(todo, 1);; + ChildOperation rootOper = model.rootChildOperation(); + rootOper.addTaskToAllChildren(todo, 1); - state.updateList(); + model.updateList(); return new CommandResult(MESSAGE_SUCCESS_ALL_GROUPS); } diff --git a/src/main/java/seedu/address/logic/commands/DeleteForStudentsAndGroupsCommand.java b/src/main/java/seedu/address/logic/commands/DeleteForStudentsAndGroupsCommand.java index a35d9372ee7..2cff7242cf2 100644 --- a/src/main/java/seedu/address/logic/commands/DeleteForStudentsAndGroupsCommand.java +++ b/src/main/java/seedu/address/logic/commands/DeleteForStudentsAndGroupsCommand.java @@ -5,6 +5,8 @@ import seedu.address.commons.util.ToStringBuilder; import seedu.address.logic.Messages; import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.model.ChildOperation; +import seedu.address.model.Model; import seedu.address.model.id.GroupId; import seedu.address.model.id.StudentId; import seedu.address.model.path.AbsolutePath; @@ -13,8 +15,7 @@ import seedu.address.model.profbook.Group; import seedu.address.model.profbook.Student; import seedu.address.model.profbook.exceptions.NoSuchChildException; -import seedu.address.model.statemanager.ChildOperation; -import seedu.address.model.statemanager.State; + /** * Deletes a {@code Student} or {@code Group} according to the targeted path. */ @@ -51,55 +52,55 @@ public DeleteForStudentsAndGroupsCommand(AbsolutePath toBeDeleted) { //path will * Executes an DeleteForStudentsAndGroupsCommand to delete a {@code Student} or {@code Group} * * @return Command result which represents the outcome of the command execution. - * @throws CommandException Exception thrown when error occurs during command execution. - * @throws InvalidPathException Exception thrown when error occurs due to invalid path. + * @throws CommandException Exception thrown when error occurs during command execution. + * @throws InvalidPathException Exception thrown when error occurs due to invalid path. * @throws UnsupportedPathOperationException Exception thrown when error occurs due to unsupported path execution. - * @throws NoSuchChildException Exception thrown when child specified does not exist. + * @throws NoSuchChildException Exception thrown when child specified does not exist. */ @Override - public CommandResult execute(State state) throws CommandException { - requireNonNull(state); + public CommandResult execute(Model model) throws CommandException { + requireNonNull(model); if (toBeDeleted.isRootDirectory()) { throw new CommandException(MESSAGE_INCORRECT_DIRECTORY_ERROR); } // Check if to be deleted path is current path. - if (toBeDeleted.equals(state.getCurrPath())) { + if (toBeDeleted.equals(model.getCurrPath())) { throw new CommandException(MESSAGE_DELETE_CURRENT_PATH); } // Check if to be deleted path is diplay path. - if (toBeDeleted.equals(state.getDisplayPath())) { + if (toBeDeleted.equals(model.getDisplayPath())) { throw new CommandException(MESSAGE_DELETE_DISPLAY_PATH); } // Check path exists in ProfBook - if (!state.hasPath(toBeDeleted)) { + if (!model.hasPath(toBeDeleted)) { throw new CommandException(MESSAGE_NO_SUCH_STUDENT_OR_GROUP); } if (toBeDeleted.isStudentDirectory()) { - ChildOperation target = state.groupChildOperation(toBeDeleted); + ChildOperation target = model.groupChildOperation(toBeDeleted); StudentId studentId = toBeDeleted.getStudentId().get(); if (!target.hasChild(studentId)) { throw new CommandException(MESSAGE_NO_SUCH_STUDENT_OR_GROUP); } stu = target.getChild(studentId); target.deleteChild(studentId); - state.updateList(); + model.updateList(); return new CommandResult(String.format(MESSAGE_SUCCESS_FOR_STUDENT, Messages.format(stu))); } if (toBeDeleted.isGroupDirectory()) { - ChildOperation target = state.rootChildOperation(); + ChildOperation target = model.rootChildOperation(); GroupId groupId = toBeDeleted.getGroupId().get(); if (!target.hasChild(groupId)) { throw new CommandException(MESSAGE_NO_SUCH_STUDENT_OR_GROUP); } grp = target.getChild(groupId); target.deleteChild(groupId); - state.updateList(); + model.updateList(); return new CommandResult(String.format(MESSAGE_SUCCESS_FOR_GROUP, Messages.format(grp))); } diff --git a/src/main/java/seedu/address/logic/commands/DeleteTaskCommand.java b/src/main/java/seedu/address/logic/commands/DeleteTaskCommand.java index eb4a26b43c4..67ee416983e 100644 --- a/src/main/java/seedu/address/logic/commands/DeleteTaskCommand.java +++ b/src/main/java/seedu/address/logic/commands/DeleteTaskCommand.java @@ -8,8 +8,8 @@ import seedu.address.commons.core.index.Index; import seedu.address.commons.util.ToStringBuilder; import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.model.statemanager.State; -import seedu.address.model.statemanager.TaskOperation; +import seedu.address.model.Model; +import seedu.address.model.TaskOperation; import seedu.address.model.taskmanager.Task; /** @@ -38,18 +38,18 @@ public DeleteTaskCommand(Index targetIndex) { } @Override - public CommandResult execute(State state) throws CommandException { - requireNonNull(state); + public CommandResult execute(Model model) throws CommandException { + requireNonNull(model); logger.info("Executing delete task command..."); // Check if diplay panel is displaying task list - if (!state.isShowTaskList()) { + if (!model.isShowTaskList()) { logger.warning("Task list is not shown. Aborting delete task command."); throw new CommandException(MESSAGE_TASK_LIST_NOT_SHOWN); } - TaskOperation taskOperation = state.taskOperation(state.getDisplayPath()); + TaskOperation taskOperation = model.taskOperation(model.getDisplayPath()); // Check if index is valid. if (!taskOperation.isValidIndex(targetIndex.getOneBased())) { @@ -60,11 +60,11 @@ public CommandResult execute(State state) throws CommandException { logger.info("Executing delete task command on index " + targetIndex.getOneBased()); Task deletedTask = taskOperation.deleteTask(targetIndex.getOneBased()); - state.updateList(); + model.updateList(); logger.info("Task deleted successfully. Deleted task: " + deletedTask.toString()); - return new CommandResult(String.format(MESSAGE_DELETE_TASK_SUCCESS, deletedTask.toString())); + return new CommandResult(String.format(MESSAGE_DELETE_TASK_SUCCESS, deletedTask)); } @Override diff --git a/src/main/java/seedu/address/logic/commands/EditCommand.java b/src/main/java/seedu/address/logic/commands/EditCommand.java index b8e65ef391a..c54b33325f5 100644 --- a/src/main/java/seedu/address/logic/commands/EditCommand.java +++ b/src/main/java/seedu/address/logic/commands/EditCommand.java @@ -11,6 +11,8 @@ import seedu.address.commons.util.ToStringBuilder; import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.model.ChildOperation; +import seedu.address.model.Model; import seedu.address.model.field.EditGroupDescriptor; import seedu.address.model.field.EditStudentDescriptor; import seedu.address.model.id.GroupId; @@ -23,8 +25,6 @@ import seedu.address.model.profbook.Name; import seedu.address.model.profbook.Phone; import seedu.address.model.profbook.Student; -import seedu.address.model.statemanager.ChildOperation; -import seedu.address.model.statemanager.State; import seedu.address.model.taskmanager.TaskList; /** @@ -74,7 +74,7 @@ public class EditCommand extends Command { /** * Constructs an EditCommand for editing a group's details. * - * @param target The path to the target group to be edited. + * @param target The path to the target group to be edited. * @param editGroupDescriptor The descriptor containing the details to edit. */ public EditCommand(AbsolutePath target, EditGroupDescriptor editGroupDescriptor) { @@ -85,7 +85,7 @@ public EditCommand(AbsolutePath target, EditGroupDescriptor editGroupDescriptor) /** * Constructs an EditCommand for editing a student's details. * - * @param target The path to the target student to be edited. + * @param target The path to the target student to be edited. * @param editStudentDescriptor The descriptor containing the details to edit. */ public EditCommand(AbsolutePath target, EditStudentDescriptor editStudentDescriptor) { @@ -127,21 +127,21 @@ private static Group createEditedGroup(Group groupToEdit, EditGroupDescriptor ed /** * Executes the EditCommand to edit a group or student's details. * - * @param state The current state of the application. + * @param model The current model of the application. * @return A CommandResult indicating the result of the execution. * @throws CommandException If there's an error during command execution. */ @Override - public CommandResult execute(State state) throws CommandException { - requireNonNull(state); + public CommandResult execute(Model model) throws CommandException { + requireNonNull(model); // Check path exists in ProfBook - if (!state.hasPath(target)) { + if (!model.hasPath(target)) { throw new CommandException(MESSAGE_NO_SUCH_PATH); } if (target.isGroupDirectory()) { - ChildOperation rootOperation = state.rootChildOperation(); + ChildOperation rootOperation = model.rootChildOperation(); GroupId groupId = target.getGroupId().get(); if (!rootOperation.hasChild(groupId)) { throw new CommandException(ERROR_MESSAGE_NO_SUCH_GROUP); @@ -150,19 +150,19 @@ public CommandResult execute(State state) throws CommandException { Group editedGroup = createEditedGroup(groupToEdit, this.editGroupDescriptor); rootOperation.deleteChild(groupId); rootOperation.addChild(groupId, editedGroup); - state.updateList(); + model.updateList(); return new CommandResult(MESSAGE_EDIT_GROUP_SUCCESS); } else if (target.isStudentDirectory()) { - ChildOperation groupOperation = state.groupChildOperation(target); + ChildOperation groupOperation = model.groupChildOperation(target); StudentId studentId = target.getStudentId().get(); Student studentToEdit = groupOperation.getChild(studentId); Student editedStudent = createEditedStudent(studentToEdit, this.editStudentDescriptor); groupOperation.deleteChild(studentId); groupOperation.addChild(editedStudent.getId(), editedStudent); - state.updateList(); + model.updateList(); return new CommandResult(MESSAGE_EDIT_STUDENT_SUCCESS); diff --git a/src/main/java/seedu/address/logic/commands/HelpCommand.java b/src/main/java/seedu/address/logic/commands/HelpCommand.java index c3cbdf502a6..2e613c1785f 100644 --- a/src/main/java/seedu/address/logic/commands/HelpCommand.java +++ b/src/main/java/seedu/address/logic/commands/HelpCommand.java @@ -1,7 +1,7 @@ package seedu.address.logic.commands; import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.model.statemanager.State; +import seedu.address.model.Model; /** * The HelpCommand class represents a command to display program usage instructions to the user. @@ -32,12 +32,12 @@ public class HelpCommand extends Command { /** * Executes the HelpCommand to display program usage instructions. * - * @param state The current program state. + * @param model The current program model. * @return A CommandResult containing the help message and related flags. * @throws CommandException If there is an error executing the command. */ @Override - public CommandResult execute(State state) throws CommandException { + public CommandResult execute(Model model) throws CommandException { return new CommandResult(SHOWING_HELP_MESSAGE, true, false); } } diff --git a/src/main/java/seedu/address/logic/commands/MarkCommand.java b/src/main/java/seedu/address/logic/commands/MarkCommand.java index 0c0b38d4757..7f5639432d1 100644 --- a/src/main/java/seedu/address/logic/commands/MarkCommand.java +++ b/src/main/java/seedu/address/logic/commands/MarkCommand.java @@ -8,9 +8,9 @@ import seedu.address.commons.core.index.Index; import seedu.address.commons.util.ToStringBuilder; import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.model.Model; +import seedu.address.model.TaskOperation; import seedu.address.model.path.AbsolutePath; -import seedu.address.model.statemanager.State; -import seedu.address.model.statemanager.TaskOperation; import seedu.address.model.taskmanager.Task; /** @@ -22,7 +22,7 @@ public class MarkCommand extends Command { public static final String COMMAND_WORD = "mark"; - public static final String MESSAGE_INCORRECT_STATE = "The current state is not showing task list."; + public static final String MESSAGE_INCORRECT_STATE = "The current model is not showing task list."; public static final String MESSAGE_INVALID_INDEX = "The task index provided is invalid."; @@ -47,23 +47,23 @@ public MarkCommand(Index index) { /** * Executes the MarkCommand to mark a task as completed. * - * @param state The current state of the application. + * @param model The current model of the application. * @return A CommandResult containing a message indicating the success of the marking operation. - * @throws CommandException If the command cannot be executed due to an incorrect state (not showing task list). + * @throws CommandException If the command cannot be executed due to an incorrect model (not showing task list). */ @Override - public CommandResult execute(State state) throws CommandException { - requireNonNull(state); + public CommandResult execute(Model model) throws CommandException { + requireNonNull(model); logger.info("Executing mark task command..."); - if (!state.isShowTaskList()) { + if (!model.isShowTaskList()) { logger.warning("Task list is not shown. Aborting mark task command."); throw new CommandException(MESSAGE_INCORRECT_STATE); } - AbsolutePath displayPath = state.getDisplayPath(); - TaskOperation taskOperation = state.taskOperation(displayPath); + AbsolutePath displayPath = model.getDisplayPath(); + TaskOperation taskOperation = model.taskOperation(displayPath); // Check if index is valid. if (!taskOperation.isValidIndex(this.index.getOneBased())) { @@ -74,7 +74,7 @@ public CommandResult execute(State state) throws CommandException { logger.info("Executing mark task command on index " + this.index.getOneBased()); Task markedTask = taskOperation.markTask(this.index.getOneBased()); - state.updateList(); + model.updateList(); logger.info("Task marked successfully. Marked task: " + markedTask.toString()); diff --git a/src/main/java/seedu/address/logic/commands/MoveStudentToGroupCommand.java b/src/main/java/seedu/address/logic/commands/MoveStudentToGroupCommand.java index de8d5922d5f..50747dfddb7 100644 --- a/src/main/java/seedu/address/logic/commands/MoveStudentToGroupCommand.java +++ b/src/main/java/seedu/address/logic/commands/MoveStudentToGroupCommand.java @@ -5,13 +5,11 @@ import seedu.address.commons.util.ToStringBuilder; import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.model.ChildOperation; +import seedu.address.model.Model; import seedu.address.model.id.StudentId; import seedu.address.model.path.AbsolutePath; import seedu.address.model.profbook.Student; -import seedu.address.model.statemanager.ChildOperation; -import seedu.address.model.statemanager.State; - - /** * Represents a command for moving a student from one group to another within ProfBook. @@ -52,31 +50,31 @@ public MoveStudentToGroupCommand(AbsolutePath source, AbsolutePath dest) { * @throws CommandException If an error occurs during command execution. */ @Override - public CommandResult execute(State state) throws CommandException { - requireNonNull(state); + public CommandResult execute(Model model) throws CommandException { + requireNonNull(model); // Check move student to group if (source.isStudentDirectory() && dest.isGroupDirectory()) { // Check student exists in ProfBook - if (!state.hasStudent(source)) { + if (!model.hasStudent(source)) { throw new CommandException(MESSAGE_STUDENT_NOT_FOUND); } // Check group exists in ProfBook - if (!state.hasGroup(dest)) { + if (!model.hasGroup(dest)) { throw new CommandException(MESSAGE_GROUP_NOT_FOUND); } StudentId toBeMovedId = source.getStudentId().get(); - ChildOperation sourceGroup = state.groupChildOperation(source); + ChildOperation sourceGroup = model.groupChildOperation(source); Student studentToBeMoved = sourceGroup.getChild(toBeMovedId); - ChildOperation destGroup = state.groupChildOperation(dest); + ChildOperation destGroup = model.groupChildOperation(dest); destGroup.addChild(toBeMovedId, studentToBeMoved); sourceGroup.deleteChild(toBeMovedId); - state.updateList(); + model.updateList(); return new CommandResult(String.format( MESSAGE_MOVE_STUDENT_SUCCESS, source.getStudentId().get(), dest.getGroupId().get())); } diff --git a/src/main/java/seedu/address/logic/commands/ShowChildrenListCommand.java b/src/main/java/seedu/address/logic/commands/ShowChildrenListCommand.java index 1e56a90f017..2f127fa86de 100644 --- a/src/main/java/seedu/address/logic/commands/ShowChildrenListCommand.java +++ b/src/main/java/seedu/address/logic/commands/ShowChildrenListCommand.java @@ -5,8 +5,8 @@ import seedu.address.commons.core.LogsCenter; import seedu.address.commons.util.ToStringBuilder; import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.model.Model; import seedu.address.model.path.AbsolutePath; -import seedu.address.model.statemanager.State; /** * Show Task List. @@ -37,32 +37,32 @@ public ShowChildrenListCommand(AbsolutePath path) { * @throws CommandException If an error occurs during command execution. */ @Override - public CommandResult execute(State state) throws CommandException { + public CommandResult execute(Model model) throws CommandException { if (target == null) { - if (!state.hasChildrenListInCurrentPath()) { + if (!model.hasChildrenListInCurrentPath()) { throw new CommandException(MESSAGE_NOT_CHILDREN_MANAGER); } - state.setDisplayPath(state.getCurrPath()); - state.showChildrenList(); + model.setDisplayPath(model.getCurrPath()); + model.showChildrenList(); return new CommandResult(String.format(MESSAGE_SUCCESS, "current directory")); } // Check path exists in ProfBook - if (!state.hasPath(target)) { - throw new CommandException(String.format(MESSAGE_PATH_NOT_FOUND, target.toString())); + if (!model.hasPath(target)) { + throw new CommandException(String.format(MESSAGE_PATH_NOT_FOUND, target)); } // Check path is children manager - if (!state.hasChildrenListInPath(target)) { - throw new CommandException(String.format(MESSAGE_NOT_CHILDREN_MANAGER, target.toString())); + if (!model.hasChildrenListInPath(target)) { + throw new CommandException(String.format(MESSAGE_NOT_CHILDREN_MANAGER, target)); } - state.setDisplayPath(target); - state.showChildrenList(); + model.setDisplayPath(target); + model.showChildrenList(); - logger.fine("Showing children list for path: " + target.toString()); + logger.fine("Showing children list for path: " + target); - return new CommandResult(String.format(MESSAGE_SUCCESS, target.toString())); + return new CommandResult(String.format(MESSAGE_SUCCESS, target)); } /** @@ -78,10 +78,7 @@ public boolean equals(Object other) { } // instanceof handles nulls - if (!(other instanceof ShowChildrenListCommand)) { - return false; - } - return true; + return other instanceof ShowChildrenListCommand; } /** diff --git a/src/main/java/seedu/address/logic/commands/ShowTaskListCommand.java b/src/main/java/seedu/address/logic/commands/ShowTaskListCommand.java index 691389228a5..dc8be14eb7e 100644 --- a/src/main/java/seedu/address/logic/commands/ShowTaskListCommand.java +++ b/src/main/java/seedu/address/logic/commands/ShowTaskListCommand.java @@ -5,8 +5,8 @@ import seedu.address.commons.core.LogsCenter; import seedu.address.commons.util.ToStringBuilder; import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.model.Model; import seedu.address.model.path.AbsolutePath; -import seedu.address.model.statemanager.State; /** * Show Task List. @@ -37,33 +37,33 @@ public ShowTaskListCommand(AbsolutePath path) { * @throws CommandException If an error occurs during command execution. */ @Override - public CommandResult execute(State state) throws CommandException { + public CommandResult execute(Model model) throws CommandException { if (target == null) { - AbsolutePath currPath = state.getCurrPath(); - if (!state.hasTaskListInCurrentPath()) { + AbsolutePath currPath = model.getCurrPath(); + if (!model.hasTaskListInCurrentPath()) { throw new CommandException(String.format(MESSAGE_NOT_TASK_MANAGER, currPath.toString())); } - state.setDisplayPath(currPath); - state.showTaskList(); + model.setDisplayPath(currPath); + model.showTaskList(); return new CommandResult(String.format(MESSAGE_SUCCESS, currPath.toString())); } // Check path exists in ProfBook - if (!state.hasPath(target)) { - throw new CommandException(String.format(MESSAGE_PATH_NOT_FOUND, target.toString())); + if (!model.hasPath(target)) { + throw new CommandException(String.format(MESSAGE_PATH_NOT_FOUND, target)); } // Check path is task manager - if (!state.hasTaskListInPath(target)) { - throw new CommandException(String.format(MESSAGE_NOT_TASK_MANAGER, target.toString())); + if (!model.hasTaskListInPath(target)) { + throw new CommandException(String.format(MESSAGE_NOT_TASK_MANAGER, target)); } - state.setDisplayPath(target); - state.showTaskList(); + model.setDisplayPath(target); + model.showTaskList(); - logger.fine("Showing task list for path: " + target.toString()); + logger.fine("Showing task list for path: " + target); - return new CommandResult(String.format(MESSAGE_SUCCESS, target.toString())); + return new CommandResult(String.format(MESSAGE_SUCCESS, target)); } /** @@ -79,10 +79,7 @@ public boolean equals(Object other) { } // instanceof handles nulls - if (!(other instanceof ShowTaskListCommand)) { - return false; - } - return true; + return other instanceof ShowTaskListCommand; } /** diff --git a/src/main/java/seedu/address/logic/commands/UnmarkCommand.java b/src/main/java/seedu/address/logic/commands/UnmarkCommand.java index 59d6e2855d4..60e66955e7c 100644 --- a/src/main/java/seedu/address/logic/commands/UnmarkCommand.java +++ b/src/main/java/seedu/address/logic/commands/UnmarkCommand.java @@ -8,9 +8,9 @@ import seedu.address.commons.core.index.Index; import seedu.address.commons.util.ToStringBuilder; import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.model.Model; +import seedu.address.model.TaskOperation; import seedu.address.model.path.AbsolutePath; -import seedu.address.model.statemanager.State; -import seedu.address.model.statemanager.TaskOperation; import seedu.address.model.taskmanager.Task; /** @@ -22,7 +22,7 @@ public class UnmarkCommand extends Command { public static final String COMMAND_WORD = "unmark"; - public static final String MESSAGE_INCORRECT_STATE = "The current state is not showing task list."; + public static final String MESSAGE_INCORRECT_STATE = "The current model is not showing task list."; public static final String MESSAGE_MARK_TASK_SUCCESS = "Unmarked task: %1$s"; @@ -47,23 +47,23 @@ public UnmarkCommand(Index index) { /** * Executes the UnmarkCommand to unmark a previously marked task. * - * @param state The current state of the application. + * @param model The current model of the application. * @return A CommandResult containing a message indicating the success of the unmarking operation. - * @throws CommandException If the command cannot be executed due to an incorrect state (not showing the task list). + * @throws CommandException If the command cannot be executed due to an incorrect model (not showing the task list). */ @Override - public CommandResult execute(State state) throws CommandException { - requireNonNull(state); + public CommandResult execute(Model model) throws CommandException { + requireNonNull(model); logger.info("Executing unmark task command..."); - if (!state.isShowTaskList()) { + if (!model.isShowTaskList()) { logger.warning("Task list is not shown. Aborting unmark task command."); throw new CommandException(MESSAGE_INCORRECT_STATE); } - AbsolutePath displayPath = state.getDisplayPath(); - TaskOperation taskOperation = state.taskOperation(displayPath); + AbsolutePath displayPath = model.getDisplayPath(); + TaskOperation taskOperation = model.taskOperation(displayPath); // Check if index is valid. if (!taskOperation.isValidIndex(this.index.getOneBased())) { @@ -74,7 +74,7 @@ public CommandResult execute(State state) throws CommandException { logger.info("Executing unmark task command on index " + this.index.getOneBased()); Task ummarkedTask = taskOperation.unmarkTask(this.index.getOneBased()); - state.updateList(); + model.updateList(); logger.info("Task unmarked successfully. Unmarked task: " + ummarkedTask.toString()); diff --git a/src/main/java/seedu/address/model/statemanager/ChildOperation.java b/src/main/java/seedu/address/model/ChildOperation.java similarity index 98% rename from src/main/java/seedu/address/model/statemanager/ChildOperation.java rename to src/main/java/seedu/address/model/ChildOperation.java index 64e420d04d2..a3831f642e2 100644 --- a/src/main/java/seedu/address/model/statemanager/ChildOperation.java +++ b/src/main/java/seedu/address/model/ChildOperation.java @@ -1,4 +1,4 @@ -package seedu.address.model.statemanager; +package seedu.address.model; import java.util.ArrayList; import java.util.List; @@ -144,7 +144,7 @@ private void addAllTaskToAllChildren(Task task, List ch Task clonedTask = task.clone(); if (child instanceof TaskListManager) { TaskListManager tlm = (TaskListManager) child; - tlm.addTask(clonedTask);; + tlm.addTask(clonedTask); } else if (child instanceof ChildrenAndTaskListManager) { ChildrenAndTaskListManager ctlm = (ChildrenAndTaskListManager) child; ctlm.addTask(clonedTask); diff --git a/src/main/java/seedu/address/model/statemanager/IChildOperation.java b/src/main/java/seedu/address/model/IChildOperation.java similarity index 95% rename from src/main/java/seedu/address/model/statemanager/IChildOperation.java rename to src/main/java/seedu/address/model/IChildOperation.java index 6e4f8b17d7b..4fc4fca2a35 100644 --- a/src/main/java/seedu/address/model/statemanager/IChildOperation.java +++ b/src/main/java/seedu/address/model/IChildOperation.java @@ -1,4 +1,4 @@ -package seedu.address.model.statemanager; +package seedu.address.model; import java.util.List; @@ -70,7 +70,7 @@ public interface IChildOperation { * Adds a task to children within the hierarchy up to a specified depth level. * e.g. if target is root and level is 2, task will be added to all student */ - public void addTaskToAllChildren(Task task, int level); + void addTaskToAllChildren(Task task, int level); /** * Returns Number of current children diff --git a/src/main/java/seedu/address/model/statemanager/ITaskOperations.java b/src/main/java/seedu/address/model/ITaskOperations.java similarity index 95% rename from src/main/java/seedu/address/model/statemanager/ITaskOperations.java rename to src/main/java/seedu/address/model/ITaskOperations.java index ed1304c141b..c2b982c12ee 100644 --- a/src/main/java/seedu/address/model/statemanager/ITaskOperations.java +++ b/src/main/java/seedu/address/model/ITaskOperations.java @@ -1,4 +1,4 @@ -package seedu.address.model.statemanager; +package seedu.address.model; import java.util.List; @@ -14,7 +14,7 @@ public interface ITaskOperations { /** * Checks if current task is present * - * @param t + * @param t The task in question */ boolean hasTask(Task t); @@ -31,7 +31,8 @@ public interface ITaskOperations { /** * Adds a new tasks to the task list. * Task must not be duplicated class. - * @param t + * + * @param t The task in question */ void addTask(Task t); diff --git a/src/main/java/seedu/address/model/statemanager/State.java b/src/main/java/seedu/address/model/Model.java similarity index 65% rename from src/main/java/seedu/address/model/statemanager/State.java rename to src/main/java/seedu/address/model/Model.java index 6a44b47ee45..2bfed9d8d8a 100644 --- a/src/main/java/seedu/address/model/statemanager/State.java +++ b/src/main/java/seedu/address/model/Model.java @@ -1,10 +1,9 @@ -package seedu.address.model.statemanager; +package seedu.address.model; import java.nio.file.Path; import javafx.collections.ObservableList; import seedu.address.commons.core.GuiSettings; -import seedu.address.model.ReadOnlyUserPrefs; import seedu.address.model.path.AbsolutePath; import seedu.address.model.profbook.Group; import seedu.address.model.profbook.Root; @@ -12,146 +11,150 @@ import seedu.address.ui.Displayable; /** - * The API of the State component. + * The API of the Model component. */ -public interface State { +public interface Model { //=========== UserPrefs ================================================================================== - public void setUserPrefs(ReadOnlyUserPrefs userPrefs); + void setUserPrefs(ReadOnlyUserPrefs userPrefs); - public ReadOnlyUserPrefs getUserPrefs(); + ReadOnlyUserPrefs getUserPrefs(); - public GuiSettings getGuiSettings(); + GuiSettings getGuiSettings(); - public void setGuiSettings(GuiSettings guiSettings); + void setGuiSettings(GuiSettings guiSettings); - public Path getProfBookFilePath(); + Path getProfBookFilePath(); - public void setAddressBookFilePath(Path addressBookFilePath); + void setAddressBookFilePath(Path addressBookFilePath); + + //=========== ProfBook Model ================================================================================ - //=========== ProfBook State ================================================================================ /** * Return current directory. */ - public AbsolutePath getCurrPath(); + AbsolutePath getCurrPath(); /** * Return Root. */ - public Root getRoot(); + Root getRoot(); + /** * Return current display path. */ - public AbsolutePath getDisplayPath(); + AbsolutePath getDisplayPath(); /** * Return true if display panel is showing task list. */ - public boolean isShowTaskList(); + boolean isShowTaskList(); /** * Return true if current path has task list. */ - public boolean hasTaskListInCurrentPath(); + boolean hasTaskListInCurrentPath(); /** * Return true if current path has children list. */ - public boolean hasChildrenListInCurrentPath(); + boolean hasChildrenListInCurrentPath(); /** * Returns true if group in given path exists in the ProfBook. * {@code path} must be path with group information. * i.e. Group directory or Student Directory. */ - public boolean hasGroup(AbsolutePath path); + boolean hasGroup(AbsolutePath path); /** * Returns true if student exists in the ProfBook. * {@code path} must be student path. */ - public boolean hasStudent(AbsolutePath path); + boolean hasStudent(AbsolutePath path); /** * Returns true if given path exists in the ProfBook. */ - public boolean hasPath(AbsolutePath path); + boolean hasPath(AbsolutePath path); /** * Change directory to destination path * {@code path} must exist in ProfBook and is not student path. */ - public void changeDirectory(AbsolutePath path); + void changeDirectory(AbsolutePath path); //=========== Display Panel Settings ============================================================= + /** * Return the current list shown on display panel. */ - public ObservableList getDisplayList(); + ObservableList getDisplayList(); /** * Update list with latest data according to * current display path and display content. */ - public void updateList(); + void updateList(); /** * Set the path to be shown on display panel. * {@code path} must exist in ProfBook. */ - public void setDisplayPath(AbsolutePath path); + void setDisplayPath(AbsolutePath path); /** * Return true if current display path has task list. */ - public boolean hasTaskListInDisplayPath(); + boolean hasTaskListInDisplayPath(); /** * Return true if current display path has children list. */ - public boolean hasChildrenListInDisplayPath(); + boolean hasChildrenListInDisplayPath(); /** * Displays a children list on the display panel. * This method should be called after checking that the current display path contains children list * by using the {@link hasChildrenListInDisplayPath} method. */ - public void showChildrenList(); + void showChildrenList(); /** * Displays a task list on the display panel. * This method should be called after checking that the current display path contains task list * by using the {@link hasTaskListInDisplayPath} method. */ - public void showTaskList(); + void showTaskList(); - //=========== State Management Operation ============================================================= + //=========== Model Management Operation ============================================================= /** * Creates a ChildOperation class that performs operation on root. */ - public ChildOperation rootChildOperation(); + ChildOperation rootChildOperation(); /** * Creates a ChildOperation that performs operation on the specified group. * {@code path} must be a directory with group information and exist in the ProfBook. */ - public ChildOperation groupChildOperation(AbsolutePath path); + ChildOperation groupChildOperation(AbsolutePath path); /** * Creates a TaskOperation that performs task operation on the specified task list. * {@code path} must be a directory with task list and exist in the ProfBook. */ - public TaskOperation taskOperation(AbsolutePath path); + TaskOperation taskOperation(AbsolutePath path); //=========== Helper Method ============================================================= + /** * Return true if given path has task list. */ - public boolean hasTaskListInPath(AbsolutePath path); + boolean hasTaskListInPath(AbsolutePath path); /** * Return true if given path has children list. */ - public boolean hasChildrenListInPath(AbsolutePath path); + boolean hasChildrenListInPath(AbsolutePath path); } diff --git a/src/main/java/seedu/address/model/statemanager/StateManager.java b/src/main/java/seedu/address/model/ModelManager.java similarity index 94% rename from src/main/java/seedu/address/model/statemanager/StateManager.java rename to src/main/java/seedu/address/model/ModelManager.java index 23687b98c6e..a28f30fe09f 100644 --- a/src/main/java/seedu/address/model/statemanager/StateManager.java +++ b/src/main/java/seedu/address/model/ModelManager.java @@ -1,4 +1,4 @@ -package seedu.address.model.statemanager; +package seedu.address.model; import static java.util.Objects.requireNonNull; import static seedu.address.commons.util.AppUtil.checkArgument; @@ -14,8 +14,6 @@ import seedu.address.commons.core.GuiSettings; import seedu.address.commons.core.LogsCenter; import seedu.address.commons.util.ToStringBuilder; -import seedu.address.model.ReadOnlyUserPrefs; -import seedu.address.model.UserPrefs; import seedu.address.model.id.GroupId; import seedu.address.model.id.StudentId; import seedu.address.model.path.AbsolutePath; @@ -28,9 +26,9 @@ /** * Represents the in-memory model of the ProfBook data. */ -public class StateManager implements State { +public class ModelManager implements Model { - private static final Logger logger = LogsCenter.getLogger(State.class); + private static final Logger logger = LogsCenter.getLogger(Model.class); private static final String MESSAGE_INTERNAL_ERROR = "Internal error: %1$s"; private final Root root; private final UserPrefs userPrefs; @@ -40,9 +38,9 @@ public class StateManager implements State { private AbsolutePath displayPath; /** - * Construct a state manager with curren path, root (ProfBook) and userPrefs. + * Construct a model manager with curren path, root (ProfBook) and userPrefs. */ - public StateManager(AbsolutePath currentPath, Root root, ReadOnlyUserPrefs userPrefs) { + public ModelManager(AbsolutePath currentPath, Root root, ReadOnlyUserPrefs userPrefs) { requireAllNonNull(currentPath, root, userPrefs); this.currentPath = currentPath; this.displayPath = currentPath; @@ -79,7 +77,7 @@ public void setAddressBookFilePath(Path addressBookFilePath) { userPrefs.setAddressBookFilePath(addressBookFilePath); } - //=========== ProfBook State ================================================================================ + //=========== ProfBook Model ================================================================================ @Override public AbsolutePath getCurrPath() { return this.currentPath; @@ -221,7 +219,7 @@ public void showTaskList() { updateList(); } - //=========== State Management Operation ============================================================= + //=========== Model Management Operation ============================================================= @Override public ChildOperation rootChildOperation() { return new ChildOperation<>(root); @@ -314,11 +312,11 @@ public boolean equals(Object other) { } // instanceof handles nulls - if (!(other instanceof StateManager)) { + if (!(other instanceof ModelManager)) { return false; } - StateManager otherStateManager = (StateManager) other; + ModelManager otherStateManager = (ModelManager) other; return this.showTaskList == otherStateManager.showTaskList && this.currentPath.equals(otherStateManager.currentPath) && this.displayList.equals(otherStateManager.displayList) diff --git a/src/main/java/seedu/address/model/statemanager/TaskOperation.java b/src/main/java/seedu/address/model/TaskOperation.java similarity index 98% rename from src/main/java/seedu/address/model/statemanager/TaskOperation.java rename to src/main/java/seedu/address/model/TaskOperation.java index 1e22702e4bc..7e87a1a6f7e 100644 --- a/src/main/java/seedu/address/model/statemanager/TaskOperation.java +++ b/src/main/java/seedu/address/model/TaskOperation.java @@ -1,4 +1,4 @@ -package seedu.address.model.statemanager; +package seedu.address.model; import static seedu.address.commons.util.AppUtil.checkArgument; diff --git a/src/main/java/seedu/address/model/path/AbsolutePath.java b/src/main/java/seedu/address/model/path/AbsolutePath.java index aa7f4e921c9..5c494f92479 100644 --- a/src/main/java/seedu/address/model/path/AbsolutePath.java +++ b/src/main/java/seedu/address/model/path/AbsolutePath.java @@ -24,6 +24,7 @@ public class AbsolutePath extends Path { /** * Construct {@code AbsolutePath} from a path string. + * * @param path The path string. * @throws InvalidPathException if the given path string is invalid. */ @@ -40,6 +41,7 @@ public AbsolutePath(String path) throws InvalidPathException { /** * Construct {@code AbsolutePath} with path element list. + * * @param fullPathElements The list of elements for the full path. */ public AbsolutePath(List fullPathElements) { @@ -100,8 +102,8 @@ public boolean isRootDirectory() { * Retrieves the student ID from the path directory. * * @return The student ID. - * @throws UnsupportedPathOperationException If the operation is not supported based on the directory's state. - * @throws InvalidIdException If the retrieved ID is invalid. + * @throws UnsupportedPathOperationException If the operation is not supported based on the directory's model. + * @throws InvalidIdException If the retrieved ID is invalid. */ public Optional getStudentId() { if (this.isGroupDirectory() || this.isRootDirectory()) { @@ -122,8 +124,8 @@ public Optional getStudentId() { * Retrieves the group ID from the path directory. * * @return The group ID. - * @throws UnsupportedPathOperationException If the operation is not supported based on the directory's state. - * @throws InvalidIdException If the retrieved ID is invalid. + * @throws UnsupportedPathOperationException If the operation is not supported based on the directory's model. + * @throws InvalidIdException If the retrieved ID is invalid. */ public Optional getGroupId() { if (this.isRootDirectory()) { diff --git a/src/main/java/seedu/address/model/path/exceptions/UnsupportedPathOperationException.java b/src/main/java/seedu/address/model/path/exceptions/UnsupportedPathOperationException.java index 35b8446ec60..e301e8b4018 100644 --- a/src/main/java/seedu/address/model/path/exceptions/UnsupportedPathOperationException.java +++ b/src/main/java/seedu/address/model/path/exceptions/UnsupportedPathOperationException.java @@ -3,7 +3,7 @@ /** * The {@code UnsupportedPathOperationException} class represents an * exception that is thrown when an operation is not supported or is - * invalid based on the state of a path directory. + * invalid based on the model of a path directory. */ public class UnsupportedPathOperationException extends Exception { /** diff --git a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java b/src/test/java/seedu/address/logic/commands/CommandTestUtil.java index 19ef2beeef1..c208cd7d1ec 100644 --- a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java +++ b/src/test/java/seedu/address/logic/commands/CommandTestUtil.java @@ -16,10 +16,10 @@ import seedu.address.logic.commands.exceptions.CommandException; import seedu.address.logic.parser.ParserUtil; import seedu.address.logic.parser.exceptions.ParseException; +import seedu.address.model.Model; import seedu.address.model.path.AbsolutePath; import seedu.address.model.path.RelativePath; import seedu.address.model.path.exceptions.InvalidPathException; -import seedu.address.model.statemanager.State; /** * Contains helper methods for testing commands. @@ -69,13 +69,13 @@ public class CommandTestUtil { + OPTION_ADDRESS + " "; // empty string not allowed for addresses public static final String INVALID_TAG_DESC = " " + OPTION_TAG + " " + "hubby*"; // '*' not allowed in tags - private static RelativePath validRootRelativePath; - private static RelativePath validGroupRelativePath; - private static RelativePath validStudentRelativePath; - private static AbsolutePath validRootAbsolutePath; - private static AbsolutePath validGroupAbsolutePath; - private static AbsolutePath validStudentAbsolutePath; - private static LocalDateTime validDateTime; + private static final RelativePath validRootRelativePath; + private static final RelativePath validGroupRelativePath; + private static final RelativePath validStudentRelativePath; + private static final AbsolutePath validRootAbsolutePath; + private static final AbsolutePath validGroupAbsolutePath; + private static final AbsolutePath validStudentAbsolutePath; + private static final LocalDateTime validDateTime; static { try { @@ -122,38 +122,38 @@ public static LocalDateTime getValidDateTime() { /** * Executes the given {@code command}, confirms that
* - the returned {@link CommandResult} matches {@code expectedCommandResult}
- * - the {@code actualState} matches {@code expectedState} + * - the {@code actualModel} matches {@code expectedModel} */ - public static void assertCommandSuccess(Command command, State actualState, CommandResult expectedCommandResult, - State expectedState) { + public static void assertCommandSuccess(Command command, Model actualModel, CommandResult expectedCommandResult, + Model expectedModel) { try { - CommandResult result = command.execute(actualState); + CommandResult result = command.execute(actualModel); assertEquals(expectedCommandResult, result); - assertEquals(expectedState, actualState); + assertEquals(expectedModel, actualModel); } catch (CommandException ce) { throw new AssertionError("Execution of command should not fail.", ce); } } /** - * Convenience wrapper to {@link #assertCommandSuccess(Command, State, CommandResult, State)} + * Convenience wrapper to {@link #assertCommandSuccess(Command, Model, CommandResult, Model)} * that takes a string {@code expectedMessage}. */ - public static void assertCommandSuccess(Command command, State actualState, String expectedMessage, - State expectedState) { + public static void assertCommandSuccess(Command command, Model actualModel, String expectedMessage, + Model expectedModel) { CommandResult expectedCommandResult = new CommandResult(expectedMessage); - assertCommandSuccess(command, actualState, expectedCommandResult, expectedState); + assertCommandSuccess(command, actualModel, expectedCommandResult, expectedModel); } /** * Executes the given {@code command}, confirms that
* - a {@code CommandException} is thrown
* - the CommandException message matches {@code expectedMessage}
- * - the {@code actualState} remain unchanged + * - the {@code actualModel} remain unchanged */ - public static void assertCommandFailure(Command command, State actualState, - String expectedMessage, State unchangedState) { - assertThrows(CommandException.class, () -> command.execute(actualState), expectedMessage); - assertEquals(unchangedState, actualState); + public static void assertCommandFailure(Command command, Model actualModel, + String expectedMessage, Model unchangedModel) { + assertThrows(CommandException.class, () -> command.execute(actualModel), expectedMessage); + assertEquals(unchangedModel, actualModel); } } diff --git a/src/test/java/seedu/address/logic/commands/CreateDeadlineCommandTest.java b/src/test/java/seedu/address/logic/commands/CreateDeadlineCommandTest.java index 4679fe7400a..23842b999b6 100644 --- a/src/test/java/seedu/address/logic/commands/CreateDeadlineCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/CreateDeadlineCommandTest.java @@ -2,6 +2,7 @@ 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.logic.commands.CreateDeadlineCommand.MESSAGE_SUCCESS; import static seedu.address.logic.commands.CreateDeadlineCommand.MESSAGE_SUCCESS_ALL_GROUPS; @@ -17,6 +18,9 @@ import org.junit.jupiter.api.Test; import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.model.Model; +import seedu.address.model.ModelManager; +import seedu.address.model.TaskOperation; import seedu.address.model.UserPrefs; import seedu.address.model.id.GroupId; import seedu.address.model.id.Id; @@ -28,9 +32,6 @@ import seedu.address.model.profbook.Name; import seedu.address.model.profbook.Root; import seedu.address.model.profbook.Student; -import seedu.address.model.statemanager.State; -import seedu.address.model.statemanager.StateManager; -import seedu.address.model.statemanager.TaskOperation; import seedu.address.model.taskmanager.Deadline; import seedu.address.model.taskmanager.Task; import seedu.address.model.taskmanager.TaskList; @@ -63,12 +64,12 @@ public void execute_deadlineForStudentAccepted_addSuccessful() throws InvalidPat RelativePath path = new RelativePath("0012Y"); AbsolutePath absolutePath = currPath.resolve(path); - State state = new StateManager(currPath, root, new UserPrefs()); + Model model = new ModelManager(currPath, root, new UserPrefs()); - TaskOperation target = state.taskOperation(absolutePath); + TaskOperation target = model.taskOperation(absolutePath); CreateDeadlineCommand command = new CreateDeadlineCommand(absolutePath, deadline); - CommandResult runCommand = command.execute(state); + CommandResult runCommand = command.execute(model); CommandResult returnStatement = new CommandResult(String.format(MESSAGE_SUCCESS, deadline)); @@ -113,8 +114,8 @@ public void execute_deadlineForAllStudentsInGroupAccepted_addSuccessful() AbsolutePath absolutePath = currPath.resolve(path); CreateDeadlineCommand command = new CreateDeadlineCommand(absolutePath, deadline, "allStu"); - State state = new StateManager(currPath, root, new UserPrefs()); - CommandResult runCommand = command.execute(state); + Model model = new ModelManager(currPath, root, new UserPrefs()); + CommandResult runCommand = command.execute(model); assertTrue(alice.checkDuplicates(deadline)); assertTrue(bob.checkDuplicates(deadline)); @@ -151,8 +152,8 @@ public void execute_deadlineForAllGroupsInRootAccepted_addSuccessful() assertFalse(grp2.checkDuplicates(deadline)); CreateDeadlineCommand command = new CreateDeadlineCommand(absolutePath, deadline, "allGrp"); - State state = new StateManager(currPath, root, new UserPrefs()); - CommandResult runCommand = command.execute(state); + Model model = new ModelManager(currPath, root, new UserPrefs()); + CommandResult runCommand = command.execute(model); assertTrue(grp1.checkDuplicates(deadline)); assertTrue(grp2.checkDuplicates(deadline)); @@ -172,7 +173,7 @@ public void execute_duplicateDeadline_throwsCommandException() throws InvalidPat groups.put(new GroupId("grp-001"), grp); Root root = new Root(groups); - State state = new StateManager(currPath, root, new UserPrefs()); + Model model = new ModelManager(currPath, root, new UserPrefs()); RelativePath path = new RelativePath("~/grp-001/0001Y"); AbsolutePath absolutePath = currPath.resolve(path); @@ -182,7 +183,7 @@ public void execute_duplicateDeadline_throwsCommandException() throws InvalidPat assertThrows(CommandException.class, CreateDeadlineCommand.MESSAGE_DUPLICATE_DEADLINE_TASK, ( - ) -> createDeadlineCommand.execute(state) + ) -> createDeadlineCommand.execute(model) ); } @@ -193,7 +194,7 @@ void equals_sameInstanceForStudentDirectory_success() throws InvalidPathExceptio Deadline deadline = new Deadline("Assignment 1", duedate); CreateDeadlineCommand command = new CreateDeadlineCommand(path, deadline); - assertTrue(command.equals(command)); + assertEquals(command, command); } @Test @@ -203,7 +204,7 @@ void equals_sameInstanceForGroupDirectory_success() throws InvalidPathException Deadline deadline = new Deadline("Assignment 1", duedate); CreateDeadlineCommand command = new CreateDeadlineCommand(path, deadline); - assertTrue(command.equals(command)); + assertEquals(command, command); } @Test @@ -218,7 +219,7 @@ void equals_sameCommandForStudentDirectory_success() throws InvalidPathException Deadline deadline2 = new Deadline("Assignment 1", duedate2); CreateDeadlineCommand command2 = new CreateDeadlineCommand(path2, deadline2); - assertTrue(command1.equals(command2)); + assertEquals(command1, command2); } @Test @@ -233,7 +234,7 @@ void equals_sameCommandForGroupDirectory_success() throws InvalidPathException { Deadline deadline2 = new Deadline("Assignment 1", duedate2); CreateDeadlineCommand command2 = new CreateDeadlineCommand(path2, deadline2); - assertTrue(command1.equals(command2)); + assertEquals(command1, command2); } @Test @@ -248,7 +249,7 @@ void equals_differentDescriptionForStudentDirectory_fail() throws InvalidPathExc Deadline deadline2 = new Deadline("Assignment 2", duedate2); CreateDeadlineCommand command2 = new CreateDeadlineCommand(path2, deadline2); - assertFalse(command1.equals(command2)); + assertNotEquals(command1, command2); } @Test @@ -263,7 +264,7 @@ void equals_differentPathForStudentDirectory_fail() throws InvalidPathException Deadline deadline2 = new Deadline("Assignment 1", duedate2); CreateDeadlineCommand command2 = new CreateDeadlineCommand(path2, deadline2); - assertFalse(command1.equals(command2)); + assertNotEquals(command1, command2); } @Test @@ -278,7 +279,7 @@ void equals_differentDueDateForStudentDirectory_fail() throws InvalidPathExcepti Deadline deadline2 = new Deadline("Assignment 1", duedate2); CreateDeadlineCommand command2 = new CreateDeadlineCommand(path2, deadline2); - assertFalse(command1.equals(command2)); + assertNotEquals(command1, command2); } @Test @@ -293,7 +294,7 @@ void equals_differentFieldsForStudentDirectory_fail() throws InvalidPathExceptio Deadline deadline2 = new Deadline("Assignment 2", duedate2); CreateDeadlineCommand command2 = new CreateDeadlineCommand(path2, deadline2); - assertFalse(command1.equals(command2)); + assertNotEquals(command1, command2); } @Test @@ -303,8 +304,8 @@ void toString_sameStringForStudentDirectory_success() throws InvalidPathExceptio Deadline deadline = new Deadline("Assignment 1", duedate); CreateDeadlineCommand command = new CreateDeadlineCommand(path, deadline); String expected = "seedu.address.logic.commands.CreateDeadlineCommand{" - + "toCreateDeadline=" - + "[D][ ] Assignment 1(by: 2023-12-03 23:58)}"; + + "toCreateDeadline=" + + "[D][ ] Assignment 1(by: 2023-12-03 23:58)}"; assertEquals(expected, command.toString()); } diff --git a/src/test/java/seedu/address/logic/commands/CreateGroupCommandTest.java b/src/test/java/seedu/address/logic/commands/CreateGroupCommandTest.java index 68f2f6e9736..68dee2ac4f0 100644 --- a/src/test/java/seedu/address/logic/commands/CreateGroupCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/CreateGroupCommandTest.java @@ -12,6 +12,8 @@ import org.junit.jupiter.api.Test; import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.model.Model; +import seedu.address.model.ModelManager; import seedu.address.model.UserPrefs; import seedu.address.model.id.GroupId; import seedu.address.model.id.Id; @@ -21,8 +23,6 @@ import seedu.address.model.profbook.Name; import seedu.address.model.profbook.Root; import seedu.address.model.profbook.Student; -import seedu.address.model.statemanager.State; -import seedu.address.model.statemanager.StateManager; import seedu.address.model.taskmanager.TaskList; public class CreateGroupCommandTest { @@ -39,13 +39,13 @@ public void execute_createGroup_success() throws CommandException, InvalidPathEx Map students = new HashMap<>(); Group group = new Group(new TaskList(new ArrayList<>()), students, new Name("Group1"), new GroupId("grp-001")); AbsolutePath currPath = new AbsolutePath("~/"); - State state = new StateManager(currPath, root, new UserPrefs()); + Model model = new ModelManager(currPath, root, new UserPrefs()); AbsolutePath target = new AbsolutePath("~/grp-001"); CreateGroupCommand createGroupCommand = new CreateGroupCommand(target, group); CommandResult successCommandResult = new CommandResult(String.format(MESSAGE_SUCCESS, group)); - assertEquals(successCommandResult, createGroupCommand.execute(state)); + assertEquals(successCommandResult, createGroupCommand.execute(model)); } @Test @@ -57,10 +57,10 @@ public void execute_duplicateGroup_throwCommandException() throws InvalidPathExc root.addChild(group.getId(), group); AbsolutePath currPath = new AbsolutePath("~/"); AbsolutePath target = new AbsolutePath("~/grp-001"); - State state = new StateManager(currPath, root, new UserPrefs()); + Model model = new ModelManager(currPath, root, new UserPrefs()); CreateGroupCommand createGroupCommand = new CreateGroupCommand(target, group); - assertThrows(CommandException.class, MESSAGE_DUPLICATE_GROUP, () -> createGroupCommand.execute(state)); + assertThrows(CommandException.class, MESSAGE_DUPLICATE_GROUP, () -> createGroupCommand.execute(model)); } @Test diff --git a/src/test/java/seedu/address/logic/commands/CreateStudentCommandTest.java b/src/test/java/seedu/address/logic/commands/CreateStudentCommandTest.java index f881a8def48..d3712a5f2ef 100644 --- a/src/test/java/seedu/address/logic/commands/CreateStudentCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/CreateStudentCommandTest.java @@ -1,8 +1,7 @@ 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 org.junit.jupiter.api.Assertions.assertNotEquals; import static seedu.address.testutil.Assert.assertThrows; import static seedu.address.testutil.TypicalStudents.ALICE; @@ -13,6 +12,8 @@ import seedu.address.logic.Messages; import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.model.Model; +import seedu.address.model.ModelManager; import seedu.address.model.UserPrefs; import seedu.address.model.id.GroupId; import seedu.address.model.id.Id; @@ -22,14 +23,12 @@ import seedu.address.model.profbook.Name; import seedu.address.model.profbook.Root; import seedu.address.model.profbook.Student; -import seedu.address.model.statemanager.State; -import seedu.address.model.statemanager.StateManager; import seedu.address.model.taskmanager.TaskList; import seedu.address.testutil.GroupBuilder; import seedu.address.testutil.StudentBuilder; class CreateStudentCommandTest { - private Student validStudent = new StudentBuilder().build(); + private final Student validStudent = new StudentBuilder().build(); @Test public void constructor_nullPersonNullPath_throwsNullPointerException() { @@ -66,8 +65,8 @@ void execute_studentAcceptedByGroup_success() throws Exception { .withId("0002Y").build(); CreateStudentCommand createStudentCommand = new CreateStudentCommand(path, bob); - State state = new StateManager(currPath, root, new UserPrefs()); - CommandResult commandResult = createStudentCommand.execute(state); + Model model = new ModelManager(currPath, root, new UserPrefs()); + CommandResult commandResult = createStudentCommand.execute(model); assertEquals(String.format(CreateStudentCommand.MESSAGE_SUCCESS, Messages.format(bob)), commandResult.getFeedbackToUser()); @@ -92,10 +91,10 @@ public void execute_duplicateStudent_throwsCommandException() throws InvalidPath AbsolutePath path = new AbsolutePath("~/grp-001/0001Y"); CreateStudentCommand createStudentCommand = new CreateStudentCommand(path, validStudent); - State state = new StateManager(currPath, root, new UserPrefs()); + Model model = new ModelManager(currPath, root, new UserPrefs()); assertThrows(CommandException.class, CreateStudentCommand.MESSAGE_DUPLICATE_STUDENT, ( - ) -> createStudentCommand.execute(state) + ) -> createStudentCommand.execute(model) ); } @@ -118,20 +117,20 @@ void testEquals() throws InvalidPathException { CreateStudentCommand createBobCommand = new CreateStudentCommand(path, bob); // same object -> returns true - assertTrue(createAliceCommand.equals(createAliceCommand)); + assertEquals(createAliceCommand, createAliceCommand); // same values -> returns true CreateStudentCommand createAliceCommandCopy = new CreateStudentCommand(path, alice); - assertTrue(createAliceCommand.equals(createAliceCommandCopy)); + assertEquals(createAliceCommand, createAliceCommandCopy); // different types -> returns false - assertFalse(createAliceCommand.equals(1)); + assertNotEquals(1, createAliceCommand); // null -> returns false - assertFalse(createAliceCommand.equals(null)); + assertNotEquals(null, createAliceCommand); // different person -> returns false - assertFalse(createAliceCommand.equals(createBobCommand)); + assertNotEquals(createAliceCommand, createBobCommand); } @Test diff --git a/src/test/java/seedu/address/logic/commands/CreateTodoCommandTest.java b/src/test/java/seedu/address/logic/commands/CreateTodoCommandTest.java index 898c6863a61..61f77f5c3f0 100644 --- a/src/test/java/seedu/address/logic/commands/CreateTodoCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/CreateTodoCommandTest.java @@ -2,6 +2,7 @@ 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.logic.commands.CreateTodoCommand.MESSAGE_SUCCESS; import static seedu.address.logic.commands.CreateTodoCommand.MESSAGE_SUCCESS_ALL_GROUPS; @@ -16,6 +17,9 @@ import org.junit.jupiter.api.Test; import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.model.Model; +import seedu.address.model.ModelManager; +import seedu.address.model.TaskOperation; import seedu.address.model.UserPrefs; import seedu.address.model.id.GroupId; import seedu.address.model.id.Id; @@ -26,9 +30,6 @@ import seedu.address.model.profbook.Name; import seedu.address.model.profbook.Root; import seedu.address.model.profbook.Student; -import seedu.address.model.statemanager.State; -import seedu.address.model.statemanager.StateManager; -import seedu.address.model.statemanager.TaskOperation; import seedu.address.model.taskmanager.Task; import seedu.address.model.taskmanager.TaskList; import seedu.address.model.taskmanager.ToDo; @@ -73,8 +74,8 @@ public void execute_todoForAllStudentsInGroupAccepted_addSuccessful() AbsolutePath path = new AbsolutePath("~/grp-003"); CreateTodoCommand command = new CreateTodoCommand(path, todo, "allStu"); - State state = new StateManager(currPath, root, new UserPrefs()); - CommandResult runCommand = command.execute(state); + Model model = new ModelManager(currPath, root, new UserPrefs()); + CommandResult runCommand = command.execute(model); assertTrue(alice.checkDuplicates(todo)); assertTrue(bob.checkDuplicates(todo)); @@ -109,8 +110,8 @@ public void execute_deadlineForAllGroupsInRootAccepted_addSuccessful() assertFalse(grp2.checkDuplicates(todo)); CreateTodoCommand command = new CreateTodoCommand(path, todo, "allGrp"); - State state = new StateManager(currPath, root, new UserPrefs()); - CommandResult runCommand = command.execute(state); + Model model = new ModelManager(currPath, root, new UserPrefs()); + CommandResult runCommand = command.execute(model); assertTrue(grp1.checkDuplicates(todo)); assertTrue(grp2.checkDuplicates(todo)); @@ -120,6 +121,7 @@ public void execute_deadlineForAllGroupsInRootAccepted_addSuccessful() assertEquals(runCommand, returnStatement); } + @Test public void execute_createTodoTask_success() throws CommandException, InvalidPathException, UnsupportedPathOperationException { @@ -131,12 +133,12 @@ public void execute_createTodoTask_success() throws CommandException, InvalidPat root.addChild(group.getId(), group); AbsolutePath currPath = new AbsolutePath("~/"); - State state = new StateManager(currPath, root, new UserPrefs()); + Model model = new ModelManager(currPath, root, new UserPrefs()); AbsolutePath target = new AbsolutePath("~/grp-001"); CreateTodoCommand createTodoCommand = new CreateTodoCommand(target, todo); CommandResult successCommandResult = new CommandResult(String.format(MESSAGE_SUCCESS, target)); - assertEquals(successCommandResult, createTodoCommand.execute(state)); + assertEquals(successCommandResult, createTodoCommand.execute(model)); } @Test @@ -150,16 +152,16 @@ public void execute_duplicateTodoTask_throwCommandException() throws InvalidPath root.addChild(group.getId(), group); AbsolutePath currPath = new AbsolutePath("~/"); - State state = new StateManager(currPath, root, new UserPrefs()); + Model model = new ModelManager(currPath, root, new UserPrefs()); AbsolutePath target = new AbsolutePath("~/grp-001"); - TaskOperation taskOperation = state.taskOperation(target); + TaskOperation taskOperation = model.taskOperation(target); taskOperation.addTask(todo); CreateTodoCommand createTodoCommand = new CreateTodoCommand(target, todo); assertThrows(CommandException.class, - CreateTodoCommand.MESSAGE_DUPLICATE_TODO_TASK_STUDENT, () -> createTodoCommand.execute(state)); + CreateTodoCommand.MESSAGE_DUPLICATE_TODO_TASK_STUDENT, () -> createTodoCommand.execute(model)); } @Test @@ -168,7 +170,7 @@ public void equals_sameInstance_success() throws InvalidPathException { AbsolutePath target = new AbsolutePath("~/grp-001"); CreateTodoCommand createTodoCommand = new CreateTodoCommand(target, todo); CreateTodoCommand duplicateCreateTodoCommand = new CreateTodoCommand(target, todo); - assertTrue(createTodoCommand.equals(duplicateCreateTodoCommand)); + assertEquals(createTodoCommand, duplicateCreateTodoCommand); } @Test @@ -178,7 +180,7 @@ public void equals_differentTodoTask_fail() throws InvalidPathException { AbsolutePath target = new AbsolutePath("~/grp-001"); CreateTodoCommand createTodoCommand1 = new CreateTodoCommand(target, todoTest1); CreateTodoCommand createTodoCommand2 = new CreateTodoCommand(target, todoTest2); - assertFalse(createTodoCommand1.equals(createTodoCommand2)); + assertNotEquals(createTodoCommand1, createTodoCommand2); } @Test diff --git a/src/test/java/seedu/address/logic/commands/DeleteForStudentsAndGroupsCommandTest.java b/src/test/java/seedu/address/logic/commands/DeleteForStudentsAndGroupsCommandTest.java index b0c9f7965fc..dd2faf67f36 100644 --- a/src/test/java/seedu/address/logic/commands/DeleteForStudentsAndGroupsCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/DeleteForStudentsAndGroupsCommandTest.java @@ -2,6 +2,7 @@ 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; @@ -12,6 +13,8 @@ import seedu.address.logic.Messages; import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.model.Model; +import seedu.address.model.ModelManager; import seedu.address.model.UserPrefs; import seedu.address.model.id.GroupId; import seedu.address.model.id.Id; @@ -21,8 +24,6 @@ import seedu.address.model.profbook.Group; import seedu.address.model.profbook.Root; import seedu.address.model.profbook.Student; -import seedu.address.model.statemanager.State; -import seedu.address.model.statemanager.StateManager; import seedu.address.testutil.GroupBuilder; import seedu.address.testutil.StudentBuilder; @@ -46,8 +47,8 @@ void execute_deleteStudent_success() throws InvalidPathException, CommandExcepti assertTrue(grp.hasChild(studentId)); DeleteForStudentsAndGroupsCommand command = new DeleteForStudentsAndGroupsCommand(path); - State state = new StateManager(currPath, root, new UserPrefs()); - CommandResult commandResult = command.execute(state); + Model model = new ModelManager(currPath, root, new UserPrefs()); + CommandResult commandResult = command.execute(model); assertFalse(root.hasChild(studentId)); @@ -67,8 +68,8 @@ void execute_deleteGroup_success() throws InvalidPathException, CommandException AbsolutePath path = new AbsolutePath("~/grp-001/"); DeleteForStudentsAndGroupsCommand command = new DeleteForStudentsAndGroupsCommand(path); - State state = new StateManager(currPath, root, new UserPrefs()); - CommandResult commandResult = command.execute(state); + Model model = new ModelManager(currPath, root, new UserPrefs()); + CommandResult commandResult = command.execute(model); GroupId groupId = new GroupId("grp-001"); assertFalse(root.hasChild(groupId)); @@ -89,10 +90,10 @@ public void execute_noSuchStudent_throwsCommandException() throws InvalidPathExc AbsolutePath path = new AbsolutePath("~/grp-001/0002Y"); DeleteForStudentsAndGroupsCommand command = new DeleteForStudentsAndGroupsCommand(path); - State state = new StateManager(currPath, root, new UserPrefs()); + Model model = new ModelManager(currPath, root, new UserPrefs()); assertThrows(CommandException.class, DeleteForStudentsAndGroupsCommand.MESSAGE_NO_SUCH_STUDENT_OR_GROUP, ( - ) -> command.execute(state) + ) -> command.execute(model) ); } @@ -108,10 +109,10 @@ public void execute_noSuchGroup_throwsCommandException() throws InvalidPathExcep AbsolutePath path = new AbsolutePath("~/grp-002/"); DeleteForStudentsAndGroupsCommand command = new DeleteForStudentsAndGroupsCommand(path); - State state = new StateManager(currPath, root, new UserPrefs()); + Model model = new ModelManager(currPath, root, new UserPrefs()); assertThrows(CommandException.class, DeleteForStudentsAndGroupsCommand.MESSAGE_NO_SUCH_STUDENT_OR_GROUP, ( - ) -> command.execute(state) + ) -> command.execute(model) ); } @@ -127,10 +128,10 @@ public void execute_incorrectDirectory_throwsCommandException() throws InvalidPa AbsolutePath path = new AbsolutePath("~/"); DeleteForStudentsAndGroupsCommand command = new DeleteForStudentsAndGroupsCommand(path); - State state = new StateManager(currPath, root, new UserPrefs()); + Model model = new ModelManager(currPath, root, new UserPrefs()); assertThrows(CommandException.class, DeleteForStudentsAndGroupsCommand.MESSAGE_INCORRECT_DIRECTORY_ERROR, ( - ) -> command.execute(state) + ) -> command.execute(model) ); } @@ -148,32 +149,32 @@ void testEquals() throws InvalidPathException { DeleteForStudentsAndGroupsCommand deleteS002 = new DeleteForStudentsAndGroupsCommand(pathStu002); // same object(Group) -> returns true - assertTrue(deleteG001.equals(deleteG001)); + assertEquals(deleteG001, deleteG001); // same object(Student) -> returns true - assertTrue(deleteS001.equals(deleteS001)); + assertEquals(deleteS001, deleteS001); // same values(Group) -> returns true DeleteForStudentsAndGroupsCommand deleteG001Copy = new DeleteForStudentsAndGroupsCommand(pathGrp001); - assertTrue(deleteG001.equals(deleteG001Copy)); + assertEquals(deleteG001, deleteG001Copy); // same values(Student) -> returns true DeleteForStudentsAndGroupsCommand deleteS001Copy = new DeleteForStudentsAndGroupsCommand(pathStu001); - assertTrue(deleteS001.equals(deleteS001Copy)); + assertEquals(deleteS001, deleteS001Copy); // different types -> returns false - assertFalse(deleteG001.equals(1)); - assertFalse(deleteS001.equals(1)); + assertNotEquals(1, deleteG001); + assertNotEquals(1, deleteS001); // null -> returns false - assertFalse(deleteG001.equals(null)); - assertFalse(deleteS001.equals(null)); + assertNotEquals(null, deleteG001); + assertNotEquals(null, deleteS001); // different group -> returns false - assertFalse(deleteG001.equals(deleteG002)); + assertNotEquals(deleteG001, deleteG002); // different student -> returns false - assertFalse(deleteS001.equals(deleteS002)); + assertNotEquals(deleteS001, deleteS002); // different area to delete -> returns false - assertFalse(deleteG001.equals(deleteS001)); + assertNotEquals(deleteG001, deleteS001); // different student -> returns false - assertFalse(deleteS001.equals(deleteS002)); + assertNotEquals(deleteS001, deleteS002); } @Test diff --git a/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java index acd4fc4d736..7ef83ea5c95 100644 --- a/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java @@ -1,8 +1,7 @@ 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 org.junit.jupiter.api.Assertions.assertNotEquals; import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure; import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; import static seedu.address.testutil.TypicalIndexes.FIRST_INDEX; @@ -13,19 +12,19 @@ import seedu.address.commons.core.index.Index; import seedu.address.logic.Messages; +import seedu.address.model.Model; +import seedu.address.model.ModelManager; +import seedu.address.model.TaskOperation; import seedu.address.model.UserPrefs; import seedu.address.model.path.AbsolutePath; import seedu.address.model.path.exceptions.InvalidPathException; import seedu.address.model.profbook.Root; -import seedu.address.model.statemanager.State; -import seedu.address.model.statemanager.StateManager; -import seedu.address.model.statemanager.TaskOperation; import seedu.address.model.taskmanager.Task; import seedu.address.model.util.SampleProfBook; public class DeleteTaskCommandTest { - private State actualState; - private State expectedState; + private Model actualModel; + private Model expectedModel; private TaskOperation taskOperation; @BeforeEach @@ -33,18 +32,18 @@ public void setup() throws InvalidPathException { AbsolutePath currentPath = new AbsolutePath("~/"); Root root1 = SampleProfBook.getRoot(); Root root2 = SampleProfBook.getRoot(); - actualState = new StateManager(currentPath, root1, new UserPrefs()); + actualModel = new ModelManager(currentPath, root1, new UserPrefs()); - expectedState = new StateManager(currentPath, root2, new UserPrefs()); + expectedModel = new ModelManager(currentPath, root2, new UserPrefs()); // Display task AbsolutePath displayPath = new AbsolutePath("~/grp-002/"); - actualState.setDisplayPath(displayPath); - actualState.showTaskList(); - expectedState.setDisplayPath(displayPath); - expectedState.showTaskList(); + actualModel.setDisplayPath(displayPath); + actualModel.showTaskList(); + expectedModel.setDisplayPath(displayPath); + expectedModel.showTaskList(); - taskOperation = expectedState.taskOperation(displayPath); + taskOperation = expectedModel.taskOperation(displayPath); } @Test @@ -56,9 +55,9 @@ public void execute_validIndex_success() { taskToDelete.toString()); taskOperation.deleteTask(FIRST_INDEX.getOneBased()); - expectedState.updateList(); + expectedModel.updateList(); - assertCommandSuccess(deleteCommand, actualState, expectedMessage, expectedState); + assertCommandSuccess(deleteCommand, actualModel, expectedMessage, expectedModel); } @Test @@ -66,8 +65,8 @@ public void execute_invalidIndex_throwsCommandException() { Index outOfBoundIndex = Index.fromOneBased(taskOperation.getTaskListSize() + 1); DeleteTaskCommand deleteCommand = new DeleteTaskCommand(outOfBoundIndex); - assertCommandFailure(deleteCommand, actualState, - Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX, expectedState); + assertCommandFailure(deleteCommand, actualModel, + Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX, expectedModel); } @Test @@ -76,20 +75,20 @@ public void equals() { DeleteTaskCommand deleteSecondCommand = new DeleteTaskCommand(SECOND_INDEX); // same object -> returns true - assertTrue(deleteFirstCommand.equals(deleteFirstCommand)); + assertEquals(deleteFirstCommand, deleteFirstCommand); // same values -> returns true DeleteTaskCommand deleteFirstCommandCopy = new DeleteTaskCommand(FIRST_INDEX); - assertTrue(deleteFirstCommand.equals(deleteFirstCommandCopy)); + assertEquals(deleteFirstCommand, deleteFirstCommandCopy); // different types -> returns false - assertFalse(deleteFirstCommand.equals(1)); + assertNotEquals(1, deleteFirstCommand); // null -> returns false - assertFalse(deleteFirstCommand.equals(null)); + assertNotEquals(null, deleteFirstCommand); // different person -> returns false - assertFalse(deleteFirstCommand.equals(deleteSecondCommand)); + assertNotEquals(deleteFirstCommand, deleteSecondCommand); } @Test diff --git a/src/test/java/seedu/address/logic/commands/EditCommandTest.java b/src/test/java/seedu/address/logic/commands/EditCommandTest.java index 0b31b745eb4..ff44a61b5d6 100644 --- a/src/test/java/seedu/address/logic/commands/EditCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/EditCommandTest.java @@ -1,7 +1,7 @@ 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.assertNotEquals; import static seedu.address.testutil.Assert.assertThrows; import java.util.HashMap; @@ -10,6 +10,8 @@ import org.junit.jupiter.api.Test; import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.model.Model; +import seedu.address.model.ModelManager; import seedu.address.model.UserPrefs; import seedu.address.model.field.EditGroupDescriptor; import seedu.address.model.field.EditStudentDescriptor; @@ -18,8 +20,6 @@ import seedu.address.model.path.exceptions.InvalidPathException; import seedu.address.model.profbook.Group; import seedu.address.model.profbook.Root; -import seedu.address.model.statemanager.State; -import seedu.address.model.statemanager.StateManager; public class EditCommandTest { @@ -41,7 +41,7 @@ public void equals_differentRelativePath_fail() throws InvalidPathException { EditCommand firstEditCommand = new EditCommand(path1, editGroupDescriptor); EditCommand secondEditCommand = new EditCommand(path2, editGroupDescriptor); - assertFalse(firstEditCommand.equals(secondEditCommand)); + assertNotEquals(firstEditCommand, secondEditCommand); } @Test @@ -61,12 +61,12 @@ public void execute_noSuchGroup_throwCommandException() throws InvalidPathExcept Root root = new Root(children); AbsolutePath currPath = new AbsolutePath("~/"); AbsolutePath path = new AbsolutePath("~/grp-001"); - State state = new StateManager(currPath, root, new UserPrefs()); + Model model = new ModelManager(currPath, root, new UserPrefs()); EditStudentDescriptor editStudentDescriptor = new EditStudentDescriptor(); EditCommand editCommand = new EditCommand(path, editStudentDescriptor); - assertThrows(CommandException.class, EditCommand.MESSAGE_NO_SUCH_PATH, () -> editCommand.execute(state)); + assertThrows(CommandException.class, EditCommand.MESSAGE_NO_SUCH_PATH, () -> editCommand.execute(model)); } @Test @@ -75,12 +75,12 @@ public void execute_invalidDirectory_throwCommandException() throws InvalidPathE Root root = new Root(children); AbsolutePath currPath = new AbsolutePath("~/"); AbsolutePath path = new AbsolutePath("~/"); - State state = new StateManager(currPath, root, new UserPrefs()); + Model model = new ModelManager(currPath, root, new UserPrefs()); EditStudentDescriptor editStudentDescriptor = new EditStudentDescriptor(); EditCommand editCommand = new EditCommand(path, editStudentDescriptor); assertThrows(CommandException.class, - EditCommand.MESSAGE_INCORRECT_DIRECTORY_ERROR, () -> editCommand.execute(state)); + EditCommand.MESSAGE_INCORRECT_DIRECTORY_ERROR, () -> editCommand.execute(model)); } } diff --git a/src/test/java/seedu/address/logic/commands/HelpCommandTest.java b/src/test/java/seedu/address/logic/commands/HelpCommandTest.java index a6e14309b2a..2d462aab918 100644 --- a/src/test/java/seedu/address/logic/commands/HelpCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/HelpCommandTest.java @@ -8,14 +8,14 @@ import org.junit.jupiter.api.Test; import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.model.Model; +import seedu.address.model.ModelManager; import seedu.address.model.UserPrefs; import seedu.address.model.id.Id; import seedu.address.model.path.AbsolutePath; import seedu.address.model.path.exceptions.InvalidPathException; import seedu.address.model.profbook.Group; import seedu.address.model.profbook.Root; -import seedu.address.model.statemanager.State; -import seedu.address.model.statemanager.StateManager; public class HelpCommandTest { @Test @@ -23,10 +23,10 @@ public void execute_validCommand_success() throws CommandException, InvalidPathE Map children = new HashMap<>(); Root root = new Root(children); AbsolutePath currPath = new AbsolutePath("~/"); - State state = new StateManager(currPath, root, new UserPrefs()); + Model model = new ModelManager(currPath, root, new UserPrefs()); HelpCommand helpCommand = new HelpCommand(); - CommandResult commandResult = helpCommand.execute(state); + CommandResult commandResult = helpCommand.execute(model); CommandResult expexctedCommandResult = new CommandResult(HelpCommand.SHOWING_HELP_MESSAGE, true, false); diff --git a/src/test/java/seedu/address/logic/commands/MarkCommandTest.java b/src/test/java/seedu/address/logic/commands/MarkCommandTest.java index 6f1be2867f7..4737ddb8b3c 100644 --- a/src/test/java/seedu/address/logic/commands/MarkCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/MarkCommandTest.java @@ -1,8 +1,7 @@ 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 org.junit.jupiter.api.Assertions.assertNotEquals; import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure; import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; import static seedu.address.testutil.TypicalIndexes.FIRST_INDEX; @@ -13,21 +12,21 @@ import seedu.address.commons.core.index.Index; import seedu.address.logic.Messages; +import seedu.address.model.Model; +import seedu.address.model.ModelManager; +import seedu.address.model.TaskOperation; import seedu.address.model.UserPrefs; import seedu.address.model.path.AbsolutePath; import seedu.address.model.path.exceptions.InvalidPathException; import seedu.address.model.profbook.Root; -import seedu.address.model.statemanager.State; -import seedu.address.model.statemanager.StateManager; -import seedu.address.model.statemanager.TaskOperation; import seedu.address.model.taskmanager.Task; import seedu.address.model.util.SampleProfBook; public class MarkCommandTest { - private State actualState; + private Model actualModel; - private State expectedState; + private Model expectedModel; private TaskOperation taskOperation; @@ -36,18 +35,18 @@ public void setup() throws InvalidPathException { AbsolutePath currentPath = new AbsolutePath("~/"); Root root1 = SampleProfBook.getRoot(); Root root2 = SampleProfBook.getRoot(); - actualState = new StateManager(currentPath, root1, new UserPrefs()); + actualModel = new ModelManager(currentPath, root1, new UserPrefs()); - expectedState = new StateManager(currentPath, root2, new UserPrefs()); + expectedModel = new ModelManager(currentPath, root2, new UserPrefs()); // Display task AbsolutePath displayPath = new AbsolutePath("~/grp-002/"); - actualState.setDisplayPath(displayPath); - actualState.showTaskList(); - expectedState.setDisplayPath(displayPath); - expectedState.showTaskList(); + actualModel.setDisplayPath(displayPath); + actualModel.showTaskList(); + expectedModel.setDisplayPath(displayPath); + expectedModel.showTaskList(); - taskOperation = expectedState.taskOperation(displayPath); + taskOperation = expectedModel.taskOperation(displayPath); } @Test @@ -59,9 +58,9 @@ public void execute_validIndex_success() { taskToMark.toString()); taskOperation.markTask(FIRST_INDEX.getOneBased()); - expectedState.updateList(); + expectedModel.updateList(); - assertCommandSuccess(markCommand, actualState, expectedMessage, expectedState); + assertCommandSuccess(markCommand, actualModel, expectedMessage, expectedModel); } @Test @@ -69,8 +68,8 @@ public void execute_invalidIndex_throwsCommandException() { Index outOfBoundIndex = Index.fromOneBased(taskOperation.getTaskListSize() + 1); MarkCommand markCommand = new MarkCommand(outOfBoundIndex); - assertCommandFailure(markCommand, actualState, - Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX, expectedState); + assertCommandFailure(markCommand, actualModel, + Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX, expectedModel); } @Test @@ -79,20 +78,20 @@ public void equals() { MarkCommand secondMarkCommand = new MarkCommand(SECOND_INDEX); // same object -> returns true - assertTrue(firstMarkCommand.equals(firstMarkCommand)); + assertEquals(firstMarkCommand, firstMarkCommand); // same values -> returns true MarkCommand firstMarkCommandCopy = new MarkCommand(FIRST_INDEX); - assertTrue(firstMarkCommand.equals(firstMarkCommandCopy)); + assertEquals(firstMarkCommand, firstMarkCommandCopy); // different types -> returns false - assertFalse(firstMarkCommand.equals(1)); + assertNotEquals(1, firstMarkCommand); // null -> returns false - assertFalse(firstMarkCommand.equals(null)); + assertNotEquals(null, firstMarkCommand); // different object -> returns false - assertFalse(firstMarkCommand.equals(secondMarkCommand)); + assertNotEquals(firstMarkCommand, secondMarkCommand); } @Test diff --git a/src/test/java/seedu/address/logic/commands/MoveStudentToGroupCommandTest.java b/src/test/java/seedu/address/logic/commands/MoveStudentToGroupCommandTest.java index 7fc5dfc7b2f..cf711b71f46 100644 --- a/src/test/java/seedu/address/logic/commands/MoveStudentToGroupCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/MoveStudentToGroupCommandTest.java @@ -10,6 +10,8 @@ import org.junit.jupiter.api.Test; import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.model.Model; +import seedu.address.model.ModelManager; import seedu.address.model.UserPrefs; import seedu.address.model.id.GroupId; import seedu.address.model.id.Id; @@ -19,8 +21,6 @@ import seedu.address.model.profbook.Name; import seedu.address.model.profbook.Root; import seedu.address.model.profbook.Student; -import seedu.address.model.statemanager.State; -import seedu.address.model.statemanager.StateManager; import seedu.address.model.taskmanager.TaskList; public class MoveStudentToGroupCommandTest { @@ -41,11 +41,11 @@ public void execute_invalidPathForSourceGroup_throwCommandException() throws Inv AbsolutePath currPath = new AbsolutePath("~/"); AbsolutePath sourcePath = new AbsolutePath("~/"); AbsolutePath destPath = new AbsolutePath("~/grp-002"); - State state = new StateManager(currPath, root, new UserPrefs()); + Model model = new ModelManager(currPath, root, new UserPrefs()); MoveStudentToGroupCommand moveStudentToGroupCommand = new MoveStudentToGroupCommand(sourcePath, destPath); - assertThrows(CommandException.class, () -> moveStudentToGroupCommand.execute(state)); + assertThrows(CommandException.class, () -> moveStudentToGroupCommand.execute(model)); } @Test diff --git a/src/test/java/seedu/address/logic/commands/UnmarkCommandTest.java b/src/test/java/seedu/address/logic/commands/UnmarkCommandTest.java index 2bb5ffd7081..9dae8e7f832 100644 --- a/src/test/java/seedu/address/logic/commands/UnmarkCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/UnmarkCommandTest.java @@ -1,8 +1,7 @@ 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 org.junit.jupiter.api.Assertions.assertNotEquals; import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure; import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; import static seedu.address.testutil.TypicalIndexes.FIRST_INDEX; @@ -13,21 +12,21 @@ import seedu.address.commons.core.index.Index; import seedu.address.logic.Messages; +import seedu.address.model.Model; +import seedu.address.model.ModelManager; +import seedu.address.model.TaskOperation; import seedu.address.model.UserPrefs; import seedu.address.model.path.AbsolutePath; import seedu.address.model.path.exceptions.InvalidPathException; import seedu.address.model.profbook.Root; -import seedu.address.model.statemanager.State; -import seedu.address.model.statemanager.StateManager; -import seedu.address.model.statemanager.TaskOperation; import seedu.address.model.taskmanager.Task; import seedu.address.model.util.SampleProfBook; public class UnmarkCommandTest { - private State actualState; + private Model actualModel; - private State expectedState; + private Model expectedModel; private TaskOperation taskOperation; @@ -36,18 +35,18 @@ public void setup() throws InvalidPathException { AbsolutePath currentPath = new AbsolutePath("~/"); Root root1 = SampleProfBook.getRoot(); Root root2 = SampleProfBook.getRoot(); - actualState = new StateManager(currentPath, root1, new UserPrefs()); + actualModel = new ModelManager(currentPath, root1, new UserPrefs()); - expectedState = new StateManager(currentPath, root2, new UserPrefs()); + expectedModel = new ModelManager(currentPath, root2, new UserPrefs()); // Display task AbsolutePath displayPath = new AbsolutePath("~/grp-002/"); - actualState.setDisplayPath(displayPath); - actualState.showTaskList(); - expectedState.setDisplayPath(displayPath); - expectedState.showTaskList(); + actualModel.setDisplayPath(displayPath); + actualModel.showTaskList(); + expectedModel.setDisplayPath(displayPath); + expectedModel.showTaskList(); - taskOperation = expectedState.taskOperation(displayPath); + taskOperation = expectedModel.taskOperation(displayPath); } @Test @@ -59,9 +58,9 @@ public void execute_validIndex_success() { taskToUnmark.toString()); taskOperation.unmarkTask(FIRST_INDEX.getOneBased()); - expectedState.updateList(); + expectedModel.updateList(); - assertCommandSuccess(unmarkCommand, actualState, expectedMessage, expectedState); + assertCommandSuccess(unmarkCommand, actualModel, expectedMessage, expectedModel); } @Test @@ -69,8 +68,8 @@ public void execute_invalidIndex_throwsCommandException() { Index outOfBoundIndex = Index.fromOneBased(taskOperation.getTaskListSize() + 1); UnmarkCommand unmarkCommand = new UnmarkCommand(outOfBoundIndex); - assertCommandFailure(unmarkCommand, actualState, - Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX, expectedState); + assertCommandFailure(unmarkCommand, actualModel, + Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX, expectedModel); } @Test @@ -79,20 +78,20 @@ public void equals() { UnmarkCommand secondUnmarkCommand = new UnmarkCommand(SECOND_INDEX); // same object -> returns true - assertTrue(firstUnmarkCommand.equals(firstUnmarkCommand)); + assertEquals(firstUnmarkCommand, firstUnmarkCommand); // same values -> returns true UnmarkCommand firstMarkCommandCopy = new UnmarkCommand(FIRST_INDEX); - assertTrue(firstUnmarkCommand.equals(firstMarkCommandCopy)); + assertEquals(firstUnmarkCommand, firstMarkCommandCopy); // different types -> returns false - assertFalse(firstUnmarkCommand.equals(1)); + assertNotEquals(1, firstUnmarkCommand); // null -> returns false - assertFalse(firstUnmarkCommand.equals(null)); + assertNotEquals(null, firstUnmarkCommand); // different object -> returns false - assertFalse(firstUnmarkCommand.equals(secondUnmarkCommand)); + assertNotEquals(firstUnmarkCommand, secondUnmarkCommand); } @Test diff --git a/src/test/java/seedu/address/statemanager/ChildOperationTest.java b/src/test/java/seedu/address/statemanager/ChildOperationTest.java index 8b89381e918..eef30bce0e5 100644 --- a/src/test/java/seedu/address/statemanager/ChildOperationTest.java +++ b/src/test/java/seedu/address/statemanager/ChildOperationTest.java @@ -13,6 +13,9 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import seedu.address.model.ChildOperation; +import seedu.address.model.Model; +import seedu.address.model.ModelManager; import seedu.address.model.UserPrefs; import seedu.address.model.id.GroupId; import seedu.address.model.id.Id; @@ -24,9 +27,6 @@ import seedu.address.model.profbook.Root; import seedu.address.model.profbook.Student; import seedu.address.model.profbook.exceptions.DuplicateChildException; -import seedu.address.model.statemanager.ChildOperation; -import seedu.address.model.statemanager.State; -import seedu.address.model.statemanager.StateManager; import seedu.address.model.taskmanager.TaskList; import seedu.address.testutil.StudentBuilder; @@ -39,7 +39,7 @@ public class ChildOperationTest { private AbsolutePath grpPath; private AbsolutePath stuPath; - private State state; + private Model model; @BeforeEach public void init() { @@ -63,25 +63,25 @@ public void init() { Map groups = new HashMap<>(); groups.put(new GroupId("grp-001"), this.group); this.root = new Root(groups); - state = new StateManager(rootPath, root, new UserPrefs()); + model = new ModelManager(rootPath, root, new UserPrefs()); } @Test public void getChildOperation_noErrorReturn() { - assertEquals(new ChildOperation<>(this.root), state.rootChildOperation()); - assertEquals(new ChildOperation<>(this.group.getChildrenManger()), state.groupChildOperation(grpPath)); - assertEquals(new ChildOperation<>(this.group.getChildrenManger()), state.groupChildOperation(stuPath)); + assertEquals(new ChildOperation<>(this.root), model.rootChildOperation()); + assertEquals(new ChildOperation<>(this.group.getChildrenManger()), model.groupChildOperation(grpPath)); + assertEquals(new ChildOperation<>(this.group.getChildrenManger()), model.groupChildOperation(stuPath)); } @Test public void getGroupChildOperationWithRoot_exceptionThrown() { - assertThrows(IllegalArgumentException.class, () -> state.groupChildOperation(rootPath)); + assertThrows(IllegalArgumentException.class, () -> model.groupChildOperation(rootPath)); } @Test public void childOperationVerifyDeleteAndAdd_noError() { StudentId stu = new StudentId("0001Y"); - ChildOperation opr = state.groupChildOperation(grpPath); + ChildOperation opr = model.groupChildOperation(grpPath); assertTrue(opr.hasChild(stu)); opr.deleteChild(stu); assertFalse(opr.hasChild(stu)); @@ -92,7 +92,7 @@ public void childOperationVerifyDeleteAndAdd_noError() { @Test public void childOperationVerifyGet_noError() { StudentId stu = new StudentId("0001Y"); - ChildOperation opr = state.groupChildOperation(grpPath); + ChildOperation opr = model.groupChildOperation(grpPath); assertTrue(opr.hasChild(stu)); assertEquals(this.student, opr.getChild(stu)); } @@ -101,7 +101,7 @@ public void childOperationVerifyGet_noError() { public void childOperationAddDuplicateChild_exceptionThrown() { StudentId stu = new StudentId("0001Y"); try { - ChildOperation opr = state.groupChildOperation(grpPath); + ChildOperation opr = model.groupChildOperation(grpPath); assertTrue(opr.hasChild(stu)); opr.addChild(stu, this.student); fail(); @@ -112,7 +112,7 @@ public void childOperationAddDuplicateChild_exceptionThrown() { @Test public void childOperationVerifyGetAll_noError() { - ChildOperation opr = state.groupChildOperation(grpPath); + ChildOperation opr = model.groupChildOperation(grpPath); ArrayList list = new ArrayList<>(); list.add(this.student); assertEquals(opr.getAllChildren(), list); @@ -127,7 +127,7 @@ public void childOperationVerifyUpdate_noError() { .withPhone("1234567") .withAddress("311, Clementi Ave 2, #02-25") .withId("0001Y").build(); - ChildOperation opr = state.groupChildOperation(grpPath); + ChildOperation opr = model.groupChildOperation(grpPath); assertTrue(opr.hasChild(stu)); opr.updateChild(stu, newStu); assertEquals(newStu, opr.getChild(stu)); diff --git a/src/test/java/seedu/address/statemanager/TaskOperationTest.java b/src/test/java/seedu/address/statemanager/TaskOperationTest.java index fd4c7ea4340..85c34fdf7ff 100644 --- a/src/test/java/seedu/address/statemanager/TaskOperationTest.java +++ b/src/test/java/seedu/address/statemanager/TaskOperationTest.java @@ -14,6 +14,9 @@ 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.TaskOperation; import seedu.address.model.UserPrefs; import seedu.address.model.id.GroupId; import seedu.address.model.id.Id; @@ -24,9 +27,6 @@ import seedu.address.model.profbook.Name; import seedu.address.model.profbook.Root; import seedu.address.model.profbook.Student; -import seedu.address.model.statemanager.State; -import seedu.address.model.statemanager.StateManager; -import seedu.address.model.statemanager.TaskOperation; import seedu.address.model.taskmanager.Deadline; import seedu.address.model.taskmanager.Task; import seedu.address.model.taskmanager.TaskList; @@ -43,7 +43,7 @@ public class TaskOperationTest { private AbsolutePath rootPath; private AbsolutePath grpPath; private AbsolutePath stuPath; - private State state; + private Model model; private final Task task = new Deadline("Assignment 3", LocalDateTime.parse("2023-12-03T23:59")); @BeforeEach @@ -68,19 +68,19 @@ public void init() { Map groups = new HashMap<>(); groups.put(new GroupId("grp-001"), this.group); this.root = new Root(groups); - state = new StateManager(rootPath, root, new UserPrefs()); + model = new ModelManager(rootPath, root, new UserPrefs()); } @Test public void getTaskOperation_noErrorReturn() { - assertEquals(new TaskOperation(this.group.getTaskListManager()), state.taskOperation(grpPath)); - assertEquals(new TaskOperation(this.student), state.taskOperation(stuPath)); + assertEquals(new TaskOperation(this.group.getTaskListManager()), model.taskOperation(grpPath)); + assertEquals(new TaskOperation(this.student), model.taskOperation(stuPath)); } @Test public void taskOperationVerifyDeleteMethod_noErrorReturn() { TaskOperation opr; - opr = state.taskOperation(stuPath); + opr = model.taskOperation(stuPath); assertTrue(this.student.checkDuplicates(task)); try { for (Task t : this.student.getAllTask()) { @@ -100,7 +100,7 @@ public void taskOperationVerifyDeleteMethod_noErrorReturn() { @Test public void taskOperationVerifyAdd_noErrorReturn() { TaskOperation opr; - opr = state.taskOperation(stuPath); + opr = model.taskOperation(stuPath); opr.deleteTask(1); assertFalse(opr.hasTask(task)); opr.addTask(task); @@ -110,7 +110,7 @@ public void taskOperationVerifyAdd_noErrorReturn() { @Test public void taskOperationVerifyMarkUnmark_noErrorReturn() { TaskOperation opr; - opr = state.taskOperation(stuPath); + opr = model.taskOperation(stuPath); List ret = opr.findTask("Assignment"); assertEquals(ret.get(0), this.task); ret = opr.findTask("not here"); @@ -120,14 +120,14 @@ public void taskOperationVerifyMarkUnmark_noErrorReturn() { @Test public void taskOperationVerifyGetTasks_noErrorReturn() { TaskOperation opr; - opr = state.taskOperation(stuPath); + opr = model.taskOperation(stuPath); assertEquals(opr.getTask(1), this.task); } @Test public void taskOperationVerifyGetAllTasks_noErrorReturn() { TaskOperation opr; - opr = state.taskOperation(stuPath); + opr = model.taskOperation(stuPath); ArrayList list = new ArrayList<>(); list.add(this.task); assertEquals(opr.getAllTasks(), list); From 99612719c895684f3a32cedb4bce7254e655d34a Mon Sep 17 00:00:00 2001 From: mingyuanc Date: Thu, 26 Oct 2023 01:36:12 +0800 Subject: [PATCH 2/7] Wrote DG for ModelManager --- docs/DeveloperGuide.md | 45 ++++++++++++++++----- docs/diagrams/AddTaskSequence.puml | 46 +++++++++++++++++++++ docs/diagrams/ModelClassDiagram.puml | 42 ++++++------------- docs/diagrams/ProfBookClassDiagram.puml | 54 +++++++++++++++++++++++++ docs/team/mingyuanc.md | 12 +++--- 5 files changed, 153 insertions(+), 46 deletions(-) create mode 100644 docs/diagrams/AddTaskSequence.puml create mode 100644 docs/diagrams/ProfBookClassDiagram.puml diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 90a3dc35993..cb2b810d7c0 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -145,29 +145,54 @@ How the parsing works: ### Model component **API -** : [`Model.java`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/model/Model.java) +** : [`Model.java`](https://github.com/AY2324S1-CS2103T-W15-2/tp/tree/master/src/main/java/seedu/address/model/Model.java) The `Model` component, -* stores the address book data i.e., all `Person` objects (which are contained in a `UniquePersonList` object). -* stores the currently 'selected' `Person` objects (e.g., results of a search query) as a separate _filtered_ list which - is exposed to outsiders as 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 ProfBook data i.e., all `Root, Group and Student` objects (which are contained in a + hierarchical structure in the ProfBook package). +* stores the currently 'selected' `Displayable` objects (e.g., selected task list, children in current folder) + as a separate _filtered_ list which is exposed to outsiders as 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 a `UserPref` object that represents the user’s preferences. This is exposed to the outside as a `ReadOnlyUserPref` objects. * does not depend on any of the other three components (as the `Model` represents data entities of the domain, they should make sense on their own without depending on other components) - + + +The diagram above shows how the folder structure is implemented in ProfBook, + +* The hierarchy is as such: `Root` -> `Group` -> `Student` +* As many of the operations are repeated (e.g., Tasks operations and Children Operation), we decided to abstract out + these logic into their own classes which is represented by `TaskListManager` and `ChildrenManager` respectively. +* ChildrenManager manages the children which is of type `IChildElement` +* We also created a wrapper classes for classes that require both of those aforementioned functionalities (e.g, `Group`, + `TutorialSlot`) + +The sequence diagram below illustrates the interactions within the Model component, taking an execution of a +CreateTodoClass as example. -**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` objects.
+ + +How the `Model` component works: + +1. Depending on the nature of the command, a static method is called to generate a `TaskOperation` or + a `ChildrenOperation` Object that acts as an interface Command object to manipulate the Model +2. In this case, a `TaskOperation` object is created. This object would store all the necessary information to make + changes directly on the correct state. +3. The command object calls the required method in the `TaskOperation` object which results in the `TaskOperation` + object adding the Todo task to the group + + - +**Note:** For ChildrenOperation, ModelManager provides more specific static factory methods (e.g., GroupChildOperation, +StudentChildOperation) to generate the `ChildOperation` object. It is implemented this way so that ModelManager is able +to check that the Operation required matches with the intended effect of the Command object's Execution diff --git a/docs/diagrams/AddTaskSequence.puml b/docs/diagrams/AddTaskSequence.puml new file mode 100644 index 00000000000..c1b7f598736 --- /dev/null +++ b/docs/diagrams/AddTaskSequence.puml @@ -0,0 +1,46 @@ +@startuml +!include style.puml +skinparam ArrowFontStyle plain + +box Command LOGIC_COLOR_T1 +participant ":CreateTodoCommand" as CreateTodoCommand LOGIC_COLOR +end box + +box Model MODEL_COLOR_T1 +participant "<>\nModelManager" as ModelManagerStatic MODEL_COLOR +participant "opr:TaskOperation" as TaskOperation MODEL_COLOR +participant "g:Group" as Group MODEL_COLOR +end box + +[-> CreateTodoCommand : execute() +activate CreateTodoCommand + +CreateTodoCommand -> ModelManagerStatic : taskOperation(new Path("~/grp-001")) +activate ModelManagerStatic + +create TaskOperation +ModelManagerStatic -> TaskOperation +activate TaskOperation + +TaskOperation --> ModelManagerStatic +deactivate TaskOperation + +ModelManagerStatic --> CreateTodoCommand :opr +deactivate ModelManagerStatic + +CreateTodoCommand -> TaskOperation : addTask(task) +activate TaskOperation + +TaskOperation -> Group : addTask(task) +activate Group + +Group --> TaskOperation +deactivate Group + +TaskOperation --> CreateTodoCommand + +destroy TaskOperation + +[<--CreateTodoCommand +deactivate CreateTodoCommand +@enduml diff --git a/docs/diagrams/ModelClassDiagram.puml b/docs/diagrams/ModelClassDiagram.puml index 0de5673070d..7f0403a9d66 100644 --- a/docs/diagrams/ModelClassDiagram.puml +++ b/docs/diagrams/ModelClassDiagram.puml @@ -5,50 +5,32 @@ skinparam arrowColor MODEL_COLOR skinparam classBackgroundColor MODEL_COLOR Package Model as ModelPackage <>{ -Class "<>\nReadOnlyAddressBook" as ReadOnlyAddressBook Class "<>\nReadOnlyUserPrefs" as ReadOnlyUserPrefs Class "<>\nModel" as Model -Class AddressBook Class ModelManager Class UserPrefs +Class Path +Class ObservableList +Class TaskList -Class UniquePersonList -Class Person -Class Address -Class Email -Class Name -Class Phone -Class Tag +Package ProfBook { + +} Class I #FFFFFF } Class HiddenOutside #FFFFFF -HiddenOutside ..> Model -AddressBook .up.|> ReadOnlyAddressBook +HiddenOutside ..> Model +ModelManager --> Path +ModelManager --> ProfBook +ModelManager --> ObservableList +ObservableList ..> ProfBook +ObservableList ..> TaskList ModelManager .up.|> Model Model .right.> ReadOnlyUserPrefs -Model .left.> ReadOnlyAddressBook -ModelManager -left-> "1" AddressBook ModelManager -right-> "1" UserPrefs UserPrefs .up.|> ReadOnlyUserPrefs - -AddressBook *--> "1" UniquePersonList -UniquePersonList --> "~* all" Person -Person *--> Name -Person *--> Phone -Person *--> Email -Person *--> Address -Person *--> "*" Tag - -Person -[hidden]up--> I -UniquePersonList -[hidden]right-> I - -Name -[hidden]right-> Phone -Phone -[hidden]right-> Address -Address -[hidden]right-> Email - -ModelManager --> "~* filtered" Person @enduml diff --git a/docs/diagrams/ProfBookClassDiagram.puml b/docs/diagrams/ProfBookClassDiagram.puml new file mode 100644 index 00000000000..c1ffe83df48 --- /dev/null +++ b/docs/diagrams/ProfBookClassDiagram.puml @@ -0,0 +1,54 @@ +@startuml +!include style.puml +skinparam arrowThickness 1.1 +skinparam arrowColor MODEL_COLOR +skinparam classBackgroundColor MODEL_COLOR + +Package ProfBook as ProfBookPackage <>{ +Class "ChildrenManager" as ChildrenManager +Class "TaskListManager" as TaskListManager +Class "<>\nIChildElement" as IChildElement +Class "{abstract}\nChildrenAndTaskListManager" as ChildrenAndTaskListManager +Class Root +Class Group +Class Student +Class Id +Class Name +Class Address +Class Email +Class Phone + + +Class I #FFFFFF +} +Class HiddenOutside #FFFFFF + +HiddenOutside ..> ChildrenManager + +ChildrenAndTaskListManager .up.|> IChildElement +Student -up-|> TaskListManager +Student .up.|> IChildElement + +Root --> Id +Group --> Id +Student --> Id + +Group --> Name +Student --> Name + +Student --> Email +Student --> Address +Student --> Phone + +ChildrenAndTaskListManager --> TaskListManager +ChildrenAndTaskListManager --> ChildrenManager + +Root -up-|> ChildrenManager +Group -up-|> ChildrenAndTaskListManager +Root --> "*" Group : Groups > + + +Group --> "*" Student : Students > + + +@enduml \ No newline at end of file diff --git a/docs/team/mingyuanc.md b/docs/team/mingyuanc.md index 74285a56c91..dbf7773ec34 100644 --- a/docs/team/mingyuanc.md +++ b/docs/team/mingyuanc.md @@ -26,12 +26,12 @@ Given below are my contributions to the project. * Implementation were also made generic to allow for future extensions if needed. * Implementation was challenging as it required modifying the whole flow and structure of the application -* **Streamline state modifications**: - * What it does: Provide a safe way for the command to modify the state +* **Streamline model modifications**: + * What it does: Provide a safe way for the command to modify the model * Justification: - * Modification of the state should be done through a state manager instead of directly being modified by an + * Modification of the model should be done through a model manager instead of directly being modified by an external class in accordance with OOP principals - * Allow for the future migration to immutable state + * Allow for the future migration to immutable model * Highlights: * Implementation of this required an in-depth analysis of design alternative as there was a need for a generic way to modify all the current different classes alongside future classes. @@ -69,9 +69,9 @@ Given below are my contributions to the project. * Provides the logic to safely manipulate data stored in Student/Group/Root * Ensure separation of concern by implementing other two other classes, TaskOperation and ChildOperation, each handling their own operation. - * Ensure the expected behaviour with regard to manipulating the state + * Ensure the expected behaviour with regard to manipulating the model * Path given matches the expected outcome - * Commands are unable to directly modify the state + * Commands are unable to directly modify the model ### **Code contributed**: From aa750ebbb59d484618b62815ab577547ee0bbbd2 Mon Sep 17 00:00:00 2001 From: mingyuanc Date: Thu, 26 Oct 2023 17:20:21 +0800 Subject: [PATCH 3/7] Add --- docs/diagrams/ProfBookClassDiagram.puml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/diagrams/ProfBookClassDiagram.puml b/docs/diagrams/ProfBookClassDiagram.puml index c1ffe83df48..cbdea587c28 100644 --- a/docs/diagrams/ProfBookClassDiagram.puml +++ b/docs/diagrams/ProfBookClassDiagram.puml @@ -49,6 +49,4 @@ Root --> "*" Group : Groups > Group --> "*" Student : Students > - - -@enduml \ No newline at end of file +@enduml From c00b95d9d3355754b2c3a7f71eb1f7460e806c1f Mon Sep 17 00:00:00 2001 From: mingyuanc Date: Thu, 26 Oct 2023 22:56:52 +0800 Subject: [PATCH 4/7] Update class diagram --- docs/diagrams/ModelClassDiagram.puml | 2 -- docs/diagrams/ProfBookClassDiagram.puml | 17 ++++++++--------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/docs/diagrams/ModelClassDiagram.puml b/docs/diagrams/ModelClassDiagram.puml index 7f0403a9d66..911996c768a 100644 --- a/docs/diagrams/ModelClassDiagram.puml +++ b/docs/diagrams/ModelClassDiagram.puml @@ -11,7 +11,6 @@ Class ModelManager Class UserPrefs Class Path Class ObservableList -Class TaskList Package ProfBook { @@ -28,7 +27,6 @@ ModelManager --> Path ModelManager --> ProfBook ModelManager --> ObservableList ObservableList ..> ProfBook -ObservableList ..> TaskList ModelManager .up.|> Model Model .right.> ReadOnlyUserPrefs ModelManager -right-> "1" UserPrefs diff --git a/docs/diagrams/ProfBookClassDiagram.puml b/docs/diagrams/ProfBookClassDiagram.puml index cbdea587c28..d9eb4d3a390 100644 --- a/docs/diagrams/ProfBookClassDiagram.puml +++ b/docs/diagrams/ProfBookClassDiagram.puml @@ -18,18 +18,17 @@ Class Address Class Email Class Phone - Class I #FFFFFF } + Class HiddenOutside #FFFFFF -HiddenOutside ..> ChildrenManager +HiddenOutside .down.> ChildrenManager ChildrenAndTaskListManager .up.|> IChildElement Student -up-|> TaskListManager Student .up.|> IChildElement -Root --> Id Group --> Id Student --> Id @@ -40,13 +39,13 @@ Student --> Email Student --> Address Student --> Phone -ChildrenAndTaskListManager --> TaskListManager -ChildrenAndTaskListManager --> ChildrenManager +ChildrenAndTaskListManager -left-> TaskListManager +ChildrenAndTaskListManager -right-> ChildrenManager + +TaskListManager -up-> TaskList Root -up-|> ChildrenManager Group -up-|> ChildrenAndTaskListManager -Root --> "*" Group : Groups > - - -Group --> "*" Student : Students > +Root -left-> "*" Group : Parent of > +Group -left-> "*" Student : Parent of > @enduml From 29acbf4449abd604b41709f41f03c28d7e53c92e Mon Sep 17 00:00:00 2001 From: mingyuanc Date: Thu, 26 Oct 2023 23:00:06 +0800 Subject: [PATCH 5/7] Update sequence diagram --- docs/diagrams/AddTaskSequence.puml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/diagrams/AddTaskSequence.puml b/docs/diagrams/AddTaskSequence.puml index c1b7f598736..4912b7227b8 100644 --- a/docs/diagrams/AddTaskSequence.puml +++ b/docs/diagrams/AddTaskSequence.puml @@ -7,7 +7,7 @@ participant ":CreateTodoCommand" as CreateTodoCommand LOGIC_COLOR end box box Model MODEL_COLOR_T1 -participant "<>\nModelManager" as ModelManagerStatic MODEL_COLOR +participant "ModelManager" as ModelManagerStatic MODEL_COLOR participant "opr:TaskOperation" as TaskOperation MODEL_COLOR participant "g:Group" as Group MODEL_COLOR end box @@ -22,13 +22,13 @@ create TaskOperation ModelManagerStatic -> TaskOperation activate TaskOperation -TaskOperation --> ModelManagerStatic +TaskOperation --> ModelManagerStatic : opr deactivate TaskOperation ModelManagerStatic --> CreateTodoCommand :opr deactivate ModelManagerStatic -CreateTodoCommand -> TaskOperation : addTask(task) +CreateTodoCommand -> TaskOperation : opr.addTask(task) activate TaskOperation TaskOperation -> Group : addTask(task) @@ -42,5 +42,5 @@ TaskOperation --> CreateTodoCommand destroy TaskOperation [<--CreateTodoCommand -deactivate CreateTodoCommand +destroy CreateTodoCommand @enduml From a2713e43623ce1af4d60f9a24af5bee2b34198bc Mon Sep 17 00:00:00 2001 From: mingyuanc Date: Thu, 26 Oct 2023 23:17:25 +0800 Subject: [PATCH 6/7] Update sequence diagram --- docs/DeveloperGuide.md | 11 +++++------ docs/diagrams/ProfBookClassDiagram.puml | 14 +++++++------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index cb2b810d7c0..569cf1ad60a 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -168,14 +168,13 @@ The `Model` component, The diagram above shows how the folder structure is implemented in ProfBook, * The hierarchy is as such: `Root` -> `Group` -> `Student` -* As many of the operations are repeated (e.g., Tasks operations and Children Operation), we decided to abstract out +* As many of the operations are repeated (e.g., tasks operations and children operation), we decided to abstract out these logic into their own classes which is represented by `TaskListManager` and `ChildrenManager` respectively. -* ChildrenManager manages the children which is of type `IChildElement` -* We also created a wrapper classes for classes that require both of those aforementioned functionalities (e.g, `Group`, - `TutorialSlot`) +* `ChildrenManager` manages the children which is of type `IChildElement` +* We also created a wrapper classes for classes that require both of those aforementioned functionalities (e.g, `Group`) -The sequence diagram below illustrates the interactions within the Model component, taking an execution of a -CreateTodoClass as example. +The sequence diagram below illustrates the interactions within the `Model` component, taking an execution of a +`CreateTodoClass` as example. diff --git a/docs/diagrams/ProfBookClassDiagram.puml b/docs/diagrams/ProfBookClassDiagram.puml index d9eb4d3a390..3b1bc10669e 100644 --- a/docs/diagrams/ProfBookClassDiagram.puml +++ b/docs/diagrams/ProfBookClassDiagram.puml @@ -29,15 +29,15 @@ ChildrenAndTaskListManager .up.|> IChildElement Student -up-|> TaskListManager Student .up.|> IChildElement -Group --> Id -Student --> Id +Group *--> Id +Student *--> Id -Group --> Name -Student --> Name +Group *--> Name +Student *--> Name -Student --> Email -Student --> Address -Student --> Phone +Student *--> Email +Student *--> Address +Student *--> Phone ChildrenAndTaskListManager -left-> TaskListManager ChildrenAndTaskListManager -right-> ChildrenManager From 68075754d616d1586beddca1490400e59cbff2cd Mon Sep 17 00:00:00 2001 From: mingyuanc Date: Thu, 26 Oct 2023 23:20:10 +0800 Subject: [PATCH 7/7] Minor bug fixes --- docs/diagrams/AddTaskSequence.puml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/diagrams/AddTaskSequence.puml b/docs/diagrams/AddTaskSequence.puml index 4912b7227b8..7c9c3ab69dd 100644 --- a/docs/diagrams/AddTaskSequence.puml +++ b/docs/diagrams/AddTaskSequence.puml @@ -7,7 +7,7 @@ participant ":CreateTodoCommand" as CreateTodoCommand LOGIC_COLOR end box box Model MODEL_COLOR_T1 -participant "ModelManager" as ModelManagerStatic MODEL_COLOR +participant ":ModelManager" as ModelManagerStatic MODEL_COLOR participant "opr:TaskOperation" as TaskOperation MODEL_COLOR participant "g:Group" as Group MODEL_COLOR end box @@ -28,7 +28,7 @@ deactivate TaskOperation ModelManagerStatic --> CreateTodoCommand :opr deactivate ModelManagerStatic -CreateTodoCommand -> TaskOperation : opr.addTask(task) +CreateTodoCommand -> TaskOperation : addTask(task) activate TaskOperation TaskOperation -> Group : addTask(task)