Developer Guide
- Acknowledgements
- Setting up, getting started
- Design
- Selected Implementation
-
Planned Enhancements
- Shorter Command Formats
- Reduce Coupling Between Availability and Animal Type
- Support More Animal Types
- Allow Fosterers To Foster More Than One Animal At A Time
- Case-sensitivity of Inputs
- Allow Symbols in Name
- Phone Number Input
- Guide Users on How To Rectify / Preventing the Corruption of Data File
- Notes Feature as a Separate Command
- Specificity of Error Messages
- Documentation, logging, testing, configuration, dev-ops
- Appendix: Requirements
-
Appendix: Instructions for manual testing
- Launch and shutdown
- Adding a fosterer
- Deleting a fosterer
- Listing a fosterer
- Saving changes in details of fosterer when add is done in the profile page
- Saving changes in details of fosterer when edit is done in the profile page
- Sorting the list of fosterers
- Undoing the previous command
- Viewing statistics of fosterers
- Editing details of a fosterer
- Resetting the address book
Acknowledgements
- File icon and Help icon used in the main window are from Flaticon.
- Useful notations in the User Guide was inspired from a past project TaskBook.
- Technical Terms in the User Guide was inspired from a past project Sellah.
Setting up, getting started
Refer to the guide Setting up and getting started.
Design
The
.puml files used to create diagrams in this document docs/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 (consisting of classes Main and MainApp) is in charge of the app launch and shut down.
- At app launch, it initializes the other components in the correct sequence, and connects them up with each other.
- At shut down, it shuts down the other components and invokes cleanup methods where necessary.
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),
- 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. Notably, Profile is a separate set of classes that handle the UI of the view command, which will be covered later in this document.
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:

The sequence diagram below illustrates the interactions within the Logic component, taking execute("delete 1") API call as an example.

DeleteCommandParser should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
AddressBookParser and ViewModeParser Classes
LogicManager class utilizes either AddressBookParser or ViewModeParser depending on whether the user is seeing the main window or a fosterer’s profile.
Given below is a sequence diagram that explains how LogicManager class chooses which parser class to use:

As the diagram suggests, the executeInView() method is used when personListPanelPlaceHolder UI element - the placeholder that contains the normal fosterer list - is invisible, which means the user sees the profile page. This triggers the ViewModeParser instance in LogicManager class to be used to parse the command. If the placeholder is visible, it means the user is seeing the main window, in which case the execute() method is used and the commands the user enters are parsed by AddressBookParser.
The reason for creating two separate parser classes is to provide mutual exclusion between the commands available in main window and in a profile page. For example, SaveCommand should only be executed in the context of editing a fosterer’s detail in profile page, not in main window.
How the Logic component works
Here is a step-by-step explanation of how the Logic component works when it uses AddressBookParser:
- When
Logicis called upon to execute a command, it is passed to anAddressBookParserobject which in turn creates a parser that matches the command (e.g.,DeleteCommandParser) and uses it to parse the command. - This results in a
Commandobject (more precisely, an object of one of its subclasses e.g.,DeleteCommand) which is executed by theLogicManager. - The command can communicate with the
Modelwhen it is executed (e.g. to delete a person). - The result of the command execution is encapsulated as a
CommandResultobject which is returned back fromLogictoUI.
Here is a step-by-step explanation of how the Logic component works when it uses ViewModeParser:
- When
Logicis called upon to execute a command, it is passed to anViewModeParserobject which in turn creates aCommandobject (e.g.,SaveCommand). - The command is then executed by the
LogicManager, communicating with theModelwhen it is executed (e.g. to save a person). - The result of the command execution is encapsulated as a
CommandResultobject which is returned back fromLogic.
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 in AddressBookParser
- 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 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.
Multiplicities and other navigabilities are omitted from diagram for simplicity.
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)
Common classes
Classes used by multiple components are in the commons package.
Selected Implementation
This section describes some noteworthy details on how certain features are implemented.
View feature
Called PersonProfile or simply “profile” internally. The profile follow this structure:

Except notes and tags, all other fosterer details are handled using dynamically created copies of PersonProfileField.
-
PersonProfileHeaderserves as headers for the data, and cannot be edited by the user. -
PersonProfileFieldhandles a field key and a field value, where the value can be edited. -
PersonProfileNoteis similar to a field, except it contains aTextAreaand supports multiline input. -
PersonProfileTagsalso supports multiline input, but when in read mode displays tags in aFlowPane.
The following is a sequence diagram that shows two sequential processes: the user starting an edit in a field, and the user successfully completing that edit. The alternative paths to this process are numerous, and covering them exhaustively is likely not productive. Instead, this represents the “success path” of a successful edit, where nearly every step handles potential failure.
Step 1. The user begins by entering “mail” in the command box of the main UI.
Step 2. The MainWindow finds the correct field that corresponds to the user input, and tells PersonProfile.
Step 3. PersonProfile locates the relevant PersonProfileField, and forwards the request for focus.
Step 4. The user’s cursor now jumps to the relevant PersonProfileField, and thus their next action is handled directly from PersonProfileField.
Step 5. The user presses the enter key, which alongside the esc key, are special keys involved in the confirmation or cancellation of the edit.
Step 6. PersonProfileField checks that the entered information is valid for that particular field.
Step 7. PersonProfileField then updates the PersonProfile about the change.
Step 8. PersonProfileField triggers the event AFTER_CONFIRM because the user started a confirmation.
Step 9. One of the event handlers listening to the AFTER_CONFIRM event is handleFieldLockIn, which initiates the next two steps.
Step 10. handleFieldLockIn checks that the new Person object described by the fields is valid, and creates one.
Step 11. handleFieldLockIn then asks the MainWindow to tell the user that the Person is created.
Further details on the MainWindow side are omitted in this explanation and diagram.

Add feature
Implementation
The add mechanism allows users to add new fosterers to the address book. This feature is facilitated by the AddCommand and AddCommandParser classes, to handle user input and create the appropriate Person object. Specifically, the feature is implemented through the following components and operations:
-
AddCommand— The core component responsible for executing the addition of a new fosterer to the address book. It handles the validation of input fields and ensures there are no duplicate persons in the address book. -
Person— Represents the structure of a person, including attributes such as name, phone, email, address, housing, availability, animal name, animal type, and associated tags. -
ParserUtilandAddCommandParser— Contains parsing methods for various input fields (e.g., name, phone, email, etc.) to ensure they are valid by meeting specific requirements and conditions. -
ArgumentMultimap— Tokenizes and manages command arguments.
Given below is an example usage scenario and how the add mechanism behaves at each step. To make the sequence diagram for adding a fosterer more readable, the following replacements for the lengthy add command format are used:
-
add n/Pete Tay p/98765411 e/pete@example.com a/Happy street block 5 housing/Condo availability/Available animal/nil animalType/able.Catis replaced withadd command. -
n/Pete Tay p/98765411 e/pete@example.com a/Happy street block 5 housing/Condo availability/Available animal/nil animalType/able.Catis replaced witharguments. -
Pete Tay, 98765411, pete@example.com, Happy street block 5, Condo, Available, nil, able.Catis replaced withattributes.

