Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor AddressBook to AgentAssist #138

Merged
merged 5 commits into from
Oct 26, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 18 additions & 20 deletions docs/DeveloperGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ The sequence diagram below illustrates the interactions within the `Logic` compo

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. When `Logic` is called upon to execute a command, it is passed to an `AgentAssistParser` 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).<br>
Note that although this is shown as a single step in the diagram above (for simplicity), in the code it can take several interactions (between the command object and the `Model`) to achieve.
Expand All @@ -113,7 +113,7 @@ Here are the other classes in `Logic` (omitted from the class diagram above) tha
<img src="images/ParserClasses.png" width="600"/>

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.
* When called upon to parse a user command, the `AgentAssistParser` 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 `AgentAssistParser` returns back as a `Command` object.
* `FilterCommandParser` is explicitly shown as unlike other command parsers, `FilterCommandParser` performs an additional task: it creates multiple predicate classes, which are combined into a `CombinedPredicate`.
* All `XYZCommandParser` classes (e.g., `AddCommandParser`, `DeleteCommandParser`, ...) and `FilterCommandParser` inherit from the `Parser` interface so that they can be treated similarly where possible e.g, during testing.

Expand All @@ -138,7 +138,7 @@ The `Model` component,

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).
* inherits from both `AgentAssistStorage` 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
Expand All @@ -155,37 +155,37 @@ 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 `VersionedAgentAssist`. It extends `AgentAssist` with an undo/redo history, stored internally as an `agentAssistStateList` 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.
* `VersionedAgentAssist#commit()` — Saves the current address book state in its history.
* `VersionedAgentAssist#undo()` — Restores the previous address book state from its history.
* `VersionedAgentAssist#redo()` — Restores a previously undone address book state 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#commitAgentAssist()`, `Model#undoAgentAssist()` and `Model#redoAgentAssist()` 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 `VersionedAgentAssist` will be initialized with the initial address book state, and the `currentStatePointer` pointing to that single address book state.

![UndoRedoState0](images/UndoRedoState0.png)

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#commitAgentAssist()`, causing the modified state of the address book after the `delete 5` command executes to be saved in the `agentAssistStateList`, and the `currentStatePointer` is shifted to the newly inserted address book state.

![UndoRedoState1](images/UndoRedoState1.png)

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#commitAgentAssist()`, causing another modified address book state to be saved into the `agentAssistStateList`.

![UndoRedoState2](images/UndoRedoState2.png)

<div markdown="span" class="alert alert-info">:information_source: **Note:** If a command fails its execution, it will not call `Model#commitAddressBook()`, so the address book state will not be saved into the `addressBookStateList`.
<div markdown="span" class="alert alert-info">:information_source: **Note:** If a command fails its execution, it will not call `Model#commitAgentAssist()`, so the address book state will not be saved into the `agentAssistStateList`.

</div>

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#undoAgentAssist()`, 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.

![UndoRedoState3](images/UndoRedoState3.png)

<div markdown="span" class="alert alert-info">:information_source: **Note:** If the `currentStatePointer` is at index 0, pointing to the initial AddressBook state, then there are no previous AddressBook states to restore. The `undo` command uses `Model#canUndoAddressBook()` to check if this is the case. If so, it will return an error to the user rather
<div markdown="span" class="alert alert-info">:information_source: **Note:** If the `currentStatePointer` is at index 0, pointing to the initial AgentAssist state, then there are no previous AgentAssist states to restore. The `undo` command uses `Model#canUndoAgentAssist()` to check if this is the case. If so, it will return an error to the user rather
than attempting to perform the undo.

</div>
Expand All @@ -202,17 +202,17 @@ Similarly, how an undo operation goes through the `Model` component is shown bel

![UndoSequenceDiagram](images/UndoSequenceDiagram-Model.png)

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#redoAgentAssist()`, which shifts the `currentStatePointer` once to the right, pointing to the previously undone state, and restores the address book to that state.

