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 i/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 i/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 NetConnectParser
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:
NetConnectParser
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 NetConnectParser
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
Here's a (partial) class diagram of the Model
component:
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. This filtered list is further filtered by the Filter classes.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 NetConnect
, which Person
references. This allows NetConnect
to only require one Tag
object per unique tag, instead of each Person
needing their own Tag
objects.
Here are the other classes in Model
(omitted from the class diagram above) that are used for filtering the list that is displayed to users:
How the filtering works:
ModelManager
stores only one instance of Filter
at any one time. The stored Filter
instance in turn stores all the XYZPredicate
objects currently applied to the filtered view.FilteredList#setPredicate(...)
is called with the Filter
instance, and only shows all Person
objects that satisfy all predicates in Filter
.API : Storage.java
The Storage
component,
state.txt
in the data folder.NetConnectStorage
, UserPrefStorage
as well as StateStorage
, 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.netconnect.commons
package.
This section describes some noteworthy details on how certain features are implemented.
The export
command allows users to export contact data from NetConnect into a CSV file. Users have the option to specify a file name. If no file path is provided, the CSV file is saved as a default name. The command exhibits the following exceptional behaviors:
The successful execution of the export
command results in the creation of a CSV file as the specified or default name at default location, containing all the contact data available in NetConnect.
A ExportCommand
instance is created in the ExportCommandParser#parse(...)
method when the user issues the export
command. The process involves the following steps:
CsvExporter
component to write the data to the CSV file.The sequence diagram below illustrates the execution of a ExportCommand
:
The sequence diagram below illustrates the creation and execution of a CsvExporter
:
Aspect: Handling of file paths in the export
command:
The person can be categorized into three roles: Client
, Supplier
, and Employee
. These classes extend the base Person
class and encapsulate various role-specific functionalities and attributes, improving the application's ability to cater to a diverse range of user interactions.
The Person
class is extended by three other classes, each with their own additional attributes:
Client
Subclass contains products
attribute of type Products
, representing the products associated with the client, and contains preferences
as a String
, detailing client-specific preferences.
Supplier
Subclass contains products
attribute of type Products
, which lists the items supplied, and holds termsOfService
of type TermsOfService
, outlining the agreement with the supplier.
Employee
Subclass includes a department
attribute of type Department
, signifying the department the employee belongs to, has a jobTitle
attribute of type JobTitle
, representing the employee's official title, and features skills
of type Skills
, indicating the competencies of the employee.
Client
, Supplier
, and Employee
classes have been added, extending the Person
class to include role-specific fields.Department
, JobTitle
, Products
, Skills
, and TermsOfService
are introduced to encapsulate relevant attributes.JsonAdaptedPerson
class has been implemented to support the conversion to and from the new role-based classes, ensuring compatibility with the enhanced JSON schema.Employee
to the system.Aspect: How to distinguish the person role:
Alternative 1 (current choice): Creation of subclasses Supplier
, Employee
, and Client
that inherit from the Person
class.
Alternative 2: Introducing a type
field within the Person
class to indicate the person's role and including all possible fields for all types.
Person
class could simplify the system.Person
object will have redundant fields that are not applicable to all types, leading to wasted storage space and potential confusion.The save state feature is implemented using the TextStateStorage
which implements StateStorage
interface. It is responsible for saving the state of the command box. The state is saved in a file called state.txt
in the data folder. The state is updated at each change in the input. Additionally, it implements the following operations:
TextStateStorage#saveState(String state)
— Saves the current state of the command box into file.TextStateStorage#readState()
— Reads the saved state of the command box from the file and returns the string.TextStateStorage#clearState()
— Clears the file storing the states.TextStateStorage#isStateStorageExists()
— Checks if the file storing the states exists.TextStateStorage#deleteStateStorage()
— Deletes the file storing the states.TextStateStorage#getStateStorageFilePath()
— Returns the file path of the file storing the states.TextStateStorage#getFilePathString()
— Returns the file path of the file storing the states as a string.TextStateStorage#getDirectoryPath()
— Returns the directory path of the file storing the states.Given below is an example usage scenario and how the save state feature behaves at each step.
Step 1. The user launches the application. During set up, the presence of the state storage file is checked. If absent, a new storage file is created. When the command box is instantiated, it calls the TextStateStorage#readState()
method to get the last command that was present in the command box before it was last closed. The text in the file is retrieved and loaded into the command box using TextField#setText
.
Note: If the storage file is not found a new empty file is created.
Step 2. The user changes the input in the command box. The TextStateStorage#saveState(String state)
method is called to save the current state of the command box into the file.
Aspect: How save state executes:
Alternative 1 (current choice): Update the storage file at every change in input.
Alternative 2: Update the storage file only when the application is closed.
Alternative 3: Update the storage file when there is a pause in typing.
The relate
command allows users to relate two persons via their unique ID
. Exceptional behavior:
ID
provided by user does not exist, an error message is displayed.ID
provided is not an integer value that is more than 0, an error message is displayed.Given a command relate i/1 i/2
, the NetConnectParser
recognises the relate
command and first instantiates a RelateCommandParser
object. It then passes the command string into RelateCommandParser#parse(...)
, where the input i/1
and i/2
is validated for its format. Following which, RelateCommandParser
instantiates a RelateCommand
object.
TheRelateCommand
object extends the Command
interface, and hence contains a method called execute(...)
, which takes in a model
. A model can be thought of as a container for the application's data, and it also controls the exact contact list that the user will see. In the execute(...)
command, we validate that NetConnect has both IDs 1
and 2
and, does not already have a relation. We add it to our RelatedList storage if both are true. To change our view and to ratify the successful command, we will have to change the view the user sees by instantiating a predicate called IdContainsDigitsPredicate
. We will then pass it into the model#stackFilters(predicate)
method in the model
object to update the filtered list of persons to only include the two people with ID 1
and 2
.
Recalling that we also have a message box to inform the result of the actions taken (in prose form), the RelateCommand#execute(...)
method will also return a CommandResult
object, which contains the summary of the number of people listed.
Aspect: How to store relations between contacts
Alternative 1 (current choice): Store the Related List within the NetConnect model as a JSON file. Each time a relate command is done, we will just have to save the NetConnect model.
Alternative 2 (previously implemented): Store the Related List as a .txt file.
Alternative 3: Store Relations as another field in every person. A relate command would add the opposing contact to both persons provided.
The showrelated
command allows users to view all persons related to a specific person via their unique ID
. Exceptional behavior:
ID
provided by user, an error message is displayed.ID
provided is not an integer value that is more than 0, an error message is displayed.Given a command showrelated i/1
, the NetConnectParser
recognises the showrelated
command and first instantiates a ShowRelatedCommandParser
object. It then passes the command string into ShowRelatedCommandParser#parse(...)
, where the input i/1
is validated for its format. Following which, ShowRelatedCommandParser
instantiates a ShowRelatedCommand
object.
TheShowRelatedCommand
object extends the Command
interface, and hence contains a method called execute(...)
, which takes in a model
. A model can be thought of as a container for the application's data, and it also controls the exact contact list that the user will see. In the execute(...)
command, we extract all the tuples that contain ID 1
and use it to instantiate a predicate called IdContainsDigitsPredicate
which extracts all the ID
of the related profiles (excluding itself of ID 1
). We will then pass it into the model#stackFilters(predicate)
method in the model
object to update the filtered list of persons to only include persons related to the person with ID of 1
.
Recalling that we also have a message box to inform the result of the actions taken (in prose form), the ShowRelatedCommand#execute(...)
method will also return a CommandResult
object, which contains the summary of the number of people listed.
Aspect: How to extract the IDs of the related profiles
Alternative 1 (current choice): Extract all the tuples from storage and use regular expressions to check if either of the ID
in the tuple is the specified ID
, then extract the ID
of the other related profile.
Alternative 2: Extract only tuples that contain the specified ID
, then extract the ID
of the other related profile.
The unrelate
command allows users to unrelate two persons via their unique ID
. Exceptional behavior:
ID
provided by user does not exist, an error message is displayed.ID
provided is not an integer value that is more than 0, an error message is displayed.Given a command unrelate i/1 i/2
, the NetConnectParser
recognises the unrelate
command and first instantiates an UnrelateCommandParser
object. It then passes the command string into UnrelateCommandParser#parse(...)
, where the input i/1
and i/2
is validated for its format. Following which, UnrelateCommandParser
instantiates an UnrelateCommand
object.
TheUnrelateCommand
object extends the Command
interface, and hence contains a method called execute(...)
, which takes in a model
. A model can be thought of as a container for the application's data, and it also controls the exact contact list that the user will see. In the execute(...)
command, we validate that NetConnect has both IDs 1
and 2
and already has a relation. We remove it from our RelatedList stored in NetConnect if both are true. To change our view and to ratify the successful user command, we will have to change the view the user sees by instantiating a predicate called IdContainsDigitsPredicate
. We will then pass it into the model#stackFilters(predicate)
method in the model
object to update the filtered list of persons to only show the two people who have just been unrelated with the ID 1
and 2
.
Recalling that we also have a message box to inform the result of the actions taken (in prose form), the UnrelateCommand#execute(...)
method will also return a CommandResult
object, which contains the id of the two people, in a 1relates2 format..
Aspect: What kind of unrelation will be done using the two IDs
Alternative 1 (current choice): The two IDs given will be used to remove that specific relation.
Alternative 2: The two IDs given will be used to remove all relations for the two contacts.
The delete
command allows users to delete Person
from NetConnect using either the target Person
's Id
or Name
. Id
allows users to directly and accurately delete the Person
if the Id
is known, while Name
provides the flexibility to delete using name if Id
is not known. Exceptional behaviour:
Id
and Name
is provided, an error message is shown.Person
s with the given Name
or Id
, the display is updated to show all Person
s, and an error message is shown.Name
is provided but there are more than one Person
with the specified Name
in NetConnect, all Person
s with the matching Name
will be displayed, and user will be prompted to re-input the delete
command using Id
instead.delete
can be done regardless of whether the target Person
is in the current displayed list. If the Person
is in the current displayed list, the display view does not change upon successful delete. If the Person
is in not in the current displayed list, the display view is changed to display all Person
s upon successful delete.
A DeleteCommand
instance is instantiated in DeleteCommandParser#parse(...)
by the factory methods DeleteCommand#byId(Id)
or DeleteComamnd#byName(Name)
. The sequence diagram below shows the creation of a DeleteCommand
with Id
. The process is similar for DeleteCommand
with Name
.
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.
Deletion of Person
from NetConnect is facilitated by Model#getPersonById(Id)
or Model#getPersonByName(Name)
, and Model#deletePerson(Person))
. The sequence diagram below shows the execution of a DeleteCommand
with Id
. The process is similar for DeleteCommand
with Name
.
Aspect: How delete command executes:
Alternative 1 (current choice): A single Model#deletePerson(Person)
method.
Model#getPersonById(Id)
and Model#getPersonByName(Name)
can be reused for other purposes.Model#deletePerson(Person)
.Person
with matching Id
or Name
exists in the list before Model#getPersonById(Id)
, Model#getPersonByName(Name)
and Model#deletePerson(Person)
are called.Alternative 2: Separate methods of Model#deletePersonById(Id)
and Model#deletePersonByName(Name)
.
DeleteCommand#execute(...)
.Model#deletePersonById(Id)
and Model#deletePersonByName(Name)
.Model#deletePersonById(Id)
and Model#deletePersonByName(Name)
are very similar.Id
of Person
The unique id of Person
is stored as a private field Id
instance in Person
. Id
value is enforced to be unique between each Person
by keeping the constructors of the Id
class private, and by using a private static field nextId
. The Id
class provides 3 factory methods to instantiate Id
:
Id#generateNextId()
— instantiates an Id
object with the next available value given by nextId
.Id#generateId(int)
— instantiates an Id
object with the given value, and updates nextId to be the given value + 1. This method is necessary to update nextId
while keeping the Id
value of each Person
the same between different runs of the application.Id#generateTempId(int)
— instantiates an Id
object with the given value, without changing the value of nextId
. This method is used for non-add
NetConnect commands that accepts id as an argument. This method is necessary as using Id#generateId(int)
in non-add
commands will cause nextId
to be updated, even if there are no persons in the NetConnect using the previous Id
. Example:
Id
1 to 5.delete i/1000
command, where Id#generateId(int)
is used.nextId
is updated to be 1001.Id#generateNextId()
, Id
value 1001 will be used although values 6 to 1000 are not used.Operations with Id
on Person
in NetConnect is facilitated through Model#hasId(Id)
and Model#getPersonById(Id)
.
Find
featureThe find
command allows users to filter the display to show Person
s from NetConnect with fields matching certain values. The command allows finding by name, phone number, tag, role, remark. Parameters provided are subjected to its respective validity checks, and mentions of these checks will be omitted in this section.
The execution of find
is facilitated by Model#clearFilter()
and Model#stackFilters(NetConnectPredicate)
. Model
uses the Filter
classes in the Model
component to facilitate the implementation. find
by each field uses its respective XYZPredicate
:
find
by name uses NameContainsKeywordsPredicate
find
by tag uses TagsContainsKeywordsPredicate
find
by phone number uses PhoneMatchesDigitsPredicate
find
by role uses RoleMatchesKeywordsPredicate
find
by remark uses RemarkContainsKeywordsPredicate
The sequence diagram below shows the parsing of a find n/John
command. The process is similar for find
command with other parameters.
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.
The sequence diagram below shows the execution of the find
command created from a find n/John
command.
The list
command, or any other command that alters the displayed view can be used to clear all existing filters. In these cases, the stored Filter
object in ModelManager
will be set to a Filter
containing no predicates.
Aspect: How the view of the displayed list is filtered
Alternative 1 (current choice): Create a new Filter
class to store all the predicates.
ModelManager
.Alternative 2: Stack the predicates using FilteredList#setPredicate(...)
, FilteredList#getPredicate()
and `Predicate#and(...), without explicitly storing the predicates.
The proposed undo/redo mechanism is facilitated by VersionedNetConnect
. It extends NetConnect
with an undo/redo history, stored internally as an netConnectStateList
and currentStatePointer
. Additionally, it implements the following operations:
VersionedNetConnect#commit()
— Saves the current netconnect state in its history.VersionedNetConnect#undo()
— Restores the previous netconnect state from its history.VersionedNetConnect#redo()
— Restores a previously undone netconnect state from its history.These operations are exposed in the Model
interface as Model#commitNetConnect()
, Model#undoNetConnect()
and Model#redoNetConnect()
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 VersionedNetConnect
will be initialized with the initial netconnect state, and the currentStatePointer
pointing to that single netconnect state.
Step 2. The user executes delete 5
command to delete the 5th person in the netconnect. The delete
command calls Model#commitNetConnect()
, causing the modified state of the netconnect after the delete 5
command executes to be saved in the netConnectStateList
, and the currentStatePointer
is shifted to the newly inserted netconnect state.
Step 3. The user executes add n/David …
to add a new person. The add
command also calls Model#commitNetConnect()
, causing another modified netconnect state to be saved into the netConnectStateList
.
Note: If a command fails its execution, it will not call Model#commitNetConnect()
, so the netconnect state will not be saved into the netConnectStateList
.
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#undoNetConnect()
, which will shift the currentStatePointer
once to the left, pointing it to the previous netconnect state, and restores the netconnect to that state.
Note: If the currentStatePointer
is at index 0, pointing to the initial NetConnect state, then there are no previous NetConnect states to restore. The undo
command uses Model#canUndoNetConnect()
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#redoNetConnect()
, which shifts the currentStatePointer
once to the right, pointing to the previously undone state, and restores the netconnect to that state.
Note: If the currentStatePointer
is at index netConnectStateList.size() - 1
, pointing to the latest netconnect state, then there are no undone NetConnect states to restore. The redo
command uses Model#canRedoNetConnect()
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 netconnect, such as list
, will usually not call Model#commitNetConnect()
, Model#undoNetConnect()
or Model#redoNetConnect()
. Thus, the netConnectStateList
remains unchanged.
Step 6. The user executes clear
, which calls Model#commitNetConnect()
. Since the currentStatePointer
is not pointing at the end of the netConnectStateList
, all netconnect 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 netconnect.
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}
Team size: 5
showrelated
command output a specific error message when an ID
that does not exist is provided: Currently, when input is showrelated i/10
but there is no Person
with ID
10, the command succeeds and outputs the message "0 persons listed!". This is not the expected result, as the command should fail with an appropriate error message. We plan to handle this erroneous input, and show the error message: "There is no person with id 10" for the above command.relate
command success message more specific: The current message for a successful relate i/1 i/2
command only shows "2 persons listed!", which is too general and might not catch user's typos or mistakes if they wanted to do relate i/1 i/3 instead
. We plan to make the success message output the two persons that are involved in the relate
command: "The relation between these two persons have been created: Alex Yeoh, Phone: 87438807, Email:alexyeoh@example.com
and Bernice Yu, Phone: 99272758, Email: berniceyu@example.com
".relate
and unrelate
command: Currently, the commands relate i/ 1 i/ 2
, relate i/1 2 i/3
, relate i/1 i/2 tag/friends
, or relate i/a 1 i/2
will fail with the following error message: "Invalid command format! ...". This is not consistent with the other commands that ignores additional whitespaces provided to arguments, invalid prefixes provided, or invalid id. We plan to accept values with trailing and leading whitespaces in relate
and unrelate
command, and output specific error message for invalid prefixes and invalid id.edit
command output a specific error message when the given values of fields are the same as existing ones: Currently, when input is edit i/1 n/Alex
but Person
with ID
1 already has the name Alex
, the command succeeds and outputs the message: "Edited Person: ..." although no values were actually changed since the same value is provided. We plan to handle this case where same values are given, making the command fail and show the error message: "There are no changes to values provided".ID
6, there will be no other persons allowed to have ID
6 in the same run of the app. The rationale for this implementation is to facilitate the feature of soft delete and data recovery. Soft delete means that we will not completely remove the deleted Person
and the details from NetConnect, but only mark it as deleted and not display it or use in any other commands. Soft delete will facilitate the data recovery feature, for user to recover the details of a deleted Person
in the event of accidental deletion.unrelate
command success message more user-friendly: The current success message for the command unrelate i/1 i/2
shows "Unrelated the following persons: 1relates2", which is not very user friendly. We plan to change the command success message to show: "Unrelated the following persons: Alex Yeoh, Phone: 87438807, Email:alexyeoh@example.com
and Bernice Yu, Phone: 99272758, Email: berniceyu@example.com
"Target user profile:
Experienced managers who:
Value proposition: provides managers a platform to manage employee, client and partner contact information easily, and to keep track of past interactions.
Priorities: High (must have) - * * *
, Medium (nice to have) - * *
, Low (unlikely to have) - *
Priority | As a … | I want to … | So that I can… |
---|---|---|---|
* * * | occasional user | add a new person | |
* * * | occasional user | delete a person | remove entries that I no longer need |
* * * | occasional user | find a person by name | quickly access their contact details |
* * * | occasional user | find a person by contact number | see who contacted me |
* * * | occasional user | find a person by remark | view all people with a particular remark |
* * * | occasional user | find a person by role | view all roles separately |
* * * | occasional user | tag roles to members | see distinctions and manage using roles |
* * | occasional user | go back to the state from where i left off | avoid going back to the same page/state when I close the application |
* * | occasional user | edit person information | refer to accurate personal information in the future |
* * | experienced user | export contact lists to a CSV file | create backups or use the data in other applications |
* * | experienced user | relate two profiles together | connect two contacts together |
* * | experienced user | view which contacts are related to a profile | assign tasks to my employees |
* * | experienced user | unrelate two profiles | disconnect two contacts |
* * | new user | see usage instructions | refer to instructions when I forget how to use the App |
* * | new user | clear all existing contacts | populate with my actual contacts |
(For all use cases below, the System is the NetConnect
and the Actor is the user
, unless specified otherwise)
Use case: UC01 - List All Persons
MSS
User requests to list all persons.
NetConnect shows the list of all persons.
Use case ends.
Extensions
2a. The list of all persons is empty.
Use case ends.
Use case: UC02 - Find a List of Persons by Name
MSS
User requests for the list of persons matching a name.
NetConnect shows a list of persons with matching name.
Use case ends.
Extensions
2a. There are no persons with a matching name.
Use case ends.
Use case: UC03 - Find a Specific Person by Contact Number
MSS
User requests for the person with the matching contact number.
NetConnect shows the person with matching contact number.
Use case ends.
Extensions
2a. There is no person with a matching number.
Use case ends.
Use case: UC04 - Find a Specific Person by Role
MSS
User requests for the person with the matching role.
NetConnect shows the person with matching role.
Use case ends.
Extensions
2a. There is no person with a matching role.
Use case ends.
Use case: UC05 - Find a Specific Person by Remark
MSS
User requests for the person with the matching remark.
NetConnect shows the person with matching remark.
Use case ends.
Extensions
2a. There is no person with a matching number.
Use case ends.
Use case: UC06 - Add a New Person
MSS
User requests to add a new person with given information.
NetConnect adds a new person to the list.
Use case ends.
Extensions
1a. Some given arguments are invalid.
1a1. NetConnect shows an error message.
Use case ends.
Use case: UC07 - Delete a Person by UID
MSS
User requests to delete a specific person by UID.
NetConnect deletes the person.
Use case ends.
Extensions
1a. There is no person with the provided UID.
1a1. NetConnect shows an error message.
Use case ends.
Use case: UC08 - Delete a Person by Name
MSS
User requests to delete a specific person by name.
NetConnect deletes the person.
Use case ends.
Extensions
1a. There are no persons with the provided name.
1a1. NetConnect shows an error message.
Use case ends.
1b. There are more than one person with the provided name.
Use case: UC09 - Tag a Person by UID with Custom Tag
MSS
User requests to tag a specific person by UID with a custom tag.
NetConnect tags the person with given custom tag.
Use case ends.
Extensions
1a. There is no person with the provided UID.
1a1. NetConnect shows an error message.
Use case ends.
Use case: UC10 - Tag a Person by Name with Custom Tag
MSS
User requests to tag a specific person by name with a custom tag.
NetConnect tags the person with given custom tag.
Use case ends.
Extensions
1a. There are no persons with the provided name.
1a1. NetConnect shows an error message.
Use case ends.
1b. There are more than one person with the provided name.
1b1. NetConnect list the persons with matching name (UC2).
1b2. User selects an UID from the list.
Use case resumes at step 2.
Use case: UC11 - Edit Person Information by UID
MSS
User requests to edit the information of a specific person by UID.
NetConnect edit the person information.
Use case ends.
Extensions
1a. There is no person with the provided UID.
1a1. NetConnect shows an error message.
Use case ends.
1b. Some given arguments are invalid.
1b1. NetConnect shows an error message.
Use case ends.
Use case: UC12 - Export Contact List to CSV File
MSS
User requests to export contact list to CSV file with a given filename.
NetConnect creates a CSV file with the contact list data.
Use case ends.
Extensions
1a. The given filename is invalid.
1a1. NetConnect shows an error message.
Use case ends.
1b. The contact list is empty.
1b1. NetConnect shows an error message.
Use case ends.
Use case: UC13 - Relate two contacts together
MSS
Extensions
1a. The given ID does not exist.
1a1. NetConnect shows an error message.
Use case ends.
1b. The contact list is empty.
1b1. NetConnect shows an error message.
Use case ends.
1c. There is an ambiguous command.
1c1. NetConnect shows an error message requesting to fix ambiguity.
Use case ends.
1c. User relates contact to the same contact.
1c1. NetConnect shows an error message.
Use case ends.
Use case ends.
Use case: UC14 - View all contacts related to a single contact
MSS
Extensions
1a. The given ID does not exist.
1a1. NetConnect shows an error message.
Use case ends.
1b. The contact list is empty.
1b1. NetConnect shows an error message.
Use case ends.
Use case ends.
Use case: UC15 - Unrelate two contacts
MSS
Extensions
1a. The given ID does not exist.
1a1. NetConnect shows an error message.
Use case ends.
1b. The contact list is empty.
1b1. NetConnect shows an error message.
Use case ends.
1c. There is an ambiguous command.
1c1. NetConnect shows an error message requesting to fix ambiguity.
Use case ends.
1c. User unrelates contact to the same contact.
1c1. NetConnect shows an error message.
Use case ends.
Use case ends.
Use case: UC16 - Clear all contact list
MSS
User requests to clear all contacts.
NetConnect requests confirmation from user.
User confirms the request.
NetConnect deletes the entire contact list.
Use case ends.
11
or above installed.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.
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 i/1
Expected: Contact with id 1 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 1
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 i/x
, ...
(where no persons have id x)
Expected: Similar to previous.
Guarantees: Person with the specified id will be deleted from NetConnect and removed from the displayed list.
Deleting a person while displayed list is filtered
Prerequisites: Filter displayed list using find
command or one of its variants. Partial contact list displayed.
Test case: delete i/x
(where x is the id of person displayed in the list)
Expected: Contact with id x 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 i/y
(where y is the id of a person not displayed in the list)
Expected: Contact with id x is deleted from NetConnect, and displayed list displays the full list of persons in NetConnect (without the person with id y. Details of the deleted contact shown in the status message. Timestamp in the status bar is updated.
Test case: delete 1
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 i/z
, ...
(where no persons have id z)
Expected: Similar to previous.
Guarantees: Person with the specified id will be deleted from NetConnect and removed from the displayed list. Full unfiltered list of persons will be displayed (similar to when list
command is entered).
Dealing with missing/corrupted data files