AddCommandParser should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
Step 1. The user enters the add command with relevant details for the new fosterer. The AddCommandParser is invoked to parse the user’s input.
Step 2. The AddCommandParser processes the user’s input and verifies the presence of mandatory fields inputted in the correct format (omitted from diagram for simplicity).
If this check fails, the system will generate a specific error message indicating which field format is invalid.
For example, if the email format is incorrect, the system will report that the email input is invalid. The error message will be displayed to the user, providing clear feedback about the issue and the specific constraints that are not met.
Step 3. If all mandatory fields are present with the valid format, the new person is created using the Person class. The person’s details, including their name, phone, email, address, housing, availability, animal name, animal type, and tags, are recorded, and the Person class also ensures that there is no conflicting data (omitted from diagram for simplicity).
If this check fails, the system will generate a specific error message indicating which field is invalid, and how can it be resolved.
Step 4. The Person is then passed to the new AddCommand created, which adds the person to the address book, ensuring that it is not a duplicate of an existing entry. This check is performed in the execute method of the AddCommand.
Step 5. A success message is displayed to the user to confirm that the new fosterer has been added to the address book.
The add feature ensures that user input is correctly parsed and validated, and it prevents duplicate entries in the address book.
The following activity diagram summarizes what happens when a user executes an add command:

Design considerations:
- Data Validation — The add feature performs thorough validation on input data, ensuring that it adheres to constraints for each field.
- Duplicates — The system checks for duplicate persons to prevent the addition of redundant data.
Aspect: Handling duplicate persons:
-
Alternative 1: Checks for duplicates based on the person’s name, which is case-sensitive.
- Pros: Easy to implement, and is simple and effective.
- Cons: May not catch duplicates with different names but similar attributes or similar names in different letter case.
-
Alternative 2: Implement a more comprehensive duplicate check considering multiple attributes.
- Pros: Provides better duplicate detection by comparing multiple attributes.
- Cons: May be more complex to implement.
-
Alternative 3 (current choice): Implement a more effective duplicate check considering the presence of multiple spaces between different words of the same name, and case-sensitivity of names.
- Pros: Provides better duplicate detection by identifying fosterers with the same name, but inputted in different formats.
- Cons: May be more complex to implement and such cases might be less likely to happen.
Aspect: How add executes:
-
Alternative 1 (current choice): Add only one fosterer at a time.
- Pros: Easy to implement.
- Cons: May be time-inefficient and inconvenient if there is an influx of new fosterers to be added.
-
Alternative 2: Add multiple fosterers at once.
- Pros: Do not have to parse user input multiple times in order for the user to perform mass addition of new fosterers.
- Cons: The add command would be even more convoluted due to the increase in length with all the fields/arguments required, making the UI less desirable.
Editing and Saving the Changes in Profile Page Feature
Handling UI Changes In Profile Page
While the profile page is opened, MainWindow classes checks the CommandType Enum value that is carried by the CommandResult object which is returned from executing a Command. Depending on the types of the commands, MainWindow assigns handler methods to handle the corresponding UI changes.
The sequence diagram given below illustrates the types of handlers MainWindow class deals with.

As the diagram suggests, depending on the different types of commands, MainWindow class executes handlers corresponding to them.
Editing A Fosterer In Profile Page
The mechanism allows the user to edit details of a fosterer in their profile page. This feature is facilitated by ViewModeParser, and EditFieldCommand classes, to handle user input in the profile page and edit the correct detail of a fosterer. This feature is implemented using the following components and operations:
-
ViewModeParser- Represents the parser that parses commands that are executed in a fosterer’s profile. -
EditFieldCommand- The core component responsible for executing the edit of a fosterer in the address book. -
MainWindow- The UI component that handles navigating through fields. -
CommandType- The Enum class that represents the type of command which MainWindow checks to handle the UI change.
Given below is an example usage scenario and how the mechanism behaves at each step, given that the user already opened person profile page:
Step 1. The user enters the name of the field. e.g. “name”. Since the fosterer list is invisible, “name” is passed to executeInView() method in MainWindow class (refer to the explanation in the section of Logic Component:AddressBookParser and ViewModeParser Classes).

Step 2. With executeInView(), ViewModeParser is used to parse the command which returns EditFieldCommand.

Step 3. EditFieldCommand is executed, and with the CommandType.EDIT_FIELD carried by CommandResult, MainWindow calls handleEditField() method. The interaction between MainWindow and PersonProfile is covered in detail in View Feature.

Saving the Changes in Profile Page Feature
The mechanism allows the user to save the edited details of a fosterer in their profile page. This feature is facilitated by ViewModeParser, and SaveCommand classes, to handle user input in the profile page and save the updated fosterer. This feature is implemented using the following components and operations:
-
ViewModeParser- Represents the parser that parses commands that are executed in a fosterer’s profile. -
SaveCommand- The core component responsible for saving the changes made by the user. -
MainWindow- The UI component that handles navigating through fields. -
CommandType- The Enum class that represents the type of command which MainWindow checks to handle the UI change.
Given below is an example usage scenario and how the save mechanism behaves at each step, given that the user already opened person profile page:
Step 1. The user enters save command. Since the normal person list is invisible, the command text “save” is passed to executeInView() method in MainWindow class (refer to the explanation in the section of Logic Component:AddressBookParser and ViewModeParser Classes).

Step 2. With executeInView(), ViewModeParser is used to parse the command text which returns SaveCommand.

Step 3. EditFieldCommand is executed, and setPerson() method from Model class is called with personToEdit and targetIndex obtained from MainWindow class.

Step 4. From MainWindow, handleSave() handler method is called which calls resetValues() in PersonProfile class that updates the field values to the currently saved fosterer’s details and change the text color from red, if exists, back to black.

Ensuring the user saved the changes before exiting profile
The mechanism ensures the user to save the edited details of a fosterer in their profile page by displaying warning message. This feature is facilitated by ViewModeParser, and ViewExitCommand classes, to handle user input in the profile page and save the updated fosterer. This feature is implemented using the following components and operations:
-
ViewModeParser- Represents the parser that parses commands that are executed in a fosterer’s profile. -
SaveCommand- The core component responsible for saving the changes made by the user. -
MainWindow- The UI component that handles navigating through fields. -
CommandBox- The UI component that detects either Enter or Esc input to continue exiting or cancel exiting. -
ResultDisplay- The UI component that displays the warning message when the user attempts to exit without saving. -
CommandType- The Enum class that represents the type of command which MainWindow checks to handle the UI change.
Given below is an example usage scenario and how this mechanism behaves at each step, given that the user already opened person profile page and did not save the edit:
Step 1. The user enters exit command in the profile page. Since the fosterer list is invisible, the command text “exit” is passed to executeInView() method in MainWindow class (refer to the explanation in the section of Logic Component:AddressBookParser and ViewModeParser Classes).

Step 2. With executeInView(), ViewModeParser is used to parse the command text which returns ViewExitCommand.

Step 3. ViewExitCommand is executed, and getFilteredPersonList() method in Model is used to compare the edited fosterer and the original fosterer to see if the details are saved. The CommandResult is returned to the MainWindow.

Step 4. From MainWindow, handleViewExit() handler method is called. The getInConfirmationDialog() method in CommandBox UI class is used to check if the user is seeing the confirmation message. If the user already saved the fosterer or is already in confirmation dialog, exitProfilePage() is called and user exits the profile. Otherwise, the user is shown the confirmation message alerting them that they did not save the details.

Step 5. If the user presses Enter in the CommandBox, handleViewExit() method is called again. This time, the screen is already showing the confirmation message, so isShowingConfirmationMessage is true. Thus, the user is exited out of the profile page. If the user presses Esc instead, handleCancelViewExit() method is called and lets the user stays in the profile page.