<div markdown="span" class="alert alert-info">:information_source: **Note:** If the `currentStatePointer` is at index `addressBookStateList.size() - 1`, pointing to the latest address book state, then there are no undone AddressBook states to restore. The `redo` command uses `Model#canRedoAddressBook()` to check if this is the case. If so, it will return an error to the user rather than attempting to perform the redo.
<div markdown="span" class="alert alert-info">:information_source: **Note:** If the `currentStatePointer` is at index `agentAssistStateList.size() - 1`, pointing to the latest address book state, then there are no undone AgentAssist states to restore. The `redo` command uses `Model#canRedoAgentAssist()` to check if this is the case. If so, it will return an error to the user rather than attempting to perform the redo.

</div>

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#commitAgentAssist()`, `Model#undoAgentAssist()` or `Model#redoAgentAssist()`. Thus, the `agentAssistStateList` remains unchanged.

![UndoRedoState4](images/UndoRedoState4.png)

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#commitAgentAssist()`. Since the `currentStatePointer` is not pointing at the end of the `agentAssistStateList`, 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.

![UndoRedoState5](images/UndoRedoState5.png)

Expand Down Expand Up @@ -304,8 +304,6 @@ Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unli

**Use case: U1 - Delete a person**

<img src="images/DeleteActivityDiagram.png" width="550" />

**MSS**

1. User requests to list persons.
Expand Down
2 changes: 1 addition & 1 deletion docs/SettingUp.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ If you plan to use Intellij IDEA (highly recommended):

1. **Learn the design**

