WedLinker is based on the AddressBook-Level3 project created by the SE-EDU initiative.
Refer to the guide Setting up and getting started.
The Architecture Diagram given below explains the high-level design of the App, giving a quick overview of main components and how they interact with each other.
Main components of the architecture
The bulk of the app's work is done by the UI
, Logic
, Model
, and Storage
components.
Main
:
UI
:
Model
.data/addressbook.json
file.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
.
Each of the four main components (also shown in the diagram above),
interface
with the same name as {Component}
.{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.
The sections below give more details of each component.
(Ui.java
)
The UI
component handles interactions between the user and the app's graphical interface, leveraging JavaFX to define and display various UI elements.
Structure:
UI
consists of a MainWindow
composed of several parts like CommandBox
, StatusBarFooter
, ResultDisplay
, and various *ListPanel
s.MainWindow
, inherits from the abstract class
(UiPart
),
capturing commonalities among visible GUI components.Class Diagram:
Diagram showing the UI
structure:
JavaFX and Layout Files:
.fxml
files in the
src/main/resources/view
,MainWindow
,
is specified in
MainWindow.fxml
,Responsibilities:
Logic
component.Model
data to refresh the UI with modified information.Logic
, relying on it for command execution.Model
classes to display Person
objects managed within Model
.The Logic
component processes user inputs passed through the UI, utilizing a series of parsers to generate Command
instances, which are then executed. Here’s an overview:
User Input Processing:
Logic
.AddressBookParser
, which delegates to the appropriate parser (e.g., DeleteCommandParser
), creating the relevant Command
instance.LogicManager
executes the Command
, interacting with the Model
to make necessary updates (e.g., deleting a person).CommandResult
and returned to Logic
, which relays the outcome back to the UI.Class Diagram:
Partial diagram of the Logic
component:
Sequence Diagram:
Example interaction in the Logic
component for execute("delete 1")
(from user inputting delete 1 on UI):
Parser Classes:
Other classes in Logic
handle command parsing:
Parsing flow:
AddressBookParser
identifies the specific command parser needed (e.g., AddCommandParser
, DeleteCommandParser
).XYZCommandParser
(e.g., AddCommandParser
) implements the Parser
interface, allowing for consistent handling and testing.Command
object (e.g., AddCommand
), which AddressBookParser
returns to Logic
.The Model
component handles the data and state management for the app, storing all entities and providing an interface for accessing and updating them.
Structure:
Model
stores various types of data:
Person
objects within a UniquePersonList
.Wedding
objects within a UniqueWeddingList
.Task
objects within a UniqueTaskList
.Class Diagram:
Diagram of the Model
structure:
Responsibilities:
Person
, Wedding
, and Task
objects.Person
, Wedding
, and Task
objects (e.g., search results), exposing these as unmodifiable ObservableList
s. This allows the UI to automatically update in response to changes.UserPref
object, which is accessible externally as ReadOnlyUserPref
.Model
does not rely on other components, as it represents the app’s core data entities, which should be logically self-contained.Functionality:
Inheritance:
AddressBookStorage
and UserPrefStorage
, allowing it to be used interchangeably with either interface, depending on the functionality needed.Dependencies:
Model
component, as Storage
is tasked with saving and retrieving Model
-related objects.Class Diagram:
Diagram illustrating Storage
structure:
Classes used by multiple components are in the
seedu.address.commons
package.
Notable classes include StringUtil
and ToStringBuilder
which help to perform operations like checking whether a string
includes non-zero unsigned integer, or whether there is a partial match for a word. These can be found in
seedu.address.commons.util
.
This section describes some noteworthy details on how certain features are implemented.
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.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 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 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
.
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
.
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.
Note: If the currentStatePointer
is at index 0, pointing to the initial AddressBook state, then there are no previous AddressBook states to restore. The undo
command uses Model#canUndoAddressBook()
to check if this is the case. If so, it will return an error to the user rather
than attempting to perform the undo.
The following sequence diagram shows how an undo operation goes through the Logic
component:
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.
Similarly, how an undo operation goes through the Model
component is shown below:
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.
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.
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.
The following activity diagram summarizes what happens when a user executes a new command:
Aspect: How undo & redo executes:
Alternative 1 (current choice): Saves the entire address book.
Alternative 2: Individual command knows how to undo/redo by itself.
delete
, just save the person being deleted).{more aspects and alternatives to be added}
{Explain here how the data archiving feature will be implemented}
Target user profile: Professional Wedding Planners
Value proposition: compilation of all contacts necessary in weddings in one location making management easier
Priorities:
High (must have) - * * *
, Medium (nice to have) - * *
, Low (unlikely to have) - *
Those without any stars are user stories that were considered but will not be implemented at this time.
Priority | As a … | I want to … | So that… |
---|---|---|---|
* * * | user | add tag(s) to each contact based on created tags such as florist, musician etc. | I can easily understand the group this person belongs to. |
* * * | user | add a phone number associated with each contact | I can easily find the contact information for each contact. |
* * * | user | add the address associated with each contact | I can easily find the address of each contact. |
* * * | user | filter contacts by tag | I can quickly see all the groups under the same tag, and find the right vendor based on the type of services provided. |
* * * | user | add new contacts into WedLinker | I can store the contact details of new contacts. |
* * * | user | delete contacts that are no longer needed | I can remove unnecessary contacts and have a more organised address book. |
* * * | user | search for contact by name | I can find specific contacts that I am looking for. |
* * * | user | create tags | I can have special categories for non traditional vendors. |
* * | user | edit information such as the contact number and address of each contact | all contacts have the most updated information. |
* * | user | clear all the contacts in the system | I can clear all my contacts quickly without having to individually delete them if I want to add in a completely new set of contacts. |
* * | careless user | receive a prompt that requires me to key in a confirmation that I want to delete a contact or clear the address book | I will not lose all my contacts when I accidentally type delete/ clear. |
* * | user | assign each guest contact its dietary requirements status | I can track the dietary requirement of each guest. |
* * | user | sort contacts by alphabetical order | I can easily find the contacts required in a large address book. |
* * | user | assign additional information for each contact | I can include important notes that may not fit into other categories, such as reminders for what the contact might need. |
* * | first-time user | see some sample contacts already available in the app | I can try out the different features without needing to add my own data (e.g allocating people to wedding, allocating task to contacts). |
* * | careless, first-time user | reload the sample contacts into the app | I can continue trying out different features without needing to add my own data in case I accidentally cleared the contacts. |
* * | first-time user | see a help message showing all the commands/feature I can use | I can try out all the different features by referring to the message. |
* | user | assign tasks to contacts | I can track which tasks have been assigned to each contact. |
* | user | update the status of tasks of contacts | I can track the status of completion of the tasks assigned to contacts. |
* | user | add a tag to each guest indicating their table number | track the table each guest is seated at. |
* | user | key in the table number and get the list of guests seated at that table | I can quickly identify all the groups seated at one table. |
* | user | assign a rating out of 5 to each vendor | I can track the experience with this vendor for future reference. |
* | busy user | add multiple wedding events | I can track contacts for multiple weddings at once. |
* | busy user | tag each contact to a wedding | I can easily see which contacts are relevant to which wedding. |
* | user | assign dates to a wedding | I can keep track of when different weddings are scheduled. |
* | user | assign dates to a wedding | I can keep track of when different weddings are scheduled. |
* | user | filter contacts by wedding | I can keep track of which contacts are relevant for each wedding. |
* | user | send out (standardised formatted) information (text/email) from the application | I can efficiently send out information without any mistakes. |
* | user | share the contact details to relevant third-parties for bookings (eg: venue bookings, suit/dress rental, etc.) | I can easily send out all relevant information (including dietary restriction, and other tags) to all the third-parties. |
* | user | exclude tags from search and filter | I can focus on contacts that are relevant to certain events or requirements without being overwhelmed by unnecessary information. |
* | busy user | autocomplete existing tags when user is inputting tag information | I can quickly assign roles for people that might be working with others I have already input into the system and not have to type the same roles in multiple times. |
* | user | assign availability to vendors | I can check who will be available for a particular wedding. |
* | user | filter availability of vendors | I can easily find vendors that can cater to a wedding. |
* | user | store multiple contact methods | I can contact the vendors through different means. |
* | user | re-assign tasks to another contact | I can account for vendors suddenly being unavailable. |
* | user | set reminders for tasks to different contacts | I can easily track and follow up with clients and vendors for deliverables. |
* | user | see a list of all tasks and reminders I have assigned to contacts in its own window | I can quickly and easily see what my earliest priorities are and act on them quickly. |
* | user | see a calendar view of tasks, reminders, and weddings I have assigned | I can see the whole timelines of my planned weddings and see how much time there is between tasks. |
* | user | set privacy setting for different contacts | I can keep personal and sensitive information private when sharing address book. |
* | forgetful user | create links between different contacts, such as assigning a vendor to a bride or groom in a wedding | I can easily navigate from key stakeholders in the wedding that I remember better to vendors who I might not remember as well. |
* | user | add certain vendors as favorites | I can remember which vendors performed well and see if they are favorites. |
* | user | access a list of all my favorite vendors | I can easily check who the best vendors were that I previously engaged with. |
user | generate a checklist of all the contacts for a particular wedding, grouped by roles | I can keep track of who is meant to be present at the wedding. | |
user | assign a time for each contact for when they are meant to arrive | I can easily keep track of which people are on time and check who to contact in case they have not arrived yet. | |
user | attach extra documents as a file to various contacts | I can store all the information in one place, eg. Invoices from a vendor. | |
user | categorize tasks based on its nature (e.g. procurement, arrangement) | I can view tasks in a more organised manner. |
(For all use cases below, the System is the WedLinker
and the Actor is the user
, unless specified otherwise)
Use Cases beginning with 'UC' cover core Wedlinker functionalities.
Use Cases beginning with 'UCSH' cover non-core Wedlinker functionalities.
MSS
User requests to view all contacts.
The system retrieves and displays the list of all contacts to the user.
Use case ends.
Similar to UC01 except to view weddings instead of contacts.
Similar to UC01 except to view tasks instead of contacts.
MSS
User requests to create a contact with the corresponding details.
The system adds the contact and displays a success message.
The system shows the new contact in WedLinker.
Use case ends.
Extensions
1a1. System does not create a new contact.
1a2. System informs the user the contact already exists.
Use case ends.
Similar to UC04 except adding a wedding to WedLinker instead of a Contact
Similar to UC04 except adding a task to WedLinker instead of a Contact
Guarantees:
MSS
User lists all contacts (UC01).
User requests to add phone number for a contact with the corresponding details.
The system adds the phone number to the contact and displays a success message.
The system displays the updated contact information in the address book.
Use case ends.
Extensions
1a. The list is empty. Use case ends.
2a. The system detects an error in the entered data.
2a1. The system displays an error message
Use case resumes at step 1.
Similar to UC07 except duplicated addresses are allowed
Similar to UC07 except duplicated email addresses are allowed
MSS
User searches for the contact by name.
System shows a list of contacts containing the name.
Use case ends.
Similar to UC10 except searching for contacts by tag.
Similar to UC10 except searching for contacts by wedding.
Similar to UC10 except searching for contacts by phone number.
Similar to UC10 except searching for contacts by address.
Similar to UC10 except searching for contacts by email address.
Similar to UC10 except searching for wedding by wedding name.
Similar to UC10 except searching for task by task name.
MSS
User lists all contacts (UC01).
User requests to delete a specific person in the list.
System deletes the contact.
Use case ends.
Extensions
1a. The list is empty. Use case ends.
2a. The to-be-deleted contact is invalid.
Similar to UC18 except deleting wedding.
Similar to UC18 except deleting task.
Similar to UC18 except deleting tag.
MSS
Extensions
1a. The list is empty.
Use case ends.
2a. The given index is invalid.
2a1. System shows an error message prompting the user to put in a valid index.
Use case resumes at step 1.
2b. The user does not specify what type of details they want to change.
2b1. System shows an error message prompting the user to put in the type of details they want to edit.
Use case resumes at step 1.
2c. The user does not specify what the new details should be.
2c1. System shows an error message prompting the user to put in the new details.
Use case resumes at step 1.
2d. The user specifies details that do not meet the requirements of the detail type.
2d1. System shows an error message prompting the user with the correct detail type format and requirements.
Use case resumes at step 1.
Similar to USCH01 except editing for wedding.
Guarantees:
MSS
User requests to clear all contact.
System deletes all contacts and shows a blank list of persons.
Use case ends.
Preconditions: User has not added or edited contacts previously.
MSS
User opens the application.
System shows a list of sample contacts.
Use case ends.
MSS
User deletes save file of WedLinker.
System shows a list of sample contacts upon restarting application.
Use case ends.
MSS
User requests to see a list of all possible commands they can use in the system.
System shows a link to the list of commands with their corresponding input format.
Use case ends.
Performance Requirements
Usability Requirements
Compatibility Requirements
17
or above installed.Data Requirements
Documentation Requirements
Development Process Requirements
Reliability and Stability Requirements
Maintainability Requirements
Quality Requirements
Given below are instructions to test the app manually.
Note: These instructions only provide a starting point for testers to work on; testers are expected to do more exploratory testing.
Initial launch
Download the jar file and copy into an empty folder
Open terminal and change into the directory where the jar file is stored.
Enter java -jar WedLinker.jar
into the terminal to run the WedLinker application.
Expected: Shows the GUI with a set of sample contacts. The window size may not be optimum.
Saving window preferences
Resize the window to an optimum size. Move the window to a different location. Close the window.
Re-launch the app by enter java -jar WedLinker.jar
into the terminal again.
Expected: The most recent window size and location is retained.
Deleting a person while all persons are being shown
Prerequisites: List all persons using the list
command. Multiple persons in the list.
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.
Test case: delete 0
Expected: No person is deleted. Error details shown in the status message. Status bar remains the same.
Other incorrect delete commands to try: delete
, delete x
, ...
(where x is larger than the list size)
Expected: Similar to previous.
Dealing with missing/corrupted data files
Upon booting up WedLinker and the contact/address/task list is not as per expected, open the docs
folder where WedLinker.jar
is stored.
Within the folder, open AddressBook.json
and identify any mistakes with stored data.
The terminal from where WedLinker.jar
is launched should log where the file is corrupted.
If the data is beyond repair, delete the entire docs
folder and the AddressBook.json
file to start afresh.