Developer Guide
Table of Contents
- Table of Contents
- Acknowledgements
- Setting up, getting started
- Design
- Implementation
- Documentation, logging, testing, configuration, dev-ops
- Appendix: Requirements
- Appendix: Instructions for manual testing
Acknowledgements
This project is created based on the AddressBook-Level3 project by the SE-EDU initiative.
Libraries used: JavaFX, Jackson, JUnit5
Setting up, getting started
Refer to the guide Setting up and getting started.
Design
.puml files used to create diagrams in this document can be found in the diagrams folder. Refer to the PlantUML Tutorial at se-edu/guides to learn how to create and edit diagrams.
Architecture

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 has two classes called Main and MainApp. It is responsible for,
- At app launch: Initializes the components in the correct sequence, and connects them up with each other.
- At shut down: Shuts down the components and invokes cleanup methods where necessary.
Commons represents a collection of classes used by multiple other components.
The rest of the App consists of 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.
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),
- defines its API in an
interfacewith the same name as the Component. - implements its functionality using a concrete
{Component Name}Managerclass (which follows the corresponding APIinterfacementioned 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 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,
- executes user commands using the
Logiccomponent. - listens for changes to
Modeldata so that the UI can be updated with the modified data. - keeps a reference to the
Logiccomponent, because theUIrelies on theLogicto execute commands. - depends on some classes in the
Modelcomponent, as it displaysPersonobject residing in theModel.
Logic component
API : Logic.java
Here’s a (partial) class diagram of the Logic component:

How the Logic component works:
- When
Logicis called upon to execute a command, it uses theAddressBookParserclass to parse the user command. - This results in a
Commandobject (more precisely, an object of one of its subclasses e.g.,AddCommand) which is executed by theLogicManager. - The command can communicate with the
Modelwhen it is executed (e.g. to add a person). - The result of the command execution is encapsulated as a
CommandResultobject which is returned fromLogic.
The Sequence Diagram below illustrates the interactions within the Logic component for the execute("delete 1") API call.

DeleteCommandParser should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
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:
- When called upon to parse a user command, the
AddressBookParserclass creates anXYZCommandParser(XYZis a placeholder for the specific command name e.g.,AddCommandParser) which uses the other classes shown above to parse the user command and create aXYZCommandobject (e.g.,AddCommand) which theAddressBookParserreturns back as aCommandobject. - All
XYZCommandParserclasses (e.g.,AddCommandParser,DeleteCommandParser, …) inherit from theParserinterface so that they can be treated similarly where possible e.g, during testing.
Model component
API : Model.java

The Model component,
- stores the address book data i.e., all
Personobjects (which are contained in aUniquePersonListobject). - stores the currently ‘selected’
Personobjects (e.g., results of a search query) as a separate filtered list which is exposed to outsiders as an unmodifiableObservableList<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. - stores a
UserPrefobject that represents the user’s preferences. This is exposed to the outside as aReadOnlyUserPrefobjects. - does not depend on any of the other three components (as the
Modelrepresents data entities of the domain, they should make sense on their own without depending on other components).
Tag-related classes is detailed in the class diagram in the implementation section of tagging feature.
Storage component
API : Storage.java

The Storage component,
- can save both address book data and user preference data in json format, and read them back into corresponding objects.
- inherits from both
AddressBookStorageandUserPrefStorage, which means it can be treated as either one (if only the functionality of only one is needed). - depends on some classes in the
Modelcomponent (because theStoragecomponent’s job is to save/retrieve objects that belong to theModel)
In the event that data saved in the json file is corrupted, the Storage component will make a copy of the
existing json file.

After the MainApp calls JsonAddressBookStorage#readAddressBook(), if the data is corrupted, JsonAddressBookStorage
will call the backup() method and make a copy of the addressbook.json. The copied file will be saved in the data
directory in a file called backup.json.
Users will still be able to use all features available, but the existing addressbook.json will be overwritten.
After closing the application, users are able to go into the data directory and rectify the problem in backup.json
before copying the information into addressbook.json.
Common classes
Classes used by multiple components are in the seedu.addressbook.commons package.
Implementation
This section describes some noteworthy details on how certain features are implemented.
Tagging feature
Implementation
Each Person object contains its own set of Tag objects, and the Tag objects are not referenced and stored by other
Person objects, even if the same Tag is used by multiple Person objects. However, there is a data structure in
AddressBook, UniqueTagList to keep track of every unique Tag objects used in the application, in order to
implement the command to list all existing tags. The class diagram below shows how the tagging feature is implemented
in the Model component.

Tag
Tag objects have the following characteristics:
- A
Tagobject only has one public data member (final),tagNameofStringobject, representing the name of theTag, which can be used to distinguish itself from otherTagobject. - The name of the
Tag,tagNameneeds to be alphanumeric (only letters and numerals are allowed). - Any two
Tagobjects are not unique if and only if theirtagNameare equal, ignoring case differences. -
Tagobjects can be sorted, and the sorted order is the natural ordering of theirtagName, ignoring case differences.
ReadOnlyUniqueTagList
ReadOnlyUniqueTagList is an interface that specifies the behaviour of a read-only UniqueTagList. It is designed to
protect the data integrity of UniqueTagList, as UniqueTagList should only be modifiable by the AddressBook object
and not by other objects at runtime. Therefore, UniqueTagList only exists in AddressBook and returns a copy of
UniqueTagList as ReadOnlyUniqueTagList type, in AddressBook#getUniqueTagList(), when requested, so that the
original copy of UniqueTagList is unmodifiable by other classes.
UniqueTagList
Due to the nature of the tagging feature implementation, UniqueTagList is implemented such that all unique tags used
are stored and maintained in a HashMap<Tag, Integer>, where the key set is the set of unique tags, and the value is
the occurrence frequency of each unique tag. For example, if a Tag with a tagName of “friends” is used twice in the
AddressBook, then the value of the Tag will be 2. This implementation requires the value of all the keys in the
HashMap to be more than 0, otherwise the key should be removed. UniqueTagList implements the following operations.
-
addTags(Set<Tag> tagsToAdd)
Adds theTagobjects inSet<Tag>to theHashMap. For eachTagobject, if it is not in theHashMap, then it will be added to theHashMapwith an initial value of 1. Otherwise, the value of theTagobject will be incremented by one. The sequence diagram of this operation is shown below.
-
removeTags(Set<Tag> tagsToRemove)
Removes theTagobjects inSet<Tag>from theHashMap. For eachTagobject, if it is in theHashMapwith a value of 1, then it will be removed from theHashMap. Otherwise, if it is in theHashMapwith a value of more than 1, the value of theTagobject will be decremented by one. The sequence diagram of this operation is shown below.

-
removeAndAddTags(Set<Tag> tagsToRemove, Set<Tag> tagsToAdd)
PerformsremoveTags(Set<Tag> tagsToRemove)andaddTags(Set<Tag> tagsToAdd)sequentially. -
clearTags()
Clears all the mappings in theHashMap. -
getUniqueTagList()
Returns a sorted list of unique tags that exists in theUniqueTagList. -
getUniqueTagListSize()
Returns the number of unique tags in theUniqueTagList.
The correctness of UniqueTagList in AddressBook is guaranteed by the immutability of the Person model that
contains Tag. Any changes to the UniquePersonList in AddressBook or any changes to any Person in AddressBook
can only be done through AddressBook. Therefore, in an event that the Person model becomes mutable, this
implementation of UniqueTagList may fail and needs to be revised.
For example, during every command that modifies the existing data in AddressBook, the method AddressBook#setPerson(p, q)
will be called. Apart from making changes to the UniquePersonList, this method call will also update the UniqueTagList,
as shown in the sequence diagram below.

UniqueTagList#addTags(Set<Tag> tagsToAdd) or UniqueTagList#removeTags(Set<Tag> tagsToRemove) will be called directly
by AddressBook in situations where new data is being added to the AddressBook or existing data is being removed
from the AddressBook respectively.
Design Consideration
Aspect: How tags are assigned to Person
- Alternative 1 (current implementation): A new tag is instantiated everytime even though there already exists a tag with
the same tag name in
UniqueTagList.
- Pros: Easy to implement, less coupling.
- Cons: May have performance issues in terms of memory usage.
- Alternative 2: Unique tags are only instantiated once. Adding an existing tag to a person creates a reference to the
existing tag. The implementation is briefly shown below.
- Pros: Better performance in terms of memory usage.
- Cons: More difficult to implement, more coupling (between
UniqueTagListand the instantiation ofPersonetc) required.
Aspect: How unique tags are stored in UniqueTagList (in the current implementation of tagging system)
- Alternative 1 (current implementation): Unique tags are stored in a
HashMapas keys, with its frequency of occurrence as values.
- Pros: Updating
UniqueTagListtakes constant time; the number of occurrence for each unique tag is recorded and can be used. - Cons: Reading the
UniqueTagListin alphabetical order takes O(n log(n)) time, incurred by sorting of the tags.
- Pros: Updating
- Alternative 2: Unique tags are stored in a
PriorityQueue.
- Pros: Reading the
UniqueTagListin alphabetical order just takes O(n) time. - Cons: Updating
UniqueTagListtakes O(log(n)) time every time; requires additional data structure to maintainUniqueTagListaccurately.
- Pros: Reading the
Date Features
Implementation
As seen in the Model component, each Person object contains its own BirthDate object,
a list of ContactedInfo and a ReminderList. The list of ContactedInfo stores ContactedInfo objects,
while the ReminderList stores Reminder objects. A ContactedInfo object has a RecentDate object,
and a Reminder object has a ReminderDate object. As BirthDate objects, RecentDate objects and ReminderDate
objects need to be displayed in the same format for consistency, we have a DocumentedDate parent class to ensure that
the three “date” type objects will use the same toString method in DocumentedDate to allow users to display the
dates in the same format, as seen in the class diagram below.

Documented Date
DocumentedDate objects have the following characteristics:
- A
DocumentedDateobject has a privateLocalDatemember to allow the application to easily store and display a formatted date. - A
DateTimeFormatterconstant is included as a member so that developers can tweak how the formatted date is shown to the users.
Documented Date Child Classes
Despite inheriting from the DocumentedDate parent class, these 3 “date” type objects have different behaviours.
A BirthDate object needs to be recurring, to check if the person’s birthday is occurring on the same day despite
being saved in a past year. A RecentDate needs to be a date that occurs in the past, and a ReminderDate needs to be
a date that has not yet occurred. To model this more concretely, we implement some checks using the ParserUtil class.
The three “date” type objects, are primarily created using static methods in the ParserUtil class.
However, there are public constructors to create each BirthDate, RecentDate and ReminderDate object. This is to
enable better testability.

As seen in the sequence diagram above, which shows the process of creating a BirthDate object,
ParserUtil#parseBirthDate(validDate) is called, with the user supplying a validDate in the form of a String.
The method will trim the validDate into a String called trimmedDate and call
DocumentedDate#isValidDate(trimmedDate) to check if it is in a valid date format. If the trimmedDate is indeed a valid date,
it will then be used to create a new BirthDate object. After that, a final check is done using the getDaysPassed()
method, before ParserUtil returns the newly created BirthDate object. For BirthDate objects, the check using the
getDaysPassed() method has to ensure that BirthDate objects are not created using dates in the future,
i.e. either past dates or the current date.
As both RecentDate and ReminderDate objects have similar requirements to the BirthDate objects, the process of
creating these objects are the same as the BirthDate objects. For better comparison, let us examine one more sequence
diagram for the creation of a ReminderDate object.

As seen above, the process exactly mirrors that of the BirthDate object. However, the biggest difference is that the
check using getDaysPassed() must make sure that ReminderDate objects cannot be created with a date that has passed.
This is because the purpose of the reminder is to ensure that users can keep track of tasks that have not yet been done
or important events that are upcoming.
The RecentDate objects are much more similar to the BirthDate objects when compared to ReminderDate objects,
as they have the same requirement of not being able to be created using a date in the future. This is because
RecentDate objects keep track of the user’s interactions with clients and contacts, and the user must have had an
interaction with the contact before they save the interaction record in the application.
Having two levels of checks ensures that the working “date” type objects are less bug prone, when using the specific
“date” type object for their designated usages. This makes features such as after or within return valid entries
when used, instead of an invalid or unexpected entry.
Design Consideration
Aspect: How date type objects are created
- Alternative 1 (current implementation): “Date” type objects extend
DocumentedDate.
- Pros: We can modify certain behaviour of each specific child class (i.e. allowing
BirthDateobjects to be read as recurring dates when necessary.)- Less duplicated bugs as each child class is independent of each other.
- Less duplicated code as the parent class can hold common methods.
- Cons: More overhead as more classes are required.
- Pros: We can modify certain behaviour of each specific child class (i.e. allowing
- Alternative 2: Use
DocumentedDatefor all dates and differentiate usingenumtypes- Pros: We can standardise all formatting and behaviour strictly, and only use type specific methods
when necessary. (i.e. Since
BirthDateandRecentDateobjects check for past and current dates only, we do not need to have duplicated code) - Cons: More checks are required within each method, may potentially violate Single Responsibility Principle and code quality due to the different types of checks required.
- Pros: We can standardise all formatting and behaviour strictly, and only use type specific methods
when necessary. (i.e. Since
Aspect: How to store dates
- Alternative 1 (current implementation):
DocumentedDateobjects use aLocalDateobject to store dates.
- Pros: We can encapsulate the processes of date manipulation and comparison.
- We can leverage on Java being a strongly typed language to ensure that inputs and outputs are less prone to errors.
- Cons: Users are restricted in the way they input dates.
- Pros: We can encapsulate the processes of date manipulation and comparison.
- Alternative 2: Use a
Stringto store dates- Pros: More flexibility in terms of user input and input manipulation by the system.
- Cons: More processes are required to parse and check for invalid inputs.
- Users might be able to abuse the system by parsing a
Stringwith a long length, which might slow down the system when the system is running other process concurrently. - Handling of behaviour for specific date types in terms of comparing dates may require more work.
- Users might be able to abuse the system by parsing a
Interaction record feature
Implementation
Each Person object contains its own List of ContactedInfo objects. The class diagram below shows how
the recently contacted information feature is implemented in the Model component.

ContactedInfo
A ContactedInfo object contains the information regarding recent interactions for a specific client.
The sequence diagram below shows how the add recently contacted information feature is parsed.

The class diagram below shows how ContactedInfo is implemented.

ContactedInfo objects have the following characteristics:
- A
ContactedInfoobject has two private data members (final),recentDateofRecentDateobject representing that date of interaction, anddescriptionofDescriptionobject, representing the description of the interaction. Both objects would distinguish one ContactedInfo object from another. - Any two
ContactedInfoobjects are not unique if bothdescriptionandrecentDateis equal. -
ContactedInfoobjects can be sorted, and the sorted order is the reverse ordering of theRecentDate.
RecentDate
RecentDate is an object that stores information regarding the interaction date for ContactedInfo. RecentDate object inherits from DocumentedDate object.
RecentDate objects have the following characteristics:
- A
RecentDateobject has two private data members (final),daterepresenting the date of interaction as aLocalDateobject, andvalueofStringformat representing the date inYYYY-MM-DDform. - input to create a
RecentDateobject needs to be the correct format (YYYY-MM-DD). - Any two
RecentDateobjects are not unique if bothRecentDaterepresents the same date. -
RecentDateobjects can be sorted, and the sorted order is the reverse ordering of theirLocalDate.
RecentDate implements the following operations.
-
parse(String parsedDate)
Creates a newRecentDateusing aString.Stringhas to have the formatYYYY-MM-DD. -
defaultRecentDate()
Returns today’s date as aRecentDateobject.
Description
Description object represents the description of the recent interaction. Description gets invoked in the ParserUtil parseContactedInfo method.
The sequence diagram below shows what happens when a Description object is instantiated.

Description objects have the following characteristics:
-
Descriptioncan take on any values, but should not be blank nor should it exceed 280 characters. - Contains one public data member (final)
valueofStringobject, representing the description of theDescriptionobject, which can be used to distinguish itself from otherDescriptionobject.
Description implements the following operations.
-
parse(String parsedDate)
Creates a newRecentDateusing aString.Stringhas to have the formatYYYY-MM-DD. -
defaultDesc()
Returns aDescriptionobject containing theStringwith the description being “First Interaction”. -
isValidDescription(String test)
Checks if the givenStringis a valid input. Returns true if the inputStringis not blank and does not exceed 280 characters, otherwise false.
Design Consideration
Aspect: How Recent Interaction feature data is handled
- Alternative 1 (current Implementation):
ContactedInfois an object that holds bothDescriptionandRecentDate.- Pros: Easy to handle, more cohesion. This method introduces more SLAP, thus making it easier to update and maintain code.
- Cons: More checks are needed to ensure that inputs by user is valid.
- Alternative 2:
DescriptionandRecentDateobjects are seperated.- Pros: Easy to implement.
- Cons: More coupling. This method would make it harder to maintain and update code. This method does not take SLAP into account, making it harder to implement commands related to this feature.
Reminder Feature
Implementation
As seen from the Model, a Person contains a ReminderList, which stores Reminder objects. The class diagram below
shows how the reminder features are implemented in the Model component.

Reminder
Each Reminder object contains information regarding reminders specific to a saved client, and has the following
characteristics:
- A
Reminderobject stores a privateReminderDescriptionobject, and a privateReminderDateobject.- A
ReminderDescriptionobject stores a privateStringwhich describes the reminder event. - A
ReminderDateobject extends fromDocumentedDatestores a privateLocalDatefield to capture the date of the reminder. - Any two
Reminderobjects are not if bothReminderDescriptionandReminderDateare equal.
- A
Reminder implements the following method:
-
isSameDateAs(ReminderDate reminderDate)
Checks if theReminderobject happens on the same date as the givenReminderDate.
The class diagram below shows how a Reminder object is implemented

The sequence diagram below shows how a user input to add a reminder is parsed into a AddReminderCommand.

ReminderDescription
Each ReminderDescription object stores information pertaining to the description of reminders.
ReminderDescription objects have the following characteristics:
- A
ReminderDescriptionobject stores a privateStringwhich describes the reminder event.- The private
Stringmust be alphanumeric, should not be blank, and should not exceed 280 characters. - This field is also being used to compare with other
ReminderDescriptionobjects to check if they are identical. For instance, any twoReminderDescriptionobjects are equal if they have the same descriptionString.
- The private
ReminderDescription implements the following method:
-
isValidDescription(String description)
Checks if the givenStringis a validReminderDescription.
ReminderDate
Each ReminderDate object stores information pertaining to the date of reminders. A ReminderDate object cannot have
a date which happens in the past, as reminders are supposed to remind users of upcoming events.
ReminderDate objects have the following characteristics:
- A
ReminderDateobject has a privateDateTimeFormatterthat provides the format in which a date is to be printed. Developers are able to conveniently alter this field to change the output format of the date. - A
ReminderDateobject has a privateStringwhich stores the displayed value of a date provided by theDateTimeFormatter.
ReminderDate implements the following method:
-
parse(String parsedDate)Creates a newReminderDateusing aString. TheStringprovided has to be in the formatyyyy-MM-dd.
ReminderList
ReminderList is an object that stores Reminder objects. ReminderList makes use of a PriorityQueue to store
Reminder objects, and makes use of the ReminderDate to arrange the Reminder objects in chronological order.
ReminderList has been designed to be immutable. Every addition or deletion of a Reminder in the ReminderList would
return a copy of the updated list. The new instance returned would then be used to replace the existing ReminderList
in a Person object. Another advantage of the immutability characteristic is that the internal state will be
consistent, even when there are exceptions.
The sequence diagram below shows how ReminderList handles a deletion of a Reminder object.

Design Consideration
Aspect: How to store information in Reminder
- Alternative 1 (current implementation):
Reminderstores the description and date of reminders as two objects, i.e.ReminderDescriptionandReminderDate.- Pros: This method applies SLAP, which increases the readability of the code, and makes the updating and debugging process simpler.
- Cons: Requires more checks on user input to make sure that legal arguments are being passed to the methods.
- Alternative 2:
Reminderstores the description and date of reminders as two primitives, i.e.StringandLocalDate.- Pros: Implementation of
Reminderis easier - Cons: Harder to debug and update the code.
- Pros: Implementation of
Documentation, logging, testing, configuration, dev-ops
Appendix: Requirements
Product scope
Target user profile:
- has a need to manage a significant number of contacts
- has a need to distinct between groups of contacts
- prefer desktop apps over other types
- can type fast
- prefers typing to mouse interactions
- is reasonably comfortable using CLI apps
- prefers getting reminders on actionable items
Value proposition: manage and consolidate information on contacts with automated reminders, faster than a typical mouse/GUI driven application
User stories
Priorities: High (must have) - * * *, Medium (nice to have) - * *, Low (unlikely to have) - *
| Priority | As a … | I want to … | So that I can… |
|---|---|---|---|
* * * |
new user | see usage instructions | refer to instructions easily when I forget how to use the App |
* * * |
user | add a new person | |
* * * |
financial advisor | add birthdays for my contacts | show my clients that I take note of their important dates personally |
* * * |
user | edit an existing person | make sure that the information stored is up to date |
* * * |
user | delete a person | remove entries that I no longer need |
* * * |
user | find a person by name | locate details of persons without having to go through the entire list |
* * |
busy user | keep track of important tasks daily | make sure I do not miss out tasks for my clients |
* * |
user with many persons in the address book | assign tags to my contacts | categorise my contacts in a meaningful manner |
* * |
financial advisor | track my last interaction with a contact | have a snapshot of the relationship |
Use cases
(For all use cases below, the System is the Address Book and the Actor is the user, unless specified otherwise)
Use case: UC01 - Add a new contact
MSS
- User requests to add a new contact to the Address Book.
-
Address Book adds contact to the contact list.
Use case ends.
Extensions
-
1a. The given input is invalid.
-
1a1. Address Book shows an error message.
Use case ends.
-
Use case: UC02 - Update a contact
MSS
- User requests to update details for a person in the Address Book.
-
Address Book updates the details of the contact.
Use case ends.
Extensions
-
1a. The given input is invalid.
-
1a1. Address Book shows an error message.
Use case ends.
-
-
1b. The given index is invalid.
-
1b1. Address Book shows an error message.
Use case ends.
-
Use case: UC03 - List all contacts
MSS
- User requests to list all contacts.
-
Address Book shows a list of contacts if any.
Use case ends.
Extensions
-
1a. The list is empty.
-
1a1. AddressBook shows an error message.
Use case ends.
-
Use case: UC04 - Delete a contact
MSS
- User lists all contacts (UC03).
- User requests to delete a specific contact in the list.
-
Address Book deletes the contact.
Use case ends.
Extensions
-
2a. The given contact is invalid.
-
2a1. AddressBook shows an error message.
Use case ends.
-
Use case: UC05 - Find contact by keyword
MSS
- User requests to find a person.
-
Address Book shows a list of persons with names containing the keyword.
Use case ends.
Extensions
-
1a. No keyword is given.
-
1a1. Address Book shows an error message.
Use case ends.
-
-
1b. The given keyword does not match any contacts.
-
1b1. Address Book shows a message that no contacts matches the keyword.
Use case ends.
-
Use case: UC06 - Set previously contacted date
MSS
- User requests to set previously contacted date for a specified contact.
-
Address Book sets the previously contacted date for the specified contact.
Use case ends.
Extensions
-
1a. No date is given.
-
1a1. Address Book sets the previously contacted date as today for the specified contact.
Use case ends.
-
-
1b. The given date is invalid.
-
1b1. Address Book shows an error message.
Use case ends.
-
-
1c. The given index is invalid.
-
1c1. Address Book shows an error message.
Use case ends.
-
-
1d. No description provided.
-
1d1. Address Book shows an error message.
Use case ends.
-
-
1e. Description provided is more than 280 characters.
-
1e1. Address Book shows an error message.
Use case ends.
-
Use case: UC07 - Show all contacted information for a specified contact
MSS
- User request to list all contacted information for a specified contact.
-
Address Book shows all contacted information for the specified contact.
Use case ends.
Extensions
-
1a. No index specifying a specific contact is given.
-
1a1. Address Book shows an error message.
Use case ends.
-
-
1b. The given index specifying a specific contact is invalid.
-
1b1. Address Book shows an error message.
Use case ends.
-
Use case: UC08 - List all contacts in Address Book within a designated time frame
MSS
- User requests to see all contacts last contacted within/outside a designated number of days.
-
Address Book shows contacts last contacted within/outside the designated time frame (i.e. less than 30 days).
Use case ends.
Extensions
-
1a. No client was contacted within/outside the designated number of days.
-
1a1. Address Book does not show any clients.
Use case ends.
-
-
1b. Invalid index provided.
-
1b1. Address Book shows an error message.
Use case ends.
-
Use case: UC09 - Set reminder
MSS
- User requests to set a reminder for a designated contact at a specified date.
-
Address Book sets a reminder for the contact tagged to the specified date.
Use case ends.
Extensions
-
1a. The given reminder message is invalid.
-
1a1. Address Book shows an error message.
Use case ends.
-
-
1b. The given reminder date is invalid.
-
1b1. Address Book shows an error message.
Use case ends.
-
Use case: UC10 - View reminders of a contact
MSS
- User requests to view reminders of a specific contact.
-
Address Book shows reminders of the specified contact.
Use case ends.
Extensions
-
1a. The given contact is invalid.
-
1a1. Address Book shows an error message.
Use case ends.
-
-
1b. No reminder is found in the given contact.
-
1b1. Address Book shows an error message.
Use case ends.
-
Use Case: UC11 - View reminders on a date
MSS
- User requests to view reminders on a specific date.
-
Address Book shows reminders associated with the specified date.
Use case ends.
Extensions
-
1a. The date given is invalid.
-
1a1. Address Book shows an error message.
Use case ends.
-
Use case: UC12 - Delete a reminder
MSS
- User views reminders of a specific contact (UC09).
- User requests to delete a reminder for a specified contact.
-
Address Book deletes a reminder for the specified contact.
Use case ends.
Extensions
-
2a. The given reminder is invalid.
-
2a1. Address Book shows an error message.
Use case ends.
-
-
2b. The given contact is invalid.
-
2b1. Address Book shows an error message.
Use case ends.
-
Use case: UC13 - Show all tags
MSS
- User requests to view all tags.
-
Address Book shows all existing tags.
Use case ends.
Extensions
-
1a. There is no tags in Address Book.
-
1a1. Address Book shows a message, stating that there is no tags.
Use case ends.
-
Use case: UC14 - Show all contacts that are tagged to a tag
MSS
- User views all tags (UC13).
- User requests to view all contacts that are tagged to the specified tag.
- Address Book shows all contacts that are tagged to the specified tag, if any.
Extensions
-
2a. The given tag is invalid.
-
2a1. Address Book shows an error message.
Use case ends.
-
Use case: UC15 - Add a tag to a contact
MSS
- User requests to add a tag to a contact.
-
Address Book appends the designated tag to the contact.
Use case ends.
Extensions
-
1a. The given contact is invalid.
-
1a1 Address Book shows an error message.
Use case ends.
-
-
1b. The given tag is invalid.
-
1b1 Address Book shows an error message.
Use case ends.
-
-
1c. The given tag already exists.
-
1c1 Address Book shows an error message.
Use case ends.
-
Use case: UC16 - Delete a tag from a contact
MSS
- User requests to delete a tag from a contact.
-
Address Book removes the specified tag from the contact.
Use case ends.
Extensions
-
1a. The given contact is invalid.
-
1a1. Address Book shows an error message.
Use case ends.
-
-
1b. The given tag is not associated with the contact.
-
1b1. Address Book shows an error message.
Use case ends.
-
-
1c. The given tag is invalid.
-
1c1. Address Book shows an error message.
Use case ends.
-
Use case: UC17 - Show all birthdays today
MSS
- User requests to view all birthdays occurring today.
-
Address Book shows all persons with birthdays today.
Use case ends.
Extensions
-
1a. No birthdays occur today.
- 1a1. Address Book shows message stating that there are 0 persons with birthdays today. Use case ends.
Non-Functional Requirements
- Should work on any mainstream OS as long as it has Java
11or above installed. - Should be able to hold up to 1000 persons without a noticeable sluggishness in performance for typical usage.
- A user with above average typing speed for regular English text (i.e. not code, not system admin commands) should be able to accomplish most of the tasks faster using commands than using the mouse.
- Should not be bigger than 100MB.
- A user should not be required to use an installer to run the application.
- A new user should know how to use or where to look for function guides within one day.
- An advanced user should be able to edit and replace the dataset manually.
- The application GUI should work well for standard screen resolutions 1920x1080 and higher, and for screen scales of 100% and 125%.
- The application should respond to user input within 2 seconds.
- The application is not required to support printing or use with other 3rd party software.
- The application is not required to implement undo, redo and data recovery functions on error.
Glossary
- Address Book: Address book used to store contacts in the application
- Application: The Automated Insurance Assistant Application
- Command Box: Box for user input, for a graphical representation, click here.
- ContactedInfo: The type of object that interaction records are saved as.
- Mainstream OS: Windows, Linux, Unix, OS-X
- MSS: Main Success Scenario that describes the most straightforward interaction for a given use case, which assumes that nothing goes wrong
- RecentDate: The type of date object used to save dates for a given interaction record.
- Result Display Message: Message shown in the Result Display.
- SLAP: Single level of abstraction principle. Refers to every method dealing with only one level of abstraction.
Appendix: Instructions for manual testing
Given below are instructions to test the app manually.
Launch and shutdown
-
Initial launch
-
Download the jar file and copy into an empty folder
-
Run the jar file in a shell application using the command
java -jar AIA.jarExpected: 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 running the jar file with the same command.
Expected: The most recent window size and location is retained.
-
Person Related Tests
Adding a contact
- Add a new contact into the contact list
-
Prerequisites: none
-
Test case:
add n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01 b/1970-01-01
Expected: Contact is added to contact list. -
Test case: Duplicate persons
Command: Run the command fromiitwice.
Expected: Duplicate person message. Error details shown in the result display message. Command box remains the same. -
Other incorrect add commands to try:
- Missing required fields
- Prefixes with no fields (e.g.
n/except tag)
Expected: Invalid command message. Error details shown in the result display message. Command box remains the same.
-
Deleting a contact
-
Deleting a contact while all contacts are being shown
-
Prerequisites: List all contacts using the
listcommand. Multiple contacts in the contact list. -
Test case:
delete 1
Expected: First contact is deleted from the contact list. Details of the deleted contact shown in the result display message. -
Test case:
delete 0
Expected: No contact is deleted. Error details shown in the result display message. Command box remains the same. -
Other incorrect delete commands to try:
delete,delete x,...(where x is larger than the contact list size)
Expected: Similar to previous.
-
Editing a contact
-
Editing a contact in contact list
-
Prerequisites: A contact with tags in the contact list.
-
Test case:
edit 1 n/name
Expected: Name of first contact is changed toname. Details of the edited contact shown in the result display message. - Other valid edit commands to try:
edit 1 p/88888888edit 1 e/email@mail.comedit 1 a/500 Dover Roadedit 1 b/2000-01-01
Expected: Similar to previous.
-
Test case:
edit 1 t/
Expected: Tags of the contact is removed. -
Test case:
edit 0 n/name
Expected: No contact is edited. Error details shown in the result display message. Command box remains the same. - Other incorrect edit commands to try:
edit,edit x n/name,...(where x is larger than the contact list size)
Expected: Similar to previous.
-
Showing all birthdays today
-
Showing all contacts with birthdays today in the contact list
-
Prerequisites: At least one contact with a birthday today in the contact list.
-
Test case:
birthdays
Expected: Contacts with birthdays today are shown in contact list. Number of contacts listed is shown in the result display message. -
Test case: no birthdays shown
Prerequisite: No contacts with birthdays today in the contact list.
Command:birthdays
Expected: No contacts are shown in contact list.0 persons listedis shown in the result display message.
-
Tag Related Tests
Adding a tag
-
Adding a tag to a contact in the contact list
-
Prerequisites: At least one contact in the contact list.
-
Test case:
tag 1 t/someTag
Expected: First contact is tagged tosomeTag. Details of the tagged contact shown in the result display message. -
Test case: Duplicate tags
Command: run the command iniitwice.
Expected: Contact is not re-tagged. Error details shown in the result display message. Command box remains the same. -
Test case:
tag 1 t/some tag
Expected: Contact is not tagged. Error details shown in the result display message. Command box remains the same. -
Other incorrect add tag commands to try:
tag,tag 1,tag x t/sometag,...(where x is larger than the contact list size)
Expected: Similar to previous.
-
Deleting a tag
-
Deleting a tag from a contact in the contact list
-
Prerequisites: At least one contact with the tag
someTagin the contact list. -
Test case:
untag 1 t/someTag
Expected: First contact is no longer tagged tosomeTag. Details of the contact shown in the result display message. -
Test case:
untag 1 t/some tag
Expected: Contact is not changed. Error details shown in the result display message. Command box remains the same. -
Other incorrect delete tag commands to try:
untag,untag 1,untag 1 t/x,...(where x isstringthat is not a tag)
Expected: Similar to previous.
-
Viewing all tags
-
Viewing all tags in the list
-
Prerequisites: At least one tag in the contact list.
-
Test case:
tags
Expected: Tag(s) is shown in the result display message. -
Test case: no tags shown
Prerequisite: No tags in the contact list.
Command:tags
Expected: No tags message shown in the result display message.
-
Finding contacts using a tag
-
Viewing all contacts associated with a tag
-
Prerequisites: At least one contact with a the
someTagtag in the contact list. -
Test case:
#someTag
Expected: Contact list shows contacts associated with the tag. Number of contacts listed is shown in the result display message. -
Test case: no contacts shown
Prerequisite: No contact with thehellotag in the contact list.
Command:#hello
Expected: No contact shown in contact list.0 persons listedshown in the result display message.
-
Interaction records related tests
Adding an interaction record
-
Adding an interaction record to a contact in the contact list
-
Prerequisites: At least one contact in the contact list.
-
Test case:
log 1 d/2022-04-09 des/Coffee
Expected: Interaction is saved for the first contact with the given date and description. Details are shown in the result display message. -
Test case:
log
Expected: Error details shown in the result display message. Command box remains the same. -
Test case:
log 1 d/3000-01-01 des/post-apocalyptic coffee
Expected: Interaction record is not saved. Error details shown in the result display message. Command box remains the same. -
Other incorrect add interaction record commands to try:
log 1 d/x des/x,log 1 d/ des/x,log 1 d/2022-01-01 des/,...(where x is astring)
Expected: Similar to previous.
-
Viewing interaction records of a contact
-
Viewing interaction records of a specific contact in the contact list
-
Prerequisites: One contact with an interaction record in the contact list.
-
Test case:
logs 1
Expected: Show the interaction records of the first contact in the result display message. -
Test case: no interaction records
Prerequisite: First contact with no interaction records.
Command:logs 1
Expected: Show no records of interaction in the result display message. -
Test case:
logs x(where x is larger than the contact list size)
Expected: Error details shown in the result display message. Command box remains the same.
-
Deleting an interaction record
-
Deleting an interaction from a contact in the contact list
-
Prerequisites: At least one contact with an interaction record in the contact list.
-
Test case:
unlog 1 del/1
Expected: First contact no longer has the first interaction record. Details of the deleted interaction record shown in the result display message. -
Test case:
unlog 1 del/x(where x is larger than the interaction record list size)
Expected: Contact’s interaction records are not changed. Error details shown in the result display message. Command box remains the same. -
Other incorrect delete interaction record commands to try:
unlog,unlog 1,unlog x del/1,...(where x is larger than contact list size)
Expected: Similar to previous.
-
Viewing contacts contacted within days
-
Viewing contacts contacted within a specified number of days
-
Prerequisites: At least one contact with an interaction record at most 5 days before the current date.
-
Test case:
within 5
Expected: Contacts with interaction records within 5 days from the current date are shown in the contact list. Number of contacts listed is shown in the result display message. -
Test case: No interaction records within 3 days prerequisite: No contacts must have interaction records within 3 days (including 3 days before current date).
Expected: No contacts shown in contact list. No contacts listed in result display message. -
Test case:
withinExpected: Error details shown in the result display message. Command box remains the same.
-
Viewing contacts contacted after days
-
Viewing contacts contacted more than a specified number of days
-
Prerequisites: At least one contact with an interaction record at least 5 days before the current date.
-
Test case:
after 5
Expected: Contacts with interaction records more than 5 days ago from the current date are shown in the contact list. Number of contacts listed is shown in the result display message. -
Test case: No interaction records more than 3 days old prerequisite: No contacts must have interaction records more than 3 days old (including 3 days before current date).
Expected: No contacts shown in contact list. No contacts listed in result display message. -
Test case:
afterExpected: Error details shown in the result display message. Command box remains the same.
-
Reminders related tests
Adding a reminder
-
Adding an reminder to a contact in the contact list
-
Prerequisites: At least one contact in the contact list.
-
Test case:
remind 1 r/Some task rd/x(Where x is a date in the future)
Expected: Reminder is saved for the first contact with the given date and description. Details are shown in the result display message. -
Test case:
remind
Expected: Error details shown in the result display message. Command box remains the same. -
Test case:
remind 1 r/Some task rd/2000-01-01
Expected: Reminder is not saved. Error details shown in the result display message. Command box remains the same. -
Other incorrect add reminder commands to try:
remind 1,remind 1 r/ rd/y,remind 1 r/x rd/,...(where x is astringand y is a valid reminder date)
Expected: Similar to previous.
-
Viewing reminders of a contact
-
Viewing reminders of a specific contact in the contact list
-
Prerequisites: One contact with a reminder in the contact list.
-
Test case:
reminder 1
Expected: Show the reminders of the first contact in the result display message. -
Test case: no reminders
Prerequisite: First contact with no reminders.
Command:reminder 1
Expected: Show no reminders in the result display message. -
Test case:
reminder x(where x is larger than the contact list size)
Expected: Error details shown in the result display message. Command box remains the same.
-
Viewing reminders by date
-
Viewing reminders in the contact list on a specific date
-
Prerequisites: At least one contact with a reminder on 01 Jan 2023 in the contact list.
-
Test case:
reminders rd/2023-01-01
Expected: Show the reminders tagged to 01 Jan 2023 in the result display message. -
Test case:
reminders rd/
Expected: Show the reminders tagged to the current date in the result display message. -
Test case: no reminders
Prerequisite: No reminders occurring on a specified datex.
Command:reminders rd/x
Expected: Show no reminders in the result display message. -
Test case:
reminders
Expected: Error details shown in the result display message. Command box remains the same.
-
Deleting a reminder
-
Deleting a reminder from a contact in the contact list
-
Prerequisites: At least one contact with a reminder in the contact list.
-
Test case:
forget 1 del/1
Expected: First contact no longer has the first reminder. Details of the deleted reminder shown in the result display message. -
Test case:
forget 1 del/x(where x is larger than the reminder list size)
Expected: Contact’s reminder list is not changed. Error details shown in the result display message. Command box remains the same. -
Other incorrect delete reminder record commands to try:
forget,forget 1,forget x del/1,...(where x is larger than contact list size)
Expected: Similar to previous.
-
Saving data
- Dealing with missing data files
- Remove addressbook.json and the data directory
-
Run the jar file
Expected: The application will automatically generate a data directory and populate addressbook.json with sample data.
- Dealing with corrupted data files
- Remove some lines from addressbook.json
-
Run the jar file
Expected: The application will make a copy of the current addressbook.json in backup.json and continue running with an empty addressbook.json. If changes are made, addressbook.json will be overwritten.