When you are ready to start coding, we recommend that you get some sense of the overall design by reading about [AddressBook’s architecture](DeveloperGuide.md#architecture).
When you are ready to start coding, we recommend that you get some sense of the overall design by reading about [AgentAssist’s architecture](DeveloperGuide.md#architecture).

1. **Do the tutorials**
These tutorials will help you get acquainted with the codebase.
Expand Down
4 changes: 2 additions & 2 deletions docs/UserGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -684,7 +684,7 @@ AgentAssist **automatically saves** all client data to your computer after each


## 5.6 Modifying the Data File
The data in AgentAssist is automatically saved as a [JSON](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/JSON) file as `[JAR file location]/data/addressbook.json`. Advanced users are welcome to update data directly by editing that data file.
The data in AgentAssist is automatically saved as a [JSON](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/JSON) file as `[JAR file location]/data/agentassist.json`. Advanced users are welcome to update data directly by editing that data file.

> ⚠️ **Danger:**
> If the data file format becomes invalid, AgentAssist will **discard all data** and start with an empty file on the next run. It's strongly recommended to back up the file before any manual edits.
Expand All @@ -697,7 +697,7 @@ The data in AgentAssist is automatically saved as a [JSON](https://developer.moz
## 6. FAQ

### How do I transfer my data to another Computer?
Install the app in the other computer and overwrite the empty data file it creates with the file that contains the data of your previous AddressBook home folder.
Install the app in the other computer and overwrite the empty data file it creates with the file that contains the data of your previous AgentAssist home folder.

### How do I change the remarks or credit card tier of an existing customer?
Use the [`edit` command](#feature-4-edit-the-existing-customer), and specify the `t/` flag for the credit card tier, and `rn/` or `ra/` for remarks. If you wish to remove the assigned tier of a contact, simply use the `t/` flag without indicating a tier.
Expand Down
2 changes: 1 addition & 1 deletion docs/diagrams/ArchitectureSequenceDiagram.puml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ activate model MODEL_COLOR
model -[MODEL_COLOR]-> logic
deactivate model

logic -[LOGIC_COLOR]> storage : saveAddressBook(addressBook)
logic -[LOGIC_COLOR]> storage : saveAgentAssist(agentAssist)
activate storage STORAGE_COLOR

storage -[STORAGE_COLOR]> storage : Save to file
Expand Down
14 changes: 7 additions & 7 deletions docs/diagrams/BetterModelClassDiagram.puml
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@ skinparam arrowThickness 1.1
skinparam arrowColor MODEL_COLOR
skinparam classBackgroundColor MODEL_COLOR

AddressBook *-right-> "1" UniquePersonList
AddressBook *-right-> "1" UniqueTagList
UniqueTagList -[hidden]down- UniquePersonList
UniqueTagList -[hidden]down- UniquePersonList
AgentAssist *-right-> "1" UniquePersonList

UniqueTagList -right-> "*" Tag
UniquePersonList -right-> Person

Person -up-> "*" Tag

Person *--> Name
Person *--> Phone
Person *--> Email
Person *--> Address
Person *--> Tier
Person *--> Job
Person *--> Income
Person *--> Status
Person *--> Remark

@enduml
6 changes: 3 additions & 3 deletions docs/diagrams/CommitActivityDiagram.puml
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ start
'Since the beta syntax does not support placing the condition outside the
'diamond we place it as the true branch instead.

if () then ([command commits AddressBook])
if () then ([command commits AgentAssist])
:Purge redundant states;
:Save AddressBook to
addressBookStateList;
:Save AgentAssist to
agentAssistStateList;
else ([else])
endif
stop
Expand Down
20 changes: 10 additions & 10 deletions docs/diagrams/DeleteSequenceDiagram.puml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ skinparam ArrowFontStyle plain

box Logic LOGIC_COLOR_T1
participant ":LogicManager" as LogicManager LOGIC_COLOR
participant ":AddressBookParser" as AddressBookParser LOGIC_COLOR
participant ":AgentAssistParser" as AgentAssistParser LOGIC_COLOR
participant ":DeleteCommandParser" as DeleteCommandParser LOGIC_COLOR
participant "d:DeleteCommand" as DeleteCommand LOGIC_COLOR
participant "r:CommandResult" as CommandResult LOGIC_COLOR
Expand All @@ -17,17 +17,17 @@ end box
[-> LogicManager : execute("delete 1")
activate LogicManager

LogicManager -> AddressBookParser : parseCommand("delete 1")
activate AddressBookParser
LogicManager -> AgentAssistParser : parseCommand("delete 1")
activate AgentAssistParser

create DeleteCommandParser
AddressBookParser -> DeleteCommandParser
AgentAssistParser -> DeleteCommandParser
activate DeleteCommandParser

DeleteCommandParser --> AddressBookParser
DeleteCommandParser --> AgentAssistParser
deactivate DeleteCommandParser

AddressBookParser -> DeleteCommandParser : parse("1")
AgentAssistParser -> DeleteCommandParser : parse("1")
activate DeleteCommandParser

create DeleteCommand
Expand All @@ -37,14 +37,14 @@ activate DeleteCommand
DeleteCommand --> DeleteCommandParser :
deactivate DeleteCommand

DeleteCommandParser --> AddressBookParser : d
DeleteCommandParser --> AgentAssistParser : d
deactivate DeleteCommandParser
'Hidden arrow to position the destroy marker below the end of the activation bar.
DeleteCommandParser -[hidden]-> AddressBookParser
DeleteCommandParser -[hidden]-> AgentAssistParser
destroy DeleteCommandParser

AddressBookParser --> LogicManager : d
deactivate AddressBookParser
AgentAssistParser --> LogicManager : d
deactivate AgentAssistParser

LogicManager -> DeleteCommand : execute(m)
activate DeleteCommand
Expand Down
12 changes: 6 additions & 6 deletions docs/diagrams/ModelClassDiagram.puml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ skinparam arrowThickness 1.1
skinparam arrowColor MODEL_COLOR
skinparam classBackgroundColor MODEL_COLOR

Class "<<interface>>\nReadOnlyAddressBook" as ReadOnlyAddressBook
Class "<<interface>>\nReadOnlyAgentAssist" as ReadOnlyAgentAssist
Class "<<interface>>\nReadOnlyUserPrefs" as ReadOnlyUserPrefs
Class "<<interface>>\nModel" as Model
Class AddressBook
Class AgentAssist
Class ModelManager
Class UserPrefs

Expand All @@ -25,16 +25,16 @@ Class I #FFFFFF
Class HiddenOutside #FFFFFF
HiddenOutside ..> Model

AddressBook .up.|> ReadOnlyAddressBook
AgentAssist .up.|> ReadOnlyAgentAssist

ModelManager .up.|> Model
Model .right.> ReadOnlyUserPrefs
Model .left.> ReadOnlyAddressBook
ModelManager -left-> "1" AddressBook
Model .left.> ReadOnlyAgentAssist
ModelManager -left-> "1" AgentAssist
ModelManager -right-> "1" UserPrefs
UserPrefs .up.|> ReadOnlyUserPrefs

AddressBook *--> "1" UniquePersonList
AgentAssist *--> "1" UniquePersonList
UniquePersonList --> "~* all" Person
Person *--> "1" Name
Person *--> "1" Phone
Expand Down
10 changes: 5 additions & 5 deletions docs/diagrams/ParserClasses.puml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Class CombinedPredicate

package "Parser classes"{
Class "<<interface>>\nParser" as Parser
Class AddressBookParser
Class AgentAssistParser
Class XYZCommandParser
Class FilterCommandParser
Class CliSyntax
Expand All @@ -22,15 +22,15 @@ Class Prefix
}

Class HiddenOutside #FFFFFF
HiddenOutside ..> AddressBookParser
HiddenOutside ..> AgentAssistParser

AddressBookParser .down.> XYZCommandParser: <<create>>
AddressBookParser .down.> FilterCommandParser: <<create>>
AgentAssistParser .down.> XYZCommandParser: <<create>>
AgentAssistParser .down.> FilterCommandParser: <<create>>

XYZCommandParser ..> XYZCommand : <<create>>
FilterCommandParser ..> FilterCommand : <<create>>
FilterCommandParser ..> CombinedPredicate : <<create>>
AddressBookParser ..> Command : <<use>>
AgentAssistParser ..> Command : <<use>>
XYZCommandParser .up.|> Parser
XYZCommandParser ..> ArgumentMultimap
XYZCommandParser ..> ArgumentTokenizer
Expand Down
18 changes: 9 additions & 9 deletions docs/diagrams/StorageClassDiagram.puml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ Class JsonUserPrefsStorage
Class "<<interface>>\nStorage" as Storage
Class StorageManager

package "AddressBook Storage" #F4F6F6{
Class "<<interface>>\nAddressBookStorage" as AddressBookStorage
Class JsonAddressBookStorage
Class JsonSerializableAddressBook
package "AgentAssist Storage" #F4F6F6{
Class "<<interface>>\nAgentAssistStorage" as AgentAssistStorage
Class JsonAgentAssistStorage
Class JsonSerializableAgentAssist
Class JsonAdaptedPerson
Class JsonAdaptedTag
}
Expand All @@ -29,15 +29,15 @@ HiddenOutside ..> Storage

StorageManager .up.|> Storage
StorageManager -up-> "1" UserPrefsStorage
StorageManager -up-> "1" AddressBookStorage
StorageManager -up-> "1" AgentAssistStorage

Storage -left-|> UserPrefsStorage
Storage -right-|> AddressBookStorage
Storage -right-|> AgentAssistStorage

JsonUserPrefsStorage .up.|> UserPrefsStorage
JsonAddressBookStorage .up.|> AddressBookStorage
JsonAddressBookStorage ..> JsonSerializableAddressBook
JsonSerializableAddressBook --> "*" JsonAdaptedPerson
JsonAgentAssistStorage .up.|> AgentAssistStorage
JsonAgentAssistStorage ..> JsonSerializableAgentAssist
JsonSerializableAgentAssist --> "*" JsonAdaptedPerson
JsonAdaptedPerson --> "*" JsonAdaptedTag

@enduml
Loading