{ list here sources of all reused/adapted ideas, code, documentation, and third-party libraries -- include links to the original source as well }
Refer to the guide Setting up and getting started.
The Architecture Diagram given above explains the high-level design of the App.
Given below is a quick overview of main components and how they interact with each other.
Main components of the architecture
Main (consisting of classes Main and MainApp) is in charge of the app launch and shut down.
The bulk of the app's work is done by the following four components:
UI: The UI of the App.Logic: The command executor.Model: Holds the data of the App in memory.Storage: Reads data from, and writes data to, the hard disk.Commons represents a collection of classes used by multiple other 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.
Each of the four main components (also shown in the diagram above),
interface with the same name as the 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.
The API of this component is specified in 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 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 is specified in MainWindow.fxml
The UI component,
Logic component.Model data so that the UI can be updated with the modified data.Logic component, because the UI relies on the Logic to execute commands.Model component, as it displays Person object residing in the Model.API : 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.
Note: The lifeline for DeleteCommandParser should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline continues till the end of diagram.
How the Logic component works:
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.Command object (more precisely, an object of one of its subclasses e.g., DeleteCommand) which is executed by the LogicManager.Model when it is executed (e.g. to delete a person).Model) to achieve.CommandResult object which is returned back from Logic.Here are the other classes in Logic (omitted from the class diagram above) that are used for parsing a user command:
How the parsing works:
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.XYZCommandParser classes (e.g., AddCommandParser, DeleteCommandParser, ...) inherit from the Parser interface so that they can be treated similarly where possible e.g, during testing.API : Model.java
The Model component,
Person objects (which are contained in a UniquePersonList object).Person objects (e.g., results of a search query) as a separate filtered list which is exposed to outsiders as an unmodifiable ObservableList<Person> 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.UserPref object that represents the user’s preferences. This is exposed to the outside as a ReadOnlyUserPref objects.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.

