Developer Guide
- 1. How to navigate this Developer Guide
- 2. Setting up, getting started
- 3. Design
- 4. Implementation
- 5. Documentation, logging, testing, configuration, dev-ops
- 6. Appendix: Requirements
- 7. Appendix: Instructions for manual testing
1. How to navigate this Developer Guide
The target audience of this guide is for anyone who wishes to extend or modify the functionality of ZooKeepBook. The guide is split into 3 sections, covering the design of ZooKeepBook, the implementation of certain features as well as how to manage the development of ZooKeepBook.
The following symbols are used throughout this developer guide. They highlight important information that may be useful to you:
| Symbol | Description | 
|---|---|
|  | This block contains additional tips that may aid you | 
|  | This block contains additional information that may be used to elaborate on the content presented | 
| text markup  | Indicates Java class and method names | 
2. Setting up, getting started
Refer to the guide Setting up and getting started.
3. Design
This section describes the high-level components that make up ZooKeep.
3.1. Architecture
The Architecture Diagram (Figure 1) given below explains the high-level design of the App.

Figure 1: The Architecture Diagram of ZooKeep
Given below is a quick overview of each component.
 Tip: The
 Tip: The .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.
Main has two classes called Main and MainApp. 
It is responsible for the following situations:
- 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.
Each of the four components
- defines its API in an interfacewith the same name as the Component.
- exposes its functionality using a concrete {Component Name}Managerclass (which implements the corresponding APIinterfacementioned in the previous point.
For example, the Logic component (see Figure 2 below) defines its API 
in the Logic.java interface and exposes its functionality using the LogicManager.java class 
which implements the Logic interface.

Figure 2: Class Diagram of Logic component
The Sequence Diagram (Figure 3) below shows how the components interact with each other for the 
scenario where the user issues the command delete 123.

Figure 3: Sequence Diagram of delete command
The sections below give more details of each component.
3.2. UI component
The Class Diagram for the UI Component is shown below (Figure 4)

Figure 4: Class Diagram of UI Component
API :
Ui.java
The UI consists of a MainWindow that is made up of parts e.g.CommandBox, ResultDisplay, AnimalListPanel, StatusBarFooter etc. All these, including the MainWindow, inherit from the abstract UiPart class.
The UI component uses 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.
3.3. Logic component
The Class Diagram for the Logic Component is shown below (Figure 5)

Figure 5: Class Diagram of Logic Component
API :
Logic.java
- 
Logicuses theZooKeepBookParserclass to parse the user command.
- This results in a Commandobject which is executed by theLogicManager.
- The command execution can affect the Model(e.g. adding an animal).
- The result of the command execution is encapsulated as a CommandResultobject which is passed back to theUi.
- In addition, the CommandResultobject can also instruct theUito perform certain actions, such as displaying help to the user.
Given below is the Sequence Diagram (Figure 6) for interactions within the Logic component for the execute("delete 1") API call.

Figure 6: Sequence Diagram for delete command
 Note: The lifeline for
 Note: The lifeline for DeleteCommandParser should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
3.4. Model component
The Class Diagram for the Model Component is shown below (Figure 7)

Figure 7: Class Diagram of Model Component
API : Model.java
The Model,
- stores a UserPrefobject that represents the user’s preferences.
- stores the ZooKeepBook data.
- exposes an unmodifiable ObservableList<Animal>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.
- does not depend on any of the other three components.
 Note: An alternative (arguably, a more OOP) model is given below. It has
 Note: An alternative (arguably, a more OOP) model is given below. It has MedicalCondition and FeedTime lists in the ZooKeepBook, which Animal references. This allows ZooKeepBook to only require one MedicalCondition or FeedTime object per unique MedicalCondition or FeedTime, instead of each Animal needing their own MedicalCondition or FeedTime objects. 
3.5. Storage component
The Class Diagram for the Storage Component is shown below (Figure 8)

Figure 8: Class Diagram of Storage Component
API : Storage.java
The Storage component,
- can save UserPrefobjects in json format and read it back.
- can save the ZooKeepBook data in json format and read it back.
3.6. Common classes
Classes used by multiple components are in the seedu.zookeepbook.commons package.
4. Implementation
This section describes some noteworthy details on how certain features are implemented.
4.1. Undo feature (by Zhi Yuan)
4.1.1. Implementation
The undo feature is facilitated by a stack data structure.
The HistoryStack class wraps a stack designed to hold ReadOnlyZooKeepBook objects.
The Singleton Pattern is employed here since only one history instance should exist in the running of the application.
HistoryStack supports the following key features:
- 
HistoryStack#addToHistory(ReadOnlyZooKeepBook)- Adds the given state of the book into history only if it differs from the most recent state.
- 
HistoryStack#removeRecentHistory()- Removes the most recent state of the book from the history.
- 
HistoryStack#viewRecentHistory()- Returns the most recent state of the book.
- 
HistoryStack#clearHistory()- Clears the history.
The undo feature also depends on the following existing methods:
- 
Model#setZooKeepBook(ReadOnlyZooKeepBook)- Replaces the current model’s book data with the given.
- 
Model#getZooKeepBook()- Returns the model’s current book.
The following classes reference the above methods:
- UndoCommand
- LogicManager
 Note: Classes pertaining to the Redo command also refer to these methods, but will be excluded here and explained in the section below instead.
 Note: Classes pertaining to the Redo command also refer to these methods, but will be excluded here and explained in the section below instead.
Given below is an example usage scenario and how the undo mechanism behaves at each step.
Step 1. The user launches the application for the first time. The HistoryStack will be initialized with a single state (Figure 9), which is the current state.

Figure 9: State of HistoryStack upon initialization
Step 2. The user executes delete 1 command to delete the animal with ID 1. LogicManager calls Model#getZooKeepBook() to retrieve the new state of the book, and adds it to the history (Figure 10) with HistoryStack#addToHistory(ReadOnlyZooKeepBook).

Figure 10: State of HistoryStack after addition of new state
Step 3. The user executes help to view the help screen. LogicManager behaves as per Step 2. However, since no changes were made to the state, the current state is not added (Figure 11) to HistoryStack.

Figure 11: State of HistoryStack unchanged
 Note: If a command fails its execution, it will not call
 Note: If a command fails its execution, it will not call HistoryStack#addToHistory(), so the state will not be saved into the HistoryStack.
Step 4. The user now decides that deleting the person was a mistake, and decides to undo that action by executing the undo command. The undo command will call HistoryStack#removeRecentHistory() which deletes the current state, and exposes the previous state. HistoryStack#viewRecentHistory() is then called to retrieve the previous state, then loaded into the model (Figure 12) using Model#setZooKeepBook(ReadOnlyZooKeepBook).

Figure 12: State of HistoryStack after loading the previous state
 Note: If the
 Note: If the HistoryStack only contains a single state, then there is no previous state to restore. The undo command uses HistoryStack#getHistorySize() to check if this is the case. If so, it will return an error to the user rather
than attempting to perform the undo.
The following Sequence Diagram (Figure 13) shows how the undo operation works:

Figure 13: Sequence Diagram when undo command is executed
 Note: The lifeline for
 Note: The lifeline for UndoCommand should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
The following 2 Activity Diagrams (Figures 14.1 & 14.2) summarize what happens when a user executes a new command and when a user executes the undo command:


Figure 14.1 (left): Activity Diagram when user executes a command
Figure 14.2 (right): Activity Diagram when user undoes a command
4.1.2. Design consideration:
4.1.2.1. Aspect: How undo executes
- 
Alternative 1 (current choice): Saves the entire ZooKeepBook as a state.
    - Pros: Easy to implement, works with all commands immediately.
- Cons: May have performance issues in terms of memory usage as product scales.
 
- 
Alternative 2: Individual command knows how to undo by
itself.
    - Pros: Will use less memory (e.g. for delete, just save the animal being deleted).
- Cons: We must ensure that the implementation of each individual command are correct.
 
- Pros: Will use less memory (e.g. for 
4.2. Redo feature (by Jun Cheng)
4.2.1. Implementation
The Redo feature was added as a complement to the Undo feature which was done earlier. The addition of this
feature required the integration of the RedoCommand class, which extends from the Command class like all other commands.
The HistoryStack class also has new key features to support the redo command:
- 
HistoryStack#addToRedo(ReadOnlyZooKeepBook)- Adds a given state of the ZooKeepBook into the redo stack.
- 
HistoryStack#removeRecentRedo()- Removes the most ‘recent’ update of the ZooKeepBook from the redo stack.
- 
HistoryStack#viewRecentRedo()- Returns (but does not remove) the most ‘recent’ update of the ZooKeepBook.
- 
HistoryStack#clearRedo()- Clears the future updates of the ZooKeepBook stored in the redo stack.
The RedoCommand class references some of these methods to accomplish the feature required. Given below is an example
usage scenario and how the redo mechanism behaves at each step.
Step 1. The user launches the application for the first time. The ZooKeepBook is initialised with the initial state
given in data/zookeepbook.json, and the HistoryStack consists of 2 stacks; the history stack and the redo stack,
each in their respective initial states (Figure 15).

Figure 15: State of both stacks during initialization
Step 2. The user executes add n/Harambe... to add a new animal into the ZooKeepBook. The LogicManager calls
Model#getZooKeepBook() to retrieve the new state of the book and calls HistoryStack#addToHistory(ReadOnlyZooKeepBook)
as per normal undo protocol (Figure 16).

Figure 16: State of both stacks after executing add command
Step 3. The user then executes delete 567 which deletes the animal in the book with an ID of 567. Similar to step 2, 
LogicManager will call Model#getZooKeepBook() to retrieve the new state of the book and then calls 
HistoryStack#addToHistory(ReadOnlyZooKeepBook) to store this state into the history stack (Figure 17).

Figure 17: State of both stacks after executing delete command
Step 4. Now the user thinks that deleting that animal was a mistake and restores the previous state by 
executing undo (explained in the previous section). However, before the current state is deleted and replaced with 
the previous one, HistoryStack#addToRedo(ReadOnlyZooKeepBook) is called to store the current state into the redo 
stack (Figure 18) for further use.

Figure 18: State of both stacks after executing undo command
 Note: If
 Note: If UndoCommand is never executed, the 
redo stack will remain empty and calling RedoCommand will do nothing, since there are no future states recorded in
the stack for retrieval. 
Step 5. However, now the user decides that deleting that animal was the correct decision after all, and now executes 
redo which calls HistoryStack#viewRecentRedo() to retrieve the future state of the ZooKeepBook where the animal
was deleted. The future state is then loaded into the model using Model#setZooKeepBook(ReadOnlyZooKeepBook).
Lastly, HistoryStack#removeRecentRedo() is called to delete that state from redo stack (Figure 19).

Figure 19: State of both stacks after executing redo command
 Note: If commands which alter the state of the 
ZooKeepBook (e.g. add or delete) are executed after an undo command, the redo stack will be emptied since the
immediate future has been altered and the future states previously stored in the redo stack are now invalid. Hence 
executing redo now will do nothing.
 Note: If commands which alter the state of the 
ZooKeepBook (e.g. add or delete) are executed after an undo command, the redo stack will be emptied since the
immediate future has been altered and the future states previously stored in the redo stack are now invalid. Hence 
executing redo now will do nothing.
The following Sequence Diagram (Figure 20) illustrates how the Redo operation is performed:

Figure 20: Sequence Diagram when redo command is executed
 Note: The lifeline for
 Note: The lifeline for RedoCommand should end 
at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
The following 2 Activity Diagrams (Figures 21.1 & 21.2) summarise what happens when a user executes the undo and redo commands:


Figure 21.1 (left): Activity Diagram when user executes an undo command
Figure 21.2 (right): Activity Diagram when user executes a redo command
4.2.2. Design consideration:
4.2.2.1. Aspect: How redo executes
- 
Alternative 1 (current choice): Saves the entire ZooKeepBook as a state.
    - Pros: Easy to implement, works with all commands immediately.
- Cons: May have performance issues in terms of memory usage as product scales.
 
- 
Alternative 2: Individual command knows how to redo by
itself.
    - Pros: Will use less memory (e.g. for delete, just save the animal being deleted).
- Cons: We must ensure that the implementation of each individual command are correct.
 
- Pros: Will use less memory (e.g. for 
4.3. Snapshot feature (by Aizat)
4.3.1. Implementation
This section explains the implementation of the snapshot feature. This feature allows users
to save the current state of their ZooKeepBook as a json file with their desired file name.
The snapshot feature is implemented by the SnapCommand and SnapCommandParser classes. 
SnapCommandParser parses the user’s input as a file name. If the file name is valid,
 it returns a SnapCommand object with a Path object representing the save destination 
 and the file name as arguments. If the file name is invalid, it returns an error message.
SnapCommand executes by copying the current state of the ZooKeepBook and then calls
StorageManager#saveZooKeepBook(...) to save the copied ZooKeepBook with the user specified file name.
The following Sequence Diagram (Figure 22) illustrates the creation and execution of a SnapCommand:

Figure 22: Sequence Diagram when snap command is executed
 Note: The lifelines for
 Note: The lifelines for SnapCommandParser, SnapCommand, StorageManager 
should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
The following Activity Diagram (Figure 23) shows the flow of the execution of a SnapCommand:

Figure 23: Activity Diagram when snap command is executed
4.3.2. Design consideration:
4.3.2.1. Aspect: Overwriting files
- We chose to prevent users from creating a snapshot if the specified file name already exists as overwriting a file is irreversible and would be disastrous for zookeepers if done unintentionally
4.4. Sort feature (by Malcolm)
4.4.1. Implementation
This section explains the implementation of the Sort command feature in the ZooKeepBook. This feature is used to sort the animals based on the different categories: name, id, feedtime or medical.
- For the animal name, it will be in alphabetical order.
- For the animal id, it will be in ascending order.
- For the animal feed time, it will be the earliest feed time in chronological order.
- For the animal medical condition, it will be the number of conditions in ascending order.
The following Sequence Diagram (Figure 24) shows the Logic and Model Components when a sort command is being executed:

Figure 24: Sequence Diagram when sort command is executed
 Note: The lifeline for
  Note: The lifeline for SortCommand should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
In the Logic Component,
After the user keys in “sort name” as input, these key methods are called:
- 
LogicManager#execute("sort name"): TheLogicManagertakes in a command text string (“sort name/id/feedtime/medical”).
- 
ZooKeepBookParser#parseCommand("sort name"): TheZooKeepBookParserparses the user input into a command word (“sort”) and arguments (“name”). Using the command word, aSortCommandParseris created.
- 
SortCommandParser#parse("name"): TheSortCommandParsertakes in the argument(“name”) and parses it. AnAnimalComparatoris created and contains the specific static comparator required to sort the animals according to the category provided. ASortCommandis created with theAnimalComparatoras an attribute.- The AnimalComparatorcontains 4 different static comparators to be used for sorting:ANIMAL_NAME_COMPARATOR,ANIMAL_ID_COMPARATOR,ANIMAL_FEEDTIME_COMPARATORandANIMAL_MEDICAL_COMPARATOR.
- In this case, the ANIMAL_NAME_COMPARATORis taken.
 
- The 
- 
SortCommand#execute(model): TheSortCommanduses theAnimalComparatorto sort the animals and returns aCommandResultobject which represents the result of a command execution.
In the Model Component,
The in-memory model of the ZooKeepBook data sorts and updates the animal list. The following key methods are used:
- 
Model#sortAnimals(animalComparator): sorts the animals in theZooKeepBookusing the givenAnimalComparatorobject.
- 
ZooKeepBook#sortAnimals(animalComparator): Retrieves the static comparator in theAnimalComparatorobject and creates aSortedListobject. TheUniqueAnimalListin theZooKeepBookis then replaced by thisSortedListobject.
- 
ZooKeepBook#updateFilteredAnimalList(predicate): Updates the filter of the filtered animal list to filter by the given predicate, which will be true here so that the sorted list will be displayed once sorted.
Upon the completion of the user command, a success message (Sorted all animals by name) and the updated sorted list is displayed below the message.
The following Activity Diagram (Figure 25) summarises what happens when a user executes a sort command.

Figure 25: Activity Diagram when user executes sort command
4.4.2. Design Consideration:
4.4.2.1. Aspect: Sorting based on different categories
We chose to allow the user to sort not only based on animal names but also by their id, earliest feed times or number of medical conditions to ease the convenience of the user when he needs data to be sorted in other ways.
4.5. Feed times feature (by Jeremy)
4.5.1. Implementation
The feed times feature utilizes a TreeSet with a custom comparator.
Each Animal object has a FeedTimes TreeSet.
The custom comparator FeedTimeComparator compares the integer values of the feed times, returning them in ascending order.
The feed times feature allows for the following functionality:
- Add multiple feed times to each animal listing.
- Ensure feed times are always displayed in chronological order.
The following notable methods are used for the feed times feature:
- 
ParserUtil#parseFeedTimes(Collection<String>)- returns a Set ofFeedTimeobjects from user input
- 
FeedTime#isValidFeedTime(String)- validates the feed time to ensure it is in the HHmm format
The parsing and displaying of feed times were adapted from the Medical Condition field.
Given below is a Sequence Diagram (Figure 26) shows how the operation of adding feed times works.

Figure 26: Sequence Diagram when animal is added with feed times
Step 1. The user inputs an add command, specifying feed times to be added for an Animal (eg. add n/Pikachu i/1307 s/Pokemon f/1234 f/0001 f/2200)
Step 2. The ZooKeepBook class receives the user input. AddCommand.COMMAND_WORD is used to identify the type of command.
Step 3. The AddCommandParser class receives the arguments in the user input. The ArgumentTokenizer class is called with the PREFIX_FEED_TIME variable.
Step 4. The ArgumentTokenizer class returns the feed times found in the users input. A set of FeedTime objects is created by the parseFeedTimes method in the ParserUtil class.
 Note: A ParseException is thrown by parseFeedTimes if the feed time input does not match the defined format.
 Note: A ParseException is thrown by parseFeedTimes if the feed time input does not match the defined format.
 Note: The TreeSet created by parseFeedTimes utilizes the FeedTimeComparator, ensuring that the set is returned in chronological order.
 Note: The TreeSet created by parseFeedTimes utilizes the FeedTimeComparator, ensuring that the set is returned in chronological order.
Step 5. An Animal object is created with the Set of FeedTime objects.
The following Activity Diagram (Figure 27) summarizes what happens when feed times are added to an Animal:

Figure 27: Activity Diagram when user adds an animal with feed times
4.5.2. Design consideration:
4.5.2.1. Aspect: How chronological order is maintained
- 
Alternative 1 (current choice): Store the feed times in chronological order
    - Pros: Quick to display when retrieving information
- Cons: Initial creation and storage of feed times takes longer
 
- 
Alternative 2: Sort the feed times when information is retrieved
itself.
    - Pros: Quick during the initial creation of Animal objects
- Cons: Additional processing time required when displaying each Animal object
 
5. Documentation, logging, testing, configuration, dev-ops
This section provides guides for developers wishing to take on this framework for extension or morphing.
6. Appendix: Requirements
This section lists the target requirements for ZooKeep.
6.1. Product scope
Target user profile:
- Has a need to manage a significant number of animals
- Prefers desktop apps over other types
- Can type fast
- Prefers typing to mouse interactions
- Is reasonably comfortable using CLI apps
Value proposition:
- Zookeepers have to account for a large number of animals and their statuses (health, feed times etc).
- It is easy to lose track without a structured database.
- We have thus decided to morph the app into a tracker for an individual zookeeper.
- Easier to transfer a large amount of animal information when zookeepers change shifts.
- Manage animals faster than a typical mouse/GUI driven app.
6.2. 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 zookeeper | see usage instructions | refer to instructions when I forget how to use the App | 
| * * * | zookeeper | add an animal entry | keep track of a new animal under my care | 
| * * * | zookeeper | delete an animal entry | remove animals from my care | 
| * * * | zookeeper | retrieve the information of all the animals | have a look at which animals are under my duty | 
| * * * | zookeeper | load a save file | keep track of all the animals I have added | 
| * * * | zookeeper | save all the information when I need to | |
| * * * | zookeeper | exit the program after I have finished using it | |
| * * | zookeeper | search for a specific animal | filter through the large number of animals without viewing the entire list | 
| * * | zookeeper | quickly edit the data of certain animals | avoid deleting and adding the animal to do so | 
| * | zookeeper with many animals in the ZooKeepBook | sort animals by name and type | locate a specific animal easily | 
| * | experienced user | use shortcut commands to carry out tasks | save time without needing to type the full length commands | 
6.3. Use cases
(For all use cases below, the System is the ZooKeepBook and the Actor is the user, unless specified otherwise)
Use case: UC01 - Add an animal
MSS
- 
    User specifies the add command with name, ID and species of animal 
- 
    ZooKeepBook adds the animal 
- 
    ZooKeepBook shows the new animal added 
- 
    ZooKeepBook refreshes to show the updated list Use case ends 
Extensions
- 
    1a. The command is incorrectly formatted - 
        1a1. ZooKeepBook shows an error message 
- 
        Use case resumes at step 1 
 
- 
        
- 
    2a. The given ID is already taken - 
        2a1. ZooKeepBook shows an error message 
- 
        Use case resumes at step 1 
 
- 
        
Use case: UC02 - Delete an animal
MSS
- 
    User specifies the delete command with ID of animal 
- 
    ZooKeepBook deletes the animal 
- 
    ZooKeepBook shows the deleted animal 
- 
    ZooKeepBook refreshes to show the updated list Use case ends 
Extensions
- 
    1a. The command is incorrectly formatted - 
        1a1. ZooKeepBook shows an error message 
- 
        Use case resumes at step 1 
 
- 
        
- 
    2a. The given ID does not exist or is out of range - 
        2a1. ZooKeepBook shows an error message 
- 
        Use case resumes at step 1 
 
- 
        
Use case: UC03 - List all animals
MSS
- 
    User specifies the list command 
- 
    ZooKeepBook displays list of all existing animals Use case ends 
Use case: UC04 - Exit program
MSS
- 
    User specifies the exit command 
- 
    ZooKeepBook quits Use case ends 
Use case: UC05 - View available commands
MSS
- 
    User specifies the help command 
- 
    ZooKeepBook displays list of all available commands Use case ends 
Use case: UC06 - Find animals based on keywords
MSS
- 
    User specifies the find command with the keywords (case-insensitive) regarding an animal’s name, id, species, medical condition or feed time 
- 
    ZooKeepBook searches for all animals with any of the exact keywords 
- 
    ZooKeepBook shows the list of animals with any of those keywords Use case ends 
Extensions
- 
    1a. The command is incorrectly formatted - 
        1a1. ZooKeepBook shows an error message 
- 
        Use case resumes at step 1 
 
- 
        
Use case: UC07 - Sort all animals
MSS
- 
    User specifies the sort command and the specific category (name, id, feedtime or medical) 
- 
    ZooKeepBook sorts the animals according to the category 
- 
    ZooKeepBook shows a success message 
- 
    ZooKeepBook refreshes to show the sorted list Use case ends 
Extensions
- 
    1a. The command is incorrectly formatted - 
        1a1. ZooKeepBook shows an error message 
- 
        Use case resumes at step 1 
 
- 
        
Use case: UC08 - Undo last command
MSS
- 
    User specifies the undo command 
- 
    ZooKeepBook reverts to the state before last command was made 
- 
    ZooKeepBook shows a success message Use case ends 
Extensions
- 
    2a. There is no previous state to revert to - 
        2a1. ZooKeepBook shows an error message 
- 
        Use case ends 
 
- 
        
Use case: UC09 - Redo last undo
MSS
- 
    User specifies the redo command 
- 
    ZooKeepBook reverts to the state before undo command was made 
- 
    ZooKeepBook shows a success message Use case ends 
Extensions
- 
    2a. There is no previous state to revert to - 
        2a1. ZooKeepBook shows an error message 
- 
        Use case ends 
 
- 
        
Use case: UC10 - Save current animal data
MSS
- 
    User specifies the snap command with the appropriate file name 
- 
    ZooKeepBook creates a snapshot of the current ZooKeep book data which is saved as a file with the user specified file name Use case ends 
Extensions
- 
    1a. The command is incorrectly formatted - 
        1a1. ZooKeepBook shows an error message 
- 
        Use case resumes at step 1 
 
- 
        
- 
    1b. An invalid file name is entered - 
        1b1. ZooKeepBook shows an error message 
- 
        Use case resumes at step 1 
 
- 
        
Use case: UC11 - Append data to an animal
MSS
- 
    User specifies the append command with the animal ID and any relevant medical conditions and/or feed times to be added 
- 
    ZooKeepBook appends the entered animal conditions and/or feed times to the specific animal 
- 
    ZooKeepBook shows the edited animal details 
- 
    ZooKeepBook refreshes to show the updated list Use case ends 
Extensions
- 
    1a. The command is incorrectly formatted - 
        1a1. ZooKeepBook shows an error message 
- 
        Use case resumes at step 1 
 
- 
        
- 
    2a. The given ID does not exist or is out of range - 
        2a1. ZooKeepBook shows an error message 
- 
        Use case resumes at step 1 
 
- 
        
- 
    2b. No details are entered or the appended details result in no change to the animal - 
        2b1. ZooKeepBook shows an error message 
- 
        Use case resumes at step 1 
 
- 
        
Use case: UC12 - Replace the data of an animal
MSS
- 
    User specifies the replace command with the animal ID and any intended changes in the animal details 
- 
    ZooKeepBook replaces the current animal details with the entered changes 
- 
    ZooKeepBook shows the updated animal details 
- 
    ZooKeepBook refreshes to show the updated list Use case ends 
Extensions
- 
    1a. The command is incorrectly formatted - 
        1a1. ZooKeepBook shows an error message 
- 
        Use case resumes at step 1 
 
- 
        
- 
    2a. The given ID does not exist or is out of range - 
        2a1. ZooKeepBook shows an error message 
- 
        Use case resumes at step 1 
 
- 
        
- 
    2b. No details are entered or the entered details result in no change to the animal - 
        2b1. ZooKeepBook shows an error message 
- 
        Use case resumes at step 1 
 
- 
        
6.4. 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 animals 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 work on both 32-bit and 64-bit environments.
- The system is expected to show data persistence.
- The system should allow different users to access the same data to allow ease of transfer during shift changes.
- The system should have clear, complete and comprehensive documentation of all available commands and/or features by the end of the project.
- The system should be extensible such that new commands or features can be easily added to it if needed.
- The system should cope with emergency situations and allow for data archiving in case users need to retrieve important data stored in older versions of the ZooKeepBook.
- The system should respond to user requests (e.g. load data, add new animals) within 2 seconds, unless an error occurs.
- The system should be intuitive enough such that new staff are able to adapt quickly and use the app smoothly within a short time frame.
- The system should be user-friendly and implement helpful features to assist careless users, such as allowing for the undoing and redoing of commands.
- The system should be backward compatible with data produced by its earlier versions.
- The system should be flexible and allow its users some degree of freedom, by allowing them to enter certain command parameters in any order they wish.
- The project is expected to adhere to the schedule of the CS2103/CS2103T tP timeline which requires weekly deliverables and increments.
- The project is not required to sort and arrange tasks among all staff or ensure efficient task allocation and completion.
6.5. Glossary
- Mainstream OS: Windows, Linux, Unix, OS-X
- Data persistence: data provided by the user can be saved and updated to the hard drive, and can also be loaded once system is booted up again
- Data archiving: the process of moving data that is no longer actively used to a specified directory for long-term retention.
7. Appendix: Instructions for manual testing
This section provides instructions for testing the application manually.
 Note: These instructions only provide a starting point for testers to work on;
testers are expected to do more exploratory testing.
 Note: These instructions only provide a starting point for testers to work on;
testers are expected to do more exploratory testing.
7.1. Launch and shutdown
7.1.1. 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. 
7.1.2. 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.
7.2. Deleting an animal
- 
    Test case: delete 123
 Expected: The animal with an ID of 123 deleted from the list. Details of the deleted animal shown in the status message. Timestamp in the status bar is updated.
- 
    Test case: delete 0
 Expected: No animal is deleted. Error details shown in the status message. Status bar remains the same.
- 
    Other incorrect delete commands to try: delete,delete x,...(where x is smaller than all 3 digit numbers or larger than all 6 digit numbers)
 Expected: Similar to previous.
7.3. Saving data
7.3.1. Dealing with missing/corrupted data files
- 
    To simulate a missing/corrupted data file, delete the data/zookeepbook.jsonfile.
- 
    Re-launch the app by double-clicking the jar file. 
 Expected: The sample ZooKeepBook will be loaded as the newdata/zookeepbook.jsonfile.
7.3.2. Auto-saving feature
- 
    After launching the application, perform actions that edit the ZooKeepBook, such as addordelete. Close the window.
- 
    Re-launch the application. The changes that you just made should be reflected in the ZooKeepBook UI.