diff --git a/.gitignore b/.gitignore
index 71c9194e8bd..6d4a9c4b45a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,3 +20,5 @@ src/test/data/sandbox/
# MacOS custom attributes files created by Finder
.DS_Store
docs/_site/
+
+/bin
diff --git a/LICENSE b/LICENSE
index 39b3478982c..c42f359e055 100644
--- a/LICENSE
+++ b/LICENSE
@@ -2,11 +2,11 @@ MIT License
Copyright (c) 2016 Software Engineering Education - FOSS Resources
-Permission is hereby granted, free of charge, to any person obtaining a copy
+Permission is hereby granted, free of charge, to any patient obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
+copies of the Software, and to permit patients to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
diff --git a/README.md b/README.md
index 13f5c77403f..959cbf914d8 100644
--- a/README.md
+++ b/README.md
@@ -1,14 +1,13 @@
-[](https://github.com/se-edu/addressbook-level3/actions)
+[](https://github.com/AY2223S2-CS2103T-T12-2/tp/actions)

-* This is **a sample project for Software Engineering (SE) students**.
+* This is **a hospital patient management system**.
Example usages:
- * as a starting point of a course project (as opposed to writing everything from scratch)
- * as a case study
-* The project simulates an ongoing software project for a desktop application (called _AddressBook_) used for managing contact details.
- * It is **written in OOP fashion**. It provides a **reasonably well-written** code base **bigger** (around 6 KLoC) than what students usually write in beginner-level SE modules, without being overwhelmingly big.
- * It comes with a **reasonable level of user and developer documentation**.
-* It is named `AddressBook Level 3` (`AB3` for short) because it was initially created as a part of a series of `AddressBook` projects (`Level 1`, `Level 2`, `Level 3` ...).
-* For the detailed documentation of this project, see the **[Address Book Product Website](https://se-education.org/addressbook-level3)**.
-* This project is a **part of the se-education.org** initiative. If you would like to contribute code to this project, see [se-education.org](https://se-education.org#https://se-education.org/#contributing) for more info.
+ * Inpro of patients
+ * Access medical records of patients
+* The patient management system (called `MedInfo`) can be used for managing patient records.
+ * It is to digitise hospital patient management data through a CLI app with a GUI to display patient information, medical records or necessary financial records.
+ * It is to computerise the Front Office Management of Hospital to develop software which is user friendly, simple, fast, and cost–effective.
+ * The main function of the system is to register and store patient details and doctor details, retrieve these details as and when required, and also to manipulate these details meaningfully.
+* This project is based on the AddressBook-Level3 project created by the [SE-EDU initiative](https://se-education.org).
diff --git a/build.gradle b/build.gradle
index 108397716bd..373bd48fc73 100644
--- a/build.gradle
+++ b/build.gradle
@@ -6,7 +6,7 @@ plugins {
id 'jacoco'
}
-mainClassName = 'seedu.address.Main'
+mainClassName = 'seedu.medinfo.Main'
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
@@ -23,6 +23,7 @@ checkstyle {
test {
useJUnitPlatform()
finalizedBy jacocoTestReport
+ enableAssertions = true
}
task coverage(type: JacocoReport) {
@@ -66,7 +67,11 @@ dependencies {
}
shadowJar {
- archiveFileName = 'addressbook.jar'
+ archiveFileName = 'medinfo.jar'
+}
+
+run {
+ enableAssertions = true
}
defaultTasks 'clean', 'test'
diff --git a/docs/AboutUs.md b/docs/AboutUs.md
index 1c9514e966a..9cb8b045ae8 100644
--- a/docs/AboutUs.md
+++ b/docs/AboutUs.md
@@ -2,58 +2,68 @@
layout: page
title: About Us
---
-
We are a team based in the [School of Computing, National University of Singapore](http://www.comp.nus.edu.sg).
You can reach us at the email `seer[at]comp.nus.edu.sg`
## Project team
-### John Doe
+### Navaneeth Ramapurath
-
+
-[[homepage](http://www.comp.nus.edu.sg/~damithch)]
-[[github](https://github.com/johndoe)]
-[[portfolio](team/johndoe.md)]
+[[github](https://github.com/nramapurath)]
+[[portfolio](team/nramapurath.md)]
-* Role: Project Advisor
+- Role: Team Lead
+- Code Focus Area: Logic, model
+- Primary Role: Scheduling and tracking
+- Secondary Role: Testing
-### Jane Doe
+### Jerald Kiew
-
+
-[[github](http://github.com/johndoe)]
-[[portfolio](team/johndoe.md)]
+[[github](http://github.com/jeraldkiew)]
+[[portfolio](team/jeraldkiew.md)]
-* Role: Team Lead
-* Responsibilities: UI
+- Role: Developer
+- Code Focus Area: Model
+- Primary Role: Documentation
+- Secondary Role: Code Quality
-### Johnny Doe
+### K Sunil Avinash
-
+
-[[github](http://github.com/johndoe)] [[portfolio](team/johndoe.md)]
+[[github](http://github.com/ksunil2001)]
+[[portfolio](team/ksunil2001.md)]
-* Role: Developer
-* Responsibilities: Data
+- Role: Developer
+- Code Focus Area: Storage
+- Primary Role: Code Quality
+- Secondary Role: Documentation
-### Jean Doe
+### Nicholas Arlin Halim
-
+
-[[github](http://github.com/johndoe)]
-[[portfolio](team/johndoe.md)]
+[[github](http://github.com/daytona65)]
+[[portfolio](team/daytona65.md)]
-* Role: Developer
-* Responsibilities: Dev Ops + Threading
+- Role: Developer
+- Code Focus Area: UI
+- Primary Role: Code Integration
+- Secondary Role: Testing
-### James Doe
+### Sun Yitong
-
+
-[[github](http://github.com/johndoe)]
-[[portfolio](team/johndoe.md)]
+[[github](http://github.com/yitong241)]
+[[portfolio](team/yitong241.md)]
-* Role: Developer
-* Responsibilities: UI
+- Role: Developer
+- Code Focus Area: Logic
+- Primary Role: Deliverables and deadlines
+- Secondary Role: Scheduling and tracking
diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md
index 46eae8ee565..a505382a352 100644
--- a/docs/DeveloperGuide.md
+++ b/docs/DeveloperGuide.md
@@ -2,64 +2,105 @@
layout: page
title: Developer Guide
---
-* Table of Contents
-{:toc}
---------------------------------------------------------------------------------------------------------------------
+**MedInfo** is a desktop application that empowers clinics and hopitals to manage their patients.
+
+This Developer Guide provides an in-depth documentation on how **MedInfo** is designed and implemented.
+It covers the architecture of **MedInfo** and provides detailed descriptions regarding the implementation design.
+
+You can use this guide to maintain, upgrade, and evolve **MedInfo**.
+
+## Table of contents
+
+* [Getting Started](#setting-up-getting-started)
+* [Design](#design)
+ * [Architecture](#architecture)
+ * [UI](#ui-component)
+ * [Logic](#logic-component)
+ * [Model](#model-component)
+ * [Storage](#storage-component)
+ * [Common Classes](#common-classes)
+* [Implementation](#implementation)
+ * [Add Patients Feature](#adding-a-patient)
+ * [Add Wards Feature](#adding-a-ward)
+ * [Edit Patients Feature](#editing-a-patient)
+ * [Delete Patients Feature](#deleting-a-patient)
+ * [Find Patients Feature](#finding-patients)
+ * [List Patients Feature](#list-all-patients)
+ * [[Proposed] Undo Redo Feature](#proposed-undoredo-feature)
+ * [[Proposed] Data Archiving](#proposed-data-archiving)
+* [Appendix: Requirements](#appendix-requirements)
+ * [Target User Profile](#target-user-profile)
+ * [Value Proposition](#value-proposition)
+ * [User Stories](#user-stories)
+ * [Use Cases](#use-cases)
+ * [Use case: **add a patient**](#use-case-uc01---add-a-patient)
+ * [Use case: **delete a patient**](#use-case-uc02---delete-a-patient)
+ * [Use case: **edit a patient**](#use-case-uc03---edit-a-patient)
+ * [Use case: **find a patient**](#use-case-uc04---find-a-patient)
+ * [Use case: **clear all patients**](#use-case-uc05---clear-all-patients)
+ * [Use case: **add a ward**](#use-case-uc06---add-a-new-ward)
+ * [Use case: **delete a ward**](#use-case-uc07---delete-a-ward)
+ * [Use case: **sort patients**](#use-case-uc08---sort-patients)
+ * [Non-Functional Requirement](#non-functional-requirements)
+ * [Glossary](#glossary)
+* [Appendix: Instructions for Manual Testing ](#appendix-instructions-for-manual-testing)
+ * [**Launch and shutdown**](#launch-and-shutdown)
+ * [**Delete a patient**](#delete-a-patient)
+ * [**Save data**](#save-data)
+* [Appendix: Planned Enhancements](#appendix-planned-enhancements)
-## **Acknowledgements**
-* {list here sources of all reused/adapted ideas, code, documentation, and third-party libraries -- include links to the original source as well}
-
---------------------------------------------------------------------------------------------------------------------
+---
-## **Setting up, getting started**
+## Setting up, getting started
Refer to the guide [_Setting up and getting started_](SettingUp.md).
---------------------------------------------------------------------------------------------------------------------
+---
-## **Design**
+## Design
:bulb: **Tip:** The `.puml` files used to create diagrams in this document can be found in the [diagrams](https://github.com/se-edu/addressbook-level3/tree/master/docs/diagrams/) folder. Refer to the [_PlantUML Tutorial_ at se-edu/guides](https://se-education.org/guides/tutorials/plantUml.html) to learn how to create and edit diagrams.
+
### Architecture
-The ***Architecture Diagram*** given above explains the high-level design of the App.
+The **_Architecture Diagram_** given above explains the high-level design of the App.
Given below is a quick overview of main components and how they interact with each other.
**Main components of the architecture**
**`Main`** has two classes called [`Main`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/Main.java) and [`MainApp`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/MainApp.java). It is responsible for,
-* At app launch: Initializes the components in the correct sequence, and connects them up with each other.
-* At shut down: Shuts down the components and invokes cleanup methods where necessary.
+
+- 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`**](#common-classes) represents a collection of classes used by multiple other components.
The rest of the App consists of four components.
-* [**`UI`**](#ui-component): The UI of the App.
-* [**`Logic`**](#logic-component): The command executor.
-* [**`Model`**](#model-component): Holds the data of the App in memory.
-* [**`Storage`**](#storage-component): Reads data from, and writes data to, the hard disk.
-
+- [**`UI`**](#ui-component): The UI of the App.
+- [**`Logic`**](#logic-component): The command executor.
+- [**`Model`**](#model-component): Holds the data of the App in memory.
+- [**`Storage`**](#storage-component): Reads data from, and writes data to, the hard disk.
**How the architecture components interact with each other**
-The *Sequence Diagram* below shows how the components interact with each other for the scenario where the user issues the command `delete 1`.
+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 `interface` with the same name as the Component.
-* implements its functionality using a concrete `{Component Name}Manager` class (which follows the corresponding API `interface` mentioned in the previous point.
+- defines its _API_ in an `interface` with the same name as the Component.
+- implements its functionality using a concrete `{Component Name}Manager` class (which follows the corresponding API `interface` mentioned in the previous point.)
For example, the `Logic` component defines its API in the `Logic.java` interface and implements its functionality using the `LogicManager.java` class which follows the `Logic` interface. Other components interact with a given component through its interface rather than the concrete class (reason: to prevent outside component's being coupled to the implementation of a component), as illustrated in the (partial) class diagram below.
@@ -79,10 +120,10 @@ The `UI` component uses the JavaFx UI framework. The layout of these UI parts ar
The `UI` component,
-* executes user commands using the `Logic` component.
-* listens for changes to `Model` data so that the UI can be updated with the modified data.
-* keeps a reference to the `Logic` component, because the `UI` relies on the `Logic` to execute commands.
-* depends on some classes in the `Model` component, as it displays `Person` object residing in the `Model`.
+- executes user commands using the `Logic` component.
+- listens for changes to `Model` data so that the UI can be updated with the modified data.
+- keeps a reference to the `Logic` component, because the `UI` relies on the `Logic` to execute commands.
+- depends on some classes in the `Model` component, as it displays `Person` object residing in the `Model`.
### Logic component
@@ -93,9 +134,10 @@ Here's a (partial) class diagram of the `Logic` component:
How the `Logic` component works:
-1. When `Logic` is called upon to execute a command, it uses the `AddressBookParser` class to parse the user command.
+
+1. When `Logic` is called upon to execute a command, it uses the `MedInfoParser` class to parse the user command.
1. This results in a `Command` object (more precisely, an object of one of its subclasses e.g., `AddCommand`) which is executed by the `LogicManager`.
-1. The command can communicate with the `Model` when it is executed (e.g. to add a person).
+1. The command can communicate with the `Model` when it is executed (e.g. to add a patient).
1. The result of the command execution is encapsulated as a `CommandResult` object which is returned back from `Logic`.
The Sequence Diagram below illustrates the interactions within the `Logic` component for the `execute("delete 1")` API call.
@@ -110,27 +152,22 @@ Here are the other classes in `Logic` (omitted from the class diagram above) tha
How the parsing works:
-* When called upon to parse a user command, the `AddressBookParser` class creates an `XYZCommandParser` (`XYZ` is a placeholder for the specific command name e.g., `AddCommandParser`) which uses the other classes shown above to parse the user command and create a `XYZCommand` object (e.g., `AddCommand`) which the `AddressBookParser` returns back as a `Command` object.
-* All `XYZCommandParser` classes (e.g., `AddCommandParser`, `DeleteCommandParser`, ...) inherit from the `Parser` interface so that they can be treated similarly where possible e.g, during testing.
+
+- When called upon to parse a user command, the `MedInfoParser` class creates an `XYZCommandParser` (`XYZ` is a placeholder for the specific command name e.g., `AddCommandParser`) which uses the other classes shown above to parse the user command and create a `XYZCommand` object (e.g., `AddCommand`) which the `MedInfoParser` returns back as a `Command` object.
+- All `XYZCommandParser` classes (e.g., `AddCommandParser`, `DeleteCommandParser`, ...) inherit from the `Parser` interface so that they can be treated similarly where possible e.g, during testing.
### Model component
+
**API** : [`Model.java`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/model/Model.java)
-
The `Model` component,
-* stores the address book data i.e., all `Person` objects (which are contained in a `UniquePersonList` object).
-* stores the currently 'selected' `Person` objects (e.g., results of a search query) as a separate _filtered_ list which is exposed to outsiders as an unmodifiable `ObservableList` 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 `UserPref` object that represents the user’s preferences. This is exposed to the outside as a `ReadOnlyUserPref` objects.
-* does not depend on any of the other three components (as the `Model` represents data entities of the domain, they should make sense on their own without depending on other components)
-
-
:information_source: **Note:** An alternative (arguably, a more OOP) model is given below. It has a `Tag` list in the `AddressBook`, which `Person` references. This allows `AddressBook` to only require one `Tag` object per unique tag, instead of each `Person` needing their own `Tag` objects.
-
-
-
-
+- stores the address book data i.e., all `Person` objects (which are contained in a `UniquePersonList` object).
+- stores the currently 'selected' `Person` objects (e.g., results of a search query) as a separate _filtered_ list which is exposed to outsiders as an unmodifiable `ObservableList` 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 `UserPref` object that represents the user’s preferences. This is exposed to the outside as a `ReadOnlyUserPref` objects.
+- does not depend on any of the other three components (as the `Model` represents data entities of the domain, they should make sense on their own without depending on other components)
### Storage component
@@ -140,190 +177,486 @@ The `Model` component,
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 `AddressBookStorage` and `UserPrefStorage`, which means it can be treated as either one (if only the functionality of only one is needed).
-* depends on some classes in the `Model` component (because the `Storage` component's job is to save/retrieve objects that belong to the `Model`)
+
+- can save both address book data and user preference data in json format, and read them back into corresponding objects.
+- inherits from both `MedInfoStorage` and `UserPrefStorage`, which means it can be treated as either one (if only the functionality of only one is needed).
+- depends on some classes in the `Model` component (because the `Storage` component's job is to save/retrieve objects that belong to the `Model`)
### Common classes
-Classes used by multiple components are in the `seedu.addressbook.commons` package.
+Classes used by multiple components are in the `seedu.medinfo.commons` package.
---------------------------------------------------------------------------------------------------------------------
+---
## **Implementation**
-This section describes some noteworthy details on how certain features are implemented.
+This section describes some noteworthy details on how certain features are implemented in MedInfo.
-### \[Proposed\] Undo/redo feature
+### Adding a patient
+In MedInfo, a user can add a patient using the `add` command.
+#### Implementation
+- The `add` command takes in 2 compulsory fields (name and NRIC) and 1 optional field (status)
+- It is supported by the `AddCommandParser` that extracts the relevant fields from the entered command.
-#### Proposed Implementation
+The following activity diagram summarizes what happens when a user enters an `add` command:
-The proposed undo/redo mechanism is facilitated by `VersionedAddressBook`. It extends `AddressBook` with an undo/redo history, stored internally as an `addressBookStateList` and `currentStatePointer`. Additionally, it implements the following operations:
+
-* `VersionedAddressBook#commit()` — Saves the current address book state in its history.
-* `VersionedAddressBook#undo()` — Restores the previous address book state from its history.
-* `VersionedAddressBook#redo()` — Restores a previously undone address book state from its history.
+Details:
+- The user enters an `add` command with the name and NRIC specified.
+- If the user entered a `Status` (prefixed by `s/`), the patient created will have that status.
+- The created patient is added to the model.
-These operations are exposed in the `Model` interface as `Model#commitAddressBook()`, `Model#undoAddressBook()` and `Model#redoAddressBook()` respectively.
-Given below is an example usage scenario and how the undo/redo mechanism behaves at each step.
+### Adding a ward
+In MedInfo, a user can add a patient using the `addward` command.
+#### Implementation
+- The `add` command takes in 1 compulsory field (ward name) and 1 optional field (capacity)
+- It is supported by the `AddWardCommandParser` that extracts the relevant fields from the entered command.
-Step 1. The user launches the application for the first time. The `VersionedAddressBook` will be initialized with the initial address book state, and the `currentStatePointer` pointing to that single address book state.
+The following activity diagram summarizes what happens when a user enters an `addward` command:
-
+
-Step 2. The user executes `delete 5` command to delete the 5th person in the address book. The `delete` command calls `Model#commitAddressBook()`, causing the modified state of the address book after the `delete 5` command executes to be saved in the `addressBookStateList`, and the `currentStatePointer` is shifted to the newly inserted address book state.
+Details:
+- The user enters an `addward` command with the ward name specified.
+- If the user entered a `Capacity` (prefixed by `c/`), the ward created will have that capacity.
+- The created ward is added to the model.
-
-Step 3. The user executes `add n/David …` to add a new person. The `add` command also calls `Model#commitAddressBook()`, causing another modified address book state to be saved into the `addressBookStateList`.
+### Editing a patient
+In MedInfo, a user can edit a patient using the `edit` command.
+#### Implementation
+- The `edit` command takes in 1 compulsory argument (index) and up to 3 optional fields (status, ward and discharge date).
+- It is supported by the `EditCommandParser` that extracts the relevant fields from the entered command.
-
+The following activity diagram summarizes what happens when a user enters an `edit` command:
-
:information_source: **Note:** If a command fails its execution, it will not call `Model#commitAddressBook()`, so the address book state will not be saved into the `addressBookStateList`.
+
-
+Details:
+- The index is based on the last displayed list of patients. This design choice was made as:
+ - A user would most likely perform a `find` or `list` operation to confirm the patient to edit.
+ - Finding patient by NRIC would be too cumbersome for the user.
+- Name and NRIC are not editable as these are identifying fields of a patient.
-Step 4. The user now decides that adding the person was a mistake, and decides to undo that action by executing the `undo` command. The `undo` command will call `Model#undoAddressBook()`, which will shift the `currentStatePointer` once to the left, pointing it to the previous address book state, and restores the address book to that state.
-
+### Deleting a patient
+In MedInfo, a user can edit a patient using the `delete` command.
+#### Implementation
+- The `delete` command takes in 1 compulsory argument (index).
+- It is supported by the `DeleteCommandParser` that extracts the index from the entered command.
-
:information_source: **Note:** If the `currentStatePointer` is at index 0, pointing to the initial AddressBook state, then there are no previous AddressBook states to restore. The `undo` command uses `Model#canUndoAddressBook()` 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 activity diagram summarizes what happens when a user enters a `delete` command:
-
+
-The following sequence diagram shows how the undo operation works:
+Details:
+- When a user executes this command, they are greeted with an alert window to confirm deletion.
+ - Clicking 'OK' at this point will let MedInfo proceed with the deletion.
+ - Clicking 'Cancel' or closing the window will abort the deletion and trigger a `list` operation.
+- Aborting a deletion leads to a `list` operation so that the user can view all patients.
+- The index is based on the last displayed list of patients. This design choice was made as:
+ - A user would most likely perform a `find` or `list` operation to confirm the patient to delete.
+ - Finding patient by NRIC would be too cumbersome for the user.
-
-
:information_source: **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.
+### Finding patients
+In MedInfo, a user can find patients matching certain conditions using the `find` command.
+#### Implementation
+- The `find` command takes in 1 compulsory field (one of either name, NRIC or status).
+- It is supported by the `FindCommandParser` which extracts one of the possible fields:
+ - Name entered in the command (prefixed by `name/`)
+ - NRIC entered in the command (prefixed by `nric/`)
+ - Status entered in the command (prefixed by `s/`)
+- If the user enters multiple fields, MedInfo highlights the error to the user.
-
+The following activity diagram summarizes what happens when a user enters a `find` command:
-The `redo` command does the opposite — it calls `Model#redoAddressBook()`, which shifts the `currentStatePointer` once to the right, pointing to the previously undone state, and restores the address book to that state.
+
-
:information_source: **Note:** If the `currentStatePointer` is at index `addressBookStateList.size() - 1`, pointing to the latest address book state, then there are no undone AddressBook states to restore. The `redo` command uses `Model#canRedoAddressBook()` to check if this is the case. If so, it will return an error to the user rather than attempting to perform the redo.
-
+### List all patients
+In MedInfo, a user can list all patients using the `list` command.
+#### Implementation
+- The `list` command does not take in any arguments.
-Step 5. The user then decides to execute the command `list`. Commands that do not modify the address book, such as `list`, will usually not call `Model#commitAddressBook()`, `Model#undoAddressBook()` or `Model#redoAddressBook()`. Thus, the `addressBookStateList` remains unchanged.
+The following activity diagram summarizes what happens when a user enters a `find` command:
-
+
-Step 6. The user executes `clear`, which calls `Model#commitAddressBook()`. Since the `currentStatePointer` is not pointing at the end of the `addressBookStateList`, all address book states after the `currentStatePointer` will be purged. Reason: It no longer makes sense to redo the `add n/David …` command. This is the behavior that most modern desktop applications follow.
+### \[Proposed\] Data archiving
-
+_{Explain here how the data archiving feature will be implemented}_
-The following activity diagram summarizes what happens when a user executes a new command:
+---
-
+## **Documentation, logging, testing, configuration, dev-ops**
-#### Design considerations:
+- [Documentation guide](Documentation.md)
+- [Testing guide](Testing.md)
+- [Logging guide](Logging.md)
+- [Configuration guide](Configuration.md)
+- [DevOps guide](DevOps.md)
-**Aspect: How undo & redo executes:**
+---
-* **Alternative 1 (current choice):** Saves the entire address book.
- * Pros: Easy to implement.
- * Cons: May have performance issues in terms of memory usage.
+## **Appendix: Requirements**
-* **Alternative 2:** Individual command knows how to undo/redo 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.
+### Target user profile
-_{more aspects and alternatives to be added}_
+- has a need to manage a significant number of patients coming into an A&E in a private hospital
+- can type fast
+- prefers typing to execute commands and allocating patients by their status to their respective wards
+- is reasonably comfortable using CLI apps
-### \[Proposed\] Data archiving
+### Value proposition
-_{Explain here how the data archiving feature will be implemented}_
+- solve the problem of slow and multiple step process of allocating patients to their respective wards in an A&E
+- provide faster access to a particular patient’s details for hospital admin staff
+- provide a more efficient process of managing patients by their status to cater to patients who are in urgent need of care, which in turn provides a better quality of service
+- provide a simple system to keep track and update a patient's discharge date
+### User stories
---------------------------------------------------------------------------------------------------------------------
+Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unlikely to have) - `*`
-## **Documentation, logging, testing, configuration, dev-ops**
+| Priority | As a … | I want to … | So that I can… |
+|----------|--------------|----------------------------------------------------|---------------------------------------------------------------------------------------------|
+| `* * *` | staff member | add a patient | record more information later |
+| `* * *` | staff member | add a ward | assign patients to the ward later |
+| `* * *` | staff member | add personal particulars to a patient | record their name and NRIC |
+| `* * *` | staff member | add current status of patient | keep track of patient status |
+| `* * *` | staff member | add current ward of patient | keep track of patient location |
+| `* * *` | staff member | add a discharge date to hospitalised patients | keep track of discharge dates |
+| `* * *` | staff member | view the list of commands | use the system proficiently |
+| `* * *` | staff member | search for patients by personal particulars | do a basic search to find a certain patient |
+| `* * *` | staff member | search for patients by discharge date | plan for future patient discharges |
+| `* * *` | staff member | update personal particulars of a patient | keep the personal particulars of a patient up to date |
+| `* * *` | staff member | update patient ward | move patients to different wards |
+| `* * *` | staff member | update the status of a patient | keep the status of a patient up to date |
+| `* * *` | staff member | update the discharge date of hospitalised patients | change the discharge date of a hospitalised patient due to unexpected medical complications |
+| `* * *` | staff member | remove a patient | put the patient on hold or remove duplicate entries |
+| `* * *` | staff member | remove the discharge date of a patient | put the patient's discharge date on hold while awaiting further assessment |
+| `* *` | staff member | view the list of patients sorted by discharge date | plan for future patient discharges |
+| `* *` | staff member | see patients with approaching discharge dates | be aware of approaching discharge patients |
+| `* *` | staff member | view patients by ward | find patients in a ward and check the occupancy within certain wards |
+| `* *` | staff member | view patients by status | address higher priority patients more quickly |
+| `* *` | staff member | view list of wards | see current wards in system at a glance |
+| `* *` | staff member | view list of patients | see current patients in system at a glance |
+| `* *` | staff member | update the name of a ward | keep the name of a ward up to date |
+| `* *` | staff member | update the capacity of a ward | keep the maximum number of patients in a ward up to date |
+| `* *` | staff member | view the current total occupancy | see the total number of patients currently admitted |
+| `* *` | staff member | view the total capacity of a ward | see the maximum number of patients I can admit to this ward |
+| `* *` | staff member | view the current occupancy of a ward | see the number of patients currently admitted to a ward, and to know if a ward is full |
+| `* *` | staff member | confirm a deletion of a patient | avoid accidentally deleting a patient, which cannot be undone |
-* [Documentation guide](Documentation.md)
-* [Testing guide](Testing.md)
-* [Logging guide](Logging.md)
-* [Configuration guide](Configuration.md)
-* [DevOps guide](DevOps.md)
---------------------------------------------------------------------------------------------------------------------
+### Use cases
-## **Appendix: Requirements**
+(For all use cases below, the **System** is the `MedInfo` and the **Actor** is the `user`, unless specified otherwise)
-### Product scope
+#### Use case: UC01 - Add a patient
-**Target user profile**:
+**MSS**
-* has a need to manage a significant number of contacts
-* prefer desktop apps over other types
-* can type fast
-* prefers typing to mouse interactions
-* is reasonably comfortable using CLI apps
+1. User requests to add a new patient to MedInfo.
+2. The user enters patient details.
+ 1. The following are required information:
+ - Name
+ - NRIC
+ 2. The following are non-required information:
+ - Status
+ - Ward
+3. The system adds the user into the MedInfo system.
+4. The system shows the new created user in the patient list.
-**Value proposition**: manage contacts faster than a typical mouse/GUI driven app
+ Use case ends.
+**Extensions**
-### User stories
+- 2a. If any of the required fields are not completed.
-Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unlikely to have) - `*`
+ - 2a1. the user is informed of this and show the correct format for the command
-| Priority | As a … | I want to … | So that I can… |
-| -------- | ------------------------------------------ | ------------------------------ | ---------------------------------------------------------------------- |
-| `* * *` | new user | see usage instructions | refer to instructions when I forget how to use the App |
-| `* * *` | user | add a new person | |
-| `* * *` | user | delete a person | remove entries that I no longer need |
-| `* * *` | user | find a person by name | locate details of persons without having to go through the entire list |
-| `* *` | user | hide private contact details | minimize chance of someone else seeing them by accident |
-| `*` | user with many persons in the address book | sort persons by name | locate a person easily |
+Use case resumes at step 2.
-*{More to be added}*
+- 2b. If the entered NRIC is already present in another record in the system.
+
+ - 2b1. the user is informed that the NRIC is already present in the system.
+
+ Use case resumes at step 2.
+
+- 2c. If the input field is invalid.
+
+ - 2c1. the user is informed of this, and correct format for the command is displayed.
+
+ Use case resumes at step 2.
-### Use cases
-(For all use cases below, the **System** is the `AddressBook` and the **Actor** is the `user`, unless specified otherwise)
+- 2d. If the entered ward is not present in the system.
-**Use case: Delete a person**
+ - 2d1. the user is informed that the ward does not exist in the system.
+
+ Use case resumes at step 2.
+
+
+#### Use case: UC02 - Delete a patient
+
+**MSS**
+
+1. User requests to list filtered patients
+2. MedInfo shows a list of filtered patients
+3. User requests to delete a specific patient in the list by index number
+4. MedInfo shows confirmation window
+5. MedInfo deletes the patient
+
+ Use case ends.
+
+**Extensions**
+
+- 2a. The list is empty.
+
+ Use case ends.
+
+- 3a. The requested patient's index number is invalid.
+
+ - 3a1. MedInfo shows an error message.
+
+ Use case resumes at step 2.
+
+- 4a. The user cancels the deletion in the confirmation window
+
+ - 4a1. MedInfo shows the patient list
+
+ - 4b1. MedInfo shows an error message.
+
+ Use case resumes at step 2.
+
+#### Use case: UC03 - Edit a patient
**MSS**
-1. User requests to list persons
-2. AddressBook shows a list of persons
-3. User requests to delete a specific person in the list
-4. AddressBook deletes the person
+1. User requests to list filtered patients
+2. MedInfo shows a list of filtered patients
+3. User requests to edit a specific patient in the list by index number
+ 1. The following can be edited:
+ - Status
+ - Ward
+ - Discharge Date
+ 2. The following cannot be edited:
+ - Name
+ - NRIC
+4. MedInfo edits the patient
Use case ends.
**Extensions**
-* 2a. The list is empty.
+- 2a. The list is empty.
Use case ends.
-* 3a. The given index is invalid.
+- 3a. The requested patient's index number is invalid.
+
+ - 3a1. MedInfo shows an error message.
+
+ Use case resumes at step 2.
- * 3a1. AddressBook shows an error message.
+- 3b. The prefixes entered are invalid.
+
+ - 3b1. MedInfo shows an error message.
Use case resumes at step 2.
-*{More to be added}*
+- 3b. The Status entered is invalid.
+
+ - 3b1. MedInfo shows an error message.
+
+ Use case resumes at step 2.
+
+- 3b. The Ward entered is invalid.
+
+ - 3b1. MedInfo shows an error message.
+
+ Use case resumes at step 2.
+
+- 3b. The Discharge Date entered is invalid.
+
+ - 3b1. MedInfo shows an error message.
+
+ Use case resumes at step 2.
+
+- 3d. User tries to edit a non-editable field (Name/NRIC).
+
+ - 3d1. MedInfo shows an error message.
+
+ Use case resumes at step 2.
+
+
+#### Use case: UC04 - Find a patient
+
+**MSS**
+
+1. User requests to find specific patients by either NRIC or Name or Status or Ward
+2. MedInfo shows a list of patients
+
+ Use case ends.
+
+**Extensions**
+
+- 1a. The requested patient's NRIC does not exist in the system.
+
+ - 1a1. MedInfo does not list any patients.
+
+ Use case ends.
+
+- 1b. The requested patient's Name does not exist in the system.
+
+ - 1b1. MedInfo does not list any patients.
+
+ Use case ends.
+
+- 1c. The requested patient's Status does not exist in the system.
+
+ - 1c1. MedInfo does not list any patients.
+
+ Use case ends.
+
+- 1d. The requested patient's Ward does not exist in the system.
+
+- 1d1. MedInfo does not list any patients.
+
+ Use case ends.
+
+#### Use case: UC05 - Clear all patients
+
+**MSS**
+
+1. User requests to clear all the patient records in the system
+2. MedInfo shows confirmation window
+3. MedInfo deletes all patients in the system
+
+ Use case ends.
+
+- 3a. The user cancels the deletion in the confirmation window
+ - 3a1. MedInfo shows the patient list
+
+
+#### Use case: UC06 - Add a new ward
+
+**MSS**
+
+1. User requests to add a new ward to MedInfo.
+2. The user enters ward details.
+ 1. The following are required information:
+ - Name
+ 2. The following are non-required information:
+ - Capacity
+3. The system adds the ward into the MedInfo system.
+4. The system shows the new created ward in the ward list.
+
+ Use case ends.
+
+**Extensions**
+* 2a. If any of the required fields are not completed.
+
+ * 2a1. the user is informed of this and show the correct format for the command
+
+Use case resumes at step 2.
+
+* 2b. If the entered Name is already present in another record in the system.
+
+ * 2b1. the user is informed that the Name is already present in the system.
+
+ Use case resumes at step 2.
+
+* 2c. If the input field is invalid.
+
+ * 2c1. the user is informed of this, and correct format for the command is displayed.
+
+ Use case resumes at step 2.
+
+
+#### Use case: UC07 - Delete a ward
+
+**MSS**
+
+1. User requests to list wards
+2. MedInfo shows a list of wards
+3. User requests to delete a specific ward in the list by index number
+4. MedInfo shows confirmation window
+5. MedInfo deletes the patient
+
+ Use case ends.
+
+**Extensions**
+
+- 2a. The ward list is empty.
+
+ Use case ends.
+
+- 3a. The requested ward's index number is invalid.
+
+ - 3a1. MedInfo shows an error message.
+
+ Use case resumes at step 2.
+
+- 3b. The requested ward has patients inside
+
+ - 3b1. MedInfo shows an error message.
+
+ Use case resumes at step 2.
+
+- 4a. The user cancels the deletion in the confirmation window
+ - 4a1. MedInfo shows the patient list
+
+ Use case resumes at step 2
+
+#### Use case: UC08 - Sort Patients
+
+**MSS**
+
+1. User requests to list patients
+2. MedInfo shows a list of patients
+3. User requests to sort all the patients by a specific order
+4. MedInfo sorts all the patients
+5. MedInfo displays the sorted list
+
+ Use case ends
+
+**Extensions**
+
+- 2. The patient list is empty
+
+ Use case ends.
+- 3a. The requested sorting order is invalid
+ - 3a1. MedInfo shows an error message.
+
+ Use case resumes at step 2.
+
+- 3b. The requested sorting field is invalid
+ - 3b1. MedInfo shows an error message.
+
+ Use case resumes at step 2.
### Non-Functional Requirements
1. Should work on any _mainstream OS_ as long as it has Java `11` or above installed.
-2. Should be able to hold up to 1000 persons without a noticeable sluggishness in performance for typical usage.
+2. Should be able to hold up to 1000 patients without a noticeable sluggishness in performance for typical usage.
3. 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.
-
-*{More to be added}*
+4. Should mask the NRIC of patients when listing (e.g. XXXXX264G).
+5. The product is not required to validate the medical records.
### Glossary
-* **Mainstream OS**: Windows, Linux, Unix, OS-X
-* **Private contact detail**: A contact detail that is not meant to be shared with others
+- **Mainstream OS**: Windows, Linux, Unix, OS-X
+- **CLI**: Command Line Interface
+- **Use case**: It describes an interaction between the user and the system for a specific functionality of the system.
+- **Priority Level**: Level of seriousness of a patient's health condition (e.g. `Stable`, `Mild`, `Severe`)
+- **Medical Record**: Blood type, allergies, medical cases and history of medical conditions
---------------------------------------------------------------------------------------------------------------------
+---
## **Appendix: Instructions for manual testing**
@@ -340,38 +673,114 @@ testers are expected to do more *exploratory* testing.
1. Download the jar file and copy into an empty folder
- 1. Double-click the jar file Expected: Shows the GUI with a set of sample contacts. The window size may not be optimum.
+ 2. Double-click the jar file Expected: Shows the GUI with a set of sample contacts. The window size may not be optimum.
-1. Saving window preferences
+2. Saving window preferences
1. Resize the window to an optimum size. Move the window to a different location. Close the window.
- 1. Re-launch the app by double-clicking the jar file.
- Expected: The most recent window size and location is retained.
+ 2. Re-launch the app by double-clicking the jar file.
+ Expected: The most recent window size and location is retained.
-1. _{ more test cases … }_
-### Deleting a person
+### Delete a patient
-1. Deleting a person while all persons are being shown
+1. Deleting a patient while all patients are being shown
- 1. Prerequisites: List all persons using the `list` command. Multiple persons in the list.
+ 1. Prerequisites: List all patients using the `list` command. Multiple patients in the list.
- 1. Test case: `delete 1`
+ 2. Test case: `delete 1`
Expected: First contact is deleted from the list. Details of the deleted contact shown in the status message. Timestamp in the status bar is updated.
- 1. Test case: `delete 0`
- Expected: No person is deleted. Error details shown in the status message. Status bar remains the same.
+ 3. Test case: `delete 0`
+ Expected: No patient is deleted. Error details shown in the status message. Status bar remains the same.
- 1. Other incorrect delete commands to try: `delete`, `delete x`, `...` (where x is larger than the list size)
+ 4. Other incorrect delete commands to try: `delete`, `delete x`, `...` (where x is larger than the list size)
Expected: Similar to previous.
-1. _{ more test cases … }_
-### Saving data
+### Save data
-1. Dealing with missing/corrupted data files
+1. Dealing with missing data files
+ 1. MedInfo will display sample data if data files cannot be found in the data directory.
- 1. _{explain how to simulate a missing/corrupted file, and the expected behavior}_
+2. Dealing with corrupted data files
+ 1. MedInfo will clear the current data if the data files are corrupted or modified invalidly.
+
+
+---
-1. _{ more test cases … }_
+## **Appendix: Planned Enhancements**
+
+Given below are a few enhancements we hope to bring into future iterations of MedInfo:
+
+### Date-time validation:
+Currently, MedInfo allows the user to input dates in the past (e.g.`01/01/1000 1000`). While there may be reason to
+input past date-times, such as if the user forgot to enter dates previously, MedInfo is meant to be a **current**
+patient tracking system. As such, inputting dates from the past would not make sense as the patients would have been
+discharged already (and hence have no reason to be recorded in MedInfo).
+Also, MedInfo currently allows entering time in non HHmm format (e.g. '210.4'). This shall be looked into while
+improving validation overall.
+
+Possible Implementation:
+- Future validation could be implemented by adding a method in `Discharge.java` to check if a given date is a valid
+future discharge date (by comparing to the current date)
+- The method created above would then be called within `parseDischarge()` in `ParserUtil.java` to ensure that a
+valid future discharge date-time was entered
+
+### Strict NRIC validation:
+Currently, MedInfo checks whether a valid NRIC has been entered based on a validaton regex within
+`Nric.java` (`^[STFG]\d{7}[A-Z]$`). This regex restricts the NRIC to be a capital letter (either
+S/F/T/G) followed by 7 numbers and a capital letter. True valid NRICs make use of stronger validation
+logic, involving check digits. Such validation would need to be added before using MedInfo in a
+real-life scenario. However, due to the constraints it would place on testing during development,
+it shall be implemented in the future instead.
+
+### UI component behaviour on window resizing
+On resizing, the status bar maintains its centered location as from the full-size window. As a result,
+the information in it gets truncated. As this information is critical, future enhancements should address this, and
+other UI components that get cut off on window resizing.
+
+Possible implementations:
+- adjusting padding
+- setting position constraint
+- setting a higher minimum window width
+
+### Multiple parameter search
+Currently, MedInfo only allows finding patients by **onw** of four parameters:
+1. name (`name/`)
+2. NRIC (`nric/`)
+3. status (`s/`)
+4. ward name (`w/`)
+
+The `find` command does not allow multiple parameters to be used at once. For example, attempting to find critical
+patients in ward 'ER1' with the command `find s/red w/ER1` would result in an error. However, as a hospital
+staff, finding patients matching multiple criteria is a valid use-case. Hence, this is planned as a future enhancement.
+
+### Find by ward
+Currently, the `find` command in MedInfo finds patients by wards as it does patients by name, i.e. by displaying
+all patients that match any of the keywords supplied. As a result, the logic is slightly flawed. Consider the
+scenario of trying to find patients in a ward named 'Class A', when the other wards in the system include 'Class B'
+and 'Class C'. Entering `find w/Class A` would also display patients in the other 2 wards due to the common keyword
+'Class'. This should be addressed in future iterations of MedInfo by making the `find` command match ward name
+exactly.
+
+
+### Handling long names
+Currently, long names are truncated (with `...`) once they go past the maximum displayable length. This makes it
+impossible to get long patient names after entry into the system. This would need to be addressed in the future.
+
+Possible implementation:
+- limit name input to 40 characters: While simple to implement (change validation regex in `Name.java` to
+`[\\p{Alnum}][\\p{Alnum} ]{0,39}`, it is not recommended, as it does not handle the case of patients with names
+longer than 40 characters
+- text wrapping to display the whole name within the patient card in the UI
+
+### Expand `help` command
+Currently, entering the `help` command in MedInfo opens a small dialog box with a link to MedInfo's website. While
+the user can read the user guide from the website to learn how to use the commands, perhaps a quick command summary
+could be added to this window for returning users who do not wish to open the website but just need a quick refresher
+on the commands.
+
+Possible implementation:
+- add command summary in text to help window display
diff --git a/docs/SettingUp.md b/docs/SettingUp.md
index 275445bd551..787ab0c455c 100644
--- a/docs/SettingUp.md
+++ b/docs/SettingUp.md
@@ -23,7 +23,7 @@ If you plan to use Intellij IDEA (highly recommended):
1. **Import the project as a Gradle project**: Follow the guide [_[se-edu/guides] IDEA: Importing a Gradle project_](https://se-education.org/guides/tutorials/intellijImportGradleProject.html) to import the project into IDEA.
:exclamation: Note: Importing a Gradle project is slightly different from importing a normal Java project.
1. **Verify the setup**:
- 1. Run the `seedu.address.Main` and try a few commands.
+ 1. Run the `seedu.medinfo.Main` and try a few commands.
1. [Run the tests](Testing.md) to ensure they all pass.
--------------------------------------------------------------------------------------------------------------------
diff --git a/docs/Testing.md b/docs/Testing.md
index 8a99e82438a..d1d455a3b96 100644
--- a/docs/Testing.md
+++ b/docs/Testing.md
@@ -29,8 +29,8 @@ There are two ways to run tests.
This project has three types of tests:
1. *Unit tests* targeting the lowest level methods/classes.
- e.g. `seedu.address.commons.StringUtilTest`
+ e.g. `seedu.medinfo.commons.StringUtilTest`
1. *Integration tests* that are checking the integration of multiple code units (those code units are assumed to be working).
- e.g. `seedu.address.storage.StorageManagerTest`
+ e.g. `seedu.medinfo.storage.StorageManagerTest`
1. Hybrids of unit and integration tests. These test are checking multiple code units as well as how the are connected together.
- e.g. `seedu.address.logic.LogicManagerTest`
+ e.g. `seedu.medinfo.logic.LogicManagerTest`
diff --git a/docs/UserGuide.md b/docs/UserGuide.md
index e7df68b01ea..8ac35365aea 100644
--- a/docs/UserGuide.md
+++ b/docs/UserGuide.md
@@ -3,191 +3,472 @@ layout: page
title: User Guide
---
-AddressBook Level 3 (AB3) is a **desktop app for managing contacts, optimized for use via a Command Line Interface** (CLI) while still having the benefits of a Graphical User Interface (GUI). If you can type fast, AB3 can get your contact management tasks done faster than traditional GUI apps.
+## Introduction
+Welcome to the MedInfo User Guide!
+MedInfo is a desktop application for **private hospital administrative staff** to
+help manage patients and wards.
+
+This User Guide will guide you through installing the app, getting familiarised with its features and using it.
+If this is your first time using this Guide, you may refer to this segment
+on [how to use our User Guide](#how-to-use-the-user-guide)
+
+## Table of Contents
* Table of Contents
{:toc}
---------------------------------------------------------------------------------------------------------------------
+---
+## About MedInfo
+MedInfo is a simple application that will help you manage your patients' **statuses, wards,
+discharge dates**, and ward **occupancies**.
+
+Considering the time-critical nature of hospital services, patient and ward management are
+of utmost priority, where the smallest delays or lapses in updating information can affect
+how your hospital attends to your patients. **MedInfo** was designed with this in mind.
+It has simplified and optimized patient and ward management, allowing you to in-process, update, and move patients
+around while still being able to view overall stats of the hospital at a glance.
+
+[Back to Table of Contents](#table-of-contents)
+
+---
-## Quick start
+## Getting Started
+Below, you'll find everything you need to install and set up MedInfo.
-1. Ensure you have Java `11` or above installed in your Computer.
+### System Requirements
+For the best possible experience, we recommend that you use MedInfo on one of the following operating systems:
+- Windows
+- macOS
+- Linux
-1. Download the latest `addressbook.jar` from [here](https://github.com/se-edu/addressbook-level3/releases).
+To run MedInfo, you will need to have Java 11 or above installed on your system. If you don't, you can find the
+appropriate version for your system [here](https://www.oracle.com/java/technologies/downloads/).
-1. Copy the file to the folder you want to use as the _home folder_ for your AddressBook.
+### Quick Start
+1. Download the latest `medinfo.jar` from [here](https://github.com/AY2223S2-CS2103T-T12-2/tp/releases).
-1. Open a command terminal, `cd` into the folder you put the jar file in, and use the `java -jar addressbook.jar` command to run the application.
- A GUI similar to the below should appear in a few seconds. Note how the app contains some sample data.
- 
+2. Copy the file to the folder you want to use as the [_home folder_](#glossary) for your MedInfo.
-1. Type the command in the command box and press Enter to execute it. e.g. typing **`help`** and pressing Enter will open the help window.
+3. Run the application by
+ 2. Double-clicking the [`.jar`](#glossary) file or
+ 3. Opening a [command terminal](#glossary), `cd` into the folder you put the `.jar` file in, and use the `java -jar medinfo.jar`
+command to run the application.
+4. A [GUI](#glossary) similar to the one below should appear in a few seconds. If you are starting the app for the first time, the
+app will contain some sample data for you to try commands.
+ 
+
+5. Type the command in the command input box and press Enter to execute it. e.g. typing **`help`** and pressing
+Enter will open the help window.
Some example commands you can try:
- * `list` : Lists all contacts.
+ - `list` : Lists all patients.
+
+ - `add nric/S1234567A name/John Doe` : Adds a patient named `John Doe` to MedInfo.
+
+ - `delete 1` : Deletes the first patient on the currently displayed list.
+
+ - `clear` : Clears all patient and ward data.
+
+ - `exit` : Exits the app.
- * `add n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01` : Adds a contact named `John Doe` to the Address Book.
+7. Refer to the [Features](#features) section below for details on each command.
+
+[Back to Table of Contents](#table-of-contents)
+
+---
+## User Interface Overview
+
+
+
+The main GUI has 7 sections as highlighted above.
+- **_Menu Bar_**: File and Help buttons to exit or get help.
+- **_Command Input_**: Key in commands here and press Enter to execute.
+- **_Result Display_**: Responses from the application including error and success messages appear here.
+- **_Adjustable Panels_**: Click and drag on the purple highlighted areas to customize the panel sizes to your preference.
+- **_Patient List_**: List of patients you have.
+- **_Ward List_**: List of wards you have.
+- **_Save Location and Stats_**: Status bar which displays the location of data storage and some statistics of your hospital.
+
+[Back to Table of Contents](#table-of-contents)
+
+---
+## How to use the User Guide
- * `delete 3` : Deletes the 3rd contact shown in the current list.
+### Navigation
+This Guide contains detailed explanations on the **commands** available and what they do. If you wish to navigate to
+any section within this Guide, the [**Table of Contents**](#table-of-contents) above provides a quick way to do so.
+Each section in the User Guide comes with a [Back to Table of Contents](#table-of-contents) link in the footer to
+take you back to the Table of Contents.
- * `clear` : Deletes all contacts.
+If you know what you're looking for, press Ctrl + F to search anywhere within this Guide
+for a keyword.
- * `exit` : Exits the app.
+### Symbols used
-1. Refer to the [Features](#features) below for details of each command.
+| Symbol | Meaning |
+|----------------------|-------------------------------------------------------------|
+| :information_source: | General information/notes. |
+| :bulb: | Tips that will optimize your usage of MedInfo. |
+| :exclamation: | Information that is crucial to know before using a command. |
---------------------------------------------------------------------------------------------------------------------
+---
## Features
+The section below describes the commands available in MedInfo. The commands fall under 3 categories:
+- [Patient Features](#patient-features)
+- [Ward Features](#ward-features)
+- [Utility Features](#utility-features)
+
+Our commands follow a certain format for ease of use. If you are new to MedInfo, do take some time to familiarise
+yourself with the command format from the notes below.
+
**:information_source: Notes about the command format:**
-* Words in `UPPER_CASE` are the parameters to be supplied by the user.
- e.g. in `add n/NAME`, `NAME` is a parameter which can be used as `add n/John Doe`.
+- Words in `UPPER_CASE` are the parameters to be supplied by you.
+ e.g. in `add nric/NRIC name/NAME`, `NRIC` and `NAME` are parameters which can be used as `add nric/S1234567A name/John Doe`.
-* Items in square brackets are optional.
- e.g `n/NAME [t/TAG]` can be used as `n/John Doe t/friend` or as `n/John Doe`.
+- Items in square brackets are optional.
+ e.g `name/NAME [s/STATUS]` can be used as `name/John Doe s/GREEN` or as `name/John Doe`.
-* Items with `…` after them can be used multiple times including zero times.
- e.g. `[t/TAG]…` can be used as ` ` (i.e. 0 times), `t/friend`, `t/friend t/family` etc.
+[//]: # 'Might be used in future features'
+[//]: # '- Items with `…` after them can be used multiple times including zero times. '
+[//]: # ' e.g. `[t/TAG]…` can be used as `` (i.e. 0 times), `t/friend`, `t/friend t/family` etc.'
-* Parameters can be in any order.
- e.g. if the command specifies `n/NAME p/PHONE_NUMBER`, `p/PHONE_NUMBER n/NAME` is also acceptable.
+- Parameters can be in any order.
+ e.g. if the command specifies `name/NAME s/STATUS`, `s/STATUS name/NAME` is also acceptable.
-* If a parameter is expected only once in the command but you specified it multiple times, only the last occurrence of the parameter will be taken.
- e.g. if you specify `p/12341234 p/56785678`, only `p/56785678` will be taken.
+- If a parameter is expected only once in the command, but you specified it multiple times, only the last occurrence of
+ the parameter will be taken.
+ e.g. if you specify `nric/S1234567X nric/S1234567A`, only `nric/S1234567A` will be taken.
-* Extraneous parameters for commands that do not take in parameters (such as `help`, `list`, `exit` and `clear`) will be ignored.
+- Commands that do not take in parameters (such as `help`, `list`, and `exit`) will ignore any parameters supplied
+ along with it.
e.g. if the command specifies `help 123`, it will be interpreted as `help`.
-### Viewing help : `help`
+## Patient Features
+### Adding a patient to the system: `add`
-Shows a message explaning how to access the help page.
+Adds the patient (NRIC, name and status).
-
+Format: `add nric/NRIC name/NAME [s/STATUS]`
-Format: `help`
+
:bulb: **Tip:**
+The first and last letters in NRIC must be capitalised.
+
+
-### Adding a person: `add`
+**:information_source: Notes about `add`:**
+- The default status is set to `GRAY`.
+- The default ward is set to `Waiting Room`.
+- No discharge date is added by default.
+
-Adds a person to the address book.
+Examples:
-Format: `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]…`
+- `add nric/S1234567A name/John Doe s/RED`
-
:bulb: **Tip:**
-A person can have any number of tags (including 0)
-
+[Back to Table of Contents](#table-of-contents)
-Examples:
-* `add n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01`
-* `add n/Betsy Crowe t/friend e/betsycrowe@example.com a/Newgate Prison p/1234567 t/criminal`
-### Listing all persons : `list`
+### Listing all patients in the system: `list`
-Shows a list of all persons in the address book.
+Shows a list of all patients with their details in the system.
Format: `list`
-### Editing a person : `edit`
+[Back to Table of Contents](#table-of-contents)
+
+
+### Editing a patient’s details in the system: `edit`
+
+Edit an existing patient’s status or ward or discharge date-time.
-Edits an existing person in the address book.
+Format: `edit INDEX [s/STATUS] [w/WARD] [d/DISCHARGE]`
-Format: `edit INDEX [n/NAME] [p/PHONE] [e/EMAIL] [a/ADDRESS] [t/TAG]…`
+- Edits the patient's details at the specified index as of the currently displayed list.
+- The status of a patient is either `GRAY` or `GREEN` or `YELLOW` or `RED`.
+- The ward allocated to a patient is represented as an alphanumeric string. E.g `A01`.
+- The discharge date-time is of the `dd/MM/yyyy HHmm` format. E.g `12/03/2023 1200` is interpreted as 12th March 2023 1200hrs.
-* Edits the person at the specified `INDEX`. The index refers to the index number shown in the displayed person list. The index **must be a positive integer** 1, 2, 3, …
-* At least one of the optional fields must be provided.
-* Existing values will be updated to the input values.
-* When editing tags, the existing tags of the person will be removed i.e adding of tags is not cumulative.
-* You can remove all the person’s tags by typing `t/` without
- specifying any tags after it.
+Examples:
+
+- `edit 1 s/GREEN` Edits the status of the first currently displayed patient to be `GREEN`.
+- `edit 5 w/A01` Edits the ward of the fifth currently displayed patient to be `A01`.
+- `edit 4 d/27/07/2023 1600` Edits the discharge date-time of the fourth currently displayed patient to be `27/07/2023 1600` which is read as 27th July 2023 1600hrs.
+
+[Back to Table of Contents](#table-of-contents)
+
+
+### Sorting all patients in the system: `sort`
+
+Sorts all the patients with the specified field and order in the system.
+
+The fields that you can sort by include:
+- patient name (`name/`)
+- status (`s/`)
+- discharge date (`d/`)
+- ward name (`w/`)
+
+You can sort in one of two orders:
+- ascending (`asc`)
+- descending (`desc`)
+
+Format: `sort FIELD/ORDER`
+
+
+
+**:information_source: Notes about `sort`:**
+- You can only sort by one field in a command.
+- When sorting by status (in ascending order), the order is `GRAY`, `GREEN`, `YELLOW`, then `RED`. The `GRAY` status is given the lowest priority as the patient's condition is unknown, while the `RED` status is given the highest priority due to the patient's critical condition.
+
Examples:
-* `edit 1 p/91234567 e/johndoe@example.com` Edits the phone number and email address of the 1st person to be `91234567` and `johndoe@example.com` respectively.
-* `edit 2 n/Betsy Crower t/` Edits the name of the 2nd person to be `Betsy Crower` and clears all existing tags.
-### Locating persons by name: `find`
+- `sort s/asc`
-Finds persons whose names contain any of the given keywords.
+[Back to Table of Contents](#table-of-contents)
-Format: `find KEYWORD [MORE_KEYWORDS]`
-* The search is case-insensitive. e.g `hans` will match `Hans`
-* The order of the keywords does not matter. e.g. `Hans Bo` will match `Bo Hans`
-* Only the name is searched.
-* Only full words will be matched e.g. `Han` will not match `Hans`
-* Persons matching at least one keyword will be returned (i.e. `OR` search).
+### Finding patients by name in the system: `find`
+
+Shows a list of all patients with their details that match input name or NRIC.
+
+Format: `find name/NAME`, `find nric/NRIC`, `find s/STATUS`, `find w/WARD`
+
+- The search is case-insensitive. e.g `hans` will match `Hans`
+- The order of the keywords does not matter. e.g. `Hans Bo` will match `Bo Hans`
+- Either only the name or only the NRIC is searched.
+- Only full words will be matched e.g. `Han` will not match `Hans`
+- Persons matching at least one keyword will be returned (i.e. `OR` search).
e.g. `Hans Bo` will return `Hans Gruber`, `Bo Yang`
+
+
:bulb: **Tip:**
+Using `find` with a status acts as a filter on that status.
+
+
Examples:
-* `find John` returns `john` and `John Doe`
-* `find alex david` returns `Alex Yeoh`, `David Li`
- 
-### Deleting a person : `delete`
+- `find name/John` returns `john` and `John Smith`
+- `find name/john carlos` returns `John Smith`, `Carlos Lopez`
+ 
+
+[Back to Table of Contents](#table-of-contents)
-Deletes the specified person from the address book.
+
+### Deleting a patient from the system: `delete`
+
+
:exclamation: **Caution:**
+Once deleted, a patient cannot be recovered.
+
+
+Deletes a patient by index.
Format: `delete INDEX`
-* Deletes the person at the specified `INDEX`.
-* The index refers to the index number shown in the displayed person list.
-* The index **must be a positive integer** 1, 2, 3, …
+- Deletes the patient at the specified index as of the currently displayed list.
+
+
+
+**:information_source: Notes about `delete`:**
+On entering a `delete` command, a confirmation window will pop-up requesting for confirmation, regardless of the command's validity. This is to verify that you truly intend to perform that action and are fully aware of its consequences.
+
+
+Examples:
+
+`delete 1`
+
+
+
+
+[Back to Table of Contents](#table-of-contents)
+
+## Ward Features
+### Adding a ward to the system: `addward`
+
+Adds the ward (name and capacity).
+
+Format: `addward w/WARD [c/CAPACITY]`
+
+- The ward name is represented as an alphanumeric string. E.g `A01`.
+- The capacity is a positive integer. E.g `50`.
+
+
+
:bulb: **Tip:**
+
+
+
+
+**:information_source: Note about `add`:**
+The default capacity is set to 10.
+
+
+Examples:
+
+- `addward w/A01 c/25` Adds the ward with name `A01` and capacity `25` to the system.
+
+[Back to Table of Contents](#table-of-contents)
+
+
+### Editing a ward's details in the system: `editward`
+
+Edit an existing ward's name or capacity.
+
+Format: `editward INDEX [w/WARD] [c/CAPACITY]`
+
+- Edits the ward's details at the specified index as of the currently displayed list.
+- The given capacity has to be an integer.
+- The given capacity has to be greater or equal to the ward's current occupancy
+
+Examples:
+
+- `editward 1 w/A02` Edits the name of the first currently displayed ward to be `A02`.
+- `editward 5 c/35` Edits the capacity of the fifth currently displayed ward to be `35`.
+
+[Back to Table of Contents](#table-of-contents)
+
+### Deleting a ward from the system: `deleteward`
+
+
:exclamation: **Caution:**
+Once deleted, a ward cannot be recovered.
+
+
+Deletes a ward by index.
+
+Format: `deleteward INDEX`
+
+- Deletes the ward at the specified index as of the currently displayed list.
+
+
+
+**:information_source: Notes about `deleteward`:**
+- On entering a `deleteward` command, a confirmation window will pop-up requesting for confirmation, regardless of the command's validity. This is to verify that you truly intend to perform that action and are fully aware of its consequences.
+- You will not be able to delete a ward that currently has patients assigned to it.
+
+
Examples:
-* `list` followed by `delete 2` deletes the 2nd person in the address book.
-* `find Betsy` followed by `delete 1` deletes the 1st person in the results of the `find` command.
-### Clearing all entries : `clear`
+`deleteward 1`
+
+[Back to Table of Contents](#table-of-contents)
+
+## Utility Features
+### Clearing all data : `clear`
+
+
:exclamation: **Caution:**
+Once cleared, MedInfo data cannot be recovered!
+
-Clears all entries from the address book.
+Clears all data (patients and wards) stored in MedInfo.
Format: `clear`
+[Back to Table of Contents](#table-of-contents)
+
+### Viewing help : `help`
+
+Shows a message explaining how to access the help page.
+
+
+
+
+Format: `help`
+
+[Back to Table of Contents](#table-of-contents)
+
### Exiting the program : `exit`
Exits the program.
Format: `exit`
+[Back to Table of Contents](#table-of-contents)
+
+
### Saving the data
+MedInfo data are saved in the hard disk automatically after any command that changes the data. There is no need to save manually.
+
+[Back to Table of Contents](#table-of-contents)
-AddressBook data are saved in the hard disk automatically after any command that changes the data. There is no need to save manually.
### Editing the data file
-AddressBook data are saved as a JSON file `[JAR file location]/data/addressbook.json`. Advanced users are welcome to update data directly by editing that data file.
+MedInfo data are saved as a JSON file `[JAR file location]/data/medinfo.json`. Advanced users can update the data directly by editing that data file.
:exclamation: **Caution:**
-If your changes to the data file makes its format invalid, AddressBook will discard all data and start with an empty data file at the next run.
+Edit the data file at your own risk! Any changes that make the data invalid will lead to MedInfo clearing
+all data and starting anew.
-### Archiving data files `[coming in v2.0]`
+[Back to Table of Contents](#table-of-contents)
+
+---
+
+## FAQ :raising_hand:
+
+**Q**: I keep forgetting the commands, is there a quick way to get help?
+
+**A**: Yes! Entering the `help` command will show a message explaining how to access the help page.
+
-_Details coming soon ..._
+**Q**: Why can't I remove the waiting room?
---------------------------------------------------------------------------------------------------------------------
+**A**: As every hospital would have some pre-screening room for patients to wait in, and to make it easier
+to start entering patients into the system, the waiting room is made un-deletable.
+
-## FAQ
+**Q**: How do I transfer my data to another device/computer?
-**Q**: How do I transfer my data to another Computer?
-**A**: Install the app in the other computer and overwrite the empty data file it creates with the file that contains the data of your previous AddressBook home folder.
+**A**: Install the app in the other device/ computer and overwrite the empty data file it creates with
+the file that contains the data of your previous MedInfo home folder.
+
---------------------------------------------------------------------------------------------------------------------
+[Back to Table of Contents](#table-of-contents)
+
+---
## Command summary
-Action | Format, Examples
---------|------------------
-**Add** | `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]…` e.g., `add n/James Ho p/22224444 e/jamesho@example.com a/123, Clementi Rd, 1234665 t/friend t/colleague`
-**Clear** | `clear`
-**Delete** | `delete INDEX` e.g., `delete 3`
-**Edit** | `edit INDEX [n/NAME] [p/PHONE_NUMBER] [e/EMAIL] [a/ADDRESS] [t/TAG]…` e.g.,`edit 2 n/James Lee e/jameslee@example.com`
-**Find** | `find KEYWORD [MORE_KEYWORDS]` e.g., `find James Jake`
-**List** | `list`
-**Help** | `help`
+| Action | Format, Examples |
+| --------------- | --------------------------------------------------------------------------------------------------- |
+| **Add** | `add nric/NRIC name/NAME [s/STATUS]` e.g., `add nric/S1234567A name/John Doe s/GREEN` |
+| **List** | `list` |
+| **Edit** | `edit INDEX [s/STATUS] [w/WARD] [d/DISCHARGE]` e.g.,`edit 1 s/GREEN` |
+| **Sort** | `sort FIELD/ORDER` e.g., `sort name/asc`, `sort d/desc` |
+| **Find** | `find name/NAME` or `find nric/NRIC` or `find s/STATUS`or `find w/WARD` e.g., `find name/John` |
+| **Delete** | `delete INDEX` e.g., `delete 1` |
+| **Add Ward** | `addward w/WARD [c/CAPACITY]` e.g., `addward w/S1234567A c/25` |
+| **Edit Ward** | `editward INDEX [w/WARD] [c/CAPACITY]` e.g., `editward 1 w/A02 c/35` |
+| **Delete Ward** | `deleteward INDEX` e.g., `deleteward 1` |
+| **Clear** | `clear` |
+| **Help** | `help` |
+| **Exit** | `exit` |
+
+[Back to Table of Contents](#table-of-contents)
+
+---
+
+## Glossary
+
+| Term | Definition |
+|----------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| **`.jar`** | A package file format that groups together Java program files and data files for ease of distribution. |
+| **`cd`** | A command used to change the current working directory in various operating systems. To use it, type `cd` followed by a space and the folder you wish to work in. |
+| **Command terminal** | A program that allows the user to enter commands that the computer processes. Examples of popular terminals include Terminal (for macOS) and PowerShell (for Windows). |
+| **Discharge Date** | The date on which a patient can be discharged from the hospital. |
+| **GUI** | Graphical User Interface. A form of user interface that allows users to interact primarily through graphics. |
+| **Home folder** | The main folder you wish to run MedInfo in. On running MedInfo, this folder will become populated with data and preference files. |
+| **In-process** | The process of checking in patients with their identifying information before they consult a medical professional. |
+| **Occupancy** | The number of patients in a given ward at a point in time. |
+| **Status** | A code indicating a patient's current condition. MedInfo works with 4 statuses: GRAY (unknown), GREEN (stable), YELLOW (serious), and RED (critical). |
+| **Ward** | A separate room in a hospital, typically allocated to a particular type of patient. |
+
+
+[Back to Table of Contents](#table-of-contents)
diff --git a/docs/_config.yml b/docs/_config.yml
index 6bd245d8f4e..3db08193a89 100644
--- a/docs/_config.yml
+++ b/docs/_config.yml
@@ -1,4 +1,4 @@
-title: "AB-3"
+title: "MedInfo"
theme: minima
header_pages:
@@ -8,7 +8,7 @@ header_pages:
markdown: kramdown
-repository: "se-edu/addressbook-level3"
+repository: "AY2223S2-CS2103T-T12-2/tp"
github_icon: "images/github-icon.png"
plugins:
diff --git a/docs/_sass/minima/_base.scss b/docs/_sass/minima/_base.scss
index 0d3f6e80ced..6d4252a28f0 100644
--- a/docs/_sass/minima/_base.scss
+++ b/docs/_sass/minima/_base.scss
@@ -268,6 +268,7 @@ table {
overflow-x: auto;
-webkit-overflow-scrolling: touch;
-ms-overflow-style: -ms-autohiding-scrollbar;
+ content: attr(href);
}
}
@@ -288,8 +289,11 @@ table {
text-align: center;
}
.site-header:before {
- content: "AB-3";
+ content: "MedInfo";
font-size: 32px;
}
+ a::after {
+ content: " (link)";
+ }
}
diff --git a/docs/diagrams/AddActivityDiagram.puml b/docs/diagrams/AddActivityDiagram.puml
new file mode 100644
index 00000000000..84b7e20db4f
--- /dev/null
+++ b/docs/diagrams/AddActivityDiagram.puml
@@ -0,0 +1,18 @@
+@startuml
+skinparam activity {
+ ArrowColor #A80036
+ BackgroundColor #FEFECE
+ BorderColor #A80036
+ BorderThickness 1.5
+}
+start
+:User executes add command;
+if () then ([Status present])
+ :Create patient with Status;
+else ([else])
+ :Create guest with Status GRAY;
+endif
+:Add patient to model;
+stop
+
+@enduml
diff --git a/docs/diagrams/AddWardActivityDiagram.puml b/docs/diagrams/AddWardActivityDiagram.puml
new file mode 100644
index 00000000000..bc14feb8060
--- /dev/null
+++ b/docs/diagrams/AddWardActivityDiagram.puml
@@ -0,0 +1,18 @@
+@startuml
+skinparam activity {
+ ArrowColor #A80036
+ BackgroundColor #FEFECE
+ BorderColor #A80036
+ BorderThickness 1.5
+}
+start
+:User executes addward command;
+if () then ([Capacity present])
+ :Create ward with capacity;
+else ([else])
+ :Create ward with default capacity;
+endif
+:Add ward to model;
+stop
+
+@enduml
diff --git a/docs/diagrams/ArchitectureSequenceDiagram.puml b/docs/diagrams/ArchitectureSequenceDiagram.puml
index ef81d18c337..37c76ffbe9c 100644
--- a/docs/diagrams/ArchitectureSequenceDiagram.puml
+++ b/docs/diagrams/ArchitectureSequenceDiagram.puml
@@ -13,13 +13,13 @@ activate ui UI_COLOR
ui -[UI_COLOR]> logic : execute("delete 1")
activate logic LOGIC_COLOR
-logic -[LOGIC_COLOR]> model : deletePerson(p)
+logic -[LOGIC_COLOR]> model : deletePatient(p)
activate model MODEL_COLOR
model -[MODEL_COLOR]-> logic
deactivate model
-logic -[LOGIC_COLOR]> storage : saveAddressBook(addressBook)
+logic -[LOGIC_COLOR]> storage : saveMedInfo(medInfo)
activate storage STORAGE_COLOR
storage -[STORAGE_COLOR]> storage : Save to file
diff --git a/docs/diagrams/BetterModelClassDiagram.puml b/docs/diagrams/BetterModelClassDiagram.puml
deleted file mode 100644
index 598474a5c82..00000000000
--- a/docs/diagrams/BetterModelClassDiagram.puml
+++ /dev/null
@@ -1,21 +0,0 @@
-@startuml
-!include style.puml
-skinparam arrowThickness 1.1
-skinparam arrowColor MODEL_COLOR
-skinparam classBackgroundColor MODEL_COLOR
-
-AddressBook *-right-> "1" UniquePersonList
-AddressBook *-right-> "1" UniqueTagList
-UniqueTagList -[hidden]down- UniquePersonList
-UniqueTagList -[hidden]down- UniquePersonList
-
-UniqueTagList -right-> "*" Tag
-UniquePersonList -right-> Person
-
-Person -up-> "*" Tag
-
-Person *--> Name
-Person *--> Phone
-Person *--> Email
-Person *--> Address
-@enduml
diff --git a/docs/diagrams/CommitActivityDiagram.puml b/docs/diagrams/CommitActivityDiagram.puml
deleted file mode 100644
index 6a6b23a006f..00000000000
--- a/docs/diagrams/CommitActivityDiagram.puml
+++ /dev/null
@@ -1,15 +0,0 @@
-@startuml
-start
-:User executes command;
-
-'Since the beta syntax does not support placing the condition outside the
-'diamond we place it as the true branch instead.
-
-if () then ([command commits AddressBook])
- :Purge redundant states;
- :Save AddressBook to
- addressBookStateList;
-else ([else])
-endif
-stop
-@enduml
diff --git a/docs/diagrams/DeleteActivityDiagram.puml b/docs/diagrams/DeleteActivityDiagram.puml
new file mode 100644
index 00000000000..39df2958735
--- /dev/null
+++ b/docs/diagrams/DeleteActivityDiagram.puml
@@ -0,0 +1,18 @@
+@startuml
+skinparam activity {
+ ArrowColor #A80036
+ BackgroundColor #FEFECE
+ BorderColor #A80036
+ BorderThickness 1.5
+}
+start
+:User executes delete command;
+if () then ([User confirms deletion])
+ :Find patient to delete;
+ :Delete patient from the model;
+else ([else])
+ :List all patients;
+endif
+stop
+
+@enduml
diff --git a/docs/diagrams/DeleteSequenceDiagram.puml b/docs/diagrams/DeleteSequenceDiagram.puml
index 1dc2311b245..425cec6eff3 100644
--- a/docs/diagrams/DeleteSequenceDiagram.puml
+++ b/docs/diagrams/DeleteSequenceDiagram.puml
@@ -3,7 +3,7 @@
box Logic LOGIC_COLOR_T1
participant ":LogicManager" as LogicManager LOGIC_COLOR
-participant ":AddressBookParser" as AddressBookParser LOGIC_COLOR
+participant ":MedInfoParser" as MedInfoParser LOGIC_COLOR
participant ":DeleteCommandParser" as DeleteCommandParser LOGIC_COLOR
participant "d:DeleteCommand" as DeleteCommand LOGIC_COLOR
participant ":CommandResult" as CommandResult LOGIC_COLOR
@@ -16,17 +16,17 @@ end box
[-> LogicManager : execute("delete 1")
activate LogicManager
-LogicManager -> AddressBookParser : parseCommand("delete 1")
-activate AddressBookParser
+LogicManager -> MedInfoParser : parseCommand("delete 1")
+activate MedInfoParser
create DeleteCommandParser
-AddressBookParser -> DeleteCommandParser
+MedInfoParser -> DeleteCommandParser
activate DeleteCommandParser
-DeleteCommandParser --> AddressBookParser
+DeleteCommandParser --> MedInfoParser
deactivate DeleteCommandParser
-AddressBookParser -> DeleteCommandParser : parse("1")
+MedInfoParser -> DeleteCommandParser : parse("1")
activate DeleteCommandParser
create DeleteCommand
@@ -36,19 +36,19 @@ activate DeleteCommand
DeleteCommand --> DeleteCommandParser : d
deactivate DeleteCommand
-DeleteCommandParser --> AddressBookParser : d
+DeleteCommandParser --> MedInfoParser : d
deactivate DeleteCommandParser
'Hidden arrow to position the destroy marker below the end of the activation bar.
-DeleteCommandParser -[hidden]-> AddressBookParser
+DeleteCommandParser -[hidden]-> MedInfoParser
destroy DeleteCommandParser
-AddressBookParser --> LogicManager : d
-deactivate AddressBookParser
+MedInfoParser --> LogicManager : d
+deactivate MedInfoParser
LogicManager -> DeleteCommand : execute()
activate DeleteCommand
-DeleteCommand -> Model : deletePerson(1)
+DeleteCommand -> Model : deletePatient(1)
activate Model
Model --> DeleteCommand
diff --git a/docs/diagrams/EditActivityDiagram.puml b/docs/diagrams/EditActivityDiagram.puml
new file mode 100644
index 00000000000..b722317f77a
--- /dev/null
+++ b/docs/diagrams/EditActivityDiagram.puml
@@ -0,0 +1,15 @@
+@startuml
+skinparam activity {
+ ArrowColor #A80036
+ BackgroundColor #FEFECE
+ BorderColor #A80036
+ BorderThickness 1.5
+}
+start
+:User executes edit command;
+:Find patient to edit;
+:Create new patient using fields entered;
+:Set new patient to the model;
+stop
+
+@enduml
diff --git a/docs/diagrams/FindActivityDiagram.puml b/docs/diagrams/FindActivityDiagram.puml
new file mode 100644
index 00000000000..b95306b506c
--- /dev/null
+++ b/docs/diagrams/FindActivityDiagram.puml
@@ -0,0 +1,14 @@
+@startuml
+skinparam activity {
+ ArrowColor #A80036
+ BackgroundColor #FEFECE
+ BorderColor #A80036
+ BorderThickness 1.5
+}
+start
+:User executes find command with a search field;
+:Find patient(s) whose corresponding field matches;
+:Update model to display the patient(s);
+stop
+
+@enduml
diff --git a/docs/diagrams/ListActivityDiagram.puml b/docs/diagrams/ListActivityDiagram.puml
new file mode 100644
index 00000000000..c9757fd9a5a
--- /dev/null
+++ b/docs/diagrams/ListActivityDiagram.puml
@@ -0,0 +1,13 @@
+@startuml
+skinparam activity {
+ ArrowColor #A80036
+ BackgroundColor #FEFECE
+ BorderColor #A80036
+ BorderThickness 1.5
+}
+start
+:User executes list command;
+:Update model to display all patients;
+stop
+
+@enduml
diff --git a/docs/diagrams/LogicClassDiagram.puml b/docs/diagrams/LogicClassDiagram.puml
index d4193173e18..3ccf6311356 100644
--- a/docs/diagrams/LogicClassDiagram.puml
+++ b/docs/diagrams/LogicClassDiagram.puml
@@ -6,7 +6,7 @@ skinparam classBackgroundColor LOGIC_COLOR
package Logic {
-Class AddressBookParser
+Class MedInfoParser
Class XYZCommand
Class CommandResult
Class "{abstract}\nCommand" as Command
@@ -27,8 +27,8 @@ Class HiddenOutside #FFFFFF
HiddenOutside ..> Logic
LogicManager .right.|> Logic
-LogicManager -right->"1" AddressBookParser
-AddressBookParser ..> XYZCommand : creates >
+LogicManager -right->"1" MedInfoParser
+MedInfoParser ..> XYZCommand : creates >
XYZCommand -up-|> Command
LogicManager .left.> Command : executes >
diff --git a/docs/diagrams/ModelClassDiagram.puml b/docs/diagrams/ModelClassDiagram.puml
index 4439108973a..43bbfc19c8d 100644
--- a/docs/diagrams/ModelClassDiagram.puml
+++ b/docs/diagrams/ModelClassDiagram.puml
@@ -5,46 +5,51 @@ skinparam arrowColor MODEL_COLOR
skinparam classBackgroundColor MODEL_COLOR
Package Model <>{
-Class "<>\nReadOnlyAddressBook" as ReadOnlyAddressBook
+Class "<>\nReadOnlyMedInfo" as ReadOnlyMedInfo
Class "<>\nReadOnlyUserPrefs" as ReadOnlyUserPrefs
Class "<>\nModel" as Model
-Class AddressBook
+Class MedInfo
Class ModelManager
Class UserPrefs
-Class UniquePersonList
-Class Person
-Class Address
-Class Email
+Class UniquePatientList
+Class Patient
+Class UniqueWardList
+Class Ward
+Class Capacity
+Class WardName
+Class Nric
Class Name
-Class Phone
-Class Tag
+Class Status
+Class Discharge
}
Class HiddenOutside #FFFFFF
HiddenOutside ..> Model
-AddressBook .up.|> ReadOnlyAddressBook
+MedInfo .up.|> ReadOnlyMedInfo
ModelManager .up.|> Model
Model .right.> ReadOnlyUserPrefs
-Model .left.> ReadOnlyAddressBook
-ModelManager -left-> "1" AddressBook
+Model .left.> ReadOnlyMedInfo
+ModelManager -left-> "1" MedInfo
ModelManager -right-> "1" UserPrefs
UserPrefs .up.|> ReadOnlyUserPrefs
-AddressBook *--> "1" UniquePersonList
-UniquePersonList --> "~* all" Person
-Person *--> Name
-Person *--> Phone
-Person *--> Email
-Person *--> Address
-Person *--> "*" Tag
-
-Name -[hidden]right-> Phone
-Phone -[hidden]right-> Address
-Address -[hidden]right-> Email
-
-ModelManager -->"~* filtered" Person
+MedInfo *--> "1" UniquePatientList
+MedInfo *--> "1" UniqueWardList
+UniquePatientList --> "~* all" Patient
+UniqueWardList --> "~* all" Ward
+Patient *--> Name
+Patient *--> Nric
+Patient *--> Status
+Patient *--> WardName
+Patient *--> Discharge
+Ward *--> Capacity
+Ward *--> WardName
+Ward *--> "1" UniquePatientList
+
+
+ModelManager -->"~* filtered" Patient
@enduml
diff --git a/docs/diagrams/ParserClasses.puml b/docs/diagrams/ParserClasses.puml
index 0c7424de6e0..e4c79b373ec 100644
--- a/docs/diagrams/ParserClasses.puml
+++ b/docs/diagrams/ParserClasses.puml
@@ -9,7 +9,7 @@ Class XYZCommand
package "Parser classes"{
Class "<>\nParser" as Parser
-Class AddressBookParser
+Class MedInfoParser
Class XYZCommandParser
Class CliSyntax
Class ParserUtil
@@ -19,12 +19,12 @@ Class Prefix
}
Class HiddenOutside #FFFFFF
-HiddenOutside ..> AddressBookParser
+HiddenOutside ..> MedInfoParser
-AddressBookParser .down.> XYZCommandParser: creates >
+MedInfoParser .down.> XYZCommandParser: creates >
XYZCommandParser ..> XYZCommand : creates >
-AddressBookParser ..> Command : returns >
+MedInfoParser ..> Command : returns >
XYZCommandParser .up.|> Parser
XYZCommandParser ..> ArgumentMultimap
XYZCommandParser ..> ArgumentTokenizer
diff --git a/docs/diagrams/StorageClassDiagram.puml b/docs/diagrams/StorageClassDiagram.puml
index 760305e0e58..d22666cb14a 100644
--- a/docs/diagrams/StorageClassDiagram.puml
+++ b/docs/diagrams/StorageClassDiagram.puml
@@ -14,12 +14,11 @@ Class JsonUserPrefsStorage
Class "<>\nStorage" as Storage
Class StorageManager
-package "AddressBook Storage" #F4F6F6{
-Class "<>\nAddressBookStorage" as AddressBookStorage
-Class JsonAddressBookStorage
-Class JsonSerializableAddressBook
+package "MedInfo Storage" #F4F6F6{
+Class "<>\nMedInfoStorage" as MedInfoStorage
+Class JsonMedInfoStorage
+Class JsonSerializableMedInfo
Class JsonAdaptedPerson
-Class JsonAdaptedTag
}
}
@@ -29,15 +28,14 @@ HiddenOutside ..> Storage
StorageManager .up.|> Storage
StorageManager -up-> "1" UserPrefsStorage
-StorageManager -up-> "1" AddressBookStorage
+StorageManager -up-> "1" MedInfoStorage
Storage -left-|> UserPrefsStorage
-Storage -right-|> AddressBookStorage
+Storage -right-|> MedInfoStorage
JsonUserPrefsStorage .up.|> UserPrefsStorage
-JsonAddressBookStorage .up.|> AddressBookStorage
-JsonAddressBookStorage ..> JsonSerializableAddressBook
-JsonSerializableAddressBook --> "*" JsonAdaptedPerson
-JsonAdaptedPerson --> "*" JsonAdaptedTag
+JsonMedInfoStorage .up.|> MedInfoStorage
+JsonMedInfoStorage ..> JsonSerializableMedInfo
+JsonSerializableMedInfo --> "*" JsonAdaptedPerson
@enduml
diff --git a/docs/diagrams/UiClassDiagram.puml b/docs/diagrams/UiClassDiagram.puml
index 95473d5aa19..5e019e425ac 100644
--- a/docs/diagrams/UiClassDiagram.puml
+++ b/docs/diagrams/UiClassDiagram.puml
@@ -11,8 +11,10 @@ Class UiManager
Class MainWindow
Class HelpWindow
Class ResultDisplay
-Class PersonListPanel
-Class PersonCard
+Class PatientListPanel
+Class PatientCard
+Class WardListPanel
+Class WardCard
Class StatusBarFooter
Class CommandBox
}
@@ -32,26 +34,30 @@ UiManager .left.|> Ui
UiManager -down-> "1" MainWindow
MainWindow *-down-> "1" CommandBox
MainWindow *-down-> "1" ResultDisplay
-MainWindow *-down-> "1" PersonListPanel
+MainWindow *-down-> "1" PatientListPanel
+MainWindow *-down-> "1" WardListPanel
MainWindow *-down-> "1" StatusBarFooter
MainWindow --> "0..1" HelpWindow
-PersonListPanel -down-> "*" PersonCard
+PatientListPanel -down-> "*" PatientCard
+WardListPanel -down-> "*" WardCard
MainWindow -left-|> UiPart
ResultDisplay --|> UiPart
CommandBox --|> UiPart
-PersonListPanel --|> UiPart
-PersonCard --|> UiPart
+PatientListPanel --|> UiPart
+PatientCard --|> UiPart
StatusBarFooter --|> UiPart
HelpWindow --|> UiPart
-PersonCard ..> Model
+PatientCard ..> Model
+WardCard ..> Model
UiManager -right-> Logic
MainWindow -left-> Logic
-PersonListPanel -[hidden]left- HelpWindow
+PatientListPanel -[hidden]left- HelpWindow
+WardListPanel -[hidden]left- HelpWindow
HelpWindow -[hidden]left- CommandBox
CommandBox -[hidden]left- ResultDisplay
ResultDisplay -[hidden]left- StatusBarFooter
diff --git a/docs/diagrams/UndoRedoState0.puml b/docs/diagrams/UndoRedoState0.puml
deleted file mode 100644
index 96e30744d24..00000000000
--- a/docs/diagrams/UndoRedoState0.puml
+++ /dev/null
@@ -1,20 +0,0 @@
-@startuml
-!include style.puml
-skinparam ClassFontColor #000000
-skinparam ClassBorderColor #000000
-
-title Initial state
-
-package States {
- class State1 as "__ab0:AddressBook__"
- class State2 as "__ab1:AddressBook__"
- class State3 as "__ab2:AddressBook__"
-}
-State1 -[hidden]right-> State2
-State2 -[hidden]right-> State3
-hide State2
-hide State3
-
-class Pointer as "Current State" #FFFFF
-Pointer -up-> State1
-@end
diff --git a/docs/diagrams/UndoRedoState1.puml b/docs/diagrams/UndoRedoState1.puml
deleted file mode 100644
index 01fcb9b2b96..00000000000
--- a/docs/diagrams/UndoRedoState1.puml
+++ /dev/null
@@ -1,22 +0,0 @@
-@startuml
-!include style.puml
-skinparam ClassFontColor #000000
-skinparam ClassBorderColor #000000
-
-title After command "delete 5"
-
-package States <> {
- class State1 as "__ab0:AddressBook__"
- class State2 as "__ab1:AddressBook__"
- class State3 as "__ab2:AddressBook__"
-}
-
-State1 -[hidden]right-> State2
-State2 -[hidden]right-> State3
-
-hide State3
-
-class Pointer as "Current State" #FFFFF
-
-Pointer -up-> State2
-@end
diff --git a/docs/diagrams/UndoRedoState2.puml b/docs/diagrams/UndoRedoState2.puml
deleted file mode 100644
index bccc230a5d1..00000000000
--- a/docs/diagrams/UndoRedoState2.puml
+++ /dev/null
@@ -1,20 +0,0 @@
-@startuml
-!include style.puml
-skinparam ClassFontColor #000000
-skinparam ClassBorderColor #000000
-
-title After command "add n/David"
-
-package States <> {
- class State1 as "__ab0:AddressBook__"
- class State2 as "__ab1:AddressBook__"
- class State3 as "__ab2:AddressBook__"
-}
-
-State1 -[hidden]right-> State2
-State2 -[hidden]right-> State3
-
-class Pointer as "Current State" #FFFFF
-
-Pointer -up-> State3
-@end
diff --git a/docs/diagrams/UndoRedoState3.puml b/docs/diagrams/UndoRedoState3.puml
deleted file mode 100644
index ea29c9483e4..00000000000
--- a/docs/diagrams/UndoRedoState3.puml
+++ /dev/null
@@ -1,20 +0,0 @@
-@startuml
-!include style.puml
-skinparam ClassFontColor #000000
-skinparam ClassBorderColor #000000
-
-title After command "undo"
-
-package States <> {
- class State1 as "__ab0:AddressBook__"
- class State2 as "__ab1:AddressBook__"
- class State3 as "__ab2:AddressBook__"
-}
-
-State1 -[hidden]right-> State2
-State2 -[hidden]right-> State3
-
-class Pointer as "Current State" #FFFFF
-
-Pointer -up-> State2
-@end
diff --git a/docs/diagrams/UndoRedoState4.puml b/docs/diagrams/UndoRedoState4.puml
deleted file mode 100644
index 1b784cece80..00000000000
--- a/docs/diagrams/UndoRedoState4.puml
+++ /dev/null
@@ -1,20 +0,0 @@
-@startuml
-!include style.puml
-skinparam ClassFontColor #000000
-skinparam ClassBorderColor #000000
-
-title After command "list"
-
-package States <> {
- class State1 as "__ab0:AddressBook__"
- class State2 as "__ab1:AddressBook__"
- class State3 as "__ab2:AddressBook__"
-}
-
-State1 -[hidden]right-> State2
-State2 -[hidden]right-> State3
-
-class Pointer as "Current State" #FFFFF
-
-Pointer -up-> State2
-@end
diff --git a/docs/diagrams/UndoRedoState5.puml b/docs/diagrams/UndoRedoState5.puml
deleted file mode 100644
index 88927be32bc..00000000000
--- a/docs/diagrams/UndoRedoState5.puml
+++ /dev/null
@@ -1,21 +0,0 @@
-@startuml
-!include style.puml
-skinparam ClassFontColor #000000
-skinparam ClassBorderColor #000000
-
-title After command "clear"
-
-package States <> {
- class State1 as "__ab0:AddressBook__"
- class State2 as "__ab1:AddressBook__"
- class State3 as "__ab3:AddressBook__"
-}
-
-State1 -[hidden]right-> State2
-State2 -[hidden]right-> State3
-
-class Pointer as "Current State" #FFFFF
-
-Pointer -up-> State3
-note right on link: State ab2 deleted.
-@end
diff --git a/docs/diagrams/UndoSequenceDiagram.puml b/docs/diagrams/UndoSequenceDiagram.puml
deleted file mode 100644
index 410aab4e412..00000000000
--- a/docs/diagrams/UndoSequenceDiagram.puml
+++ /dev/null
@@ -1,53 +0,0 @@
-@startuml
-!include style.puml
-
-box Logic LOGIC_COLOR_T1
-participant ":LogicManager" as LogicManager LOGIC_COLOR
-participant ":AddressBookParser" as AddressBookParser LOGIC_COLOR
-participant "u:UndoCommand" as UndoCommand LOGIC_COLOR
-end box
-
-box Model MODEL_COLOR_T1
-participant ":Model" as Model MODEL_COLOR
-participant ":VersionedAddressBook" as VersionedAddressBook MODEL_COLOR
-end box
-[-> LogicManager : execute(undo)
-activate LogicManager
-
-LogicManager -> AddressBookParser : parseCommand(undo)
-activate AddressBookParser
-
-create UndoCommand
-AddressBookParser -> UndoCommand
-activate UndoCommand
-
-UndoCommand --> AddressBookParser
-deactivate UndoCommand
-
-AddressBookParser --> LogicManager : u
-deactivate AddressBookParser
-
-LogicManager -> UndoCommand : execute()
-activate UndoCommand
-
-UndoCommand -> Model : undoAddressBook()
-activate Model
-
-Model -> VersionedAddressBook : undo()
-activate VersionedAddressBook
-
-VersionedAddressBook -> VersionedAddressBook :resetData(ReadOnlyAddressBook)
-VersionedAddressBook --> Model :
-deactivate VersionedAddressBook
-
-Model --> UndoCommand
-deactivate Model
-
-UndoCommand --> LogicManager : result
-deactivate UndoCommand
-UndoCommand -[hidden]-> LogicManager : result
-destroy UndoCommand
-
-[<--LogicManager
-deactivate LogicManager
-@enduml
diff --git a/docs/diagrams/tracing/LogicSequenceDiagram.puml b/docs/diagrams/tracing/LogicSequenceDiagram.puml
index fdcbe1c0ccc..495e67f6405 100644
--- a/docs/diagrams/tracing/LogicSequenceDiagram.puml
+++ b/docs/diagrams/tracing/LogicSequenceDiagram.puml
@@ -2,7 +2,7 @@
!include ../style.puml
Participant ":LogicManager" as logic LOGIC_COLOR
-Participant ":AddressBookParser" as abp LOGIC_COLOR
+Participant ":MedInfoParser" as abp LOGIC_COLOR
Participant ":EditCommandParser" as ecp LOGIC_COLOR
Participant "command:EditCommand" as ec LOGIC_COLOR
@@ -13,7 +13,7 @@ create ecp
abp -> ecp
abp -> ecp ++: parse(arguments)
create ec
-ecp -> ec ++: index, editPersonDescriptor
+ecp -> ec ++: index, editPatientDescriptor
ec --> ecp --
ecp --> abp --: command
abp --> logic --: command
diff --git a/docs/images/AddActivityDiagram.png b/docs/images/AddActivityDiagram.png
new file mode 100644
index 00000000000..d3b38ec58c1
Binary files /dev/null and b/docs/images/AddActivityDiagram.png differ
diff --git a/docs/images/AddWardActivityDiagram.png b/docs/images/AddWardActivityDiagram.png
new file mode 100644
index 00000000000..efe8474b546
Binary files /dev/null and b/docs/images/AddWardActivityDiagram.png differ
diff --git a/docs/images/ArchitectureSequenceDiagram.png b/docs/images/ArchitectureSequenceDiagram.png
index 2f1346869d0..b40184c42ed 100644
Binary files a/docs/images/ArchitectureSequenceDiagram.png and b/docs/images/ArchitectureSequenceDiagram.png differ
diff --git a/docs/images/BetterModelClassDiagram.png b/docs/images/BetterModelClassDiagram.png
deleted file mode 100644
index 94440f0ac4a..00000000000
Binary files a/docs/images/BetterModelClassDiagram.png and /dev/null differ
diff --git a/docs/images/CommitActivityDiagram.png b/docs/images/CommitActivityDiagram.png
deleted file mode 100644
index c08c13f5c8b..00000000000
Binary files a/docs/images/CommitActivityDiagram.png and /dev/null differ
diff --git a/docs/images/DeleteActivityDiagram.png b/docs/images/DeleteActivityDiagram.png
new file mode 100644
index 00000000000..c9788d56210
Binary files /dev/null and b/docs/images/DeleteActivityDiagram.png differ
diff --git a/docs/images/DeleteSequenceDiagram.png b/docs/images/DeleteSequenceDiagram.png
index fa327b39618..c1f68fa1fe3 100644
Binary files a/docs/images/DeleteSequenceDiagram.png and b/docs/images/DeleteSequenceDiagram.png differ
diff --git a/docs/images/EditActivityDiagram.png b/docs/images/EditActivityDiagram.png
new file mode 100644
index 00000000000..9c7e6b066ce
Binary files /dev/null and b/docs/images/EditActivityDiagram.png differ
diff --git a/docs/images/FindActivityDiagram.png b/docs/images/FindActivityDiagram.png
new file mode 100644
index 00000000000..008d08ffe0f
Binary files /dev/null and b/docs/images/FindActivityDiagram.png differ
diff --git a/docs/images/ListActivityDiagram.png b/docs/images/ListActivityDiagram.png
new file mode 100644
index 00000000000..ecaafcca88f
Binary files /dev/null and b/docs/images/ListActivityDiagram.png differ
diff --git a/docs/images/LogicClassDiagram.png b/docs/images/LogicClassDiagram.png
index 9e9ba9f79e5..10efd4ea493 100644
Binary files a/docs/images/LogicClassDiagram.png and b/docs/images/LogicClassDiagram.png differ
diff --git a/docs/images/ModelClassDiagram.png b/docs/images/ModelClassDiagram.png
index 04070af60d8..0e6788365f2 100644
Binary files a/docs/images/ModelClassDiagram.png and b/docs/images/ModelClassDiagram.png differ
diff --git a/docs/images/ParserClasses.png b/docs/images/ParserClasses.png
index e7b4c8880cd..661eef23295 100644
Binary files a/docs/images/ParserClasses.png and b/docs/images/ParserClasses.png differ
diff --git a/docs/images/StorageClassDiagram.png b/docs/images/StorageClassDiagram.png
index 2533a5c1af0..1ccf5167fdd 100644
Binary files a/docs/images/StorageClassDiagram.png and b/docs/images/StorageClassDiagram.png differ
diff --git a/docs/images/Ui.png b/docs/images/Ui.png
index 5bd77847aa2..541b80650b7 100644
Binary files a/docs/images/Ui.png and b/docs/images/Ui.png differ
diff --git a/docs/images/UiClassDiagram.png b/docs/images/UiClassDiagram.png
index 785e04dbab4..a59a49b7edf 100644
Binary files a/docs/images/UiClassDiagram.png and b/docs/images/UiClassDiagram.png differ
diff --git a/docs/images/UiOverview.png b/docs/images/UiOverview.png
new file mode 100644
index 00000000000..26d29dbf45c
Binary files /dev/null and b/docs/images/UiOverview.png differ
diff --git a/docs/images/UndoRedoState0.png b/docs/images/UndoRedoState0.png
deleted file mode 100644
index 8f7538cd884..00000000000
Binary files a/docs/images/UndoRedoState0.png and /dev/null differ
diff --git a/docs/images/UndoRedoState1.png b/docs/images/UndoRedoState1.png
deleted file mode 100644
index df9908d0948..00000000000
Binary files a/docs/images/UndoRedoState1.png and /dev/null differ
diff --git a/docs/images/UndoRedoState2.png b/docs/images/UndoRedoState2.png
deleted file mode 100644
index 36519c1015b..00000000000
Binary files a/docs/images/UndoRedoState2.png and /dev/null differ
diff --git a/docs/images/UndoRedoState3.png b/docs/images/UndoRedoState3.png
deleted file mode 100644
index 19959d01712..00000000000
Binary files a/docs/images/UndoRedoState3.png and /dev/null differ
diff --git a/docs/images/UndoRedoState4.png b/docs/images/UndoRedoState4.png
deleted file mode 100644
index 4c623e4f2c5..00000000000
Binary files a/docs/images/UndoRedoState4.png and /dev/null differ
diff --git a/docs/images/UndoRedoState5.png b/docs/images/UndoRedoState5.png
deleted file mode 100644
index 84ad2afa6bd..00000000000
Binary files a/docs/images/UndoRedoState5.png and /dev/null differ
diff --git a/docs/images/UndoSequenceDiagram.png b/docs/images/UndoSequenceDiagram.png
deleted file mode 100644
index 6addcd3a8d9..00000000000
Binary files a/docs/images/UndoSequenceDiagram.png and /dev/null differ
diff --git a/docs/images/daytona65.png b/docs/images/daytona65.png
new file mode 100644
index 00000000000..aa708c60d74
Binary files /dev/null and b/docs/images/daytona65.png differ
diff --git a/docs/images/findAlexDavidResult.png b/docs/images/findAlexDavidResult.png
deleted file mode 100644
index 235da1c273e..00000000000
Binary files a/docs/images/findAlexDavidResult.png and /dev/null differ
diff --git a/docs/images/findJohnCarlosResult.png b/docs/images/findJohnCarlosResult.png
new file mode 100644
index 00000000000..9c975591112
Binary files /dev/null and b/docs/images/findJohnCarlosResult.png differ
diff --git a/docs/images/helpMessage.png b/docs/images/helpMessage.png
index b1f70470137..83891b4097b 100644
Binary files a/docs/images/helpMessage.png and b/docs/images/helpMessage.png differ
diff --git a/docs/images/jeraldkiew.png b/docs/images/jeraldkiew.png
new file mode 100644
index 00000000000..2bee9784cee
Binary files /dev/null and b/docs/images/jeraldkiew.png differ
diff --git a/docs/images/ksunil2001.png b/docs/images/ksunil2001.png
new file mode 100644
index 00000000000..4e727bce52b
Binary files /dev/null and b/docs/images/ksunil2001.png differ
diff --git a/docs/images/nramapurath.png b/docs/images/nramapurath.png
new file mode 100644
index 00000000000..d333486b3a0
Binary files /dev/null and b/docs/images/nramapurath.png differ
diff --git a/docs/images/tracing/LogicSequenceDiagram.png b/docs/images/tracing/LogicSequenceDiagram.png
index c9b1f6cc232..04561d95143 100644
Binary files a/docs/images/tracing/LogicSequenceDiagram.png and b/docs/images/tracing/LogicSequenceDiagram.png differ
diff --git a/docs/images/yitong241.png b/docs/images/yitong241.png
new file mode 100644
index 00000000000..236c92ec961
Binary files /dev/null and b/docs/images/yitong241.png differ
diff --git a/docs/index.md b/docs/index.md
index 7601dbaad0d..0954fb12411 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -1,6 +1,6 @@
---
layout: page
-title: AddressBook Level-3
+title: MedInfo
---
[](https://github.com/se-edu/addressbook-level3/actions)
@@ -8,10 +8,11 @@ title: AddressBook Level-3

-**AddressBook is a desktop application for managing your contact details.** While it has a GUI, most of the user interactions happen using a CLI (Command Line Interface).
+**MedInfo is a desktop application for managing patients and wards.** While it has a GUI, most of the user interactions happen using a CLI (Command Line Interface).
-* If you are interested in using AddressBook, head over to the [_Quick Start_ section of the **User Guide**](UserGuide.html#quick-start).
-* If you are interested about developing AddressBook, the [**Developer Guide**](DeveloperGuide.html) is a good place to start.
+* If you are interested in using MedInfo, head over to the [_Quick Start_ section of the **User Guide**](UserGuide.html#quick-start).
+* If you are interested about developing MedInfo, the [**Developer Guide**](DeveloperGuide.html) is a good place to start.
+* Find out more about the team behind MedInfo [**here**](AboutUs.html).
**Acknowledgements**
diff --git a/docs/team/daytona65.md b/docs/team/daytona65.md
new file mode 100644
index 00000000000..6ec58e16433
--- /dev/null
+++ b/docs/team/daytona65.md
@@ -0,0 +1,66 @@
+---
+layout: page
+title: Nicholas Halim's Project Portfolio Page
+---
+
+### Project: MedInfo
+
+MedInfo is a desktop application for private hospital administrative staff. It helps manage patients,
+their status, discharge dates and wards. MedInfo aims to solve the problem of slow, multiple step process of
+documenting patient medical records during in-processing by zeroing in on the important details and provide simple,
+fast access to a particular patient’s medical records for hospital admin staff.
+
+The user interacts with MedInfo using a CLI, and it has a GUI created with JavaFX.
+MedInfo is written in Java, and has about 10 kLoC.
+
+Given below are my contributions to the project.
+
+* **New Feature**:
+ * Ward class and its associated classes
+ * Ward to Patient interactions
+ * Occupancy and capacity tracking for wards
+ * Patient coloured status bars
+ * Split screens
+ * Overall stats display in status bar footer
+
+
+* Code contributed: [**RepoSense**](https://nus-cs2103-ay2223s2.github.io/tp-dashboard/?search=daytona65&sort=groupTitle&sortWithin=title&timeframe=commit&mergegroup=&groupSelect=groupByRepos&breakdown=true&checkedFileTypes=docs~functional-code~test-code~other&since=2023-02-17&tabOpen=false&zFR=false)
+
+
+* View Pull Requests I have authored [**here**](https://github.com/AY2223S2-CS2103T-T12-2/tp/pulls?q=is%3Apr+author%3Adaytona65+) .
+
+
+* **Project management and Contributions**:
+ * Led ideation and implementation of new features for my team
+ * Managed the review and merging of my team's PRs
+ * Helped assign and delegate some tasks to team members
+ * Ensured team vision was aligned
+ * Wrote Javadocs and helped to check code quality.
+
+
+* **Enhancements to existing features**:
+ * Enhance the GUI and added split screens
+ * Mostly worked on implementing new features without breaking existing features
+
+
+* **Documentation**:
+ * User Guide:
+ * Fixed Table of Contents links
+ * Added User Interface Overview
+ * Updated Introduction and About MedInfo
+ * Developer Guide:
+ * Helped review the Guide.
+
+* **Community**:
+ * View PRs I have reviewed [**here**](https://github.com/AY2223S2-CS2103T-T12-2/tp/pulls?q=is%3Apr+reviewed-by%3Adaytona65+).
+ * View my contributions to forum discussions [**here**](https://github.com/nus-cs2103-AY2223S2/forum/issues?q=is%3Aissue+author%3Adaytona65+).
+ * View my reported bugs and suggestions for other teams in the class [**here**](https://github.com/AY2223S2-CS2103-F11-1/tp/issues?q=is%3Aissue+is%3Aclosed)
+ , under Tester D.
+
+
+* **Tools**:
+ * Figma used for initial UI draft
+ * Google Docs for miscellaneous documentation and changelog
+ * Zoom for weekly team meetings
+ * Telegram for team discussions
+
diff --git a/docs/team/jeraldkiew.md b/docs/team/jeraldkiew.md
new file mode 100644
index 00000000000..55021c8d0f6
--- /dev/null
+++ b/docs/team/jeraldkiew.md
@@ -0,0 +1,75 @@
+---
+layout: page
+title: Jerald Kiew's Project Portfolio Page
+---
+
+### Project: MedInfo
+
+MedInfo is a desktop application for private hospital administrative staff. It helps manage patients,
+their status, discharge dates and wards. MedInfo aims to solve the problem of slow, multiple step process of
+documenting patient medical records during in-processing by zeroing in on the important details and provide simple,
+fast access to a particular patient’s medical records for hospital admin staff.
+
+The user interacts with MedInfo using a CLI, and it has a GUI created with JavaFX.
+MedInfo is written in Java, and has about 10 kLoC.
+
+Given below are my contributions to the project.
+
+- **New Feature**
+
+ - Ward implementation
+ - `editward` command is a core feature required to augment the name and capacities of existing wards, and ensure these changes reflect for the corresponding patients [\#163](https://github.com/AY2223S2-CS2103T-T12-2/tp/pull/163)
+ - `Capacity` class together with `Ward` helped check that every ward's occupancy does not exceed its allocated capacity [\#138](https://github.com/AY2223S2-CS2103T-T12-2/tp/pull/138)
+ - Status implementation
+ - Patient Class implementation
+ - Refactoring `Patient` class to accomodate a `Ward`, so that patients can be assigned to their respective wards [\#109](https://github.com/AY2223S2-CS2103T-T12-2/tp/pull/109)
+
+- **Code contributed**: [RepoSense link](https://nus-cs2103-ay2223s2.github.io/tp-dashboard/?search=jeraldkiew&breakdown=true&sort=groupTitle%20dsc&sortWithin=title&since=2023-02-17&timeframe=commit&mergegroup=&groupSelect=groupByRepos&checkedFileTypes=docs~functional-code~test-code~other)
+
+- **Project management**:
+
+ - Reviewed and merged teammate's PRs
+ - Overviewed the design of classes under model
+ - Spearheaded documentation
+ - Ensured team vision was aligned
+
+- **Enhancements to existing features**:
+
+ - Implemented total occupancy of MedInfo
+ - Tracks and displays total number of patients currently in MedInfo [\#146](https://github.com/AY2223S2-CS2103T-T12-2/tp/pull/146)
+ - Fixed response and error messages
+ - Standardised and corrected messages concerning optional parameters [\#265](https://github.com/AY2223S2-CS2103T-T12-2/tp/pull/265)
+ - Fixed `help` message linking user to User Guide [\#265](https://github.com/AY2223S2-CS2103T-T12-2/tp/pull/265)
+ - Refactored initial `Person` and `Person`-related classes to `Patient`
+ - Refactored existing classes as well as designed new classes for our new purposes in model [\#85](https://github.com/AY2223S2-CS2103T-T12-2/tp/pull/85) [\#86](https://github.com/AY2223S2-CS2103T-T12-2/tp/pull/86) [\#89](https://github.com/AY2223S2-CS2103T-T12-2/tp/pull/89)
+
+- **Documentation**:
+
+ - User Guide
+ - Added documentation for `editward` and `deleteward` [\#171](https://github.com/AY2223S2-CS2103T-T12-2/tp/pull/171)
+ - Added informative sections for `delete` and `deleteward` confirmation and constraints [\#265](https://github.com/AY2223S2-CS2103T-T12-2/tp/pull/265)
+ - Added and corrected Ui screenshots [\#265](https://github.com/AY2223S2-CS2103T-T12-2/tp/pull/265)
+ - Developer Guide:
+ - Added various user stories [\#137](https://github.com/AY2223S2-CS2103T-T12-2/tp/pull/137)
+ - Added and updated PUML diagrams [\#152](https://github.com/AY2223S2-CS2103T-T12-2/tp/pull/152) [\#251](https://github.com/AY2223S2-CS2103T-T12-2/tp/pull/251) [\#265](https://github.com/AY2223S2-CS2103T-T12-2/tp/pull/265)
+
+
+
+
+
+
+
+
+
+
+- **Contributions to Team-based tasks**:
+ - Refactored Person to Patient throughout the code
+ - Maintained issue tracker
+ - Updated user and developer docs
+
+- **Review/mentoring contributions**:
+
+ - PRs reviewed (with non-trivial review comments): [\#136](https://github.com/AY2223S2-CS2103T-T12-2/tp/pull/136) [\#159](https://github.com/AY2223S2-CS2103T-T12-2/tp/pull/159)
+
+- **Contributions beyond the project team**:
+ - Reported bugs and suggestion for another team in the class - [Ultron](https://github.com/AY2223S2-CS2103T-F12-4/tp) [\#154](https://github.com/AY2223S2-CS2103T-F12-4/tp/issues/154) [\#160](https://github.com/AY2223S2-CS2103T-F12-4/tp/issues/160) [\#167](https://github.com/AY2223S2-CS2103T-F12-4/tp/issues/167)
diff --git a/docs/team/johndoe.md b/docs/team/johndoe.md
deleted file mode 100644
index 773a07794e2..00000000000
--- a/docs/team/johndoe.md
+++ /dev/null
@@ -1,46 +0,0 @@
----
-layout: page
-title: John Doe's Project Portfolio Page
----
-
-### Project: AddressBook Level 3
-
-AddressBook - Level 3 is a desktop address book application used for teaching Software Engineering principles. The user interacts with it using a CLI, and it has a GUI created with JavaFX. It is written in Java, and has about 10 kLoC.
-
-Given below are my contributions to the project.
-
-* **New Feature**: Added the ability to undo/redo previous commands.
- * What it does: allows the user to undo all previous commands one at a time. Preceding undo commands can be reversed by using the redo command.
- * Justification: This feature improves the product significantly because a user can make mistakes in commands and the app should provide a convenient way to rectify them.
- * Highlights: This enhancement affects existing commands and commands to be added in future. It required an in-depth analysis of design alternatives. The implementation too was challenging as it required changes to existing commands.
- * Credits: *{mention here if you reused any code/ideas from elsewhere or if a third-party library is heavily used in the feature so that a reader can make a more accurate judgement of how much effort went into the feature}*
-
-* **New Feature**: Added a history command that allows the user to navigate to previous commands using up/down keys.
-
-* **Code contributed**: [RepoSense link]()
-
-* **Project management**:
- * Managed releases `v1.3` - `v1.5rc` (3 releases) on GitHub
-
-* **Enhancements to existing features**:
- * Updated the GUI color scheme (Pull requests [\#33](), [\#34]())
- * Wrote additional tests for existing features to increase coverage from 88% to 92% (Pull requests [\#36](), [\#38]())
-
-* **Documentation**:
- * User Guide:
- * Added documentation for the features `delete` and `find` [\#72]()
- * Did cosmetic tweaks to existing documentation of features `clear`, `exit`: [\#74]()
- * Developer Guide:
- * Added implementation details of the `delete` feature.
-
-* **Community**:
- * PRs reviewed (with non-trivial review comments): [\#12](), [\#32](), [\#19](), [\#42]()
- * Contributed to forum discussions (examples: [1](), [2](), [3](), [4]())
- * Reported bugs and suggestions for other teams in the class (examples: [1](), [2](), [3]())
- * Some parts of the history feature I added was adopted by several other class mates ([1](), [2]())
-
-* **Tools**:
- * Integrated a third party library (Natty) to the project ([\#42]())
- * Integrated a new Github plugin (CircleCI) to the team repo
-
-* _{you can add/remove categories in the list above}_
diff --git a/docs/team/ksunil2001.md b/docs/team/ksunil2001.md
new file mode 100644
index 00000000000..5bff13f82e4
--- /dev/null
+++ b/docs/team/ksunil2001.md
@@ -0,0 +1,56 @@
+---
+layout: page
+title: K Sunil Avinash's Project Portfolio Page
+---
+
+### Project: MedInfo
+
+MedInfo is a desktop application for private hospital administrative staff. It helps manage patients,
+their status, discharge dates and wards. MedInfo aims to solve the problem of slow, multiple step process of
+documenting patient medical records during in-processing by zeroing in on the important details and provide simple,
+fast access to a particular patient’s medical records for hospital admin staff.
+
+The user interacts with MedInfo using a CLI, and it has a GUI created with JavaFX.
+MedInfo is written in Java, and has about 10 kLoC.
+
+Given below are my contributions to the project.
+
+- **New Feature**
+ - Added discharge date-time field to patient
+
+
+- **Code contributed**: [RepoSense](https://nus-cs2103-ay2223s2.github.io/tp-dashboard/?search=ksunil2001&breakdown=true)
+
+
+- **Enhancements to existing features**:
+ - Fixed majority of the failing testcases
+ - This was hard to fix for some testcases, as it required me to dig deep inside the code with the debugger to find the errors
+ - Even after finding the error, it took some time to understand how and why the error occurred before I could fix it
+ - Overall it was a time-consuming process
+ - Updated json files for test cases
+ - Fixed the display of ward name when editing a patient's details
+ - Created a help.txt file to summarise the list of commands and their syntax
+
+
+- **Documentation**:
+ - Organised features by Patient, Ward and Utility in the User Guide
+ - Updated the editward and addward command features in the User Guide
+ - Added a use case for the find command in the Developer Guide
+ - Updated the product scope, target user profile, value proposition, user stories, use cases and glossary of the Developer Guide
+
+
+- **Contributions to Team-based tasks**:
+ - Refactored Person to Patient throughout the code
+ - Fixed checkstyle issues
+
+
+- **Review/mentoring contributions**:
+ - This link lists all the PRs I have reviewed: [Reviewed PRs](https://github.com/AY2223S2-CS2103T-T12-2/tp/pulls?q=is%3Apr+is%3Aclosed+reviewed-by%3Aksunil2001)
+ - Helped to verify the code style and clarify a doubt in this PR: [PR](https://github.com/AY2223S2-CS2103T-T12-2/tp/pull/121)
+ - Corrected the code to implement abstraction and improve the code style in this PR: [PR](https://github.com/AY2223S2-CS2103T-T12-2/tp/pull/159)
+ - Checked the grammar of the UG in this PR: [PR](https://github.com/AY2223S2-CS2103T-T12-2/tp/pull/249)
+
+
+- **Contributions beyond the project team**:
+ - Reported a total of 11 bugs during the PE dry run
+ - I made sure to describe all the bugs as detailed and clear as possible with screenshots, to ensure the product's team would not have any doubts
diff --git a/docs/team/nramapurath.md b/docs/team/nramapurath.md
new file mode 100644
index 00000000000..bda8a5a1683
--- /dev/null
+++ b/docs/team/nramapurath.md
@@ -0,0 +1,66 @@
+---
+layout: page
+title: Navaneeth Ramapurath's Project Portfolio Page
+---
+
+### Project: MedInfo
+
+MedInfo is a desktop application for private hospital administrative staff. It helps manage patients,
+their status, discharge dates and wards. MedInfo aims to solve the problem of slow, multiple step process of
+documenting patient medical records during in-processing by zeroing in on the important details and provide simple,
+fast access to a particular patient’s medical records for hospital admin staff.
+
+The user interacts with MedInfo using a CLI, and it has a GUI created with JavaFX.
+MedInfo is written in Java, and has about 10 kLoC.
+
+Given below are my contributions to the project.
+
+- **New Feature**
+ - Edit patient status
+ - Edit patient ward
+ - Confirmation window pop-up on delete operations
+ - This was crucial to prevent admin staff from accidentally performing potentially destructive operations
+
+
+- **Code contributed**: [RepoSense link](https://nus-cs2103-ay2223s2.github.io/tp-dashboard/?search=nramapurath&breakdown=true)
+ - You can view the list of PRs that I have authored [here](https://github.com/AY2223S2-CS2103T-T12-2/tp/pulls?page=1&q=is%3Apr+author%3Anramapurath)
+
+
+- **Enhancements to existing features**:
+ - Fixed logic to improve sorting by discharge date
+ - Made ward uniqueness case-insensitive to prevent duplicate wards
+ - Fixed app crash on invalid save data
+
+
+- **Project management**:
+ - GitHub Issues to track bugs, features and user stories
+ - GitHub Projects to view progress at a glance
+ - Maintained changelog on a collaborative document
+ - Weekly team meetings held over Zoom to track progress
+
+
+- **Documentation**:
+ - User Guide:
+ - Updated Introduction and About MedInfo
+ - Added Glossary for definitions and technical term descriptions
+ - Added Getting Started section
+ - Added FAQs
+ - Developer Guide:
+ - Added Planned Enhancements section
+ - Added activity diagrams for user interactions
+ - Edited user stories to match project scope
+
+
+- **Review/mentoring contributions**:
+ - You can view the list of PRs that I have reviewed [here](https://github.com/AY2223S2-CS2103T-T12-2/tp/pulls?q=is%3Apr+reviewed-by%3Anramapurath)
+ - Facilitated discussions with team on design decisions
+ - Provided technical support when necessary over Telegram
+
+
+- **Other Tools**:
+ - Figma used for initial UI draft
+ - PlantUML for class and activity diagrams
+ - Google Docs for miscellaneous documentation and changelog
+ - Microsoft Teams for communication with CS2103T Teaching Team
+ - Zoom for weekly team meetings
+ - Telegram for team discussions
diff --git a/docs/team/yitong241.md b/docs/team/yitong241.md
new file mode 100644
index 00000000000..7a7c1a72094
--- /dev/null
+++ b/docs/team/yitong241.md
@@ -0,0 +1,70 @@
+---
+layout: page
+title: Sun Yitong's Project Portfolio Page
+---
+
+### Project: MedInfo
+
+MedInfo is a desktop application for private hospital administrative staff. It helps manage patients,
+their status, discharge dates and wards. MedInfo aims to solve the problem of slow, multiple step process of
+documenting patient medical records during in-processing by zeroing in on the important details and provide simple,
+fast access to a particular patient’s medical records for hospital admin staff.
+
+The user interacts with MedInfo using a CLI, and it has a GUI created with JavaFX.
+MedInfo is written in Java, and has about 10 kLoC.
+
+Given below are my contributions to the project.
+
+* **New Feature**:
+ * `status` attribute [#95](https://github.com/AY2223S2-CS2103T-T12-2/tp/pull/95)
+ * represent the medical status of the patients with `status`
+ * `find` command [#110](https://github.com/AY2223S2-CS2103T-T12-2/tp/pull/110)
+ * find the patient by searching for specific `name`, `nric`, `status` and `ward`.
+ * `addward` command [#143](https://github.com/AY2223S2-CS2103T-T12-2/tp/pull/131)
+ * add new wards into the MedInfo system
+ * `deleteward` command [#156](https://github.com/AY2223S2-CS2103T-T12-2/tp/pull/156)
+ * delete an existing ward in the system
+ * `sort` command [#159](https://github.com/AY2223S2-CS2103T-T12-2/tp/pull/159)
+ * sort the displayed list of patients by `name`, `status`, `ward name` and `discharge date` in `ascending` or `descending` order.
+
+* **Code contributed**: [RepoSense link](https://nus-cs2103-ay2223s2.github.io/tp-dashboard/?search=yitong241&breakdown=true)
+* **PR contributed**: [PR](https://github.com/AY2223S2-CS2103T-T12-2/tp/pulls?page=1&q=is%3Apr+is%3Aclosed+author%3Ayitong241)
+
+* **Project management**:
+ - Active reviewer for code-related Pull Requests;
+ - Active contributor of issue tracker;
+ - Manage the deadlines and tasks for teammates;
+
+* **Enhancements to existing features**:
+ *Modify the logic to adapt to MedInfo [#93](https://github.com/AY2223S2-CS2103T-T12-2/tp/pull/93)
+ * `add` command
+ * add new patients with specific `name`, `nric`, `status` and `ward` [#115](https://github.com/AY2223S2-CS2103T-T12-2/tp/pull/115)
+ * `find` command
+ * modify FindCommand to find based on `name`, `nric`, or `status` [#110](https://github.com/AY2223S2-CS2103T-T12-2/tp/pull/110)
+ * add confirmation windows when clearing [#151](https://github.com/AY2223S2-CS2103T-T12-2/tp/pull/131)
+
+* **Documentation**:
+ * User Guide:
+ * `sort-by` command
+ * refine overall structure (table of contents, summary table)
+ * Developer Guide:
+ * Table of content [#165](https://github.com/AY2223S2-CS2103T-T12-2/tp/pull/165)
+ * `add` command and corresponding use cases [#131](https://github.com/AY2223S2-CS2103T-T12-2/tp/pull/131)
+ * `sort` command and corresponding explanations [#165](https://github.com/AY2223S2-CS2103T-T12-2/tp/pull/165)
+
+* **Community**:
+ * Review many code-related PRs by the whole group with detailed insights and comments
+ * [Reviewed PRs](https://github.com/AY2223S2-CS2103T-T12-2/tp/pulls?q=is%3Apr+is%3Aclosed+reviewed-by%3Ayitong241)
+ * Refactor the application from AB3 to MedInfo completely
+ * [Link to PR](https://github.com/AY2223S2-CS2103T-T12-2/tp/pull/177)
+
+* **Issues Fixed**:
+ * Fix message constraints bug in Storage [#94](https://github.com/AY2223S2-CS2103T-T12-2/tp/pull/94)
+ * Fix bugs caused by improper use of Enum [#95](https://github.com/AY2223S2-CS2103T-T12-2/tp/pull/95)
+ * Fix bugs caused by inputting multiple prefixes when finding [#116](https://github.com/AY2223S2-CS2103T-T12-2/tp/pull/116)
+ * Fix issue with sort command error message display [#167](https://github.com/AY2223S2-CS2103T-T12-2/tp/pull/167)
+ * Fix issue with date time validation [#234](https://github.com/AY2223S2-CS2103T-T12-2/tp/pull/234)
+
+* **Testing**:
+ * Add test cases for find command [#123](https://github.com/AY2223S2-CS2103T-T12-2/tp/pull/123)
+
diff --git a/docs/tutorials/AddRemark.md b/docs/tutorials/AddRemark.md
index 880c701042f..4ea4578a334 100644
--- a/docs/tutorials/AddRemark.md
+++ b/docs/tutorials/AddRemark.md
@@ -23,12 +23,12 @@ For now, let’s keep `RemarkCommand` as simple as possible and print some outpu
**`RemarkCommand.java`:**
``` java
-package seedu.address.logic.commands;
+package seedu.medinfo.logic.commands;
-import seedu.address.model.Model;
+import seedu.medinfo.model.Model;
/**
- * Changes the remark of an existing person in the address book.
+ * Changes the remark of an existing patient in the address book.
*/
public class RemarkCommand extends Command {
@@ -65,8 +65,8 @@ Following the convention in other commands, we add relevant messages as constant
``` java
public static final String MESSAGE_USAGE = COMMAND_WORD
- + ": Edits the remark of the person identified "
- + "by the index number used in the last person listing. "
+ + ": Edits the remark of the patient identified "
+ + "by the index number used in the last patient listing. "
+ "Existing remark will be overwritten by the input.\n"
+ "Parameters: INDEX (must be a positive integer) "
+ "r/ [REMARK]\n"
@@ -91,7 +91,7 @@ Let’s change `RemarkCommand` to parse input from the user.
We start by modifying the constructor of `RemarkCommand` to accept an `Index` and a `String`. While we are at it, let’s change the error message to echo the values. While this is not a replacement for tests, it is an obvious way to tell if our code is functioning as intended.
``` java
-import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
+import static seedu.medinfo.commons.util.CollectionUtil.requireAllNonNull;
//...
public class RemarkCommand extends Command {
//...
@@ -101,8 +101,8 @@ public class RemarkCommand extends Command {
private final String remark;
/**
- * @param index of the person in the filtered person list to edit the remark
- * @param remark of the person to be updated to
+ * @param index of the patient in the filtered patient list to edit the remark
+ * @param remark of the patient to be updated to
*/
public RemarkCommand(Index index, String remark) {
requireAllNonNull(index, remark);
@@ -142,7 +142,7 @@ Your code should look something like [this](https://github.com/se-edu/addressboo
Now let’s move on to writing a parser that will extract the index and remark from the input provided by the user.
-Create a `RemarkCommandParser` class in the `seedu.address.logic.parser` package. The class must extend the `Parser` interface.
+Create a `RemarkCommandParser` class in the `seedu.medinfo.logic.parser` package. The class must extend the `Parser` interface.

@@ -225,11 +225,11 @@ If you are stuck, check out the sample
## Add `Remark` to the model
-Now that we have all the information that we need, let’s lay the groundwork for propagating the remarks added into the in-memory storage of person data. We achieve that by working with the `Person` model. Each field in a Person is implemented as a separate class (e.g. a `Name` object represents the person’s name). That means we should add a `Remark` class so that we can use a `Remark` object to represent a remark given to a person.
+Now that we have all the information that we need, let’s lay the groundwork for propagating the remarks added into the in-memory storage of patient data. We achieve that by working with the `Person` model. Each field in a Person is implemented as a separate class (e.g. a `Name` object represents the patient’s name). That means we should add a `Remark` class so that we can use a `Remark` object to represent a remark given to a patient.
### Add a new `Remark` class
-Create a new `Remark` in `seedu.address.model.person`. Since a `Remark` is a field that is similar to `Address`, we can reuse a significant bit of code.
+Create a new `Remark` in `seedu.medinfo.model.patient`. Since a `Remark` is a field that is similar to `Address`, we can reuse a significant bit of code.
A copy-paste and search-replace later, you should have something like [this](https://github.com/se-edu/addressbook-level3/commit/4516e099699baa9e2d51801bd26f016d812dedcc#diff-41bb13c581e280c686198251ad6cc337cd5e27032772f06ed9bf7f1440995ece). Note how `Remark` has no constrains and thus does not require input
validation.
@@ -240,9 +240,9 @@ Let’s change `RemarkCommand` and `RemarkCommandParser` to use the new `Remark`
## Add a placeholder element for remark to the UI
-Without getting too deep into `fxml`, let’s go on a 5 minute adventure to get some placeholder text to show up for each person.
+Without getting too deep into `fxml`, let’s go on a 5 minute adventure to get some placeholder text to show up for each patient.
-Simply add the following to [`seedu.address.ui.PersonCard`](https://github.com/se-edu/addressbook-level3/commit/850b78879582f38accb05dd20c245963c65ea599#diff-639834f1e05afe2276a86372adf0fe5f69314642c2d93cfa543d614ce5a76688).
+Simply add the following to [`seedu.medinfo.ui.PatientCard`](https://github.com/se-edu/addressbook-level3/commit/850b78879582f38accb05dd20c245963c65ea599#diff-639834f1e05afe2276a86372adf0fe5f69314642c2d93cfa543d614ce5a76688).
**`PersonCard.java`:**
@@ -311,9 +311,9 @@ Just add [this one line of code!](https://github.com/se-edu/addressbook-level3/c
**`PersonCard.java`:**
``` java
-public PersonCard(Person person, int displayedIndex) {
+public PersonCard(Person patient, int displayedIndex) {
//...
- remark.setText(person.getRemark().value);
+ remark.setText(patient.getRemark().value);
}
```
@@ -343,25 +343,25 @@ save it with `Model#setPerson()`.
throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
}
- Person personToEdit = lastShownList.get(index.getZeroBased());
- Person editedPerson = new Person(
- personToEdit.getName(), personToEdit.getPhone(), personToEdit.getEmail(),
- personToEdit.getAddress(), remark, personToEdit.getTags());
+ Person patientToEdit = lastShownList.get(index.getZeroBased());
+ Person editedPatient = new Person(
+ patientToEdit.getName(), patientToEdit.getPhone(), patientToEdit.getEmail(),
+ patientToEdit.getAddress(), remark, patientToEdit.getTags());
- model.setPerson(personToEdit, editedPerson);
+ model.setPerson(patientToEdit, editedPatient);
model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
- return new CommandResult(generateSuccessMessage(editedPerson));
+ return new CommandResult(generateSuccessMessage(editedPatient));
}
/**
* Generates a command execution success message based on whether
* the remark is added to or removed from
- * {@code personToEdit}.
+ * {@code patientToEdit}.
*/
- private String generateSuccessMessage(Person personToEdit) {
+ private String generateSuccessMessage(Person patientToEdit) {
String message = !remark.value.isEmpty() ? MESSAGE_ADD_REMARK_SUCCESS : MESSAGE_DELETE_REMARK_SUCCESS;
- return String.format(message, personToEdit);
+ return String.format(message, patientToEdit);
}
```
diff --git a/docs/tutorials/RemovingFields.md b/docs/tutorials/RemovingFields.md
index f29169bc924..79bb6b0b14f 100644
--- a/docs/tutorials/RemovingFields.md
+++ b/docs/tutorials/RemovingFields.md
@@ -28,7 +28,7 @@ IntelliJ IDEA provides a refactoring tool that can identify *most* parts of a re
### Assisted refactoring
-The `address` field in `Person` is actually an instance of the `seedu.address.model.person.Address` class. Since removing the `Address` class will break the application, we start by identifying `Address`'s usages. This allows us to see code that depends on `Address` to function properly and edit them on a case-by-case basis. Right-click the `Address` class and select `Refactor` \> `Safe Delete` through the menu.
+The `address` field in `Person` is actually an instance of the `seedu.medinfo.model.patient.Address` class. Since removing the `Address` class will break the application, we start by identifying `Address`'s usages. This allows us to see code that depends on `Address` to function properly and edit them on a case-by-case basis. Right-click the `Address` class and select `Refactor` \> `Safe Delete` through the menu.
* :bulb: To make things simpler, you can unselect the options `Search in comments and strings` and `Search for text occurrences`

@@ -100,7 +100,7 @@ In `src/test/data/`, data meant for testing purposes are stored. While keeping t
```json
{
- "persons": [ {
+ "patients": [ {
"name": "Person with invalid name field: Ha!ns Mu@ster",
"phone": "9482424",
"email": "hans@example.com",
diff --git a/docs/tutorials/TracingCode.md b/docs/tutorials/TracingCode.md
index 4fb62a83ef6..230ede22b03 100644
--- a/docs/tutorials/TracingCode.md
+++ b/docs/tutorials/TracingCode.md
@@ -39,7 +39,7 @@ In our case, we would want to begin the tracing at the very point where the App
-According to the sequence diagram you saw earlier (and repeated above for reference), the `UI` component yields control to the `Logic` component through a method named `execute`. Searching through the code base for an `execute()` method that belongs to the `Logic` component yields a promising candidate in `seedu.address.logic.Logic`.
+According to the sequence diagram you saw earlier (and repeated above for reference), the `UI` component yields control to the `Logic` component through a method named `execute`. Searching through the code base for an `execute()` method that belongs to the `Logic` component yields a promising candidate in `seedu.medinfo.logic.Logic`.
@@ -48,7 +48,7 @@ According to the sequence diagram you saw earlier (and repeated above for refere
:bulb: **Intellij Tip:** The ['**Search Everywhere**' feature](https://www.jetbrains.com/help/idea/searching-everywhere.html) can be used here. In particular, the '**Find Symbol**' ('Symbol' here refers to methods, variables, classes etc.) variant of that feature is quite useful here as we are looking for a _method_ named `execute`, not simply the text `execute`.
-A quick look at the `seedu.address.logic.Logic` (an extract given below) confirms that this indeed might be what we’re looking for.
+A quick look at the `seedu.medinfo.logic.Logic` (an extract given below) confirms that this indeed might be what we’re looking for.
```java
public interface Logic {
@@ -189,22 +189,22 @@ Recall from the User Guide that the `edit` command has the format: `edit INDEX [
@Override
public CommandResult execute(Model model) throws CommandException {
...
- Person personToEdit = lastShownList.get(index.getZeroBased());
- Person editedPerson = createEditedPerson(personToEdit, editPersonDescriptor);
- if (!personToEdit.isSamePerson(editedPerson) && model.hasPerson(editedPerson)) {
+ Person patientToEdit = lastShownList.get(index.getZeroBased());
+ Person editedPatient = createEditedPerson(patientToEdit, editPatientDescriptor);
+ if (!patientToEdit.isSamePerson(editedPatient) && model.hasPerson(editedPatient)) {
throw new CommandException(MESSAGE_DUPLICATE_PERSON);
}
- model.setPerson(personToEdit, editedPerson);
+ model.setPerson(patientToEdit, editedPatient);
model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
- return new CommandResult(String.format(MESSAGE_EDIT_PERSON_SUCCESS, editedPerson));
+ return new CommandResult(String.format(MESSAGE_EDIT_PERSON_SUCCESS, editedPatient));
}
```
1. As suspected, `command#execute()` does indeed make changes to the `model` object. Specifically,
- * it uses the `setPerson()` method (defined in the interface `Model` and implemented in `ModelManager` as per the usual pattern) to update the person data.
- * it uses the `updateFilteredPersonList` method to ask the `Model` to populate the 'filtered list' with _all_ persons.
- FYI, The 'filtered list' is the list of persons resulting from the most recent operation that will be shown to the user immediately after. For the `edit` command, we populate it with all the persons so that the user can see the edited person along with all other persons. If this was a `find` command, we would be setting that list to contain the search results instead.
- To provide some context, given below is the class diagram of the `Model` component. See if you can figure out where the 'filtered list' of persons is being tracked.
+ * it uses the `setPerson()` method (defined in the interface `Model` and implemented in `ModelManager` as per the usual pattern) to update the patient data.
+ * it uses the `updateFilteredPersonList` method to ask the `Model` to populate the 'filtered list' with _all_ patients.
+ FYI, The 'filtered list' is the list of patients resulting from the most recent operation that will be shown to the user immediately after. For the `edit` command, we populate it with all the patients so that the user can see the edited patient along with all other patients. If this was a `find` command, we would be setting that list to contain the search results instead.
+ To provide some context, given below is the class diagram of the `Model` component. See if you can figure out where the 'filtered list' of patients is being tracked.
* :bulb: This may be a good time to read through the [`Model` component section of the DG](../DeveloperGuide.html#model-component)
@@ -231,7 +231,7 @@ Recall from the User Guide that the `edit` command has the format: `edit INDEX [
* {@code JsonSerializableAddressBook}.
*/
public JsonSerializableAddressBook(ReadOnlyAddressBook source) {
- persons.addAll(
+ patients.addAll(
source.getPersonList()
.stream()
.map(JsonAdaptedPerson::new)
diff --git a/src/main/java/seedu/address/commons/core/Messages.java b/src/main/java/seedu/address/commons/core/Messages.java
deleted file mode 100644
index 1deb3a1e469..00000000000
--- a/src/main/java/seedu/address/commons/core/Messages.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package seedu.address.commons.core;
-
-/**
- * Container for user visible messages.
- */
-public class Messages {
-
- public static final String MESSAGE_UNKNOWN_COMMAND = "Unknown command";
- public static final String MESSAGE_INVALID_COMMAND_FORMAT = "Invalid command format! \n%1$s";
- public static final String MESSAGE_INVALID_PERSON_DISPLAYED_INDEX = "The person index provided is invalid";
- public static final String MESSAGE_PERSONS_LISTED_OVERVIEW = "%1$d persons listed!";
-
-}
diff --git a/src/main/java/seedu/address/logic/Logic.java b/src/main/java/seedu/address/logic/Logic.java
deleted file mode 100644
index 92cd8fa605a..00000000000
--- a/src/main/java/seedu/address/logic/Logic.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package seedu.address.logic;
-
-import java.nio.file.Path;
-
-import javafx.collections.ObservableList;
-import seedu.address.commons.core.GuiSettings;
-import seedu.address.logic.commands.CommandResult;
-import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.logic.parser.exceptions.ParseException;
-import seedu.address.model.ReadOnlyAddressBook;
-import seedu.address.model.person.Person;
-
-/**
- * API of the Logic component
- */
-public interface Logic {
- /**
- * Executes the command and returns the result.
- * @param commandText The command as entered by the user.
- * @return the result of the command execution.
- * @throws CommandException If an error occurs during command execution.
- * @throws ParseException If an error occurs during parsing.
- */
- CommandResult execute(String commandText) throws CommandException, ParseException;
-
- /**
- * Returns the AddressBook.
- *
- * @see seedu.address.model.Model#getAddressBook()
- */
- ReadOnlyAddressBook getAddressBook();
-
- /** Returns an unmodifiable view of the filtered list of persons */
- ObservableList getFilteredPersonList();
-
- /**
- * Returns the user prefs' address book file path.
- */
- Path getAddressBookFilePath();
-
- /**
- * Returns the user prefs' GUI settings.
- */
- GuiSettings getGuiSettings();
-
- /**
- * Set the user prefs' GUI settings.
- */
- void setGuiSettings(GuiSettings guiSettings);
-}
diff --git a/src/main/java/seedu/address/logic/commands/AddCommand.java b/src/main/java/seedu/address/logic/commands/AddCommand.java
deleted file mode 100644
index 71656d7c5c8..00000000000
--- a/src/main/java/seedu/address/logic/commands/AddCommand.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package seedu.address.logic.commands;
-
-import static java.util.Objects.requireNonNull;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
-
-import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.model.Model;
-import seedu.address.model.person.Person;
-
-/**
- * Adds a person to the address book.
- */
-public class AddCommand extends Command {
-
- public static final String COMMAND_WORD = "add";
-
- public static final String MESSAGE_USAGE = COMMAND_WORD + ": Adds a person to the address book. "
- + "Parameters: "
- + PREFIX_NAME + "NAME "
- + PREFIX_PHONE + "PHONE "
- + PREFIX_EMAIL + "EMAIL "
- + PREFIX_ADDRESS + "ADDRESS "
- + "[" + PREFIX_TAG + "TAG]...\n"
- + "Example: " + COMMAND_WORD + " "
- + PREFIX_NAME + "John Doe "
- + PREFIX_PHONE + "98765432 "
- + PREFIX_EMAIL + "johnd@example.com "
- + PREFIX_ADDRESS + "311, Clementi Ave 2, #02-25 "
- + PREFIX_TAG + "friends "
- + PREFIX_TAG + "owesMoney";
-
- public static final String MESSAGE_SUCCESS = "New person added: %1$s";
- public static final String MESSAGE_DUPLICATE_PERSON = "This person already exists in the address book";
-
- private final Person toAdd;
-
- /**
- * Creates an AddCommand to add the specified {@code Person}
- */
- public AddCommand(Person person) {
- requireNonNull(person);
- toAdd = person;
- }
-
- @Override
- public CommandResult execute(Model model) throws CommandException {
- requireNonNull(model);
-
- if (model.hasPerson(toAdd)) {
- throw new CommandException(MESSAGE_DUPLICATE_PERSON);
- }
-
- model.addPerson(toAdd);
- return new CommandResult(String.format(MESSAGE_SUCCESS, toAdd));
- }
-
- @Override
- public boolean equals(Object other) {
- return other == this // short circuit if same object
- || (other instanceof AddCommand // instanceof handles nulls
- && toAdd.equals(((AddCommand) other).toAdd));
- }
-}
diff --git a/src/main/java/seedu/address/logic/commands/ClearCommand.java b/src/main/java/seedu/address/logic/commands/ClearCommand.java
deleted file mode 100644
index 9c86b1fa6e4..00000000000
--- a/src/main/java/seedu/address/logic/commands/ClearCommand.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package seedu.address.logic.commands;
-
-import static java.util.Objects.requireNonNull;
-
-import seedu.address.model.AddressBook;
-import seedu.address.model.Model;
-
-/**
- * Clears the address book.
- */
-public class ClearCommand extends Command {
-
- public static final String COMMAND_WORD = "clear";
- public static final String MESSAGE_SUCCESS = "Address book has been cleared!";
-
-
- @Override
- public CommandResult execute(Model model) {
- requireNonNull(model);
- model.setAddressBook(new AddressBook());
- return new CommandResult(MESSAGE_SUCCESS);
- }
-}
diff --git a/src/main/java/seedu/address/logic/commands/DeleteCommand.java b/src/main/java/seedu/address/logic/commands/DeleteCommand.java
deleted file mode 100644
index 02fd256acba..00000000000
--- a/src/main/java/seedu/address/logic/commands/DeleteCommand.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package seedu.address.logic.commands;
-
-import static java.util.Objects.requireNonNull;
-
-import java.util.List;
-
-import seedu.address.commons.core.Messages;
-import seedu.address.commons.core.index.Index;
-import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.model.Model;
-import seedu.address.model.person.Person;
-
-/**
- * Deletes a person identified using it's displayed index from the address book.
- */
-public class DeleteCommand extends Command {
-
- public static final String COMMAND_WORD = "delete";
-
- public static final String MESSAGE_USAGE = COMMAND_WORD
- + ": Deletes the person identified by the index number used in the displayed person list.\n"
- + "Parameters: INDEX (must be a positive integer)\n"
- + "Example: " + COMMAND_WORD + " 1";
-
- public static final String MESSAGE_DELETE_PERSON_SUCCESS = "Deleted Person: %1$s";
-
- private final Index targetIndex;
-
- public DeleteCommand(Index targetIndex) {
- this.targetIndex = targetIndex;
- }
-
- @Override
- public CommandResult execute(Model model) throws CommandException {
- requireNonNull(model);
- List lastShownList = model.getFilteredPersonList();
-
- if (targetIndex.getZeroBased() >= lastShownList.size()) {
- throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
- }
-
- Person personToDelete = lastShownList.get(targetIndex.getZeroBased());
- model.deletePerson(personToDelete);
- return new CommandResult(String.format(MESSAGE_DELETE_PERSON_SUCCESS, personToDelete));
- }
-
- @Override
- public boolean equals(Object other) {
- return other == this // short circuit if same object
- || (other instanceof DeleteCommand // instanceof handles nulls
- && targetIndex.equals(((DeleteCommand) other).targetIndex)); // state check
- }
-}
diff --git a/src/main/java/seedu/address/logic/commands/EditCommand.java b/src/main/java/seedu/address/logic/commands/EditCommand.java
deleted file mode 100644
index 7e36114902f..00000000000
--- a/src/main/java/seedu/address/logic/commands/EditCommand.java
+++ /dev/null
@@ -1,226 +0,0 @@
-package seedu.address.logic.commands;
-
-import static java.util.Objects.requireNonNull;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
-import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS;
-
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Optional;
-import java.util.Set;
-
-import seedu.address.commons.core.Messages;
-import seedu.address.commons.core.index.Index;
-import seedu.address.commons.util.CollectionUtil;
-import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.model.Model;
-import seedu.address.model.person.Address;
-import seedu.address.model.person.Email;
-import seedu.address.model.person.Name;
-import seedu.address.model.person.Person;
-import seedu.address.model.person.Phone;
-import seedu.address.model.tag.Tag;
-
-/**
- * Edits the details of an existing person in the address book.
- */
-public class EditCommand extends Command {
-
- public static final String COMMAND_WORD = "edit";
-
- public static final String MESSAGE_USAGE = COMMAND_WORD + ": Edits the details of the person identified "
- + "by the index number used in the displayed person list. "
- + "Existing values will be overwritten by the input values.\n"
- + "Parameters: INDEX (must be a positive integer) "
- + "[" + PREFIX_NAME + "NAME] "
- + "[" + PREFIX_PHONE + "PHONE] "
- + "[" + PREFIX_EMAIL + "EMAIL] "
- + "[" + PREFIX_ADDRESS + "ADDRESS] "
- + "[" + PREFIX_TAG + "TAG]...\n"
- + "Example: " + COMMAND_WORD + " 1 "
- + PREFIX_PHONE + "91234567 "
- + PREFIX_EMAIL + "johndoe@example.com";
-
- public static final String MESSAGE_EDIT_PERSON_SUCCESS = "Edited Person: %1$s";
- public static final String MESSAGE_NOT_EDITED = "At least one field to edit must be provided.";
- public static final String MESSAGE_DUPLICATE_PERSON = "This person already exists in the address book.";
-
- private final Index index;
- private final EditPersonDescriptor editPersonDescriptor;
-
- /**
- * @param index of the person in the filtered person list to edit
- * @param editPersonDescriptor details to edit the person with
- */
- public EditCommand(Index index, EditPersonDescriptor editPersonDescriptor) {
- requireNonNull(index);
- requireNonNull(editPersonDescriptor);
-
- this.index = index;
- this.editPersonDescriptor = new EditPersonDescriptor(editPersonDescriptor);
- }
-
- @Override
- public CommandResult execute(Model model) throws CommandException {
- requireNonNull(model);
- List lastShownList = model.getFilteredPersonList();
-
- if (index.getZeroBased() >= lastShownList.size()) {
- throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
- }
-
- Person personToEdit = lastShownList.get(index.getZeroBased());
- Person editedPerson = createEditedPerson(personToEdit, editPersonDescriptor);
-
- if (!personToEdit.isSamePerson(editedPerson) && model.hasPerson(editedPerson)) {
- throw new CommandException(MESSAGE_DUPLICATE_PERSON);
- }
-
- model.setPerson(personToEdit, editedPerson);
- model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
- return new CommandResult(String.format(MESSAGE_EDIT_PERSON_SUCCESS, editedPerson));
- }
-
- /**
- * Creates and returns a {@code Person} with the details of {@code personToEdit}
- * edited with {@code editPersonDescriptor}.
- */
- private static Person createEditedPerson(Person personToEdit, EditPersonDescriptor editPersonDescriptor) {
- assert personToEdit != null;
-
- Name updatedName = editPersonDescriptor.getName().orElse(personToEdit.getName());
- Phone updatedPhone = editPersonDescriptor.getPhone().orElse(personToEdit.getPhone());
- Email updatedEmail = editPersonDescriptor.getEmail().orElse(personToEdit.getEmail());
- Address updatedAddress = editPersonDescriptor.getAddress().orElse(personToEdit.getAddress());
- Set updatedTags = editPersonDescriptor.getTags().orElse(personToEdit.getTags());
-
- return new Person(updatedName, updatedPhone, updatedEmail, updatedAddress, updatedTags);
- }
-
- @Override
- public boolean equals(Object other) {
- // short circuit if same object
- if (other == this) {
- return true;
- }
-
- // instanceof handles nulls
- if (!(other instanceof EditCommand)) {
- return false;
- }
-
- // state check
- EditCommand e = (EditCommand) other;
- return index.equals(e.index)
- && editPersonDescriptor.equals(e.editPersonDescriptor);
- }
-
- /**
- * Stores the details to edit the person with. Each non-empty field value will replace the
- * corresponding field value of the person.
- */
- public static class EditPersonDescriptor {
- private Name name;
- private Phone phone;
- private Email email;
- private Address address;
- private Set tags;
-
- public EditPersonDescriptor() {}
-
- /**
- * Copy constructor.
- * A defensive copy of {@code tags} is used internally.
- */
- public EditPersonDescriptor(EditPersonDescriptor toCopy) {
- setName(toCopy.name);
- setPhone(toCopy.phone);
- setEmail(toCopy.email);
- setAddress(toCopy.address);
- setTags(toCopy.tags);
- }
-
- /**
- * Returns true if at least one field is edited.
- */
- public boolean isAnyFieldEdited() {
- return CollectionUtil.isAnyNonNull(name, phone, email, address, tags);
- }
-
- public void setName(Name name) {
- this.name = name;
- }
-
- public Optional getName() {
- return Optional.ofNullable(name);
- }
-
- public void setPhone(Phone phone) {
- this.phone = phone;
- }
-
- public Optional getPhone() {
- return Optional.ofNullable(phone);
- }
-
- public void setEmail(Email email) {
- this.email = email;
- }
-
- public Optional getEmail() {
- return Optional.ofNullable(email);
- }
-
- public void setAddress(Address address) {
- this.address = address;
- }
-
- public Optional getAddress() {
- return Optional.ofNullable(address);
- }
-
- /**
- * Sets {@code tags} to this object's {@code tags}.
- * A defensive copy of {@code tags} is used internally.
- */
- public void setTags(Set tags) {
- this.tags = (tags != null) ? new HashSet<>(tags) : null;
- }
-
- /**
- * Returns an unmodifiable tag set, which throws {@code UnsupportedOperationException}
- * if modification is attempted.
- * Returns {@code Optional#empty()} if {@code tags} is null.
- */
- public Optional> getTags() {
- return (tags != null) ? Optional.of(Collections.unmodifiableSet(tags)) : Optional.empty();
- }
-
- @Override
- public boolean equals(Object other) {
- // short circuit if same object
- if (other == this) {
- return true;
- }
-
- // instanceof handles nulls
- if (!(other instanceof EditPersonDescriptor)) {
- return false;
- }
-
- // state check
- EditPersonDescriptor e = (EditPersonDescriptor) other;
-
- return getName().equals(e.getName())
- && getPhone().equals(e.getPhone())
- && getEmail().equals(e.getEmail())
- && getAddress().equals(e.getAddress())
- && getTags().equals(e.getTags());
- }
- }
-}
diff --git a/src/main/java/seedu/address/logic/commands/ExitCommand.java b/src/main/java/seedu/address/logic/commands/ExitCommand.java
deleted file mode 100644
index 3dd85a8ba90..00000000000
--- a/src/main/java/seedu/address/logic/commands/ExitCommand.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package seedu.address.logic.commands;
-
-import seedu.address.model.Model;
-
-/**
- * Terminates the program.
- */
-public class ExitCommand extends Command {
-
- public static final String COMMAND_WORD = "exit";
-
- public static final String MESSAGE_EXIT_ACKNOWLEDGEMENT = "Exiting Address Book as requested ...";
-
- @Override
- public CommandResult execute(Model model) {
- return new CommandResult(MESSAGE_EXIT_ACKNOWLEDGEMENT, false, true);
- }
-
-}
diff --git a/src/main/java/seedu/address/logic/commands/FindCommand.java b/src/main/java/seedu/address/logic/commands/FindCommand.java
deleted file mode 100644
index d6b19b0a0de..00000000000
--- a/src/main/java/seedu/address/logic/commands/FindCommand.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package seedu.address.logic.commands;
-
-import static java.util.Objects.requireNonNull;
-
-import seedu.address.commons.core.Messages;
-import seedu.address.model.Model;
-import seedu.address.model.person.NameContainsKeywordsPredicate;
-
-/**
- * Finds and lists all persons in address book whose name contains any of the argument keywords.
- * Keyword matching is case insensitive.
- */
-public class FindCommand extends Command {
-
- public static final String COMMAND_WORD = "find";
-
- public static final String MESSAGE_USAGE = COMMAND_WORD + ": Finds all persons whose names contain any of "
- + "the specified keywords (case-insensitive) and displays them as a list with index numbers.\n"
- + "Parameters: KEYWORD [MORE_KEYWORDS]...\n"
- + "Example: " + COMMAND_WORD + " alice bob charlie";
-
- private final NameContainsKeywordsPredicate predicate;
-
- public FindCommand(NameContainsKeywordsPredicate predicate) {
- this.predicate = predicate;
- }
-
- @Override
- public CommandResult execute(Model model) {
- requireNonNull(model);
- model.updateFilteredPersonList(predicate);
- return new CommandResult(
- String.format(Messages.MESSAGE_PERSONS_LISTED_OVERVIEW, model.getFilteredPersonList().size()));
- }
-
- @Override
- public boolean equals(Object other) {
- return other == this // short circuit if same object
- || (other instanceof FindCommand // instanceof handles nulls
- && predicate.equals(((FindCommand) other).predicate)); // state check
- }
-}
diff --git a/src/main/java/seedu/address/logic/commands/ListCommand.java b/src/main/java/seedu/address/logic/commands/ListCommand.java
deleted file mode 100644
index 84be6ad2596..00000000000
--- a/src/main/java/seedu/address/logic/commands/ListCommand.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package seedu.address.logic.commands;
-
-import static java.util.Objects.requireNonNull;
-import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS;
-
-import seedu.address.model.Model;
-
-/**
- * Lists all persons in the address book to the user.
- */
-public class ListCommand extends Command {
-
- public static final String COMMAND_WORD = "list";
-
- public static final String MESSAGE_SUCCESS = "Listed all persons";
-
-
- @Override
- public CommandResult execute(Model model) {
- requireNonNull(model);
- model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
- return new CommandResult(MESSAGE_SUCCESS);
- }
-}
diff --git a/src/main/java/seedu/address/logic/parser/AddCommandParser.java b/src/main/java/seedu/address/logic/parser/AddCommandParser.java
deleted file mode 100644
index 3b8bfa035e8..00000000000
--- a/src/main/java/seedu/address/logic/parser/AddCommandParser.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package seedu.address.logic.parser;
-
-import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
-
-import java.util.Set;
-import java.util.stream.Stream;
-
-import seedu.address.logic.commands.AddCommand;
-import seedu.address.logic.parser.exceptions.ParseException;
-import seedu.address.model.person.Address;
-import seedu.address.model.person.Email;
-import seedu.address.model.person.Name;
-import seedu.address.model.person.Person;
-import seedu.address.model.person.Phone;
-import seedu.address.model.tag.Tag;
-
-/**
- * Parses input arguments and creates a new AddCommand object
- */
-public class AddCommandParser implements Parser {
-
- /**
- * Parses the given {@code String} of arguments in the context of the AddCommand
- * and returns an AddCommand object for execution.
- * @throws ParseException if the user input does not conform the expected format
- */
- public AddCommand parse(String args) throws ParseException {
- ArgumentMultimap argMultimap =
- ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, PREFIX_TAG);
-
- if (!arePrefixesPresent(argMultimap, PREFIX_NAME, PREFIX_ADDRESS, PREFIX_PHONE, PREFIX_EMAIL)
- || !argMultimap.getPreamble().isEmpty()) {
- throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE));
- }
-
- Name name = ParserUtil.parseName(argMultimap.getValue(PREFIX_NAME).get());
- Phone phone = ParserUtil.parsePhone(argMultimap.getValue(PREFIX_PHONE).get());
- Email email = ParserUtil.parseEmail(argMultimap.getValue(PREFIX_EMAIL).get());
- Address address = ParserUtil.parseAddress(argMultimap.getValue(PREFIX_ADDRESS).get());
- Set tagList = ParserUtil.parseTags(argMultimap.getAllValues(PREFIX_TAG));
-
- Person person = new Person(name, phone, email, address, tagList);
-
- return new AddCommand(person);
- }
-
- /**
- * Returns true if none of the prefixes contains empty {@code Optional} values in the given
- * {@code ArgumentMultimap}.
- */
- private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) {
- return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent());
- }
-
-}
diff --git a/src/main/java/seedu/address/logic/parser/AddressBookParser.java b/src/main/java/seedu/address/logic/parser/AddressBookParser.java
deleted file mode 100644
index 1e466792b46..00000000000
--- a/src/main/java/seedu/address/logic/parser/AddressBookParser.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package seedu.address.logic.parser;
-
-import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
-import static seedu.address.commons.core.Messages.MESSAGE_UNKNOWN_COMMAND;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import seedu.address.logic.commands.AddCommand;
-import seedu.address.logic.commands.ClearCommand;
-import seedu.address.logic.commands.Command;
-import seedu.address.logic.commands.DeleteCommand;
-import seedu.address.logic.commands.EditCommand;
-import seedu.address.logic.commands.ExitCommand;
-import seedu.address.logic.commands.FindCommand;
-import seedu.address.logic.commands.HelpCommand;
-import seedu.address.logic.commands.ListCommand;
-import seedu.address.logic.parser.exceptions.ParseException;
-
-/**
- * Parses user input.
- */
-public class AddressBookParser {
-
- /**
- * Used for initial separation of command word and args.
- */
- private static final Pattern BASIC_COMMAND_FORMAT = Pattern.compile("(?\\S+)(?.*)");
-
- /**
- * Parses user input into command for execution.
- *
- * @param userInput full user input string
- * @return the command based on the user input
- * @throws ParseException if the user input does not conform the expected format
- */
- public Command parseCommand(String userInput) throws ParseException {
- final Matcher matcher = BASIC_COMMAND_FORMAT.matcher(userInput.trim());
- if (!matcher.matches()) {
- throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, HelpCommand.MESSAGE_USAGE));
- }
-
- final String commandWord = matcher.group("commandWord");
- final String arguments = matcher.group("arguments");
- switch (commandWord) {
-
- case AddCommand.COMMAND_WORD:
- return new AddCommandParser().parse(arguments);
-
- case EditCommand.COMMAND_WORD:
- return new EditCommandParser().parse(arguments);
-
- case DeleteCommand.COMMAND_WORD:
- return new DeleteCommandParser().parse(arguments);
-
- case ClearCommand.COMMAND_WORD:
- return new ClearCommand();
-
- case FindCommand.COMMAND_WORD:
- return new FindCommandParser().parse(arguments);
-
- case ListCommand.COMMAND_WORD:
- return new ListCommand();
-
- case ExitCommand.COMMAND_WORD:
- return new ExitCommand();
-
- case HelpCommand.COMMAND_WORD:
- return new HelpCommand();
-
- default:
- throw new ParseException(MESSAGE_UNKNOWN_COMMAND);
- }
- }
-
-}
diff --git a/src/main/java/seedu/address/logic/parser/CliSyntax.java b/src/main/java/seedu/address/logic/parser/CliSyntax.java
deleted file mode 100644
index 75b1a9bf119..00000000000
--- a/src/main/java/seedu/address/logic/parser/CliSyntax.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package seedu.address.logic.parser;
-
-/**
- * Contains Command Line Interface (CLI) syntax definitions common to multiple commands
- */
-public class CliSyntax {
-
- /* Prefix definitions */
- public static final Prefix PREFIX_NAME = new Prefix("n/");
- public static final Prefix PREFIX_PHONE = new Prefix("p/");
- public static final Prefix PREFIX_EMAIL = new Prefix("e/");
- public static final Prefix PREFIX_ADDRESS = new Prefix("a/");
- public static final Prefix PREFIX_TAG = new Prefix("t/");
-
-}
diff --git a/src/main/java/seedu/address/logic/parser/EditCommandParser.java b/src/main/java/seedu/address/logic/parser/EditCommandParser.java
deleted file mode 100644
index 845644b7dea..00000000000
--- a/src/main/java/seedu/address/logic/parser/EditCommandParser.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package seedu.address.logic.parser;
-
-import static java.util.Objects.requireNonNull;
-import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Optional;
-import java.util.Set;
-
-import seedu.address.commons.core.index.Index;
-import seedu.address.logic.commands.EditCommand;
-import seedu.address.logic.commands.EditCommand.EditPersonDescriptor;
-import seedu.address.logic.parser.exceptions.ParseException;
-import seedu.address.model.tag.Tag;
-
-/**
- * Parses input arguments and creates a new EditCommand object
- */
-public class EditCommandParser implements Parser {
-
- /**
- * Parses the given {@code String} of arguments in the context of the EditCommand
- * and returns an EditCommand object for execution.
- * @throws ParseException if the user input does not conform the expected format
- */
- public EditCommand parse(String args) throws ParseException {
- requireNonNull(args);
- ArgumentMultimap argMultimap =
- ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, PREFIX_TAG);
-
- Index index;
-
- try {
- index = ParserUtil.parseIndex(argMultimap.getPreamble());
- } catch (ParseException pe) {
- throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditCommand.MESSAGE_USAGE), pe);
- }
-
- EditPersonDescriptor editPersonDescriptor = new EditPersonDescriptor();
- if (argMultimap.getValue(PREFIX_NAME).isPresent()) {
- editPersonDescriptor.setName(ParserUtil.parseName(argMultimap.getValue(PREFIX_NAME).get()));
- }
- if (argMultimap.getValue(PREFIX_PHONE).isPresent()) {
- editPersonDescriptor.setPhone(ParserUtil.parsePhone(argMultimap.getValue(PREFIX_PHONE).get()));
- }
- if (argMultimap.getValue(PREFIX_EMAIL).isPresent()) {
- editPersonDescriptor.setEmail(ParserUtil.parseEmail(argMultimap.getValue(PREFIX_EMAIL).get()));
- }
- if (argMultimap.getValue(PREFIX_ADDRESS).isPresent()) {
- editPersonDescriptor.setAddress(ParserUtil.parseAddress(argMultimap.getValue(PREFIX_ADDRESS).get()));
- }
- parseTagsForEdit(argMultimap.getAllValues(PREFIX_TAG)).ifPresent(editPersonDescriptor::setTags);
-
- if (!editPersonDescriptor.isAnyFieldEdited()) {
- throw new ParseException(EditCommand.MESSAGE_NOT_EDITED);
- }
-
- return new EditCommand(index, editPersonDescriptor);
- }
-
- /**
- * Parses {@code Collection tags} into a {@code Set} if {@code tags} is non-empty.
- * If {@code tags} contain only one element which is an empty string, it will be parsed into a
- * {@code Set} containing zero tags.
- */
- private Optional> parseTagsForEdit(Collection tags) throws ParseException {
- assert tags != null;
-
- if (tags.isEmpty()) {
- return Optional.empty();
- }
- Collection tagSet = tags.size() == 1 && tags.contains("") ? Collections.emptySet() : tags;
- return Optional.of(ParserUtil.parseTags(tagSet));
- }
-
-}
diff --git a/src/main/java/seedu/address/logic/parser/FindCommandParser.java b/src/main/java/seedu/address/logic/parser/FindCommandParser.java
deleted file mode 100644
index 4fb71f23103..00000000000
--- a/src/main/java/seedu/address/logic/parser/FindCommandParser.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package seedu.address.logic.parser;
-
-import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
-
-import java.util.Arrays;
-
-import seedu.address.logic.commands.FindCommand;
-import seedu.address.logic.parser.exceptions.ParseException;
-import seedu.address.model.person.NameContainsKeywordsPredicate;
-
-/**
- * Parses input arguments and creates a new FindCommand object
- */
-public class FindCommandParser implements Parser {
-
- /**
- * Parses the given {@code String} of arguments in the context of the FindCommand
- * and returns a FindCommand object for execution.
- * @throws ParseException if the user input does not conform the expected format
- */
- public FindCommand parse(String args) throws ParseException {
- String trimmedArgs = args.trim();
- if (trimmedArgs.isEmpty()) {
- throw new ParseException(
- String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_USAGE));
- }
-
- String[] nameKeywords = trimmedArgs.split("\\s+");
-
- return new FindCommand(new NameContainsKeywordsPredicate(Arrays.asList(nameKeywords)));
- }
-
-}
diff --git a/src/main/java/seedu/address/logic/parser/ParserUtil.java b/src/main/java/seedu/address/logic/parser/ParserUtil.java
deleted file mode 100644
index b117acb9c55..00000000000
--- a/src/main/java/seedu/address/logic/parser/ParserUtil.java
+++ /dev/null
@@ -1,124 +0,0 @@
-package seedu.address.logic.parser;
-
-import static java.util.Objects.requireNonNull;
-
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Set;
-
-import seedu.address.commons.core.index.Index;
-import seedu.address.commons.util.StringUtil;
-import seedu.address.logic.parser.exceptions.ParseException;
-import seedu.address.model.person.Address;
-import seedu.address.model.person.Email;
-import seedu.address.model.person.Name;
-import seedu.address.model.person.Phone;
-import seedu.address.model.tag.Tag;
-
-/**
- * Contains utility methods used for parsing strings in the various *Parser classes.
- */
-public class ParserUtil {
-
- public static final String MESSAGE_INVALID_INDEX = "Index is not a non-zero unsigned integer.";
-
- /**
- * Parses {@code oneBasedIndex} into an {@code Index} and returns it. Leading and trailing whitespaces will be
- * trimmed.
- * @throws ParseException if the specified index is invalid (not non-zero unsigned integer).
- */
- public static Index parseIndex(String oneBasedIndex) throws ParseException {
- String trimmedIndex = oneBasedIndex.trim();
- if (!StringUtil.isNonZeroUnsignedInteger(trimmedIndex)) {
- throw new ParseException(MESSAGE_INVALID_INDEX);
- }
- return Index.fromOneBased(Integer.parseInt(trimmedIndex));
- }
-
- /**
- * Parses a {@code String name} into a {@code Name}.
- * Leading and trailing whitespaces will be trimmed.
- *
- * @throws ParseException if the given {@code name} is invalid.
- */
- public static Name parseName(String name) throws ParseException {
- requireNonNull(name);
- String trimmedName = name.trim();
- if (!Name.isValidName(trimmedName)) {
- throw new ParseException(Name.MESSAGE_CONSTRAINTS);
- }
- return new Name(trimmedName);
- }
-
- /**
- * Parses a {@code String phone} into a {@code Phone}.
- * Leading and trailing whitespaces will be trimmed.
- *
- * @throws ParseException if the given {@code phone} is invalid.
- */
- public static Phone parsePhone(String phone) throws ParseException {
- requireNonNull(phone);
- String trimmedPhone = phone.trim();
- if (!Phone.isValidPhone(trimmedPhone)) {
- throw new ParseException(Phone.MESSAGE_CONSTRAINTS);
- }
- return new Phone(trimmedPhone);
- }
-
- /**
- * Parses a {@code String address} into an {@code Address}.
- * Leading and trailing whitespaces will be trimmed.
- *
- * @throws ParseException if the given {@code address} is invalid.
- */
- public static Address parseAddress(String address) throws ParseException {
- requireNonNull(address);
- String trimmedAddress = address.trim();
- if (!Address.isValidAddress(trimmedAddress)) {
- throw new ParseException(Address.MESSAGE_CONSTRAINTS);
- }
- return new Address(trimmedAddress);
- }
-
- /**
- * Parses a {@code String email} into an {@code Email}.
- * Leading and trailing whitespaces will be trimmed.
- *
- * @throws ParseException if the given {@code email} is invalid.
- */
- public static Email parseEmail(String email) throws ParseException {
- requireNonNull(email);
- String trimmedEmail = email.trim();
- if (!Email.isValidEmail(trimmedEmail)) {
- throw new ParseException(Email.MESSAGE_CONSTRAINTS);
- }
- return new Email(trimmedEmail);
- }
-
- /**
- * Parses a {@code String tag} into a {@code Tag}.
- * Leading and trailing whitespaces will be trimmed.
- *
- * @throws ParseException if the given {@code tag} is invalid.
- */
- public static Tag parseTag(String tag) throws ParseException {
- requireNonNull(tag);
- String trimmedTag = tag.trim();
- if (!Tag.isValidTagName(trimmedTag)) {
- throw new ParseException(Tag.MESSAGE_CONSTRAINTS);
- }
- return new Tag(trimmedTag);
- }
-
- /**
- * Parses {@code Collection tags} into a {@code Set}.
- */
- public static Set parseTags(Collection tags) throws ParseException {
- requireNonNull(tags);
- final Set tagSet = new HashSet<>();
- for (String tagName : tags) {
- tagSet.add(parseTag(tagName));
- }
- return tagSet;
- }
-}
diff --git a/src/main/java/seedu/address/model/AddressBook.java b/src/main/java/seedu/address/model/AddressBook.java
deleted file mode 100644
index 1a943a0781a..00000000000
--- a/src/main/java/seedu/address/model/AddressBook.java
+++ /dev/null
@@ -1,120 +0,0 @@
-package seedu.address.model;
-
-import static java.util.Objects.requireNonNull;
-
-import java.util.List;
-
-import javafx.collections.ObservableList;
-import seedu.address.model.person.Person;
-import seedu.address.model.person.UniquePersonList;
-
-/**
- * Wraps all data at the address-book level
- * Duplicates are not allowed (by .isSamePerson comparison)
- */
-public class AddressBook implements ReadOnlyAddressBook {
-
- private final UniquePersonList persons;
-
- /*
- * The 'unusual' code block below is a non-static initialization block, sometimes used to avoid duplication
- * between constructors. See https://docs.oracle.com/javase/tutorial/java/javaOO/initial.html
- *
- * Note that non-static init blocks are not recommended to use. There are other ways to avoid duplication
- * among constructors.
- */
- {
- persons = new UniquePersonList();
- }
-
- public AddressBook() {}
-
- /**
- * Creates an AddressBook using the Persons in the {@code toBeCopied}
- */
- public AddressBook(ReadOnlyAddressBook toBeCopied) {
- this();
- resetData(toBeCopied);
- }
-
- //// list overwrite operations
-
- /**
- * Replaces the contents of the person list with {@code persons}.
- * {@code persons} must not contain duplicate persons.
- */
- public void setPersons(List persons) {
- this.persons.setPersons(persons);
- }
-
- /**
- * Resets the existing data of this {@code AddressBook} with {@code newData}.
- */
- public void resetData(ReadOnlyAddressBook newData) {
- requireNonNull(newData);
-
- setPersons(newData.getPersonList());
- }
-
- //// person-level operations
-
- /**
- * Returns true if a person with the same identity as {@code person} exists in the address book.
- */
- public boolean hasPerson(Person person) {
- requireNonNull(person);
- return persons.contains(person);
- }
-
- /**
- * Adds a person to the address book.
- * The person must not already exist in the address book.
- */
- public void addPerson(Person p) {
- persons.add(p);
- }
-
- /**
- * Replaces the given person {@code target} in the list with {@code editedPerson}.
- * {@code target} must exist in the address book.
- * The person identity of {@code editedPerson} must not be the same as another existing person in the address book.
- */
- public void setPerson(Person target, Person editedPerson) {
- requireNonNull(editedPerson);
-
- persons.setPerson(target, editedPerson);
- }
-
- /**
- * Removes {@code key} from this {@code AddressBook}.
- * {@code key} must exist in the address book.
- */
- public void removePerson(Person key) {
- persons.remove(key);
- }
-
- //// util methods
-
- @Override
- public String toString() {
- return persons.asUnmodifiableObservableList().size() + " persons";
- // TODO: refine later
- }
-
- @Override
- public ObservableList getPersonList() {
- return persons.asUnmodifiableObservableList();
- }
-
- @Override
- public boolean equals(Object other) {
- return other == this // short circuit if same object
- || (other instanceof AddressBook // instanceof handles nulls
- && persons.equals(((AddressBook) other).persons));
- }
-
- @Override
- public int hashCode() {
- return persons.hashCode();
- }
-}
diff --git a/src/main/java/seedu/address/model/Model.java b/src/main/java/seedu/address/model/Model.java
deleted file mode 100644
index d54df471c1f..00000000000
--- a/src/main/java/seedu/address/model/Model.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package seedu.address.model;
-
-import java.nio.file.Path;
-import java.util.function.Predicate;
-
-import javafx.collections.ObservableList;
-import seedu.address.commons.core.GuiSettings;
-import seedu.address.model.person.Person;
-
-/**
- * The API of the Model component.
- */
-public interface Model {
- /** {@code Predicate} that always evaluate to true */
- Predicate PREDICATE_SHOW_ALL_PERSONS = unused -> true;
-
- /**
- * Replaces user prefs data with the data in {@code userPrefs}.
- */
- void setUserPrefs(ReadOnlyUserPrefs userPrefs);
-
- /**
- * Returns the user prefs.
- */
- ReadOnlyUserPrefs getUserPrefs();
-
- /**
- * Returns the user prefs' GUI settings.
- */
- GuiSettings getGuiSettings();
-
- /**
- * Sets the user prefs' GUI settings.
- */
- void setGuiSettings(GuiSettings guiSettings);
-
- /**
- * Returns the user prefs' address book file path.
- */
- Path getAddressBookFilePath();
-
- /**
- * Sets the user prefs' address book file path.
- */
- void setAddressBookFilePath(Path addressBookFilePath);
-
- /**
- * Replaces address book data with the data in {@code addressBook}.
- */
- void setAddressBook(ReadOnlyAddressBook addressBook);
-
- /** Returns the AddressBook */
- ReadOnlyAddressBook getAddressBook();
-
- /**
- * Returns true if a person with the same identity as {@code person} exists in the address book.
- */
- boolean hasPerson(Person person);
-
- /**
- * Deletes the given person.
- * The person must exist in the address book.
- */
- void deletePerson(Person target);
-
- /**
- * Adds the given person.
- * {@code person} must not already exist in the address book.
- */
- void addPerson(Person person);
-
- /**
- * Replaces the given person {@code target} with {@code editedPerson}.
- * {@code target} must exist in the address book.
- * The person identity of {@code editedPerson} must not be the same as another existing person in the address book.
- */
- void setPerson(Person target, Person editedPerson);
-
- /** Returns an unmodifiable view of the filtered person list */
- ObservableList getFilteredPersonList();
-
- /**
- * Updates the filter of the filtered person list to filter by the given {@code predicate}.
- * @throws NullPointerException if {@code predicate} is null.
- */
- void updateFilteredPersonList(Predicate predicate);
-}
diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java
deleted file mode 100644
index 86c1df298d7..00000000000
--- a/src/main/java/seedu/address/model/ModelManager.java
+++ /dev/null
@@ -1,150 +0,0 @@
-package seedu.address.model;
-
-import static java.util.Objects.requireNonNull;
-import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
-
-import java.nio.file.Path;
-import java.util.function.Predicate;
-import java.util.logging.Logger;
-
-import javafx.collections.ObservableList;
-import javafx.collections.transformation.FilteredList;
-import seedu.address.commons.core.GuiSettings;
-import seedu.address.commons.core.LogsCenter;
-import seedu.address.model.person.Person;
-
-/**
- * Represents the in-memory model of the address book data.
- */
-public class ModelManager implements Model {
- private static final Logger logger = LogsCenter.getLogger(ModelManager.class);
-
- private final AddressBook addressBook;
- private final UserPrefs userPrefs;
- private final FilteredList filteredPersons;
-
- /**
- * Initializes a ModelManager with the given addressBook and userPrefs.
- */
- public ModelManager(ReadOnlyAddressBook addressBook, ReadOnlyUserPrefs userPrefs) {
- requireAllNonNull(addressBook, userPrefs);
-
- logger.fine("Initializing with address book: " + addressBook + " and user prefs " + userPrefs);
-
- this.addressBook = new AddressBook(addressBook);
- this.userPrefs = new UserPrefs(userPrefs);
- filteredPersons = new FilteredList<>(this.addressBook.getPersonList());
- }
-
- public ModelManager() {
- this(new AddressBook(), new UserPrefs());
- }
-
- //=========== UserPrefs ==================================================================================
-
- @Override
- public void setUserPrefs(ReadOnlyUserPrefs userPrefs) {
- requireNonNull(userPrefs);
- this.userPrefs.resetData(userPrefs);
- }
-
- @Override
- public ReadOnlyUserPrefs getUserPrefs() {
- return userPrefs;
- }
-
- @Override
- public GuiSettings getGuiSettings() {
- return userPrefs.getGuiSettings();
- }
-
- @Override
- public void setGuiSettings(GuiSettings guiSettings) {
- requireNonNull(guiSettings);
- userPrefs.setGuiSettings(guiSettings);
- }
-
- @Override
- public Path getAddressBookFilePath() {
- return userPrefs.getAddressBookFilePath();
- }
-
- @Override
- public void setAddressBookFilePath(Path addressBookFilePath) {
- requireNonNull(addressBookFilePath);
- userPrefs.setAddressBookFilePath(addressBookFilePath);
- }
-
- //=========== AddressBook ================================================================================
-
- @Override
- public void setAddressBook(ReadOnlyAddressBook addressBook) {
- this.addressBook.resetData(addressBook);
- }
-
- @Override
- public ReadOnlyAddressBook getAddressBook() {
- return addressBook;
- }
-
- @Override
- public boolean hasPerson(Person person) {
- requireNonNull(person);
- return addressBook.hasPerson(person);
- }
-
- @Override
- public void deletePerson(Person target) {
- addressBook.removePerson(target);
- }
-
- @Override
- public void addPerson(Person person) {
- addressBook.addPerson(person);
- updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
- }
-
- @Override
- public void setPerson(Person target, Person editedPerson) {
- requireAllNonNull(target, editedPerson);
-
- addressBook.setPerson(target, editedPerson);
- }
-
- //=========== Filtered Person List Accessors =============================================================
-
- /**
- * Returns an unmodifiable view of the list of {@code Person} backed by the internal list of
- * {@code versionedAddressBook}
- */
- @Override
- public ObservableList getFilteredPersonList() {
- return filteredPersons;
- }
-
- @Override
- public void updateFilteredPersonList(Predicate predicate) {
- requireNonNull(predicate);
- filteredPersons.setPredicate(predicate);
- }
-
- @Override
- public boolean equals(Object obj) {
- // short circuit if same object
- if (obj == this) {
- return true;
- }
-
- // instanceof handles nulls
- if (!(obj instanceof ModelManager)) {
- return false;
- }
-
- // state check
- ModelManager other = (ModelManager) obj;
- return addressBook.equals(other.addressBook)
- && userPrefs.equals(other.userPrefs)
- && filteredPersons.equals(other.filteredPersons);
- }
-
-}
diff --git a/src/main/java/seedu/address/model/ReadOnlyAddressBook.java b/src/main/java/seedu/address/model/ReadOnlyAddressBook.java
deleted file mode 100644
index 6ddc2cd9a29..00000000000
--- a/src/main/java/seedu/address/model/ReadOnlyAddressBook.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package seedu.address.model;
-
-import javafx.collections.ObservableList;
-import seedu.address.model.person.Person;
-
-/**
- * Unmodifiable view of an address book
- */
-public interface ReadOnlyAddressBook {
-
- /**
- * Returns an unmodifiable view of the persons list.
- * This list will not contain any duplicate persons.
- */
- ObservableList getPersonList();
-
-}
diff --git a/src/main/java/seedu/address/model/person/Address.java b/src/main/java/seedu/address/model/person/Address.java
deleted file mode 100644
index 60472ca22a0..00000000000
--- a/src/main/java/seedu/address/model/person/Address.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package seedu.address.model.person;
-
-import static java.util.Objects.requireNonNull;
-import static seedu.address.commons.util.AppUtil.checkArgument;
-
-/**
- * Represents a Person's address in the address book.
- * Guarantees: immutable; is valid as declared in {@link #isValidAddress(String)}
- */
-public class Address {
-
- public static final String MESSAGE_CONSTRAINTS = "Addresses can take any values, and it should not be blank";
-
- /*
- * The first character of the address must not be a whitespace,
- * otherwise " " (a blank string) becomes a valid input.
- */
- public static final String VALIDATION_REGEX = "[^\\s].*";
-
- public final String value;
-
- /**
- * Constructs an {@code Address}.
- *
- * @param address A valid address.
- */
- public Address(String address) {
- requireNonNull(address);
- checkArgument(isValidAddress(address), MESSAGE_CONSTRAINTS);
- value = address;
- }
-
- /**
- * Returns true if a given string is a valid email.
- */
- public static boolean isValidAddress(String test) {
- return test.matches(VALIDATION_REGEX);
- }
-
- @Override
- public String toString() {
- return value;
- }
-
- @Override
- public boolean equals(Object other) {
- return other == this // short circuit if same object
- || (other instanceof Address // instanceof handles nulls
- && value.equals(((Address) other).value)); // state check
- }
-
- @Override
- public int hashCode() {
- return value.hashCode();
- }
-
-}
diff --git a/src/main/java/seedu/address/model/person/Email.java b/src/main/java/seedu/address/model/person/Email.java
deleted file mode 100644
index f866e7133de..00000000000
--- a/src/main/java/seedu/address/model/person/Email.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package seedu.address.model.person;
-
-import static java.util.Objects.requireNonNull;
-import static seedu.address.commons.util.AppUtil.checkArgument;
-
-/**
- * Represents a Person's email in the address book.
- * Guarantees: immutable; is valid as declared in {@link #isValidEmail(String)}
- */
-public class Email {
-
- private static final String SPECIAL_CHARACTERS = "+_.-";
- public static final String MESSAGE_CONSTRAINTS = "Emails should be of the format local-part@domain "
- + "and adhere to the following constraints:\n"
- + "1. The local-part should only contain alphanumeric characters and these special characters, excluding "
- + "the parentheses, (" + SPECIAL_CHARACTERS + "). The local-part may not start or end with any special "
- + "characters.\n"
- + "2. This is followed by a '@' and then a domain name. The domain name is made up of domain labels "
- + "separated by periods.\n"
- + "The domain name must:\n"
- + " - end with a domain label at least 2 characters long\n"
- + " - have each domain label start and end with alphanumeric characters\n"
- + " - have each domain label consist of alphanumeric characters, separated only by hyphens, if any.";
- // alphanumeric and special characters
- private static final String ALPHANUMERIC_NO_UNDERSCORE = "[^\\W_]+"; // alphanumeric characters except underscore
- private static final String LOCAL_PART_REGEX = "^" + ALPHANUMERIC_NO_UNDERSCORE + "([" + SPECIAL_CHARACTERS + "]"
- + ALPHANUMERIC_NO_UNDERSCORE + ")*";
- private static final String DOMAIN_PART_REGEX = ALPHANUMERIC_NO_UNDERSCORE
- + "(-" + ALPHANUMERIC_NO_UNDERSCORE + ")*";
- private static final String DOMAIN_LAST_PART_REGEX = "(" + DOMAIN_PART_REGEX + "){2,}$"; // At least two chars
- private static final String DOMAIN_REGEX = "(" + DOMAIN_PART_REGEX + "\\.)*" + DOMAIN_LAST_PART_REGEX;
- public static final String VALIDATION_REGEX = LOCAL_PART_REGEX + "@" + DOMAIN_REGEX;
-
- public final String value;
-
- /**
- * Constructs an {@code Email}.
- *
- * @param email A valid email address.
- */
- public Email(String email) {
- requireNonNull(email);
- checkArgument(isValidEmail(email), MESSAGE_CONSTRAINTS);
- value = email;
- }
-
- /**
- * Returns if a given string is a valid email.
- */
- public static boolean isValidEmail(String test) {
- return test.matches(VALIDATION_REGEX);
- }
-
- @Override
- public String toString() {
- return value;
- }
-
- @Override
- public boolean equals(Object other) {
- return other == this // short circuit if same object
- || (other instanceof Email // instanceof handles nulls
- && value.equals(((Email) other).value)); // state check
- }
-
- @Override
- public int hashCode() {
- return value.hashCode();
- }
-
-}
diff --git a/src/main/java/seedu/address/model/person/Person.java b/src/main/java/seedu/address/model/person/Person.java
deleted file mode 100644
index 8ff1d83fe89..00000000000
--- a/src/main/java/seedu/address/model/person/Person.java
+++ /dev/null
@@ -1,123 +0,0 @@
-package seedu.address.model.person;
-
-import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
-
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Objects;
-import java.util.Set;
-
-import seedu.address.model.tag.Tag;
-
-/**
- * Represents a Person in the address book.
- * Guarantees: details are present and not null, field values are validated, immutable.
- */
-public class Person {
-
- // Identity fields
- private final Name name;
- private final Phone phone;
- private final Email email;
-
- // Data fields
- private final Address address;
- private final Set tags = new HashSet<>();
-
- /**
- * Every field must be present and not null.
- */
- public Person(Name name, Phone phone, Email email, Address address, Set tags) {
- requireAllNonNull(name, phone, email, address, tags);
- this.name = name;
- this.phone = phone;
- this.email = email;
- this.address = address;
- this.tags.addAll(tags);
- }
-
- public Name getName() {
- return name;
- }
-
- public Phone getPhone() {
- return phone;
- }
-
- public Email getEmail() {
- return email;
- }
-
- public Address getAddress() {
- return address;
- }
-
- /**
- * Returns an immutable tag set, which throws {@code UnsupportedOperationException}
- * if modification is attempted.
- */
- public Set getTags() {
- return Collections.unmodifiableSet(tags);
- }
-
- /**
- * Returns true if both persons have the same name.
- * This defines a weaker notion of equality between two persons.
- */
- public boolean isSamePerson(Person otherPerson) {
- if (otherPerson == this) {
- return true;
- }
-
- return otherPerson != null
- && otherPerson.getName().equals(getName());
- }
-
- /**
- * Returns true if both persons have the same identity and data fields.
- * This defines a stronger notion of equality between two persons.
- */
- @Override
- public boolean equals(Object other) {
- if (other == this) {
- return true;
- }
-
- if (!(other instanceof Person)) {
- return false;
- }
-
- Person otherPerson = (Person) other;
- return otherPerson.getName().equals(getName())
- && otherPerson.getPhone().equals(getPhone())
- && otherPerson.getEmail().equals(getEmail())
- && otherPerson.getAddress().equals(getAddress())
- && otherPerson.getTags().equals(getTags());
- }
-
- @Override
- public int hashCode() {
- // use this method for custom fields hashing instead of implementing your own
- return Objects.hash(name, phone, email, address, tags);
- }
-
- @Override
- public String toString() {
- final StringBuilder builder = new StringBuilder();
- builder.append(getName())
- .append("; Phone: ")
- .append(getPhone())
- .append("; Email: ")
- .append(getEmail())
- .append("; Address: ")
- .append(getAddress());
-
- Set tags = getTags();
- if (!tags.isEmpty()) {
- builder.append("; Tags: ");
- tags.forEach(builder::append);
- }
- return builder.toString();
- }
-
-}
diff --git a/src/main/java/seedu/address/model/person/Phone.java b/src/main/java/seedu/address/model/person/Phone.java
deleted file mode 100644
index 872c76b382f..00000000000
--- a/src/main/java/seedu/address/model/person/Phone.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package seedu.address.model.person;
-
-import static java.util.Objects.requireNonNull;
-import static seedu.address.commons.util.AppUtil.checkArgument;
-
-/**
- * Represents a Person's phone number in the address book.
- * Guarantees: immutable; is valid as declared in {@link #isValidPhone(String)}
- */
-public class Phone {
-
-
- public static final String MESSAGE_CONSTRAINTS =
- "Phone numbers should only contain numbers, and it should be at least 3 digits long";
- public static final String VALIDATION_REGEX = "\\d{3,}";
- public final String value;
-
- /**
- * Constructs a {@code Phone}.
- *
- * @param phone A valid phone number.
- */
- public Phone(String phone) {
- requireNonNull(phone);
- checkArgument(isValidPhone(phone), MESSAGE_CONSTRAINTS);
- value = phone;
- }
-
- /**
- * Returns true if a given string is a valid phone number.
- */
- public static boolean isValidPhone(String test) {
- return test.matches(VALIDATION_REGEX);
- }
-
- @Override
- public String toString() {
- return value;
- }
-
- @Override
- public boolean equals(Object other) {
- return other == this // short circuit if same object
- || (other instanceof Phone // instanceof handles nulls
- && value.equals(((Phone) other).value)); // state check
- }
-
- @Override
- public int hashCode() {
- return value.hashCode();
- }
-
-}
diff --git a/src/main/java/seedu/address/model/person/UniquePersonList.java b/src/main/java/seedu/address/model/person/UniquePersonList.java
deleted file mode 100644
index 0fee4fe57e6..00000000000
--- a/src/main/java/seedu/address/model/person/UniquePersonList.java
+++ /dev/null
@@ -1,137 +0,0 @@
-package seedu.address.model.person;
-
-import static java.util.Objects.requireNonNull;
-import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
-
-import java.util.Iterator;
-import java.util.List;
-
-import javafx.collections.FXCollections;
-import javafx.collections.ObservableList;
-import seedu.address.model.person.exceptions.DuplicatePersonException;
-import seedu.address.model.person.exceptions.PersonNotFoundException;
-
-/**
- * A list of persons that enforces uniqueness between its elements and does not allow nulls.
- * A person is considered unique by comparing using {@code Person#isSamePerson(Person)}. As such, adding and updating of
- * persons uses Person#isSamePerson(Person) for equality so as to ensure that the person being added or updated is
- * unique in terms of identity in the UniquePersonList. However, the removal of a person uses Person#equals(Object) so
- * as to ensure that the person with exactly the same fields will be removed.
- *
- * Supports a minimal set of list operations.
- *
- * @see Person#isSamePerson(Person)
- */
-public class UniquePersonList implements Iterable {
-
- private final ObservableList internalList = FXCollections.observableArrayList();
- private final ObservableList internalUnmodifiableList =
- FXCollections.unmodifiableObservableList(internalList);
-
- /**
- * Returns true if the list contains an equivalent person as the given argument.
- */
- public boolean contains(Person toCheck) {
- requireNonNull(toCheck);
- return internalList.stream().anyMatch(toCheck::isSamePerson);
- }
-
- /**
- * Adds a person to the list.
- * The person must not already exist in the list.
- */
- public void add(Person toAdd) {
- requireNonNull(toAdd);
- if (contains(toAdd)) {
- throw new DuplicatePersonException();
- }
- internalList.add(toAdd);
- }
-
- /**
- * Replaces the person {@code target} in the list with {@code editedPerson}.
- * {@code target} must exist in the list.
- * The person identity of {@code editedPerson} must not be the same as another existing person in the list.
- */
- public void setPerson(Person target, Person editedPerson) {
- requireAllNonNull(target, editedPerson);
-
- int index = internalList.indexOf(target);
- if (index == -1) {
- throw new PersonNotFoundException();
- }
-
- if (!target.isSamePerson(editedPerson) && contains(editedPerson)) {
- throw new DuplicatePersonException();
- }
-
- internalList.set(index, editedPerson);
- }
-
- /**
- * Removes the equivalent person from the list.
- * The person must exist in the list.
- */
- public void remove(Person toRemove) {
- requireNonNull(toRemove);
- if (!internalList.remove(toRemove)) {
- throw new PersonNotFoundException();
- }
- }
-
- public void setPersons(UniquePersonList replacement) {
- requireNonNull(replacement);
- internalList.setAll(replacement.internalList);
- }
-
- /**
- * Replaces the contents of this list with {@code persons}.
- * {@code persons} must not contain duplicate persons.
- */
- public void setPersons(List persons) {
- requireAllNonNull(persons);
- if (!personsAreUnique(persons)) {
- throw new DuplicatePersonException();
- }
-
- internalList.setAll(persons);
- }
-
- /**
- * Returns the backing list as an unmodifiable {@code ObservableList}.
- */
- public ObservableList asUnmodifiableObservableList() {
- return internalUnmodifiableList;
- }
-
- @Override
- public Iterator iterator() {
- return internalList.iterator();
- }
-
- @Override
- public boolean equals(Object other) {
- return other == this // short circuit if same object
- || (other instanceof UniquePersonList // instanceof handles nulls
- && internalList.equals(((UniquePersonList) other).internalList));
- }
-
- @Override
- public int hashCode() {
- return internalList.hashCode();
- }
-
- /**
- * Returns true if {@code persons} contains only unique persons.
- */
- private boolean personsAreUnique(List persons) {
- for (int i = 0; i < persons.size() - 1; i++) {
- for (int j = i + 1; j < persons.size(); j++) {
- if (persons.get(i).isSamePerson(persons.get(j))) {
- return false;
- }
- }
- }
- return true;
- }
-}
diff --git a/src/main/java/seedu/address/model/person/exceptions/DuplicatePersonException.java b/src/main/java/seedu/address/model/person/exceptions/DuplicatePersonException.java
deleted file mode 100644
index d7290f59442..00000000000
--- a/src/main/java/seedu/address/model/person/exceptions/DuplicatePersonException.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package seedu.address.model.person.exceptions;
-
-/**
- * Signals that the operation will result in duplicate Persons (Persons are considered duplicates if they have the same
- * identity).
- */
-public class DuplicatePersonException extends RuntimeException {
- public DuplicatePersonException() {
- super("Operation would result in duplicate persons");
- }
-}
diff --git a/src/main/java/seedu/address/model/person/exceptions/PersonNotFoundException.java b/src/main/java/seedu/address/model/person/exceptions/PersonNotFoundException.java
deleted file mode 100644
index fa764426ca7..00000000000
--- a/src/main/java/seedu/address/model/person/exceptions/PersonNotFoundException.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package seedu.address.model.person.exceptions;
-
-/**
- * Signals that the operation is unable to find the specified person.
- */
-public class PersonNotFoundException extends RuntimeException {}
diff --git a/src/main/java/seedu/address/model/tag/Tag.java b/src/main/java/seedu/address/model/tag/Tag.java
deleted file mode 100644
index b0ea7e7dad7..00000000000
--- a/src/main/java/seedu/address/model/tag/Tag.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package seedu.address.model.tag;
-
-import static java.util.Objects.requireNonNull;
-import static seedu.address.commons.util.AppUtil.checkArgument;
-
-/**
- * Represents a Tag in the address book.
- * Guarantees: immutable; name is valid as declared in {@link #isValidTagName(String)}
- */
-public class Tag {
-
- public static final String MESSAGE_CONSTRAINTS = "Tags names should be alphanumeric";
- public static final String VALIDATION_REGEX = "\\p{Alnum}+";
-
- public final String tagName;
-
- /**
- * Constructs a {@code Tag}.
- *
- * @param tagName A valid tag name.
- */
- public Tag(String tagName) {
- requireNonNull(tagName);
- checkArgument(isValidTagName(tagName), MESSAGE_CONSTRAINTS);
- this.tagName = tagName;
- }
-
- /**
- * Returns true if a given string is a valid tag name.
- */
- public static boolean isValidTagName(String test) {
- return test.matches(VALIDATION_REGEX);
- }
-
- @Override
- public boolean equals(Object other) {
- return other == this // short circuit if same object
- || (other instanceof Tag // instanceof handles nulls
- && tagName.equals(((Tag) other).tagName)); // state check
- }
-
- @Override
- public int hashCode() {
- return tagName.hashCode();
- }
-
- /**
- * Format state as text for viewing.
- */
- public String toString() {
- return '[' + tagName + ']';
- }
-
-}
diff --git a/src/main/java/seedu/address/model/util/SampleDataUtil.java b/src/main/java/seedu/address/model/util/SampleDataUtil.java
deleted file mode 100644
index 1806da4facf..00000000000
--- a/src/main/java/seedu/address/model/util/SampleDataUtil.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package seedu.address.model.util;
-
-import java.util.Arrays;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import seedu.address.model.AddressBook;
-import seedu.address.model.ReadOnlyAddressBook;
-import seedu.address.model.person.Address;
-import seedu.address.model.person.Email;
-import seedu.address.model.person.Name;
-import seedu.address.model.person.Person;
-import seedu.address.model.person.Phone;
-import seedu.address.model.tag.Tag;
-
-/**
- * Contains utility methods for populating {@code AddressBook} with sample data.
- */
-public class SampleDataUtil {
- public static Person[] getSamplePersons() {
- return new Person[] {
- new Person(new Name("Alex Yeoh"), new Phone("87438807"), new Email("alexyeoh@example.com"),
- new Address("Blk 30 Geylang Street 29, #06-40"),
- getTagSet("friends")),
- new Person(new Name("Bernice Yu"), new Phone("99272758"), new Email("berniceyu@example.com"),
- new Address("Blk 30 Lorong 3 Serangoon Gardens, #07-18"),
- getTagSet("colleagues", "friends")),
- new Person(new Name("Charlotte Oliveiro"), new Phone("93210283"), new Email("charlotte@example.com"),
- new Address("Blk 11 Ang Mo Kio Street 74, #11-04"),
- getTagSet("neighbours")),
- new Person(new Name("David Li"), new Phone("91031282"), new Email("lidavid@example.com"),
- new Address("Blk 436 Serangoon Gardens Street 26, #16-43"),
- getTagSet("family")),
- new Person(new Name("Irfan Ibrahim"), new Phone("92492021"), new Email("irfan@example.com"),
- new Address("Blk 47 Tampines Street 20, #17-35"),
- getTagSet("classmates")),
- new Person(new Name("Roy Balakrishnan"), new Phone("92624417"), new Email("royb@example.com"),
- new Address("Blk 45 Aljunied Street 85, #11-31"),
- getTagSet("colleagues"))
- };
- }
-
- public static ReadOnlyAddressBook getSampleAddressBook() {
- AddressBook sampleAb = new AddressBook();
- for (Person samplePerson : getSamplePersons()) {
- sampleAb.addPerson(samplePerson);
- }
- return sampleAb;
- }
-
- /**
- * Returns a tag set containing the list of strings given.
- */
- public static Set getTagSet(String... strings) {
- return Arrays.stream(strings)
- .map(Tag::new)
- .collect(Collectors.toSet());
- }
-
-}
diff --git a/src/main/java/seedu/address/storage/AddressBookStorage.java b/src/main/java/seedu/address/storage/AddressBookStorage.java
deleted file mode 100644
index 4599182b3f9..00000000000
--- a/src/main/java/seedu/address/storage/AddressBookStorage.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package seedu.address.storage;
-
-import java.io.IOException;
-import java.nio.file.Path;
-import java.util.Optional;
-
-import seedu.address.commons.exceptions.DataConversionException;
-import seedu.address.model.ReadOnlyAddressBook;
-
-/**
- * Represents a storage for {@link seedu.address.model.AddressBook}.
- */
-public interface AddressBookStorage {
-
- /**
- * Returns the file path of the data file.
- */
- Path getAddressBookFilePath();
-
- /**
- * Returns AddressBook data as a {@link ReadOnlyAddressBook}.
- * Returns {@code Optional.empty()} if storage file is not found.
- * @throws DataConversionException if the data in storage is not in the expected format.
- * @throws IOException if there was any problem when reading from the storage.
- */
- Optional readAddressBook() throws DataConversionException, IOException;
-
- /**
- * @see #getAddressBookFilePath()
- */
- Optional readAddressBook(Path filePath) throws DataConversionException, IOException;
-
- /**
- * Saves the given {@link ReadOnlyAddressBook} to the storage.
- * @param addressBook cannot be null.
- * @throws IOException if there was any problem writing to the file.
- */
- void saveAddressBook(ReadOnlyAddressBook addressBook) throws IOException;
-
- /**
- * @see #saveAddressBook(ReadOnlyAddressBook)
- */
- void saveAddressBook(ReadOnlyAddressBook addressBook, Path filePath) throws IOException;
-
-}
diff --git a/src/main/java/seedu/address/storage/JsonAdaptedPerson.java b/src/main/java/seedu/address/storage/JsonAdaptedPerson.java
deleted file mode 100644
index a6321cec2ea..00000000000
--- a/src/main/java/seedu/address/storage/JsonAdaptedPerson.java
+++ /dev/null
@@ -1,109 +0,0 @@
-package seedu.address.storage;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-import seedu.address.commons.exceptions.IllegalValueException;
-import seedu.address.model.person.Address;
-import seedu.address.model.person.Email;
-import seedu.address.model.person.Name;
-import seedu.address.model.person.Person;
-import seedu.address.model.person.Phone;
-import seedu.address.model.tag.Tag;
-
-/**
- * Jackson-friendly version of {@link Person}.
- */
-class JsonAdaptedPerson {
-
- public static final String MISSING_FIELD_MESSAGE_FORMAT = "Person's %s field is missing!";
-
- private final String name;
- private final String phone;
- private final String email;
- private final String address;
- private final List tagged = new ArrayList<>();
-
- /**
- * Constructs a {@code JsonAdaptedPerson} with the given person details.
- */
- @JsonCreator
- public JsonAdaptedPerson(@JsonProperty("name") String name, @JsonProperty("phone") String phone,
- @JsonProperty("email") String email, @JsonProperty("address") String address,
- @JsonProperty("tagged") List tagged) {
- this.name = name;
- this.phone = phone;
- this.email = email;
- this.address = address;
- if (tagged != null) {
- this.tagged.addAll(tagged);
- }
- }
-
- /**
- * Converts a given {@code Person} into this class for Jackson use.
- */
- public JsonAdaptedPerson(Person source) {
- name = source.getName().fullName;
- phone = source.getPhone().value;
- email = source.getEmail().value;
- address = source.getAddress().value;
- tagged.addAll(source.getTags().stream()
- .map(JsonAdaptedTag::new)
- .collect(Collectors.toList()));
- }
-
- /**
- * Converts this Jackson-friendly adapted person object into the model's {@code Person} object.
- *
- * @throws IllegalValueException if there were any data constraints violated in the adapted person.
- */
- public Person toModelType() throws IllegalValueException {
- final List personTags = new ArrayList<>();
- for (JsonAdaptedTag tag : tagged) {
- personTags.add(tag.toModelType());
- }
-
- if (name == null) {
- throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Name.class.getSimpleName()));
- }
- if (!Name.isValidName(name)) {
- throw new IllegalValueException(Name.MESSAGE_CONSTRAINTS);
- }
- final Name modelName = new Name(name);
-
- if (phone == null) {
- throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Phone.class.getSimpleName()));
- }
- if (!Phone.isValidPhone(phone)) {
- throw new IllegalValueException(Phone.MESSAGE_CONSTRAINTS);
- }
- final Phone modelPhone = new Phone(phone);
-
- if (email == null) {
- throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Email.class.getSimpleName()));
- }
- if (!Email.isValidEmail(email)) {
- throw new IllegalValueException(Email.MESSAGE_CONSTRAINTS);
- }
- final Email modelEmail = new Email(email);
-
- if (address == null) {
- throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Address.class.getSimpleName()));
- }
- if (!Address.isValidAddress(address)) {
- throw new IllegalValueException(Address.MESSAGE_CONSTRAINTS);
- }
- final Address modelAddress = new Address(address);
-
- final Set modelTags = new HashSet<>(personTags);
- return new Person(modelName, modelPhone, modelEmail, modelAddress, modelTags);
- }
-
-}
diff --git a/src/main/java/seedu/address/storage/JsonAdaptedTag.java b/src/main/java/seedu/address/storage/JsonAdaptedTag.java
deleted file mode 100644
index 0df22bdb754..00000000000
--- a/src/main/java/seedu/address/storage/JsonAdaptedTag.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package seedu.address.storage;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonValue;
-
-import seedu.address.commons.exceptions.IllegalValueException;
-import seedu.address.model.tag.Tag;
-
-/**
- * Jackson-friendly version of {@link Tag}.
- */
-class JsonAdaptedTag {
-
- private final String tagName;
-
- /**
- * Constructs a {@code JsonAdaptedTag} with the given {@code tagName}.
- */
- @JsonCreator
- public JsonAdaptedTag(String tagName) {
- this.tagName = tagName;
- }
-
- /**
- * Converts a given {@code Tag} into this class for Jackson use.
- */
- public JsonAdaptedTag(Tag source) {
- tagName = source.tagName;
- }
-
- @JsonValue
- public String getTagName() {
- return tagName;
- }
-
- /**
- * Converts this Jackson-friendly adapted tag object into the model's {@code Tag} object.
- *
- * @throws IllegalValueException if there were any data constraints violated in the adapted tag.
- */
- public Tag toModelType() throws IllegalValueException {
- if (!Tag.isValidTagName(tagName)) {
- throw new IllegalValueException(Tag.MESSAGE_CONSTRAINTS);
- }
- return new Tag(tagName);
- }
-
-}
diff --git a/src/main/java/seedu/address/storage/JsonAddressBookStorage.java b/src/main/java/seedu/address/storage/JsonAddressBookStorage.java
deleted file mode 100644
index dfab9daaa0d..00000000000
--- a/src/main/java/seedu/address/storage/JsonAddressBookStorage.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package seedu.address.storage;
-
-import static java.util.Objects.requireNonNull;
-
-import java.io.IOException;
-import java.nio.file.Path;
-import java.util.Optional;
-import java.util.logging.Logger;
-
-import seedu.address.commons.core.LogsCenter;
-import seedu.address.commons.exceptions.DataConversionException;
-import seedu.address.commons.exceptions.IllegalValueException;
-import seedu.address.commons.util.FileUtil;
-import seedu.address.commons.util.JsonUtil;
-import seedu.address.model.ReadOnlyAddressBook;
-
-/**
- * A class to access AddressBook data stored as a json file on the hard disk.
- */
-public class JsonAddressBookStorage implements AddressBookStorage {
-
- private static final Logger logger = LogsCenter.getLogger(JsonAddressBookStorage.class);
-
- private Path filePath;
-
- public JsonAddressBookStorage(Path filePath) {
- this.filePath = filePath;
- }
-
- public Path getAddressBookFilePath() {
- return filePath;
- }
-
- @Override
- public Optional readAddressBook() throws DataConversionException {
- return readAddressBook(filePath);
- }
-
- /**
- * Similar to {@link #readAddressBook()}.
- *
- * @param filePath location of the data. Cannot be null.
- * @throws DataConversionException if the file is not in the correct format.
- */
- public Optional readAddressBook(Path filePath) throws DataConversionException {
- requireNonNull(filePath);
-
- Optional jsonAddressBook = JsonUtil.readJsonFile(
- filePath, JsonSerializableAddressBook.class);
- if (!jsonAddressBook.isPresent()) {
- return Optional.empty();
- }
-
- try {
- return Optional.of(jsonAddressBook.get().toModelType());
- } catch (IllegalValueException ive) {
- logger.info("Illegal values found in " + filePath + ": " + ive.getMessage());
- throw new DataConversionException(ive);
- }
- }
-
- @Override
- public void saveAddressBook(ReadOnlyAddressBook addressBook) throws IOException {
- saveAddressBook(addressBook, filePath);
- }
-
- /**
- * Similar to {@link #saveAddressBook(ReadOnlyAddressBook)}.
- *
- * @param filePath location of the data. Cannot be null.
- */
- public void saveAddressBook(ReadOnlyAddressBook addressBook, Path filePath) throws IOException {
- requireNonNull(addressBook);
- requireNonNull(filePath);
-
- FileUtil.createIfMissing(filePath);
- JsonUtil.saveJsonFile(new JsonSerializableAddressBook(addressBook), filePath);
- }
-
-}
diff --git a/src/main/java/seedu/address/storage/JsonSerializableAddressBook.java b/src/main/java/seedu/address/storage/JsonSerializableAddressBook.java
deleted file mode 100644
index 5efd834091d..00000000000
--- a/src/main/java/seedu/address/storage/JsonSerializableAddressBook.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package seedu.address.storage;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.stream.Collectors;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.annotation.JsonRootName;
-
-import seedu.address.commons.exceptions.IllegalValueException;
-import seedu.address.model.AddressBook;
-import seedu.address.model.ReadOnlyAddressBook;
-import seedu.address.model.person.Person;
-
-/**
- * An Immutable AddressBook that is serializable to JSON format.
- */
-@JsonRootName(value = "addressbook")
-class JsonSerializableAddressBook {
-
- public static final String MESSAGE_DUPLICATE_PERSON = "Persons list contains duplicate person(s).";
-
- private final List persons = new ArrayList<>();
-
- /**
- * Constructs a {@code JsonSerializableAddressBook} with the given persons.
- */
- @JsonCreator
- public JsonSerializableAddressBook(@JsonProperty("persons") List persons) {
- this.persons.addAll(persons);
- }
-
- /**
- * Converts a given {@code ReadOnlyAddressBook} into this class for Jackson use.
- *
- * @param source future changes to this will not affect the created {@code JsonSerializableAddressBook}.
- */
- public JsonSerializableAddressBook(ReadOnlyAddressBook source) {
- persons.addAll(source.getPersonList().stream().map(JsonAdaptedPerson::new).collect(Collectors.toList()));
- }
-
- /**
- * Converts this address book into the model's {@code AddressBook} object.
- *
- * @throws IllegalValueException if there were any data constraints violated.
- */
- public AddressBook toModelType() throws IllegalValueException {
- AddressBook addressBook = new AddressBook();
- for (JsonAdaptedPerson jsonAdaptedPerson : persons) {
- Person person = jsonAdaptedPerson.toModelType();
- if (addressBook.hasPerson(person)) {
- throw new IllegalValueException(MESSAGE_DUPLICATE_PERSON);
- }
- addressBook.addPerson(person);
- }
- return addressBook;
- }
-
-}
diff --git a/src/main/java/seedu/address/storage/Storage.java b/src/main/java/seedu/address/storage/Storage.java
deleted file mode 100644
index beda8bd9f11..00000000000
--- a/src/main/java/seedu/address/storage/Storage.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package seedu.address.storage;
-
-import java.io.IOException;
-import java.nio.file.Path;
-import java.util.Optional;
-
-import seedu.address.commons.exceptions.DataConversionException;
-import seedu.address.model.ReadOnlyAddressBook;
-import seedu.address.model.ReadOnlyUserPrefs;
-import seedu.address.model.UserPrefs;
-
-/**
- * API of the Storage component
- */
-public interface Storage extends AddressBookStorage, UserPrefsStorage {
-
- @Override
- Optional readUserPrefs() throws DataConversionException, IOException;
-
- @Override
- void saveUserPrefs(ReadOnlyUserPrefs userPrefs) throws IOException;
-
- @Override
- Path getAddressBookFilePath();
-
- @Override
- Optional readAddressBook() throws DataConversionException, IOException;
-
- @Override
- void saveAddressBook(ReadOnlyAddressBook addressBook) throws IOException;
-
-}
diff --git a/src/main/java/seedu/address/storage/StorageManager.java b/src/main/java/seedu/address/storage/StorageManager.java
deleted file mode 100644
index 6cfa0162164..00000000000
--- a/src/main/java/seedu/address/storage/StorageManager.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package seedu.address.storage;
-
-import java.io.IOException;
-import java.nio.file.Path;
-import java.util.Optional;
-import java.util.logging.Logger;
-
-import seedu.address.commons.core.LogsCenter;
-import seedu.address.commons.exceptions.DataConversionException;
-import seedu.address.model.ReadOnlyAddressBook;
-import seedu.address.model.ReadOnlyUserPrefs;
-import seedu.address.model.UserPrefs;
-
-/**
- * Manages storage of AddressBook data in local storage.
- */
-public class StorageManager implements Storage {
-
- private static final Logger logger = LogsCenter.getLogger(StorageManager.class);
- private AddressBookStorage addressBookStorage;
- private UserPrefsStorage userPrefsStorage;
-
- /**
- * Creates a {@code StorageManager} with the given {@code AddressBookStorage} and {@code UserPrefStorage}.
- */
- public StorageManager(AddressBookStorage addressBookStorage, UserPrefsStorage userPrefsStorage) {
- this.addressBookStorage = addressBookStorage;
- this.userPrefsStorage = userPrefsStorage;
- }
-
- // ================ UserPrefs methods ==============================
-
- @Override
- public Path getUserPrefsFilePath() {
- return userPrefsStorage.getUserPrefsFilePath();
- }
-
- @Override
- public Optional readUserPrefs() throws DataConversionException, IOException {
- return userPrefsStorage.readUserPrefs();
- }
-
- @Override
- public void saveUserPrefs(ReadOnlyUserPrefs userPrefs) throws IOException {
- userPrefsStorage.saveUserPrefs(userPrefs);
- }
-
-
- // ================ AddressBook methods ==============================
-
- @Override
- public Path getAddressBookFilePath() {
- return addressBookStorage.getAddressBookFilePath();
- }
-
- @Override
- public Optional readAddressBook() throws DataConversionException, IOException {
- return readAddressBook(addressBookStorage.getAddressBookFilePath());
- }
-
- @Override
- public Optional readAddressBook(Path filePath) throws DataConversionException, IOException {
- logger.fine("Attempting to read data from file: " + filePath);
- return addressBookStorage.readAddressBook(filePath);
- }
-
- @Override
- public void saveAddressBook(ReadOnlyAddressBook addressBook) throws IOException {
- saveAddressBook(addressBook, addressBookStorage.getAddressBookFilePath());
- }
-
- @Override
- public void saveAddressBook(ReadOnlyAddressBook addressBook, Path filePath) throws IOException {
- logger.fine("Attempting to write to data file: " + filePath);
- addressBookStorage.saveAddressBook(addressBook, filePath);
- }
-
-}
diff --git a/src/main/java/seedu/address/ui/PersonCard.java b/src/main/java/seedu/address/ui/PersonCard.java
deleted file mode 100644
index 7fc927bc5d9..00000000000
--- a/src/main/java/seedu/address/ui/PersonCard.java
+++ /dev/null
@@ -1,77 +0,0 @@
-package seedu.address.ui;
-
-import java.util.Comparator;
-
-import javafx.fxml.FXML;
-import javafx.scene.control.Label;
-import javafx.scene.layout.FlowPane;
-import javafx.scene.layout.HBox;
-import javafx.scene.layout.Region;
-import seedu.address.model.person.Person;
-
-/**
- * An UI component that displays information of a {@code Person}.
- */
-public class PersonCard extends UiPart {
-
- private static final String FXML = "PersonListCard.fxml";
-
- /**
- * Note: Certain keywords such as "location" and "resources" are reserved keywords in JavaFX.
- * As a consequence, UI elements' variable names cannot be set to such keywords
- * or an exception will be thrown by JavaFX during runtime.
- *
- * @see The issue on AddressBook level 4
- */
-
- public final Person person;
-
- @FXML
- private HBox cardPane;
- @FXML
- private Label name;
- @FXML
- private Label id;
- @FXML
- private Label phone;
- @FXML
- private Label address;
- @FXML
- private Label email;
- @FXML
- private FlowPane tags;
-
- /**
- * Creates a {@code PersonCode} with the given {@code Person} and index to display.
- */
- public PersonCard(Person person, int displayedIndex) {
- super(FXML);
- this.person = person;
- id.setText(displayedIndex + ". ");
- name.setText(person.getName().fullName);
- phone.setText(person.getPhone().value);
- address.setText(person.getAddress().value);
- email.setText(person.getEmail().value);
- person.getTags().stream()
- .sorted(Comparator.comparing(tag -> tag.tagName))
- .forEach(tag -> tags.getChildren().add(new Label(tag.tagName)));
- }
-
- @Override
- public boolean equals(Object other) {
- // short circuit if same object
- if (other == this) {
- return true;
- }
-
- // instanceof handles nulls
- if (!(other instanceof PersonCard)) {
- return false;
- }
-
- // state check
- PersonCard card = (PersonCard) other;
- return id.getText().equals(card.id.getText())
- && person.equals(card.person);
- }
-}
diff --git a/src/main/java/seedu/address/ui/PersonListPanel.java b/src/main/java/seedu/address/ui/PersonListPanel.java
deleted file mode 100644
index f4c501a897b..00000000000
--- a/src/main/java/seedu/address/ui/PersonListPanel.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package seedu.address.ui;
-
-import java.util.logging.Logger;
-
-import javafx.collections.ObservableList;
-import javafx.fxml.FXML;
-import javafx.scene.control.ListCell;
-import javafx.scene.control.ListView;
-import javafx.scene.layout.Region;
-import seedu.address.commons.core.LogsCenter;
-import seedu.address.model.person.Person;
-
-/**
- * Panel containing the list of persons.
- */
-public class PersonListPanel extends UiPart {
- private static final String FXML = "PersonListPanel.fxml";
- private final Logger logger = LogsCenter.getLogger(PersonListPanel.class);
-
- @FXML
- private ListView personListView;
-
- /**
- * Creates a {@code PersonListPanel} with the given {@code ObservableList}.
- */
- public PersonListPanel(ObservableList personList) {
- super(FXML);
- personListView.setItems(personList);
- personListView.setCellFactory(listView -> new PersonListViewCell());
- }
-
- /**
- * Custom {@code ListCell} that displays the graphics of a {@code Person} using a {@code PersonCard}.
- */
- class PersonListViewCell extends ListCell {
- @Override
- protected void updateItem(Person person, boolean empty) {
- super.updateItem(person, empty);
-
- if (empty || person == null) {
- setGraphic(null);
- setText(null);
- } else {
- setGraphic(new PersonCard(person, getIndex() + 1).getRoot());
- }
- }
- }
-
-}
diff --git a/src/main/java/seedu/address/AppParameters.java b/src/main/java/seedu/medinfo/AppParameters.java
similarity index 93%
rename from src/main/java/seedu/address/AppParameters.java
rename to src/main/java/seedu/medinfo/AppParameters.java
index ab552c398f3..faf1915254f 100644
--- a/src/main/java/seedu/address/AppParameters.java
+++ b/src/main/java/seedu/medinfo/AppParameters.java
@@ -1,4 +1,4 @@
-package seedu.address;
+package seedu.medinfo;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -7,8 +7,8 @@
import java.util.logging.Logger;
import javafx.application.Application;
-import seedu.address.commons.core.LogsCenter;
-import seedu.address.commons.util.FileUtil;
+import seedu.medinfo.commons.core.LogsCenter;
+import seedu.medinfo.commons.util.FileUtil;
/**
* Represents the parsed command-line parameters given to the application.
diff --git a/src/main/java/seedu/address/Main.java b/src/main/java/seedu/medinfo/Main.java
similarity index 97%
rename from src/main/java/seedu/address/Main.java
rename to src/main/java/seedu/medinfo/Main.java
index 052a5068631..e772532a3f2 100644
--- a/src/main/java/seedu/address/Main.java
+++ b/src/main/java/seedu/medinfo/Main.java
@@ -1,4 +1,4 @@
-package seedu.address;
+package seedu.medinfo;
import javafx.application.Application;
diff --git a/src/main/java/seedu/address/MainApp.java b/src/main/java/seedu/medinfo/MainApp.java
similarity index 63%
rename from src/main/java/seedu/address/MainApp.java
rename to src/main/java/seedu/medinfo/MainApp.java
index 4133aaa0151..d34272d5888 100644
--- a/src/main/java/seedu/address/MainApp.java
+++ b/src/main/java/seedu/medinfo/MainApp.java
@@ -1,4 +1,4 @@
-package seedu.address;
+package seedu.medinfo;
import java.io.IOException;
import java.nio.file.Path;
@@ -7,36 +7,37 @@
import javafx.application.Application;
import javafx.stage.Stage;
-import seedu.address.commons.core.Config;
-import seedu.address.commons.core.LogsCenter;
-import seedu.address.commons.core.Version;
-import seedu.address.commons.exceptions.DataConversionException;
-import seedu.address.commons.util.ConfigUtil;
-import seedu.address.commons.util.StringUtil;
-import seedu.address.logic.Logic;
-import seedu.address.logic.LogicManager;
-import seedu.address.model.AddressBook;
-import seedu.address.model.Model;
-import seedu.address.model.ModelManager;
-import seedu.address.model.ReadOnlyAddressBook;
-import seedu.address.model.ReadOnlyUserPrefs;
-import seedu.address.model.UserPrefs;
-import seedu.address.model.util.SampleDataUtil;
-import seedu.address.storage.AddressBookStorage;
-import seedu.address.storage.JsonAddressBookStorage;
-import seedu.address.storage.JsonUserPrefsStorage;
-import seedu.address.storage.Storage;
-import seedu.address.storage.StorageManager;
-import seedu.address.storage.UserPrefsStorage;
-import seedu.address.ui.Ui;
-import seedu.address.ui.UiManager;
+import seedu.medinfo.commons.core.Config;
+import seedu.medinfo.commons.core.LogsCenter;
+import seedu.medinfo.commons.core.Version;
+import seedu.medinfo.commons.exceptions.DataConversionException;
+import seedu.medinfo.commons.util.ConfigUtil;
+import seedu.medinfo.commons.util.StringUtil;
+import seedu.medinfo.logic.Logic;
+import seedu.medinfo.logic.LogicManager;
+import seedu.medinfo.logic.commands.exceptions.CommandException;
+import seedu.medinfo.model.MedInfo;
+import seedu.medinfo.model.Model;
+import seedu.medinfo.model.ModelManager;
+import seedu.medinfo.model.ReadOnlyMedInfo;
+import seedu.medinfo.model.ReadOnlyUserPrefs;
+import seedu.medinfo.model.UserPrefs;
+import seedu.medinfo.model.util.SampleDataUtil;
+import seedu.medinfo.storage.JsonMedInfoStorage;
+import seedu.medinfo.storage.JsonUserPrefsStorage;
+import seedu.medinfo.storage.MedInfoStorage;
+import seedu.medinfo.storage.Storage;
+import seedu.medinfo.storage.StorageManager;
+import seedu.medinfo.storage.UserPrefsStorage;
+import seedu.medinfo.ui.Ui;
+import seedu.medinfo.ui.UiManager;
/**
* Runs the application.
*/
public class MainApp extends Application {
- public static final Version VERSION = new Version(0, 2, 0, true);
+ public static final Version VERSION = new Version(1, 3, 0, true);
private static final Logger logger = LogsCenter.getLogger(MainApp.class);
@@ -48,7 +49,7 @@ public class MainApp extends Application {
@Override
public void init() throws Exception {
- logger.info("=============================[ Initializing AddressBook ]===========================");
+ logger.info("=============================[ Initializing MedInfo ]===========================");
super.init();
AppParameters appParameters = AppParameters.parse(getParameters());
@@ -56,8 +57,8 @@ public void init() throws Exception {
UserPrefsStorage userPrefsStorage = new JsonUserPrefsStorage(config.getUserPrefsFilePath());
UserPrefs userPrefs = initPrefs(userPrefsStorage);
- AddressBookStorage addressBookStorage = new JsonAddressBookStorage(userPrefs.getAddressBookFilePath());
- storage = new StorageManager(addressBookStorage, userPrefsStorage);
+ MedInfoStorage medInfoStorage = new JsonMedInfoStorage(userPrefs.getMedInfoFilePath());
+ storage = new StorageManager(medInfoStorage, userPrefsStorage);
initLogging(config);
@@ -69,27 +70,34 @@ public void init() throws Exception {
}
/**
- * Returns a {@code ModelManager} with the data from {@code storage}'s address book and {@code userPrefs}.
- * The data from the sample address book will be used instead if {@code storage}'s address book is not found,
- * or an empty address book will be used instead if errors occur when reading {@code storage}'s address book.
+ * Returns a {@code ModelManager} with the data from {@code storage}'s medinfo book and {@code userPrefs}.
+ * The data from the sample medinfo book will be used instead if {@code storage}'s medinfo book is not found,
+ * or an empty medinfo book will be used instead if errors occur when reading {@code storage}'s medinfo book.
*/
private Model initModelManager(Storage storage, ReadOnlyUserPrefs userPrefs) {
- Optional addressBookOptional;
- ReadOnlyAddressBook initialData;
+ Optional medInfoOptional;
+ ReadOnlyMedInfo initialData;
try {
- addressBookOptional = storage.readAddressBook();
- if (!addressBookOptional.isPresent()) {
- logger.info("Data file not found. Will be starting with a sample AddressBook");
+ medInfoOptional = storage.readMedInfo();
+ if (!medInfoOptional.isPresent()) {
+ logger.info("Data file not found. Will be starting with a sample MedInfo");
}
- initialData = addressBookOptional.orElseGet(SampleDataUtil::getSampleAddressBook);
- } catch (DataConversionException e) {
- logger.warning("Data file not in the correct format. Will be starting with an empty AddressBook");
- initialData = new AddressBook();
+ Optional sampleData = Optional.ofNullable(SampleDataUtil.getSampleMedInfo());
+ initialData = medInfoOptional.orElseGet(() -> {
+ try {
+ return SampleDataUtil.getSampleMedInfo();
+ } catch (CommandException e) {
+ logger.warning("Data file not in the correct format. Will be starting with an empty MedInfo");
+ return new MedInfo();
+ }
+ });
+ } catch (CommandException | DataConversionException e) {
+ logger.warning("Data file not in the correct format. Will be starting with an empty MedInfo");
+ initialData = new MedInfo();
} catch (IOException e) {
- logger.warning("Problem while reading from the file. Will be starting with an empty AddressBook");
- initialData = new AddressBook();
+ logger.warning("Problem while reading from the file. Will be starting with an empty MedInfo");
+ initialData = new MedInfo();
}
-
return new ModelManager(initialData, userPrefs);
}
@@ -151,7 +159,7 @@ protected UserPrefs initPrefs(UserPrefsStorage storage) {
+ "Using default user prefs");
initializedPrefs = new UserPrefs();
} catch (IOException e) {
- logger.warning("Problem while reading from the file. Will be starting with an empty AddressBook");
+ logger.warning("Problem while reading from the file. Will be starting with an empty MedInfo");
initializedPrefs = new UserPrefs();
}
@@ -167,13 +175,13 @@ protected UserPrefs initPrefs(UserPrefsStorage storage) {
@Override
public void start(Stage primaryStage) {
- logger.info("Starting AddressBook " + MainApp.VERSION);
+ logger.info("Starting MedInfo " + MainApp.VERSION);
ui.start(primaryStage);
}
@Override
public void stop() {
- logger.info("============================ [ Stopping Address Book ] =============================");
+ logger.info("============================ [ Stopping MedInfo ] =============================");
try {
storage.saveUserPrefs(model.getUserPrefs());
} catch (IOException e) {
diff --git a/src/main/java/seedu/address/commons/core/Config.java b/src/main/java/seedu/medinfo/commons/core/Config.java
similarity index 97%
rename from src/main/java/seedu/address/commons/core/Config.java
rename to src/main/java/seedu/medinfo/commons/core/Config.java
index 91145745521..96f54bdb89d 100644
--- a/src/main/java/seedu/address/commons/core/Config.java
+++ b/src/main/java/seedu/medinfo/commons/core/Config.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.core;
+package seedu.medinfo.commons.core;
import java.nio.file.Path;
import java.nio.file.Paths;
diff --git a/src/main/java/seedu/address/commons/core/GuiSettings.java b/src/main/java/seedu/medinfo/commons/core/GuiSettings.java
similarity index 98%
rename from src/main/java/seedu/address/commons/core/GuiSettings.java
rename to src/main/java/seedu/medinfo/commons/core/GuiSettings.java
index ba33653be67..5b0ecd54841 100644
--- a/src/main/java/seedu/address/commons/core/GuiSettings.java
+++ b/src/main/java/seedu/medinfo/commons/core/GuiSettings.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.core;
+package seedu.medinfo.commons.core;
import java.awt.Point;
import java.io.Serializable;
diff --git a/src/main/java/seedu/address/commons/core/LogsCenter.java b/src/main/java/seedu/medinfo/commons/core/LogsCenter.java
similarity index 97%
rename from src/main/java/seedu/address/commons/core/LogsCenter.java
rename to src/main/java/seedu/medinfo/commons/core/LogsCenter.java
index 431e7185e76..89ff45bfd0a 100644
--- a/src/main/java/seedu/address/commons/core/LogsCenter.java
+++ b/src/main/java/seedu/medinfo/commons/core/LogsCenter.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.core;
+package seedu.medinfo.commons.core;
import java.io.IOException;
import java.util.Arrays;
@@ -18,7 +18,7 @@
public class LogsCenter {
private static final int MAX_FILE_COUNT = 5;
private static final int MAX_FILE_SIZE_IN_BYTES = (int) (Math.pow(2, 20) * 5); // 5MB
- private static final String LOG_FILE = "addressbook.log";
+ private static final String LOG_FILE = "medinfo.log";
private static Level currentLogLevel = Level.INFO;
private static final Logger logger = LogsCenter.getLogger(LogsCenter.class);
private static FileHandler fileHandler;
diff --git a/src/main/java/seedu/medinfo/commons/core/Messages.java b/src/main/java/seedu/medinfo/commons/core/Messages.java
new file mode 100644
index 00000000000..a8e8d34113a
--- /dev/null
+++ b/src/main/java/seedu/medinfo/commons/core/Messages.java
@@ -0,0 +1,21 @@
+package seedu.medinfo.commons.core;
+
+/**
+ * Container for user visible messages.
+ */
+public class Messages {
+
+ public static final String MESSAGE_UNKNOWN_COMMAND = "Unknown command";
+ public static final String MESSAGE_INVALID_COMMAND_FORMAT = "Invalid command format! \n%1$s";
+ public static final String MESSAGE_INVALID_PATIENT_DISPLAYED_INDEX = "The patient index provided is invalid";
+ public static final String MESSAGE_INVALID_WARD_DISPLAYED_INDEX = "The ward index provided is invalid";
+ public static final String MESSAGE_DELETE_WAITING_ROOM = "The Waiting Room cannot be deleted";
+ public static final String MESSAGE_ABORT_DELETE = "Deletion cancelled";
+
+ public static final String MESSAGE_DELETE_WARD_WITH_PATIENTS =
+ "The ward cannot be deleted as there are patients inside";
+
+ public static final String MESSAGE_ALL_PATIENTS_LISTED_OVERVIEW = "All %1$d patients listed!";
+ public static final String MESSAGE_PATIENTS_LISTED_OVERVIEW = "%1$d out of %2$d patients listed!";
+
+}
diff --git a/src/main/java/seedu/address/commons/core/Version.java b/src/main/java/seedu/medinfo/commons/core/Version.java
similarity index 98%
rename from src/main/java/seedu/address/commons/core/Version.java
rename to src/main/java/seedu/medinfo/commons/core/Version.java
index 12142ec1e32..cd658844227 100644
--- a/src/main/java/seedu/address/commons/core/Version.java
+++ b/src/main/java/seedu/medinfo/commons/core/Version.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.core;
+package seedu.medinfo.commons.core;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
diff --git a/src/main/java/seedu/address/commons/core/index/Index.java b/src/main/java/seedu/medinfo/commons/core/index/Index.java
similarity index 97%
rename from src/main/java/seedu/address/commons/core/index/Index.java
rename to src/main/java/seedu/medinfo/commons/core/index/Index.java
index 19536439c09..bcfb9ec3fd1 100644
--- a/src/main/java/seedu/address/commons/core/index/Index.java
+++ b/src/main/java/seedu/medinfo/commons/core/index/Index.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.core.index;
+package seedu.medinfo.commons.core.index;
/**
* Represents a zero-based or one-based index.
diff --git a/src/main/java/seedu/address/commons/exceptions/DataConversionException.java b/src/main/java/seedu/medinfo/commons/exceptions/DataConversionException.java
similarity index 84%
rename from src/main/java/seedu/address/commons/exceptions/DataConversionException.java
rename to src/main/java/seedu/medinfo/commons/exceptions/DataConversionException.java
index 1f689bd8e3f..50d4b069b47 100644
--- a/src/main/java/seedu/address/commons/exceptions/DataConversionException.java
+++ b/src/main/java/seedu/medinfo/commons/exceptions/DataConversionException.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.exceptions;
+package seedu.medinfo.commons.exceptions;
/**
* Represents an error during conversion of data from one format to another
diff --git a/src/main/java/seedu/address/commons/exceptions/IllegalValueException.java b/src/main/java/seedu/medinfo/commons/exceptions/IllegalValueException.java
similarity index 93%
rename from src/main/java/seedu/address/commons/exceptions/IllegalValueException.java
rename to src/main/java/seedu/medinfo/commons/exceptions/IllegalValueException.java
index 19124db485c..4f834f2bdd3 100644
--- a/src/main/java/seedu/address/commons/exceptions/IllegalValueException.java
+++ b/src/main/java/seedu/medinfo/commons/exceptions/IllegalValueException.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.exceptions;
+package seedu.medinfo.commons.exceptions;
/**
* Signals that some given data does not fulfill some constraints.
diff --git a/src/main/java/seedu/address/commons/util/AppUtil.java b/src/main/java/seedu/medinfo/commons/util/AppUtil.java
similarity index 94%
rename from src/main/java/seedu/address/commons/util/AppUtil.java
rename to src/main/java/seedu/medinfo/commons/util/AppUtil.java
index 87aa89c0326..ee5c9601cf1 100644
--- a/src/main/java/seedu/address/commons/util/AppUtil.java
+++ b/src/main/java/seedu/medinfo/commons/util/AppUtil.java
@@ -1,9 +1,9 @@
-package seedu.address.commons.util;
+package seedu.medinfo.commons.util;
import static java.util.Objects.requireNonNull;
import javafx.scene.image.Image;
-import seedu.address.MainApp;
+import seedu.medinfo.MainApp;
/**
* A container for App specific utility functions
diff --git a/src/main/java/seedu/address/commons/util/CollectionUtil.java b/src/main/java/seedu/medinfo/commons/util/CollectionUtil.java
similarity index 96%
rename from src/main/java/seedu/address/commons/util/CollectionUtil.java
rename to src/main/java/seedu/medinfo/commons/util/CollectionUtil.java
index eafe4dfd681..8f1e3e39afd 100644
--- a/src/main/java/seedu/address/commons/util/CollectionUtil.java
+++ b/src/main/java/seedu/medinfo/commons/util/CollectionUtil.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.util;
+package seedu.medinfo.commons.util;
import static java.util.Objects.requireNonNull;
diff --git a/src/main/java/seedu/address/commons/util/ConfigUtil.java b/src/main/java/seedu/medinfo/commons/util/ConfigUtil.java
similarity index 77%
rename from src/main/java/seedu/address/commons/util/ConfigUtil.java
rename to src/main/java/seedu/medinfo/commons/util/ConfigUtil.java
index f7f8a2bd44c..8ffe09bfc0b 100644
--- a/src/main/java/seedu/address/commons/util/ConfigUtil.java
+++ b/src/main/java/seedu/medinfo/commons/util/ConfigUtil.java
@@ -1,11 +1,11 @@
-package seedu.address.commons.util;
+package seedu.medinfo.commons.util;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Optional;
-import seedu.address.commons.core.Config;
-import seedu.address.commons.exceptions.DataConversionException;
+import seedu.medinfo.commons.core.Config;
+import seedu.medinfo.commons.exceptions.DataConversionException;
/**
* A class for accessing the Config File.
diff --git a/src/main/java/seedu/address/commons/util/FileUtil.java b/src/main/java/seedu/medinfo/commons/util/FileUtil.java
similarity index 98%
rename from src/main/java/seedu/address/commons/util/FileUtil.java
rename to src/main/java/seedu/medinfo/commons/util/FileUtil.java
index b1e2767cdd9..0f6bd0e354b 100644
--- a/src/main/java/seedu/address/commons/util/FileUtil.java
+++ b/src/main/java/seedu/medinfo/commons/util/FileUtil.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.util;
+package seedu.medinfo.commons.util;
import java.io.IOException;
import java.nio.file.Files;
diff --git a/src/main/java/seedu/address/commons/util/JsonUtil.java b/src/main/java/seedu/medinfo/commons/util/JsonUtil.java
similarity index 97%
rename from src/main/java/seedu/address/commons/util/JsonUtil.java
rename to src/main/java/seedu/medinfo/commons/util/JsonUtil.java
index 8ef609f055d..d3a75235022 100644
--- a/src/main/java/seedu/address/commons/util/JsonUtil.java
+++ b/src/main/java/seedu/medinfo/commons/util/JsonUtil.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.util;
+package seedu.medinfo.commons.util;
import static java.util.Objects.requireNonNull;
@@ -20,8 +20,8 @@
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
-import seedu.address.commons.core.LogsCenter;
-import seedu.address.commons.exceptions.DataConversionException;
+import seedu.medinfo.commons.core.LogsCenter;
+import seedu.medinfo.commons.exceptions.DataConversionException;
/**
* Converts a Java object instance to JSON and vice versa
diff --git a/src/main/java/seedu/address/commons/util/StringUtil.java b/src/main/java/seedu/medinfo/commons/util/StringUtil.java
similarity index 77%
rename from src/main/java/seedu/address/commons/util/StringUtil.java
rename to src/main/java/seedu/medinfo/commons/util/StringUtil.java
index 61cc8c9a1cb..d47d43f4a06 100644
--- a/src/main/java/seedu/address/commons/util/StringUtil.java
+++ b/src/main/java/seedu/medinfo/commons/util/StringUtil.java
@@ -1,7 +1,7 @@
-package seedu.address.commons.util;
+package seedu.medinfo.commons.util;
import static java.util.Objects.requireNonNull;
-import static seedu.address.commons.util.AppUtil.checkArgument;
+import static seedu.medinfo.commons.util.AppUtil.checkArgument;
import java.io.PrintWriter;
import java.io.StringWriter;
@@ -14,24 +14,28 @@ public class StringUtil {
/**
* Returns true if the {@code sentence} contains the {@code word}.
- * Ignores case, but a full word match is required.
- * examples:
+ * Ignores case, but a full word match is required.
+ *
+ * examples:
+ *
+ *
* containsWordIgnoreCase("ABc def", "abc") == true
* containsWordIgnoreCase("ABc def", "DEF") == true
* containsWordIgnoreCase("ABc def", "AB") == false //not a full word match
- *
- * @param sentence cannot be null
- * @param word cannot be null, cannot be empty, must be a single word
+ *
+ *
+ * @param fullName cannot be null
+ * @param word cannot be null, cannot be empty, must be a single word
*/
- public static boolean containsWordIgnoreCase(String sentence, String word) {
- requireNonNull(sentence);
+ public static boolean containsWordIgnoreCase(String fullName, String word) {
+ requireNonNull(fullName);
requireNonNull(word);
String preppedWord = word.trim();
checkArgument(!preppedWord.isEmpty(), "Word parameter cannot be empty");
checkArgument(preppedWord.split("\\s+").length == 1, "Word parameter should be a single word");
- String preppedSentence = sentence;
+ String preppedSentence = fullName.toString();
String[] wordsInPreppedSentence = preppedSentence.split("\\s+");
return Arrays.stream(wordsInPreppedSentence)
@@ -52,7 +56,9 @@ public static String getDetails(Throwable t) {
* Returns true if {@code s} represents a non-zero unsigned integer
* e.g. 1, 2, 3, ..., {@code Integer.MAX_VALUE}
* Will return false for any other non-null string input
- * e.g. empty string, "-1", "0", "+1", and " 2 " (untrimmed), "3 0" (contains whitespace), "1 a" (contains letters)
+ * e.g. empty string, "-1", "0", "+1", and " 2 " (untrimmed), "3 0" (contains
+ * whitespace), "1 a" (contains letters)
+ *
* @throws NullPointerException if {@code s} is null.
*/
public static boolean isNonZeroUnsignedInteger(String s) {
diff --git a/src/main/java/seedu/medinfo/logic/Logic.java b/src/main/java/seedu/medinfo/logic/Logic.java
new file mode 100644
index 00000000000..ba547bc7763
--- /dev/null
+++ b/src/main/java/seedu/medinfo/logic/Logic.java
@@ -0,0 +1,58 @@
+package seedu.medinfo.logic;
+
+import java.nio.file.Path;
+import java.util.List;
+
+import javafx.collections.ObservableList;
+import seedu.medinfo.commons.core.GuiSettings;
+import seedu.medinfo.logic.commands.CommandResult;
+import seedu.medinfo.logic.commands.exceptions.CommandException;
+import seedu.medinfo.logic.parser.exceptions.ParseException;
+import seedu.medinfo.model.ReadOnlyMedInfo;
+import seedu.medinfo.model.patient.Patient;
+import seedu.medinfo.model.ward.Ward;
+
+/**
+ * API of the Logic component
+ */
+public interface Logic {
+ /**
+ * Executes the command and returns the result.
+ * @param commandText The command as entered by the user.
+ * @return the result of the command execution.
+ * @throws CommandException If an error occurs during command execution.
+ * @throws ParseException If an error occurs during parsing.
+ */
+ CommandResult execute(String commandText) throws CommandException, ParseException;
+
+ /**
+ * Returns the MedInfo.
+ *
+ * @see seedu.medinfo.model.Model#getMedInfo()
+ */
+ ReadOnlyMedInfo getMedInfo();
+
+ List getStatsInfo();
+
+ /** Returns an unmodifiable view of the filtered list of patients */
+ ObservableList getFilteredPatientList();
+
+ /** Returns an unmodifiable view of the filtered list of wards */
+ ObservableList getFilteredWardList();
+
+ /**
+ * Returns the user prefs' medinfo book file path.
+ */
+ Path getMedInfoFilePath();
+
+ /**
+ * Returns the user prefs' GUI settings.
+ */
+ GuiSettings getGuiSettings();
+
+ /**
+ * Set the user prefs' GUI settings.
+ */
+ void setGuiSettings(GuiSettings guiSettings);
+
+}
diff --git a/src/main/java/seedu/address/logic/LogicManager.java b/src/main/java/seedu/medinfo/logic/LogicManager.java
similarity index 51%
rename from src/main/java/seedu/address/logic/LogicManager.java
rename to src/main/java/seedu/medinfo/logic/LogicManager.java
index 9d9c6d15bdc..85edc837e04 100644
--- a/src/main/java/seedu/address/logic/LogicManager.java
+++ b/src/main/java/seedu/medinfo/logic/LogicManager.java
@@ -1,21 +1,23 @@
-package seedu.address.logic;
+package seedu.medinfo.logic;
import java.io.IOException;
import java.nio.file.Path;
+import java.util.List;
import java.util.logging.Logger;
import javafx.collections.ObservableList;
-import seedu.address.commons.core.GuiSettings;
-import seedu.address.commons.core.LogsCenter;
-import seedu.address.logic.commands.Command;
-import seedu.address.logic.commands.CommandResult;
-import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.logic.parser.AddressBookParser;
-import seedu.address.logic.parser.exceptions.ParseException;
-import seedu.address.model.Model;
-import seedu.address.model.ReadOnlyAddressBook;
-import seedu.address.model.person.Person;
-import seedu.address.storage.Storage;
+import seedu.medinfo.commons.core.GuiSettings;
+import seedu.medinfo.commons.core.LogsCenter;
+import seedu.medinfo.logic.commands.Command;
+import seedu.medinfo.logic.commands.CommandResult;
+import seedu.medinfo.logic.commands.exceptions.CommandException;
+import seedu.medinfo.logic.parser.MedInfoParser;
+import seedu.medinfo.logic.parser.exceptions.ParseException;
+import seedu.medinfo.model.Model;
+import seedu.medinfo.model.ReadOnlyMedInfo;
+import seedu.medinfo.model.patient.Patient;
+import seedu.medinfo.model.ward.Ward;
+import seedu.medinfo.storage.Storage;
/**
* The main LogicManager of the app.
@@ -26,7 +28,7 @@ public class LogicManager implements Logic {
private final Model model;
private final Storage storage;
- private final AddressBookParser addressBookParser;
+ private final MedInfoParser medInfoParser;
/**
* Constructs a {@code LogicManager} with the given {@code Model} and {@code Storage}.
@@ -34,7 +36,12 @@ public class LogicManager implements Logic {
public LogicManager(Model model, Storage storage) {
this.model = model;
this.storage = storage;
- addressBookParser = new AddressBookParser();
+ medInfoParser = new MedInfoParser();
+ }
+
+ @Override
+ public List getStatsInfo() {
+ return model.getStatsInfo();
}
@Override
@@ -42,11 +49,11 @@ public CommandResult execute(String commandText) throws CommandException, ParseE
logger.info("----------------[USER COMMAND][" + commandText + "]");
CommandResult commandResult;
- Command command = addressBookParser.parseCommand(commandText);
+ Command command = medInfoParser.parseCommand(commandText);
commandResult = command.execute(model);
try {
- storage.saveAddressBook(model.getAddressBook());
+ storage.saveMedInfo(model.getMedInfo());
} catch (IOException ioe) {
throw new CommandException(FILE_OPS_ERROR_MESSAGE + ioe, ioe);
}
@@ -55,18 +62,23 @@ public CommandResult execute(String commandText) throws CommandException, ParseE
}
@Override
- public ReadOnlyAddressBook getAddressBook() {
- return model.getAddressBook();
+ public ReadOnlyMedInfo getMedInfo() {
+ return model.getMedInfo();
+ }
+
+ @Override
+ public ObservableList getFilteredPatientList() {
+ return model.getFilteredPatientList();
}
@Override
- public ObservableList getFilteredPersonList() {
- return model.getFilteredPersonList();
+ public ObservableList getFilteredWardList() {
+ return model.getFilteredWardList();
}
@Override
- public Path getAddressBookFilePath() {
- return model.getAddressBookFilePath();
+ public Path getMedInfoFilePath() {
+ return model.getMedInfoFilePath();
}
@Override
diff --git a/src/main/java/seedu/medinfo/logic/commands/AddCommand.java b/src/main/java/seedu/medinfo/logic/commands/AddCommand.java
new file mode 100644
index 00000000000..adc0381e10d
--- /dev/null
+++ b/src/main/java/seedu/medinfo/logic/commands/AddCommand.java
@@ -0,0 +1,64 @@
+package seedu.medinfo.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.medinfo.logic.parser.CliSyntax.PREFIX_NAME;
+import static seedu.medinfo.logic.parser.CliSyntax.PREFIX_NRIC;
+import static seedu.medinfo.logic.parser.CliSyntax.PREFIX_STATUS;
+
+import seedu.medinfo.logic.commands.exceptions.CommandException;
+import seedu.medinfo.model.Model;
+import seedu.medinfo.model.patient.Patient;
+
+/**
+ * Adds a patient to MedInfo.
+ */
+public class AddCommand extends Command {
+
+ public static final String COMMAND_WORD = "add";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Adds a patient to MedInfo. \n"
+ + "Parameters: "
+ + PREFIX_NAME + "NAME "
+ + PREFIX_NRIC + "NRIC "
+ + "[" + PREFIX_STATUS + "STATUS] \n"
+ + "Example: " + COMMAND_WORD + " "
+ + PREFIX_NAME + "John Doe " + PREFIX_NRIC + "S1234567A " + PREFIX_STATUS + "GRAY \n";
+
+ public static final String MESSAGE_SUCCESS = "New patient added: %1$s";
+ public static final String MESSAGE_DUPLICATE_PATIENT = "This patient already exists in MedInfo";
+
+ private final Patient toAdd;
+
+ /**
+ * Constructs a new {@code AddCommand} to add the specified {@code Patient}.
+ */
+ public AddCommand(Patient patient) {
+ requireNonNull(patient);
+ toAdd = patient;
+ }
+
+ /**
+ * Executes the {@code AddCommand} on the given model.
+ * @param model {@code Model} which the command should operate on.
+ * @return CommandResult which is the result of the operation.
+ * @throws CommandException
+ */
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+
+ if (model.hasPatientNric(toAdd)) {
+ throw new CommandException(MESSAGE_DUPLICATE_PATIENT);
+ }
+
+ model.addPatient(toAdd);
+ return new CommandResult(String.format(MESSAGE_SUCCESS, toAdd));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof AddCommand // instanceof handles nulls
+ && toAdd.equals(((AddCommand) other).toAdd));
+ }
+}
diff --git a/src/main/java/seedu/medinfo/logic/commands/AddWardCommand.java b/src/main/java/seedu/medinfo/logic/commands/AddWardCommand.java
new file mode 100644
index 00000000000..4ce0d7bba54
--- /dev/null
+++ b/src/main/java/seedu/medinfo/logic/commands/AddWardCommand.java
@@ -0,0 +1,63 @@
+package seedu.medinfo.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.medinfo.logic.parser.CliSyntax.PREFIX_CAPACITY;
+import static seedu.medinfo.logic.parser.CliSyntax.PREFIX_WARD;
+
+import seedu.medinfo.logic.commands.exceptions.CommandException;
+import seedu.medinfo.model.Model;
+import seedu.medinfo.model.ward.Ward;
+
+/**
+ * Adds a ward to MedInfo.
+ */
+public class AddWardCommand extends Command {
+
+ public static final String COMMAND_WORD = "addward";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Adds a ward to MedInfo. \n"
+ + "Parameters: "
+ + PREFIX_WARD + "WARD "
+ + "[" + PREFIX_CAPACITY + "CAPACITY] \n"
+ + "Example: " + COMMAND_WORD + " "
+ + PREFIX_WARD + "A03 " + PREFIX_CAPACITY + "100\n";
+
+ public static final String MESSAGE_SUCCESS = "New ward added: %1$s";
+ public static final String MESSAGE_DUPLICATE_WARD = "This ward already exists in MedInfo";
+
+ private final Ward toAdd;
+
+ /**
+ * Constructs a new {@code AddWardCommand} to add the specified {@code Ward}.
+ */
+ public AddWardCommand(Ward ward) {
+ requireNonNull(ward);
+ toAdd = ward;
+ }
+
+ /**
+ * Executes the {@code AddWardCommand} on the given model.
+ * @param model {@code Model} which the command should operate on.
+ * @return CommandResult which is the result of the operation.
+ * @throws CommandException
+ */
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+
+ if (model.hasWard(toAdd)) {
+ throw new CommandException(MESSAGE_DUPLICATE_WARD);
+ }
+
+ model.addWard(toAdd);
+ return new CommandResult(String.format(MESSAGE_SUCCESS, toAdd));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof AddWardCommand // instanceof handles nulls
+ && toAdd.equals(((AddWardCommand) other).toAdd));
+ }
+
+}
diff --git a/src/main/java/seedu/medinfo/logic/commands/ClearCommand.java b/src/main/java/seedu/medinfo/logic/commands/ClearCommand.java
new file mode 100644
index 00000000000..f036ed0c75b
--- /dev/null
+++ b/src/main/java/seedu/medinfo/logic/commands/ClearCommand.java
@@ -0,0 +1,31 @@
+package seedu.medinfo.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+
+import seedu.medinfo.logic.commands.exceptions.CommandException;
+import seedu.medinfo.model.MedInfo;
+import seedu.medinfo.model.Model;
+
+/**
+ * Clears the medinfo book.
+ */
+public class ClearCommand extends Command {
+
+ public static final String COMMAND_WORD = "clear";
+ public static final String MESSAGE_SUCCESS = "MedInfo has been cleared!";
+
+ /**
+ * Executes the {@code ClearCommand} on the given model.
+ * @param model {@code Model} which the command should operate on.
+ * @return CommandResult which is the result of the operation.
+ * @throws CommandException
+ */
+ @Override
+ public CommandResult execute(Model model) {
+ requireNonNull(model);
+ MedInfo newMedInfo = new MedInfo();
+ newMedInfo.newMedInfo();
+ model.setMedInfo(newMedInfo);
+ return new CommandResult(MESSAGE_SUCCESS);
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/Command.java b/src/main/java/seedu/medinfo/logic/commands/Command.java
similarity index 55%
rename from src/main/java/seedu/address/logic/commands/Command.java
rename to src/main/java/seedu/medinfo/logic/commands/Command.java
index 64f18992160..ca0961bbf79 100644
--- a/src/main/java/seedu/address/logic/commands/Command.java
+++ b/src/main/java/seedu/medinfo/logic/commands/Command.java
@@ -1,15 +1,15 @@
-package seedu.address.logic.commands;
+package seedu.medinfo.logic.commands;
-import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.model.Model;
+import seedu.medinfo.logic.commands.exceptions.CommandException;
+import seedu.medinfo.model.Model;
/**
- * Represents a command with hidden internal logic and the ability to be executed.
+ * Represents a {@code Command} with hidden internal logic and the ability to be executed.
*/
public abstract class Command {
/**
- * Executes the command and returns the result message.
+ * Executes the {@code Command} and returns the result message.
*
* @param model {@code Model} which the command should operate on.
* @return feedback message of the operation result for display
diff --git a/src/main/java/seedu/address/logic/commands/CommandResult.java b/src/main/java/seedu/medinfo/logic/commands/CommandResult.java
similarity index 92%
rename from src/main/java/seedu/address/logic/commands/CommandResult.java
rename to src/main/java/seedu/medinfo/logic/commands/CommandResult.java
index 92f900b7916..95b24a93342 100644
--- a/src/main/java/seedu/address/logic/commands/CommandResult.java
+++ b/src/main/java/seedu/medinfo/logic/commands/CommandResult.java
@@ -1,14 +1,15 @@
-package seedu.address.logic.commands;
+package seedu.medinfo.logic.commands;
import static java.util.Objects.requireNonNull;
import java.util.Objects;
/**
- * Represents the result of a command execution.
+ * Represents the result of a {@code Command} execution.
*/
public class CommandResult {
+ /** Result of the executed {@code Command} */
private final String feedbackToUser;
/** Help information should be shown to the user. */
diff --git a/src/main/java/seedu/medinfo/logic/commands/DeleteCommand.java b/src/main/java/seedu/medinfo/logic/commands/DeleteCommand.java
new file mode 100644
index 00000000000..b64cf36c267
--- /dev/null
+++ b/src/main/java/seedu/medinfo/logic/commands/DeleteCommand.java
@@ -0,0 +1,63 @@
+package seedu.medinfo.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+
+import java.util.List;
+
+import seedu.medinfo.commons.core.Messages;
+import seedu.medinfo.commons.core.index.Index;
+import seedu.medinfo.logic.commands.exceptions.CommandException;
+import seedu.medinfo.model.Model;
+import seedu.medinfo.model.patient.Patient;
+
+/**
+ * Deletes a patient identified using its displayed index from MedInfo.
+ */
+public class DeleteCommand extends Command {
+
+ public static final String COMMAND_WORD = "delete";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Deletes the patient identified by the index number used in the displayed patient list.\n"
+ + "Parameters: INDEX (must be a positive integer)\n"
+ + "Example: " + COMMAND_WORD + " 1";
+
+ public static final String MESSAGE_DELETE_PATIENT_SUCCESS = "Deleted Patient: %1$s";
+
+ private final Index targetIndex;
+
+ /**
+ * Constructs a new {@code DeleteCommand} to delete the {@code Patient} at the specified index.
+ * @param targetIndex Index of the {@code Patient} to be deleted in the list.
+ */
+ public DeleteCommand(Index targetIndex) {
+ this.targetIndex = targetIndex;
+ }
+
+ /**
+ * Executes the {@code DeleteCommand} on the given model.
+ * @param model {@code Model} which the command should operate on.
+ * @return CommandResult which is the result of the operation.
+ * @throws CommandException
+ */
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ List lastShownList = model.getFilteredPatientList();
+
+ if (targetIndex.getZeroBased() >= lastShownList.size()) {
+ throw new CommandException(Messages.MESSAGE_INVALID_PATIENT_DISPLAYED_INDEX);
+ }
+
+ Patient patientToDelete = lastShownList.get(targetIndex.getZeroBased());
+ model.deletePatient(patientToDelete);
+ return new CommandResult(String.format(MESSAGE_DELETE_PATIENT_SUCCESS, patientToDelete));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof DeleteCommand // instanceof handles nulls
+ && targetIndex.equals(((DeleteCommand) other).targetIndex)); // state check
+ }
+}
diff --git a/src/main/java/seedu/medinfo/logic/commands/DeleteWardCommand.java b/src/main/java/seedu/medinfo/logic/commands/DeleteWardCommand.java
new file mode 100644
index 00000000000..389ab5406de
--- /dev/null
+++ b/src/main/java/seedu/medinfo/logic/commands/DeleteWardCommand.java
@@ -0,0 +1,72 @@
+package seedu.medinfo.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+
+import java.util.List;
+
+import seedu.medinfo.commons.core.Messages;
+import seedu.medinfo.commons.core.index.Index;
+import seedu.medinfo.logic.commands.exceptions.CommandException;
+import seedu.medinfo.model.Model;
+import seedu.medinfo.model.ward.Ward;
+
+/**
+ * Deletes a ward identified using its displayed index from MedInfo.
+ */
+public class DeleteWardCommand extends Command {
+
+ public static final String COMMAND_WORD = "deleteward";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Deletes the ward identified by the index number used in the displayed ward list.\n"
+ + "Parameters: INDEX (must be a positive integer)\n"
+ + "Example: " + COMMAND_WORD + " 1";
+
+ public static final String MESSAGE_DELETE_WARD_SUCCESS = "Deleted Ward: %1$s";
+
+ private final Index targetIndex;
+
+ /**
+ * Constructs a new {@code DeleteWardCommand} to delete the {@code Ward} at the specified index.
+ * @param targetIndex Index of the {@code Ward} to be deleted in the list.
+ */
+ public DeleteWardCommand(Index targetIndex) {
+ this.targetIndex = targetIndex;
+ }
+
+ /**
+ * Executes the {@code DeleteWardCommand} on the given model.
+ * @param model {@code Model} which the command should operate on.
+ * @return CommandResult which is the result of the operation.
+ * @throws CommandException
+ */
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ List lastShownList = model.getFilteredWardList();
+
+ if (targetIndex.getZeroBased() >= lastShownList.size()) {
+ throw new CommandException(Messages.MESSAGE_INVALID_WARD_DISPLAYED_INDEX);
+ }
+
+ if (targetIndex.getZeroBased() == 0) {
+ throw new CommandException(Messages.MESSAGE_DELETE_WAITING_ROOM);
+ }
+
+ Ward wardToDelete = lastShownList.get(targetIndex.getZeroBased());
+
+ if (wardToDelete.getOccupancy() > 0) {
+ throw new CommandException(Messages.MESSAGE_DELETE_WARD_WITH_PATIENTS);
+ }
+
+ model.deleteWard(wardToDelete);
+ return new CommandResult(String.format(MESSAGE_DELETE_WARD_SUCCESS, wardToDelete));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof DeleteWardCommand // instanceof handles nulls
+ && targetIndex.equals(((DeleteWardCommand) other).targetIndex)); // state check
+ }
+}
diff --git a/src/main/java/seedu/medinfo/logic/commands/EditCommand.java b/src/main/java/seedu/medinfo/logic/commands/EditCommand.java
new file mode 100644
index 00000000000..f71b312aca1
--- /dev/null
+++ b/src/main/java/seedu/medinfo/logic/commands/EditCommand.java
@@ -0,0 +1,226 @@
+package seedu.medinfo.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.medinfo.logic.parser.CliSyntax.PREFIX_DISCHARGE;
+import static seedu.medinfo.logic.parser.CliSyntax.PREFIX_STATUS;
+import static seedu.medinfo.logic.parser.CliSyntax.PREFIX_WARD;
+import static seedu.medinfo.model.Model.PREDICATE_SHOW_ALL_PATIENTS;
+
+import java.util.List;
+import java.util.Optional;
+
+import seedu.medinfo.commons.core.Messages;
+import seedu.medinfo.commons.core.index.Index;
+import seedu.medinfo.commons.util.CollectionUtil;
+import seedu.medinfo.logic.commands.exceptions.CommandException;
+import seedu.medinfo.model.Model;
+import seedu.medinfo.model.patient.Discharge;
+import seedu.medinfo.model.patient.Name;
+import seedu.medinfo.model.patient.Nric;
+import seedu.medinfo.model.patient.Patient;
+import seedu.medinfo.model.patient.Status;
+import seedu.medinfo.model.ward.WardName;
+
+/**
+ * Edits the details of an existing patient in the medinfo book.
+ */
+public class EditCommand extends Command {
+
+ public static final String COMMAND_WORD = "edit";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Edits the status and/or ward and/or discharge "
+ + "date-time of the patient identified by the index number used in the displayed patient list. "
+ + "Existing values will be overwritten by the input values.\n"
+ + "Parameters: INDEX (must be a positive integer) "
+ + "[" + PREFIX_STATUS + "STATUS] "
+ + "[" + PREFIX_WARD + "WARD] "
+ + "[" + PREFIX_DISCHARGE + "DISCHARGE] \n"
+ + "Example: " + COMMAND_WORD + " 1 "
+ + PREFIX_STATUS + "GREEN " + PREFIX_WARD + "A1 " + PREFIX_DISCHARGE + "14/07/2023 1600 ";
+
+ public static final String MESSAGE_EDIT_PATIENT_SUCCESS = "Edited Patient: %1$s";
+ public static final String MESSAGE_NOT_EDITED = "At least one field to edit must be provided.";
+ public static final String MESSAGE_DUPLICATE_PATIENT = "This patient already exists in MedInfo.";
+ public static final String MESSAGE_WARD_NOT_FOUND = "Ward not found.";
+
+ private final Index index;
+ private final EditPatientDescriptor editPatientDescriptor;
+
+ /**
+ * Constructs {@code EditCommand} to edit {@code Patient} at specified index.
+ * @param index Index of the {@code Patient} to be edited in the list.
+ * @param editPatientDescriptor Description of the {@code Patient} details to be edited.
+ */
+ public EditCommand(Index index, EditPatientDescriptor editPatientDescriptor) {
+ requireNonNull(index);
+ requireNonNull(editPatientDescriptor);
+
+ this.index = index;
+ this.editPatientDescriptor = new EditPatientDescriptor(editPatientDescriptor);
+ }
+
+ /**
+ * Executes the {@code EditCommand} on the given model.
+ * @param model {@code Model} which the command should operate on.
+ * @return CommandResult which is the result of the operation.
+ * @throws CommandException
+ */
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ List lastShownList = model.getFilteredPatientList();
+
+ if (index.getZeroBased() >= lastShownList.size()) {
+ throw new CommandException(Messages.MESSAGE_INVALID_PATIENT_DISPLAYED_INDEX);
+ }
+
+ Patient patientToEdit = lastShownList.get(index.getZeroBased());
+ Patient editedPatient = createEditedPatient(patientToEdit, editPatientDescriptor);
+
+ if (!patientToEdit.isSamePatient(editedPatient) && model.hasPatient(editedPatient)) {
+ throw new CommandException(MESSAGE_DUPLICATE_PATIENT);
+ }
+
+ if (!model.hasWard(editedPatient.getWard())) {
+ throw new CommandException(MESSAGE_WARD_NOT_FOUND);
+ }
+
+ model.setPatient(patientToEdit, editedPatient);
+ model.updateFilteredPatientList(PREDICATE_SHOW_ALL_PATIENTS);
+ return new CommandResult(String.format(MESSAGE_EDIT_PATIENT_SUCCESS, editedPatient));
+ }
+
+ /**
+ * Creates and returns a {@code Patient} with the details of
+ * {@code patientToEdit}
+ * edited with {@code editPatientDescriptor}.
+ */
+ private static Patient createEditedPatient(Patient patientToEdit, EditPatientDescriptor editPatientDescriptor) {
+ assert patientToEdit != null;
+
+ Name updatedName = editPatientDescriptor.getName().orElse((Name) patientToEdit.getName());
+ Nric updatedNric = editPatientDescriptor.getNric().orElse((Nric) patientToEdit.getNric());
+ Status updatedStatus = editPatientDescriptor.getStatus().orElse((Status) patientToEdit.getStatus());
+ WardName updatedWard = editPatientDescriptor.getWard().orElse(patientToEdit.getWardName());
+ Discharge updatedDischarge = editPatientDescriptor.getDischarge()
+ .orElse((Discharge) patientToEdit.getDischarge());
+
+ return new Patient(updatedNric, updatedName, updatedStatus, updatedWard, updatedDischarge);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ // short circuit if same object
+ if (other == this) {
+ return true;
+ }
+
+ // instanceof handles nulls
+ if (!(other instanceof EditCommand)) {
+ return false;
+ }
+
+ // state check
+ EditCommand e = (EditCommand) other;
+ return index.equals(e.index)
+ && editPatientDescriptor.equals(e.editPatientDescriptor);
+ }
+
+ /**
+ * Stores the details to edit the patient with. Each non-empty field value will
+ * replace the
+ * corresponding field value of the patient.
+ */
+ public static class EditPatientDescriptor {
+ private Name name;
+ private Nric nric;
+ private Status status;
+ private WardName ward;
+ private Discharge discharge;
+
+ public EditPatientDescriptor() {
+ }
+
+ /**
+ * Copy constructor.
+ * A defensive copy of {@code tags} is used internally.
+ */
+ public EditPatientDescriptor(EditPatientDescriptor toCopy) {
+ setName(toCopy.name);
+ setNric(toCopy.nric);
+ setStatus(toCopy.status);
+ setWard(toCopy.ward);
+ setDischarge(toCopy.discharge);
+
+ }
+
+ /**
+ * Returns true if at least one field is edited.
+ */
+ public boolean isAnyFieldEdited() {
+ return CollectionUtil.isAnyNonNull(name, nric, status, ward, discharge);
+ }
+
+ public void setName(Name name) {
+ this.name = name;
+ }
+
+ public void setNric(Nric nric) {
+ this.nric = nric;
+ }
+
+ public void setStatus(Status status) {
+ this.status = status;
+ }
+
+ public void setWard(WardName ward) {
+ this.ward = ward;
+ }
+
+ public void setDischarge(Discharge discharge) {
+ this.discharge = discharge;
+ }
+
+ public Optional getName() {
+ return Optional.ofNullable(name);
+ }
+
+ public Optional getNric() {
+ return Optional.ofNullable(nric);
+ }
+
+ public Optional getStatus() {
+ return Optional.ofNullable(status);
+ }
+
+ public Optional getWard() {
+ return Optional.ofNullable(ward);
+ }
+
+ public Optional getDischarge() {
+ return Optional.ofNullable(discharge);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ // short circuit if same object
+ if (other == this) {
+ return true;
+ }
+
+ // instanceof handles nulls
+ if (!(other instanceof EditPatientDescriptor)) {
+ return false;
+ }
+
+ // state check
+ EditPatientDescriptor e = (EditPatientDescriptor) other;
+
+ return getName().equals(e.getName())
+ && getNric().equals(e.getNric())
+ && getStatus().equals(e.getStatus())
+ && getWard().equals(e.getWard())
+ && getDischarge().equals(e.getDischarge());
+ }
+ }
+}
diff --git a/src/main/java/seedu/medinfo/logic/commands/EditWardCommand.java b/src/main/java/seedu/medinfo/logic/commands/EditWardCommand.java
new file mode 100644
index 00000000000..f0a0eda4e91
--- /dev/null
+++ b/src/main/java/seedu/medinfo/logic/commands/EditWardCommand.java
@@ -0,0 +1,185 @@
+package seedu.medinfo.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.medinfo.logic.parser.CliSyntax.PREFIX_CAPACITY;
+import static seedu.medinfo.logic.parser.CliSyntax.PREFIX_WARD;
+import static seedu.medinfo.model.Model.PREDICATE_SHOW_ALL_PATIENTS;
+
+import java.util.List;
+import java.util.Optional;
+
+import seedu.medinfo.commons.core.Messages;
+import seedu.medinfo.commons.core.index.Index;
+import seedu.medinfo.commons.util.CollectionUtil;
+import seedu.medinfo.logic.commands.exceptions.CommandException;
+import seedu.medinfo.model.Model;
+import seedu.medinfo.model.ward.Capacity;
+import seedu.medinfo.model.ward.Ward;
+import seedu.medinfo.model.ward.WardName;
+
+/**
+ * Edits the details of an existing patient in the medinfo book.
+ */
+public class EditWardCommand extends Command {
+
+ public static final String COMMAND_WORD = "editward";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Edits the ward name or capacity "
+ + "of the ward identified by the index number used in the displayed ward list. "
+ + "Existing values will be overwritten by the input values.\n"
+ + "Parameters: INDEX (must be a positive integer) "
+ + "[" + PREFIX_WARD + "WARD " + PREFIX_CAPACITY + "CAPACITY]\n"
+ + "Example: " + COMMAND_WORD + " 1 "
+ + PREFIX_WARD + "A1" + " " + PREFIX_CAPACITY + "35";
+
+ public static final String MESSAGE_EDIT_PATIENT_SUCCESS = "Edited Ward: %1$s";
+ public static final String MESSAGE_NOT_EDITED = "At least one field to edit must be provided.";
+ public static final String MESSAGE_DUPLICATE_WARD = "This ward already exists in MedInfo.";
+ public static final String MESSAGE_EDITED_WARD_INSUFFICIENT_CAPACITY = "The given capacity is insufficient"
+ + " for this ward.";
+ public static final String MESSAGE_WAITING_ROOM_NAME_EDIT = "Waiting Room name cannot be edited.";
+ private final Index index;
+ private final EditWardDescriptor editWardDescriptor;
+
+ /**
+ * Constructs {@code EditWardCommand} to edit {@code Ward} at specified index.
+ * @param index Index of the {@code Ward} to be edited in the list.
+ * @param editWardDescriptor Description of the {@code Ward} details to be edited.
+ */
+ public EditWardCommand(Index index, EditWardDescriptor editWardDescriptor) {
+ requireNonNull(index);
+ requireNonNull(editWardDescriptor);
+
+ this.index = index;
+ this.editWardDescriptor = new EditWardDescriptor(editWardDescriptor);
+ }
+
+ /**
+ * Executes the {@code EditWardCommand} on the given model.
+ * @param model {@code Model} which the command should operate on.
+ * @return CommandResult which is the result of the operation.
+ * @throws CommandException
+ */
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ List lastShownList = model.getFilteredWardList();
+
+ if (index.getZeroBased() >= lastShownList.size()) {
+ throw new CommandException(Messages.MESSAGE_INVALID_WARD_DISPLAYED_INDEX);
+ }
+
+ Ward wardToEdit = lastShownList.get(index.getZeroBased());
+ Ward editedWard = createEditedWard(wardToEdit, editWardDescriptor);
+
+ if (!wardToEdit.isSameWard(editedWard) && model.hasWard(editedWard)) {
+ throw new CommandException(MESSAGE_DUPLICATE_WARD);
+ }
+
+ if (!editedWard.canSupport(wardToEdit.getOccupancy())) {
+ throw new CommandException(MESSAGE_EDITED_WARD_INSUFFICIENT_CAPACITY);
+ }
+
+ model.setWard(wardToEdit, editedWard);
+ model.updateFilteredPatientList(PREDICATE_SHOW_ALL_PATIENTS);
+ return new CommandResult(String.format(MESSAGE_EDIT_PATIENT_SUCCESS, editedWard));
+ }
+
+ /**
+ * Creates and returns a {@code Patient} with the details of
+ * {@code wardToEdit}
+ * edited with {@code editWardDescriptor}.
+ */
+ private static Ward createEditedWard(Ward wardToEdit, EditWardDescriptor editWardDescriptor) {
+ assert wardToEdit != null;
+
+ WardName updatedName = editWardDescriptor.getWard().orElse(wardToEdit.getName());
+
+ Capacity updatedCapacity = editWardDescriptor.getCapacity()
+ .orElse(wardToEdit.getCapacity());
+
+ return new Ward(updatedName, updatedCapacity);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ // short circuit if same object
+ if (other == this) {
+ return true;
+ }
+
+ // instanceof handles nulls
+ if (!(other instanceof EditWardCommand)) {
+ return false;
+ }
+
+ // state check
+ EditWardCommand e = (EditWardCommand) other;
+ return index.equals(e.index)
+ && editWardDescriptor.equals(e.editWardDescriptor);
+ }
+
+ /**
+ * Stores the details to edit the patient with. Each non-empty field value will
+ * replace the
+ * corresponding field value of the patient.
+ */
+ public static class EditWardDescriptor {
+ private WardName ward;
+ private Capacity capacity;
+
+ public EditWardDescriptor() {
+ }
+
+ /**
+ * Copy constructor.
+ * A defensive copy of {@code tags} is used internally.
+ */
+ public EditWardDescriptor(EditWardDescriptor toCopy) {
+ setWard(toCopy.ward);
+ setCapacity(toCopy.capacity);
+ }
+
+ /**
+ * Returns true if at least one field is edited.
+ */
+ public boolean isAnyFieldEdited() {
+ return CollectionUtil.isAnyNonNull(ward, capacity);
+ }
+
+ public void setWard(WardName ward) {
+ this.ward = ward;
+ }
+
+ public void setCapacity(Capacity capacity) {
+ this.capacity = capacity;
+ }
+
+ public Optional getWard() {
+ return Optional.ofNullable(ward);
+ }
+
+ public Optional getCapacity() {
+ return Optional.ofNullable(capacity);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ // short circuit if same object
+ if (other == this) {
+ return true;
+ }
+
+ // instanceof handles nulls
+ if (!(other instanceof EditWardDescriptor)) {
+ return false;
+ }
+
+ // state check
+ EditWardDescriptor e = (EditWardDescriptor) other;
+
+ return getWard().equals(e.getWard())
+ && getCapacity().equals(e.getCapacity());
+ }
+ }
+}
diff --git a/src/main/java/seedu/medinfo/logic/commands/ExitCommand.java b/src/main/java/seedu/medinfo/logic/commands/ExitCommand.java
new file mode 100644
index 00000000000..84f9fd54abc
--- /dev/null
+++ b/src/main/java/seedu/medinfo/logic/commands/ExitCommand.java
@@ -0,0 +1,26 @@
+package seedu.medinfo.logic.commands;
+
+import seedu.medinfo.logic.commands.exceptions.CommandException;
+import seedu.medinfo.model.Model;
+
+/**
+ * Terminates the program.
+ */
+public class ExitCommand extends Command {
+
+ public static final String COMMAND_WORD = "exit";
+
+ public static final String MESSAGE_EXIT_ACKNOWLEDGEMENT = "Exiting MedInfo as requested ...";
+
+ /**
+ * Executes the {@code ExitCommand} on the given model.
+ * @param model {@code Model} which the command should operate on.
+ * @return CommandResult which is the result of the operation.
+ * @throws CommandException
+ */
+ @Override
+ public CommandResult execute(Model model) {
+ return new CommandResult(MESSAGE_EXIT_ACKNOWLEDGEMENT, false, true);
+ }
+
+}
diff --git a/src/main/java/seedu/medinfo/logic/commands/FindCommand.java b/src/main/java/seedu/medinfo/logic/commands/FindCommand.java
new file mode 100644
index 00000000000..459caa1ed30
--- /dev/null
+++ b/src/main/java/seedu/medinfo/logic/commands/FindCommand.java
@@ -0,0 +1,80 @@
+package seedu.medinfo.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.medinfo.logic.parser.CliSyntax.PREFIX_NAME;
+import static seedu.medinfo.logic.parser.CliSyntax.PREFIX_NRIC;
+import static seedu.medinfo.logic.parser.CliSyntax.PREFIX_STATUS;
+import static seedu.medinfo.logic.parser.CliSyntax.PREFIX_WARD;
+import static seedu.medinfo.model.Model.PREDICATE_SHOW_ALL_PATIENTS;
+
+import java.util.function.Predicate;
+
+import seedu.medinfo.commons.core.Messages;
+import seedu.medinfo.logic.commands.exceptions.CommandException;
+import seedu.medinfo.model.Model;
+import seedu.medinfo.model.patient.Patient;
+
+/**
+ * Finds and lists all patients in MedInfo whose name contains any of the
+ * argument keywords.
+ * Keyword matching is case-insensitive.
+ */
+public class FindCommand extends Command {
+
+ public static final String COMMAND_WORD = "find";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + " "
+ + PREFIX_NAME
+ + ": Finds all patients whose names contain any of "
+ + "the specified keywords (case-insensitive) and displays them as a list with index numbers.\n"
+ + "Parameters: KEYWORD [MORE_KEYWORDS]...\n"
+ + "Example: " + COMMAND_WORD + " " + PREFIX_NAME + " alice bob charlie\n"
+ + COMMAND_WORD + " " + PREFIX_NRIC
+ + ": Finds all patients whose NRIC matches any of "
+ + "the specified keywords (case-insensitive) and displays them as a list with index numbers.\n"
+ + "Parameters: KEYWORD [MORE_KEYWORDS]...\n"
+ + "Example: " + COMMAND_WORD + " " + PREFIX_NRIC + " S1234567A\n"
+ + COMMAND_WORD + " " + PREFIX_STATUS
+ + ": Finds all patients whose Status is any of "
+ + "the specified keywords (case-insensitive) and displays them as a list with index numbers.\n"
+ + "Parameters: KEYWORD [MORE_KEYWORDS]...\n"
+ + "Example: " + COMMAND_WORD + " " + PREFIX_STATUS + " GRAY GREEN\n"
+ + COMMAND_WORD + " " + PREFIX_WARD
+ + ": Finds all patients whose ward is any of "
+ + "the specified keywords (case-insensitive) and displays them as a list with index numbers.\n"
+ + "Parameters: KEYWORD [MORE_KEYWORDS]...\n"
+ + "Example: " + COMMAND_WORD + " " + PREFIX_WARD + " A03\n";
+
+ private final Predicate predicate;
+
+ /**
+ * Constructs a {@code FindCommand} to display {@code Patients} which meet the given predicate.
+ * @param predicate Condition to be met by the displayed {@code Patients}.
+ */
+ public FindCommand(Predicate predicate) {
+ this.predicate = predicate;
+ }
+
+ /**
+ * Executes the {@code FindCommand} on the given model.
+ * @param model {@code Model} which the command should operate on.
+ * @return CommandResult which is the result of the operation.
+ * @throws CommandException
+ */
+ @Override
+ public CommandResult execute(Model model) {
+ requireNonNull(model);
+ model.updateFilteredPatientList(PREDICATE_SHOW_ALL_PATIENTS);
+ int total = model.getFilteredPatientList().size();
+ model.updateFilteredPatientList(predicate);
+ return new CommandResult(
+ String.format(Messages.MESSAGE_PATIENTS_LISTED_OVERVIEW, model.getFilteredPatientList().size(), total));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof FindCommand // instanceof handles nulls
+ && predicate.equals(((FindCommand) other).predicate)); // state check
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/HelpCommand.java b/src/main/java/seedu/medinfo/logic/commands/HelpCommand.java
similarity index 58%
rename from src/main/java/seedu/address/logic/commands/HelpCommand.java
rename to src/main/java/seedu/medinfo/logic/commands/HelpCommand.java
index bf824f91bd0..9e62b785bf0 100644
--- a/src/main/java/seedu/address/logic/commands/HelpCommand.java
+++ b/src/main/java/seedu/medinfo/logic/commands/HelpCommand.java
@@ -1,6 +1,7 @@
-package seedu.address.logic.commands;
+package seedu.medinfo.logic.commands;
-import seedu.address.model.Model;
+import seedu.medinfo.logic.commands.exceptions.CommandException;
+import seedu.medinfo.model.Model;
/**
* Format full help instructions for every command for display.
@@ -14,6 +15,12 @@ public class HelpCommand extends Command {
public static final String SHOWING_HELP_MESSAGE = "Opened help window.";
+ /**
+ * Executes the {@code HelpCommand} on the given model.
+ * @param model {@code Model} which the command should operate on.
+ * @return CommandResult which is the result of the operation.
+ * @throws CommandException
+ */
@Override
public CommandResult execute(Model model) {
return new CommandResult(SHOWING_HELP_MESSAGE, true, false);
diff --git a/src/main/java/seedu/medinfo/logic/commands/ListCommand.java b/src/main/java/seedu/medinfo/logic/commands/ListCommand.java
new file mode 100644
index 00000000000..4d10a70e9ac
--- /dev/null
+++ b/src/main/java/seedu/medinfo/logic/commands/ListCommand.java
@@ -0,0 +1,30 @@
+package seedu.medinfo.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.medinfo.model.Model.PREDICATE_SHOW_ALL_PATIENTS;
+
+import seedu.medinfo.commons.core.Messages;
+import seedu.medinfo.logic.commands.exceptions.CommandException;
+import seedu.medinfo.model.Model;
+
+/**
+ * Lists all patients in MedInfo to the user.
+ */
+public class ListCommand extends Command {
+
+ public static final String COMMAND_WORD = "list";
+
+ /**
+ * Executes the {@code ListCommand} on the given model.
+ * @param model {@code Model} which the command should operate on.
+ * @return CommandResult which is the result of the operation.
+ * @throws CommandException
+ */
+ @Override
+ public CommandResult execute(Model model) {
+ requireNonNull(model);
+ model.updateFilteredPatientList(PREDICATE_SHOW_ALL_PATIENTS);
+ return new CommandResult(
+ String.format(Messages.MESSAGE_ALL_PATIENTS_LISTED_OVERVIEW, model.getFilteredPatientList().size()));
+ }
+}
diff --git a/src/main/java/seedu/medinfo/logic/commands/SortCommand.java b/src/main/java/seedu/medinfo/logic/commands/SortCommand.java
new file mode 100644
index 00000000000..9dc5e32ec79
--- /dev/null
+++ b/src/main/java/seedu/medinfo/logic/commands/SortCommand.java
@@ -0,0 +1,139 @@
+package seedu.medinfo.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.medinfo.logic.parser.CliSyntax.PREFIX_DISCHARGE;
+import static seedu.medinfo.logic.parser.CliSyntax.PREFIX_NAME;
+import static seedu.medinfo.logic.parser.CliSyntax.PREFIX_STATUS;
+import static seedu.medinfo.logic.parser.CliSyntax.PREFIX_WARD;
+
+import java.util.Comparator;
+
+import seedu.medinfo.logic.commands.exceptions.CommandException;
+import seedu.medinfo.model.Model;
+import seedu.medinfo.model.patient.Patient;
+
+
+
+/**
+ * Sort all patients in MedInfo based on the field and the order.
+ */
+
+// Solution below adapted from
+// https://github.com/AY2223S1-CS2103T-T09-4/tp/blob/master/src/main/java/seedu/address/logic/commands/SortCommand.java
+public class SortCommand extends Command {
+
+ public static final String COMMAND_WORD = "sort";
+
+ public static final String MESSAGE_UNKNOWN_ORDER_KEYWORD =
+ "The order of Sort Command should be 'ASC' or 'DESC'.";
+ public static final String MESSAGE_UNKNOWN_TYPE_KEYWORD = "You may only sort by 'name', 'status', 'discharge date'"
+ + "or 'ward name' "
+ + "followed by 'asc' or 'desc' order.\n"
+ + "Example: sort name/asc";
+
+ public static final String MESSAGE_SUCCESS = "Sorted all patients by the given order\n";
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + " " + PREFIX_NAME
+ + ": Sorts the list of all patients by name. \n"
+ + "Parameters: asc/desc\n"
+ + "Example: " + COMMAND_WORD + " " + PREFIX_NAME + "asc\n"
+ + COMMAND_WORD + " " + PREFIX_STATUS
+ + ": Sorts all patients by status. \n"
+ + "Parameters: asc/desc\n"
+ + "Example: " + COMMAND_WORD + " " + PREFIX_STATUS + "asc\n"
+ + COMMAND_WORD + " " + PREFIX_DISCHARGE
+ + ": Sorts all patients by discharge date. \n"
+ + "Parameters: asc/desc\n"
+ + "Example: " + COMMAND_WORD + " " + PREFIX_DISCHARGE + "asc\n"
+ + COMMAND_WORD + " " + PREFIX_WARD
+ + ": Sorts all patients by ward name. \n"
+ + "Parameters: asc/desc\n"
+ + "Example: " + COMMAND_WORD + " " + PREFIX_WARD + "asc\n";
+
+ /**
+ * {@code FIELD} specifies what possible types {@code SortCommand} can accept.
+ */
+ public static enum Field {
+ NAME,
+ STATUS,
+ DISCHARGE,
+ WARD
+ };
+
+ /**
+ * {@code ORDER} specifies what possible order {@code SortCommand} can accept.
+ */
+ public static enum Order {
+ ASC,
+ DESC
+ };
+
+ private final Comparator comparator;
+
+ /**
+ * Constructs a {@code SortCommand} to sort {@code Patients} by the given field in the given order.
+ * @param field The {@code Patient} field to be sorted by.
+ * @param order The order for {@code Patients} to be displayed.
+ */
+ public SortCommand(Field field, Order order) {
+ this.comparator = generateComparator(field, order);
+ }
+
+ /**
+ * Generates a Comparator for {@code Patients} based on parameters.
+ *
+ * @param field field of attribute to be compared
+ * @param order order of sorting
+ */
+ public static Comparator generateComparator(Field field, Order order) {
+ switch (field) {
+ case NAME:
+ if (order.equals(Order.ASC)) {
+ return Patient::compareToByNameAsc;
+ } else {
+ return Patient::compareToByNameDesc;
+ }
+ case STATUS:
+ if (order.equals(Order.ASC)) {
+ return Patient::compareToByStatusAsc;
+ } else {
+ return Patient::compareToByStatusDesc;
+ }
+ case DISCHARGE:
+ if (order.equals(Order.ASC)) {
+ return Patient::compareToByDischargeAsc;
+ } else {
+ return Patient::compareToByDischargeDesc;
+ }
+ case WARD:
+ if (order.equals(Order.ASC)) {
+ return Patient::compareToByWardAsc;
+ } else {
+ return Patient::compareToByWardDesc;
+ }
+ default:
+ // default sorting order is by Name Asc
+ return Patient::compareToByNameAsc;
+ }
+ }
+
+ /**
+ * Executes the {@code SortCommand} on the given model.
+ * @param model {@code Model} which the command should operate on.
+ * @return CommandResult which is the result of the operation.
+ * @throws CommandException
+ */
+ @Override
+ public CommandResult execute(Model model) {
+ requireNonNull(model);
+ model.sortPatients(this.comparator);
+ return new CommandResult(MESSAGE_SUCCESS);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return this == other // short circuit if same object
+ || (other instanceof SortCommand // instanceof handles null
+ && this.comparator.equals(((SortCommand) other).comparator)); // state check
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/exceptions/CommandException.java b/src/main/java/seedu/medinfo/logic/commands/exceptions/CommandException.java
similarity index 82%
rename from src/main/java/seedu/address/logic/commands/exceptions/CommandException.java
rename to src/main/java/seedu/medinfo/logic/commands/exceptions/CommandException.java
index a16bd14f2cd..775bf4e2cc3 100644
--- a/src/main/java/seedu/address/logic/commands/exceptions/CommandException.java
+++ b/src/main/java/seedu/medinfo/logic/commands/exceptions/CommandException.java
@@ -1,4 +1,6 @@
-package seedu.address.logic.commands.exceptions;
+package seedu.medinfo.logic.commands.exceptions;
+
+import seedu.medinfo.logic.commands.Command;
/**
* Represents an error which occurs during execution of a {@link Command}.
diff --git a/src/main/java/seedu/medinfo/logic/parser/AddCommandParser.java b/src/main/java/seedu/medinfo/logic/parser/AddCommandParser.java
new file mode 100644
index 00000000000..15e189e1316
--- /dev/null
+++ b/src/main/java/seedu/medinfo/logic/parser/AddCommandParser.java
@@ -0,0 +1,64 @@
+package seedu.medinfo.logic.parser;
+
+import static seedu.medinfo.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.medinfo.logic.parser.CliSyntax.PREFIX_NAME;
+import static seedu.medinfo.logic.parser.CliSyntax.PREFIX_NRIC;
+import static seedu.medinfo.logic.parser.CliSyntax.PREFIX_STATUS;
+
+import java.util.stream.Stream;
+
+import seedu.medinfo.logic.commands.AddCommand;
+import seedu.medinfo.logic.parser.exceptions.ParseException;
+import seedu.medinfo.model.patient.Name;
+import seedu.medinfo.model.patient.Nric;
+import seedu.medinfo.model.patient.Patient;
+import seedu.medinfo.model.patient.Status;
+
+/**
+ * Parses input arguments and creates a new AddCommand object
+ */
+public class AddCommandParser implements Parser {
+
+ /**
+ * Parses the given {@code String} of arguments in the context of the {@code AddCommand}
+ * and returns an {@code AddCommand} object for execution.
+ *
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public AddCommand parse(String args) throws ParseException {
+
+ ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_NRIC, PREFIX_STATUS);
+
+ if (!arePrefixesPresent(argMultimap, PREFIX_NAME, PREFIX_NRIC)
+ || !argMultimap.getPreamble().isEmpty()) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE));
+ }
+
+ Name name = ParserUtil.parseName(argMultimap.getValue(PREFIX_NAME).get());
+ assert (name != null);
+ Nric nric = ParserUtil.parseNric(argMultimap.getValue(PREFIX_NRIC).get());
+ assert (nric != null);
+
+ Patient patient;
+
+ if (arePrefixesPresent(argMultimap, PREFIX_STATUS)) {
+ Status status = ParserUtil.parseStatus(argMultimap.getValue(PREFIX_STATUS).get());
+ assert(status != null);
+ patient = new Patient(nric, name, status);
+ } else {
+ patient = new Patient(nric, name);
+ }
+
+ return new AddCommand(patient);
+ }
+
+ /**
+ * Returns true if none of the prefixes contains empty {@code Optional} values
+ * in the given
+ * {@code ArgumentMultimap}.
+ */
+ private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) {
+ return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent());
+ }
+
+}
diff --git a/src/main/java/seedu/medinfo/logic/parser/AddWardCommandParser.java b/src/main/java/seedu/medinfo/logic/parser/AddWardCommandParser.java
new file mode 100644
index 00000000000..303fc4e09e7
--- /dev/null
+++ b/src/main/java/seedu/medinfo/logic/parser/AddWardCommandParser.java
@@ -0,0 +1,56 @@
+package seedu.medinfo.logic.parser;
+
+import static seedu.medinfo.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.medinfo.logic.parser.CliSyntax.PREFIX_CAPACITY;
+import static seedu.medinfo.logic.parser.CliSyntax.PREFIX_WARD;
+
+import java.util.stream.Stream;
+
+import seedu.medinfo.logic.commands.AddWardCommand;
+import seedu.medinfo.logic.parser.exceptions.ParseException;
+import seedu.medinfo.model.ward.Capacity;
+import seedu.medinfo.model.ward.Ward;
+import seedu.medinfo.model.ward.WardName;
+
+
+/**
+ * Parses input arguments and creates a new AddWardCommand object
+ */
+public class AddWardCommandParser implements Parser {
+
+ /**
+ * Parses the given {@code String} of arguments in the context of the {@code AddWardCommand}
+ * and returns an {@code AddWardCommand} object for execution.
+ *
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public AddWardCommand parse(String args) throws ParseException {
+
+ ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, PREFIX_WARD, PREFIX_CAPACITY);
+
+ if (!arePrefixesPresent(argMultimap, PREFIX_WARD)
+ || !argMultimap.getPreamble().isEmpty()) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddWardCommand.MESSAGE_USAGE));
+ }
+
+ if (!arePrefixesPresent(argMultimap, PREFIX_CAPACITY)) {
+ WardName wardName = ParserUtil.parseWardName(argMultimap.getValue(PREFIX_WARD).get());
+ Ward ward = new Ward(wardName);
+ return new AddWardCommand(ward);
+ }
+
+ WardName wardName = ParserUtil.parseWardName(argMultimap.getValue(PREFIX_WARD).get());
+ Capacity wardCapacity = ParserUtil.parseCapacity(argMultimap.getValue(PREFIX_CAPACITY).get());
+ Ward ward = new Ward(wardName, wardCapacity);
+ return new AddWardCommand(ward);
+ }
+
+ /**
+ * Returns true if none of the prefixes contains empty {@code Optional} values
+ * in the given
+ * {@code ArgumentMultimap}.
+ */
+ private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) {
+ return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent());
+ }
+}
diff --git a/src/main/java/seedu/address/logic/parser/ArgumentMultimap.java b/src/main/java/seedu/medinfo/logic/parser/ArgumentMultimap.java
similarity index 98%
rename from src/main/java/seedu/address/logic/parser/ArgumentMultimap.java
rename to src/main/java/seedu/medinfo/logic/parser/ArgumentMultimap.java
index 954c8e18f8e..e9f5ac17de1 100644
--- a/src/main/java/seedu/address/logic/parser/ArgumentMultimap.java
+++ b/src/main/java/seedu/medinfo/logic/parser/ArgumentMultimap.java
@@ -1,4 +1,4 @@
-package seedu.address.logic.parser;
+package seedu.medinfo.logic.parser;
import java.util.ArrayList;
import java.util.HashMap;
diff --git a/src/main/java/seedu/address/logic/parser/ArgumentTokenizer.java b/src/main/java/seedu/medinfo/logic/parser/ArgumentTokenizer.java
similarity index 99%
rename from src/main/java/seedu/address/logic/parser/ArgumentTokenizer.java
rename to src/main/java/seedu/medinfo/logic/parser/ArgumentTokenizer.java
index 5c9aebfa488..bdadbd3c5bc 100644
--- a/src/main/java/seedu/address/logic/parser/ArgumentTokenizer.java
+++ b/src/main/java/seedu/medinfo/logic/parser/ArgumentTokenizer.java
@@ -1,4 +1,4 @@
-package seedu.address.logic.parser;
+package seedu.medinfo.logic.parser;
import java.util.ArrayList;
import java.util.Arrays;
diff --git a/src/main/java/seedu/medinfo/logic/parser/CliSyntax.java b/src/main/java/seedu/medinfo/logic/parser/CliSyntax.java
new file mode 100644
index 00000000000..a2a89bc017a
--- /dev/null
+++ b/src/main/java/seedu/medinfo/logic/parser/CliSyntax.java
@@ -0,0 +1,16 @@
+package seedu.medinfo.logic.parser;
+
+/**
+ * Contains Command Line Interface (CLI) syntax definitions common to multiple
+ * commands
+ */
+public class CliSyntax {
+
+ /* Prefix definitions */
+ public static final Prefix PREFIX_NRIC = new Prefix("nric/");
+ public static final Prefix PREFIX_NAME = new Prefix("name/");
+ public static final Prefix PREFIX_STATUS = new Prefix("s/");
+ public static final Prefix PREFIX_WARD = new Prefix("w/");
+ public static final Prefix PREFIX_DISCHARGE = new Prefix("d/");
+ public static final Prefix PREFIX_CAPACITY = new Prefix("c/");
+}
diff --git a/src/main/java/seedu/address/logic/parser/DeleteCommandParser.java b/src/main/java/seedu/medinfo/logic/parser/DeleteCommandParser.java
similarity index 66%
rename from src/main/java/seedu/address/logic/parser/DeleteCommandParser.java
rename to src/main/java/seedu/medinfo/logic/parser/DeleteCommandParser.java
index 522b93081cc..d8a36c9cb9e 100644
--- a/src/main/java/seedu/address/logic/parser/DeleteCommandParser.java
+++ b/src/main/java/seedu/medinfo/logic/parser/DeleteCommandParser.java
@@ -1,10 +1,10 @@
-package seedu.address.logic.parser;
+package seedu.medinfo.logic.parser;
-import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.medinfo.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
-import seedu.address.commons.core.index.Index;
-import seedu.address.logic.commands.DeleteCommand;
-import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.medinfo.commons.core.index.Index;
+import seedu.medinfo.logic.commands.DeleteCommand;
+import seedu.medinfo.logic.parser.exceptions.ParseException;
/**
* Parses input arguments and creates a new DeleteCommand object
@@ -12,8 +12,8 @@
public class DeleteCommandParser implements Parser {
/**
- * Parses the given {@code String} of arguments in the context of the DeleteCommand
- * and returns a DeleteCommand object for execution.
+ * Parses the given {@code String} of arguments in the context of the {@code DeleteCommand}
+ * and returns a {@code DeleteCommand} object for execution.
* @throws ParseException if the user input does not conform the expected format
*/
public DeleteCommand parse(String args) throws ParseException {
diff --git a/src/main/java/seedu/medinfo/logic/parser/DeleteWardCommandParser.java b/src/main/java/seedu/medinfo/logic/parser/DeleteWardCommandParser.java
new file mode 100644
index 00000000000..10947c52e82
--- /dev/null
+++ b/src/main/java/seedu/medinfo/logic/parser/DeleteWardCommandParser.java
@@ -0,0 +1,29 @@
+package seedu.medinfo.logic.parser;
+
+import static seedu.medinfo.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+
+import seedu.medinfo.commons.core.index.Index;
+import seedu.medinfo.logic.commands.DeleteWardCommand;
+import seedu.medinfo.logic.parser.exceptions.ParseException;
+
+/**
+ * Parses input arguments and creates a new DeleteWardCommand object
+ */
+public class DeleteWardCommandParser implements Parser {
+
+ /**
+ * Parses the given {@code String} of arguments in the context of the {@code DeleteWardCommand}
+ * and returns a {@code DeleteWardCommand} object for execution.
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public DeleteWardCommand parse(String args) throws ParseException {
+ try {
+ Index index = ParserUtil.parseIndex(args);
+ return new DeleteWardCommand(index);
+ } catch (ParseException pe) {
+ throw new ParseException(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteWardCommand.MESSAGE_USAGE), pe);
+ }
+ }
+
+}
diff --git a/src/main/java/seedu/medinfo/logic/parser/EditCommandParser.java b/src/main/java/seedu/medinfo/logic/parser/EditCommandParser.java
new file mode 100644
index 00000000000..2864938d9c9
--- /dev/null
+++ b/src/main/java/seedu/medinfo/logic/parser/EditCommandParser.java
@@ -0,0 +1,56 @@
+package seedu.medinfo.logic.parser;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.medinfo.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.medinfo.logic.parser.CliSyntax.PREFIX_DISCHARGE;
+import static seedu.medinfo.logic.parser.CliSyntax.PREFIX_STATUS;
+import static seedu.medinfo.logic.parser.CliSyntax.PREFIX_WARD;
+
+import seedu.medinfo.commons.core.index.Index;
+import seedu.medinfo.logic.commands.EditCommand;
+import seedu.medinfo.logic.commands.EditCommand.EditPatientDescriptor;
+import seedu.medinfo.logic.parser.exceptions.ParseException;
+
+/**
+ * Parses input arguments and creates a new EditCommand object
+ */
+public class EditCommandParser implements Parser {
+
+ /**
+ * Parses the given {@code String} of arguments in the context of the
+ * {@code EditCommand}
+ * and returns an {@code EditCommand} object for execution.
+ *
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public EditCommand parse(String args) throws ParseException {
+ requireNonNull(args);
+ ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, PREFIX_STATUS, PREFIX_WARD, PREFIX_DISCHARGE);
+
+ Index index;
+
+ try {
+ index = ParserUtil.parseIndex(argMultimap.getPreamble());
+ } catch (ParseException pe) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditCommand.MESSAGE_USAGE), pe);
+ }
+
+ EditPatientDescriptor editPatientDescriptor = new EditCommand.EditPatientDescriptor();
+ if (argMultimap.getValue(PREFIX_STATUS).isPresent()) {
+ editPatientDescriptor.setStatus(ParserUtil.parseStatus(argMultimap.getValue(PREFIX_STATUS).get()));
+ }
+ if (argMultimap.getValue(PREFIX_WARD).isPresent()) {
+ editPatientDescriptor.setWard(ParserUtil.parseWardName(argMultimap.getValue(PREFIX_WARD).get()));
+ }
+ if (argMultimap.getValue(PREFIX_DISCHARGE).isPresent()) {
+ editPatientDescriptor.setDischarge(ParserUtil.parseDischarge(argMultimap.getValue(PREFIX_DISCHARGE).get()));
+ }
+
+ if (!editPatientDescriptor.isAnyFieldEdited()) {
+ throw new ParseException(EditCommand.MESSAGE_NOT_EDITED);
+ }
+
+ return new EditCommand(index, editPatientDescriptor);
+ }
+
+}
diff --git a/src/main/java/seedu/medinfo/logic/parser/EditWardCommandParser.java b/src/main/java/seedu/medinfo/logic/parser/EditWardCommandParser.java
new file mode 100644
index 00000000000..6efa256a764
--- /dev/null
+++ b/src/main/java/seedu/medinfo/logic/parser/EditWardCommandParser.java
@@ -0,0 +1,56 @@
+package seedu.medinfo.logic.parser;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.medinfo.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.medinfo.logic.parser.CliSyntax.PREFIX_CAPACITY;
+import static seedu.medinfo.logic.parser.CliSyntax.PREFIX_WARD;
+
+import seedu.medinfo.commons.core.index.Index;
+import seedu.medinfo.logic.commands.EditWardCommand;
+import seedu.medinfo.logic.commands.EditWardCommand.EditWardDescriptor;
+import seedu.medinfo.logic.parser.exceptions.ParseException;
+
+/**
+ * Parses input arguments and creates a new EditCommand object
+ */
+public class EditWardCommandParser implements Parser {
+
+ /**
+ * Parses the given {@code String} of arguments in the context of the
+ * {@code EditWardCommand}
+ * and returns an {@code EditWardCommand} object for execution.
+ *
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public EditWardCommand parse(String args) throws ParseException {
+ requireNonNull(args);
+ ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, PREFIX_WARD, PREFIX_CAPACITY);
+
+ Index index;
+
+ try {
+ index = ParserUtil.parseIndex(argMultimap.getPreamble());
+ } catch (ParseException pe) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditWardCommand.MESSAGE_USAGE), pe);
+ }
+
+ EditWardDescriptor editWardDescriptor = new EditWardCommand.EditWardDescriptor();
+ if (argMultimap.getValue(PREFIX_WARD).isPresent()) {
+ if (index.getOneBased() == 1) {
+ throw new ParseException(EditWardCommand.MESSAGE_WAITING_ROOM_NAME_EDIT);
+ } else {
+ editWardDescriptor.setWard(ParserUtil.parseWardName(argMultimap.getValue(PREFIX_WARD).get()));
+ }
+ }
+ if (argMultimap.getValue(PREFIX_CAPACITY).isPresent()) {
+ editWardDescriptor.setCapacity(ParserUtil.parseCapacity(argMultimap.getValue(PREFIX_CAPACITY).get()));
+ }
+
+ if (!editWardDescriptor.isAnyFieldEdited()) {
+ throw new ParseException(EditWardCommand.MESSAGE_NOT_EDITED);
+ }
+
+ return new EditWardCommand(index, editWardDescriptor);
+ }
+
+}
diff --git a/src/main/java/seedu/medinfo/logic/parser/FindCommandParser.java b/src/main/java/seedu/medinfo/logic/parser/FindCommandParser.java
new file mode 100644
index 00000000000..7453aff0f0e
--- /dev/null
+++ b/src/main/java/seedu/medinfo/logic/parser/FindCommandParser.java
@@ -0,0 +1,78 @@
+package seedu.medinfo.logic.parser;
+
+import static seedu.medinfo.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.medinfo.logic.parser.CliSyntax.PREFIX_NAME;
+import static seedu.medinfo.logic.parser.CliSyntax.PREFIX_NRIC;
+import static seedu.medinfo.logic.parser.CliSyntax.PREFIX_STATUS;
+import static seedu.medinfo.logic.parser.CliSyntax.PREFIX_WARD;
+
+import java.util.Arrays;
+import java.util.stream.Stream;
+
+import seedu.medinfo.logic.commands.FindCommand;
+import seedu.medinfo.logic.parser.exceptions.ParseException;
+import seedu.medinfo.model.patient.NameContainsKeywordsPredicate;
+import seedu.medinfo.model.patient.NricContainsKeywordsPredicate;
+import seedu.medinfo.model.patient.StatusContainsKeywordsPredicate;
+import seedu.medinfo.model.ward.WardNameContainsKeywordsPredicate;
+
+/**
+ * Parses input arguments and creates a new FindCommand object
+ */
+public class FindCommandParser implements Parser {
+
+ /**
+ * Parses the given {@code String} of arguments in the context of the FindCommand
+ * and returns a FindCommand object for execution.
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public FindCommand parse(String args) throws ParseException {
+
+ ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_NRIC, PREFIX_STATUS,
+ PREFIX_WARD);
+
+ if (!anyPrefixesPresent(argMultimap, PREFIX_NAME, PREFIX_NRIC, PREFIX_STATUS, PREFIX_WARD)
+ || !argMultimap.getPreamble().isEmpty()
+ || manyPrefixesPresent(argMultimap, PREFIX_NAME, PREFIX_NRIC, PREFIX_STATUS, PREFIX_WARD)) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_USAGE));
+ }
+
+ if (anyPrefixesPresent(argMultimap, PREFIX_NAME)) {
+ String trimmedNames = argMultimap.getValue(PREFIX_NAME).get();
+ checkArgsEmpty(trimmedNames);
+ String[] nameKeywords = trimmedNames.split("\\s+");
+ return new FindCommand(new NameContainsKeywordsPredicate(Arrays.asList(nameKeywords)));
+ } else if (anyPrefixesPresent(argMultimap, PREFIX_NRIC)) {
+ String trimmedNric = argMultimap.getValue(PREFIX_NRIC).get();
+ checkArgsEmpty(trimmedNric);
+ String [] nricKeywords = trimmedNric.split("\\s+");
+ return new FindCommand(new NricContainsKeywordsPredicate(Arrays.asList(nricKeywords)));
+ } else if (anyPrefixesPresent(argMultimap, PREFIX_STATUS)) {
+ String trimmedStatus = argMultimap.getValue(PREFIX_STATUS).get();
+ checkArgsEmpty(trimmedStatus);
+ String [] statusKeywords = trimmedStatus.split("\\s+");
+ return new FindCommand(new StatusContainsKeywordsPredicate(Arrays.asList(statusKeywords)));
+ } else {
+ String trimmedWardName = argMultimap.getValue(PREFIX_WARD).get();
+ checkArgsEmpty(trimmedWardName);
+ String [] statusKeywords = trimmedWardName.split("\\s+");
+ return new FindCommand(new WardNameContainsKeywordsPredicate(Arrays.asList(statusKeywords)));
+ }
+ }
+
+ private static boolean anyPrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) {
+ return Stream.of(prefixes).anyMatch(prefix -> argumentMultimap.getValue(prefix).isPresent());
+ }
+
+ private static boolean manyPrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) {
+ return Stream.of(prefixes).filter(prefix -> argumentMultimap.getValue(prefix).isPresent()).count() > 1;
+ }
+
+ private void checkArgsEmpty(String trimmedArgs) throws ParseException {
+ if (trimmedArgs.isEmpty()) {
+ throw new ParseException(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_USAGE));
+ }
+ }
+
+}
diff --git a/src/main/java/seedu/medinfo/logic/parser/MedInfoParser.java b/src/main/java/seedu/medinfo/logic/parser/MedInfoParser.java
new file mode 100644
index 00000000000..e3e47286129
--- /dev/null
+++ b/src/main/java/seedu/medinfo/logic/parser/MedInfoParser.java
@@ -0,0 +1,121 @@
+package seedu.medinfo.logic.parser;
+
+import static seedu.medinfo.commons.core.Messages.MESSAGE_ABORT_DELETE;
+import static seedu.medinfo.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.medinfo.commons.core.Messages.MESSAGE_UNKNOWN_COMMAND;
+
+import java.util.Optional;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javafx.scene.control.Alert;
+import javafx.scene.control.ButtonType;
+import seedu.medinfo.logic.commands.AddCommand;
+import seedu.medinfo.logic.commands.AddWardCommand;
+import seedu.medinfo.logic.commands.ClearCommand;
+import seedu.medinfo.logic.commands.Command;
+import seedu.medinfo.logic.commands.DeleteCommand;
+import seedu.medinfo.logic.commands.DeleteWardCommand;
+import seedu.medinfo.logic.commands.EditCommand;
+import seedu.medinfo.logic.commands.EditWardCommand;
+import seedu.medinfo.logic.commands.ExitCommand;
+import seedu.medinfo.logic.commands.FindCommand;
+import seedu.medinfo.logic.commands.HelpCommand;
+import seedu.medinfo.logic.commands.ListCommand;
+import seedu.medinfo.logic.commands.SortCommand;
+import seedu.medinfo.logic.parser.exceptions.ParseException;
+
+/**
+ * Parses user input.
+ */
+public class MedInfoParser {
+
+ /**
+ * Used for initial separation of command word and args.
+ */
+ private static final Pattern BASIC_COMMAND_FORMAT = Pattern.compile("(?\\S+)(?.*)");
+
+ /**
+ * Parses user input into command for execution.
+ *
+ * @param userInput full user input string
+ * @return the command based on the user input
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public Command parseCommand(String userInput) throws ParseException {
+ final Matcher matcher = BASIC_COMMAND_FORMAT.matcher(userInput.trim());
+ if (!matcher.matches()) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, HelpCommand.MESSAGE_USAGE));
+ }
+
+ final String commandWord = matcher.group("commandWord");
+ final String arguments = matcher.group("arguments");
+
+ // for confirmation window
+ Alert confirmationDialog;
+ Optional result;
+
+ switch (commandWord) {
+ case AddCommand.COMMAND_WORD:
+ return new AddCommandParser().parse(arguments);
+
+ case EditCommand.COMMAND_WORD:
+ return new EditCommandParser().parse(arguments);
+
+ case DeleteCommand.COMMAND_WORD:
+ confirmationDialog = new Alert(Alert.AlertType.CONFIRMATION,
+ "Are you sure you want to delete the patient?");
+ result = confirmationDialog.showAndWait();
+ if (result.isPresent() && result.get() == ButtonType.OK) {
+ return new DeleteCommandParser().parse(arguments);
+ } else {
+ throw new ParseException(MESSAGE_ABORT_DELETE); // cancel the deletion command
+ }
+
+ case ClearCommand.COMMAND_WORD:
+ confirmationDialog = new Alert(Alert.AlertType.CONFIRMATION,
+ "Are you sure you want to clear ALL patients and wards?");
+ result = confirmationDialog.showAndWait();
+ if (result.isPresent() && result.get() == ButtonType.OK) {
+ return new ClearCommand();
+ } else {
+ throw new ParseException(MESSAGE_ABORT_DELETE); // cancel the deletion command
+ }
+
+ case FindCommand.COMMAND_WORD:
+ return new FindCommandParser().parse(arguments);
+
+ case ListCommand.COMMAND_WORD:
+ return new ListCommand();
+
+ case ExitCommand.COMMAND_WORD:
+ return new ExitCommand();
+
+ case HelpCommand.COMMAND_WORD:
+ return new HelpCommand();
+
+ case AddWardCommand.COMMAND_WORD:
+ return new AddWardCommandParser().parse(arguments);
+
+ case EditWardCommand.COMMAND_WORD:
+ return new EditWardCommandParser().parse(arguments);
+
+ case DeleteWardCommand.COMMAND_WORD:
+ confirmationDialog = new Alert(Alert.AlertType.CONFIRMATION,
+ "Are you sure you want to delete the ward?");
+ result = confirmationDialog.showAndWait();
+ if (result.isPresent() && result.get() == ButtonType.OK) {
+ return new DeleteWardCommandParser().parse(arguments);
+ } else {
+ throw new ParseException(MESSAGE_ABORT_DELETE); // cancel the deletion command
+ }
+
+ case SortCommand.COMMAND_WORD:
+ return new SortCommandParser().parse(arguments);
+
+ default:
+ throw new ParseException(MESSAGE_UNKNOWN_COMMAND);
+ }
+ }
+
+}
diff --git a/src/main/java/seedu/address/logic/parser/Parser.java b/src/main/java/seedu/medinfo/logic/parser/Parser.java
similarity index 72%
rename from src/main/java/seedu/address/logic/parser/Parser.java
rename to src/main/java/seedu/medinfo/logic/parser/Parser.java
index d6551ad8e3f..1f25d243f69 100644
--- a/src/main/java/seedu/address/logic/parser/Parser.java
+++ b/src/main/java/seedu/medinfo/logic/parser/Parser.java
@@ -1,7 +1,7 @@
-package seedu.address.logic.parser;
+package seedu.medinfo.logic.parser;
-import seedu.address.logic.commands.Command;
-import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.medinfo.logic.commands.Command;
+import seedu.medinfo.logic.parser.exceptions.ParseException;
/**
* Represents a Parser that is able to parse user input into a {@code Command} of type {@code T}.
diff --git a/src/main/java/seedu/medinfo/logic/parser/ParserUtil.java b/src/main/java/seedu/medinfo/logic/parser/ParserUtil.java
new file mode 100644
index 00000000000..cb505c49752
--- /dev/null
+++ b/src/main/java/seedu/medinfo/logic/parser/ParserUtil.java
@@ -0,0 +1,147 @@
+package seedu.medinfo.logic.parser;
+
+import static java.util.Objects.requireNonNull;
+
+import seedu.medinfo.commons.core.index.Index;
+import seedu.medinfo.commons.util.StringUtil;
+import seedu.medinfo.logic.commands.SortCommand;
+import seedu.medinfo.logic.commands.SortCommand.Order;
+import seedu.medinfo.logic.parser.exceptions.ParseException;
+import seedu.medinfo.model.patient.Discharge;
+import seedu.medinfo.model.patient.Name;
+import seedu.medinfo.model.patient.Nric;
+import seedu.medinfo.model.patient.Status;
+import seedu.medinfo.model.ward.Capacity;
+import seedu.medinfo.model.ward.WardName;
+
+/**
+ * Contains utility methods used for parsing strings in the various *Parser
+ * classes.
+ */
+public class ParserUtil {
+
+ public static final String MESSAGE_INVALID_INDEX = "Index is not a non-zero unsigned integer.";
+
+ /**
+ * Parses {@code oneBasedIndex} into an {@code Index} and returns it. Leading
+ * and trailing whitespaces will be
+ * trimmed.
+ *
+ * @throws ParseException if the specified index is invalid (not non-zero
+ * unsigned integer).
+ */
+ public static Index parseIndex(String oneBasedIndex) throws ParseException {
+ String trimmedIndex = oneBasedIndex.trim();
+ if (!StringUtil.isNonZeroUnsignedInteger(trimmedIndex)) {
+ throw new ParseException(MESSAGE_INVALID_INDEX);
+ }
+ return Index.fromOneBased(Integer.parseInt(trimmedIndex));
+ }
+
+ /**
+ * Parses a {@code String} nric into a {@code Nric}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given {@code nric} is invalid.
+ */
+ public static Nric parseNric(String nric) throws ParseException {
+ requireNonNull(nric);
+ String trimmedNric = nric.trim();
+ if (!Nric.isValidNric(trimmedNric)) {
+ throw new ParseException(Nric.MESSAGE_CONSTRAINTS);
+ }
+ return new Nric(trimmedNric);
+ }
+
+ /**
+ * Parses a {@code String} name into a {@code Name}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given {@code name} is invalid.
+ */
+ public static Name parseName(String name) throws ParseException {
+ requireNonNull(name);
+ String trimmedName = name.trim();
+ if (!Name.isValidName(trimmedName)) {
+ throw new ParseException(Name.MESSAGE_CONSTRAINTS);
+ }
+ return new Name(trimmedName);
+ }
+
+ /**
+ * Parses a {@code String} status into a {@code Status}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given {@code status} is invalid.
+ */
+ public static Status parseStatus(String status) throws ParseException {
+ requireNonNull(status);
+ String trimmedStatus = status.trim();
+ if (!Status.isValidStatus(trimmedStatus)) {
+ throw new ParseException(Status.MESSAGE_CONSTRAINTS);
+ }
+ return new Status(trimmedStatus);
+ }
+
+ /**
+ * Parses a {@code String} ward into a {@code WardName}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given {@code ward} is invalid.
+ */
+ public static WardName parseWardName(String ward) throws ParseException {
+ requireNonNull(ward);
+ String trimmedWard = ward.trim();
+ if (!WardName.isValidWardName(trimmedWard)) {
+ throw new ParseException(WardName.MESSAGE_CONSTRAINTS);
+ }
+ return new WardName(trimmedWard);
+ }
+
+ /**
+ * Parses a {@code String} capacity into a {@code Capacity}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given {@code ward} is invalid.
+ */
+ public static Capacity parseCapacity(String capacity) throws ParseException {
+ requireNonNull(capacity);
+ String trimmedCapacity = capacity.trim();
+ if (!Capacity.isValidCapacity(trimmedCapacity)) {
+ throw new ParseException(Capacity.MESSAGE_CONSTRAINTS);
+ }
+ return new Capacity(trimmedCapacity);
+ }
+
+ /**
+ * Parses a {@code String} discharge into a {@code Discharge}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given {@code discharge} is invalid.
+ */
+ public static Discharge parseDischarge(String discharge) throws ParseException {
+ requireNonNull(discharge);
+ String trimmedDischarge = discharge.trim();
+ if (!Discharge.isValidDischarge(trimmedDischarge)) {
+ throw new ParseException(Discharge.MESSAGE_CONSTRAINTS);
+ }
+ return new Discharge(trimmedDischarge);
+ }
+
+
+ /**
+ * Parses {@code String} order into a {@code Order}.
+ *
+ * @throws ParseException if the given {@code order} is invalid.
+ */
+ // @@author {Echomo-Xinyu}-reused
+ // Referenced the parseSortOrder method
+ public static Order parseSortOrder(String order) throws ParseException {
+ try {
+ return Order.valueOf(order.toUpperCase());
+ } catch (IllegalArgumentException e) {
+ throw new ParseException(SortCommand.MESSAGE_UNKNOWN_ORDER_KEYWORD);
+ }
+ }
+ //@@author
+}
diff --git a/src/main/java/seedu/address/logic/parser/Prefix.java b/src/main/java/seedu/medinfo/logic/parser/Prefix.java
similarity index 95%
rename from src/main/java/seedu/address/logic/parser/Prefix.java
rename to src/main/java/seedu/medinfo/logic/parser/Prefix.java
index c859d5fa5db..1b54e4751a0 100644
--- a/src/main/java/seedu/address/logic/parser/Prefix.java
+++ b/src/main/java/seedu/medinfo/logic/parser/Prefix.java
@@ -1,4 +1,4 @@
-package seedu.address.logic.parser;
+package seedu.medinfo.logic.parser;
/**
* A prefix that marks the beginning of an argument in an arguments string.
diff --git a/src/main/java/seedu/medinfo/logic/parser/SortCommandParser.java b/src/main/java/seedu/medinfo/logic/parser/SortCommandParser.java
new file mode 100644
index 00000000000..f3566874c31
--- /dev/null
+++ b/src/main/java/seedu/medinfo/logic/parser/SortCommandParser.java
@@ -0,0 +1,91 @@
+package seedu.medinfo.logic.parser;
+
+import static seedu.medinfo.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.medinfo.logic.parser.CliSyntax.PREFIX_DISCHARGE;
+import static seedu.medinfo.logic.parser.CliSyntax.PREFIX_NAME;
+import static seedu.medinfo.logic.parser.CliSyntax.PREFIX_STATUS;
+import static seedu.medinfo.logic.parser.CliSyntax.PREFIX_WARD;
+import static seedu.medinfo.logic.parser.ParserUtil.parseSortOrder;
+
+import java.util.stream.Stream;
+
+import seedu.medinfo.logic.commands.SortCommand;
+import seedu.medinfo.logic.commands.SortCommand.Field;
+import seedu.medinfo.logic.commands.SortCommand.Order;
+import seedu.medinfo.logic.parser.exceptions.ParseException;
+
+
+/**
+ * Parses input arguments and creates a new SortCommand object
+ */
+public class SortCommandParser implements Parser {
+
+ /**
+ * Parses the given {@code String} of arguments in the context of the FindCommand
+ * and returns a FindCommand object for execution.
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public SortCommand parse(String args) throws ParseException {
+
+ ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_STATUS, PREFIX_DISCHARGE,
+ PREFIX_WARD);
+
+ if (!anyPrefixesPresent(argMultimap, PREFIX_NAME, PREFIX_STATUS, PREFIX_DISCHARGE, PREFIX_WARD)
+ || !argMultimap.getPreamble().isEmpty()
+ || manyPrefixesPresent(argMultimap, PREFIX_NAME, PREFIX_STATUS, PREFIX_DISCHARGE, PREFIX_WARD)) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, SortCommand.MESSAGE_USAGE));
+ }
+
+ if (anyPrefixesPresent(argMultimap, PREFIX_NAME)) {
+ String trimmedName = argMultimap.getValue(PREFIX_NAME).get();
+ checkArgsEmpty(trimmedName);
+ Order order = parseSortOrder(trimmedName);
+ return new SortCommand(Field.NAME, order);
+ } else if (anyPrefixesPresent(argMultimap, PREFIX_STATUS)) {
+ String trimmedStatus = argMultimap.getValue(PREFIX_STATUS).get();
+ checkArgsEmpty(trimmedStatus);
+ Order order = parseSortOrder(trimmedStatus);
+ return new SortCommand(Field.STATUS, order);
+ } else if (anyPrefixesPresent(argMultimap, PREFIX_DISCHARGE)) {
+ String trimmedDischarge = argMultimap.getValue(PREFIX_DISCHARGE).get();
+ checkArgsEmpty(trimmedDischarge);
+ Order order = parseSortOrder(trimmedDischarge);
+ return new SortCommand(Field.DISCHARGE, order);
+ } else {
+ String trimmedWard = argMultimap.getValue(PREFIX_WARD).get();
+ checkArgsEmpty(trimmedWard);
+ Order order = parseSortOrder(trimmedWard);
+ return new SortCommand(Field.WARD, order);
+ }
+ }
+
+ /**
+ * Returns true if none of the prefixes contains empty {@code Optional} values
+ * in the given
+ * {@code ArgumentMultimap}.
+ */
+ private static boolean anyPrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) {
+ return Stream.of(prefixes).anyMatch(prefix -> argumentMultimap.getValue(prefix).isPresent());
+ }
+
+ /**
+ * Returns true if more than one of the prefixes contains {@code Optional} values
+ * in the given
+ * {@code ArgumentMultimap}.
+ */
+ private static boolean manyPrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) {
+ return Stream.of(prefixes).filter(prefix -> argumentMultimap.getValue(prefix).isPresent()).count() > 1;
+ }
+
+ /**
+ * Checks if a given argument is empty
+ * @param trimmedArgs if the argument is empty
+ */
+ private void checkArgsEmpty(String trimmedArgs) throws ParseException {
+ if (trimmedArgs.isEmpty()) {
+ throw new ParseException(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, SortCommand.MESSAGE_USAGE));
+ }
+ }
+
+}
diff --git a/src/main/java/seedu/address/logic/parser/exceptions/ParseException.java b/src/main/java/seedu/medinfo/logic/parser/exceptions/ParseException.java
similarity index 60%
rename from src/main/java/seedu/address/logic/parser/exceptions/ParseException.java
rename to src/main/java/seedu/medinfo/logic/parser/exceptions/ParseException.java
index 158a1a54c1c..bbf90187acf 100644
--- a/src/main/java/seedu/address/logic/parser/exceptions/ParseException.java
+++ b/src/main/java/seedu/medinfo/logic/parser/exceptions/ParseException.java
@@ -1,9 +1,9 @@
-package seedu.address.logic.parser.exceptions;
+package seedu.medinfo.logic.parser.exceptions;
-import seedu.address.commons.exceptions.IllegalValueException;
+import seedu.medinfo.commons.exceptions.IllegalValueException;
/**
- * Represents a parse error encountered by a parser.
+ * Signals a parse error encountered by a parser.
*/
public class ParseException extends IllegalValueException {
diff --git a/src/main/java/seedu/medinfo/model/MedInfo.java b/src/main/java/seedu/medinfo/model/MedInfo.java
new file mode 100644
index 00000000000..9face4f3cc5
--- /dev/null
+++ b/src/main/java/seedu/medinfo/model/MedInfo.java
@@ -0,0 +1,256 @@
+package seedu.medinfo.model;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.medinfo.commons.util.CollectionUtil.requireAllNonNull;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+
+import javafx.collections.ObservableList;
+import seedu.medinfo.logic.commands.exceptions.CommandException;
+import seedu.medinfo.model.patient.Patient;
+import seedu.medinfo.model.patient.UniquePatientList;
+import seedu.medinfo.model.ward.UniqueWardList;
+import seedu.medinfo.model.ward.Ward;
+import seedu.medinfo.model.ward.exceptions.WardFullException;
+import seedu.medinfo.model.ward.exceptions.WardNotFoundException;
+
+/**
+ * Wraps all data at the medinfo-book level
+ * Duplicates are not allowed (by .isSamePatient comparison)
+ */
+public class MedInfo implements ReadOnlyMedInfo {
+
+ private final UniquePatientList patients;
+ private final UniqueWardList wards;
+
+ /*
+ * The 'unusual' code block below is a non-static initialization block,
+ * sometimes used to avoid duplication
+ * between constructors. See
+ * https://docs.oracle.com/javase/tutorial/java/javaOO/initial.html
+ *
+ * Note that non-static init blocks are not recommended to use. There are other
+ * ways to avoid duplication
+ * among constructors.
+ */
+ {
+ patients = new UniquePatientList();
+ wards = new UniqueWardList();
+ }
+
+ public MedInfo() {
+ }
+
+ /**
+ * Creates an MedInfo using the Patients in the {@code toBeCopied}
+ */
+ public MedInfo(ReadOnlyMedInfo toBeCopied) {
+ this();
+ resetData(toBeCopied);
+ }
+
+ /**
+ * Adds Waiting room for clear command.
+ */
+ public void newMedInfo() {
+ wards.newUniqueWardList();
+ }
+
+ //// List overwrite operations ====================================================================================
+
+ /**
+ * FOR TESTING
+ * Replaces the contents of the patient list with a COPY of {@code patients}.
+ * {@code patients} must not contain duplicate patients.
+ */
+ public void setPatients(List patients) {
+ List patientsCopy = new ArrayList<>();
+ for (Patient patient : patients) {
+ Patient toCopy = new Patient(patient.getNric(), patient.getName(),
+ patient.getStatus(), patient.getWardName(), patient.getDischarge());
+ patientsCopy.add(toCopy);
+ }
+ this.patients.setPatients(patientsCopy);
+ }
+
+ /**
+ * FOR TESTING
+ * Replaces the contents of the ward list with {@code wards}.
+ * {@code wards} must not contain duplicate wards.
+ */
+ public void setWards(List wards) {
+ this.wards.setWards(wards);
+ }
+
+ /**
+ * Resets the existing data of this {@code MedInfo} with {@code newData}.
+ */
+ public void resetData(ReadOnlyMedInfo newData) {
+ requireNonNull(newData);
+ setWards(newData.getWardList());
+ setPatients(newData.getPatientList());
+ }
+
+ //// Patient operations ===========================================================================================
+
+ /**
+ * Returns true if a patient with the same identity as {@code patient} exists in
+ * the medinfo book.
+ */
+ public boolean hasPatient(Patient patient) {
+ requireNonNull(patient);
+ return patients.contains(patient);
+ }
+
+ /**
+ * Returns true if a patient with the same NRIC as {@code patient} exists in
+ * the medinfo book.
+ */
+ public boolean hasPatientNric(Patient patient) {
+ requireNonNull(patient);
+ return patients.containsNric(patient);
+ }
+
+ /**
+ * Adds a patient to the medinfo book.
+ * The patient must not already exist in the medinfo book.
+ */
+ public void addPatient(Patient p) throws CommandException, WardNotFoundException {
+ if (!wards.contains(p.getWardNameString())) {
+ throw new WardNotFoundException(p.getWardNameString());
+ }
+ try {
+ wards.addPatient(p);
+ patients.add(p);
+ } catch (WardFullException e) {
+ throw new CommandException(e.toString(), e);
+ }
+ }
+
+ /**
+ * Replaces the given patient {@code target} in the list with
+ * {@code editedPatient}.
+ * {@code target} must exist in the medinfo book.
+ * The patient identity of {@code editedPatient} must not be the same as another
+ * existing patient in the medinfo book.
+ */
+ public void setPatient(Patient target, Patient editedPatient) throws CommandException {
+ requireAllNonNull(target, editedPatient);
+ try {
+ wards.setPatient(target, editedPatient);
+ patients.setPatient(target, editedPatient);
+ } catch (WardFullException e) {
+ throw new CommandException(e.toString(), e);
+ }
+ }
+
+ /**
+ * Removes {@code key} from this {@code MedInfo}.
+ * {@code key} must exist in the medinfo book.
+ */
+ public void removePatient(Patient key) {
+ requireNonNull(key);
+ patients.remove(key);
+ wards.remove(key);
+ }
+
+ @Override
+ public void sortPatients(Comparator comparator) {
+ patients.sortPatients(comparator);
+ }
+
+ //// Ward operations ==============================================================================================
+
+ /**
+ * Returns true if a ward with the same identity as {@code ward} exists in
+ * the medinfo book.
+ */
+ public boolean hasWard(Ward ward) {
+ requireNonNull(ward);
+ return wards.contains(ward);
+ }
+
+ /**
+ * Adds a ward to the medinfo book.
+ * The ward must not already exist in the medinfo book.
+ */
+ public void addWard(Ward ward) {
+ wards.add(ward);
+ }
+
+ /**
+ * Replaces the given ward {@code target} in the list with
+ * {@code editedWard}.
+ * {@code target} must exist in the medinfo book.
+ * The ward identity of {@code editedWard} must not be the same as another
+ * existing ward in the medinfo book.
+ */
+ public void setWard(Ward target, Ward editedWard) {
+ requireNonNull(editedWard);
+ wards.setWard(target, editedWard);
+
+ for (Patient patient : patients) {
+ if (patient.getWardName().equals(target.getName())) {
+ Patient editedPatient = new Patient(patient.getNric(), patient.getName(), patient.getStatus(),
+ editedWard.getName(),
+ patient.getDischarge());
+ patients.setPatient(patient, editedPatient);
+ }
+ }
+ }
+
+ /**
+ * Removes {@code key} from this {@code MedInfo}.
+ * {@code key} must exist in the medinfo book.
+ */
+ public void removeWard(Ward ward) {
+ wards.remove(ward);
+ }
+
+ //// Util methods =================================================================================================
+
+ @Override
+ public String toString() {
+ return patients.asUnmodifiableObservableList().size() + " patients";
+ }
+
+ @Override
+ public ObservableList getPatientList() {
+ return patients.asUnmodifiableObservableList();
+ }
+
+ @Override
+ public ObservableList getWardList() {
+ return wards.asUnmodifiableObservableList();
+ }
+
+ /**
+ * Stats to be displayed on StatusBarFooter.
+ * This is the method to modify to choose what you want to display.
+ *
+ * @return List of information to display.
+ */
+ @Override
+ public List getStatsInfo() {
+ List statsInfo = new ArrayList<>();
+ String currentOccupancy = "Current Occupancy: " + patients.size() + "/" + wards.capacity();
+ String currentCriticals = "Critical Patients: " + patients.numberOfCritical();
+ statsInfo.add(currentOccupancy);
+ statsInfo.add(currentCriticals);
+ return statsInfo;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof MedInfo // instanceof handles nulls
+ && patients.equals(((MedInfo) other).patients));
+ }
+
+ @Override
+ public int hashCode() {
+ return patients.hashCode();
+ }
+}
diff --git a/src/main/java/seedu/medinfo/model/Model.java b/src/main/java/seedu/medinfo/model/Model.java
new file mode 100644
index 00000000000..77a7c0f035f
--- /dev/null
+++ b/src/main/java/seedu/medinfo/model/Model.java
@@ -0,0 +1,142 @@
+package seedu.medinfo.model;
+
+import java.nio.file.Path;
+import java.util.Comparator;
+import java.util.List;
+import java.util.function.Predicate;
+
+import javafx.collections.ObservableList;
+import seedu.medinfo.commons.core.GuiSettings;
+import seedu.medinfo.logic.commands.exceptions.CommandException;
+import seedu.medinfo.model.patient.Patient;
+import seedu.medinfo.model.ward.Ward;
+
+/**
+ * The API of the Model component.
+ */
+public interface Model {
+ /** {@code Predicate} that always evaluate to true */
+ Predicate PREDICATE_SHOW_ALL_PATIENTS = unused -> true;
+
+ /** {@code Predicate} that always evaluate to true */
+ Predicate PREDICATE_SHOW_ALL_WARDS = unused -> true;
+
+ /**
+ * Replaces user prefs data with the data in {@code userPrefs}.
+ */
+ void setUserPrefs(ReadOnlyUserPrefs userPrefs);
+
+ /**
+ * Returns the user prefs.
+ */
+ ReadOnlyUserPrefs getUserPrefs();
+
+ /**
+ * Returns the user prefs' GUI settings.
+ */
+ GuiSettings getGuiSettings();
+
+ /**
+ * Sets the user prefs' GUI settings.
+ */
+ void setGuiSettings(GuiSettings guiSettings);
+
+ /**
+ * Returns the user prefs' medinfo book file path.
+ */
+ Path getMedInfoFilePath();
+
+ /**
+ * Sets the user prefs' medinfo book file path.
+ */
+ void setMedInfoFilePath(Path medInfoFilePath);
+
+ /**
+ * Replaces medinfo book data with the data in {@code medInfo}.
+ */
+ void setMedInfo(ReadOnlyMedInfo medInfo);
+
+ /** Returns the MedInfo */
+ ReadOnlyMedInfo getMedInfo();
+
+ /**
+ * Returns true if a patient with the same identity as {@code patient} exists in the medinfo book.
+ */
+ boolean hasPatient(Patient patient);
+
+ /**
+ * Deletes the given patient.
+ * The patient must exist in the medinfo book.
+ */
+ void deletePatient(Patient target);
+
+ /**
+ * Adds the given patient.
+ * {@code patient} must not already exist in the medinfo book.
+ */
+ void addPatient(Patient patient) throws CommandException;
+
+ /**
+ * Replaces the given patient {@code target} with {@code editedPatient}.
+ * {@code target} must exist in the medinfo book.
+ * The patient identity of {@code editedPatient} must not be the same as another
+ * existing patient in the medinfo book.
+ */
+ void setPatient(Patient target, Patient editedPatient) throws CommandException;
+
+ /**
+ * Sorts the list of patients by given {@code comparator}
+ */
+ void sortPatients(Comparator comparator);
+
+ /**
+ * Returns true if a ward with the same identity as {@code ward} exists in the medinfo book.
+ */
+ boolean hasWard(Ward ward);
+
+ /**
+ * Deletes the given ward.
+ * The ward must exist in the medinfo book.
+ */
+ void deleteWard(Ward target);
+
+ /**
+ * Adds the given ward.
+ * {@code ward} must not already exist in the medinfo book.
+ */
+ void addWard(Ward ward);
+
+ /**
+ * Replaces the given ward {@code target} with {@code editedWard}.
+ * {@code target} must exist in the medinfo book.
+ * The ward identity of {@code editedWard} must not be the same as another
+ * existing ward in the medinfo book.
+ */
+ void setWard(Ward target, Ward editedWard);
+
+ List getStatsInfo();
+
+ /** Returns an unmodifiable view of the filtered patient list */
+ ObservableList getFilteredPatientList();
+
+ /** Returns an unmodifiable view of the filtered ward list */
+ ObservableList getFilteredWardList();
+
+ /**
+ * Updates the filter of the filtered patient list to filter by the given {@code predicate}.
+ * @throws NullPointerException if {@code predicate} is null.
+ */
+ void updateFilteredPatientList(Predicate predicate);
+
+ /**
+ * Updates the filter of the filtered ward list to filter by the given {@code predicate}.
+ * @throws NullPointerException if {@code predicate} is null.
+ */
+ void updateFilteredWardList(Predicate predicate);
+
+ /**
+ * Returns true if a patient with the same NRIC as {@code patient} exists in the medinfo book.
+ */
+ boolean hasPatientNric(Patient patient);
+
+}
diff --git a/src/main/java/seedu/medinfo/model/ModelManager.java b/src/main/java/seedu/medinfo/model/ModelManager.java
new file mode 100644
index 00000000000..b2af9e1650f
--- /dev/null
+++ b/src/main/java/seedu/medinfo/model/ModelManager.java
@@ -0,0 +1,213 @@
+package seedu.medinfo.model;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.medinfo.commons.util.CollectionUtil.requireAllNonNull;
+
+import java.nio.file.Path;
+import java.util.Comparator;
+import java.util.List;
+import java.util.function.Predicate;
+import java.util.logging.Logger;
+
+import javafx.collections.ObservableList;
+import javafx.collections.transformation.FilteredList;
+import seedu.medinfo.commons.core.GuiSettings;
+import seedu.medinfo.commons.core.LogsCenter;
+import seedu.medinfo.logic.commands.exceptions.CommandException;
+import seedu.medinfo.model.patient.Patient;
+import seedu.medinfo.model.ward.Ward;
+
+/**
+ * Represents the in-memory model of the MedInfo data.
+ */
+public class ModelManager implements Model {
+ private static final Logger logger = LogsCenter.getLogger(ModelManager.class);
+
+ private final MedInfo medInfo;
+ private final UserPrefs userPrefs;
+ private final FilteredList filteredPatients;
+ private final FilteredList filteredWards;
+
+ /**
+ * Initializes a ModelManager with the given medInfo and userPrefs.
+ */
+ public ModelManager(ReadOnlyMedInfo medInfo, ReadOnlyUserPrefs userPrefs) {
+ requireAllNonNull(medInfo, userPrefs);
+
+ logger.fine("Initializing with MedInfo: " + medInfo + " and user prefs " + userPrefs);
+
+ this.medInfo = new MedInfo(medInfo);
+ this.userPrefs = new UserPrefs(userPrefs);
+ filteredPatients = new FilteredList<>(this.medInfo.getPatientList());
+ filteredWards = new FilteredList<>(this.medInfo.getWardList());
+ }
+
+ public ModelManager() {
+ this(new MedInfo(), new UserPrefs());
+ }
+
+ //=========== UserPrefs ==================================================================================
+
+ @Override
+ public void setUserPrefs(ReadOnlyUserPrefs userPrefs) {
+ requireNonNull(userPrefs);
+ this.userPrefs.resetData(userPrefs);
+ }
+
+ @Override
+ public ReadOnlyUserPrefs getUserPrefs() {
+ return userPrefs;
+ }
+
+ @Override
+ public GuiSettings getGuiSettings() {
+ return userPrefs.getGuiSettings();
+ }
+
+ @Override
+ public void setGuiSettings(GuiSettings guiSettings) {
+ requireNonNull(guiSettings);
+ userPrefs.setGuiSettings(guiSettings);
+ }
+
+ @Override
+ public Path getMedInfoFilePath() {
+ return userPrefs.getMedInfoFilePath();
+ }
+
+ @Override
+ public void setMedInfoFilePath(Path medInfoFilePath) {
+ requireNonNull(medInfoFilePath);
+ userPrefs.setMedInfoFilePath(medInfoFilePath);
+ }
+
+ //=========== MedInfo ================================================================================
+
+ @Override
+ public void setMedInfo(ReadOnlyMedInfo medInfo) {
+ this.medInfo.resetData(medInfo);
+ }
+
+ @Override
+ public ReadOnlyMedInfo getMedInfo() {
+ return medInfo;
+ }
+
+ //// Patient methods =====================================================================================
+ @Override
+ public boolean hasPatient(Patient patient) {
+ requireNonNull(patient);
+ return medInfo.hasPatient(patient);
+ }
+
+ @Override
+ public boolean hasPatientNric(Patient patient) {
+ requireNonNull(patient);
+ return medInfo.hasPatientNric(patient);
+ }
+
+ @Override
+ public void deletePatient(Patient target) {
+ medInfo.removePatient(target);
+ }
+
+ @Override
+ public void addPatient(Patient patient) throws CommandException {
+ medInfo.addPatient(patient);
+ }
+
+ @Override
+ public void setPatient(Patient target, Patient editedPatient) throws CommandException {
+ requireAllNonNull(target, editedPatient);
+ medInfo.setPatient(target, editedPatient);
+ }
+
+ @Override
+ public void sortPatients(Comparator comparator) {
+ requireNonNull(comparator);
+ medInfo.sortPatients(comparator);
+
+ }
+
+ //// Ward methods =====================================================================================
+ @Override
+ public boolean hasWard(Ward ward) {
+ requireNonNull(ward);
+ return medInfo.hasWard(ward);
+ }
+
+ @Override
+ public void deleteWard(Ward target) {
+ medInfo.removeWard(target);
+ }
+
+ @Override
+ public void addWard(Ward ward) {
+ medInfo.addWard(ward);
+ }
+
+ @Override
+ public void setWard(Ward target, Ward editedWard) {
+ requireAllNonNull(target, editedWard);
+ medInfo.setWard(target, editedWard);
+ }
+
+ //=========== Filtered Patient List Accessors =============================================================
+
+ /**
+ * Returns an unmodifiable view of the list of {@code Patient} backed by the internal list of
+ * {@code versionedMedInfo}
+ */
+ @Override
+ public ObservableList getFilteredPatientList() {
+ return filteredPatients;
+ }
+
+ @Override
+ public void updateFilteredPatientList(Predicate predicate) {
+ requireNonNull(predicate);
+ filteredPatients.setPredicate(predicate);
+ }
+
+ //=========== Filtered Ward List Accessors =============================================================
+
+ /**
+ * Returns an unmodifiable view of the list of {@code Ward} backed by the internal list of
+ * {@code versionedMedInfo}
+ */
+ @Override
+ public ObservableList getFilteredWardList() {
+ return filteredWards;
+ }
+
+ @Override
+ public void updateFilteredWardList(Predicate predicate) {
+ requireNonNull(predicate);
+ filteredWards.setPredicate(predicate);
+ }
+
+ @Override
+ public List getStatsInfo() {
+ return medInfo.getStatsInfo();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ // short circuit if same object
+ if (obj == this) {
+ return true;
+ }
+
+ // instanceof handles nulls
+ if (!(obj instanceof ModelManager)) {
+ return false;
+ }
+
+ // state check
+ ModelManager other = (ModelManager) obj;
+ return medInfo.equals(other.medInfo)
+ && userPrefs.equals(other.userPrefs)
+ && filteredPatients.equals(other.filteredPatients);
+ }
+
+}
diff --git a/src/main/java/seedu/medinfo/model/ReadOnlyMedInfo.java b/src/main/java/seedu/medinfo/model/ReadOnlyMedInfo.java
new file mode 100644
index 00000000000..b7f457aaad3
--- /dev/null
+++ b/src/main/java/seedu/medinfo/model/ReadOnlyMedInfo.java
@@ -0,0 +1,27 @@
+package seedu.medinfo.model;
+
+import java.util.Comparator;
+import java.util.List;
+
+import javafx.collections.ObservableList;
+import seedu.medinfo.model.patient.Patient;
+import seedu.medinfo.model.ward.Ward;
+
+
+/**
+ * Unmodifiable view of a MedInfo
+ */
+public interface ReadOnlyMedInfo {
+
+ void sortPatients(Comparator comparator);
+
+ /**
+ * Returns an unmodifiable view of the patients list.
+ * This list will not contain any duplicate patients.
+ */
+ ObservableList getPatientList();
+
+ ObservableList getWardList();
+
+ List getStatsInfo();
+}
diff --git a/src/main/java/seedu/address/model/ReadOnlyUserPrefs.java b/src/main/java/seedu/medinfo/model/ReadOnlyUserPrefs.java
similarity index 57%
rename from src/main/java/seedu/address/model/ReadOnlyUserPrefs.java
rename to src/main/java/seedu/medinfo/model/ReadOnlyUserPrefs.java
index befd58a4c73..cbc571c76ee 100644
--- a/src/main/java/seedu/address/model/ReadOnlyUserPrefs.java
+++ b/src/main/java/seedu/medinfo/model/ReadOnlyUserPrefs.java
@@ -1,8 +1,8 @@
-package seedu.address.model;
+package seedu.medinfo.model;
import java.nio.file.Path;
-import seedu.address.commons.core.GuiSettings;
+import seedu.medinfo.commons.core.GuiSettings;
/**
* Unmodifiable view of user prefs.
@@ -11,6 +11,6 @@ public interface ReadOnlyUserPrefs {
GuiSettings getGuiSettings();
- Path getAddressBookFilePath();
+ Path getMedInfoFilePath();
}
diff --git a/src/main/java/seedu/address/model/UserPrefs.java b/src/main/java/seedu/medinfo/model/UserPrefs.java
similarity index 70%
rename from src/main/java/seedu/address/model/UserPrefs.java
rename to src/main/java/seedu/medinfo/model/UserPrefs.java
index 25a5fd6eab9..bfecc3cdea7 100644
--- a/src/main/java/seedu/address/model/UserPrefs.java
+++ b/src/main/java/seedu/medinfo/model/UserPrefs.java
@@ -1,4 +1,4 @@
-package seedu.address.model;
+package seedu.medinfo.model;
import static java.util.Objects.requireNonNull;
@@ -6,7 +6,7 @@
import java.nio.file.Paths;
import java.util.Objects;
-import seedu.address.commons.core.GuiSettings;
+import seedu.medinfo.commons.core.GuiSettings;
/**
* Represents User's preferences.
@@ -14,7 +14,7 @@
public class UserPrefs implements ReadOnlyUserPrefs {
private GuiSettings guiSettings = new GuiSettings();
- private Path addressBookFilePath = Paths.get("data" , "addressbook.json");
+ private Path medInfoFilePath = Paths.get("data" , "medinfo.json");
/**
* Creates a {@code UserPrefs} with default values.
@@ -35,7 +35,7 @@ public UserPrefs(ReadOnlyUserPrefs userPrefs) {
public void resetData(ReadOnlyUserPrefs newUserPrefs) {
requireNonNull(newUserPrefs);
setGuiSettings(newUserPrefs.getGuiSettings());
- setAddressBookFilePath(newUserPrefs.getAddressBookFilePath());
+ setMedInfoFilePath(newUserPrefs.getMedInfoFilePath());
}
public GuiSettings getGuiSettings() {
@@ -47,13 +47,13 @@ public void setGuiSettings(GuiSettings guiSettings) {
this.guiSettings = guiSettings;
}
- public Path getAddressBookFilePath() {
- return addressBookFilePath;
+ public Path getMedInfoFilePath() {
+ return medInfoFilePath;
}
- public void setAddressBookFilePath(Path addressBookFilePath) {
- requireNonNull(addressBookFilePath);
- this.addressBookFilePath = addressBookFilePath;
+ public void setMedInfoFilePath(Path medInfoFilePath) {
+ requireNonNull(medInfoFilePath);
+ this.medInfoFilePath = medInfoFilePath;
}
@Override
@@ -68,19 +68,19 @@ public boolean equals(Object other) {
UserPrefs o = (UserPrefs) other;
return guiSettings.equals(o.guiSettings)
- && addressBookFilePath.equals(o.addressBookFilePath);
+ && medInfoFilePath.equals(o.medInfoFilePath);
}
@Override
public int hashCode() {
- return Objects.hash(guiSettings, addressBookFilePath);
+ return Objects.hash(guiSettings, medInfoFilePath);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("Gui Settings : " + guiSettings);
- sb.append("\nLocal data file location : " + addressBookFilePath);
+ sb.append("\nLocal data file location : " + medInfoFilePath);
return sb.toString();
}
diff --git a/src/main/java/seedu/medinfo/model/patient/Discharge.java b/src/main/java/seedu/medinfo/model/patient/Discharge.java
new file mode 100644
index 00000000000..02d3ca62eaa
--- /dev/null
+++ b/src/main/java/seedu/medinfo/model/patient/Discharge.java
@@ -0,0 +1,84 @@
+package seedu.medinfo.model.patient;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.medinfo.commons.util.AppUtil.checkArgument;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * Represents a Patient's discharge date in MedInfo.
+ */
+public class Discharge {
+
+ public static final String MESSAGE_CONSTRAINTS = "Discharge date-time should be a valid future date-time"
+ + " of the format dd/MM/yyyy HHmm";
+ public static final String DEFAULT_DISCHARGE = "To Be Confirmed";
+ public static final String DATE_FORMAT = "dd/MM/yyyy HHmm";
+
+ public final String value;
+
+ /**
+ * Constructs a {@code Discharge}.
+ *
+ * @param discharge A valid discharge date.
+ */
+ public Discharge(String discharge) {
+ requireNonNull(discharge);
+ checkArgument(isValidDischarge(discharge), MESSAGE_CONSTRAINTS);
+ value = discharge;
+ }
+
+ /**
+ * Returns true if a given discharge date-time is valid.
+ * @param date Date to check.
+ */
+ public static boolean isValidDischarge(String date) {
+ if (date.equals(DEFAULT_DISCHARGE)) {
+ return true;
+ }
+ try {
+ DateFormat df = new SimpleDateFormat(DATE_FORMAT);
+ df.setLenient(false);
+ df.parse(date);
+ return true;
+ } catch (ParseException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Returns the dateTime.
+ * @return LocalDateTime
+ */
+ public Date getDateTime() {
+ try {
+ DateFormat df = new SimpleDateFormat(DATE_FORMAT);
+ df.setLenient(false);
+ return df.parse(value);
+ } catch (ParseException e) {
+ return new Date();
+ }
+ }
+
+ @Override
+ public String toString() {
+ return value;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this
+ || (other instanceof Discharge
+ && value.equals(((Discharge) other).value));
+ }
+
+ @Override
+ public int hashCode() {
+ return value.hashCode();
+ }
+
+}
+
diff --git a/src/main/java/seedu/address/model/person/Name.java b/src/main/java/seedu/medinfo/model/patient/Name.java
similarity index 69%
rename from src/main/java/seedu/address/model/person/Name.java
rename to src/main/java/seedu/medinfo/model/patient/Name.java
index 79244d71cf7..308b322e867 100644
--- a/src/main/java/seedu/address/model/person/Name.java
+++ b/src/main/java/seedu/medinfo/model/patient/Name.java
@@ -1,19 +1,19 @@
-package seedu.address.model.person;
+package seedu.medinfo.model.patient;
import static java.util.Objects.requireNonNull;
-import static seedu.address.commons.util.AppUtil.checkArgument;
+import static seedu.medinfo.commons.util.AppUtil.checkArgument;
/**
- * Represents a Person's name in the address book.
+ * Represents a Patient's name in MedInfo.
* Guarantees: immutable; is valid as declared in {@link #isValidName(String)}
*/
public class Name {
- public static final String MESSAGE_CONSTRAINTS =
- "Names should only contain alphanumeric characters and spaces, and it should not be blank";
+ public static final String MESSAGE_CONSTRAINTS = "Names should only contain alphanumeric characters"
+ + " and spaces, and it should not be blank";
/*
- * The first character of the address must not be a whitespace,
+ * The first character of the name must not be a whitespace,
* otherwise " " (a blank string) becomes a valid input.
*/
public static final String VALIDATION_REGEX = "[\\p{Alnum}][\\p{Alnum} ]*";
@@ -22,7 +22,6 @@ public class Name {
/**
* Constructs a {@code Name}.
- *
* @param name A valid name.
*/
public Name(String name) {
@@ -33,12 +32,12 @@ public Name(String name) {
/**
* Returns true if a given string is a valid name.
+ * @param test The string to be tested.
*/
public static boolean isValidName(String test) {
return test.matches(VALIDATION_REGEX);
}
-
@Override
public String toString() {
return fullName;
@@ -48,7 +47,7 @@ public String toString() {
public boolean equals(Object other) {
return other == this // short circuit if same object
|| (other instanceof Name // instanceof handles nulls
- && fullName.equals(((Name) other).fullName)); // state check
+ && fullName.equals(((Name) other).fullName)); // state check
}
@Override
diff --git a/src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java b/src/main/java/seedu/medinfo/model/patient/NameContainsKeywordsPredicate.java
similarity index 62%
rename from src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java
rename to src/main/java/seedu/medinfo/model/patient/NameContainsKeywordsPredicate.java
index c9b5868427c..9b62bd19142 100644
--- a/src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java
+++ b/src/main/java/seedu/medinfo/model/patient/NameContainsKeywordsPredicate.java
@@ -1,14 +1,15 @@
-package seedu.address.model.person;
+package seedu.medinfo.model.patient;
import java.util.List;
import java.util.function.Predicate;
-import seedu.address.commons.util.StringUtil;
+import seedu.medinfo.commons.util.StringUtil;
/**
- * Tests that a {@code Person}'s {@code Name} matches any of the keywords given.
+ * Tests that a {@code Patient}'s {@code Name} matches any of the keywords
+ * given.
*/
-public class NameContainsKeywordsPredicate implements Predicate {
+public class NameContainsKeywordsPredicate implements Predicate {
private final List keywords;
public NameContainsKeywordsPredicate(List keywords) {
@@ -16,16 +17,16 @@ public NameContainsKeywordsPredicate(List keywords) {
}
@Override
- public boolean test(Person person) {
+ public boolean test(Patient patient) {
return keywords.stream()
- .anyMatch(keyword -> StringUtil.containsWordIgnoreCase(person.getName().fullName, keyword));
+ .anyMatch(keyword -> StringUtil.containsWordIgnoreCase(patient.getName().fullName, keyword));
}
@Override
public boolean equals(Object other) {
return other == this // short circuit if same object
|| (other instanceof NameContainsKeywordsPredicate // instanceof handles nulls
- && keywords.equals(((NameContainsKeywordsPredicate) other).keywords)); // state check
+ && keywords.equals(((NameContainsKeywordsPredicate) other).keywords)); // state check
}
}
diff --git a/src/main/java/seedu/medinfo/model/patient/Nric.java b/src/main/java/seedu/medinfo/model/patient/Nric.java
new file mode 100644
index 00000000000..5caf01b3d08
--- /dev/null
+++ b/src/main/java/seedu/medinfo/model/patient/Nric.java
@@ -0,0 +1,59 @@
+package seedu.medinfo.model.patient;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.medinfo.commons.util.AppUtil.checkArgument;
+
+/**
+ * Represents a Patient's Nric in MedInfo.
+ * Guarantees: immutable; is valid as declared in {@link #isValidNric(String)}
+ */
+public class Nric {
+ public static final String MESSAGE_CONSTRAINTS = "NRIC should not be blank. It should only begin with either "
+ + "the letter S, T, F or G, followed by 7 numbers, then ending with a capital letter.";
+
+ /**
+ * The National Registry Identification Number (NRIC) of Singapore
+ * is made up of the first character being a S/F/T or G.
+ * The next 2 numbers is the year of birth for people born 1967 and later.
+ * The last character is a checksum done on the numbers,
+ * and the algorithm will not be released.
+ */
+ public static final String VALIDATION_REGEX = "^[STFG]\\d{7}[A-Z]$";
+
+ public final String value;
+
+ /**
+ * Constructs an {@code Nric}.
+ *
+ * @param nric A valid NRIC.
+ */
+ public Nric(String nric) {
+ requireNonNull(nric);
+ checkArgument(isValidNric(nric), MESSAGE_CONSTRAINTS);
+ value = nric;
+ }
+
+ /**
+ * Returns true if a given string is a valid NRIC.
+ */
+ public static boolean isValidNric(String test) {
+ return test.matches(VALIDATION_REGEX);
+ }
+
+ @Override
+ public String toString() {
+ return value;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof Nric // instanceof handles nulls
+ && value.equals(((Nric) other).value)); // state check
+ }
+
+ @Override
+ public int hashCode() {
+ return value.hashCode();
+ }
+}
diff --git a/src/main/java/seedu/medinfo/model/patient/NricContainsKeywordsPredicate.java b/src/main/java/seedu/medinfo/model/patient/NricContainsKeywordsPredicate.java
new file mode 100644
index 00000000000..faceefc87c3
--- /dev/null
+++ b/src/main/java/seedu/medinfo/model/patient/NricContainsKeywordsPredicate.java
@@ -0,0 +1,32 @@
+package seedu.medinfo.model.patient;
+
+import java.util.List;
+import java.util.function.Predicate;
+
+import seedu.medinfo.commons.util.StringUtil;
+
+/**
+ * Tests that a {@code Patient}'s {@code NRIC} matches any of the keywords
+ * given.
+ */
+public class NricContainsKeywordsPredicate implements Predicate {
+ private final List keywords;
+
+ public NricContainsKeywordsPredicate(List keywords) {
+ this.keywords = keywords;
+ }
+
+ @Override
+ public boolean test(Patient patient) {
+ return keywords.stream()
+ .anyMatch(keyword -> StringUtil.containsWordIgnoreCase(patient.getNric().value, keyword));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof NricContainsKeywordsPredicate // instanceof handles nulls
+ && keywords.equals(((NricContainsKeywordsPredicate) other).keywords)); // state check
+ }
+
+}
diff --git a/src/main/java/seedu/medinfo/model/patient/Patient.java b/src/main/java/seedu/medinfo/model/patient/Patient.java
new file mode 100644
index 00000000000..af5c3b80243
--- /dev/null
+++ b/src/main/java/seedu/medinfo/model/patient/Patient.java
@@ -0,0 +1,393 @@
+package seedu.medinfo.model.patient;
+
+import static seedu.medinfo.commons.util.CollectionUtil.requireAllNonNull;
+import static seedu.medinfo.model.ward.Ward.wardWithName;
+
+import java.util.Date;
+import java.util.Objects;
+
+import seedu.medinfo.model.ward.Ward;
+import seedu.medinfo.model.ward.WardName;
+
+/**
+ * Represents a Patient in the medinfo book.
+ * Guarantees: details are present and not null, field values are validated,
+ * immutable.
+ */
+public class Patient {
+ private static final int INVERTER = -1;
+
+ // Identity fields
+ private final Nric nric;
+ private final Name name;
+
+ // Data fields
+ private Status status = new Status("GRAY");
+ private WardName ward = new WardName("Waiting Room");
+ private Discharge discharge = new Discharge("To Be Confirmed");
+
+ /**
+ * Constructor for Patient taking in nric and name.
+ *
+ * @param nric Patient NRIC
+ * @param name Patient name
+ * Every field must be present and not null.
+ */
+ public Patient(Nric nric, Name name) {
+ requireAllNonNull(nric, name);
+ this.nric = nric;
+ this.name = name;
+ }
+
+ /**
+ * Constructor for Patient taking in nric, name, status.
+ *
+ * @param nric Patient NRIC
+ * @param name Patient name
+ * @param status Patient status
+ * Every field must be present and not null.
+ */
+ public Patient(Nric nric, Name name, Status status) {
+ requireAllNonNull(nric, name, status);
+ this.nric = nric;
+ this.name = name;
+ this.status = status;
+ }
+
+ /**
+ * Constructor for Patient taking in nric, name, ward.
+ *
+ * @param nric Patient NRIC
+ * @param name Patient name
+ * @param ward Patient ward
+ * Every field must be present and not null.
+ */
+ public Patient(Nric nric, Name name, WardName ward) {
+ requireAllNonNull(nric, name, ward);
+ this.nric = nric;
+ this.name = name;
+ this.ward = ward;
+ }
+
+ /**
+ * Constructor for Patient taking in nric, name, status, ward.
+ *
+ * @param nric Patient NRIC
+ * @param name Patient name
+ * @param status Patient status
+ * @param ward Patient ward
+ * Every field must be present and not null.
+ */
+ public Patient(Nric nric, Name name, Status status, WardName ward) {
+ requireAllNonNull(nric, name, status, ward);
+ this.nric = nric;
+ this.name = name;
+ this.status = status;
+ this.ward = ward;
+ }
+
+ /**
+ * Constructor for Patient taking in nric, name, status, ward.
+ *
+ * @param nric Patient NRIC
+ * @param name Patient name
+ * @param status Patient status
+ * @param ward Patient ward
+ * @param discharge Patient discharge
+ * Every field must be present and not null.
+ */
+ public Patient(Nric nric, Name name, Status status, WardName ward, Discharge discharge) {
+ requireAllNonNull(nric, name, status, ward, discharge);
+ this.nric = nric;
+ this.name = name;
+ this.status = status;
+ this.ward = ward;
+ this.discharge = discharge;
+ }
+
+ /**
+ * Returns the Nric.
+ *
+ * @return Patient Nric.
+ */
+ public Nric getNric() {
+ return nric;
+ }
+
+ /**
+ * Returns the Name.
+ *
+ * @return Patient Name.
+ */
+ public Name getName() {
+ return name;
+ }
+
+ /**
+ * Returns the Name as a String.
+ *
+ * @return Patient Name as a String.
+ */
+ public String getNameString() {
+ return name.fullName;
+ }
+
+ /**
+ * Returns the Status.
+ *
+ * @return Patient Status.
+ */
+ public Status getStatus() {
+ return status;
+ }
+
+ /**
+ * Returns the Status as a String.
+ *
+ * @return Patient Status as a String.
+ */
+ public String getStatusDesc() {
+ return status.getDesc();
+ }
+
+ /**
+ * Returns the Ward for comparison.
+ *
+ * @return Placeholder Ward for comparison.
+ */
+ public Ward getWard() {
+ return wardWithName(ward.wardName);
+ }
+
+ /**
+ * Returns the WardName.
+ *
+ * @return Patient WardName.
+ */
+ public WardName getWardName() {
+ return ward;
+ }
+
+ /**
+ * Returns the WardName as a String.
+ *
+ * @return Patient WardName as a String.
+ */
+ public String getWardNameString() {
+ return wardWithName(ward.wardName).getNameString();
+ }
+
+ /**
+ * Returns the discharge date.
+ *
+ * @return Patient Discharge.
+ */
+ public Discharge getDischarge() {
+ return discharge;
+ }
+
+ /**
+ * Returns the discharge date as a String.
+ *
+ * @return Patient Discharge as a String.
+ */
+ public String getDischargeString() {
+ return discharge.value;
+ }
+
+ /**
+ * Returns the discharge date as LocalDateTime.
+ *
+ * @return LocalDateTime representing the discharge date-time.
+ */
+ public Date getDischargeDateTime() {
+ return discharge.getDateTime();
+ }
+
+ /**
+ * Sets a new Status.
+ *
+ * @param newStatus Status to be set.
+ */
+ public void setStatus(Status newStatus) {
+ requireAllNonNull(newStatus);
+ status = newStatus;
+ }
+
+ /**
+ * Sets a new Ward.
+ *
+ * @param newWard Ward to be set.
+ */
+ public void setWard(WardName newWard) {
+ requireAllNonNull(newWard);
+ ward = newWard;
+ }
+
+ /**
+ * Sets a new Discharge.
+ *
+ * @param newDischarge Discharge to be set.
+ */
+ public void setDischarge(Discharge newDischarge) {
+ requireAllNonNull(newDischarge);
+ discharge = newDischarge;
+ }
+
+ /**
+ * Returns true if both patients have the same nric and name.
+ * This defines a weaker notion of equality between two patients.
+ *
+ * @param otherPatient Patient to be compared with.
+ * @return If the patients are the same.
+ */
+ public boolean isSamePatient(Patient otherPatient) {
+ return this.equals(otherPatient);
+ }
+
+ /**
+ * Returns true if both patients have the same Nric.
+ * This defines a weaker notion of equality between two patients in order to prevent duplicate Nric
+ * being added to the list.
+ *
+ * @param otherPatient Patient to be compared with.
+ * @return If the patients have the same Nric.
+ */
+ public boolean isSameNric(Patient otherPatient) {
+ if (otherPatient == this) {
+ return true;
+ }
+
+ return otherPatient != null
+ && otherPatient.getNric().equals(this.getNric());
+ }
+
+ /**
+ * Returns compared result between {@code this} and the given {@code patient} by Name in ascending order.
+ * Returns positive integer if {@code this} should be placed after, 0 if same, and negative if before.
+ *
+ * @param otherPatient Patient to be compared with.
+ * @return If the patient should be placed before or after.
+ */
+ public int compareToByNameAsc(Patient otherPatient) {
+ return this.getNameString().compareTo(otherPatient.getNameString());
+ }
+
+
+ /**
+ * Returns compared result between {@code this} and the given {@code patient} by Name in descending order.
+ * Returns positive integer if {@code this} should be placed after, 0 if same, and negative if before.
+ *
+ * @param otherPatient Patient to be compared with.
+ * @return If the patient should be placed before or after.
+ */
+ public int compareToByNameDesc(Patient otherPatient) {
+ return INVERTER * this.getNameString().compareTo(otherPatient.getNameString());
+ }
+
+ /**
+ * Returns compared result between {@code this} and the given {@code patient} by Status in ascending order.
+ * Returns positive integer if {@code this} should be placed after, 0 if same, and negative if before.
+ *
+ * @param otherPatient Patient to be compared with.
+ * @return If the patient should be placed before or after.
+ */
+ public int compareToByStatusAsc(Patient otherPatient) {
+ return this.getStatus().getValue().compareTo(otherPatient.getStatus().getValue());
+ }
+
+ /**
+ * Returns compared result between {@code this} and the given {@code patient} by Status in descending order.
+ * Returns positive integer if {@code this} should be placed after, 0 if same, and negative if before.
+ *
+ * @param otherPatient Patient to be compared with.
+ * @return If the patient should be placed before or after.
+ */
+ public int compareToByStatusDesc(Patient otherPatient) {
+ return INVERTER * this.getStatus().getValue().compareTo(otherPatient.getStatus().getValue());
+ }
+
+ /**
+ * Returns compared result between {@code this} and the given {@code patient} by Discharge in ascending order.
+ * Returns positive integer if {@code this} should be placed after, 0 if same, and negative if before.
+ *
+ * @param otherPatient Patient to be compared with.
+ * @return If the patient should be placed before or after.
+ */
+ public int compareToByDischargeAsc(Patient otherPatient) {
+ return this.getDischargeDateTime().compareTo(otherPatient.getDischargeDateTime());
+ }
+
+ /**
+ * Returns compared result between {@code this} and the given {@code patient} by Discharge in descending order.
+ * Returns positive integer if {@code this} should be placed after, 0 if same, and negative if before.
+ *
+ * @param otherPatient Patient to be compared with.
+ * @return If the patient should be placed before or after.
+ */
+ public int compareToByDischargeDesc(Patient otherPatient) {
+ return INVERTER * this.getDischargeDateTime().compareTo(otherPatient.getDischargeDateTime());
+ }
+
+ /**
+ * Returns compared result between {@code this} and the given {@code patient} by Ward in ascending order.
+ * Returns positive integer if {@code this} should be placed after, 0 if same, and negative if before.
+ *
+ * @param otherPatient Patient to be compared with.
+ * @return If the patient should be placed before or after.
+ */
+ public int compareToByWardAsc(Patient otherPatient) {
+ return this.getWardNameString().compareTo(otherPatient.getWardNameString());
+ }
+
+ /**
+ * Returns compared result between {@code this} and the given {@code patient} by Ward in descending order.
+ * Returns positive integer if {@code this} should be placed after, 0 if same, and negative if before.
+ *
+ * @param otherPatient Patient to be compared with.
+ * @return If the patient should be placed before or after.
+ */
+ public int compareToByWardDesc(Patient otherPatient) {
+ return INVERTER * this.getWardNameString().compareTo(otherPatient.getWardNameString());
+ }
+
+ /**
+ * Returns true if both patients have the same identity and data fields.
+ * This defines a stronger notion of equality between two patients.
+ */
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ }
+
+ if (!(other instanceof Patient)) {
+ return false;
+ }
+
+ Patient otherPatient = (Patient) other;
+ return otherPatient.getNric().equals(getNric())
+ && otherPatient.getName().equals(getName());
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(nric, name, status, ward, discharge);
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append(getNric())
+ .append("; Name: ")
+ .append(getName())
+ .append("; Status: ")
+ .append(getStatus())
+ .append("; Ward: ")
+ .append(getWardNameString())
+ .append("; Discharge: ")
+ .append(getDischarge());
+
+ return builder.toString();
+ }
+}
diff --git a/src/main/java/seedu/medinfo/model/patient/Status.java b/src/main/java/seedu/medinfo/model/patient/Status.java
new file mode 100644
index 00000000000..0d0f5efef70
--- /dev/null
+++ b/src/main/java/seedu/medinfo/model/patient/Status.java
@@ -0,0 +1,100 @@
+package seedu.medinfo.model.patient;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.medinfo.commons.util.AppUtil.checkArgument;
+
+/**
+ * Represents a patient status in the medinfo book.
+ */
+public class Status {
+ /**
+ * The colour codes below reflect the severity of a patient's condition
+ * and the urgency of treatment needed.
+ *
+ * GRAY: Unknown condition, waiting for evaluation
+ * GREEN: Stable condition, re-evaluation every 180 min
+ * YELLOW: Serious condition, re-evaluation every 60 min
+ * RED: Critical condition, requires immediate evaluation by physician
+ */
+
+ public static final String MESSAGE_CONSTRAINTS = "Statuses should only be 'GRAY', 'GREEN', 'YELLOW', or 'RED'";
+ private static String[] values = { "GRAY", "GREEN", "YELLOW", "RED" };
+
+ public final String value;
+
+ /**
+ * Constructs an {@code status}.
+ *
+ * @param status A valid status.
+ */
+ public Status(String status) {
+ requireNonNull(status);
+ checkArgument(isValidStatus(status), MESSAGE_CONSTRAINTS);
+ value = status;
+ }
+
+ /**
+ * Returns true if a given string is a valid status.
+ */
+ public static boolean isValidStatus(String test) {
+ for (String value : values) {
+ if (test.equals(value)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns description of the status code.
+ *
+ * @return Description of status code.
+ */
+ public String getDesc() {
+ switch(value) {
+ case "GREEN":
+ return "STABLE";
+ case "YELLOW":
+ return "SERIOUS";
+ case "RED":
+ return "CRITICAL";
+ default:
+ return "UNKNOWN";
+ }
+ }
+
+ /**
+ * Returns the numeric value of each status.
+ *
+ * @return Numeric value of each status.
+ */
+ public Integer getValue() {
+ switch ((value)) {
+ case "GREEN":
+ return 1;
+ case "YELLOW":
+ return 2;
+ case "RED":
+ return 3;
+ default:
+ return 0;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return value;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof Status // instanceof handles nulls
+ && value.equals(((Status) other).value)); // state check
+ }
+
+ @Override
+ public int hashCode() {
+ return value.hashCode();
+ }
+}
diff --git a/src/main/java/seedu/medinfo/model/patient/StatusContainsKeywordsPredicate.java b/src/main/java/seedu/medinfo/model/patient/StatusContainsKeywordsPredicate.java
new file mode 100644
index 00000000000..81ad3c4e5f6
--- /dev/null
+++ b/src/main/java/seedu/medinfo/model/patient/StatusContainsKeywordsPredicate.java
@@ -0,0 +1,32 @@
+package seedu.medinfo.model.patient;
+
+import java.util.List;
+import java.util.function.Predicate;
+
+import seedu.medinfo.commons.util.StringUtil;
+
+/**
+ * Tests that a {@code Patient}'s {@code Status} matches any of the keywords
+ * given.
+ */
+public class StatusContainsKeywordsPredicate implements Predicate {
+ private final List keywords;
+
+ public StatusContainsKeywordsPredicate(List keywords) {
+ this.keywords = keywords;
+ }
+
+ @Override
+ public boolean test(Patient patient) {
+ return keywords.stream()
+ .anyMatch(keyword -> StringUtil.containsWordIgnoreCase(patient.getStatus().value, keyword));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof StatusContainsKeywordsPredicate // instanceof handles nulls
+ && keywords.equals(((StatusContainsKeywordsPredicate) other).keywords)); // state check
+ }
+
+}
diff --git a/src/main/java/seedu/medinfo/model/patient/UniquePatientList.java b/src/main/java/seedu/medinfo/model/patient/UniquePatientList.java
new file mode 100644
index 00000000000..359aab5240a
--- /dev/null
+++ b/src/main/java/seedu/medinfo/model/patient/UniquePatientList.java
@@ -0,0 +1,212 @@
+package seedu.medinfo.model.patient;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.medinfo.commons.util.CollectionUtil.requireAllNonNull;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
+import seedu.medinfo.model.patient.exceptions.DuplicatePatientException;
+import seedu.medinfo.model.patient.exceptions.PatientNotFoundException;
+
+/**
+ * A list of patients that enforces uniqueness between its elements and does not
+ * allow nulls.
+ * A patient is considered unique by comparing using
+ * {@code Patient#isSamePatient(Patient)}. As such, adding and updating of
+ * patients uses Patient#isSamePatient(Patient) for equality so as to ensure that
+ * the patient being added or updated is
+ * unique in terms of identity in the UniquePatientList. However, the removal of
+ * a patient uses Patient#equals(Object) so
+ * as to ensure that the patient with exactly the same fields will be removed.
+ *
+ * Supports a minimal set of list operations.
+ *
+ * @see Patient#isSamePatient(Patient)
+ */
+public class UniquePatientList implements Iterable {
+
+ private final ObservableList internalList = FXCollections.observableArrayList();
+ private final ObservableList internalUnmodifiableList = FXCollections
+ .unmodifiableObservableList(internalList);
+
+
+ /**
+ * Returns size of list.
+ */
+ public int size() {
+ return internalList.size();
+ }
+
+ /**
+ * Returns total number of critical patients.
+ */
+ public int numberOfCritical() {
+ int critical = 0;
+ for (Patient patient:internalList) {
+ critical = patient.getStatusDesc().equals("CRITICAL") ? critical + 1 : critical;
+ }
+ return critical;
+ }
+
+ /**
+ * Returns true if the list contains an equivalent patient as the given
+ * argument.
+ * @param toCheck Patient to be checked.
+ */
+ public boolean contains(Patient toCheck) {
+ requireNonNull(toCheck);
+ return internalList.stream().anyMatch(toCheck::isSamePatient);
+ }
+
+ /**
+ * Returns true if the list contains a patient with equivalent NRIC as the given
+ * argument.
+ * @param toCheck Patient to be checked.
+ */
+ public boolean containsNric(Patient toCheck) {
+ requireNonNull(toCheck);
+ return internalList.stream().anyMatch(toCheck::isSameNric);
+ }
+
+ /**
+ * Adds a patient to the list.
+ * The patient must not already exist in the list.
+ * @param toAdd Patient to be added.
+ */
+ public void add(Patient toAdd) {
+ requireNonNull(toAdd);
+ if (contains(toAdd)) {
+ throw new DuplicatePatientException();
+ }
+ internalList.add(toAdd);
+ }
+
+ /**
+ * Replaces the patient {@code target} in the list with {@code editedPatient}.
+ * {@code target} must exist in the list.
+ * The patient identity of {@code editedPatient} must not be the same as another
+ * existing patient in the list.
+ */
+ public void setPatient(Patient target, Patient editedPatient) {
+ requireAllNonNull(target, editedPatient);
+
+ int index = internalList.indexOf(target);
+ if (index == -1) {
+ throw new PatientNotFoundException();
+ }
+
+ if (!target.isSamePatient(editedPatient) && contains(editedPatient)) {
+ throw new DuplicatePatientException();
+ }
+
+ internalList.set(index, editedPatient);
+ }
+
+ /**
+ * Removes the equivalent patient from the list.
+ * The patient must exist in the list.
+ * @param toRemove Patient to be removed.
+ */
+ public void remove(Patient toRemove) {
+ requireNonNull(toRemove);
+ if (!internalList.remove(toRemove)) {
+ throw new PatientNotFoundException();
+ }
+ }
+
+ /**
+ * Replaces the contents of this list with {@code replacement}.
+ * {@code replacement} must not contain duplicate patients.
+ * @param replacement List of patients to be set.
+ */
+ public void setPatients(UniquePatientList replacement) {
+ requireNonNull(replacement);
+ internalList.setAll(replacement.internalList);
+ }
+
+ /**
+ * Replaces the contents of this list with {@code patients}.
+ * {@code patients} must not contain duplicate patients.
+ * @param patients List of patients to be set.
+ */
+ public void setPatients(List patients) {
+ requireAllNonNull(patients);
+ if (!patientsAreUnique(patients)) {
+ throw new DuplicatePatientException();
+ }
+ internalList.setAll(patients);
+ }
+
+
+ // @@author {Echomo-Xinyu}-reused
+ // Referenced the sortPatient and replaceSort methods
+ /**
+ * Sorts the patient list with {@code comparator}.
+ * @param comparator Comparator used.
+ */
+ public void sortPatients(Comparator comparator) {
+ requireNonNull(comparator);
+ ArrayList sortedList = replaceSort(internalList, comparator);
+ internalList.setAll(sortedList);
+ }
+
+ /**
+ * Sorts the list of patients and returns the sorted list.
+ * @param observableList List to be sorted.
+ * @param comparator Comparator used.
+ * @return The sorted list.
+ */
+ private static ArrayList replaceSort(
+ ObservableList observableList, Comparator comparator) {
+ ArrayList duplicatedList = new ArrayList<>();
+ for (int i = 0; i < observableList.size(); i++) {
+ duplicatedList.add(observableList.get(i));
+ }
+ duplicatedList.sort(comparator);
+ return duplicatedList;
+ }
+ //@@author
+
+ /**
+ * Returns the backing list as an unmodifiable {@code ObservableList}.
+ */
+ public ObservableList asUnmodifiableObservableList() {
+ return internalUnmodifiableList;
+ }
+
+ @Override
+ public Iterator iterator() {
+ return internalList.iterator();
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof UniquePatientList // instanceof handles nulls
+ && internalList.equals(((UniquePatientList) other).internalList));
+ }
+
+ @Override
+ public int hashCode() {
+ return internalList.hashCode();
+ }
+
+ /**
+ * Returns true if {@code patients} contains only unique patients.
+ */
+ private boolean patientsAreUnique(List patients) {
+ for (int i = 0; i < patients.size() - 1; i++) {
+ for (int j = i + 1; j < patients.size(); j++) {
+ if (patients.get(i).isSamePatient(patients.get(j))) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+}
diff --git a/src/main/java/seedu/medinfo/model/patient/exceptions/DuplicatePatientException.java b/src/main/java/seedu/medinfo/model/patient/exceptions/DuplicatePatientException.java
new file mode 100644
index 00000000000..abb739c5a0f
--- /dev/null
+++ b/src/main/java/seedu/medinfo/model/patient/exceptions/DuplicatePatientException.java
@@ -0,0 +1,12 @@
+package seedu.medinfo.model.patient.exceptions;
+
+/**
+ * Signals that the operation will result in duplicate Patients.
+ * Patients are considered duplicates if they have the same identity.
+ */
+public class DuplicatePatientException extends RuntimeException {
+ public DuplicatePatientException() {
+ super("Operation would result in duplicate patients");
+ }
+
+}
diff --git a/src/main/java/seedu/medinfo/model/patient/exceptions/PatientNotFoundException.java b/src/main/java/seedu/medinfo/model/patient/exceptions/PatientNotFoundException.java
new file mode 100644
index 00000000000..f439eb3f063
--- /dev/null
+++ b/src/main/java/seedu/medinfo/model/patient/exceptions/PatientNotFoundException.java
@@ -0,0 +1,6 @@
+package seedu.medinfo.model.patient.exceptions;
+
+/**
+ * Signals that the operation is unable to find the specified patient.
+ */
+public class PatientNotFoundException extends RuntimeException {}
diff --git a/src/main/java/seedu/medinfo/model/util/SampleDataUtil.java b/src/main/java/seedu/medinfo/model/util/SampleDataUtil.java
new file mode 100644
index 00000000000..fd188002ef3
--- /dev/null
+++ b/src/main/java/seedu/medinfo/model/util/SampleDataUtil.java
@@ -0,0 +1,64 @@
+package seedu.medinfo.model.util;
+
+import seedu.medinfo.logic.commands.exceptions.CommandException;
+import seedu.medinfo.model.MedInfo;
+import seedu.medinfo.model.ReadOnlyMedInfo;
+import seedu.medinfo.model.patient.Name;
+import seedu.medinfo.model.patient.Nric;
+import seedu.medinfo.model.patient.Patient;
+import seedu.medinfo.model.patient.Status;
+import seedu.medinfo.model.ward.Ward;
+import seedu.medinfo.model.ward.WardName;
+
+/**
+ * Contains utility methods for populating {@code MedInfo} with sample data.
+ */
+public class SampleDataUtil {
+
+ /**
+ * Sample Patients for testing.
+ * @return Array of sample Patients.
+ */
+ public static Patient[] getSamplePatients() {
+ return new Patient[] {
+ new Patient(new Nric("S1234567A"), new Name("Alex Yeoh"), new Status("RED"),
+ new WardName("Intensive Care")),
+ new Patient(new Nric("S0000000A"), new Name("Bernice Yu"), new WardName("Class C")),
+ new Patient(new Nric("S0000001A"), new Name("Charlotte Oliveiro"), new Status("GRAY")),
+ new Patient(new Nric("S0000002A"), new Name("David Li"), new Status("GREEN")),
+ new Patient(new Nric("S0000003A"), new Name("Irfan Ibrahim"), new Status("YELLOW")),
+ new Patient(new Nric("S0000004A"), new Name("Roy Balakrishnan"), new Status("RED"))
+ };
+ }
+
+ /**
+ * Sample Wards for testing.
+ * @return Array of sample Wards.
+ */
+ public static Ward[] getSampleWards() {
+ return new Ward[] {
+ new Ward(new WardName("Waiting Room")),
+ new Ward(new WardName("Class A")),
+ new Ward(new WardName("Class B")),
+ new Ward(new WardName("Class C")),
+ new Ward(new WardName("Intensive Care"))
+ };
+ }
+
+ /**
+ * Creates a {@code ReadOnlyMedInfo} with the sample data in this class.
+ * @return ReadOnlyMedInfo with sample data initialized.
+ */
+ public static ReadOnlyMedInfo getSampleMedInfo() throws CommandException {
+ MedInfo sampleAb = new MedInfo();
+ for (Ward sampleWard : getSampleWards()) {
+ sampleAb.addWard(sampleWard);
+ }
+
+ for (Patient samplePatient : getSamplePatients()) {
+ sampleAb.addPatient(samplePatient);
+ }
+
+ return sampleAb;
+ }
+}
diff --git a/src/main/java/seedu/medinfo/model/ward/Capacity.java b/src/main/java/seedu/medinfo/model/ward/Capacity.java
new file mode 100644
index 00000000000..0ef7f66ec5b
--- /dev/null
+++ b/src/main/java/seedu/medinfo/model/ward/Capacity.java
@@ -0,0 +1,75 @@
+package seedu.medinfo.model.ward;
+
+/**
+ * Represents the capacity and occupancy of a ward.
+ */
+public class Capacity {
+ private static final int MIN_CAPACITY = 1;
+ private static final int MAX_CAPACITY = 1000;
+
+ public static final String MESSAGE_CONSTRAINTS = "Capacity should be a"
+ + " positive integer (at least " + Integer.valueOf(MIN_CAPACITY) + " and less than or equal to "
+ + Integer.valueOf(MAX_CAPACITY) + ")"
+ + " and it should not be blank";
+
+ private int value;
+
+ /**
+ * Constructs a {@code Capacity} with the given capacity.
+ *
+ * @param capacity Integer value of the capacity.
+ */
+ public Capacity(int capacity) {
+ value = capacity;
+ }
+
+ /**
+ * Constructs a {@code Capacity} with the given capacity.
+ *
+ * @param capacity String value of the capacity.
+ */
+ public Capacity(String capacity) {
+ value = Integer.parseInt(capacity);
+ }
+
+ /**
+ * Sets the Capacity value.
+ *
+ * @param capacity Integer value to be set.
+ */
+ public void setCapacity(int capacity) {
+ value = capacity;
+ }
+
+ /**
+ * Returns true if a given string is a valid capacity.
+ *
+ * @param test String capacity value to be tested.
+ * @return If the given string is a valid capacity.
+ */
+ public static boolean isValidCapacity(String test) {
+ try {
+ int value = Integer.parseInt(test);
+ if (value < MIN_CAPACITY || value > MAX_CAPACITY) {
+ return false;
+ }
+ return true;
+ } catch (NumberFormatException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Returns the Integer value of {@code this}.
+ *
+ * @return
+ */
+ public int getValue() {
+ return value;
+ }
+
+ @Override
+ public String toString() {
+ return Integer.toString(value);
+ }
+}
diff --git a/src/main/java/seedu/medinfo/model/ward/UniqueWardList.java b/src/main/java/seedu/medinfo/model/ward/UniqueWardList.java
new file mode 100644
index 00000000000..4a4f8ea78f8
--- /dev/null
+++ b/src/main/java/seedu/medinfo/model/ward/UniqueWardList.java
@@ -0,0 +1,305 @@
+package seedu.medinfo.model.ward;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.medinfo.commons.util.CollectionUtil.requireAllNonNull;
+import static seedu.medinfo.model.ward.Ward.wardWithName;
+
+import java.util.Iterator;
+import java.util.List;
+
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
+import seedu.medinfo.logic.commands.exceptions.CommandException;
+import seedu.medinfo.model.patient.Patient;
+import seedu.medinfo.model.patient.exceptions.DuplicatePatientException;
+import seedu.medinfo.model.ward.exceptions.DuplicateWardException;
+import seedu.medinfo.model.ward.exceptions.InsufficientCapacityException;
+import seedu.medinfo.model.ward.exceptions.WardFullException;
+import seedu.medinfo.model.ward.exceptions.WardNotFoundException;
+
+/**
+ * A list of wards that enforces uniqueness between its elements and does not
+ * allow nulls.
+ * A ward is considered unique by comparing using
+ * {@code Ward#isSameWard(Ward)}. As such, adding and updating of
+ * wards uses Ward#isSameWard(Ward) for equality so as to ensure that
+ * the ward being added or updated is
+ * unique in terms of identity in the UniqueWardList. However, the removal of
+ * a ward uses Ward#equals(Object) so
+ * as to ensure that the ward with exactly the same fields will be removed.
+ *
+ * Supports a minimal set of list operations.
+ *
+ * @see Ward#isSameWard(Ward)
+ */
+public class UniqueWardList implements Iterable {
+
+ private static final WardName WAITING_ROOM = new WardName("Waiting Room");
+ private final ObservableList internalList = FXCollections.observableArrayList();
+ private final ObservableList internalUnmodifiableList = FXCollections
+ .unmodifiableObservableList(internalList);
+
+ /**
+ * Constructor for a UniqueWardList.
+ */
+ public UniqueWardList() {
+
+ }
+
+ /**
+ * Initializes default Waiting Room ward with capacity of 10 inside.
+ */
+ public void newUniqueWardList() {
+ Ward waitingRoom = new Ward(WAITING_ROOM);
+ internalList.add(waitingRoom);
+ }
+
+ /**
+ * Returns size of list.
+ *
+ * @return Size of List.
+ */
+ public int size() {
+ return internalList.size();
+ }
+
+ /**
+ * Returns total capacity of all wards in the list.
+ *
+ * @return Total capacity of all wards.
+ */
+ public int capacity() {
+ int capacity = 0;
+ for (Ward ward: internalList) {
+ Capacity cap = ward.getCapacity();
+ capacity += cap.getValue();
+ }
+ return capacity;
+ }
+
+ /**
+ * Returns specified ward to edit.
+ *
+ * @param wardName String name of ward to be edited.
+ * @return Target ward.
+ */
+ public Ward getWard(String wardName) {
+ return internalList.get(internalList.indexOf(wardWithName(wardName)));
+ }
+
+ /**
+ * Returns true if the list contains an equivalent ward as the given
+ * {@code Ward}.
+ *
+ * @param toCheck Ward to be checked.
+ */
+ public boolean contains(Ward toCheck) {
+ requireNonNull(toCheck);
+ return internalList.stream().anyMatch(toCheck::isSameWard);
+ }
+
+ /**
+ * Returns true if the list contains an equivalent ward as the given
+ * {@code String}.
+ *
+ * @param toCheckName String to be checked.
+ */
+ public boolean contains(String toCheckName) {
+ requireNonNull(toCheckName);
+ WardName wardName = new WardName(toCheckName);
+ Ward toCheck = new Ward(wardName);
+ return internalList.stream().anyMatch(toCheck::isSameWard);
+ }
+
+ /**
+ * Adds a ward to the list.
+ * The ward must not already exist in the list.
+ *
+ * @param toAdd Ward to be added.
+ */
+ public void add(Ward toAdd) {
+ requireNonNull(toAdd);
+ if (!contains(toAdd)) {
+ internalList.add(toAdd);
+ }
+ }
+
+ /**
+ * Adds patient p to their assigned ward.
+ *
+ * @param p Patient to be added.
+ */
+ public void addPatient(Patient p) throws CommandException, WardFullException {
+ requireNonNull(p);
+ String targetName = p.getWardNameString();
+ int index = internalList.indexOf(wardWithName(targetName));
+ Ward target = internalList.get(index);
+ target.addPatient(p);
+ internalList.set(index, target);
+ }
+
+ /**
+ * Replaces the ward {@code target} in the list with {@code editedWard}.
+ * {@code target} must exist in the list.
+ * The ward identity of {@code editedWard} must not be the same as another
+ * existing ward in the list.
+ *
+ * @param target Target ward.
+ * @param editedWard Ward to edit {@code target} to.
+ */
+ public void setWard(Ward target, Ward editedWard) {
+ requireAllNonNull(target, editedWard);
+
+ int index = internalList.indexOf(target);
+ if (index == -1) {
+ throw new WardNotFoundException(target.getNameString());
+ }
+
+ if (!target.isSameWard(editedWard) && contains(editedWard)) {
+ throw new DuplicatePatientException();
+ }
+
+ if (editedWard.getCapacity().getValue() < target.getOccupancy()) {
+ throw new InsufficientCapacityException();
+ }
+
+ ObservableList patients = target.getPatientList();
+ for (Patient patient : patients) {
+ editedWard.addPatient(patient);
+ }
+
+ internalList.set(index, editedWard);
+ }
+
+ /**
+ * Replaces the ward {@code target} in the target's ward with
+ * {@code editedPatient}.
+ * {@code target} must exist in the ward.
+ *
+ * @param target Target patient
+ * @param editedPatient Patient to edit {@code target} to.
+ */
+ public void setPatient(Patient target, Patient editedPatient) throws CommandException, WardFullException {
+ String targetName = target.getWardNameString();
+ String editedName = editedPatient.getWardNameString();
+ int targetIndex = internalList.indexOf(wardWithName(targetName));
+ int editedIndex = internalList.indexOf(wardWithName(editedName));
+
+ if (!targetName.equals(editedName)) {
+ changePatientWard(target, targetIndex, editedIndex);
+ } else {
+ Ward targetWard = internalList.get(targetIndex);
+ targetWard.setPatient(target, editedPatient);
+ internalList.set(targetIndex, targetWard);
+ }
+ }
+
+ /**
+ * Moves patient from one ward to another
+ *
+ * @param target The target patient
+ * @param from The patient's current ward index in internalList.
+ * @param to The patient's next ward index in internalList.
+ */
+ public void changePatientWard(Patient target, int from, int to) throws WardFullException {
+ Ward start = internalList.get(from);
+ Ward end = internalList.get(to);
+ end.addPatient(target);
+ start.removePatient(target);
+ internalList.set(from, start);
+ internalList.set(to, end);
+ }
+
+ /**
+ * Removes the equivalent ward from the list.
+ * The ward must exist in the list.
+ *
+ * @param toRemove Ward to be removed.
+ */
+ public void remove(Ward toRemove) {
+ requireNonNull(toRemove);
+ if (!internalList.remove(toRemove)) {
+ throw new WardNotFoundException(toRemove.getNameString());
+ }
+ }
+
+ /**
+ * Removes the equivalent patient from their assigned ward.
+ *
+ * @param toRemove Patient to be removed.
+ */
+ public void remove(Patient toRemove) {
+ requireNonNull(toRemove);
+ String targetName = toRemove.getWardNameString();
+ int index = internalList.indexOf(wardWithName(targetName));
+ Ward targetWard = internalList.get(index);
+ targetWard.removePatient(toRemove);
+ internalList.set(index, targetWard);
+ }
+
+ /**
+ * Replaces the entire ward list with {@code replacement}.
+ *
+ * @param replacement Ward list to be replaced with.
+ */
+ public void setWards(UniqueWardList replacement) {
+ requireNonNull(replacement);
+ internalList.setAll(replacement.internalList);
+ }
+
+ /**
+ * Replaces the contents of this list with {@code wards}.
+ * {@code wards} must not contain duplicate wards.
+ *
+ * @param wards Ward list to be replaced with.
+ */
+ public void setWards(List wards) {
+ requireAllNonNull(wards);
+ if (!wardsAreUnique(wards)) {
+ throw new DuplicateWardException();
+ }
+
+ internalList.setAll(wards);
+ }
+
+ /**
+ * Returns true if {@code patients} contains only unique patients.
+ *
+ * @param wards Ward list to be checked.
+ * @return If the ward list contains only unique patients.
+ */
+ private boolean wardsAreUnique(List wards) {
+ for (int i = 0; i < wards.size() - 1; i++) {
+ for (int j = i + 1; j < wards.size(); j++) {
+ if (wards.get(i).isSameWard(wards.get(j))) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Returns the backing list as an unmodifiable {@code ObservableList}.
+ */
+ public ObservableList asUnmodifiableObservableList() {
+ return internalUnmodifiableList;
+ }
+
+ @Override
+ public Iterator iterator() {
+ return internalList.iterator();
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof UniqueWardList // instanceof handles nulls
+ && internalList.equals(((UniqueWardList) other).internalList));
+ }
+
+ @Override
+ public int hashCode() {
+ return internalList.hashCode();
+ }
+}
diff --git a/src/main/java/seedu/medinfo/model/ward/Ward.java b/src/main/java/seedu/medinfo/model/ward/Ward.java
new file mode 100644
index 00000000000..006b2a47afa
--- /dev/null
+++ b/src/main/java/seedu/medinfo/model/ward/Ward.java
@@ -0,0 +1,189 @@
+package seedu.medinfo.model.ward;
+
+import static java.util.Objects.requireNonNull;
+
+import java.util.List;
+
+import javafx.collections.ObservableList;
+import seedu.medinfo.model.patient.Patient;
+import seedu.medinfo.model.patient.UniquePatientList;
+import seedu.medinfo.model.ward.exceptions.WardFullException;
+
+/**
+ * Represents a ward which stores patients.
+ */
+public class Ward {
+
+ public final WardName value;
+
+ private Capacity capacity;
+
+ private UniquePatientList patients;
+
+ /**
+ * Constructs a {@code Ward}.
+ *
+ * @param name A valid name.
+ */
+ public Ward(WardName name) {
+ requireNonNull(name);
+ this.value = name;
+ this.capacity = new Capacity(10);
+ patients = new UniquePatientList();
+ }
+
+ /**
+ * Constructs a {@code Ward}.
+ *
+ * @param name A valid name.
+ * @param capacity A specified capacity.
+ */
+ public Ward(WardName name, Capacity capacity) {
+ requireNonNull(name);
+ this.value = name;
+ this.capacity = capacity;
+ patients = new UniquePatientList();
+ }
+
+ /**
+ * Ward factory constructor with string for comparing.
+ *
+ * @param name Name of the ward.
+ * @return placeholder Ward for comparison.
+ */
+ public static Ward wardWithName(String name) {
+ WardName wardName = new WardName(name);
+ return new Ward(wardName);
+ }
+
+ /**
+ * Edit capacity of this ward
+ *
+ * @param capacity
+ * @return Ward with edited capacity
+ */
+ public Ward withCapacity(int capacity) {
+ this.capacity = new Capacity(capacity);
+ return this;
+ }
+
+ /**
+ * Returns true if a given occupany can fit in the
+ * ward's capacity
+ *
+ * @param occupancy Occupancy to check.
+ * @return If occupancy can fit in the capacity.
+ */
+ public boolean canSupport(int occupancy) {
+ return capacity.getValue() >= occupancy;
+ }
+
+ /**
+ * Returns true if a given String is a valid Ward name.
+ *
+ * @param test String to check.
+ * @return If the String is a valid Ward name.
+ */
+ public static boolean isValidWardName(String test) {
+ return WardName.isValidWardName(test);
+ }
+
+ public WardName getName() {
+ return value;
+ }
+
+ public String getNameString() {
+ return value.wardName;
+ }
+
+ public Capacity getCapacity() {
+ return capacity;
+ }
+
+ public String getCapacityString() {
+ return capacity.toString();
+ }
+
+ public int getOccupancy() {
+ return patients.size();
+ }
+
+ public String getOccupancyString() {
+ return "Current occupancy: " + getOccupancy() + "/" + capacity.getValue();
+ }
+
+ public boolean isSameWard(Ward other) {
+ return this.equals(other);
+ }
+
+ /**
+ * Replaces the contents of the patient list with {@code patients}.
+ * {@code patients} must not contain duplicate patients.
+ *
+ * @param patients List of patients to replace with.
+ */
+ public void setPatients(List patients) {
+ this.patients.setPatients(patients);
+ }
+
+ /**
+ * Adds a patient to the ward.
+ * The patient must not already exist in the medinfo book.
+ *
+ * @param patient Patient to be added.
+ */
+ public void addPatient(Patient patient) throws WardFullException {
+ requireNonNull(patient);
+ if (patients.size() == capacity.getValue()) {
+ throw new WardFullException(value.toString());
+ }
+ patients.add(patient);
+ }
+
+ /**
+ * Replaces the given patient {@code target} in the list with
+ * {@code editedPatient}.
+ * {@code target} must exist in the medinfo book.
+ * The patient identity of {@code editedPatient} must not be the same as another
+ * existing patient in the medinfo book.
+ *
+ * @param target Target Patient.
+ * @param editedPatient Patient to edit {@code target} to.
+ */
+ public void setPatient(Patient target, Patient editedPatient) {
+ requireNonNull(editedPatient);
+ patients.setPatient(target, editedPatient);
+ }
+
+ /**
+ * Removes {@code key} from this {@code Ward}.
+ * {@code key} must exist in the medinfo book.
+ *
+ * @param patient Patient to be removed.
+ */
+ public void removePatient(Patient patient) {
+ patients.remove(patient);
+ }
+
+ @Override
+ public String toString() {
+ return patients.asUnmodifiableObservableList().size() + " patients";
+ }
+
+ public ObservableList getPatientList() {
+ return patients.asUnmodifiableObservableList();
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof Ward // instanceof handles nulls
+ && value.equals(((Ward) other).value));
+ }
+
+ @Override
+ public int hashCode() {
+ return patients.hashCode();
+ }
+
+}
diff --git a/src/main/java/seedu/medinfo/model/ward/WardName.java b/src/main/java/seedu/medinfo/model/ward/WardName.java
new file mode 100644
index 00000000000..60af11a34cd
--- /dev/null
+++ b/src/main/java/seedu/medinfo/model/ward/WardName.java
@@ -0,0 +1,61 @@
+package seedu.medinfo.model.ward;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.medinfo.commons.util.AppUtil.checkArgument;
+
+/**
+ * Represents a Ward's name in MedInfo.
+ * Guarantees: immutable; is valid as declared in {@link #isValidWardName(String)}
+ */
+public class WardName {
+
+ public static final String MESSAGE_CONSTRAINTS = "Ward names should only contain alphanumeric characters"
+ + "and spaces, and it should not be blank";
+
+ /*
+ * The first character of the name must not be a whitespace,
+ * otherwise " " (a blank string) becomes a valid input.
+ */
+ public static final String VALIDATION_REGEX = "[\\p{Alnum}][\\p{Alnum} ]*";
+
+ public final String wardName;
+
+ /**
+ * Constructs a {@code WardName}.
+ *
+ * @param name A valid ward name.
+ */
+ public WardName(String name) {
+ requireNonNull(name);
+ checkArgument(isValidWardName(name), MESSAGE_CONSTRAINTS);
+ wardName = name;
+ }
+
+ /**
+ * Returns true if a given string is a valid ward name.
+ *
+ * @param test String to be tested.
+ * @return if the given string is a valid ward name.
+ */
+ public static boolean isValidWardName(String test) {
+ return test.matches(VALIDATION_REGEX);
+ }
+
+ @Override
+ public String toString() {
+ return wardName;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof WardName // instanceof handles nulls
+ && wardName.equalsIgnoreCase(((WardName) other).wardName)); // state check
+ }
+
+ @Override
+ public int hashCode() {
+ return wardName.hashCode();
+ }
+
+}
diff --git a/src/main/java/seedu/medinfo/model/ward/WardNameContainsKeywordsPredicate.java b/src/main/java/seedu/medinfo/model/ward/WardNameContainsKeywordsPredicate.java
new file mode 100644
index 00000000000..e37970626a3
--- /dev/null
+++ b/src/main/java/seedu/medinfo/model/ward/WardNameContainsKeywordsPredicate.java
@@ -0,0 +1,33 @@
+package seedu.medinfo.model.ward;
+
+import java.util.List;
+import java.util.function.Predicate;
+
+import seedu.medinfo.commons.util.StringUtil;
+import seedu.medinfo.model.patient.Patient;
+
+/**
+ * Tests that a {@code Patient}'s {@code Status} matches any of the keywords
+ * given.
+ */
+public class WardNameContainsKeywordsPredicate implements Predicate {
+ private final List keywords;
+
+ public WardNameContainsKeywordsPredicate(List keywords) {
+ this.keywords = keywords;
+ }
+
+ @Override
+ public boolean test(Patient patient) {
+ return keywords.stream()
+ .anyMatch(keyword -> StringUtil.containsWordIgnoreCase(patient.getWard().getNameString(), keyword));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this
+ || (other instanceof WardNameContainsKeywordsPredicate
+ && keywords.equals(((WardNameContainsKeywordsPredicate) other).keywords));
+ }
+
+}
diff --git a/src/main/java/seedu/medinfo/model/ward/exceptions/DuplicateWardException.java b/src/main/java/seedu/medinfo/model/ward/exceptions/DuplicateWardException.java
new file mode 100644
index 00000000000..6219c440e32
--- /dev/null
+++ b/src/main/java/seedu/medinfo/model/ward/exceptions/DuplicateWardException.java
@@ -0,0 +1,11 @@
+package seedu.medinfo.model.ward.exceptions;
+
+/**
+ * Signals that the operation will result in duplicate Wards.
+ * Wards are considered duplicates if they have the same name.
+ */
+public class DuplicateWardException extends RuntimeException {
+ public DuplicateWardException() {
+ super("Operation would result in duplicate wards");
+ }
+}
diff --git a/src/main/java/seedu/medinfo/model/ward/exceptions/InsufficientCapacityException.java b/src/main/java/seedu/medinfo/model/ward/exceptions/InsufficientCapacityException.java
new file mode 100644
index 00000000000..38ecdbdc639
--- /dev/null
+++ b/src/main/java/seedu/medinfo/model/ward/exceptions/InsufficientCapacityException.java
@@ -0,0 +1,11 @@
+package seedu.medinfo.model.ward.exceptions;
+
+/**
+ * Signals that the operation will result in an edited Ward with insufficient
+ * capacity.
+ */
+public class InsufficientCapacityException extends RuntimeException {
+ public InsufficientCapacityException() {
+ super("Operation would result in the edited ward having insufficient capacity!");
+ }
+}
diff --git a/src/main/java/seedu/medinfo/model/ward/exceptions/WardFullException.java b/src/main/java/seedu/medinfo/model/ward/exceptions/WardFullException.java
new file mode 100644
index 00000000000..49c64cba657
--- /dev/null
+++ b/src/main/java/seedu/medinfo/model/ward/exceptions/WardFullException.java
@@ -0,0 +1,21 @@
+package seedu.medinfo.model.ward.exceptions;
+
+/**
+ * Signals that the ward is full.
+ */
+public class WardFullException extends RuntimeException {
+ private String name;
+
+ /**
+ * Constructs a new {@code WardFullException} with the specified ward name {@code name}.
+ */
+ public WardFullException(String name) {
+ super(name + " is full!");
+ this.name = name;
+ }
+
+ @Override
+ public String toString() {
+ return name + " is full!";
+ }
+}
diff --git a/src/main/java/seedu/medinfo/model/ward/exceptions/WardNotFoundException.java b/src/main/java/seedu/medinfo/model/ward/exceptions/WardNotFoundException.java
new file mode 100644
index 00000000000..e203ae73a61
--- /dev/null
+++ b/src/main/java/seedu/medinfo/model/ward/exceptions/WardNotFoundException.java
@@ -0,0 +1,10 @@
+package seedu.medinfo.model.ward.exceptions;
+
+/**
+ * Signals that the operation is unable to find the specified ward.
+ */
+public class WardNotFoundException extends RuntimeException {
+ public WardNotFoundException(String name) {
+ super("Ward " + name + " not found!");
+ }
+}
diff --git a/src/main/java/seedu/medinfo/storage/JsonAdaptedPatient.java b/src/main/java/seedu/medinfo/storage/JsonAdaptedPatient.java
new file mode 100644
index 00000000000..51c42309d81
--- /dev/null
+++ b/src/main/java/seedu/medinfo/storage/JsonAdaptedPatient.java
@@ -0,0 +1,108 @@
+package seedu.medinfo.storage;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import seedu.medinfo.commons.exceptions.IllegalValueException;
+import seedu.medinfo.model.patient.Discharge;
+import seedu.medinfo.model.patient.Name;
+import seedu.medinfo.model.patient.Nric;
+import seedu.medinfo.model.patient.Patient;
+import seedu.medinfo.model.patient.Status;
+import seedu.medinfo.model.ward.Ward;
+import seedu.medinfo.model.ward.WardName;
+
+
+/**
+ * Jackson-friendly version of {@link Patient}.
+ */
+class JsonAdaptedPatient {
+
+ public static final String MISSING_FIELD_MESSAGE_FORMAT = "Patient's %s field is missing!";
+
+ private final String name;
+ private final String nric;
+ private final String status;
+ private final String ward;
+ private final String discharge;
+
+
+ /**
+ * Constructs a {@code JsonAdaptedPatient} with the given patient details.
+ */
+ @JsonCreator
+ public JsonAdaptedPatient(@JsonProperty("name") String name, @JsonProperty("nric") String nric,
+ @JsonProperty("status") String status, @JsonProperty("ward") String ward,
+ @JsonProperty("discharge") String discharge) {
+ this.name = name;
+ this.nric = nric;
+ this.status = status;
+ this.ward = ward;
+ this.discharge = discharge;
+ }
+
+ /**
+ * Converts a given {@code Patient} into this class for Jackson use.
+ */
+ public JsonAdaptedPatient(Patient source) {
+ name = source.getName().fullName;
+ nric = source.getNric().value;
+ status = source.getStatus().value;
+ ward = source.getWardNameString();
+ discharge = source.getDischarge().value;
+
+ }
+
+ /**
+ * Converts this Jackson-friendly adapted patient object into the model's
+ * {@code Patient} object.
+ *
+ * @throws IllegalValueException if there were any data constraints violated in
+ * the adapted patient.
+ */
+ public Patient toModelType() throws IllegalValueException {
+
+ if (name == null) {
+ throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Name.class.getSimpleName()));
+ }
+ if (!Name.isValidName(name)) {
+ throw new IllegalValueException(Name.MESSAGE_CONSTRAINTS);
+ }
+ final Name modelName = new Name(name);
+
+ if (nric == null) {
+ throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Nric.class.getSimpleName()));
+ }
+ if (!Nric.isValidNric(nric)) {
+ throw new IllegalValueException(Nric.MESSAGE_CONSTRAINTS);
+ }
+ final Nric modelNric = new Nric(nric);
+
+ if (status == null) {
+ throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Status.class.getSimpleName()));
+ }
+ if (!Status.isValidStatus(status)) {
+ throw new IllegalValueException(Status.MESSAGE_CONSTRAINTS);
+ }
+ final Status modelStatus = new Status(status);
+
+ if (ward == null) {
+ throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Ward.class.getSimpleName()));
+ }
+ if (!Ward.isValidWardName(ward)) {
+ throw new IllegalValueException(WardName.MESSAGE_CONSTRAINTS);
+ }
+ final WardName modelWard = new WardName(ward);
+
+ if (discharge == null) {
+ throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT,
+ Discharge.class.getSimpleName()));
+ }
+ if (!Discharge.isValidDischarge(discharge)) {
+ throw new IllegalValueException(Discharge.MESSAGE_CONSTRAINTS);
+ }
+ final Discharge modelDischarge = new Discharge(discharge);
+ return new Patient(modelNric, modelName, modelStatus, modelWard, modelDischarge);
+ }
+
+}
diff --git a/src/main/java/seedu/medinfo/storage/JsonAdaptedWard.java b/src/main/java/seedu/medinfo/storage/JsonAdaptedWard.java
new file mode 100644
index 00000000000..0628d5092f1
--- /dev/null
+++ b/src/main/java/seedu/medinfo/storage/JsonAdaptedWard.java
@@ -0,0 +1,71 @@
+package seedu.medinfo.storage;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import seedu.medinfo.commons.exceptions.IllegalValueException;
+import seedu.medinfo.model.patient.Name;
+import seedu.medinfo.model.ward.Capacity;
+import seedu.medinfo.model.ward.Ward;
+import seedu.medinfo.model.ward.WardName;
+
+
+/**
+ * Jackson-friendly version of {@link Ward}.
+ */
+class JsonAdaptedWard {
+
+ public static final String MISSING_FIELD_MESSAGE_FORMAT = "Ward %s field is missing!";
+
+ private final String name;
+ private final String capacity;
+
+
+ /**
+ * Constructs a {@code JsonAdaptedWard} with the given details.
+ */
+ @JsonCreator
+ public JsonAdaptedWard(@JsonProperty("name") String name, @JsonProperty("capacity") String capacity) {
+ this.name = name;
+ this.capacity = capacity;
+ }
+
+ /**
+ * Converts a given {@code Ward} into this class for Jackson use.
+ */
+ public JsonAdaptedWard(Ward source) {
+ name = source.getNameString();
+ capacity = source.getCapacityString();
+
+ }
+
+ /**
+ * Converts this Jackson-friendly adapted patient object into the model's
+ * {@code Ward} object.
+ *
+ * @throws IllegalValueException if there were any data constraints violated in
+ * the adapted patient.
+ */
+ public Ward toModelType() throws IllegalValueException {
+
+ if (name == null) {
+ throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Name.class.getSimpleName()));
+ }
+ if (!Name.isValidName(name)) {
+ throw new IllegalValueException(Name.MESSAGE_CONSTRAINTS);
+ }
+ final WardName modelName = new WardName(name);
+
+ if (capacity == null) {
+ throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT,
+ Capacity.class.getSimpleName()));
+ }
+ if (!Capacity.isValidCapacity(capacity)) {
+ throw new IllegalValueException(Capacity.MESSAGE_CONSTRAINTS);
+ }
+ final Capacity modelCapacity = new Capacity(capacity);
+
+ return new Ward(modelName, modelCapacity);
+ }
+
+}
diff --git a/src/main/java/seedu/medinfo/storage/JsonMedInfoStorage.java b/src/main/java/seedu/medinfo/storage/JsonMedInfoStorage.java
new file mode 100644
index 00000000000..9be278bc771
--- /dev/null
+++ b/src/main/java/seedu/medinfo/storage/JsonMedInfoStorage.java
@@ -0,0 +1,81 @@
+package seedu.medinfo.storage;
+
+import static java.util.Objects.requireNonNull;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.Optional;
+import java.util.logging.Logger;
+
+import seedu.medinfo.commons.core.LogsCenter;
+import seedu.medinfo.commons.exceptions.DataConversionException;
+import seedu.medinfo.commons.exceptions.IllegalValueException;
+import seedu.medinfo.commons.util.FileUtil;
+import seedu.medinfo.commons.util.JsonUtil;
+import seedu.medinfo.logic.commands.exceptions.CommandException;
+import seedu.medinfo.model.ReadOnlyMedInfo;
+
+/**
+ * A class to access MedInfo data stored as a json file on the hard disk.
+ */
+public class JsonMedInfoStorage implements MedInfoStorage {
+
+ private static final Logger logger = LogsCenter.getLogger(JsonMedInfoStorage.class);
+
+ private Path filePath;
+
+ public JsonMedInfoStorage(Path filePath) {
+ this.filePath = filePath;
+ }
+
+ public Path getMedInfoFilePath() {
+ return filePath;
+ }
+
+ @Override
+ public Optional readMedInfo() throws DataConversionException, CommandException {
+ return readMedInfo(filePath);
+ }
+
+ /**
+ * Similar to {@link #readMedInfo()}.
+ *
+ * @param filePath location of the data. Cannot be null.
+ * @throws DataConversionException if the file is not in the correct format.
+ */
+ public Optional readMedInfo(Path filePath) throws DataConversionException, CommandException {
+ requireNonNull(filePath);
+
+ Optional jsonMedInfo = JsonUtil.readJsonFile(
+ filePath, JsonSerializableMedInfo.class);
+ if (!jsonMedInfo.isPresent()) {
+ return Optional.empty();
+ }
+
+ try {
+ return Optional.of(jsonMedInfo.get().toModelType());
+ } catch (IllegalValueException ive) {
+ logger.info("Illegal values found in " + filePath + ": " + ive.getMessage());
+ throw new DataConversionException(ive);
+ }
+ }
+
+ @Override
+ public void saveMedInfo(ReadOnlyMedInfo medInfo) throws IOException {
+ saveMedInfo(medInfo, filePath);
+ }
+
+ /**
+ * Similar to {@link #saveMedInfo(ReadOnlyMedInfo)}.
+ *
+ * @param filePath location of the data. Cannot be null.
+ */
+ public void saveMedInfo(ReadOnlyMedInfo medInfo, Path filePath) throws IOException {
+ requireNonNull(medInfo);
+ requireNonNull(filePath);
+
+ FileUtil.createIfMissing(filePath);
+ JsonUtil.saveJsonFile(new JsonSerializableMedInfo(medInfo), filePath);
+ }
+
+}
diff --git a/src/main/java/seedu/medinfo/storage/JsonSerializableMedInfo.java b/src/main/java/seedu/medinfo/storage/JsonSerializableMedInfo.java
new file mode 100644
index 00000000000..27d94c55600
--- /dev/null
+++ b/src/main/java/seedu/medinfo/storage/JsonSerializableMedInfo.java
@@ -0,0 +1,80 @@
+package seedu.medinfo.storage;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonRootName;
+
+import seedu.medinfo.commons.exceptions.IllegalValueException;
+import seedu.medinfo.logic.commands.exceptions.CommandException;
+import seedu.medinfo.model.MedInfo;
+import seedu.medinfo.model.ReadOnlyMedInfo;
+import seedu.medinfo.model.patient.Patient;
+import seedu.medinfo.model.ward.Ward;
+import seedu.medinfo.model.ward.exceptions.WardNotFoundException;
+
+/**
+ * An Immutable MedInfo that is serializable to JSON format.
+ */
+@JsonRootName(value = "medinfo")
+class JsonSerializableMedInfo {
+
+ public static final String MESSAGE_DUPLICATE_PATIENT = "Patients list contains duplicate patient(s).";
+ public static final String MESSAGE_DUPLICATE_WARD = "Ward list contains duplicate ward(s).";
+ public static final String MESSAGE_MISSING_WARD = "Patient(s) linked to wards that do not exist.";
+
+ private final List patients = new ArrayList<>();
+ private final List wards = new ArrayList<>();
+
+ /**
+ * Constructs a {@code JsonSerializableMedInfo} with the given patients.
+ */
+ @JsonCreator
+ public JsonSerializableMedInfo(@JsonProperty("patients") List patients,
+ @JsonProperty("wards") List wards) {
+ this.patients.addAll(patients);
+ this.wards.addAll(wards);
+ }
+
+ /**
+ * Converts a given {@code ReadOnlyMedInfo} into this class for Jackson use.
+ *
+ * @param source future changes to this will not affect the created {@code JsonSerializableMedInfo}.
+ */
+ public JsonSerializableMedInfo(ReadOnlyMedInfo source) {
+ patients.addAll(source.getPatientList().stream().map(JsonAdaptedPatient::new).collect(Collectors.toList()));
+ wards.addAll(source.getWardList().stream().map(JsonAdaptedWard::new).collect(Collectors.toList()));
+ }
+
+ /**
+ * Converts this medinfo book into the model's {@code MedInfo} object.
+ *
+ * @throws IllegalValueException if there were any data constraints violated.
+ */
+ public MedInfo toModelType() throws IllegalValueException, CommandException {
+ MedInfo medInfo = new MedInfo();
+ for (JsonAdaptedWard jsonAdaptedWard : wards) {
+ Ward ward = jsonAdaptedWard.toModelType();
+ if (!medInfo.hasWard(ward)) {
+ medInfo.addWard(ward);
+ }
+ }
+
+ for (JsonAdaptedPatient jsonAdaptedPatient : patients) {
+ Patient patient = jsonAdaptedPatient.toModelType();
+ if (medInfo.hasPatient(patient)) {
+ throw new IllegalValueException(MESSAGE_DUPLICATE_PATIENT);
+ }
+ try {
+ medInfo.addPatient(patient);
+ } catch (WardNotFoundException e) {
+ throw new IllegalValueException(MESSAGE_MISSING_WARD);
+ }
+ }
+ return medInfo;
+ }
+
+}
diff --git a/src/main/java/seedu/address/storage/JsonUserPrefsStorage.java b/src/main/java/seedu/medinfo/storage/JsonUserPrefsStorage.java
similarity index 83%
rename from src/main/java/seedu/address/storage/JsonUserPrefsStorage.java
rename to src/main/java/seedu/medinfo/storage/JsonUserPrefsStorage.java
index bc2bbad84aa..3276a2de7ab 100644
--- a/src/main/java/seedu/address/storage/JsonUserPrefsStorage.java
+++ b/src/main/java/seedu/medinfo/storage/JsonUserPrefsStorage.java
@@ -1,13 +1,13 @@
-package seedu.address.storage;
+package seedu.medinfo.storage;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Optional;
-import seedu.address.commons.exceptions.DataConversionException;
-import seedu.address.commons.util.JsonUtil;
-import seedu.address.model.ReadOnlyUserPrefs;
-import seedu.address.model.UserPrefs;
+import seedu.medinfo.commons.exceptions.DataConversionException;
+import seedu.medinfo.commons.util.JsonUtil;
+import seedu.medinfo.model.ReadOnlyUserPrefs;
+import seedu.medinfo.model.UserPrefs;
/**
* A class to access UserPrefs stored in the hard disk as a json file
diff --git a/src/main/java/seedu/medinfo/storage/MedInfoStorage.java b/src/main/java/seedu/medinfo/storage/MedInfoStorage.java
new file mode 100644
index 00000000000..9fc4d171452
--- /dev/null
+++ b/src/main/java/seedu/medinfo/storage/MedInfoStorage.java
@@ -0,0 +1,47 @@
+package seedu.medinfo.storage;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.Optional;
+
+import seedu.medinfo.commons.exceptions.DataConversionException;
+import seedu.medinfo.logic.commands.exceptions.CommandException;
+import seedu.medinfo.model.MedInfo;
+import seedu.medinfo.model.ReadOnlyMedInfo;
+
+/**
+ * Represents a storage for {@link MedInfo}.
+ */
+public interface MedInfoStorage {
+
+ /**
+ * Returns the file path of the data file.
+ */
+ Path getMedInfoFilePath();
+
+ /**
+ * Returns MedInfo data as a {@link ReadOnlyMedInfo}.
+ * Returns {@code Optional.empty()} if storage file is not found.
+ * @throws DataConversionException if the data in storage is not in the expected format.
+ * @throws IOException if there was any problem when reading from the storage.
+ */
+ Optional readMedInfo() throws DataConversionException, IOException, CommandException;
+
+ /**
+ * @see #getMedInfoFilePath()
+ */
+ Optional readMedInfo(Path filePath) throws DataConversionException, IOException, CommandException;
+
+ /**
+ * Saves the given {@link ReadOnlyMedInfo} to the storage.
+ * @param medInfo cannot be null.
+ * @throws IOException if there was any problem writing to the file.
+ */
+ void saveMedInfo(ReadOnlyMedInfo medInfo) throws IOException;
+
+ /**
+ * @see #saveMedInfo(ReadOnlyMedInfo)
+ */
+ void saveMedInfo(ReadOnlyMedInfo medInfo, Path filePath) throws IOException;
+
+}
diff --git a/src/main/java/seedu/medinfo/storage/Storage.java b/src/main/java/seedu/medinfo/storage/Storage.java
new file mode 100644
index 00000000000..f5062dabc56
--- /dev/null
+++ b/src/main/java/seedu/medinfo/storage/Storage.java
@@ -0,0 +1,33 @@
+package seedu.medinfo.storage;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.Optional;
+
+import seedu.medinfo.commons.exceptions.DataConversionException;
+import seedu.medinfo.logic.commands.exceptions.CommandException;
+import seedu.medinfo.model.ReadOnlyMedInfo;
+import seedu.medinfo.model.ReadOnlyUserPrefs;
+import seedu.medinfo.model.UserPrefs;
+
+/**
+ * API of the Storage component
+ */
+public interface Storage extends MedInfoStorage, UserPrefsStorage {
+
+ @Override
+ Optional readUserPrefs() throws DataConversionException, IOException;
+
+ @Override
+ void saveUserPrefs(ReadOnlyUserPrefs userPrefs) throws IOException;
+
+ @Override
+ Path getMedInfoFilePath();
+
+ @Override
+ Optional readMedInfo() throws DataConversionException, IOException, CommandException;
+
+ @Override
+ void saveMedInfo(ReadOnlyMedInfo medInfo) throws IOException;
+
+}
diff --git a/src/main/java/seedu/medinfo/storage/StorageManager.java b/src/main/java/seedu/medinfo/storage/StorageManager.java
new file mode 100644
index 00000000000..a5114af6887
--- /dev/null
+++ b/src/main/java/seedu/medinfo/storage/StorageManager.java
@@ -0,0 +1,80 @@
+package seedu.medinfo.storage;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.Optional;
+import java.util.logging.Logger;
+
+import seedu.medinfo.commons.core.LogsCenter;
+import seedu.medinfo.commons.exceptions.DataConversionException;
+import seedu.medinfo.logic.commands.exceptions.CommandException;
+import seedu.medinfo.model.ReadOnlyMedInfo;
+import seedu.medinfo.model.ReadOnlyUserPrefs;
+import seedu.medinfo.model.UserPrefs;
+
+/**
+ * Manages storage of MedInfo data in local storage.
+ */
+public class StorageManager implements Storage {
+
+ private static final Logger logger = LogsCenter.getLogger(StorageManager.class);
+ private MedInfoStorage medInfoStorage;
+ private UserPrefsStorage userPrefsStorage;
+
+ /**
+ * Creates a {@code StorageManager} with the given {@code MedInfoStorage} and {@code UserPrefStorage}.
+ */
+ public StorageManager(MedInfoStorage medInfoStorage, UserPrefsStorage userPrefsStorage) {
+ this.medInfoStorage = medInfoStorage;
+ this.userPrefsStorage = userPrefsStorage;
+ }
+
+ // ================ UserPrefs methods ==============================
+
+ @Override
+ public Path getUserPrefsFilePath() {
+ return userPrefsStorage.getUserPrefsFilePath();
+ }
+
+ @Override
+ public Optional readUserPrefs() throws DataConversionException, IOException {
+ return userPrefsStorage.readUserPrefs();
+ }
+
+ @Override
+ public void saveUserPrefs(ReadOnlyUserPrefs userPrefs) throws IOException {
+ userPrefsStorage.saveUserPrefs(userPrefs);
+ }
+
+
+ // ================ MedInfo methods ==============================
+
+ @Override
+ public Path getMedInfoFilePath() {
+ return medInfoStorage.getMedInfoFilePath();
+ }
+
+ @Override
+ public Optional readMedInfo() throws DataConversionException, IOException, CommandException {
+ return readMedInfo(medInfoStorage.getMedInfoFilePath());
+ }
+
+ @Override
+ public Optional readMedInfo(Path filePath) throws DataConversionException, IOException,
+ CommandException {
+ logger.fine("Attempting to read data from file: " + filePath);
+ return medInfoStorage.readMedInfo(filePath);
+ }
+
+ @Override
+ public void saveMedInfo(ReadOnlyMedInfo medInfo) throws IOException {
+ saveMedInfo(medInfo, medInfoStorage.getMedInfoFilePath());
+ }
+
+ @Override
+ public void saveMedInfo(ReadOnlyMedInfo medInfo, Path filePath) throws IOException {
+ logger.fine("Attempting to write to data file: " + filePath);
+ medInfoStorage.saveMedInfo(medInfo, filePath);
+ }
+
+}
diff --git a/src/main/java/seedu/address/storage/UserPrefsStorage.java b/src/main/java/seedu/medinfo/storage/UserPrefsStorage.java
similarity index 73%
rename from src/main/java/seedu/address/storage/UserPrefsStorage.java
rename to src/main/java/seedu/medinfo/storage/UserPrefsStorage.java
index 29eef178dbc..98e13643331 100644
--- a/src/main/java/seedu/address/storage/UserPrefsStorage.java
+++ b/src/main/java/seedu/medinfo/storage/UserPrefsStorage.java
@@ -1,15 +1,15 @@
-package seedu.address.storage;
+package seedu.medinfo.storage;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Optional;
-import seedu.address.commons.exceptions.DataConversionException;
-import seedu.address.model.ReadOnlyUserPrefs;
-import seedu.address.model.UserPrefs;
+import seedu.medinfo.commons.exceptions.DataConversionException;
+import seedu.medinfo.model.ReadOnlyUserPrefs;
+import seedu.medinfo.model.UserPrefs;
/**
- * Represents a storage for {@link seedu.address.model.UserPrefs}.
+ * Represents a storage for {@link seedu.medinfo.model.UserPrefs}.
*/
public interface UserPrefsStorage {
@@ -27,7 +27,7 @@ public interface UserPrefsStorage {
Optional readUserPrefs() throws DataConversionException, IOException;
/**
- * Saves the given {@link seedu.address.model.ReadOnlyUserPrefs} to the storage.
+ * Saves the given {@link seedu.medinfo.model.ReadOnlyUserPrefs} to the storage.
* @param userPrefs cannot be null.
* @throws IOException if there was any problem writing to the file.
*/
diff --git a/src/main/java/seedu/address/ui/CommandBox.java b/src/main/java/seedu/medinfo/ui/CommandBox.java
similarity index 89%
rename from src/main/java/seedu/address/ui/CommandBox.java
rename to src/main/java/seedu/medinfo/ui/CommandBox.java
index 9e75478664b..ff961310b93 100644
--- a/src/main/java/seedu/address/ui/CommandBox.java
+++ b/src/main/java/seedu/medinfo/ui/CommandBox.java
@@ -1,12 +1,12 @@
-package seedu.address.ui;
+package seedu.medinfo.ui;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.TextField;
import javafx.scene.layout.Region;
-import seedu.address.logic.commands.CommandResult;
-import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.medinfo.logic.commands.CommandResult;
+import seedu.medinfo.logic.commands.exceptions.CommandException;
+import seedu.medinfo.logic.parser.exceptions.ParseException;
/**
* The UI component that is responsible for receiving user command inputs.
@@ -77,7 +77,7 @@ public interface CommandExecutor {
/**
* Executes the command and returns the result.
*
- * @see seedu.address.logic.Logic#execute(String)
+ * @see seedu.medinfo.logic.Logic#execute(String)
*/
CommandResult execute(String commandText) throws CommandException, ParseException;
}
diff --git a/src/main/java/seedu/address/ui/HelpWindow.java b/src/main/java/seedu/medinfo/ui/HelpWindow.java
similarity index 90%
rename from src/main/java/seedu/address/ui/HelpWindow.java
rename to src/main/java/seedu/medinfo/ui/HelpWindow.java
index 3f16b2fcf26..befaac588b2 100644
--- a/src/main/java/seedu/address/ui/HelpWindow.java
+++ b/src/main/java/seedu/medinfo/ui/HelpWindow.java
@@ -1,4 +1,4 @@
-package seedu.address.ui;
+package seedu.medinfo.ui;
import java.util.logging.Logger;
@@ -8,14 +8,14 @@
import javafx.scene.input.Clipboard;
import javafx.scene.input.ClipboardContent;
import javafx.stage.Stage;
-import seedu.address.commons.core.LogsCenter;
+import seedu.medinfo.commons.core.LogsCenter;
/**
* Controller for a help page
*/
public class HelpWindow extends UiPart {
- public static final String USERGUIDE_URL = "https://se-education.org/addressbook-level3/UserGuide.html";
+ public static final String USERGUIDE_URL = "https://ay2223s2-cs2103t-t12-2.github.io/tp/UserGuide.html";
public static final String HELP_MESSAGE = "Refer to the user guide: " + USERGUIDE_URL;
private static final Logger logger = LogsCenter.getLogger(HelpWindow.class);
@@ -70,6 +70,8 @@ public void show() {
/**
* Returns true if the help window is currently being shown.
+ *
+ * @return Boolean indicating if help window is being shown.
*/
public boolean isShowing() {
return getRoot().isShowing();
diff --git a/src/main/java/seedu/address/ui/MainWindow.java b/src/main/java/seedu/medinfo/ui/MainWindow.java
similarity index 80%
rename from src/main/java/seedu/address/ui/MainWindow.java
rename to src/main/java/seedu/medinfo/ui/MainWindow.java
index 9106c3aa6e5..36498c6d7c3 100644
--- a/src/main/java/seedu/address/ui/MainWindow.java
+++ b/src/main/java/seedu/medinfo/ui/MainWindow.java
@@ -1,4 +1,4 @@
-package seedu.address.ui;
+package seedu.medinfo.ui;
import java.util.logging.Logger;
@@ -10,12 +10,12 @@
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
-import seedu.address.commons.core.GuiSettings;
-import seedu.address.commons.core.LogsCenter;
-import seedu.address.logic.Logic;
-import seedu.address.logic.commands.CommandResult;
-import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.medinfo.commons.core.GuiSettings;
+import seedu.medinfo.commons.core.LogsCenter;
+import seedu.medinfo.logic.Logic;
+import seedu.medinfo.logic.commands.CommandResult;
+import seedu.medinfo.logic.commands.exceptions.CommandException;
+import seedu.medinfo.logic.parser.exceptions.ParseException;
/**
* The Main Window. Provides the basic application layout containing
@@ -31,7 +31,8 @@ public class MainWindow extends UiPart {
private Logic logic;
// Independent Ui parts residing in this Ui container
- private PersonListPanel personListPanel;
+ private PatientListPanel patientListPanel;
+ private WardListPanel wardListPanel;
private ResultDisplay resultDisplay;
private HelpWindow helpWindow;
@@ -42,7 +43,9 @@ public class MainWindow extends UiPart {
private MenuItem helpMenuItem;
@FXML
- private StackPane personListPanelPlaceholder;
+ private StackPane patientListPanelPlaceholder;
+ @FXML
+ private StackPane wardListPanelPlaceholder;
@FXML
private StackPane resultDisplayPlaceholder;
@@ -68,6 +71,11 @@ public MainWindow(Stage primaryStage, Logic logic) {
helpWindow = new HelpWindow();
}
+ /**
+ * Returns the primary stage.
+ *
+ * @return The primary stage of the app.
+ */
public Stage getPrimaryStage() {
return primaryStage;
}
@@ -78,7 +86,7 @@ private void setAccelerators() {
/**
* Sets the accelerator of a MenuItem.
- * @param keyCombination the KeyCombination value of the accelerator
+ * @param keyCombination the KeyCombination value of the accelerator.
*/
private void setAccelerator(MenuItem menuItem, KeyCombination keyCombination) {
menuItem.setAccelerator(keyCombination);
@@ -110,19 +118,30 @@ private void setAccelerator(MenuItem menuItem, KeyCombination keyCombination) {
* Fills up all the placeholders of this window.
*/
void fillInnerParts() {
- personListPanel = new PersonListPanel(logic.getFilteredPersonList());
- personListPanelPlaceholder.getChildren().add(personListPanel.getRoot());
+ patientListPanel = new PatientListPanel(logic.getFilteredPatientList());
+ patientListPanelPlaceholder.getChildren().add(patientListPanel.getRoot());
+
+ wardListPanel = new WardListPanel(logic.getFilteredWardList());
+ wardListPanelPlaceholder.getChildren().add(wardListPanel.getRoot());
resultDisplay = new ResultDisplay();
resultDisplayPlaceholder.getChildren().add(resultDisplay.getRoot());
- StatusBarFooter statusBarFooter = new StatusBarFooter(logic.getAddressBookFilePath());
+ StatusBarFooter statusBarFooter = new StatusBarFooter(logic.getMedInfoFilePath(), logic.getStatsInfo());
statusbarPlaceholder.getChildren().add(statusBarFooter.getRoot());
CommandBox commandBox = new CommandBox(this::executeCommand);
commandBoxPlaceholder.getChildren().add(commandBox.getRoot());
}
+ /**
+ * Updates Stats placeholder.
+ */
+ void updateStats() {
+ StatusBarFooter statusBarFooter = new StatusBarFooter(logic.getMedInfoFilePath(), logic.getStatsInfo());
+ statusbarPlaceholder.getChildren().add(statusBarFooter.getRoot());
+ }
+
/**
* Sets the default size based on {@code guiSettings}.
*/
@@ -163,18 +182,16 @@ private void handleExit() {
primaryStage.hide();
}
- public PersonListPanel getPersonListPanel() {
- return personListPanel;
- }
-
/**
* Executes the command and returns the result.
*
- * @see seedu.address.logic.Logic#execute(String)
+ * @see seedu.medinfo.logic.Logic#execute(String)
*/
private CommandResult executeCommand(String commandText) throws CommandException, ParseException {
try {
+
CommandResult commandResult = logic.execute(commandText);
+ updateStats();
logger.info("Result: " + commandResult.getFeedbackToUser());
resultDisplay.setFeedbackToUser(commandResult.getFeedbackToUser());
diff --git a/src/main/java/seedu/medinfo/ui/PatientCard.java b/src/main/java/seedu/medinfo/ui/PatientCard.java
new file mode 100644
index 00000000000..0451876d821
--- /dev/null
+++ b/src/main/java/seedu/medinfo/ui/PatientCard.java
@@ -0,0 +1,86 @@
+package seedu.medinfo.ui;
+
+import javafx.fxml.FXML;
+import javafx.scene.control.Label;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.Region;
+import seedu.medinfo.model.patient.Patient;
+
+
+/**
+ * An UI component that displays information of a {@code Patient}.
+ */
+public class PatientCard extends UiPart {
+
+ private static final String FXML = "PatientListCard.fxml";
+
+ /**
+ * Note: Certain keywords such as "location" and "resources" are reserved
+ * keywords in JavaFX.
+ * As a consequence, UI elements' variable names cannot be set to such keywords
+ * or an exception will be thrown by JavaFX during runtime.
+ *
+ * @see The
+ * issue on MedInfo level 4
+ */
+
+ public final Patient patient;
+
+ @FXML
+ private HBox cardPane;
+ @FXML
+ private Label name;
+ @FXML
+ private Label id;
+ @FXML
+ private Label nric;
+ @FXML
+ private Label status;
+ @FXML
+ private Label ward;
+ @FXML
+ private Label discharge;
+
+ /**
+ * Creates a {@code PatientCode} with the given {@code Patient} and index to
+ * display.
+ */
+ public PatientCard(Patient patient, int displayedIndex) {
+ super(FXML);
+ this.patient = patient;
+ id.setText(displayedIndex + ". ");
+ name.setText(patient.getName().fullName);
+ nric.setText(patient.getNric().value);
+ String statusString = patient.getStatusDesc();
+ status.setText(statusString);
+ status.getStyleClass().clear();
+ status.getStyleClass().add("status-" + statusString);
+ ward.setText(patient.getWardNameString());
+ discharge.setText(patient.getDischargeString());
+ }
+
+ /**
+ * Overrides equality check for PatientCard to compare two patient cards by
+ * the NRICs and the patients.
+ *
+ * @param other Object to check equality with.
+ * @return Boolean indicating whether objects are equal.
+ */
+ @Override
+ public boolean equals(Object other) {
+ // short circuit if same object
+ if (other == this) {
+ return true;
+ }
+
+ // instanceof handles nulls
+ if (!(other instanceof PatientCard)) {
+ return false;
+ }
+
+ // state check
+ PatientCard card = (PatientCard) other;
+ return nric.getText().equals(card.nric.getText())
+ && patient.equals(card.patient);
+ }
+}
diff --git a/src/main/java/seedu/medinfo/ui/PatientListPanel.java b/src/main/java/seedu/medinfo/ui/PatientListPanel.java
new file mode 100644
index 00000000000..a487847be6d
--- /dev/null
+++ b/src/main/java/seedu/medinfo/ui/PatientListPanel.java
@@ -0,0 +1,46 @@
+package seedu.medinfo.ui;
+
+import javafx.collections.ObservableList;
+import javafx.fxml.FXML;
+import javafx.scene.control.ListCell;
+import javafx.scene.control.ListView;
+import javafx.scene.layout.Region;
+import seedu.medinfo.model.patient.Patient;
+
+/**
+ * Panel containing the list of patients.
+ */
+public class PatientListPanel extends UiPart {
+ private static final String FXML = "PatientListPanel.fxml";
+
+ @FXML
+ private ListView patientListView;
+
+ /**
+ * Creates a {@code PatientListPanel} with the given {@code ObservableList}.
+ */
+ public PatientListPanel(ObservableList patientList) {
+ super(FXML);
+ patientListView.setItems(patientList);
+ patientListView.setCellFactory(listView -> new PatientListViewCell());
+ }
+
+ /**
+ * Custom {@code ListCell} that displays the graphics of a {@code Patient} using
+ * a {@code PatientCard}.
+ */
+ class PatientListViewCell extends ListCell {
+ @Override
+ protected void updateItem(Patient patient, boolean empty) {
+ super.updateItem(patient, empty);
+
+ if (empty || patient == null) {
+ setGraphic(null);
+ setText(null);
+ } else {
+ setGraphic(new PatientCard(patient, getIndex() + 1).getRoot());
+ }
+ }
+ }
+
+}
diff --git a/src/main/java/seedu/address/ui/ResultDisplay.java b/src/main/java/seedu/medinfo/ui/ResultDisplay.java
similarity index 72%
rename from src/main/java/seedu/address/ui/ResultDisplay.java
rename to src/main/java/seedu/medinfo/ui/ResultDisplay.java
index 7d98e84eedf..9d4ddc6d765 100644
--- a/src/main/java/seedu/address/ui/ResultDisplay.java
+++ b/src/main/java/seedu/medinfo/ui/ResultDisplay.java
@@ -1,4 +1,4 @@
-package seedu.address.ui;
+package seedu.medinfo.ui;
import static java.util.Objects.requireNonNull;
@@ -16,10 +16,18 @@ public class ResultDisplay extends UiPart {
@FXML
private TextArea resultDisplay;
+ /**
+ * Creates a {@code ResultDisplay}.
+ */
public ResultDisplay() {
super(FXML);
}
+ /**
+ * Sets text to feedback to the user in the result display.
+ *
+ * @param feedbackToUser String to feedback to user.
+ */
public void setFeedbackToUser(String feedbackToUser) {
requireNonNull(feedbackToUser);
resultDisplay.setText(feedbackToUser);
diff --git a/src/main/java/seedu/address/ui/StatusBarFooter.java b/src/main/java/seedu/medinfo/ui/StatusBarFooter.java
similarity index 55%
rename from src/main/java/seedu/address/ui/StatusBarFooter.java
rename to src/main/java/seedu/medinfo/ui/StatusBarFooter.java
index b577f829423..b1b6d5958f3 100644
--- a/src/main/java/seedu/address/ui/StatusBarFooter.java
+++ b/src/main/java/seedu/medinfo/ui/StatusBarFooter.java
@@ -1,7 +1,8 @@
-package seedu.address.ui;
+package seedu.medinfo.ui;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.util.List;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
@@ -16,13 +17,20 @@ public class StatusBarFooter extends UiPart {
@FXML
private Label saveLocationStatus;
+ @FXML
+ private Label stats;
/**
* Creates a {@code StatusBarFooter} with the given {@code Path}.
*/
- public StatusBarFooter(Path saveLocation) {
+ public StatusBarFooter(Path saveLocation, List statsInfo) {
super(FXML);
- saveLocationStatus.setText(Paths.get(".").resolve(saveLocation).toString());
+ statsInfo.get(0);
+ statsInfo.get(1);
+ this.saveLocationStatus.setText(Paths.get(".").resolve(saveLocation).toString());
+ for (String stat:statsInfo) {
+ stats.setText(stats.getText() + " " + stat + " ");
+ }
}
}
diff --git a/src/main/java/seedu/address/ui/Ui.java b/src/main/java/seedu/medinfo/ui/Ui.java
similarity index 61%
rename from src/main/java/seedu/address/ui/Ui.java
rename to src/main/java/seedu/medinfo/ui/Ui.java
index 17aa0b494fe..cdf8e60ba92 100644
--- a/src/main/java/seedu/address/ui/Ui.java
+++ b/src/main/java/seedu/medinfo/ui/Ui.java
@@ -1,4 +1,4 @@
-package seedu.address.ui;
+package seedu.medinfo.ui;
import javafx.stage.Stage;
@@ -7,7 +7,9 @@
*/
public interface Ui {
- /** Starts the UI (and the App). */
+ /**
+ * Starts the UI (and the App).
+ */
void start(Stage primaryStage);
}
diff --git a/src/main/java/seedu/address/ui/UiManager.java b/src/main/java/seedu/medinfo/ui/UiManager.java
similarity index 87%
rename from src/main/java/seedu/address/ui/UiManager.java
rename to src/main/java/seedu/medinfo/ui/UiManager.java
index fdf024138bc..35c5d4e38d1 100644
--- a/src/main/java/seedu/address/ui/UiManager.java
+++ b/src/main/java/seedu/medinfo/ui/UiManager.java
@@ -1,4 +1,4 @@
-package seedu.address.ui;
+package seedu.medinfo.ui;
import java.util.logging.Logger;
@@ -7,10 +7,10 @@
import javafx.scene.control.Alert.AlertType;
import javafx.scene.image.Image;
import javafx.stage.Stage;
-import seedu.address.MainApp;
-import seedu.address.commons.core.LogsCenter;
-import seedu.address.commons.util.StringUtil;
-import seedu.address.logic.Logic;
+import seedu.medinfo.MainApp;
+import seedu.medinfo.commons.core.LogsCenter;
+import seedu.medinfo.commons.util.StringUtil;
+import seedu.medinfo.logic.Logic;
/**
* The manager of the UI component.
@@ -20,7 +20,7 @@ public class UiManager implements Ui {
public static final String ALERT_DIALOG_PANE_FIELD_ID = "alertDialogPane";
private static final Logger logger = LogsCenter.getLogger(UiManager.class);
- private static final String ICON_APPLICATION = "/images/address_book_32.png";
+ private static final String ICON_APPLICATION = "/images/MedInfo.png";
private Logic logic;
private MainWindow mainWindow;
@@ -32,6 +32,11 @@ public UiManager(Logic logic) {
this.logic = logic;
}
+ /**
+ * Start the Ui components with the given primary stage.
+ *
+ * @param primaryStage Primary stage of the app.
+ */
@Override
public void start(Stage primaryStage) {
logger.info("Starting UI...");
diff --git a/src/main/java/seedu/address/ui/UiPart.java b/src/main/java/seedu/medinfo/ui/UiPart.java
similarity index 97%
rename from src/main/java/seedu/address/ui/UiPart.java
rename to src/main/java/seedu/medinfo/ui/UiPart.java
index fc820e01a9c..b33e39e4d28 100644
--- a/src/main/java/seedu/address/ui/UiPart.java
+++ b/src/main/java/seedu/medinfo/ui/UiPart.java
@@ -1,4 +1,4 @@
-package seedu.address.ui;
+package seedu.medinfo.ui;
import static java.util.Objects.requireNonNull;
@@ -6,7 +6,7 @@
import java.net.URL;
import javafx.fxml.FXMLLoader;
-import seedu.address.MainApp;
+import seedu.medinfo.MainApp;
/**
* Represents a distinct part of the UI. e.g. Windows, dialogs, panels, status bars, etc.
diff --git a/src/main/java/seedu/medinfo/ui/WardCard.java b/src/main/java/seedu/medinfo/ui/WardCard.java
new file mode 100644
index 00000000000..30ffa39f129
--- /dev/null
+++ b/src/main/java/seedu/medinfo/ui/WardCard.java
@@ -0,0 +1,68 @@
+package seedu.medinfo.ui;
+
+import javafx.fxml.FXML;
+import javafx.scene.control.Label;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.Region;
+import seedu.medinfo.model.ward.Ward;
+
+
+/**
+ * An UI component that displays information of a {@code Patient}.
+ */
+public class WardCard extends UiPart {
+
+ private static final String FXML = "WardListCard.fxml";
+
+ /**
+ * Note: Certain keywords such as "location" and "resources" are reserved
+ * keywords in JavaFX.
+ * As a consequence, UI elements' variable names cannot be set to such keywords
+ * or an exception will be thrown by JavaFX during runtime.
+ *
+ * @see The
+ * issue on MedInfo level 4
+ */
+
+ public final Ward ward;
+
+ @FXML
+ private HBox cardPane;
+ @FXML
+ private Label name;
+ @FXML
+ private Label id;
+ @FXML
+ private Label capacity;
+
+ /**
+ * Creates a {@code PatientCode} with the given {@code Patient} and index to
+ * display.
+ */
+ public WardCard(Ward ward, int displayedIndex) {
+ super(FXML);
+ this.ward = ward;
+ id.setText(displayedIndex + ". ");
+
+ name.setText(ward.getNameString());
+ capacity.setText(ward.getOccupancyString());
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ // short circuit if same object
+ if (other == this) {
+ return true;
+ }
+
+ // instanceof handles nulls
+ if (!(other instanceof WardCard)) {
+ return false;
+ }
+
+ // state check
+ WardCard card = (WardCard) other;
+ return name.getText().equals(card.name.getText())
+ && ward.equals(card.ward);
+ }
+}
diff --git a/src/main/java/seedu/medinfo/ui/WardListPanel.java b/src/main/java/seedu/medinfo/ui/WardListPanel.java
new file mode 100644
index 00000000000..6042b170ced
--- /dev/null
+++ b/src/main/java/seedu/medinfo/ui/WardListPanel.java
@@ -0,0 +1,46 @@
+package seedu.medinfo.ui;
+
+import javafx.collections.ObservableList;
+import javafx.fxml.FXML;
+import javafx.scene.control.ListCell;
+import javafx.scene.control.ListView;
+import javafx.scene.layout.Region;
+import seedu.medinfo.model.ward.Ward;
+
+/**
+ * Panel containing the list of wards.
+ */
+public class WardListPanel extends UiPart {
+ private static final String FXML = "WardListPanel.fxml";
+
+ @FXML
+ private ListView wardListView;
+
+ /**
+ * Creates a {@code WardListPanel} with the given {@code ObservableList}.
+ */
+ public WardListPanel(ObservableList wardList) {
+ super(FXML);
+ wardListView.setItems(wardList);
+ wardListView.setCellFactory(listView -> new WardListViewCell());
+ }
+
+ /**
+ * Custom {@code ListCell} that displays the graphics of a {@code Ward} using
+ * a {@code WardCard}.
+ */
+ class WardListViewCell extends ListCell {
+ @Override
+ protected void updateItem(Ward ward, boolean empty) {
+ super.updateItem(ward, empty);
+
+ if (empty || ward == null) {
+ setGraphic(null);
+ setText(null);
+ } else {
+ setGraphic(new WardCard(ward, getIndex() + 1).getRoot());
+ }
+ }
+ }
+
+}
diff --git a/src/main/resources/images/MedInfo.png b/src/main/resources/images/MedInfo.png
new file mode 100644
index 00000000000..7bf880f0476
Binary files /dev/null and b/src/main/resources/images/MedInfo.png differ
diff --git a/src/main/resources/images/address_book_32.png b/src/main/resources/images/address_book_32.png
deleted file mode 100644
index 29810cf1fd9..00000000000
Binary files a/src/main/resources/images/address_book_32.png and /dev/null differ
diff --git a/src/main/resources/images/calendar.png b/src/main/resources/images/calendar.png
deleted file mode 100644
index 8b2bdf4f1c1..00000000000
Binary files a/src/main/resources/images/calendar.png and /dev/null differ
diff --git a/src/main/resources/images/clock.png b/src/main/resources/images/clock.png
deleted file mode 100644
index 0807cbf6451..00000000000
Binary files a/src/main/resources/images/clock.png and /dev/null differ
diff --git a/src/main/resources/images/fail.png b/src/main/resources/images/fail.png
deleted file mode 100644
index 6daf01290dd..00000000000
Binary files a/src/main/resources/images/fail.png and /dev/null differ
diff --git a/src/main/resources/images/help_icon.png b/src/main/resources/images/help_icon.png
index f8e80d6c1c5..bda6e8f44ca 100644
Binary files a/src/main/resources/images/help_icon.png and b/src/main/resources/images/help_icon.png differ
diff --git a/src/main/resources/images/info_icon.png b/src/main/resources/images/info_icon.png
index f8cef714095..54f7c434ab3 100644
Binary files a/src/main/resources/images/info_icon.png and b/src/main/resources/images/info_icon.png differ
diff --git a/src/main/resources/view/DarkTheme.css b/src/main/resources/view/DarkTheme.css
index 36e6b001cd8..b54e3b86861 100644
--- a/src/main/resources/view/DarkTheme.css
+++ b/src/main/resources/view/DarkTheme.css
@@ -328,7 +328,7 @@
-fx-text-fill: white;
}
-#filterField, #personListPanel, #personWebpage {
+#filterField, #patientListPanel, #patientWebpage {
-fx-effect: innershadow(gaussian, black, 10, 0, 0, 0);
}
diff --git a/src/main/resources/view/Extensions.css b/src/main/resources/view/Extensions.css
index bfe82a85964..5a2ef0b24fc 100644
--- a/src/main/resources/view/Extensions.css
+++ b/src/main/resources/view/Extensions.css
@@ -1,10 +1,9 @@
.error {
- -fx-text-fill: #d06651 !important; /* The error class should always override the default text-fill style */
+ -fx-text-fill: #d06651 !important;
}
.list-cell:empty {
- /* Empty cells will not have alternating colours */
-fx-background: #383838;
}
diff --git a/src/main/resources/view/HelpWindow.css b/src/main/resources/view/HelpWindow.css
index 17e8a8722cd..bee23565408 100644
--- a/src/main/resources/view/HelpWindow.css
+++ b/src/main/resources/view/HelpWindow.css
@@ -1,5 +1,5 @@
#copyButton, #helpMessage {
- -fx-text-fill: white;
+ -fx-text-fill: black;
}
#copyButton {
@@ -15,5 +15,5 @@
}
#helpMessageContainer {
- -fx-background-color: derive(#1d1d1d, 20%);
+ -fx-background-color: derive(#ccedee, 10%);
}
diff --git a/src/main/resources/view/MainWindow.fxml b/src/main/resources/view/MainWindow.fxml
index a431648f6c0..eec28607eb5 100644
--- a/src/main/resources/view/MainWindow.fxml
+++ b/src/main/resources/view/MainWindow.fxml
@@ -7,19 +7,22 @@
+
+
+
+ title="MedInfo" minWidth="450" minHeight="600" onCloseRequest="#handleExit">
-
+
-
+
@@ -39,20 +42,23 @@
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/view/MedInfoTheme.css b/src/main/resources/view/MedInfoTheme.css
new file mode 100644
index 00000000000..598592c818b
--- /dev/null
+++ b/src/main/resources/view/MedInfoTheme.css
@@ -0,0 +1,454 @@
+.background {
+ -fx-background-color: derive(#1d1d1d, 20%);
+ background-color: #1d1d1d; /* Used in the default.html file */
+}
+
+.label {
+ -fx-font-size: 11pt;
+ -fx-font-family: "Segoe UI Semibold";
+ /* -fx-text-fill: #555555; */
+ -fx-opacity: 0.9;
+}
+
+.label-bright {
+ -fx-font-size: 11pt;
+ -fx-font-family: "Segoe UI Semibold";
+ -fx-text-fill: white;
+ -fx-opacity: 1;
+}
+
+.label-header {
+ -fx-font-size: 32pt;
+ -fx-font-family: "Segoe UI Light";
+ -fx-text-fill: white;
+ -fx-opacity: 1;
+}
+
+.text-field {
+ -fx-font-size: 12pt;
+ -fx-font-family: "Segoe UI Semibold";
+}
+
+.tab-pane {
+ -fx-padding: 0 0 0 1;
+}
+
+.tab-pane .tab-header-area {
+ -fx-padding: 0 0 0 0;
+ -fx-min-height: 0;
+ -fx-max-height: 0;
+}
+
+.table-view {
+ -fx-base: #1d1d1d;
+ -fx-control-inner-background: #1d1d1d;
+ -fx-background-color: #1d1d1d;
+ -fx-table-cell-border-color: transparent;
+ -fx-table-header-border-color: transparent;
+ -fx-padding: 5;
+}
+
+.table-view .column-header-background {
+ -fx-background-color: transparent;
+}
+
+.table-view .column-header, .table-view .filler {
+ -fx-size: 35;
+ -fx-border-width: 0 0 1 0;
+ -fx-background-color: transparent;
+ -fx-border-color:
+ transparent
+ transparent
+ derive(-fx-base, 80%)
+ transparent;
+ -fx-border-insets: 0 10 1 0;
+}
+
+.table-view .column-header .label {
+ -fx-font-size: 20pt;
+ -fx-font-family: "Segoe UI Light";
+ -fx-text-fill: white;
+ -fx-alignment: center-left;
+ -fx-opacity: 1;
+}
+
+.table-view:focused .table-row-cell:filled:focused:selected {
+ -fx-background-color: -fx-focus-color;
+}
+
+.split-pane-divider {
+ -fx-background-color: derive(#A8C5C9, 10%);
+ -fx-border-color: transparent;
+}
+
+.split-pane {
+ -fx-border-radius: 5;
+ -fx-border-width: 0;
+ -fx-background-color: derive(#FFFFFF, 20%);
+}
+
+.list-view {
+ -fx-background-insets: 0;
+ -fx-padding: 0;
+ -fx-background-color: derive(#1d1d1d, 20%);
+}
+
+.list-cell {
+ -fx-label-padding: 0 0 0 0;
+ -fx-graphic-text-gap : 0;
+ -fx-padding: 0 0 0 0;
+}
+
+.list-cell:filled:even {
+ -fx-background-color: #a8acad;
+}
+
+.list-cell:filled:odd {
+ -fx-background-color: #8c9091;
+}
+
+.list-cell:filled:selected {
+ -fx-background-color: #424d5f;
+}
+
+.list-cell:filled:selected #cardPane {
+ -fx-border-color: #3e7b91;
+ -fx-border-width: 1;
+}
+
+.list-cell .label {
+ -fx-text-fill: black;
+}
+
+.cell_big_label {
+ -fx-font-family: "Segoe UI Semibold";
+ -fx-font-size: 16px;
+ -fx-text-fill: #010504;
+}
+
+.cell_small_label {
+ -fx-font-family: "Segoe UI";
+ -fx-font-size: 13px;
+ -fx-text-fill: #010504;
+}
+
+/**
+ * CLI Text box
+ * MainWindow.fxml
+ */
+.stack-pane {
+ -fx-background-color: derive(#A8C5C9, 20%);
+ -fx-border-radius: 100;
+}
+
+/**
+ * Main body holding CLI and lists
+ * MainWindow.fxml
+ */
+.pane-with-border {
+ -fx-background-color: derive(#FFFFFF, 20%);
+ -fx-border-color: derive(#FFFFFF, 10%);
+ -fx-border-top-width: 1px;
+ -fx-border-radius: 100;
+}
+
+/**
+ * Used at the bottom status-bar
+ * StatusBarFooter.fxml
+ */
+.status-bar {
+ -fx-background-color: derive(#A8C5C9, 30%);
+}
+
+/**
+ * Status indicators GRAY/GREEN/YELLOW/RED
+ * PatientListCard.fxml
+ */
+.status-UNKNOWN {
+ -fx-background-color: derive(#1d1d1d, 30%);
+ -fx-font-family: "Segoe UI Light";
+ -fx-font-size: 13pt;
+ -fx-text-fill: white;
+ -fx-padding: 20px;
+}
+
+.status-STABLE {
+ -fx-background-color: derive(#023020, 30%);
+ -fx-font-family: "Segoe UI Light";
+ -fx-font-size: 13pt;
+ -fx-text-fill: white;
+ -fx-padding: 20px;
+}
+
+.status-SERIOUS {
+ -fx-background-color: derive(#c29500, 30%);
+ -fx-font-family: "Segoe UI Light";
+ -fx-font-size: 13pt;
+ -fx-text-fill: black;
+ -fx-padding: 20px;
+}
+
+.status-CRITICAL {
+ -fx-background-color: derive(#8B0000, 30%);
+ -fx-font-family: "Segoe UI Light";
+ -fx-font-size: 13pt;
+ -fx-text-fill: white;
+ -fx-padding: 20px;
+}
+
+.status-bar .label {
+ -fx-font-family: "Segoe UI Light";
+ -fx-text-fill: black;
+ -fx-padding: 4px;
+ -fx-pref-height: 30px;
+}
+
+.status-bar-with-border {
+ -fx-background-color: derive(#1d1d1d, 30%);
+ -fx-border-color: derive(#1d1d1d, 25%);
+ -fx-border-width: 1px;
+ -fx-text-fill: black;
+}
+
+.status-bar-with-border .label {
+ -fx-text-fill: black;
+}
+
+.grid-pane {
+ -fx-background-color: derive(#1d1d1d, 30%);
+ -fx-border-color: derive(#1d1d1d, 30%);
+ -fx-border-width: 1px;
+}
+
+.grid-pane .stack-pane {
+ -fx-background-color: derive(#1d1d1d, 30%);
+}
+
+.context-menu {
+ -fx-background-color: derive(#1d1d1d, 50%);
+}
+
+.context-menu .label {
+ -fx-text-fill: white;
+}
+
+/**
+ * Menu
+ */
+.menu-bar {
+ -fx-background-color: derive(#A8C5C9, 20%);
+}
+
+.menu-bar .label {
+ -fx-font-size: 14pt;
+ -fx-font-family: "Segoe UI Light";
+ -fx-text-fill: black;
+ -fx-opacity: 0.9;
+}
+
+.menu .left-container {
+ -fx-background-color: black;
+}
+
+/*
+ * Metro style Push Button
+ * Author: Pedro Duque Vieira
+ * http://pixelduke.wordpress.com/2012/10/23/jmetro-windows-8-controls-on-java/
+ */
+.button {
+ -fx-padding: 5 22 5 22;
+ -fx-border-color: #e2e2e2;
+ -fx-border-width: 2;
+ -fx-background-radius: 0;
+ -fx-background-color: #1d1d1d;
+ -fx-font-family: "Segoe UI", Helvetica, Arial, sans-serif;
+ -fx-font-size: 11pt;
+ -fx-text-fill: #d8d8d8;
+ -fx-background-insets: 0 0 0 0, 0, 1, 2;
+}
+
+.button:hover {
+ -fx-background-color: #3a3a3a;
+}
+
+.button:pressed, .button:default:hover:pressed {
+ -fx-background-color: white;
+ -fx-text-fill: #1d1d1d;
+}
+
+.button:focused {
+ -fx-border-color: white, white;
+ -fx-border-width: 1, 1;
+ -fx-border-style: solid, segments(1, 1);
+ -fx-border-radius: 0, 0;
+ -fx-border-insets: 1 1 1 1, 0;
+}
+
+.button:disabled, .button:default:disabled {
+ -fx-opacity: 0.4;
+ -fx-background-color: #1d1d1d;
+ -fx-text-fill: white;
+}
+
+.button:default {
+ -fx-background-color: -fx-focus-color;
+ -fx-text-fill: #ffffff;
+}
+
+.button:default:hover {
+ -fx-background-color: derive(-fx-focus-color, 30%);
+}
+
+.dialog-pane {
+ -fx-background-color: #1d1d1d;
+}
+
+.dialog-pane > *.button-bar > *.container {
+ -fx-background-color: #1d1d1d;
+}
+
+.dialog-pane > *.label.content {
+ -fx-font-size: 14px;
+ -fx-font-weight: bold;
+ -fx-text-fill: white;
+}
+
+.dialog-pane:header *.header-panel {
+ -fx-background-color: derive(#1d1d1d, 25%);
+}
+
+.dialog-pane:header *.header-panel *.label {
+ -fx-font-size: 18px;
+ -fx-font-style: italic;
+ -fx-fill: white;
+ -fx-text-fill: white;
+}
+
+.scroll-bar {
+ -fx-background-color: derive(#A8C5C9, 20%);
+}
+
+.scroll-bar .thumb {
+ -fx-background-color: derive(#1d1d1d, 50%);
+ -fx-background-insets: 3;
+}
+
+.scroll-bar .increment-button, .scroll-bar .decrement-button {
+ -fx-background-color: transparent;
+ -fx-padding: 0 0 0 0;
+}
+
+.scroll-bar .increment-arrow, .scroll-bar .decrement-arrow {
+ -fx-shape: " ";
+}
+
+.scroll-bar:vertical .increment-arrow, .scroll-bar:vertical .decrement-arrow {
+ -fx-padding: 1 8 1 8;
+}
+
+.scroll-bar:horizontal .increment-arrow, .scroll-bar:horizontal .decrement-arrow {
+ -fx-padding: 8 1 8 1;
+}
+
+
+
+/**
+ * Patient card
+ * PatientListCard.fxml
+ */
+#cardPane {
+ -fx-background-color: transparent;
+ -fx-border-width: 0;
+}
+
+#cardPaneRed {
+ -fx-background-color: red;
+ -fx-border-width: 0;
+}
+
+/**
+ * List for patients/wards
+ * PatientListPanel.fxml
+ * WardListPanel.fxml
+ */
+#listView {
+ -fx-background-color: transparent;
+ -fx-border-width: 0;
+ -fx-border-radius: 400;
+ -fx-background-radius: 400;
+}
+
+#commandTypeLabel {
+ -fx-font-size: 11px;
+ -fx-text-fill: #F70D1A;
+}
+
+/**
+ * CLI text field
+ * MainWindow.fxml
+ */
+#commandTextField {
+ -fx-background-color: transparent;
+ -fx-background-insets: 0;
+ -fx-border-color: transparent;
+ -fx-border-insets: 0;
+ -fx-border-width: 1;
+ -fx-border-radius: 100;
+ -fx-font-family: "Segoe UI Light";
+ -fx-font-size: 13pt;
+ -fx-text-fill: black;
+ -fx-prompt-text-fill: grey;
+}
+
+#filterField, #patientListPanel, #patientWebpage {
+ -fx-effect: innershadow(gaussian, black, 10, 0, 0, 0);
+}
+
+/**
+ * Results Display
+ * ResultDisplay.fxml
+ */
+#resultDisplay .content {
+ -fx-background-color: #A8C5C9;
+ -fx-background-radius: 0;
+}
+
+/**
+ * Stats
+ */
+#stats {
+ -fx-background-color: gray;
+ -fx-background-radius: 50;
+ -fx-font-family: "Segoe UI Semibold";
+ -fx-text-fill: white;
+}
+
+/**
+ * RESULT display output font
+ * ResultDisplay.fxml
+ */
+.result-display {
+ -fx-background-color: #A8C5C9;
+ -fx-font-family: "Segoe UI Light";
+ -fx-font-size: 11pt;
+ -fx-text-fill: black;
+ -fx-padding: 5px;
+}
+
+.result-display .label {
+ -fx-text-fill: black !important;
+}
+
+#tags {
+ -fx-hgap: 7;
+ -fx-vgap: 3;
+}
+
+#tags .label {
+ -fx-text-fill: white;
+ -fx-background-color: #3e7b91;
+ -fx-padding: 1 3 1 3;
+ -fx-border-radius: 2;
+ -fx-background-radius: 2;
+ -fx-font-size: 11;
+}
diff --git a/src/main/resources/view/PatientListCard.fxml b/src/main/resources/view/PatientListCard.fxml
new file mode 100644
index 00000000000..76f63260f01
--- /dev/null
+++ b/src/main/resources/view/PatientListCard.fxml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/view/PatientListPanel.fxml b/src/main/resources/view/PatientListPanel.fxml
new file mode 100644
index 00000000000..a93537aa97e
--- /dev/null
+++ b/src/main/resources/view/PatientListPanel.fxml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/view/ResultDisplay.fxml b/src/main/resources/view/ResultDisplay.fxml
index 58d5ad3dc56..2173e64bf0b 100644
--- a/src/main/resources/view/ResultDisplay.fxml
+++ b/src/main/resources/view/ResultDisplay.fxml
@@ -5,5 +5,5 @@
-
+
diff --git a/src/main/resources/view/StatusBarFooter.fxml b/src/main/resources/view/StatusBarFooter.fxml
index 149f62bd29c..a8a103c3ab1 100644
--- a/src/main/resources/view/StatusBarFooter.fxml
+++ b/src/main/resources/view/StatusBarFooter.fxml
@@ -4,9 +4,10 @@
-
-
-
-
+
+
+
+
-
+
+
diff --git a/src/main/resources/view/PersonListCard.fxml b/src/main/resources/view/WardListCard.fxml
similarity index 65%
rename from src/main/resources/view/PersonListCard.fxml
rename to src/main/resources/view/WardListCard.fxml
index f08ea32ad55..88b2ac96ad0 100644
--- a/src/main/resources/view/PersonListCard.fxml
+++ b/src/main/resources/view/WardListCard.fxml
@@ -3,7 +3,6 @@
-
@@ -14,23 +13,20 @@
-
+
-
+
-
+
-
-
-
-
+
diff --git a/src/main/resources/view/PersonListPanel.fxml b/src/main/resources/view/WardListPanel.fxml
similarity index 77%
rename from src/main/resources/view/PersonListPanel.fxml
rename to src/main/resources/view/WardListPanel.fxml
index 8836d323cc5..b0accfc02a5 100644
--- a/src/main/resources/view/PersonListPanel.fxml
+++ b/src/main/resources/view/WardListPanel.fxml
@@ -4,5 +4,5 @@
-
+
diff --git a/src/test/data/JsonAddressBookStorageTest/invalidAndValidPersonAddressBook.json b/src/test/data/JsonAddressBookStorageTest/invalidAndValidPersonAddressBook.json
deleted file mode 100644
index 6a4d2b7181c..00000000000
--- a/src/test/data/JsonAddressBookStorageTest/invalidAndValidPersonAddressBook.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "persons": [ {
- "name": "Valid Person",
- "phone": "9482424",
- "email": "hans@example.com",
- "address": "4th street"
- }, {
- "name": "Person With Invalid Phone Field",
- "phone": "948asdf2424",
- "email": "hans@example.com",
- "address": "4th street"
- } ]
-}
diff --git a/src/test/data/JsonAddressBookStorageTest/invalidPersonAddressBook.json b/src/test/data/JsonAddressBookStorageTest/invalidPersonAddressBook.json
deleted file mode 100644
index ccd21f7d1a9..00000000000
--- a/src/test/data/JsonAddressBookStorageTest/invalidPersonAddressBook.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "persons": [ {
- "name": "Person with invalid name field: Ha!ns Mu@ster",
- "phone": "9482424",
- "email": "hans@example.com",
- "address": "4th street"
- } ]
-}
diff --git a/src/test/data/JsonMedInfoStorageTest/invalidAndValidPatientMedInfo.json b/src/test/data/JsonMedInfoStorageTest/invalidAndValidPatientMedInfo.json
new file mode 100644
index 00000000000..ccff7ddceb4
--- /dev/null
+++ b/src/test/data/JsonMedInfoStorageTest/invalidAndValidPatientMedInfo.json
@@ -0,0 +1,31 @@
+{
+ "patients": [ {
+ "name": "Valid Patient",
+ "nric": "S1234567A",
+ "status": "GRAY",
+ "ward" : "Class A",
+ "discharge" : "24/01/2023 1800"
+ }, {
+ "name": "Patient With Invalid Status",
+ "nric": "S1234567A",
+ "status": "CYAN",
+ "ward" : "Class A",
+ "discharge" : "24/01/2023 1800"
+ } ],
+ "wards" : [ {
+ "name" : "Waiting Room",
+ "capacity" : 10
+ }, {
+ "name" : "Class A",
+ "capacity" : 30
+ }, {
+ "name" : "Class B",
+ "capacity" : 30
+ }, {
+ "name" : "Class C",
+ "capacity" : 30
+ }, {
+ "name" : "ICU",
+ "capacity" : 40
+ } ]
+}
diff --git a/src/test/data/JsonMedInfoStorageTest/invalidPatientMedInfo.json b/src/test/data/JsonMedInfoStorageTest/invalidPatientMedInfo.json
new file mode 100644
index 00000000000..b0e48de5881
--- /dev/null
+++ b/src/test/data/JsonMedInfoStorageTest/invalidPatientMedInfo.json
@@ -0,0 +1,25 @@
+{
+ "patients": [ {
+ "name": "Patient with invalid nric",
+ "nric": "X1234567A",
+ "status": "GRAY",
+ "ward" : "Class A",
+ "discharge" : "24/01/2023 1800"
+ } ],
+ "wards" : [ {
+ "name" : "Waiting Room",
+ "capacity" : 10
+ }, {
+ "name" : "Class A",
+ "capacity" : 30
+ }, {
+ "name" : "Class B",
+ "capacity" : 30
+ }, {
+ "name" : "Class C",
+ "capacity" : 30
+ }, {
+ "name" : "ICU",
+ "capacity" : 40
+ } ]
+}
diff --git a/src/test/data/JsonAddressBookStorageTest/notJsonFormatAddressBook.json b/src/test/data/JsonMedInfoStorageTest/notJsonFormatMedInfo.json
similarity index 100%
rename from src/test/data/JsonAddressBookStorageTest/notJsonFormatAddressBook.json
rename to src/test/data/JsonMedInfoStorageTest/notJsonFormatMedInfo.json
diff --git a/src/test/data/JsonSerializableAddressBookTest/duplicatePersonAddressBook.json b/src/test/data/JsonSerializableAddressBookTest/duplicatePersonAddressBook.json
deleted file mode 100644
index 48831cc7674..00000000000
--- a/src/test/data/JsonSerializableAddressBookTest/duplicatePersonAddressBook.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "persons": [ {
- "name": "Alice Pauline",
- "phone": "94351253",
- "email": "alice@example.com",
- "address": "123, Jurong West Ave 6, #08-111",
- "tagged": [ "friends" ]
- }, {
- "name": "Alice Pauline",
- "phone": "94351253",
- "email": "pauline@example.com",
- "address": "4th street"
- } ]
-}
diff --git a/src/test/data/JsonSerializableAddressBookTest/invalidPersonAddressBook.json b/src/test/data/JsonSerializableAddressBookTest/invalidPersonAddressBook.json
deleted file mode 100644
index ad3f135ae42..00000000000
--- a/src/test/data/JsonSerializableAddressBookTest/invalidPersonAddressBook.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "persons": [ {
- "name": "Hans Muster",
- "phone": "9482424",
- "email": "invalid@email!3e",
- "address": "4th street"
- } ]
-}
diff --git a/src/test/data/JsonSerializableAddressBookTest/typicalPersonsAddressBook.json b/src/test/data/JsonSerializableAddressBookTest/typicalPersonsAddressBook.json
deleted file mode 100644
index f10eddee12e..00000000000
--- a/src/test/data/JsonSerializableAddressBookTest/typicalPersonsAddressBook.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "_comment": "AddressBook save file which contains the same Person values as in TypicalPersons#getTypicalAddressBook()",
- "persons" : [ {
- "name" : "Alice Pauline",
- "phone" : "94351253",
- "email" : "alice@example.com",
- "address" : "123, Jurong West Ave 6, #08-111",
- "tagged" : [ "friends" ]
- }, {
- "name" : "Benson Meier",
- "phone" : "98765432",
- "email" : "johnd@example.com",
- "address" : "311, Clementi Ave 2, #02-25",
- "tagged" : [ "owesMoney", "friends" ]
- }, {
- "name" : "Carl Kurz",
- "phone" : "95352563",
- "email" : "heinz@example.com",
- "address" : "wall street",
- "tagged" : [ ]
- }, {
- "name" : "Daniel Meier",
- "phone" : "87652533",
- "email" : "cornelia@example.com",
- "address" : "10th street",
- "tagged" : [ "friends" ]
- }, {
- "name" : "Elle Meyer",
- "phone" : "9482224",
- "email" : "werner@example.com",
- "address" : "michegan ave",
- "tagged" : [ ]
- }, {
- "name" : "Fiona Kunz",
- "phone" : "9482427",
- "email" : "lydia@example.com",
- "address" : "little tokyo",
- "tagged" : [ ]
- }, {
- "name" : "George Best",
- "phone" : "9482442",
- "email" : "anna@example.com",
- "address" : "4th street",
- "tagged" : [ ]
- } ]
-}
diff --git a/src/test/data/JsonSerializableMedInfoTest/duplicatePatientMedInfo.json b/src/test/data/JsonSerializableMedInfoTest/duplicatePatientMedInfo.json
new file mode 100644
index 00000000000..a7c40f4b599
--- /dev/null
+++ b/src/test/data/JsonSerializableMedInfoTest/duplicatePatientMedInfo.json
@@ -0,0 +1,31 @@
+{
+ "patients": [ {
+ "name" : "Alex Smith",
+ "nric" : "S1334567A",
+ "status" : "GRAY",
+ "ward" : "Class A",
+ "discharge" : "16/06/2023 1500"
+ }, {
+ "name" : "Alex Smith",
+ "nric" : "S1334567A",
+ "status" : "GRAY",
+ "ward" : "Class A",
+ "discharge" : "16/06/2023 1500"
+ } ],
+ "wards" : [ {
+ "name" : "Waiting Room",
+ "capacity" : 10
+ }, {
+ "name" : "Class A",
+ "capacity" : 30
+ }, {
+ "name" : "Class B",
+ "capacity" : 30
+ }, {
+ "name" : "Class C",
+ "capacity" : 30
+ }, {
+ "name" : "ICU",
+ "capacity" : 40
+ } ]
+}
diff --git a/src/test/data/JsonSerializableMedInfoTest/invalidPatientMedInfo.json b/src/test/data/JsonSerializableMedInfoTest/invalidPatientMedInfo.json
new file mode 100644
index 00000000000..909200be721
--- /dev/null
+++ b/src/test/data/JsonSerializableMedInfoTest/invalidPatientMedInfo.json
@@ -0,0 +1,25 @@
+{
+ "patients": [ {
+ "name" : "Alex Smith",
+ "nric" : "X1334567A",
+ "status" : "LIME",
+ "ward" : "@#$",
+ "discharge" : "12/32/1232 1687"
+ } ],
+ "wards" : [ {
+ "name" : "Waiting Room",
+ "capacity" : 10
+ }, {
+ "name" : "Class A",
+ "capacity" : 30
+ }, {
+ "name" : "Class B",
+ "capacity" : 30
+ }, {
+ "name" : "Class C",
+ "capacity" : 30
+ }, {
+ "name" : "ICU",
+ "capacity" : 40
+ } ]
+}
diff --git a/src/test/data/JsonSerializableMedInfoTest/typicalPatientsMedInfo.json b/src/test/data/JsonSerializableMedInfoTest/typicalPatientsMedInfo.json
new file mode 100644
index 00000000000..c77db6e6d49
--- /dev/null
+++ b/src/test/data/JsonSerializableMedInfoTest/typicalPatientsMedInfo.json
@@ -0,0 +1,62 @@
+{
+ "_comment": "MedInfo save file which contains the same Patient values as in TypicalPatient#getTypicalMedInfo()",
+ "patients" : [ {
+ "name" : "Alex Smith",
+ "nric" : "S1000007A",
+ "status" : "GRAY",
+ "ward" : "Waiting Room",
+ "discharge" : "12/02/2023 1400"
+ }, {
+ "name" : "Benson Tillman",
+ "nric" : "S7654321F",
+ "status" : "GRAY",
+ "ward" : "Waiting Room",
+ "discharge" : "12/02/2023 1500"
+ }, {
+ "name" : "Carl Leigh",
+ "nric" : "S2468024G",
+ "status" : "GREEN",
+ "ward" : "Class A",
+ "discharge" : "12/02/2023 1600"
+ }, {
+ "name" : "Daniel Wellington",
+ "nric" : "S1244567A",
+ "status" : "YELLOW",
+ "ward" : "Class B",
+ "discharge" : "13/02/2023 1400"
+ }, {
+ "name" : "Elle Schmidt",
+ "nric" : "S1235567A",
+ "status" : "GREEN",
+ "ward" : "Class C",
+ "discharge" : "13/02/2023 1500"
+ }, {
+ "name" : "Fiona Shrekt",
+ "nric" : "S6969696B",
+ "status" : "RED",
+ "ward" : "ICU",
+ "discharge" : "13/02/2023 1600"
+ }, {
+ "name" : "George Townsend",
+ "nric" : "S1224567A",
+ "status" : "RED",
+ "ward" : "ICU",
+ "discharge" : "14/02/2023 1400"
+ } ],
+ "wards" : [ {
+ "name" : "Waiting Room",
+ "capacity" : 10
+ }, {
+ "name" : "Class A",
+ "capacity" : 30
+ }, {
+ "name" : "Class B",
+ "capacity" : 30
+ }, {
+ "name" : "Class C",
+ "capacity" : 30
+ }, {
+ "name" : "ICU",
+ "capacity" : 40
+ } ]
+}
diff --git a/src/test/data/JsonUserPrefsStorageTest/ExtraValuesUserPref.json b/src/test/data/JsonUserPrefsStorageTest/ExtraValuesUserPref.json
index 1037548a9cd..9b0d6e03289 100644
--- a/src/test/data/JsonUserPrefsStorageTest/ExtraValuesUserPref.json
+++ b/src/test/data/JsonUserPrefsStorageTest/ExtraValuesUserPref.json
@@ -9,5 +9,5 @@
"z" : 99
}
},
- "addressBookFilePath" : "addressbook.json"
+ "medInfoFilePath" : "medinfo.json"
}
diff --git a/src/test/data/JsonUserPrefsStorageTest/TypicalUserPref.json b/src/test/data/JsonUserPrefsStorageTest/TypicalUserPref.json
index b819bed900a..6a1234e28df 100644
--- a/src/test/data/JsonUserPrefsStorageTest/TypicalUserPref.json
+++ b/src/test/data/JsonUserPrefsStorageTest/TypicalUserPref.json
@@ -7,5 +7,5 @@
"y" : 100
}
},
- "addressBookFilePath" : "addressbook.json"
+ "medInfoFilePath" : "medinfo.json"
}
diff --git a/src/test/java/seedu/address/logic/commands/AddCommandIntegrationTest.java b/src/test/java/seedu/address/logic/commands/AddCommandIntegrationTest.java
deleted file mode 100644
index cb8714bb055..00000000000
--- a/src/test/java/seedu/address/logic/commands/AddCommandIntegrationTest.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package seedu.address.logic.commands;
-
-import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure;
-import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
-import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import seedu.address.model.Model;
-import seedu.address.model.ModelManager;
-import seedu.address.model.UserPrefs;
-import seedu.address.model.person.Person;
-import seedu.address.testutil.PersonBuilder;
-
-/**
- * Contains integration tests (interaction with the Model) for {@code AddCommand}.
- */
-public class AddCommandIntegrationTest {
-
- private Model model;
-
- @BeforeEach
- public void setUp() {
- model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
- }
-
- @Test
- public void execute_newPerson_success() {
- Person validPerson = new PersonBuilder().build();
-
- Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs());
- expectedModel.addPerson(validPerson);
-
- assertCommandSuccess(new AddCommand(validPerson), model,
- String.format(AddCommand.MESSAGE_SUCCESS, validPerson), expectedModel);
- }
-
- @Test
- public void execute_duplicatePerson_throwsCommandException() {
- Person personInList = model.getAddressBook().getPersonList().get(0);
- assertCommandFailure(new AddCommand(personInList), model, AddCommand.MESSAGE_DUPLICATE_PERSON);
- }
-
-}
diff --git a/src/test/java/seedu/address/logic/commands/AddCommandTest.java b/src/test/java/seedu/address/logic/commands/AddCommandTest.java
deleted file mode 100644
index 5865713d5dd..00000000000
--- a/src/test/java/seedu/address/logic/commands/AddCommandTest.java
+++ /dev/null
@@ -1,194 +0,0 @@
-package seedu.address.logic.commands;
-
-import static java.util.Objects.requireNonNull;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.testutil.Assert.assertThrows;
-
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.function.Predicate;
-
-import org.junit.jupiter.api.Test;
-
-import javafx.collections.ObservableList;
-import seedu.address.commons.core.GuiSettings;
-import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.model.AddressBook;
-import seedu.address.model.Model;
-import seedu.address.model.ReadOnlyAddressBook;
-import seedu.address.model.ReadOnlyUserPrefs;
-import seedu.address.model.person.Person;
-import seedu.address.testutil.PersonBuilder;
-
-public class AddCommandTest {
-
- @Test
- public void constructor_nullPerson_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> new AddCommand(null));
- }
-
- @Test
- public void execute_personAcceptedByModel_addSuccessful() throws Exception {
- ModelStubAcceptingPersonAdded modelStub = new ModelStubAcceptingPersonAdded();
- Person validPerson = new PersonBuilder().build();
-
- CommandResult commandResult = new AddCommand(validPerson).execute(modelStub);
-
- assertEquals(String.format(AddCommand.MESSAGE_SUCCESS, validPerson), commandResult.getFeedbackToUser());
- assertEquals(Arrays.asList(validPerson), modelStub.personsAdded);
- }
-
- @Test
- public void execute_duplicatePerson_throwsCommandException() {
- Person validPerson = new PersonBuilder().build();
- AddCommand addCommand = new AddCommand(validPerson);
- ModelStub modelStub = new ModelStubWithPerson(validPerson);
-
- assertThrows(CommandException.class, AddCommand.MESSAGE_DUPLICATE_PERSON, () -> addCommand.execute(modelStub));
- }
-
- @Test
- public void equals() {
- Person alice = new PersonBuilder().withName("Alice").build();
- Person bob = new PersonBuilder().withName("Bob").build();
- AddCommand addAliceCommand = new AddCommand(alice);
- AddCommand addBobCommand = new AddCommand(bob);
-
- // same object -> returns true
- assertTrue(addAliceCommand.equals(addAliceCommand));
-
- // same values -> returns true
- AddCommand addAliceCommandCopy = new AddCommand(alice);
- assertTrue(addAliceCommand.equals(addAliceCommandCopy));
-
- // different types -> returns false
- assertFalse(addAliceCommand.equals(1));
-
- // null -> returns false
- assertFalse(addAliceCommand.equals(null));
-
- // different person -> returns false
- assertFalse(addAliceCommand.equals(addBobCommand));
- }
-
- /**
- * A default model stub that have all of the methods failing.
- */
- private class ModelStub implements Model {
- @Override
- public void setUserPrefs(ReadOnlyUserPrefs userPrefs) {
- throw new AssertionError("This method should not be called.");
- }
-
- @Override
- public ReadOnlyUserPrefs getUserPrefs() {
- throw new AssertionError("This method should not be called.");
- }
-
- @Override
- public GuiSettings getGuiSettings() {
- throw new AssertionError("This method should not be called.");
- }
-
- @Override
- public void setGuiSettings(GuiSettings guiSettings) {
- throw new AssertionError("This method should not be called.");
- }
-
- @Override
- public Path getAddressBookFilePath() {
- throw new AssertionError("This method should not be called.");
- }
-
- @Override
- public void setAddressBookFilePath(Path addressBookFilePath) {
- throw new AssertionError("This method should not be called.");
- }
-
- @Override
- public void addPerson(Person person) {
- throw new AssertionError("This method should not be called.");
- }
-
- @Override
- public void setAddressBook(ReadOnlyAddressBook newData) {
- throw new AssertionError("This method should not be called.");
- }
-
- @Override
- public ReadOnlyAddressBook getAddressBook() {
- throw new AssertionError("This method should not be called.");
- }
-
- @Override
- public boolean hasPerson(Person person) {
- throw new AssertionError("This method should not be called.");
- }
-
- @Override
- public void deletePerson(Person target) {
- throw new AssertionError("This method should not be called.");
- }
-
- @Override
- public void setPerson(Person target, Person editedPerson) {
- throw new AssertionError("This method should not be called.");
- }
-
- @Override
- public ObservableList getFilteredPersonList() {
- throw new AssertionError("This method should not be called.");
- }
-
- @Override
- public void updateFilteredPersonList(Predicate predicate) {
- throw new AssertionError("This method should not be called.");
- }
- }
-
- /**
- * A Model stub that contains a single person.
- */
- private class ModelStubWithPerson extends ModelStub {
- private final Person person;
-
- ModelStubWithPerson(Person person) {
- requireNonNull(person);
- this.person = person;
- }
-
- @Override
- public boolean hasPerson(Person person) {
- requireNonNull(person);
- return this.person.isSamePerson(person);
- }
- }
-
- /**
- * A Model stub that always accept the person being added.
- */
- private class ModelStubAcceptingPersonAdded extends ModelStub {
- final ArrayList personsAdded = new ArrayList<>();
-
- @Override
- public boolean hasPerson(Person person) {
- requireNonNull(person);
- return personsAdded.stream().anyMatch(person::isSamePerson);
- }
-
- @Override
- public void addPerson(Person person) {
- requireNonNull(person);
- personsAdded.add(person);
- }
-
- @Override
- public ReadOnlyAddressBook getAddressBook() {
- return new AddressBook();
- }
- }
-
-}
diff --git a/src/test/java/seedu/address/logic/commands/ClearCommandTest.java b/src/test/java/seedu/address/logic/commands/ClearCommandTest.java
deleted file mode 100644
index 80d9110c03a..00000000000
--- a/src/test/java/seedu/address/logic/commands/ClearCommandTest.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package seedu.address.logic.commands;
-
-import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
-import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;
-
-import org.junit.jupiter.api.Test;
-
-import seedu.address.model.AddressBook;
-import seedu.address.model.Model;
-import seedu.address.model.ModelManager;
-import seedu.address.model.UserPrefs;
-
-public class ClearCommandTest {
-
- @Test
- public void execute_emptyAddressBook_success() {
- Model model = new ModelManager();
- Model expectedModel = new ModelManager();
-
- assertCommandSuccess(new ClearCommand(), model, ClearCommand.MESSAGE_SUCCESS, expectedModel);
- }
-
- @Test
- public void execute_nonEmptyAddressBook_success() {
- Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
- Model expectedModel = new ModelManager(getTypicalAddressBook(), new UserPrefs());
- expectedModel.setAddressBook(new AddressBook());
-
- assertCommandSuccess(new ClearCommand(), model, ClearCommand.MESSAGE_SUCCESS, expectedModel);
- }
-
-}
diff --git a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java b/src/test/java/seedu/address/logic/commands/CommandTestUtil.java
deleted file mode 100644
index 643a1d08069..00000000000
--- a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java
+++ /dev/null
@@ -1,128 +0,0 @@
-package seedu.address.logic.commands;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
-import static seedu.address.testutil.Assert.assertThrows;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import seedu.address.commons.core.index.Index;
-import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.model.AddressBook;
-import seedu.address.model.Model;
-import seedu.address.model.person.NameContainsKeywordsPredicate;
-import seedu.address.model.person.Person;
-import seedu.address.testutil.EditPersonDescriptorBuilder;
-
-/**
- * Contains helper methods for testing commands.
- */
-public class CommandTestUtil {
-
- public static final String VALID_NAME_AMY = "Amy Bee";
- public static final String VALID_NAME_BOB = "Bob Choo";
- public static final String VALID_PHONE_AMY = "11111111";
- public static final String VALID_PHONE_BOB = "22222222";
- public static final String VALID_EMAIL_AMY = "amy@example.com";
- public static final String VALID_EMAIL_BOB = "bob@example.com";
- public static final String VALID_ADDRESS_AMY = "Block 312, Amy Street 1";
- public static final String VALID_ADDRESS_BOB = "Block 123, Bobby Street 3";
- public static final String VALID_TAG_HUSBAND = "husband";
- public static final String VALID_TAG_FRIEND = "friend";
-
- public static final String NAME_DESC_AMY = " " + PREFIX_NAME + VALID_NAME_AMY;
- public static final String NAME_DESC_BOB = " " + PREFIX_NAME + VALID_NAME_BOB;
- public static final String PHONE_DESC_AMY = " " + PREFIX_PHONE + VALID_PHONE_AMY;
- public static final String PHONE_DESC_BOB = " " + PREFIX_PHONE + VALID_PHONE_BOB;
- public static final String EMAIL_DESC_AMY = " " + PREFIX_EMAIL + VALID_EMAIL_AMY;
- public static final String EMAIL_DESC_BOB = " " + PREFIX_EMAIL + VALID_EMAIL_BOB;
- public static final String ADDRESS_DESC_AMY = " " + PREFIX_ADDRESS + VALID_ADDRESS_AMY;
- public static final String ADDRESS_DESC_BOB = " " + PREFIX_ADDRESS + VALID_ADDRESS_BOB;
- public static final String TAG_DESC_FRIEND = " " + PREFIX_TAG + VALID_TAG_FRIEND;
- public static final String TAG_DESC_HUSBAND = " " + PREFIX_TAG + VALID_TAG_HUSBAND;
-
- public static final String INVALID_NAME_DESC = " " + PREFIX_NAME + "James&"; // '&' not allowed in names
- public static final String INVALID_PHONE_DESC = " " + PREFIX_PHONE + "911a"; // 'a' not allowed in phones
- public static final String INVALID_EMAIL_DESC = " " + PREFIX_EMAIL + "bob!yahoo"; // missing '@' symbol
- public static final String INVALID_ADDRESS_DESC = " " + PREFIX_ADDRESS; // empty string not allowed for addresses
- public static final String INVALID_TAG_DESC = " " + PREFIX_TAG + "hubby*"; // '*' not allowed in tags
-
- public static final String PREAMBLE_WHITESPACE = "\t \r \n";
- public static final String PREAMBLE_NON_EMPTY = "NonEmptyPreamble";
-
- public static final EditCommand.EditPersonDescriptor DESC_AMY;
- public static final EditCommand.EditPersonDescriptor DESC_BOB;
-
- static {
- DESC_AMY = new EditPersonDescriptorBuilder().withName(VALID_NAME_AMY)
- .withPhone(VALID_PHONE_AMY).withEmail(VALID_EMAIL_AMY).withAddress(VALID_ADDRESS_AMY)
- .withTags(VALID_TAG_FRIEND).build();
- DESC_BOB = new EditPersonDescriptorBuilder().withName(VALID_NAME_BOB)
- .withPhone(VALID_PHONE_BOB).withEmail(VALID_EMAIL_BOB).withAddress(VALID_ADDRESS_BOB)
- .withTags(VALID_TAG_HUSBAND, VALID_TAG_FRIEND).build();
- }
-
- /**
- * Executes the given {@code command}, confirms that
- * - the returned {@link CommandResult} matches {@code expectedCommandResult}
- * - the {@code actualModel} matches {@code expectedModel}
- */
- public static void assertCommandSuccess(Command command, Model actualModel, CommandResult expectedCommandResult,
- Model expectedModel) {
- try {
- CommandResult result = command.execute(actualModel);
- assertEquals(expectedCommandResult, result);
- assertEquals(expectedModel, actualModel);
- } catch (CommandException ce) {
- throw new AssertionError("Execution of command should not fail.", ce);
- }
- }
-
- /**
- * Convenience wrapper to {@link #assertCommandSuccess(Command, Model, CommandResult, Model)}
- * that takes a string {@code expectedMessage}.
- */
- public static void assertCommandSuccess(Command command, Model actualModel, String expectedMessage,
- Model expectedModel) {
- CommandResult expectedCommandResult = new CommandResult(expectedMessage);
- assertCommandSuccess(command, actualModel, expectedCommandResult, expectedModel);
- }
-
- /**
- * Executes the given {@code command}, confirms that
- * - a {@code CommandException} is thrown
- * - the CommandException message matches {@code expectedMessage}
- * - the address book, filtered person list and selected person in {@code actualModel} remain unchanged
- */
- public static void assertCommandFailure(Command command, Model actualModel, String expectedMessage) {
- // we are unable to defensively copy the model for comparison later, so we can
- // only do so by copying its components.
- AddressBook expectedAddressBook = new AddressBook(actualModel.getAddressBook());
- List expectedFilteredList = new ArrayList<>(actualModel.getFilteredPersonList());
-
- assertThrows(CommandException.class, expectedMessage, () -> command.execute(actualModel));
- assertEquals(expectedAddressBook, actualModel.getAddressBook());
- assertEquals(expectedFilteredList, actualModel.getFilteredPersonList());
- }
- /**
- * Updates {@code model}'s filtered list to show only the person at the given {@code targetIndex} in the
- * {@code model}'s address book.
- */
- public static void showPersonAtIndex(Model model, Index targetIndex) {
- assertTrue(targetIndex.getZeroBased() < model.getFilteredPersonList().size());
-
- Person person = model.getFilteredPersonList().get(targetIndex.getZeroBased());
- final String[] splitName = person.getName().fullName.split("\\s+");
- model.updateFilteredPersonList(new NameContainsKeywordsPredicate(Arrays.asList(splitName[0])));
-
- assertEquals(1, model.getFilteredPersonList().size());
- }
-
-}
diff --git a/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java b/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java
deleted file mode 100644
index 45a8c910ba1..00000000000
--- a/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java
+++ /dev/null
@@ -1,109 +0,0 @@
-package seedu.address.logic.commands;
-
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure;
-import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
-import static seedu.address.logic.commands.CommandTestUtil.showPersonAtIndex;
-import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
-import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PERSON;
-import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;
-
-import org.junit.jupiter.api.Test;
-
-import seedu.address.commons.core.Messages;
-import seedu.address.commons.core.index.Index;
-import seedu.address.model.Model;
-import seedu.address.model.ModelManager;
-import seedu.address.model.UserPrefs;
-import seedu.address.model.person.Person;
-
-/**
- * Contains integration tests (interaction with the Model) and unit tests for
- * {@code DeleteCommand}.
- */
-public class DeleteCommandTest {
-
- private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
-
- @Test
- public void execute_validIndexUnfilteredList_success() {
- Person personToDelete = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased());
- DeleteCommand deleteCommand = new DeleteCommand(INDEX_FIRST_PERSON);
-
- String expectedMessage = String.format(DeleteCommand.MESSAGE_DELETE_PERSON_SUCCESS, personToDelete);
-
- ModelManager expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs());
- expectedModel.deletePerson(personToDelete);
-
- assertCommandSuccess(deleteCommand, model, expectedMessage, expectedModel);
- }
-
- @Test
- public void execute_invalidIndexUnfilteredList_throwsCommandException() {
- Index outOfBoundIndex = Index.fromOneBased(model.getFilteredPersonList().size() + 1);
- DeleteCommand deleteCommand = new DeleteCommand(outOfBoundIndex);
-
- assertCommandFailure(deleteCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
- }
-
- @Test
- public void execute_validIndexFilteredList_success() {
- showPersonAtIndex(model, INDEX_FIRST_PERSON);
-
- Person personToDelete = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased());
- DeleteCommand deleteCommand = new DeleteCommand(INDEX_FIRST_PERSON);
-
- String expectedMessage = String.format(DeleteCommand.MESSAGE_DELETE_PERSON_SUCCESS, personToDelete);
-
- Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs());
- expectedModel.deletePerson(personToDelete);
- showNoPerson(expectedModel);
-
- assertCommandSuccess(deleteCommand, model, expectedMessage, expectedModel);
- }
-
- @Test
- public void execute_invalidIndexFilteredList_throwsCommandException() {
- showPersonAtIndex(model, INDEX_FIRST_PERSON);
-
- Index outOfBoundIndex = INDEX_SECOND_PERSON;
- // ensures that outOfBoundIndex is still in bounds of address book list
- assertTrue(outOfBoundIndex.getZeroBased() < model.getAddressBook().getPersonList().size());
-
- DeleteCommand deleteCommand = new DeleteCommand(outOfBoundIndex);
-
- assertCommandFailure(deleteCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
- }
-
- @Test
- public void equals() {
- DeleteCommand deleteFirstCommand = new DeleteCommand(INDEX_FIRST_PERSON);
- DeleteCommand deleteSecondCommand = new DeleteCommand(INDEX_SECOND_PERSON);
-
- // same object -> returns true
- assertTrue(deleteFirstCommand.equals(deleteFirstCommand));
-
- // same values -> returns true
- DeleteCommand deleteFirstCommandCopy = new DeleteCommand(INDEX_FIRST_PERSON);
- assertTrue(deleteFirstCommand.equals(deleteFirstCommandCopy));
-
- // different types -> returns false
- assertFalse(deleteFirstCommand.equals(1));
-
- // null -> returns false
- assertFalse(deleteFirstCommand.equals(null));
-
- // different person -> returns false
- assertFalse(deleteFirstCommand.equals(deleteSecondCommand));
- }
-
- /**
- * Updates {@code model}'s filtered list to show no one.
- */
- private void showNoPerson(Model model) {
- model.updateFilteredPersonList(p -> false);
-
- assertTrue(model.getFilteredPersonList().isEmpty());
- }
-}
diff --git a/src/test/java/seedu/address/logic/commands/EditCommandTest.java b/src/test/java/seedu/address/logic/commands/EditCommandTest.java
deleted file mode 100644
index 214c6c2507b..00000000000
--- a/src/test/java/seedu/address/logic/commands/EditCommandTest.java
+++ /dev/null
@@ -1,173 +0,0 @@
-package seedu.address.logic.commands;
-
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.logic.commands.CommandTestUtil.DESC_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.DESC_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND;
-import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure;
-import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
-import static seedu.address.logic.commands.CommandTestUtil.showPersonAtIndex;
-import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
-import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PERSON;
-import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;
-
-import org.junit.jupiter.api.Test;
-
-import seedu.address.commons.core.Messages;
-import seedu.address.commons.core.index.Index;
-import seedu.address.logic.commands.EditCommand.EditPersonDescriptor;
-import seedu.address.model.AddressBook;
-import seedu.address.model.Model;
-import seedu.address.model.ModelManager;
-import seedu.address.model.UserPrefs;
-import seedu.address.model.person.Person;
-import seedu.address.testutil.EditPersonDescriptorBuilder;
-import seedu.address.testutil.PersonBuilder;
-
-/**
- * Contains integration tests (interaction with the Model) and unit tests for EditCommand.
- */
-public class EditCommandTest {
-
- private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
-
- @Test
- public void execute_allFieldsSpecifiedUnfilteredList_success() {
- Person editedPerson = new PersonBuilder().build();
- EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(editedPerson).build();
- EditCommand editCommand = new EditCommand(INDEX_FIRST_PERSON, descriptor);
-
- String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedPerson);
-
- Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs());
- expectedModel.setPerson(model.getFilteredPersonList().get(0), editedPerson);
-
- assertCommandSuccess(editCommand, model, expectedMessage, expectedModel);
- }
-
- @Test
- public void execute_someFieldsSpecifiedUnfilteredList_success() {
- Index indexLastPerson = Index.fromOneBased(model.getFilteredPersonList().size());
- Person lastPerson = model.getFilteredPersonList().get(indexLastPerson.getZeroBased());
-
- PersonBuilder personInList = new PersonBuilder(lastPerson);
- Person editedPerson = personInList.withName(VALID_NAME_BOB).withPhone(VALID_PHONE_BOB)
- .withTags(VALID_TAG_HUSBAND).build();
-
- EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withName(VALID_NAME_BOB)
- .withPhone(VALID_PHONE_BOB).withTags(VALID_TAG_HUSBAND).build();
- EditCommand editCommand = new EditCommand(indexLastPerson, descriptor);
-
- String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedPerson);
-
- Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs());
- expectedModel.setPerson(lastPerson, editedPerson);
-
- assertCommandSuccess(editCommand, model, expectedMessage, expectedModel);
- }
-
- @Test
- public void execute_noFieldSpecifiedUnfilteredList_success() {
- EditCommand editCommand = new EditCommand(INDEX_FIRST_PERSON, new EditPersonDescriptor());
- Person editedPerson = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased());
-
- String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedPerson);
-
- Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs());
-
- assertCommandSuccess(editCommand, model, expectedMessage, expectedModel);
- }
-
- @Test
- public void execute_filteredList_success() {
- showPersonAtIndex(model, INDEX_FIRST_PERSON);
-
- Person personInFilteredList = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased());
- Person editedPerson = new PersonBuilder(personInFilteredList).withName(VALID_NAME_BOB).build();
- EditCommand editCommand = new EditCommand(INDEX_FIRST_PERSON,
- new EditPersonDescriptorBuilder().withName(VALID_NAME_BOB).build());
-
- String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedPerson);
-
- Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs());
- expectedModel.setPerson(model.getFilteredPersonList().get(0), editedPerson);
-
- assertCommandSuccess(editCommand, model, expectedMessage, expectedModel);
- }
-
- @Test
- public void execute_duplicatePersonUnfilteredList_failure() {
- Person firstPerson = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased());
- EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(firstPerson).build();
- EditCommand editCommand = new EditCommand(INDEX_SECOND_PERSON, descriptor);
-
- assertCommandFailure(editCommand, model, EditCommand.MESSAGE_DUPLICATE_PERSON);
- }
-
- @Test
- public void execute_duplicatePersonFilteredList_failure() {
- showPersonAtIndex(model, INDEX_FIRST_PERSON);
-
- // edit person in filtered list into a duplicate in address book
- Person personInList = model.getAddressBook().getPersonList().get(INDEX_SECOND_PERSON.getZeroBased());
- EditCommand editCommand = new EditCommand(INDEX_FIRST_PERSON,
- new EditPersonDescriptorBuilder(personInList).build());
-
- assertCommandFailure(editCommand, model, EditCommand.MESSAGE_DUPLICATE_PERSON);
- }
-
- @Test
- public void execute_invalidPersonIndexUnfilteredList_failure() {
- Index outOfBoundIndex = Index.fromOneBased(model.getFilteredPersonList().size() + 1);
- EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withName(VALID_NAME_BOB).build();
- EditCommand editCommand = new EditCommand(outOfBoundIndex, descriptor);
-
- assertCommandFailure(editCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
- }
-
- /**
- * Edit filtered list where index is larger than size of filtered list,
- * but smaller than size of address book
- */
- @Test
- public void execute_invalidPersonIndexFilteredList_failure() {
- showPersonAtIndex(model, INDEX_FIRST_PERSON);
- Index outOfBoundIndex = INDEX_SECOND_PERSON;
- // ensures that outOfBoundIndex is still in bounds of address book list
- assertTrue(outOfBoundIndex.getZeroBased() < model.getAddressBook().getPersonList().size());
-
- EditCommand editCommand = new EditCommand(outOfBoundIndex,
- new EditPersonDescriptorBuilder().withName(VALID_NAME_BOB).build());
-
- assertCommandFailure(editCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
- }
-
- @Test
- public void equals() {
- final EditCommand standardCommand = new EditCommand(INDEX_FIRST_PERSON, DESC_AMY);
-
- // same values -> returns true
- EditPersonDescriptor copyDescriptor = new EditPersonDescriptor(DESC_AMY);
- EditCommand commandWithSameValues = new EditCommand(INDEX_FIRST_PERSON, copyDescriptor);
- assertTrue(standardCommand.equals(commandWithSameValues));
-
- // same object -> returns true
- assertTrue(standardCommand.equals(standardCommand));
-
- // null -> returns false
- assertFalse(standardCommand.equals(null));
-
- // different types -> returns false
- assertFalse(standardCommand.equals(new ClearCommand()));
-
- // different index -> returns false
- assertFalse(standardCommand.equals(new EditCommand(INDEX_SECOND_PERSON, DESC_AMY)));
-
- // different descriptor -> returns false
- assertFalse(standardCommand.equals(new EditCommand(INDEX_FIRST_PERSON, DESC_BOB)));
- }
-
-}
diff --git a/src/test/java/seedu/address/logic/commands/EditPersonDescriptorTest.java b/src/test/java/seedu/address/logic/commands/EditPersonDescriptorTest.java
deleted file mode 100644
index e0288792e72..00000000000
--- a/src/test/java/seedu/address/logic/commands/EditPersonDescriptorTest.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package seedu.address.logic.commands;
-
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.logic.commands.CommandTestUtil.DESC_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.DESC_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND;
-
-import org.junit.jupiter.api.Test;
-
-import seedu.address.logic.commands.EditCommand.EditPersonDescriptor;
-import seedu.address.testutil.EditPersonDescriptorBuilder;
-
-public class EditPersonDescriptorTest {
-
- @Test
- public void equals() {
- // same values -> returns true
- EditPersonDescriptor descriptorWithSameValues = new EditPersonDescriptor(DESC_AMY);
- assertTrue(DESC_AMY.equals(descriptorWithSameValues));
-
- // same object -> returns true
- assertTrue(DESC_AMY.equals(DESC_AMY));
-
- // null -> returns false
- assertFalse(DESC_AMY.equals(null));
-
- // different types -> returns false
- assertFalse(DESC_AMY.equals(5));
-
- // different values -> returns false
- assertFalse(DESC_AMY.equals(DESC_BOB));
-
- // different name -> returns false
- EditPersonDescriptor editedAmy = new EditPersonDescriptorBuilder(DESC_AMY).withName(VALID_NAME_BOB).build();
- assertFalse(DESC_AMY.equals(editedAmy));
-
- // different phone -> returns false
- editedAmy = new EditPersonDescriptorBuilder(DESC_AMY).withPhone(VALID_PHONE_BOB).build();
- assertFalse(DESC_AMY.equals(editedAmy));
-
- // different email -> returns false
- editedAmy = new EditPersonDescriptorBuilder(DESC_AMY).withEmail(VALID_EMAIL_BOB).build();
- assertFalse(DESC_AMY.equals(editedAmy));
-
- // different address -> returns false
- editedAmy = new EditPersonDescriptorBuilder(DESC_AMY).withAddress(VALID_ADDRESS_BOB).build();
- assertFalse(DESC_AMY.equals(editedAmy));
-
- // different tags -> returns false
- editedAmy = new EditPersonDescriptorBuilder(DESC_AMY).withTags(VALID_TAG_HUSBAND).build();
- assertFalse(DESC_AMY.equals(editedAmy));
- }
-}
diff --git a/src/test/java/seedu/address/logic/commands/FindCommandTest.java b/src/test/java/seedu/address/logic/commands/FindCommandTest.java
deleted file mode 100644
index 9b15db28bbb..00000000000
--- a/src/test/java/seedu/address/logic/commands/FindCommandTest.java
+++ /dev/null
@@ -1,83 +0,0 @@
-package seedu.address.logic.commands;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.commons.core.Messages.MESSAGE_PERSONS_LISTED_OVERVIEW;
-import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
-import static seedu.address.testutil.TypicalPersons.CARL;
-import static seedu.address.testutil.TypicalPersons.ELLE;
-import static seedu.address.testutil.TypicalPersons.FIONA;
-import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;
-
-import java.util.Arrays;
-import java.util.Collections;
-
-import org.junit.jupiter.api.Test;
-
-import seedu.address.model.Model;
-import seedu.address.model.ModelManager;
-import seedu.address.model.UserPrefs;
-import seedu.address.model.person.NameContainsKeywordsPredicate;
-
-/**
- * Contains integration tests (interaction with the Model) for {@code FindCommand}.
- */
-public class FindCommandTest {
- private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
- private Model expectedModel = new ModelManager(getTypicalAddressBook(), new UserPrefs());
-
- @Test
- public void equals() {
- NameContainsKeywordsPredicate firstPredicate =
- new NameContainsKeywordsPredicate(Collections.singletonList("first"));
- NameContainsKeywordsPredicate secondPredicate =
- new NameContainsKeywordsPredicate(Collections.singletonList("second"));
-
- FindCommand findFirstCommand = new FindCommand(firstPredicate);
- FindCommand findSecondCommand = new FindCommand(secondPredicate);
-
- // same object -> returns true
- assertTrue(findFirstCommand.equals(findFirstCommand));
-
- // same values -> returns true
- FindCommand findFirstCommandCopy = new FindCommand(firstPredicate);
- assertTrue(findFirstCommand.equals(findFirstCommandCopy));
-
- // different types -> returns false
- assertFalse(findFirstCommand.equals(1));
-
- // null -> returns false
- assertFalse(findFirstCommand.equals(null));
-
- // different person -> returns false
- assertFalse(findFirstCommand.equals(findSecondCommand));
- }
-
- @Test
- public void execute_zeroKeywords_noPersonFound() {
- String expectedMessage = String.format(MESSAGE_PERSONS_LISTED_OVERVIEW, 0);
- NameContainsKeywordsPredicate predicate = preparePredicate(" ");
- FindCommand command = new FindCommand(predicate);
- expectedModel.updateFilteredPersonList(predicate);
- assertCommandSuccess(command, model, expectedMessage, expectedModel);
- assertEquals(Collections.emptyList(), model.getFilteredPersonList());
- }
-
- @Test
- public void execute_multipleKeywords_multiplePersonsFound() {
- String expectedMessage = String.format(MESSAGE_PERSONS_LISTED_OVERVIEW, 3);
- NameContainsKeywordsPredicate predicate = preparePredicate("Kurz Elle Kunz");
- FindCommand command = new FindCommand(predicate);
- expectedModel.updateFilteredPersonList(predicate);
- assertCommandSuccess(command, model, expectedMessage, expectedModel);
- assertEquals(Arrays.asList(CARL, ELLE, FIONA), model.getFilteredPersonList());
- }
-
- /**
- * Parses {@code userInput} into a {@code NameContainsKeywordsPredicate}.
- */
- private NameContainsKeywordsPredicate preparePredicate(String userInput) {
- return new NameContainsKeywordsPredicate(Arrays.asList(userInput.split("\\s+")));
- }
-}
diff --git a/src/test/java/seedu/address/logic/commands/ListCommandTest.java b/src/test/java/seedu/address/logic/commands/ListCommandTest.java
deleted file mode 100644
index 435ff1f7275..00000000000
--- a/src/test/java/seedu/address/logic/commands/ListCommandTest.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package seedu.address.logic.commands;
-
-import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
-import static seedu.address.logic.commands.CommandTestUtil.showPersonAtIndex;
-import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
-import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import seedu.address.model.Model;
-import seedu.address.model.ModelManager;
-import seedu.address.model.UserPrefs;
-
-/**
- * Contains integration tests (interaction with the Model) and unit tests for ListCommand.
- */
-public class ListCommandTest {
-
- private Model model;
- private Model expectedModel;
-
- @BeforeEach
- public void setUp() {
- model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
- expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs());
- }
-
- @Test
- public void execute_listIsNotFiltered_showsSameList() {
- assertCommandSuccess(new ListCommand(), model, ListCommand.MESSAGE_SUCCESS, expectedModel);
- }
-
- @Test
- public void execute_listIsFiltered_showsEverything() {
- showPersonAtIndex(model, INDEX_FIRST_PERSON);
- assertCommandSuccess(new ListCommand(), model, ListCommand.MESSAGE_SUCCESS, expectedModel);
- }
-}
diff --git a/src/test/java/seedu/address/logic/parser/AddCommandParserTest.java b/src/test/java/seedu/address/logic/parser/AddCommandParserTest.java
deleted file mode 100644
index 5cf487d7ebb..00000000000
--- a/src/test/java/seedu/address/logic/parser/AddCommandParserTest.java
+++ /dev/null
@@ -1,141 +0,0 @@
-package seedu.address.logic.parser;
-
-import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
-import static seedu.address.logic.commands.CommandTestUtil.ADDRESS_DESC_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.ADDRESS_DESC_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.EMAIL_DESC_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.EMAIL_DESC_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.INVALID_ADDRESS_DESC;
-import static seedu.address.logic.commands.CommandTestUtil.INVALID_EMAIL_DESC;
-import static seedu.address.logic.commands.CommandTestUtil.INVALID_NAME_DESC;
-import static seedu.address.logic.commands.CommandTestUtil.INVALID_PHONE_DESC;
-import static seedu.address.logic.commands.CommandTestUtil.INVALID_TAG_DESC;
-import static seedu.address.logic.commands.CommandTestUtil.NAME_DESC_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.NAME_DESC_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.PHONE_DESC_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.PHONE_DESC_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.PREAMBLE_NON_EMPTY;
-import static seedu.address.logic.commands.CommandTestUtil.PREAMBLE_WHITESPACE;
-import static seedu.address.logic.commands.CommandTestUtil.TAG_DESC_FRIEND;
-import static seedu.address.logic.commands.CommandTestUtil.TAG_DESC_HUSBAND;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_FRIEND;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND;
-import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure;
-import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess;
-import static seedu.address.testutil.TypicalPersons.AMY;
-import static seedu.address.testutil.TypicalPersons.BOB;
-
-import org.junit.jupiter.api.Test;
-
-import seedu.address.logic.commands.AddCommand;
-import seedu.address.model.person.Address;
-import seedu.address.model.person.Email;
-import seedu.address.model.person.Name;
-import seedu.address.model.person.Person;
-import seedu.address.model.person.Phone;
-import seedu.address.model.tag.Tag;
-import seedu.address.testutil.PersonBuilder;
-
-public class AddCommandParserTest {
- private AddCommandParser parser = new AddCommandParser();
-
- @Test
- public void parse_allFieldsPresent_success() {
- Person expectedPerson = new PersonBuilder(BOB).withTags(VALID_TAG_FRIEND).build();
-
- // whitespace only preamble
- assertParseSuccess(parser, PREAMBLE_WHITESPACE + NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB
- + ADDRESS_DESC_BOB + TAG_DESC_FRIEND, new AddCommand(expectedPerson));
-
- // multiple names - last name accepted
- assertParseSuccess(parser, NAME_DESC_AMY + NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB
- + ADDRESS_DESC_BOB + TAG_DESC_FRIEND, new AddCommand(expectedPerson));
-
- // multiple phones - last phone accepted
- assertParseSuccess(parser, NAME_DESC_BOB + PHONE_DESC_AMY + PHONE_DESC_BOB + EMAIL_DESC_BOB
- + ADDRESS_DESC_BOB + TAG_DESC_FRIEND, new AddCommand(expectedPerson));
-
- // multiple emails - last email accepted
- assertParseSuccess(parser, NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_AMY + EMAIL_DESC_BOB
- + ADDRESS_DESC_BOB + TAG_DESC_FRIEND, new AddCommand(expectedPerson));
-
- // multiple addresses - last address accepted
- assertParseSuccess(parser, NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_AMY
- + ADDRESS_DESC_BOB + TAG_DESC_FRIEND, new AddCommand(expectedPerson));
-
- // multiple tags - all accepted
- Person expectedPersonMultipleTags = new PersonBuilder(BOB).withTags(VALID_TAG_FRIEND, VALID_TAG_HUSBAND)
- .build();
- assertParseSuccess(parser, NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB
- + TAG_DESC_HUSBAND + TAG_DESC_FRIEND, new AddCommand(expectedPersonMultipleTags));
- }
-
- @Test
- public void parse_optionalFieldsMissing_success() {
- // zero tags
- Person expectedPerson = new PersonBuilder(AMY).withTags().build();
- assertParseSuccess(parser, NAME_DESC_AMY + PHONE_DESC_AMY + EMAIL_DESC_AMY + ADDRESS_DESC_AMY,
- new AddCommand(expectedPerson));
- }
-
- @Test
- public void parse_compulsoryFieldMissing_failure() {
- String expectedMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE);
-
- // missing name prefix
- assertParseFailure(parser, VALID_NAME_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB,
- expectedMessage);
-
- // missing phone prefix
- assertParseFailure(parser, NAME_DESC_BOB + VALID_PHONE_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB,
- expectedMessage);
-
- // missing email prefix
- assertParseFailure(parser, NAME_DESC_BOB + PHONE_DESC_BOB + VALID_EMAIL_BOB + ADDRESS_DESC_BOB,
- expectedMessage);
-
- // missing address prefix
- assertParseFailure(parser, NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + VALID_ADDRESS_BOB,
- expectedMessage);
-
- // all prefixes missing
- assertParseFailure(parser, VALID_NAME_BOB + VALID_PHONE_BOB + VALID_EMAIL_BOB + VALID_ADDRESS_BOB,
- expectedMessage);
- }
-
- @Test
- public void parse_invalidValue_failure() {
- // invalid name
- assertParseFailure(parser, INVALID_NAME_DESC + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB
- + TAG_DESC_HUSBAND + TAG_DESC_FRIEND, Name.MESSAGE_CONSTRAINTS);
-
- // invalid phone
- assertParseFailure(parser, NAME_DESC_BOB + INVALID_PHONE_DESC + EMAIL_DESC_BOB + ADDRESS_DESC_BOB
- + TAG_DESC_HUSBAND + TAG_DESC_FRIEND, Phone.MESSAGE_CONSTRAINTS);
-
- // invalid email
- assertParseFailure(parser, NAME_DESC_BOB + PHONE_DESC_BOB + INVALID_EMAIL_DESC + ADDRESS_DESC_BOB
- + TAG_DESC_HUSBAND + TAG_DESC_FRIEND, Email.MESSAGE_CONSTRAINTS);
-
- // invalid address
- assertParseFailure(parser, NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + INVALID_ADDRESS_DESC
- + TAG_DESC_HUSBAND + TAG_DESC_FRIEND, Address.MESSAGE_CONSTRAINTS);
-
- // invalid tag
- assertParseFailure(parser, NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB
- + INVALID_TAG_DESC + VALID_TAG_FRIEND, Tag.MESSAGE_CONSTRAINTS);
-
- // two invalid values, only first invalid value reported
- assertParseFailure(parser, INVALID_NAME_DESC + PHONE_DESC_BOB + EMAIL_DESC_BOB + INVALID_ADDRESS_DESC,
- Name.MESSAGE_CONSTRAINTS);
-
- // non-empty preamble
- assertParseFailure(parser, PREAMBLE_NON_EMPTY + NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB
- + ADDRESS_DESC_BOB + TAG_DESC_HUSBAND + TAG_DESC_FRIEND,
- String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE));
- }
-}
diff --git a/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java b/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java
deleted file mode 100644
index d9659205b57..00000000000
--- a/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java
+++ /dev/null
@@ -1,101 +0,0 @@
-package seedu.address.logic.parser;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
-import static seedu.address.commons.core.Messages.MESSAGE_UNKNOWN_COMMAND;
-import static seedu.address.testutil.Assert.assertThrows;
-import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.stream.Collectors;
-
-import org.junit.jupiter.api.Test;
-
-import seedu.address.logic.commands.AddCommand;
-import seedu.address.logic.commands.ClearCommand;
-import seedu.address.logic.commands.DeleteCommand;
-import seedu.address.logic.commands.EditCommand;
-import seedu.address.logic.commands.EditCommand.EditPersonDescriptor;
-import seedu.address.logic.commands.ExitCommand;
-import seedu.address.logic.commands.FindCommand;
-import seedu.address.logic.commands.HelpCommand;
-import seedu.address.logic.commands.ListCommand;
-import seedu.address.logic.parser.exceptions.ParseException;
-import seedu.address.model.person.NameContainsKeywordsPredicate;
-import seedu.address.model.person.Person;
-import seedu.address.testutil.EditPersonDescriptorBuilder;
-import seedu.address.testutil.PersonBuilder;
-import seedu.address.testutil.PersonUtil;
-
-public class AddressBookParserTest {
-
- private final AddressBookParser parser = new AddressBookParser();
-
- @Test
- public void parseCommand_add() throws Exception {
- Person person = new PersonBuilder().build();
- AddCommand command = (AddCommand) parser.parseCommand(PersonUtil.getAddCommand(person));
- assertEquals(new AddCommand(person), command);
- }
-
- @Test
- public void parseCommand_clear() throws Exception {
- assertTrue(parser.parseCommand(ClearCommand.COMMAND_WORD) instanceof ClearCommand);
- assertTrue(parser.parseCommand(ClearCommand.COMMAND_WORD + " 3") instanceof ClearCommand);
- }
-
- @Test
- public void parseCommand_delete() throws Exception {
- DeleteCommand command = (DeleteCommand) parser.parseCommand(
- DeleteCommand.COMMAND_WORD + " " + INDEX_FIRST_PERSON.getOneBased());
- assertEquals(new DeleteCommand(INDEX_FIRST_PERSON), command);
- }
-
- @Test
- public void parseCommand_edit() throws Exception {
- Person person = new PersonBuilder().build();
- EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(person).build();
- EditCommand command = (EditCommand) parser.parseCommand(EditCommand.COMMAND_WORD + " "
- + INDEX_FIRST_PERSON.getOneBased() + " " + PersonUtil.getEditPersonDescriptorDetails(descriptor));
- assertEquals(new EditCommand(INDEX_FIRST_PERSON, descriptor), command);
- }
-
- @Test
- public void parseCommand_exit() throws Exception {
- assertTrue(parser.parseCommand(ExitCommand.COMMAND_WORD) instanceof ExitCommand);
- assertTrue(parser.parseCommand(ExitCommand.COMMAND_WORD + " 3") instanceof ExitCommand);
- }
-
- @Test
- public void parseCommand_find() throws Exception {
- List keywords = Arrays.asList("foo", "bar", "baz");
- FindCommand command = (FindCommand) parser.parseCommand(
- FindCommand.COMMAND_WORD + " " + keywords.stream().collect(Collectors.joining(" ")));
- assertEquals(new FindCommand(new NameContainsKeywordsPredicate(keywords)), command);
- }
-
- @Test
- public void parseCommand_help() throws Exception {
- assertTrue(parser.parseCommand(HelpCommand.COMMAND_WORD) instanceof HelpCommand);
- assertTrue(parser.parseCommand(HelpCommand.COMMAND_WORD + " 3") instanceof HelpCommand);
- }
-
- @Test
- public void parseCommand_list() throws Exception {
- assertTrue(parser.parseCommand(ListCommand.COMMAND_WORD) instanceof ListCommand);
- assertTrue(parser.parseCommand(ListCommand.COMMAND_WORD + " 3") instanceof ListCommand);
- }
-
- @Test
- public void parseCommand_unrecognisedInput_throwsParseException() {
- assertThrows(ParseException.class, String.format(MESSAGE_INVALID_COMMAND_FORMAT, HelpCommand.MESSAGE_USAGE), ()
- -> parser.parseCommand(""));
- }
-
- @Test
- public void parseCommand_unknownCommand_throwsParseException() {
- assertThrows(ParseException.class, MESSAGE_UNKNOWN_COMMAND, () -> parser.parseCommand("unknownCommand"));
- }
-}
diff --git a/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java b/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java
deleted file mode 100644
index 2ff31522486..00000000000
--- a/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java
+++ /dev/null
@@ -1,211 +0,0 @@
-package seedu.address.logic.parser;
-
-import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
-import static seedu.address.logic.commands.CommandTestUtil.ADDRESS_DESC_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.ADDRESS_DESC_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.EMAIL_DESC_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.EMAIL_DESC_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.INVALID_ADDRESS_DESC;
-import static seedu.address.logic.commands.CommandTestUtil.INVALID_EMAIL_DESC;
-import static seedu.address.logic.commands.CommandTestUtil.INVALID_NAME_DESC;
-import static seedu.address.logic.commands.CommandTestUtil.INVALID_PHONE_DESC;
-import static seedu.address.logic.commands.CommandTestUtil.INVALID_TAG_DESC;
-import static seedu.address.logic.commands.CommandTestUtil.NAME_DESC_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.PHONE_DESC_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.PHONE_DESC_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.TAG_DESC_FRIEND;
-import static seedu.address.logic.commands.CommandTestUtil.TAG_DESC_HUSBAND;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_FRIEND;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
-import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure;
-import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess;
-import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
-import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PERSON;
-import static seedu.address.testutil.TypicalIndexes.INDEX_THIRD_PERSON;
-
-import org.junit.jupiter.api.Test;
-
-import seedu.address.commons.core.index.Index;
-import seedu.address.logic.commands.EditCommand;
-import seedu.address.logic.commands.EditCommand.EditPersonDescriptor;
-import seedu.address.model.person.Address;
-import seedu.address.model.person.Email;
-import seedu.address.model.person.Name;
-import seedu.address.model.person.Phone;
-import seedu.address.model.tag.Tag;
-import seedu.address.testutil.EditPersonDescriptorBuilder;
-
-public class EditCommandParserTest {
-
- private static final String TAG_EMPTY = " " + PREFIX_TAG;
-
- private static final String MESSAGE_INVALID_FORMAT =
- String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditCommand.MESSAGE_USAGE);
-
- private EditCommandParser parser = new EditCommandParser();
-
- @Test
- public void parse_missingParts_failure() {
- // no index specified
- assertParseFailure(parser, VALID_NAME_AMY, MESSAGE_INVALID_FORMAT);
-
- // no field specified
- assertParseFailure(parser, "1", EditCommand.MESSAGE_NOT_EDITED);
-
- // no index and no field specified
- assertParseFailure(parser, "", MESSAGE_INVALID_FORMAT);
- }
-
- @Test
- public void parse_invalidPreamble_failure() {
- // negative index
- assertParseFailure(parser, "-5" + NAME_DESC_AMY, MESSAGE_INVALID_FORMAT);
-
- // zero index
- assertParseFailure(parser, "0" + NAME_DESC_AMY, MESSAGE_INVALID_FORMAT);
-
- // invalid arguments being parsed as preamble
- assertParseFailure(parser, "1 some random string", MESSAGE_INVALID_FORMAT);
-
- // invalid prefix being parsed as preamble
- assertParseFailure(parser, "1 i/ string", MESSAGE_INVALID_FORMAT);
- }
-
- @Test
- public void parse_invalidValue_failure() {
- assertParseFailure(parser, "1" + INVALID_NAME_DESC, Name.MESSAGE_CONSTRAINTS); // invalid name
- assertParseFailure(parser, "1" + INVALID_PHONE_DESC, Phone.MESSAGE_CONSTRAINTS); // invalid phone
- assertParseFailure(parser, "1" + INVALID_EMAIL_DESC, Email.MESSAGE_CONSTRAINTS); // invalid email
- assertParseFailure(parser, "1" + INVALID_ADDRESS_DESC, Address.MESSAGE_CONSTRAINTS); // invalid address
- assertParseFailure(parser, "1" + INVALID_TAG_DESC, Tag.MESSAGE_CONSTRAINTS); // invalid tag
-
- // invalid phone followed by valid email
- assertParseFailure(parser, "1" + INVALID_PHONE_DESC + EMAIL_DESC_AMY, Phone.MESSAGE_CONSTRAINTS);
-
- // valid phone followed by invalid phone. The test case for invalid phone followed by valid phone
- // is tested at {@code parse_invalidValueFollowedByValidValue_success()}
- assertParseFailure(parser, "1" + PHONE_DESC_BOB + INVALID_PHONE_DESC, Phone.MESSAGE_CONSTRAINTS);
-
- // while parsing {@code PREFIX_TAG} alone will reset the tags of the {@code Person} being edited,
- // parsing it together with a valid tag results in error
- assertParseFailure(parser, "1" + TAG_DESC_FRIEND + TAG_DESC_HUSBAND + TAG_EMPTY, Tag.MESSAGE_CONSTRAINTS);
- assertParseFailure(parser, "1" + TAG_DESC_FRIEND + TAG_EMPTY + TAG_DESC_HUSBAND, Tag.MESSAGE_CONSTRAINTS);
- assertParseFailure(parser, "1" + TAG_EMPTY + TAG_DESC_FRIEND + TAG_DESC_HUSBAND, Tag.MESSAGE_CONSTRAINTS);
-
- // multiple invalid values, but only the first invalid value is captured
- assertParseFailure(parser, "1" + INVALID_NAME_DESC + INVALID_EMAIL_DESC + VALID_ADDRESS_AMY + VALID_PHONE_AMY,
- Name.MESSAGE_CONSTRAINTS);
- }
-
- @Test
- public void parse_allFieldsSpecified_success() {
- Index targetIndex = INDEX_SECOND_PERSON;
- String userInput = targetIndex.getOneBased() + PHONE_DESC_BOB + TAG_DESC_HUSBAND
- + EMAIL_DESC_AMY + ADDRESS_DESC_AMY + NAME_DESC_AMY + TAG_DESC_FRIEND;
-
- EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withName(VALID_NAME_AMY)
- .withPhone(VALID_PHONE_BOB).withEmail(VALID_EMAIL_AMY).withAddress(VALID_ADDRESS_AMY)
- .withTags(VALID_TAG_HUSBAND, VALID_TAG_FRIEND).build();
- EditCommand expectedCommand = new EditCommand(targetIndex, descriptor);
-
- assertParseSuccess(parser, userInput, expectedCommand);
- }
-
- @Test
- public void parse_someFieldsSpecified_success() {
- Index targetIndex = INDEX_FIRST_PERSON;
- String userInput = targetIndex.getOneBased() + PHONE_DESC_BOB + EMAIL_DESC_AMY;
-
- EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withPhone(VALID_PHONE_BOB)
- .withEmail(VALID_EMAIL_AMY).build();
- EditCommand expectedCommand = new EditCommand(targetIndex, descriptor);
-
- assertParseSuccess(parser, userInput, expectedCommand);
- }
-
- @Test
- public void parse_oneFieldSpecified_success() {
- // name
- Index targetIndex = INDEX_THIRD_PERSON;
- String userInput = targetIndex.getOneBased() + NAME_DESC_AMY;
- EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withName(VALID_NAME_AMY).build();
- EditCommand expectedCommand = new EditCommand(targetIndex, descriptor);
- assertParseSuccess(parser, userInput, expectedCommand);
-
- // phone
- userInput = targetIndex.getOneBased() + PHONE_DESC_AMY;
- descriptor = new EditPersonDescriptorBuilder().withPhone(VALID_PHONE_AMY).build();
- expectedCommand = new EditCommand(targetIndex, descriptor);
- assertParseSuccess(parser, userInput, expectedCommand);
-
- // email
- userInput = targetIndex.getOneBased() + EMAIL_DESC_AMY;
- descriptor = new EditPersonDescriptorBuilder().withEmail(VALID_EMAIL_AMY).build();
- expectedCommand = new EditCommand(targetIndex, descriptor);
- assertParseSuccess(parser, userInput, expectedCommand);
-
- // address
- userInput = targetIndex.getOneBased() + ADDRESS_DESC_AMY;
- descriptor = new EditPersonDescriptorBuilder().withAddress(VALID_ADDRESS_AMY).build();
- expectedCommand = new EditCommand(targetIndex, descriptor);
- assertParseSuccess(parser, userInput, expectedCommand);
-
- // tags
- userInput = targetIndex.getOneBased() + TAG_DESC_FRIEND;
- descriptor = new EditPersonDescriptorBuilder().withTags(VALID_TAG_FRIEND).build();
- expectedCommand = new EditCommand(targetIndex, descriptor);
- assertParseSuccess(parser, userInput, expectedCommand);
- }
-
- @Test
- public void parse_multipleRepeatedFields_acceptsLast() {
- Index targetIndex = INDEX_FIRST_PERSON;
- String userInput = targetIndex.getOneBased() + PHONE_DESC_AMY + ADDRESS_DESC_AMY + EMAIL_DESC_AMY
- + TAG_DESC_FRIEND + PHONE_DESC_AMY + ADDRESS_DESC_AMY + EMAIL_DESC_AMY + TAG_DESC_FRIEND
- + PHONE_DESC_BOB + ADDRESS_DESC_BOB + EMAIL_DESC_BOB + TAG_DESC_HUSBAND;
-
- EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withPhone(VALID_PHONE_BOB)
- .withEmail(VALID_EMAIL_BOB).withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_FRIEND, VALID_TAG_HUSBAND)
- .build();
- EditCommand expectedCommand = new EditCommand(targetIndex, descriptor);
-
- assertParseSuccess(parser, userInput, expectedCommand);
- }
-
- @Test
- public void parse_invalidValueFollowedByValidValue_success() {
- // no other valid values specified
- Index targetIndex = INDEX_FIRST_PERSON;
- String userInput = targetIndex.getOneBased() + INVALID_PHONE_DESC + PHONE_DESC_BOB;
- EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withPhone(VALID_PHONE_BOB).build();
- EditCommand expectedCommand = new EditCommand(targetIndex, descriptor);
- assertParseSuccess(parser, userInput, expectedCommand);
-
- // other valid values specified
- userInput = targetIndex.getOneBased() + EMAIL_DESC_BOB + INVALID_PHONE_DESC + ADDRESS_DESC_BOB
- + PHONE_DESC_BOB;
- descriptor = new EditPersonDescriptorBuilder().withPhone(VALID_PHONE_BOB).withEmail(VALID_EMAIL_BOB)
- .withAddress(VALID_ADDRESS_BOB).build();
- expectedCommand = new EditCommand(targetIndex, descriptor);
- assertParseSuccess(parser, userInput, expectedCommand);
- }
-
- @Test
- public void parse_resetTags_success() {
- Index targetIndex = INDEX_THIRD_PERSON;
- String userInput = targetIndex.getOneBased() + TAG_EMPTY;
-
- EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withTags().build();
- EditCommand expectedCommand = new EditCommand(targetIndex, descriptor);
-
- assertParseSuccess(parser, userInput, expectedCommand);
- }
-}
diff --git a/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java b/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java
deleted file mode 100644
index 70f4f0e79c4..00000000000
--- a/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package seedu.address.logic.parser;
-
-import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
-import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure;
-import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess;
-
-import java.util.Arrays;
-
-import org.junit.jupiter.api.Test;
-
-import seedu.address.logic.commands.FindCommand;
-import seedu.address.model.person.NameContainsKeywordsPredicate;
-
-public class FindCommandParserTest {
-
- private FindCommandParser parser = new FindCommandParser();
-
- @Test
- public void parse_emptyArg_throwsParseException() {
- assertParseFailure(parser, " ", String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_USAGE));
- }
-
- @Test
- public void parse_validArgs_returnsFindCommand() {
- // no leading and trailing whitespaces
- FindCommand expectedFindCommand =
- new FindCommand(new NameContainsKeywordsPredicate(Arrays.asList("Alice", "Bob")));
- assertParseSuccess(parser, "Alice Bob", expectedFindCommand);
-
- // multiple whitespaces between keywords
- assertParseSuccess(parser, " \n Alice \n \t Bob \t", expectedFindCommand);
- }
-
-}
diff --git a/src/test/java/seedu/address/logic/parser/ParserUtilTest.java b/src/test/java/seedu/address/logic/parser/ParserUtilTest.java
deleted file mode 100644
index 4256788b1a7..00000000000
--- a/src/test/java/seedu/address/logic/parser/ParserUtilTest.java
+++ /dev/null
@@ -1,196 +0,0 @@
-package seedu.address.logic.parser;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.logic.parser.ParserUtil.MESSAGE_INVALID_INDEX;
-import static seedu.address.testutil.Assert.assertThrows;
-import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
-import org.junit.jupiter.api.Test;
-
-import seedu.address.logic.parser.exceptions.ParseException;
-import seedu.address.model.person.Address;
-import seedu.address.model.person.Email;
-import seedu.address.model.person.Name;
-import seedu.address.model.person.Phone;
-import seedu.address.model.tag.Tag;
-
-public class ParserUtilTest {
- private static final String INVALID_NAME = "R@chel";
- private static final String INVALID_PHONE = "+651234";
- private static final String INVALID_ADDRESS = " ";
- private static final String INVALID_EMAIL = "example.com";
- private static final String INVALID_TAG = "#friend";
-
- private static final String VALID_NAME = "Rachel Walker";
- private static final String VALID_PHONE = "123456";
- private static final String VALID_ADDRESS = "123 Main Street #0505";
- private static final String VALID_EMAIL = "rachel@example.com";
- private static final String VALID_TAG_1 = "friend";
- private static final String VALID_TAG_2 = "neighbour";
-
- private static final String WHITESPACE = " \t\r\n";
-
- @Test
- public void parseIndex_invalidInput_throwsParseException() {
- assertThrows(ParseException.class, () -> ParserUtil.parseIndex("10 a"));
- }
-
- @Test
- public void parseIndex_outOfRangeInput_throwsParseException() {
- assertThrows(ParseException.class, MESSAGE_INVALID_INDEX, ()
- -> ParserUtil.parseIndex(Long.toString(Integer.MAX_VALUE + 1)));
- }
-
- @Test
- public void parseIndex_validInput_success() throws Exception {
- // No whitespaces
- assertEquals(INDEX_FIRST_PERSON, ParserUtil.parseIndex("1"));
-
- // Leading and trailing whitespaces
- assertEquals(INDEX_FIRST_PERSON, ParserUtil.parseIndex(" 1 "));
- }
-
- @Test
- public void parseName_null_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> ParserUtil.parseName((String) null));
- }
-
- @Test
- public void parseName_invalidValue_throwsParseException() {
- assertThrows(ParseException.class, () -> ParserUtil.parseName(INVALID_NAME));
- }
-
- @Test
- public void parseName_validValueWithoutWhitespace_returnsName() throws Exception {
- Name expectedName = new Name(VALID_NAME);
- assertEquals(expectedName, ParserUtil.parseName(VALID_NAME));
- }
-
- @Test
- public void parseName_validValueWithWhitespace_returnsTrimmedName() throws Exception {
- String nameWithWhitespace = WHITESPACE + VALID_NAME + WHITESPACE;
- Name expectedName = new Name(VALID_NAME);
- assertEquals(expectedName, ParserUtil.parseName(nameWithWhitespace));
- }
-
- @Test
- public void parsePhone_null_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> ParserUtil.parsePhone((String) null));
- }
-
- @Test
- public void parsePhone_invalidValue_throwsParseException() {
- assertThrows(ParseException.class, () -> ParserUtil.parsePhone(INVALID_PHONE));
- }
-
- @Test
- public void parsePhone_validValueWithoutWhitespace_returnsPhone() throws Exception {
- Phone expectedPhone = new Phone(VALID_PHONE);
- assertEquals(expectedPhone, ParserUtil.parsePhone(VALID_PHONE));
- }
-
- @Test
- public void parsePhone_validValueWithWhitespace_returnsTrimmedPhone() throws Exception {
- String phoneWithWhitespace = WHITESPACE + VALID_PHONE + WHITESPACE;
- Phone expectedPhone = new Phone(VALID_PHONE);
- assertEquals(expectedPhone, ParserUtil.parsePhone(phoneWithWhitespace));
- }
-
- @Test
- public void parseAddress_null_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> ParserUtil.parseAddress((String) null));
- }
-
- @Test
- public void parseAddress_invalidValue_throwsParseException() {
- assertThrows(ParseException.class, () -> ParserUtil.parseAddress(INVALID_ADDRESS));
- }
-
- @Test
- public void parseAddress_validValueWithoutWhitespace_returnsAddress() throws Exception {
- Address expectedAddress = new Address(VALID_ADDRESS);
- assertEquals(expectedAddress, ParserUtil.parseAddress(VALID_ADDRESS));
- }
-
- @Test
- public void parseAddress_validValueWithWhitespace_returnsTrimmedAddress() throws Exception {
- String addressWithWhitespace = WHITESPACE + VALID_ADDRESS + WHITESPACE;
- Address expectedAddress = new Address(VALID_ADDRESS);
- assertEquals(expectedAddress, ParserUtil.parseAddress(addressWithWhitespace));
- }
-
- @Test
- public void parseEmail_null_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> ParserUtil.parseEmail((String) null));
- }
-
- @Test
- public void parseEmail_invalidValue_throwsParseException() {
- assertThrows(ParseException.class, () -> ParserUtil.parseEmail(INVALID_EMAIL));
- }
-
- @Test
- public void parseEmail_validValueWithoutWhitespace_returnsEmail() throws Exception {
- Email expectedEmail = new Email(VALID_EMAIL);
- assertEquals(expectedEmail, ParserUtil.parseEmail(VALID_EMAIL));
- }
-
- @Test
- public void parseEmail_validValueWithWhitespace_returnsTrimmedEmail() throws Exception {
- String emailWithWhitespace = WHITESPACE + VALID_EMAIL + WHITESPACE;
- Email expectedEmail = new Email(VALID_EMAIL);
- assertEquals(expectedEmail, ParserUtil.parseEmail(emailWithWhitespace));
- }
-
- @Test
- public void parseTag_null_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> ParserUtil.parseTag(null));
- }
-
- @Test
- public void parseTag_invalidValue_throwsParseException() {
- assertThrows(ParseException.class, () -> ParserUtil.parseTag(INVALID_TAG));
- }
-
- @Test
- public void parseTag_validValueWithoutWhitespace_returnsTag() throws Exception {
- Tag expectedTag = new Tag(VALID_TAG_1);
- assertEquals(expectedTag, ParserUtil.parseTag(VALID_TAG_1));
- }
-
- @Test
- public void parseTag_validValueWithWhitespace_returnsTrimmedTag() throws Exception {
- String tagWithWhitespace = WHITESPACE + VALID_TAG_1 + WHITESPACE;
- Tag expectedTag = new Tag(VALID_TAG_1);
- assertEquals(expectedTag, ParserUtil.parseTag(tagWithWhitespace));
- }
-
- @Test
- public void parseTags_null_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> ParserUtil.parseTags(null));
- }
-
- @Test
- public void parseTags_collectionWithInvalidTags_throwsParseException() {
- assertThrows(ParseException.class, () -> ParserUtil.parseTags(Arrays.asList(VALID_TAG_1, INVALID_TAG)));
- }
-
- @Test
- public void parseTags_emptyCollection_returnsEmptySet() throws Exception {
- assertTrue(ParserUtil.parseTags(Collections.emptyList()).isEmpty());
- }
-
- @Test
- public void parseTags_collectionWithValidTags_returnsTagSet() throws Exception {
- Set actualTagSet = ParserUtil.parseTags(Arrays.asList(VALID_TAG_1, VALID_TAG_2));
- Set expectedTagSet = new HashSet(Arrays.asList(new Tag(VALID_TAG_1), new Tag(VALID_TAG_2)));
-
- assertEquals(expectedTagSet, actualTagSet);
- }
-}
diff --git a/src/test/java/seedu/address/model/AddressBookTest.java b/src/test/java/seedu/address/model/AddressBookTest.java
deleted file mode 100644
index 87782528ecd..00000000000
--- a/src/test/java/seedu/address/model/AddressBookTest.java
+++ /dev/null
@@ -1,102 +0,0 @@
-package seedu.address.model;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND;
-import static seedu.address.testutil.Assert.assertThrows;
-import static seedu.address.testutil.TypicalPersons.ALICE;
-import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
-import org.junit.jupiter.api.Test;
-
-import javafx.collections.FXCollections;
-import javafx.collections.ObservableList;
-import seedu.address.model.person.Person;
-import seedu.address.model.person.exceptions.DuplicatePersonException;
-import seedu.address.testutil.PersonBuilder;
-
-public class AddressBookTest {
-
- private final AddressBook addressBook = new AddressBook();
-
- @Test
- public void constructor() {
- assertEquals(Collections.emptyList(), addressBook.getPersonList());
- }
-
- @Test
- public void resetData_null_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> addressBook.resetData(null));
- }
-
- @Test
- public void resetData_withValidReadOnlyAddressBook_replacesData() {
- AddressBook newData = getTypicalAddressBook();
- addressBook.resetData(newData);
- assertEquals(newData, addressBook);
- }
-
- @Test
- public void resetData_withDuplicatePersons_throwsDuplicatePersonException() {
- // Two persons with the same identity fields
- Person editedAlice = new PersonBuilder(ALICE).withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND)
- .build();
- List newPersons = Arrays.asList(ALICE, editedAlice);
- AddressBookStub newData = new AddressBookStub(newPersons);
-
- assertThrows(DuplicatePersonException.class, () -> addressBook.resetData(newData));
- }
-
- @Test
- public void hasPerson_nullPerson_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> addressBook.hasPerson(null));
- }
-
- @Test
- public void hasPerson_personNotInAddressBook_returnsFalse() {
- assertFalse(addressBook.hasPerson(ALICE));
- }
-
- @Test
- public void hasPerson_personInAddressBook_returnsTrue() {
- addressBook.addPerson(ALICE);
- assertTrue(addressBook.hasPerson(ALICE));
- }
-
- @Test
- public void hasPerson_personWithSameIdentityFieldsInAddressBook_returnsTrue() {
- addressBook.addPerson(ALICE);
- Person editedAlice = new PersonBuilder(ALICE).withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND)
- .build();
- assertTrue(addressBook.hasPerson(editedAlice));
- }
-
- @Test
- public void getPersonList_modifyList_throwsUnsupportedOperationException() {
- assertThrows(UnsupportedOperationException.class, () -> addressBook.getPersonList().remove(0));
- }
-
- /**
- * A stub ReadOnlyAddressBook whose persons list can violate interface constraints.
- */
- private static class AddressBookStub implements ReadOnlyAddressBook {
- private final ObservableList persons = FXCollections.observableArrayList();
-
- AddressBookStub(Collection persons) {
- this.persons.setAll(persons);
- }
-
- @Override
- public ObservableList getPersonList() {
- return persons;
- }
- }
-
-}
diff --git a/src/test/java/seedu/address/model/ModelManagerTest.java b/src/test/java/seedu/address/model/ModelManagerTest.java
deleted file mode 100644
index 2cf1418d116..00000000000
--- a/src/test/java/seedu/address/model/ModelManagerTest.java
+++ /dev/null
@@ -1,132 +0,0 @@
-package seedu.address.model;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS;
-import static seedu.address.testutil.Assert.assertThrows;
-import static seedu.address.testutil.TypicalPersons.ALICE;
-import static seedu.address.testutil.TypicalPersons.BENSON;
-
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.Arrays;
-
-import org.junit.jupiter.api.Test;
-
-import seedu.address.commons.core.GuiSettings;
-import seedu.address.model.person.NameContainsKeywordsPredicate;
-import seedu.address.testutil.AddressBookBuilder;
-
-public class ModelManagerTest {
-
- private ModelManager modelManager = new ModelManager();
-
- @Test
- public void constructor() {
- assertEquals(new UserPrefs(), modelManager.getUserPrefs());
- assertEquals(new GuiSettings(), modelManager.getGuiSettings());
- assertEquals(new AddressBook(), new AddressBook(modelManager.getAddressBook()));
- }
-
- @Test
- public void setUserPrefs_nullUserPrefs_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> modelManager.setUserPrefs(null));
- }
-
- @Test
- public void setUserPrefs_validUserPrefs_copiesUserPrefs() {
- UserPrefs userPrefs = new UserPrefs();
- userPrefs.setAddressBookFilePath(Paths.get("address/book/file/path"));
- userPrefs.setGuiSettings(new GuiSettings(1, 2, 3, 4));
- modelManager.setUserPrefs(userPrefs);
- assertEquals(userPrefs, modelManager.getUserPrefs());
-
- // Modifying userPrefs should not modify modelManager's userPrefs
- UserPrefs oldUserPrefs = new UserPrefs(userPrefs);
- userPrefs.setAddressBookFilePath(Paths.get("new/address/book/file/path"));
- assertEquals(oldUserPrefs, modelManager.getUserPrefs());
- }
-
- @Test
- public void setGuiSettings_nullGuiSettings_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> modelManager.setGuiSettings(null));
- }
-
- @Test
- public void setGuiSettings_validGuiSettings_setsGuiSettings() {
- GuiSettings guiSettings = new GuiSettings(1, 2, 3, 4);
- modelManager.setGuiSettings(guiSettings);
- assertEquals(guiSettings, modelManager.getGuiSettings());
- }
-
- @Test
- public void setAddressBookFilePath_nullPath_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> modelManager.setAddressBookFilePath(null));
- }
-
- @Test
- public void setAddressBookFilePath_validPath_setsAddressBookFilePath() {
- Path path = Paths.get("address/book/file/path");
- modelManager.setAddressBookFilePath(path);
- assertEquals(path, modelManager.getAddressBookFilePath());
- }
-
- @Test
- public void hasPerson_nullPerson_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> modelManager.hasPerson(null));
- }
-
- @Test
- public void hasPerson_personNotInAddressBook_returnsFalse() {
- assertFalse(modelManager.hasPerson(ALICE));
- }
-
- @Test
- public void hasPerson_personInAddressBook_returnsTrue() {
- modelManager.addPerson(ALICE);
- assertTrue(modelManager.hasPerson(ALICE));
- }
-
- @Test
- public void getFilteredPersonList_modifyList_throwsUnsupportedOperationException() {
- assertThrows(UnsupportedOperationException.class, () -> modelManager.getFilteredPersonList().remove(0));
- }
-
- @Test
- public void equals() {
- AddressBook addressBook = new AddressBookBuilder().withPerson(ALICE).withPerson(BENSON).build();
- AddressBook differentAddressBook = new AddressBook();
- UserPrefs userPrefs = new UserPrefs();
-
- // same values -> returns true
- modelManager = new ModelManager(addressBook, userPrefs);
- ModelManager modelManagerCopy = new ModelManager(addressBook, userPrefs);
- assertTrue(modelManager.equals(modelManagerCopy));
-
- // same object -> returns true
- assertTrue(modelManager.equals(modelManager));
-
- // null -> returns false
- assertFalse(modelManager.equals(null));
-
- // different types -> returns false
- assertFalse(modelManager.equals(5));
-
- // different addressBook -> returns false
- assertFalse(modelManager.equals(new ModelManager(differentAddressBook, userPrefs)));
-
- // different filteredList -> returns false
- String[] keywords = ALICE.getName().fullName.split("\\s+");
- modelManager.updateFilteredPersonList(new NameContainsKeywordsPredicate(Arrays.asList(keywords)));
- assertFalse(modelManager.equals(new ModelManager(addressBook, userPrefs)));
-
- // resets modelManager to initial state for upcoming tests
- modelManager.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
-
- // different userPrefs -> returns false
- UserPrefs differentUserPrefs = new UserPrefs();
- differentUserPrefs.setAddressBookFilePath(Paths.get("differentFilePath"));
- assertFalse(modelManager.equals(new ModelManager(addressBook, differentUserPrefs)));
- }
-}
diff --git a/src/test/java/seedu/address/model/person/AddressTest.java b/src/test/java/seedu/address/model/person/AddressTest.java
deleted file mode 100644
index dcd3be87b3a..00000000000
--- a/src/test/java/seedu/address/model/person/AddressTest.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package seedu.address.model.person;
-
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.testutil.Assert.assertThrows;
-
-import org.junit.jupiter.api.Test;
-
-public class AddressTest {
-
- @Test
- public void constructor_null_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> new Address(null));
- }
-
- @Test
- public void constructor_invalidAddress_throwsIllegalArgumentException() {
- String invalidAddress = "";
- assertThrows(IllegalArgumentException.class, () -> new Address(invalidAddress));
- }
-
- @Test
- public void isValidAddress() {
- // null address
- assertThrows(NullPointerException.class, () -> Address.isValidAddress(null));
-
- // invalid addresses
- assertFalse(Address.isValidAddress("")); // empty string
- assertFalse(Address.isValidAddress(" ")); // spaces only
-
- // valid addresses
- assertTrue(Address.isValidAddress("Blk 456, Den Road, #01-355"));
- assertTrue(Address.isValidAddress("-")); // one character
- assertTrue(Address.isValidAddress("Leng Inc; 1234 Market St; San Francisco CA 2349879; USA")); // long address
- }
-}
diff --git a/src/test/java/seedu/address/model/person/EmailTest.java b/src/test/java/seedu/address/model/person/EmailTest.java
deleted file mode 100644
index bbcc6c8c98e..00000000000
--- a/src/test/java/seedu/address/model/person/EmailTest.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package seedu.address.model.person;
-
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.testutil.Assert.assertThrows;
-
-import org.junit.jupiter.api.Test;
-
-public class EmailTest {
-
- @Test
- public void constructor_null_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> new Email(null));
- }
-
- @Test
- public void constructor_invalidEmail_throwsIllegalArgumentException() {
- String invalidEmail = "";
- assertThrows(IllegalArgumentException.class, () -> new Email(invalidEmail));
- }
-
- @Test
- public void isValidEmail() {
- // null email
- assertThrows(NullPointerException.class, () -> Email.isValidEmail(null));
-
- // blank email
- assertFalse(Email.isValidEmail("")); // empty string
- assertFalse(Email.isValidEmail(" ")); // spaces only
-
- // missing parts
- assertFalse(Email.isValidEmail("@example.com")); // missing local part
- assertFalse(Email.isValidEmail("peterjackexample.com")); // missing '@' symbol
- assertFalse(Email.isValidEmail("peterjack@")); // missing domain name
-
- // invalid parts
- assertFalse(Email.isValidEmail("peterjack@-")); // invalid domain name
- assertFalse(Email.isValidEmail("peterjack@exam_ple.com")); // underscore in domain name
- assertFalse(Email.isValidEmail("peter jack@example.com")); // spaces in local part
- assertFalse(Email.isValidEmail("peterjack@exam ple.com")); // spaces in domain name
- assertFalse(Email.isValidEmail(" peterjack@example.com")); // leading space
- assertFalse(Email.isValidEmail("peterjack@example.com ")); // trailing space
- assertFalse(Email.isValidEmail("peterjack@@example.com")); // double '@' symbol
- assertFalse(Email.isValidEmail("peter@jack@example.com")); // '@' symbol in local part
- assertFalse(Email.isValidEmail("-peterjack@example.com")); // local part starts with a hyphen
- assertFalse(Email.isValidEmail("peterjack-@example.com")); // local part ends with a hyphen
- assertFalse(Email.isValidEmail("peter..jack@example.com")); // local part has two consecutive periods
- assertFalse(Email.isValidEmail("peterjack@example@com")); // '@' symbol in domain name
- assertFalse(Email.isValidEmail("peterjack@.example.com")); // domain name starts with a period
- assertFalse(Email.isValidEmail("peterjack@example.com.")); // domain name ends with a period
- assertFalse(Email.isValidEmail("peterjack@-example.com")); // domain name starts with a hyphen
- assertFalse(Email.isValidEmail("peterjack@example.com-")); // domain name ends with a hyphen
- assertFalse(Email.isValidEmail("peterjack@example.c")); // top level domain has less than two chars
-
- // valid email
- assertTrue(Email.isValidEmail("PeterJack_1190@example.com")); // underscore in local part
- assertTrue(Email.isValidEmail("PeterJack.1190@example.com")); // period in local part
- assertTrue(Email.isValidEmail("PeterJack+1190@example.com")); // '+' symbol in local part
- assertTrue(Email.isValidEmail("PeterJack-1190@example.com")); // hyphen in local part
- assertTrue(Email.isValidEmail("a@bc")); // minimal
- assertTrue(Email.isValidEmail("test@localhost")); // alphabets only
- assertTrue(Email.isValidEmail("123@145")); // numeric local part and domain name
- assertTrue(Email.isValidEmail("a1+be.d@example1.com")); // mixture of alphanumeric and special characters
- assertTrue(Email.isValidEmail("peter_jack@very-very-very-long-example.com")); // long domain name
- assertTrue(Email.isValidEmail("if.you.dream.it_you.can.do.it@example.com")); // long local part
- assertTrue(Email.isValidEmail("e1234567@u.nus.edu")); // more than one period in domain
- }
-}
diff --git a/src/test/java/seedu/address/model/person/PersonTest.java b/src/test/java/seedu/address/model/person/PersonTest.java
deleted file mode 100644
index b29c097cfd4..00000000000
--- a/src/test/java/seedu/address/model/person/PersonTest.java
+++ /dev/null
@@ -1,91 +0,0 @@
-package seedu.address.model.person;
-
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND;
-import static seedu.address.testutil.Assert.assertThrows;
-import static seedu.address.testutil.TypicalPersons.ALICE;
-import static seedu.address.testutil.TypicalPersons.BOB;
-
-import org.junit.jupiter.api.Test;
-
-import seedu.address.testutil.PersonBuilder;
-
-public class PersonTest {
-
- @Test
- public void asObservableList_modifyList_throwsUnsupportedOperationException() {
- Person person = new PersonBuilder().build();
- assertThrows(UnsupportedOperationException.class, () -> person.getTags().remove(0));
- }
-
- @Test
- public void isSamePerson() {
- // same object -> returns true
- assertTrue(ALICE.isSamePerson(ALICE));
-
- // null -> returns false
- assertFalse(ALICE.isSamePerson(null));
-
- // same name, all other attributes different -> returns true
- Person editedAlice = new PersonBuilder(ALICE).withPhone(VALID_PHONE_BOB).withEmail(VALID_EMAIL_BOB)
- .withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND).build();
- assertTrue(ALICE.isSamePerson(editedAlice));
-
- // different name, all other attributes same -> returns false
- editedAlice = new PersonBuilder(ALICE).withName(VALID_NAME_BOB).build();
- assertFalse(ALICE.isSamePerson(editedAlice));
-
- // name differs in case, all other attributes same -> returns false
- Person editedBob = new PersonBuilder(BOB).withName(VALID_NAME_BOB.toLowerCase()).build();
- assertFalse(BOB.isSamePerson(editedBob));
-
- // name has trailing spaces, all other attributes same -> returns false
- String nameWithTrailingSpaces = VALID_NAME_BOB + " ";
- editedBob = new PersonBuilder(BOB).withName(nameWithTrailingSpaces).build();
- assertFalse(BOB.isSamePerson(editedBob));
- }
-
- @Test
- public void equals() {
- // same values -> returns true
- Person aliceCopy = new PersonBuilder(ALICE).build();
- assertTrue(ALICE.equals(aliceCopy));
-
- // same object -> returns true
- assertTrue(ALICE.equals(ALICE));
-
- // null -> returns false
- assertFalse(ALICE.equals(null));
-
- // different type -> returns false
- assertFalse(ALICE.equals(5));
-
- // different person -> returns false
- assertFalse(ALICE.equals(BOB));
-
- // different name -> returns false
- Person editedAlice = new PersonBuilder(ALICE).withName(VALID_NAME_BOB).build();
- assertFalse(ALICE.equals(editedAlice));
-
- // different phone -> returns false
- editedAlice = new PersonBuilder(ALICE).withPhone(VALID_PHONE_BOB).build();
- assertFalse(ALICE.equals(editedAlice));
-
- // different email -> returns false
- editedAlice = new PersonBuilder(ALICE).withEmail(VALID_EMAIL_BOB).build();
- assertFalse(ALICE.equals(editedAlice));
-
- // different address -> returns false
- editedAlice = new PersonBuilder(ALICE).withAddress(VALID_ADDRESS_BOB).build();
- assertFalse(ALICE.equals(editedAlice));
-
- // different tags -> returns false
- editedAlice = new PersonBuilder(ALICE).withTags(VALID_TAG_HUSBAND).build();
- assertFalse(ALICE.equals(editedAlice));
- }
-}
diff --git a/src/test/java/seedu/address/model/person/PhoneTest.java b/src/test/java/seedu/address/model/person/PhoneTest.java
deleted file mode 100644
index 8dd52766a5f..00000000000
--- a/src/test/java/seedu/address/model/person/PhoneTest.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package seedu.address.model.person;
-
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.testutil.Assert.assertThrows;
-
-import org.junit.jupiter.api.Test;
-
-public class PhoneTest {
-
- @Test
- public void constructor_null_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> new Phone(null));
- }
-
- @Test
- public void constructor_invalidPhone_throwsIllegalArgumentException() {
- String invalidPhone = "";
- assertThrows(IllegalArgumentException.class, () -> new Phone(invalidPhone));
- }
-
- @Test
- public void isValidPhone() {
- // null phone number
- assertThrows(NullPointerException.class, () -> Phone.isValidPhone(null));
-
- // invalid phone numbers
- assertFalse(Phone.isValidPhone("")); // empty string
- assertFalse(Phone.isValidPhone(" ")); // spaces only
- assertFalse(Phone.isValidPhone("91")); // less than 3 numbers
- assertFalse(Phone.isValidPhone("phone")); // non-numeric
- assertFalse(Phone.isValidPhone("9011p041")); // alphabets within digits
- assertFalse(Phone.isValidPhone("9312 1534")); // spaces within digits
-
- // valid phone numbers
- assertTrue(Phone.isValidPhone("911")); // exactly 3 numbers
- assertTrue(Phone.isValidPhone("93121534"));
- assertTrue(Phone.isValidPhone("124293842033123")); // long phone numbers
- }
-}
diff --git a/src/test/java/seedu/address/model/person/UniquePersonListTest.java b/src/test/java/seedu/address/model/person/UniquePersonListTest.java
deleted file mode 100644
index 1cc5fe9e0fe..00000000000
--- a/src/test/java/seedu/address/model/person/UniquePersonListTest.java
+++ /dev/null
@@ -1,170 +0,0 @@
-package seedu.address.model.person;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND;
-import static seedu.address.testutil.Assert.assertThrows;
-import static seedu.address.testutil.TypicalPersons.ALICE;
-import static seedu.address.testutil.TypicalPersons.BOB;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-import org.junit.jupiter.api.Test;
-
-import seedu.address.model.person.exceptions.DuplicatePersonException;
-import seedu.address.model.person.exceptions.PersonNotFoundException;
-import seedu.address.testutil.PersonBuilder;
-
-public class UniquePersonListTest {
-
- private final UniquePersonList uniquePersonList = new UniquePersonList();
-
- @Test
- public void contains_nullPerson_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> uniquePersonList.contains(null));
- }
-
- @Test
- public void contains_personNotInList_returnsFalse() {
- assertFalse(uniquePersonList.contains(ALICE));
- }
-
- @Test
- public void contains_personInList_returnsTrue() {
- uniquePersonList.add(ALICE);
- assertTrue(uniquePersonList.contains(ALICE));
- }
-
- @Test
- public void contains_personWithSameIdentityFieldsInList_returnsTrue() {
- uniquePersonList.add(ALICE);
- Person editedAlice = new PersonBuilder(ALICE).withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND)
- .build();
- assertTrue(uniquePersonList.contains(editedAlice));
- }
-
- @Test
- public void add_nullPerson_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> uniquePersonList.add(null));
- }
-
- @Test
- public void add_duplicatePerson_throwsDuplicatePersonException() {
- uniquePersonList.add(ALICE);
- assertThrows(DuplicatePersonException.class, () -> uniquePersonList.add(ALICE));
- }
-
- @Test
- public void setPerson_nullTargetPerson_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> uniquePersonList.setPerson(null, ALICE));
- }
-
- @Test
- public void setPerson_nullEditedPerson_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> uniquePersonList.setPerson(ALICE, null));
- }
-
- @Test
- public void setPerson_targetPersonNotInList_throwsPersonNotFoundException() {
- assertThrows(PersonNotFoundException.class, () -> uniquePersonList.setPerson(ALICE, ALICE));
- }
-
- @Test
- public void setPerson_editedPersonIsSamePerson_success() {
- uniquePersonList.add(ALICE);
- uniquePersonList.setPerson(ALICE, ALICE);
- UniquePersonList expectedUniquePersonList = new UniquePersonList();
- expectedUniquePersonList.add(ALICE);
- assertEquals(expectedUniquePersonList, uniquePersonList);
- }
-
- @Test
- public void setPerson_editedPersonHasSameIdentity_success() {
- uniquePersonList.add(ALICE);
- Person editedAlice = new PersonBuilder(ALICE).withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND)
- .build();
- uniquePersonList.setPerson(ALICE, editedAlice);
- UniquePersonList expectedUniquePersonList = new UniquePersonList();
- expectedUniquePersonList.add(editedAlice);
- assertEquals(expectedUniquePersonList, uniquePersonList);
- }
-
- @Test
- public void setPerson_editedPersonHasDifferentIdentity_success() {
- uniquePersonList.add(ALICE);
- uniquePersonList.setPerson(ALICE, BOB);
- UniquePersonList expectedUniquePersonList = new UniquePersonList();
- expectedUniquePersonList.add(BOB);
- assertEquals(expectedUniquePersonList, uniquePersonList);
- }
-
- @Test
- public void setPerson_editedPersonHasNonUniqueIdentity_throwsDuplicatePersonException() {
- uniquePersonList.add(ALICE);
- uniquePersonList.add(BOB);
- assertThrows(DuplicatePersonException.class, () -> uniquePersonList.setPerson(ALICE, BOB));
- }
-
- @Test
- public void remove_nullPerson_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> uniquePersonList.remove(null));
- }
-
- @Test
- public void remove_personDoesNotExist_throwsPersonNotFoundException() {
- assertThrows(PersonNotFoundException.class, () -> uniquePersonList.remove(ALICE));
- }
-
- @Test
- public void remove_existingPerson_removesPerson() {
- uniquePersonList.add(ALICE);
- uniquePersonList.remove(ALICE);
- UniquePersonList expectedUniquePersonList = new UniquePersonList();
- assertEquals(expectedUniquePersonList, uniquePersonList);
- }
-
- @Test
- public void setPersons_nullUniquePersonList_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> uniquePersonList.setPersons((UniquePersonList) null));
- }
-
- @Test
- public void setPersons_uniquePersonList_replacesOwnListWithProvidedUniquePersonList() {
- uniquePersonList.add(ALICE);
- UniquePersonList expectedUniquePersonList = new UniquePersonList();
- expectedUniquePersonList.add(BOB);
- uniquePersonList.setPersons(expectedUniquePersonList);
- assertEquals(expectedUniquePersonList, uniquePersonList);
- }
-
- @Test
- public void setPersons_nullList_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> uniquePersonList.setPersons((List) null));
- }
-
- @Test
- public void setPersons_list_replacesOwnListWithProvidedList() {
- uniquePersonList.add(ALICE);
- List personList = Collections.singletonList(BOB);
- uniquePersonList.setPersons(personList);
- UniquePersonList expectedUniquePersonList = new UniquePersonList();
- expectedUniquePersonList.add(BOB);
- assertEquals(expectedUniquePersonList, uniquePersonList);
- }
-
- @Test
- public void setPersons_listWithDuplicatePersons_throwsDuplicatePersonException() {
- List listWithDuplicatePersons = Arrays.asList(ALICE, ALICE);
- assertThrows(DuplicatePersonException.class, () -> uniquePersonList.setPersons(listWithDuplicatePersons));
- }
-
- @Test
- public void asUnmodifiableObservableList_modifyList_throwsUnsupportedOperationException() {
- assertThrows(UnsupportedOperationException.class, ()
- -> uniquePersonList.asUnmodifiableObservableList().remove(0));
- }
-}
diff --git a/src/test/java/seedu/address/model/tag/TagTest.java b/src/test/java/seedu/address/model/tag/TagTest.java
deleted file mode 100644
index 64d07d79ee2..00000000000
--- a/src/test/java/seedu/address/model/tag/TagTest.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package seedu.address.model.tag;
-
-import static seedu.address.testutil.Assert.assertThrows;
-
-import org.junit.jupiter.api.Test;
-
-public class TagTest {
-
- @Test
- public void constructor_null_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> new Tag(null));
- }
-
- @Test
- public void constructor_invalidTagName_throwsIllegalArgumentException() {
- String invalidTagName = "";
- assertThrows(IllegalArgumentException.class, () -> new Tag(invalidTagName));
- }
-
- @Test
- public void isValidTagName() {
- // null tag name
- assertThrows(NullPointerException.class, () -> Tag.isValidTagName(null));
- }
-
-}
diff --git a/src/test/java/seedu/address/storage/JsonAdaptedPersonTest.java b/src/test/java/seedu/address/storage/JsonAdaptedPersonTest.java
deleted file mode 100644
index 83b11331cdb..00000000000
--- a/src/test/java/seedu/address/storage/JsonAdaptedPersonTest.java
+++ /dev/null
@@ -1,110 +0,0 @@
-package seedu.address.storage;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static seedu.address.storage.JsonAdaptedPerson.MISSING_FIELD_MESSAGE_FORMAT;
-import static seedu.address.testutil.Assert.assertThrows;
-import static seedu.address.testutil.TypicalPersons.BENSON;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.stream.Collectors;
-
-import org.junit.jupiter.api.Test;
-
-import seedu.address.commons.exceptions.IllegalValueException;
-import seedu.address.model.person.Address;
-import seedu.address.model.person.Email;
-import seedu.address.model.person.Name;
-import seedu.address.model.person.Phone;
-
-public class JsonAdaptedPersonTest {
- private static final String INVALID_NAME = "R@chel";
- private static final String INVALID_PHONE = "+651234";
- private static final String INVALID_ADDRESS = " ";
- private static final String INVALID_EMAIL = "example.com";
- private static final String INVALID_TAG = "#friend";
-
- private static final String VALID_NAME = BENSON.getName().toString();
- private static final String VALID_PHONE = BENSON.getPhone().toString();
- private static final String VALID_EMAIL = BENSON.getEmail().toString();
- private static final String VALID_ADDRESS = BENSON.getAddress().toString();
- private static final List VALID_TAGS = BENSON.getTags().stream()
- .map(JsonAdaptedTag::new)
- .collect(Collectors.toList());
-
- @Test
- public void toModelType_validPersonDetails_returnsPerson() throws Exception {
- JsonAdaptedPerson person = new JsonAdaptedPerson(BENSON);
- assertEquals(BENSON, person.toModelType());
- }
-
- @Test
- public void toModelType_invalidName_throwsIllegalValueException() {
- JsonAdaptedPerson person =
- new JsonAdaptedPerson(INVALID_NAME, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS);
- String expectedMessage = Name.MESSAGE_CONSTRAINTS;
- assertThrows(IllegalValueException.class, expectedMessage, person::toModelType);
- }
-
- @Test
- public void toModelType_nullName_throwsIllegalValueException() {
- JsonAdaptedPerson person = new JsonAdaptedPerson(null, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS);
- String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, Name.class.getSimpleName());
- assertThrows(IllegalValueException.class, expectedMessage, person::toModelType);
- }
-
- @Test
- public void toModelType_invalidPhone_throwsIllegalValueException() {
- JsonAdaptedPerson person =
- new JsonAdaptedPerson(VALID_NAME, INVALID_PHONE, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS);
- String expectedMessage = Phone.MESSAGE_CONSTRAINTS;
- assertThrows(IllegalValueException.class, expectedMessage, person::toModelType);
- }
-
- @Test
- public void toModelType_nullPhone_throwsIllegalValueException() {
- JsonAdaptedPerson person = new JsonAdaptedPerson(VALID_NAME, null, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS);
- String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, Phone.class.getSimpleName());
- assertThrows(IllegalValueException.class, expectedMessage, person::toModelType);
- }
-
- @Test
- public void toModelType_invalidEmail_throwsIllegalValueException() {
- JsonAdaptedPerson person =
- new JsonAdaptedPerson(VALID_NAME, VALID_PHONE, INVALID_EMAIL, VALID_ADDRESS, VALID_TAGS);
- String expectedMessage = Email.MESSAGE_CONSTRAINTS;
- assertThrows(IllegalValueException.class, expectedMessage, person::toModelType);
- }
-
- @Test
- public void toModelType_nullEmail_throwsIllegalValueException() {
- JsonAdaptedPerson person = new JsonAdaptedPerson(VALID_NAME, VALID_PHONE, null, VALID_ADDRESS, VALID_TAGS);
- String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, Email.class.getSimpleName());
- assertThrows(IllegalValueException.class, expectedMessage, person::toModelType);
- }
-
- @Test
- public void toModelType_invalidAddress_throwsIllegalValueException() {
- JsonAdaptedPerson person =
- new JsonAdaptedPerson(VALID_NAME, VALID_PHONE, VALID_EMAIL, INVALID_ADDRESS, VALID_TAGS);
- String expectedMessage = Address.MESSAGE_CONSTRAINTS;
- assertThrows(IllegalValueException.class, expectedMessage, person::toModelType);
- }
-
- @Test
- public void toModelType_nullAddress_throwsIllegalValueException() {
- JsonAdaptedPerson person = new JsonAdaptedPerson(VALID_NAME, VALID_PHONE, VALID_EMAIL, null, VALID_TAGS);
- String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, Address.class.getSimpleName());
- assertThrows(IllegalValueException.class, expectedMessage, person::toModelType);
- }
-
- @Test
- public void toModelType_invalidTags_throwsIllegalValueException() {
- List invalidTags = new ArrayList<>(VALID_TAGS);
- invalidTags.add(new JsonAdaptedTag(INVALID_TAG));
- JsonAdaptedPerson person =
- new JsonAdaptedPerson(VALID_NAME, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, invalidTags);
- assertThrows(IllegalValueException.class, person::toModelType);
- }
-
-}
diff --git a/src/test/java/seedu/address/storage/JsonAddressBookStorageTest.java b/src/test/java/seedu/address/storage/JsonAddressBookStorageTest.java
deleted file mode 100644
index ac3c3af9566..00000000000
--- a/src/test/java/seedu/address/storage/JsonAddressBookStorageTest.java
+++ /dev/null
@@ -1,110 +0,0 @@
-package seedu.address.storage;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static seedu.address.testutil.Assert.assertThrows;
-import static seedu.address.testutil.TypicalPersons.ALICE;
-import static seedu.address.testutil.TypicalPersons.HOON;
-import static seedu.address.testutil.TypicalPersons.IDA;
-import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;
-
-import java.io.IOException;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.io.TempDir;
-
-import seedu.address.commons.exceptions.DataConversionException;
-import seedu.address.model.AddressBook;
-import seedu.address.model.ReadOnlyAddressBook;
-
-public class JsonAddressBookStorageTest {
- private static final Path TEST_DATA_FOLDER = Paths.get("src", "test", "data", "JsonAddressBookStorageTest");
-
- @TempDir
- public Path testFolder;
-
- @Test
- public void readAddressBook_nullFilePath_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> readAddressBook(null));
- }
-
- private java.util.Optional readAddressBook(String filePath) throws Exception {
- return new JsonAddressBookStorage(Paths.get(filePath)).readAddressBook(addToTestDataPathIfNotNull(filePath));
- }
-
- private Path addToTestDataPathIfNotNull(String prefsFileInTestDataFolder) {
- return prefsFileInTestDataFolder != null
- ? TEST_DATA_FOLDER.resolve(prefsFileInTestDataFolder)
- : null;
- }
-
- @Test
- public void read_missingFile_emptyResult() throws Exception {
- assertFalse(readAddressBook("NonExistentFile.json").isPresent());
- }
-
- @Test
- public void read_notJsonFormat_exceptionThrown() {
- assertThrows(DataConversionException.class, () -> readAddressBook("notJsonFormatAddressBook.json"));
- }
-
- @Test
- public void readAddressBook_invalidPersonAddressBook_throwDataConversionException() {
- assertThrows(DataConversionException.class, () -> readAddressBook("invalidPersonAddressBook.json"));
- }
-
- @Test
- public void readAddressBook_invalidAndValidPersonAddressBook_throwDataConversionException() {
- assertThrows(DataConversionException.class, () -> readAddressBook("invalidAndValidPersonAddressBook.json"));
- }
-
- @Test
- public void readAndSaveAddressBook_allInOrder_success() throws Exception {
- Path filePath = testFolder.resolve("TempAddressBook.json");
- AddressBook original = getTypicalAddressBook();
- JsonAddressBookStorage jsonAddressBookStorage = new JsonAddressBookStorage(filePath);
-
- // Save in new file and read back
- jsonAddressBookStorage.saveAddressBook(original, filePath);
- ReadOnlyAddressBook readBack = jsonAddressBookStorage.readAddressBook(filePath).get();
- assertEquals(original, new AddressBook(readBack));
-
- // Modify data, overwrite exiting file, and read back
- original.addPerson(HOON);
- original.removePerson(ALICE);
- jsonAddressBookStorage.saveAddressBook(original, filePath);
- readBack = jsonAddressBookStorage.readAddressBook(filePath).get();
- assertEquals(original, new AddressBook(readBack));
-
- // Save and read without specifying file path
- original.addPerson(IDA);
- jsonAddressBookStorage.saveAddressBook(original); // file path not specified
- readBack = jsonAddressBookStorage.readAddressBook().get(); // file path not specified
- assertEquals(original, new AddressBook(readBack));
-
- }
-
- @Test
- public void saveAddressBook_nullAddressBook_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> saveAddressBook(null, "SomeFile.json"));
- }
-
- /**
- * Saves {@code addressBook} at the specified {@code filePath}.
- */
- private void saveAddressBook(ReadOnlyAddressBook addressBook, String filePath) {
- try {
- new JsonAddressBookStorage(Paths.get(filePath))
- .saveAddressBook(addressBook, addToTestDataPathIfNotNull(filePath));
- } catch (IOException ioe) {
- throw new AssertionError("There should not be an error writing to the file.", ioe);
- }
- }
-
- @Test
- public void saveAddressBook_nullFilePath_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> saveAddressBook(new AddressBook(), null));
- }
-}
diff --git a/src/test/java/seedu/address/storage/JsonSerializableAddressBookTest.java b/src/test/java/seedu/address/storage/JsonSerializableAddressBookTest.java
deleted file mode 100644
index 188c9058d20..00000000000
--- a/src/test/java/seedu/address/storage/JsonSerializableAddressBookTest.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package seedu.address.storage;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static seedu.address.testutil.Assert.assertThrows;
-
-import java.nio.file.Path;
-import java.nio.file.Paths;
-
-import org.junit.jupiter.api.Test;
-
-import seedu.address.commons.exceptions.IllegalValueException;
-import seedu.address.commons.util.JsonUtil;
-import seedu.address.model.AddressBook;
-import seedu.address.testutil.TypicalPersons;
-
-public class JsonSerializableAddressBookTest {
-
- private static final Path TEST_DATA_FOLDER = Paths.get("src", "test", "data", "JsonSerializableAddressBookTest");
- private static final Path TYPICAL_PERSONS_FILE = TEST_DATA_FOLDER.resolve("typicalPersonsAddressBook.json");
- private static final Path INVALID_PERSON_FILE = TEST_DATA_FOLDER.resolve("invalidPersonAddressBook.json");
- private static final Path DUPLICATE_PERSON_FILE = TEST_DATA_FOLDER.resolve("duplicatePersonAddressBook.json");
-
- @Test
- public void toModelType_typicalPersonsFile_success() throws Exception {
- JsonSerializableAddressBook dataFromFile = JsonUtil.readJsonFile(TYPICAL_PERSONS_FILE,
- JsonSerializableAddressBook.class).get();
- AddressBook addressBookFromFile = dataFromFile.toModelType();
- AddressBook typicalPersonsAddressBook = TypicalPersons.getTypicalAddressBook();
- assertEquals(addressBookFromFile, typicalPersonsAddressBook);
- }
-
- @Test
- public void toModelType_invalidPersonFile_throwsIllegalValueException() throws Exception {
- JsonSerializableAddressBook dataFromFile = JsonUtil.readJsonFile(INVALID_PERSON_FILE,
- JsonSerializableAddressBook.class).get();
- assertThrows(IllegalValueException.class, dataFromFile::toModelType);
- }
-
- @Test
- public void toModelType_duplicatePersons_throwsIllegalValueException() throws Exception {
- JsonSerializableAddressBook dataFromFile = JsonUtil.readJsonFile(DUPLICATE_PERSON_FILE,
- JsonSerializableAddressBook.class).get();
- assertThrows(IllegalValueException.class, JsonSerializableAddressBook.MESSAGE_DUPLICATE_PERSON,
- dataFromFile::toModelType);
- }
-
-}
diff --git a/src/test/java/seedu/address/testutil/AddressBookBuilder.java b/src/test/java/seedu/address/testutil/AddressBookBuilder.java
deleted file mode 100644
index d53799fd110..00000000000
--- a/src/test/java/seedu/address/testutil/AddressBookBuilder.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package seedu.address.testutil;
-
-import seedu.address.model.AddressBook;
-import seedu.address.model.person.Person;
-
-/**
- * A utility class to help with building Addressbook objects.
- * Example usage:
- * {@code AddressBook ab = new AddressBookBuilder().withPerson("John", "Doe").build();}
- */
-public class AddressBookBuilder {
-
- private AddressBook addressBook;
-
- public AddressBookBuilder() {
- addressBook = new AddressBook();
- }
-
- public AddressBookBuilder(AddressBook addressBook) {
- this.addressBook = addressBook;
- }
-
- /**
- * Adds a new {@code Person} to the {@code AddressBook} that we are building.
- */
- public AddressBookBuilder withPerson(Person person) {
- addressBook.addPerson(person);
- return this;
- }
-
- public AddressBook build() {
- return addressBook;
- }
-}
diff --git a/src/test/java/seedu/address/testutil/EditPersonDescriptorBuilder.java b/src/test/java/seedu/address/testutil/EditPersonDescriptorBuilder.java
deleted file mode 100644
index 4584bd5044e..00000000000
--- a/src/test/java/seedu/address/testutil/EditPersonDescriptorBuilder.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package seedu.address.testutil;
-
-import java.util.Set;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import seedu.address.logic.commands.EditCommand.EditPersonDescriptor;
-import seedu.address.model.person.Address;
-import seedu.address.model.person.Email;
-import seedu.address.model.person.Name;
-import seedu.address.model.person.Person;
-import seedu.address.model.person.Phone;
-import seedu.address.model.tag.Tag;
-
-/**
- * A utility class to help with building EditPersonDescriptor objects.
- */
-public class EditPersonDescriptorBuilder {
-
- private EditPersonDescriptor descriptor;
-
- public EditPersonDescriptorBuilder() {
- descriptor = new EditPersonDescriptor();
- }
-
- public EditPersonDescriptorBuilder(EditPersonDescriptor descriptor) {
- this.descriptor = new EditPersonDescriptor(descriptor);
- }
-
- /**
- * Returns an {@code EditPersonDescriptor} with fields containing {@code person}'s details
- */
- public EditPersonDescriptorBuilder(Person person) {
- descriptor = new EditPersonDescriptor();
- descriptor.setName(person.getName());
- descriptor.setPhone(person.getPhone());
- descriptor.setEmail(person.getEmail());
- descriptor.setAddress(person.getAddress());
- descriptor.setTags(person.getTags());
- }
-
- /**
- * Sets the {@code Name} of the {@code EditPersonDescriptor} that we are building.
- */
- public EditPersonDescriptorBuilder withName(String name) {
- descriptor.setName(new Name(name));
- return this;
- }
-
- /**
- * Sets the {@code Phone} of the {@code EditPersonDescriptor} that we are building.
- */
- public EditPersonDescriptorBuilder withPhone(String phone) {
- descriptor.setPhone(new Phone(phone));
- return this;
- }
-
- /**
- * Sets the {@code Email} of the {@code EditPersonDescriptor} that we are building.
- */
- public EditPersonDescriptorBuilder withEmail(String email) {
- descriptor.setEmail(new Email(email));
- return this;
- }
-
- /**
- * Sets the {@code Address} of the {@code EditPersonDescriptor} that we are building.
- */
- public EditPersonDescriptorBuilder withAddress(String address) {
- descriptor.setAddress(new Address(address));
- return this;
- }
-
- /**
- * Parses the {@code tags} into a {@code Set} and set it to the {@code EditPersonDescriptor}
- * that we are building.
- */
- public EditPersonDescriptorBuilder withTags(String... tags) {
- Set tagSet = Stream.of(tags).map(Tag::new).collect(Collectors.toSet());
- descriptor.setTags(tagSet);
- return this;
- }
-
- public EditPersonDescriptor build() {
- return descriptor;
- }
-}
diff --git a/src/test/java/seedu/address/testutil/PersonBuilder.java b/src/test/java/seedu/address/testutil/PersonBuilder.java
deleted file mode 100644
index 6be381d39ba..00000000000
--- a/src/test/java/seedu/address/testutil/PersonBuilder.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package seedu.address.testutil;
-
-import java.util.HashSet;
-import java.util.Set;
-
-import seedu.address.model.person.Address;
-import seedu.address.model.person.Email;
-import seedu.address.model.person.Name;
-import seedu.address.model.person.Person;
-import seedu.address.model.person.Phone;
-import seedu.address.model.tag.Tag;
-import seedu.address.model.util.SampleDataUtil;
-
-/**
- * A utility class to help with building Person objects.
- */
-public class PersonBuilder {
-
- public static final String DEFAULT_NAME = "Amy Bee";
- public static final String DEFAULT_PHONE = "85355255";
- public static final String DEFAULT_EMAIL = "amy@gmail.com";
- public static final String DEFAULT_ADDRESS = "123, Jurong West Ave 6, #08-111";
-
- private Name name;
- private Phone phone;
- private Email email;
- private Address address;
- private Set tags;
-
- /**
- * Creates a {@code PersonBuilder} with the default details.
- */
- public PersonBuilder() {
- name = new Name(DEFAULT_NAME);
- phone = new Phone(DEFAULT_PHONE);
- email = new Email(DEFAULT_EMAIL);
- address = new Address(DEFAULT_ADDRESS);
- tags = new HashSet<>();
- }
-
- /**
- * Initializes the PersonBuilder with the data of {@code personToCopy}.
- */
- public PersonBuilder(Person personToCopy) {
- name = personToCopy.getName();
- phone = personToCopy.getPhone();
- email = personToCopy.getEmail();
- address = personToCopy.getAddress();
- tags = new HashSet<>(personToCopy.getTags());
- }
-
- /**
- * Sets the {@code Name} of the {@code Person} that we are building.
- */
- public PersonBuilder withName(String name) {
- this.name = new Name(name);
- return this;
- }
-
- /**
- * Parses the {@code tags} into a {@code Set} and set it to the {@code Person} that we are building.
- */
- public PersonBuilder withTags(String ... tags) {
- this.tags = SampleDataUtil.getTagSet(tags);
- return this;
- }
-
- /**
- * Sets the {@code Address} of the {@code Person} that we are building.
- */
- public PersonBuilder withAddress(String address) {
- this.address = new Address(address);
- return this;
- }
-
- /**
- * Sets the {@code Phone} of the {@code Person} that we are building.
- */
- public PersonBuilder withPhone(String phone) {
- this.phone = new Phone(phone);
- return this;
- }
-
- /**
- * Sets the {@code Email} of the {@code Person} that we are building.
- */
- public PersonBuilder withEmail(String email) {
- this.email = new Email(email);
- return this;
- }
-
- public Person build() {
- return new Person(name, phone, email, address, tags);
- }
-
-}
diff --git a/src/test/java/seedu/address/testutil/PersonUtil.java b/src/test/java/seedu/address/testutil/PersonUtil.java
deleted file mode 100644
index 90849945183..00000000000
--- a/src/test/java/seedu/address/testutil/PersonUtil.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package seedu.address.testutil;
-
-import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
-
-import java.util.Set;
-
-import seedu.address.logic.commands.AddCommand;
-import seedu.address.logic.commands.EditCommand.EditPersonDescriptor;
-import seedu.address.model.person.Person;
-import seedu.address.model.tag.Tag;
-
-/**
- * A utility class for Person.
- */
-public class PersonUtil {
-
- /**
- * Returns an add command string for adding the {@code person}.
- */
- public static String getAddCommand(Person person) {
- return AddCommand.COMMAND_WORD + " " + getPersonDetails(person);
- }
-
- /**
- * Returns the part of command string for the given {@code person}'s details.
- */
- public static String getPersonDetails(Person person) {
- StringBuilder sb = new StringBuilder();
- sb.append(PREFIX_NAME + person.getName().fullName + " ");
- sb.append(PREFIX_PHONE + person.getPhone().value + " ");
- sb.append(PREFIX_EMAIL + person.getEmail().value + " ");
- sb.append(PREFIX_ADDRESS + person.getAddress().value + " ");
- person.getTags().stream().forEach(
- s -> sb.append(PREFIX_TAG + s.tagName + " ")
- );
- return sb.toString();
- }
-
- /**
- * Returns the part of command string for the given {@code EditPersonDescriptor}'s details.
- */
- public static String getEditPersonDescriptorDetails(EditPersonDescriptor descriptor) {
- StringBuilder sb = new StringBuilder();
- descriptor.getName().ifPresent(name -> sb.append(PREFIX_NAME).append(name.fullName).append(" "));
- descriptor.getPhone().ifPresent(phone -> sb.append(PREFIX_PHONE).append(phone.value).append(" "));
- descriptor.getEmail().ifPresent(email -> sb.append(PREFIX_EMAIL).append(email.value).append(" "));
- descriptor.getAddress().ifPresent(address -> sb.append(PREFIX_ADDRESS).append(address.value).append(" "));
- if (descriptor.getTags().isPresent()) {
- Set tags = descriptor.getTags().get();
- if (tags.isEmpty()) {
- sb.append(PREFIX_TAG);
- } else {
- tags.forEach(s -> sb.append(PREFIX_TAG).append(s.tagName).append(" "));
- }
- }
- return sb.toString();
- }
-}
diff --git a/src/test/java/seedu/address/testutil/TypicalPersons.java b/src/test/java/seedu/address/testutil/TypicalPersons.java
deleted file mode 100644
index fec76fb7129..00000000000
--- a/src/test/java/seedu/address/testutil/TypicalPersons.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package seedu.address.testutil;
-
-import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_FRIEND;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import seedu.address.model.AddressBook;
-import seedu.address.model.person.Person;
-
-/**
- * A utility class containing a list of {@code Person} objects to be used in tests.
- */
-public class TypicalPersons {
-
- public static final Person ALICE = new PersonBuilder().withName("Alice Pauline")
- .withAddress("123, Jurong West Ave 6, #08-111").withEmail("alice@example.com")
- .withPhone("94351253")
- .withTags("friends").build();
- public static final Person BENSON = new PersonBuilder().withName("Benson Meier")
- .withAddress("311, Clementi Ave 2, #02-25")
- .withEmail("johnd@example.com").withPhone("98765432")
- .withTags("owesMoney", "friends").build();
- public static final Person CARL = new PersonBuilder().withName("Carl Kurz").withPhone("95352563")
- .withEmail("heinz@example.com").withAddress("wall street").build();
- public static final Person DANIEL = new PersonBuilder().withName("Daniel Meier").withPhone("87652533")
- .withEmail("cornelia@example.com").withAddress("10th street").withTags("friends").build();
- public static final Person ELLE = new PersonBuilder().withName("Elle Meyer").withPhone("9482224")
- .withEmail("werner@example.com").withAddress("michegan ave").build();
- public static final Person FIONA = new PersonBuilder().withName("Fiona Kunz").withPhone("9482427")
- .withEmail("lydia@example.com").withAddress("little tokyo").build();
- public static final Person GEORGE = new PersonBuilder().withName("George Best").withPhone("9482442")
- .withEmail("anna@example.com").withAddress("4th street").build();
-
- // Manually added
- public static final Person HOON = new PersonBuilder().withName("Hoon Meier").withPhone("8482424")
- .withEmail("stefan@example.com").withAddress("little india").build();
- public static final Person IDA = new PersonBuilder().withName("Ida Mueller").withPhone("8482131")
- .withEmail("hans@example.com").withAddress("chicago ave").build();
-
- // Manually added - Person's details found in {@code CommandTestUtil}
- public static final Person AMY = new PersonBuilder().withName(VALID_NAME_AMY).withPhone(VALID_PHONE_AMY)
- .withEmail(VALID_EMAIL_AMY).withAddress(VALID_ADDRESS_AMY).withTags(VALID_TAG_FRIEND).build();
- public static final Person BOB = new PersonBuilder().withName(VALID_NAME_BOB).withPhone(VALID_PHONE_BOB)
- .withEmail(VALID_EMAIL_BOB).withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND, VALID_TAG_FRIEND)
- .build();
-
- public static final String KEYWORD_MATCHING_MEIER = "Meier"; // A keyword that matches MEIER
-
- private TypicalPersons() {} // prevents instantiation
-
- /**
- * Returns an {@code AddressBook} with all the typical persons.
- */
- public static AddressBook getTypicalAddressBook() {
- AddressBook ab = new AddressBook();
- for (Person person : getTypicalPersons()) {
- ab.addPerson(person);
- }
- return ab;
- }
-
- public static List getTypicalPersons() {
- return new ArrayList<>(Arrays.asList(ALICE, BENSON, CARL, DANIEL, ELLE, FIONA, GEORGE));
- }
-}
diff --git a/src/test/java/seedu/address/AppParametersTest.java b/src/test/java/seedu/medinfo/AppParametersTest.java
similarity index 98%
rename from src/test/java/seedu/address/AppParametersTest.java
rename to src/test/java/seedu/medinfo/AppParametersTest.java
index 61326b2d31a..73ab6eeff15 100644
--- a/src/test/java/seedu/address/AppParametersTest.java
+++ b/src/test/java/seedu/medinfo/AppParametersTest.java
@@ -1,4 +1,4 @@
-package seedu.address;
+package seedu.medinfo;
import static org.junit.jupiter.api.Assertions.assertEquals;
diff --git a/src/test/java/seedu/address/commons/core/ConfigTest.java b/src/test/java/seedu/medinfo/commons/core/ConfigTest.java
similarity index 95%
rename from src/test/java/seedu/address/commons/core/ConfigTest.java
rename to src/test/java/seedu/medinfo/commons/core/ConfigTest.java
index 07cd7f73d53..34a479ed5ab 100644
--- a/src/test/java/seedu/address/commons/core/ConfigTest.java
+++ b/src/test/java/seedu/medinfo/commons/core/ConfigTest.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.core;
+package seedu.medinfo.commons.core;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
diff --git a/src/test/java/seedu/address/commons/core/VersionTest.java b/src/test/java/seedu/medinfo/commons/core/VersionTest.java
similarity index 98%
rename from src/test/java/seedu/address/commons/core/VersionTest.java
rename to src/test/java/seedu/medinfo/commons/core/VersionTest.java
index 495cd231554..1cafa397274 100644
--- a/src/test/java/seedu/address/commons/core/VersionTest.java
+++ b/src/test/java/seedu/medinfo/commons/core/VersionTest.java
@@ -1,8 +1,8 @@
-package seedu.address.commons.core;
+package seedu.medinfo.commons.core;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.testutil.Assert.assertThrows;
+import static seedu.medinfo.testutil.Assert.assertThrows;
import org.junit.jupiter.api.Test;
diff --git a/src/test/java/seedu/address/commons/core/index/IndexTest.java b/src/test/java/seedu/medinfo/commons/core/index/IndexTest.java
similarity index 95%
rename from src/test/java/seedu/address/commons/core/index/IndexTest.java
rename to src/test/java/seedu/medinfo/commons/core/index/IndexTest.java
index a3ec6f8e747..23701dd97fc 100644
--- a/src/test/java/seedu/address/commons/core/index/IndexTest.java
+++ b/src/test/java/seedu/medinfo/commons/core/index/IndexTest.java
@@ -1,9 +1,9 @@
-package seedu.address.commons.core.index;
+package seedu.medinfo.commons.core.index;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.testutil.Assert.assertThrows;
+import static seedu.medinfo.testutil.Assert.assertThrows;
import org.junit.jupiter.api.Test;
diff --git a/src/test/java/seedu/address/commons/util/AppUtilTest.java b/src/test/java/seedu/medinfo/commons/util/AppUtilTest.java
similarity index 85%
rename from src/test/java/seedu/address/commons/util/AppUtilTest.java
rename to src/test/java/seedu/medinfo/commons/util/AppUtilTest.java
index 594de1e6365..d4bce6f6093 100644
--- a/src/test/java/seedu/address/commons/util/AppUtilTest.java
+++ b/src/test/java/seedu/medinfo/commons/util/AppUtilTest.java
@@ -1,7 +1,7 @@
-package seedu.address.commons.util;
+package seedu.medinfo.commons.util;
import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static seedu.address.testutil.Assert.assertThrows;
+import static seedu.medinfo.testutil.Assert.assertThrows;
import org.junit.jupiter.api.Test;
@@ -9,7 +9,7 @@ public class AppUtilTest {
@Test
public void getImage_exitingImage() {
- assertNotNull(AppUtil.getImage("/images/address_book_32.png"));
+ assertNotNull(AppUtil.getImage("/images/MedInfo.png"));
}
@Test
diff --git a/src/test/java/seedu/address/commons/util/CollectionUtilTest.java b/src/test/java/seedu/medinfo/commons/util/CollectionUtilTest.java
similarity index 96%
rename from src/test/java/seedu/address/commons/util/CollectionUtilTest.java
rename to src/test/java/seedu/medinfo/commons/util/CollectionUtilTest.java
index b467a3dc025..4740d955449 100644
--- a/src/test/java/seedu/address/commons/util/CollectionUtilTest.java
+++ b/src/test/java/seedu/medinfo/commons/util/CollectionUtilTest.java
@@ -1,9 +1,9 @@
-package seedu.address.commons.util;
+package seedu.medinfo.commons.util;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
-import static seedu.address.testutil.Assert.assertThrows;
+import static seedu.medinfo.commons.util.CollectionUtil.requireAllNonNull;
+import static seedu.medinfo.testutil.Assert.assertThrows;
import java.util.Arrays;
import java.util.Collection;
diff --git a/src/test/java/seedu/address/commons/util/ConfigUtilTest.java b/src/test/java/seedu/medinfo/commons/util/ConfigUtilTest.java
similarity index 94%
rename from src/test/java/seedu/address/commons/util/ConfigUtilTest.java
rename to src/test/java/seedu/medinfo/commons/util/ConfigUtilTest.java
index d2ab2839a52..6736099fc00 100644
--- a/src/test/java/seedu/address/commons/util/ConfigUtilTest.java
+++ b/src/test/java/seedu/medinfo/commons/util/ConfigUtilTest.java
@@ -1,8 +1,8 @@
-package seedu.address.commons.util;
+package seedu.medinfo.commons.util;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
-import static seedu.address.testutil.Assert.assertThrows;
+import static seedu.medinfo.testutil.Assert.assertThrows;
import java.io.IOException;
import java.nio.file.Path;
@@ -13,8 +13,8 @@
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
-import seedu.address.commons.core.Config;
-import seedu.address.commons.exceptions.DataConversionException;
+import seedu.medinfo.commons.core.Config;
+import seedu.medinfo.commons.exceptions.DataConversionException;
public class ConfigUtilTest {
diff --git a/src/test/java/seedu/address/commons/util/FileUtilTest.java b/src/test/java/seedu/medinfo/commons/util/FileUtilTest.java
similarity index 84%
rename from src/test/java/seedu/address/commons/util/FileUtilTest.java
rename to src/test/java/seedu/medinfo/commons/util/FileUtilTest.java
index 1fe5478c756..c88af715181 100644
--- a/src/test/java/seedu/address/commons/util/FileUtilTest.java
+++ b/src/test/java/seedu/medinfo/commons/util/FileUtilTest.java
@@ -1,8 +1,8 @@
-package seedu.address.commons.util;
+package seedu.medinfo.commons.util;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.testutil.Assert.assertThrows;
+import static seedu.medinfo.testutil.Assert.assertThrows;
import org.junit.jupiter.api.Test;
diff --git a/src/test/java/seedu/address/commons/util/JsonUtilTest.java b/src/test/java/seedu/medinfo/commons/util/JsonUtilTest.java
similarity index 84%
rename from src/test/java/seedu/address/commons/util/JsonUtilTest.java
rename to src/test/java/seedu/medinfo/commons/util/JsonUtilTest.java
index d4907539dee..c6285b47997 100644
--- a/src/test/java/seedu/address/commons/util/JsonUtilTest.java
+++ b/src/test/java/seedu/medinfo/commons/util/JsonUtilTest.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.util;
+package seedu.medinfo.commons.util;
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -7,8 +7,8 @@
import org.junit.jupiter.api.Test;
-import seedu.address.testutil.SerializableTestClass;
-import seedu.address.testutil.TestUtil;
+import seedu.medinfo.testutil.SerializableTestClass;
+import seedu.medinfo.testutil.TestUtil;
/**
* Tests JSON Read and Write
@@ -39,7 +39,4 @@ public void deserializeObjectFromJsonFile_noExceptionThrown() throws IOException
assertEquals(serializableTestClass.getMapOfIntegerToString(), SerializableTestClass.getHashMapTestValues());
}
- //TODO: @Test jsonUtil_readJsonStringToObjectInstance_correctObject()
-
- //TODO: @Test jsonUtil_writeThenReadObjectToJson_correctObject()
}
diff --git a/src/test/java/seedu/address/commons/util/StringUtilTest.java b/src/test/java/seedu/medinfo/commons/util/StringUtilTest.java
similarity index 98%
rename from src/test/java/seedu/address/commons/util/StringUtilTest.java
rename to src/test/java/seedu/medinfo/commons/util/StringUtilTest.java
index c56d407bf3f..8e203c6c641 100644
--- a/src/test/java/seedu/address/commons/util/StringUtilTest.java
+++ b/src/test/java/seedu/medinfo/commons/util/StringUtilTest.java
@@ -1,8 +1,8 @@
-package seedu.address.commons.util;
+package seedu.medinfo.commons.util;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.testutil.Assert.assertThrows;
+import static seedu.medinfo.testutil.Assert.assertThrows;
import java.io.FileNotFoundException;
diff --git a/src/test/java/seedu/address/logic/LogicManagerTest.java b/src/test/java/seedu/medinfo/logic/LogicManagerTest.java
similarity index 51%
rename from src/test/java/seedu/address/logic/LogicManagerTest.java
rename to src/test/java/seedu/medinfo/logic/LogicManagerTest.java
index ad923ac249a..3cdf75d6580 100644
--- a/src/test/java/seedu/address/logic/LogicManagerTest.java
+++ b/src/test/java/seedu/medinfo/logic/LogicManagerTest.java
@@ -1,14 +1,9 @@
-package seedu.address.logic;
+package seedu.medinfo.logic;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static seedu.address.commons.core.Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX;
-import static seedu.address.commons.core.Messages.MESSAGE_UNKNOWN_COMMAND;
-import static seedu.address.logic.commands.CommandTestUtil.ADDRESS_DESC_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.EMAIL_DESC_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.NAME_DESC_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.PHONE_DESC_AMY;
-import static seedu.address.testutil.Assert.assertThrows;
-import static seedu.address.testutil.TypicalPersons.AMY;
+import static seedu.medinfo.commons.core.Messages.MESSAGE_ALL_PATIENTS_LISTED_OVERVIEW;
+import static seedu.medinfo.commons.core.Messages.MESSAGE_UNKNOWN_COMMAND;
+import static seedu.medinfo.testutil.Assert.assertThrows;
import java.io.IOException;
import java.nio.file.Path;
@@ -17,20 +12,17 @@
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
-import seedu.address.logic.commands.AddCommand;
-import seedu.address.logic.commands.CommandResult;
-import seedu.address.logic.commands.ListCommand;
-import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.logic.parser.exceptions.ParseException;
-import seedu.address.model.Model;
-import seedu.address.model.ModelManager;
-import seedu.address.model.ReadOnlyAddressBook;
-import seedu.address.model.UserPrefs;
-import seedu.address.model.person.Person;
-import seedu.address.storage.JsonAddressBookStorage;
-import seedu.address.storage.JsonUserPrefsStorage;
-import seedu.address.storage.StorageManager;
-import seedu.address.testutil.PersonBuilder;
+import seedu.medinfo.logic.commands.CommandResult;
+import seedu.medinfo.logic.commands.ListCommand;
+import seedu.medinfo.logic.commands.exceptions.CommandException;
+import seedu.medinfo.logic.parser.exceptions.ParseException;
+import seedu.medinfo.model.Model;
+import seedu.medinfo.model.ModelManager;
+import seedu.medinfo.model.ReadOnlyMedInfo;
+import seedu.medinfo.model.UserPrefs;
+import seedu.medinfo.storage.JsonMedInfoStorage;
+import seedu.medinfo.storage.JsonUserPrefsStorage;
+import seedu.medinfo.storage.StorageManager;
public class LogicManagerTest {
private static final IOException DUMMY_IO_EXCEPTION = new IOException("dummy exception");
@@ -43,10 +35,10 @@ public class LogicManagerTest {
@BeforeEach
public void setUp() {
- JsonAddressBookStorage addressBookStorage =
- new JsonAddressBookStorage(temporaryFolder.resolve("addressBook.json"));
+ JsonMedInfoStorage medInfoStorage = new JsonMedInfoStorage(
+ temporaryFolder.resolve("medinfo.json"));
JsonUserPrefsStorage userPrefsStorage = new JsonUserPrefsStorage(temporaryFolder.resolve("userPrefs.json"));
- StorageManager storage = new StorageManager(addressBookStorage, userPrefsStorage);
+ StorageManager storage = new StorageManager(medInfoStorage, userPrefsStorage);
logic = new LogicManager(model, storage);
}
@@ -56,48 +48,25 @@ public void execute_invalidCommandFormat_throwsParseException() {
assertParseException(invalidCommand, MESSAGE_UNKNOWN_COMMAND);
}
- @Test
- public void execute_commandExecutionError_throwsCommandException() {
- String deleteCommand = "delete 9";
- assertCommandException(deleteCommand, MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
- }
-
@Test
public void execute_validCommand_success() throws Exception {
+ String expectedMessage = String.format(MESSAGE_ALL_PATIENTS_LISTED_OVERVIEW, 0);
String listCommand = ListCommand.COMMAND_WORD;
- assertCommandSuccess(listCommand, ListCommand.MESSAGE_SUCCESS, model);
- }
-
- @Test
- public void execute_storageThrowsIoException_throwsCommandException() {
- // Setup LogicManager with JsonAddressBookIoExceptionThrowingStub
- JsonAddressBookStorage addressBookStorage =
- new JsonAddressBookIoExceptionThrowingStub(temporaryFolder.resolve("ioExceptionAddressBook.json"));
- JsonUserPrefsStorage userPrefsStorage =
- new JsonUserPrefsStorage(temporaryFolder.resolve("ioExceptionUserPrefs.json"));
- StorageManager storage = new StorageManager(addressBookStorage, userPrefsStorage);
- logic = new LogicManager(model, storage);
-
- // Execute add command
- String addCommand = AddCommand.COMMAND_WORD + NAME_DESC_AMY + PHONE_DESC_AMY + EMAIL_DESC_AMY
- + ADDRESS_DESC_AMY;
- Person expectedPerson = new PersonBuilder(AMY).withTags().build();
- ModelManager expectedModel = new ModelManager();
- expectedModel.addPerson(expectedPerson);
- String expectedMessage = LogicManager.FILE_OPS_ERROR_MESSAGE + DUMMY_IO_EXCEPTION;
- assertCommandFailure(addCommand, CommandException.class, expectedMessage, expectedModel);
+ assertCommandSuccess(listCommand, expectedMessage, model);
}
@Test
public void getFilteredPersonList_modifyList_throwsUnsupportedOperationException() {
- assertThrows(UnsupportedOperationException.class, () -> logic.getFilteredPersonList().remove(0));
+ assertThrows(UnsupportedOperationException.class, () -> logic.getFilteredPatientList().remove(0));
}
/**
* Executes the command and confirms that
* - no exceptions are thrown
* - the feedback message is equal to {@code expectedMessage}
- * - the internal model manager state is the same as that in {@code expectedModel}
+ * - the internal model manager state is the same as that in
+ * {@code expectedModel}
+ *
* @see #assertCommandFailure(String, Class, String, Model)
*/
private void assertCommandSuccess(String inputCommand, String expectedMessage,
@@ -108,7 +77,9 @@ private void assertCommandSuccess(String inputCommand, String expectedMessage,
}
/**
- * Executes the command, confirms that a ParseException is thrown and that the result message is correct.
+ * Executes the command, confirms that a ParseException is thrown and that the
+ * result message is correct.
+ *
* @see #assertCommandFailure(String, Class, String, Model)
*/
private void assertParseException(String inputCommand, String expectedMessage) {
@@ -116,7 +87,9 @@ private void assertParseException(String inputCommand, String expectedMessage) {
}
/**
- * Executes the command, confirms that a CommandException is thrown and that the result message is correct.
+ * Executes the command, confirms that a CommandException is thrown and that the
+ * result message is correct.
+ *
* @see #assertCommandFailure(String, Class, String, Model)
*/
private void assertCommandException(String inputCommand, String expectedMessage) {
@@ -124,12 +97,14 @@ private void assertCommandException(String inputCommand, String expectedMessage)
}
/**
- * Executes the command, confirms that the exception is thrown and that the result message is correct.
+ * Executes the command, confirms that the exception is thrown and that the
+ * result message is correct.
+ *
* @see #assertCommandFailure(String, Class, String, Model)
*/
private void assertCommandFailure(String inputCommand, Class extends Throwable> expectedException,
String expectedMessage) {
- Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs());
+ Model expectedModel = new ModelManager(model.getMedInfo(), new UserPrefs());
assertCommandFailure(inputCommand, expectedException, expectedMessage, expectedModel);
}
@@ -137,7 +112,9 @@ private void assertCommandFailure(String inputCommand, Class extends Throwable
* Executes the command and confirms that
* - the {@code expectedException} is thrown
* - the resulting error message is equal to {@code expectedMessage}
- * - the internal model manager state is the same as that in {@code expectedModel}
+ * - the internal model manager state is the same as that in
+ * {@code expectedModel}
+ *
* @see #assertCommandSuccess(String, String, Model)
*/
private void assertCommandFailure(String inputCommand, Class extends Throwable> expectedException,
@@ -149,13 +126,13 @@ private void assertCommandFailure(String inputCommand, Class extends Throwable
/**
* A stub class to throw an {@code IOException} when the save method is called.
*/
- private static class JsonAddressBookIoExceptionThrowingStub extends JsonAddressBookStorage {
- private JsonAddressBookIoExceptionThrowingStub(Path filePath) {
+ private static class JsonMedInfoIoExceptionThrowingStub extends JsonMedInfoStorage {
+ private JsonMedInfoIoExceptionThrowingStub(Path filePath) {
super(filePath);
}
@Override
- public void saveAddressBook(ReadOnlyAddressBook addressBook, Path filePath) throws IOException {
+ public void saveMedInfo(ReadOnlyMedInfo medInfo, Path filePath) throws IOException {
throw DUMMY_IO_EXCEPTION;
}
}
diff --git a/src/test/java/seedu/medinfo/logic/commands/AddCommandIntegrationTest.java b/src/test/java/seedu/medinfo/logic/commands/AddCommandIntegrationTest.java
new file mode 100644
index 00000000000..48e83b090b9
--- /dev/null
+++ b/src/test/java/seedu/medinfo/logic/commands/AddCommandIntegrationTest.java
@@ -0,0 +1,23 @@
+package seedu.medinfo.logic.commands;
+
+import static seedu.medinfo.testutil.TypicalPatients.getTypicalMedInfo;
+
+import org.junit.jupiter.api.BeforeEach;
+
+import seedu.medinfo.model.Model;
+import seedu.medinfo.model.ModelManager;
+import seedu.medinfo.model.UserPrefs;
+
+/**
+ * Contains integration tests (interaction with the Model) for {@code AddCommand}.
+ */
+public class AddCommandIntegrationTest {
+
+ private Model model;
+
+ @BeforeEach
+ public void setUp() {
+ model = new ModelManager(getTypicalMedInfo(), new UserPrefs());
+ }
+
+}
diff --git a/src/test/java/seedu/medinfo/logic/commands/AddCommandTest.java b/src/test/java/seedu/medinfo/logic/commands/AddCommandTest.java
new file mode 100644
index 00000000000..b8e68315674
--- /dev/null
+++ b/src/test/java/seedu/medinfo/logic/commands/AddCommandTest.java
@@ -0,0 +1,253 @@
+package seedu.medinfo.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.medinfo.testutil.Assert.assertThrows;
+
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+import java.util.function.Predicate;
+
+import org.junit.jupiter.api.Test;
+
+import javafx.collections.ObservableList;
+import seedu.medinfo.commons.core.GuiSettings;
+import seedu.medinfo.logic.commands.exceptions.CommandException;
+import seedu.medinfo.model.MedInfo;
+import seedu.medinfo.model.Model;
+import seedu.medinfo.model.ReadOnlyMedInfo;
+import seedu.medinfo.model.ReadOnlyUserPrefs;
+import seedu.medinfo.model.patient.Patient;
+import seedu.medinfo.model.ward.Ward;
+import seedu.medinfo.testutil.PatientBuilder;
+
+public class AddCommandTest {
+
+ @Test
+ public void constructor_nullPerson_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> new AddCommand(null));
+ }
+
+ @Test
+ public void execute_personAcceptedByModel_addSuccessful() throws Exception {
+ ModelStubAcceptingPersonAdded modelStub = new ModelStubAcceptingPersonAdded();
+ Patient validPatient = new PatientBuilder().build();
+
+ CommandResult commandResult = new AddCommand(validPatient).execute(modelStub);
+
+ assertEquals(String.format(AddCommand.MESSAGE_SUCCESS, validPatient), commandResult.getFeedbackToUser());
+ assertEquals(Arrays.asList(validPatient), modelStub.personsAdded);
+ }
+
+ @Test
+ public void execute_duplicatePerson_throwsCommandException() {
+ Patient validPatient = new PatientBuilder().build();
+ AddCommand addCommand = new AddCommand(validPatient);
+ ModelStub modelStub = new ModelStubWithPerson(validPatient);
+
+ assertThrows(CommandException.class, AddCommand.MESSAGE_DUPLICATE_PATIENT, () -> addCommand.execute(modelStub));
+ }
+
+ @Test
+ public void equals() {
+ Patient alice = new PatientBuilder().withName("Alice").build();
+ Patient bob = new PatientBuilder().withName("Bob").build();
+ AddCommand addAliceCommand = new AddCommand(alice);
+ AddCommand addBobCommand = new AddCommand(bob);
+
+ // same object -> returns true
+ assertTrue(addAliceCommand.equals(addAliceCommand));
+
+ // same values -> returns true
+ AddCommand addAliceCommandCopy = new AddCommand(alice);
+ assertTrue(addAliceCommand.equals(addAliceCommandCopy));
+
+ // different types -> returns false
+ assertFalse(addAliceCommand.equals(1));
+
+ // null -> returns false
+ assertFalse(addAliceCommand.equals(null));
+
+ // different patient -> returns false
+ assertFalse(addAliceCommand.equals(addBobCommand));
+ }
+
+ /**
+ * A default model stub that have all of the methods failing.
+ */
+ private class ModelStub implements Model {
+ @Override
+ public void setUserPrefs(ReadOnlyUserPrefs userPrefs) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public ReadOnlyUserPrefs getUserPrefs() {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public GuiSettings getGuiSettings() {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void setGuiSettings(GuiSettings guiSettings) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public Path getMedInfoFilePath() {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void setMedInfoFilePath(Path medInfoFilePath) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ //// Patient methods ==========================================================================================
+ @Override
+ public void addPatient(Patient patient) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void setMedInfo(ReadOnlyMedInfo newData) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public ReadOnlyMedInfo getMedInfo() {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public boolean hasPatient(Patient patient) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public boolean hasPatientNric(Patient patient) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void deletePatient(Patient target) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void setPatient(Patient target, Patient editedPatient) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void sortPatients(Comparator comparator) {}
+
+ @Override
+ public ObservableList getFilteredPatientList() {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void updateFilteredPatientList(Predicate predicate) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ //// Ward methods ==========================================================================================
+ @Override
+ public void addWard(Ward ward) {
+ throw new AssertionError("This method should not be called.");
+ }
+ @Override
+ public boolean hasWard(Ward ward) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void deleteWard(Ward target) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void setWard(Ward target, Ward editedWard) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public ObservableList getFilteredWardList() {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void updateFilteredWardList(Predicate predicate) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public List getStatsInfo() {
+ throw new AssertionError("This method should not be called.");
+ }
+ }
+
+ /**
+ * A Model stub that contains a single patient.
+ */
+ private class ModelStubWithPerson extends ModelStub {
+ private final Patient patient;
+
+ ModelStubWithPerson(Patient patient) {
+ requireNonNull(patient);
+ this.patient = patient;
+ }
+
+ @Override
+ public boolean hasPatient(Patient patient) {
+ requireNonNull(patient);
+ return this.patient.isSamePatient(patient);
+ }
+
+ @Override
+ public boolean hasPatientNric(Patient patient) {
+ requireNonNull(patient);
+ return this.patient.isSameNric(patient);
+ }
+ }
+
+ /**
+ * A Model stub that always accept the patient being added.
+ */
+ private class ModelStubAcceptingPersonAdded extends ModelStub {
+ final ArrayList personsAdded = new ArrayList<>();
+
+ @Override
+ public boolean hasPatient(Patient patient) {
+ requireNonNull(patient);
+ return personsAdded.stream().anyMatch(patient::isSamePatient);
+ }
+
+ @Override
+ public boolean hasPatientNric(Patient patient) {
+ requireNonNull(patient);
+ return personsAdded.stream().anyMatch(patient::isSameNric);
+ }
+
+ @Override
+ public void addPatient(Patient patient) {
+ requireNonNull(patient);
+ personsAdded.add(patient);
+ }
+
+ @Override
+ public ReadOnlyMedInfo getMedInfo() {
+ return new MedInfo();
+ }
+ }
+
+}
diff --git a/src/test/java/seedu/medinfo/logic/commands/ClearCommandTest.java b/src/test/java/seedu/medinfo/logic/commands/ClearCommandTest.java
new file mode 100644
index 00000000000..c5ab8cfe45a
--- /dev/null
+++ b/src/test/java/seedu/medinfo/logic/commands/ClearCommandTest.java
@@ -0,0 +1,19 @@
+package seedu.medinfo.logic.commands;
+
+import static seedu.medinfo.logic.commands.CommandTestUtil.assertCommandSuccess;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.medinfo.model.Model;
+import seedu.medinfo.model.ModelManager;
+
+public class ClearCommandTest {
+
+ @Test
+ public void execute_emptyMedInfo_success() {
+ Model model = new ModelManager();
+ Model expectedModel = new ModelManager();
+
+ assertCommandSuccess(new ClearCommand(), model, ClearCommand.MESSAGE_SUCCESS, expectedModel);
+ }
+}
diff --git a/src/test/java/seedu/address/logic/commands/CommandResultTest.java b/src/test/java/seedu/medinfo/logic/commands/CommandResultTest.java
similarity index 98%
rename from src/test/java/seedu/address/logic/commands/CommandResultTest.java
rename to src/test/java/seedu/medinfo/logic/commands/CommandResultTest.java
index 4f3eb46e9ef..ff44af57e57 100644
--- a/src/test/java/seedu/address/logic/commands/CommandResultTest.java
+++ b/src/test/java/seedu/medinfo/logic/commands/CommandResultTest.java
@@ -1,4 +1,4 @@
-package seedu.address.logic.commands;
+package seedu.medinfo.logic.commands;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
diff --git a/src/test/java/seedu/medinfo/logic/commands/CommandTestUtil.java b/src/test/java/seedu/medinfo/logic/commands/CommandTestUtil.java
new file mode 100644
index 00000000000..8d70944977a
--- /dev/null
+++ b/src/test/java/seedu/medinfo/logic/commands/CommandTestUtil.java
@@ -0,0 +1,128 @@
+package seedu.medinfo.logic.commands;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.medinfo.logic.parser.CliSyntax.PREFIX_DISCHARGE;
+import static seedu.medinfo.logic.parser.CliSyntax.PREFIX_NAME;
+import static seedu.medinfo.logic.parser.CliSyntax.PREFIX_NRIC;
+import static seedu.medinfo.logic.parser.CliSyntax.PREFIX_STATUS;
+import static seedu.medinfo.logic.parser.CliSyntax.PREFIX_WARD;
+import static seedu.medinfo.testutil.Assert.assertThrows;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import seedu.medinfo.commons.core.index.Index;
+import seedu.medinfo.logic.commands.exceptions.CommandException;
+import seedu.medinfo.model.MedInfo;
+import seedu.medinfo.model.Model;
+import seedu.medinfo.model.patient.NameContainsKeywordsPredicate;
+import seedu.medinfo.model.patient.Patient;
+import seedu.medinfo.testutil.EditPatientDescriptorBuilder;
+
+/**
+ * Contains helper methods for testing commands.
+ */
+public class CommandTestUtil {
+
+ public static final String VALID_NAME_AMY = "Amy Bee";
+ public static final String VALID_NAME_BOB = "Bob Choo";
+ public static final String VALID_NRIC_AMY = "S9999999P";
+ public static final String VALID_NRIC_BOB = "S8888888P";
+ public static final String VALID_STATUS_AMY = "RED";
+ public static final String VALID_STATUS_BOB = "GRAY";
+ public static final String VALID_WARD_AMY = "Waiting Room";
+ public static final String VALID_WARD_BOB = "A2";
+ public static final String VALID_DISCHARGE_AMY = "04/12/2023 1200";
+ public static final String VALID_DISCHARGE_BOB = "25/07/2023 1600";
+
+ public static final String NAME_DESC_AMY = " " + PREFIX_NAME + VALID_NAME_AMY;
+ public static final String NRIC_DESC_AMY = " " + PREFIX_NRIC + VALID_NRIC_AMY;
+ public static final String STATUS_DESC_AMY = " " + PREFIX_STATUS + VALID_STATUS_AMY;
+ public static final String WARD_DESC_AMY = " " + PREFIX_WARD + VALID_WARD_AMY;
+ public static final String DISCHARGE_DESC_AMY = " " + PREFIX_DISCHARGE + VALID_DISCHARGE_AMY;
+ public static final String NAME_DESC_BOB = " " + PREFIX_NAME + VALID_NAME_BOB;
+ public static final String NRIC_DESC_BOB = " " + PREFIX_NRIC + VALID_NRIC_BOB;
+ public static final String STATUS_DESC_BOB = " " + PREFIX_STATUS + VALID_STATUS_BOB;
+ public static final String WARD_DESC_BOB = " " + PREFIX_WARD + VALID_WARD_BOB;
+ public static final String DISCHARGE_DESC_BOB = " " + PREFIX_DISCHARGE + VALID_DISCHARGE_BOB;
+
+ public static final String INVALID_NAME_DESC = " " + PREFIX_NAME + "James&"; // '&' not allowed in names
+ public static final String INVALID_STATUS_DESC = " " + PREFIX_STATUS + "ORANGE";
+ public static final String INVALID_STATUS = "ORANGE";
+
+ public static final String PREAMBLE_WHITESPACE = "\t \r \n";
+ public static final String PREAMBLE_NON_EMPTY = "NonEmptyPreamble";
+
+ public static final EditCommand.EditPatientDescriptor DESC_AMY;
+ public static final EditCommand.EditPatientDescriptor DESC_BOB;
+
+ static {
+ DESC_AMY = new EditPatientDescriptorBuilder().withName(VALID_NAME_AMY).build();
+
+ DESC_BOB = new EditPatientDescriptorBuilder().withName(VALID_NAME_BOB).build();
+ }
+
+ /**
+ * Executes the given {@code command}, confirms that
+ * - the returned {@link CommandResult} matches {@code expectedCommandResult}
+ *
+ * - the {@code actualModel} matches {@code expectedModel}
+ */
+ public static void assertCommandSuccess(Command command, Model actualModel, CommandResult expectedCommandResult,
+ Model expectedModel) {
+ try {
+ CommandResult result = command.execute(actualModel);
+ assertEquals(expectedCommandResult, result);
+ assertEquals(expectedModel, actualModel);
+ } catch (CommandException ce) {
+ throw new AssertionError("Execution of command should not fail.", ce);
+ }
+ }
+
+ /**
+ * Convenience wrapper to
+ * {@link #assertCommandSuccess(Command, Model, CommandResult, Model)}
+ * that takes a string {@code expectedMessage}.
+ */
+ public static void assertCommandSuccess(Command command, Model actualModel, String expectedMessage,
+ Model expectedModel) {
+ CommandResult expectedCommandResult = new CommandResult(expectedMessage);
+ assertCommandSuccess(command, actualModel, expectedCommandResult, expectedModel);
+ }
+
+ /**
+ * Executes the given {@code command}, confirms that
+ * - a {@code CommandException} is thrown
+ * - the CommandException message matches {@code expectedMessage}
+ * - the medinfo book, filtered patient list and selected patient in
+ * {@code actualModel} remain unchanged
+ */
+ public static void assertCommandFailure(Command command, Model actualModel, String expectedMessage) {
+ // we are unable to defensively copy the model for comparison later, so we can
+ // only do so by copying its components.
+ MedInfo expectedMedInfo = new MedInfo(actualModel.getMedInfo());
+ List expectedFilteredList = new ArrayList<>(actualModel.getFilteredPatientList());
+
+ assertThrows(CommandException.class, expectedMessage, () -> command.execute(actualModel));
+ assertEquals(expectedMedInfo, actualModel.getMedInfo());
+ assertEquals(expectedFilteredList, actualModel.getFilteredPatientList());
+ }
+
+ /**
+ * Updates {@code model}'s filtered list to show only the patient at the given
+ * {@code targetIndex} in the
+ * {@code model}'s medinfo book.
+ */
+ public static void showPersonAtIndex(Model model, Index targetIndex) {
+ assertTrue(targetIndex.getZeroBased() < model.getFilteredPatientList().size());
+
+ Patient patient = model.getFilteredPatientList().get(targetIndex.getZeroBased());
+ final String[] splitName = patient.getName().fullName.split("\\s+");
+ model.updateFilteredPatientList(new NameContainsKeywordsPredicate(Arrays.asList(splitName[0])));
+
+ assertEquals(1, model.getFilteredPatientList().size());
+ }
+
+}
diff --git a/src/test/java/seedu/medinfo/logic/commands/DeleteCommandTest.java b/src/test/java/seedu/medinfo/logic/commands/DeleteCommandTest.java
new file mode 100644
index 00000000000..219c278c148
--- /dev/null
+++ b/src/test/java/seedu/medinfo/logic/commands/DeleteCommandTest.java
@@ -0,0 +1,26 @@
+package seedu.medinfo.logic.commands;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.medinfo.testutil.TypicalPatients.getTypicalMedInfo;
+
+import seedu.medinfo.model.Model;
+import seedu.medinfo.model.ModelManager;
+import seedu.medinfo.model.UserPrefs;
+
+/**
+ * Contains integration tests (interaction with the Model) and unit tests for
+ * {@code DeleteCommand}.
+ */
+public class DeleteCommandTest {
+
+ private Model model = new ModelManager(getTypicalMedInfo(), new UserPrefs());
+
+ /**
+ * Updates {@code model}'s filtered list to show no one.
+ */
+ private void showNoPerson(Model model) {
+ model.updateFilteredPatientList(p -> false);
+
+ assertTrue(model.getFilteredPatientList().isEmpty());
+ }
+}
diff --git a/src/test/java/seedu/medinfo/logic/commands/EditCommandTest.java b/src/test/java/seedu/medinfo/logic/commands/EditCommandTest.java
new file mode 100644
index 00000000000..3742ff993f8
--- /dev/null
+++ b/src/test/java/seedu/medinfo/logic/commands/EditCommandTest.java
@@ -0,0 +1,17 @@
+package seedu.medinfo.logic.commands;
+
+import static seedu.medinfo.testutil.TypicalPatients.getTypicalMedInfo;
+
+import seedu.medinfo.model.Model;
+import seedu.medinfo.model.ModelManager;
+import seedu.medinfo.model.UserPrefs;
+
+/**
+ * Contains integration tests (interaction with the Model) and unit tests for
+ * EditCommand.
+ */
+public class EditCommandTest {
+
+ private Model model = new ModelManager(getTypicalMedInfo(), new UserPrefs());
+
+}
diff --git a/src/test/java/seedu/medinfo/logic/commands/EditPatientDescriptorTest.java b/src/test/java/seedu/medinfo/logic/commands/EditPatientDescriptorTest.java
new file mode 100644
index 00000000000..77bdbdd5a17
--- /dev/null
+++ b/src/test/java/seedu/medinfo/logic/commands/EditPatientDescriptorTest.java
@@ -0,0 +1,48 @@
+package seedu.medinfo.logic.commands;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.medinfo.logic.commands.CommandTestUtil.DESC_AMY;
+import static seedu.medinfo.logic.commands.CommandTestUtil.DESC_BOB;
+import static seedu.medinfo.logic.commands.CommandTestUtil.VALID_NAME_BOB;
+import static seedu.medinfo.logic.commands.CommandTestUtil.VALID_NRIC_BOB;
+import static seedu.medinfo.logic.commands.CommandTestUtil.VALID_STATUS_BOB;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.medinfo.logic.commands.EditCommand.EditPatientDescriptor;
+import seedu.medinfo.testutil.EditPatientDescriptorBuilder;
+
+public class EditPatientDescriptorTest {
+
+ @Test
+ public void equals() {
+ // same values -> returns true
+ EditPatientDescriptor descriptorWithSameValues = new EditPatientDescriptor(DESC_AMY);
+ assertTrue(DESC_AMY.equals(descriptorWithSameValues));
+
+ // same object -> returns true
+ assertTrue(DESC_AMY.equals(DESC_AMY));
+
+ // null -> returns false
+ assertFalse(DESC_AMY.equals(null));
+
+ // different types -> returns false
+ assertFalse(DESC_AMY.equals(5));
+
+ // different values -> returns false
+ assertFalse(DESC_AMY.equals(DESC_BOB));
+
+ // different name -> returns false
+ EditPatientDescriptor editedAmy = new EditPatientDescriptorBuilder(DESC_AMY).withName(VALID_NAME_BOB).build();
+ assertFalse(DESC_AMY.equals(editedAmy));
+
+ // different nric -> returns false
+ editedAmy = new EditPatientDescriptorBuilder(DESC_AMY).withNric(VALID_NRIC_BOB).build();
+ assertFalse(DESC_AMY.equals(editedAmy));
+
+ // different status -> returns false
+ editedAmy = new EditPatientDescriptorBuilder(DESC_AMY).withStatus(VALID_STATUS_BOB).build();
+ assertFalse(DESC_AMY.equals(editedAmy));
+ }
+}
diff --git a/src/test/java/seedu/address/logic/commands/ExitCommandTest.java b/src/test/java/seedu/medinfo/logic/commands/ExitCommandTest.java
similarity index 66%
rename from src/test/java/seedu/address/logic/commands/ExitCommandTest.java
rename to src/test/java/seedu/medinfo/logic/commands/ExitCommandTest.java
index 9533c473875..ddfada7b3da 100644
--- a/src/test/java/seedu/address/logic/commands/ExitCommandTest.java
+++ b/src/test/java/seedu/medinfo/logic/commands/ExitCommandTest.java
@@ -1,12 +1,12 @@
-package seedu.address.logic.commands;
+package seedu.medinfo.logic.commands;
-import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
-import static seedu.address.logic.commands.ExitCommand.MESSAGE_EXIT_ACKNOWLEDGEMENT;
+import static seedu.medinfo.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.medinfo.logic.commands.ExitCommand.MESSAGE_EXIT_ACKNOWLEDGEMENT;
import org.junit.jupiter.api.Test;
-import seedu.address.model.Model;
-import seedu.address.model.ModelManager;
+import seedu.medinfo.model.Model;
+import seedu.medinfo.model.ModelManager;
public class ExitCommandTest {
private Model model = new ModelManager();
diff --git a/src/test/java/seedu/medinfo/logic/commands/FindCommandTest.java b/src/test/java/seedu/medinfo/logic/commands/FindCommandTest.java
new file mode 100644
index 00000000000..2dcc45baa58
--- /dev/null
+++ b/src/test/java/seedu/medinfo/logic/commands/FindCommandTest.java
@@ -0,0 +1,35 @@
+package seedu.medinfo.logic.commands;
+
+import static seedu.medinfo.testutil.TypicalPatients.getTypicalMedInfo;
+
+import java.util.Arrays;
+
+import seedu.medinfo.model.Model;
+import seedu.medinfo.model.ModelManager;
+import seedu.medinfo.model.UserPrefs;
+import seedu.medinfo.model.patient.NameContainsKeywordsPredicate;
+import seedu.medinfo.model.patient.NricContainsKeywordsPredicate;
+import seedu.medinfo.model.patient.StatusContainsKeywordsPredicate;
+
+/**
+ * Contains integration tests (interaction with the Model) for {@code FindCommand}.
+ */
+public class FindCommandTest {
+ private Model model = new ModelManager(getTypicalMedInfo(), new UserPrefs());
+ private Model expectedModel = new ModelManager(getTypicalMedInfo(), new UserPrefs());
+
+ /**
+ * Parses {@code userInput} into a {@code NameContainsKeywordsPredicate}.
+ */
+ private NameContainsKeywordsPredicate prepareNamePredicate(String userInput) {
+ return new NameContainsKeywordsPredicate(Arrays.asList(userInput.split("\\s+")));
+ }
+
+ private NricContainsKeywordsPredicate prepareNricPredicate(String userInput) {
+ return new NricContainsKeywordsPredicate(Arrays.asList(userInput.split("\\s+")));
+ }
+
+ private StatusContainsKeywordsPredicate prepareStatusPredicate(String userInput) {
+ return new StatusContainsKeywordsPredicate(Arrays.asList(userInput.split("\\s+")));
+ }
+}
diff --git a/src/test/java/seedu/address/logic/commands/HelpCommandTest.java b/src/test/java/seedu/medinfo/logic/commands/HelpCommandTest.java
similarity index 65%
rename from src/test/java/seedu/address/logic/commands/HelpCommandTest.java
rename to src/test/java/seedu/medinfo/logic/commands/HelpCommandTest.java
index 4904fc4352e..e139830a9c7 100644
--- a/src/test/java/seedu/address/logic/commands/HelpCommandTest.java
+++ b/src/test/java/seedu/medinfo/logic/commands/HelpCommandTest.java
@@ -1,12 +1,12 @@
-package seedu.address.logic.commands;
+package seedu.medinfo.logic.commands;
-import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
-import static seedu.address.logic.commands.HelpCommand.SHOWING_HELP_MESSAGE;
+import static seedu.medinfo.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.medinfo.logic.commands.HelpCommand.SHOWING_HELP_MESSAGE;
import org.junit.jupiter.api.Test;
-import seedu.address.model.Model;
-import seedu.address.model.ModelManager;
+import seedu.medinfo.model.Model;
+import seedu.medinfo.model.ModelManager;
public class HelpCommandTest {
private Model model = new ModelManager();
diff --git a/src/test/java/seedu/medinfo/logic/commands/ListCommandTest.java b/src/test/java/seedu/medinfo/logic/commands/ListCommandTest.java
new file mode 100644
index 00000000000..bbf235a3cfc
--- /dev/null
+++ b/src/test/java/seedu/medinfo/logic/commands/ListCommandTest.java
@@ -0,0 +1,25 @@
+package seedu.medinfo.logic.commands;
+
+import static seedu.medinfo.testutil.TypicalPatients.getTypicalMedInfo;
+
+import org.junit.jupiter.api.BeforeEach;
+
+import seedu.medinfo.model.Model;
+import seedu.medinfo.model.ModelManager;
+import seedu.medinfo.model.UserPrefs;
+
+/**
+ * Contains integration tests (interaction with the Model) and unit tests for
+ * ListCommand.
+ */
+public class ListCommandTest {
+
+ private Model model;
+ private Model expectedModel;
+
+ @BeforeEach
+ public void setUp() {
+ model = new ModelManager(getTypicalMedInfo(), new UserPrefs());
+ expectedModel = new ModelManager(model.getMedInfo(), new UserPrefs());
+ }
+}
diff --git a/src/test/java/seedu/medinfo/logic/parser/AddCommandParserTest.java b/src/test/java/seedu/medinfo/logic/parser/AddCommandParserTest.java
new file mode 100644
index 00000000000..e1427218b98
--- /dev/null
+++ b/src/test/java/seedu/medinfo/logic/parser/AddCommandParserTest.java
@@ -0,0 +1,73 @@
+package seedu.medinfo.logic.parser;
+
+import static seedu.medinfo.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.medinfo.logic.commands.CommandTestUtil.INVALID_NAME_DESC;
+import static seedu.medinfo.logic.commands.CommandTestUtil.NAME_DESC_AMY;
+import static seedu.medinfo.logic.commands.CommandTestUtil.NAME_DESC_BOB;
+import static seedu.medinfo.logic.commands.CommandTestUtil.NRIC_DESC_AMY;
+import static seedu.medinfo.logic.commands.CommandTestUtil.NRIC_DESC_BOB;
+import static seedu.medinfo.logic.commands.CommandTestUtil.PREAMBLE_NON_EMPTY;
+import static seedu.medinfo.logic.commands.CommandTestUtil.PREAMBLE_WHITESPACE;
+import static seedu.medinfo.logic.commands.CommandTestUtil.VALID_NAME_BOB;
+import static seedu.medinfo.logic.parser.CommandParserTestUtil.assertParseFailure;
+import static seedu.medinfo.logic.parser.CommandParserTestUtil.assertParseSuccess;
+import static seedu.medinfo.testutil.TypicalPatients.AMY;
+import static seedu.medinfo.testutil.TypicalPatients.BOB;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.medinfo.logic.commands.AddCommand;
+import seedu.medinfo.model.patient.Name;
+import seedu.medinfo.model.patient.Patient;
+import seedu.medinfo.testutil.PatientBuilder;
+
+public class AddCommandParserTest {
+ private AddCommandParser parser = new AddCommandParser();
+
+ @Test
+ public void parse_allFieldsPresent_success() {
+ Patient expectedPatient = new PatientBuilder(BOB).build();
+
+ // whitespace only preamble
+ assertParseSuccess(parser, PREAMBLE_WHITESPACE + NAME_DESC_BOB
+ + NRIC_DESC_BOB, new AddCommand(expectedPatient));
+
+ // multiple names - last name accepted
+ assertParseSuccess(parser, NAME_DESC_AMY
+ + NAME_DESC_BOB + NRIC_DESC_BOB, new AddCommand(expectedPatient));
+
+ // multiple nrics - last phone accepted
+ assertParseSuccess(parser, NAME_DESC_BOB + NRIC_DESC_AMY
+ + NRIC_DESC_BOB, new AddCommand(expectedPatient));
+ }
+
+ @Test
+ public void parse_optionalFieldsMissing_success() {
+ // zero tags
+ Patient expectedPatient = new PatientBuilder(AMY).build();
+ assertParseSuccess(parser, NAME_DESC_AMY + NRIC_DESC_AMY, new AddCommand(expectedPatient));
+ }
+
+ @Test
+ public void parse_compulsoryFieldMissing_failure() {
+ String expectedMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE);
+
+ // missing name prefix
+ assertParseFailure(parser, VALID_NAME_BOB,
+ expectedMessage);
+
+ // all prefixes missing
+ assertParseFailure(parser, VALID_NAME_BOB,
+ expectedMessage);
+ }
+
+ @Test
+ public void parse_invalidValue_failure() {
+ // invalid name
+ assertParseFailure(parser, INVALID_NAME_DESC + NRIC_DESC_AMY, Name.MESSAGE_CONSTRAINTS);
+
+ // non-empty preamble
+ assertParseFailure(parser, PREAMBLE_NON_EMPTY + NAME_DESC_BOB + NRIC_DESC_BOB,
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE));
+ }
+}
diff --git a/src/test/java/seedu/address/logic/parser/ArgumentTokenizerTest.java b/src/test/java/seedu/medinfo/logic/parser/ArgumentTokenizerTest.java
similarity index 99%
rename from src/test/java/seedu/address/logic/parser/ArgumentTokenizerTest.java
rename to src/test/java/seedu/medinfo/logic/parser/ArgumentTokenizerTest.java
index c97308935f5..7016199875d 100644
--- a/src/test/java/seedu/address/logic/parser/ArgumentTokenizerTest.java
+++ b/src/test/java/seedu/medinfo/logic/parser/ArgumentTokenizerTest.java
@@ -1,4 +1,4 @@
-package seedu.address.logic.parser;
+package seedu.medinfo.logic.parser;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
diff --git a/src/test/java/seedu/address/logic/parser/CommandParserTestUtil.java b/src/test/java/seedu/medinfo/logic/parser/CommandParserTestUtil.java
similarity index 89%
rename from src/test/java/seedu/address/logic/parser/CommandParserTestUtil.java
rename to src/test/java/seedu/medinfo/logic/parser/CommandParserTestUtil.java
index 9bf1ccf1cef..bbdf6e84c1b 100644
--- a/src/test/java/seedu/address/logic/parser/CommandParserTestUtil.java
+++ b/src/test/java/seedu/medinfo/logic/parser/CommandParserTestUtil.java
@@ -1,9 +1,9 @@
-package seedu.address.logic.parser;
+package seedu.medinfo.logic.parser;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import seedu.address.logic.commands.Command;
-import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.medinfo.logic.commands.Command;
+import seedu.medinfo.logic.parser.exceptions.ParseException;
/**
* Contains helper methods for testing command parsers.
diff --git a/src/test/java/seedu/address/logic/parser/DeleteCommandParserTest.java b/src/test/java/seedu/medinfo/logic/parser/DeleteCommandParserTest.java
similarity index 73%
rename from src/test/java/seedu/address/logic/parser/DeleteCommandParserTest.java
rename to src/test/java/seedu/medinfo/logic/parser/DeleteCommandParserTest.java
index 27eaec84450..a690fc50b03 100644
--- a/src/test/java/seedu/address/logic/parser/DeleteCommandParserTest.java
+++ b/src/test/java/seedu/medinfo/logic/parser/DeleteCommandParserTest.java
@@ -1,13 +1,13 @@
-package seedu.address.logic.parser;
+package seedu.medinfo.logic.parser;
-import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
-import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure;
-import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess;
-import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
+import static seedu.medinfo.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.medinfo.logic.parser.CommandParserTestUtil.assertParseFailure;
+import static seedu.medinfo.logic.parser.CommandParserTestUtil.assertParseSuccess;
+import static seedu.medinfo.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
import org.junit.jupiter.api.Test;
-import seedu.address.logic.commands.DeleteCommand;
+import seedu.medinfo.logic.commands.DeleteCommand;
/**
* As we are only doing white-box testing, our test cases do not cover path variations
diff --git a/src/test/java/seedu/medinfo/logic/parser/EditCommandParserTest.java b/src/test/java/seedu/medinfo/logic/parser/EditCommandParserTest.java
new file mode 100644
index 00000000000..8e5243a7eea
--- /dev/null
+++ b/src/test/java/seedu/medinfo/logic/parser/EditCommandParserTest.java
@@ -0,0 +1,119 @@
+package seedu.medinfo.logic.parser;
+
+import static seedu.medinfo.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.medinfo.logic.commands.CommandTestUtil.DISCHARGE_DESC_AMY;
+import static seedu.medinfo.logic.commands.CommandTestUtil.INVALID_STATUS_DESC;
+import static seedu.medinfo.logic.commands.CommandTestUtil.NAME_DESC_AMY;
+import static seedu.medinfo.logic.commands.CommandTestUtil.STATUS_DESC_AMY;
+import static seedu.medinfo.logic.commands.CommandTestUtil.STATUS_DESC_BOB;
+import static seedu.medinfo.logic.commands.CommandTestUtil.VALID_DISCHARGE_AMY;
+import static seedu.medinfo.logic.commands.CommandTestUtil.VALID_NAME_AMY;
+import static seedu.medinfo.logic.commands.CommandTestUtil.VALID_STATUS_AMY;
+import static seedu.medinfo.logic.commands.CommandTestUtil.VALID_STATUS_BOB;
+import static seedu.medinfo.logic.commands.CommandTestUtil.VALID_WARD_AMY;
+import static seedu.medinfo.logic.commands.CommandTestUtil.VALID_WARD_BOB;
+import static seedu.medinfo.logic.commands.CommandTestUtil.WARD_DESC_AMY;
+import static seedu.medinfo.logic.commands.CommandTestUtil.WARD_DESC_BOB;
+import static seedu.medinfo.logic.parser.CommandParserTestUtil.assertParseFailure;
+import static seedu.medinfo.logic.parser.CommandParserTestUtil.assertParseSuccess;
+import static seedu.medinfo.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
+import static seedu.medinfo.testutil.TypicalIndexes.INDEX_SECOND_PERSON;
+import static seedu.medinfo.testutil.TypicalIndexes.INDEX_THIRD_PERSON;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.medinfo.commons.core.index.Index;
+import seedu.medinfo.logic.commands.EditCommand;
+import seedu.medinfo.logic.commands.EditCommand.EditPatientDescriptor;
+import seedu.medinfo.model.patient.Status;
+import seedu.medinfo.testutil.EditPatientDescriptorBuilder;
+
+public class EditCommandParserTest {
+ private static final String MESSAGE_INVALID_FORMAT = String.format(MESSAGE_INVALID_COMMAND_FORMAT,
+ EditCommand.MESSAGE_USAGE);
+
+ private EditCommandParser parser = new EditCommandParser();
+
+ @Test
+ public void parse_missingParts_failure() {
+ // no index specified
+ assertParseFailure(parser, VALID_NAME_AMY, MESSAGE_INVALID_FORMAT);
+
+ // no field specified
+ assertParseFailure(parser, "1", EditCommand.MESSAGE_NOT_EDITED);
+
+ // no index and no field specified
+ assertParseFailure(parser, "", MESSAGE_INVALID_FORMAT);
+ }
+
+ @Test
+ public void parse_invalidPreamble_failure() {
+ // negative index
+ assertParseFailure(parser, "-5" + NAME_DESC_AMY, MESSAGE_INVALID_FORMAT);
+
+ // zero index
+ assertParseFailure(parser, "0" + NAME_DESC_AMY, MESSAGE_INVALID_FORMAT);
+
+ // invalid arguments being parsed as preamble
+ assertParseFailure(parser, "1 some random string", MESSAGE_INVALID_FORMAT);
+
+ // invalid prefix being parsed as preamble
+ assertParseFailure(parser, "1 i/ string", MESSAGE_INVALID_FORMAT);
+ }
+
+ @Test
+ public void parse_invalidValue_failure() {
+ assertParseFailure(parser, "1" + INVALID_STATUS_DESC, Status.MESSAGE_CONSTRAINTS);
+ }
+
+ @Test
+ public void parse_allFieldsSpecified_success() {
+ Index targetIndex = INDEX_SECOND_PERSON;
+ String userInput = targetIndex.getOneBased() + STATUS_DESC_AMY + WARD_DESC_AMY + DISCHARGE_DESC_AMY;
+
+ EditPatientDescriptor descriptor = new EditPatientDescriptorBuilder()
+ .withStatus(VALID_STATUS_AMY).withWard(VALID_WARD_AMY).withDischarge(VALID_DISCHARGE_AMY).build();
+ EditCommand expectedCommand = new EditCommand(targetIndex, descriptor);
+
+ assertParseSuccess(parser, userInput, expectedCommand);
+ }
+
+ @Test
+ public void parse_someFieldsSpecified_success() {
+ Index targetIndex = INDEX_FIRST_PERSON;
+ String userInput = targetIndex.getOneBased() + STATUS_DESC_BOB + WARD_DESC_BOB;
+
+ EditCommand.EditPatientDescriptor descriptor = new EditPatientDescriptorBuilder()
+ .withStatus(VALID_STATUS_BOB).withWard(VALID_WARD_BOB).build();
+ EditCommand expectedCommand = new EditCommand(targetIndex, descriptor);
+
+ assertParseSuccess(parser, userInput, expectedCommand);
+ }
+
+ @Test
+ public void parse_oneFieldSpecified_success() {
+ // status
+ Index targetIndex = INDEX_THIRD_PERSON;
+ String userInput = targetIndex.getOneBased() + STATUS_DESC_AMY;
+ EditPatientDescriptor descriptor = new EditPatientDescriptorBuilder().withStatus(VALID_STATUS_AMY).build();
+ EditCommand expectedCommand = new EditCommand(targetIndex, descriptor);
+ assertParseSuccess(parser, userInput, expectedCommand);
+
+ // discharge
+ userInput = targetIndex.getOneBased() + DISCHARGE_DESC_AMY;
+ descriptor = new EditPatientDescriptorBuilder().withDischarge(VALID_DISCHARGE_AMY).build();
+ expectedCommand = new EditCommand(targetIndex, descriptor);
+ assertParseSuccess(parser, userInput, expectedCommand);
+ }
+
+ @Test
+ public void parse_multipleRepeatedFields_acceptsLast() {
+ Index targetIndex = INDEX_FIRST_PERSON;
+ String userInput = targetIndex.getOneBased() + STATUS_DESC_AMY + STATUS_DESC_AMY;
+
+ EditPatientDescriptor descriptor = new EditPatientDescriptorBuilder().withStatus(VALID_STATUS_AMY).build();
+ EditCommand expectedCommand = new EditCommand(targetIndex, descriptor);
+
+ assertParseSuccess(parser, userInput, expectedCommand);
+ }
+}
diff --git a/src/test/java/seedu/medinfo/logic/parser/FindCommandParserTest.java b/src/test/java/seedu/medinfo/logic/parser/FindCommandParserTest.java
new file mode 100644
index 00000000000..50366b33b29
--- /dev/null
+++ b/src/test/java/seedu/medinfo/logic/parser/FindCommandParserTest.java
@@ -0,0 +1,17 @@
+package seedu.medinfo.logic.parser;
+
+import static seedu.medinfo.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.medinfo.logic.parser.CommandParserTestUtil.assertParseFailure;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.medinfo.logic.commands.FindCommand;
+
+public class FindCommandParserTest {
+ private FindCommandParser parser = new FindCommandParser();
+
+ @Test
+ public void parse_emptyArg_throwsParseException() {
+ assertParseFailure(parser, " ", String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_USAGE));
+ }
+}
diff --git a/src/test/java/seedu/medinfo/logic/parser/MedInfoParserTest.java b/src/test/java/seedu/medinfo/logic/parser/MedInfoParserTest.java
new file mode 100644
index 00000000000..13604cd6e20
--- /dev/null
+++ b/src/test/java/seedu/medinfo/logic/parser/MedInfoParserTest.java
@@ -0,0 +1,59 @@
+package seedu.medinfo.logic.parser;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.medinfo.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.medinfo.commons.core.Messages.MESSAGE_UNKNOWN_COMMAND;
+import static seedu.medinfo.testutil.Assert.assertThrows;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.medinfo.logic.commands.AddCommand;
+import seedu.medinfo.logic.commands.ExitCommand;
+import seedu.medinfo.logic.commands.HelpCommand;
+import seedu.medinfo.logic.commands.ListCommand;
+import seedu.medinfo.logic.parser.exceptions.ParseException;
+import seedu.medinfo.model.patient.Patient;
+import seedu.medinfo.testutil.PatientBuilder;
+import seedu.medinfo.testutil.PatientUtil;
+
+public class MedInfoParserTest {
+
+ private final MedInfoParser parser = new MedInfoParser();
+
+ @Test
+ public void parseCommand_add() throws Exception {
+ Patient patient = new PatientBuilder().build();
+ AddCommand command = (AddCommand) parser.parseCommand(PatientUtil.getAddCommand(patient));
+ assertEquals(new AddCommand(patient), command);
+ }
+
+ @Test
+ public void parseCommand_exit() throws Exception {
+ assertTrue(parser.parseCommand(ExitCommand.COMMAND_WORD) instanceof ExitCommand);
+ assertTrue(parser.parseCommand(ExitCommand.COMMAND_WORD + " 3") instanceof ExitCommand);
+ }
+
+ @Test
+ public void parseCommand_help() throws Exception {
+ assertTrue(parser.parseCommand(HelpCommand.COMMAND_WORD) instanceof HelpCommand);
+ assertTrue(parser.parseCommand(HelpCommand.COMMAND_WORD + " 3") instanceof HelpCommand);
+ }
+
+ @Test
+ public void parseCommand_list() throws Exception {
+ assertTrue(parser.parseCommand(ListCommand.COMMAND_WORD) instanceof ListCommand);
+ assertTrue(parser.parseCommand(ListCommand.COMMAND_WORD + " 3") instanceof ListCommand);
+ }
+
+ @Test
+ public void parseCommand_unrecognisedInput_throwsParseException() {
+ assertThrows(ParseException.class, String.format(MESSAGE_INVALID_COMMAND_FORMAT, HelpCommand.MESSAGE_USAGE), ()
+ -> parser.parseCommand(""));
+ }
+
+ @Test
+ public void parseCommand_unknownCommand_throwsParseException() {
+ assertThrows(ParseException.class, MESSAGE_UNKNOWN_COMMAND, () -> parser.parseCommand("unknownCommand"));
+ }
+}
diff --git a/src/test/java/seedu/medinfo/logic/parser/ParserUtilTest.java b/src/test/java/seedu/medinfo/logic/parser/ParserUtilTest.java
new file mode 100644
index 00000000000..625e7c88e88
--- /dev/null
+++ b/src/test/java/seedu/medinfo/logic/parser/ParserUtilTest.java
@@ -0,0 +1,60 @@
+package seedu.medinfo.logic.parser;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static seedu.medinfo.logic.parser.ParserUtil.MESSAGE_INVALID_INDEX;
+import static seedu.medinfo.testutil.Assert.assertThrows;
+import static seedu.medinfo.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.medinfo.logic.parser.exceptions.ParseException;
+import seedu.medinfo.model.patient.Name;
+
+public class ParserUtilTest {
+ private static final String INVALID_NAME = "R@chel";
+ private static final String VALID_NAME = "Rachel Walker";
+ private static final String WHITESPACE = " \t\r\n";
+
+ @Test
+ public void parseIndex_invalidInput_throwsParseException() {
+ assertThrows(ParseException.class, () -> ParserUtil.parseIndex("10 a"));
+ }
+
+ @Test
+ public void parseIndex_outOfRangeInput_throwsParseException() {
+ assertThrows(ParseException.class, MESSAGE_INVALID_INDEX, () ->
+ ParserUtil.parseIndex(Long.toString(Integer.MAX_VALUE + 1)));
+ }
+
+ @Test
+ public void parseIndex_validInput_success() throws Exception {
+ // No whitespaces
+ assertEquals(INDEX_FIRST_PERSON, ParserUtil.parseIndex("1"));
+
+ // Leading and trailing whitespaces
+ assertEquals(INDEX_FIRST_PERSON, ParserUtil.parseIndex(" 1 "));
+ }
+
+ @Test
+ public void parseName_null_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> ParserUtil.parseName((String) null));
+ }
+
+ @Test
+ public void parseName_invalidValue_throwsParseException() {
+ assertThrows(ParseException.class, () -> ParserUtil.parseName(INVALID_NAME));
+ }
+
+ @Test
+ public void parseName_validValueWithoutWhitespace_returnsName() throws Exception {
+ Name expectedName = new Name(VALID_NAME);
+ assertEquals(expectedName, ParserUtil.parseName(VALID_NAME));
+ }
+
+ @Test
+ public void parseName_validValueWithWhitespace_returnsTrimmedName() throws Exception {
+ String nameWithWhitespace = WHITESPACE + VALID_NAME + WHITESPACE;
+ Name expectedName = new Name(VALID_NAME);
+ assertEquals(expectedName, ParserUtil.parseName(nameWithWhitespace));
+ }
+}
diff --git a/src/test/java/seedu/medinfo/model/MedInfoTest.java b/src/test/java/seedu/medinfo/model/MedInfoTest.java
new file mode 100644
index 00000000000..08a3d9127b8
--- /dev/null
+++ b/src/test/java/seedu/medinfo/model/MedInfoTest.java
@@ -0,0 +1,101 @@
+package seedu.medinfo.model;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static seedu.medinfo.testutil.Assert.assertThrows;
+import static seedu.medinfo.testutil.TypicalPatients.ALEX;
+import static seedu.medinfo.testutil.TypicalPatients.getTypicalMedInfo;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
+import seedu.medinfo.model.patient.Patient;
+import seedu.medinfo.model.patient.exceptions.DuplicatePatientException;
+import seedu.medinfo.model.ward.Ward;
+import seedu.medinfo.testutil.PatientBuilder;
+
+public class MedInfoTest {
+
+ private final MedInfo medInfo = new MedInfo();
+
+ @Test
+ public void constructor() {
+ assertEquals(Collections.emptyList(), medInfo.getPatientList());
+ }
+
+ @Test
+ public void resetData_null_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> medInfo.resetData(null));
+ }
+
+ @Test
+ public void resetData_withValidReadOnlyMedInfo_replacesData() {
+ MedInfo newData = getTypicalMedInfo();
+ medInfo.resetData(newData);
+ assertEquals(newData, medInfo);
+ }
+
+ @Test
+ public void resetData_withDuplicatePersons_throwsDuplicatePersonException() {
+ // Two patients with the same identity fields
+ Patient editedAlice = new PatientBuilder(ALEX).withNric("S1000007A").build();
+ List newPatients = Arrays.asList(ALEX, editedAlice);
+ MedInfoStub newData = new MedInfoStub(newPatients);
+
+ assertThrows(DuplicatePatientException.class, () -> medInfo.resetData(newData));
+ }
+
+ @Test
+ public void hasPerson_nullPerson_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> medInfo.hasPatient(null));
+ }
+
+ @Test
+ public void hasPerson_personNotInMedInfo_returnsFalse() {
+ assertFalse(medInfo.hasPatient(ALEX));
+ }
+
+ @Test
+ public void getPersonList_modifyList_throwsUnsupportedOperationException() {
+ assertThrows(UnsupportedOperationException.class, () -> medInfo.getPatientList().remove(0));
+ }
+
+ /**
+ * A stub ReadOnlyMedInfo whose patients list can violate interface constraints.
+ */
+ private static class MedInfoStub implements ReadOnlyMedInfo {
+ private final ObservableList patients = FXCollections.observableArrayList();
+ private final ObservableList