API : Storage.java
The Storage component,
CLinkedinStorage and UserPrefStorage, which means it can be treated as either one (if only the functionality of only one is needed).Model component (because the Storage component's job is to save/retrieve objects that belong to the Model)Classes used by multiple components are in the seedu.clinkedin.commons package.
This section describes some noteworthy details on how certain features are implemented.
The findcom command allows users to find contacts whose company matches one or more keywords.
When the command is executed, the system first checks whether any company keyword was provided. If the input is empty, the command fails and an error message is shown.
If input is provided, the system updates the filtered contact list to show contacts whose company matches any of the given keywords, case-insensitively.
The following activity diagram illustrates the decision flow of the findcom command:
The following sequence diagram illustrates how the findcom command is handled by the system components:
The sortcom command allows users to sort the currently displayed contact list alphabetically by company name.
Note: The sorting operation is applied only to the filtered contact list (i.e., the currently displayed contacts), not the entire dataset.
When the command is executed, the system sorts the filtered contact list by company name in a case-insensitive manner. Contacts without a company are treated as having an empty value and will appear at the top of the displayed list. The sorted list is then shown to the user together with a success message.
The following activity diagram illustrates the flow of the sortcom command:
The following sequence diagram illustrates how the sortcom command is handled by the system components:
The restore command allows users to restore a previously deleted contact from the deleted contacts list.
Users can use the deleted command to view the list of deleted contacts and identify the correct index for restoration.
Contacts can only be restored within 7 days of deletion.
When the command is executed, the system first checks whether the provided index is valid in the deleted contacts list. If the index is invalid, the command fails and an error message is shown.
If the index is valid, the system checks whether restoring the contact would cause a conflict, such as a duplicate phone number or an already existing contact. If such a conflict exists, the command fails.
If restoration is allowed, the contact is added back to the main contact list and removed from the deleted contacts list. Tags whose names no longer exist will not be restored. Tags whose names still exist will be restored using their current tag definitions.
The following activity diagram illustrates the decision flow of the restore command:
The following sequence diagram illustrates how the restore command is handled by the system components:
The tag create command allows users to create a new tag with an optional colour.
When the command is executed, the system first checks whether a tag with the same name already exists. Since duplicate tag names are not allowed, the command fails if the tag already exists.
If the tag name is valid and no duplicate is found, the system checks whether a colour was provided. If no colour is specified, a default colour is assigned. The tag is then added to the tag list.
The following activity diagram illustrates the decision flow of the tag create command:
The following sequence diagram illustrates how the tag create command is handled by the system components:
The tag delete command allows users to delete an existing tag.
When the command is executed, the system first checks whether the specified tag exists. If the tag does not exist, the command fails and an error message is shown.
If the tag exists, the tag is removed from the tag list. The system then removes that tag from all contacts currently using it, while leaving all other tags on those contacts unchanged.
The following activity diagram illustrates the decision flow of the tag delete command:
The following sequence diagram illustrates how the tag delete command is handled by the system components:
The tag assign command allows users to assign an existing tag to one or more contacts at once.
When the command is executed, the system first verifies that the specified tag exists in the tag list. If it does, it checks that all provided contact indices are valid. If any index is invalid, the command aborts to prevent partial execution. Upon successful validation, the tag is added to the specified contacts, and the model is updated.
The following activity diagram illustrates the decision flow:
The following sequence diagram illustrates the execution:
The tag unassign command allows users to unassign an existing tag to one or more contacts at once.
When the command is executed, the system first verifies that the specified tag exists in the tag list. If it does, it checks that all provided contact indices are valid and has the specified tag. If any index is invalid or one or more user does not have the tag, the command aborts to prevent partial execution. Upon successful validation, the tag is removed from the specified contacts, and the model is updated.
The following activity diagram illustrates the decision flow:
The following sequence diagram illustrates the execution:
The tag rename commands allow users to modify the name of an existing tag, while also replacing the tag attached to the respective contacts.
Because tags are immutable objects in this architecture, modifying a tag requires replacing it. The system first validates that the old tag exists. It then creates the new tag in the global CLinkedin tag list and attach it to the contacts containing the old tag through iteration. Finally, it removes the old tag from the tag list.
The following activity diagram illustrates the decision flow:
The sequence diagram below illustrates the execution:
Target user profile:
Value proposition: Helps NUS SoC students manage and recall networking contacts quickly by providing a structured, command-line address book tailored for technical users.
Priorities: High (must have) - * * *, Medium (nice to have) - * *, Low (unlikely to have) - *
| Priority | As a … | I want to … | So that I can… |
|---|---|---|---|
* * * | new user | add a new contact with name, phone number and email | store and connect with them |
* * * | new user | click on a contact link | view their social media page or company website |
* * * | new user | edit contact details | update information without deleting and recreating contacts |
* * * | new user | receive clear error messages | correct mistakes when I input invalid commands |
* * * | new user | search a contact by name | find the person I’m connecting with quickly |
* * * | new user | view command instructions | quickly recall available commands and their valid formats |
* * * | organised user | add a tag to a contact | categorise a group of people together |
* * * | organised user | create and delete my own tags | categorise contacts the way I like |
* * * | organised user | list all contacts under a specific tag | quickly see related connections and contacts |
* * * | organised user | remove a tag from a contact | re-categorise people |
* * * | organised user | rename a tag | keep my tagging system consistent |
* * * | organised user | sort contacts by company | view grouped workplace connections |
* * * | organised user | view all existing tags | know how contacts are categorised |
* * * | networking-focused user | search for contacts in a specified company | quickly find all my connections working at the company |
* * | new user | add remarks to contacts | store more personal information (like hobbies/interests) |
* * | organised user | colour code my tags | visually distinguish categories |
* * | expert user | search using partial keywords | avoid remembering exact spelling |
* * | expert user | see date when contact was added | recall when I met someone |
* * | expert user | search for contacts in multiple specified companies | view a combined list of connections from specified companies fast and efficiently |
* * | networking-focused user | add meaningful remarks about a contact | recall conversations for networking purpose |
* | user with many persons in the address book | find contacts by name | locate a person easily |
* | expert user | recover deleted contacts | restore accidentally removed contacts |
* | expert user | tag multiple contacts at once | group people fast and efficiently |
(For all use cases below, the System is the CLinkedin and the Actor is the user, unless specified otherwise)
Preconditions:
Guarantees:
User requests to list contacts.
CLinkedin displays the list of contacts.
User requests to edit a contact by entering the edit command with the contact's index and the fields to be updated.
CLinkedin validates the provided index and updated field values.
CLinkedin updates the contact with the new details.
CLinkedin displays a success message with the edited contact's details.
Use case ends.
3a. The user provides an index that does not exist in the list.
3a1. CLinkedin shows an error message that the index is invalid.
Use case resumes at step 1.
3b. The user provides an invalid command format.
3b1. CLinkedin shows an error message that the command format is invalid.
Use case resumes at step 1.
4a. The updated field value is invalid.
4a1. CLinkedin shows an error message indicating which field value is invalid.
Use case resumes at step 1.
4b. The updated phone number already exists in another contact.
4b1. CLinkedin shows an error message that the phone number already exists in the list.
Use case resumes at step 1.
Preconditions:
Guarantees:
User requests to list contacts.
CLinkedin displays the list of contacts.
User requests to delete a contact by entering the delete command with the contact's index.
CLinkedin validates that the provided index is valid.
CLinkedin removes the contact from the contact list and stores it in the deleted contacts list with a timestamp.
CLinkedin displays a success message that the contact has been deleted.
Use case ends.
3a. The user provides an index that does not exist in the list.
3a1. CLinkedin shows an error message that the index is invalid.
Use case resumes at step 1.
3b. The user provides an invalid command format.
3b1. CLinkedin shows an error message that the command format is invalid.
Use case resumes at step 1.
Preconditions:
Guarantees:
User requests to create a tag with a name and an optional color.
CLinkedin validates the provided tag details.
CLinkedin creates the tag.
CLinkedin displays a success message.
Use case ends.
2a. The tag name already exists.
2a1. CLinkedin shows an error message that the tag already exists.
Use case resumes at step 1.
2b. The tag color format is invalid.
2b1. CLinkedin shows an error message that the tag color format is invalid.
Use case resumes at step 1.
Preconditions:
Guarantees:
User requests to rename a tag.
CLinkedin validates the new tag name.
CLinkedin updates the tag name.
CLinkedin updates all contacts that contain the tag.
CLinkedin displays a success message.
Use case ends.
2a. The new tag name already exists.
2a1. CLinkedin shows an error message that the tag name already exists.
Use case resumes at step 1.
1a. User requests to change a tag's color.
1a1. CLinkedin validates the new color value.
1a2. CLinkedin updates the tag color.
1a3. CLinkedin displays a success message.
Use case ends.
1b. User requests to delete a tag.
1b1. CLinkedin removes the tag from the tag list.
1b2. CLinkedin removes the tag from all associated contacts.
1b3. CLinkedin displays a success message.
Use case ends.
Preconditions:
Guarantees:
User requests to assign a tag to one or more contacts.
CLinkedin validates the provided contact indexes and tag name.
CLinkedin assigns the tag to the specified contacts.
CLinkedin displays a success message.
Use case ends.
2a. The user provides an invalid contact index.
2a1. CLinkedin shows an error message that the index is invalid.
Use case resumes at step 1.
2b. The tag does not exist.
2b1. CLinkedin shows an error message that the tag does not exist.
Use case resumes at step 1.
1a. User requests to unassign a tag from one or more contacts.
1a1. CLinkedin validates the provided contact indexes and tag name.
1a2. CLinkedin removes the tag from the specified contacts.
1a3. CLinkedin displays a success message.
Use case ends.
Preconditions:
Guarantees:
User requests to find contacts by entering the findcom command with one or more company keywords.
CLinkedin parses the input keywords.
CLinkedin filters the contact list to include contacts whose company matches any of the keywords.
CLinkedin displays the filtered list of contacts along with a summary message.
Use case ends.
1a. The user provides no keywords.
1a1. CLinkedin shows an error message that the command format is invalid.
Use case resumes at step 1.
2a. The input format is invalid.
2a1. CLinkedin shows an error message that the command format is invalid.
Use case resumes at step 1.
3a. No contacts match the given keywords.
3a1. CLinkedin displays an empty list with a summary message indicating 0 contacts found.
Use case ends.
Preconditions:
Guarantees:
User requests to sort contacts by entering the sortcom command.
CLinkedin sorts the currently displayed contact list alphabetically by company name (case-insensitive).
CLinkedin displays the sorted contact list.
CLinkedin displays a success message.
Use case ends.
1a. The user provides an invalid command format.
1a1. CLinkedin shows an error message that the command format is invalid.
Use case resumes at step 1.
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
Double-click the jar file 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 double-clicking the jar file.
Expected: The most recent window size and location is retained.
{ more test cases … }
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.
{ more test cases … }
Dealing with missing/corrupted data files
{ more test cases … }