Design considerations:
Aspect 1: Different SaveCommand behaviors for adding and editing a fosterer in profile page:
Here are the justifications of why SaveCommand exits the profile page when adding a new fosterer but does not when editing a fosterer’s details.
-
Alternative 1 (current choice): Executing
SaveCommandexits directly when adding a new fosterer, but does not exit when editing a fosterer on their profile page.- Pros: Less error-prone. Duplicate fosterers are checked with the names. If the user edits the person’s name and enters save again, it would create another fosterer.
- Cons: May be cumbersome for users who want to edit the user’s details on the same page.
-
Alternative 2: Users are able to continue adding details when adding or editing a fosterer.
- Pros: Gives better user experience since user can continue working without exiting the profile page.
- Cons: Harder to implement without making it error prone.
-
Alternative 3:
SaveCommandexits the profile page for both adding and editing a fosterer.- Pros: Least error-prone and less confusing because of its consistent behavior.
- Cons: Users have to exit and re-enter profile page several times.
Aspect 2: How displaying confirmation message is implemented:
-
Alternative 1 (current choice): Accepts inputs (Enter or Esc) from
CommandBoxand callMainWindowhandlers from it.- Pros: Does not have to create separate command for confirming or cancelling exit. Since the user may type other commands instead of such confirming command, this prevents potential errors that may arise from attempting to execute commands while the message is shown.
- Cons: Increases coupling between
MainWindowandCommandBox.
-
Alternative 2: Create another command for confirming or cancelling exit.
- Pros: Easy to implement. Utilizes the current architecture and does not add additional coupling between
MainWindowandCommandBox. - Cons: May potentially cause errors since users may type in different commands.
- Pros: Easy to implement. Utilizes the current architecture and does not add additional coupling between
List feature
Implementation
The list feature allows users to filter through the address book. Note that internally, find and list are considered the same command.
For class naming purposes, ListCommand displays all individuals, while FindCommand parses a search expression.
This naming oddity is due to historical reasons; currently, the user triggers ListCommand with find (no search expression), and triggers FindCommand with list Tom.
In this section, we focus only on FindCommand, which is strictly the more complex of the two. Particularly important classes are as follows:
-
FindCommand— The core component responsible for applying the filter to the address book. -
Model— An object representing all the fosterers in the address book. Required forFindCommandto pass aPredicateto, to begin filtering. -
SearchPredicate—Predicatewrapper around other search objects, to be passed to theModel. -
FindCommandParserandFindCommandArgumentParser— Parse user arguments after thefindkeyword.FindCommandParseradheres to the same method convention as otherParsersfor other commands, while callingFindCommandArgumentParserto turn the user argument into aSearchPredicate.
The following class diagram shows all classes involved:

To illustrate how everything works together, we trace the flow of execution as the user searches for Tom / Sam. Details involving MainWindow and LogicManager are ignored, especially since they are common across all commands.
Step 1. The user enters list Tom/Sam. MainWindow calls LogicManager, which calls AddressBookParser, and in turn FindCommandParser, which handles the resulting String.
Step 2. FindCommandParser calls FindCommandArgumentParser, to turn the string into a SearchPredicate containing a SearchMatcher.
Step 3. FindCommandParser uses the SearchPredicate to initialize a FindCommand, and returns it to AddressBookParser, which in turn returns to LogicManager.
Step 4. LogicManager calls the execute function of the command it received. In this case, it received FindCommand. It passes a Model to the execute function as well.
Step 5. FindCommand calls updateFilteredPersonList of the Model, which refreshes the currently displayed list of fosterers.
Step 6. The list command stops here, and execution is returned to the LogicManager, and then MainWindow. The MainWindow shows text feedback, together with the updated list of fosterers.
The following diagram ignores details for SearchPredicate, which will be covered shortly:

Let’s dive into greater detail for SearchPredicate. We look at how the SearchPredicate handles a Person object:

To illustrate how SearchMatcher works, we consider the object diagram for the command list John & Doe / Mae.
These objects are created by FindCommandArgumentParser through parse("John & Doe / Mae):

When the Search Predicate is applied to a specific Person, the resulting flow of calls is as depicted by the following sequence diagram:

Design Considerations
- Expressiveness — The search is required to be sufficiently expressive to handle common everyday tasks with efficient, singular commands. This includes brackets.
- Typing Flow — Where possible, search expressions should support being written from left to right, without having to use the cursor, arrow keys or backspace key to backtrack or rewrite. This is the primary reason the search has two
ANDsymbols of different precedences. - Intuitiveness — Search expressions use symbols
&and/, which are intuitive for the target user. - Conciseness — Search expressions are as short as possible. This is the primary reason for not including field-specific searches, as that would increase the amount of text users have to type, often for minimal benefit.
- Flexibility — Where possible, search expressions are allowed to be flexible. This includes automatically closing brackets and allowing any number of whitespaces (including none) between expression terms.
Note: The Range return value from SearchMatcher is kept for potential future work, such as matches that avoid overlaps, or matches that must adhere to a certain order. Current functionality does not take advantage of Range.
Delete feature
Implementation
The delete mechanism allows users to delete fosterers in the address book. This feature is facilitated by the DeleteCommand, DeleteCommandParser and Indices classes, to handle user input and delete the correct fosterers. This feature is implemented using the following components and operations:
-
DeleteCommand— The core component responsible for executing the deletion of fosterers in the address book. -
Indices— Represents the indices that the user inputs, each index corresponding to a fosterer in the last seen list of fosterers. This class encapsulates one or moreIndexobjects. -
ParserUtilandDeleteCommandParser— Contains the parsing methods for string input of the user. They ensure that the indices are valid by meeting specific requirements.
Given below is an example usage scenario and how the delete mechanism behaves at each step. The sequence diagram for deleting multiple fosterers is similar to the example in Logic.

DeleteCommandParser should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
Step 1. The user enters the delete command with at least one index. In this example, the user inputs indices 1 2 3, which means that they want to delete the first, second and third fosterers in the currently displayed list. The DeleteCommandParser is invoked to parse the user’s input.
Step 2. DeleteCommandParser will then invoke the ParserUtil to check for the validity of indices (invocation of methods in ParserUtil and Indices classes are omitted from diagram for simplicity). If indices are invalid, the system will generate an error message. The error message will be displayed to the user, providing feedback about the issue and the specific constraints that are not met.
Step 3. For each valid index, the DeleteCommand will execute the deletion by obtaining that fosterer from the list of unique persons in the address book, and then updating the model to remove the fosterer. This is done in the execute method of DeleteCommand.
Step 4. A success message is displayed to the user to confirm that the selected fosterers have been deleted from the address book.
Therefore, by ensuring that the user input indices are correctly parsed and validated, this delete feature allows the user to delete multiple fosterers at once.
Design considerations:
Aspect: How delete executes:
-
Alternative 1 (current choice): Delete multiple fosterers at once.
- Pros: Do not have to parse user input multiple times in order for the user to perform mass deletion.
- Cons: Slightly harder to implement.
-
Alternative 2: Delete only one fosterer at a time.
- Pros: Easy to implement.
- Cons: Overhead associated with the chain of delete commands should the user choose to perform multiple deletions.
Sort feature
Implementation
The Sort feature allows the user to sort the list of fosterers alphabetically by name, to make the address book more organised.
This is facilitated by the SortCommand, Model, AddressBook, and UniquePersonList classes:
-
SortCommand— This class represents the command to sort the list of persons by name. It calls thesortByNamemethod in theModelclass. -
ModelandModelManager— Declares and implements thesortByNamemethod, specifying a comparator based on the person’s name. It calls thesortNamesmethod in theAddressBookclass. -
AddressBook— Implements thesortNamesmethod which usessorton thepersonsUniquePersonList. -
UniquePersonList— Contains thesortmethod to perform the sorting operation by using the method on itsinternalList.
Given below is an example usage scenario and how the sort feature behaves at each step.

Step 1. The user enters the sort command. The SortCommand is invoked, and it calls the sortByName method in the Model interface, which is implemented in the ModelManager class.
Step 2. The sortByName method creates a comparator based on the name of a person.
It then calls the sortNames method in the AddressBook class (omitted from diagram for simplicity).
Step 3. The sortNames method initiates the sorting process and sorts the list of persons using the provided comparator.
It calls the sort method on the persons UniquePersonList (omitted from diagram for simplicity).
Step 4. The sort method in the UniquePersonList class performs the actual sorting operation on its internalList.
Step 5. A success message is displayed to the user to confirm that the address book has been sorted alphabetically by the names of the fosterers.
The sort feature offers the user a choice to ensure that the list of fosterers in the address book is collated neatly and systematically.
Design considerations:
Aspect: How sort executes:
-
Alternative 1 (current choice): Sort alphabetically only based on the fosterers’ names.
- Pros: Easier to implement.
- Cons: Users may have different preferences for sorting (e.g., sorting by first name, last name, or a combination)..
-
Alternative 2: Customisable sorting - Allow the user to choose to sort the list alphabetically based on either the fosterers’ names or the names of the animals fostered.
- Pros: Offers greater flexibility for the users to choose which sorting criteria he/she prefers.
- Cons: If two animals have the same name or if both are
nil, the sorting operation may change their relative order.
Aspect: Reverting the sort operation:
-
Alternative 1 (current choice): Implement an
undocommand to revert the list back to its original state (sorted chronologically based on when the fosterer is added).- Pros: Maintains consistency with undo mechanisms used in other features of Foster Family.
- Cons: If
sortis executed multiple times consecutively followed byundo, the list will not revert back to its original state with the current implementation ofundo, which only allows the users to undo the last valid command.
-
Alternative 2: Implement another
sortcommand likesort timeto revert the list back to its original state (sorted chronologically based on when the fosterer is added).- Pros: Offers an explicit and clear command for reverting to the original sorting of the address book list.
- Cons: Introduces additional commands, potentially leading to increased cognitive load for the users.
Statistics feature
Implementation
The Statistics feature provides a summary of selected address book data to the user. The data we can provide insights to are those of available fosterers, current fosterers and housing type of fosterers. Statistics include number and percentage information.
This is facilitated by the StatsCommand, StatsAvailCommand, StatsCurrentCommand and StatsHousingCommand classes, as well as the StatsCommandParser class. The relationship between the Stats command classes are shown below.

-
StatsCommand— This is an abstract class that contains utility methods used by its subclasses for percentage calculation. -
StatsAvailCommand— Contains methods to calculate statistics of available fosterers and the animals they can foster. -
StatsCurrentCommand— Contains methods to calculate statistics of current fosterers and the animals they are currently fostering. -
StatsHousingCommand— Contains methods to calculate statistics of the different housing types of fosterers. -
StatsCommandParser— Contains the parsing methods for string input of the user. It is in charge of parsing the type of statistics requested by the user, and creating the correspondingStatsCommand.
Given below is an example usage scenario and how the statistics feature behaves at each step. It shows the execution of a stats avail command, which requests for statistics about available fosterers.

StatsCommandParser should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
Step 1. The user enters the stats avail command.
Step 2. StatsCommandParser is then invoked to parse the argument inputted with the stats command, in this case it is avail. If the argument is not avail, current or housing, the StatsCommandParser will generate an error message to the user, indicating that the requested statistic is not available.
Step 3. The StatsAvailCommand will then call relevant methods to obtain the needed numbers and percentages, done in the execute command.

Step 4. A success message with the statistics will then be displayed to the user.
The other commands stats current and stats housing have a similar execution path, replacing StatsAvailCommand with StatsCurrentCommand and StatsHousingCommand respectively, and obtaining their own relevant statistics.
Design considerations:
Aspect: How to display the statistics:
-
Alternative 1 (current choice): Show the availability and current statistics separately.
- Pros: Displayed statistics are specific to the user’s query, showing only the relevant data.
- Cons: User may need to query multiple times to get all desired statistics.
-
Alternative 2: Show availability and current statistics together.
- Pros: Easier to implement. More convenient for user, only one query needed to get all statistics.
- Cons: Result message displayed will be very long, making the UI less desirable.
Aspect: Which list should the statistics be calculated from:
-
Alternative 1 (current choice): Calculated from the currently displayed list.
- Pros: The resulting statistic corresponds to what the user sees, allowing for easy verification.
- Cons: The user may first need to perform a
findorlistcommand to query the list of interest before entering the stats command.
-
Alternative 2: Calculated from the main list of fosterers.
- Pros: The resulting statistic corresponds to the whole address book, which may cause less confusion for the user.
- Cons: Less flexibility for the user.
Undo feature
Implementation
The undo feature allows users to revert the last executed command in the address book. This feature is facilitated by the UndoCommand, AddressBookParser, and LogicManager classes. The undo feature is implemented using the following components and operations:
-
UndoCommand— The core component responsible for executing the undo operation in the address book. -
AddressBookParser— Handles the parsing of the user’s undo command. -
LogicManager— Represents the application’s data and business logic, including the functionality to undo the last command.
Given below is an example usage scenario and how the undo mechanism behaves at each step. The sequence diagram illustrates the interactions inside the Logic component for the undo command. The diagrams illustrate the flow of the execution of a successful undo command. In the diagrams below, the instance of backupModel is a separate instance from the current model and only serves as a container to save the data from the current model.

Step 1. The user launches the application for the first time. The backupModel will be initialized with the initial address book state.
Step 2. The user executes a command. The LogicManager checks if the command is an instance of the undo command.
Step 3. If the command is an instance of the add, delete, edit, sort or a successful execution of the reset command, the backupmodel data will be replaced with a copy of the current model data before the execution of the entered command.
Step 4. If the command is an instance of the undo command and the current model data is not the same as the data from the backupModel, the current model data will be replaced with the data from the backupModel. Else an error message will be displayed.
Step 5. A success message is displayed to the user to confirm that the last command has been undone.
The following activity diagram summarizes what happens when a user executes an undo command:

addressBookStateList.
Design considerations:
Aspect: How undo executes:
-
Alternative 1 (current choice): Saves a backup of the entire address book.
- Pros: Easy to implement and not too memory intensive.
- Cons: Can only save one previous instance of the address book.
-
Alternative 2: Individual commands knows how to undo by itself.
- Pros: Will use less memory (e.g. for
delete, just save the person being deleted). - Cons: We must ensure that the implementation of each individual command are correct.
- Pros: Will use less memory (e.g. for
-
Alternative 3: Saves multiple backups of the entire address book.
- Pros: Easy to implement.
- Cons: Memory intensive and may have performance issues in terms of memory usage.
Reset feature
Implementation
The reset feature allows users to erase the contents of the address book. This feature is facilitated by the ClearCommand, ClearCommandParser, AddressBookParser, and LogicManager classes. The undo feature is implemented using the following components and operations:
-
ClearCommand— The core component responsible for erasing the entire address book. -
ClearCommandParser— Handles the parsing of the arguments for the reset command. -
AddressBookParser— Handles the parsing of the user’s reset command. -
LogicManager— Represents the application’s data and business logic, including the functionality to check if the user has properly gone through the appropriate steps to execute a successful address book reset.
Given below is an example usage scenario and how the reset mechanism behaves at each step. The sequence diagram illustrates the interactions inside the Logic component for the first execution of the reset command. The diagrams illustrate the flow of the execution of a successful reset command.
Step 1. The user enters the reset command. And is given a warning of the functionality of the reset command and is prompted to enter reset confirm to continue executing the command.

Step 2. The user enters the reset confirm command.

Step 3. A success message is displayed to the user to confirm that the entire address book has been erased.
The following activity diagram summarizes what happens when a user executes a reset command:

Design considerations:
Aspect: How reset prompts confirmation:
-
Alternative 1 (current choice): Require a
resetcommand followed byreset confirm.- Pros: Intuitive and prevents accidental resets.
- Cons: Troublesome to execute.
-
Alternative 2: Make
resetthrow an error and havereset confirmbe the actual command.- Pros: Easy to implement.
- Cons: Accidental resets can still happen.
Planned Enhancements
Shorter Command Formats
Currently, the default add command may be too long for an average typer to key in quickly. A future enhancement we are planning would be to allow the addition of a fosterer with just the basic details, such as their name, phone number, email, housing type and availability. The rest of the fields will be set to nil by default.
Only when the fosterer is ready to foster, then other details such as animal name, animal type and address need to be filled in via the edit command.
We are also planning to shorten some input parameters when adding or editing a fosterer:
| Current | Enhancement |
|---|---|
availability/Available |
avail/true |
availability/NotAvailable |
avail/false |
availability/nil |
avail/nil |
animalType/ |
type/ |
With this, the command add n/Jerry Tan p/98765412 e/jerry123@example.com housing/HDB avail/true will be a valid add
command.
Reduce Coupling Between Availability and Animal Type
Currently, the animalType field also contains information about the availability of a fosterer.
e.g. if the animalType field of a fosterer is able.Dog, it suggests that the fosterer is available, and is
able to foster a dog. However, the user will still need to enter the availability field as available.
Building on the enhancement in Shorter Command Formats, we will be revising the
AVAILABILITY and ANIMAL_TYPE parameters:
| Parameter | About | Values |
|---|---|---|
AVAILABILITY |
Indicates availability of fosterer |
false, true, nil
|
ABLE_ANIMAL_TYPE |
Indicates the type of animals the fosterer can foster |
dog, cat, nil
|
CURRENT_ANIMAL_TYPE |
Indicates the type of animals the fosterer is currently fostering |
dog, cat, nil
|
Support More Animal Types
Building on the enhancement in Reduce Coupling Between Availability and Animal Type, we can support more animal types by allowing the addition of animals other than cats and dogs under ABLE_ANIMAL_TYPE and CURRENT_ANIMAL_TYPE. Some examples include
hamster and rabbit. This will make our product available to more animal shelters.
Allow Fosterers To Foster More Than One Animal At A Time
Currently, we only allow the assignment of one fosterer to one animal. To improve this, we can make the ANIMAL_NAME,
ABLE_ANIMAL_TYPE and CURRENT_ANIMAL_TYPE fields to be maintained as lists instead. This will allow one fosterer to be associated with more than one animal.
Case-sensitivity of Inputs
Currently, the fields and parameters for housing, availability and animal type are case-sensitive. An enhancement to this would be to make these fields and their parameters case-insensitive to improve the user experience. Moreover, the aforementioned enhancements will also be case-insensitive.
Allow Symbols in Name
Currently, names in Foster Family must be alphanumeric. However, this excludes certain legal names that have other
characters such as /. For example, we currently do not allow s/o in a person’s name as the / is used as a command
delimiter. Hence, one possible improvement is to enforce that the name inputted by the user must be enclosed in quotation marks for parsing, and to allow symbols such as /, ', - etc. using regex. Additionally, we will disallow the use of numeric values in names, to prevent the case where a number is inputted as a name.
e.g. n/"Henry Tan" and n/"Nagaratnam s/o Suppiah" are now valid name parameters.
Phone Number Input
Currently, phone numbers in Foster Family accept more than 8 digits as a valid input. This might cause invalid phone numbers to be recorded without error messages to warn the user of such mistakes, especially in the situation where local phone numbers are used. Hence, one possible improvement is to enforce that the phone number inputted by the user must be restricted to a maximum of 15 digits (according to the international phone numbering plan).
e.g. p/90876534567890234567 is now an invalid phone number parameter.
Guide Users on How To Rectify / Preventing the Corruption of Data File
Currently, the Foster Family data is saved automatically as a JSON file, and in the case where the data file is updated directly
and made invalid, Foster Family would either discard all data and start with an empty data file. Even though it is advised in the
user guide that user should not make changes to the data file directly, one possible improvement to be made to prevent such
incidents would be to either use a database with username and password authentication or implement encryption. An alternative
solution would be to account for all the cases and error messages to handle an invalid fosterer entry in the data file. We can do so
by editing the classes in storage such that the user would be informed, through the message, of the steps to take to rectify the
errors made.
Notes Feature as a Separate Command
Currently, the notes feature is only available in the profile page, and its content, which can only be recorded via the
save command, is inputted through the text box visible next to the Notes field. However, it could potentially be
inconvenient for the user to have to use a combination of different commands (an example would be view, followed by notes and
save) in order to record additional crucial information with regard to a particular fosterer. This breeds inefficiency in some
scenarios, especially in the situation where an animal with existing medical conditions is fostered and its health status has to
be frequently updated. Hence, an enhancement to this feature would be to make the notes feature a separate command, such that the
user would be able to add important notes in the main window, without having to navigate to the profile page and using the
additional save command to add the notes.
e.g. notes 1 n/require an urgent visit to the vet would add the notes “require an urgent visit to the vet” under the fosterer
listed at index 1.
Specificity of Error Messages
Currently, when the user attempts to add a fosterer with an invalid combination of availability, animal name and animal type, the same error message with multiple details of how to rectify different errors is sometimes shown, which can be confusing for the user. In particular, in the following three cases, the same error message is displayed:
Cases:
-
availability/nilbutanimalType/is notnil. -
availability/AvailablewithanimalType/values set to other values which are NOTable.Cat,able.Dogornil. -
availability/NotAvailablewithanimalType/values set to other values which are NOTcurrent.Cat,current.Dogornil.
Error message:
“If fosterer is available, animal type should be ‘able.Dog’ / ‘able.Cat’.
If animal type information is not available, it should be inputted as ‘nil’.
If fosterer is NOT available and is currently fostering, animal type should be ‘current.Dog’ / ‘current.Cat’.
If fosterer is currently unable to foster, animal type should be inputted as ‘nil’.
If availability is ‘nil’, animal type should be ‘nil’ too.”
Hence, an enhancement would be to split the error message up to only show when each specific case occur, instead of grouping them all together into a single message. This would reduce confusion for the user and provide more convenience as the user is no longer required to read long error messages with details that might be irrelevant to the specific error made.
| Cases | Enhanced error message |
|---|---|
availability/nil but animalType/ is not nil
|
If availability is ‘nil’, animal type should be ‘nil’ too. |
availability/Available with animalType/ values set to other values which are NOT able.Cat, able.Dog or nil
|
If fosterer is available, animal type should be ‘able.Dog’ / ‘able.Cat’. If animal type information is not available, it should be inputted as ‘nil’. |
availability/NotAvailable with animalType/ values set to other values which are NOT current.Cat, current.Dog or nil
|
If fosterer is NOT available and is currently fostering, animal type should be ‘current.Dog’ / ‘current.Cat’. If fosterer is currently unable to foster, animal type should be inputted as ‘nil’. |
Documentation, logging, testing, configuration, dev-ops
Appendix: Requirements
Product scope
Target user profile:
- Foster manager of non-profit animal shelters for cats and dogs, who currently do not have a good logistical workflow to keep track of their fosterers
- Prefer desktop apps over other types
- Can type fast
- Prefers typing to mouse interactions
- Is reasonably comfortable using CLI apps
Value proposition: Low budget and efficient system that manages fosterers
User stories
Priorities: High (must have) - * * *, Medium (nice to have) - * *, Low (unlikely to have) - *
| Priority | As a … | I want to … | So that I can… |
|---|---|---|---|
* * * |
foster manager | delete a fosterer from the list when they want to stop fostering with us | update the list to see the fosterers who are currently in our program |
* * * |
foster manager | delete multiple fosterers at once | perform mass deletions quickly |
* * * |
foster manager | add each fosterer’s details efficiently | know how to contact the fosterer should I have animals that require fostering |
* * * |
foster manager | assign an animal to a fosterer | provide the animal with a temporary home, and make a record of who is taking care of the animal |
* * * |
foster manager | provide details of the fostered animal of concern to the fosterer | ensure that the animal is well taken care by informing the fosterer of existing health conditions to prepare for |
* * * |
foster manager | update a fosterer’s details | keep track of fosterer’s most up-to-date information, including information about the animal fostered |
* * * |
foster manager | search for a specific animal / fosterer’s detail instead of browsing through the entire list | be more productive when searching for suitable fosterers for the animal that needs fostering |
* * * |
foster manager | to be aware of the address of the fosterer | conduct checks on the fosterer to ensure the animal is well taken care of |
* * * |
foster manager | retrieve information about the foster family | provide the necessary information to the Nparks authorities for audit |
* * * |
foster manager | note down the foster period of the animal | keep track of when the fosterer is supposed to return the animal to the shelter |
* * * |
foster manager | sort the list of fosterers alphabetically | have a neater, and more organised view of all the fosterers |
* * * |
foster manager | know the distribution of the different housing types among fosterers | correctly allocate the animals to foster homes that are able to accommodate them |
* * * |
foster manager | obtain statistics about available fosterers | better estimate shelter capacity, since having more animals under the care of fosterers will allow me to have more temporary space in the shelter for more animals |
* * |
foster manager | have the fosterer’s important information collated neatly | get all the information I need with one glance |
* * |
foster manager | have an easily accessible and visible help button | get help when I am unsure of what command to use |
* * |
foster manager | undo my previous command | quickly resolve errors caused by the erroneous command |
* * |
new foster manager | have my initial data file pre-populated with sample data | work with this sample data as an introduction to the app |
* * |
new foster manager | purge all current data from address book | remove all sample/ experimental data I used to explore the app |
* * |
careless foster manager | be asked to confirm my decision before purging all fosterer data | prevent myself from accidentally deleting all fosterer records |
* * |
foster manager | keep track of animals who are eligible for fostering | know which animal is ready to be assigned to a fosterer |
* * |
foster manager | assign a volunteer to the fosterer | have volunteers check up on the foster animal, to verify its well being |
* * |
foster manager | view which volunteer is assigned to which animal | properly balance workload and ensure that no volunteer is overburdened |
* |
foster manager | retrieve documentation of all species of animals under the purview of the shelter | ensure compliance with regulations for wildlife, protected or endangered species (Nparks audit) |
* |
foster manager | retrieve history of whereabouts of an animal | ensure accountability for pets’ accommodations, and verify that pets are monitored daily for signs of illness, injury or disease (Nparks audit) |
* |
foster manager | assign more than one animal to the fosterer | allow more animals to benefit from living under the care of a fosterer |
Use cases
(For all use cases below, the System is the Foster Family, and the Actor is the Foster Manager, unless specified otherwise)
Use case: UC1 - Add Fosterer
Preconditions: Foster Manager has collected fosterer details.
MSS
- Foster Manager requests to add fosterer to the System.
-
System adds the specified fosterer.
Use case ends.
Extensions
- 1a. System detects a format error in the entered command.
- 1a1. System indicates the error and requests for data to be inputted in the correct format.
-
1a2. Foster Manager enters new command.
Steps 1a1 - 1a2 are repeated until the command entered is in the correct format.
Use case resumes from step 2.
- 1b. System detects a conflicting add that will create an invalid fosterer.
- 1b1. System indicates the error and requests for Foster Manager to input a valid fosterer.
-
1b2. Foster Manager enters new command.
Steps 1b1 - 1b2 are repeated until the fosterer is valid.
Use case resumes from step 2.
Use case: UC2 - List / Find Fosterers
MSS
- Foster Manager requests to list fosterers.
-
System displays list of fosterers that matches the Foster Manager’s query.
Use case ends.
Extensions
- 1a. System detects a format error in the entered command.
- 1a1. System indicates the error and requests for data to be inputted in the correct format.
-
1a2. Foster Manager enters new command.
Steps 1a1 - 1a2 are repeated until the command entered is in the correct format.
Use case resumes from step 2.
Use case: UC3 - Edit Fosterer Using Main Window
MSS
- Foster Manager lists fosterers (UC2).
- Foster Manager requests to edit a fosterer referenced by their index shown in the list, specifying details to edit.
- System updates fosterer details.
-
System displays updated fosterer.
Use case ends.
Extensions
- 2a. System detects an invalid index.
- 2a1. System indicates the error and requests for a valid index.
-
2a2. Foster Manager enters new command.
Steps 2a1 - 2a2 are repeated until the entered index is valid.
Use case resumes from step 3.
- 2b. System detects a format error in the entered command.
- 2b1. System indicates the error and requests for data to be inputted in the correct format.
-
2b2. Foster Manager enters new command.
Steps 2b1 - 2b2 are repeated until the command entered is in the correct format.
Use case resumes from step 3.
- 2c. System detects a conflicting edit that will create an invalid fosterer.
- 2c1. System indicates the error and requests for Foster Manager to input a valid edit.
-
2c2. Foster Manager enters new command.
Steps 2c1 - 2c2 are repeated until the command entered is valid.
Use case resumes from step 3.
Use case: UC4 - Edit Fosterer Using Profile
MSS
- Foster Manager lists fosterers (UC2).
- Foster Manager requests to edit a fosterer referenced by their index shown in the list.
- System displays details of the selected fosterer.
- Foster Manager enters the desired changes.
- Foster Manager requests to save the changes.
-
System displays the updated list of fosterers.
Use case ends.
Extensions
- 1a. System detects an invalid index.
- 1a1. System indicates the error and requests for a valid index.
-
1a2. Foster Manager enters new command.
Steps 1a1 - 1a2 are repeated until the entered index is valid.
Use case resumes from step 2.
- 4a. System detects that the Foster Manager did not fill up compulsory fields.
- 4a1. System indicates missing field error.
- 4a2. Foster Manager fills up the missing compulsory fields.
-
4a3. Foster Manager requests to save the changes.
Steps 4a1-4a3 are repeated until every compulsory field is filled.
Use case resumes from step 5.
- 4b. System detects a conflicting edit that will create an invalid fosterer.
- 4b1. System indicates the error and requests for Foster Manager to input a valid edit.
-
4b2. Foster Manager enters new command.
Steps 4b1 - 4b2 are repeated until the command entered is valid.
Use case resumes from step 5.
Use case: UC5 - Delete Fosterers
MSS
- Foster Manager lists fosterers (UC2).
- Foster Manager requests to delete fosterers referenced by their index shown in the list.
- System deletes selected fosterers.
-
System displays the updated list of fosterers.
Use case ends.
Extensions
- 2a. System detects invalid indices.
- 2a1. System indicates the error and requests for valid indices.
-
2a2. Foster Manager enters new command.
Steps 2a1 - 2a2 are repeated until all entered indices are valid.
Use case resumes from step 3.
Use case: UC6 - Sort List Of Fosterers
MSS
- Foster Manager lists fosterers (UC2).
- Foster Manager requests to sort the list of fosterers.
-
System displays the updated list of fosterers, sorted alphabetically by name, where uppercase letters come before lowercase letters.
Use case ends.
Extensions
- 1a. System detects an error in the entered command.
- 1a1. System indicates the error.
- 1a2. Foster Manager requests for command 'help' (UC8).
-
1a3. Foster Manager enters new command.
Steps 1a1 - 1a3 are repeated until the command entered is correct.
Use case resumes from step 2.
Use case: UC7 - View Statistics
MSS
- Foster Manager lists fosterers (UC2).
- Foster Manager requests to view a certain statistic of the displayed fosterers.
-
System displays the relevant statistic.
Use case ends.
Extensions
- 2a. The displayed list is empty.
-
2a1. System indicates error.
Use case ends.
-
- 2b. Requested statistic is invalid.
- 2b1. System indicates error, and prompts Foster Manager to request for a valid statistic.
-
2b2. Foster Manager enters new command.
Steps 2b1 - 2b2 are repeated until a valid statistic is requested.
Use case resumes from step 3.
Use case: UC8 - Undo Previous Command
MSS
- Foster Manager requests to undo the previous command.
-
System undoes the previous command.
Use case ends.
Extensions
- 1a. No more undo history is found.
-
1a1. System indicates error.
Use case ends.
-
Use case: UC9 - Request For Command Help
MSS
- Foster Manager requests for help.
-
System displays the help page link.
Use case ends.
Use case: UC10 - Reset System
MSS
- Foster Manager requests to reset the System.
- System requests for confirmation.
- Foster Manager confirms.
-
System purges all fosterer data from the system.
Use case ends.
Extensions
-
2a. Foster Manager chooses to cancel reset.
Use case ends.
Use case: UC11 - Exit
MSS
- Foster Manager requests to exit the program.
-
System closes program.
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 500 fosterers 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.
- The system should be usable by a novice foster manager who has never tried out keeping track of fosterers through this new system.
- The system should respond within two seconds. (i.e. each time a valid command is entered or there is any use action)
- The user interface should be intuitive enough for users who are not IT-savvy.
- The user guide should be easily understood by target users. (foster managers of animal shelters, assuming they have no relevant technical knowledge)
- The system should be able to detect invalidity of command within 2 seconds.
- The system must be able to scale up or down as needed (in the case where there is a sudden fosterers).
- The system should not contain the fosterer’s private information in the case that the fosterer did not give consent.
- The system must comply with all applicable laws and regulations like the Personal Data Protection Act (PDPA).
- The system should be reliable, easy to maintain, and accessible 24/7.
- The product should be able to run on mainstream OS.
Glossary
- Mainstream OS: Windows, Linux, Unix, OS-X
- Fosterer: A person who temporarily cares for an animal in their own home
- Housing type: Categorised into HDB, Condo, Landed
- Types of animal fostered: Categorised into solely cats and/or dogs (current.Dog/Cat or able.Dog/Cat depends on availability of fosterer)
- Current list: The currently displayed list obtained from a list command or its variants
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
-
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.
-
Adding a fosterer
-
Adding a fosterer after collecting all the mandatory details to be inputted
-
Prerequisites: Foster Manager has collected fosterer details such as name, phone number, email, address, housing type, availability, name of animal fostered (if currently fostering) and type of animal fostered (if currently fostering).
-
Test case (valid):
add n/Anne Lim p/98765422 e/anne123@example.com a/Baker street, block 6, #27-01 housing/Landed availability/NotAvailable animal/Bucky animalType/current.Dog
Expected: Fosterer named Anne Lim is added to the list. Details of the added fosterer are shown in the status message. -
Test case (non-exhaustive list of invalid add commands):
-
| Scenario | Example command | Expected Error Message |
|---|---|---|
Without any of the following: n/, p/,e/, a/, housing/, availability/, animal/, animalType/
|
add n/Jerry Tan p/98765412 e/jerry123@example.com a/Baker street, block 5, #27-01 housing/HDB animal/Dexter animalType/current.Cat t/Urgent |
Invalid command format! add: Adds a person to the address book. Parameters: n/NAME p/PHONE e/EMAIL a/ADDRESS housing/HOUSING availability/AVAILABILITY animal/ANIMAL_NAME animalType/ANIMAL_TYPE [t/TAG]... Note: If information for that field is not available, put 'nil'. Example: add n/John Doe p/98765432 e/johnd@example.com a/311, Clementi Ave 2, #02-25 housing/HDB availability/NotAvailable animal/Dexter animalType/current.Dog t/Urgent t/goodWithDogs |
availability/nil but animal/ is not ‘nil’ |
add n/Jerry Tan p/98765412 e/jerry123@example.com a/Baker street, block 5, #27-01 housing/HDB availability/nil animal/Dexter animalType/nil t/Urgent |
When an animal name is provided, availability should not be 'Available' or 'nil'. |
availability/Available but animal/ is not ‘nil’ |
add n/Jerry Tan p/98765412 e/jerry123@example.com a/Baker street, block 5, #27-01 housing/HDB availability/Available animal/Dexter animalType/nil t/Urgent |
When an animal name is provided, availability should not be 'Available' or 'nil'. |
housing/ with values other than ‘HDB’, ‘Condo’, ‘Landed’, ‘nil’ |
add n/Jerry Tan p/98765412 e/jerry123@example.com a/Baker street, block 5, #27-01 housing/hdb availability/NotAvailable animal/Dexter animalType/current.Cat t/Urgent |
Housing type should be either 'HDB', 'Condo', 'Landed' or 'nil' |
availability/ with values other than ‘Available’, ‘NotAvailable’, ‘nil’ |
add n/Jerry Tan p/98765412 e/jerry123@example.com a/Baker street, block 5, #27-01 housing/HDB availability/available animal/Dexter animalType/current.Cat t/Urgent |
Availability should be either 'Available', 'NotAvailable' or 'nil' |
availability/nil but animalType/ is not ‘nil’ |
add n/Jerry Tan p/98765412 e/jerry123@example.com a/Baker street, block 5, #27-01 housing/HDB availability/nil animal/nil animalType/able.Cat t/Urgent |
If fosterer is available, animal type should be 'able.Dog' / 'able.Cat'. If animal type information is not available, it should be inputted as 'nil'. If fosterer is NOT available and is currently fostering, animal type should be 'current.Dog' / 'current.Cat'. If fosterer is currently unable to foster, animal type should be inputted as 'nil'. If availability is 'nil', animal type should be 'nil' too. |
availability/Available with animalType/ values set to other values which are NOT ‘able.Cat’ or ‘able.Dog’ or ‘nil’ |
add n/Jerry Tan p/98765412 e/jerry123@example.com a/Baker street, block 5, #27-01 housing/HDB availability/Available animal/nil animalType/current.Cat t/Urgent |
If fosterer is available, animal type should be 'able.Dog' / 'able.Cat'. If animal type information is not available, it should be inputted as 'nil'. If fosterer is NOT available and is currently fostering, animal type should be 'current.Dog' / 'current.Cat'. If fosterer is currently unable to foster, animal type should be inputted as 'nil'. If availability is 'nil', animal type should be 'nil' too. |
availability/NotAvailable with animalType/ values set to other values which are NOT ‘current.Cat’ or ‘current.Dog’ or ‘nil’ |
add n/Jerry Tan p/98765412 e/jerry123@example.com a/Baker street, block 5, #27-01 housing/HDB availability/NotAvailable animal/Dexter animalType/able.Cat t/Urgent |
If fosterer is available, animal type should be 'able.Dog' / 'able.Cat'. If animal type information is not available, it should be inputted as 'nil'. If fosterer is NOT available and is currently fostering, animal type should be 'current.Dog' / 'current.Cat'. If fosterer is currently unable to foster, animal type should be inputted as 'nil'. If availability is 'nil', animal type should be 'nil' too. |
availability/NotAvailable with animalType/ values set to ‘nil’ but animal/ values NOT ‘nil’ |
add n/Jerry Tan p/98765412 e/jerry123@example.com a/Baker street, block 5, #27-01 housing/HDB availability/NotAvailable animal/Dexter animalType/nil t/Urgent |
When availability is 'NotAvailable', animal name and type have to either be both 'nil' or both not 'nil'. |
availability/NotAvailable with animal/ values set to ‘nil’ but animalType/ values NOT ‘nil’ |
add n/Jerry Tan p/98765412 e/jerry123@example.com a/Baker street, block 5, #27-01 housing/HDB availability/NotAvailable animal/nil animalType/current.Cat t/Urgent |
When availability is 'NotAvailable', animal name and type have to either be both 'nil' or both not 'nil'. |
Deleting a fosterer
-
Deleting a fosterer while all fosterers are being shown
-
Prerequisites: List all fosterers using the
listorfindcommand. At least 3 fosterers in the list. -
Test case:
delete 1
Expected: First fosterer is deleted from the list. Details of the deleted fosterer are shown in the status message. -
Test case:
delete 1 2 3
Expected: First, second and third fosterers are deleted from the list. Number of deleted fosterers, and their details are shown in the status message. -
Test case:
delete 0
Expected: No person is deleted. Error details are shown in the status message. -
Other incorrect delete commands to try:
delete,delete x, (where x is larger than the list size)
Expected: Similar to previous.
-
-
Deleting fosterers while only some fosterers are shown follows similar test cases.
Listing a fosterer
-
Find through an exact, quoted match with
".- Test case:
list "Pete"
Expected: Shown fosterers include “Pete” but not “Peter”.
- Test case:
-
Verify operator precedence and parentheses.
-
Test case:
list Doe & Sam / John
Expected: Equivalent tolist Doe & (Sam / John). Shown fosterers include “John Doe” but not “John Snow”. -
Test case:
list (Doe & Sam) / John
Expected: Shown fosterers include “Sam Doe” and “John Snow”.
-
Saving changes in details of fosterer when add is done in the profile page
-
Saving the new fosterer added through the profile page
- Test case:
save
Expected: Exits the profile page. Fosterer will be successfully added to the address book.
- Test case:
Saving changes in details of fosterer when edit is done in the profile page
-
Saving the edits made to a fosterer in the profile page
- Test case:
save
Expected: Fosterer’s details will be successfully edited and saved if they are valid. Command success message is shown.
- Test case:
Sorting the list of fosterers
-
Sorting the list of fosterers in the main window alphabetically by name, where uppercase letters come before lowercase letters
-
Test case:
sort
Expected: The whole list of fosterers will be sorted alphabetically. Command success message is shown. -
Test case:
sort 12345
Expected: The whole list of fosterers will be sorted alphabetically. Command success message is shown.
-
Undoing the previous command
-
Undoing the previous command successfully executed
-
Prerequisites: The previous command successfully executed is either
add,delete,edit,sortor a successful execution of theresetcommand. -
Test case:
undo
Expected: Previous command will be undone. Command success message is shown. -
Test case:
undo 12345
Expected: Previous command will be undone. Command success message is shown.
-
Viewing statistics of fosterers
- Viewing statistics of available fosterers
-
Prerequisites: List all fosterers using the list or find command. At least 1 fosterer in the list.
-
Test case:
stats avail
Expected: Availability statistics shown. -
Test case:
stats <multiple whitespaces> avail
Expected: Similar to previous. -
Test case:
stats availl avail
Expected: Invalid command, error details shown in status message. -
Test case:
stats avail list
Expected: Availability statistics shown.statscommands ignore extraneous parameters after the valid command is detected. -
Test case:
stats avail current
Expected: Only availability statistics shown.statscommands will only display the first valid statistic field detected (ie. eitheravail,currentorhousing).
-
- Viewing statistics of current fosterers and housing types work similarly, replacing
availwithcurrentandhousingrespectively.
Editing details of a fosterer
- Editing through the main window
- Prerequisites: At least one fosterer in the list, and the first fosterer has at least 2 tags.
-
Test case:
edit 1 p/99887776
Expected: Fosterer 1’s phone number successfully edited. -
Test case:
edit 1 t/new
Expected: Fosterer 1’s existing tags are overwritten. The only tag is thenewtag. -
Test case:
edit 1 n/Ben Yeo e/benyeo123@gmail.com
Expected: Fosterer 1’s name and email successfully edited. - Invalid edit commands to try:
edit n/Ben Yeo,edit x n/Ben Yeo(where x is larger than the list size).
- Prerequisites: At least one fosterer in the list, and the first fosterer has at least 2 tags.
- Opening the profile view for editing
-
Prerequisites: At least one fosterer in the list, and the first fosterer has at least 2 tags.
-
Test case:
edit 1orview 1
Expected: Profile view of fosterer 1 opens for editing. -
Test case:
edit 1 listoreditorview
Expected: Profile view does not open, error message shown.
-
- Field jumping in profile view
-
Prerequisites: The profile view of a fosterer is currently open.
-
Test case:
ph
Expected: Cursor jumps to the Phone field for editing. -
Test case:
type
Expected: Cursor jumps to the Animal Type field for editing.
-
- Editing details in profile view
-
Availability =
NotAvailable, Animal Name =nilAnimal Type =nil
Expected on Enter: Valid fosterer. -
Availability =
Available, Animal Name =nilAnimal Type =nil
Expected on Enter: Valid fosterer. -
Availability =
NotAvailable, Animal Name =mewAnimal Type =able.Cat
Expected on Enter: Invalid fosterer, and error message shown.
-
Resetting the address book
- Resetting the Address Book
-
Prerequisites:
resetcommand must be entered first, before enteringreset confirm. -
Test case:
reset
Expected: Warning displayed of the function of theresetcommand and a prompt of enteringreset confirmis displayed to continue executing the command. -
Test case:
reset confirm
Expected: A prompt to enterresetfirst followed byreset confirmto execute the command. -
Test case:
reset randomArg
Expected: Warning displayed of the function of theresetcommand and a prompt of enteringreset confirmis displayed to continue executing the command. -
Test case:
resetfollowed byreset confirm
Expected: The Address Book is erased and a command success massage is displayed.
-