diff --git a/LICENSE b/LICENSE
index 39b3478982c..93c6f332326 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 company 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 companies 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..66661bf07c4 100644
--- a/README.md
+++ b/README.md
@@ -1,14 +1,26 @@
-[![CI Status](https://github.com/se-edu/addressbook-level3/workflows/Java%20CI/badge.svg)](https://github.com/se-edu/addressbook-level3/actions)
+# LinkMeIn
+
+[![CI Status](https://github.com/AY2324S1-CS2103T-T17-2/tp/workflows/Java%20CI/badge.svg)](https://github.com/AY2324S1-CS2103T-T17-2/tp/actions)
![Ui](docs/images/Ui.png)
-* This is **a sample project for Software Engineering (SE) students**.
- 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.
+* This is **a project forked from CS2103T TP Software Engineering (SE) for SE students**.
+
+ * This application allows students to track their applications to companies
+
+ * It also allows students to take note of application deadlines
+
+ * 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.
+
+ * It is named `LinkMeIn` as it was inspired from LinkedIn's functionality. However, this
+ project puts a spin on LinkedIn by allowing students to track their applications to companies.
+
+* This project is based on the AddressBook-Level3 project created by the
+[SE-EDU initiative](https://se-education.org).
+
+* 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.
diff --git a/build.gradle b/build.gradle
index a2951cc709e..72b0263738e 100644
--- a/build.gradle
+++ b/build.gradle
@@ -66,7 +66,11 @@ dependencies {
}
shadowJar {
- archiveFileName = 'addressbook.jar'
+ archiveFileName = 'LinkMeIn.jar'
+}
+
+run {
+ enableAssertions = true
}
defaultTasks 'clean', 'test'
diff --git a/codecov.yml b/codecov.yml
new file mode 100644
index 00000000000..3189404d2e0
--- /dev/null
+++ b/codecov.yml
@@ -0,0 +1,8 @@
+coverage:
+ status:
+ project:
+ default:
+ informational: true # Project status checks will be informational
+ patch:
+ default:
+ informational: true # Patch status checks will be informational
diff --git a/docs/AboutUs.md b/docs/AboutUs.md
index 1c9514e966a..64ed3231f0c 100644
--- a/docs/AboutUs.md
+++ b/docs/AboutUs.md
@@ -7,53 +7,50 @@ We are a team based in the [School of Computing, National University of Singapor
You can reach us at the email `seer[at]comp.nus.edu.sg`
-## Project team
+## Project Team
-### John Doe
+### Alagappan Ramanathan
-
+
-[[homepage](http://www.comp.nus.edu.sg/~damithch)]
-[[github](https://github.com/johndoe)]
-[[portfolio](team/johndoe.md)]
+[[Github](https://github.com/AlagappanRa)][[Portfolio](team/alagappanra.md)]
-* Role: Project Advisor
+* Role: Developer
+* Responsibilities: Testing
-### Jane Doe
+### Tay Ru Xin
-
+
-[[github](http://github.com/johndoe)]
-[[portfolio](team/johndoe.md)]
+[[Github](http://github.com/tayruxin)][[Portfolio](team/tayruxin.md)]
-* Role: Team Lead
-* Responsibilities: UI
+* Role: Developer
+* Responsibilities: Deliverables and Deadlines
-### Johnny Doe
+### Glenda Chong Rui Ting
-
+
-[[github](http://github.com/johndoe)] [[portfolio](team/johndoe.md)]
+[[Github](http://github.com/glendachong)][[LinkedIn](https://www.linkedin.com/in/glenda-chong-149367237)][[Portfolio](team/glendachong.md)]
* Role: Developer
-* Responsibilities: Data
+* Responsibilities: Documentation
-### Jean Doe
+### Lim En Tian
-
+
+
+[[Github](http://github.com/alientian)][[Portfolio](team/alientian.md)]
-[[github](http://github.com/johndoe)]
-[[portfolio](team/johndoe.md)]
* Role: Developer
-* Responsibilities: Dev Ops + Threading
+* Responsibilities: UI
-### James Doe
+### Ramu Rithik Vijay
-
+
-[[github](http://github.com/johndoe)]
-[[portfolio](team/johndoe.md)]
+[[Github](http://github.com/papataco14)][[LinkedIn](https://www.linkedin.com/in/rithikvijay/)][[Portfolio](team/papataco14.md)]
* Role: Developer
-* Responsibilities: UI
+* Responsibilities: Deciphering requirements
diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md
index 8a861859bfd..9f16f3ec37b 100644
--- a/docs/DeveloperGuide.md
+++ b/docs/DeveloperGuide.md
@@ -2,63 +2,74 @@
layout: page
title: Developer Guide
---
+
+## **Table of Contents**
* Table of Contents
{:toc}
---------------------------------------------------------------------------------------------------------------------
+---
## **Acknowledgements**
-* {list here sources of all reused/adapted ideas, code, documentation, and third-party libraries -- include links to the original source as well}
+This project is based on the AddressBook-Level3 project created by the [SE-EDU initiative](https://se-education.org).
---------------------------------------------------------------------------------------------------------------------
+* Libraries used:
+ * [JavaFX](https://openjfx.io/)
+ * [Jackson](https://github.com/FasterXML/jackson)
+ * [JUnit](https://junit.org/junit5/)
+
+---
-## **Setting up, getting started**
+## **Setting Up, Getting Started**
Refer to the guide [_Setting up and getting started_](SettingUp.md).
---------------------------------------------------------------------------------------------------------------------
+---
+
## **Design**
:bulb: **Tip:** The `.puml` files used to create diagrams in this document `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`** (consisting of classes [`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)) is in charge of the app launch and shut down.
-* At app launch, it initializes the other components in the correct sequence, and connects them up with each other.
-* At shut down, it shuts down the other components and invokes cleanup methods where necessary.
+**`Main`** (consisting of classes [`Main`](https://github.com/AY2324S1-CS2103T-T17-2/tp/blob/master/src/main/java/seedu/address/Main.java) and [`MainApp`](https://github.com/AY2324S1-CS2103T-T17-2/tp/blob/master/src/main/java/seedu/address/MainApp.java)) is in charge of the app launch and shut down.
+
+- At app launch, it initializes the other components in the correct sequence, and connects them up with each other.
+- At shut down, it shuts down the other components and invokes cleanup methods where necessary.
The bulk of the app's work is done by the following four components:
-* [**`UI`**](#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.
[**`Commons`**](#common-classes) represents a collection of classes used by multiple other components.
**How the architecture components interact with each other**
-The *Sequence Diagram* below shows how the components interact with each other for the scenario where the user issues the command `delete 1`.
+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.
@@ -66,26 +77,30 @@ For example, the `Logic` component defines its API in the `Logic.java` interface
The sections below give more details of each component.
-### UI component
+
+
+### UI Component
-The **API** of this component is specified in [`Ui.java`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/ui/Ui.java)
+The **API** of this component is specified in [`Ui.java`](https://github.com/AY2324S1-CS2103T-T17-2/tp/blob/master/src/main/java/seedu/address/ui/Ui.java)
![Structure of the UI Component](images/UiClassDiagram.png)
-The UI consists of a `MainWindow` that is made up of parts e.g.`CommandBox`, `ResultDisplay`, `PersonListPanel`, `StatusBarFooter` etc. All these, including the `MainWindow`, inherit from the abstract `UiPart` class which captures the commonalities between classes that represent parts of the visible GUI.
+The UI consists of a `MainWindow` that is made up of parts e.g.`CommandBox`, `ResultDisplay`, `CompanyListPanel`, `CompanyDetailPanel`, `StatusBarFooter` etc. All these, including the `MainWindow`, inherit from the abstract `UiPart` class which captures the commonalities between classes that represent parts of the visible GUI.
-The `UI` component uses the JavaFx UI framework. The layout of these UI parts are defined in matching `.fxml` files that are in the `src/main/resources/view` folder. For example, the layout of the [`MainWindow`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/ui/MainWindow.java) is specified in [`MainWindow.fxml`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/resources/view/MainWindow.fxml)
+The `UI` component uses the JavaFX UI framework. The layout of these UI parts are defined in matching `.fxml` files that are in the `src/main/resources/view` folder. For example, the layout of the [`MainWindow`](https://github.com/AY2324S1-CS2103T-T17-2/tp/blob/master/src/main/java/seedu/address/ui/MainWindow.java) is specified in [`MainWindow.fxml`](https://github.com/AY2324S1-CS2103T-T17-2/tp/blob/master/src/main/resources/view/MainWindow.fxml)
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 `Company` object residing in the `Model`.
-### Logic component
+
-**API** : [`Logic.java`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/logic/Logic.java)
+### Logic Component
+
+**API** : [`Logic.java`](https://github.com/AY2324S1-CS2103T-T17-2/tp/blob/master/src/main/java/seedu/address/logic/Logic.java)
Here's a (partial) class diagram of the `Logic` component:
@@ -101,231 +116,950 @@ The sequence diagram below illustrates the interactions within the `Logic` compo
How the `Logic` component works:
1. When `Logic` is called upon to execute a command, it is passed to an `AddressBookParser` object which in turn creates a parser that matches the command (e.g., `DeleteCommandParser`) and uses it to parse the command.
-1. This results in a `Command` object (more precisely, an object of one of its subclasses e.g., `DeleteCommand`) which is executed by the `LogicManager`.
-1. The command can communicate with the `Model` when it is executed (e.g. to delete a person).
-1. The result of the command execution is encapsulated as a `CommandResult` object which is returned back from `Logic`.
+2. This results in a `Command` object (more precisely, an object of one of its subclasses e.g., `DeleteCommand`) which is executed by the `LogicManager`.
+3. The command can communicate with the `Model` when it is executed (e.g. to delete a company).
+4. The result of the command execution is encapsulated as a `CommandResult` object which is returned back from `Logic`.
Here are the other classes in `Logic` (omitted from the class diagram above) that are used for parsing a user command:
How the parsing works:
-* 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.
-### Model component
-**API** : [`Model.java`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/model/Model.java)
+- 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.
-
+
+### Model Component
-The `Model` component,
+**API** : [`Model.java`](https://github.com/AY2324S1-CS2103T-T17-2/tp/blob/master/src/main/java/seedu/address/model/Model.java)
-* 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.
-
-
+The `Model` component,
-
+- stores the address book data i.e., all `Company` objects (which are contained in a `UniqueCompanyList` object).
+- stores the currently 'selected' `Company` 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
+### Storage Component
-**API** : [`Storage.java`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/storage/Storage.java)
+**API** : [`Storage.java`](https://github.com/AY2324S1-CS2103T-T17-2/tp/blob/master/src/main/java/seedu/address/storage/Storage.java)
-
+
The `Storage` component,
-* can save both address book data and user preference data in JSON format, and read them back into corresponding objects.
-* inherits from both `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`)
-### Common classes
+- 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`)
+
+### Common Classes
Classes used by multiple components are in the `seedu.addressbook.commons` package.
---------------------------------------------------------------------------------------------------------------------
+---
## **Implementation**
This section describes some noteworthy details on how certain features are implemented.
-### \[Proposed\] Undo/redo feature
+### Company Detail Panel (UI Component)
+The `CompanyDetailPanel` allows the user to view the company details of the selected company in the company list.
+Recruiter's information, company's information and remarks will be shown in the `CompanyDetailPanel`.
-#### Proposed Implementation
+#### Implementation
-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:
+`CompanyDetailCard` and `CompanyDetailPanel`, both inheriting `UiPart`, are used to display the company details. More details of the class implementation can be seen in the class diagram below.
-* `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.
+
-These operations are exposed in the `Model` interface as `Model#commitAddressBook()`, `Model#undoAddressBook()` and `Model#redoAddressBook()` respectively.
+`CompanyDetailCard` calls the static method `createPriorityFlowPane` from `CompanyCardUtils`, which creates a `FlowPane` to display the priority of the company.
+The color of the `FlowPane` is determined by the priority of the company. Red is used to indicate high priority,
+orange is used to indicate medium priority and green is used to indicate low priority.
-Given below is an example usage scenario and how the undo/redo mechanism behaves at each step.
+As for the other information, FXML labels are used to display the information. Within the constructor of `CompanyDetailCard`,
+the respective FXML labels are set with the information of the company.
-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.
+To display the details in 3 different boxes, `CompanyDetailCard.fxml` is divided into 3 sections with each section
+being a `VBox`. The 3 `VBox` are then added into a `HBox` to display the details in 3 different boxes.
-![UndoRedoState0](images/UndoRedoState0.png)
+As for `CompanyDetailPanel`, there is an inner class `CompanyDetailViewCell` which extends `ListCell`. This class
+sets the graphics to the `CompanyDetailCard` by constructing a new `CompanyDetailCard` with the company details of the company.
-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.
+#### Design Considerations
-![UndoRedoState1](images/UndoRedoState1.png)
+**Aspect: How details of the company are displayed**
-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`.
+- **Alternative 1 (Current Choice):** Display the details of the company in a separate panel.
-![UndoRedoState2](images/UndoRedoState2.png)
+ - Pros: The information is well compartmentalized. This improves the user viewing experience.
+ - Cons: One additional command is needed to view the details of the company.
-
: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`.
+- **Alternative 2:** Display all the details of the company in the same panel as the company list.
+ - Pros: The user does not need to key in additional commands to view the details of the company.
+ - Cons: The `CompanyListPanel` will be too cluttered with too much information displayed in a company card.
-
+
+
+### View Feature
+The `CompanyDetailPanel` allows the user to view the company details of the selected company in the company list.
+The user can use the `view` command to select the company to view.
+
+#### Implementation
+A new `UniqueCompanyList` is created in `AddressBook` to store the selected company which the user wishes to view.
+Additionally, the following operations are implemented in `AddressBook` to support the `view` and other commands:
+
+- `setCurrentViewedCompany(Company company)` - Sets the selected company to be viewed.
+- `clearDetailPanel()` - Clears the `UniqueCompanyList` to remove the selected company from the company detail panel.
+
+These operations are exposed in the `Model` interface as `Model#setCurrentViewedCompany(Company company)` and
+`Model#checkDelete()` respectively.
+
+The `view` function is implemented in the `ViewCommand` class which calls `Model#setCurrentViewedCopany(Company company)`
+to insert the selected company into the `UniqueCompanyList`.
+The follow sequence diagram depicts how the `view` command is executed.
+
+
+
+
+ **:information_source: Note:**
+ The lifeline for `ViewCommandParser` should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
+
+
+Since only the detail of one company will be displayed anytime, `Model#setCurrentViewedCopany(Company company)` will
+clear the `UniqueCompanyList` before inserting the selected company.
+Since `UniqueCompanyList` is an observable list, the `CompanyDetailPanel` will be updated automatically
+when there is any changes made to the `UniqueCompanyList`.
+
+When the `edit`, `add`, `view` or `delete` command is executed, the `CompanyDetailPanel` will be updated respectively as
+shown in the activity diagram below.
+
+
+
+#### Design Considerations
+
+**Aspect: How the company to be viewed is stored in the `AddressBook`**
-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.
+- **Alternative 1 (Current Choice):** Create a new `UniqueCompanyList` in `AddressBook` to store the selected company which the user wishes to view.
-![UndoRedoState3](images/UndoRedoState3.png)
+ - Pros: Since the `UniqueCompanyList` is an observable list, the `CompanyDetailPanel` will be updated automatically when there is any changes made to the `UniqueCompanyList`.
+ - Cons: There is a need to clear the list before adding the selected company to the `UniqueCompanyList` to ensure that only one company is displayed in the `CompanyDetailPanel` at any time.
-
: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.
+- **Alternative 2:** Create a new `Company` object in `AddressBook` to store the selected company which the user wishes to view.
+ - Pros: Since there are no lists involved, there is no need to clear the list.
+ - Cons: The `CompanyDetailPanel` will not be updated automatically when there are any changes made to the `Company` object. There is a need to create additional methods to update the `CompanyDetailPanel` when changes are made to the `Company` object.
+
+
+### Find Feature
+
+#### Implementation
+
+The `find` command allows users to search for companies using one or more keywords. Companies matching any of the keywords in their names will be returned. This search is case-insensitive, and partial matches are valid. The critical change in the implementation centers around the modification of the `NameContainsKeywordsPredicate` class.
+
+**How `NameContainsKeywordsPredicate` Works**
+
+Previously, `NameContainsKeywordsPredicate` was designed to match a company name against a whole keyword. However, the modified implementation allows it to test a company's name against substrings and return true if the company's name contains the substring.
+
+When `find` is executed, it uses the `Model` interface's `updateFilteredCompanyList(Predicate predicate)` method, passing in the modified `NameContainsKeywordsPredicate` to filter the list of companies.
+
+The sequence diagram below illustrates the processing of a `find` command, such as `find tech sta`:
+
+
+
+
+**:information_source: Notes:**
+* The above sequence diagram simplifies the interaction by focusing on the primary components involved in processing the `find` command.
+* The lifeline for `FindCommandParser` should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
-The following sequence diagram shows how the undo operation works:
+#### Design Considerations
+
+**Aspect: Approach to matching keywords**
+
+- **Alternative 1 (Current Choice):** Match company names that contain the keyword **anywhere** within them.
+
+ - Pros: Flexible search, allows partial keyword matching.
+ - Cons: Might produce more results than expected.
+
+- **Alternative 2:** Match company names that **start** with the given keyword.
+
+ - Pros: Precise results.
+ - Cons: Might omit some relevant results if user does not remember the exact start of the company's name.
+
+**Aspect: Case-sensitivity**
-![UndoSequenceDiagram](images/UndoSequenceDiagram.png)
+- **Alternative 1 (Current Choice):** Case-insensitive matching.
-
: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.
+ - Pros: User-friendly; users don’t need to remember exact case.
+ - Cons: Might produce a broader range of results.
+- **Alternative 2:** Case-sensitive matching.
+
+ - Pros: More exact matches.
+ - Cons: Less user-friendly, especially if users do not recall the exact case of company names.
+
+With the design considerations, we've chosen the alternatives that provide a balance between user-friendliness and precision.
+
+
+
+### Filter Feature
+
+The `filter` command allows users to filter the list of companies based on the valid application status.
+
+#### Implementation
+
+The `filter` command uses a new predicate, `ApplicationStatusPredicate`, which tests and returns true if a company's application status matches the application status input specified by the user. The `ApplicationStatusPredicate` class implements the `Predicate` interface, which allows it to be used in the `Model#updateFilteredCompanyList(Predicate predicate)` method to filter the list of companies. All companies that match the application status input will be displayed in the updated `CompanyListPanel`.
+
+The following sequence diagram will illustrate the process of performing the `filter` command, taking `filter s/pa` as an example.
+
+
+
+
+
+
+**:information_source: Note:**
+The lifeline for `FilterCommandParser` should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
-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.
+#### Design Considerations
+
+**Aspect: UI of the Filter Command**
+
+* **Alternative 1:** The `CompanyDetailPanel` will still display the details of the company that was last viewed before the `filter` command is executed.
+ * Pros: Users can still view the details of the last viewed company in the `CompanyDetailPanel` alongside the filtered list of companies.
+ * Cons: Users may be confused as the last viewed company in the `CompanyDetailPanel` may not be in the filtered list of companies after filtering.
+
+* **Alternative 2 (Current Choice):** The `CompanyDetailPanel` will be cleared whenever the `filter` command is executed.
+ * Pros: Users can focus on viewing details of company(s) belonging to the filtered list only, reducing distractions and confusions.
+ * Cons: Users might have to execute the `view` command again to access details of the last viewed company before filtering even if that company is still in the filtered list, potentially leading to additional steps taken.
-
: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.
+
+### Edit Feature
+
+#### Implementation
+The edit mechanism is facilitated by `EditCompanyDescriptor`, which is a nested class of `EditCommand` that is similar to the `Company` model, except that the value of parameters can be null.
+The `EditCommandParser` parses the user input and stores the values of the parameters to be edited in an `EditCompanyDescriptor` object while unedited parameters are `null`.
+Additionally, `EditCommand` implements the `EditCommand#execute(Model model)`operation which edits all the parameters indicated by the user input.
+This operation is exposed in the `Model` interface as:
+
+* `Model#setCompany(Company target, Company editedCompany)` - Updates a company in the list to a new company with edited parameters.
+* `Model#setCurrentViewedCompany(Company company)` - Sets the selected company to be viewed in the `CompanyDetailPanel`.
+
+The following sequence diagram will illustrate the process of performing the `edit` command, taking `edit 1 r/SWE` as an example.
+
+
+
+
+
+
+**:information_source: Note:**
+The lifeline for `EditCommandParser` should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
-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 `Model#getCompany(Index index)` is a pseudo method to represent getting the original `Company` object, `target`, from `Model`.
+When `EditCommand#execute()` is called, an edited `Company` object, `c`, is created by a self-invoked method since `Company` is immutable.
+When `Model#setCompany(Company company)` is called, the original `target` in the `AddressBook` is replaced with the edited `c`.
+
+#### Design Considerations
+
+**Aspect: How to edit different attributes of a company**
+
+* **Alternative 1 (Current Choice):** Edits all attributes using one command.
+ * Pros: Easy to implement.
+ * Cons: More prone to errors and bugs/ require more test cases for code coverage.
+
+* **Alternative 2:** Have a command to edit each attribute.
+ * Pros: Command line is shorter which reduces users' error such as duplicates or invalid command. This improves user experience.
+ * Cons: We must ensure that the implementation of each individual command are correct. This may also require more memory usage as a `Company` object is initialized for every modified attribute.
+
+
+
+### Duplicate Detection
+
+
+
+#### Implementation
+The term _duplicate_ hereafter refers to companies with the same company name, role and deadline.
+
+The _duplicate_ detection mechanism is facilitated by `Company#isSameCompany(Company otherCompany)`.
+This method checks if two `Company` entities are the same by checking if their `Name`, `Role` and
+`Deadline` parameters are equal. This method is used by `AddCommand` and `EditCommand` to check if
+the company to be added or edited already exists in the company list.
+
+The above sequence diagram shows the events when a user attempts to **edit** the details of an existing company,
+namely the company name, role and deadline parameters to match that of another company in the company list.
+The purpose of the diagram is a **simplified** view of the message passing when a _duplicate_ company is detected.
+
+Therefore, the diagram omits the following:
+1. The `if` statements in the `isSameCompany` method checking for strict equality with `this` and company d with`null`.
+ This is removed to simplify the diagram and not show the inner-workings of the method in detail.
+2. The `equals` method propagated after the `getName()`, `getRole()` and `getDeadline()` methods. Again, this would
+ involve the details of the equality checks of the `Name`, `Role` and `Deadline` classes, overcomplicating the
+ diagram with three more classes.
+
+**Description of the diagram**
+
+Upon ascertaining that the edited company is a duplicate,
+1. The `EditCommand` class calls the `getDuplicateCompany(c)` method in the `ModelManager` class.
+2. `ModelManager` forwards the call to the `AddressBook` class.
+3. The `AddressBook` class calls the `contains(c)` method in the `UniqueCompanyList` class.
+4. The `UniqueCompanyList` class calls the `Company::isSameCompany` method for each company in the list
+ to check if the edited company is a duplicate.
+5. `Company::isSameCompany` self-invokes the `getName()`, `getRole()` and `getDeadline()` methods and also
+ invokes the `getName()`, `getRole()` and `getDeadline()` on the company d to check for equality.
+6. The duplicated company is returned to the `EditCommand` class.
+
+Below is an activity diagram showing the events when a user attempts to **add** a duplicate company to the company list.
+
+
+
+The purpose of the diagram is to show the difference in the message passing when a duplicate company is detected
+between the `AddCommand` and `EditCommand` classes. Therefore, the diagram omits the propagation of the
+getDuplicateCompany(toAdd) method, which has already been shown in the sequence diagram prior.
+
+#### Design Considerations
+**Aspect: Change the location of the duplicate detection**
+- **Alternative:** Implement the duplicate detection logic within the `AddCommandParser` or `EditCommandParser` classes.
+ - Pros: The `execute` method's sole responsibility will be to execute the `add` or `edit` command without
+ needing to handle duplicate detection logic, adhering to the Single Responsibility Principle.
+ - Cons: The current architecture design dictates that `Model` be separate from `Logic`. The interaction
+ between `Model` and `Logic` is through the `execute` method. Implementing the duplicate detection in the
+ `Parser` classes will require the `Parser` classes to have access to the `Model` class, which violates the
+ current architecture design.
+
+**Aspect: Change the definition of a _duplicate_**
+- **Alternative:** Define _duplicates_ as equivalence of all parameters other than just `Name`, `Role` and `Deadline`.
+ - Pros: Allows users to add companies with the same name, role and deadline but different contact details.
+ - Cons: This approach does not align with real-world scenarios where if the Name, Role, and Deadline parameters
+ are identical, it likely indicates the same job application. The purpose of the duplicate detection is to prevent
+ interns from inadvertently applying multiple times to the same position at a company with the same role and
+ application deadline.
+
+
+
+### Remark Feature
+
+The `remark` feature allows user to add and delete remarks from a company.
+
+#### Implementation
+
+Unlike other `Command` class, the `RemarkCommand` class has two `COMMAND_WORD` - remark and unremark.
+Hence, it is a dependency for two `Parser` - `RemarkCommandParser` and `UnremarkCommandParser`.
+The two command words require two different parsers as they have different command format.
+Meanwhile, both can create the same type of Command object, `RemarkCommand`, because both command words results in a change in remarks of a company.
+The following activity diagram will show how `RemarkCommand` can achieve the functionality of both `COMMAND_WORD`.
-![UndoRedoState4](images/UndoRedoState4.png)
+
-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.
+The remark feature has a similar implementation as the [edit feature](#edit-feature), except that a `Remark` object is initialized instead of `EditCompanyDescriptor`.
-![UndoRedoState5](images/UndoRedoState5.png)
+#### Design Considerations
-The following activity diagram summarizes what happens when a user executes a new command:
+**Aspect: Implementation of `COMMAND_WORD` for Remark**
+- **Alternative 1 (Current Choice):** Use two `COMMAND_WORD`
+ - Pros: More specific commands allow for better error handling i.e. empty remark can be considered invalid input, thus more defensive programming
+ - Cons: More test cases needed to find bugs/More prone to bugs if error handling not implemented correctly.
+- **Alternative 2:** Use only one `COMMAND_WORD` - remark
+ - Pros: Easier to implement.
+ - Cons: Remarks may be accidentally deleted by an empty input for the parameter. This can affect user experience negatively.
-
+
-#### Design considerations:
+### Add Feature
+The `add` command allows users to add companies into LinkMeIn.
-**Aspect: How undo & redo executes:**
+#### Implementation
+The `add` feature is implemented using the `AddCommand` class. The `AddCommand` object takes in a `Company` object. Only if all the inputs for the parameters are valid, all compulsory parameters are present and there is no duplicate company in LinkMeIn, then the `Company` object is created.
-* **Alternative 1 (current choice):** Saves the entire address book.
- * Pros: Easy to implement.
- * Cons: May have performance issues in terms of memory usage.
+The `add` feature includes the following operations in `ModelManager`, which implements the `Model` interface:
+* `Model#hasCompany(Company company)` — Checks if the company is a _duplicate_ company in LinkMeIn.
+* `Model#addCompany(Company company)` — Adds a company into LinkMeIn.
+* `Model#setCurrentViewedCompany(Company company)` - Sets the selected company to be viewed in the `CompanyDetailPanel`.
-* **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.
+The following sequence diagram illustrates how the `add` command works and interacts between the `Logic` and `Model` components, taking the input `add c/Google r/Software Engineer s/PA d/10-10-2023 n/Francis Tan p/98765432 e/francist@gmail.com` as an example.
-_{more aspects and alternatives to be added}_
+
-### \[Proposed\] Data archiving
+
+**:information_source: Note:**
+The lifeline for `AddCommandParser` should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
+
+
+The following activity diagram shows what happens when the user executes the `add` command.
+
+
+
+
-_{Explain here how the data archiving feature will be implemented}_
+#### Design Considerations
+**Aspect: Parameters to be Added into Company**
+* **Alternative 1:** A `Company` object only requires the company's name, application's role and deadline as parameters for `add` command.
+ * Pros: Short and concise `add` command for users to type in. Easy for developers to implement with less code.
+ * Cons: Users may not be able to store necessary information in LinkMeIn, such as recruiter's information. Users may also be unable to keep track of which stage of the application they are at.
+* **Alternative 2 (Current Choice):** A `Company` object also includes application status, recruiter's name, phone and email address. The priority parameter is kept optional.
+ * Pros: Users can add in all the information at once, minimising the need to use other commands to do so afterward, like using `edit` command.
+ * Cons: Longer `add` command for users. Users may also not have recruiter's information at hand, especially during the initial stage of the application. Hence, users may not be able to add in the company into LinkMeIn.
---------------------------------------------------------------------------------------------------------------------
+
-## **Documentation, logging, testing, configuration, dev-ops**
+### Sort Feature
+The `sort` command allows users to sort the list of companies by their application deadlines in either ascending or
+descending order.
-* [Documentation guide](Documentation.md)
-* [Testing guide](Testing.md)
-* [Logging guide](Logging.md)
-* [Configuration guide](Configuration.md)
-* [DevOps guide](DevOps.md)
+#### Implementation
+The `Deadline` class implements the `java.lang.Comparable` interface, which provides a natural ordering of deadlines.
+The sort feature leverages the fact that the `Deadline` parameter in a `Company` object is comparable and uses
+the Java `Comparator` interface to sort companies based on their deadlines.
---------------------------------------------------------------------------------------------------------------------
+The sequence diagram below illustrates the execution of the SortCommand, when it is called with a `sortOrder` that can
+be either `ASCENDING` or `DESCENDING`. For simplicity, the parsing of the command prior to the execution of the command
+has been excluded.
-## **Appendix: Requirements**
+
-### Product scope
+
-**Target user profile**:
+
+**:information_source: Note:**
+The corresponding methods `createComparator`, `getUnmodifiableObservableList` and `sortCompanies` in the sequence diagram
+are simplifications of the actual code implementations for their respective actions. Also, the `sortOrder` is stored
+as an attribute in the `SortCommand` object, when it is created during parsing. It is shown as the way it is in the
+diagram for simplicity.
+
-* 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
+---
+
-**Value proposition**: manage contacts faster than a typical mouse/GUI driven app
+## **Documentation, Logging, Testing, Configuration, DevOps**
+- [Documentation guide](Documentation.md)
+- [Testing guide](Testing.md)
+- [Logging guide](Logging.md)
+- [Configuration guide](Configuration.md)
+- [DevOps guide](DevOps.md)
-### User stories
+---
+
+
+## **Appendix A: Requirements**
+
+### Product Scope
+
+**Target User Profile**
+
+National University of Singapore Computer Science students preparing for an internship who
+- prefer desktop apps over other types,
+- can type quickly,
+- prefer typing to mouse interactions,
+- are reasonably comfortable using CLI apps.
+
+**Value Proposition**
+CS students often struggle to manage a multitude of internship applications and track their application progress. An intuitive CLI address book not only efficiently stores these applications but also offers a valuable tool for monitoring and organizing the entire application process, simplifying the pursuit of career opportunities.
+
+
+
+### User Stories
+
+**Priority:**
+- `* * *` - High (must have)
+- `* *` - Medium (nice to have)
+- `*` - Low (unlikely to have)
+
+| Priority | As a … | I want to … | So that I can… |
+|----------|---------------------------------|--------------------------------------------------------------|--------------------------------------------------------------------------------------------|
+| `* * *` | user | add a new company to LinkMeIn | manage my internship applications for that company |
+| `* * *` | thorough user | view the recruiter's information of a company | follow up on my internship application |
+| `* * *` | tidy user | delete a company | ensure my list of companies remains organised by removing those I no longer wish to manage |
+| `* * *` | user | list out all my companies | have an overview of my internship applications |
+| `* *` | careless user | edit the details of a company | rectify any typographical errors in the company details |
+| `* *` | user managing many applications | find companies by their name | locate details of companies without having to go through the entire list |
+| `* *` | user managing many applications | sort companies by application deadline | view applications with nearer or further deadlines easily to plan my schedule |
+| `* *` | meticulous user | add remarks for a company | keep track of specific notes, thoughts or important details related to that application |
+| `* *` | meticulous user | remove remarks for a company | remove irrelevant information and keep my remarks up to date |
+| `* *` | seasoned user | clear all data | start afresh on a internship application cycle |
+| `* *` | user | exit the app quickly | conclude my session and ensure the application is not running in the background |
+| `* *` | confused user | view a list of available CLI commands and their descriptions | learn more about the application's features |
+| `* *` | new user | access a list of sample data | test the application out |
+| `* *` | seasoned user | filter companies by application status | focus on the most pertinent and relevant applications of interest |
+| `* *` | careless user | check for duplicate entries before adding an entry | avoid redundancy and maintain an accurate representation of my internship applications |
+| `* ` | creative user | be able to change the theme of LinkMeIn | personalise the visual appearance of the interface based on my preferences |
+| `*` | new user | import data from an Excel file | easily switch from excel to LinkMeIn and continue tracking my internship applications |
+| `*` | new user | export data to an Excel file | easily switch from LinkMeIn to excel and continue tracking my internship applications |
+
+
+
+### Use Cases
+
+
+**:information_source: Note:**
+For all use cases below, the **System** is `LinkMeIn` and the **Actor** is the `user`, unless specified otherwise.
+
-Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unlikely to have) - `*`
-| Priority | As a … | I want to … | So that I can… |
-| -------- | ------------------------------------------ | ------------------------------ | ---------------------------------------------------------------------- |
-| `* * *` | new user | see usage instructions | refer to instructions 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: UC01 - List all Companies**
-*{More to be added}*
+**MSS**
+1. User requests to list all companies.
+2. LinkMeIn displays the full list of companies.
+ Use case ends.
-### Use cases
+**Extensions**
+* 1a. LinkMeIn detects an invalid command format error in the input.
+ * 1a1. LinkMeIn displays an error message.
+ * 1a2. User enters a new command to list all companies.
+ Use case resumes from Step 1.
-(For all use cases below, the **System** is the `AddressBook` and the **Actor** is the `user`, unless specified otherwise)
-**Use case: Delete a person**
+**Use Case: UC02 - Add a Company**
-**MSS**
+**MSS**
+1. User requests to add a company.
+2. LinkMeIn adds the company.
+ Use case ends.
-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
+**Extensions**
+* 1a. LinkMeIn detects an invalid command format error in the input → handled similarly to 1a of UC01.
+* 1b. LinkMeIn detects an invalid parameter input.
+ * 1b1. LinkMeIn displays an error message.
+ * 1b2. User enters new data for the parameter.
+ Use case resumes from Step 1.
+* 1c. User requests to add a duplicate company.
+ * 1c1. LinkMeIn displays an error message.
+ * 1c2. User enters the information of a new company.
+ Use case resumes from Step 1.
- Use case ends.
+**Use Case: UC03 - Delete a Company**
+
+**MSS**
+1. User requests to delete a specific company from the list of companies.
+2. LinkMeIn deletes the company.
+ Use case ends.
+
+**Extensions**
+* 1a. LinkMeIn detects an invalid index input.
+ * 1a1. LinkMeIn displays an error message.
+ * 1a2. User enters a new index.
+ Use case resumes from Step 1.
+
+* 1b. LinkMeIn detects an invalid command format error in the input → handled similarly to 1a of UC01.
+
+
+**Use Case: UC04 - View a Company Detailed Information**
+
+**MSS**
+1. User requests to view a specific company from the list of companies.
+2. LinkMeIn shows the full information of the company in the company detail panel.
+ Use case ends.
**Extensions**
+* 1a. LinkMeIn detects an invalid index input → handled similarly to 1a of UC03.
+* 1b. LinkMeIn detects an invalid command format error in the input → handled similarly to 1a of UC01.
+
+
+**Use Case: UC05 - Clear all Companies**
+
+**MSS**
+1. User requests to clear all companies from the full list of companies.
+2. LinkMeIn clears all companies in the data.
+ Use case ends.
+
+**Extensions**
+* 1a. LinkMeIn detects an invalid command format error in the input → handled similarly to 1a of UC01.
+
+**Use Case: UC06 - Edit a Company**
+
+**MSS**
+1. User requests to edit parameter(s) of a specific company in the list.
+2. LinkMeIn edits the company.
+ Use case ends.
+
+**Extensions**
+* 1a. LinkMeIn detects an invalid index input → handled similarly to 1a of UC03.
+* 1b. LinkMeIn detects an invalid command format error in the input → handled similarly to 1a of UC01.
+* 1c. User requests to edit to a duplicate company → handled similarly to 1c of UC02.
+
+
+**Use Case: UC07 - Find a Company**
+
+**MSS**
+1. User requests to find companies based on the keywords.
+2. LinkMeIn displays a list of companies with matching keywords.
+ Use case ends.
+
+**Extensions**
+* 1a. LinkMeIn detects an invalid command format error in the input → handled similarly to 1a of UC01.
+
+
+**Use Case: UC08 - Filter Companies by Application Status**
+
+**MSS**
+1. User requests to filter the list of companies by one of the application statuses.
+2. LinkMein displays a list of companies matching the application status.
+ Use case ends.
+
+**Extensions**
+* 1a. LinkMeIn detects an invalid command format error in the input → handled similarly to 1a of UC01.
+* 1b. LinkMeIn detects an invalid parameter input → handled similarly to 1b of UC02.
-* 2a. The list is empty.
- Use case ends.
+**Use Case: UC09 - Sort Companies by Deadline**
-* 3a. The given index is invalid.
+**MSS**
+1. User requests to sort the list of companies by deadline.
+2. LinkMeIn displays the sorted list of companies.
+ Use case ends.
- * 3a1. AddressBook shows an error message.
+**Extensions**
+* 1a. LinkMeIn detects an invalid command format error in the input → handled similarly to 1a of UC01.
+* 1b. LinkMeIn detects an invalid parameter input → handled similarly to 1b of UC02.
- Use case resumes at step 2.
-*{More to be added}*
+**Use Case: UC10 - Add Remarks for a Company**
+
+**MSS**
+1. User requests to add remarks for a specific company.
+2. LinkMeIn adds the remarks to the company.
+ Use case ends.
+
+**Extensions**
+* 1a. LinkMeIn detects an invalid index input → handled similarly to 1a of UC03.
+* 1b. LinkMeIn detects an invalid parameter input → handled similarly to 1b of UC02.
+
+
+**Use Case: UC11 - Delete Remarks for a Company**
+
+**MSS**
+1. User requests to delete remarks for a specific company from the list of companies.
+2. LinkMeIn deletes the remarks from the company.
+ Use case ends.
+
+**Extensions**
+* 1a. LinkMeIn detects an invalid index input → handled similarly to 1a of UC03.
+
+
+**Use Case: UC12 - Exit the Program**
+
+**MSS**
+1. User requests to exit the program.
+2. LinkMeIn exits the program.
+ Use case ends.
+
+**Extensions**
+* 1a. LinkMeIn detects an invalid command format error in the input → handled similarly to 1a of UC01.
+
+
+**Use Case: UC13 - View Help**
+
+**MSS**
+1. User requests for help to use LinkMeIn.
+2. LinkMeIn displays a window with a link to the user guide.
+ Use case ends.
+
+**Extensions**
+* 1a. LinkMeIn detects an invalid command format error in the input → handled similarly to 1a of UC01.
+
+
### 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.
-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.
+1. The system should be available for download on our GitHub release page in the form of a JAR file.
+2. The system should work on any mainstream OS as long as it has Java 11 or above installed.
+3. The system should be able to hold up to 300 companies without a noticeable sluggishness in performance for typical usage.
+4. The system should be a single-user application.
+5. The response to any user input should become visible within 2 seconds.
+6. 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.
+7. The system should be easily picked up by a novice with no experience with managing internship applications.
+8. Data should be stored locally in the device.
+9. The application should guide the user if it fails to execute any of the user’s commands for various reasons.
+10. The application should be packaged into a single JAR file with size not exceeding 100MB.
+11. The code should meet the coding standard of CS2103T for maintainability.
-*{More to be added}*
+
### Glossary
-* **Mainstream OS**: Windows, Linux, Unix, OS-X
-* **Private contact detail**: A contact detail that is not meant to be shared with others
+| Term | Definition |
+|-------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| **Actor** | Represents an external entity that interacts with the system being modeled. Actors can be individuals, external systems, or organizations. |
+| **Alphanumeric** | Refers to a character set that includes both letters and numbers. It includes the 26 letters of the English alphabet (both uppercase and lowercase) and the numbers 0 through 9. |
+| **CLI** | Command-Line Interface (CLI) is a text-based user interface where users interact with the application by typing commands. |
+| **Command** | A command is an instruction given by a user to LinkMeIn to perform a specific action. For example,`add` command is a command to add the company's application into LinkMeIn. |
+| **Component** | A part of the application that serves a particular function (e.g., Logic, Storage). |
+| **GUI** | Graphical User Interface (GUI) is a visual method to interact with software using icons, buttons, and windows. GUI provides a user-friendly way to interact with software using graphical elements rather than text-based commands. |
+| **Index** | Refers to the index number shown in the displayed company list. |
+| **JAR** | JAR stands for Java Archive and is a package file format typically used to aggregate many Java class files and associated metadata and resources into one file for distribution. |
+| **JavaFX** | The UI framework that is used in this project. |
+| **JSON** | JSON stands for JavaScript Object Notation. It is a lightweight format for data interchange, easy to read and write for humans, and easy to parse for machines. Often used in web applications and configuration files. |
+| **Mainstream OS** | Windows, Linux, Unix, OS-X. |
+| **PlantUML** | Diagramming tool used to make the diagrams in this guide. |
+| **System** | Refers to the LinkMeIn application. |
+
+
+**:information_source: Note:**
+The definitions for parameters and prefixes have been omitted as they have already been defined in the user guide.
+
+
+---
+
+
+## **Appendix B: Planned Enhancements**
+
+### More Specific Success Message for Company
+
+**Feature Flaw in Current Implementation**
+
+Currently, the success message for `view`, `edit`, `remark`, `unremark`, and `add` commands only displays the company name.
+However, the duplicate check implemented in LinkMeIn uses 3 criteria, company name, role, and deadline. As such, there
+can be more than one entry with the same company name. The user might want to know the role and deadline to
+differentiate between applications with the same company name. As such, the current success message displayed can be confusing for the user as to which company specifically has been modified.
+
+**Proposed Enhancement**
+
+Instead of displaying only the company name, the success message will display the company name, role and deadline.
+This will be the same implementation done for the existing `delete` command. As such, a method was already created in
+the `Messages` class called `getCompanyInfo` where the company name, role and deadline from the company object will be
+returned as a string.
+
+The following implementation will be adopted instead:
+`return new CommandResult(String.format(MESSAGE_SUCCESS, Messages.getCompanyInfo(toAdd)));`
+
+**Examples**
+
+- **view**: `Viewing company: COMPANY_NAME (ROLE, DEADLINE)`
+- **edit**: `COMPANY_NAME (ROLE, DEADLINE) company edited`
+- **remark**: `Added remark to company: COMPANY_NAME (ROLE, DEADLINE)`
+- **unremark**: `Removed remark from company: COMPANY_NAME (ROLE, DEADLINE)`
+- **add**: `New company added: COMPANY_NAME (ROLE, DEADLINE)`
+
+
+
+### Make Recruiter Name, Phone and Email Parameters Optional in Add Command
+**Feature Flaw in Current Implementation**
+Currently, the recruiter’s information, namely recruiter’s name, phone number and email address, are compulsory parameters as inputs for `add` command. However, the user may not have the recruiter’s information at the point of applying to the company, which is common in most internship applications now. The user may only have the recruiter’s information at a later point in time. Hence, the user will not be able to add the company into LinkMeIn, without the recruiter's name, phone number and email address.
+
+**Proposed Enhancement**
+Instead of having the recruiter's name, phone number and email address to be compulsory parameters, they will be changed to optional parameters in the `add` command. This will allow the user to add the company into LinkMeIn without the recruiter's information.
+
+The updated `add` command format would be as follows:
+`add c/COMPANY_NAME r/ROLE s/APPLICATION_STATUS d/DEADLINE [n/RECRUITER_NAME] [p/PHONE] [e/EMAIL] [pr/PRIORITY]`.
+
+If the user did not add in the recruiter's name, phone number and email address upon adding the company into LinkMeIn, they can still do so with the existing `edit` command afterward.
+
+**Examples**
+* `add c/Google r/Software Engineer s/pa d/11-11-2023`
+* `add c/TikTok r/Data Analyst s/pa d/10-12-2023 n/Ben Tan`
+
+
+
+### Omit Alphanumeric Checks for Company Name, Recruiter Name and Role Parameters
+**Feature Flaw in Current Implementation**
+
+Currently, recruiter name, company name and role are checked for non-alphanumeric characters (defined as all characters other than alphabets and digits), and as a result, non-complying inputs are blocked.
+
+**Examples:**
+- `X Æ A-12` for recruiter name.
+- `H20.ai` for company name.
+- `Software Engineer (Backend)` for the role.
+
+The above inputs are all currently blocked due to the alphanumeric requirement.
+The input validation may be overly restrictive, restricting possible company names, recruiter names and roles inputs.
+
+**Proposed Enhancement**
+
+Instead of the current regex check located within the `Name`, `Role` and `RecruiterName` classes, the new regex check:
+- Allows periods (.) and parentheses ((, )) since these are common in company names and job titles.
+- Allows special characters like Æ and hyphens (-).
+- Allows any Unicode letter using \p{L}.
+- Allows for special characters at the start of the string as well.
+
+With the proposed change in the regular expression, the validation criteria for company names, recruiter names, and roles will be more inclusive.
+
+**Examples**
+
+Here are some examples illustrating what will now be allowed and what will remain disallowed:
+
+**Allowed Inputs**
+1. **Company Names:**
+ - `H20.ai`: Includes a period and digits.
+ - `Klüft Skogar`: Includes a special character (ü).
+ - `Déjà Vu Inc.`: Includes special characters (é, à) and a period.
+
+2. **Recruiter Names:**
+ - `X Æ A-12`: Includes a special character (Æ) and a hyphen.
+ - `Anne-Marie`: Includes a hyphen.
+ - `O’Connor`: Includes an apostrophe.
+
+3. **Roles:**
+ - `Software Engineer (Backend)`: Includes parentheses.
+ - `C++ Developer`: Includes a plus sign.
+ - `Sr. Manager - R&D`: Includes a period and a hyphen.
+
+**Disallowed Inputs**
+**Company Names, Recruiter Names, and Roles:**
+- `@example.com`: Starts with a disallowed special character (@).
+- `Jane#Doe`: Includes a disallowed special character (#).
+- `$$$ Enterprises`: Starts with disallowed special characters ($$$).
+- `Developer!!!`: Ends with disallowed special characters (!!!).
+
+The new regex allows for a more diverse range of characters, accommodating special characters, Unicode letters, numbers, spaces, periods, parentheses, and hyphens.
+It still restricts inputs that start with or contain certain special characters not typically found in names or titles.
+
+
+
+### Enhanced Flexibility in Phone Number Parameter Input
+
+**Feature Flaw in Current Implementation**
+
+Currently, the phone number parameter only accepts integers as valid user inputs. However, users may encounter scenarios,
+such as applying for overseas internships, where they want to include symbols like `()`, `+`, `-` and `.` in the phone
+number parameter. The current restriction prevents users from indicating country codes, potentially causing confusion about
+the origin of the phone number.
+
+**Proposed Enhancement**
+
+The regex checking for a valid phone number will be changed to allow for `()`, `+`, `-` and `.` in the phone number
+parameter. In addition, the character `+` will only be allowed at the start while, the other symbols have no positioning restrictions.
+
+**Examples**
+
+- +33 (0)6 12 34 56 78: will be accepted.
+- +33612345678: will be accepted.
+- 06.12.34.56.78: will be accepted.
+- 06-12-34-56-78: will be accepted.
+- 922492304: will be accepted.
+- 24234 + 234243: will **not** be accepted.
+
+
+
+### Enhance Find Feature to Search with Other Parameters
+**Potential Flaw in Current Implementation**
+Currently, LinkMeIn only allows searching through the list of companies by the `COMPANY_NAME` parameter. However,
+users might want to search through the list using other parameters, like `RECRUITER_NAME`, `PRIORITY` and `ROLE`.
---------------------------------------------------------------------------------------------------------------------
+**Proposed Enhancement**
+We plan to expand the current find command’s capability to allow for search using other parameters. Users will
+be able to specify the prefix that corresponds to the parameter they wish to use for the search, before the keyword(s).
+The prefixes used will be consistent with the rest of the application, in regard to what parameter they represent.
-## **Appendix: Instructions for manual testing**
+Here are the new suggested formats :
+* Find using `RECRUITER_NAME` : `find n/KEYWORD [KEYWORDS]...`
+* Find using `PRIORITY`: `find pr/KEYWORD [KEYWORDS]...`
+* Find using `Role`: `find r/KEYWORD [KEYWORDS]...`
+
+**Examples**
+* `find n/John Doe`
+* `find pr/High`
+* `find r/Software Engineer`
+
+
+
+### Enhance Find Feature to Allow for Search of Exact Company Names
+**Potential Flaw in Current Implementation**
+If users would like to find a specific company that has two or more words in their name such as `Microsoft
+Corporation`, using the current `find` command will return companies that match either `Microsoft` or `Corporation`.
+This can potentially pollute the results and defeat the purpose of the find feature.
+
+**Proposed Enhancement**
+We plan to expand the `find` command's capability, to allow for exact keyword matching. This can be done by specifying
+the keyword(s) within quotations.
+
+Suggested command format for exact find: `find “KEYWORD [KEYWORDS]...”`
+
+For example, users can now type: `find “Microsoft Corporation”`. This will return companies with names that match
+`Microsoft Corporation` exactly, reducing the potential for polluted find results.
+
+### Improve Error Message for Deadline Parameter
+**Potential Flaw in Current Implementation**
+Currently, users are able to input deadline past the current date successfully. We have allowed this in our current implementation because we understand that some users would like to track internship applications even if they have passed, but still belong in that internship cycle.
+
+However, some users might perceive it as a lack of validation check in LinkMeIn to inform them about an incorrectly entered deadline input.
+
+**Proposed Enhancement**
+To enhance the deadline parameter input, we will add a check to determine if the input deadline has already passed. If the deadline is before the current date, the user will still be able to add or edit the deadline. However, instead of the success message being `New company added: COMPANY_NAME`, we will improve the success message to be:
+```
+New company added: COMPANY_NAME.
+Note that you have entered a deadline past the current date. If you made a mistake in your input, please use the `edit` command to update the deadline.
+```
+
+
+### Enhance Flexibility in Deadline Parameter Input
+**Potential Flaw in Current Implementation**
+Currently, users are constrained to adhere strictly to the DD-MM-YYYY format for inputting deadline parameters. This rigid format might be inconvenient for some users, who prefer different date formats, which are equally common.
+
+**Proposed Enhancement**
+To enhance user flexibility and accommodate various user preferences, we will allow multiple deadline formats. Instead of accepting only DD-MM-YYYY format, we will also accept DD/MM/YYYY, YYYY/MM/DD and YYYY-MM-DD formats.
+
+Also, we understand that some users may not wish to type leading zeros for days and months with leading zeros, D/M/YYYY, D-M-YYYY, YYYY-M-D and YYYY/M/D formats will also be accepted.
+
+**Examples**
+* 1/1/2024 is in D/M/YYYY format.
+* 2024-1-1 is in YYYY-M-D format.
+* 12/12/2023 is in DD/MM/YYYY format.
+
+
+
+### Allow Multiple Indices Input for Delete Command
+
+**Feature Flaw in Current Implementation**
+
+Currently, the user can only delete one company at once. However, there will be cases where the user wishes to delete multiple entries at once, such as deleting all the companies that the user got rejected from. This can be tedious and inconvenient for the user.
+
+**Proposed Enhancement**
+
+Enable the user to input multiple indices when attempting to delete entries. Users can separate each index with a comma. If the user wishes to delete a range of indices, they can use a dash, to indicate the range. The format to delete a range of companies is `INDEX_START - INDEX_END`.
+The `DeleteCommandParser` will split the string by commas and remove the companies corresponding to the specified indices. There will also be checks to see if the user keyed in the same index more than once. If the same index is keyed in more than once, the parser will accept the input but treat it as if the user only keyed in that same index once.
+If the user keys in a range of indices, the parser will check if `INDEX_START` is smaller than or equals to `INDEX_END`. If `INDEX_START` is larger than `INDEX_END`, an error message will be displayed to the user. Besides, if `INDEX_END` is larger than the size of the list of companies, an error message will also be displayed to the user. `INDEX_START` and `INDEX_END` must be positive integers less than or equal to the maximum integer.
+
+**Examples**
+
+- `delete 1, 2`: deletes companies at index 1 and 2.
+- `delete 1`: deletes company at index 1.
+- `delete 4 - 7`: deletes companies at index 4, 5, 6, 7.
+
+
+
+### Enhance Remark Feature
+**Potential Flaw in Current Implementation**
+
+Currently, users are unable to copy texts from the `CompanyDetailPanel` in our UI.
+If users wish to add on to the existing remarks, they need to re-type the existing remarks into the Command Box, followed by their new remarks.
+This may not be a practical implementation, especially if the existing remarks are long, negatively affecting the user experience.
+
+**Proposed Enhancement**
+
+Edit the error message returned for `remark INDEX re/`.
+Currently, when `remark 1 re/` is entered, the error message returned is `Oops! Remark should not be empty. Please try again!`.
+This can be enhanced to return the existing remarks in the Message Box where the user can copy the content unlike in the`CompanyDetailPanel` where the user is unable to do so.
+Hence, the `remark INDEX re/` command will be modified such that if the user does not enter any remarks after `re/` prefix, the message displayed to the user will include their existing remarks.
+Should they wish to add on to their existing remarks, they can easily copy their existing remarks from the Message Box.
+The success message for a valid cumulative remark command will be the same as the usual remark command, which is `Added remark to Company: COMPANY_NAME`.
+
+**Examples**
+* Google is the first company in the list and the user wants to add remarks cumulatively.
+
+When `remark 1 re/` is entered, the Message Box will display the following message.
+```
+Remarks in Google:
+Require experience in Java, Interview on 12/12/2023
+```
+The user can copy from the Message Box and add on to his remarks. A sample input of an updated remark will then be:
+
+`remark 1 re/Require experience in Java, Interview on 12/12/2023, Interview went well!`
+
+---
+
+
+## **Appendix C: Instructions for Manual Testing**
Given below are instructions to test the app manually.
@@ -334,44 +1068,155 @@ testers are expected to do more *exploratory* testing.
-### Launch and shutdown
-
+### Launch and Shutdown
1. Initial launch
+ 1. Download the jar file and copy into an empty folder.
+ 2. Run `java -jar LinkMeIn.jar` in the folder containing the jar file to launch LinkMeIn.
+ Expected: Shows the GUI with a set of sample companies. The window size may not be optimum.
+2. Saving window preferences
+ 1. Resize the window to an optimum size. Move the window to a different location. Close the window.
+ 2. Re-launch LinkMeIn.
+ Expected: The most recent window size and location is retained.
- 1. Download the jar file and copy into an empty folder
+### Adding a Company
+1. Test case: `add c/Google r/Software Engineer s/PA d/10-10-2023 n/Francis Tan p/98765432 e/johnd@example.com pr/HIGH`
+ Expected: A new company is added to the end of the list of companies. Details of the added company is displayed in the `CompanyDetailPanel`.
+2. Test case: `add c/Google r/Software Engineer s/PA d/10-10-2023 n/Francis Tan`
+ Expected: No company is added. Error details shown in the command message.
+3. Try adding the same test case from Step 1. Check that an error message is displayed.
- 1. 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
+### Editing a Company
+Prerequisite: There is at least one company in the list.
- 1. Resize the window to an optimum size. Move the window to a different location. Close the window.
+1. Test case: `edit 1 r/Data Analyst`
+ Expected: First company’s role is updated in the list. Details of the edited company is displayed in the `CompanyDetailPanel`.
+2. Try editing other companies with different parameters.
- 1. Re-launch the app by double-clicking the jar file.
- Expected: The most recent window size and location is retained.
+### Deleting a Company
+Prerequisite: There is at least one company in the list.
+
+1. Test case: `delete 1`
+ Expected: First contact is deleted from the list. Details of the deleted company shown in the Message Box.
+
+2. Test case: `delete 0`
+ Expected: No company is deleted. Error details shown in the Message Box.
+
+3. Other incorrect delete commands to try: `delete`, `delete x`, `...` (where x is larger than the list size)
+ Expected: Similar to previous.
+
+### Viewing a Company
+Prerequisites: List all companies using the `list` command. Multiple companies in the list.
+
+1. Test case: `view 1`
+ Expected: First company is shown in the `CompanyDetailPanel`.
+2. Test case: `view 0`
+ Expected: No company is shown in the `CompanyDetailPanel`. Error details shown in the Message Box.
+3. Other incorrect view commands to try: `view`, `view x`, `...` (where x is larger than the list size)
+ Expected: Similar to previous.
+
+
+
+### Adding Remarks to a Company
+Prerequisite: There is at least one company in the list.
+
+1. Test case: `remark 1 r/This is a remark`
+ Expected: Remarks are added to the first company in the list.
+2. Try adding remarks to a company with an index greater than the number of companies in the current list. Check that an error message is displayed and no remarks are added.
+
+### Deleting Remarks from a Company
+Prerequisite: There is at least one company in the list.
+
+1. Test case: `unremark 1`
+ Expected: Remarks deleted from the first company in the list. `CompanyDetailPanel` will display "No remarks" under Remarks.
+
+### Listing Companies
+1. Test case: `list`
+ Expected: All companies in the list are displayed in the `CompanyListPanel`.
+
+### Finding Companies
+1. Test case: `find Google`
+ Expected: All companies with the keyword "Google" in their names are displayed in the `CompanyListPanel`.
+2. Try finding for a company that does not exist in the list.
+ Expected: No company is displayed in the `CompanyListPanel`.
+
+
+
+### Sorting Companies by Deadline
+1. Test case: `sort`
+ Expected: All companies in the list are displayed in the `CompanyListPanel`, sorted by deadline in ascending order.
+2. Test case: `sort d`
+ Expected: All companies in the list are displayed in the `CompanyListPanel`, sorted by deadline in descending order.
+3. Try sorting companies by an invalid parameter. Check that an error message is displayed.
+
+### Filtering Companies by Application Status
+1. Test case: `filter s/PA`
+ Expected: All companies with the application status "PA" are displayed in the `CompanyListPanel`.
+2. Try again with an invalid application status. Check that an error message is displayed.
+
+### Clearing All Data
+1. Test case: `clear`
+ Expected: All companies are deleted from the list.
+
+### Exiting LinkMeIn
+1. Test case: `exit`
+ Expected: LinkMeIn closes.
+
+
+
+### Saving Data
+1. Dealing with missing data file
+ 1. Delete the file named `companydata.json` located in the `data` folder.
+ 2. Relaunch LinkMeIn.
+ Expected: A new `companydata.json` file is created in the `data` folder, with sample companies shown in the GUI.
+2. Dealing with corrupted data file
+ 1. Open the `companydata.json` file located in the `data` folder with a text editor.
+ 2. Corrupt the file by deleting a few characters. Save the file.
+ 3. Relaunch LinkMeIn.
+ Expected: No companies will be shown in LinkMeIn.
+
+
+
+## **Appendix D: Effort**
+### Effort
+**UI Enhancements**
+
+With JavaFX, the UI has been revamped by importing different components such as `SplitPane` and `ListView`.
+Implementing these components requires us to learn more about JavaFX and experiment on our own.
+
+**Enhancements to Existing AB3 Features**
-1. _{ more test cases … }_
+While editing the commands to include new parameters may require less effort, we have put in substantial effort to enhance commands and issues inherited from AB3.
+This includes implementing a more optimised `find` command to search with greater flexibility and more extensive checks for more specific error messages which can guide users better.
+Duplicate check is one of the most commendable efforts for checks.
-### Deleting a person
+**New Classes Implemented**
-1. Deleting a person while all persons are being shown
+Examples of new classes created:
- 1. Prerequisites: List all persons using the `list` command. Multiple persons in the list.
+`Model` classes - Deadline, Priority, Status, Role etc.
- 1. 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.
+`Command` classes - Filter, Remark, Sort, View
- 1. Test case: `delete 0`
- Expected: No person is deleted. Error details shown in the status message. Status bar remains the same.
+Besides ensuring that new classes added follow the architecture, another important aspect is the code quality.
+We have added test cases for all new classes and practised defensive programming by adding assertion and logging statements.
- 1. 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 … }_
+### Challenges Faced
+- **Coding within a team:**
+Most of us were used to doing personal projects or pair projects, which are much easier to manage in terms of workflow.
+In the short amount of time we had, we had to familiarise ourselves with the GitHub workflow to enhance our collaboration.
+Merge conflicts and issues arising from minor mistakes with pull requests required a significant amount of time to resolve.
-### Saving data
+- **Using JavaFX:**
+We were newly introduced to the JavaFX package in this course, which we had little experience with.
+Editing the UI aspect is also more complex than coding the frontend and backend systems, as changing the UI relies on visualisation, which requires much trial and error to perfect. This steep learning curve for UI enhancements took us more time and effort to overcome.
-1. Dealing with missing/corrupted data files
+- **Evolving from AB-3:**
+Refactoring AB-3 code was challenging, especially at the start of the project. Significant time was spent understanding how the large codebase works. This proved even more challenging as we only learned software design patterns quite late into the semester. Hence, the code did not make much sense to us when we first started.
- 1. _{explain how to simulate a missing/corrupted file, and the expected behavior}_
+When evolving from AB-3 to LinkMeIn, we made a fair amount of enhancements, covering various aspects of the software, including changes in UI, addition of new commands, and error handling. LinkMeIn is a small evolution from AB3. With these considerations, the difficulty level for the LinkMeIn project is moderate.
-1. _{ more test cases … }_
+### Achievements
+We have made significant progress since the start of this module. We have familiarised ourselves with the GitHub workflow and successfully developed a CLI application that follows proper code quality standards, achieving readability and maintainability. We are genuinely proud of what we have achieved!
diff --git a/docs/UserGuide.md b/docs/UserGuide.md
index 57437026c7b..e4a33f014d6 100644
--- a/docs/UserGuide.md
+++ b/docs/UserGuide.md
@@ -3,195 +3,1014 @@ 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.
+# Welcome to LinkMeIn!
-* Table of Contents
+_Your One-Stop Internship Application Tracker._
+
+It's that time of the year again! You're scrolling through LinkedIn to discover internship opportunities, in hopes of trying to secure one for summer. To increase your chances, you've mass-applied to multiple companies, and now you're struggling to keep track of all your applications
+
+Well, fret not! LinkMeIn is here to help you! LinkMeIn is a **desktop application** specifically designed for all of you, NUS School Of Computing's Computer Science students, to effectively manage and track your internship applications.
+
+Here is a **quick** overview of how LinkMeIn transforms your internship application process:
+
+- Dynamic Data Management: Easily **add**, **edit**, **find** and **filter** companies for targeted application tracking.
+- Smart Organization: **Sort** applications by deadline and quickly pinpoint key opportunities.
+- Interactive Cards: Easily **view** details of a specific company — a sleeker approach than Excel sheets.
+
+LinkMeIn is more than just an application — it's your **personalized** partner, offering a seamless experience that outclasses conventional tracking methods.
+
+Moreover, LinkMeIn combines the **efficiency** of the [Command Line Interface (CLI)](#introducing-linkmeins-cli) with the visual clarity of the [Graphical User Interface (GUI)](#introducing-linkmeins-gui), offering a **best-of-both-worlds** experience.
+
+
+
+# Table of Contents
+* TOC
{:toc}
---------------------------------------------------------------------------------------------------------------------
+
+
+# Usage of This Guide
+
+This user guide aims to empower you with the knowledge and skills needed to maximize the potential of LinkMeIn. We are
+committed to guide you at every step of your internship journey. Whether you're a new user looking to get started or
+an experienced one seeking advanced insights, you'll find valuable information tailored to your unique
+needs and expertise.
+
+Before we begin, let us first introduce you to the annotations that you will encounter throughout this user guide.
+
+
+**:bulb: Useful Tip:**
+* Provides you with additional insights or more efficient ways to enhance your user experience with LinkMeIn.
+
+
+
+**:information_source: Note:**
+* Presents additional details to you that are valuable to know when using LinkMeIn.
+
+
+
+**:exclamation: Warning:**
+* Alerts you of potential pitfalls or things to be cautious of when using LinkMeIn.
+
+
+
+
+Throughout this guide, you will also notice **various text styles**. Here's what each of them means:
+- _Used to show possible scenarios that you can use a feature for (mainly in the feature sections)._
+- [Represents hyperlinks that you can click into, which will direct you to another section of this user guide or to
+ a website.]()
+- `Used to highlight specific elements such as file names, commands, or any text that should be viewed as code.`
+- > Used to describe information about the parameters that you can key into a command.
+
+Now that you are familiar with the annotations and text styles, let us teach you how to navigate this user guide according
+to your level of expertise.
-## Quick start
+## New to LinkMeIn? ##
-1. Ensure you have Java `11` or above installed in your Computer.
+Thank you for choosing LinkMeIn as your internship tracking ally! We are excited to embark on this journey with you.
-1. Download the latest `addressbook.jar` from [here](https://github.com/se-edu/addressbook-level3/releases).
+1. To get started, you can refer to the [Quick Start Section](#quick-start) to set up LinkMeIn.
+2. After downloading LinkMeIn and setting up your computer, we have prepared a
+ [Quick Tour](#introducing-linkmein-a-quick-tour) for you. This tour will help you get started with the key features of
+ LinkMeIn that you will be using quite often.
+3. If you choose to explore LinkMeIn on your own, you can refer to the [Features Section](#current-features) to find out
+ more about LinkMeIn's features.
-1. Copy the file to the folder you want to use as the _home folder_ for your AddressBook.
+
-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.
- ![Ui](images/Ui.png)
+## LinkMeIn Experts? ##
+Welcome back! We hope that you have been enjoying your internship tracking journey with LinkMeIn.
-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.
- Some example commands you can try:
+1. If you need a refresher on how to use a feature, you can refer to the [Features Section](#current-features) to find
+ out more about LinkMeIn's features. In the Features Section, there are **detailed explanations** of each feature and
+ **examples** to help you better understand how to use them.
+2. To quickly refer to the command format of a feature, you can head over to the [Command Summary Section](#command-summary)
+ where all the commands are listed out in a table format.
- * `list` : Lists all contacts.
+If you face any issues while using LinkMeIn, you can refer to the [FAQ Section](#faq) to see if your issue has been addressed before.
- * `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.
+[↑ Back to Table of Contents](#table-of-contents)
- * `delete 3` : Deletes the 3rd contact shown in the current list.
+
+
+# Quick Start
+In this section, you will learn how to set up LinkMeIn on your computer.
+
+1. Make sure that you have **Java 11 or above** installed on your Computer. Click
+ [here](#1-how-do-i-check-if-i-have-java-11-installed) if you are unsure of how to check if you have Java 11 installed.
+
+2. With Java 11 installed, you can now download our latest jar file from [here](https://github.com/AY2324S1-CS2103T-T17-2/tp/releases/latest).
+
+3. Click on the `LinkMeIn.jar` file to download it.
+
+
+
+
+4. Move the downloaded jar file into a home folder of your choice, such as the **Desktop** or **Documents** folder.
+
+5. Open up your command terminal. If you are unsure of how to do so, you can check out [this FAQ](#2-how-do-i-open-up-my-terminal).
+
+6. Navigate to the folder where you have placed the jar file by typing `cd`, followed by the folder path.
+ - For example if you have placed the jar file in the **Documents** folder, type `cd ~/Documents` and press `Enter`.
+
+
+
+7. Type the command `java -jar LinkMeIn.jar` and press `Enter`. Your command terminal should look like this after
+ Steps 6 and 7:
+
+
+
+
+
+ **:exclamation: Warning:**
+ * Do not move or delete the `data` folder as it contains the data of your internship applications.
+
+
+
+
+8. You should have successfully launched LinkMeIn with the following interface appearing on your screen.
+
+
+
+
+9. Great job! You are now ready to learn about the **GUI** of LinkMeIn!
+
+[↑ Back to Table of Contents](#table-of-contents)
+
+
+
+# Introducing LinkMeIn's GUI
+LinkMeIn's [GUI](#glossary) is designed to be **simple** and **intuitive**, with you in mind.
+The GUI consists of four main components:
+
+![uiIntro.png](images/ui-intro/uiIntro.png)
+
+| Number | Component | Description |
+|--------|----------------------|----------------------------------------------------------|
+| 1 | Command Box | Key in your commands here and LinkMeIn will execute them |
+| 2 | Message Box | Displays success or error messages to you |
+| 3 | Company List Panel | Displays the list of companies that you have added |
+| 4 | Company Detail Panel | Displays the details of a company that you are viewing |
+
+
+
+
+**:bulb: Useful Tip:**
+* To maximise your viewing experience, opt for full-screen mode in LinkMeIn!
+
- * `clear` : Deletes all contacts.
+Now that you've been introduced to LinkMeIn's GUI, let's proceed to learn how you can use the CLI to interact with LinkMeIn.
- * `exit` : Exits the app.
+[↑ Back to Table of Contents](#table-of-contents)
-1. Refer to the [Features](#features) below for details of each command.
+
---------------------------------------------------------------------------------------------------------------------
+# Introducing LinkMeIn's CLI
-## Features
+LinkMeIn operates through the Command Line Interface (CLI), where you interact with our app by simply **typing commands**. Say goodbye to the days of multitasking between typing and clicking, and say hello to the world of CLI!
+
+Don't let the name intimidate you! Continue reading on to discover how **E**ffortless, **E**asy and **E**fficient CLI is when using LinkMeIn.
+
+
+
+
+
+The Command Box serves as the gateway for entering command lines. Once you press enter, LinkMeIn processes your input and provides responses through the Message Box. This process of interacting with LinkMeIn through text is exactly how CLI works!
+Now, let's move on to learn how to write command lines, and you are ready to try LinkMeIn!
+
+## Command Format
+A command line has 4 components, **command word**, **index**, **prefix** and **parameter**.
+
+| Component | Example | Description |
+|--------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| Command Word | `add` | Indicates the feature to be executed |
+| Index | `1`, `5` | Indicates the position of the company in the list (e.g., 5th company in the list) |
+| Parameter | `John` | Represents the updated value or content. These values, which are provided by the user, replaces the `UPPER_CASE` placeholders in the command format
|
+| Prefix | `c/` | Indicates the type of parameter to be edited (e.g., company's name) |
+
+You can find all the parameters used in LinkMeIn [here](#parameters-description).
+To learn more about the prefixes and command words used in LinkMeIn, you can refer to the [Command Summary Section](#command-summary).
+
+Now, let's see how you can use these components to easily write a command!
+The following color code will assist you in highlighting each component for better understanding.
+
+
+
+
+
+Let's use the [`add` command](#adding-a-company--add) format as shown below to explain the components.
+
+
+
+
+The `add` command word is used to initiate the adding of a company into LinkMeIn.
+
+The prefix indicates the parameter type. For example, `c/John` adds "John" as the company name while `n/John` adds "John" as the recruiter's name.
+Simply replace the parameters with your specific application details, and you have effectively crafted an `add` command!
+
+But wait! Notice the `[]` around `pr/PRIORITY`? Here's what it means:
+
+| Symbol | Description | Example | Interpretation |
+|---------|------------------|------------------|-------------------------------------------------------|
+| None | Compulsory field | `C/COMPANY_NAME` | The company's name is required when adding a company |
+| `[ ]` | Optional field | `[pr/PRIORITY]` | Not a must to indicate priority when adding a company |
+
+Since `PRIORITY` parameter is optional, the following command lines are accepted for the `add` command.
+
+
+
+**Examples:**
+- `add c/GovTech r/Software Engineer s/PA n/John Doe d/12-12-2023 e/johnDoe@gmail.com p/98765432 pr/medium`
+- `add c/GovTech r/Software Engineer s/PA n/John Doe d/12-12-2023 e/johnDoe@gmail.com p/98765432`
+**:information_source: Notes:**
+* Parameters can be in any order (e.g., if the command specifies `c/COMPANY_NAME r/ROLE`, `r/ROLE c/COMPANY_NAME` is also acceptable).
+* Parameters and prefixes are case-insensitive (e.g., `c/COMPANY_NAME` is the same as `C/company_name`).
+
-**:information_source: Notes about the command format:**
+Notice that the `add` command does not use `INDEX` in its command format. Each feature has a unique command format, but every command line must begin with a command word to specify the desired feature. You can find the command format for each feature in the [Features](#current-features) section or take a **quick tour** to get hands-on experience with LinkMeIn, right below!
-* 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`.
+[↑ Back to Table of Contents](#table-of-contents)
-* 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 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.
+# Introducing LinkMeIn: A Quick Tour
-* 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.
+_If you are new to LinkMeIn, welcome aboard! We know that navigating the world of internship applications can be
+daunting, especially when you have multiple opportunities in sight. But fret not, because with LinkMeIn,
+you have a reliable companion to guide you through this exciting journey._
-* Extraneous parameters for commands that do not take in parameters (such as `help`, `list`, `exit` and `clear`) will be ignored.
- e.g. if the command specifies `help 123`, it will be interpreted as `help`.
+This tour aims to help you get started with LinkMeIn by introducing you to its essential features that you will be
+using quite often. In this tour, you will be learning how and when to:
-* If you are using a PDF version of this document, be careful when copying and pasting commands that span multiple lines as space characters surrounding line-breaks may be omitted when copied over to the application.
+- [add a company](#1-adding-a-company),
+- [view its details](#2-viewing-company-details),
+- [edit its details](#3-editing-company-details),
+- [delete it](#4-deleting-a-company).
+
+Before we embark on this tour, remember to download LinkMeIn and have your computer set up correctly. If you have not
+done so, do check out the [Quick Start Guide](#quick-start) for more information.
+Now, follow us along this tour and transform yourself into a master of tracking your internship applications!
+
+## 1. Adding a Company
+
+Adding a company is the first step to tracking your internship applications. Let us start off by adding your first company to LinkMeIn.
+
+**Step 1:** Let's say you are interested to apply for the **Software Engineer** role from **Apple**. Through the application description, you obtained the following information:
+* **Deadline:** 10-10-2023
+* **Recruiter Name:** Francis Tan
+* **Email:** francistan@example.com
+* **Phone Number:** 88287345
+
+This application is of **medium** priority as you have other applications that you want to focus on first.
+
+
+
+**Step 2:** With the details above, simply type `add c/Apple r/Software Engineer s/PA n/Francis Tan d/10-10-2023 e/francistan@example.com p/88287345 pr/medium` into the Command Box and press `Enter`.
+
+![img.png](images/add-command/BeforeAddCommand.png)
+
+
+
+**Step 3:** The Company Detail Panel will be updated to show the details of the newly added company's application, and the company will be added to the list of companies.
+
+![img.png](images/add-command/AfterAddCommand.png)
+
+
+**:bulb: Useful Tip:**
+* To quickly navigate to the start and end of your command line, you can use 'Ctrl' (Windows User) / 'Command' (Mac User) with the 'Left' and 'Right' arrow keys respectively!
-### Viewing help : `help`
+Congratulations! You have successfully added your first company to LinkMeIn. Go ahead and try adding a few more companies on your own!
+
+If you wish to learn more about the `add` command, you can do so [here](#adding-a-company--add).
+
+
+
+## 2. Viewing Company Details
+
+Now that you have added your first few companies into LinkMeIn, you may want to view the details of a specific company.
+
+**Step 1:** After scrolling through your list of companies, you wish to view the details of the company DSTA.
+Simply type `view 3` to view DSTA's details.
+
+![img.png](images/view-command/BeforeViewCommand.png)
+
+
+
+**Step 2:** The Company Detail Panel will be updated to show the details of DSTA.
-Shows a message explaning how to access the help page.
+![img.png](images/view-command/AfterViewCommand.png)
-![help message](images/helpMessage.png)
+Go ahead and try viewing the details of a few more companies on your own!
-Format: `help`
+If you wish to read up more on the `view` command, you can do so [here](#viewing-full-companys-information-view).
+
-### Adding a person: `add`
+## 3. Editing Company Details
-Adds a person to the address book.
+Suppose you received an email from DSTA inviting you to interview for a Frontend Developer role, which differs from the Software Engineer role you initially applied for.
-Format: `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]…`
+**Step 1.** To edit the company's information, type `edit 3 s/PI r/Frontend Developer`
-
:bulb: **Tip:**
-A person can have any number of tags (including 0)
+![EditDemo1.png](images/edit-command/EditDemo1.png)
+
+
+
+**Step 2.** The application status and role of the 3rd company in the list is edited to be Pending Interview and Frontend Developer respectively.
+
+![EditDemo2.png](images/edit-command/EditDemo2.png)
+
+Go ahead and try editing the other companies too. If you wish to read up more on the `edit` command, you can do so [here](#editing-a-companys-information-edit).
+
+
+
+## 4. Deleting a Company
+
+Suppose you no longer wish to track the DSTA application from earlier, you can easily delete the company from LinkMeIn.
+
+**Step 1:** To delete DSTA, type `delete 3` in the command box and press enter
+
+![img.png](images/delete-command/BeforeDeleteCommand.png)
+
+
+
+**Step 2:** DSTA will be removed from the list of companies. The Company Detail Panel will be cleared too.
+
+![img.png](images/delete-command/AfterDeleteCommand.png)
+
+Go ahead and try deleting the other companies too. If you wish to read up more on the delete command, you can do so
+[here](#deleting-a-company--delete).
+
+
+**Congratulations!** You have completed the quick tour of LinkMeIn. You are now ready to use LinkMeIn to track your own
+internship applications. To remove the sample data provided in LinkMeIn, simply type `clear` in the command box to remove
+all existing entries. Find out more about the `clear` command [here](#clearing-all-companies-clear).
+
+LinkMeIn offers more than just the features that you have learnt in this tour.
+If you wish to learn more about the other features of LinkMeIn, head over to our **Features Section** right below!
+You can also visit the [FAQ](#faq) to view the frequently asked questions if you need more help!
+
+[↑ Back to Table of Contents](#table-of-contents)
+
+---
+
+
+# Current Features
+
+LinkMeIn's features can be categorised into 3 broad categories:
+
+- [General Features](#general-features): This section equips you with essential tools to **navigate** LinkMeIn effectively.
+ Here, you can access help, clear all entries, and gracefully exit LinkMeIn.
+- [Company Management Features](#company-management-features): Dive into this section to **engage with individual company entries.** You can easily
+ add, view, edit, delete companies, as well as add your own remarks to them.
+- [Company List Features](#company-list-features): This section allows you to **interact with the list of companies,** thereby unlocking LinkMeIn's full potential.
+ Explore options to find, list, filter and sort companies, managing all companies with ease.
+
+
+**:information_source: Notes:**
+* For commands that do not take in any parameters (such as `help`, `list`, `exit` and `clear`), anything typed after the command word will be ignored. For example, if you type `help 123`, `123` will be ignored, and the command will just be interpreted as `help`.
+* If you are using a PDF version of this document, be careful when copying and pasting commands that span multiple lines! It could result in an invalid input.
+
+
+
+
+## General Features
+These general features are here to enhance your user experience when using LinkMeIn. Keep reading to find out more about them!
+
+### Clearing All Companies: `clear`
+
+_You've just completed an internship cycle and are preparing for the next one! Want to keep your list of companies clutter-free? Just use the `clear` command to clear all the existing companies in LinkMeIn at once._
+
+**Format:** `clear`
+
+**Example:**
+
+**Step 1:** Type `clear` in the Command Box and press `Enter`.
+
+**Step 2:** You should see an empty list of companies immediately.
+
+![img.png](images/clear-command/clear.png)
+
+
+
+
+**:exclamation: Warning:**
+* Companies cannot be recovered after clearing! Please only use the `clear` command when you are very sure that you no longer wish to track the existing list of companies!
+
+
+[↑ Back to Table of Contents](#table-of-contents)
+
+### Exiting LinkMeIn: `exit`
+_You are done tracking for the day and wish to exit LinkMeIn. Simply use the `exit` command to bid farewell to LinkMeIn._
+
+**Format:** `exit`
+
+
+**:information_source: Note:**
+* Don't worry about losing your data; it's safe with LinkMeIn, thanks to automatic saving!
-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`
+[↑ Back to Table of Contents](#table-of-contents)
+
+
+
+### Accessing Help: `help`
-### Listing all persons : `list`
+_You find yourself wrecking your brains just to think of that one command that you need to use. Just use the `help` command to access our User Guide, and you can easily get the help you need!_
-Shows a list of all persons in the address book.
+**Format:** `help`
-Format: `list`
+Simply copy the link provided and paste it into your web browser to access LinkMeIn's User Guide!
-### Editing a person : `edit`
+![img.png](images/help-command/helpcommand.png)
-Edits an existing person in the address book.
+[↑ Back to Table of Contents](#table-of-contents)
-Format: `edit INDEX [n/NAME] [p/PHONE] [e/EMAIL] [a/ADDRESS] [t/TAG]…`
+
-* 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.
+## Company Management Features
+These features are designed to make managing individual companies in LinkMeIn a breeze for you! Read on further to find out more about them!
-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.
+### Adding a Company : `add`
-### Locating persons by name: `find`
+_You scroll through your LinkedIn feed and see a company that you are interested in.
+You wish to start on the application later, but you are afraid that you will forget about it.
+Add the company to LinkMeIn now to keep track of the application process using the `add` command!_
-Finds persons whose names contain any of the given keywords.
+**Format**:
+`add c/COMPANY_NAME r/ROLE s/APPLICATION_STATUS d/DEADLINE n/RECRUITER_NAME e/EMAIL p/PHONE_NUMBER [pr/PRIORITY]`
-Format: `find KEYWORD [MORE_KEYWORDS]`
+> All [**parameters**](#parameters-description) specified in the format are compulsory except for PRIORITY.
+
+
+**:information_source: Note:**
+* Parameters can be in any order.
+
-* 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).
- e.g. `Hans Bo` will return `Hans Gruber`, `Bo Yang`
+**Examples:**
-Examples:
-* `find John` returns `john` and `John Doe`
-* `find alex david` returns `Alex Yeoh`, `David Li`
- ![result for 'find alex david'](images/findAlexDavidResult.png)
+If you've completed the Quick Tour of LinkMeIn, you've likely added a few companies to your app. If not, you can refer to the [Quick Tour Section](#1-adding-a-company) for guidance on adding companies.
-### Deleting a person : `delete`
+Here are some other examples of `add` commands that you can try:
+- `add c/Uber r/Software Engineer s/PA n/Mavis d/02-03-2023 e/mavis@example.com p/88284452 pr/low`
+- `add c/Oracle r/Data Analyst s/PA n/Marry Lim d/12-11-2023 e/marrylim@example.com p/98452321`
-Deletes the specified person from the address book.
+
-Format: `delete INDEX`
+**Possible Error:**
-* 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, …
+If you made a mistake for any of the parameters input, you will see an error message in the Message Box informing you of the specific error message. Don't worry, just update your input accordingly and try again! An example of the error message is shown below.
-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.
+![img.png](images/add-command/AddCommandError2.png)
-### Clearing all entries : `clear`
+[↑ Back to Table of Contents](#table-of-contents)
-Clears all entries from the address book.
+### Viewing Full Company's Information: `view`
-Format: `clear`
+_You look at the list of companies, and you realise that it's been 3 weeks since the interview, yet the company has not gotten back to you.
+With the `view` command, you can easily view the full details of a specific company, including the recruiter's contact details, and follow up with them!_
+
+**Format:** `view INDEX`
+
+> `INDEX` must be a positive integer less than or equal to the maximum integer (i.e., 1, 2, 3, ..., 2147483647). It must also not be greater than the number of companies in the list.
+
+
+**:information_source: Note:**
+* You can only view the full details of one company at any time.
+
-### Exiting the program : `exit`
+**Examples:**
-Exits the program.
+If you've completed the Quick Tour of LinkMeIn, you've likely viewed a few companies. If not, you can refer to the [Quick Tour Section](#2-viewing-company-details) for guidance on viewing companies!
-Format: `exit`
+Here are some other examples of `view` commands that you can try:
+- `view 1`
+- `view 4`
-### Saving the data
+
-AddressBook data are saved in the hard disk automatically after any command that changes the data. There is no need to save manually.
+**Possible Error:**
-### Editing the data file
+If you have entered an [**invalid index**](#5-what-is-an-invalid-index), you will see an error message in the Message Box as shown below. Don’t worry, just edit your index accordingly and try the command again!
-AddressBook data are saved automatically as a JSON file `[JAR file location]/data/addressbook.json`. Advanced users are welcome to update data directly by editing that data file.
+![img.png](images/view-command/ViewCommandError.png)
-
: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. Hence, it is recommended to take a backup of the file before editing it.
+[↑ Back to Table of Contents](#table-of-contents)
+
+### Deleting a Company : `delete`
+
+_Whether you accidentally added a company or no longer want to track it, don't worry! LinkMeIn has got you covered!
+You can use the `delete` command to delete any company from your list of companies._
+
+**Format:`delete INDEX`**
+
+> `INDEX` must be a positive integer less than or equal to the maximum integer (i.e., 1, 2, 3, ..., 2147483647). It must also not be greater than the number of companies in the list.
+
+
+**:information_source: Note:**
+* You can only delete one company at a time.
-### Archiving data files `[coming in v2.0]`
+**Examples:**
+
+If you've completed the Quick Tour of LinkMeIn, you've likely deleted a few companies. If not, you can refer to the [Quick Tour Section](#4-deleting-a-company) for guidance on deleting companies.
+
+Here are some other examples of `delete` commands that you can try:
+- `delete 1`
+- `delete 2`
+
+
+
+**Possible Error:**
+
+If you have entered an [**invalid index**](#5-what-is-an-invalid-index),
+you will see an error message in the Message Box as shown below. Don’t worry, just edit your index accordingly and try the command again!
+
+![img.png](images/delete-command/DeleteCommandError.png)
+
+[↑ Back to Table of Contents](#table-of-contents)
+
+
+
+### Adding Remarks to a Company: `remark`
+
+_After adding a company, you wish to note down more information such as the job description, pre-requisites and mental notes for yourself! Just use the `remark` command to input these additional details!_
+
+**Format:** `remark INDEX re/REMARK`
+
+> `INDEX` must be a positive integer less than or equal to the maximum integer (i.e., 1, 2, 3, ..., 2147483647). It must also not be greater than the number of companies in the list.
+>
+> Remarks cannot be empty.
+
+
+**:exclamation: Warning:**
+* When adding remarks, the existing remarks of the company is not cumulative. This means that whenever you type new remarks, your existing remarks will be completely overwritten!
+
+
+**Examples:**
+
+**Step 1.** After adding the internship for DSTA into LinkMeIn,
+you want to note that this internship requires experience in Java.
+
+
+
+**Step 2.** To note this down, type `remark 3 re/need Java` and press `Enter`.
+
+![RemarkDemo1.png](images/remark-command/RemarkDemo1.png)
+
+
+
+**Step 3.** You can view the remarks of the 3rd company as shown below in the Company Detail Panel.
+
+![RemarkDemo2.png](images/remark-command/RemarkDemo2.png)
+
+Here are some other examples of `remark` commands that you can try:
+- `remark 4 re/interview went well!`
+- `remark 5 re/$800 per month`
+
+
-_Details coming soon ..._
+**Possible Error:**
---------------------------------------------------------------------------------------------------------------------
+If you have entered an **empty remark**,
+you will see an error message in the Message Box as shown below. Don’t worry, just try again with remarks now!
+
+![RemarkErrMsg.png](images/remark-command/RemarkErrMsg.png)
+
+
+**:bulb: Useful Tip:**
+* However, if you intend to delete the existing remarks of a company and hence entered an empty remark, you should use the `unremark` command instead.
+
+
+[↑ Back to Table of Contents](#table-of-contents)
+
+
+
+### Deleting Remarks of a Company: `unremark`
+
+_You have previously added some remarks to a company, but the remarks have become outdated and you no longer need them anymore. Use the `unremark` command to quickly delete them._
+
+**Format:** `unremark INDEX`
+
+> `INDEX` must be a positive integer less than or equal to the maximum integer (i.e., 1, 2, 3, ..., 2147483647). It must also not be greater than the number of companies in the list.
+
+
+**:bulb: Useful Tip:**
+* To add new remarks, you do **NOT** need to delete the existing remarks using `unremark` command first. Directly use the `remark` command to add your new remarks.
+
+
+
+**:information_source: Note:**
+* You can unremark a company that already has no remarks.
+LinkMeIn does not check for the existence of remarks.
+The same success message will be displayed regardless of whether remarks exist for a company.
+
+
+
+
+**Example:**
+
+**Step 1.** If you wish to delete the remarks of DSTA company, which is 3rd in the Company List Panel, type `unremark 3` and press `Enter`.
+
+![UnremarkDemo1.png](images/remark-command/UnremarkDemo1.png)
+
+
+
+**Step 2.** The remarks of DSTA will be removed as shown below.
+
+![UnremarkDemo2.png](images/remark-command/UnremarkDemo2.png)
+
+**Possible Error:**
+
+If you have entered an [**invalid index**](#5-what-is-an-invalid-index),
+you will see an error message in the Message Box as shown below. Don’t worry, just edit your index accordingly and try the command again!
+
+![UnremarkErrMsg.png](images/remark-command/UnremarkErrMsg.png)
+
+[↑ Back to Table of Contents](#table-of-contents)
+
+
+
+### Editing a Company's Information: `edit`
+
+_You look at the details of the application, and realise that you have made a typo or need to update the progress of application. Use the `edit` command to input the accurate details._
+
+**Format:** `edit INDEX [c/COMPANY_NAME] [n/RECRUITER_NAME] [r/ROLE] [s/APPLICATION_STATUS] [d/DEADLINE] [e/EMAIL] [p/PHONE_NUMBER] [pr/PRIORITY]`
+
+> `INDEX` must be a positive integer less than or equal to the maximum integer (i.e., 1, 2, 3, ..., 2147483647). It must also not be greater than the number of companies in the list.
+>
+> At least one of the optional parameters must be provided.
+
+**Examples:**
+
+If you've completed the Quick Tour of LinkMeIn, you've likely edited a few companies. If not, you can refer to the [Quick Tour Section](#3-editing-company-details) for guidance on editing companies.
+
+Here are some more examples of `edit` commands that you can try:
+
+- `edit 3 d/11-09-2025 pr/LOW`
+ Edits the deadline and priority of the 3rd company in the displayed list.
+
+- `edit 1 n/Amy Tan e/amytan@gmail.com`
+ Edits the recruiter's name and email of the 1st company in the displayed list.
+
+**Possible Error:**
+
+If you have entered an **invalid prefix**, you will see an error message in the Message Box. Don’t worry, just edit your prefixes accordingly and
+try the command again! An example of an invalid input and error message is shown below.
+![EditErrMsg.png](images/edit-command/EditErrMsg.png)
+
+[↑ Back to Table of Contents](#table-of-contents)
+
+
+
+### Duplicate Detection
+
+_Seeking an internship but worried about double-applying?
+Our duplicate detection swiftly ensures you never submit the same application twice!_
+
+If you attempt to **add** or **edit** an application, you might accidentally create a duplicate entry with the same **company name**, **role**, and **deadline** as an existing company in LinkMeIn. An error message will be displayed in the Message Box, informing you of the **company name**, **role** and **deadline** of that duplicate company.
+
+
+**:information_source: Note:**
+* LinkMeIn's duplicate check is case-insensitive (e.g., `tiktok` is the same as `TikTok`).
+
+
+**Example 1:**
+Suppose you attempt to add a company with the **exact same company and recruiter information** as an existing entry in LinkMeIn, you will be notified of the duplicate company, as seen below.
+
+![img.png](images/duplicate-detection/add-command/duplicate-exact-match.png)
+
+
+
+**Example 2:**
+If you attempt to add a company with the **same company name, role and deadline**, but different recruiter information, you will be see an error message similar to that in Example 1. However, in this case, LinkMeIn will also prompt you to edit the parameter that differs from the duplicate company, recognizing that you may have accidentally used the `add` command instead of the `edit` command.
+
+![img.png](images/duplicate-detection/add-command/duplicate-partial-match.png)
+
+
+
+**Example 3:**
+LinkMeIn's duplicate check does not stop with adding entries. If you attempt to **edit** an application, creating a
+duplicate entry with the **same company name, role, and deadline** as an existing application in LinkMeIn,
+an error message will be displayed in the Message Box, notifying you of the duplicate company as seen below.
+
+![img.png](images/duplicate-detection/edit-command/duplicate-edit.png)
+
+[↑ Back to Table of Contents](#table-of-contents)
+
+
+
+## Company List Features
+These features are crafted to simplify the management of your list of companies in LinkMeIn! Continue reading to discover more about how they work!
+
+### Finding a Company: `find`
+
+_You've applied to many companies, and now you wish to monitor your internship applications for a specific company. Use the find command for a swift and efficient way to locate the company you want!_
+
+**Format:** `find KEYWORD [MORE_KEYWORDS]...`
+> KEYWORD must be at least 1 character long. Multiple keywords can be provided.
+
+
+**:information_source: Notes:**
+* The `find` command searches only the company name.
+* Companies with names that contain **any** of the keywords will be returned.
+* Keyword is case-insensitive (e.g. `tiktok` will match `TikTok`).
+* The order of your keywords doesn't matter (e.g. `tiktok google` will match `google tiktok`).
+* LinkMeIn's `find` command will always find from the **full** list of companies. This means that if you have previously used `filter`, performing `find`, will not search from the filtered list of companies.
+
+
+
+**:bulb: Useful Tip:**
+* You don't have to type the full name of the company. Partial names work too! For example, `tik` will match
+`tiktok`. Use this to find companies quickly!
+
+
+
+
+**Example:**
+
+**Step 1:** Let's say you want to follow up on a DSTA application. Simply type `find ds` to search for DSTA.
+
+![img.png](images/find-command/BeforeFind.png)
+
+
+
+**Step 2:** You will see the list of companies that match your search criteria. In this case, the company DSTA will be
+shown. And that is it! You have found the company you wanted.
+
+![img.png](images/find-command/AfterFind.png)
+
+[↑ Back to Table of Contents](#table-of-contents)
+
+
+
+### Listing All Companies: `list`
+
+_You've found the specific company you wanted using the find command earlier, and now you want to see all of your applications in one list again. You can do so easily with the `list` command!_
+
+**Format:** `list`
+
+**Example:**
+
+**Step 1:** You have used the `find` command to find the company _DSTA_ earlier. Now, to view the full list of companies again, simply type `list` and press `Enter`!
+
+![img.png](images/list-command/ListCommand.png)
+
+
+**:information_source: Note:**
+* Upon launching LinkMeIn, you will see your full list of companies (i.e., `list` command is executed automatically).
+
+
+[↑ Back to Table of Contents](#table-of-contents)
+
+
+
+### Filtering Companies by Application Status: `filter`
+
+_Can't remember which applications you haven't submitted or want to prepare for the companies that have offered you an interview?
+Filter the list of companies by their application status using the `filter` command!_
+
+**Format:** `filter s/APPLICATION_STATUS`
+
+> [**APPLICATION_STATUS**](#application-status-parameter-description) should be one of the following: `PA`, `PI`, `PO`, `A`, `R`.
+
+
+**:information_source: Note:**
+* LinkMeIn's `filter` command will always filter from the **full** list of companies. This means that if you have previously used `find`, performing `filter`, will not filter from the list of companies that you have searched for.
+
+
+
+
+**Example:**
+
+**Step 1:** You wish to prepare for the upcoming interviews that you have secured.
+
+**Step 2:** Simply type `filter s/PI` to filter the list of companies to show only companies with status "Pending Interview" and press `Enter`.
+
+![img.png](images/filter-command/FilterByPI.png)
+
+
+
+**Step 3:** You can then check the Company List Panel for all the companies where you have pending interviews.
+
+![img.png](images/filter-command/AfterFilterCommand.png)
+
+**Possible Error:**
+
+If you enter an invalid prefix for the filter command, you will see an error message informing you of the invalid command, and suggest the correct format to follow.
+
+![img.png](images/filter-command/FilterCommandError.png)
+
+[↑ Back to Table of Contents](#table-of-contents)
+
+
+
+### Sorting Companies by Deadlines: `sort`
+
+_Want to see which application deadlines are coming up soon or which ones are far off? Use the `sort` command to
+arrange your list of applications based on their deadlines!_
+
+**Format:** `sort SORT_ORDER`
+> SORT_ORDER should be one of the following: `ascending`, `a`, `asc` for ascending order, and `descending`, `d`, `desc` for descending order.
+
+
+**:information_source: Notes:**
+* Ascending order means that the nearest deadlines will be shown first.
+* Descending order means that the furthest deadlines will be shown first.
+* The case of `SORT_ORDER` does not matter (e.g., `ASCENDING` and `ascending` are treated the same).
+
+
+
+**:bulb: Useful Tip:**
+* If no `SORT_ORDER` is specified, it will be set to `ascending` by default. Use this to quickly see which deadlines are
+coming up soon by simply typing `sort`!
+
+
+
+
+**Example:**
+
+**Step 1.** You've lost track of time and are uncertain about which internship deadlines are looming. Your current
+list looks chaotic. Just type `sort ascending` to sort the list of applications by their deadlines.
+
+![typecommand.png](images/sort-command/BeforeSorting.png)
+
+
+
+**Step 2.** Your applications are now organized by upcoming deadlines. Time to start applying without delay!
+
+![img.png](images/sort-command/AfterSorting.png)
+
+**Possible Error:**
+
+Suppose you misspelled the `SORT-ORDER` keyword, you will see an error message informing you of the invalid keyword,
+and suggest the correct keyword to use:
+
+![img.png](images/sort-command/SortError.png)
+
+[↑ Back to Table of Contents](#table-of-contents)
+
+---
+
+
+## Glossary
+
+### Definitions of Key Terms
+
+Encountered an unfamiliar term when using LinkMeIn? Read the respective descriptions to better understand the term!
+
+| Term | Definition |
+|----------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| **Alphanumeric** | Alphanumeric refers to a character set that includes both letters and numbers. It includes the 26 letters of the English alphabet (both uppercase and lowercase) and the numbers 0 through 9. |
+| **Case-insensitive** | Upper case and lower case are being treated the same way. For example, `tiktok` and `TikTok` will be considered the same. |
+| **CLI** | Command-Line Interface (CLI) is a text-based user interface where users interact with the application by typing commands. |
+| **Command** | A command is an instruction given by a user to LinkMeIn to perform a specific action. For example,`add` command is a command to add the company's application into LinkMeIn. |
+| **GUI** | Graphical User Interface (GUI) is a visual method to interact with software using icons, buttons, and windows. GUI provides a user-friendly way to interact with software using graphical elements rather than text-based commands. |
+| **Index** | Refers to the index number shown in the displayed company list. |
+| **JAR** | JAR stands for Java Archive and is a package file format typically used to aggregate many Java class files and associated metadata and resources into one file for distribution. |
+| **JSON** | JSON stands for JavaScript Object Notation. It is lightweight format for data interchange, easy to read and write for humans, and easy to parse for machines. Often used in web applications and configuration files. |
+| **Parameter** | Parameter is similar to a field in a form you have to fill up. For example, in the command `edit 1 c/COMPANY_NAME e/EMAIL`, `COMPANY_NAME` and `EMAIL` are parameters in the command. |
+| **Prefix** | Prefix is a keyword that is used to identify the parameter. For example, in the command `edit 1 c/COMPANY_NAME e/EMAIL`, `c/` and `e/` are prefixes. |
+
+
+
+### Parameters Description
+
+| Parameter | Description | Constraints |
+|--------------------|-----------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------|
+| COMPANY_NAME | Name of the company that you are applying to. | Only contain alphanumeric characters and spaces, and should not be blank. Maximum of 100 characters (excluding spaces). |
+| ROLE | Role of the internship that you are applying. | Only contain alphanumeric characters and spaces, and should not be blank. Maximum of 100 characters (excluding spaces). |
+| APPLICATION_STATUS | Status of the application. | Case-insensitive. Refer to [Application Status Description](#application-status-parameter-description) for all possible inputs. |
+| DEADLINE | Deadline of the application. | Should be in DD-MM-YYYY format. Dates before the current date are allowed. |
+| RECRUITER_NAME | Name of the recruiter. | Only contain alphanumeric characters and spaces, and should not be blank. Maximum of 100 characters (excluding spaces). |
+| EMAIL | Email of the recruiter. | Should be in the format of [`local-part@domain`](#email-format-description) and should not be blank. |
+| PHONE_NUMBER | Phone number of the recruiter. | Only contain numbers, be at least 3 digits and at most 20 digits long. Should not be blank. |
+| PRIORITY | Priority of the application. | Case-insensitive and should be one of the following: `high`, `medium`, `low`, `none`.
|
+| REMARK | Remark of the application. | Should not be blank. |
+
+
+
+**:information_source: Note:**
+* If you enter an invalid input for any of the prefixes, you will see an error message in the command box. Refer to the error message, check the description for the respective prefix and try the command again! An example of an error message is shown below.
+
+![img.png](images/add-command/AddCommandError.png)
+
+
+
+
+#### Application Status Parameter Description
+
+| Application Status | Other Accepted Inputs | What it means |
+|-----------------------|-------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------|
+| `PENDING APPLICATION` | `PA`, `PENDAPP`, `PENDINGAPP`, `PENDINGAPPLICATION`, `P A`, `PENDING A` | You have not submitted the application, but are currently working on it. |
+| `PENDING INTERVIEW` | `PI`, `PENDINT`, `PENDINGINT`, `PENDINGINTERVIEW`, `P I`, `PENDING I` | You have submitted the application, and are either waiting for an interview offer, or waiting to go for the interview. |
+| `PENDING OUTCOME` | `PO`, `PENDOUT`, `PENDINGOUT`, `PENDINGOUTCOME`, `P O`, `PENDING O` | You have went through the interview, but the final decision or outcome (whether accepted or rejected) hasn't been communicated yet. |
+| `ACCEPTED` | `A`, `ACC`, `ACPT`, `ACCEPT` | You have been offered the internship position. Congratulations! |
+| `REJECTED` | `R`, `REJ`, `REJECT` | Unfortunately, the application wasn't successful and you were not offered the internship. Don't worry, try again next time! |
+
+
+
+#### Email Format Description
+The email format is `local-part@domain`.
+
+`local-part` constraints:
+* Only contain alphanumeric characters and these special characters, excluding the parentheses, (+_.-).
+* May not start or end with any special characters.
+
+`domain` name constraints:
+* Made up of domain labels separated by periods.
+* End with a domain label at least 2 characters long
+* Have each domain label start and end with alphanumeric characters
+* Have each domain label consist of alphanumeric characters, separated only by hyphens, if any.
+
+[↑ Back to Table of Contents](#table-of-contents)
+
+---
+
## FAQ
-**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.
+### 1. How do I check if I have Java 11 installed?
+
+* Open up your terminal. If you are unsure of how to do so, you can refer [here](#2-how-do-i-open-up-my-terminal).
+* Type `java -version`. If you have Java installed, you will see the following:
+
+![img.png](images/quick-start/java11.png)
+
+* If you do not have Java installed, you can download it [here](https://www.oracle.com/sg/java/technologies/downloads/#java11).
+ Remember to download the Java 11 version.
+* You can refer to the guides below to install Java 11 for your respective operating systems:
+ * [Windows Guide](https://www.java.com/en/download/help/windows_manual_download.html) to install Java.
+ * [macOS Guide](https://www.java.com/en/download/help/mac_install.html) to install Java.
+ * [Linux Guide](https://www.java.com/en/download/help/linux_x64_install.html) to install Java.
+
+[↑ Back to Quick Start](#quick-start)
+
+
+
+### 2. How do I open up my terminal?
+* **Windows:** Click the Windows Start button, and type **'Command Prompt'** or **'cmd'** into the search bar.
+ Press Enter to open it.
+* **macOS:** Click on **'F4'** and type **'terminal'**. Press Enter when it appears in the
+ search results.
+* **Linux:** Press **'Ctrl'**, **'Alt'** and **'T'** simultaneously to open the terminal.
+
+[↑ Back to Quick Start](#quick-start)
---------------------------------------------------------------------------------------------------------------------
+### 3. How do I load data from another computer?
-## Known issues
+Delete the `companydata.json` file stored at `[JAR file location]/data/companydata.json` from the computer that you
+wish to use LinkMeIn on (refer to image below).
-1. **When using multiple screens**, if you move the application to a secondary screen, and later switch to using only the primary screen, the GUI will open off-screen. The remedy is to delete the `preferences.json` file created by the application before running the application again.
+![img.png](images/CompanyDataLocation.png)
---------------------------------------------------------------------------------------------------------------------
+Then, copy over the `companydata.json` file from the other computer. And that's it! Just start LinkMeIn to
+check whether your data is properly loaded into the new computer and you're good to go!
-## Command summary
+### 4. Why am I unable to run LinkMeIn?
-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`
+Make sure you have Java 11 installed on your machine as the product only runs on Java 11.
+
+
+
+### 5. What is an invalid index?
+
+An invalid index is a non-positive integer or an index greater than the number of companies you have.
+Examples: -1, 0, a, \*, 1 0 (Only one index is allowed at a time). Positive index should not exceed the maximum allowed
+range of 2147483647.
+
+### 6. Do I need an internet connection to use LinkMeIn?
+
+LinkMeIn is an offline application that functions well without an internet connection. However, an Internet connection is required to download the application.
+
+### 7. How do I save my data on LinkMeIn?
+
+With LinkMeIn, there is no need for you to save manually. Everything is saved automatically for you.
+
+[↑ Back to Table of Contents](#table-of-contents)
+
+---
+
+
+## Command Summary
+
+| Command | Format | Example |
+|----------|----------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------|
+| `add` | `add c/COMPANY_NAME r/ROLE s/APPLICATION_STATUS d/DEADLINE n/RECRUITER_NAME e/EMAIL p/PHONE_NUMBER [pr/PRIORITY]` | `add c/Apple r/Software Engineer s/PA d/12-12-2023 n/John Tan e/johntan@gmail.com p/98765432` |
+| `view` | `view INDEX` | `view 1` |
+| `delete` | `delete INDEX` | `delete 1` |
+| `remark` | `remark INDEX re/REMARK` | `remark 1 re/need Java` |
+| `list` | `list` | `list` |
+| `filter` | `filter s/APPLICATION_STATUS` | `filter s/PI` |
+| `sort` | `sort SORT_ORDER` | `sort ascending` |
+| `edit` | `edit INDEX [c/COMPANY_NAME] [n/RECRUITER_NAME] [r/ROLE] [s/APPLICATION_STATUS] [d/DEADLINE] [e/EMAIL] [p/PHONE_NUMBER] [pr/PRIORITY] [re/REMARK]` | `edit 1 s/PI r/Frontend Developer` |
+| `find` | `find KEYWORD [MORE_KEYWORDS]...` | `find ds` |
+| `clear` | `clear` | `clear` |
+| `exit` | `exit` | `exit`
|
+| `help` | `help` | `help` |
+
+[↑ Back to Table of Contents](#table-of-contents)
diff --git a/docs/_config.yml b/docs/_config.yml
index 6bd245d8f4e..482a6da2e3c 100644
--- a/docs/_config.yml
+++ b/docs/_config.yml
@@ -1,4 +1,4 @@
-title: "AB-3"
+title: "LinkMeIn"
theme: minima
header_pages:
@@ -8,7 +8,7 @@ header_pages:
markdown: kramdown
-repository: "se-edu/addressbook-level3"
+repository: "AY2324S1-CS2103T-T17-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..cee47b86288 100644
--- a/docs/_sass/minima/_base.scss
+++ b/docs/_sass/minima/_base.scss
@@ -288,7 +288,7 @@ table {
text-align: center;
}
.site-header:before {
- content: "AB-3";
+ content: "LinkMeIn";
font-size: 32px;
}
}
diff --git a/docs/assets/css/style.scss b/docs/assets/css/style.scss
index b5ec6976efa..c7facf4a5e0 100644
--- a/docs/assets/css/style.scss
+++ b/docs/assets/css/style.scss
@@ -3,10 +3,13 @@
---
@import
- "minima/skins/{{ site.minima.skin | default: 'classic' }}",
- "minima/initialize";
+"minima/skins/{{ site.minima.skin | default: 'classic' }}",
+"minima/initialize";
-.icon {
- height: 21px;
- width: 21px
+blockquote {
+ font-size: 1rem; /* This sets the font size to the base font size, which should match your normal text if that's also set to 1rem */
+ margin-left: 20px; /* Adjust as needed to match your layout */
+ padding-left: 20px; /* Adjust as needed for padding inside the blockquote */
+ border-left: 4px solid #d3d3d3; /* A typical blockquote border, adjust the color as needed */
+ /* Other styles as needed to match your typography */
}
diff --git a/docs/diagrams/AddActivityDiagram.puml b/docs/diagrams/AddActivityDiagram.puml
new file mode 100644
index 00000000000..8c2ce80dfaa
--- /dev/null
+++ b/docs/diagrams/AddActivityDiagram.puml
@@ -0,0 +1,25 @@
+@startuml
+skin rose
+skinparam ActivityFontSize 12
+skinparam ArrowFontSize 12
+start
+:User executes AddCommand;
+
+'Since the beta syntax does not support placing the condition outside the
+'diamond we place it as the true branch instead.
+
+if () then ([user input is valid])
+ if () then ([company already exists])
+ :System displays duplicate company error message;
+ else ([else])
+ :System inserts company to list of companies;
+ :System displays added company in CompanyListPanel;
+ :System displays added company in CompanyDetailPanel;
+ endif
+
+else ([else])
+:System displays specific error message;
+
+endif
+stop
+@enduml
diff --git a/docs/diagrams/AddSequenceDiagram.puml b/docs/diagrams/AddSequenceDiagram.puml
new file mode 100644
index 00000000000..24a96a430af
--- /dev/null
+++ b/docs/diagrams/AddSequenceDiagram.puml
@@ -0,0 +1,101 @@
+@startuml
+!include style.puml
+skinparam ArrowFontStyle plain
+
+box Logic LOGIC_COLOR_T1
+
+participant ":LogicManager" as LogicManager LOGIC_COLOR
+participant ":AddressBookParser" as AddressBookParser LOGIC_COLOR
+participant ":AddCommandParser" as AddCommandParser LOGIC_COLOR
+participant "c:Company" as Company MODEL_COLOR
+participant "a:AddCommand" as AddCommand LOGIC_COLOR
+participant ":CommandResult" as CommandResult LOGIC_COLOR
+
+end box
+
+box Model MODEL_COLOR_T1
+participant "m:ModelManager" as Model MODEL_COLOR
+end box
+
+note left of LogicManager
+ In the diagram, params refers to the following:
+ "c/Google r/Software Engineer
+ s/PA d/10-10-2023 n/Francis Tan
+ p/98765432 e/francist@gmail.com"
+end note
+
+[-> LogicManager : execute(params)
+activate LogicManager
+
+LogicManager -> AddressBookParser : parseCommand(params)
+activate AddressBookParser
+
+create AddCommandParser
+AddressBookParser -> AddCommandParser
+activate AddCommandParser
+
+AddCommandParser --> AddressBookParser
+deactivate AddCommandParser
+
+AddressBookParser -> AddCommandParser : parse(params)
+activate AddCommandParser
+
+create Company
+AddCommandParser -> Company: Company(...)
+activate Company
+
+Company --> AddCommandParser
+deactivate Company
+
+create AddCommand
+AddCommandParser -> AddCommand
+activate AddCommand
+
+AddCommand --> AddCommandParser : a
+deactivate AddCommand
+
+
+AddCommandParser --> AddressBookParser : a
+deactivate AddCommandParser
+'Hidden arrow to position the destroy marker below the end of the activation bar.
+AddCommandParser -[hidden]-> AddressBookParser
+destroy AddCommandParser
+
+AddressBookParser --> LogicManager : a
+deactivate AddressBookParser
+
+LogicManager -> AddCommand : execute(m)
+activate AddCommand
+
+AddCommand -> Model : hasCompany(c)
+activate Model
+
+Model --> AddCommand
+deactivate Model
+
+AddCommand -> Model : addCompany(c)
+activate Model
+
+Model --> AddCommand
+deactivate Model
+
+AddCommand -> Model : setCurrentViewedCompany(c)
+activate Model
+
+Model --> AddCommand
+deactivate Model
+
+create CommandResult
+AddCommand -> CommandResult
+activate CommandResult
+
+CommandResult --> AddCommand
+deactivate CommandResult
+
+AddCommand --> LogicManager
+deactivate AddCommand
+
+[<--LogicManager
+deactivate LogicManager
+
+@enduml
diff --git a/docs/diagrams/ArchitectureSequenceDiagram.puml b/docs/diagrams/ArchitectureSequenceDiagram.puml
index 48b6cc4333c..ea564e5cb83 100644
--- a/docs/diagrams/ArchitectureSequenceDiagram.puml
+++ b/docs/diagrams/ArchitectureSequenceDiagram.puml
@@ -14,7 +14,7 @@ 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 : deleteCompany(p)
activate model MODEL_COLOR
model -[MODEL_COLOR]-> logic
diff --git a/docs/diagrams/BetterModelClassDiagram.puml b/docs/diagrams/BetterModelClassDiagram.puml
index 598474a5c82..bf3bb90075b 100644
--- a/docs/diagrams/BetterModelClassDiagram.puml
+++ b/docs/diagrams/BetterModelClassDiagram.puml
@@ -4,18 +4,18 @@ 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
+AddressBook *-right-> "1" UniqueCompanyList
-UniqueTagList -right-> "*" Tag
-UniquePersonList -right-> Person
+UniqueCompanyList -right-> Company
-Person -up-> "*" Tag
-
-Person *--> Name
-Person *--> Phone
-Person *--> Email
-Person *--> Address
+Company *--> Name
+Company *--> Phone
+Company *--> Email
+Company *--> Address
+Company *--> ApplicationStatus
+Company *--> Deadline
+Company *--> RecruiterName
+Company *--> Role
+Company *--> Priority
+Company *--> Remark
@enduml
diff --git a/docs/diagrams/CompanyDetailPanelActivityDiagram.puml b/docs/diagrams/CompanyDetailPanelActivityDiagram.puml
new file mode 100644
index 00000000000..0ca53b4d2f6
--- /dev/null
+++ b/docs/diagrams/CompanyDetailPanelActivityDiagram.puml
@@ -0,0 +1,24 @@
+@startuml
+skin rose
+skinparam ActivityFontSize 15
+skinparam ArrowFontSize 12
+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 ([view, edit or add command])
+ :Clear UniqueCompanyList;
+ :Add the company to
+ UniqueCompanyList;
+ :Company detail panel displays company;
+else ([delete command])
+ if () then ([viewing the company to be deleted])
+ :Clear company detail panel;
+ else ([else])
+ endif
+
+endif
+stop
+@enduml
diff --git a/docs/diagrams/DeleteSequenceDiagram.puml b/docs/diagrams/DeleteSequenceDiagram.puml
index 40ea6c9dc4c..bf760d7dce2 100644
--- a/docs/diagrams/DeleteSequenceDiagram.puml
+++ b/docs/diagrams/DeleteSequenceDiagram.puml
@@ -11,7 +11,7 @@ participant ":CommandResult" as CommandResult LOGIC_COLOR
end box
box Model MODEL_COLOR_T1
-participant ":Model" as Model MODEL_COLOR
+participant "m:ModelManager" as Model MODEL_COLOR
end box
[-> LogicManager : execute("delete 1")
@@ -46,10 +46,10 @@ destroy DeleteCommandParser
AddressBookParser --> LogicManager : d
deactivate AddressBookParser
-LogicManager -> DeleteCommand : execute()
+LogicManager -> DeleteCommand : execute(m)
activate DeleteCommand
-DeleteCommand -> Model : deletePerson(1)
+DeleteCommand -> Model : deleteCompany(1)
activate Model
Model --> DeleteCommand
diff --git a/docs/diagrams/DetailPanelClassDiagram.puml b/docs/diagrams/DetailPanelClassDiagram.puml
new file mode 100644
index 00000000000..d82c6e3c324
--- /dev/null
+++ b/docs/diagrams/DetailPanelClassDiagram.puml
@@ -0,0 +1,30 @@
+@startuml
+!include style.puml
+skinparam arrowThickness 1.1
+skinparam arrowColor UI_COLOR_T4
+skinparam classBackgroundColor UI_COLOR
+
+package UI <>{
+Class MainWindow
+Class CompanyDetailPanel
+Class CompanyDetailCard
+Class "{abstract}\nUiPart" as UiPart
+Class CompanyCardUtils {
+ createPriorityFlowPane(Company, Boolean) : FlowPane
+}
+}
+package Model <> {
+Class HiddenModel #FFFFFF
+}
+
+MainWindow *-right-> "1" CompanyDetailPanel
+CompanyDetailPanel *-down-> "0...1" CompanyDetailCard
+CompanyDetailCard -right..> Model
+MainWindow -down-|> UiPart
+CompanyDetailPanel -down-|> UiPart
+CompanyDetailCard -down-|> UiPart
+CompanyDetailCard .down.> CompanyCardUtils
+
+show CompanyCardUtils members
+
+@enduml
diff --git a/docs/diagrams/DuplicateActivityDiagram.puml b/docs/diagrams/DuplicateActivityDiagram.puml
new file mode 100644
index 00000000000..6366f60166c
--- /dev/null
+++ b/docs/diagrams/DuplicateActivityDiagram.puml
@@ -0,0 +1,19 @@
+@startuml
+skin rose
+skinparam ActivityFontSize 15
+skinparam ArrowFontSize 12
+start
+
+'Since the beta syntax does not support placing the condition outside the
+'diamond we place it as the true branch instead.
+
+: Get the existing duplicate \n company from the model;
+:Get the index of the duplicate company from the \n filtered company list panel;
+if () then ([else])
+ :Get the index of the duplicate company from the \n full company list panel;
+else ([Duplicate company is in filtered company list panel])
+ endif
+: Get all the fields that were different between \nthe duplicate existing company and inputted company;
+:Format the error message with the fields and the index;
+stop
+@enduml
diff --git a/docs/diagrams/DuplicateSequenceDiagram.puml b/docs/diagrams/DuplicateSequenceDiagram.puml
new file mode 100644
index 00000000000..a321c174ecd
--- /dev/null
+++ b/docs/diagrams/DuplicateSequenceDiagram.puml
@@ -0,0 +1,76 @@
+@startuml
+!include style.puml
+skinparam ArrowFontStyle plain
+
+box "Logic" LOGIC_COLOR_T1
+participant ":EditCommand" as EditCommand LOGIC_COLOR
+end box
+
+box "Model" MODEL_COLOR_T1
+participant ":ModelManager" as ModelManager MODEL_COLOR
+participant ":AddressBook" as AddressBook MODEL_COLOR
+participant ":UniqueCompanyList" as UniqueCompanyList MODEL_COLOR
+participant "c:Company" as CompanyC MODEL_COLOR
+participant "d:Company" as CompanyD MODEL_COLOR
+end box
+
+EditCommand -> ModelManager : getDuplicateCompany(c)
+activate EditCommand
+activate ModelManager
+
+ModelManager -> AddressBook : getDuplicateCompany(c)
+activate AddressBook
+
+AddressBook -> UniqueCompanyList : contains(c)
+activate UniqueCompanyList
+
+loop for each company in UniqueCompanyList
+ UniqueCompanyList -> CompanyC : isSameCompany(d)
+ activate CompanyC
+ ' Self-invocation within Company
+ CompanyC -> CompanyD : getName()
+ activate CompanyD
+ CompanyD --> CompanyC
+ deactivate CompanyD
+
+ CompanyC -> CompanyC : getName()
+ activate CompanyC #DarkSlateGray
+ CompanyC --> CompanyC
+ deactivate CompanyC #DarkSlateGray
+
+ CompanyC -> CompanyD : getRole()
+ activate CompanyD
+ CompanyD --> CompanyC
+ deactivate CompanyD
+
+ CompanyC -> CompanyC : getRole()
+ activate CompanyC #DarkSlateGray
+ CompanyC --> CompanyC
+ deactivate CompanyC #DarkSlateGray
+
+ CompanyC -> CompanyD : getDeadline()
+ activate CompanyD
+ CompanyD --> CompanyC
+ deactivate CompanyD
+
+ CompanyC -> CompanyC : getDeadline()
+ activate CompanyC #DarkSlateGray
+ CompanyC --> CompanyC
+ deactivate CompanyC #DarkSlateGray
+
+ CompanyC --> UniqueCompanyList
+ deactivate CompanyC
+end
+
+UniqueCompanyList --> AddressBook
+deactivate UniqueCompanyList
+
+AddressBook --> ModelManager
+deactivate AddressBook
+
+ModelManager --> EditCommand
+deactivate ModelManager
+
+deactivate EditCommand
+
+@enduml
diff --git a/docs/diagrams/EditSequenceDiagram.puml b/docs/diagrams/EditSequenceDiagram.puml
new file mode 100644
index 00000000000..3bd3f0695b4
--- /dev/null
+++ b/docs/diagrams/EditSequenceDiagram.puml
@@ -0,0 +1,98 @@
+@startuml
+!include style.puml
+skinparam ArrowFontStyle plain
+
+box Logic LOGIC_COLOR_T1
+
+participant ":LogicManager" as LogicManager LOGIC_COLOR
+participant ":AddressBookParser" as AddressBookParser LOGIC_COLOR
+participant ":EditCommandParser" as EditCommandParser LOGIC_COLOR
+participant "d:EditCompanyDescriptor" as EditCompanyDescriptor LOGIC_COLOR
+participant "e:EditCommand" as EditCommand LOGIC_COLOR
+participant ":CommandResult" as CommandResult LOGIC_COLOR
+
+end box
+
+box Model MODEL_COLOR_T1
+participant "m:ModelManager" as Model MODEL_COLOR
+end box
+
+[-> LogicManager : execute("edit 1 r/SWE")
+activate LogicManager
+
+LogicManager -> AddressBookParser : parseCommand("edit 1 r/SWE")
+activate AddressBookParser
+
+create EditCommandParser
+AddressBookParser -> EditCommandParser
+activate EditCommandParser
+
+EditCommandParser --> AddressBookParser
+deactivate EditCommandParser
+
+AddressBookParser -> EditCommandParser : parse("1 r/SWE")
+activate EditCommandParser
+
+create EditCompanyDescriptor
+EditCommandParser -> EditCompanyDescriptor
+activate EditCompanyDescriptor
+
+EditCompanyDescriptor --> EditCommandParser : d
+deactivate EditCompanyDescriptor
+
+create EditCommand
+EditCommandParser -> EditCommand : EditCommand(1, d)
+activate EditCommand
+
+EditCommand --> EditCommandParser : e
+deactivate EditCommand
+
+EditCommandParser --> AddressBookParser : e
+deactivate EditCommandParser
+'Hidden arrow to position the destroy marker below the end of the activation bar.
+EditCommandParser -[hidden]-> AddressBookParser
+destroy EditCommandParser
+
+AddressBookParser --> LogicManager : e
+deactivate AddressBookParser
+
+LogicManager -> EditCommand : execute(m)
+activate EditCommand
+
+EditCommand -> Model : getCompany(1)
+activate Model
+
+Model --> EditCommand : target
+deactivate Model
+
+EditCommand -> EditCommand : createEditedCompany(target, d)
+activate EditCommand
+EditCommand --> EditCommand : c
+deactivate EditCommand
+
+EditCommand -> Model : setCompany(target, c)
+activate Model
+
+Model --> EditCommand
+deactivate Model
+
+EditCommand -> Model : setCurrentViewedCompany(c)
+activate Model
+
+Model --> EditCommand
+deactivate Model
+
+create CommandResult
+EditCommand -> CommandResult
+activate CommandResult
+
+CommandResult --> EditCommand
+deactivate CommandResult
+
+EditCommand --> LogicManager : result
+deactivate EditCommand
+
+[<--LogicManager
+deactivate LogicManager
+
+@enduml
diff --git a/docs/diagrams/FilterSequenceDiagram.puml b/docs/diagrams/FilterSequenceDiagram.puml
new file mode 100644
index 00000000000..72d6deda03a
--- /dev/null
+++ b/docs/diagrams/FilterSequenceDiagram.puml
@@ -0,0 +1,81 @@
+@startuml
+!include style.puml
+skinparam ArrowFontStyle plain
+
+box Logic LOGIC_COLOR_T1
+
+participant ":LogicManager" as LogicManager LOGIC_COLOR
+participant ":AddressBookParser" as AddressBookParser LOGIC_COLOR
+participant ":FilterCommandParser" as FilterCommandParser LOGIC_COLOR
+participant "p:ApplicationStatusPredicate" as ApplicationStatusPredicate MODEL_COLOR
+participant "f:FilterCommand" as FilterCommand LOGIC_COLOR
+participant ":CommandResult" as CommandResult LOGIC_COLOR
+
+end box
+
+box Model MODEL_COLOR_T1
+participant "m:ModelManager" as Model MODEL_COLOR
+end box
+
+[-> LogicManager : execute("filter s/pa")
+activate LogicManager
+
+LogicManager -> AddressBookParser : parseCommand("filter s/pa")
+activate AddressBookParser
+
+create FilterCommandParser
+AddressBookParser -> FilterCommandParser
+activate FilterCommandParser
+
+FilterCommandParser --> AddressBookParser
+deactivate FilterCommandParser
+
+AddressBookParser -> FilterCommandParser : parse("s/pa")
+activate FilterCommandParser
+
+create ApplicationStatusPredicate
+FilterCommandParser -> ApplicationStatusPredicate
+activate ApplicationStatusPredicate
+
+ApplicationStatusPredicate --> FilterCommandParser
+deactivate ApplicationStatusPredicate
+
+create FilterCommand
+FilterCommandParser -> FilterCommand
+activate FilterCommand
+
+FilterCommand --> FilterCommandParser : f
+deactivate FilterCommand
+
+FilterCommandParser --> AddressBookParser : f
+deactivate FilterCommandParser
+'Hidden arrow to position the destroy marker below the end of the activation bar.
+FilterCommandParser -[hidden]-> AddressBookParser
+destroy FilterCommandParser
+
+AddressBookParser --> LogicManager : f
+deactivate AddressBookParser
+
+LogicManager -> FilterCommand : execute(m)
+activate FilterCommand
+
+FilterCommand -> Model : filterCompaniesByStatus(p)
+activate Model
+
+Model -->FilterCommand
+deactivate Model
+
+create CommandResult
+FilterCommand -> CommandResult
+activate CommandResult
+
+CommandResult --> FilterCommand
+deactivate CommandResult
+
+FilterCommand --> LogicManager : result
+deactivate FilterCommand
+
+[<--LogicManager
+deactivate LogicManager
+
+@enduml
diff --git a/docs/diagrams/FindCompanySequenceDiagram.puml b/docs/diagrams/FindCompanySequenceDiagram.puml
new file mode 100644
index 00000000000..1df8d91c8f7
--- /dev/null
+++ b/docs/diagrams/FindCompanySequenceDiagram.puml
@@ -0,0 +1,78 @@
+@startuml
+!include style.puml
+skinparam ArrowFontStyle plain
+
+box Logic LOGIC_COLOR_T1
+participant ":LogicManager" as LogicManager LOGIC_COLOR
+participant ":AddressBookParser" as AddressBookParser LOGIC_COLOR
+participant ":FindCommandParser" as FindCommandParser LOGIC_COLOR
+participant "u:FindCommand" as FindCommand LOGIC_COLOR
+participant "u:CommandResult" as CommandResult LOGIC_COLOR
+participant "p :NameContainsKeywordsPredicate" as NameContainsKeywordsPredicate MODEL_COLOR
+end box
+
+box Model MODEL_COLOR_T1
+participant "m:ModelManager" as Model MODEL_COLOR
+end box
+
+[-> LogicManager : execute("find tech sta")
+activate LogicManager
+
+LogicManager -> AddressBookParser : parseCommand("find tech sta")
+activate AddressBookParser
+
+create FindCommandParser
+AddressBookParser -> FindCommandParser
+activate FindCommandParser
+
+FindCommandParser --> AddressBookParser
+deactivate FindCommandParser
+
+AddressBookParser -> FindCommandParser : parse("find tech sta")
+activate FindCommandParser
+
+create NameContainsKeywordsPredicate
+FindCommandParser -> NameContainsKeywordsPredicate
+activate NameContainsKeywordsPredicate
+
+NameContainsKeywordsPredicate --> FindCommandParser
+deactivate NameContainsKeywordsPredicate
+
+create FindCommand
+FindCommandParser -> FindCommand
+activate FindCommand
+
+FindCommand --> FindCommandParser : u
+deactivate FindCommand
+
+FindCommandParser --> AddressBookParser : u
+deactivate FindCommandParser
+'Hidden arrow to position the destroy marker below the end of the activation bar.
+FindCommandParser -[hidden]-> AddressBookParser
+destroy FindCommandParser
+
+AddressBookParser --> LogicManager : u
+deactivate AddressBookParser
+
+LogicManager -> FindCommand : execute(m)
+activate FindCommand
+
+FindCommand -> Model : updateFilteredCompanyList(p)
+activate Model
+
+Model --> FindCommand
+deactivate Model
+
+create CommandResult
+FindCommand -> CommandResult
+activate CommandResult
+
+CommandResult --> FindCommand
+deactivate CommandResult
+
+FindCommand --> LogicManager : result
+deactivate FindCommand
+
+[<--LogicManager
+deactivate LogicManager
+@enduml
diff --git a/docs/diagrams/ModelClassDiagram.puml b/docs/diagrams/ModelClassDiagram.puml
index 0de5673070d..d8e597c8f39 100644
--- a/docs/diagrams/ModelClassDiagram.puml
+++ b/docs/diagrams/ModelClassDiagram.puml
@@ -12,13 +12,18 @@ Class AddressBook
Class ModelManager
Class UserPrefs
-Class UniquePersonList
-Class Person
-Class Address
+Class UniqueCompanyList
+Class Company
Class Email
Class Name
Class Phone
-Class Tag
+Class ApplicationStatus
+Class Deadline
+Class Priority
+Class RecruiterName
+Class Role
+Class Priority
+Class Remark
Class I #FFFFFF
}
@@ -35,20 +40,22 @@ ModelManager -left-> "1" AddressBook
ModelManager -right-> "1" UserPrefs
UserPrefs .up.|> ReadOnlyUserPrefs
-AddressBook *--> "1" UniquePersonList
-UniquePersonList --> "~* all" Person
-Person *--> Name
-Person *--> Phone
-Person *--> Email
-Person *--> Address
-Person *--> "*" Tag
-
-Person -[hidden]up--> I
-UniquePersonList -[hidden]right-> I
+AddressBook *--> "1" UniqueCompanyList
+UniqueCompanyList --> "~* all" Company
+Company *--> Email
+Company *--> Name
+Company *--> Phone
+Company *--> ApplicationStatus
+Company *--> Deadline
+Company *--> RecruiterName
+Company *--> Role
+Company *--> Priority
+Company *--> Remark
+
+Company -[hidden]up--> I
+UniqueCompanyList -[hidden]right-> I
Name -[hidden]right-> Phone
-Phone -[hidden]right-> Address
-Address -[hidden]right-> Email
-ModelManager --> "~* filtered" Person
+ModelManager --> "~* filtered" Company
@enduml
diff --git a/docs/diagrams/RemarkActivityDiagram.puml b/docs/diagrams/RemarkActivityDiagram.puml
new file mode 100644
index 00000000000..06d873d5192
--- /dev/null
+++ b/docs/diagrams/RemarkActivityDiagram.puml
@@ -0,0 +1,27 @@
+@startuml
+skin rose
+skinparam ActivityFontSize 15
+skinparam ArrowFontSize 12
+start
+:AddressBookParser parses user input;
+
+'Since the beta syntax does not support placing the condition outside the
+'diamond we place it as the true branch instead.
+
+if () then ([remark command word])
+ :Create RemarkCommandParser;
+ :Parse user input;
+ :Create RemarkCommand
+ with user input as remark;
+
+else ([unremark command word])
+ :Create UnremarkCommandParser;
+ : Create RemarkCommand
+ with "No remarks" as remark;
+
+endif
+
+: RemarkCommand.execute()
+updates remark of the company;
+stop
+@enduml
diff --git a/docs/diagrams/SortSequenceDiagram.puml b/docs/diagrams/SortSequenceDiagram.puml
new file mode 100644
index 00000000000..13c6749599d
--- /dev/null
+++ b/docs/diagrams/SortSequenceDiagram.puml
@@ -0,0 +1,46 @@
+@startuml
+!include style.puml
+skinparam ArrowFontStyle plain
+
+box Logic LOGIC_COLOR_T1
+participant ":SortCommand" as SortCommand LOGIC_COLOR
+participant "c:Comparator" as Comparator LOGIC_COLOR
+participant ":CommandResult" as CommandResult LOGIC_COLOR
+
+box Model MODEL_COLOR_T1
+participant ":ModelManager" as Model MODEL_COLOR
+
+-> SortCommand : execute(sortOrder)
+activate SortCommand
+create Comparator
+SortCommand -> Comparator : createComparator(sortOrder)
+
+activate Comparator
+Comparator --> SortCommand
+deactivate Comparator
+
+SortCommand -> Model : getUnmodifiableObservableList()
+activate Model
+Model --> SortCommand : companyList
+deactivate Model
+
+SortCommand -> SortCommand : sortCompanies(companyList, c)
+activate SortCommand
+SortCommand --> SortCommand : sortedList
+deactivate SortCommand
+
+SortCommand -> Model : setAllCompanies(sortedList)
+activate Model
+Model --> SortCommand
+deactivate Model
+
+create CommandResult
+SortCommand -> CommandResult
+activate CommandResult
+
+CommandResult --> SortCommand
+deactivate CommandResult
+
+<-- SortCommand : result
+deactivate SortCommand
+@enduml
diff --git a/docs/diagrams/StorageClassDiagram.puml b/docs/diagrams/StorageClassDiagram.puml
index a821e06458c..bcc9fbac70d 100644
--- a/docs/diagrams/StorageClassDiagram.puml
+++ b/docs/diagrams/StorageClassDiagram.puml
@@ -18,8 +18,8 @@ package "AddressBook Storage" #F4F6F6{
Class "<>\nAddressBookStorage" as AddressBookStorage
Class JsonAddressBookStorage
Class JsonSerializableAddressBook
-Class JsonAdaptedPerson
-Class JsonAdaptedTag
+Class JsonAdaptedCompany
+
}
}
@@ -37,7 +37,6 @@ Storage -right-|> AddressBookStorage
JsonUserPrefsStorage .up.|> UserPrefsStorage
JsonAddressBookStorage .up.|> AddressBookStorage
JsonAddressBookStorage ..> JsonSerializableAddressBook
-JsonSerializableAddressBook --> "*" JsonAdaptedPerson
-JsonAdaptedPerson --> "*" JsonAdaptedTag
+JsonSerializableAddressBook --> "*" JsonAdaptedCompany
@enduml
diff --git a/docs/diagrams/UiClassDiagram.puml b/docs/diagrams/UiClassDiagram.puml
index 95473d5aa19..63d12d69048 100644
--- a/docs/diagrams/UiClassDiagram.puml
+++ b/docs/diagrams/UiClassDiagram.puml
@@ -11,9 +11,11 @@ Class UiManager
Class MainWindow
Class HelpWindow
Class ResultDisplay
-Class PersonListPanel
-Class PersonCard
+Class CompanyListPanel
+Class CompanyCard
Class StatusBarFooter
+Class CompanyDetailPanel
+Class CompanyDetailCard
Class CommandBox
}
@@ -32,26 +34,31 @@ UiManager .left.|> Ui
UiManager -down-> "1" MainWindow
MainWindow *-down-> "1" CommandBox
MainWindow *-down-> "1" ResultDisplay
-MainWindow *-down-> "1" PersonListPanel
+MainWindow *-down-> "1" CompanyListPanel
MainWindow *-down-> "1" StatusBarFooter
MainWindow --> "0..1" HelpWindow
-
-PersonListPanel -down-> "*" PersonCard
+MainWindow *-down-> "1" CompanyDetailPanel
+CompanyListPanel -down-> "*" CompanyCard
+CompanyDetailPanel -down-> "0...1" CompanyDetailCard
MainWindow -left-|> UiPart
-ResultDisplay --|> UiPart
-CommandBox --|> UiPart
-PersonListPanel --|> UiPart
-PersonCard --|> UiPart
+ResultDisplay -down--|> UiPart
+CommandBox -down--|> UiPart
+CompanyCard -down--|> UiPart
+CompanyDetailCard -down--|> UiPart
+CompanyListPanel -down--|> UiPart
+CompanyDetailPanel -down--|> UiPart
+
StatusBarFooter --|> UiPart
HelpWindow --|> UiPart
-PersonCard ..> Model
+CompanyCard -down..> Model
+CompanyDetailCard -down..> Model
UiManager -right-> Logic
MainWindow -left-> Logic
-PersonListPanel -[hidden]left- HelpWindow
+CompanyListPanel -[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 43a45903ac9..00000000000
--- a/docs/diagrams/UndoRedoState0.puml
+++ /dev/null
@@ -1,21 +0,0 @@
-@startuml
-!include style.puml
-skinparam ClassFontColor #000000
-skinparam ClassBorderColor #000000
-skinparam ClassBackgroundColor #FFFFAA
-
-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" #FFFFFF
-Pointer -up-> State1
-@end
diff --git a/docs/diagrams/UndoRedoState1.puml b/docs/diagrams/UndoRedoState1.puml
deleted file mode 100644
index 5a41e9e1651..00000000000
--- a/docs/diagrams/UndoRedoState1.puml
+++ /dev/null
@@ -1,23 +0,0 @@
-@startuml
-!include style.puml
-skinparam ClassFontColor #000000
-skinparam ClassBorderColor #000000
-skinparam ClassBackgroundColor #FFFFAA
-
-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" #FFFFFF
-
-Pointer -up-> State2
-@end
diff --git a/docs/diagrams/UndoRedoState2.puml b/docs/diagrams/UndoRedoState2.puml
deleted file mode 100644
index ad32fce1b0b..00000000000
--- a/docs/diagrams/UndoRedoState2.puml
+++ /dev/null
@@ -1,21 +0,0 @@
-@startuml
-!include style.puml
-skinparam ClassFontColor #000000
-skinparam ClassBorderColor #000000
-skinparam ClassBackgroundColor #FFFFAA
-
-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" #FFFFFF
-
-Pointer -up-> State3
-@end
diff --git a/docs/diagrams/UndoRedoState3.puml b/docs/diagrams/UndoRedoState3.puml
deleted file mode 100644
index 9187a690036..00000000000
--- a/docs/diagrams/UndoRedoState3.puml
+++ /dev/null
@@ -1,21 +0,0 @@
-@startuml
-!include style.puml
-skinparam ClassFontColor #000000
-skinparam ClassBorderColor #000000
-skinparam ClassBackgroundColor #FFFFAA
-
-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" #FFFFFF
-
-Pointer -up-> State2
-@end
diff --git a/docs/diagrams/UndoRedoState4.puml b/docs/diagrams/UndoRedoState4.puml
deleted file mode 100644
index 2bc631ffcd0..00000000000
--- a/docs/diagrams/UndoRedoState4.puml
+++ /dev/null
@@ -1,21 +0,0 @@
-@startuml
-!include style.puml
-skinparam ClassFontColor #000000
-skinparam ClassBorderColor #000000
-skinparam ClassBackgroundColor #FFFFAA
-
-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" #FFFFFF
-
-Pointer -up-> State2
-@end
diff --git a/docs/diagrams/UndoRedoState5.puml b/docs/diagrams/UndoRedoState5.puml
deleted file mode 100644
index e77b04104aa..00000000000
--- a/docs/diagrams/UndoRedoState5.puml
+++ /dev/null
@@ -1,22 +0,0 @@
-@startuml
-!include style.puml
-skinparam ClassFontColor #000000
-skinparam ClassBorderColor #000000
-skinparam ClassBackgroundColor #FFFFAA
-
-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" #FFFFFF
-
-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 87ff3e9237e..00000000000
--- a/docs/diagrams/UndoSequenceDiagram.puml
+++ /dev/null
@@ -1,54 +0,0 @@
-@startuml
-!include style.puml
-skinparam ArrowFontStyle plain
-
-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/ViewSequenceDiagram.puml b/docs/diagrams/ViewSequenceDiagram.puml
new file mode 100644
index 00000000000..fb27244573e
--- /dev/null
+++ b/docs/diagrams/ViewSequenceDiagram.puml
@@ -0,0 +1,86 @@
+@startuml
+!include style.puml
+skinparam ArrowFontStyle plain
+
+box Logic LOGIC_COLOR_T1
+
+participant ":LogicManager" as LogicManager LOGIC_COLOR
+participant ":AddressBookParser" as AddressBookParser LOGIC_COLOR
+participant ":ViewCommandParser" as ViewCommandParser LOGIC_COLOR
+participant "c:Company" as Company MODEL_COLOR
+participant "v:ViewCommand" as ViewCommand LOGIC_COLOR
+participant ":CommandResult" as CommandResult LOGIC_COLOR
+
+end box
+
+box Model MODEL_COLOR_T1
+participant "m:ModelManager" as Model MODEL_COLOR
+end box
+
+[-> LogicManager : execute("view 1")
+activate LogicManager
+
+LogicManager -> AddressBookParser : parseCommand("view 1")
+activate AddressBookParser
+
+create ViewCommandParser
+AddressBookParser -> ViewCommandParser
+activate ViewCommandParser
+
+ViewCommandParser --> AddressBookParser
+deactivate ViewCommandParser
+
+AddressBookParser -> ViewCommandParser : parse("1")
+activate ViewCommandParser
+
+create Company
+ViewCommandParser -> Company: Company(...)
+activate Company
+
+Company --> ViewCommandParser
+deactivate Company
+
+create ViewCommand
+ViewCommandParser -> ViewCommand
+activate ViewCommand
+
+ViewCommand --> ViewCommandParser : v
+deactivate ViewCommand
+
+ViewCommandParser --> AddressBookParser : v
+deactivate ViewCommandParser
+'Hidden arrow to position the destroy marker below the end of the activation bar.
+ViewCommandParser -[hidden]-> AddressBookParser
+destroy ViewCommandParser
+
+AddressBookParser --> LogicManager : v
+deactivate AddressBookParser
+
+LogicManager -> ViewCommand : execute(m)
+activate ViewCommand
+
+ViewCommand -> Model : setCurrentViewedCompany(c)
+
+activate Model
+
+Model --> ViewCommand
+deactivate Model
+
+create CommandResult
+ViewCommand -> CommandResult
+activate CommandResult
+
+CommandResult --> ViewCommand
+deactivate CommandResult
+
+ViewCommand --> LogicManager : result
+deactivate ViewCommand
+
+[<--LogicManager
+deactivate LogicManager
+
+
+
+
+
+@enduml
diff --git a/docs/diagrams/add-remark/ParserClass.puml b/docs/diagrams/add-remark/ParserClass.puml
deleted file mode 100644
index 24d390a4023..00000000000
--- a/docs/diagrams/add-remark/ParserClass.puml
+++ /dev/null
@@ -1,14 +0,0 @@
-@startuml
-hide circle
-skinparam classAttributeIconSize 0
-
-Class "<>\nParser" as Parser
-Class RemarkCommandParser {
- +parse(): RemarkCommand
-}
-Class ParserException
-
-RemarkCommandParser .up.|> Parser
-Parser .right.> ParserException: throws >
-RemarkCommandParser .right.> ParserException: throws >
-@enduml
diff --git a/docs/diagrams/add-remark/RemarkClass.puml b/docs/diagrams/add-remark/RemarkClass.puml
deleted file mode 100644
index 019c1ecbbf1..00000000000
--- a/docs/diagrams/add-remark/RemarkClass.puml
+++ /dev/null
@@ -1,19 +0,0 @@
-@startuml
-hide circle
-skinparam classAttributeIconSize 0
-
-Class "{abstract}\nCommand" as Command {
- +execute(Model): CommandResult
-}
-Class RemarkCommand {
- +COMMAND_WORD: String
- +MESSAGE_USAGE: String
- +MESSAGE_NOT_IMPLEMENTED_YET: String
- +execute(Model): CommandResult
-}
-Class CommandException
-
-RemarkCommand -up-|> Command
-Command ..> CommandException: throws >
-RemarkCommand .right.> CommandException: throws >
-@enduml
diff --git a/docs/diagrams/style.puml b/docs/diagrams/style.puml
index f7d7347ae84..7765e080ee0 100644
--- a/docs/diagrams/style.puml
+++ b/docs/diagrams/style.puml
@@ -48,6 +48,15 @@ skinparam Class {
FontName Arial
}
+skinparam ClassAttribute {
+ FontColor #FFFFFF
+ FontSize 15
+ BorderThickness 1
+ BorderColor #FFFFFF
+ StereotypeFontColor #FFFFFF
+ FontName Arial
+}
+
skinparam Actor {
BorderColor USER_COLOR
Color USER_COLOR
diff --git a/docs/diagrams/tracing/LogicSequenceDiagram.puml b/docs/diagrams/tracing/LogicSequenceDiagram.puml
deleted file mode 100644
index 42bf46d3ce8..00000000000
--- a/docs/diagrams/tracing/LogicSequenceDiagram.puml
+++ /dev/null
@@ -1,22 +0,0 @@
-@startuml
-!include ../style.puml
-skinparam ArrowFontStyle plain
-
-Participant ":LogicManager" as logic LOGIC_COLOR
-Participant ":AddressBookParser" as abp LOGIC_COLOR
-Participant ":EditCommandParser" as ecp LOGIC_COLOR
-Participant "command:EditCommand" as ec LOGIC_COLOR
-
-[-> logic : execute
-activate logic
-logic -> abp ++: parseCommand(commandText)
-create ecp
-abp -> ecp
-abp -> ecp ++: parse(arguments)
-create ec
-ecp -> ec ++: index, editPersonDescriptor
-ec --> ecp --
-ecp --> abp --: command
-abp --> logic --: command
-
-@enduml
diff --git a/docs/images/AddActivityDiagram.png b/docs/images/AddActivityDiagram.png
new file mode 100644
index 00000000000..3ac16c9cfa8
Binary files /dev/null and b/docs/images/AddActivityDiagram.png differ
diff --git a/docs/images/AddSequenceDiagram.png b/docs/images/AddSequenceDiagram.png
new file mode 100644
index 00000000000..b5bc6c1269d
Binary files /dev/null and b/docs/images/AddSequenceDiagram.png differ
diff --git a/docs/images/ArchitectureSequenceDiagram.png b/docs/images/ArchitectureSequenceDiagram.png
index 37ad06a2803..b0c67abfc9e 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
index 02a42e35e76..62dcbb88e13 100644
Binary files a/docs/images/BetterModelClassDiagram.png and b/docs/images/BetterModelClassDiagram.png differ
diff --git a/docs/images/CompanyDataLocation.png b/docs/images/CompanyDataLocation.png
new file mode 100644
index 00000000000..506d29c6f54
Binary files /dev/null and b/docs/images/CompanyDataLocation.png differ
diff --git a/docs/images/CompanyDetailPanelActivityDiagram.png b/docs/images/CompanyDetailPanelActivityDiagram.png
new file mode 100644
index 00000000000..9c43b6eb978
Binary files /dev/null and b/docs/images/CompanyDetailPanelActivityDiagram.png differ
diff --git a/docs/images/DeleteSequenceDiagram.png b/docs/images/DeleteSequenceDiagram.png
index e186f7ba096..5590902f31e 100644
Binary files a/docs/images/DeleteSequenceDiagram.png and b/docs/images/DeleteSequenceDiagram.png differ
diff --git a/docs/images/DetailPanelClassDiagram.png b/docs/images/DetailPanelClassDiagram.png
new file mode 100644
index 00000000000..86f6e1318b3
Binary files /dev/null and b/docs/images/DetailPanelClassDiagram.png differ
diff --git a/docs/images/EditSequenceDiagram.png b/docs/images/EditSequenceDiagram.png
new file mode 100644
index 00000000000..1fcd9b42aaf
Binary files /dev/null and b/docs/images/EditSequenceDiagram.png differ
diff --git a/docs/images/FilterSequenceDiagram.png b/docs/images/FilterSequenceDiagram.png
new file mode 100644
index 00000000000..151b22c6429
Binary files /dev/null and b/docs/images/FilterSequenceDiagram.png differ
diff --git a/docs/images/FindCompanySequenceDiagram.png b/docs/images/FindCompanySequenceDiagram.png
new file mode 100644
index 00000000000..b42ef29a683
Binary files /dev/null and b/docs/images/FindCompanySequenceDiagram.png differ
diff --git a/docs/images/ModelClassDiagram.png b/docs/images/ModelClassDiagram.png
index a19fb1b4ac8..34a873e4dbe 100644
Binary files a/docs/images/ModelClassDiagram.png and b/docs/images/ModelClassDiagram.png differ
diff --git a/docs/images/RemarkActivityDiagram.png b/docs/images/RemarkActivityDiagram.png
new file mode 100644
index 00000000000..8c6699e2320
Binary files /dev/null and b/docs/images/RemarkActivityDiagram.png differ
diff --git a/docs/images/SortSequenceDiagram.png b/docs/images/SortSequenceDiagram.png
new file mode 100644
index 00000000000..5033e129000
Binary files /dev/null and b/docs/images/SortSequenceDiagram.png differ
diff --git a/docs/images/StorageClassDiagram.png b/docs/images/StorageClassDiagram.png
index 18fa4d0d51f..1ccdaa5898f 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..01fd42327df 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 11f06d68671..6adf5f2442c 100644
Binary files a/docs/images/UiClassDiagram.png and b/docs/images/UiClassDiagram.png differ
diff --git a/docs/images/UndoRedoState0.png b/docs/images/UndoRedoState0.png
deleted file mode 100644
index c5f91b58533..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 2d3ad09c047..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 20853694e03..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 1a9551b31be..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 46dfae78c94..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 f45889b5fdf..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 c7a7e637266..00000000000
Binary files a/docs/images/UndoSequenceDiagram.png and /dev/null differ
diff --git a/docs/images/ViewSequenceDiagram.png b/docs/images/ViewSequenceDiagram.png
new file mode 100644
index 00000000000..293f642a31b
Binary files /dev/null and b/docs/images/ViewSequenceDiagram.png differ
diff --git a/docs/images/add-command/AddCommandError.png b/docs/images/add-command/AddCommandError.png
new file mode 100644
index 00000000000..f5f2d1d5564
Binary files /dev/null and b/docs/images/add-command/AddCommandError.png differ
diff --git a/docs/images/add-command/AddCommandError2.png b/docs/images/add-command/AddCommandError2.png
new file mode 100644
index 00000000000..918d54f7c6f
Binary files /dev/null and b/docs/images/add-command/AddCommandError2.png differ
diff --git a/docs/images/add-command/AfterAddCommand.png b/docs/images/add-command/AfterAddCommand.png
new file mode 100644
index 00000000000..a2e7234d4c2
Binary files /dev/null and b/docs/images/add-command/AfterAddCommand.png differ
diff --git a/docs/images/add-command/BeforeAddCommand.png b/docs/images/add-command/BeforeAddCommand.png
new file mode 100644
index 00000000000..b1d9d520469
Binary files /dev/null and b/docs/images/add-command/BeforeAddCommand.png differ
diff --git a/docs/images/alagappanra.png b/docs/images/alagappanra.png
new file mode 100644
index 00000000000..079fc03a5be
Binary files /dev/null and b/docs/images/alagappanra.png differ
diff --git a/docs/images/alientian.png b/docs/images/alientian.png
new file mode 100644
index 00000000000..770882717ad
Binary files /dev/null and b/docs/images/alientian.png differ
diff --git a/docs/images/clear-command/clear.png b/docs/images/clear-command/clear.png
new file mode 100644
index 00000000000..1b1a7f56be6
Binary files /dev/null and b/docs/images/clear-command/clear.png differ
diff --git a/docs/images/cli-description/CliDescription1.png b/docs/images/cli-description/CliDescription1.png
new file mode 100644
index 00000000000..9aca7d1b575
Binary files /dev/null and b/docs/images/cli-description/CliDescription1.png differ
diff --git a/docs/images/cli-description/CommandFormat1.png b/docs/images/cli-description/CommandFormat1.png
new file mode 100644
index 00000000000..a83e8eb950a
Binary files /dev/null and b/docs/images/cli-description/CommandFormat1.png differ
diff --git a/docs/images/cli-description/CommandFormat2.png b/docs/images/cli-description/CommandFormat2.png
new file mode 100644
index 00000000000..efb4ee51d8a
Binary files /dev/null and b/docs/images/cli-description/CommandFormat2.png differ
diff --git a/docs/images/delete-command/AfterDeleteCommand.png b/docs/images/delete-command/AfterDeleteCommand.png
new file mode 100644
index 00000000000..311e7347710
Binary files /dev/null and b/docs/images/delete-command/AfterDeleteCommand.png differ
diff --git a/docs/images/delete-command/BeforeDeleteCommand.png b/docs/images/delete-command/BeforeDeleteCommand.png
new file mode 100644
index 00000000000..8ab98786c38
Binary files /dev/null and b/docs/images/delete-command/BeforeDeleteCommand.png differ
diff --git a/docs/images/delete-command/DeleteCommandError.png b/docs/images/delete-command/DeleteCommandError.png
new file mode 100644
index 00000000000..a98f39a5877
Binary files /dev/null and b/docs/images/delete-command/DeleteCommandError.png differ
diff --git a/docs/images/duplicate-detection/add-command/DuplicateActivityDiagram.png b/docs/images/duplicate-detection/add-command/DuplicateActivityDiagram.png
new file mode 100644
index 00000000000..2cf188d9398
Binary files /dev/null and b/docs/images/duplicate-detection/add-command/DuplicateActivityDiagram.png differ
diff --git a/docs/images/duplicate-detection/add-command/duplicate-exact-match.png b/docs/images/duplicate-detection/add-command/duplicate-exact-match.png
new file mode 100644
index 00000000000..63234ee1a5b
Binary files /dev/null and b/docs/images/duplicate-detection/add-command/duplicate-exact-match.png differ
diff --git a/docs/images/duplicate-detection/add-command/duplicate-partial-match.png b/docs/images/duplicate-detection/add-command/duplicate-partial-match.png
new file mode 100644
index 00000000000..9af73a5fceb
Binary files /dev/null and b/docs/images/duplicate-detection/add-command/duplicate-partial-match.png differ
diff --git a/docs/images/duplicate-detection/edit-command/DuplicateSequenceDiagram.png b/docs/images/duplicate-detection/edit-command/DuplicateSequenceDiagram.png
new file mode 100644
index 00000000000..720d601e375
Binary files /dev/null and b/docs/images/duplicate-detection/edit-command/DuplicateSequenceDiagram.png differ
diff --git a/docs/images/duplicate-detection/edit-command/duplicate-edit.png b/docs/images/duplicate-detection/edit-command/duplicate-edit.png
new file mode 100644
index 00000000000..1707519244a
Binary files /dev/null and b/docs/images/duplicate-detection/edit-command/duplicate-edit.png differ
diff --git a/docs/images/edit-command/EditDemo1.png b/docs/images/edit-command/EditDemo1.png
new file mode 100644
index 00000000000..f4c04a383a5
Binary files /dev/null and b/docs/images/edit-command/EditDemo1.png differ
diff --git a/docs/images/edit-command/EditDemo2.png b/docs/images/edit-command/EditDemo2.png
new file mode 100644
index 00000000000..5762f4bfd44
Binary files /dev/null and b/docs/images/edit-command/EditDemo2.png differ
diff --git a/docs/images/edit-command/EditErrMsg.png b/docs/images/edit-command/EditErrMsg.png
new file mode 100644
index 00000000000..fbf37cf5f8e
Binary files /dev/null and b/docs/images/edit-command/EditErrMsg.png differ
diff --git a/docs/images/filter-command/AfterFilterCommand.png b/docs/images/filter-command/AfterFilterCommand.png
new file mode 100644
index 00000000000..9a84748aee8
Binary files /dev/null and b/docs/images/filter-command/AfterFilterCommand.png differ
diff --git a/docs/images/filter-command/FilterByPI.png b/docs/images/filter-command/FilterByPI.png
new file mode 100644
index 00000000000..11b558798ad
Binary files /dev/null and b/docs/images/filter-command/FilterByPI.png differ
diff --git a/docs/images/filter-command/FilterCommandError.png b/docs/images/filter-command/FilterCommandError.png
new file mode 100644
index 00000000000..e2dc731a10e
Binary files /dev/null and b/docs/images/filter-command/FilterCommandError.png differ
diff --git a/docs/images/find-command/AfterFind.png b/docs/images/find-command/AfterFind.png
new file mode 100644
index 00000000000..f1126c964dd
Binary files /dev/null and b/docs/images/find-command/AfterFind.png differ
diff --git a/docs/images/find-command/BeforeFind.png b/docs/images/find-command/BeforeFind.png
new file mode 100644
index 00000000000..4fd586d1391
Binary files /dev/null and b/docs/images/find-command/BeforeFind.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/glendachong.png b/docs/images/glendachong.png
new file mode 100644
index 00000000000..6fa692db0d6
Binary files /dev/null and b/docs/images/glendachong.png differ
diff --git a/docs/images/help-command/helpcommand.png b/docs/images/help-command/helpcommand.png
new file mode 100644
index 00000000000..926acb8c5d1
Binary files /dev/null and b/docs/images/help-command/helpcommand.png differ
diff --git a/docs/images/helpMessage.png b/docs/images/helpMessage.png
deleted file mode 100644
index b1f70470137..00000000000
Binary files a/docs/images/helpMessage.png and /dev/null differ
diff --git a/docs/images/johndoe.png b/docs/images/johndoe.png
deleted file mode 100644
index 1ce7ce16dc8..00000000000
Binary files a/docs/images/johndoe.png and /dev/null differ
diff --git a/docs/images/list-command/ListCommand.png b/docs/images/list-command/ListCommand.png
new file mode 100644
index 00000000000..5708682b3b4
Binary files /dev/null and b/docs/images/list-command/ListCommand.png differ
diff --git a/docs/images/papataco14.png b/docs/images/papataco14.png
new file mode 100644
index 00000000000..d6b94b23142
Binary files /dev/null and b/docs/images/papataco14.png differ
diff --git a/docs/images/quick-start/githubRelease.png b/docs/images/quick-start/githubRelease.png
new file mode 100644
index 00000000000..7189b94a194
Binary files /dev/null and b/docs/images/quick-start/githubRelease.png differ
diff --git a/docs/images/quick-start/java11.png b/docs/images/quick-start/java11.png
new file mode 100644
index 00000000000..07cee395246
Binary files /dev/null and b/docs/images/quick-start/java11.png differ
diff --git a/docs/images/quick-start/launchLinkMeIn.png b/docs/images/quick-start/launchLinkMeIn.png
new file mode 100644
index 00000000000..cf9f9ef4d2d
Binary files /dev/null and b/docs/images/quick-start/launchLinkMeIn.png differ
diff --git a/docs/images/quick-start/startupPage.png b/docs/images/quick-start/startupPage.png
new file mode 100644
index 00000000000..8c7f48c144b
Binary files /dev/null and b/docs/images/quick-start/startupPage.png differ
diff --git a/docs/images/remark-command/RemarkDemo1.png b/docs/images/remark-command/RemarkDemo1.png
new file mode 100644
index 00000000000..c3e39e37e8b
Binary files /dev/null and b/docs/images/remark-command/RemarkDemo1.png differ
diff --git a/docs/images/remark-command/RemarkDemo2.png b/docs/images/remark-command/RemarkDemo2.png
new file mode 100644
index 00000000000..aa8f87d3df5
Binary files /dev/null and b/docs/images/remark-command/RemarkDemo2.png differ
diff --git a/docs/images/remark-command/RemarkErrMsg.png b/docs/images/remark-command/RemarkErrMsg.png
new file mode 100644
index 00000000000..8ad17e26d52
Binary files /dev/null and b/docs/images/remark-command/RemarkErrMsg.png differ
diff --git a/docs/images/remark-command/UnremarkDemo1.png b/docs/images/remark-command/UnremarkDemo1.png
new file mode 100644
index 00000000000..5c9b76c64cd
Binary files /dev/null and b/docs/images/remark-command/UnremarkDemo1.png differ
diff --git a/docs/images/remark-command/UnremarkDemo2.png b/docs/images/remark-command/UnremarkDemo2.png
new file mode 100644
index 00000000000..089488fe0df
Binary files /dev/null and b/docs/images/remark-command/UnremarkDemo2.png differ
diff --git a/docs/images/remark-command/UnremarkErrMsg.png b/docs/images/remark-command/UnremarkErrMsg.png
new file mode 100644
index 00000000000..590b41dfbc0
Binary files /dev/null and b/docs/images/remark-command/UnremarkErrMsg.png differ
diff --git a/docs/images/request_access.png b/docs/images/request_access.png
deleted file mode 100644
index 12e8a81bd28..00000000000
Binary files a/docs/images/request_access.png and /dev/null differ
diff --git a/docs/images/sort-command/AfterSorting.png b/docs/images/sort-command/AfterSorting.png
new file mode 100644
index 00000000000..1beb18daee0
Binary files /dev/null and b/docs/images/sort-command/AfterSorting.png differ
diff --git a/docs/images/sort-command/BeforeSorting.png b/docs/images/sort-command/BeforeSorting.png
new file mode 100644
index 00000000000..32f8c6c88ae
Binary files /dev/null and b/docs/images/sort-command/BeforeSorting.png differ
diff --git a/docs/images/sort-command/SortError.png b/docs/images/sort-command/SortError.png
new file mode 100644
index 00000000000..54f596d86de
Binary files /dev/null and b/docs/images/sort-command/SortError.png differ
diff --git a/docs/images/sort-command/TypeCommand.png b/docs/images/sort-command/TypeCommand.png
new file mode 100644
index 00000000000..c5155594819
Binary files /dev/null and b/docs/images/sort-command/TypeCommand.png differ
diff --git a/docs/images/tayruxin.png b/docs/images/tayruxin.png
new file mode 100644
index 00000000000..2c6ca169903
Binary files /dev/null and b/docs/images/tayruxin.png differ
diff --git a/docs/images/ui-intro/uiIntro.png b/docs/images/ui-intro/uiIntro.png
new file mode 100644
index 00000000000..c0e6c0bc615
Binary files /dev/null and b/docs/images/ui-intro/uiIntro.png differ
diff --git a/docs/images/view-command/AfterViewCommand.png b/docs/images/view-command/AfterViewCommand.png
new file mode 100644
index 00000000000..2142570fba6
Binary files /dev/null and b/docs/images/view-command/AfterViewCommand.png differ
diff --git a/docs/images/view-command/BeforeViewCommand.png b/docs/images/view-command/BeforeViewCommand.png
new file mode 100644
index 00000000000..a3de2d3f1bb
Binary files /dev/null and b/docs/images/view-command/BeforeViewCommand.png differ
diff --git a/docs/images/view-command/ViewCommandError.png b/docs/images/view-command/ViewCommandError.png
new file mode 100644
index 00000000000..f4cee8d8cbe
Binary files /dev/null and b/docs/images/view-command/ViewCommandError.png differ
diff --git a/docs/index.md b/docs/index.md
index 7601dbaad0d..a35b0b1ba2b 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -1,19 +1,19 @@
---
layout: page
-title: AddressBook Level-3
+title: "LinkMeIn"
---
+[![CI Status](https://github.com/se-edu/addressbook-level3/workflows/Java%20CI/badge.svg)](https://github.com/AY2324S1-CS2103T-T17-2/tp/actions/workflows/gradle.yml)
+[![codecov](https://codecov.io/gh/se-edu/addressbook-level3/branch/master/graph/badge.svg)](https://app.codecov.io/gh/AY2324S1-CS2103T-T17-2/tp)
-[![CI Status](https://github.com/se-edu/addressbook-level3/workflows/Java%20CI/badge.svg)](https://github.com/se-edu/addressbook-level3/actions)
-[![codecov](https://codecov.io/gh/se-edu/addressbook-level3/branch/master/graph/badge.svg)](https://codecov.io/gh/se-edu/addressbook-level3)
![Ui](images/Ui.png)
-**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).
-
-* 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.
+**LinkMeIn is a desktop application for managing your internship applications as a Computer Science student.** While it has a GUI, most of the user interactions happen using a CLI (Command Line Interface).
+* If you are interested in using LinkMeIn, head over to the [_Quick Start_ section of the **User Guide**](UserGuide.html#quick-start).
+* If you are interested about developing LinkMeIn, the [**Developer Guide**](DeveloperGuide.html) is a good place to start.
**Acknowledgements**
* Libraries used: [JavaFX](https://openjfx.io/), [Jackson](https://github.com/FasterXML/jackson), [JUnit5](https://github.com/junit-team/junit5)
+* This project is based on the AddressBook-Level3 project created by the [SE-EDU initiative](https://se-education.org).
diff --git a/docs/team/alagappanra.md b/docs/team/alagappanra.md
new file mode 100644
index 00000000000..81877509032
--- /dev/null
+++ b/docs/team/alagappanra.md
@@ -0,0 +1,98 @@
+---
+layout: page
+title: Alagappan Ramanathan's Project Portfolio Page
+---
+
+### Project: LinkMeIn
+LinkMeIn - Is a desktop address book application
+used to track student's job applications to companies.
+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.
+
+## **Code contributed**:
+The code that I have contributed can be found in this [RepoSense link](https://nus-cs2103-ay2324s1.github.io/tp-dashboard/?search=AlagappanRa&breakdown=false&sort=groupTitle%20dsc&sortWithin=title&since=2023-09-22&timeframe=commit&mergegroup=&groupSelect=groupByRepos)
+
+## Enhancements implemented:
+**Duplicate checking algorithm for the add and edit command**
+
+**What it does:**
+The duplicate checking algorithm checks if the company that the user is trying to add or edit is already present in the
+company list. If the company is already present in the company list, a specific error message will be raised to the
+user, informing them of the corrective action they need to take.
+
+**Justification:**
+This feature was implemented to inform the user of an accidental duplicate company that they
+tried to add or edit. The associated error message covers 4 different cases, each of which
+guides the user towards a specific corrective action. These cases are filtered list view,
+original list view, partial match and complete match of fields.
+
+**Input validation method for all fields**
+
+**What it does:**
+- Company name, recruiter name, role, phone number, email, application status and priority fields are validated to
+ensure that they are not empty and that they follow the correct regex.
+- Implemented specific REGEX to ensure that the phone number and email fields are in the correct format.
+
+**Justification:**
+Input validation allows us to validate duplicates, while allowing the user to see whatever they typed. This allows
+for flexibility in the user interface, while ensuring that the user does not enter invalid inputs.
+
+**Test cases for the duplicate checking algorithm**
+Added close to 990 lines of test cases for the duplicate checking algorithm and the input validation fields
+to ensure behaviour was as expected.
+
+## General
+**Bug Fixes**:
+* Fixed a [bug](https://github.com/AY2324S1-CS2103T-T17-2/tp/pull/232) where the duplicate detection algorithm gave a wrong output
+* Fixed a bug where `Software Engineer 2` and `Software Engineer` were considered equals
+* Sequence diagrams and Activity Diagrams [bug](https://github.com/AY2324S1-CS2103T-T17-2/tp/pull/322) fixes
+
+**Team Contributions**:
+* PR's reviewed non-trivially
+ [#325](https://github.com/AY2324S1-CS2103T-T17-2/tp/pull/325),
+ [#287](https://github.com/AY2324S1-CS2103T-T17-2/tp/pull/287),
+ [#236](https://github.com/AY2324S1-CS2103T-T17-2/tp/pull/236)
+
+**Forum Enthusiast**
+* Resolved other classmate's code related issues (examples:
+ [#104](https://github.com/nus-cs2103-AY2324S1/forum/issues/104#issuecomment-1706219015),
+ [#154](https://github.com/nus-cs2103-AY2324S1/forum/issues/154#issuecomment-1726817514),
+ [#170](https://github.com/nus-cs2103-AY2324S1/forum/issues/170#issuecomment-1730530807),
+ [#249](https://github.com/nus-cs2103-AY2324S1/forum/issues/249#issuecomment-1759469324))
+* Resolved a bug in the [JavaFX tutorial](https://se-education.org/guides/tutorials/javaFxPart1.html)
+ regarding a JavaFX MAC-OS dependency issue. Recommended a modification to build gradle to solve the issue
+ [#159](https://github.com/nus-cs2103-AY2324S1/forum/issues/159#issuecomment-1728708305)
+* Questions asked in the forum (examples:
+ [#434](https://github.com/nus-cs2103-AY2324S1/forum/issues/434),
+ [#339](https://github.com/nus-cs2103-AY2324S1/forum/issues/339),
+ [#411](https://github.com/nus-cs2103-AY2324S1/forum/issues/411),
+ [#336](https://github.com/nus-cs2103-AY2324S1/forum/issues/336))
+
+**PE-D Testing**
+* Reported [10 bugs, of which 9 out of 10 were triaged](https://github.com/AY2324S1-CS2103T-T15-1/tp/issues?q=is%3Aissue+is%3Aclosed+AlagappanRa)
+* Breakdown: 2 High, 2 Medium, 3 Low, 2 Very Low, 1 Rejected
+
+### Contributions to the UG:
+The following sections from the UG were contributed by me:
+1. **Features**:
+ - Duplicate detection algorithm: Added description, examples for the various errors that can arise
+2. **Added FAQ**:
+ - Added questions 1 and 2 to the FAQ section.
+3. **Introduction section**
+ - Added a section on the motivation behind LinkMeIn
+ - Quick summary of features
+4. **Code block text size re-adjustment**
+ - Adjusted the code block text size to be smaller for better readability.
+
+### Contributions to the DG:
+The following sections from the DG were contributed by me:
+- Added activity & sequence diagrams for the duplicate checking algorithm
+- Planned enhancements
+ - Remove the alphanumeric checks for the company name, recruiter name and role fields
+ - Expanding acceptance for phone number field
+- Effort section
+
+
diff --git a/docs/team/alientian.md b/docs/team/alientian.md
new file mode 100644
index 00000000000..cc4f32eb706
--- /dev/null
+++ b/docs/team/alientian.md
@@ -0,0 +1,84 @@
+---
+layout: page
+title: Lim En Tian's Project Portfolio Page
+---
+
+# Project: LinkMeIn
+
+## Overview
+
+LinkMeIn is a desktop address book application used to track computer science student's job applications to companies.
+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.
+
+The features in LinkMeIn can be categorised into 3 main categories:
+1. **General features:** Navigating the application. Includes, help, exit and clear commands.
+2. **Company management features:** Manage an entry of a company. Includes, add, delete, edit, view, remark and
+ unremark commands.
+3. **Company list features:** Manage the list of companies added. Includes, list, find, sort and filter commands.
+
+## Summary of Contributions
+
+Given below are my contributions to the project.
+
+### Code contributed
+You can find all the code I have contributed in [RepoSense](https://nus-cs2103-ay2324s1.github.io/tp-dashboard/?search=alientian&breakdown=false&sort=groupTitle%20dsc&sortWithin=title&since=2023-09-22&timeframe=commit&mergegroup=&groupSelect=groupByRepos).
+
+### Enhancements implemented
+
+#### 1. Implemented display of application details in the GUI
+This enhancement adds a horizontal SplitPane to add a panel to show application details of all the fields input by user.
+Users change the company viewed by clicking on the list of companies on the right panel.
+This is later on enhanced by my team member, Ru Xin, to be controlled by the `view` command to adhere to our CLI app.
+Edited `MainWinfow.fxml` to restructure the GUI and created `CompanyDetailCard.fxml` file to define structure of the panel added and its Java class to render the UI.
+
+#### 2. Implemented new feature: Remark feature
+This allows users to write additional details to a specific application.
+Created the `Remark` class to add a remark to the `Company` model.
+`RemarkCommandParser` and `UnremarkCommandParser` classes are created to add and remove remarks respectively.
+`RemarkCommand` class is also created so that both parser extends from `Parser`.
+Test cases were added for all the classes created.
+
+#### 3. Modified the edit command
+Edited the code for `edit` command so that the command can edit all the fields that we have added to the `Company` model.
+The `edit` command should allow users to edit all the fields for more convenience and better user experience.
+Added more checks in `EditCommandParser` to provide more specific error message for invalid inputs.
+Test cases were edited to test for fields and error messages added.
+
+### **Contributions to the UG**
+
+- **CLI Description** :
+Added an introduction to CLI for users to learn how to write commands.
+
+- **Features** :
+Added description, examples, possible errors and images for the following features.
+Tips, notes and warnings are also added if applicable.
+ - **Edit**
+ - **Remark**
+ - **Unremark**
+ - **Clear**
+ - **Exit**
+
+### **Contributions to the DG**
+
+- Added NFRs
+- Added planned enhancements
+- Added how Edit Command and Remark Command works under Implementation
+- Created a UML sequence diagram to explain Edit Command
+- Created a UML activity diagram to explain Remark Command
+
+### **Contributions to team-based tasks**
+
+- Created new issues under the issue tracker
+
+### **Review/Mentoring contributions**
+
+- Non-trivial PRs reviewed:
+[\#145](https://github.com/AY2324S1-CS2103T-T17-2/tp/pull/145),
+[\#232](https://github.com/AY2324S1-CS2103T-T17-2/tp/pull/232),
+[\#274](https://github.com/AY2324S1-CS2103T-T17-2/tp/pull/274)
+
+
+### **Contributions beyond the project team**
+
+- [Bugs reported during PE-D](https://github.com/alientian/ped/issues)
diff --git a/docs/team/glendachong.md b/docs/team/glendachong.md
new file mode 100644
index 00000000000..a5d991a4919
--- /dev/null
+++ b/docs/team/glendachong.md
@@ -0,0 +1,59 @@
+---
+layout: page
+title: Glenda Chong Rui Ting's Project Portfolio Page
+---
+
+# Project: LinkMeIn
+
+LinkMeIn is a desktop address book application for NUS Computer Science students to track their internship applications.
+The user interacts with it using a Command Line Interface (CLI), and it has a Graphical User Interface (GUI) created with JavaFX. It is written in Java, and has about
+~10 kLoC.
+
+## Summary of Contributions
+
+Given below are my contributions to the project.
+
+* **Code Contributed:** The code that I have contributed can be found in this [RepoSense link](https://nus-cs2103-ay2324s1.github.io/tp-dashboard/?search=GlendaChong&sort=groupTitle&sortWithin=title&timeframe=commit&mergegroup=&groupSelect=groupByRepos&breakdown=true&checkedFileTypes=docs~functional-code~test-code&since=2023-09-22).
+
+* **New Feature: Filter Companies**
+ * **What it does:** Filters the list of companies by application status.
+ * **Justifications:** Users may wish to only view internship applications of a particular status. For example, they may wish to put more attention into applications that are pending interviews, so that they can prepare for the interviews.
+ * **Highlights:** The `filter` command relies on the new predicate, `ApplicationStatusPredicate`, to test if the company's application status matches the application status given by the user. The `filter` command also uses the updated `CompanyListPanel` to display the filtered list of companies.
+
+* **New Feature: Update GUI for `CompanyListPanel` and `CompanyDetailPanel`**
+ * **What it does:** `CompanyListPanel` and `CompanyDetailPanel` are of a similar colour theme. All the fields displayed will not be truncated, and will be soft-wrapped instead.
+ * **Justifications:** This update will improve the user experience of the GUI, and allow them to view the full information of the company.
+
+* **Enhancement to Existing Features:**
+ * **Enhance Error Messages for Fields in Company Model**
+ * **What it does:** For each field, there will be 2 main error messages, 1 for when the field is empty and 1 for when the field does not follow the valid regex.
+ * **Justifications:** The user needs to know exactly what is wrong with the input, and be able to correct it easily.
+ * **Highlights:** While the change was not difficult to implement, it was very tedious due to the large number of fields in the company model. It was very crucial to also not break the existing code base.
+ * **Enhance Existing `add` Command**
+ * **What it does:** The `add` command now accepts all the new fields added to the company model, including `Role`, `RecruiterName`, `ApplicationStatus` and `Deadline`. The error messages for the `add` command now also differentiates between empty inputs, invalid fields, or duplicate fields.
+ * **Justifications:** The `add` command is one of the most important commands in LinkMeIn. By adding more fields to the `add` command, it allows the user to add more information about the company. More specific error messages also allow the user to know exactly what is wrong with the input, and be able to correct it easily.
+
+* **Contributions to the UG**
+ * **Navigating the User Guide:** Add the annotations and icons using bootstrap alert icons.
+ * **Quick Start:** Improve on this section with step-by-step instructions, including adding more details and screenshots.
+ * **Features:** Add a company (`add`), List all companies (`list`), Filter companies by application status (`filter`)
+ * Include description of command, format, notes, tips, examples and possible errors.
+ * **Glossary:** Add definitions of key terms, parameters description, application status parameter description and email format description sections.
+ * **Command Summary:** Add the command summary table.
+
+* **Contributions to the DG**
+ * Add use cases.
+ * Add 3 planned enhancements.
+ * Add non-functional requirements.
+ * Add implementation details for `filter` and `add` commands.
+ * Add instructions for manual testing section.
+
+* **Contributions to Team-Based Tasks**
+ * Set up CodeCov for the project.
+ * Update landing page for the project website and AboutUs page.
+ * Manage milestones, change their due dates, and wrap-up milestones.
+ * Review PRs for the team regularly.
+ * Non-trivial PRs reviewed: [#271](https://github.com/AY2324S1-CS2103T-T17-2/tp/pull/271), [#261](https://github.com/AY2324S1-CS2103T-T17-2/tp/pull/261), [#226](https://github.com/AY2324S1-CS2103T-T17-2/tp/pull/226), [#156](https://github.com/AY2324S1-CS2103T-T17-2/tp/pull/156), [#169](https://github.com/AY2324S1-CS2103T-T17-2/tp/pull/169), [#142](https://github.com/AY2324S1-CS2103T-T17-2/tp/pull/142), [#135](https://github.com/AY2324S1-CS2103T-T17-2/tp/pull/135), [#109](https://github.com/AY2324S1-CS2103T-T17-2/tp/pull/109), [#104](https://github.com/AY2324S1-CS2103T-T17-2/tp/pull/104).
+
+* **Contributions beyond the Project Team**
+ * Extensive number of bugs reported for the other team's product during PE-D (28 bug reports)
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/papataco14.md b/docs/team/papataco14.md
new file mode 100644
index 00000000000..e2a3b70a4b0
--- /dev/null
+++ b/docs/team/papataco14.md
@@ -0,0 +1,100 @@
+---
+layout: page
+title: Ramu Rithik Vijay's Project Portfolio Page
+---
+
+#### Project: LinkMeIn
+
+LinkMeIn - Is a desktop address book application made for NUS Computer Science students to track their internship
+applications. 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.
+
+The features in LinkMeIn can be categorised into 3 main categories:
+
+1. **General features:** Navigating the application. Includes, help, exit and clear commands.
+2. **Company management features:** Manage an entry of a company. Includes, add, delete, edit, view, remark and unremark commands.
+3. **Company list features:** Manage the list of companies added. Includes, list, find, sort and filter commands.
+
+Given below are my contributions to the project.
+**Code contributed**:
+
+The code that I have contributed can be found in this [RepoSense link](https://nus-cs2103-ay2324s1.github.io/tp-dashboard/?search=papataco&breakdown=false&sort=groupTitle%20dsc&sortWithin=title&since=2023-09-22&timeframe=commit&mergegroup=&groupSelect=groupByRepos)
+
+#### Enhancements implemented:
+
+**1. Implemented the sort command.**
+
+**What it does:**
+
+The `sort` command organizes the list of companies by their respective deadlines, in either ascending or descending order.
+
+**Justification:**
+
+This feature was implemented to assist users in efficiently managing their application deadlines. It addresses the need for quick prioritization and helps prevent missing important deadlines by keeping the closest deadlines at the forefront.
+
+**Highlights:**
+
+- **Ease of Use**: Case-insensitive input and a default to the most commonly used sorting order (ascending). Also allow various other `SORT-ORDER` inputs such as `asc` and `desc` for fast typists.
+- **Robust Error Handling**: Informs users of incorrect input and guides them towards correct usage.
+- **Thorough Testing**: Ensured reliability and performance across diverse scenarios and data sets.
+
+**2. Implemented the find command.**
+
+**What it does:**
+
+The `find` command enables users to search for companies by keywords, with case-insensitive and partial matching capabilities.
+
+**Justification:**
+
+Implemented to enhance navigability and accessibility, this command allows users to locate companies quickly without exact name recall, significantly improving user experience.
+
+**Highlights:**
+
+- **Flexible Search**: Supports partial keyword matching for broader search results.
+- **Case-Insensitive Logic**: Ensures user convenience by eliminating the need for precise casing.
+- **Predicate Enhancement**: Modified `NameContainsKeywordsPredicate` for substring matching, boosting the command's functionality.
+- **User-Centric Design**: Selected design alternatives aim for the optimal balance between flexibility and precision, prioritizing ease of use.
+
+**3. Modified the Deadline class**
+Previously, the deadline field in the Deadline class was a string. I have modified this to be a java LocalDate object for better date time management. I also modified the validation regex and error messages to distinguish between invalid date formats and invalid dates. For implementation of the sorting functionality, instead of having the basis of comparison between deadlines being defined in the sort method, I have modified the Deadline class to implement the comparable interface and defined the basis of comparison within the Deadline class itself. This allows for simpler code and better abstraction.
+
+**4. Refactor person to company**
+Changed the person model to company model for better OOP at the start of the project.
+
+#### Contribution to the UG:
+
+The following sections from the UG were contributed by me:
+
+1. Features:
+ - Sort command: Added description, examples and possible errors for the sort command.
+ - Find a company: Added description, examples and possible error for the find command.
+2. Added known issues
+3. Added FAQ:
+ - How do I load data from another computer?
+ - How do I open up my terminal?
+
+#### Contribution to the DG:
+
+- Updated the models to use Company instead of Person
+- Added a sequence diagram for the find command implementation discussion
+- Added uses cases for sorting by deadline
+- Reordered the user stories table to be in order of priority
+
+#### Contribution to team-based tasks:
+
+- Created the developers team in our team organization and linked the team repo to it.
+- Created additional labels for bug triaging for the project.
+- Created a release template for the project and managed two releases, v1.2.0 and v1.3.0.
+- Created a pull request template for the project.
+- Maintained the GitHub issues page to remove duplicates and close issues that are no longer relevant.
+
+#### Review/mentoring contributions:
+
+- PRs reviewed:
+ - [#107](https://github.com/AY2324S1-CS2103T-T17-2/tp/pull/107), [#92](https://github.com/AY2324S1-CS2103T-T17-2/tp/pull/92), [#140](https://github.com/AY2324S1-CS2103T-T17-2/tp/pull/140), [#167](https://github.com/AY2324S1-CS2103T-T17-2/tp/pull/167)
+
+#### Contributions beyond the project team:
+
+- Bugs reported for the other team during PE-D: [link to issues](https://github.com/papataco14/ped/issues)
+- Helped others on the forum with smoke testing on Windows [link to forum post](https://github.com/nus-cs2103-AY2324S1/forum/issues/218)
+- Suggested a fix for better code in course textbook website [link to issue](https://github.com/nus-cs2103-AY2324S1/website/issues/2)
diff --git a/docs/team/tayruxin.md b/docs/team/tayruxin.md
new file mode 100644
index 00000000000..2bcd4a33f20
--- /dev/null
+++ b/docs/team/tayruxin.md
@@ -0,0 +1,97 @@
+---
+layout: page
+title: Tay Ru Xin's Project Portfolio Page
+---
+
+# Project: LinkMeIn
+
+LinkMeIn - Is a desktop address book application made for computer science to
+their internship application.
+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.
+
+The features in LinkMeIn can be categorised into 3 main categories:
+1. **General features:** Navigating the application. Includes, help, exit and clear commands.
+2. **Company management features:** Manage an entry of a company. Includes, add, delete, edit, view, remark and unremark commands.
+3. **Company list features:** Manage the list of companies added. Includes, list, find, sort and filter commands.
+
+Given below are my contributions to the project.
+
+## **Code contributed**:
+The code that I have contributed can be found in this [RepoSense link](https://nus-cs2103-ay2324s1.github.io/tp-dashboard/?search=tayruxin&breakdown=false&sort=groupTitle%20dsc&sortWithin=title&since=2023-09-22&timeframe=commit&mergegroup=&groupSelect=groupByRepos)
+
+## Enhancements implemented:
+
+**1. Implemented the view command.**
+
+Created a new command class `ViewCommand` to handle the view command. A new parser class `ViewCommandParser` was created to handle the parsing of the view command.
+Furthermore, a new UniqueCompanyList was created in `AddressBook` to store the
+filtered company list which will contain the company that the user wish to view. Test cases were added to test the view command.
+
+**2. Enhance error message for invalid index**
+
+Previously, when checking for invalid index, the error message is the same regardless of whether the index is out of bounds or the index is not a positive integer.
+
+I have enhanced the error message to be more specific to the error. I have added new methods in `String.util` to check if the index passed is an integer with the
+`isInteger` method.
+
+**3. Added the company detail panel and company detail card to the GUI.**
+
+Previously, the GUI only shows the list of companies that the user have. I have added a `CompanyDetailPanel` which extends `UiPart` to the GUI.
+Furthermore, I have added `CompanyDetailPanel.fxml` to the GUI.
+
+
+**4. Added the priority field to company model.**
+
+A new priority field was added to the company model. I have made the priority filed optional. When the user adds a company
+without indicated the priority, the priority will be set to `none`.
+
+**5. Added the application status field to company model.**
+
+A new application status field was added to the company model. The application status is an enums with 5 possible values.
+
+**6. Delete address field from the company model.**
+
+The address field was deleted from the company model as the address field was not used in any of the commands. Address field was also removed in all the various
+test cases.
+
+## Contribution to the UG:
+
+The following sections from the UG were contributed by me:
+1. **Introducing LinkMeIn's User Interface:** Added an intro to LinkMeIn's GUI.
+2. **Navigating the User Guide:** Added a section on how to navigate the UG, which includes symbols used and how the user guide is catered for all levels of users.
+3. **Quick Start:** Added this section to teach user how to download and set-up LinkMeIn.
+4. **Introducing LinkMeIn: A quick tour:** Added this section to teach first-time users how to use the application. Included features like
+add, view, delete, edit and clear.
+5. Features:
+ - View full company information: Added description, examples and possible errors for the view command.
+ - Delete a company: Added description, examples and possible error for the delete command.
+6. Added FAQ:
+ - How do I check if I have Java 11 installed?
+ - How do I open up my terminal?
+ - What is an invalid index?
+
+## Contribution to the DG:
+- Added use cases into the DG.
+- Added planned enhancements into the DG.
+- Added a UML sequence diagram for the view command into the DG.
+- Added a UML Activity diagram for the view command into the DG.
+- Elaborated on how the View command works in the DG.
+
+## Contribution to team-based tasks:
+- Set up the team repo and organisation on GitHub.
+- Created the labels that are required for the project.
+- Set up the project board in GitHub for user stories.
+- Help to enable assertion in the team repo (in `build.gradle`).
+
+## Review/mentoring contributions:
+- PRs reviewed:
+ - [\#135](https://github.com/AY2324S1-CS2103T-T17-2/tp/pull/135), [\#111](https://github.com/AY2324S1-CS2103T-T17-2/tp/pull/111),
+[\#89](https://github.com/AY2324S1-CS2103T-T17-2/tp/pull/89), [\#110](https://github.com/AY2324S1-CS2103T-T17-2/tp/pull/110),
+[\#147](https://github.com/AY2324S1-CS2103T-T17-2/tp/pull/147),
+[\#105](https://github.com/AY2324S1-CS2103T-T17-2/tp/pull/105)
+
+## Contributions beyond the project team:
+- Bugs reported for the other team during PE-D: [link to issues](https://github.com/tayruxin/ped/issues)
+
diff --git a/docs/tutorials/AddRemark.md b/docs/tutorials/AddRemark.md
deleted file mode 100644
index d98f38982e7..00000000000
--- a/docs/tutorials/AddRemark.md
+++ /dev/null
@@ -1,399 +0,0 @@
----
-layout: page
-title: "Tutorial: Adding a command"
----
-
-Let's walk you through the implementation of a new command — `remark`.
-
-This command allows users of the AddressBook application to add optional remarks to people in their address book and edit it if required. The command should have the following format:
-
-`remark INDEX r/REMARK` (e.g., `remark 2 r/Likes baseball`)
-
-We’ll assume that you have already set up the development environment as outlined in the Developer’s Guide.
-
-
-## Create a new `remark` command
-
-Looking in the `logic.command` package, you will notice that each existing command have their own class. All the commands inherit from the abstract class `Command` which means that they must override `execute()`. Each `Command` returns an instance of `CommandResult` upon success and `CommandResult#feedbackToUser` is printed to the `ResultDisplay`.
-
-Let’s start by creating a new `RemarkCommand` class in the `src/main/java/seedu/address/logic/command` directory.
-
-For now, let’s keep `RemarkCommand` as simple as possible and print some output. We accomplish that by returning a `CommandResult` with an accompanying message.
-
-**`RemarkCommand.java`:**
-
-``` java
-package seedu.address.logic.commands;
-
-import seedu.address.model.Model;
-
-/**
- * Changes the remark of an existing person in the address book.
- */
-public class RemarkCommand extends Command {
-
- public static final String COMMAND_WORD = "remark";
-
- @Override
- public CommandResult execute(Model model) {
- return new CommandResult("Hello from remark");
- }
-}
-```
-
-### Hook `RemarkCommand` into the application
-
-Now that we have our `RemarkCommand` ready to be executed, we need to update `AddressBookParser#parseCommand()` to recognize the `remark` keyword. Add the new command to the `switch` block by creating a new `case` that returns a new instance of `RemarkCommand`.
-
-You can refer to the changes in this [diff](https://github.com/se-edu/addressbook-level3/commit/35eb7286f18a029d39cb7a29df8f172a001e4fd8#diff-399c284cb892c20b7c04a69116fcff6ccc0666c5230a1db8e4a9145def8fa4ee).
-
-### Run the application
-
-Run `Main#main` and try out your new `RemarkCommand`. If everything went well, you should see something like this:
-
-![Output displayed](../images/add-remark/RemarkHello.png)
-
-## Change `RemarkCommand` to throw an exception
-
-While we have successfully printed a message to `ResultDisplay`, the command does not do what it is supposed to do. Let’s change the command to throw a `CommandException` to accurately reflect that our command is still a work in progress.
-
-![The relationship between RemarkCommand and Command](../images/add-remark/RemarkCommandClass.png)
-
-Following the convention in other commands, we add relevant messages as constants and use them.
-
-**`RemarkCommand.java`:**
-
-``` 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. "
- + "Existing remark will be overwritten by the input.\n"
- + "Parameters: INDEX (must be a positive integer) "
- + "r/ [REMARK]\n"
- + "Example: " + COMMAND_WORD + " 1 "
- + "r/ Likes to swim.";
-
- public static final String MESSAGE_NOT_IMPLEMENTED_YET =
- "Remark command not implemented yet";
-
- @Override
- public CommandResult execute(Model model) throws CommandException {
- throw new CommandException(MESSAGE_NOT_IMPLEMENTED_YET);
- }
-```
-
-## Enhancing `RemarkCommand`
-
-Let’s change `RemarkCommand` to parse input from the user.
-
-### Make the command accept parameters
-
-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;
-//...
-public class RemarkCommand extends Command {
- //...
- public static final String MESSAGE_ARGUMENTS = "Index: %1$d, Remark: %2$s";
-
- private final Index index;
- 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
- */
- public RemarkCommand(Index index, String remark) {
- requireAllNonNull(index, remark);
-
- this.index = index;
- this.remark = remark;
- }
- @Override
- public CommandResult execute(Model model) throws CommandException {
- throw new CommandException(
- String.format(MESSAGE_ARGUMENTS, index.getOneBased(), remark));
- }
-
- @Override
- public boolean equals(Object other) {
- if (other == this) {
- return true;
- }
-
- // instanceof handles nulls
- if (!(other instanceof RemarkCommand)) {
- return false;
- }
-
- RemarkCommand e = (RemarkCommand) other;
- return index.equals(e.index)
- && remark.equals(e.remark);
- }
-}
-```
-
-Your code should look something like [this](https://github.com/se-edu/addressbook-level3/commit/dc6d5139d08f6403da0ec624ea32bd79a2ae0cbf#diff-a8e35af8f9c251525063fae36c9852922a7e7195763018eacec60f3a4d87c594) after you are done.
-
-### Parse user input
-
-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.
-
-![The relationship between Parser and RemarkCommandParser](../images/add-remark/RemarkCommandParserClass.png)
-
-Thankfully, `ArgumentTokenizer#tokenize()` makes it trivial to parse user input. Let’s take a look at the JavaDoc provided for the function to understand what it does.
-
-**`ArgumentTokenizer.java`:**
-
-``` java
-/**
- * Tokenizes an arguments string and returns an {@code ArgumentMultimap}
- * object that maps prefixes to their respective argument values. Only the
- * given prefixes will be recognized in the arguments string.
- *
- * @param argsString Arguments string of the form:
- * {@code preamble value value ...}
- * @param prefixes Prefixes to tokenize the arguments string with
- * @return ArgumentMultimap object that maps prefixes to their
- * arguments
- */
-```
-
-We can tell `ArgumentTokenizer#tokenize()` to look out for our new prefix `r/` and it will return us an instance of `ArgumentMultimap`. Now let’s find out what we need to do in order to obtain the Index and String that we need. Let’s look through `ArgumentMultimap` :
-
-**`ArgumentMultimap.java`:**
-
-``` java
-/**
- * Returns the last value of {@code prefix}.
- */
-public Optional getValue(Prefix prefix) {
- List values = getAllValues(prefix);
- return values.isEmpty() ? Optional.empty() :
- Optional.of(values.get(values.size() - 1));
-}
-```
-
-This appears to be what we need to get a String of the remark. But what about the Index? Let's take a quick peek at existing `Command` that uses an index to see how it is done.
-
-**`DeleteCommandParser.java`:**
-
-``` java
-Index index = ParserUtil.parseIndex(args);
-return new DeleteCommand(index);
-```
-
-There appears to be another utility class that obtains an `Index` from the input provided by the user.
-
-Now that we have the know-how to extract the data that we need from the user’s input, we can parse the user command and create a new instance of `RemarkCommand`, as given below.
-
-**`RemarkCommandParser.java`:**
-
-``` java
-public RemarkCommand parse(String args) throws ParseException {
- requireNonNull(args);
- ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args,
- PREFIX_REMARK);
-
- Index index;
- try {
- index = ParserUtil.parseIndex(argMultimap.getPreamble());
- } catch (IllegalValueException ive) {
- throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT,
- RemarkCommand.MESSAGE_USAGE), ive);
- }
-
- String remark = argMultimap.getValue(PREFIX_REMARK).orElse("");
-
- return new RemarkCommand(index, remark);
-}
-```
-
-
-
-:information_source: Don’t forget to update `AddressBookParser` to use our new `RemarkCommandParser`!
-
-
-
-If you are stuck, check out the sample
-[here](https://github.com/se-edu/addressbook-level3/commit/dc6d5139d08f6403da0ec624ea32bd79a2ae0cbf#diff-8bf239e8e9529369b577701303ddd96af93178b4ed6735f91c2d8488b20c6b4a).
-
-## 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.
-
-### 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.
-
-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.
-
-### Make use of `Remark`
-
-Let’s change `RemarkCommand` and `RemarkCommandParser` to use the new `Remark` class instead of plain `String`. These should be relatively simple changes.
-
-## 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.
-
-Simply add the following to [`seedu.address.ui.PersonCard`](https://github.com/se-edu/addressbook-level3/commit/850b78879582f38accb05dd20c245963c65ea599#diff-639834f1e05afe2276a86372adf0fe5f69314642c2d93cfa543d614ce5a76688).
-
-**`PersonCard.java`:**
-
-``` java
-@FXML
-private Label remark;
-```
-
-
-`@FXML` is an annotation that marks a private or protected field and makes it accessible to FXML. It might sound like Greek to you right now, don’t worry — we will get back to it later.
-
-Then insert the following into [`main/resources/view/PersonListCard.fxml`](https://github.com/se-edu/addressbook-level3/commit/850b78879582f38accb05dd20c245963c65ea599#diff-d44c4f51c24f6253c277a2bb9bc440b8064d9c15ad7cb7ceda280bca032efce9).
-
-**`PersonListCard.fxml`:**
-
-``` xml
-
-```
-
-That’s it! Fire up the application again and you should see something like this:
-
-![$remark shows up in each entry](../images/add-remark/$Remark.png)
-
-## Modify `Person` to support a `Remark` field
-
-Since `PersonCard` displays data from a `Person`, we need to update `Person` to get our `Remark` displayed!
-
-### Modify `Person`
-
-We change the constructor of `Person` to take a `Remark`. We will also need to define new fields and accessors accordingly to store our new addition.
-
-### Update other usages of `Person`
-
-Unfortunately, a change to `Person` will cause other commands to break, you will have to modify these commands to use the updated `Person`!
-
-
-
-:bulb: Use the `Find Usages` feature in IntelliJ IDEA on the `Person` class to find these commands.
-
-
-
-Refer to [this commit](https://github.com/se-edu/addressbook-level3/commit/ce998c37e65b92d35c91d28c7822cd139c2c0a5c) and check that you have got everything in order!
-
-
-## Updating Storage
-
-AddressBook stores data by serializing `JsonAdaptedPerson` into `json` with the help of an external library — Jackson. Let’s update `JsonAdaptedPerson` to work with our new `Person`!
-
-While the changes to code may be minimal, the test data will have to be updated as well.
-
-
-
-:exclamation: You must delete AddressBook’s storage file located at `/data/addressbook.json` before running it! Not doing so will cause AddressBook to default to an empty address book!
-
-
-
-Check out [this commit](https://github.com/se-edu/addressbook-level3/commit/556cbd0e03ff224d7a68afba171ad2eb0ce56bbf)
-to see what the changes entail.
-
-## Finalizing the UI
-
-Now that we have finalized the `Person` class and its dependencies, we can now bind the `Remark` field to the UI.
-
-Just add [this one line of code!](https://github.com/se-edu/addressbook-level3/commit/5b98fee11b6b3f5749b6b943c4f3bd3aa049b692)
-
-**`PersonCard.java`:**
-
-``` java
-public PersonCard(Person person, int displayedIndex) {
- //...
- remark.setText(person.getRemark().value);
-}
-```
-
-![The remark label is bound properly!](../images/add-remark/RemarkBound.png)
-
-## Putting everything together
-
-After the previous step, we notice a peculiar regression — we went from displaying something to nothing at all. However, this is expected behavior as we are yet to update the `RemarkCommand` to make use of the code we've been adding in the last few steps.
-
-### Update `RemarkCommand` and `RemarkCommandParser`
-
-In this last step, we modify `RemarkCommand#execute()` to change the `Remark` of a `Person`. Since all fields in a `Person` are immutable, we create a new instance of a `Person` with the values that we want and
-save it with `Model#setPerson()`.
-
-**`RemarkCommand.java`:**
-
-``` java
-//...
- public static final String MESSAGE_ADD_REMARK_SUCCESS = "Added remark to Person: %1$s";
- public static final String MESSAGE_DELETE_REMARK_SUCCESS = "Removed remark from Person: %1$s";
-//...
- @Override
- public CommandResult execute(Model model) throws CommandException {
- 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 = new Person(
- personToEdit.getName(), personToEdit.getPhone(), personToEdit.getEmail(),
- personToEdit.getAddress(), remark, personToEdit.getTags());
-
- model.setPerson(personToEdit, editedPerson);
- model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
-
- return new CommandResult(generateSuccessMessage(editedPerson));
- }
-
- /**
- * Generates a command execution success message based on whether
- * the remark is added to or removed from
- * {@code personToEdit}.
- */
- private String generateSuccessMessage(Person personToEdit) {
- String message = !remark.value.isEmpty() ? MESSAGE_ADD_REMARK_SUCCESS : MESSAGE_DELETE_REMARK_SUCCESS;
- return String.format(message, personToEdit);
- }
-```
-
-![Congratulations!](../images/add-remark/RemarkComplete.png)
-
-## Writing tests
-
-Tests are crucial to ensuring that bugs don’t slip into the codebase unnoticed. This is especially true for large code bases where a change might lead to unintended behavior.
-
-Let’s verify the correctness of our code by writing some tests!
-
-Of course you can simply add the test cases manually, like you've been doing all along this tutorial. The result would be like the test cases in [here](https://github.com/se-edu/addressbook-level3/commit/fac8f3fd855d55831ca0cc73313b5943d49d4d6e#diff-ff58f7c10338b34f76645df49b71ecb2bafaf7611b20e7ff59ebc98475538a01). Alternatively, you can get the help of IntelliJ to generate the skeletons of the test cases, as explained in the next section.
-
-### Automatically generating tests
-
-The goal is to write effective and efficient tests to ensure that `RemarkCommand#execute()` behaves as expected.
-
-The convention for test names is `methodName_testScenario_expectedResult`. An example would be
-`execute_filteredList_success`.
-
-Let’s create a test for `RemarkCommand#execute()` to test that adding a remark works. On `IntelliJ IDEA` you can bring up the context menu and choose to `Go To` \> `Test` or use the appropriate keyboard shortcut.
-
-![Using the context menu to jump to tests](../images/add-remark/ContextMenu.png)
-
-Then, create a test for the `execute` method.
-
-![Creating a test for `execute`.](../images/add-remark/CreateTest.png)
-
-Following convention, let’s change the name of the generated method to `execute_addRemarkUnfilteredList_success`.
-
-Let’s use the utility functions provided in `CommandTestUtil`. The functions ensure that commands produce the expected `CommandResult` and output the correct message. In this case, `CommandTestUtil#assertCommandSuccess` is the best fit as we are testing that a `RemarkCommand` will successfully add a `Remark`.
-
-You should end up with a test that looks something like [this](https://github.com/se-edu/addressbook-level3/commit/fac8f3fd855d55831ca0cc73313b5943d49d4d6e#diff-ff58f7c10338b34f76645df49b71ecb2bafaf7611b20e7ff59ebc98475538a01R36-R49).
-
-## Conclusion
-
-This concludes the tutorial for adding a new `Command` to AddressBook.
diff --git a/docs/tutorials/RemovingFields.md b/docs/tutorials/RemovingFields.md
deleted file mode 100644
index f29169bc924..00000000000
--- a/docs/tutorials/RemovingFields.md
+++ /dev/null
@@ -1,112 +0,0 @@
----
-layout: page
-title: "Tutorial: Removing Fields"
----
-
-> Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.
->
-> — Antoine de Saint-Exupery
-
-When working on an existing code base, you will most likely find that some features that are no longer necessary.
-This tutorial aims to give you some practice on such a code 'removal' activity by removing the `address` field from `Person` class.
-
-
-
-**If you have done the [Add `remark` command tutorial](AddRemark.html) already**, you should know where the code had to be updated to add the field `remark`. From that experience, you can deduce where the code needs to be changed to _remove_ that field too. The removing of the `address` field can be done similarly.
-
-
-However, if you have no such prior knowledge, removing a field can take a quite a bit of detective work. This tutorial takes you through that process. **At least have a read even if you don't actually do the steps yourself.**
-
-
-
-* Table of Contents
-{:toc}
-
-## Safely deleting `Address`
-
-IntelliJ IDEA provides a refactoring tool that can identify *most* parts of a removal easily. Let’s try to use it as much as we can.
-
-### 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.
-* :bulb: To make things simpler, you can unselect the options `Search in comments and strings` and `Search for text occurrences`
-
-![Usages detected](../images/remove/UnsafeDelete.png)
-
-Choose to `View Usages` and you should be presented with a list of `Safe Delete Conflicts`. These conflicts describe locations in which the `Address` class is used.
-
-![List of conflicts](../images/remove/SafeDeleteConflicts.png)
-
-Remove usages of `Address` by performing `Safe Delete`s on each entry i.e., double-click on the entry (which takes you to the code in concern, right-click on that entity, and choose `Refactor` -> `Safe delete` as before). You will need to exercise discretion when removing usages of `Address`. Functions like `ParserUtil#parseAddress()` can be safely removed but its usages must be removed as well. Other usages like in `EditPersonDescriptor` may require more careful inspection.
-
-Let’s try removing references to `Address` in `EditPersonDescriptor`.
-
-1. Safe delete the field `address` in `EditPersonDescriptor`.
-
-1. Select `Yes` when prompted to remove getters and setters.
-
-1. Select `View Usages` again.
- ![UnsafeDeleteOnField](../images/remove/UnsafeDeleteOnField.png)
-
-1. Remove the usages of `address` and select `Do refactor` when you are done.
-
-
-
- :bulb: **Tip:** Removing usages may result in errors. Exercise discretion and fix them. For example, removing the `address` field from the `Person` class will require you to modify its constructor.
-
-
-1. Repeat the steps for the remaining usages of `Address`
-
-After you are done, verify that the application still works by compiling and running it again.
-
-### Manual refactoring
-
-Unfortunately, there are usages of `Address` that IntelliJ IDEA cannot identify. You can find them by searching for instances of the word `address` in your code (`Edit` \> `Find` \> `Find in path`).
-
-Places of interest to look out for would be resources used by the application. `main/resources` contains images and `fxml` files used by the application and `test/resources` contains test data. For example, there is a `$address` in each `PersonCard` that has not been removed nor identified.
-
-![$address](../images/remove/$address.png)
-
-A quick look at the `PersonCard` class and its `fxml` file quickly reveals why it slipped past the automated refactoring.
-
-**`PersonCard.java`**
-
-``` java
-...
-@FXML
-private Label address;
-...
-```
-
-**`PersonCard.fxml`**
-
-``` xml
-...
-
-
-
-...
-```
-
-After removing the `Label`, we can proceed to formally test our code. If everything went well, you should have most of your tests pass. Fix any remaining errors until the tests all pass.
-
-## Tidying up
-
-At this point, your application is working as intended and all your tests are passing. What’s left to do is to clean up references to `Address` in test data and documentation.
-
-In `src/test/data/`, data meant for testing purposes are stored. While keeping the `address` field in the json files does not cause the tests to fail, it is not good practice to let cruft from old features accumulate.
-
-**`invalidPersonAddressBook.json`:**
-
-```json
-{
- "persons": [ {
- "name": "Person with invalid name field: Ha!ns Mu@ster",
- "phone": "9482424",
- "email": "hans@example.com",
- "address": "4th street"
- } ]
-}
-```
-
-You can go through each individual `json` file and manually remove the `address` field.
diff --git a/docs/tutorials/TracingCode.md b/docs/tutorials/TracingCode.md
deleted file mode 100644
index 4fb62a83ef6..00000000000
--- a/docs/tutorials/TracingCode.md
+++ /dev/null
@@ -1,301 +0,0 @@
----
-layout: page
-title: "Tutorial: Tracing code"
----
-
-> Indeed, the ratio of time spent reading versus writing is well over 10 to 1. We are constantly reading old code as part of the effort to write new code. …\[Therefore,\] making it easy to read makes it easier to write.
->
-> — Robert C. Martin Clean Code: A Handbook of Agile Software Craftsmanship
-
-When trying to understand an unfamiliar code base, one common strategy used is to trace some representative execution path through the code base. One easy way to trace an execution path is to use a debugger to step through the code. In this tutorial, you will be using the IntelliJ IDEA’s debugger to trace the execution path of a specific user command.
-
-* Table of Contents
-{:toc}
-
-## Before we start
-
-Before we jump into the code, it is useful to get an idea of the overall structure and the high-level behavior of the application. This is provided in the 'Architecture' section of the developer guide. In particular, the architecture diagram (reproduced below), tells us that the App consists of several components.
-
-![ArchitectureDiagram](../images/ArchitectureDiagram.png)
-
-It also has a sequence diagram (reproduced below) that tells us how a command propagates through the App.
-
-
-
-Note how the diagram shows only the execution flows _between_ the main components. That is, it does not show details of the execution path *inside* each component. By hiding those details, the diagram aims to inform the reader about the overall execution path of a command without overwhelming the reader with too much details. In this tutorial, you aim to find those omitted details so that you get a more in-depth understanding of how the code works.
-
-Before we proceed, ensure that you have done the following:
-1. Read the [*Architecture* section of the DG](../DeveloperGuide.md#architecture)
-1. Set up the project in Intellij IDEA
-1. Learn basic debugging features of Intellij IDEA
- * If you are using a different IDE, we'll leave it to you to figure out the equivalent feature to use in your IDE.
- * If you are not using an IDE, we'll let you figure out how to achieve the same using your coding toolchain.
-
-## Setting a breakpoint
-
-As you know, the first step of debugging is to put in a breakpoint where you want the debugger to pause the execution. For example, if you are trying to understand how the App starts up, you would put a breakpoint in the first statement of the `main` method.
-
-In our case, we would want to begin the tracing at the very point where the App start processing user input (i.e., somewhere in the UI component), and then trace through how the execution proceeds through the UI component. However, the execution path through a GUI is often somewhat obscure due to various *event-driven mechanisms* used by GUI frameworks, which happens to be the case here too. Therefore, let us put the breakpoint where the `UI` transfers control to the `Logic` component.
-
-
-
-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`.
-
-
-
-
-
-: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.
-
-```java
-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;
-...
-}
-```
-
-But apparently, this is an interface, not a concrete implementation.
-That should be fine because the [Architecture section of the Developer Guide](../DeveloperGuide.html#architecture) tells us that components interact through interfaces. Here's the relevant diagram:
-
-
-
-Next, let's find out which statement(s) in the `UI` code is calling this method, thus transferring control from the `UI` to the `Logic`.
-
-
-
-:bulb: **Intellij Tip:** The ['**Find Usages**' feature](https://www.jetbrains.com/help/idea/find-highlight-usages.html#find-usages) can find from which parts of the code a class/method/variable is being used.
-
-
-![`Find Usages` tool window. `Edit` \> `Find` \> `Find Usages`.](../images/tracing/FindUsages.png)
-
-Bingo\! `MainWindow#executeCommand()` seems to be exactly what we’re looking for\!
-
-Now let’s set the breakpoint. First, double-click the item to reach the corresponding code. Once there, click on the left gutter to set a breakpoint, as shown below.
- ![LeftGutter](../images/tracing/LeftGutter.png)
-
-## Tracing the execution path
-
-Recall from the User Guide that the `edit` command has the format: `edit INDEX [n/NAME] [p/PHONE] [e/EMAIL] [a/ADDRESS] [t/TAG]…` For this tutorial we will be issuing the command `edit 1 n/Alice Yeoh`.
-
-
-
-:bulb: **Tip:** Over the course of the debugging session, you will encounter every major component in the application. Try to keep track of what happens inside the component and where the execution transfers to another component.
-
-
-1. To start the debugging session, simply `Run` \> `Debug Main`
-
-1. When the GUI appears, enter `edit 1 n/Alice Yeoh` into the command box and press `Enter`.
-
-1. The Debugger tool window should show up and show something like this:
- ![DebuggerStep1](../images/tracing/DebuggerStep1.png)
-
-1. Use the _Show execution point_ feature to jump to the line of code that we stopped at:
- ![ShowExecutionPoint](../images/tracing/ShowExecutionPoint.png)
- `CommandResult commandResult = logic.execute(commandText);` is the line that you end up at (i.e., the place where we put the breakpoint).
-
-1. We are interested in the `logic.execute(commandText)` portion of that line so let’s _Step in_ into that method call:
- ![StepInto](../images/tracing/StepInto.png)
-
-1. We end up in `LogicManager#execute()` (not `Logic#execute` -- but this is expected because we know the `execute()` method in the `Logic` interface is actually implemented by the `LogicManager` class). Let’s take a look at the body of the method. Given below is the same code, with additional explanatory comments.
-
- **LogicManager\#execute().**
-
- ``` java
- @Override
- public CommandResult execute(String commandText)
- throws CommandException, ParseException {
-
- //Logging, safe to ignore
- logger.info("----------------[USER COMMAND][" + commandText + "]");
-
- CommandResult commandResult;
- //Parse user input from String to a Command
- Command command = addressBookParser.parseCommand(commandText);
- //Executes the Command and stores the result
- commandResult = command.execute(model);
-
- try {
- //We can deduce that the previous line of code modifies model in some way
- // since it's being stored here.
- storage.saveAddressBook(model.getAddressBook());
- } catch (IOException ioe) {
- throw new CommandException(FILE_OPS_ERROR_MESSAGE + ioe, ioe);
- }
-
- return commandResult;
- }
- ```
-
-1. `LogicManager#execute()` appears to delegate most of the heavy lifting to other components. Let’s take a closer look at each one.
-
-1. _Step over_ the logging code since it is of no interest to us now.
- ![StepOver](../images/tracing/StepOver.png)
-
-1. _Step into_ the line where user input in parsed from a String to a Command, which should bring you to the `AddressBookParser#parseCommand()` method (partial code given below):
- ``` java
- public Command parseCommand(String userInput) throws ParseException {
- ...
- final String commandWord = matcher.group("commandWord");
- final String arguments = matcher.group("arguments");
- ...
- ```
-
-1. _Step over_ the statements in that method until you reach the `switch` statement. The 'Variables' window now shows the value of both `commandWord` and `arguments`:
- ![Variables](../images/tracing/Variables.png)
-
-1. We see that the value of `commandWord` is now `edit` but `arguments` is still not processed in any meaningful way.
-
-1. Stepping through the `switch` block, we end up at a call to `EditCommandParser().parse()` as expected (because the command we typed is an edit command).
-
- ``` java
- ...
- case EditCommand.COMMAND_WORD:
- return new EditCommandParser().parse(arguments);
- ...
- ```
-
-1. Let’s see what `EditCommandParser#parse()` does by stepping into it. You might have to click the 'step into' button multiple times here because there are two method calls in that statement: `EditCommandParser()` and `parse()`.
-
-
:bulb: **Intellij Tip:** Sometimes, you might end up stepping into functions that are not of interest. Simply use the `step out` button to get out of them!
-
-
-1. Stepping through the method shows that it calls `ArgumentTokenizer#tokenize()` and `ParserUtil#parseIndex()` to obtain the arguments and index required.
-
-1. The rest of the method seems to exhaustively check for the existence of each possible parameter of the `edit` command and store any possible changes in an `EditPersonDescriptor`. Recall that we can verify the contents of `editPersonDesciptor` through the 'Variables' window.
- ![EditCommand](../images/tracing/EditCommand.png)
-
-1. As you just traced through some code involved in parsing a command, you can take a look at this class diagram to see where the various parsing-related classes you encountered fit into the design of the `Logic` component.
-
-
-1. Let’s continue stepping through until we return to `LogicManager#execute()`.
-
- The sequence diagram below shows the details of the execution path through the Logic component. Does the execution path you traced in the code so far match the diagram?
- ![Tracing an `edit` command through the Logic component](../images/tracing/LogicSequenceDiagram.png)
-
-1. Now, step over until you read the statement that calls the `execute()` method of the `EditCommand` object received, and step into that `execute()` method (partial code given below):
-
- **`EditCommand#execute()`:**
- ``` java
- @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)) {
- 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));
- }
- ```
-
-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.
-
- * :bulb: This may be a good time to read through the [`Model` component section of the DG](../DeveloperGuide.html#model-component)
-
-1. As you step through the rest of the statements in the `EditCommand#execute()` method, you'll see that it creates a `CommandResult` object (containing information about the result of the execution) and returns it.
- Advancing the debugger by one more step should take you back to the middle of the `LogicManager#execute()` method.
-
-1. Given that you have already seen quite a few classes in the `Logic` component in action, see if you can identify in this partial class diagram some of the classes you've encountered so far, and see how they fit into the class structure of the `Logic` component:
-
- * :bulb: This may be a good time to read through the [`Logic` component section of the DG](../DeveloperGuide.html#logic-component)
-
-1. Similar to before, you can step over/into statements in the `LogicManager#execute()` method to examine how the control is transferred to the `Storage` component and what happens inside that component.
-
-
:bulb: **Intellij Tip:** When trying to step into a statement such as `storage.saveAddressBook(model.getAddressBook())` which contains multiple method calls, Intellij will let you choose (by clicking) which one you want to step into.
-
-
-1. As you step through the code inside the `Storage` component, you will eventually arrive at the `JsonAddressBook#saveAddressBook()` method which calls the `JsonSerializableAddressBook` constructor, to create an object that can be _serialized_ (i.e., stored in storage medium) in JSON format. That constructor is given below (with added line breaks for easier readability):
-
- **`JsonSerializableAddressBook` constructor:**
- ``` java
- /**
- * 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()));
- }
- ```
-
-1. It appears that a `JsonAdaptedPerson` is created for each `Person` and then added to the `JsonSerializableAddressBook`.
- This is because regular Java objects need to go through an _adaptation_ for them to be suitable to be saved in JSON format.
-
-1. While you are stepping through the classes in the `Storage` component, here is the component's class diagram to help you understand how those classes fit into the structure of the component.
-
- * :bulb: This may be a good time to read through the [`Storage` component section of the DG](../DeveloperGuide.html#storage-component)
-
-1. We can continue to step through until you reach the end of the `LogicManager#execute()` method and return to the `MainWindow#executeCommand()` method (the place where we put the original breakpoint).
-
-1. Stepping into `resultDisplay.setFeedbackToUser(commandResult.getFeedbackToUser());`, we end up in:
-
- **`ResultDisplay#setFeedbackToUser()`**
- ``` java
- public void setFeedbackToUser(String feedbackToUser) {
- requireNonNull(feedbackToUser);
- resultDisplay.setText(feedbackToUser);
- }
- ```
-
-1. Finally, you can step through until you reach the end of`MainWindow#executeCommand()`.
- :bulb: This may be a good time to read through the [`UI` component section of the DG](../DeveloperGuide.html#ui-component)
-
-
-## Conclusion
-
-In this tutorial, we traced a valid edit command from raw user input to the result being displayed to the user. From this tutorial, you learned more about how the various components work together to produce a response to a user command.
-
-Here are some quick questions you can try to answer based on your execution path tracing. In some cases, you can do further tracing for the given commands to find exactly what happens.
-
-1. In this tutorial, we traced the "happy path" (i.e., no errors). What
- do you think will happen if we traced the following commands
- instead? What exceptions do you think will be thrown (if any), where
- will the exceptions be thrown and where will they be handled?
-
- 1. `redit 1 n/Alice Yu`
-
- 2. `edit 0 n/Alice Yu`
-
- 3. `edit 1 n/Alex Yeoh`
-
- 4. `edit 1`
-
- 5. `edit 1 n/アリス ユー`
-
- 6. `edit 1 t/one t/two t/three t/one`
-
-2. What components will you have to modify to perform the following
- enhancements to the application?
-
- 1. Make command words case-insensitive
-
- 2. Allow `delete` to remove more than one index at a time
-
- 3. Save the address book in the CSV format instead
-
- 4. Add a new command
-
- 5. Add a new field to `Person`
-
- 6. Add a new entity to the address book
diff --git a/src/main/java/seedu/address/MainApp.java b/src/main/java/seedu/address/MainApp.java
index 3d6bd06d5af..f5333cf64b6 100644
--- a/src/main/java/seedu/address/MainApp.java
+++ b/src/main/java/seedu/address/MainApp.java
@@ -36,7 +36,7 @@
*/
public class MainApp extends Application {
- public static final Version VERSION = new Version(0, 2, 2, true);
+ public static final Version VERSION = new Version(1, 4, 0, true);
private static final Logger logger = LogsCenter.getLogger(MainApp.class);
@@ -45,7 +45,6 @@ public class MainApp extends Application {
protected Storage storage;
protected Model model;
protected Config config;
-
@Override
public void init() throws Exception {
logger.info("=============================[ Initializing AddressBook ]===========================");
@@ -89,7 +88,6 @@ private Model initModelManager(Storage storage, ReadOnlyUserPrefs userPrefs) {
+ " Will be starting with an empty AddressBook.");
initialData = new AddressBook();
}
-
return new ModelManager(initialData, userPrefs);
}
diff --git a/src/main/java/seedu/address/commons/util/StringUtil.java b/src/main/java/seedu/address/commons/util/StringUtil.java
index 61cc8c9a1cb..e138fdee395 100644
--- a/src/main/java/seedu/address/commons/util/StringUtil.java
+++ b/src/main/java/seedu/address/commons/util/StringUtil.java
@@ -65,4 +65,23 @@ public static boolean isNonZeroUnsignedInteger(String s) {
return false;
}
}
+
+ /**
+ * Checks if the provided string represents a valid non-zero integer.
+ *
+ * @param s The string to be checked for integer validity. Must not be null.
+ * @return {@code true} if the string represents an integer (e.g., 1, 2, 3, up to {@code Integer.MAX_VALUE}),
+ * {@code false} for any other non-null string input (e.g., empty string, "d", "c", "*", " a " (untrimmed),
+ * "3 0" (contains whitespace), "1 a" (contains letters).
+ * @throws NullPointerException if {@code s} is null.
+ */
+ public static boolean isInteger(String s) {
+ requireNonNull(s);
+ try {
+ int value = Integer.parseInt(s);
+ return true;
+ } catch (NumberFormatException nfe) {
+ return false; // Not an integer
+ }
+ }
}
diff --git a/src/main/java/seedu/address/logic/Logic.java b/src/main/java/seedu/address/logic/Logic.java
index 92cd8fa605a..4f486a746ae 100644
--- a/src/main/java/seedu/address/logic/Logic.java
+++ b/src/main/java/seedu/address/logic/Logic.java
@@ -8,7 +8,7 @@
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;
+import seedu.address.model.company.Company;
/**
* API of the Logic component
@@ -30,8 +30,8 @@ public interface Logic {
*/
ReadOnlyAddressBook getAddressBook();
- /** Returns an unmodifiable view of the filtered list of persons */
- ObservableList getFilteredPersonList();
+ /** Returns an unmodifiable view of the filtered list of companies */
+ ObservableList getFilteredCompanyList();
/**
* Returns the user prefs' address book file path.
@@ -47,4 +47,10 @@ public interface Logic {
* Set the user prefs' GUI settings.
*/
void setGuiSettings(GuiSettings guiSettings);
+
+ /**
+ * Returns the current viewed company.
+ */
+ public ObservableList getCurrentViewedCompany();
+
}
diff --git a/src/main/java/seedu/address/logic/LogicManager.java b/src/main/java/seedu/address/logic/LogicManager.java
index 5aa3b91c7d0..a990cb52f91 100644
--- a/src/main/java/seedu/address/logic/LogicManager.java
+++ b/src/main/java/seedu/address/logic/LogicManager.java
@@ -15,7 +15,7 @@
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.model.company.Company;
import seedu.address.storage.Storage;
/**
@@ -33,6 +33,7 @@ public class LogicManager implements Logic {
private final Storage storage;
private final AddressBookParser addressBookParser;
+
/**
* Constructs a {@code LogicManager} with the given {@code Model} and {@code Storage}.
*/
@@ -67,8 +68,8 @@ public ReadOnlyAddressBook getAddressBook() {
}
@Override
- public ObservableList getFilteredPersonList() {
- return model.getFilteredPersonList();
+ public ObservableList getFilteredCompanyList() {
+ return model.getFilteredCompanyList();
}
@Override
@@ -85,4 +86,10 @@ public GuiSettings getGuiSettings() {
public void setGuiSettings(GuiSettings guiSettings) {
model.setGuiSettings(guiSettings);
}
+
+ @Override
+ public ObservableList getCurrentViewedCompany() {
+ return model.getCurrentViewedCompany();
+ }
+
}
diff --git a/src/main/java/seedu/address/logic/Messages.java b/src/main/java/seedu/address/logic/Messages.java
index ecd32c31b53..d373786b262 100644
--- a/src/main/java/seedu/address/logic/Messages.java
+++ b/src/main/java/seedu/address/logic/Messages.java
@@ -5,19 +5,59 @@
import java.util.stream.Stream;
import seedu.address.logic.parser.Prefix;
-import seedu.address.model.person.Person;
+import seedu.address.model.company.Company;
/**
* 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!";
+
+ public static final String MESSAGE_INVALID_COMMAND_FORMAT =
+ "Oops! You have entered an invalid command format. "
+ + "Please follow the command format below and try again! \n%1$s";
+
+ public static final String MESSAGE_INVALID_COMPANY_DISPLAYED_INDEX =
+ "Oops! You have entered an index that is greater than the number of companies that you have in the "
+ + "current list. Please try again!";
+
+ public static final String MESSAGE_COMPANIES_LISTED_OVERVIEW = "Company(s) listed: %1$d";
+
public static final String MESSAGE_DUPLICATE_FIELDS =
- "Multiple values specified for the following single-valued field(s): ";
+ "Oops! Multiple values are specified for the following single-valued parameter(s): ";
+
+ public static final String MESSAGE_NON_INTEGER_INDEX = "Oops! The index you provided is not valid.\n"
+ + "It should be a positive integer and within the range of 1 to "
+ + Integer.MAX_VALUE + ".\n"
+ + "Please try again with a valid index!";
+
+ public static final String MESSAGE_NON_POSITIVE_INTEGER_INDEX = "Oops! The index you have given is not a "
+ + "positive integer. Please try again with a positive integer!";
+
+ public static final String MESSAGE_EMPTY_INDEX = "Oops! The index you have given is empty. "
+ + "Remember to key in an index!";
+
+ public static final String MESSAGE_EMPTY_PREFIX = "Oops! You have not entered any parameters. "
+ + "Remember to follow the command format below! \n%1$s";
+
+ public static final String MESSAGE_DUPLICATE_COMPANY_ADD_COMMAND_WITH_NO_CHANGES =
+ "Oops! Duplicate entry is detected. \n"
+ + "You already have another entry with the exact same details for the "
+ + "company %s with the role %s and deadline %s.";
+
+ public static final String MESSAGE_DUPLICATE_COMPANY_ADD_COMMAND_WITH_CHANGES_ON_UNFILTERED_LIST =
+ "Oops! Duplicate Entry Detected\n"
+ + "You already have another entry for the company %s with the role %s and deadline %s.\n"
+ + "Perhaps you meant to use the edit command instead? Type: list, followed by edit %d %s";
+
+ public static final String MESSAGE_DUPLICATE_COMPANY_ADD_COMMAND_WITH_CHANGES_ON_FILTERED_LIST =
+ "Oops! Duplicate Entry Detected\n"
+ + "You already have another entry for the company %s with the role %s and deadline %s.\n"
+ + "Perhaps you meant to use the edit command instead? Type: edit %d %s";
+
+ public static final String MESSAGE_DUPLICATE_COMPANY_EDIT_COMMAND =
+ "Oops! Duplicate Entry Detected\nYou already have another entry for the company %s with the "
+ + "role %s and deadline %s";
/**
* Returns an error message indicating the duplicate prefixes.
@@ -28,24 +68,88 @@ public static String getErrorMessageForDuplicatePrefixes(Prefix... duplicatePref
Set duplicateFields =
Stream.of(duplicatePrefixes).map(Prefix::toString).collect(Collectors.toSet());
- return MESSAGE_DUPLICATE_FIELDS + String.join(" ", duplicateFields);
+ return MESSAGE_DUPLICATE_FIELDS + String.join(" ", duplicateFields) + "\n"
+ + "Please try again with only one value for each parameter!";
}
/**
- * Formats the {@code person} for display to the user.
+ * Returns an error message indicating the duplicate company information for the add command.
+ *
+ * @param company
+ * @param index
+ * @param allChangedFields
+ * @return string representing the error message
*/
- public static String format(Person person) {
+ public static String getErrorMessageForDuplicateCompanyAddCommand(Company company,
+ int index, String allChangedFields,
+ boolean isFiltered) {
+ if (allChangedFields.isEmpty()) {
+ return String.format(MESSAGE_DUPLICATE_COMPANY_ADD_COMMAND_WITH_NO_CHANGES,
+ company.getName(), company.getRole(), company.getDeadline(), index + 1);
+ }
+ if (isFiltered) {
+ return String.format(MESSAGE_DUPLICATE_COMPANY_ADD_COMMAND_WITH_CHANGES_ON_FILTERED_LIST,
+ company.getName(), company.getRole(), company.getDeadline(), index + 1, allChangedFields);
+ } else {
+ return String.format(MESSAGE_DUPLICATE_COMPANY_ADD_COMMAND_WITH_CHANGES_ON_UNFILTERED_LIST,
+ company.getName(), company.getRole(), company.getDeadline(), index + 1, allChangedFields);
+ }
+ }
+
+ /**
+ * Returns an error message indicating the duplicate company information for the edit command.
+ *
+ * @param company
+ * @return string representing the error message
+ */
+ public static String getDupErrMsgEdit(Company company) {
+ return String.format(MESSAGE_DUPLICATE_COMPANY_EDIT_COMMAND,
+ company.getName(), company.getRole(), company.getDeadline());
+ }
+
+ /**
+ * Formats the {@code company} for display to the user.
+ */
+ public static String format(Company company) {
final StringBuilder builder = new StringBuilder();
- builder.append(person.getName())
+ builder.append(company.getName())
+ .append("; Role: ")
+ .append(company.getRole())
+ .append("; Status: ")
+ .append(company.getStatus())
+ .append("; Deadline: ")
+ .append(company.getDeadline())
+ .append("; Recruiter Name: ")
+ .append(company.getRecruiterName())
.append("; Phone: ")
- .append(person.getPhone())
+ .append(company.getPhone())
.append("; Email: ")
- .append(person.getEmail())
- .append("; Address: ")
- .append(person.getAddress())
- .append("; Tags: ");
- person.getTags().forEach(builder::append);
+ .append(company.getEmail())
+ .append("; Priority: ")
+ .append(company.getPriority());
return builder.toString();
}
+ /**
+ * Generates a string containing the name of the given {@code Company}.
+ *
+ * @param company The company for which the name is to be generated.
+ * @return A string containing the name of the given {@code Company}.
+ */
+ public static String getCompanyName(Company company) {
+ return company.getName().toString();
+ }
+
+ /**
+ * Generates a string containing relevant information about the given {@code Company}.
+ * The information includes the company name, role, and deadline.
+ *
+ * @param company The company for which information is to be generated.
+ * @return A string containing relevant information about the given {@code Company}.
+ */
+ public static String getCompanyInfo(Company company) {
+ return company.getName().toString() + " (" + "Role: " + company.getRole().toString()
+ + ", " + "Deadline: " + company.getDeadline().toString() + ")";
+
+ }
}
diff --git a/src/main/java/seedu/address/logic/SortOrder.java b/src/main/java/seedu/address/logic/SortOrder.java
new file mode 100644
index 00000000000..a67f7633120
--- /dev/null
+++ b/src/main/java/seedu/address/logic/SortOrder.java
@@ -0,0 +1,9 @@
+package seedu.address.logic;
+
+/**
+ * Represents the order in which the companies are sorted.
+ */
+public enum SortOrder {
+ ASCENDING,
+ DESCENDING
+}
diff --git a/src/main/java/seedu/address/logic/commands/AddCommand.java b/src/main/java/seedu/address/logic/commands/AddCommand.java
index 5d7185a9680..b8547303a2b 100644
--- a/src/main/java/seedu/address/logic/commands/AddCommand.java
+++ b/src/main/java/seedu/address/logic/commands/AddCommand.java
@@ -1,65 +1,98 @@
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_COMPANY_NAME;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_DEADLINE;
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.logic.parser.CliSyntax.PREFIX_PRIORITY;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_RECRUITER_NAME;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_ROLE;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_STATUS;
+import java.util.logging.Logger;
+
+import seedu.address.commons.core.LogsCenter;
import seedu.address.commons.util.ToStringBuilder;
import seedu.address.logic.Messages;
import seedu.address.logic.commands.exceptions.CommandException;
import seedu.address.model.Model;
-import seedu.address.model.person.Person;
+import seedu.address.model.company.Company;
/**
- * Adds a person to the address book.
+ * Adds a company 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 "
+ public static final String MESSAGE_USAGE =
+ "Format: " + COMMAND_WORD + " "
+ + PREFIX_COMPANY_NAME + "COMPANY_NAME "
+ + PREFIX_ROLE + "ROLE "
+ + PREFIX_STATUS + "STATUS "
+ + PREFIX_DEADLINE + "DEADLINE "
+ + PREFIX_RECRUITER_NAME + "RECRUITER_NAME "
+ PREFIX_PHONE + "PHONE "
+ PREFIX_EMAIL + "EMAIL "
- + PREFIX_ADDRESS + "ADDRESS "
- + "[" + PREFIX_TAG + "TAG]...\n"
+ + "[" + PREFIX_PRIORITY + "PRIORITY] \n"
+ "Example: " + COMMAND_WORD + " "
- + PREFIX_NAME + "John Doe "
+ + PREFIX_COMPANY_NAME + "Google "
+ + PREFIX_ROLE + "Software Engineer "
+ + PREFIX_STATUS + "PA "
+ + PREFIX_DEADLINE + "10-10-2023 "
+ + PREFIX_RECRUITER_NAME + "Francis Tan "
+ PREFIX_PHONE + "98765432 "
+ PREFIX_EMAIL + "johnd@example.com "
- + PREFIX_ADDRESS + "311, Clementi Ave 2, #02-25 "
- + PREFIX_TAG + "friends "
- + PREFIX_TAG + "owesMoney";
+ + PREFIX_PRIORITY + "HIGH ";
+
+ public static final String MESSAGE_SUCCESS = "New company added: %1$s";
- 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 static final Logger logger = LogsCenter.getLogger(AddCommand.class);
- private final Person toAdd;
+ private final Company toAdd;
/**
- * Creates an AddCommand to add the specified {@code Person}
+ * Creates an AddCommand to add the specified {@code Company}
*/
- public AddCommand(Person person) {
- requireNonNull(person);
- toAdd = person;
+ public AddCommand(Company company) {
+ requireNonNull(company);
+ toAdd = company;
}
@Override
public CommandResult execute(Model model) throws CommandException {
requireNonNull(model);
- if (model.hasPerson(toAdd)) {
- throw new CommandException(MESSAGE_DUPLICATE_PERSON);
+ if (model.hasCompany(toAdd)) {
+ Company duplicateCompany = model.getDuplicateCompany(toAdd);
+ int indexOfDuplicateCompany = model.getDuplicateIndexFromFilteredAddressbook(duplicateCompany);
+ boolean inFilteredList = true;
+
+ if (indexOfDuplicateCompany == -1) {
+ indexOfDuplicateCompany = model.getDuplicateIndexFromOriginalAddressbook(duplicateCompany);
+ inFilteredList = false;
+ }
+
+ String allChangedFields = toAdd.listAllChangedFields(duplicateCompany);
+
+ throw new CommandException.DuplicateException(
+ Messages.getErrorMessageForDuplicateCompanyAddCommand(
+ duplicateCompany, indexOfDuplicateCompany, allChangedFields,
+ inFilteredList));
}
- model.addPerson(toAdd);
- return new CommandResult(String.format(MESSAGE_SUCCESS, Messages.format(toAdd)));
+ logger.info("Executing add command: " + toAdd.toString());
+ model.addCompany(toAdd);
+ model.setCurrentViewedCompany(toAdd);
+
+ return new CommandResult(String.format(MESSAGE_SUCCESS, Messages.getCompanyName(toAdd)));
}
+ /**
+ * Returns true if both companies have the same identity and data fields.
+ * This defines a stronger notion of equality between two companies.
+ */
@Override
public boolean equals(Object other) {
if (other == this) {
diff --git a/src/main/java/seedu/address/logic/commands/ClearCommand.java b/src/main/java/seedu/address/logic/commands/ClearCommand.java
index 9c86b1fa6e4..0c53cf522a0 100644
--- a/src/main/java/seedu/address/logic/commands/ClearCommand.java
+++ b/src/main/java/seedu/address/logic/commands/ClearCommand.java
@@ -11,13 +11,14 @@
public class ClearCommand extends Command {
public static final String COMMAND_WORD = "clear";
- public static final String MESSAGE_SUCCESS = "Address book has been cleared!";
+ public static final String MESSAGE_SUCCESS = "The list of companies has been cleared!";
@Override
public CommandResult execute(Model model) {
requireNonNull(model);
model.setAddressBook(new AddressBook());
+ model.clearCompanyDetailPanel();
return new CommandResult(MESSAGE_SUCCESS);
}
}
diff --git a/src/main/java/seedu/address/logic/commands/Command.java b/src/main/java/seedu/address/logic/commands/Command.java
index 64f18992160..68b9f092d60 100644
--- a/src/main/java/seedu/address/logic/commands/Command.java
+++ b/src/main/java/seedu/address/logic/commands/Command.java
@@ -12,7 +12,7 @@ public abstract class Command {
* Executes the 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
+ * @return feedback message of the operation result for display.
* @throws CommandException If an error occurs during command execution.
*/
public abstract CommandResult execute(Model model) throws CommandException;
diff --git a/src/main/java/seedu/address/logic/commands/DeleteCommand.java b/src/main/java/seedu/address/logic/commands/DeleteCommand.java
index 1135ac19b74..7b4a54348e7 100644
--- a/src/main/java/seedu/address/logic/commands/DeleteCommand.java
+++ b/src/main/java/seedu/address/logic/commands/DeleteCommand.java
@@ -9,21 +9,21 @@
import seedu.address.logic.Messages;
import seedu.address.logic.commands.exceptions.CommandException;
import seedu.address.model.Model;
-import seedu.address.model.person.Person;
+import seedu.address.model.company.Company;
/**
- * Deletes a person identified using it's displayed index from the address book.
+ * Deletes a company 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"
+ + ": Deletes the company identified by the index number used in the displayed company 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";
+ public static final String MESSAGE_DELETE_COMPANY_SUCCESS = "Deleted Company: %1$s";
private final Index targetIndex;
@@ -34,15 +34,18 @@ public DeleteCommand(Index targetIndex) {
@Override
public CommandResult execute(Model model) throws CommandException {
requireNonNull(model);
- List lastShownList = model.getFilteredPersonList();
+ List lastShownList = model.getFilteredCompanyList();
if (targetIndex.getZeroBased() >= lastShownList.size()) {
- throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
+ throw new CommandException(Messages.MESSAGE_INVALID_COMPANY_DISPLAYED_INDEX);
}
- Person personToDelete = lastShownList.get(targetIndex.getZeroBased());
- model.deletePerson(personToDelete);
- return new CommandResult(String.format(MESSAGE_DELETE_PERSON_SUCCESS, Messages.format(personToDelete)));
+ Company companyToDelete = lastShownList.get(targetIndex.getZeroBased());
+ model.deleteCompany(companyToDelete);
+ model.checkDelete(companyToDelete);
+
+ return new CommandResult(String.format(MESSAGE_DELETE_COMPANY_SUCCESS,
+ Messages.getCompanyInfo(companyToDelete)));
}
@Override
diff --git a/src/main/java/seedu/address/logic/commands/EditCommand.java b/src/main/java/seedu/address/logic/commands/EditCommand.java
index 4b581c7331e..f03b703398a 100644
--- a/src/main/java/seedu/address/logic/commands/EditCommand.java
+++ b/src/main/java/seedu/address/logic/commands/EditCommand.java
@@ -1,107 +1,122 @@
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_COMPANY_NAME;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_DEADLINE;
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 static seedu.address.logic.parser.CliSyntax.PREFIX_PRIORITY;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_RECRUITER_NAME;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_ROLE;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_STATUS;
-import java.util.Collections;
-import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
-import java.util.Set;
+import java.util.logging.Logger;
+import seedu.address.commons.core.LogsCenter;
import seedu.address.commons.core.index.Index;
import seedu.address.commons.util.CollectionUtil;
import seedu.address.commons.util.ToStringBuilder;
import seedu.address.logic.Messages;
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;
+import seedu.address.model.company.ApplicationStatus;
+import seedu.address.model.company.Company;
+import seedu.address.model.company.Deadline;
+import seedu.address.model.company.Email;
+import seedu.address.model.company.Name;
+import seedu.address.model.company.Phone;
+import seedu.address.model.company.Priority;
+import seedu.address.model.company.RecruiterName;
+import seedu.address.model.company.Remark;
+import seedu.address.model.company.Role;
/**
- * Edits the details of an existing person in the address book.
+ * Edits the details of an existing company 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] "
+ public static final String MESSAGE_USAGE = "Format: " + COMMAND_WORD + " "
+ + "INDEX "
+ + "[" + PREFIX_COMPANY_NAME + "COMPANY_NAME] "
+ + "[" + PREFIX_RECRUITER_NAME + "RECRUITER_NAME] "
+ + "[" + PREFIX_ROLE + "ROLE] "
+ + "[" + PREFIX_STATUS + "APPLICATION_STATUS] "
+ + "[" + PREFIX_DEADLINE + "DEADLINE] "
+ "[" + PREFIX_EMAIL + "EMAIL] "
- + "[" + PREFIX_ADDRESS + "ADDRESS] "
- + "[" + PREFIX_TAG + "TAG]...\n"
+ + "[" + PREFIX_PHONE + "PHONE] "
+ + "[" + PREFIX_PRIORITY + "PRIORITY]\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_EDIT_COMPANY_SUCCESS = "%1$s company edited.";
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 static final Logger logger = LogsCenter.getLogger(EditCommand.class);
private final Index index;
- private final EditPersonDescriptor editPersonDescriptor;
+ private final EditCompanyDescriptor editCompanyDescriptor;
/**
- * @param index of the person in the filtered person list to edit
- * @param editPersonDescriptor details to edit the person with
+ * @param index of the company in the filtered company list to edit.
+ * @param editCompanyDescriptor details to edit the company with.
*/
- public EditCommand(Index index, EditPersonDescriptor editPersonDescriptor) {
+ public EditCommand(Index index, EditCompanyDescriptor editCompanyDescriptor) {
requireNonNull(index);
- requireNonNull(editPersonDescriptor);
+ requireNonNull(editCompanyDescriptor);
this.index = index;
- this.editPersonDescriptor = new EditPersonDescriptor(editPersonDescriptor);
+ this.editCompanyDescriptor = new EditCompanyDescriptor(editCompanyDescriptor);
}
@Override
public CommandResult execute(Model model) throws CommandException {
requireNonNull(model);
- List lastShownList = model.getFilteredPersonList();
+ List lastShownList = model.getFilteredCompanyList();
if (index.getZeroBased() >= lastShownList.size()) {
- throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
+ throw new CommandException(Messages.MESSAGE_INVALID_COMPANY_DISPLAYED_INDEX);
}
- Person personToEdit = lastShownList.get(index.getZeroBased());
- Person editedPerson = createEditedPerson(personToEdit, editPersonDescriptor);
+ Company companyToEdit = lastShownList.get(index.getZeroBased());
+ Company editedCompany = createEditedCompany(companyToEdit, editCompanyDescriptor);
- if (!personToEdit.isSamePerson(editedPerson) && model.hasPerson(editedPerson)) {
- throw new CommandException(MESSAGE_DUPLICATE_PERSON);
+ if (!companyToEdit.isSameCompany(editedCompany) && model.hasCompany(editedCompany)) {
+ Company duplicateCompany = model.getDuplicateCompany(editedCompany);
+
+ throw new CommandException.DuplicateException(
+ Messages.getDupErrMsgEdit(duplicateCompany));
}
- model.setPerson(personToEdit, editedPerson);
- model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
- return new CommandResult(String.format(MESSAGE_EDIT_PERSON_SUCCESS, Messages.format(editedPerson)));
+ logger.info("Executing edit command: " + editCompanyDescriptor);
+ model.setCompany(companyToEdit, editedCompany);
+ model.setCurrentViewedCompany(editedCompany);
+ return new CommandResult(String.format(MESSAGE_EDIT_COMPANY_SUCCESS, Messages.getCompanyName(editedCompany)));
}
/**
- * Creates and returns a {@code Person} with the details of {@code personToEdit}
- * edited with {@code editPersonDescriptor}.
+ * Creates and returns a {@code Company} with the details of {@code companyToEdit}
+ * edited with {@code editCompanyDescriptor}.
*/
- 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);
+ private static Company createEditedCompany(Company companyToEdit, EditCompanyDescriptor editCompanyDescriptor) {
+ assert companyToEdit != null;
+
+ Name updatedName = editCompanyDescriptor.getName().orElse(companyToEdit.getName());
+ Phone updatedPhone = editCompanyDescriptor.getPhone().orElse(companyToEdit.getPhone());
+ Email updatedEmail = editCompanyDescriptor.getEmail().orElse(companyToEdit.getEmail());
+ Role updatedRole = editCompanyDescriptor.getRole().orElse(companyToEdit.getRole());
+ Deadline updatedDeadline = editCompanyDescriptor.getDeadline().orElse(companyToEdit.getDeadline());
+ ApplicationStatus updatedStatus = editCompanyDescriptor.getStatus().orElse(companyToEdit.getStatus());
+ RecruiterName updatedRecruiterName = editCompanyDescriptor.getRecruiterName()
+ .orElse(companyToEdit.getRecruiterName());
+ Priority updatedPriority = editCompanyDescriptor.getPriority().orElse(companyToEdit.getPriority());
+ Remark updatedRemark = companyToEdit.getRemark();
+
+ return new Company(updatedName, updatedPhone, updatedEmail, updatedRole, updatedDeadline,
+ updatedStatus, updatedRecruiterName, updatedPriority, updatedRemark);
}
@Override
@@ -117,47 +132,53 @@ public boolean equals(Object other) {
EditCommand otherEditCommand = (EditCommand) other;
return index.equals(otherEditCommand.index)
- && editPersonDescriptor.equals(otherEditCommand.editPersonDescriptor);
+ && editCompanyDescriptor.equals(otherEditCommand.editCompanyDescriptor);
}
@Override
public String toString() {
return new ToStringBuilder(this)
.add("index", index)
- .add("editPersonDescriptor", editPersonDescriptor)
+ .add("editCompanyDescriptor", editCompanyDescriptor)
.toString();
}
/**
- * Stores the details to edit the person with. Each non-empty field value will replace the
- * corresponding field value of the person.
+ * Stores the details to edit the company with. Each non-empty field value will replace the
+ * corresponding field value of the company.
*/
- public static class EditPersonDescriptor {
+ public static class EditCompanyDescriptor {
private Name name;
private Phone phone;
private Email email;
- private Address address;
- private Set tags;
+ private Role role;
+ private Deadline deadline;
+ private ApplicationStatus status;
+ private RecruiterName recruiterName;
+ private Priority priority;
- public EditPersonDescriptor() {}
+ public EditCompanyDescriptor() {}
/**
* Copy constructor.
- * A defensive copy of {@code tags} is used internally.
*/
- public EditPersonDescriptor(EditPersonDescriptor toCopy) {
+ public EditCompanyDescriptor(EditCompanyDescriptor toCopy) {
setName(toCopy.name);
setPhone(toCopy.phone);
setEmail(toCopy.email);
- setAddress(toCopy.address);
- setTags(toCopy.tags);
+ setRole(toCopy.role);
+ setDeadline(toCopy.deadline);
+ setStatus(toCopy.status);
+ setRecruiterName(toCopy.recruiterName);
+ setPriority(toCopy.priority);
}
/**
* Returns true if at least one field is edited.
*/
public boolean isAnyFieldEdited() {
- return CollectionUtil.isAnyNonNull(name, phone, email, address, tags);
+ return CollectionUtil.isAnyNonNull(name, phone, email, role, deadline, status,
+ recruiterName, priority);
}
public void setName(Name name) {
@@ -184,29 +205,44 @@ public Optional getEmail() {
return Optional.ofNullable(email);
}
- public void setAddress(Address address) {
- this.address = address;
+ public void setRole(Role role) {
+ this.role = role;
}
- public Optional getAddress() {
- return Optional.ofNullable(address);
+ public Optional getRole() {
+ return Optional.ofNullable(role);
}
- /**
- * 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;
+ public void setDeadline(Deadline deadline) {
+ this.deadline = deadline;
}
- /**
- * 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();
+ public Optional getDeadline() {
+ return Optional.ofNullable(deadline);
+ }
+
+ public void setStatus(ApplicationStatus status) {
+ this.status = status;
+ }
+
+ public Optional getStatus() {
+ return Optional.ofNullable(status);
+ }
+
+ public void setRecruiterName(RecruiterName recruiterName) {
+ this.recruiterName = recruiterName;
+ }
+
+ public Optional getRecruiterName() {
+ return Optional.ofNullable(recruiterName);
+ }
+
+ public void setPriority(Priority priority) {
+ this.priority = priority;
+ }
+
+ public Optional getPriority() {
+ return Optional.ofNullable(priority);
}
@Override
@@ -216,26 +252,32 @@ public boolean equals(Object other) {
}
// instanceof handles nulls
- if (!(other instanceof EditPersonDescriptor)) {
+ if (!(other instanceof EditCompanyDescriptor)) {
return false;
}
- EditPersonDescriptor otherEditPersonDescriptor = (EditPersonDescriptor) other;
- return Objects.equals(name, otherEditPersonDescriptor.name)
- && Objects.equals(phone, otherEditPersonDescriptor.phone)
- && Objects.equals(email, otherEditPersonDescriptor.email)
- && Objects.equals(address, otherEditPersonDescriptor.address)
- && Objects.equals(tags, otherEditPersonDescriptor.tags);
+ EditCompanyDescriptor otherCompanyDescriptor = (EditCompanyDescriptor) other;
+ return Objects.equals(name, otherCompanyDescriptor.name)
+ && Objects.equals(phone, otherCompanyDescriptor.phone)
+ && Objects.equals(email, otherCompanyDescriptor.email)
+ && Objects.equals(role, otherCompanyDescriptor.role)
+ && Objects.equals(deadline, otherCompanyDescriptor.deadline)
+ && Objects.equals(status, otherCompanyDescriptor.status)
+ && Objects.equals(recruiterName, otherCompanyDescriptor.recruiterName)
+ && Objects.equals(priority, otherCompanyDescriptor.priority);
}
@Override
public String toString() {
return new ToStringBuilder(this)
.add("name", name)
+ .add("role", role)
+ .add("deadline", deadline)
+ .add("status", status)
+ .add("recruiter name", recruiterName)
.add("phone", phone)
.add("email", email)
- .add("address", address)
- .add("tags", tags)
+ .add("priority", priority)
.toString();
}
}
diff --git a/src/main/java/seedu/address/logic/commands/FilterCommand.java b/src/main/java/seedu/address/logic/commands/FilterCommand.java
new file mode 100644
index 00000000000..6271bbb71a0
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/FilterCommand.java
@@ -0,0 +1,74 @@
+package seedu.address.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_STATUS;
+
+import java.util.logging.Logger;
+
+import seedu.address.commons.core.LogsCenter;
+import seedu.address.commons.util.ToStringBuilder;
+import seedu.address.logic.commands.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.company.ApplicationStatus;
+import seedu.address.model.company.predicates.ApplicationStatusPredicate;
+
+/**
+ * Filters the company list by application status.
+ */
+public class FilterCommand extends Command {
+
+ public static final String COMMAND_WORD = "filter";
+
+ public static final String MESSAGE_USAGE =
+ "Format: " + COMMAND_WORD + " " + PREFIX_STATUS + "STATUS. Valid statuses are: PA, PI, PO, A, R\n"
+ + "Example: " + COMMAND_WORD + " " + PREFIX_STATUS + "PA";
+
+ public static final String MESSAGE_SUCCESS = "Filtered company list by application status: %1$s";
+
+ private static final Logger logger = LogsCenter.getLogger(FilterCommand.class);
+ private final ApplicationStatus status;
+ private final ApplicationStatusPredicate predicate;
+
+ /**
+ * Creates a FilterCommand to filter the company list by the specified {@code ApplicationStatus}.
+ *
+ * @param status application status to filter the company list by.
+ * @param predicate predicate to filter the company list by.
+ */
+ public FilterCommand(ApplicationStatus status, ApplicationStatusPredicate predicate) {
+ this.status = status;
+ this.predicate = predicate;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ logger.info("Executing filter command with status: " + status);
+ model.filterCompaniesByStatus(predicate);
+ return new CommandResult(String.format(MESSAGE_SUCCESS, status));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ }
+
+ // instanceof handles nulls
+ if (!(other instanceof FilterCommand)) {
+ return false;
+ }
+
+ FilterCommand otherFilterCommand = (FilterCommand) other;
+ return status.equals(otherFilterCommand.status)
+ && predicate.equals(otherFilterCommand.predicate);
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this)
+ .add("status", status)
+ .add("predicate", predicate)
+ .toString();
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/FindCommand.java b/src/main/java/seedu/address/logic/commands/FindCommand.java
index 72b9eddd3a7..2b161384d3f 100644
--- a/src/main/java/seedu/address/logic/commands/FindCommand.java
+++ b/src/main/java/seedu/address/logic/commands/FindCommand.java
@@ -2,23 +2,29 @@
import static java.util.Objects.requireNonNull;
+import java.util.logging.Logger;
+
+import seedu.address.commons.core.LogsCenter;
import seedu.address.commons.util.ToStringBuilder;
import seedu.address.logic.Messages;
import seedu.address.model.Model;
-import seedu.address.model.person.NameContainsKeywordsPredicate;
+import seedu.address.model.company.predicates.NameContainsKeywordsPredicate;
/**
- * Finds and lists all persons in address book whose name contains any of the argument keywords.
- * Keyword matching is case insensitive.
+ * Finds and lists all companies in the address book whose name matches the criteria
+ * specified in the provided predicate.
+ *
+ * For detailed matching behavior, see {@link NameContainsKeywordsPredicate}.
*/
public class FindCommand extends Command {
public static final String COMMAND_WORD = "find";
+ private static final Logger logger = LogsCenter.getLogger(FindCommand.class);
- public static final String MESSAGE_USAGE = COMMAND_WORD + ": Finds all persons whose names contain any of "
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Finds all companies 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";
+ + "Example: " + COMMAND_WORD + " micro ";
private final NameContainsKeywordsPredicate predicate;
@@ -29,9 +35,10 @@ public FindCommand(NameContainsKeywordsPredicate predicate) {
@Override
public CommandResult execute(Model model) {
requireNonNull(model);
- model.updateFilteredPersonList(predicate);
+ logger.info("Executing FindCommand with predicate: " + predicate);
+ model.findCompanies(predicate);
return new CommandResult(
- String.format(Messages.MESSAGE_PERSONS_LISTED_OVERVIEW, model.getFilteredPersonList().size()));
+ String.format(Messages.MESSAGE_COMPANIES_LISTED_OVERVIEW, model.getFilteredCompanyList().size()));
}
@Override
diff --git a/src/main/java/seedu/address/logic/commands/ListCommand.java b/src/main/java/seedu/address/logic/commands/ListCommand.java
index 84be6ad2596..f5a27dcc40b 100644
--- a/src/main/java/seedu/address/logic/commands/ListCommand.java
+++ b/src/main/java/seedu/address/logic/commands/ListCommand.java
@@ -1,24 +1,25 @@
package seedu.address.logic.commands;
import static java.util.Objects.requireNonNull;
-import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS;
+import static seedu.address.model.Model.PREDICATE_SHOW_ALL_COMPANIES;
import seedu.address.model.Model;
/**
- * Lists all persons in the address book to the user.
+ * Lists all companies 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";
+ public static final String MESSAGE_SUCCESS = "Listed all companies";
@Override
public CommandResult execute(Model model) {
requireNonNull(model);
- model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
+ model.updateFilteredCompanyList(PREDICATE_SHOW_ALL_COMPANIES);
+
return new CommandResult(MESSAGE_SUCCESS);
}
}
diff --git a/src/main/java/seedu/address/logic/commands/RemarkCommand.java b/src/main/java/seedu/address/logic/commands/RemarkCommand.java
new file mode 100644
index 00000000000..5b5a16fcf1c
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/RemarkCommand.java
@@ -0,0 +1,105 @@
+package seedu.address.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_REMARK;
+
+import java.util.List;
+import java.util.logging.Logger;
+
+import seedu.address.commons.core.LogsCenter;
+import seedu.address.commons.core.index.Index;
+import seedu.address.logic.Messages;
+import seedu.address.logic.commands.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.company.Company;
+import seedu.address.model.company.Remark;
+
+/**
+ * Adds a remark to an existing company in the address book.
+ */
+public class RemarkCommand extends Command {
+
+ public static final String COMMAND_WORD = "remark";
+ public static final String REMOVE_COMMAND_WORD = "unremark";
+ public static final String MESSAGE_USAGE = "Format: " + COMMAND_WORD
+ + " INDEX (must be a positive integer) "
+ + PREFIX_REMARK + "REMARK\n"
+ + "Example: " + COMMAND_WORD + " 1 "
+ + PREFIX_REMARK + "Experience in Java";
+ public static final String MESSAGE_REMOVE_USAGE = REMOVE_COMMAND_WORD
+ + ": Removes the remark identified by the index number used in the displayed company list.\n"
+ + "Parameters: INDEX (must be a positive integer)\n"
+ + "Example: " + COMMAND_WORD + " 1";
+
+ public static final String MESSAGE_NO_REMARK = "Oops! No remarks found in entry. Please try again!\n"
+ + MESSAGE_USAGE;
+ public static final String MESSAGE_ADD_REMARK_SUCCESS = "Added remark to Company: %1$s";
+ public static final String MESSAGE_DELETE_REMARK_SUCCESS = "Removed remark from Company: %1$s";
+
+ private static final Logger logger = LogsCenter.getLogger(RemarkCommand.class);
+ private final Index index;
+ private final Remark remark;
+
+ /**
+ * @param index of the company in the filtered company list to edit the remark.
+ * @param remark of the company to be updated to.
+ */
+ public RemarkCommand(Index index, Remark remark) {
+ requireAllNonNull(index, remark);
+
+ this.index = index;
+ this.remark = remark;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ List lastShownList = model.getFilteredCompanyList();
+
+ if (index.getZeroBased() >= lastShownList.size()) {
+ throw new CommandException(Messages.MESSAGE_INVALID_COMPANY_DISPLAYED_INDEX);
+ }
+
+
+ Company companyToRemark = lastShownList.get(index.getZeroBased());
+ Company remarkedCompany = new Company(companyToRemark.getName(), companyToRemark.getPhone(),
+ companyToRemark.getEmail(), companyToRemark.getRole(), companyToRemark.getDeadline(),
+ companyToRemark.getStatus(), companyToRemark.getRecruiterName(), companyToRemark.getPriority(),
+ remark);
+
+ logger.info("Executing remark command with remark: " + remark);
+ model.setCompany(companyToRemark, remarkedCompany);
+ model.setCurrentViewedCompany(remarkedCompany);
+
+ return new CommandResult(generateSuccessMessage(remarkedCompany));
+ }
+
+ /**
+ * Generates a command execution success message based on whether the remark is added to or removed from
+ * {@code companyToEdit}.
+ */
+ private String generateSuccessMessage(Company companyToEdit) {
+ assert companyToEdit != null;
+
+ String message = remark.getIsDeleted() ? MESSAGE_DELETE_REMARK_SUCCESS : MESSAGE_ADD_REMARK_SUCCESS;
+ return String.format(message, Messages.getCompanyName(companyToEdit));
+ }
+
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ }
+
+ // instanceof handles nulls
+ if (!(other instanceof RemarkCommand)) {
+ return false;
+ }
+
+ RemarkCommand e = (RemarkCommand) other;
+ return index.equals(e.index)
+ && remark.equals(e.remark);
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/SortCommand.java b/src/main/java/seedu/address/logic/commands/SortCommand.java
new file mode 100644
index 00000000000..864bc38ab38
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/SortCommand.java
@@ -0,0 +1,77 @@
+package seedu.address.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+
+import java.util.Comparator;
+import java.util.List;
+import java.util.logging.Logger;
+import java.util.stream.Collectors;
+
+import javafx.collections.FXCollections;
+import seedu.address.commons.core.LogsCenter;
+import seedu.address.logic.SortOrder;
+import seedu.address.model.Model;
+import seedu.address.model.company.Company;
+
+/**
+ * Sorts and lists all companies in the address book to the user by their deadlines.
+ */
+public class SortCommand extends Command {
+
+ public static final String COMMAND_WORD = "sort";
+
+ public static final String MESSAGE_SUCCESS_ASCENDING = "Sorted all companies by their deadlines in ascending order";
+ public static final String MESSAGE_SUCCESS_DESCENDING = "Sorted all companies by their deadlines in descending "
+ + "order";
+ public static final String MESSAGE_INVALID_SORT_ORDER = "Oops! You have entered an invalid sort order. "
+ + "Please try again with a valid sort order! \n%1$s";
+
+ public static final String MESSAGE_USAGE = "Valid ascending sort orders: a, asc, ascending. Valid descending "
+ + "sort orders: d, desc, descending, \n" + "Example: " + COMMAND_WORD + " ascending";
+ private static final Logger logger = LogsCenter.getLogger(SortCommand.class);
+ private final SortOrder sortOrder;
+
+ /**
+ * Creates a SortCommand to sort the companies by their deadlines.
+ *
+ * @param sortOrder the order in which the companies are sorted.
+ */
+ public SortCommand(SortOrder sortOrder) {
+ this.sortOrder = sortOrder;
+ }
+ @Override
+ public CommandResult execute(Model model) {
+ requireNonNull(model);
+ logger.info("Executing SortCommand in " + sortOrder.toString().toLowerCase() + " order");
+
+ Comparator comparator = sortOrder == SortOrder.ASCENDING
+ ? Comparator.comparing(Company::getDeadline) : Comparator.comparing(Company::getDeadline).reversed();
+
+ List sortedList = model.getAddressBook().getCompanyList().stream()
+ .sorted(comparator)
+ .collect(Collectors.toList());
+
+ model.setAllCompanies(FXCollections.observableArrayList(sortedList));
+ return new CommandResult(sortOrder == SortOrder.ASCENDING ? MESSAGE_SUCCESS_ASCENDING
+ : MESSAGE_SUCCESS_DESCENDING);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+
+ if (!(other instanceof SortCommand)) {
+ return false;
+ }
+
+ SortCommand otherSortCommand = (SortCommand) other;
+ return sortOrder == otherSortCommand.sortOrder;
+ }
+
+ @Override
+ public String toString() {
+ return COMMAND_WORD + " " + sortOrder.toString();
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/ViewCommand.java b/src/main/java/seedu/address/logic/commands/ViewCommand.java
new file mode 100644
index 00000000000..069964f4979
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/ViewCommand.java
@@ -0,0 +1,83 @@
+package seedu.address.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.model.Model.PREDICATE_SHOW_ALL_COMPANIES;
+
+import java.util.List;
+import java.util.logging.Logger;
+
+import seedu.address.commons.core.LogsCenter;
+import seedu.address.commons.core.index.Index;
+import seedu.address.commons.util.ToStringBuilder;
+import seedu.address.logic.Messages;
+import seedu.address.logic.commands.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.company.Company;
+
+/**
+ * Views a company identified using it's displayed index from the address book.
+ */
+public class ViewCommand extends Command {
+
+ public static final String COMMAND_WORD = "view";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Views the company identified by the index number used in the displayed company list.\n"
+ + "Parameters: INDEX (must be a positive integer)\n"
+ + "Example: " + COMMAND_WORD + " 1";
+
+ public static final String MESSAGE_VIEW_COMPANY_SUCCESS = "Viewing Company: %1$s";
+
+ private static final Logger logger = LogsCenter.getLogger(FindCommand.class);
+
+ private final Index targetIndex;
+
+ /**
+ * Creates an ViewCommand to view the specified {@code Company}.
+ *
+ * @param targetIndex index of the company in the filtered company list to view
+ */
+ public ViewCommand(Index targetIndex) {
+ this.targetIndex = targetIndex;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ List lastShownList = model.getFilteredCompanyList();
+
+ if (targetIndex.getZeroBased() >= lastShownList.size()) {
+ throw new CommandException(Messages.MESSAGE_INVALID_COMPANY_DISPLAYED_INDEX);
+ }
+ Company companyToView = lastShownList.get(targetIndex.getZeroBased());
+
+ model.setCurrentViewedCompany(companyToView);
+ model.updateCurrentViewedCompany(PREDICATE_SHOW_ALL_COMPANIES);
+ logger.info("Executing view command: " + companyToView.toString());
+
+ // name of the company to view
+ String companyDetailsToDisplayString = companyToView.getName().toString();
+ return new CommandResult(String.format(MESSAGE_VIEW_COMPANY_SUCCESS, companyDetailsToDisplayString));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ }
+
+ if (!(other instanceof ViewCommand)) {
+ return false;
+ }
+
+ ViewCommand otherViewCommand = (ViewCommand) other;
+ return targetIndex.equals(otherViewCommand.targetIndex);
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this)
+ .add("targetIndex", targetIndex)
+ .toString();
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/exceptions/CommandException.java b/src/main/java/seedu/address/logic/commands/exceptions/CommandException.java
index a16bd14f2cd..160e58ad8d9 100644
--- a/src/main/java/seedu/address/logic/commands/exceptions/CommandException.java
+++ b/src/main/java/seedu/address/logic/commands/exceptions/CommandException.java
@@ -1,5 +1,7 @@
package seedu.address.logic.commands.exceptions;
+import seedu.address.logic.commands.Command;
+
/**
* Represents an error which occurs during execution of a {@link Command}.
*/
@@ -14,4 +16,18 @@ public CommandException(String message) {
public CommandException(String message, Throwable cause) {
super(message, cause);
}
+
+ /**
+ * Represents an error when a duplicate company is added. Duplicate company refers to
+ * companies with the same name field and the same role field.
+ */
+ public static class DuplicateException extends CommandException {
+ /**
+ * Constructs a new {@code DuplicateException} with the specified detail {@code message}.
+ * This is to be used for user interaction for the ADD AND EDIT command.
+ */
+ public DuplicateException(String message) {
+ super(message);
+ }
+ }
}
diff --git a/src/main/java/seedu/address/logic/parser/AddCommandParser.java b/src/main/java/seedu/address/logic/parser/AddCommandParser.java
index 4ff1a97ed77..c3439d09954 100644
--- a/src/main/java/seedu/address/logic/parser/AddCommandParser.java
+++ b/src/main/java/seedu/address/logic/parser/AddCommandParser.java
@@ -1,23 +1,30 @@
package seedu.address.logic.parser;
+import static seedu.address.logic.Messages.MESSAGE_EMPTY_PREFIX;
import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_COMPANY_NAME;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_DEADLINE;
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.logic.parser.CliSyntax.PREFIX_PRIORITY;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_RECRUITER_NAME;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_ROLE;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_STATUS;
-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;
+import seedu.address.model.company.ApplicationStatus;
+import seedu.address.model.company.Company;
+import seedu.address.model.company.Deadline;
+import seedu.address.model.company.Email;
+import seedu.address.model.company.Name;
+import seedu.address.model.company.Phone;
+import seedu.address.model.company.Priority;
+import seedu.address.model.company.RecruiterName;
+import seedu.address.model.company.Remark;
+import seedu.address.model.company.Role;
/**
* Parses input arguments and creates a new AddCommand object
@@ -31,23 +38,36 @@ public class AddCommandParser implements Parser {
*/
public AddCommand parse(String args) throws ParseException {
ArgumentMultimap argMultimap =
- ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, PREFIX_TAG);
+ ArgumentTokenizer.tokenize(args, PREFIX_COMPANY_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ROLE,
+ PREFIX_DEADLINE, PREFIX_STATUS, PREFIX_RECRUITER_NAME, PREFIX_PRIORITY);
- if (!arePrefixesPresent(argMultimap, PREFIX_NAME, PREFIX_ADDRESS, PREFIX_PHONE, PREFIX_EMAIL)
- || !argMultimap.getPreamble().isEmpty()) {
+ // Checks for empty text after add word
+ if (args.isEmpty()) {
+ throw new ParseException(String.format(MESSAGE_EMPTY_PREFIX, AddCommand.MESSAGE_USAGE));
+ }
+
+ // Checks for missing prefixes after add word
+ if (!argMultimap.getPreamble().isEmpty()
+ || !arePrefixesPresent(argMultimap, PREFIX_COMPANY_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ROLE,
+ PREFIX_DEADLINE, PREFIX_STATUS, PREFIX_RECRUITER_NAME)) {
throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE));
}
- argMultimap.verifyNoDuplicatePrefixesFor(PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS);
- Name name = ParserUtil.parseName(argMultimap.getValue(PREFIX_NAME).get());
+ argMultimap.verifyNoDuplicatePrefixesFor(PREFIX_COMPANY_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ROLE,
+ PREFIX_DEADLINE, PREFIX_STATUS, PREFIX_RECRUITER_NAME, PREFIX_PRIORITY);
+ Name name = ParserUtil.parseName(argMultimap.getValue(PREFIX_COMPANY_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));
+ Role role = ParserUtil.parseRole(argMultimap.getValue(PREFIX_ROLE).get());
+ Deadline deadline = ParserUtil.parseDeadline(argMultimap.getValue(PREFIX_DEADLINE).get());
+ ApplicationStatus status = ParserUtil.parseStatus(argMultimap.getValue(PREFIX_STATUS).get());
+ RecruiterName recruiterName = ParserUtil.parseRecruiterName(argMultimap.getValue(PREFIX_RECRUITER_NAME).get());
+ Priority priority = ParserUtil.parsePriority(argMultimap.getValue(PREFIX_PRIORITY).orElse("NONE"));
+ Remark remark = ParserUtil.parseRemark("No remarks");
- Person person = new Person(name, phone, email, address, tagList);
+ Company company = new Company(name, phone, email, role, deadline, status, recruiterName, priority, remark);
- return new AddCommand(person);
+ return new AddCommand(company);
}
/**
diff --git a/src/main/java/seedu/address/logic/parser/AddressBookParser.java b/src/main/java/seedu/address/logic/parser/AddressBookParser.java
index 3149ee07e0b..e50a547c2c2 100644
--- a/src/main/java/seedu/address/logic/parser/AddressBookParser.java
+++ b/src/main/java/seedu/address/logic/parser/AddressBookParser.java
@@ -14,9 +14,13 @@
import seedu.address.logic.commands.DeleteCommand;
import seedu.address.logic.commands.EditCommand;
import seedu.address.logic.commands.ExitCommand;
+import seedu.address.logic.commands.FilterCommand;
import seedu.address.logic.commands.FindCommand;
import seedu.address.logic.commands.HelpCommand;
import seedu.address.logic.commands.ListCommand;
+import seedu.address.logic.commands.RemarkCommand;
+import seedu.address.logic.commands.SortCommand;
+import seedu.address.logic.commands.ViewCommand;
import seedu.address.logic.parser.exceptions.ParseException;
/**
@@ -43,7 +47,7 @@ public Command parseCommand(String userInput) throws ParseException {
throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, HelpCommand.MESSAGE_USAGE));
}
- final String commandWord = matcher.group("commandWord");
+ final String commandWord = matcher.group("commandWord").toLowerCase();
final String arguments = matcher.group("arguments");
// Note to developers: Change the log level in config.json to enable lower level (i.e., FINE, FINER and lower)
@@ -52,7 +56,6 @@ public Command parseCommand(String userInput) throws ParseException {
logger.fine("Command word: " + commandWord + "; Arguments: " + arguments);
switch (commandWord) {
-
case AddCommand.COMMAND_WORD:
return new AddCommandParser().parse(arguments);
@@ -77,6 +80,21 @@ public Command parseCommand(String userInput) throws ParseException {
case HelpCommand.COMMAND_WORD:
return new HelpCommand();
+ case SortCommand.COMMAND_WORD:
+ return new SortCommandParser().parse(arguments);
+
+ case ViewCommand.COMMAND_WORD:
+ return new ViewCommandParser().parse(arguments);
+
+ case RemarkCommand.COMMAND_WORD:
+ return new RemarkCommandParser().parse(arguments);
+
+ case RemarkCommand.REMOVE_COMMAND_WORD:
+ return new UnremarkCommandParser().parse(arguments);
+
+ case FilterCommand.COMMAND_WORD:
+ return new FilterCommandParser().parse(arguments);
+
default:
logger.finer("This user input caused a ParseException: " + userInput);
throw new ParseException(MESSAGE_UNKNOWN_COMMAND);
diff --git a/src/main/java/seedu/address/logic/parser/ArgumentMultimap.java b/src/main/java/seedu/address/logic/parser/ArgumentMultimap.java
index 21e26887a83..c524f6daac8 100644
--- a/src/main/java/seedu/address/logic/parser/ArgumentMultimap.java
+++ b/src/main/java/seedu/address/logic/parser/ArgumentMultimap.java
@@ -18,6 +18,9 @@
* can be inserted multiple times for the same prefix.
*/
public class ArgumentMultimap {
+ public static final String PREAMBLE_VALIDATION_REGEX = "^(\\S*[0-9]+\\S*)$";
+
+ public static final String INVALID_PREFIX_REGEX = "^[\\p{Alnum} ]*\\s+\\p{Alpha}+/[\\p{Alnum} ]*";
/** Prefixes mapped to their respective arguments**/
private final Map> argMultimap = new HashMap<>();
@@ -55,6 +58,18 @@ public List getAllValues(Prefix prefix) {
return new ArrayList<>(argMultimap.get(prefix));
}
+ /**
+ * Returns true if the preamble of argument parsed is valid.
+ *
+ */
+ public Boolean isValidPreamble() {
+ String preamble = getPreamble();
+ if (preamble.isEmpty()) {
+ return true;
+ }
+ return !preamble.matches(INVALID_PREFIX_REGEX) && preamble.matches(PREAMBLE_VALIDATION_REGEX);
+ }
+
/**
* Returns the preamble (text before the first valid prefix). Trims any leading/trailing spaces.
*/
@@ -75,4 +90,15 @@ public void verifyNoDuplicatePrefixesFor(Prefix... prefixes) throws ParseExcepti
throw new ParseException(Messages.getErrorMessageForDuplicatePrefixes(duplicatedPrefixes));
}
}
+
+ /**
+ * Checks if there is any invalid prefixes parsed as the value of the prefixes given in {@code prefixes}.
+ */
+ public boolean verifyNoInvalidPrefixesFor(Prefix... prefixes) {
+ Prefix[] invalidPrefixes = Stream.of(prefixes)
+ .filter(prefix -> this.getValue(prefix).orElse("").matches(INVALID_PREFIX_REGEX))
+ .toArray(Prefix[]::new);
+
+ return invalidPrefixes.length == 0;
+ }
}
diff --git a/src/main/java/seedu/address/logic/parser/ArgumentTokenizer.java b/src/main/java/seedu/address/logic/parser/ArgumentTokenizer.java
index 5c9aebfa488..26cc6b8b851 100644
--- a/src/main/java/seedu/address/logic/parser/ArgumentTokenizer.java
+++ b/src/main/java/seedu/address/logic/parser/ArgumentTokenizer.java
@@ -58,7 +58,7 @@ private static List findPrefixPositions(String argsString, Prefi
}
/**
- * Returns the index of the first occurrence of {@code prefix} in
+ * Returns the index of the first case-insensitive occurrence of {@code prefix} in
* {@code argsString} starting from index {@code fromIndex}. An occurrence
* is valid if there is a whitespace before {@code prefix}. Returns -1 if no
* such occurrence can be found.
@@ -70,7 +70,7 @@ private static List findPrefixPositions(String argsString, Prefi
* {@code fromIndex} = 0, this method returns 5.
*/
private static int findPrefixPosition(String argsString, String prefix, int fromIndex) {
- int prefixIndex = argsString.indexOf(" " + prefix, fromIndex);
+ int prefixIndex = argsString.toLowerCase().indexOf((" " + prefix).toLowerCase(), fromIndex);
return prefixIndex == -1 ? -1
: prefixIndex + 1; // +1 as offset for whitespace
}
diff --git a/src/main/java/seedu/address/logic/parser/CliSyntax.java b/src/main/java/seedu/address/logic/parser/CliSyntax.java
index 75b1a9bf119..c2f29e40643 100644
--- a/src/main/java/seedu/address/logic/parser/CliSyntax.java
+++ b/src/main/java/seedu/address/logic/parser/CliSyntax.java
@@ -6,10 +6,14 @@
public class CliSyntax {
/* Prefix definitions */
- public static final Prefix PREFIX_NAME = new Prefix("n/");
+ public static final Prefix PREFIX_COMPANY_NAME = new Prefix("c/");
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/");
+ public static final Prefix PREFIX_ROLE = new Prefix("r/");
+ public static final Prefix PREFIX_DEADLINE = new Prefix("d/");
+ public static final Prefix PREFIX_STATUS = new Prefix("s/");
+ public static final Prefix PREFIX_PRIORITY = new Prefix("pr/");
+ public static final Prefix PREFIX_RECRUITER_NAME = new Prefix("n/");
+ public static final Prefix PREFIX_REMARK = new Prefix("re/");
}
diff --git a/src/main/java/seedu/address/logic/parser/DeleteCommandParser.java b/src/main/java/seedu/address/logic/parser/DeleteCommandParser.java
index 3527fe76a3e..6103fdfa2c6 100644
--- a/src/main/java/seedu/address/logic/parser/DeleteCommandParser.java
+++ b/src/main/java/seedu/address/logic/parser/DeleteCommandParser.java
@@ -1,7 +1,5 @@
package seedu.address.logic.parser;
-import static seedu.address.logic.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;
@@ -22,7 +20,7 @@ public DeleteCommand parse(String args) throws ParseException {
return new DeleteCommand(index);
} catch (ParseException pe) {
throw new ParseException(
- String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE), pe);
+ String.format(pe.getMessage()), pe);
}
}
diff --git a/src/main/java/seedu/address/logic/parser/EditCommandParser.java b/src/main/java/seedu/address/logic/parser/EditCommandParser.java
index 46b3309a78b..9e2c5ed3fd7 100644
--- a/src/main/java/seedu/address/logic/parser/EditCommandParser.java
+++ b/src/main/java/seedu/address/logic/parser/EditCommandParser.java
@@ -2,84 +2,96 @@
import static java.util.Objects.requireNonNull;
import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_COMPANY_NAME;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_DEADLINE;
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 static seedu.address.logic.parser.CliSyntax.PREFIX_PRIORITY;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_RECRUITER_NAME;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_REMARK;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_ROLE;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_STATUS;
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
+ * 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
+ * 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
+ * @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);
+ ArgumentTokenizer.tokenize(args, PREFIX_COMPANY_NAME, PREFIX_RECRUITER_NAME, PREFIX_ROLE, PREFIX_STATUS,
+ PREFIX_DEADLINE, PREFIX_EMAIL, PREFIX_PHONE, PREFIX_PRIORITY, PREFIX_REMARK);
Index index;
+ // Checks for invalid prefixes parsed as the preamble
+ if (!argMultimap.isValidPreamble()) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditCommand.MESSAGE_USAGE));
+ }
+
+ // Checks for invalid prefixes parsed as fields
+ if (!argMultimap.verifyNoInvalidPrefixesFor(PREFIX_COMPANY_NAME, PREFIX_RECRUITER_NAME, PREFIX_ROLE,
+ PREFIX_STATUS, PREFIX_DEADLINE, PREFIX_EMAIL, PREFIX_PHONE, PREFIX_PRIORITY, PREFIX_REMARK)) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditCommand.MESSAGE_USAGE));
+ }
+
+ //Checks for valid index
try {
index = ParserUtil.parseIndex(argMultimap.getPreamble());
} catch (ParseException pe) {
- throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditCommand.MESSAGE_USAGE), pe);
+ throw new ParseException(pe.getMessage(), pe);
}
- argMultimap.verifyNoDuplicatePrefixesFor(PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS);
+ // Checks for duplicate prefix
+ argMultimap.verifyNoDuplicatePrefixesFor(PREFIX_COMPANY_NAME, PREFIX_RECRUITER_NAME, PREFIX_ROLE, PREFIX_STATUS,
+ PREFIX_DEADLINE, PREFIX_EMAIL, PREFIX_PHONE, PREFIX_PRIORITY, PREFIX_REMARK);
- EditPersonDescriptor editPersonDescriptor = new EditPersonDescriptor();
+ EditCommand.EditCompanyDescriptor editCompanyDescriptor = new EditCommand.EditCompanyDescriptor();
- if (argMultimap.getValue(PREFIX_NAME).isPresent()) {
- editPersonDescriptor.setName(ParserUtil.parseName(argMultimap.getValue(PREFIX_NAME).get()));
+ if (argMultimap.getValue(PREFIX_COMPANY_NAME).isPresent()) {
+ editCompanyDescriptor.setName(ParserUtil.parseName(argMultimap.getValue(PREFIX_COMPANY_NAME).get()));
}
if (argMultimap.getValue(PREFIX_PHONE).isPresent()) {
- editPersonDescriptor.setPhone(ParserUtil.parsePhone(argMultimap.getValue(PREFIX_PHONE).get()));
+ editCompanyDescriptor.setPhone(ParserUtil.parsePhone(argMultimap.getValue(PREFIX_PHONE).get()));
}
if (argMultimap.getValue(PREFIX_EMAIL).isPresent()) {
- editPersonDescriptor.setEmail(ParserUtil.parseEmail(argMultimap.getValue(PREFIX_EMAIL).get()));
+ editCompanyDescriptor.setEmail(ParserUtil.parseEmail(argMultimap.getValue(PREFIX_EMAIL).get()));
}
- if (argMultimap.getValue(PREFIX_ADDRESS).isPresent()) {
- editPersonDescriptor.setAddress(ParserUtil.parseAddress(argMultimap.getValue(PREFIX_ADDRESS).get()));
+ if (argMultimap.getValue(PREFIX_ROLE).isPresent()) {
+ editCompanyDescriptor.setRole(ParserUtil.parseRole(argMultimap.getValue(PREFIX_ROLE).get()));
}
- parseTagsForEdit(argMultimap.getAllValues(PREFIX_TAG)).ifPresent(editPersonDescriptor::setTags);
-
- if (!editPersonDescriptor.isAnyFieldEdited()) {
- throw new ParseException(EditCommand.MESSAGE_NOT_EDITED);
+ if (argMultimap.getValue(PREFIX_DEADLINE).isPresent()) {
+ editCompanyDescriptor.setDeadline(ParserUtil.parseDeadline(argMultimap.getValue(PREFIX_DEADLINE).get()));
+ }
+ if (argMultimap.getValue(PREFIX_STATUS).isPresent()) {
+ editCompanyDescriptor.setStatus(ParserUtil.parseStatus(argMultimap.getValue(PREFIX_STATUS).get()));
+ }
+ if (argMultimap.getValue(PREFIX_RECRUITER_NAME).isPresent()) {
+ editCompanyDescriptor.setRecruiterName(
+ ParserUtil.parseRecruiterName(argMultimap.getValue(PREFIX_RECRUITER_NAME).get()));
+ }
+ if (argMultimap.getValue(PREFIX_PRIORITY).isPresent()) {
+ editCompanyDescriptor.setPriority(ParserUtil.parsePriority(argMultimap.getValue(PREFIX_PRIORITY).get()));
}
- 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 (argMultimap.getValue(PREFIX_REMARK).isPresent()) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditCommand.MESSAGE_USAGE));
+ }
- if (tags.isEmpty()) {
- return Optional.empty();
+ if (!editCompanyDescriptor.isAnyFieldEdited()) {
+ throw new ParseException(EditCommand.MESSAGE_NOT_EDITED);
}
- Collection tagSet = tags.size() == 1 && tags.contains("") ? Collections.emptySet() : tags;
- return Optional.of(ParserUtil.parseTags(tagSet));
- }
+ return new EditCommand(index, editCompanyDescriptor);
+ }
}
diff --git a/src/main/java/seedu/address/logic/parser/FilterCommandParser.java b/src/main/java/seedu/address/logic/parser/FilterCommandParser.java
new file mode 100644
index 00000000000..b4215724f0d
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/FilterCommandParser.java
@@ -0,0 +1,55 @@
+package seedu.address.logic.parser;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.logic.Messages.MESSAGE_EMPTY_PREFIX;
+import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_STATUS;
+
+import java.util.stream.Stream;
+
+import seedu.address.logic.commands.FilterCommand;
+import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.address.model.company.ApplicationStatus;
+import seedu.address.model.company.predicates.ApplicationStatusPredicate;
+
+/**
+ * Parses input arguments and creates a new FilterCommand object.
+ */
+public class FilterCommandParser implements Parser {
+ /**
+ * Parses the given {@code String} of arguments in the context of the FilterCommand
+ * and returns a FilterCommand object for execution.
+ */
+ public FilterCommand parse(String args) throws ParseException {
+ requireNonNull(args);
+ ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, PREFIX_STATUS);
+
+ // Checks for empty text after filter word
+ if (args.isEmpty()) {
+ throw new ParseException(String.format(MESSAGE_EMPTY_PREFIX, FilterCommand.MESSAGE_USAGE));
+ }
+
+ // Checks for missing prefixes after filter word
+ if (!arePrefixesPresent(argMultimap, PREFIX_STATUS) || !argMultimap.getPreamble().isEmpty()) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, FilterCommand.MESSAGE_USAGE));
+ }
+
+ // Checks for duplicate status prefixes
+ argMultimap.verifyNoDuplicatePrefixesFor(PREFIX_STATUS);
+
+ ApplicationStatus applicationStatus;
+ ApplicationStatusPredicate predicate;
+
+ applicationStatus = ParserUtil.parseStatus(argMultimap.getValue(PREFIX_STATUS).get());
+ predicate = new ApplicationStatusPredicate(applicationStatus);
+ return new FilterCommand(applicationStatus, predicate);
+ }
+
+ /**
+ * 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/FindCommandParser.java b/src/main/java/seedu/address/logic/parser/FindCommandParser.java
index 2867bde857b..8c04582d25d 100644
--- a/src/main/java/seedu/address/logic/parser/FindCommandParser.java
+++ b/src/main/java/seedu/address/logic/parser/FindCommandParser.java
@@ -1,24 +1,29 @@
package seedu.address.logic.parser;
+import static java.util.Objects.requireNonNull;
import static seedu.address.logic.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;
+import seedu.address.model.company.predicates.NameContainsKeywordsPredicate;
/**
- * Parses input arguments and creates a new FindCommand object
+ * 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
+ * Parses the given {@code String} of arguments to produce a FindCommand for execution.
+ * Each whitespace-separated part of the input is treated as an individual keyword.
+ *
+ * @param args The raw input from the user.
+ * @return A FindCommand object tailored to the user's input keywords.
+ * @throws ParseException if the user input does not conform to the expected format.
*/
public FindCommand parse(String args) throws ParseException {
+ requireNonNull(args);
String trimmedArgs = args.trim();
if (trimmedArgs.isEmpty()) {
throw new ParseException(
diff --git a/src/main/java/seedu/address/logic/parser/ParserUtil.java b/src/main/java/seedu/address/logic/parser/ParserUtil.java
index b117acb9c55..6c27db91ad6 100644
--- a/src/main/java/seedu/address/logic/parser/ParserUtil.java
+++ b/src/main/java/seedu/address/logic/parser/ParserUtil.java
@@ -1,19 +1,24 @@
package seedu.address.logic.parser;
import static java.util.Objects.requireNonNull;
+import static seedu.address.logic.Messages.MESSAGE_EMPTY_INDEX;
+import static seedu.address.logic.Messages.MESSAGE_NON_INTEGER_INDEX;
+import static seedu.address.logic.Messages.MESSAGE_NON_POSITIVE_INTEGER_INDEX;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Set;
+import java.util.logging.Logger;
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;
+import seedu.address.model.company.ApplicationStatus;
+import seedu.address.model.company.Deadline;
+import seedu.address.model.company.Email;
+import seedu.address.model.company.Name;
+import seedu.address.model.company.Phone;
+import seedu.address.model.company.Priority;
+import seedu.address.model.company.RecruiterName;
+import seedu.address.model.company.Remark;
+import seedu.address.model.company.Role;
/**
* Contains utility methods used for parsing strings in the various *Parser classes.
@@ -29,8 +34,14 @@ public class ParserUtil {
*/
public static Index parseIndex(String oneBasedIndex) throws ParseException {
String trimmedIndex = oneBasedIndex.trim();
+ if (trimmedIndex.isEmpty()) {
+ throw new ParseException(MESSAGE_EMPTY_INDEX);
+ }
+ if (!StringUtil.isInteger(trimmedIndex)) {
+ throw new ParseException(MESSAGE_NON_INTEGER_INDEX);
+ }
if (!StringUtil.isNonZeroUnsignedInteger(trimmedIndex)) {
- throw new ParseException(MESSAGE_INVALID_INDEX);
+ throw new ParseException(MESSAGE_NON_POSITIVE_INTEGER_INDEX);
}
return Index.fromOneBased(Integer.parseInt(trimmedIndex));
}
@@ -43,43 +54,37 @@ public static Index parseIndex(String oneBasedIndex) throws ParseException {
*/
public static Name parseName(String name) throws ParseException {
requireNonNull(name);
- String trimmedName = name.trim();
+ String trimmedName = name.trim().replaceAll("\\s+", " ");
+ if (trimmedName.isEmpty()) {
+ throw new ParseException(Name.MESSAGE_CONSTRAINTS_NON_EMPTY);
+ }
if (!Name.isValidName(trimmedName)) {
- throw new ParseException(Name.MESSAGE_CONSTRAINTS);
+ throw new ParseException(Name.MESSAGE_CONSTRAINTS_INVALID_REGEX);
+ }
+ if (!Name.isValidNameLength(trimmedName)) {
+ throw new ParseException(Name.MESSAGE_CONSTRAINTS_INVALID_LENGTH);
}
return new Name(trimmedName);
}
/**
* Parses a {@code String phone} into a {@code Phone}.
- * Leading and trailing whitespaces will be trimmed.
+ * Leading, trailing and in-between 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();
+ String trimmedPhone = phone.trim().replaceAll("\\s+", "");
+ if (trimmedPhone.isEmpty()) {
+ throw new ParseException(Phone.MESSAGE_CONSTRAINTS_NON_EMPTY);
+ }
if (!Phone.isValidPhone(trimmedPhone)) {
- throw new ParseException(Phone.MESSAGE_CONSTRAINTS);
+ throw new ParseException(Phone.MESSAGE_CONSTRAINTS_VALID_REGEX);
}
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.
@@ -89,36 +94,127 @@ public static Address parseAddress(String address) throws ParseException {
public static Email parseEmail(String email) throws ParseException {
requireNonNull(email);
String trimmedEmail = email.trim();
+ if (trimmedEmail.isEmpty()) {
+ throw new ParseException(Email.MESSAGE_CONSTRAINTS_NON_EMPTY);
+ }
if (!Email.isValidEmail(trimmedEmail)) {
- throw new ParseException(Email.MESSAGE_CONSTRAINTS);
+ throw new ParseException(Email.MESSAGE_CONSTRAINTS_VALID_REGEX);
}
return new Email(trimmedEmail);
}
/**
- * Parses a {@code String tag} into a {@code Tag}.
+ * Parses a {@code String role} into an {@code Role}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given {@code role} is invalid.
+ */
+ public static Role parseRole(String role) throws ParseException {
+ requireNonNull(role);
+ String trimmedRole = role.trim().replaceAll("\\s+", " ");
+ if (trimmedRole.isEmpty()) {
+ throw new ParseException(Role.MESSAGE_CONSTRAINTS_NON_EMPTY);
+ }
+ if (!Role.isValidRole(trimmedRole)) {
+ throw new ParseException(Role.MESSAGE_CONSTRAINTS_INVALID_REGEX);
+ }
+ if (!Role.isValidRoleLength(trimmedRole)) {
+ throw new ParseException(Role.MESSAGE_CONSTRAINTS_INVALID_LENGTH);
+ }
+ return new Role(trimmedRole);
+ }
+
+ /**
+ * Parses a {@code String deadline} into an {@code Deadline}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given {@code deadline} is invalid.
+ */
+ public static Deadline parseDeadline(String deadline) throws ParseException {
+ requireNonNull(deadline);
+ String trimmedDeadline = deadline.trim();
+ if (trimmedDeadline.isEmpty()) {
+ throw new ParseException(Deadline.MESSAGE_CONSTRAINTS_NON_EMPTY);
+ }
+ if (!Deadline.isValidFormat(trimmedDeadline)) {
+ throw new ParseException(Deadline.MESSAGE_CONSTRAINTS_WRONG_FORMAT);
+ }
+ if (!Deadline.isValidDeadline(trimmedDeadline)) {
+ throw new ParseException(Deadline.MESSAGE_CONSTRAINTS_INVALID_DEADLINE);
+ }
+ return new Deadline(trimmedDeadline);
+ }
+
+ /**
+ * Parses a {@code String status} into an {@code ApplicationStatus}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given {@code status} is invalid.
+ */
+ public static ApplicationStatus parseStatus(String status) throws ParseException {
+ requireNonNull(status);
+ String trimmedStatus = status.trim();
+ if (trimmedStatus.isEmpty()) {
+ throw new ParseException(ApplicationStatus.MESSAGE_CONSTRAINTS_NON_EMPTY);
+ }
+ if (!ApplicationStatus.isValidApplicationStatus(trimmedStatus)) {
+ Logger.getGlobal().warning("CAUGHT HERE");
+ throw new ParseException(ApplicationStatus.MESSAGE_CONSTRAINTS_VALID_STATUS);
+ }
+ return new ApplicationStatus(trimmedStatus);
+ }
+
+ /**
+ * Parses a {@code String recruiterName} into an {@code RecruiterName}.
* Leading and trailing whitespaces will be trimmed.
*
- * @throws ParseException if the given {@code tag} is invalid.
+ * @throws ParseException if the given {@code recruiterName} 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);
+ public static RecruiterName parseRecruiterName(String recruiterName) throws ParseException {
+ requireNonNull(recruiterName);
+ String trimmedRecruiterName = recruiterName.trim().replaceAll("\\s+", " ");;
+ if (trimmedRecruiterName.isEmpty()) {
+ throw new ParseException(RecruiterName.MESSAGE_CONSTRAINTS_NON_EMPTY);
+ }
+ if (!RecruiterName.isValidName(trimmedRecruiterName)) {
+ throw new ParseException(RecruiterName.MESSAGE_CONSTRAINTS_INVALID_REGEX);
}
- return new Tag(trimmedTag);
+ if (!RecruiterName.isValidNameLength(trimmedRecruiterName)) {
+ throw new ParseException(RecruiterName.MESSAGE_CONSTRAINTS_INVALID_LENGTH);
+ }
+ return new RecruiterName(trimmedRecruiterName);
}
/**
- * Parses {@code Collection tags} into a {@code Set}.
+ * Parses a {@code String priority} into an {@code Priority}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given {@code priority} is invalid.
+ */
+ public static Priority parsePriority(String priority) throws ParseException {
+ requireNonNull(priority);
+ String trimmedPriority = priority.trim().toUpperCase();
+ if (trimmedPriority.isEmpty()) {
+ throw new ParseException(Priority.MESSAGE_CONSTRAINTS_NON_EMPTY);
+ }
+ if (!Priority.isValidPriority(trimmedPriority)) {
+ throw new ParseException(Priority.MESSAGE_CONSTRAINTS_VALID_REGEX);
+ }
+ return new Priority(trimmedPriority);
+ }
+
+ /**
+ * Parses a {@code String remark} into a {@code Remark}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given {@code remark} is invalid.
*/
- public static Set parseTags(Collection tags) throws ParseException {
- requireNonNull(tags);
- final Set tagSet = new HashSet<>();
- for (String tagName : tags) {
- tagSet.add(parseTag(tagName));
+ public static Remark parseRemark(String remark) throws ParseException {
+ requireNonNull(remark);
+ String trimmedRemark = remark.trim();
+ if (!Remark.isValidRemark(trimmedRemark)) {
+ throw new ParseException(Remark.MESSAGE_CONSTRAINTS);
}
- return tagSet;
+ return new Remark(trimmedRemark);
}
}
diff --git a/src/main/java/seedu/address/logic/parser/RemarkCommandParser.java b/src/main/java/seedu/address/logic/parser/RemarkCommandParser.java
new file mode 100644
index 00000000000..beb4c0ae289
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/RemarkCommandParser.java
@@ -0,0 +1,49 @@
+package seedu.address.logic.parser;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_REMARK;
+
+import seedu.address.commons.core.index.Index;
+import seedu.address.logic.commands.RemarkCommand;
+import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.address.model.company.Remark;
+
+/**
+ * Parses input arguments and creates a new RemarkCommand object.
+ */
+public class RemarkCommandParser implements Parser {
+ /**
+ * Parses the given {@code String} of arguments in the context of the RemarkCommand
+ * and returns a RemarkCommand object for execution.
+ * @throws ParseException if the user input does not conform the expected format.
+ */
+ public RemarkCommand parse(String args) throws ParseException {
+ requireNonNull(args);
+ ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, PREFIX_REMARK);
+
+ Index index;
+
+ // Checks for invalid prefixes parsed as the preamble
+ if (!argMultimap.isValidPreamble()) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, RemarkCommand.MESSAGE_USAGE));
+ }
+
+ try {
+ index = ParserUtil.parseIndex(argMultimap.getPreamble());
+ } catch (ParseException pe) {
+ throw new ParseException(String.format(pe.getMessage(), pe));
+ }
+
+ // Checks for duplicate prefix
+ argMultimap.verifyNoDuplicatePrefixesFor(PREFIX_REMARK);
+
+ if (argMultimap.getValue(PREFIX_REMARK).isEmpty()) {
+ throw new ParseException(RemarkCommand.MESSAGE_NO_REMARK);
+ }
+
+ Remark remark = ParserUtil.parseRemark(argMultimap.getValue(PREFIX_REMARK).get());
+
+ return new RemarkCommand(index, remark);
+ }
+}
diff --git a/src/main/java/seedu/address/logic/parser/SortCommandParser.java b/src/main/java/seedu/address/logic/parser/SortCommandParser.java
new file mode 100644
index 00000000000..fc87aec26b8
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/SortCommandParser.java
@@ -0,0 +1,35 @@
+package seedu.address.logic.parser;
+
+import static java.util.Objects.requireNonNull;
+
+import seedu.address.logic.SortOrder;
+import seedu.address.logic.commands.SortCommand;
+import seedu.address.logic.parser.exceptions.ParseException;
+
+/**
+ * Parses input arguments and creates a new SortCommand object.
+ */
+public class SortCommandParser implements Parser {
+
+ @Override
+ public SortCommand parse(String args) throws ParseException {
+ requireNonNull(args);
+ String trimmedArgs = args.trim().toLowerCase();
+
+ switch (trimmedArgs) {
+ case "d":
+ case "desc":
+ case "descending":
+ return new SortCommand(SortOrder.DESCENDING);
+
+ case "": // if user does not specify order, default to ascending
+ case "a":
+ case "asc":
+ case "ascending":
+ return new SortCommand(SortOrder.ASCENDING);
+
+ default:
+ throw new ParseException(String.format(SortCommand.MESSAGE_INVALID_SORT_ORDER, SortCommand.MESSAGE_USAGE));
+ }
+ }
+}
diff --git a/src/main/java/seedu/address/logic/parser/UnremarkCommandParser.java b/src/main/java/seedu/address/logic/parser/UnremarkCommandParser.java
new file mode 100644
index 00000000000..85be8624933
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/UnremarkCommandParser.java
@@ -0,0 +1,32 @@
+package seedu.address.logic.parser;
+
+import static java.util.Objects.requireNonNull;
+
+import seedu.address.commons.core.index.Index;
+import seedu.address.logic.commands.RemarkCommand;
+import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.address.model.company.Remark;
+
+
+/**
+ * Parses input arguments and creates a new RemarkCommand object.
+ */
+public class UnremarkCommandParser implements Parser {
+ /**
+ * Parses the given {@code String} of arguments in the context of the RemarkCommand
+ * and returns a RemarkCommand object for execution.
+ * @throws ParseException if the user input does not conform the expected format.
+ */
+ public RemarkCommand parse(String args) throws ParseException {
+ requireNonNull(args);
+ try {
+ Index index = ParserUtil.parseIndex(args);
+ Remark remark = new Remark("No remarks");
+ remark.deleteRemark();
+ return new RemarkCommand(index, remark);
+
+ } catch (ParseException pe) {
+ throw new ParseException(String.format(pe.getMessage()), pe);
+ }
+ }
+}
diff --git a/src/main/java/seedu/address/logic/parser/ViewCommandParser.java b/src/main/java/seedu/address/logic/parser/ViewCommandParser.java
new file mode 100644
index 00000000000..cbc8283cd92
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/ViewCommandParser.java
@@ -0,0 +1,30 @@
+package seedu.address.logic.parser;
+
+import seedu.address.commons.core.index.Index;
+import seedu.address.logic.commands.ViewCommand;
+import seedu.address.logic.parser.exceptions.ParseException;
+
+/**
+ * Parses input arguments and creates a new ViewCommand object.
+ */
+public class ViewCommandParser implements Parser {
+
+ /**
+ * Parses the given {@code String} of arguments in the context of the ViewCommand
+ * and returns a ViewCommand object for execution.
+ *
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public ViewCommand parse(String args) throws ParseException {
+ assert args != null;
+
+ try {
+ Index index = ParserUtil.parseIndex(args);
+ return new ViewCommand(index);
+ } catch (ParseException pe) {
+ throw new ParseException(
+ String.format(pe.getMessage()), pe);
+ }
+ }
+
+}
diff --git a/src/main/java/seedu/address/model/AddressBook.java b/src/main/java/seedu/address/model/AddressBook.java
index 73397161e84..2f5750846ad 100644
--- a/src/main/java/seedu/address/model/AddressBook.java
+++ b/src/main/java/seedu/address/model/AddressBook.java
@@ -6,16 +6,18 @@
import javafx.collections.ObservableList;
import seedu.address.commons.util.ToStringBuilder;
-import seedu.address.model.person.Person;
-import seedu.address.model.person.UniquePersonList;
+import seedu.address.model.company.Company;
+import seedu.address.model.company.UniqueCompanyList;
/**
* Wraps all data at the address-book level
- * Duplicates are not allowed (by .isSamePerson comparison)
+ * Duplicates are not allowed (by .isSameCompany comparison)
*/
public class AddressBook implements ReadOnlyAddressBook {
- private final UniquePersonList persons;
+ private final UniqueCompanyList companies;
+
+ private final UniqueCompanyList currentViewedCompany;
/*
* The 'unusual' code block below is a non-static initialization block, sometimes used to avoid duplication
@@ -25,13 +27,14 @@ public class AddressBook implements ReadOnlyAddressBook {
* among constructors.
*/
{
- persons = new UniquePersonList();
+ companies = new UniqueCompanyList();
+ currentViewedCompany = new UniqueCompanyList();
}
public AddressBook() {}
/**
- * Creates an AddressBook using the Persons in the {@code toBeCopied}
+ * Creates an AddressBook using the Companies in the {@code toBeCopied}
*/
public AddressBook(ReadOnlyAddressBook toBeCopied) {
this();
@@ -41,11 +44,19 @@ public AddressBook(ReadOnlyAddressBook toBeCopied) {
//// list overwrite operations
/**
- * Replaces the contents of the person list with {@code persons}.
- * {@code persons} must not contain duplicate persons.
+ * Sets the current viewed company to the company {@code company}.
+ */
+ public void setCurrentViewedCompany(Company company) {
+ currentViewedCompany.clear();
+ currentViewedCompany.add(company);
+ }
+
+ /**
+ * Replaces the contents of the company list with {@code companies}.
+ * {@code companies} must not contain duplicate companies.
*/
- public void setPersons(List persons) {
- this.persons.setPersons(persons);
+ public void setCompanies(List companies) {
+ this.companies.setCompanies(companies);
}
/**
@@ -54,44 +65,64 @@ public void setPersons(List persons) {
public void resetData(ReadOnlyAddressBook newData) {
requireNonNull(newData);
- setPersons(newData.getPersonList());
+ setCompanies(newData.getCompanyList());
}
- //// person-level operations
+ //// company-level operations
+
+ /**
+ * Returns true if a company with the same identity as {@code company} exists in the address book.
+ */
+ public boolean hasCompany(Company company) {
+ requireNonNull(company);
+ return companies.contains(company);
+ }
/**
- * Returns true if a person with the same identity as {@code person} exists in the address book.
+ * Returns Company that is duplicated with the same identity as {@code company}.
+ * Only executed if {@code hasCompany} returns true.
*/
- public boolean hasPerson(Person person) {
- requireNonNull(person);
- return persons.contains(person);
+ public Company getDuplicateCompany(Company company) {
+ requireNonNull(company);
+ return companies.getDuplicateCompany(company);
}
/**
- * Adds a person to the address book.
- * The person must not already exist in the address book.
+ * Adds a company to the address book.
+ * The company must not already exist in the address book.
*/
- public void addPerson(Person p) {
- persons.add(p);
+ public void addCompany(Company p) {
+ companies.add(p);
}
/**
- * Replaces the given person {@code target} in the list with {@code editedPerson}.
+ * Replaces the given company {@code target} in the list with {@code editedCompany}.
* {@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.
+ * The company identity of {@code editedCompany} must not be the same as another existing company in the address
+ * book.
*/
- public void setPerson(Person target, Person editedPerson) {
- requireNonNull(editedPerson);
+ public void setCompany(Company target, Company editedCompany) {
+ requireNonNull(editedCompany);
+ companies.setCompany(target, editedCompany);
+ }
- persons.setPerson(target, editedPerson);
+ public int getDuplicateIndex(Company company) {
+ return companies.getDuplicateIndex(company);
}
/**
* Removes {@code key} from this {@code AddressBook}.
* {@code key} must exist in the address book.
*/
- public void removePerson(Person key) {
- persons.remove(key);
+ public void removeCompany(Company key) {
+ companies.remove(key);
+ }
+
+ /**
+ * Clears currentViewedCompany.
+ */
+ public void clearDetailPanel() {
+ currentViewedCompany.clear();
}
//// util methods
@@ -99,13 +130,18 @@ public void removePerson(Person key) {
@Override
public String toString() {
return new ToStringBuilder(this)
- .add("persons", persons)
+ .add("companies", companies)
.toString();
}
@Override
- public ObservableList getPersonList() {
- return persons.asUnmodifiableObservableList();
+ public ObservableList getCompanyList() {
+ return companies.asUnmodifiableObservableList();
+ }
+
+ @Override
+ public ObservableList getCurrentViewedCompany() {
+ return currentViewedCompany.asUnmodifiableObservableList();
}
@Override
@@ -120,11 +156,11 @@ public boolean equals(Object other) {
}
AddressBook otherAddressBook = (AddressBook) other;
- return persons.equals(otherAddressBook.persons);
+ return companies.equals(otherAddressBook.companies);
}
@Override
public int hashCode() {
- return persons.hashCode();
+ return companies.hashCode();
}
}
diff --git a/src/main/java/seedu/address/model/Model.java b/src/main/java/seedu/address/model/Model.java
index d54df471c1f..9ed9e610f86 100644
--- a/src/main/java/seedu/address/model/Model.java
+++ b/src/main/java/seedu/address/model/Model.java
@@ -1,18 +1,19 @@
package seedu.address.model;
import java.nio.file.Path;
+import java.util.List;
import java.util.function.Predicate;
import javafx.collections.ObservableList;
import seedu.address.commons.core.GuiSettings;
-import seedu.address.model.person.Person;
+import seedu.address.model.company.Company;
/**
* The API of the Model component.
*/
public interface Model {
/** {@code Predicate} that always evaluate to true */
- Predicate PREDICATE_SHOW_ALL_PERSONS = unused -> true;
+ Predicate PREDICATE_SHOW_ALL_COMPANIES = unused -> true;
/**
* Replaces user prefs data with the data in {@code userPrefs}.
@@ -53,35 +54,115 @@ public interface Model {
ReadOnlyAddressBook getAddressBook();
/**
- * Returns true if a person with the same identity as {@code person} exists in the address book.
+ * Returns true if a company with the same identity as {@code company} exists in the address book.
*/
- boolean hasPerson(Person person);
+ boolean hasCompany(Company company);
+
+ Company getDuplicateCompany(Company company);
/**
- * Deletes the given person.
- * The person must exist in the address book.
+ * Deletes the given company.
+ * The company must exist in the address book.
*/
- void deletePerson(Person target);
+ void deleteCompany(Company target);
/**
- * Adds the given person.
- * {@code person} must not already exist in the address book.
+ * Adds the given company.
+ * {@code company} must not already exist in the address book.
*/
- void addPerson(Person person);
+ void addCompany(Company company);
/**
- * Replaces the given person {@code target} with {@code editedPerson}.
+ * Replaces the given company {@code target} with {@code editedCompany}.
* {@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.
+ * The company identity of {@code editedCompany} must not be the same as another existing company in the address
+ * book.
*/
- void setPerson(Person target, Person editedPerson);
+ void setCompany(Company target, Company editedCompany);
- /** Returns an unmodifiable view of the filtered person list */
- ObservableList getFilteredPersonList();
+ /**
+ * Sets all the companies in the address book.
+ *
+ * @param companies the list of companies to be set.
+ */
+ void setAllCompanies(List companies);
/**
- * Updates the filter of the filtered person list to filter by the given {@code predicate}.
+ * Returns an unmodifiable view of the filtered company list.
+ *
+ * @return the filtered company list.
+ */
+ ObservableList getFilteredCompanyList();
+
+ /**
+ * Updates the filter of the filtered company list to filter by the given {@code predicate}.
+ *
* @throws NullPointerException if {@code predicate} is null.
*/
- void updateFilteredPersonList(Predicate predicate);
+ void updateFilteredCompanyList(Predicate predicate);
+
+ /**
+ * Sets the current viewed company to the company {@code company}.
+ *
+ * @param company the company to be set as the current viewed company.
+ */
+ void setCurrentViewedCompany(Company company);
+
+ /**
+ * Returns the current viewed company.
+ *
+ * @return the current viewed company.
+ */
+ public ObservableList getCurrentViewedCompany();
+
+ /**
+ * Updates the current viewed company to the company {@code company}.
+ *
+ * @param predicate the predicate to be used to update the current viewed company.
+ */
+ public void updateCurrentViewedCompany(Predicate predicate);
+
+ /**
+ * Checks if the company to be deleted is the current viewed company.
+ * If it is, the detail panel will be cleared.
+ *
+ * @param company the company to be deleted.
+ */
+ public void checkDelete(Company company);
+
+
+ /**
+ * Clears the company detail panel.
+ */
+ public void clearCompanyDetailPanel();
+
+ /**
+ * Filters the companies in the address book by their application status.
+ *
+ * @param predicate the predicate to be used to filter the companies.
+ */
+ void filterCompaniesByStatus(Predicate predicate);
+
+ /**
+ * Returns the index of the duplicate company in the original address book.
+ *
+ * @param company the company to be checked.
+ * @return the index of the duplicate company in the original address book.
+ */
+ int getDuplicateIndexFromOriginalAddressbook(Company company);
+
+ /**
+ * Returns the index of the duplicate company in the filtered address book.
+ *
+ * @param company the company to be checked.
+ * @return the index of the duplicate company in the filtered address book.
+ */
+ int getDuplicateIndexFromFilteredAddressbook(Company company);
+
+ /**
+ * Finds the companies in the address book by their application status.
+ *
+ * @param predicate the predicate to be used to find the companies.
+ */
+ void findCompanies(Predicate predicate);
}
diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java
index 57bc563fde6..e0421159e5f 100644
--- a/src/main/java/seedu/address/model/ModelManager.java
+++ b/src/main/java/seedu/address/model/ModelManager.java
@@ -4,6 +4,7 @@
import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
import java.nio.file.Path;
+import java.util.List;
import java.util.function.Predicate;
import java.util.logging.Logger;
@@ -11,7 +12,7 @@
import javafx.collections.transformation.FilteredList;
import seedu.address.commons.core.GuiSettings;
import seedu.address.commons.core.LogsCenter;
-import seedu.address.model.person.Person;
+import seedu.address.model.company.Company;
/**
* Represents the in-memory model of the address book data.
@@ -21,7 +22,8 @@ public class ModelManager implements Model {
private final AddressBook addressBook;
private final UserPrefs userPrefs;
- private final FilteredList filteredPersons;
+ private final FilteredList filteredCompanies;
+ private final FilteredList currentViewedCompany;
/**
* Initializes a ModelManager with the given addressBook and userPrefs.
@@ -33,7 +35,8 @@ public ModelManager(ReadOnlyAddressBook addressBook, ReadOnlyUserPrefs userPrefs
this.addressBook = new AddressBook(addressBook);
this.userPrefs = new UserPrefs(userPrefs);
- filteredPersons = new FilteredList<>(this.addressBook.getPersonList());
+ filteredCompanies = new FilteredList<>(this.addressBook.getCompanyList());
+ currentViewedCompany = new FilteredList<>(this.addressBook.getCurrentViewedCompany());
}
public ModelManager() {
@@ -88,46 +91,97 @@ public ReadOnlyAddressBook getAddressBook() {
}
@Override
- public boolean hasPerson(Person person) {
- requireNonNull(person);
- return addressBook.hasPerson(person);
+ public boolean hasCompany(Company company) {
+ requireNonNull(company);
+ return addressBook.hasCompany(company);
}
@Override
- public void deletePerson(Person target) {
- addressBook.removePerson(target);
+ public Company getDuplicateCompany(Company company) {
+ requireNonNull(company);
+ return addressBook.getDuplicateCompany(company);
}
@Override
- public void addPerson(Person person) {
- addressBook.addPerson(person);
- updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
+ public void deleteCompany(Company target) {
+ addressBook.removeCompany(target);
}
@Override
- public void setPerson(Person target, Person editedPerson) {
- requireAllNonNull(target, editedPerson);
+ public void addCompany(Company company) {
+ addressBook.addCompany(company);
+ updateFilteredCompanyList(PREDICATE_SHOW_ALL_COMPANIES);
+ }
+
+ @Override
+ public void setCompany(Company target, Company editedCompany) {
+ requireAllNonNull(target, editedCompany);
- addressBook.setPerson(target, editedPerson);
+ addressBook.setCompany(target, editedCompany);
}
- //=========== Filtered Person List Accessors =============================================================
+ @Override
+ public void setCurrentViewedCompany(Company company) {
+ requireNonNull(company);
+ addressBook.setCurrentViewedCompany(company);
+ }
+
+ @Override
+ public void checkDelete(Company company) {
+ if (currentViewedCompany != null && currentViewedCompany.contains(company)) {
+ addressBook.clearDetailPanel();
+ }
+ }
+
+ @Override
+ public void clearCompanyDetailPanel() {
+ addressBook.clearDetailPanel();
+ }
+
+ @Override
+ public void filterCompaniesByStatus(Predicate predicate) {
+ addressBook.clearDetailPanel();
+ updateFilteredCompanyList(predicate);
+ }
+
+ @Override
+ public void findCompanies(Predicate predicate) {
+ addressBook.clearDetailPanel();
+ updateFilteredCompanyList(predicate);
+ }
+
+ @Override
+ public void setAllCompanies(List companies) {
+ addressBook.setCompanies(companies);
+ }
+
+ //=========== Filtered Company List Accessors =============================================================
/**
- * Returns an unmodifiable view of the list of {@code Person} backed by the internal list of
+ * Returns an unmodifiable view of the list of {@code Company} backed by the internal list of
* {@code versionedAddressBook}
*/
@Override
- public ObservableList getFilteredPersonList() {
- return filteredPersons;
+ public ObservableList getFilteredCompanyList() {
+ return filteredCompanies;
+ }
+
+ @Override
+ public void updateFilteredCompanyList(Predicate predicate) {
+ requireNonNull(predicate);
+ filteredCompanies.setPredicate(predicate);
}
@Override
- public void updateFilteredPersonList(Predicate predicate) {
+ public void updateCurrentViewedCompany(Predicate predicate) {
requireNonNull(predicate);
- filteredPersons.setPredicate(predicate);
+ currentViewedCompany.setPredicate(predicate);
}
+ @Override
+ public ObservableList getCurrentViewedCompany() {
+ return currentViewedCompany;
+ }
@Override
public boolean equals(Object other) {
if (other == this) {
@@ -142,7 +196,16 @@ public boolean equals(Object other) {
ModelManager otherModelManager = (ModelManager) other;
return addressBook.equals(otherModelManager.addressBook)
&& userPrefs.equals(otherModelManager.userPrefs)
- && filteredPersons.equals(otherModelManager.filteredPersons);
+ && filteredCompanies.equals(otherModelManager.filteredCompanies);
+ }
+
+ @Override
+ public int getDuplicateIndexFromOriginalAddressbook(Company company) {
+ return addressBook.getDuplicateIndex(company);
}
+ @Override
+ public int getDuplicateIndexFromFilteredAddressbook(Company company) {
+ return filteredCompanies.indexOf(company);
+ }
}
diff --git a/src/main/java/seedu/address/model/ReadOnlyAddressBook.java b/src/main/java/seedu/address/model/ReadOnlyAddressBook.java
index 6ddc2cd9a29..1a9177f0450 100644
--- a/src/main/java/seedu/address/model/ReadOnlyAddressBook.java
+++ b/src/main/java/seedu/address/model/ReadOnlyAddressBook.java
@@ -1,7 +1,7 @@
package seedu.address.model;
import javafx.collections.ObservableList;
-import seedu.address.model.person.Person;
+import seedu.address.model.company.Company;
/**
* Unmodifiable view of an address book
@@ -9,9 +9,14 @@
public interface ReadOnlyAddressBook {
/**
- * Returns an unmodifiable view of the persons list.
- * This list will not contain any duplicate persons.
+ * Returns an unmodifiable view of the companies list.
+ * This list will not contain any duplicate companies.
*/
- ObservableList getPersonList();
+ ObservableList getCompanyList();
+
+ /**
+ * Returns an unmodifiable view of the current viewed company.
+ */
+ ObservableList getCurrentViewedCompany();
}
diff --git a/src/main/java/seedu/address/model/UserPrefs.java b/src/main/java/seedu/address/model/UserPrefs.java
index 6be655fb4c7..1748a41eb5a 100644
--- a/src/main/java/seedu/address/model/UserPrefs.java
+++ b/src/main/java/seedu/address/model/UserPrefs.java
@@ -14,7 +14,7 @@
public class UserPrefs implements ReadOnlyUserPrefs {
private GuiSettings guiSettings = new GuiSettings();
- private Path addressBookFilePath = Paths.get("data" , "addressbook.json");
+ private Path addressBookFilePath = Paths.get("data" , "companydata.json");
/**
* Creates a {@code UserPrefs} with default values.
diff --git a/src/main/java/seedu/address/model/company/ApplicationStatus.java b/src/main/java/seedu/address/model/company/ApplicationStatus.java
new file mode 100644
index 00000000000..0b08b4a85d3
--- /dev/null
+++ b/src/main/java/seedu/address/model/company/ApplicationStatus.java
@@ -0,0 +1,119 @@
+package seedu.address.model.company;
+
+import static java.util.Objects.requireNonNull;
+
+/**
+ * Represents a Company's application status in the address book.
+ * Guarantees: immutable; is valid as declared in {@link #isValidApplicationStatus(String)}
+ */
+public class ApplicationStatus {
+
+ public static final String MESSAGE_CONSTRAINTS_NON_EMPTY =
+ "Oops! Application status should not be blank! Please try again with a valid application status.";
+ public static final String MESSAGE_CONSTRAINTS_VALID_STATUS =
+ "Oops! You have entered an invalid application status! \n"
+ + "Valid statuses: PA (Pending Application), PI (Pending Interview), PO (Pending Outcome), "
+ + "A (Accepted), R (Rejected). \n"
+ + "Please try again with a valid application status.";
+
+ /**
+ * The application status of a company.
+ */
+ public enum ApplicationStatusEnum {
+ PA("PA", "PENDING APPLICATION"),
+ PI("PI", "PENDING INTERVIEW"),
+ PO("PO", "PENDING OUTCOME"),
+ A("A", "ACCEPTED"),
+ R("R", "REJECTED");
+
+ private final String code;
+ private final String description;
+
+ ApplicationStatusEnum(String code, String description) {
+ this.code = code;
+ this.description = description;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+ }
+
+ public final ApplicationStatusEnum status;
+
+ /**
+ * Constructs an {@code ApplicationStatus} based on the given status string.
+ * The constructor supports a range of status inputs for flexibility, allowing
+ * for both short codes and various longer forms. This includes allowing
+ * infinite spaces between letters such as 'P' and 'O'. Refer to the class
+ * documentation for a detailed list of supported status inputs.
+ *
+ * @param status A string representation of the application status.
+ * @throws IllegalArgumentException If the provided status string is invalid.
+ */
+ public ApplicationStatus(String status) throws IllegalArgumentException {
+ requireNonNull(status);
+ status = status.toUpperCase().replaceAll("\\s+", " ").trim();
+
+ if (status.matches("^(PA|PEND\\s*APP|PENDING\\s*APP|PENDING\\s*APPLICATION|P\\sA|PENDING\\sA)$")) {
+ this.status = ApplicationStatusEnum.PA;
+ } else if (status.matches("^(PI|PEND\\s*INT|PENDING\\s*INT|PENDING\\s*INTERVIEW|P\\sI|PENDING\\sI)$")) {
+ this.status = ApplicationStatusEnum.PI;
+ } else if (status.matches("^(PO|PEND\\s*OUT|PENDING\\s*OUT|PENDING\\s*OUTCOME|P\\sO|PENDING\\sO)$")) {
+ this.status = ApplicationStatusEnum.PO;
+ } else if (status.matches("^(A|ACC|ACCEPT|ACPT|ACCEPTED)$")) {
+ this.status = ApplicationStatusEnum.A;
+ } else if (status.matches("^(R|REJ|REJECT|REJECTED)$")) {
+ this.status = ApplicationStatusEnum.R;
+ } else {
+ throw new IllegalArgumentException("Invalid application status");
+ }
+ }
+
+ /**
+ * Returns true if a given string is a valid application status.
+ */
+ public static boolean isValidApplicationStatus(String test) {
+ test = test.toUpperCase().replaceAll("\\s+", " ").trim();
+ return test.matches("^(PA|PEND\\s*APP|PENDING\\s*APP"
+ + "|PENDING\\s*APPLICATION|P\\sA|PENDING\\sA|PI|PEND\\s*INT|"
+ + "PENDING\\s*INT|PENDING\\s*INTERVIEW|P\\sI|PENDING\\sI|PO|PEND\\s*OUT|"
+ + "PENDING\\s*OUT|PENDING\\s*OUTCOME|P\\sO|PENDING\\sO|A|ACC|ACCEPT|ACPT|"
+ + "ACCEPTED|R|REJ|REJECT|REJECTED)$");
+ }
+
+ @Override
+ public String toString() {
+ return status.getCode();
+ }
+
+ public String getDescription() {
+ return status.getDescription();
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ }
+
+ // instanceof handles nulls
+ if (!(other instanceof ApplicationStatus)) {
+ return false;
+ }
+
+ ApplicationStatus otherApplicationStatus = (ApplicationStatus) other;
+ return status.equals(otherApplicationStatus.status);
+ }
+
+ @Override
+ public int hashCode() {
+ return status.hashCode();
+ }
+
+}
+
diff --git a/src/main/java/seedu/address/model/company/Company.java b/src/main/java/seedu/address/model/company/Company.java
new file mode 100644
index 00000000000..5722cc1ed36
--- /dev/null
+++ b/src/main/java/seedu/address/model/company/Company.java
@@ -0,0 +1,185 @@
+package seedu.address.model.company;
+
+import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_PRIORITY;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_RECRUITER_NAME;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_STATUS;
+
+import java.util.Objects;
+
+import seedu.address.commons.util.ToStringBuilder;
+
+/**
+ * Represents a Company in the address book.
+ * Guarantees: details are present and not null, field values are validated, immutable.
+ */
+public class Company {
+
+ // Identity fields
+ private final Name name;
+ private final Phone phone;
+ private final Email email;
+ private final Role role;
+ private final Deadline deadline;
+ private final ApplicationStatus status;
+ private final RecruiterName recruiterName;
+ private final Priority priority;
+ private final Remark remark;
+
+
+ /**
+ * Every field must be present and not null.
+ */
+ public Company(Name name, Phone phone, Email email, Role role, Deadline deadline, ApplicationStatus status,
+ RecruiterName recruiterName, Priority priority, Remark remark) {
+ requireAllNonNull(name, phone, email, role, deadline, status, priority, remark);
+ this.name = name;
+ this.phone = phone;
+ this.email = email;
+ this.role = role;
+ this.deadline = deadline;
+ this.status = status;
+ this.recruiterName = recruiterName;
+ this.priority = priority;
+ this.remark = remark;
+ }
+
+ public Name getName() {
+ return name;
+ }
+
+ public Phone getPhone() {
+ return phone;
+ }
+
+ public Email getEmail() {
+ return email;
+ }
+
+ public Role getRole() {
+ return role;
+ }
+
+ public Deadline getDeadline() {
+ return deadline;
+ }
+
+ public ApplicationStatus getStatus() {
+ return status;
+ }
+
+ public RecruiterName getRecruiterName() {
+ return recruiterName;
+ }
+
+ public Priority getPriority() {
+ return priority;
+ }
+
+ public Remark getRemark() {
+ return remark;
+ }
+
+ /**
+ * Returns true if both entries have the same company name, role and deadline.
+ */
+ public boolean isSameCompany(Company otherCompany) {
+ if (otherCompany == this) {
+ return true;
+ }
+
+ if (otherCompany == null) {
+ return false;
+ }
+
+ return otherCompany.getName() != null
+ && otherCompany.getName().equals(getName())
+ && otherCompany.getRole() != null
+ && otherCompany.getRole().equals(getRole())
+ && otherCompany.getDeadline() != null
+ && otherCompany.getDeadline().equals(getDeadline());
+ }
+
+ /**
+ * Returns string of all fields that are different between the two companies.
+ * Only to be used by add command's exception for duplicate companies.
+ * @param duplicatedCompany
+ * @return string of all fields that are different between the two companies.
+ */
+ public String listAllChangedFields(Company duplicatedCompany) {
+ String changedFields = "";
+ final String space = " ";
+
+ assert getName().equals(duplicatedCompany.getName());
+ assert getRole().equals(duplicatedCompany.getRole());
+ assert getDeadline().equals(duplicatedCompany.getDeadline());
+
+ if (!getPhone().equals(duplicatedCompany.getPhone())) {
+ changedFields += PREFIX_PHONE.getPrefix() + this.getPhone() + space;
+ }
+ if (!getEmail().equals(duplicatedCompany.getEmail())) {
+ changedFields += PREFIX_EMAIL.getPrefix() + this.getEmail() + space;
+ }
+ if (!getStatus().equals(duplicatedCompany.getStatus())) {
+ changedFields += PREFIX_STATUS.getPrefix() + this.getStatus() + space;
+ }
+ if (!getRecruiterName().equals(duplicatedCompany.getRecruiterName())) {
+ changedFields += PREFIX_RECRUITER_NAME.getPrefix() + this.getRecruiterName() + space;
+ }
+ if (!getPriority().equals(duplicatedCompany.getPriority())) {
+ changedFields += PREFIX_PRIORITY.getPrefix() + this.getPriority() + space;
+ }
+
+ return changedFields.strip();
+ }
+
+ /**
+ * Returns true if both companies have the same identity and data fields.
+ * This defines a stronger notion of equality between two companies.
+ */
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ }
+
+ // instanceof handles nulls
+ if (!(other instanceof Company)) {
+ return false;
+ }
+
+ Company otherCompany = (Company) other;
+ return name.equals(otherCompany.name)
+ && phone.equals(otherCompany.phone)
+ && email.equals(otherCompany.email)
+ && role.equals(otherCompany.role)
+ && deadline.equals(otherCompany.deadline)
+ && status.equals(otherCompany.status)
+ && recruiterName.equals(otherCompany.recruiterName)
+ && priority.equals(otherCompany.priority)
+ && remark.equals(otherCompany.remark);
+ }
+ @Override
+ public int hashCode() {
+ // use this method for custom fields hashing instead of implementing your own
+ return Objects.hash(name, phone, email, role, deadline, status, recruiterName, priority, remark);
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this)
+ .add("name", name)
+ .add("role", role)
+ .add("status", status)
+ .add("deadline", deadline)
+ .add("recruiterName", recruiterName)
+ .add("phone", phone)
+ .add("email", email)
+ .add("priority", priority)
+ .add("remark", remark)
+ .toString();
+ }
+
+}
diff --git a/src/main/java/seedu/address/model/company/Deadline.java b/src/main/java/seedu/address/model/company/Deadline.java
new file mode 100644
index 00000000000..a9573c388ed
--- /dev/null
+++ b/src/main/java/seedu/address/model/company/Deadline.java
@@ -0,0 +1,100 @@
+package seedu.address.model.company;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.util.AppUtil.checkArgument;
+
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
+import java.time.format.ResolverStyle;
+
+/**
+ * Represents a Company's deadline in the address book.
+ * Guarantees: immutable; is valid as declared in {@link #isValidDeadline(String)}
+ */
+public class Deadline implements Comparable {
+
+ public static final String MESSAGE_CONSTRAINTS_NON_EMPTY =
+ "Oops! Deadline should not be blank! Please try again with a valid deadline of format DD-MM-YYYY.";
+ public static final String MESSAGE_CONSTRAINTS_INVALID_DEADLINE =
+ "Oops! You have entered an invalid deadline! Please try again with the deadline format DD-MM-YYYY.";
+
+ public static final String MESSAGE_CONSTRAINTS_WRONG_FORMAT =
+ "Oops! You have entered an incorrect format for the deadline! Please use the format DD-MM-YYYY.";
+
+ public static final String FORMAT_REGEX = "^\\d{2}-\\d{2}-\\d{4}$";
+ public static final DateTimeFormatter FORMATTER =
+ DateTimeFormatter.ofPattern("dd-MM-uuuu").withResolverStyle(ResolverStyle.STRICT);
+ public final LocalDate value;
+
+ /**
+ * Constructs a {@code Deadline}.
+ *
+ * @param deadline A valid deadline.
+ */
+ public Deadline(String deadline) {
+ requireNonNull(deadline);
+ checkArgument(!deadline.isBlank(), MESSAGE_CONSTRAINTS_NON_EMPTY);
+ checkArgument(isValidFormat(deadline), MESSAGE_CONSTRAINTS_WRONG_FORMAT);
+ checkArgument(isValidDeadline(deadline), MESSAGE_CONSTRAINTS_INVALID_DEADLINE);
+ this.value = LocalDate.parse(deadline, FORMATTER);
+ }
+
+ /**
+ * Returns true if the given string follows the correct format.
+ */
+ public static boolean isValidFormat(String test) {
+ return test.matches(FORMAT_REGEX);
+ }
+
+ /**
+ * Returns true if a given string is a valid deadline.
+ */
+ public static boolean isValidDeadline(String test) {
+ if (!isValidFormat(test)) {
+ return false;
+ }
+
+ try {
+ LocalDate.parse(test, FORMATTER);
+ return true;
+ } catch (DateTimeParseException e) {
+ return false;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return value.format(FORMATTER);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ }
+
+ // instanceof handles nulls
+ if (!(other instanceof Deadline)) {
+ return false;
+ }
+
+ Deadline otherDeadline = (Deadline) other;
+ return value.equals(otherDeadline.value);
+ }
+
+ @Override
+ public int hashCode() {
+ return value.hashCode();
+ }
+
+ //@@author papataco14-reused
+ // The compareTo method was adapted from GitHub co-pilot suggestion
+ @Override
+ public int compareTo(Deadline other) {
+ if (other == null) {
+ return 1; // or -1 depending on how you want to handle nulls
+ }
+ return this.value.compareTo(other.value);
+ }
+}
diff --git a/src/main/java/seedu/address/model/person/Email.java b/src/main/java/seedu/address/model/company/Email.java
similarity index 74%
rename from src/main/java/seedu/address/model/person/Email.java
rename to src/main/java/seedu/address/model/company/Email.java
index c62e512bc29..bbe7b904695 100644
--- a/src/main/java/seedu/address/model/person/Email.java
+++ b/src/main/java/seedu/address/model/company/Email.java
@@ -1,16 +1,19 @@
-package seedu.address.model.person;
+package seedu.address.model.company;
import static java.util.Objects.requireNonNull;
import static seedu.address.commons.util.AppUtil.checkArgument;
/**
- * Represents a Person's email in the address book.
+ * Represents a Recruiter's email in the address book.
* Guarantees: immutable; is valid as declared in {@link #isValidEmail(String)}
*/
public class Email {
+ public static final String MESSAGE_CONSTRAINTS_NON_EMPTY = "Oops! Email should not be blank! "
+ + "Please try again with a valid email.";
private static final String SPECIAL_CHARACTERS = "+_.-";
- public static final String MESSAGE_CONSTRAINTS = "Emails should be of the format local-part@domain "
+ public static final String MESSAGE_CONSTRAINTS_VALID_REGEX =
+ "Oops! 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 "
@@ -20,7 +23,9 @@ public class Email {
+ "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.";
+ + " - have each domain label consist of alphanumeric characters, separated only by hyphens, if any.\n"
+ + "Please try again with a valid email.";
+
// 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 + "]"
@@ -40,8 +45,17 @@ public class Email {
*/
public Email(String email) {
requireNonNull(email);
- checkArgument(isValidEmail(email), MESSAGE_CONSTRAINTS);
- value = email;
+ String sanitizedEmail = sanitizeEmail(email);
+ checkArgument(!sanitizedEmail.isBlank(), MESSAGE_CONSTRAINTS_NON_EMPTY);
+ checkArgument(isValidEmail(sanitizedEmail), MESSAGE_CONSTRAINTS_VALID_REGEX);
+ value = sanitizedEmail;
+ }
+
+ /**
+ * Sanitizes the email by trimming and converting to lower case.
+ */
+ private static String sanitizeEmail(String email) {
+ return email.trim().toLowerCase();
}
/**
diff --git a/src/main/java/seedu/address/model/company/Name.java b/src/main/java/seedu/address/model/company/Name.java
new file mode 100644
index 00000000000..d9ef825917b
--- /dev/null
+++ b/src/main/java/seedu/address/model/company/Name.java
@@ -0,0 +1,106 @@
+package seedu.address.model.company;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.util.AppUtil.checkArgument;
+
+/**
+ * Represents a Company's name in the address book.
+ * Guarantees: immutable; is valid as declared in {@link #isValidName(String)}
+ */
+public class Name {
+ public static final int MAX_NAME_LENGTH = 100;
+ public static final String MESSAGE_CONSTRAINTS_NON_EMPTY =
+ "Oops! Company's name should not be blank. Please try again with a valid company name.";
+
+ public static final String MESSAGE_CONSTRAINTS_INVALID_REGEX =
+ "Oops! Company's name should only contain alphanumeric characters and spaces! Please try again with"
+ + " a valid company name.";
+
+ public static final String MESSAGE_CONSTRAINTS_INVALID_LENGTH =
+ "Oops! Company's name should not be more than " + MAX_NAME_LENGTH + " characters long (excluding spaces). "
+ + "Please try again with a shorter input.";
+
+ public static final String VALIDATION_REGEX = "[\\p{Alnum}][\\p{Alnum} ]*";
+
+ public final String fullName;
+
+ /**
+ * Constructs a {@code Name}.
+ *
+ * @param name A valid name.
+ */
+ public Name(String name) {
+ requireNonNull(name);
+ checkArgument(!name.isBlank(), MESSAGE_CONSTRAINTS_NON_EMPTY);
+ checkArgument(isValidName(name), MESSAGE_CONSTRAINTS_INVALID_REGEX);
+ checkArgument(isValidNameLength(name), MESSAGE_CONSTRAINTS_INVALID_LENGTH);
+ fullName = name;
+ }
+
+ /**
+ * Returns true if a given string is a valid name.
+ */
+ public static boolean isValidName(String test) {
+ return test.matches(VALIDATION_REGEX);
+ }
+
+ /**
+ * Returns true if a given string is a valid name length.
+ */
+ public static boolean isValidNameLength(String test) {
+ return test.length() <= MAX_NAME_LENGTH;
+ }
+
+
+ @Override
+ public String toString() {
+ return fullName;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ }
+
+ // instanceof handles nulls
+ if (!(other instanceof Name)) {
+ return false;
+ }
+
+ Name otherName = (Name) other;
+
+
+ return sanitize(fullName).equals(sanitize(otherName.fullName));
+ }
+
+ /**
+ * Sanitizes the name for comparison purposes:
+ * 1. Converts to lowercase.
+ * 2. Trims whitespace and reduces consecutive whitespaces to a single space.
+ * 3. Removes special characters.
+ * @param name Name to sanitize
+ * @return Sanitized name
+ */
+ private String sanitize(String name) {
+ if (name == null) {
+ return null;
+ }
+
+ // Convert to lowercase
+ name = name.toLowerCase();
+
+ // Remove special characters, excluding spaces, alphanumeric characters
+ name = name.replaceAll("[^a-zA-Z0-9 ]", "");
+
+ // Trim whitespace and removes all whitespace between words
+ name = name.trim().replaceAll("\\s+", "");
+
+ return name;
+ }
+
+ @Override
+ public int hashCode() {
+ return fullName.hashCode();
+ }
+}
diff --git a/src/main/java/seedu/address/model/person/Phone.java b/src/main/java/seedu/address/model/company/Phone.java
similarity index 58%
rename from src/main/java/seedu/address/model/person/Phone.java
rename to src/main/java/seedu/address/model/company/Phone.java
index d733f63d739..31f05f12308 100644
--- a/src/main/java/seedu/address/model/person/Phone.java
+++ b/src/main/java/seedu/address/model/company/Phone.java
@@ -1,18 +1,22 @@
-package seedu.address.model.person;
+package seedu.address.model.company;
import static java.util.Objects.requireNonNull;
import static seedu.address.commons.util.AppUtil.checkArgument;
/**
- * Represents a Person's phone number in the address book.
+ * Represents a Company'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_NON_EMPTY =
+ "Oops! Phone number should not be blank! Please try again with a valid phone number.";
+ public static final String MESSAGE_CONSTRAINTS_VALID_REGEX =
+ "Oops! Phone number should only contain numbers. \n"
+ + "It should be at least 3 digits and at most 20 characters long (excluding spaces). \n"
+ + "Please try again with a valid phone number. ";
+ public static final String VALIDATION_REGEX = "^(?=.*\\d)\\s*\\d\\s*(?:\\s*\\d\\s*){2,19}$";
- 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;
/**
@@ -22,7 +26,8 @@ public class Phone {
*/
public Phone(String phone) {
requireNonNull(phone);
- checkArgument(isValidPhone(phone), MESSAGE_CONSTRAINTS);
+ checkArgument(!phone.isBlank(), MESSAGE_CONSTRAINTS_NON_EMPTY);
+ checkArgument(isValidPhone(phone), MESSAGE_CONSTRAINTS_VALID_REGEX);
value = phone;
}
diff --git a/src/main/java/seedu/address/model/company/Priority.java b/src/main/java/seedu/address/model/company/Priority.java
new file mode 100644
index 00000000000..4093fb3f55c
--- /dev/null
+++ b/src/main/java/seedu/address/model/company/Priority.java
@@ -0,0 +1,67 @@
+package seedu.address.model.company;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.util.AppUtil.checkArgument;
+
+/**
+ * Represents a Company's priority in the address book.
+ * Guarantees: immutable; is valid as declared in {@link #isValidPriority(String)}
+ */
+public class Priority {
+ public static final String MESSAGE_CONSTRAINTS_NON_EMPTY =
+ "Oops! Priority description should not be blank! Please either try again with a valid priority, "
+ + "or remove the priority prefix. ";
+ public static final String MESSAGE_CONSTRAINTS_VALID_REGEX =
+ "Oops! You have entered an invalid priority! Priority should only be high, medium, "
+ + "low or none (to remove priority). \n"
+ + "Please try again.";
+
+
+ public static final String VALIDATION_REGEX = "(HIGH|MEDIUM|LOW|NONE)";
+
+ public final String priority;
+
+ /**
+ * Constructs a {@code Priority}.
+ *
+ * @param priority A valid priority.
+ */
+ public Priority(String priority) {
+ requireNonNull(priority);
+ checkArgument(!priority.isBlank(), MESSAGE_CONSTRAINTS_NON_EMPTY);
+ checkArgument(isValidPriority(priority), MESSAGE_CONSTRAINTS_VALID_REGEX);
+ this.priority = priority;
+ }
+
+ /**
+ * Returns true if a given string is a valid priority.
+ */
+ public static boolean isValidPriority(String test) {
+ return test.matches(VALIDATION_REGEX);
+ }
+
+ @Override
+ public String toString() {
+ return priority;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ }
+
+ // instanceof handles nulls
+ if (!(other instanceof Priority)) {
+ return false;
+ }
+
+ Priority otherPriority = (Priority) other;
+ return priority.equals(otherPriority.priority);
+ }
+
+ @Override
+ public int hashCode() {
+ return priority.hashCode();
+ }
+}
diff --git a/src/main/java/seedu/address/model/company/RecruiterName.java b/src/main/java/seedu/address/model/company/RecruiterName.java
new file mode 100644
index 00000000000..e4382a92b73
--- /dev/null
+++ b/src/main/java/seedu/address/model/company/RecruiterName.java
@@ -0,0 +1,106 @@
+package seedu.address.model.company;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.util.AppUtil.checkArgument;
+
+/**
+ * Represents a Company's recruiter name in the address book.
+ * Guarantees: immutable; is valid as declared in {@link #isValidName(String)}
+ */
+public class RecruiterName {
+
+ public static final int MAX_NAME_LENGTH = 100;
+
+ public static final String MESSAGE_CONSTRAINTS_NON_EMPTY =
+ "Oops! Recruiter's name should not be blank! Please try again with a valid recruiter name.";
+
+ public static final String MESSAGE_CONSTRAINTS_INVALID_REGEX =
+ "Oops! Recruiter's name should only contain alphanumeric characters and spaces! Please try again with"
+ + " a valid recruiter name.";
+
+ public static final String MESSAGE_CONSTRAINTS_INVALID_LENGTH =
+ "Oops! Recruiter's name should not be more than " + MAX_NAME_LENGTH + " characters "
+ + "long (excluding spaces). Please try again with a shorter input.";
+
+ public static final String VALIDATION_REGEX = "[\\p{Alnum}][\\p{Alnum} ]*";
+
+ public final String fullName;
+
+ /**
+ * Constructs a {@code RecruiterName}.
+ *
+ * @param name A valid name.
+ */
+ public RecruiterName(String name) {
+ requireNonNull(name);
+ checkArgument(!name.isBlank(), MESSAGE_CONSTRAINTS_NON_EMPTY);
+ checkArgument(isValidName(name), MESSAGE_CONSTRAINTS_INVALID_REGEX);
+ fullName = name;
+ }
+
+ /**
+ * Returns true if a given string is a valid name.
+ */
+ public static boolean isValidName(String test) {
+ return test.matches(VALIDATION_REGEX);
+ }
+
+ /**
+ * Returns true if a given string is a valid name length.
+ */
+ public static boolean isValidNameLength(String test) {
+ return test.length() <= MAX_NAME_LENGTH;
+ }
+
+ @Override
+ public String toString() {
+ return fullName;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ }
+
+ // instanceof handles nulls
+ if (!(other instanceof RecruiterName)) {
+ return false;
+ }
+
+ RecruiterName otherName = (RecruiterName) other;
+ return sanitize(fullName).equals(sanitize(otherName.fullName));
+ }
+
+ /**
+ * Sanitizes the name for comparison purposes:
+ * 1. Converts to lowercase.
+ * 2. Trims whitespace and reduces consecutive whitespaces to a single space.
+ * 3. Removes special characters.
+ *
+ * @param name Name to sanitize.
+ * @return Sanitized name.
+ */
+ private String sanitize(String name) {
+ if (name == null) {
+ return null;
+ }
+
+ // Convert to lowercase
+ name = name.toLowerCase();
+
+ // Remove special characters, excluding spaces, alphanumeric characters
+ name = name.replaceAll("[^a-zA-Z0-9 ]", "");
+
+ // Trim whitespace and remove all whitespaces
+ name = name.trim().replaceAll("\\s+", "");
+
+ return name;
+ }
+
+ @Override
+ public int hashCode() {
+ return fullName.hashCode();
+ }
+
+}
diff --git a/src/main/java/seedu/address/model/company/Remark.java b/src/main/java/seedu/address/model/company/Remark.java
new file mode 100644
index 00000000000..044e683f1b2
--- /dev/null
+++ b/src/main/java/seedu/address/model/company/Remark.java
@@ -0,0 +1,74 @@
+package seedu.address.model.company;
+
+import static java.util.Objects.requireNonNull;
+
+/**
+ * Represents user's remark for a Company in the address book.
+ * Guarantees: immutable; is valid as declared in {@link #isValidRemark(String)}
+ */
+public class Remark {
+
+ public static final String MESSAGE_CONSTRAINTS = "Oops! Remark should not be empty. Please try again!";
+
+ /*
+ * The remark must not consist of whitespace only,
+ * otherwise " " (a blank string) becomes a valid input.
+ */
+ public static final String VALIDATION_REGEX = "^(?!\\s+$).+";
+
+ public final String value;
+
+ private boolean isDeleted = false;
+
+ /**
+ * Constructs a {@code Remark}.
+ *
+ * @param remark A valid remark.
+ */
+ public Remark(String remark) {
+ requireNonNull(remark);
+ this.value = remark;
+ }
+
+ /**
+ * Returns true if a given string is a valid remark.
+ */
+ public static boolean isValidRemark(String test) {
+ return test.matches(VALIDATION_REGEX);
+ }
+
+ public void deleteRemark() {
+ this.isDeleted = true;
+ }
+
+ public boolean getIsDeleted() {
+ return this.isDeleted;
+ }
+
+
+ @Override
+ public String toString() {
+ return value;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ }
+
+ // instanceof handles nulls
+ if (!(other instanceof Remark)) {
+ return false;
+ }
+
+ Remark otherremark = (Remark) other;
+ return value.equals(otherremark.value);
+ }
+
+ @Override
+ public int hashCode() {
+ return value.hashCode();
+ }
+
+}
diff --git a/src/main/java/seedu/address/model/company/Role.java b/src/main/java/seedu/address/model/company/Role.java
new file mode 100644
index 00000000000..498f4c1d319
--- /dev/null
+++ b/src/main/java/seedu/address/model/company/Role.java
@@ -0,0 +1,104 @@
+package seedu.address.model.company;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.util.AppUtil.checkArgument;
+
+/**
+ * Represents a Company's role in the address book.
+ * Guarantees: immutable; is valid as declared in {@link #isValidRole(String)}
+ */
+public class Role {
+ public static final int MAX_NAME_LENGTH = 100;
+
+ public static final String MESSAGE_CONSTRAINTS_NON_EMPTY =
+ "Oops! Role should not be blank! Please try again with a valid role.";
+
+ public static final String MESSAGE_CONSTRAINTS_INVALID_REGEX =
+ "Oops! Role should only contain alphanumeric characters and spaces! Please try again with"
+ + " a valid role.";
+
+ public static final String MESSAGE_CONSTRAINTS_INVALID_LENGTH =
+ "Oops! Role should not be more than " + MAX_NAME_LENGTH + " characters long (excluding spaces). "
+ + "Please try again with a shorter input.";
+
+ public static final String VALIDATION_REGEX = "[\\p{Alnum}][\\p{Alnum} ]*";
+
+ public final String jobRole;
+
+ /**
+ * Constructs a {@code ApplyingRole}.
+ *
+ * @param role A valid role.
+ */
+ public Role(String role) {
+ requireNonNull(role);
+ checkArgument(!role.isBlank(), MESSAGE_CONSTRAINTS_NON_EMPTY);
+ checkArgument(isValidRole(role), MESSAGE_CONSTRAINTS_INVALID_REGEX);
+ checkArgument(isValidRoleLength(role), MESSAGE_CONSTRAINTS_INVALID_LENGTH);
+ jobRole = role;
+ }
+
+ /**
+ * Returns true if a given string is a valid role.
+ */
+ public static boolean isValidRole(String test) {
+ return test.matches(VALIDATION_REGEX);
+ }
+
+ /**
+ * Returns true if a given string is a valid role length.
+ */
+ public static boolean isValidRoleLength(String test) {
+ return test.length() <= MAX_NAME_LENGTH;
+ }
+
+ @Override
+ public String toString() {
+ return jobRole;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ }
+
+ // instanceof handles nulls
+ if (!(other instanceof Role)) {
+ return false;
+ }
+
+ Role otherRole = (Role) other;
+ return sanitize(jobRole).equals(sanitize(otherRole.jobRole));
+ }
+
+ /**
+ * Sanitizes the role for comparison purposes:
+ * 1. Converts to lowercase.
+ * 2. Trims whitespace and reduces consecutive whitespaces to a single space.
+ * 3. Removes special characters.
+ * @param role Role to sanitize
+ * @return Sanitized role
+ */
+ private String sanitize(String role) {
+ if (role == null) {
+ return null;
+ }
+
+ // Convert to lowercase
+ role = role.toLowerCase();
+
+ // Remove special characters, excluding spaces, alphanumeric characters
+ role = role.replaceAll("[^a-zA-Z0-9 ]", "");
+
+ // Trim whitespace and remove all whitespaces
+ role = role.trim().replaceAll("\\s+", "");
+
+ return role;
+ }
+
+ @Override
+ public int hashCode() {
+ return jobRole.hashCode();
+ }
+}
diff --git a/src/main/java/seedu/address/model/company/UniqueCompanyList.java b/src/main/java/seedu/address/model/company/UniqueCompanyList.java
new file mode 100644
index 00000000000..e0e67ddcc0e
--- /dev/null
+++ b/src/main/java/seedu/address/model/company/UniqueCompanyList.java
@@ -0,0 +1,178 @@
+package seedu.address.model.company;
+
+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.company.exceptions.CompanyNotFoundException;
+import seedu.address.model.company.exceptions.DuplicateCompanyException;
+
+/**
+ * A list of companies that enforces uniqueness between its elements and does not allow nulls.
+ * A company is considered unique by comparing using {@code Company#isSameCompany(Company)}. As such, adding and
+ * updating of companies uses Company#isSameCompany(Company) for equality so as to ensure that the company being added
+ * or updated is unique in terms of identity in the UniqueCompanyList. However, the removal of a company uses
+ * Company#equals(Object) so as to ensure that the company with exactly the same fields will be removed.
+ *
+ * Supports a minimal set of list operations.
+ *
+ * @see Company#isSameCompany(Company)
+ */
+public class UniqueCompanyList implements Iterable {
+
+ private final ObservableList internalList = FXCollections.observableArrayList();
+ private final ObservableList internalUnmodifiableList =
+ FXCollections.unmodifiableObservableList(internalList);
+
+ /**
+ * Returns true if the list contains an equivalent company as the given argument.
+ */
+ public boolean contains(Company toCheck) {
+ requireNonNull(toCheck);
+ return internalList.stream().anyMatch(toCheck::isSameCompany);
+ }
+
+ /**
+ * Returns Company if the list contains an equivalent company as the given argument.
+ * Implements findFirst to act as protection against multiple companies with the same name.
+ */
+ public Company getDuplicateCompany(Company toCheck) {
+ requireNonNull(toCheck);
+ assert(contains(toCheck));
+ return internalList.stream().filter(toCheck::isSameCompany).findFirst().get();
+ }
+
+ /**
+ * Returns the index of the duplicate company [zero-based] as the given argument.
+ * @param company
+ * @return integer index of the duplicate company
+ */
+ public int getDuplicateIndex(Company company) {
+ requireNonNull(company);
+ assert(contains(company));
+ return internalList.indexOf(company);
+ }
+
+ /**
+ * Adds a company to the list.
+ * The company must not already exist in the list.
+ */
+ public void add(Company toAdd) {
+ requireNonNull(toAdd);
+ if (contains(toAdd)) {
+ throw new DuplicateCompanyException();
+ }
+ internalList.add(toAdd);
+ }
+
+ /**
+ * Clears the list.
+ */
+ public void clear() {
+ internalList.clear();
+ }
+
+ /**
+ * Replaces the company {@code target} in the list with {@code editedCompany}.
+ * {@code target} must exist in the list.
+ * The company identity of {@code editedCompany} must not be the same as another existing company in the list.
+ */
+ public void setCompany(Company target, Company editedCompany) {
+ requireAllNonNull(target, editedCompany);
+
+ int index = internalList.indexOf(target);
+ if (index == -1) {
+ throw new CompanyNotFoundException();
+ }
+
+ if (!target.isSameCompany(editedCompany) && contains(editedCompany)) {
+ throw new DuplicateCompanyException();
+ }
+
+ internalList.set(index, editedCompany);
+ }
+
+ /**
+ * Removes the equivalent company from the list.
+ * The company must exist in the list.
+ */
+ public void remove(Company toRemove) {
+ requireNonNull(toRemove);
+ if (!internalList.remove(toRemove)) {
+ throw new CompanyNotFoundException();
+ }
+ }
+
+ public void setCompanies(UniqueCompanyList replacement) {
+ requireNonNull(replacement);
+ internalList.setAll(replacement.internalList);
+ }
+
+ /**
+ * Replaces the contents of this list with {@code companies}.
+ * {@code companies} must not contain duplicate companies.
+ */
+ public void setCompanies(List companies) {
+ requireAllNonNull(companies);
+ if (!companiesAreUnique(companies)) {
+ throw new DuplicateCompanyException();
+ }
+
+ internalList.setAll(companies);
+ }
+
+ /**
+ * 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) {
+ if (other == this) {
+ return true;
+ }
+
+ // instanceof handles nulls
+ if (!(other instanceof UniqueCompanyList)) {
+ return false;
+ }
+
+ UniqueCompanyList otherUniqueCompanyList = (UniqueCompanyList) other;
+ return internalList.equals(otherUniqueCompanyList.internalList);
+ }
+
+ @Override
+ public int hashCode() {
+ return internalList.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return internalList.toString();
+ }
+
+ /**
+ * Returns true if {@code companies} contains only unique companies.
+ */
+ private boolean companiesAreUnique(List companies) {
+ for (int i = 0; i < companies.size() - 1; i++) {
+ for (int j = i + 1; j < companies.size(); j++) {
+ if (companies.get(i).isSameCompany(companies.get(j))) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+}
diff --git a/src/main/java/seedu/address/model/company/exceptions/CompanyNotFoundException.java b/src/main/java/seedu/address/model/company/exceptions/CompanyNotFoundException.java
new file mode 100644
index 00000000000..c193ff67db7
--- /dev/null
+++ b/src/main/java/seedu/address/model/company/exceptions/CompanyNotFoundException.java
@@ -0,0 +1,6 @@
+package seedu.address.model.company.exceptions;
+
+/**
+ * Signals that the operation is unable to find the specified company.
+ */
+public class CompanyNotFoundException extends RuntimeException {}
diff --git a/src/main/java/seedu/address/model/company/exceptions/DuplicateCompanyException.java b/src/main/java/seedu/address/model/company/exceptions/DuplicateCompanyException.java
new file mode 100644
index 00000000000..164dde3e2c5
--- /dev/null
+++ b/src/main/java/seedu/address/model/company/exceptions/DuplicateCompanyException.java
@@ -0,0 +1,12 @@
+package seedu.address.model.company.exceptions;
+
+/**
+ * Signals that the operation will result in duplicate Companies (Companies are considered duplicates if they have
+ * the same identity).
+ * This is only to be used for model's testing. It is not to be used for user interaction.
+ */
+public class DuplicateCompanyException extends RuntimeException {
+ public DuplicateCompanyException() {
+ super("Operation would result in duplicate companies");
+ }
+}
diff --git a/src/main/java/seedu/address/model/company/predicates/ApplicationStatusPredicate.java b/src/main/java/seedu/address/model/company/predicates/ApplicationStatusPredicate.java
new file mode 100644
index 00000000000..d6deba7ca0c
--- /dev/null
+++ b/src/main/java/seedu/address/model/company/predicates/ApplicationStatusPredicate.java
@@ -0,0 +1,29 @@
+package seedu.address.model.company.predicates;
+
+import java.util.function.Predicate;
+
+import seedu.address.model.company.ApplicationStatus;
+import seedu.address.model.company.Company;
+
+/**
+ * Tests that a {@code Company}'s {@code ApplicationStatus} matches the status given.
+ */
+public class ApplicationStatusPredicate implements Predicate {
+ private final ApplicationStatus status;
+
+ public ApplicationStatusPredicate(ApplicationStatus status) {
+ this.status = status;
+ }
+
+ @Override
+ public boolean test(Company company) {
+ return company.getStatus().equals(status);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this
+ || (other instanceof ApplicationStatusPredicate
+ && status.equals(((ApplicationStatusPredicate) other).status));
+ }
+}
diff --git a/src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java b/src/main/java/seedu/address/model/company/predicates/NameContainsKeywordsPredicate.java
similarity index 53%
rename from src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java
rename to src/main/java/seedu/address/model/company/predicates/NameContainsKeywordsPredicate.java
index 62d19be2977..6ca80b4e573 100644
--- a/src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java
+++ b/src/main/java/seedu/address/model/company/predicates/NameContainsKeywordsPredicate.java
@@ -1,25 +1,35 @@
-package seedu.address.model.person;
+package seedu.address.model.company.predicates;
import java.util.List;
import java.util.function.Predicate;
-import seedu.address.commons.util.StringUtil;
import seedu.address.commons.util.ToStringBuilder;
+import seedu.address.model.company.Company;
/**
- * Tests that a {@code Person}'s {@code Name} matches any of the keywords given.
+ * Represents a predicate to test if a {@code Company}'s {@code Name} contains
+ * any of the specified keywords. The matching is case-insensitive.
*/
-public class NameContainsKeywordsPredicate implements Predicate {
+public class NameContainsKeywordsPredicate implements Predicate {
private final List keywords;
public NameContainsKeywordsPredicate(List keywords) {
this.keywords = keywords;
}
+ /**
+ * Tests if the {@code Company}'s name contains any of the keywords as substrings.
+ *
+ *
For instance, if the keyword is "tech", then companies with names "Tech Corp",
+ * "Biotech Industries", and "Infotech Solutions" would all be matched.
+ *
+ * @param company The company to be tested against the keywords.
+ * @return True if the company's name contains any keyword as a substring, false otherwise.
+ */
@Override
- public boolean test(Person person) {
+ public boolean test(Company company) {
return keywords.stream()
- .anyMatch(keyword -> StringUtil.containsWordIgnoreCase(person.getName().fullName, keyword));
+ .anyMatch(keyword -> company.getName().toString().toLowerCase().contains(keyword.toLowerCase()));
}
@Override
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 469a2cc9a1e..00000000000
--- a/src/main/java/seedu/address/model/person/Address.java
+++ /dev/null
@@ -1,65 +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) {
- if (other == this) {
- return true;
- }
-
- // instanceof handles nulls
- if (!(other instanceof Address)) {
- return false;
- }
-
- Address otherAddress = (Address) other;
- return value.equals(otherAddress.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/address/model/person/Name.java
deleted file mode 100644
index 173f15b9b00..00000000000
--- a/src/main/java/seedu/address/model/person/Name.java
+++ /dev/null
@@ -1,67 +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 name in the address book.
- * 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";
-
- /*
- * 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 = "[\\p{Alnum}][\\p{Alnum} ]*";
-
- public final String fullName;
-
- /**
- * Constructs a {@code Name}.
- *
- * @param name A valid name.
- */
- public Name(String name) {
- requireNonNull(name);
- checkArgument(isValidName(name), MESSAGE_CONSTRAINTS);
- fullName = name;
- }
-
- /**
- * Returns true if a given string is a valid name.
- */
- public static boolean isValidName(String test) {
- return test.matches(VALIDATION_REGEX);
- }
-
-
- @Override
- public String toString() {
- return fullName;
- }
-
- @Override
- public boolean equals(Object other) {
- if (other == this) {
- return true;
- }
-
- // instanceof handles nulls
- if (!(other instanceof Name)) {
- return false;
- }
-
- Name otherName = (Name) other;
- return fullName.equals(otherName.fullName);
- }
-
- @Override
- public int hashCode() {
- return fullName.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 abe8c46b535..00000000000
--- a/src/main/java/seedu/address/model/person/Person.java
+++ /dev/null
@@ -1,117 +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.commons.util.ToStringBuilder;
-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;
- }
-
- // instanceof handles nulls
- if (!(other instanceof Person)) {
- return false;
- }
-
- Person otherPerson = (Person) other;
- return name.equals(otherPerson.name)
- && phone.equals(otherPerson.phone)
- && email.equals(otherPerson.email)
- && address.equals(otherPerson.address)
- && tags.equals(otherPerson.tags);
- }
-
- @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() {
- return new ToStringBuilder(this)
- .add("name", name)
- .add("phone", phone)
- .add("email", email)
- .add("address", address)
- .add("tags", tags)
- .toString();
- }
-
-}
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 cc0a68d79f9..00000000000
--- a/src/main/java/seedu/address/model/person/UniquePersonList.java
+++ /dev/null
@@ -1,150 +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) {
- if (other == this) {
- return true;
- }
-
- // instanceof handles nulls
- if (!(other instanceof UniquePersonList)) {
- return false;
- }
-
- UniquePersonList otherUniquePersonList = (UniquePersonList) other;
- return internalList.equals(otherUniquePersonList.internalList);
- }
-
- @Override
- public int hashCode() {
- return internalList.hashCode();
- }
-
- @Override
- public String toString() {
- return internalList.toString();
- }
-
- /**
- * 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 f1a0d4e233b..00000000000
--- a/src/main/java/seedu/address/model/tag/Tag.java
+++ /dev/null
@@ -1,62 +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) {
- if (other == this) {
- return true;
- }
-
- // instanceof handles nulls
- if (!(other instanceof Tag)) {
- return false;
- }
-
- Tag otherTag = (Tag) other;
- return tagName.equals(otherTag.tagName);
- }
-
- @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
index 1806da4facf..354c43810fa 100644
--- a/src/main/java/seedu/address/model/util/SampleDataUtil.java
+++ b/src/main/java/seedu/address/model/util/SampleDataUtil.java
@@ -1,60 +1,56 @@
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;
+import seedu.address.model.company.ApplicationStatus;
+import seedu.address.model.company.Company;
+import seedu.address.model.company.Deadline;
+import seedu.address.model.company.Email;
+import seedu.address.model.company.Name;
+import seedu.address.model.company.Phone;
+import seedu.address.model.company.Priority;
+import seedu.address.model.company.RecruiterName;
+import seedu.address.model.company.Remark;
+import seedu.address.model.company.Role;
/**
* 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 Company[] getSampleCompanies() {
+ return new Company[] {
+ new Company(new Name("Google"), new Phone("87438807"), new Email("alexyeoh@example.com"),
+ new Role("Software Engineer"), new Deadline("10-11-2023"),
+ new ApplicationStatus("PA"), new RecruiterName("Francis Tan"),
+ new Priority("LOW"), new Remark("Java/Python")),
+ new Company(new Name("Tiktok"), new Phone("99272758"), new Email("berniceyu@example.com"),
+ new Role("Software Engineer"), new Deadline("20-12-2023"),
+ new ApplicationStatus("PA"), new RecruiterName("Alice Tan"),
+ new Priority("MEDIUM"), new Remark("No remarks")),
+ new Company(new Name("DSTA"), new Phone("93210283"), new Email("charlotte@example.com"),
+ new Role("Software Engineer"), new Deadline("01-12-2023"),
+ new ApplicationStatus("PA"), new RecruiterName("Eve Lim"),
+ new Priority("HIGH"), new Remark("Java")),
+ new Company(new Name("Microsoft"), new Phone("91031282"), new Email("lidavid@example.com"),
+ new Role("Data Analyst"), new Deadline("18-11-2023"),
+ new ApplicationStatus("PA"), new RecruiterName("Jovie Tan"),
+ new Priority("NONE"), new Remark("www.bing.com")),
+ new Company(new Name("Meta"), new Phone("92492021"), new Email("irfan@example.com"),
+ new Role("Data Analyst"), new Deadline("19-11-2023"),
+ new ApplicationStatus("PA"), new RecruiterName("Poppins Lam"),
+ new Priority("LOW"), new Remark("No remarks")),
+ new Company(new Name("Amazon"), new Phone("92624417"), new Email("royb@example.com"),
+ new Role("Web Developer"), new Deadline("20-11-2023"),
+ new ApplicationStatus("PA"), new RecruiterName("Jarvis Koh"),
+ new Priority("NONE"), new Remark("JavaScript&CSS"))
};
}
public static ReadOnlyAddressBook getSampleAddressBook() {
AddressBook sampleAb = new AddressBook();
- for (Person samplePerson : getSamplePersons()) {
- sampleAb.addPerson(samplePerson);
+ for (Company sampleCompany : getSampleCompanies()) {
+ sampleAb.addCompany(sampleCompany);
}
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/JsonAdaptedCompany.java b/src/main/java/seedu/address/storage/JsonAdaptedCompany.java
new file mode 100644
index 00000000000..7caaac1dbe3
--- /dev/null
+++ b/src/main/java/seedu/address/storage/JsonAdaptedCompany.java
@@ -0,0 +1,155 @@
+package seedu.address.storage;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import seedu.address.commons.exceptions.IllegalValueException;
+import seedu.address.model.company.ApplicationStatus;
+import seedu.address.model.company.Company;
+import seedu.address.model.company.Deadline;
+import seedu.address.model.company.Email;
+import seedu.address.model.company.Name;
+import seedu.address.model.company.Phone;
+import seedu.address.model.company.Priority;
+import seedu.address.model.company.RecruiterName;
+import seedu.address.model.company.Remark;
+import seedu.address.model.company.Role;
+
+/**
+ * Jackson-friendly version of {@link Company}.
+ */
+class JsonAdaptedCompany {
+
+ public static final String MISSING_FIELD_MESSAGE_FORMAT = "Company's %s field is missing!";
+
+ private final String name;
+ private final String phone;
+ private final String email;
+ private final String role;
+ private final String deadline;
+ private final String status;
+ private final String recruiterName;
+ private final String priority;
+ private final String remark;
+
+ /**
+ * Constructs a {@code JsonAdaptedCompany} with the given company details.
+ */
+ @JsonCreator
+ public JsonAdaptedCompany(@JsonProperty("name") String name, @JsonProperty("phone") String phone,
+ @JsonProperty("email") String email, @JsonProperty("role") String role,
+ @JsonProperty("deadline") String deadline, @JsonProperty("status") String status,
+ @JsonProperty("recruiterName") String recruiterName,
+ @JsonProperty("priority") String priority, @JsonProperty("remark") String remark) {
+ this.name = name;
+ this.phone = phone;
+ this.email = email;
+ this.role = role;
+ this.deadline = deadline;
+ this.status = status;
+ this.priority = priority;
+ this.recruiterName = recruiterName;
+ this.remark = remark;
+ }
+
+ /**
+ * Converts a given {@code Company} into this class for Jackson use.
+ */
+ public JsonAdaptedCompany(Company source) {
+ name = source.getName().fullName;
+ phone = source.getPhone().value;
+ email = source.getEmail().value;
+ role = source.getRole().jobRole;
+ deadline = source.getDeadline().toString();
+ status = source.getStatus().toString();
+ recruiterName = source.getRecruiterName().fullName;
+ priority = source.getPriority().priority;
+ remark = source.getRemark().value;
+ }
+
+ /**
+ * Converts this Jackson-friendly adapted company object into the model's {@code Company} object.
+ *
+ * @throws IllegalValueException if there were any data constraints violated in the adapted company.
+ */
+ public Company 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_INVALID_REGEX);
+ }
+ 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_VALID_REGEX);
+ }
+ 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_VALID_REGEX);
+ }
+ final Email modelEmail = new Email(email);
+
+ if (role == null) {
+ throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Role.class.getSimpleName()));
+ }
+ if (!Role.isValidRole(role)) {
+ throw new IllegalValueException(Role.MESSAGE_CONSTRAINTS_INVALID_REGEX);
+ }
+ final Role modelRole = new Role(role);
+
+ if (deadline == null) {
+ throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT,
+ Deadline.class.getSimpleName()));
+ }
+ if (!Deadline.isValidDeadline(deadline)) {
+ throw new IllegalValueException(Deadline.MESSAGE_CONSTRAINTS_INVALID_DEADLINE);
+ }
+ final Deadline modelDeadline = new Deadline(deadline);
+
+ if (status == null) {
+ throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT,
+ ApplicationStatus.class.getSimpleName()));
+ }
+ if (!ApplicationStatus.isValidApplicationStatus(status)) {
+ throw new IllegalValueException(ApplicationStatus.MESSAGE_CONSTRAINTS_VALID_STATUS);
+ }
+ final ApplicationStatus modelStatus = new ApplicationStatus(status);
+
+ if (recruiterName == null) {
+ throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT,
+ RecruiterName.class.getSimpleName()));
+ }
+ if (!RecruiterName.isValidName(recruiterName)) {
+ throw new IllegalValueException(RecruiterName.MESSAGE_CONSTRAINTS_INVALID_REGEX);
+ }
+ final RecruiterName modelRecruiterName = new RecruiterName(recruiterName);
+
+ if (priority == null) {
+ throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT,
+ Priority.class.getSimpleName()));
+ }
+ if (!Priority.isValidPriority(priority)) {
+ throw new IllegalValueException(Priority.MESSAGE_CONSTRAINTS_VALID_REGEX);
+ }
+ final Priority modelPriority = new Priority(priority);
+
+ if (remark == null) {
+ throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Remark.class.getSimpleName()));
+ }
+
+ final Remark modelRemark = new Remark(remark);
+
+ return new Company(modelName, modelPhone, modelEmail, modelRole, modelDeadline, modelStatus,
+ modelRecruiterName, modelPriority, modelRemark);
+ }
+
+}
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 bd1ca0f56c8..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 tags = 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("tags") List tags) {
- this.name = name;
- this.phone = phone;
- this.email = email;
- this.address = address;
- if (tags != null) {
- this.tags.addAll(tags);
- }
- }
-
- /**
- * 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;
- tags.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 : tags) {
- 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/JsonSerializableAddressBook.java b/src/main/java/seedu/address/storage/JsonSerializableAddressBook.java
index 5efd834091d..fa30e55466c 100644
--- a/src/main/java/seedu/address/storage/JsonSerializableAddressBook.java
+++ b/src/main/java/seedu/address/storage/JsonSerializableAddressBook.java
@@ -11,7 +11,7 @@
import seedu.address.commons.exceptions.IllegalValueException;
import seedu.address.model.AddressBook;
import seedu.address.model.ReadOnlyAddressBook;
-import seedu.address.model.person.Person;
+import seedu.address.model.company.Company;
/**
* An Immutable AddressBook that is serializable to JSON format.
@@ -19,16 +19,16 @@
@JsonRootName(value = "addressbook")
class JsonSerializableAddressBook {
- public static final String MESSAGE_DUPLICATE_PERSON = "Persons list contains duplicate person(s).";
+ public static final String MESSAGE_DUPLICATE_COMPANY = "Company list contains duplicate company(s).";
- private final List persons = new ArrayList<>();
+ private final List companies = new ArrayList<>();
/**
- * Constructs a {@code JsonSerializableAddressBook} with the given persons.
+ * Constructs a {@code JsonSerializableAddressBook} with the given companies.
*/
@JsonCreator
- public JsonSerializableAddressBook(@JsonProperty("persons") List persons) {
- this.persons.addAll(persons);
+ public JsonSerializableAddressBook(@JsonProperty("companies") List companies) {
+ this.companies.addAll(companies);
}
/**
@@ -37,7 +37,7 @@ public JsonSerializableAddressBook(@JsonProperty("persons") List {
+
+ private static final String FXML = "CompanyListCard.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 Company company;
+
+ @FXML
+ private Label name;
+ @FXML
+ private Label id;
+ @FXML
+ private Label role;
+ @FXML
+ private Label deadline;
+ @FXML
+ private Label status;
+ @FXML
+ private FlowPane priority;
+
+ /**
+ * Creates a {@code CompanyCode} with the given {@code Company} and index to display.
+ */
+ public CompanyCard(Company company, int displayedIndex) {
+ super(FXML);
+ this.company = company;
+ id.setText(displayedIndex + ". ");
+ name.setText(company.getName().fullName);
+ role.setText(company.getRole().jobRole);
+ deadline.setText(company.getDeadline().toString());
+ status.setText(company.getStatus().getDescription());
+ priority.getChildren().add(createPriorityFlowPane(company, false));
+ }
+}
diff --git a/src/main/java/seedu/address/ui/CompanyCardUtils.java b/src/main/java/seedu/address/ui/CompanyCardUtils.java
new file mode 100644
index 00000000000..fb7a95953b7
--- /dev/null
+++ b/src/main/java/seedu/address/ui/CompanyCardUtils.java
@@ -0,0 +1,56 @@
+package seedu.address.ui;
+
+import javafx.scene.control.Label;
+import javafx.scene.layout.FlowPane;
+import seedu.address.model.company.Company;
+
+/**
+ * Utility class for creating FlowPanes for CompanyCards.
+ */
+public class CompanyCardUtils {
+
+ /**
+ * Generates a FlowPane representing the priority information of the given {@code Company}.
+ * If the priority is not "NONE," a FlowPane containing a label and a value label with a background color
+ * corresponding to the priority level is created and added to the {@code priority} FlowPane.
+ * @param company The company for which the priority FlowPane is to be generated.
+ * @param includeLabel Whether to include the label in the priority FlowPane.
+ * @return A FlowPane representing the priority information of the given {@code Company}.
+ */
+ public static FlowPane createPriorityFlowPane(Company company, boolean includeLabel) {
+ assert company != null;
+ FlowPane priorityPane = new FlowPane();
+
+ if (!company.getPriority().priority.equals("NONE")) {
+ Label priorityLabel = new Label("Priority: ");
+ Label priorityValue = new Label(company.getPriority().priority);
+
+ String backgroundColor = "#444444"; // Dark gray (default)
+
+ switch (company.getPriority().priority) {
+ case "HIGH":
+ backgroundColor = "#990000"; // Dark red
+ break;
+ case "MEDIUM":
+ backgroundColor = "#FF8000"; // Dark orange
+ break;
+ case "LOW":
+ backgroundColor = "#006400"; // Dark green
+ break;
+ default:
+ break;
+ }
+
+ priorityValue.setStyle("-fx-background-color: " + backgroundColor);
+
+ if (includeLabel) {
+ priorityPane.getChildren().addAll(priorityLabel, priorityValue);
+ } else {
+ priorityPane.getChildren().addAll(priorityValue);
+ }
+ }
+
+ return priorityPane;
+ }
+
+}
diff --git a/src/main/java/seedu/address/ui/CompanyDetailCard.java b/src/main/java/seedu/address/ui/CompanyDetailCard.java
new file mode 100644
index 00000000000..aeec9946efd
--- /dev/null
+++ b/src/main/java/seedu/address/ui/CompanyDetailCard.java
@@ -0,0 +1,65 @@
+package seedu.address.ui;
+
+import static seedu.address.ui.CompanyCardUtils.createPriorityFlowPane;
+
+import javafx.fxml.FXML;
+import javafx.scene.control.Label;
+import javafx.scene.layout.FlowPane;
+import javafx.scene.layout.Region;
+import seedu.address.model.company.Company;
+
+/**
+ * An UI component that displays detailed information of a {@code Company}.
+ */
+public class CompanyDetailCard extends UiPart {
+
+ private static final String FXML = "CompanyDetailCard.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 Company company;
+ @FXML
+ private Label name;
+ @FXML
+ private Label phone;
+ @FXML
+ private Label email;
+ @FXML
+ private Label role;
+ @FXML
+ private Label deadline;
+ @FXML
+ private Label status;
+ @FXML
+ private Label recruiterName;
+ @FXML
+ private FlowPane priority;
+ @FXML
+ private Label remark;
+
+ /**
+ * Creates a {@code CompanyDetailCard} with the given {@code Company}.
+ */
+ public CompanyDetailCard(Company company) {
+ super(FXML);
+ assert company != null;
+ this.company = company;
+ name.setText(company.getName().fullName);
+ phone.setText("Phone: " + company.getPhone().value);
+ email.setText("Email: " + company.getEmail().value);
+ role.setText("Role: " + company.getRole().jobRole);
+ deadline.setText("Deadline: " + company.getDeadline().toString());
+ status.setText("Application status: " + company.getStatus().getDescription());
+ recruiterName.setText("Name: " + company.getRecruiterName().fullName);
+ priority.getChildren().add(createPriorityFlowPane(company, true));
+ remark.setText(company.getRemark().value);
+
+ }
+}
+
diff --git a/src/main/java/seedu/address/ui/CompanyDetailPanel.java b/src/main/java/seedu/address/ui/CompanyDetailPanel.java
new file mode 100644
index 00000000000..b77c746e3d6
--- /dev/null
+++ b/src/main/java/seedu/address/ui/CompanyDetailPanel.java
@@ -0,0 +1,53 @@
+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.company.Company;
+
+/**
+ * Panel containing the detail of company.
+ */
+public class CompanyDetailPanel extends UiPart {
+ private static final String FXML = "CompanyDetailPanel.fxml";
+ private final Logger logger = LogsCenter.getLogger(CompanyDetailPanel.class);
+
+ @FXML
+ private ListView companyDetailView;
+
+ /**
+ * Creates a {@code CompanyDetailPanel} with the given {@code ObservableList}.
+ */
+ public CompanyDetailPanel(ObservableList company) {
+ super(FXML);
+ companyDetailView.setItems(company);
+ companyDetailView.setCellFactory(listView -> new CompanyDetailViewCell());
+ }
+
+ public ListView getCompanyDetailView() {
+ return companyDetailView;
+ }
+
+ /**
+ * Custom {@code ListCell} that displays the graphics of a {@code Company} using a {@code CompanyDetailCard}.
+ */
+ class CompanyDetailViewCell extends ListCell {
+ @Override
+ protected void updateItem(Company company, boolean empty) {
+ super.updateItem(company, empty);
+
+ if (empty || company == null) {
+ setGraphic(null);
+ setText(null);
+ } else {
+ setGraphic(new CompanyDetailCard(company).getRoot());
+ }
+ }
+ }
+
+}
diff --git a/src/main/java/seedu/address/ui/CompanyListPanel.java b/src/main/java/seedu/address/ui/CompanyListPanel.java
new file mode 100644
index 00000000000..e5a9d311a68
--- /dev/null
+++ b/src/main/java/seedu/address/ui/CompanyListPanel.java
@@ -0,0 +1,59 @@
+package seedu.address.ui;
+
+import java.util.logging.Logger;
+
+import javafx.collections.ObservableList;
+import javafx.fxml.FXML;
+import javafx.scene.control.Label;
+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.company.Company;
+
+/**
+ * Panel containing the list of companies.
+ */
+public class CompanyListPanel extends UiPart {
+ private static final String FXML = "CompanyListPanel.fxml";
+ private final Logger logger = LogsCenter.getLogger(CompanyListPanel.class);
+
+ @FXML
+ private ListView companyListView;
+
+ /**
+ * Creates a {@code CompanyListPanel} with the given {@code ObservableList}.
+ */
+ public CompanyListPanel(ObservableList companyList) {
+ super(FXML);
+ // Set a placeholder message for an empty list
+ Label placeholderLabel = new Label("No company to display.");
+ placeholderLabel.setStyle("-fx-text-fill: white;"); // Set the text color to white
+ companyListView.setPlaceholder(placeholderLabel);
+
+ companyListView.setItems(companyList);
+ companyListView.setCellFactory(listView -> new CompanyListViewCell());
+ }
+
+ public ListView getCompanyListView() {
+ return companyListView;
+ }
+
+ /**
+ * Custom {@code ListCell} that displays the graphics of a {@code Company} using a {@code CompanyCard}.
+ */
+ class CompanyListViewCell extends ListCell {
+ @Override
+ protected void updateItem(Company company, boolean empty) {
+ super.updateItem(company, empty);
+
+ if (empty || company == null) {
+ setGraphic(null);
+ setText(null);
+ } else {
+ setGraphic(new CompanyCard(company, getIndex() + 1).getRoot());
+ }
+ }
+ }
+
+}
diff --git a/src/main/java/seedu/address/ui/HelpWindow.java b/src/main/java/seedu/address/ui/HelpWindow.java
index 3f16b2fcf26..72b172aca8d 100644
--- a/src/main/java/seedu/address/ui/HelpWindow.java
+++ b/src/main/java/seedu/address/ui/HelpWindow.java
@@ -15,7 +15,7 @@
*/
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://ay2324s1-cs2103t-t17-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);
diff --git a/src/main/java/seedu/address/ui/MainWindow.java b/src/main/java/seedu/address/ui/MainWindow.java
index 79e74ef37c0..3d7f4afa32c 100644
--- a/src/main/java/seedu/address/ui/MainWindow.java
+++ b/src/main/java/seedu/address/ui/MainWindow.java
@@ -31,10 +31,14 @@ public class MainWindow extends UiPart {
private Logic logic;
// Independent Ui parts residing in this Ui container
- private PersonListPanel personListPanel;
+ private CompanyListPanel companyListPanel;
+ private CompanyDetailCard companyDetailCard;
+ private CompanyDetailPanel companyDetailPanel;
private ResultDisplay resultDisplay;
private HelpWindow helpWindow;
+ @FXML
+ private StackPane companyDetailPanelPlaceholder;
@FXML
private StackPane commandBoxPlaceholder;
@@ -42,7 +46,9 @@ public class MainWindow extends UiPart {
private MenuItem helpMenuItem;
@FXML
- private StackPane personListPanelPlaceholder;
+ private StackPane companyListPanelPlaceholder;
+ @FXML
+ private StackPane companyDetailCardPlaceholder;
@FXML
private StackPane resultDisplayPlaceholder;
@@ -110,8 +116,11 @@ 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());
+ companyListPanel = new CompanyListPanel(logic.getFilteredCompanyList());
+ companyListPanelPlaceholder.getChildren().add(companyListPanel.getRoot());
+
+ companyDetailPanel = new CompanyDetailPanel(logic.getCurrentViewedCompany());
+ companyDetailPanelPlaceholder.getChildren().add(companyDetailPanel.getRoot());
resultDisplay = new ResultDisplay();
resultDisplayPlaceholder.getChildren().add(resultDisplay.getRoot());
@@ -163,8 +172,8 @@ private void handleExit() {
primaryStage.hide();
}
- public PersonListPanel getPersonListPanel() {
- return personListPanel;
+ public CompanyListPanel getCompanyListPanel() {
+ return companyListPanel;
}
/**
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 094c42cda82..00000000000
--- a/src/main/java/seedu/address/ui/PersonCard.java
+++ /dev/null
@@ -1,59 +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)));
- }
-}
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/ui/UiManager.java b/src/main/java/seedu/address/ui/UiManager.java
index fdf024138bc..0e122b8314d 100644
--- a/src/main/java/seedu/address/ui/UiManager.java
+++ b/src/main/java/seedu/address/ui/UiManager.java
@@ -36,7 +36,7 @@ public UiManager(Logic logic) {
public void start(Stage primaryStage) {
logger.info("Starting UI...");
- //Set the application icon.
+ // Set the application icon.
primaryStage.getIcons().add(getImage(ICON_APPLICATION));
try {
@@ -85,4 +85,7 @@ private void showFatalErrorDialogAndShutdown(String title, Throwable e) {
System.exit(1);
}
+ public MainWindow getMainWindow() {
+ return mainWindow;
+ }
}
diff --git a/src/main/resources/view/CompanyDetailCard.fxml b/src/main/resources/view/CompanyDetailCard.fxml
new file mode 100644
index 00000000000..3bdee78abee
--- /dev/null
+++ b/src/main/resources/view/CompanyDetailCard.fxml
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/view/CompanyDetailPanel.fxml b/src/main/resources/view/CompanyDetailPanel.fxml
new file mode 100644
index 00000000000..1a39632ab4f
--- /dev/null
+++ b/src/main/resources/view/CompanyDetailPanel.fxml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/view/PersonListCard.fxml b/src/main/resources/view/CompanyListCard.fxml
similarity index 70%
rename from src/main/resources/view/PersonListCard.fxml
rename to src/main/resources/view/CompanyListCard.fxml
index f5e812e25e6..0f6338c98ba 100644
--- a/src/main/resources/view/PersonListCard.fxml
+++ b/src/main/resources/view/CompanyListCard.fxml
@@ -10,7 +10,7 @@
-
+
@@ -18,19 +18,23 @@
-
+
-
+
+
+
+
-
-
-
-
+
+
+
+
+
diff --git a/src/main/resources/view/PersonListPanel.fxml b/src/main/resources/view/CompanyListPanel.fxml
similarity index 77%
rename from src/main/resources/view/PersonListPanel.fxml
rename to src/main/resources/view/CompanyListPanel.fxml
index a1bb6bbace8..941906d0f05 100644
--- a/src/main/resources/view/PersonListPanel.fxml
+++ b/src/main/resources/view/CompanyListPanel.fxml
@@ -4,5 +4,5 @@
-
+
diff --git a/src/main/resources/view/DarkTheme.css b/src/main/resources/view/DarkTheme.css
index 36e6b001cd8..b0060ad2570 100644
--- a/src/main/resources/view/DarkTheme.css
+++ b/src/main/resources/view/DarkTheme.css
@@ -123,13 +123,13 @@
.cell_big_label {
-fx-font-family: "Segoe UI Semibold";
-fx-font-size: 16px;
- -fx-text-fill: #010504;
+ -fx-text-fill: #ffffff;
}
.cell_small_label {
-fx-font-family: "Segoe UI";
-fx-font-size: 13px;
- -fx-text-fill: #010504;
+ -fx-text-fill: #ffffff;
}
.stack-pane {
@@ -176,14 +176,41 @@
.grid-pane {
-fx-background-color: derive(#1d1d1d, 30%);
- -fx-border-color: derive(#1d1d1d, 30%);
+ -fx-background-color: #3c3e3f;
-fx-border-width: 1px;
}
.grid-pane .stack-pane {
+ -fx-padding: 0;
-fx-background-color: derive(#1d1d1d, 30%);
+ -fx-border-width: 2px;
+}
+
+.card-with-border {
+ -fx-background-color: #515658;
+ -fx-border-color: derive(#1d1d1d, 25%);
+ -fx-padding: 13;
+ -fx-border-insets: 15;
+ -fx-background-insets: 15;
+}
+
+.card_big_label {
+ -fx-font-family: "Segoe UI Semibold";
+ -fx-font-size: 20px;
+ -fx-text-fill: #ffffff;
}
+.card_medium_label {
+ -fx-font-family: "Segoe UI Semibold";
+ -fx-font-size: 16px;
+ -fx-text-fill: #ffffff;
+}
+
+.card_small_label {
+ -fx-font-family: "Segoe UI";
+ -fx-font-size: 15px;
+ -fx-text-fill: #ffffff;
+}
.context-menu {
-fx-background-color: derive(#1d1d1d, 50%);
}
@@ -328,7 +355,7 @@
-fx-text-fill: white;
}
-#filterField, #personListPanel, #personWebpage {
+#filterField, #companyListPanel, #companyWebpage {
-fx-effect: innershadow(gaussian, black, 10, 0, 0, 0);
}
@@ -337,16 +364,15 @@
-fx-background-radius: 0;
}
-#tags {
+#priority {
-fx-hgap: 7;
-fx-vgap: 3;
}
-#tags .label {
+#priority .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;
+ -fx-font-size: 12;
}
diff --git a/src/main/resources/view/MainWindow.fxml b/src/main/resources/view/MainWindow.fxml
index 7778f666a0a..2b289c3dcc3 100644
--- a/src/main/resources/view/MainWindow.fxml
+++ b/src/main/resources/view/MainWindow.fxml
@@ -12,7 +12,7 @@
+ title="LinkMeIn" minWidth="450" minHeight="600" onCloseRequest="#handleExit">
@@ -46,12 +46,20 @@
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/test/data/JsonAddressBookStorageTest/invalidAndValidPersonAddressBook.json b/src/test/data/JsonAddressBookStorageTest/invalidAndValidCompanyAddressBook.json
similarity index 66%
rename from src/test/data/JsonAddressBookStorageTest/invalidAndValidPersonAddressBook.json
rename to src/test/data/JsonAddressBookStorageTest/invalidAndValidCompanyAddressBook.json
index 6a4d2b7181c..cb88382b0fc 100644
--- a/src/test/data/JsonAddressBookStorageTest/invalidAndValidPersonAddressBook.json
+++ b/src/test/data/JsonAddressBookStorageTest/invalidAndValidCompanyAddressBook.json
@@ -1,11 +1,11 @@
{
- "persons": [ {
- "name": "Valid Person",
+ "companies": [ {
+ "name": "Valid Company",
"phone": "9482424",
"email": "hans@example.com",
"address": "4th street"
}, {
- "name": "Person With Invalid Phone Field",
+ "name": "Company 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/invalidCompanyAddressBook.json
similarity index 53%
rename from src/test/data/JsonAddressBookStorageTest/invalidPersonAddressBook.json
rename to src/test/data/JsonAddressBookStorageTest/invalidCompanyAddressBook.json
index ccd21f7d1a9..3daf574aced 100644
--- a/src/test/data/JsonAddressBookStorageTest/invalidPersonAddressBook.json
+++ b/src/test/data/JsonAddressBookStorageTest/invalidCompanyAddressBook.json
@@ -1,6 +1,6 @@
{
- "persons": [ {
- "name": "Person with invalid name field: Ha!ns Mu@ster",
+ "companies": [ {
+ "name": "Company with invalid name field: Ha!ns Mu@ster",
"phone": "9482424",
"email": "hans@example.com",
"address": "4th street"
diff --git a/src/test/data/JsonSerializableAddressBookTest/duplicateCompanyAddressBook.json b/src/test/data/JsonSerializableAddressBookTest/duplicateCompanyAddressBook.json
new file mode 100644
index 00000000000..4c3ff181f5a
--- /dev/null
+++ b/src/test/data/JsonSerializableAddressBookTest/duplicateCompanyAddressBook.json
@@ -0,0 +1,23 @@
+{
+ "companies": [ {
+ "name": "Meta",
+ "phone": "94351253",
+ "email": "alice@example.com",
+ "role": "Software Engineer",
+ "deadline": "10-10-2023",
+ "status": "PA",
+ "recruiterName": "Alice Pauline",
+ "priority": "HIGH",
+ "remark" : "No remarks"
+ }, {
+ "name": "Meta",
+ "phone": "94351253",
+ "email": "pauline@example.com",
+ "role": "Software Engineer",
+ "deadline": "10-10-2023",
+ "status": "PA",
+ "recruiterName": "Alice Pauline",
+ "priority": "HIGH",
+ "remark" : "No remarks"
+ } ]
+}
diff --git a/src/test/data/JsonSerializableAddressBookTest/duplicatePersonAddressBook.json b/src/test/data/JsonSerializableAddressBookTest/duplicatePersonAddressBook.json
deleted file mode 100644
index a7427fe7aa2..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",
- "tags": [ "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/invalidCompanyAddressBook.json
similarity index 86%
rename from src/test/data/JsonSerializableAddressBookTest/invalidPersonAddressBook.json
rename to src/test/data/JsonSerializableAddressBookTest/invalidCompanyAddressBook.json
index ad3f135ae42..bda80072ddb 100644
--- a/src/test/data/JsonSerializableAddressBookTest/invalidPersonAddressBook.json
+++ b/src/test/data/JsonSerializableAddressBookTest/invalidCompanyAddressBook.json
@@ -1,5 +1,5 @@
{
- "persons": [ {
+ "companies": [ {
"name": "Hans Muster",
"phone": "9482424",
"email": "invalid@email!3e",
diff --git a/src/test/data/JsonSerializableAddressBookTest/typicalCompaniesAddressBook.json b/src/test/data/JsonSerializableAddressBookTest/typicalCompaniesAddressBook.json
new file mode 100644
index 00000000000..166ab703202
--- /dev/null
+++ b/src/test/data/JsonSerializableAddressBookTest/typicalCompaniesAddressBook.json
@@ -0,0 +1,74 @@
+{
+ "_comment": "AddressBook save file which contains the same Company values as in TypicalCompanies#getTypicalAddressBook()",
+ "companies" : [ {
+ "name" : "Meta",
+ "phone" : "94351253",
+ "email" : "alice@example.com",
+ "role" : "Software Engineer",
+ "deadline": "10-10-2023",
+ "status": "PA",
+ "recruiterName": "John Doe",
+ "priority": "LOW",
+ "remark" : "No remarks"
+ }, {
+ "name" : "Amazon",
+ "phone" : "98765432",
+ "email" : "janed@example.com",
+ "role" : "Software Engineer",
+ "deadline": "11-11-2023",
+ "status": "PA",
+ "recruiterName": "Jane Doe",
+ "priority": "MEDIUM",
+ "remark" : "JavaScript&CSS"
+ }, {
+ "name" : "Microsoft",
+ "phone" : "95352563",
+ "email" : "heinz@example.com",
+ "deadline": "11-12-2023",
+ "role" : "Data Engineer",
+ "status": "PA",
+ "recruiterName": "Jim Doe",
+ "priority": "HIGH",
+ "remark" : "www.bing.com"
+ }, {
+ "name" : "DSTA",
+ "phone" : "87652533",
+ "email" : "cornelia@example.com",
+ "role" : "Data Engineer",
+ "deadline": "03-12-2023",
+ "status": "PA",
+ "recruiterName": "Tim Doe",
+ "priority": "LOW",
+ "remark" : "Java"
+ }, {
+ "name" : "Apple",
+ "phone" : "9482224",
+ "email" : "werner@example.com",
+ "role" : "UX Designer",
+ "deadline": "09-11-2023",
+ "status": "PA",
+ "recruiterName": "Tom Doe",
+ "priority": "MEDIUM",
+ "remark" : "Python"
+ }, {
+ "name" : "Accenture",
+ "phone" : "9482427",
+ "email" : "lydia@example.com",
+ "role" : "UI Designer",
+ "deadline": "08-11-2023",
+ "status": "PA",
+ "recruiterName": "Mary Doe",
+ "priority": "HIGH",
+ "remark" : "No remarks"
+ }, {
+ "name" : "Netflix",
+ "phone" : "9482442",
+ "email" : "anna@example.com",
+ "role" : "Web Developer",
+ "deadline": "05-12-2023",
+ "status": "PA",
+ "recruiterName": "Timmy Doe",
+ "priority": "HIGH",
+ "remark" : "No remarks"
+ }]
+}
diff --git a/src/test/data/JsonSerializableAddressBookTest/typicalPersonsAddressBook.json b/src/test/data/JsonSerializableAddressBookTest/typicalPersonsAddressBook.json
deleted file mode 100644
index 72262099d35..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",
- "tags" : [ "friends" ]
- }, {
- "name" : "Benson Meier",
- "phone" : "98765432",
- "email" : "johnd@example.com",
- "address" : "311, Clementi Ave 2, #02-25",
- "tags" : [ "owesMoney", "friends" ]
- }, {
- "name" : "Carl Kurz",
- "phone" : "95352563",
- "email" : "heinz@example.com",
- "address" : "wall street",
- "tags" : [ ]
- }, {
- "name" : "Daniel Meier",
- "phone" : "87652533",
- "email" : "cornelia@example.com",
- "address" : "10th street",
- "tags" : [ "friends" ]
- }, {
- "name" : "Elle Meyer",
- "phone" : "9482224",
- "email" : "werner@example.com",
- "address" : "michegan ave",
- "tags" : [ ]
- }, {
- "name" : "Fiona Kunz",
- "phone" : "9482427",
- "email" : "lydia@example.com",
- "address" : "little tokyo",
- "tags" : [ ]
- }, {
- "name" : "George Best",
- "phone" : "9482442",
- "email" : "anna@example.com",
- "address" : "4th street",
- "tags" : [ ]
- } ]
-}
diff --git a/src/test/data/JsonUserPrefsStorageTest/ExtraValuesUserPref.json b/src/test/data/JsonUserPrefsStorageTest/ExtraValuesUserPref.json
index 1037548a9cd..743ad62b140 100644
--- a/src/test/data/JsonUserPrefsStorageTest/ExtraValuesUserPref.json
+++ b/src/test/data/JsonUserPrefsStorageTest/ExtraValuesUserPref.json
@@ -9,5 +9,5 @@
"z" : 99
}
},
- "addressBookFilePath" : "addressbook.json"
+ "addressBookFilePath" : "companydata.json"
}
diff --git a/src/test/data/JsonUserPrefsStorageTest/TypicalUserPref.json b/src/test/data/JsonUserPrefsStorageTest/TypicalUserPref.json
index b819bed900a..5dfdb22c23f 100644
--- a/src/test/data/JsonUserPrefsStorageTest/TypicalUserPref.json
+++ b/src/test/data/JsonUserPrefsStorageTest/TypicalUserPref.json
@@ -7,5 +7,5 @@
"y" : 100
}
},
- "addressBookFilePath" : "addressbook.json"
+ "addressBookFilePath" : "companydata.json"
}
diff --git a/src/test/java/seedu/address/commons/core/index/IndexTest.java b/src/test/java/seedu/address/commons/core/index/IndexTest.java
index fc395ab964b..ae5396041a1 100644
--- a/src/test/java/seedu/address/commons/core/index/IndexTest.java
+++ b/src/test/java/seedu/address/commons/core/index/IndexTest.java
@@ -39,23 +39,23 @@ public void createZeroBasedIndex() {
@Test
public void equals() {
- final Index fifthPersonIndex = Index.fromOneBased(5);
+ final Index fifthCompanyIndex = Index.fromOneBased(5);
// same values -> returns true
- assertTrue(fifthPersonIndex.equals(Index.fromOneBased(5)));
- assertTrue(fifthPersonIndex.equals(Index.fromZeroBased(4)));
+ assertTrue(fifthCompanyIndex.equals(Index.fromOneBased(5)));
+ assertTrue(fifthCompanyIndex.equals(Index.fromZeroBased(4)));
// same object -> returns true
- assertTrue(fifthPersonIndex.equals(fifthPersonIndex));
+ assertTrue(fifthCompanyIndex.equals(fifthCompanyIndex));
// null -> returns false
- assertFalse(fifthPersonIndex.equals(null));
+ assertFalse(fifthCompanyIndex.equals(null));
// different types -> returns false
- assertFalse(fifthPersonIndex.equals(5.0f));
+ assertFalse(fifthCompanyIndex.equals(5.0f));
// different index -> returns false
- assertFalse(fifthPersonIndex.equals(Index.fromOneBased(1)));
+ assertFalse(fifthCompanyIndex.equals(Index.fromOneBased(1)));
}
@Test
diff --git a/src/test/java/seedu/address/commons/util/StringUtilTest.java b/src/test/java/seedu/address/commons/util/StringUtilTest.java
index c56d407bf3f..9df6db8fcc9 100644
--- a/src/test/java/seedu/address/commons/util/StringUtilTest.java
+++ b/src/test/java/seedu/address/commons/util/StringUtilTest.java
@@ -10,6 +10,31 @@
public class StringUtilTest {
+ //---------------- Tests for isInteger ----------------------------------------------------
+ @Test
+ public void isInteger() {
+ // EP: empty strings
+ assertFalse(StringUtil.isInteger("")); // Boundary value
+ assertFalse(StringUtil.isInteger(" "));
+
+ // EP: not a number
+ assertFalse(StringUtil.isInteger("a"));
+ assertFalse(StringUtil.isInteger("aaa"));
+
+ // EP: signed numbers
+ assertTrue(StringUtil.isInteger("-1"));
+ assertTrue(StringUtil.isInteger("+1"));
+
+ // EP: numbers with white space
+ assertFalse(StringUtil.isInteger(" 10 ")); // Leading/trailing spaces
+ assertFalse(StringUtil.isInteger("1 0")); // Spaces in the middle
+
+ // EP: valid numbers, should return true
+ assertTrue(StringUtil.isInteger("0")); // Boundary value
+ assertTrue(StringUtil.isInteger("1"));
+ assertTrue(StringUtil.isInteger("10"));
+ }
+
//---------------- Tests for isNonZeroUnsignedInteger --------------------------------------
@Test
diff --git a/src/test/java/seedu/address/logic/LogicManagerTest.java b/src/test/java/seedu/address/logic/LogicManagerTest.java
index baf8ce336a2..428ff282168 100644
--- a/src/test/java/seedu/address/logic/LogicManagerTest.java
+++ b/src/test/java/seedu/address/logic/LogicManagerTest.java
@@ -1,14 +1,18 @@
package seedu.address.logic;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static seedu.address.logic.Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX;
+import static seedu.address.logic.Messages.MESSAGE_INVALID_COMPANY_DISPLAYED_INDEX;
import static seedu.address.logic.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.logic.commands.CommandTestUtil.DEADLINE_DESC_GOOGLE;
+import static seedu.address.logic.commands.CommandTestUtil.EMAIL_DESC_GOOGLE;
+import static seedu.address.logic.commands.CommandTestUtil.NAME_DESC_GOOGLE;
+import static seedu.address.logic.commands.CommandTestUtil.PHONE_DESC_GOOGLE;
+import static seedu.address.logic.commands.CommandTestUtil.PRIORITY_DESC_GOOGLE;
+import static seedu.address.logic.commands.CommandTestUtil.RECRUITER_NAME_DESC_GOOGLE;
+import static seedu.address.logic.commands.CommandTestUtil.ROLE_DESC_GOOGLE;
+import static seedu.address.logic.commands.CommandTestUtil.STATUS_DESC_GOOGLE;
import static seedu.address.testutil.Assert.assertThrows;
-import static seedu.address.testutil.TypicalPersons.AMY;
+import static seedu.address.testutil.TypicalCompanies.GOOGLE;
import java.io.IOException;
import java.nio.file.AccessDeniedException;
@@ -27,11 +31,11 @@
import seedu.address.model.ModelManager;
import seedu.address.model.ReadOnlyAddressBook;
import seedu.address.model.UserPrefs;
-import seedu.address.model.person.Person;
+import seedu.address.model.company.Company;
import seedu.address.storage.JsonAddressBookStorage;
import seedu.address.storage.JsonUserPrefsStorage;
import seedu.address.storage.StorageManager;
-import seedu.address.testutil.PersonBuilder;
+import seedu.address.testutil.CompanyBuilder;
public class LogicManagerTest {
private static final IOException DUMMY_IO_EXCEPTION = new IOException("dummy IO exception");
@@ -46,7 +50,7 @@ public class LogicManagerTest {
@BeforeEach
public void setUp() {
JsonAddressBookStorage addressBookStorage =
- new JsonAddressBookStorage(temporaryFolder.resolve("addressBook.json"));
+ new JsonAddressBookStorage(temporaryFolder.resolve("companydata.json"));
JsonUserPrefsStorage userPrefsStorage = new JsonUserPrefsStorage(temporaryFolder.resolve("userPrefs.json"));
StorageManager storage = new StorageManager(addressBookStorage, userPrefsStorage);
logic = new LogicManager(model, storage);
@@ -61,7 +65,7 @@ public void execute_invalidCommandFormat_throwsParseException() {
@Test
public void execute_commandExecutionError_throwsCommandException() {
String deleteCommand = "delete 9";
- assertCommandException(deleteCommand, MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
+ assertCommandException(deleteCommand, MESSAGE_INVALID_COMPANY_DISPLAYED_INDEX);
}
@Test
@@ -83,8 +87,8 @@ public void execute_storageThrowsAdException_throwsCommandException() {
}
@Test
- public void getFilteredPersonList_modifyList_throwsUnsupportedOperationException() {
- assertThrows(UnsupportedOperationException.class, () -> logic.getFilteredPersonList().remove(0));
+ public void getFilteredCompanyList_modifyList_throwsUnsupportedOperationException() {
+ assertThrows(UnsupportedOperationException.class, () -> logic.getFilteredCompanyList().remove(0));
}
/**
@@ -165,11 +169,12 @@ public void saveAddressBook(ReadOnlyAddressBook addressBook, Path filePath)
logic = new LogicManager(model, storage);
// Triggers the saveAddressBook method by executing an 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();
+ String addCommand = AddCommand.COMMAND_WORD + NAME_DESC_GOOGLE + PHONE_DESC_GOOGLE + EMAIL_DESC_GOOGLE
+ + ROLE_DESC_GOOGLE + DEADLINE_DESC_GOOGLE + STATUS_DESC_GOOGLE
+ + RECRUITER_NAME_DESC_GOOGLE + PRIORITY_DESC_GOOGLE;
+ Company expectedCompany = new CompanyBuilder(GOOGLE).withRemark("No remarks").build();
ModelManager expectedModel = new ModelManager();
- expectedModel.addPerson(expectedPerson);
+ expectedModel.addCompany(expectedCompany);
assertCommandFailure(addCommand, CommandException.class, expectedMessage, expectedModel);
}
}
diff --git a/src/test/java/seedu/address/logic/commands/AddCommandIntegrationTest.java b/src/test/java/seedu/address/logic/commands/AddCommandIntegrationTest.java
index 162a0c86031..51514d5b34d 100644
--- a/src/test/java/seedu/address/logic/commands/AddCommandIntegrationTest.java
+++ b/src/test/java/seedu/address/logic/commands/AddCommandIntegrationTest.java
@@ -2,17 +2,18 @@
import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure;
import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
-import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;
+import static seedu.address.testutil.TypicalCompanies.getTypicalAddressBook;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import seedu.address.logic.Messages;
+import seedu.address.logic.commands.exceptions.CommandException;
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;
+import seedu.address.model.company.Company;
+import seedu.address.testutil.CompanyBuilder;
/**
* Contains integration tests (interaction with the Model) for {@code AddCommand}.
@@ -25,24 +26,28 @@ public class AddCommandIntegrationTest {
public void setUp() {
model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
}
-
@Test
- public void execute_newPerson_success() {
- Person validPerson = new PersonBuilder().build();
+ public void execute_newCompany_success() {
+ Company validCompany = new CompanyBuilder().build();
Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs());
- expectedModel.addPerson(validPerson);
+ expectedModel.addCompany(validCompany);
- assertCommandSuccess(new AddCommand(validPerson), model,
- String.format(AddCommand.MESSAGE_SUCCESS, Messages.format(validPerson)),
+ assertCommandSuccess(new AddCommand(validCompany), model,
+ String.format(AddCommand.MESSAGE_SUCCESS, Messages.getCompanyName(validCompany)),
expectedModel);
}
@Test
- public void execute_duplicatePerson_throwsCommandException() {
- Person personInList = model.getAddressBook().getPersonList().get(0);
- assertCommandFailure(new AddCommand(personInList), model,
- AddCommand.MESSAGE_DUPLICATE_PERSON);
+ public void execute_duplicateCompany_throwsCommandException() {
+ Company companyInList = model.getAddressBook().getCompanyList().get(0);
+ assertCommandFailure(new AddCommand(companyInList), model,
+ new CommandException.DuplicateException(
+ Messages.getErrorMessageForDuplicateCompanyAddCommand(
+ companyInList,
+ model.getDuplicateIndexFromOriginalAddressbook(companyInList),
+ companyInList.listAllChangedFields(model.getDuplicateCompany(companyInList)),
+ true)
+ ).getMessage());
}
-
}
diff --git a/src/test/java/seedu/address/logic/commands/AddCommandTest.java b/src/test/java/seedu/address/logic/commands/AddCommandTest.java
index 90e8253f48e..c303b834a5f 100644
--- a/src/test/java/seedu/address/logic/commands/AddCommandTest.java
+++ b/src/test/java/seedu/address/logic/commands/AddCommandTest.java
@@ -1,204 +1,535 @@
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.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
import static seedu.address.testutil.Assert.assertThrows;
-import static seedu.address.testutil.TypicalPersons.ALICE;
+import static seedu.address.testutil.TypicalCompanies.META;
-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.Messages;
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;
+import seedu.address.logic.commands.stubs.ModelStub;
+import seedu.address.logic.commands.stubs.ModelStubAcceptingCompanyAdded;
+import seedu.address.logic.commands.stubs.ModelStubWithCompanyInFilteredCompanyList;
+import seedu.address.logic.commands.stubs.ModelStubWithCompanyNotInFilteredCompanyList;
+import seedu.address.model.company.Company;
+import seedu.address.testutil.CompanyBuilder;
public class AddCommandTest {
@Test
- public void constructor_nullPerson_throwsNullPointerException() {
+ public void constructor_nullCompany_throwsNullPointerException() {
assertThrows(NullPointerException.class, () -> new AddCommand(null));
}
@Test
- public void execute_personAcceptedByModel_addSuccessful() throws Exception {
- ModelStubAcceptingPersonAdded modelStub = new ModelStubAcceptingPersonAdded();
- Person validPerson = new PersonBuilder().build();
+ public void execute_companyAcceptedByModel_addSuccessful() throws Exception {
+ ModelStubAcceptingCompanyAdded modelStub = new ModelStubAcceptingCompanyAdded();
+ Company validCompany = new CompanyBuilder().build();
- CommandResult commandResult = new AddCommand(validPerson).execute(modelStub);
+ CommandResult commandResult = new AddCommand(validCompany).execute(modelStub);
- assertEquals(String.format(AddCommand.MESSAGE_SUCCESS, Messages.format(validPerson)),
+ assertEquals(String.format(AddCommand.MESSAGE_SUCCESS, Messages.getCompanyName(validCompany)),
commandResult.getFeedbackToUser());
- assertEquals(Arrays.asList(validPerson), modelStub.personsAdded);
+ assertEquals(Arrays.asList(validCompany), modelStub.companiesAdded);
}
+ //Duplicate tests, considered duplicate if same company name, same role and deadline
@Test
- public void execute_duplicatePerson_throwsCommandException() {
- Person validPerson = new PersonBuilder().build();
- AddCommand addCommand = new AddCommand(validPerson);
- ModelStub modelStub = new ModelStubWithPerson(validPerson);
+ public void execute_fullyDuplicatedCompany_throwsCommandException() {
+ Company validCompany = new CompanyBuilder().build();
+ AddCommand addCommand = new AddCommand(validCompany);
+ ModelStub modelStub = new ModelStubWithCompanyNotInFilteredCompanyList(validCompany);
+
+ assertThrows(CommandException.DuplicateException.class,
+ new CommandException.DuplicateException(
+ Messages.getErrorMessageForDuplicateCompanyAddCommand(validCompany,
+ modelStub.getDuplicateIndexFromOriginalAddressbook(validCompany),
+ validCompany.listAllChangedFields(
+ modelStub.getDuplicateCompany(validCompany)),
+ false)).getMessage(), (
+ ) -> addCommand.execute(modelStub));
+ }
- assertThrows(CommandException.class, AddCommand.MESSAGE_DUPLICATE_PERSON, () -> addCommand.execute(modelStub));
+ @Test
+ public void execute_successDifferentCompanyName_doesNotThrowCommandException() {
+ CompanyBuilder companyBuilder = new CompanyBuilder();
+ Company validCompany = companyBuilder.build();
+ Company duplicateCompanyWithDifferentNames = companyBuilder.withName("Google").build();
+ ModelStubWithCompanyNotInFilteredCompanyList modelStub =
+ new ModelStubWithCompanyNotInFilteredCompanyList(validCompany);
+
+ assertFalse(validCompany.isSameCompany(duplicateCompanyWithDifferentNames));
+
+ CommandResult commandResult = null;
+ try {
+ commandResult = new AddCommand(duplicateCompanyWithDifferentNames).execute(modelStub);
+ } catch (CommandException e) {
+ fail("Execution of command should not throw CommandException.");
+ }
+
+ assertNotNull(commandResult);
+ assertEquals(String.format(AddCommand.MESSAGE_SUCCESS, Messages.getCompanyName(
+ duplicateCompanyWithDifferentNames)),
+ commandResult.getFeedbackToUser());
+ assertTrue(modelStub.getLastViewedCompany().equals(duplicateCompanyWithDifferentNames));
}
@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);
+ public void execute_successOnlyDifferentRoles_addsCompany() {
+ CompanyBuilder companyBuilder = new CompanyBuilder();
+ Company validCompany = companyBuilder.build();
+ Company duplicateCompanyWithDifferentRole = companyBuilder.withRole("Chief Designer").build();
+ ModelStubWithCompanyNotInFilteredCompanyList modelStub =
+ new ModelStubWithCompanyNotInFilteredCompanyList(validCompany);
+
+ assertFalse(validCompany.isSameCompany(duplicateCompanyWithDifferentRole));
+
+ CommandResult commandResult = null;
+ try {
+ commandResult = new AddCommand(duplicateCompanyWithDifferentRole).execute(modelStub);
+ } catch (CommandException e) {
+ fail("Execution of command should not throw CommandException.");
+ }
- // same object -> returns true
- assertTrue(addAliceCommand.equals(addAliceCommand));
+ assertNotNull(commandResult);
+ assertEquals(String.format(AddCommand.MESSAGE_SUCCESS, Messages.getCompanyName(
+ duplicateCompanyWithDifferentRole)),
+ commandResult.getFeedbackToUser());
+ assertTrue(modelStub.getLastViewedCompany().equals(duplicateCompanyWithDifferentRole));
+ }
- // same values -> returns true
- AddCommand addAliceCommandCopy = new AddCommand(alice);
- assertTrue(addAliceCommand.equals(addAliceCommandCopy));
+ @Test
+ public void execute_onlySameCompanyAndSameRole_throwsCommandException() {
+ CompanyBuilder companyBuilder = new CompanyBuilder();
+ Company validCompany = companyBuilder.build();
+ Company duplicateCompany = companyBuilder
+ .withEmail("hello@gmail.com")
+ .withPhone("89004789")
+ .withPriority("HIGH")
+ .withRecruiterName("Cameron")
+ .withStatus("PA")
+ .build();
+
+ assert duplicateCompany.isSameCompany(validCompany);
+ AddCommand addCommand = new AddCommand(duplicateCompany);
+ ModelStub modelStub = new ModelStubWithCompanyNotInFilteredCompanyList(validCompany);
+
+ //assumes the caller of listAllChangedFields() is correct
+ assertThrows(CommandException.DuplicateException.class,
+ new CommandException.DuplicateException(
+ Messages.getErrorMessageForDuplicateCompanyAddCommand(validCompany,
+ modelStub.getDuplicateIndexFromOriginalAddressbook(validCompany),
+ duplicateCompany.listAllChangedFields(
+ modelStub.getDuplicateCompany(duplicateCompany)),
+ false)).getMessage(), (
+ ) -> addCommand.execute(modelStub));
+ }
- // different types -> returns false
- assertFalse(addAliceCommand.equals(1));
+ @Test
+ public void execute_successOnlySameRole() {
+ CompanyBuilder companyBuilder = new CompanyBuilder();
+ Company validCompany = companyBuilder.build();
+ Company duplicateCompanyWithSameRole = companyBuilder
+ .withEmail("hello@gmail.com")
+ .withPhone("89004789")
+ .withDeadline("12-10-2015")
+ .withPriority("LOW")
+ .withRecruiterName("Cameron")
+ .withStatus("PA")
+ .withName("Google")
+ .build();
+
+ ModelStubWithCompanyNotInFilteredCompanyList modelStub =
+ new ModelStubWithCompanyNotInFilteredCompanyList(validCompany);
+
+ CommandResult commandResult = null;
+ try {
+ commandResult = new AddCommand(duplicateCompanyWithSameRole).execute(modelStub);
+ } catch (CommandException e) {
+ fail("Execution of command should not throw CommandException.");
+ }
- // null -> returns false
- assertFalse(addAliceCommand.equals(null));
+ assertNotNull(commandResult);
+ assertEquals(String.format(AddCommand.MESSAGE_SUCCESS, Messages.getCompanyName(
+ duplicateCompanyWithSameRole)),
+ commandResult.getFeedbackToUser());
+ assertTrue(modelStub.getLastViewedCompany().equals(duplicateCompanyWithSameRole));
+ }
+
+ @Test
+ public void execute_successOnlySameCompany() {
+ CompanyBuilder companyBuilder = new CompanyBuilder();
+ Company validCompany = companyBuilder.build();
+ Company duplicateCompanyWithSameCompany = companyBuilder
+ .withEmail("hello@gmail.com")
+ .withPhone("89004789")
+ .withDeadline("12-10-2015")
+ .withPriority("LOW")
+ .withRecruiterName("Cameron")
+ .withStatus("PA")
+ .withRole("UI UX Designer")
+ .build();
+
+ ModelStubWithCompanyNotInFilteredCompanyList modelStub =
+ new ModelStubWithCompanyNotInFilteredCompanyList(validCompany);
+
+ CommandResult commandResult = null;
+ try {
+ commandResult = new AddCommand(duplicateCompanyWithSameCompany).execute(modelStub);
+ } catch (CommandException e) {
+ fail("Execution of command should not throw CommandException.");
+ }
- // different person -> returns false
- assertFalse(addAliceCommand.equals(addBobCommand));
+ assertNotNull(commandResult);
+ assertEquals(String.format(AddCommand.MESSAGE_SUCCESS, Messages.getCompanyName(
+ duplicateCompanyWithSameCompany)),
+ commandResult.getFeedbackToUser());
+ assertTrue(modelStub.getLastViewedCompany().equals(duplicateCompanyWithSameCompany));
}
+ //More than one company present in the address book
@Test
- public void toStringMethod() {
- AddCommand addCommand = new AddCommand(ALICE);
- String expected = AddCommand.class.getCanonicalName() + "{toAdd=" + ALICE + "}";
- assertEquals(expected, addCommand.toString());
+ public void execute_successOneFullyDuplicatedCompanyInList_throwsCommandException() {
+ Company validCompany = new CompanyBuilder().build();
+ AddCommand addCommand = new AddCommand(validCompany);
+ ModelStub modelStub = new ModelStubWithCompanyNotInFilteredCompanyList(validCompany, 1);
+
+ assertThrows(CommandException.DuplicateException.class,
+ new CommandException.DuplicateException(
+ Messages.getErrorMessageForDuplicateCompanyAddCommand(validCompany,
+ modelStub.getDuplicateIndexFromOriginalAddressbook(validCompany),
+ validCompany.listAllChangedFields(
+ modelStub.getDuplicateCompany(validCompany)),
+ false)).getMessage(), (
+ ) -> addCommand.execute(modelStub));
}
- /**
- * 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.");
+ @Test
+ public void execute_successTwoDifferentCompanyName_doesNotThrowCommandException() {
+ CompanyBuilder companyBuilder = new CompanyBuilder();
+ Company validCompany = companyBuilder.build();
+ Company duplicateCompanyWithDifferentNames = companyBuilder.withName("Google").build();
+ ModelStubWithCompanyNotInFilteredCompanyList modelStub =
+ new ModelStubWithCompanyNotInFilteredCompanyList(validCompany, 2);
+
+ assertFalse(validCompany.isSameCompany(duplicateCompanyWithDifferentNames));
+
+ CommandResult commandResult = null;
+ try {
+ commandResult = new AddCommand(duplicateCompanyWithDifferentNames).execute(modelStub);
+ } catch (CommandException e) {
+ fail("Execution of command should not throw CommandException.");
}
- @Override
- public ReadOnlyUserPrefs getUserPrefs() {
- throw new AssertionError("This method should not be called.");
- }
+ assertNotNull(commandResult);
+ assertEquals(String.format(AddCommand.MESSAGE_SUCCESS, Messages.getCompanyName(
+ duplicateCompanyWithDifferentNames)),
+ commandResult.getFeedbackToUser());
+ assertTrue(modelStub.getLastViewedCompany().equals(duplicateCompanyWithDifferentNames));
+ }
- @Override
- public GuiSettings getGuiSettings() {
- throw new AssertionError("This method should not be called.");
+ @Test
+ public void execute_successOnlyDifferentRolesWithThreeCompanies_addsCompany() {
+ CompanyBuilder companyBuilder = new CompanyBuilder();
+ Company validCompany = companyBuilder.build();
+ Company duplicateCompanyWithDifferentRole = companyBuilder.withRole("Chief Designer").build();
+ ModelStubWithCompanyNotInFilteredCompanyList modelStub =
+ new ModelStubWithCompanyNotInFilteredCompanyList(validCompany, 3);
+
+ assertFalse(validCompany.isSameCompany(duplicateCompanyWithDifferentRole));
+
+ CommandResult commandResult = null;
+ try {
+ commandResult = new AddCommand(duplicateCompanyWithDifferentRole).execute(modelStub);
+ } catch (CommandException e) {
+ fail("Execution of command should not throw CommandException.");
}
- @Override
- public void setGuiSettings(GuiSettings guiSettings) {
- throw new AssertionError("This method should not be called.");
- }
+ assertNotNull(commandResult);
+ assertEquals(String.format(AddCommand.MESSAGE_SUCCESS, Messages.getCompanyName(
+ duplicateCompanyWithDifferentRole)),
+ commandResult.getFeedbackToUser());
+ assertTrue(modelStub.getLastViewedCompany().equals(duplicateCompanyWithDifferentRole));
+ }
- @Override
- public Path getAddressBookFilePath() {
- throw new AssertionError("This method should not be called.");
- }
+ @Test
+ public void execute_onlySameCompanyAndSameRoleWithOneCompany_throwsCommandException() {
+ CompanyBuilder companyBuilder = new CompanyBuilder();
+ Company validCompany = companyBuilder.build();
+ Company duplicateCompany = companyBuilder
+ .withEmail("hello@gmail.com")
+ .withPhone("89004789")
+ .withPriority("HIGH")
+ .withRecruiterName("Cameron")
+ .withStatus("PA")
+ .build();
+
+ assert duplicateCompany.isSameCompany(validCompany);
+ AddCommand addCommand = new AddCommand(duplicateCompany);
+ ModelStub modelStub = new ModelStubWithCompanyNotInFilteredCompanyList(validCompany, 1);
+
+ //assumes the caller of listAllChangedFields() is correct
+ assertThrows(CommandException.DuplicateException.class,
+ new CommandException.DuplicateException(
+ Messages.getErrorMessageForDuplicateCompanyAddCommand(validCompany,
+ modelStub.getDuplicateIndexFromOriginalAddressbook(validCompany),
+ duplicateCompany.listAllChangedFields(
+ modelStub.getDuplicateCompany(duplicateCompany)),
+ false)).getMessage(), (
+ ) -> addCommand.execute(modelStub));
+ }
- @Override
- public void setAddressBookFilePath(Path addressBookFilePath) {
- throw new AssertionError("This method should not be called.");
+ @Test
+ public void execute_successOnlySameRoleWithTwoCompanies() {
+ CompanyBuilder companyBuilder = new CompanyBuilder();
+ Company validCompany = companyBuilder.build();
+ Company duplicateCompanyWithSameRole = companyBuilder
+ .withEmail("hello@gmail.com")
+ .withPhone("89004789")
+ .withDeadline("12-10-2015")
+ .withPriority("LOW")
+ .withRecruiterName("Cameron")
+ .withStatus("PA")
+ .withName("Google")
+ .build();
+
+ ModelStubWithCompanyNotInFilteredCompanyList modelStub =
+ new ModelStubWithCompanyNotInFilteredCompanyList(validCompany, 2);
+
+ CommandResult commandResult = null;
+ try {
+ commandResult = new AddCommand(duplicateCompanyWithSameRole).execute(modelStub);
+ } catch (CommandException e) {
+ fail("Execution of command should not throw CommandException.");
}
- @Override
- public void addPerson(Person person) {
- throw new AssertionError("This method should not be called.");
- }
+ assertNotNull(commandResult);
+ assertEquals(String.format(AddCommand.MESSAGE_SUCCESS, Messages.getCompanyName(
+ duplicateCompanyWithSameRole)),
+ commandResult.getFeedbackToUser());
+ assertTrue(modelStub.getLastViewedCompany().equals(duplicateCompanyWithSameRole));
+ }
- @Override
- public void setAddressBook(ReadOnlyAddressBook newData) {
- throw new AssertionError("This method should not be called.");
+ @Test
+ public void execute_successOnlySameCompanyWithThreeCompanies() {
+ CompanyBuilder companyBuilder = new CompanyBuilder();
+ Company validCompany = companyBuilder.build();
+ Company duplicateCompanyWithSameCompany = companyBuilder
+ .withEmail("hello@gmail.com")
+ .withPhone("89004789")
+ .withDeadline("12-10-2015")
+ .withPriority("LOW")
+ .withRecruiterName("Cameron")
+ .withStatus("PA")
+ .withRole("UI UX Designer")
+ .build();
+
+ ModelStubWithCompanyNotInFilteredCompanyList modelStub =
+ new ModelStubWithCompanyNotInFilteredCompanyList(validCompany, 3);
+
+ CommandResult commandResult = null;
+ try {
+ commandResult = new AddCommand(duplicateCompanyWithSameCompany).execute(modelStub);
+ } catch (CommandException e) {
+ fail("Execution of command should not throw CommandException.");
}
- @Override
- public ReadOnlyAddressBook getAddressBook() {
- throw new AssertionError("This method should not be called.");
- }
+ assertNotNull(commandResult);
+ assertEquals(String.format(AddCommand.MESSAGE_SUCCESS, Messages.getCompanyName(
+ duplicateCompanyWithSameCompany)),
+ commandResult.getFeedbackToUser());
+ assertTrue(modelStub.getLastViewedCompany().equals(duplicateCompanyWithSameCompany));
+ }
- @Override
- public boolean hasPerson(Person person) {
- throw new AssertionError("This method should not be called.");
- }
+ //Duplicate tests - with duplicate in filtered company view
+ @Test
+ public void execute_fullyDuplicatedCompanyFiltered_throwsCommandException() {
+ Company validCompany = new CompanyBuilder().build();
+ AddCommand addCommand = new AddCommand(validCompany);
+ ModelStub modelStub = new ModelStubWithCompanyInFilteredCompanyList(validCompany);
+
+ assertThrows(CommandException.DuplicateException.class,
+ new CommandException.DuplicateException(
+ Messages.getErrorMessageForDuplicateCompanyAddCommand(validCompany,
+ modelStub.getDuplicateIndexFromOriginalAddressbook(validCompany),
+ validCompany.listAllChangedFields(
+ modelStub.getDuplicateCompany(validCompany)),
+ true)).getMessage(), (
+ ) -> addCommand.execute(modelStub));
+ }
- @Override
- public void deletePerson(Person target) {
- throw new AssertionError("This method should not be called.");
+ @Test
+ public void execute_successDifferentCompanyNameFiltered_doesNotThrowCommandException() {
+ CompanyBuilder companyBuilder = new CompanyBuilder();
+ Company validCompany = companyBuilder.build();
+ Company duplicateCompanyWithDifferentNames = companyBuilder.withName("Google").build();
+ ModelStubWithCompanyInFilteredCompanyList modelStub =
+ new ModelStubWithCompanyInFilteredCompanyList(validCompany);
+
+ assertFalse(validCompany.isSameCompany(duplicateCompanyWithDifferentNames));
+
+ CommandResult commandResult = null;
+ try {
+ commandResult = new AddCommand(duplicateCompanyWithDifferentNames).execute(modelStub);
+ } catch (CommandException e) {
+ fail("Execution of command should not throw CommandException.");
}
- @Override
- public void setPerson(Person target, Person editedPerson) {
- throw new AssertionError("This method should not be called.");
- }
+ assertNotNull(commandResult);
+ assertEquals(String.format(AddCommand.MESSAGE_SUCCESS, Messages.getCompanyName(
+ duplicateCompanyWithDifferentNames)),
+ commandResult.getFeedbackToUser());
+ assertTrue(modelStub.getLastViewedCompany().equals(duplicateCompanyWithDifferentNames));
+ }
- @Override
- public ObservableList getFilteredPersonList() {
- throw new AssertionError("This method should not be called.");
+ @Test
+ public void execute_successOnlyDifferentRolesFiltered_addsCompany() {
+ CompanyBuilder companyBuilder = new CompanyBuilder();
+ Company validCompany = companyBuilder.build();
+ Company duplicateCompanyWithDifferentRole = companyBuilder.withRole("Chief Designer").build();
+ ModelStubWithCompanyInFilteredCompanyList modelStub =
+ new ModelStubWithCompanyInFilteredCompanyList(validCompany);
+
+ assertFalse(validCompany.isSameCompany(duplicateCompanyWithDifferentRole));
+
+ CommandResult commandResult = null;
+ try {
+ commandResult = new AddCommand(duplicateCompanyWithDifferentRole).execute(modelStub);
+ } catch (CommandException e) {
+ fail("Execution of command should not throw CommandException.");
}
- @Override
- public void updateFilteredPersonList(Predicate predicate) {
- throw new AssertionError("This method should not be called.");
- }
+ assertNotNull(commandResult);
+ assertEquals(String.format(AddCommand.MESSAGE_SUCCESS, Messages.getCompanyName(
+ duplicateCompanyWithDifferentRole)),
+ commandResult.getFeedbackToUser());
+ assertTrue(modelStub.getLastViewedCompany().equals(duplicateCompanyWithDifferentRole));
}
- /**
- * A Model stub that contains a single person.
- */
- private class ModelStubWithPerson extends ModelStub {
- private final Person person;
+ @Test
+ public void execute_onlySameCompanyAndSameRoleFiltered_throwsCommandException() {
+ CompanyBuilder companyBuilder = new CompanyBuilder();
+ Company validCompany = companyBuilder.build();
+ Company duplicateCompany = companyBuilder
+ .withEmail("hello@gmail.com")
+ .withPhone("89004789")
+ .withPriority("HIGH")
+ .withRecruiterName("Cameron")
+ .withStatus("PA")
+ .build();
+
+ assert duplicateCompany.isSameCompany(validCompany);
+ AddCommand addCommand = new AddCommand(duplicateCompany);
+ ModelStub modelStub = new ModelStubWithCompanyInFilteredCompanyList(validCompany);
+
+ assertThrows(CommandException.DuplicateException.class,
+ new CommandException.DuplicateException(
+ Messages.getErrorMessageForDuplicateCompanyAddCommand(validCompany,
+ modelStub.getDuplicateIndexFromOriginalAddressbook(validCompany),
+ duplicateCompany.listAllChangedFields(
+ modelStub.getDuplicateCompany(duplicateCompany)),
+ true)).getMessage(), (
+ ) -> addCommand.execute(modelStub));
+ }
- ModelStubWithPerson(Person person) {
- requireNonNull(person);
- this.person = person;
+ @Test
+ public void execute_successOnlySameRoleFiltered() {
+ CompanyBuilder companyBuilder = new CompanyBuilder();
+ Company validCompany = companyBuilder.build();
+ Company duplicateCompanyWithSameRole = companyBuilder
+ .withEmail("hello@gmail.com")
+ .withPhone("89004789")
+ .withDeadline("12-10-2015")
+ .withPriority("LOW")
+ .withRecruiterName("Cameron")
+ .withStatus("PA")
+ .withName("Google")
+ .build();
+
+ ModelStubWithCompanyInFilteredCompanyList modelStub =
+ new ModelStubWithCompanyInFilteredCompanyList(validCompany);
+
+ CommandResult commandResult = null;
+ try {
+ commandResult = new AddCommand(duplicateCompanyWithSameRole).execute(modelStub);
+ } catch (CommandException e) {
+ fail("Execution of command should not throw CommandException.");
}
- @Override
- public boolean hasPerson(Person person) {
- requireNonNull(person);
- return this.person.isSamePerson(person);
+ assertNotNull(commandResult);
+ assertEquals(String.format(AddCommand.MESSAGE_SUCCESS, Messages.getCompanyName(
+ duplicateCompanyWithSameRole)),
+ commandResult.getFeedbackToUser());
+ assertTrue(modelStub.getLastViewedCompany().equals(duplicateCompanyWithSameRole));
+ }
+
+ @Test
+ public void execute_successOnlySameCompanyFiltered() {
+ CompanyBuilder companyBuilder = new CompanyBuilder();
+ Company validCompany = companyBuilder.build();
+ Company duplicateCompanyWithSameCompany = companyBuilder
+ .withEmail("hello@gmail.com")
+ .withPhone("89004789")
+ .withDeadline("12-10-2015")
+ .withPriority("LOW")
+ .withRecruiterName("Cameron")
+ .withStatus("PA")
+ .withRole("UI UX Designer")
+ .build();
+
+ ModelStubWithCompanyInFilteredCompanyList modelStub =
+ new ModelStubWithCompanyInFilteredCompanyList(validCompany);
+
+ CommandResult commandResult = null;
+ try {
+ commandResult = new AddCommand(duplicateCompanyWithSameCompany).execute(modelStub);
+ } catch (CommandException e) {
+ fail("Execution of command should not throw CommandException.");
}
+
+ assertNotNull(commandResult);
+ assertEquals(String.format(AddCommand.MESSAGE_SUCCESS, Messages.getCompanyName(
+ duplicateCompanyWithSameCompany)),
+ commandResult.getFeedbackToUser());
+ assertTrue(modelStub.getLastViewedCompany().equals(duplicateCompanyWithSameCompany));
}
- /**
- * 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);
- }
+ @Test
+ public void equals() {
+ Company meta = new CompanyBuilder().withName("Meta").build();
+ Company tiktok = new CompanyBuilder().withName("Tiktok").build();
+ AddCommand addMetaCommand = new AddCommand(meta);
+ AddCommand addTiktokCommand = new AddCommand(tiktok);
- @Override
- public void addPerson(Person person) {
- requireNonNull(person);
- personsAdded.add(person);
- }
+ // same object -> returns true
+ assertTrue(addMetaCommand.equals(addMetaCommand));
- @Override
- public ReadOnlyAddressBook getAddressBook() {
- return new AddressBook();
- }
+ // same values -> returns true
+ AddCommand addMetaCommandCopy = new AddCommand(meta);
+ assertTrue(addMetaCommand.equals(addMetaCommandCopy));
+
+ // different types -> returns false
+ assertFalse(addMetaCommand.equals(1));
+
+ // null -> returns false
+ assertFalse(addMetaCommand.equals(null));
+
+ // different company -> returns false
+ assertFalse(addMetaCommand.equals(addTiktokCommand));
}
+ @Test
+ public void toStringMethod() {
+ AddCommand addCommand = new AddCommand(META);
+ String expected = AddCommand.class.getCanonicalName() + "{toAdd=" + META + "}";
+ assertEquals(expected, addCommand.toString());
+ }
}
diff --git a/src/test/java/seedu/address/logic/commands/ClearCommandTest.java b/src/test/java/seedu/address/logic/commands/ClearCommandTest.java
index 80d9110c03a..dd1e368faf9 100644
--- a/src/test/java/seedu/address/logic/commands/ClearCommandTest.java
+++ b/src/test/java/seedu/address/logic/commands/ClearCommandTest.java
@@ -1,7 +1,7 @@
package seedu.address.logic.commands;
import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
-import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;
+import static seedu.address.testutil.TypicalCompanies.getTypicalAddressBook;
import org.junit.jupiter.api.Test;
diff --git a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java b/src/test/java/seedu/address/logic/commands/CommandTestUtil.java
index 643a1d08069..90bc2bb6f78 100644
--- a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java
+++ b/src/test/java/seedu/address/logic/commands/CommandTestUtil.java
@@ -2,11 +2,15 @@
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_COMPANY_NAME;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_DEADLINE;
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.logic.parser.CliSyntax.PREFIX_PRIORITY;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_RECRUITER_NAME;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_REMARK;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_ROLE;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_STATUS;
import static seedu.address.testutil.Assert.assertThrows;
import java.util.ArrayList;
@@ -17,56 +21,76 @@
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;
+import seedu.address.model.company.Company;
+import seedu.address.model.company.predicates.NameContainsKeywordsPredicate;
+import seedu.address.testutil.EditCompanyDescriptorBuilder;
/**
* 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 VALID_NAME_GOOGLE = "Google";
+ public static final String VALID_NAME_TIKTOK = "Tiktok";
+ public static final String VALID_PHONE_GOOGLE = "11111111";
+ public static final String VALID_PHONE_TIKTOK = "22222222";
+ public static final String VALID_EMAIL_GOOGLE = "amy@example.com";
+ public static final String VALID_EMAIL_TIKTOK = "bob@example.com";
+ public static final String VALID_ROLE_GOOGLE = "Software Engineer";
+ public static final String VALID_ROLE_TIKTOK = "Data Scientist";
+ public static final String VALID_DEADLINE_GOOGLE = "10-10-2023";
+ public static final String VALID_DEADLINE_TIKTOK = "11-11-2023";
+ public static final String VALID_STATUS_GOOGLE = "PA";
+ public static final String VALID_STATUS_TIKTOK = "PI";
+ public static final String VALID_RECRUITER_NAME_GOOGLE = "John Doe";
+ public static final String VALID_RECRUITER_NAME_TIKTOK = "Timmy Tan";
+ public static final String VALID_PRIORITY_GOOGLE = "HIGH";
+ public static final String VALID_PRIORITY_TIKTOK = "LOW";
+ public static final String VALID_REMARK_GOOGLE = "Java/Python";
+ public static final String VALID_REMARK_TIKTOK = "NO REMARKS";
+
+ public static final String NAME_DESC_GOOGLE = " " + PREFIX_COMPANY_NAME + VALID_NAME_GOOGLE;
+ public static final String NAME_DESC_TIKTOK = " " + PREFIX_COMPANY_NAME + VALID_NAME_TIKTOK;
+ public static final String PHONE_DESC_GOOGLE = " " + PREFIX_PHONE + VALID_PHONE_GOOGLE;
+ public static final String PHONE_DESC_TIKTOK = " " + PREFIX_PHONE + VALID_PHONE_TIKTOK;
+ public static final String EMAIL_DESC_GOOGLE = " " + PREFIX_EMAIL + VALID_EMAIL_GOOGLE;
+ public static final String EMAIL_DESC_TIKTOK = " " + PREFIX_EMAIL + VALID_EMAIL_TIKTOK;
+ public static final String ROLE_DESC_GOOGLE = " " + PREFIX_ROLE + VALID_ROLE_GOOGLE;
+ public static final String ROLE_DESC_TIKTOK = " " + PREFIX_ROLE + VALID_ROLE_TIKTOK;
+ public static final String DEADLINE_DESC_GOOGLE = " " + PREFIX_DEADLINE + VALID_DEADLINE_GOOGLE;
+ public static final String DEADLINE_DESC_TIKTOK = " " + PREFIX_DEADLINE + VALID_DEADLINE_TIKTOK;
+ public static final String STATUS_DESC_GOOGLE = " " + PREFIX_STATUS + VALID_STATUS_GOOGLE;
+ public static final String STATUS_DESC_TIKTOK = " " + PREFIX_STATUS + VALID_STATUS_TIKTOK;
+ public static final String RECRUITER_NAME_DESC_GOOGLE = " " + PREFIX_RECRUITER_NAME + VALID_RECRUITER_NAME_GOOGLE;
+ public static final String RECRUITER_NAME_DESC_TIKTOK = " " + PREFIX_RECRUITER_NAME + VALID_RECRUITER_NAME_TIKTOK;
+ public static final String PRIORITY_DESC_GOOGLE = " " + PREFIX_PRIORITY + VALID_PRIORITY_GOOGLE;
+ public static final String PRIORITY_DESC_TIKTOK = " " + PREFIX_PRIORITY + VALID_PRIORITY_TIKTOK;
+ public static final String REMARK_DESC_GOOGLE = " " + PREFIX_REMARK + VALID_REMARK_GOOGLE;
+ public static final String REMARK_DESC_TIKTOK = " " + PREFIX_REMARK + VALID_REMARK_TIKTOK;
+ public static final String INVALID_NAME_DESC = " " + PREFIX_COMPANY_NAME + "Google&"; // '&' 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 INVALID_ROLE_DESC = " " + PREFIX_ROLE + "Software*"; // '*' not allowed in roles
+ public static final String INVALID_DEADLINE_DESC = " " + PREFIX_DEADLINE + "10-10-20223"; // yyyy format
+ public static final String INVALID_STATUS_DESC = " " + PREFIX_STATUS + "L"; // invalid status
+ public static final String INVALID_RECRUITER_NAME_DESC =
+ " " + PREFIX_RECRUITER_NAME + "Google&"; // '&' not allowed in names
+
+ public static final String INVALID_PRIORITY_DESC = " " + PREFIX_PRIORITY + "HIGHH"; // invalid priority
+ public static final String INVALID_REMARK_DESC = " " + PREFIX_REMARK + " "; // invalid remark
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;
+ public static final EditCommand.EditCompanyDescriptor DESC_GOOGLE;
+ public static final EditCommand.EditCompanyDescriptor DESC_TIKTOK;
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();
+ DESC_GOOGLE = new EditCompanyDescriptorBuilder().withName(VALID_NAME_GOOGLE)
+ .withPhone(VALID_PHONE_GOOGLE).withEmail(VALID_EMAIL_GOOGLE).withPriority(VALID_PRIORITY_GOOGLE)
+ .build();
+ DESC_TIKTOK = new EditCompanyDescriptorBuilder().withName(VALID_NAME_TIKTOK)
+ .withPhone(VALID_PHONE_TIKTOK).withEmail(VALID_EMAIL_TIKTOK).withPriority(VALID_PRIORITY_TIKTOK)
+ .build();
}
/**
@@ -99,30 +123,30 @@ public static void assertCommandSuccess(Command command, Model actualModel, Stri
* 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
+ * - the address book, filtered company list and selected company 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());
+ List expectedFilteredList = new ArrayList<>(actualModel.getFilteredCompanyList());
assertThrows(CommandException.class, expectedMessage, () -> command.execute(actualModel));
assertEquals(expectedAddressBook, actualModel.getAddressBook());
- assertEquals(expectedFilteredList, actualModel.getFilteredPersonList());
+ assertEquals(expectedFilteredList, actualModel.getFilteredCompanyList());
}
/**
- * Updates {@code model}'s filtered list to show only the person at the given {@code targetIndex} in the
+ * Updates {@code model}'s filtered list to show only the company 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());
+ public static void showCompanyAtIndex(Model model, Index targetIndex) {
+ assertTrue(targetIndex.getZeroBased() < model.getFilteredCompanyList().size());
- Person person = model.getFilteredPersonList().get(targetIndex.getZeroBased());
- final String[] splitName = person.getName().fullName.split("\\s+");
- model.updateFilteredPersonList(new NameContainsKeywordsPredicate(Arrays.asList(splitName[0])));
+ Company company = model.getFilteredCompanyList().get(targetIndex.getZeroBased());
+ final String[] splitName = company.getName().fullName.split("\\s+");
+ model.updateFilteredCompanyList(new NameContainsKeywordsPredicate(Arrays.asList(splitName[0])));
- assertEquals(1, model.getFilteredPersonList().size());
+ assertEquals(1, model.getFilteredCompanyList().size());
}
}
diff --git a/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java b/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java
index b6f332eabca..e9c9fcfda71 100644
--- a/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java
+++ b/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java
@@ -5,10 +5,10 @@
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 static seedu.address.logic.commands.CommandTestUtil.showCompanyAtIndex;
+import static seedu.address.testutil.TypicalCompanies.getTypicalAddressBook;
+import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_COMPANY;
+import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_COMPANY;
import org.junit.jupiter.api.Test;
@@ -17,7 +17,7 @@
import seedu.address.model.Model;
import seedu.address.model.ModelManager;
import seedu.address.model.UserPrefs;
-import seedu.address.model.person.Person;
+import seedu.address.model.company.Company;
/**
* Contains integration tests (interaction with the Model) and unit tests for
@@ -29,66 +29,66 @@ public class DeleteCommandTest {
@Test
public void execute_validIndexUnfilteredList_success() {
- Person personToDelete = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased());
- DeleteCommand deleteCommand = new DeleteCommand(INDEX_FIRST_PERSON);
+ Company companyToDelete = model.getFilteredCompanyList().get(INDEX_FIRST_COMPANY.getZeroBased());
+ DeleteCommand deleteCommand = new DeleteCommand(INDEX_FIRST_COMPANY);
- String expectedMessage = String.format(DeleteCommand.MESSAGE_DELETE_PERSON_SUCCESS,
- Messages.format(personToDelete));
+ String expectedMessage = String.format(DeleteCommand.MESSAGE_DELETE_COMPANY_SUCCESS,
+ Messages.getCompanyInfo(companyToDelete));
ModelManager expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs());
- expectedModel.deletePerson(personToDelete);
+ expectedModel.deleteCompany(companyToDelete);
assertCommandSuccess(deleteCommand, model, expectedMessage, expectedModel);
}
@Test
public void execute_invalidIndexUnfilteredList_throwsCommandException() {
- Index outOfBoundIndex = Index.fromOneBased(model.getFilteredPersonList().size() + 1);
+ Index outOfBoundIndex = Index.fromOneBased(model.getFilteredCompanyList().size() + 1);
DeleteCommand deleteCommand = new DeleteCommand(outOfBoundIndex);
- assertCommandFailure(deleteCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
+ assertCommandFailure(deleteCommand, model, Messages.MESSAGE_INVALID_COMPANY_DISPLAYED_INDEX);
}
@Test
public void execute_validIndexFilteredList_success() {
- showPersonAtIndex(model, INDEX_FIRST_PERSON);
+ showCompanyAtIndex(model, INDEX_FIRST_COMPANY);
- Person personToDelete = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased());
- DeleteCommand deleteCommand = new DeleteCommand(INDEX_FIRST_PERSON);
+ Company companyToDelete = model.getFilteredCompanyList().get(INDEX_FIRST_COMPANY.getZeroBased());
+ DeleteCommand deleteCommand = new DeleteCommand(INDEX_FIRST_COMPANY);
- String expectedMessage = String.format(DeleteCommand.MESSAGE_DELETE_PERSON_SUCCESS,
- Messages.format(personToDelete));
+ String expectedMessage = String.format(DeleteCommand.MESSAGE_DELETE_COMPANY_SUCCESS,
+ Messages.getCompanyInfo(companyToDelete));
Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs());
- expectedModel.deletePerson(personToDelete);
- showNoPerson(expectedModel);
+ expectedModel.deleteCompany(companyToDelete);
+ showNoCompany(expectedModel);
assertCommandSuccess(deleteCommand, model, expectedMessage, expectedModel);
}
@Test
public void execute_invalidIndexFilteredList_throwsCommandException() {
- showPersonAtIndex(model, INDEX_FIRST_PERSON);
+ showCompanyAtIndex(model, INDEX_FIRST_COMPANY);
- Index outOfBoundIndex = INDEX_SECOND_PERSON;
+ Index outOfBoundIndex = INDEX_SECOND_COMPANY;
// ensures that outOfBoundIndex is still in bounds of address book list
- assertTrue(outOfBoundIndex.getZeroBased() < model.getAddressBook().getPersonList().size());
+ assertTrue(outOfBoundIndex.getZeroBased() < model.getAddressBook().getCompanyList().size());
DeleteCommand deleteCommand = new DeleteCommand(outOfBoundIndex);
- assertCommandFailure(deleteCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
+ assertCommandFailure(deleteCommand, model, Messages.MESSAGE_INVALID_COMPANY_DISPLAYED_INDEX);
}
@Test
public void equals() {
- DeleteCommand deleteFirstCommand = new DeleteCommand(INDEX_FIRST_PERSON);
- DeleteCommand deleteSecondCommand = new DeleteCommand(INDEX_SECOND_PERSON);
+ DeleteCommand deleteFirstCommand = new DeleteCommand(INDEX_FIRST_COMPANY);
+ DeleteCommand deleteSecondCommand = new DeleteCommand(INDEX_SECOND_COMPANY);
// same object -> returns true
assertTrue(deleteFirstCommand.equals(deleteFirstCommand));
// same values -> returns true
- DeleteCommand deleteFirstCommandCopy = new DeleteCommand(INDEX_FIRST_PERSON);
+ DeleteCommand deleteFirstCommandCopy = new DeleteCommand(INDEX_FIRST_COMPANY);
assertTrue(deleteFirstCommand.equals(deleteFirstCommandCopy));
// different types -> returns false
@@ -97,7 +97,7 @@ public void equals() {
// null -> returns false
assertFalse(deleteFirstCommand.equals(null));
- // different person -> returns false
+ // different company -> returns false
assertFalse(deleteFirstCommand.equals(deleteSecondCommand));
}
@@ -112,9 +112,9 @@ public void toStringMethod() {
/**
* Updates {@code model}'s filtered list to show no one.
*/
- private void showNoPerson(Model model) {
- model.updateFilteredPersonList(p -> false);
+ private void showNoCompany(Model model) {
+ model.updateFilteredCompanyList(p -> false);
- assertTrue(model.getFilteredPersonList().isEmpty());
+ assertTrue(model.getFilteredCompanyList().isEmpty());
}
}
diff --git a/src/test/java/seedu/address/logic/commands/EditCommandTest.java b/src/test/java/seedu/address/logic/commands/EditCommandTest.java
index 469dd97daa7..5c5cefa8146 100644
--- a/src/test/java/seedu/address/logic/commands/EditCommandTest.java
+++ b/src/test/java/seedu/address/logic/commands/EditCommandTest.java
@@ -3,30 +3,32 @@
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.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.DESC_GOOGLE;
+import static seedu.address.logic.commands.CommandTestUtil.DESC_TIKTOK;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_TIKTOK;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_TIKTOK;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_PRIORITY_TIKTOK;
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 static seedu.address.logic.commands.CommandTestUtil.showCompanyAtIndex;
+import static seedu.address.logic.commands.EditCommand.MESSAGE_EDIT_COMPANY_SUCCESS;
+import static seedu.address.testutil.TypicalCompanies.getTypicalAddressBook;
+import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_COMPANY;
+import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_COMPANY;
import org.junit.jupiter.api.Test;
import seedu.address.commons.core.index.Index;
import seedu.address.logic.Messages;
-import seedu.address.logic.commands.EditCommand.EditPersonDescriptor;
+import seedu.address.logic.commands.EditCommand.EditCompanyDescriptor;
+import seedu.address.logic.commands.exceptions.CommandException;
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;
+import seedu.address.model.company.Company;
+import seedu.address.testutil.CompanyBuilder;
+import seedu.address.testutil.EditCompanyDescriptorBuilder;
/**
* Contains integration tests (interaction with the Model) and unit tests for EditCommand.
@@ -36,46 +38,52 @@ 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);
+ public void execute_allFieldsSpecified_success() {
+ Company editedCompany = new CompanyBuilder().build();
+ EditCompanyDescriptor descriptor = new EditCompanyDescriptorBuilder(editedCompany).build();
+ EditCommand editCommand = new EditCommand(INDEX_FIRST_COMPANY, descriptor);
- String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, Messages.format(editedPerson));
+ String expectedMessage = String.format(MESSAGE_EDIT_COMPANY_SUCCESS,
+ Messages.getCompanyName(editedCompany));
Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs());
- expectedModel.setPerson(model.getFilteredPersonList().get(0), editedPerson);
+ expectedModel.setCompany(model.getFilteredCompanyList().get(0), editedCompany);
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());
+ public void execute_someFieldsSpecified_success() {
+ Index indexLastCompany = Index.fromOneBased(model.getFilteredCompanyList().size());
+ Company lastCompany = model.getFilteredCompanyList().get(indexLastCompany.getZeroBased());
- PersonBuilder personInList = new PersonBuilder(lastPerson);
- Person editedPerson = personInList.withName(VALID_NAME_BOB).withPhone(VALID_PHONE_BOB)
- .withTags(VALID_TAG_HUSBAND).build();
+ CompanyBuilder companyInList = new CompanyBuilder(lastCompany);
+ Company editedCompany = companyInList.withName(VALID_NAME_TIKTOK).withPhone(VALID_PHONE_TIKTOK)
+ .withPriority(VALID_PRIORITY_TIKTOK)
+ .build();
- EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withName(VALID_NAME_BOB)
- .withPhone(VALID_PHONE_BOB).withTags(VALID_TAG_HUSBAND).build();
- EditCommand editCommand = new EditCommand(indexLastPerson, descriptor);
+ EditCompanyDescriptor descriptor = new EditCompanyDescriptorBuilder().withName(VALID_NAME_TIKTOK)
+ .withPhone(VALID_PHONE_TIKTOK)
+ .withPriority(VALID_PRIORITY_TIKTOK)
+ .build();
+ EditCommand editCommand = new EditCommand(indexLastCompany, descriptor);
- String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, Messages.format(editedPerson));
+ String expectedMessage = String.format(MESSAGE_EDIT_COMPANY_SUCCESS,
+ Messages.getCompanyName(editedCompany));
Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs());
- expectedModel.setPerson(lastPerson, editedPerson);
+ expectedModel.setCompany(lastCompany, editedCompany);
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());
+ public void execute_noFieldSpecified_success() {
+ EditCommand editCommand = new EditCommand(INDEX_FIRST_COMPANY, new EditCompanyDescriptor());
+ Company editedCompany = model.getFilteredCompanyList().get(INDEX_FIRST_COMPANY.getZeroBased());
- String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, Messages.format(editedPerson));
+ String expectedMessage = String.format(MESSAGE_EDIT_COMPANY_SUCCESS,
+ Messages.getCompanyName(editedCompany));
Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs());
@@ -84,49 +92,120 @@ public void execute_noFieldSpecifiedUnfilteredList_success() {
@Test
public void execute_filteredList_success() {
- showPersonAtIndex(model, INDEX_FIRST_PERSON);
+ showCompanyAtIndex(model, INDEX_FIRST_COMPANY);
- 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());
+ Company companyInFilteredList = model.getFilteredCompanyList().get(INDEX_FIRST_COMPANY.getZeroBased());
+ Company editedCompany = new CompanyBuilder(companyInFilteredList).withName(VALID_NAME_TIKTOK).build();
+ EditCommand editCommand = new EditCommand(INDEX_FIRST_COMPANY,
+ new EditCompanyDescriptorBuilder().withName(VALID_NAME_TIKTOK).build());
- String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, Messages.format(editedPerson));
+ String expectedMessage = String.format(MESSAGE_EDIT_COMPANY_SUCCESS,
+ Messages.getCompanyName(editedCompany));
Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs());
- expectedModel.setPerson(model.getFilteredPersonList().get(0), editedPerson);
+ showCompanyAtIndex(expectedModel, INDEX_FIRST_COMPANY);
+ expectedModel.setCompany(model.getFilteredCompanyList().get(0), editedCompany);
assertCommandSuccess(editCommand, model, expectedMessage, expectedModel);
}
+ //Duplicate checks
@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);
+ public void execute_fullDuplicateCompany_failure() {
+ Company firstCompany = model.getFilteredCompanyList().get(INDEX_FIRST_COMPANY.getZeroBased());
+ EditCompanyDescriptor descriptor = new EditCompanyDescriptorBuilder(firstCompany).build();
+ EditCommand editCommand = new EditCommand(INDEX_SECOND_COMPANY, descriptor);
+
+ assertCommandFailure(editCommand,
+ model,
+ new CommandException.DuplicateException(
+ Messages.getDupErrMsgEdit(
+ firstCompany)).getMessage());
+ }
- assertCommandFailure(editCommand, model, EditCommand.MESSAGE_DUPLICATE_PERSON);
+ @Test
+ public void execute_duplicatedNameAndRoleAndDeadline_failure() {
+ Company firstCompany = model.getFilteredCompanyList().get(INDEX_FIRST_COMPANY.getZeroBased());
+ EditCompanyDescriptor descriptor = new EditCompanyDescriptorBuilder(firstCompany)
+ .withEmail("gy@gmail.com")
+ .withPhone("91234567")
+ .withPriority("LOW")
+ .withStatus("PA")
+ .withRecruiterName("Gerald Yeo")
+ .build();
+ EditCommand editCommand = new EditCommand(INDEX_SECOND_COMPANY, descriptor);
+
+ assertCommandFailure(editCommand,
+ model,
+ new CommandException.DuplicateException(
+ Messages.getDupErrMsgEdit(
+ firstCompany)).getMessage());
}
@Test
- public void execute_duplicatePersonFilteredList_failure() {
- showPersonAtIndex(model, INDEX_FIRST_PERSON);
+ public void execute_duplicatedRoleOnly_success() {
+ Company firstCompany = model.getFilteredCompanyList().get(INDEX_FIRST_COMPANY.getZeroBased());
+ EditCompanyDescriptor descriptor = new EditCompanyDescriptorBuilder(firstCompany)
+ .withEmail("gy@gmail.com")
+ .withPhone("91234567")
+ .withPriority("LOW")
+ .withStatus("PA")
+ .withDeadline("10-10-2021")
+ .withRecruiterName("Gerald Yeo")
+ .withName("Tiktok")
+ .build();
+ EditCommand editCommand = new EditCommand(INDEX_SECOND_COMPANY, descriptor);
+
+ assert descriptor.getName().isPresent();
+ assertCommandSuccess(editCommand,
+ model,
+ String.format(MESSAGE_EDIT_COMPANY_SUCCESS, descriptor.getName().get()), model);
+ }
- // 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());
+ @Test
+ public void execute_duplicatedNameOnly_success() {
+ Company firstCompany = model.getFilteredCompanyList().get(INDEX_FIRST_COMPANY.getZeroBased());
+ EditCompanyDescriptor descriptor = new EditCompanyDescriptorBuilder(firstCompany)
+ .withEmail("gy@gmail.com")
+ .withPhone("91234567")
+ .withPriority("LOW")
+ .withStatus("PA")
+ .withDeadline("10-10-2021")
+ .withRecruiterName("Gerald Yeo")
+ .withRole("UI UX Designer")
+ .build();
+ EditCommand editCommand = new EditCommand(INDEX_SECOND_COMPANY, descriptor);
+
+ assert descriptor.getName().isPresent();
+ assertCommandSuccess(editCommand,
+ model,
+ String.format(MESSAGE_EDIT_COMPANY_SUCCESS, descriptor.getName().get()),
+ model);
+ }
- assertCommandFailure(editCommand, model, EditCommand.MESSAGE_DUPLICATE_PERSON);
+ @Test
+ public void execute_duplicateCompany_failure() {
+ showCompanyAtIndex(model, INDEX_FIRST_COMPANY);
+
+ // edit company in filtered list into a duplicate in address book
+ Company companyInList = model.getAddressBook().getCompanyList().get(INDEX_SECOND_COMPANY.getZeroBased());
+ EditCommand editCommand = new EditCommand(INDEX_FIRST_COMPANY,
+ new EditCompanyDescriptorBuilder(companyInList).build());
+
+ assertCommandFailure(editCommand,
+ model,
+ new CommandException.DuplicateException(
+ Messages.getDupErrMsgEdit(
+ companyInList)).getMessage());
}
@Test
- public void execute_invalidPersonIndexUnfilteredList_failure() {
- Index outOfBoundIndex = Index.fromOneBased(model.getFilteredPersonList().size() + 1);
- EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withName(VALID_NAME_BOB).build();
+ public void execute_invalidCompanyIndexUnfilteredList_failure() {
+ Index outOfBoundIndex = Index.fromOneBased(model.getFilteredCompanyList().size() + 1);
+ EditCompanyDescriptor descriptor = new EditCompanyDescriptorBuilder().withName(VALID_NAME_TIKTOK).build();
EditCommand editCommand = new EditCommand(outOfBoundIndex, descriptor);
- assertCommandFailure(editCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
+ assertCommandFailure(editCommand, model, Messages.MESSAGE_INVALID_COMPANY_DISPLAYED_INDEX);
}
/**
@@ -134,25 +213,25 @@ public void execute_invalidPersonIndexUnfilteredList_failure() {
* but smaller than size of address book
*/
@Test
- public void execute_invalidPersonIndexFilteredList_failure() {
- showPersonAtIndex(model, INDEX_FIRST_PERSON);
- Index outOfBoundIndex = INDEX_SECOND_PERSON;
+ public void execute_invalidCompanyIndexFilteredList_failure() {
+ showCompanyAtIndex(model, INDEX_FIRST_COMPANY);
+ Index outOfBoundIndex = INDEX_SECOND_COMPANY;
// ensures that outOfBoundIndex is still in bounds of address book list
- assertTrue(outOfBoundIndex.getZeroBased() < model.getAddressBook().getPersonList().size());
+ assertTrue(outOfBoundIndex.getZeroBased() < model.getAddressBook().getCompanyList().size());
EditCommand editCommand = new EditCommand(outOfBoundIndex,
- new EditPersonDescriptorBuilder().withName(VALID_NAME_BOB).build());
+ new EditCompanyDescriptorBuilder().withName(VALID_NAME_TIKTOK).build());
- assertCommandFailure(editCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
+ assertCommandFailure(editCommand, model, Messages.MESSAGE_INVALID_COMPANY_DISPLAYED_INDEX);
}
@Test
public void equals() {
- final EditCommand standardCommand = new EditCommand(INDEX_FIRST_PERSON, DESC_AMY);
+ final EditCommand standardCommand = new EditCommand(INDEX_FIRST_COMPANY, DESC_GOOGLE);
// same values -> returns true
- EditPersonDescriptor copyDescriptor = new EditPersonDescriptor(DESC_AMY);
- EditCommand commandWithSameValues = new EditCommand(INDEX_FIRST_PERSON, copyDescriptor);
+ EditCompanyDescriptor copyDescriptor = new EditCompanyDescriptor(DESC_GOOGLE);
+ EditCommand commandWithSameValues = new EditCommand(INDEX_FIRST_COMPANY, copyDescriptor);
assertTrue(standardCommand.equals(commandWithSameValues));
// same object -> returns true
@@ -165,19 +244,19 @@ public void equals() {
assertFalse(standardCommand.equals(new ClearCommand()));
// different index -> returns false
- assertFalse(standardCommand.equals(new EditCommand(INDEX_SECOND_PERSON, DESC_AMY)));
+ assertFalse(standardCommand.equals(new EditCommand(INDEX_SECOND_COMPANY, DESC_GOOGLE)));
// different descriptor -> returns false
- assertFalse(standardCommand.equals(new EditCommand(INDEX_FIRST_PERSON, DESC_BOB)));
+ assertFalse(standardCommand.equals(new EditCommand(INDEX_FIRST_COMPANY, DESC_TIKTOK)));
}
@Test
public void toStringMethod() {
Index index = Index.fromOneBased(1);
- EditPersonDescriptor editPersonDescriptor = new EditPersonDescriptor();
- EditCommand editCommand = new EditCommand(index, editPersonDescriptor);
- String expected = EditCommand.class.getCanonicalName() + "{index=" + index + ", editPersonDescriptor="
- + editPersonDescriptor + "}";
+ EditCompanyDescriptor editCompanyDescriptor = new EditCompanyDescriptor();
+ EditCommand editCommand = new EditCommand(index, editCompanyDescriptor);
+ String expected = EditCommand.class.getCanonicalName() + "{index=" + index + ", editCompanyDescriptor="
+ + editCompanyDescriptor + "}";
assertEquals(expected, editCommand.toString());
}
diff --git a/src/test/java/seedu/address/logic/commands/EditCompanyDescriptorTest.java b/src/test/java/seedu/address/logic/commands/EditCompanyDescriptorTest.java
new file mode 100644
index 00000000000..f791e18a3d9
--- /dev/null
+++ b/src/test/java/seedu/address/logic/commands/EditCompanyDescriptorTest.java
@@ -0,0 +1,70 @@
+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.logic.commands.CommandTestUtil.DESC_GOOGLE;
+import static seedu.address.logic.commands.CommandTestUtil.DESC_TIKTOK;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_TIKTOK;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_TIKTOK;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_TIKTOK;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.address.logic.commands.EditCommand.EditCompanyDescriptor;
+import seedu.address.testutil.EditCompanyDescriptorBuilder;
+
+public class EditCompanyDescriptorTest {
+
+ @Test
+ public void equals() {
+ // same values -> returns true
+ EditCompanyDescriptor descriptorWithSameValues = new EditCompanyDescriptor(DESC_GOOGLE);
+ assertTrue(DESC_GOOGLE.equals(descriptorWithSameValues));
+
+ // same object -> returns true
+ assertTrue(DESC_GOOGLE.equals(DESC_GOOGLE));
+
+ // null -> returns false
+ assertFalse(DESC_GOOGLE.equals(null));
+
+ // different types -> returns false
+ assertFalse(DESC_GOOGLE.equals(5));
+
+ // different values -> returns false
+ assertFalse(DESC_GOOGLE.equals(DESC_TIKTOK));
+
+ // different name -> returns false
+ EditCommand.EditCompanyDescriptor editedGoogle = new EditCompanyDescriptorBuilder(DESC_GOOGLE)
+ .withName(VALID_NAME_TIKTOK).build();
+ assertFalse(DESC_GOOGLE.equals(editedGoogle));
+
+ // different phone -> returns false
+ editedGoogle = new EditCompanyDescriptorBuilder(DESC_GOOGLE).withPhone(VALID_PHONE_TIKTOK).build();
+ assertFalse(DESC_GOOGLE.equals(editedGoogle));
+
+ // different email -> returns false
+ editedGoogle = new EditCompanyDescriptorBuilder(DESC_GOOGLE).withEmail(VALID_EMAIL_TIKTOK).build();
+ assertFalse(DESC_GOOGLE.equals(editedGoogle));
+
+ // different priority -> returns false
+ editedGoogle = new EditCompanyDescriptorBuilder(DESC_GOOGLE).withPriority("MEDIUM").build();
+ assertFalse(DESC_GOOGLE.equals(editedGoogle));
+ }
+
+ @Test
+ public void toStringMethod() {
+ EditCommand.EditCompanyDescriptor editCompanyDescriptor = new EditCommand.EditCompanyDescriptor();
+ String expected = EditCommand.EditCompanyDescriptor.class.getCanonicalName() + "{name="
+ + editCompanyDescriptor.getName().orElse(null) + ", role="
+ + editCompanyDescriptor.getRole().orElse(null) + ", deadline="
+ + editCompanyDescriptor.getDeadline().orElse(null) + ", status="
+ + editCompanyDescriptor.getStatus().orElse(null) + ", recruiter name="
+ + editCompanyDescriptor.getRecruiterName().orElse(null) + ", phone="
+ + editCompanyDescriptor.getPhone().orElse(null) + ", email="
+ + editCompanyDescriptor.getEmail().orElse(null) + ", priority="
+ + editCompanyDescriptor.getPriority().orElse(null)
+ + "}";
+ assertEquals(expected, editCompanyDescriptor.toString());
+ }
+}
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 b17c1f3d5c2..00000000000
--- a/src/test/java/seedu/address/logic/commands/EditPersonDescriptorTest.java
+++ /dev/null
@@ -1,71 +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.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));
- }
-
- @Test
- public void toStringMethod() {
- EditPersonDescriptor editPersonDescriptor = new EditPersonDescriptor();
- String expected = EditPersonDescriptor.class.getCanonicalName() + "{name="
- + editPersonDescriptor.getName().orElse(null) + ", phone="
- + editPersonDescriptor.getPhone().orElse(null) + ", email="
- + editPersonDescriptor.getEmail().orElse(null) + ", address="
- + editPersonDescriptor.getAddress().orElse(null) + ", tags="
- + editPersonDescriptor.getTags().orElse(null) + "}";
- assertEquals(expected, editPersonDescriptor.toString());
- }
-}
diff --git a/src/test/java/seedu/address/logic/commands/FilterCommandTest.java b/src/test/java/seedu/address/logic/commands/FilterCommandTest.java
new file mode 100644
index 00000000000..b6acb4ec682
--- /dev/null
+++ b/src/test/java/seedu/address/logic/commands/FilterCommandTest.java
@@ -0,0 +1,72 @@
+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.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.address.testutil.TypicalCompanies.getTypicalAddressBook;
+
+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.company.ApplicationStatus;
+import seedu.address.model.company.predicates.ApplicationStatusPredicate;
+
+/**
+ * Contains integration tests (interaction with the Model) and unit tests for FilterCommand.
+ */
+public class FilterCommandTest {
+
+ private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
+ private Model expectedModel = new ModelManager(getTypicalAddressBook(), new UserPrefs());
+
+ @Test
+ public void execute_validStatusUnfilteredList_success() {
+ ApplicationStatus status = new ApplicationStatus("pa");
+ String expectedMessage = String.format(FilterCommand.MESSAGE_SUCCESS, status);
+ ApplicationStatusPredicate predicate = new ApplicationStatusPredicate(status);
+ FilterCommand filterCommand = new FilterCommand(status, predicate);
+ expectedModel.updateFilteredCompanyList(predicate);
+ assertCommandSuccess(filterCommand, model, expectedMessage, expectedModel);
+ assertEquals(model.getFilteredCompanyList(), expectedModel.getFilteredCompanyList());
+ }
+
+ @Test
+ public void equals() {
+ ApplicationStatus firstStatus = new ApplicationStatus("pa");
+ ApplicationStatus secondStatus = new ApplicationStatus("pi");
+ ApplicationStatusPredicate firstPredicate = new ApplicationStatusPredicate(firstStatus);
+ ApplicationStatusPredicate secondPredicate = new ApplicationStatusPredicate(secondStatus);
+
+ FilterCommand filterFirstCommand = new FilterCommand(firstStatus, firstPredicate);
+ FilterCommand filterSecondCommand = new FilterCommand(secondStatus, secondPredicate);
+
+ // same object -> returns true
+ assertTrue(filterFirstCommand.equals(filterFirstCommand));
+
+ // same values -> returns true
+ FilterCommand findFirstCommandCopy = new FilterCommand(firstStatus, firstPredicate);
+ assertTrue(filterFirstCommand.equals(findFirstCommandCopy));
+
+ // different types -> returns false
+ assertFalse(filterFirstCommand.equals(1));
+
+ // null -> returns false
+ assertFalse(filterFirstCommand.equals(null));
+
+ // different company -> returns false
+ assertFalse(filterFirstCommand.equals(filterSecondCommand));
+ }
+
+ @Test
+ public void toStringMethod() {
+ ApplicationStatus status = new ApplicationStatus("pa");
+ ApplicationStatusPredicate predicate = new ApplicationStatusPredicate(status);
+ FilterCommand filterCommand = new FilterCommand(status, predicate);
+ String expected = FilterCommand.class.getCanonicalName()
+ + "{status=" + status + ", predicate=" + predicate + "}";
+ assertEquals(expected, filterCommand.toString());
+ }
+}
diff --git a/src/test/java/seedu/address/logic/commands/FindCommandTest.java b/src/test/java/seedu/address/logic/commands/FindCommandTest.java
index b8b7dbba91a..9d7c88a10d4 100644
--- a/src/test/java/seedu/address/logic/commands/FindCommandTest.java
+++ b/src/test/java/seedu/address/logic/commands/FindCommandTest.java
@@ -3,12 +3,16 @@
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.Messages.MESSAGE_PERSONS_LISTED_OVERVIEW;
+import static seedu.address.logic.Messages.MESSAGE_COMPANIES_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 static seedu.address.logic.commands.testdata.FindCommandTestCompanies.APPLESTORE;
+import static seedu.address.logic.commands.testdata.FindCommandTestCompanies.APPLE_STORES;
+import static seedu.address.logic.commands.testdata.FindCommandTestCompanies.B;
+import static seedu.address.logic.commands.testdata.FindCommandTestCompanies.BANANASTORE;
+import static seedu.address.logic.commands.testdata.FindCommandTestCompanies.getFindCommandTestAddressBook;
+import static seedu.address.testutil.TypicalCompanies.ACCENTURE;
+import static seedu.address.testutil.TypicalCompanies.APPLE;
+import static seedu.address.testutil.TypicalCompanies.MICROSOFT;
import java.util.Arrays;
import java.util.Collections;
@@ -18,14 +22,14 @@
import seedu.address.model.Model;
import seedu.address.model.ModelManager;
import seedu.address.model.UserPrefs;
-import seedu.address.model.person.NameContainsKeywordsPredicate;
+import seedu.address.model.company.predicates.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());
+ private Model model = new ModelManager(getFindCommandTestAddressBook(), new UserPrefs());
+ private Model expectedModel = new ModelManager(getFindCommandTestAddressBook(), new UserPrefs());
@Test
public void equals() {
@@ -50,28 +54,28 @@ public void equals() {
// null -> returns false
assertFalse(findFirstCommand.equals(null));
- // different person -> returns false
+ // different company -> returns false
assertFalse(findFirstCommand.equals(findSecondCommand));
}
@Test
- public void execute_zeroKeywords_noPersonFound() {
- String expectedMessage = String.format(MESSAGE_PERSONS_LISTED_OVERVIEW, 0);
+ public void execute_zeroKeywords_noCompanyFound() {
+ String expectedMessage = String.format(MESSAGE_COMPANIES_LISTED_OVERVIEW, 0);
NameContainsKeywordsPredicate predicate = preparePredicate(" ");
FindCommand command = new FindCommand(predicate);
- expectedModel.updateFilteredPersonList(predicate);
+ expectedModel.findCompanies(predicate);
assertCommandSuccess(command, model, expectedMessage, expectedModel);
- assertEquals(Collections.emptyList(), model.getFilteredPersonList());
+ assertEquals(Collections.emptyList(), model.getFilteredCompanyList());
}
@Test
- public void execute_multipleKeywords_multiplePersonsFound() {
- String expectedMessage = String.format(MESSAGE_PERSONS_LISTED_OVERVIEW, 3);
- NameContainsKeywordsPredicate predicate = preparePredicate("Kurz Elle Kunz");
+ public void execute_multipleKeywords_multipleCompaniesFound() {
+ String expectedMessage = String.format(MESSAGE_COMPANIES_LISTED_OVERVIEW, 2);
+ NameContainsKeywordsPredicate predicate = preparePredicate("Microsoft Accenture");
FindCommand command = new FindCommand(predicate);
- expectedModel.updateFilteredPersonList(predicate);
+ expectedModel.findCompanies(predicate);
assertCommandSuccess(command, model, expectedMessage, expectedModel);
- assertEquals(Arrays.asList(CARL, ELLE, FIONA), model.getFilteredPersonList());
+ assertEquals(Arrays.asList(MICROSOFT, ACCENTURE), model.getFilteredCompanyList());
}
@Test
@@ -82,6 +86,57 @@ public void toStringMethod() {
assertEquals(expected, findCommand.toString());
}
+ @Test
+ public void execute_findA_multipleCompaniesFound() {
+ String expectedMessage = String.format(MESSAGE_COMPANIES_LISTED_OVERVIEW, 5);
+ NameContainsKeywordsPredicate predicate = preparePredicate("A");
+ FindCommand command = new FindCommand(predicate);
+ expectedModel.findCompanies(predicate);
+ assertCommandSuccess(command, model, expectedMessage, expectedModel);
+ assertEquals(Arrays.asList(APPLE, APPLESTORE, APPLE_STORES, BANANASTORE, ACCENTURE),
+ model.getFilteredCompanyList());
+ }
+
+ @Test
+ public void execute_findAp_multipleCompaniesFound() {
+ String expectedMessage = String.format(MESSAGE_COMPANIES_LISTED_OVERVIEW, 3);
+ NameContainsKeywordsPredicate predicate = preparePredicate("Ap");
+ FindCommand command = new FindCommand(predicate);
+ expectedModel.findCompanies(predicate);
+ assertCommandSuccess(command, model, expectedMessage, expectedModel);
+ assertEquals(Arrays.asList(APPLE, APPLESTORE, APPLE_STORES), model.getFilteredCompanyList());
+ }
+
+ @Test
+ public void execute_findAppleStore_singleCompanyFound() {
+ String expectedMessage = String.format(MESSAGE_COMPANIES_LISTED_OVERVIEW, 1);
+ NameContainsKeywordsPredicate predicate = preparePredicate("AppleStore");
+ FindCommand command = new FindCommand(predicate);
+ expectedModel.findCompanies(predicate);
+ assertCommandSuccess(command, model, expectedMessage, expectedModel);
+ assertEquals(Collections.singletonList(APPLESTORE), model.getFilteredCompanyList());
+ }
+
+ @Test
+ public void execute_findAppleStoreWithSpace_multipleCompaniesFound() {
+ String expectedMessage = String.format(MESSAGE_COMPANIES_LISTED_OVERVIEW, 4);
+ NameContainsKeywordsPredicate predicate = preparePredicate("Apple Store");
+ FindCommand command = new FindCommand(predicate);
+ expectedModel.findCompanies(predicate);
+ assertCommandSuccess(command, model, expectedMessage, expectedModel);
+ assertEquals(Arrays.asList(APPLE, APPLESTORE, APPLE_STORES, BANANASTORE), model.getFilteredCompanyList());
+ }
+
+ @Test
+ public void execute_findB_multipleCompaniesFound() {
+ String expectedMessage = String.format(MESSAGE_COMPANIES_LISTED_OVERVIEW, 2);
+ NameContainsKeywordsPredicate predicate = preparePredicate("B");
+ FindCommand command = new FindCommand(predicate);
+ expectedModel.findCompanies(predicate);
+ assertCommandSuccess(command, model, expectedMessage, expectedModel);
+ assertEquals(Arrays.asList(BANANASTORE, B), model.getFilteredCompanyList());
+ }
+
/**
* Parses {@code userInput} into a {@code NameContainsKeywordsPredicate}.
*/
diff --git a/src/test/java/seedu/address/logic/commands/ListCommandTest.java b/src/test/java/seedu/address/logic/commands/ListCommandTest.java
index 435ff1f7275..7325bda84ca 100644
--- a/src/test/java/seedu/address/logic/commands/ListCommandTest.java
+++ b/src/test/java/seedu/address/logic/commands/ListCommandTest.java
@@ -1,9 +1,9 @@
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 static seedu.address.logic.commands.CommandTestUtil.showCompanyAtIndex;
+import static seedu.address.testutil.TypicalCompanies.getTypicalAddressBook;
+import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_COMPANY;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -33,7 +33,7 @@ public void execute_listIsNotFiltered_showsSameList() {
@Test
public void execute_listIsFiltered_showsEverything() {
- showPersonAtIndex(model, INDEX_FIRST_PERSON);
+ showCompanyAtIndex(model, INDEX_FIRST_COMPANY);
assertCommandSuccess(new ListCommand(), model, ListCommand.MESSAGE_SUCCESS, expectedModel);
}
}
diff --git a/src/test/java/seedu/address/logic/commands/RemarkCommandTest.java b/src/test/java/seedu/address/logic/commands/RemarkCommandTest.java
new file mode 100644
index 00000000000..c2f630dd88e
--- /dev/null
+++ b/src/test/java/seedu/address/logic/commands/RemarkCommandTest.java
@@ -0,0 +1,164 @@
+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.VALID_REMARK_GOOGLE;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_REMARK_TIKTOK;
+import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure;
+import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.address.logic.commands.CommandTestUtil.showCompanyAtIndex;
+import static seedu.address.testutil.TypicalCompanies.getTypicalAddressBook;
+import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_COMPANY;
+import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_COMPANY;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.address.commons.core.index.Index;
+import seedu.address.logic.Messages;
+import seedu.address.model.AddressBook;
+import seedu.address.model.Model;
+import seedu.address.model.ModelManager;
+import seedu.address.model.UserPrefs;
+import seedu.address.model.company.Company;
+import seedu.address.model.company.Remark;
+import seedu.address.testutil.CompanyBuilder;
+
+/**
+ * Contains integration tests (interaction with the Model) and unit tests for RemarkCommand.
+ */
+public class RemarkCommandTest {
+
+ private static final String REMARK_STUB = "No remarks"; //default remark after delete
+
+ private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
+
+ @Test
+ public void execute_addRemarkUnfilteredList_success() {
+ Company firstCompany = model.getFilteredCompanyList().get(INDEX_FIRST_COMPANY.getZeroBased());
+ Company editedCompany = new CompanyBuilder(firstCompany).withRemark(VALID_REMARK_GOOGLE).build();
+
+ RemarkCommand remarkCommand = new RemarkCommand(INDEX_FIRST_COMPANY,
+ new Remark(editedCompany.getRemark().value));
+
+ String expectedMessage = String.format(RemarkCommand.MESSAGE_ADD_REMARK_SUCCESS,
+ editedCompany.getName().fullName);
+
+ Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs());
+ expectedModel.setCompany(firstCompany, editedCompany);
+
+ assertCommandSuccess(remarkCommand, model, expectedMessage, expectedModel);
+ }
+
+ @Test
+ public void execute_removeRemarkUnfilteredList_success() {
+ Company firstCompany = model.getFilteredCompanyList().get(INDEX_FIRST_COMPANY.getZeroBased());
+ Company editedCompany = new CompanyBuilder(firstCompany).withRemark(REMARK_STUB).build();
+
+ Remark remark = new Remark(REMARK_STUB);
+ remark.deleteRemark();
+ RemarkCommand remarkCommand = new RemarkCommand(INDEX_FIRST_COMPANY, remark);
+
+ String expectedMessage = String.format(RemarkCommand.MESSAGE_DELETE_REMARK_SUCCESS,
+ editedCompany.getName().fullName);
+
+ Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs());
+ expectedModel.setCompany(firstCompany, editedCompany);
+
+ assertCommandSuccess(remarkCommand, model, expectedMessage, expectedModel);
+ }
+
+ @Test
+ public void execute_addRemarkFilteredList_success() {
+ showCompanyAtIndex(model, INDEX_FIRST_COMPANY);
+
+ Company firstCompany = model.getFilteredCompanyList().get(INDEX_FIRST_COMPANY.getZeroBased());
+ Company editedCompany = new CompanyBuilder(model.getFilteredCompanyList()
+ .get(INDEX_FIRST_COMPANY.getZeroBased())).withRemark(REMARK_STUB).build();
+
+ RemarkCommand remarkCommand = new RemarkCommand(INDEX_FIRST_COMPANY,
+ new Remark(editedCompany.getRemark().value));
+
+ String expectedMessage = String.format(RemarkCommand.MESSAGE_ADD_REMARK_SUCCESS,
+ editedCompany.getName().fullName);
+
+ Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs());
+ showCompanyAtIndex(expectedModel, INDEX_FIRST_COMPANY);
+ expectedModel.setCompany(firstCompany, editedCompany);
+
+ assertCommandSuccess(remarkCommand, model, expectedMessage, expectedModel);
+ }
+
+ @Test
+ public void execute_removeRemarkFilteredList_success() {
+ showCompanyAtIndex(model, INDEX_FIRST_COMPANY);
+
+ Company firstCompany = model.getFilteredCompanyList().get(INDEX_FIRST_COMPANY.getZeroBased());
+ Company editedCompany = new CompanyBuilder(model.getFilteredCompanyList()
+ .get(INDEX_FIRST_COMPANY.getZeroBased())).withRemark(REMARK_STUB).build();
+
+ Remark remark = new Remark(REMARK_STUB);
+ remark.deleteRemark();
+ RemarkCommand remarkCommand = new RemarkCommand(INDEX_FIRST_COMPANY, remark);
+
+ String expectedMessage = String.format(RemarkCommand.MESSAGE_DELETE_REMARK_SUCCESS,
+ editedCompany.getName().fullName);
+
+ Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs());
+ showCompanyAtIndex(expectedModel, INDEX_FIRST_COMPANY);
+ expectedModel.setCompany(firstCompany, editedCompany);
+
+ assertCommandSuccess(remarkCommand, model, expectedMessage, expectedModel);
+ }
+
+ @Test
+ public void execute_invalidCompanyIndexUnfilteredList_failure() {
+ Index outOfBoundIndex = Index.fromOneBased(model.getFilteredCompanyList().size() + 1);
+ RemarkCommand remarkCommand = new RemarkCommand(outOfBoundIndex, new Remark(VALID_REMARK_TIKTOK));
+
+ assertCommandFailure(remarkCommand, model, Messages.MESSAGE_INVALID_COMPANY_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_invalidCompanyIndexFilteredList_failure() {
+ showCompanyAtIndex(model, INDEX_FIRST_COMPANY);
+ Index outOfBoundIndex = INDEX_SECOND_COMPANY;
+ // ensures that outOfBoundIndex is still in bounds of address book list
+ assertTrue(outOfBoundIndex.getZeroBased() < model.getAddressBook().getCompanyList().size());
+
+ RemarkCommand remarkCommand = new RemarkCommand(outOfBoundIndex, new Remark(VALID_REMARK_TIKTOK));
+
+ assertCommandFailure(remarkCommand, model, Messages.MESSAGE_INVALID_COMPANY_DISPLAYED_INDEX);
+ }
+
+ @Test
+ public void equals() {
+ final RemarkCommand standardCommand = new RemarkCommand(INDEX_FIRST_COMPANY,
+ new Remark(VALID_REMARK_GOOGLE));
+
+ // same values -> returns true
+ RemarkCommand commandWithSameValues = new RemarkCommand(INDEX_FIRST_COMPANY,
+ new Remark(VALID_REMARK_GOOGLE));
+ 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 RemarkCommand(INDEX_SECOND_COMPANY,
+ new Remark(VALID_REMARK_GOOGLE))));
+
+ // different remark -> returns false
+ assertFalse(standardCommand.equals(new RemarkCommand(INDEX_FIRST_COMPANY,
+ new Remark(VALID_REMARK_TIKTOK))));
+ }
+}
diff --git a/src/test/java/seedu/address/logic/commands/SortCommandTest.java b/src/test/java/seedu/address/logic/commands/SortCommandTest.java
new file mode 100644
index 00000000000..0d765ad2063
--- /dev/null
+++ b/src/test/java/seedu/address/logic/commands/SortCommandTest.java
@@ -0,0 +1,81 @@
+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.logic.commands.CommandTestUtil.assertCommandSuccess;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.address.logic.SortOrder;
+import seedu.address.logic.commands.testdata.SortCommandTestCompanies;
+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 SortCommand.
+ */
+public class SortCommandTest {
+
+ @Test
+ public void execute_sortAscending_success() {
+ SortCommand sortCommand = new SortCommand(SortOrder.ASCENDING);
+ String expectedMessage = SortCommand.MESSAGE_SUCCESS_ASCENDING;
+
+ // Creating a model with unsorted companies
+ Model unsortedModel = new ModelManager(SortCommandTestCompanies.getUnsortedAddressBook(), new UserPrefs());
+
+ // Expected sorted model
+ Model expectedModel = new ModelManager(SortCommandTestCompanies.getSortedAscendingAddressBook(),
+ new UserPrefs());
+
+ assertCommandSuccess(sortCommand, unsortedModel, expectedMessage, expectedModel);
+ }
+ @Test
+ public void execute_sortDescending_success() {
+ SortCommand sortCommand = new SortCommand(SortOrder.DESCENDING);
+ String expectedMessage = SortCommand.MESSAGE_SUCCESS_DESCENDING;
+
+ // Creating a model with unsorted companies
+ Model unsortedModel = new ModelManager(SortCommandTestCompanies.getUnsortedAddressBook(), new UserPrefs());
+
+ // Expected sorted model
+ Model expectedModel = new ModelManager(SortCommandTestCompanies.getSortedDescendingAddressBook(),
+ new UserPrefs());
+
+ assertCommandSuccess(sortCommand, unsortedModel, expectedMessage, expectedModel);
+
+ }
+
+ @Test
+ public void equals() {
+ SortCommand sortAscendCommand = new SortCommand(SortOrder.ASCENDING);
+ SortCommand sortDescendCommand = new SortCommand(SortOrder.DESCENDING);
+
+ // same object -> returns true
+ assertTrue(sortAscendCommand.equals(sortAscendCommand));
+
+ // same values -> returns true
+ SortCommand sortAscendCommandCopy = new SortCommand(SortOrder.ASCENDING);
+ assertTrue(sortAscendCommand.equals(sortAscendCommandCopy));
+
+ // different types -> returns false
+ assertFalse(sortAscendCommand.equals(1));
+
+ // null -> returns false
+ assertFalse(sortAscendCommand.equals(null));
+
+ // different order -> returns false
+ assertFalse(sortAscendCommand.equals(sortDescendCommand));
+ }
+
+ @Test
+ public void toStringTest() {
+ SortCommand sortAscendCommand = new SortCommand(SortOrder.ASCENDING);
+ assertEquals(SortCommand.COMMAND_WORD + " " + SortOrder.ASCENDING, sortAscendCommand.toString());
+
+ SortCommand sortDescendCommand = new SortCommand(SortOrder.DESCENDING);
+ assertEquals(SortCommand.COMMAND_WORD + " " + SortOrder.DESCENDING, sortDescendCommand.toString());
+ }
+}
diff --git a/src/test/java/seedu/address/logic/commands/ViewCommandTest.java b/src/test/java/seedu/address/logic/commands/ViewCommandTest.java
new file mode 100644
index 00000000000..61a02c8fa40
--- /dev/null
+++ b/src/test/java/seedu/address/logic/commands/ViewCommandTest.java
@@ -0,0 +1,96 @@
+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.logic.commands.CommandTestUtil.assertCommandFailure;
+import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.address.logic.commands.CommandTestUtil.showCompanyAtIndex;
+import static seedu.address.testutil.TypicalCompanies.getTypicalAddressBook;
+import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_COMPANY;
+import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_COMPANY;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.address.commons.core.index.Index;
+import seedu.address.logic.Messages;
+import seedu.address.model.Model;
+import seedu.address.model.ModelManager;
+import seedu.address.model.UserPrefs;
+import seedu.address.model.company.Company;
+
+/**
+ * Contains integration tests (interaction with the Model) and unit tests for
+ * {@code ViewCommand}.
+ */
+public class ViewCommandTest {
+
+ private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
+
+ @Test
+ public void execute_validIndexUnfilteredList_success() {
+ Company companyToView = model.getFilteredCompanyList().get(INDEX_FIRST_COMPANY.getZeroBased());
+ ViewCommand viewCommand = new ViewCommand(INDEX_FIRST_COMPANY);
+
+ String companyDetailsToDisplayString = companyToView.getName().toString();
+
+ String expectedMessage = String.format(ViewCommand.MESSAGE_VIEW_COMPANY_SUCCESS,
+ companyDetailsToDisplayString);
+
+ ModelManager expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs());
+ expectedModel.setCurrentViewedCompany(companyToView);
+
+ assertCommandSuccess(viewCommand, model, expectedMessage, expectedModel);
+ }
+
+ @Test
+ public void execute_invalidIndexUnfilteredList_throwsCommandException() {
+ Index outOfBoundIndex = Index.fromOneBased(model.getFilteredCompanyList().size() + 1);
+ ViewCommand viewCommand = new ViewCommand(outOfBoundIndex);
+
+ assertCommandFailure(viewCommand, model, Messages.MESSAGE_INVALID_COMPANY_DISPLAYED_INDEX);
+ }
+
+ @Test
+ public void execute_invalidIndexFilteredList_throwsCommandException() {
+ showCompanyAtIndex(model, INDEX_FIRST_COMPANY);
+
+ Index outOfBoundIndex = INDEX_SECOND_COMPANY;
+ // ensures that outOfBoundIndex is still in bounds of address book list
+ assertTrue(outOfBoundIndex.getZeroBased() < model.getAddressBook().getCompanyList().size());
+
+ ViewCommand viewCommand = new ViewCommand(outOfBoundIndex);
+
+ assertCommandFailure(viewCommand, model, Messages.MESSAGE_INVALID_COMPANY_DISPLAYED_INDEX);
+ }
+
+ @Test
+ public void equals() {
+ ViewCommand viewFirstCommand = new ViewCommand(INDEX_FIRST_COMPANY);
+ ViewCommand viewSecondCommand = new ViewCommand(INDEX_SECOND_COMPANY);
+
+ // same object -> returns true
+ assertTrue(viewFirstCommand.equals(viewFirstCommand));
+
+ // same values -> returns true
+ ViewCommand viewFirstCommandCopy = new ViewCommand(INDEX_FIRST_COMPANY);
+ assertTrue(viewFirstCommand.equals(viewFirstCommandCopy));
+
+ // different types -> returns false
+ assertFalse(viewFirstCommand.equals(1));
+
+ // null -> returns false
+ assertFalse(viewFirstCommand.equals(null));
+
+ // different company -> returns false
+ assertFalse(viewFirstCommand.equals(viewSecondCommand));
+ }
+
+ @Test
+ public void toStringMethod() {
+ Index targetIndex = Index.fromOneBased(1);
+ ViewCommand viewCommand = new ViewCommand(targetIndex);
+ String expected = ViewCommand.class.getCanonicalName() + "{targetIndex=" + targetIndex + "}";
+ assertEquals(expected, viewCommand.toString());
+ }
+}
diff --git a/src/test/java/seedu/address/logic/commands/stubs/ModelStub.java b/src/test/java/seedu/address/logic/commands/stubs/ModelStub.java
new file mode 100644
index 00000000000..2e21b57ae37
--- /dev/null
+++ b/src/test/java/seedu/address/logic/commands/stubs/ModelStub.java
@@ -0,0 +1,143 @@
+package seedu.address.logic.commands.stubs;
+
+import java.nio.file.Path;
+import java.util.List;
+import java.util.function.Predicate;
+
+import javafx.collections.ObservableList;
+import seedu.address.commons.core.GuiSettings;
+import seedu.address.model.Model;
+import seedu.address.model.ReadOnlyAddressBook;
+import seedu.address.model.ReadOnlyUserPrefs;
+import seedu.address.model.company.Company;
+
+/**
+ * A default model stub that have all the methods failing.
+ */
+public 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 addCompany(Company company) {
+ 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 hasCompany(Company company) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void deleteCompany(Company target) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void setCompany(Company target, Company editedCompany) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void setAllCompanies(List companies) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public ObservableList getFilteredCompanyList() {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void updateFilteredCompanyList(Predicate predicate) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void setCurrentViewedCompany(Company company) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public ObservableList getCurrentViewedCompany() {
+ throw new AssertionError("This method should not be called.");
+ }
+
+
+ @Override
+ public void updateCurrentViewedCompany(Predicate predicate) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void clearCompanyDetailPanel() {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void checkDelete(Company company) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void filterCompaniesByStatus(Predicate predicate) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public Company getDuplicateCompany(Company company) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public int getDuplicateIndexFromFilteredAddressbook(Company company) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public int getDuplicateIndexFromOriginalAddressbook(Company company) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void findCompanies(Predicate predicate) {
+ throw new AssertionError("This method should not be called.");
+ }
+}
diff --git a/src/test/java/seedu/address/logic/commands/stubs/ModelStubAcceptingCompanyAdded.java b/src/test/java/seedu/address/logic/commands/stubs/ModelStubAcceptingCompanyAdded.java
new file mode 100644
index 00000000000..24b9993deda
--- /dev/null
+++ b/src/test/java/seedu/address/logic/commands/stubs/ModelStubAcceptingCompanyAdded.java
@@ -0,0 +1,40 @@
+package seedu.address.logic.commands.stubs;
+
+import static java.util.Objects.requireNonNull;
+
+import java.util.ArrayList;
+
+import seedu.address.model.AddressBook;
+import seedu.address.model.ReadOnlyAddressBook;
+import seedu.address.model.company.Company;
+
+/**
+ * A Model stub that always accept the company being added.
+ */
+public class ModelStubAcceptingCompanyAdded extends ModelStub {
+ public final ArrayList companiesAdded = new ArrayList<>();
+ public final ArrayList companiesToView = new ArrayList<>();
+
+ @Override
+ public boolean hasCompany(Company company) {
+ requireNonNull(company);
+ return companiesAdded.stream().anyMatch(company::isSameCompany);
+ }
+
+ @Override
+ public void addCompany(Company company) {
+ requireNonNull(company);
+ companiesAdded.add(company);
+ }
+
+ @Override
+ public void setCurrentViewedCompany(Company company) {
+ requireNonNull(company);
+ companiesToView.add(company);
+ }
+
+ @Override
+ public ReadOnlyAddressBook getAddressBook() {
+ return new AddressBook();
+ }
+}
diff --git a/src/test/java/seedu/address/logic/commands/stubs/ModelStubWithCompanyInFilteredCompanyList.java b/src/test/java/seedu/address/logic/commands/stubs/ModelStubWithCompanyInFilteredCompanyList.java
new file mode 100644
index 00000000000..943ca71118c
--- /dev/null
+++ b/src/test/java/seedu/address/logic/commands/stubs/ModelStubWithCompanyInFilteredCompanyList.java
@@ -0,0 +1,93 @@
+package seedu.address.logic.commands.stubs;
+
+import static java.util.Objects.requireNonNull;
+
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
+import seedu.address.model.company.Company;
+import seedu.address.testutil.CompanyBuilder;
+
+/**
+ * A Model stub will be populated with exactly 1 company that is
+ * a duplicate of the company being added, before the execution
+ * of the add command. The duplicate company will be found in both the
+ * filteredCompanyList and in the full company list. This simulates state
+ * after any other command other than filter or find is executed.
+ */
+public class ModelStubWithCompanyInFilteredCompanyList extends ModelStub {
+
+ public final ObservableList filteredCompanyList = FXCollections.observableArrayList();
+ public final ObservableList fullCompanyList = FXCollections.observableArrayList();
+ private final Company company;
+ private Company lastViewedCompany;
+
+ /**
+ * Creates a ModelStub populated with a company that is a duplicate of the company being added.
+ */
+ public ModelStubWithCompanyInFilteredCompanyList(Company company, int... additionalCompanies) {
+ requireNonNull(company);
+ this.company = company;
+ fullCompanyList.add(company);
+ filteredCompanyList.add(company);
+ CompanyBuilder cb = new CompanyBuilder(company);
+
+ for (int i : additionalCompanies) {
+ Company duplicateCompany = cb.withName("Company " + i).build();
+ fullCompanyList.add(duplicateCompany);
+ filteredCompanyList.add(duplicateCompany);
+ }
+ }
+
+ @Override
+ public boolean hasCompany(Company company) {
+ requireNonNull(company);
+ return this.company.isSameCompany(company);
+ }
+
+ @Override
+ public Company getDuplicateCompany(Company otherCompany) {
+ assert (otherCompany != null);
+
+ if (otherCompany == this.company) {
+ return this.company;
+ }
+
+ boolean condition = otherCompany.getName() != null
+ && otherCompany.getName().equals(this.company.getName())
+ && otherCompany.getRole() != null
+ && otherCompany.getRole().equals(this.company.getRole())
+ && otherCompany.getDeadline() != null
+ && otherCompany.getDeadline().equals(this.company.getDeadline());
+
+ return condition ? this.company : null;
+ }
+
+ @Override
+ public void addCompany(Company company) {
+ requireNonNull(company);
+ fullCompanyList.add(company);
+ }
+
+ @Override
+ public void setCurrentViewedCompany(Company company) {
+ requireNonNull(company);
+ lastViewedCompany = company;
+ }
+
+ @Override
+ public int getDuplicateIndexFromOriginalAddressbook(Company company) {
+ return fullCompanyList.indexOf(company);
+ }
+
+ @Override
+ public int getDuplicateIndexFromFilteredAddressbook(Company company) {
+ return filteredCompanyList.indexOf(company);
+ }
+
+ /**
+ * Returns the last viewed company.
+ */
+ public Company getLastViewedCompany() {
+ return lastViewedCompany;
+ }
+}
diff --git a/src/test/java/seedu/address/logic/commands/stubs/ModelStubWithCompanyNotInFilteredCompanyList.java b/src/test/java/seedu/address/logic/commands/stubs/ModelStubWithCompanyNotInFilteredCompanyList.java
new file mode 100644
index 00000000000..df02beda496
--- /dev/null
+++ b/src/test/java/seedu/address/logic/commands/stubs/ModelStubWithCompanyNotInFilteredCompanyList.java
@@ -0,0 +1,93 @@
+package seedu.address.logic.commands.stubs;
+
+import static java.util.Objects.requireNonNull;
+
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
+import seedu.address.model.company.Company;
+import seedu.address.testutil.CompanyBuilder;
+
+/**
+ * A Model stub will be populated with exactly 1 company that is
+ * a duplicate of the company being added, before the execution
+ * of the add command. The duplicate company will not be found in the
+ * filteredCompanyList, only in the full company list. This simulates state
+ * after a find or filter command is executed.
+ */
+public class ModelStubWithCompanyNotInFilteredCompanyList extends ModelStub {
+ public final ObservableList filteredCompanyList = FXCollections.observableArrayList();
+ public final ObservableList fullCompanyList = FXCollections.observableArrayList();
+ private final Company company;
+ private Company lastViewedCompany;
+
+ /**
+ * Creates a ModelStub populated with a company that is a duplicate of the company being added.
+ */
+ public ModelStubWithCompanyNotInFilteredCompanyList(Company company, int... additionalCompanies) {
+ requireNonNull(company);
+ this.company = company;
+ fullCompanyList.add(company);
+ CompanyBuilder cb = new CompanyBuilder(company);
+
+ for (int i : additionalCompanies) {
+ Company duplicateCompany = cb.withName("Company " + i).build();
+ fullCompanyList.add(duplicateCompany);
+ }
+ }
+
+ @Override
+ public boolean hasCompany(Company company) {
+ requireNonNull(company);
+ return this.company.isSameCompany(company);
+ }
+
+ @Override
+ public Company getDuplicateCompany(Company otherCompany) {
+ assert (otherCompany != null);
+
+ if (otherCompany == this.company) {
+ return this.company;
+ }
+
+ boolean condition = otherCompany.getName() != null
+ && otherCompany.getName().equals(this.company.getName())
+ && otherCompany.getRole() != null
+ && otherCompany.getRole().equals(this.company.getRole())
+ && otherCompany.getDeadline() != null
+ && otherCompany.getDeadline().equals(this.company.getDeadline());
+
+ return condition ? this.company : null;
+ }
+
+ @Override
+ public void addCompany(Company company) {
+ requireNonNull(company);
+ fullCompanyList.add(company);
+ }
+
+ @Override
+ public void setCurrentViewedCompany(Company company) {
+ requireNonNull(company);
+ lastViewedCompany = company;
+ }
+
+ @Override
+ public int getDuplicateIndexFromOriginalAddressbook(Company company) {
+ return fullCompanyList.indexOf(company);
+ }
+
+ // Simulate duplicate company to the one that is being added not being in the
+ // filtered company list. Aka, result on the company panel not showing the
+ // duplicate company after find or sort command is executed
+ // must not be found in the filteredCompanyList, only in the fullCompanyList
+ @Override
+ public int getDuplicateIndexFromFilteredAddressbook(Company company) {
+ int index = filteredCompanyList.indexOf(company);
+ assert (index == -1);
+ return index;
+ }
+
+ public Company getLastViewedCompany() {
+ return lastViewedCompany;
+ }
+}
diff --git a/src/test/java/seedu/address/logic/commands/testdata/FindCommandTestCompanies.java b/src/test/java/seedu/address/logic/commands/testdata/FindCommandTestCompanies.java
new file mode 100644
index 00000000000..ebaf09bfad4
--- /dev/null
+++ b/src/test/java/seedu/address/logic/commands/testdata/FindCommandTestCompanies.java
@@ -0,0 +1,39 @@
+package seedu.address.logic.commands.testdata;
+
+import static seedu.address.testutil.TypicalCompanies.ACCENTURE;
+import static seedu.address.testutil.TypicalCompanies.APPLE;
+import static seedu.address.testutil.TypicalCompanies.MICROSOFT;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import seedu.address.model.AddressBook;
+import seedu.address.model.company.Company;
+import seedu.address.testutil.CompanyBuilder;
+
+/**
+ * A utility class containing a list of {@code Company} objects to be used in FindCommand tests.
+ */
+public class FindCommandTestCompanies {
+
+ public static final Company APPLESTORE = new CompanyBuilder().withName("AppleStore").build();
+ public static final Company APPLE_STORES = new CompanyBuilder().withName("Apple Stores").build();
+ public static final Company BANANASTORE = new CompanyBuilder().withName("BananaStore").build();
+ public static final Company B = new CompanyBuilder().withName("B").build();
+ public static final Company C = new CompanyBuilder().withName("C").build();
+
+ private FindCommandTestCompanies() {} // prevents instantiation
+
+ public static AddressBook getFindCommandTestAddressBook() {
+ AddressBook ab = new AddressBook();
+ for (Company company : getFindCommandTestCompanies()) {
+ ab.addCompany(company);
+ }
+ return ab;
+ }
+
+ public static List getFindCommandTestCompanies() {
+ return new ArrayList<>(Arrays.asList(APPLE, APPLESTORE, APPLE_STORES, BANANASTORE, B, C, MICROSOFT, ACCENTURE));
+ }
+}
diff --git a/src/test/java/seedu/address/logic/commands/testdata/SortCommandTestCompanies.java b/src/test/java/seedu/address/logic/commands/testdata/SortCommandTestCompanies.java
new file mode 100644
index 00000000000..c6cfba383dc
--- /dev/null
+++ b/src/test/java/seedu/address/logic/commands/testdata/SortCommandTestCompanies.java
@@ -0,0 +1,45 @@
+package seedu.address.logic.commands.testdata;
+
+import seedu.address.model.AddressBook;
+import seedu.address.model.company.Company;
+import seedu.address.testutil.CompanyBuilder;
+
+/**
+ * A utility class containing a list of {@code Company} objects to be used in SortCommand tests.
+ */
+public class SortCommandTestCompanies {
+
+ public static final Company FIRST = new CompanyBuilder().withName("Google")
+ .withDeadline("01-01-2023").build();
+ public static final Company SECOND = new CompanyBuilder().withName("Amazon")
+ .withDeadline("01-06-2023").build();
+ public static final Company THIRD = new CompanyBuilder().withName("Facebook")
+ .withDeadline("01-12-2023").build();
+
+
+ private SortCommandTestCompanies() {} // prevents instantiation
+
+ public static AddressBook getUnsortedAddressBook() {
+ AddressBook ab = new AddressBook();
+ ab.addCompany(FIRST);
+ ab.addCompany(THIRD);
+ ab.addCompany(SECOND);
+ return ab;
+ }
+
+ public static AddressBook getSortedAscendingAddressBook() {
+ AddressBook ab = new AddressBook();
+ ab.addCompany(FIRST);
+ ab.addCompany(SECOND);
+ ab.addCompany(THIRD);
+ return ab;
+ }
+
+ public static AddressBook getSortedDescendingAddressBook() {
+ AddressBook ab = new AddressBook();
+ ab.addCompany(THIRD);
+ ab.addCompany(SECOND);
+ ab.addCompany(FIRST);
+ return ab;
+ }
+}
diff --git a/src/test/java/seedu/address/logic/parser/AddCommandParserTest.java b/src/test/java/seedu/address/logic/parser/AddCommandParserTest.java
index 5bc11d3cdaa..1584c24f123 100644
--- a/src/test/java/seedu/address/logic/parser/AddCommandParserTest.java
+++ b/src/test/java/seedu/address/logic/parser/AddCommandParserTest.java
@@ -1,140 +1,201 @@
package seedu.address.logic.parser;
import static seedu.address.logic.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.DEADLINE_DESC_GOOGLE;
+import static seedu.address.logic.commands.CommandTestUtil.DEADLINE_DESC_TIKTOK;
+import static seedu.address.logic.commands.CommandTestUtil.EMAIL_DESC_GOOGLE;
+import static seedu.address.logic.commands.CommandTestUtil.EMAIL_DESC_TIKTOK;
+import static seedu.address.logic.commands.CommandTestUtil.INVALID_DEADLINE_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.INVALID_PRIORITY_DESC;
+import static seedu.address.logic.commands.CommandTestUtil.INVALID_RECRUITER_NAME_DESC;
+import static seedu.address.logic.commands.CommandTestUtil.INVALID_ROLE_DESC;
+import static seedu.address.logic.commands.CommandTestUtil.INVALID_STATUS_DESC;
+import static seedu.address.logic.commands.CommandTestUtil.NAME_DESC_GOOGLE;
+import static seedu.address.logic.commands.CommandTestUtil.NAME_DESC_TIKTOK;
+import static seedu.address.logic.commands.CommandTestUtil.PHONE_DESC_GOOGLE;
+import static seedu.address.logic.commands.CommandTestUtil.PHONE_DESC_TIKTOK;
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.CliSyntax.PREFIX_ADDRESS;
+import static seedu.address.logic.commands.CommandTestUtil.PRIORITY_DESC_GOOGLE;
+import static seedu.address.logic.commands.CommandTestUtil.PRIORITY_DESC_TIKTOK;
+import static seedu.address.logic.commands.CommandTestUtil.RECRUITER_NAME_DESC_GOOGLE;
+import static seedu.address.logic.commands.CommandTestUtil.RECRUITER_NAME_DESC_TIKTOK;
+import static seedu.address.logic.commands.CommandTestUtil.ROLE_DESC_GOOGLE;
+import static seedu.address.logic.commands.CommandTestUtil.ROLE_DESC_TIKTOK;
+import static seedu.address.logic.commands.CommandTestUtil.STATUS_DESC_GOOGLE;
+import static seedu.address.logic.commands.CommandTestUtil.STATUS_DESC_TIKTOK;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_DEADLINE_TIKTOK;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_TIKTOK;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_TIKTOK;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_TIKTOK;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_RECRUITER_NAME_TIKTOK;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_ROLE_TIKTOK;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_STATUS_TIKTOK;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_COMPANY_NAME;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_DEADLINE;
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_PRIORITY;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_RECRUITER_NAME;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_ROLE;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_STATUS;
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 static seedu.address.testutil.TypicalCompanies.GOOGLE;
+import static seedu.address.testutil.TypicalCompanies.TIKTOK;
import org.junit.jupiter.api.Test;
import seedu.address.logic.Messages;
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;
+import seedu.address.model.company.ApplicationStatus;
+import seedu.address.model.company.Company;
+import seedu.address.model.company.Deadline;
+import seedu.address.model.company.Email;
+import seedu.address.model.company.Name;
+import seedu.address.model.company.Phone;
+import seedu.address.model.company.Priority;
+import seedu.address.model.company.RecruiterName;
+import seedu.address.model.company.Role;
+import seedu.address.testutil.CompanyBuilder;
public class AddCommandParserTest {
private AddCommandParser parser = new AddCommandParser();
@Test
public void parse_allFieldsPresent_success() {
- Person expectedPerson = new PersonBuilder(BOB).withTags(VALID_TAG_FRIEND).build();
+ Company expectedCompany = new CompanyBuilder(TIKTOK).withRemark("No remarks").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));
+ assertParseSuccess(parser, PREAMBLE_WHITESPACE + NAME_DESC_TIKTOK + PHONE_DESC_TIKTOK + EMAIL_DESC_TIKTOK
+ + ROLE_DESC_TIKTOK + DEADLINE_DESC_TIKTOK + STATUS_DESC_TIKTOK + RECRUITER_NAME_DESC_TIKTOK
+ + PRIORITY_DESC_TIKTOK, new AddCommand(expectedCompany));
- // 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_repeatedNonTagValue_failure() {
- String validExpectedPersonString = NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB
- + ADDRESS_DESC_BOB + TAG_DESC_FRIEND;
+ String validExpectedCompanyString = NAME_DESC_TIKTOK + PHONE_DESC_TIKTOK + EMAIL_DESC_TIKTOK + ROLE_DESC_TIKTOK
+ + DEADLINE_DESC_TIKTOK + STATUS_DESC_TIKTOK + RECRUITER_NAME_DESC_TIKTOK + PRIORITY_DESC_TIKTOK;
// multiple names
- assertParseFailure(parser, NAME_DESC_AMY + validExpectedPersonString,
- Messages.getErrorMessageForDuplicatePrefixes(PREFIX_NAME));
+ assertParseFailure(parser, NAME_DESC_GOOGLE + validExpectedCompanyString,
+ Messages.getErrorMessageForDuplicatePrefixes(PREFIX_COMPANY_NAME));
// multiple phones
- assertParseFailure(parser, PHONE_DESC_AMY + validExpectedPersonString,
+ assertParseFailure(parser, PHONE_DESC_GOOGLE + validExpectedCompanyString,
Messages.getErrorMessageForDuplicatePrefixes(PREFIX_PHONE));
// multiple emails
- assertParseFailure(parser, EMAIL_DESC_AMY + validExpectedPersonString,
+ assertParseFailure(parser, EMAIL_DESC_GOOGLE + validExpectedCompanyString,
Messages.getErrorMessageForDuplicatePrefixes(PREFIX_EMAIL));
- // multiple addresses
- assertParseFailure(parser, ADDRESS_DESC_AMY + validExpectedPersonString,
- Messages.getErrorMessageForDuplicatePrefixes(PREFIX_ADDRESS));
+ // multiple roles
+ assertParseFailure(parser, ROLE_DESC_GOOGLE + validExpectedCompanyString,
+ Messages.getErrorMessageForDuplicatePrefixes(PREFIX_ROLE));
+
+ // multiple deadlines
+ assertParseFailure(parser, DEADLINE_DESC_GOOGLE + validExpectedCompanyString,
+ Messages.getErrorMessageForDuplicatePrefixes(PREFIX_DEADLINE));
+
+ // multiple statuses
+ assertParseFailure(parser, STATUS_DESC_GOOGLE + validExpectedCompanyString,
+ Messages.getErrorMessageForDuplicatePrefixes(PREFIX_STATUS));
+
+ // multiple recruiter names
+ assertParseFailure(parser, RECRUITER_NAME_DESC_GOOGLE + validExpectedCompanyString,
+ Messages.getErrorMessageForDuplicatePrefixes(PREFIX_RECRUITER_NAME));
+
+ // multiple priorities
+ assertParseFailure(parser, PRIORITY_DESC_GOOGLE + validExpectedCompanyString,
+ Messages.getErrorMessageForDuplicatePrefixes(PREFIX_PRIORITY));
// multiple fields repeated
- assertParseFailure(parser,
- validExpectedPersonString + PHONE_DESC_AMY + EMAIL_DESC_AMY + NAME_DESC_AMY + ADDRESS_DESC_AMY
- + validExpectedPersonString,
- Messages.getErrorMessageForDuplicatePrefixes(PREFIX_NAME, PREFIX_ADDRESS, PREFIX_EMAIL, PREFIX_PHONE));
+ assertParseFailure(parser, NAME_DESC_GOOGLE + PHONE_DESC_GOOGLE + EMAIL_DESC_GOOGLE + ROLE_DESC_GOOGLE
+ + DEADLINE_DESC_GOOGLE + STATUS_DESC_TIKTOK + RECRUITER_NAME_DESC_TIKTOK
+ + validExpectedCompanyString,
+ Messages.getErrorMessageForDuplicatePrefixes(PREFIX_COMPANY_NAME, PREFIX_PHONE, PREFIX_EMAIL,
+ PREFIX_ROLE, PREFIX_DEADLINE, PREFIX_STATUS, PREFIX_RECRUITER_NAME));
// invalid value followed by valid value
// invalid name
- assertParseFailure(parser, INVALID_NAME_DESC + validExpectedPersonString,
- Messages.getErrorMessageForDuplicatePrefixes(PREFIX_NAME));
+ assertParseFailure(parser, INVALID_NAME_DESC + validExpectedCompanyString,
+ Messages.getErrorMessageForDuplicatePrefixes(PREFIX_COMPANY_NAME));
// invalid email
- assertParseFailure(parser, INVALID_EMAIL_DESC + validExpectedPersonString,
+ assertParseFailure(parser, INVALID_EMAIL_DESC + validExpectedCompanyString,
Messages.getErrorMessageForDuplicatePrefixes(PREFIX_EMAIL));
// invalid phone
- assertParseFailure(parser, INVALID_PHONE_DESC + validExpectedPersonString,
+ assertParseFailure(parser, INVALID_PHONE_DESC + validExpectedCompanyString,
Messages.getErrorMessageForDuplicatePrefixes(PREFIX_PHONE));
- // invalid address
- assertParseFailure(parser, INVALID_ADDRESS_DESC + validExpectedPersonString,
- Messages.getErrorMessageForDuplicatePrefixes(PREFIX_ADDRESS));
+ // invalid role
+ assertParseFailure(parser, INVALID_ROLE_DESC + validExpectedCompanyString,
+ Messages.getErrorMessageForDuplicatePrefixes(PREFIX_ROLE));
+
+ // invalid deadline
+ assertParseFailure(parser, INVALID_DEADLINE_DESC + validExpectedCompanyString,
+ Messages.getErrorMessageForDuplicatePrefixes(PREFIX_DEADLINE));
+
+ // invalid status
+ assertParseFailure(parser, INVALID_STATUS_DESC + validExpectedCompanyString,
+ Messages.getErrorMessageForDuplicatePrefixes(PREFIX_STATUS));
+
+ // invalid recruiter name
+ assertParseFailure(parser, INVALID_RECRUITER_NAME_DESC + validExpectedCompanyString,
+ Messages.getErrorMessageForDuplicatePrefixes(PREFIX_RECRUITER_NAME));
+
+ // invalid priority
+ assertParseFailure(parser, INVALID_PRIORITY_DESC + validExpectedCompanyString,
+ Messages.getErrorMessageForDuplicatePrefixes(PREFIX_PRIORITY));
// valid value followed by invalid value
// invalid name
- assertParseFailure(parser, validExpectedPersonString + INVALID_NAME_DESC,
- Messages.getErrorMessageForDuplicatePrefixes(PREFIX_NAME));
+ assertParseFailure(parser, validExpectedCompanyString + INVALID_NAME_DESC,
+ Messages.getErrorMessageForDuplicatePrefixes(PREFIX_COMPANY_NAME));
// invalid email
- assertParseFailure(parser, validExpectedPersonString + INVALID_EMAIL_DESC,
+ assertParseFailure(parser, validExpectedCompanyString + INVALID_EMAIL_DESC,
Messages.getErrorMessageForDuplicatePrefixes(PREFIX_EMAIL));
// invalid phone
- assertParseFailure(parser, validExpectedPersonString + INVALID_PHONE_DESC,
+ assertParseFailure(parser, validExpectedCompanyString + INVALID_PHONE_DESC,
Messages.getErrorMessageForDuplicatePrefixes(PREFIX_PHONE));
- // invalid address
- assertParseFailure(parser, validExpectedPersonString + INVALID_ADDRESS_DESC,
- Messages.getErrorMessageForDuplicatePrefixes(PREFIX_ADDRESS));
+ // invalid role
+ assertParseFailure(parser, validExpectedCompanyString + INVALID_ROLE_DESC,
+ Messages.getErrorMessageForDuplicatePrefixes(PREFIX_ROLE));
+
+ // invalid deadline
+ assertParseFailure(parser, validExpectedCompanyString + INVALID_DEADLINE_DESC,
+ Messages.getErrorMessageForDuplicatePrefixes(PREFIX_DEADLINE));
+
+ // invalid status
+ assertParseFailure(parser, validExpectedCompanyString + INVALID_STATUS_DESC,
+ Messages.getErrorMessageForDuplicatePrefixes(PREFIX_STATUS));
+
+ // invalid recruiter name
+ assertParseFailure(parser, validExpectedCompanyString + INVALID_RECRUITER_NAME_DESC,
+ Messages.getErrorMessageForDuplicatePrefixes(PREFIX_RECRUITER_NAME));
+
+ // invalid priority
+ assertParseFailure(parser, validExpectedCompanyString + INVALID_PRIORITY_DESC,
+ Messages.getErrorMessageForDuplicatePrefixes(PREFIX_PRIORITY));
}
@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));
+ public void parse_optionalremarkMissing_success() {
+ Company expectedCompany = new CompanyBuilder(GOOGLE).withRemark("No remarks").build();
+ assertParseSuccess(parser, NAME_DESC_GOOGLE + PHONE_DESC_GOOGLE + EMAIL_DESC_GOOGLE + ROLE_DESC_GOOGLE
+ + DEADLINE_DESC_GOOGLE + STATUS_DESC_GOOGLE + RECRUITER_NAME_DESC_GOOGLE + PRIORITY_DESC_GOOGLE,
+ new AddCommand(expectedCompany));
}
@Test
@@ -142,55 +203,101 @@ 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);
+ assertParseFailure(parser, VALID_NAME_TIKTOK + PHONE_DESC_TIKTOK + EMAIL_DESC_TIKTOK + ROLE_DESC_TIKTOK
+ + DEADLINE_DESC_TIKTOK + STATUS_DESC_TIKTOK + RECRUITER_NAME_DESC_TIKTOK, expectedMessage);
// missing phone prefix
- assertParseFailure(parser, NAME_DESC_BOB + VALID_PHONE_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB,
- expectedMessage);
+ assertParseFailure(parser, NAME_DESC_TIKTOK + VALID_PHONE_TIKTOK + EMAIL_DESC_TIKTOK + ROLE_DESC_TIKTOK
+ + DEADLINE_DESC_TIKTOK + STATUS_DESC_TIKTOK + RECRUITER_NAME_DESC_TIKTOK, expectedMessage);
// missing email prefix
- assertParseFailure(parser, NAME_DESC_BOB + PHONE_DESC_BOB + VALID_EMAIL_BOB + ADDRESS_DESC_BOB,
- expectedMessage);
+ assertParseFailure(parser, NAME_DESC_TIKTOK + PHONE_DESC_TIKTOK + VALID_EMAIL_TIKTOK + ROLE_DESC_TIKTOK
+ + DEADLINE_DESC_TIKTOK + STATUS_DESC_TIKTOK + RECRUITER_NAME_DESC_TIKTOK, expectedMessage);
+
+ // missing role prefix
+ assertParseFailure(parser, NAME_DESC_TIKTOK + PHONE_DESC_TIKTOK + EMAIL_DESC_TIKTOK + VALID_ROLE_TIKTOK
+ + DEADLINE_DESC_TIKTOK + STATUS_DESC_TIKTOK + RECRUITER_NAME_DESC_TIKTOK, expectedMessage);
+
+ // missing deadline prefix
+ assertParseFailure(parser, NAME_DESC_TIKTOK + PHONE_DESC_TIKTOK + EMAIL_DESC_TIKTOK + ROLE_DESC_TIKTOK
+ + VALID_DEADLINE_TIKTOK + STATUS_DESC_TIKTOK + RECRUITER_NAME_DESC_TIKTOK, expectedMessage);
- // missing address prefix
- assertParseFailure(parser, NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + VALID_ADDRESS_BOB,
- expectedMessage);
+ // missing status prefix
+ assertParseFailure(parser, NAME_DESC_TIKTOK + PHONE_DESC_TIKTOK + EMAIL_DESC_TIKTOK + ROLE_DESC_TIKTOK
+ + DEADLINE_DESC_TIKTOK + VALID_STATUS_TIKTOK + RECRUITER_NAME_DESC_TIKTOK, expectedMessage);
+
+ // missing recruiter name prefix
+ assertParseFailure(parser, NAME_DESC_TIKTOK + PHONE_DESC_TIKTOK + EMAIL_DESC_TIKTOK + ROLE_DESC_TIKTOK
+ + DEADLINE_DESC_TIKTOK + STATUS_DESC_TIKTOK + VALID_RECRUITER_NAME_TIKTOK, expectedMessage);
// all prefixes missing
- assertParseFailure(parser, VALID_NAME_BOB + VALID_PHONE_BOB + VALID_EMAIL_BOB + VALID_ADDRESS_BOB,
- expectedMessage);
+ assertParseFailure(parser, VALID_NAME_TIKTOK + VALID_PHONE_TIKTOK + VALID_EMAIL_TIKTOK + VALID_ROLE_TIKTOK
+ + VALID_DEADLINE_TIKTOK + VALID_STATUS_TIKTOK + VALID_RECRUITER_NAME_TIKTOK, 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);
+ assertParseFailure(parser, INVALID_NAME_DESC + PHONE_DESC_TIKTOK + EMAIL_DESC_TIKTOK
+ + ROLE_DESC_TIKTOK + DEADLINE_DESC_TIKTOK + STATUS_DESC_TIKTOK + RECRUITER_NAME_DESC_TIKTOK
+ + PRIORITY_DESC_TIKTOK, Name.MESSAGE_CONSTRAINTS_INVALID_REGEX);
// 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);
+ assertParseFailure(parser, NAME_DESC_TIKTOK + INVALID_PHONE_DESC + EMAIL_DESC_TIKTOK
+ + ROLE_DESC_TIKTOK + DEADLINE_DESC_TIKTOK + STATUS_DESC_TIKTOK + RECRUITER_NAME_DESC_TIKTOK
+ + PRIORITY_DESC_TIKTOK, Phone.MESSAGE_CONSTRAINTS_VALID_REGEX);
// 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);
+ assertParseFailure(parser, NAME_DESC_TIKTOK + PHONE_DESC_TIKTOK + INVALID_EMAIL_DESC
+ + ROLE_DESC_TIKTOK + DEADLINE_DESC_TIKTOK + STATUS_DESC_TIKTOK + RECRUITER_NAME_DESC_TIKTOK
+ + PRIORITY_DESC_TIKTOK, Email.MESSAGE_CONSTRAINTS_VALID_REGEX);
+
+ // invalid role
+ assertParseFailure(parser, NAME_DESC_TIKTOK + PHONE_DESC_TIKTOK + EMAIL_DESC_TIKTOK
+ + INVALID_ROLE_DESC + DEADLINE_DESC_TIKTOK + STATUS_DESC_TIKTOK + RECRUITER_NAME_DESC_TIKTOK
+ + PRIORITY_DESC_TIKTOK, Role.MESSAGE_CONSTRAINTS_INVALID_REGEX);
+
+ // invalid deadline
+ assertParseFailure(parser, NAME_DESC_TIKTOK + PHONE_DESC_TIKTOK + EMAIL_DESC_TIKTOK
+ + ROLE_DESC_TIKTOK + INVALID_DEADLINE_DESC + STATUS_DESC_TIKTOK + RECRUITER_NAME_DESC_TIKTOK
+ + PRIORITY_DESC_TIKTOK, Deadline.MESSAGE_CONSTRAINTS_WRONG_FORMAT);
+
+ // invalid status
+ assertParseFailure(parser, NAME_DESC_TIKTOK + PHONE_DESC_TIKTOK + EMAIL_DESC_TIKTOK
+ + ROLE_DESC_TIKTOK + DEADLINE_DESC_TIKTOK + INVALID_STATUS_DESC + RECRUITER_NAME_DESC_TIKTOK
+ + PRIORITY_DESC_TIKTOK, ApplicationStatus.MESSAGE_CONSTRAINTS_VALID_STATUS);
+
+ // invalid recruiter name
+ assertParseFailure(parser, NAME_DESC_TIKTOK + PHONE_DESC_TIKTOK + EMAIL_DESC_TIKTOK
+ + ROLE_DESC_TIKTOK + DEADLINE_DESC_TIKTOK + STATUS_DESC_TIKTOK + INVALID_RECRUITER_NAME_DESC
+ + PRIORITY_DESC_TIKTOK, RecruiterName.MESSAGE_CONSTRAINTS_INVALID_REGEX);
+
+ // invalid priority
+ assertParseFailure(parser, NAME_DESC_TIKTOK + PHONE_DESC_TIKTOK + EMAIL_DESC_TIKTOK
+ + ROLE_DESC_TIKTOK + DEADLINE_DESC_TIKTOK + STATUS_DESC_TIKTOK + RECRUITER_NAME_DESC_TIKTOK
+ + INVALID_PRIORITY_DESC, Priority.MESSAGE_CONSTRAINTS_VALID_REGEX);
// 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);
+ assertParseFailure(parser, INVALID_NAME_DESC + INVALID_PHONE_DESC + EMAIL_DESC_TIKTOK
+ + ROLE_DESC_TIKTOK + DEADLINE_DESC_TIKTOK + STATUS_DESC_TIKTOK
+ + RECRUITER_NAME_DESC_TIKTOK + PRIORITY_DESC_TIKTOK, Name.MESSAGE_CONSTRAINTS_INVALID_REGEX);
// 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,
+ assertParseFailure(parser, PREAMBLE_NON_EMPTY + NAME_DESC_TIKTOK + PHONE_DESC_TIKTOK + EMAIL_DESC_TIKTOK
+ + STATUS_DESC_TIKTOK + RECRUITER_NAME_DESC_TIKTOK + PRIORITY_DESC_TIKTOK,
String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE));
}
+
+ @Test
+ public void parsePrefixPriority_notPresent_returnsPriorityNoneObject() {
+ String userInput = NAME_DESC_TIKTOK + PHONE_DESC_TIKTOK + EMAIL_DESC_TIKTOK
+ + ROLE_DESC_TIKTOK + DEADLINE_DESC_TIKTOK + STATUS_DESC_TIKTOK + RECRUITER_NAME_DESC_TIKTOK;
+ assertParseSuccess(parser, userInput, new AddCommand(
+ new CompanyBuilder(TIKTOK)
+ .withPriority("NONE")
+ .withRemark("No remarks")
+ .build()
+ ));
+ }
+
}
diff --git a/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java b/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java
index 5a1ab3dbc0c..2d7c7f7778d 100644
--- a/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java
+++ b/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java
@@ -5,7 +5,7 @@
import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
import static seedu.address.logic.Messages.MESSAGE_UNKNOWN_COMMAND;
import static seedu.address.testutil.Assert.assertThrows;
-import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
+import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_COMPANY;
import java.util.Arrays;
import java.util.List;
@@ -17,17 +17,19 @@
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.FilterCommand;
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;
+import seedu.address.model.company.ApplicationStatus;
+import seedu.address.model.company.Company;
+import seedu.address.model.company.predicates.ApplicationStatusPredicate;
+import seedu.address.model.company.predicates.NameContainsKeywordsPredicate;
+import seedu.address.testutil.CompanyBuilder;
+import seedu.address.testutil.CompanyUtil;
+import seedu.address.testutil.EditCompanyDescriptorBuilder;
public class AddressBookParserTest {
@@ -35,9 +37,9 @@ public class AddressBookParserTest {
@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);
+ Company company = new CompanyBuilder().build();
+ AddCommand command = (AddCommand) parser.parseCommand(CompanyUtil.getAddCommand(company));
+ assertEquals(new AddCommand(company), command);
}
@Test
@@ -49,17 +51,17 @@ public void parseCommand_clear() throws Exception {
@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);
+ DeleteCommand.COMMAND_WORD + " " + INDEX_FIRST_COMPANY.getOneBased());
+ assertEquals(new DeleteCommand(INDEX_FIRST_COMPANY), command);
}
@Test
public void parseCommand_edit() throws Exception {
- Person person = new PersonBuilder().build();
- EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(person).build();
+ Company company = new CompanyBuilder().build();
+ EditCommand.EditCompanyDescriptor descriptor = new EditCompanyDescriptorBuilder(company).build();
EditCommand command = (EditCommand) parser.parseCommand(EditCommand.COMMAND_WORD + " "
- + INDEX_FIRST_PERSON.getOneBased() + " " + PersonUtil.getEditPersonDescriptorDetails(descriptor));
- assertEquals(new EditCommand(INDEX_FIRST_PERSON, descriptor), command);
+ + INDEX_FIRST_COMPANY.getOneBased() + " " + CompanyUtil.getEditCompanyDescriptorDetails(descriptor));
+ assertEquals(new EditCommand(INDEX_FIRST_COMPANY, descriptor), command);
}
@Test
@@ -88,6 +90,15 @@ public void parseCommand_list() throws Exception {
assertTrue(parser.parseCommand(ListCommand.COMMAND_WORD + " 3") instanceof ListCommand);
}
+ @Test
+ public void parseCommand_filter() throws Exception {
+ Company company = new CompanyBuilder().build();
+ ApplicationStatus status = company.getStatus();
+ ApplicationStatusPredicate predicate = new ApplicationStatusPredicate(status);
+ FilterCommand command = (FilterCommand) parser.parseCommand(FilterCommand.COMMAND_WORD + " s/" + status);
+ assertEquals(new FilterCommand(status, predicate), command);
+ }
+
@Test
public void parseCommand_unrecognisedInput_throwsParseException() {
assertThrows(ParseException.class, String.format(MESSAGE_INVALID_COMMAND_FORMAT, HelpCommand.MESSAGE_USAGE), ()
diff --git a/src/test/java/seedu/address/logic/parser/DeleteCommandParserTest.java b/src/test/java/seedu/address/logic/parser/DeleteCommandParserTest.java
index 6a40e14a649..fea98e59850 100644
--- a/src/test/java/seedu/address/logic/parser/DeleteCommandParserTest.java
+++ b/src/test/java/seedu/address/logic/parser/DeleteCommandParserTest.java
@@ -1,9 +1,9 @@
package seedu.address.logic.parser;
-import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.address.logic.Messages.MESSAGE_NON_INTEGER_INDEX;
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_FIRST_COMPANY;
import org.junit.jupiter.api.Test;
@@ -22,11 +22,11 @@ public class DeleteCommandParserTest {
@Test
public void parse_validArgs_returnsDeleteCommand() {
- assertParseSuccess(parser, "1", new DeleteCommand(INDEX_FIRST_PERSON));
+ assertParseSuccess(parser, "1", new DeleteCommand(INDEX_FIRST_COMPANY));
}
@Test
public void parse_invalidArgs_throwsParseException() {
- assertParseFailure(parser, "a", String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE));
+ assertParseFailure(parser, "a", MESSAGE_NON_INTEGER_INDEX);
}
}
diff --git a/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java b/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java
index cc7175172d4..800449f5817 100644
--- a/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java
+++ b/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java
@@ -1,54 +1,53 @@
package seedu.address.logic.parser;
+import static seedu.address.logic.Messages.MESSAGE_EMPTY_INDEX;
import static seedu.address.logic.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.Messages.MESSAGE_NON_POSITIVE_INTEGER_INDEX;
+import static seedu.address.logic.commands.CommandTestUtil.EMAIL_DESC_GOOGLE;
+import static seedu.address.logic.commands.CommandTestUtil.EMAIL_DESC_TIKTOK;
+import static seedu.address.logic.commands.CommandTestUtil.INVALID_DEADLINE_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_EMAIL_AMY;
-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_ADDRESS;
+import static seedu.address.logic.commands.CommandTestUtil.INVALID_PRIORITY_DESC;
+import static seedu.address.logic.commands.CommandTestUtil.INVALID_STATUS_DESC;
+import static seedu.address.logic.commands.CommandTestUtil.NAME_DESC_GOOGLE;
+import static seedu.address.logic.commands.CommandTestUtil.PHONE_DESC_GOOGLE;
+import static seedu.address.logic.commands.CommandTestUtil.PHONE_DESC_TIKTOK;
+import static seedu.address.logic.commands.CommandTestUtil.PRIORITY_DESC_GOOGLE;
+import static seedu.address.logic.commands.CommandTestUtil.PRIORITY_DESC_TIKTOK;
+import static seedu.address.logic.commands.CommandTestUtil.REMARK_DESC_GOOGLE;
+import static seedu.address.logic.commands.CommandTestUtil.ROLE_DESC_GOOGLE;
+import static seedu.address.logic.commands.CommandTestUtil.STATUS_DESC_GOOGLE;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_GOOGLE;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_GOOGLE;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_GOOGLE;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_TIKTOK;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_PRIORITY_GOOGLE;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_PRIORITY_TIKTOK;
import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL;
import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE;
-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 static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_COMPANY;
+import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_COMPANY;
+import static seedu.address.testutil.TypicalIndexes.INDEX_THIRD_COMPANY;
import org.junit.jupiter.api.Test;
import seedu.address.commons.core.index.Index;
import seedu.address.logic.Messages;
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;
+import seedu.address.model.company.ApplicationStatus;
+import seedu.address.model.company.Deadline;
+import seedu.address.model.company.Email;
+import seedu.address.model.company.Name;
+import seedu.address.model.company.Phone;
+import seedu.address.model.company.Priority;
+import seedu.address.testutil.EditCompanyDescriptorBuilder;
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);
@@ -57,22 +56,22 @@ public class EditCommandParserTest {
@Test
public void parse_missingParts_failure() {
// no index specified
- assertParseFailure(parser, VALID_NAME_AMY, MESSAGE_INVALID_FORMAT);
+ assertParseFailure(parser, NAME_DESC_GOOGLE, MESSAGE_EMPTY_INDEX);
// no field specified
assertParseFailure(parser, "1", EditCommand.MESSAGE_NOT_EDITED);
// no index and no field specified
- assertParseFailure(parser, "", MESSAGE_INVALID_FORMAT);
+ assertParseFailure(parser, "", MESSAGE_EMPTY_INDEX);
}
@Test
public void parse_invalidPreamble_failure() {
// negative index
- assertParseFailure(parser, "-5" + NAME_DESC_AMY, MESSAGE_INVALID_FORMAT);
+ assertParseFailure(parser, "-5" + NAME_DESC_GOOGLE, MESSAGE_NON_POSITIVE_INTEGER_INDEX);
// zero index
- assertParseFailure(parser, "0" + NAME_DESC_AMY, MESSAGE_INVALID_FORMAT);
+ assertParseFailure(parser, "0" + NAME_DESC_GOOGLE, MESSAGE_NON_POSITIVE_INTEGER_INDEX);
// invalid arguments being parsed as preamble
assertParseFailure(parser, "1 some random string", MESSAGE_INVALID_FORMAT);
@@ -81,37 +80,52 @@ public void parse_invalidPreamble_failure() {
assertParseFailure(parser, "1 i/ string", MESSAGE_INVALID_FORMAT);
}
+ @Test
+ public void parse_remarkField_failure() {
+ // only remark field
+ assertParseFailure(parser, "1" + REMARK_DESC_GOOGLE, MESSAGE_INVALID_FORMAT);
+
+
+ // remark field parsed with other fields
+ assertParseFailure(parser, "1" + ROLE_DESC_GOOGLE + REMARK_DESC_GOOGLE, MESSAGE_INVALID_FORMAT);
+ assertParseFailure(parser, "1" + REMARK_DESC_GOOGLE + PHONE_DESC_GOOGLE + STATUS_DESC_GOOGLE,
+ 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 name
+ assertParseFailure(parser, "1" + INVALID_NAME_DESC, Name.MESSAGE_CONSTRAINTS_INVALID_REGEX);
+ // invalid phone
+ assertParseFailure(parser, "1" + INVALID_PHONE_DESC, Phone.MESSAGE_CONSTRAINTS_VALID_REGEX);
+ // invalid email
+ assertParseFailure(parser, "1" + INVALID_EMAIL_DESC, Email.MESSAGE_CONSTRAINTS_VALID_REGEX);
+ // invalid deadline
+ assertParseFailure(parser, "1" + INVALID_DEADLINE_DESC, Deadline.MESSAGE_CONSTRAINTS_WRONG_FORMAT);
+ // invalid status
+ assertParseFailure(parser, "1" + INVALID_STATUS_DESC,
+ ApplicationStatus.MESSAGE_CONSTRAINTS_VALID_STATUS);
+ //invalid priority
+ assertParseFailure(parser, "1" + INVALID_PRIORITY_DESC, Priority.MESSAGE_CONSTRAINTS_VALID_REGEX);
- // invalid phone followed by valid email
- assertParseFailure(parser, "1" + INVALID_PHONE_DESC + EMAIL_DESC_AMY, 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);
+ // invalid phone followed by valid email
+ assertParseFailure(parser, "1" + INVALID_PHONE_DESC + EMAIL_DESC_GOOGLE, Phone.MESSAGE_CONSTRAINTS_VALID_REGEX);
// 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);
+ assertParseFailure(parser, "1" + INVALID_NAME_DESC + INVALID_EMAIL_DESC + VALID_PHONE_GOOGLE,
+ Name.MESSAGE_CONSTRAINTS_INVALID_REGEX);
}
@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;
+ Index targetIndex = INDEX_SECOND_COMPANY;
+ String userInput = targetIndex.getOneBased() + PHONE_DESC_TIKTOK
+ + EMAIL_DESC_GOOGLE + NAME_DESC_GOOGLE + PRIORITY_DESC_TIKTOK;
- 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.EditCompanyDescriptor descriptor = new EditCompanyDescriptorBuilder().withName(VALID_NAME_GOOGLE)
+ .withPhone(VALID_PHONE_TIKTOK).withEmail(VALID_EMAIL_GOOGLE).withPriority(VALID_PRIORITY_TIKTOK)
+ .build();
EditCommand expectedCommand = new EditCommand(targetIndex, descriptor);
assertParseSuccess(parser, userInput, expectedCommand);
@@ -119,11 +133,11 @@ public void parse_allFieldsSpecified_success() {
@Test
public void parse_someFieldsSpecified_success() {
- Index targetIndex = INDEX_FIRST_PERSON;
- String userInput = targetIndex.getOneBased() + PHONE_DESC_BOB + EMAIL_DESC_AMY;
+ Index targetIndex = INDEX_FIRST_COMPANY;
+ String userInput = targetIndex.getOneBased() + PHONE_DESC_TIKTOK + EMAIL_DESC_GOOGLE;
- EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withPhone(VALID_PHONE_BOB)
- .withEmail(VALID_EMAIL_AMY).build();
+ EditCommand.EditCompanyDescriptor descriptor = new EditCompanyDescriptorBuilder().withPhone(VALID_PHONE_TIKTOK)
+ .withEmail(VALID_EMAIL_GOOGLE).build();
EditCommand expectedCommand = new EditCommand(targetIndex, descriptor);
assertParseSuccess(parser, userInput, expectedCommand);
@@ -132,33 +146,28 @@ public void parse_someFieldsSpecified_success() {
@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();
+ Index targetIndex = INDEX_THIRD_COMPANY;
+ String userInput = targetIndex.getOneBased() + NAME_DESC_GOOGLE;
+ EditCommand.EditCompanyDescriptor descriptor = new EditCompanyDescriptorBuilder()
+ .withName(VALID_NAME_GOOGLE).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();
+ userInput = targetIndex.getOneBased() + PHONE_DESC_GOOGLE;
+ descriptor = new EditCompanyDescriptorBuilder().withPhone(VALID_PHONE_GOOGLE).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();
+ userInput = targetIndex.getOneBased() + EMAIL_DESC_GOOGLE;
+ descriptor = new EditCompanyDescriptorBuilder().withEmail(VALID_EMAIL_GOOGLE).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();
+ // priority
+ userInput = targetIndex.getOneBased() + PRIORITY_DESC_GOOGLE;
+ descriptor = new EditCompanyDescriptorBuilder().withPriority(VALID_PRIORITY_GOOGLE).build();
expectedCommand = new EditCommand(targetIndex, descriptor);
assertParseSuccess(parser, userInput, expectedCommand);
}
@@ -169,40 +178,29 @@ public void parse_multipleRepeatedFields_failure() {
// AddCommandParserTest#parse_repeatedNonTagValue_failure()
// valid followed by invalid
- Index targetIndex = INDEX_FIRST_PERSON;
- String userInput = targetIndex.getOneBased() + INVALID_PHONE_DESC + PHONE_DESC_BOB;
+ Index targetIndex = INDEX_FIRST_COMPANY;
+ String userInput = targetIndex.getOneBased() + INVALID_PHONE_DESC + PHONE_DESC_TIKTOK;
assertParseFailure(parser, userInput, Messages.getErrorMessageForDuplicatePrefixes(PREFIX_PHONE));
// invalid followed by valid
- userInput = targetIndex.getOneBased() + PHONE_DESC_BOB + INVALID_PHONE_DESC;
+ userInput = targetIndex.getOneBased() + PHONE_DESC_TIKTOK + INVALID_PHONE_DESC;
assertParseFailure(parser, userInput, Messages.getErrorMessageForDuplicatePrefixes(PREFIX_PHONE));
- // mulltiple valid fields repeated
- 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;
+ // multiple valid fields repeated
+ userInput = targetIndex.getOneBased() + PHONE_DESC_GOOGLE + EMAIL_DESC_GOOGLE
+ + PHONE_DESC_GOOGLE + EMAIL_DESC_GOOGLE
+ + PHONE_DESC_TIKTOK + EMAIL_DESC_TIKTOK;
assertParseFailure(parser, userInput,
- Messages.getErrorMessageForDuplicatePrefixes(PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS));
+ Messages.getErrorMessageForDuplicatePrefixes(PREFIX_PHONE, PREFIX_EMAIL));
// multiple invalid values
- userInput = targetIndex.getOneBased() + INVALID_PHONE_DESC + INVALID_ADDRESS_DESC + INVALID_EMAIL_DESC
- + INVALID_PHONE_DESC + INVALID_ADDRESS_DESC + INVALID_EMAIL_DESC;
+ userInput = targetIndex.getOneBased() + INVALID_PHONE_DESC + INVALID_EMAIL_DESC
+ + INVALID_PHONE_DESC + INVALID_EMAIL_DESC;
assertParseFailure(parser, userInput,
- Messages.getErrorMessageForDuplicatePrefixes(PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS));
- }
-
- @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);
+ Messages.getErrorMessageForDuplicatePrefixes(PREFIX_PHONE, PREFIX_EMAIL));
}
}
diff --git a/src/test/java/seedu/address/logic/parser/FilterCommandParserTest.java b/src/test/java/seedu/address/logic/parser/FilterCommandParserTest.java
new file mode 100644
index 00000000000..3f06dedb3d3
--- /dev/null
+++ b/src/test/java/seedu/address/logic/parser/FilterCommandParserTest.java
@@ -0,0 +1,49 @@
+package seedu.address.logic.parser;
+
+import static seedu.address.logic.Messages.MESSAGE_EMPTY_PREFIX;
+import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_STATUS;
+import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure;
+import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess;
+import static seedu.address.model.company.ApplicationStatus.MESSAGE_CONSTRAINTS_VALID_STATUS;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.address.logic.commands.FilterCommand;
+import seedu.address.model.company.ApplicationStatus;
+import seedu.address.model.company.predicates.ApplicationStatusPredicate;
+
+public class FilterCommandParserTest {
+ private FilterCommandParser parser = new FilterCommandParser();
+
+ @Test
+ public void parse_validArgs_success() {
+ ApplicationStatus status = new ApplicationStatus("pa");
+ String userInput = " " + PREFIX_STATUS + "pa";
+ ApplicationStatusPredicate predicate = new ApplicationStatusPredicate(status);
+ FilterCommand expectedFilterCommand = new FilterCommand(status, predicate);
+ assertParseSuccess(parser, userInput, expectedFilterCommand);
+ }
+
+ @Test
+ public void parse_emptyArg_failure() {
+ assertParseFailure(parser, "", String.format(MESSAGE_EMPTY_PREFIX, FilterCommand.MESSAGE_USAGE));
+ }
+
+ @Test
+ public void parse_missingPrefix_failure() {
+ assertParseFailure(parser, "pa", String.format(MESSAGE_INVALID_COMMAND_FORMAT, FilterCommand.MESSAGE_USAGE));
+ }
+
+ @Test
+ public void parse_invalidPreamble_failure() {
+ // invalid status
+ String userInput = " " + PREFIX_STATUS + "pp";
+ assertParseFailure(parser, userInput, MESSAGE_CONSTRAINTS_VALID_STATUS);
+
+ // invalid prefix
+ userInput = " " + "ss/ " + "pp";
+ assertParseFailure(parser, userInput,
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, FilterCommand.MESSAGE_USAGE));
+ }
+}
diff --git a/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java b/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java
index d92e64d12f9..e3f56effb45 100644
--- a/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java
+++ b/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java
@@ -9,7 +9,7 @@
import org.junit.jupiter.api.Test;
import seedu.address.logic.commands.FindCommand;
-import seedu.address.model.person.NameContainsKeywordsPredicate;
+import seedu.address.model.company.predicates.NameContainsKeywordsPredicate;
public class FindCommandParserTest {
@@ -31,4 +31,18 @@ public void parse_validArgs_returnsFindCommand() {
assertParseSuccess(parser, " \n Alice \n \t Bob \t", expectedFindCommand);
}
+ @Test
+ public void parse_singleKeyword_returnsFindCommand() {
+ FindCommand expectedFindCommand =
+ new FindCommand(new NameContainsKeywordsPredicate(Arrays.asList("Te")));
+ assertParseSuccess(parser, "Te", expectedFindCommand);
+ }
+
+ @Test
+ public void parse_multipleKeywordsWithDuplicate_returnsFindCommand() {
+ // When duplicates are entered, they are still considered distinct keywords
+ FindCommand expectedFindCommand =
+ new FindCommand(new NameContainsKeywordsPredicate(Arrays.asList("Tech", "Tech", "Corp")));
+ assertParseSuccess(parser, "Tech Tech Corp", expectedFindCommand);
+ }
}
diff --git a/src/test/java/seedu/address/logic/parser/ParserUtilTest.java b/src/test/java/seedu/address/logic/parser/ParserUtilTest.java
index 4256788b1a7..6734086702b 100644
--- a/src/test/java/seedu/address/logic/parser/ParserUtilTest.java
+++ b/src/test/java/seedu/address/logic/parser/ParserUtilTest.java
@@ -1,38 +1,30 @@
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.logic.Messages.MESSAGE_NON_POSITIVE_INTEGER_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 static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_COMPANY;
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;
+import seedu.address.model.company.Email;
+import seedu.address.model.company.Name;
+import seedu.address.model.company.Phone;
+import seedu.address.model.company.Priority;
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_COMPANY_NAME = "G@ogle";
+ private static final String INVALID_PHONE_NON_NUMERICAL_DIGITS = "+65&1234";
+ private static final String INVALID_PHONE_LESS_THAN_3_DIGITS = " 1 1 ";
private static final String INVALID_EMAIL = "example.com";
- private static final String INVALID_TAG = "#friend";
+ private static final String INVALID_PRIORITY = "0";
- 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_COMPANY_NAME = "Google";
+ private static final String VALID_PHONE_WITHOUT_SPACES = "98765432";
+ private static final String VALID_PHONE_IN_BETWEEN_WHITESPACES = "9 87 6 54 3 2";
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 VALID_PRIORITY = "NONE";
private static final String WHITESPACE = " \t\r\n";
@@ -43,86 +35,84 @@ public void parseIndex_invalidInput_throwsParseException() {
@Test
public void parseIndex_outOfRangeInput_throwsParseException() {
- assertThrows(ParseException.class, MESSAGE_INVALID_INDEX, ()
+ assertThrows(ParseException.class, MESSAGE_NON_POSITIVE_INTEGER_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"));
+ assertEquals(INDEX_FIRST_COMPANY, ParserUtil.parseIndex("1"));
// Leading and trailing whitespaces
- assertEquals(INDEX_FIRST_PERSON, ParserUtil.parseIndex(" 1 "));
+ assertEquals(INDEX_FIRST_COMPANY, ParserUtil.parseIndex(" 1 "));
}
@Test
public void parseName_null_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> ParserUtil.parseName((String) null));
+ assertThrows(NullPointerException.class, () -> ParserUtil.parseName(null));
}
@Test
public void parseName_invalidValue_throwsParseException() {
- assertThrows(ParseException.class, () -> ParserUtil.parseName(INVALID_NAME));
+ assertThrows(ParseException.class, () -> ParserUtil.parseName(INVALID_COMPANY_NAME));
+ }
+
+ @Test
+ public void parseName_emptyValue_throwsParseException() {
+ assertThrows(ParseException.class, () -> ParserUtil.parseName(""));
}
@Test
public void parseName_validValueWithoutWhitespace_returnsName() throws Exception {
- Name expectedName = new Name(VALID_NAME);
- assertEquals(expectedName, ParserUtil.parseName(VALID_NAME));
+ Name expectedName = new Name(VALID_COMPANY_NAME);
+ assertEquals(expectedName, ParserUtil.parseName(VALID_COMPANY_NAME));
}
@Test
public void parseName_validValueWithWhitespace_returnsTrimmedName() throws Exception {
- String nameWithWhitespace = WHITESPACE + VALID_NAME + WHITESPACE;
- Name expectedName = new Name(VALID_NAME);
+ String nameWithWhitespace = WHITESPACE + VALID_COMPANY_NAME + WHITESPACE;
+ Name expectedName = new Name(VALID_COMPANY_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));
+ assertThrows(NullPointerException.class, () -> ParserUtil.parsePhone(null));
}
@Test
- public void parsePhone_validValueWithoutWhitespace_returnsPhone() throws Exception {
- Phone expectedPhone = new Phone(VALID_PHONE);
- assertEquals(expectedPhone, ParserUtil.parsePhone(VALID_PHONE));
+ public void parsePhone_invalidValueWithNonNumerical_throwsParseException() {
+ assertThrows(ParseException.class, () -> ParserUtil.parsePhone(INVALID_PHONE_NON_NUMERICAL_DIGITS));
}
@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));
+ public void parsePhone_invalidValueWithLessThan3Digits_throwsParseException() {
+ assertThrows(ParseException.class, () -> ParserUtil.parsePhone(INVALID_PHONE_LESS_THAN_3_DIGITS));
}
@Test
- public void parseAddress_null_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> ParserUtil.parseAddress((String) null));
+ public void parsePhone_emptyValue_throwsParseException() {
+ assertThrows(ParseException.class, () -> ParserUtil.parsePhone(""));
}
@Test
- public void parseAddress_invalidValue_throwsParseException() {
- assertThrows(ParseException.class, () -> ParserUtil.parseAddress(INVALID_ADDRESS));
+ public void parsePhone_validValueWithInBetweenWhiteSpace_returnsPhone() throws Exception {
+ Phone expectedPhone = new Phone(VALID_PHONE_WITHOUT_SPACES);
+ assertEquals(expectedPhone, ParserUtil.parsePhone(VALID_PHONE_IN_BETWEEN_WHITESPACES));
}
@Test
- public void parseAddress_validValueWithoutWhitespace_returnsAddress() throws Exception {
- Address expectedAddress = new Address(VALID_ADDRESS);
- assertEquals(expectedAddress, ParserUtil.parseAddress(VALID_ADDRESS));
+ public void parsePhone_validValueWithoutWhitespace_returnsPhone() throws Exception {
+ Phone expectedPhone = new Phone(VALID_PHONE_WITHOUT_SPACES);
+ assertEquals(expectedPhone, ParserUtil.parsePhone(VALID_PHONE_WITHOUT_SPACES));
}
@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));
+ public void parsePhone_validValueWithTrailingWhitespace_returnsTrimmedPhone() throws Exception {
+ String phoneWithWhitespace = WHITESPACE + VALID_PHONE_WITHOUT_SPACES + WHITESPACE;
+ Phone expectedPhone = new Phone(VALID_PHONE_WITHOUT_SPACES);
+ assertEquals(expectedPhone, ParserUtil.parsePhone(phoneWithWhitespace));
}
@Test
@@ -135,6 +125,11 @@ public void parseEmail_invalidValue_throwsParseException() {
assertThrows(ParseException.class, () -> ParserUtil.parseEmail(INVALID_EMAIL));
}
+ @Test
+ public void parseEmail_emptyValue_throwsParseException() {
+ assertThrows(ParseException.class, () -> ParserUtil.parseEmail(""));
+ }
+
@Test
public void parseEmail_validValueWithoutWhitespace_returnsEmail() throws Exception {
Email expectedEmail = new Email(VALID_EMAIL);
@@ -149,48 +144,30 @@ public void parseEmail_validValueWithWhitespace_returnsTrimmedEmail() throws Exc
}
@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));
+ public void parsePriority_null_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> ParserUtil.parsePriority((String) null));
}
@Test
- public void parseTags_null_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> ParserUtil.parseTags(null));
+ public void parsePriority_invalidValue_throwsParseException() {
+ assertThrows(ParseException.class, () -> ParserUtil.parsePriority(INVALID_PRIORITY));
}
@Test
- public void parseTags_collectionWithInvalidTags_throwsParseException() {
- assertThrows(ParseException.class, () -> ParserUtil.parseTags(Arrays.asList(VALID_TAG_1, INVALID_TAG)));
+ public void parsePriority_emptyValue_throwsParseException() {
+ assertThrows(ParseException.class, () -> ParserUtil.parsePriority(""));
}
@Test
- public void parseTags_emptyCollection_returnsEmptySet() throws Exception {
- assertTrue(ParserUtil.parseTags(Collections.emptyList()).isEmpty());
+ public void parsePriority_validValueWithoutWhitespace_returnsPriority() throws Exception {
+ Priority expectedPriority = new Priority(VALID_PRIORITY);
+ assertEquals(expectedPriority, ParserUtil.parsePriority(VALID_PRIORITY));
}
@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);
+ public void parsePriority_validValueWithWhitespace_returnsTrimmedPriority() throws Exception {
+ String priorityWithWhitespace = WHITESPACE + VALID_PRIORITY + WHITESPACE;
+ Priority expectedPriority = new Priority(VALID_PRIORITY);
+ assertEquals(expectedPriority, ParserUtil.parsePriority(priorityWithWhitespace));
}
}
diff --git a/src/test/java/seedu/address/logic/parser/RemarkCommandParserTest.java b/src/test/java/seedu/address/logic/parser/RemarkCommandParserTest.java
new file mode 100644
index 00000000000..5afa9900826
--- /dev/null
+++ b/src/test/java/seedu/address/logic/parser/RemarkCommandParserTest.java
@@ -0,0 +1,53 @@
+package seedu.address.logic.parser;
+
+import static seedu.address.logic.Messages.MESSAGE_EMPTY_INDEX;
+import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.address.logic.commands.CommandTestUtil.INVALID_REMARK_DESC;
+import static seedu.address.logic.commands.CommandTestUtil.REMARK_DESC_GOOGLE;
+import static seedu.address.logic.commands.CommandTestUtil.REMARK_DESC_TIKTOK;
+import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure;
+import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess;
+import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_COMPANY;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.address.commons.core.index.Index;
+import seedu.address.logic.commands.RemarkCommand;
+import seedu.address.model.company.Remark;
+
+public class RemarkCommandParserTest {
+ private RemarkCommandParser parser = new RemarkCommandParser();
+ private final String nonEmptyRemark = "Some remark.";
+
+ @Test
+ public void parse_indexSpecified_success() {
+ // have remark
+ Index targetIndex = INDEX_FIRST_COMPANY;
+ String userInput = targetIndex.getOneBased() + REMARK_DESC_GOOGLE;
+ RemarkCommand expectedCommand = new RemarkCommand(INDEX_FIRST_COMPANY, new Remark("Java/Python"));
+ assertParseSuccess(parser, userInput, expectedCommand);
+ }
+
+ @Test
+ public void parse_missingCompulsoryField_failure() {
+ Index targetIndex = INDEX_FIRST_COMPANY;
+ String expectedMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, RemarkCommand.MESSAGE_USAGE);
+
+ // no prefix
+ assertParseFailure(parser, targetIndex.getOneBased() + nonEmptyRemark, expectedMessage);
+
+ // no index
+ assertParseFailure(parser, REMARK_DESC_TIKTOK, MESSAGE_EMPTY_INDEX);
+
+ // no remark
+ expectedMessage = Remark.MESSAGE_CONSTRAINTS;
+ String userInput = targetIndex.getOneBased() + INVALID_REMARK_DESC;
+ assertParseFailure(parser, userInput, expectedMessage);
+
+ // no prefix and remark
+ expectedMessage = RemarkCommand.MESSAGE_NO_REMARK;
+ userInput = targetIndex.getOneBased() + "";
+ assertParseFailure(parser, userInput, expectedMessage);
+
+ }
+}
diff --git a/src/test/java/seedu/address/logic/parser/SortCommandParserTest.java b/src/test/java/seedu/address/logic/parser/SortCommandParserTest.java
new file mode 100644
index 00000000000..c38b6154c42
--- /dev/null
+++ b/src/test/java/seedu/address/logic/parser/SortCommandParserTest.java
@@ -0,0 +1,42 @@
+package seedu.address.logic.parser;
+
+import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure;
+import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.address.logic.SortOrder;
+import seedu.address.logic.commands.SortCommand;
+
+public class SortCommandParserTest {
+ private SortCommandParser parser = new SortCommandParser();
+
+ @Test
+ public void parse_validAscendingInputs_success() {
+ // various valid ways to denote ascending
+ assertParseSuccess(parser, "a", new SortCommand(SortOrder.ASCENDING));
+ assertParseSuccess(parser, "asc", new SortCommand(SortOrder.ASCENDING));
+ assertParseSuccess(parser, "ascending", new SortCommand(SortOrder.ASCENDING));
+ }
+
+ @Test
+ public void parse_validDescendingInputs_success() {
+ // various valid ways to denote descending
+ assertParseSuccess(parser, "d", new SortCommand(SortOrder.DESCENDING));
+ assertParseSuccess(parser, "desc", new SortCommand(SortOrder.DESCENDING));
+ assertParseSuccess(parser, "descending", new SortCommand(SortOrder.DESCENDING));
+ }
+
+ @Test
+ public void parse_defaultBehavior_success() {
+ // default to ascending when no order is specified
+ assertParseSuccess(parser, "", new SortCommand(SortOrder.ASCENDING));
+ }
+
+ @Test
+ public void parse_invalidInputs_throwsParseException() {
+ // invalid sort order
+ assertParseFailure(parser, "invalidOrder",
+ String.format(SortCommand.MESSAGE_INVALID_SORT_ORDER, SortCommand.MESSAGE_USAGE));
+ }
+}
diff --git a/src/test/java/seedu/address/logic/parser/UnremarkCommandParserTest.java b/src/test/java/seedu/address/logic/parser/UnremarkCommandParserTest.java
new file mode 100644
index 00000000000..5dc18249fd1
--- /dev/null
+++ b/src/test/java/seedu/address/logic/parser/UnremarkCommandParserTest.java
@@ -0,0 +1,42 @@
+package seedu.address.logic.parser;
+
+import static seedu.address.logic.Messages.MESSAGE_EMPTY_INDEX;
+import static seedu.address.logic.Messages.MESSAGE_NON_INTEGER_INDEX;
+import static seedu.address.logic.Messages.MESSAGE_NON_POSITIVE_INTEGER_INDEX;
+import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure;
+import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess;
+import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_COMPANY;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.address.commons.core.index.Index;
+import seedu.address.logic.commands.RemarkCommand;
+import seedu.address.model.company.Remark;
+
+public class UnremarkCommandParserTest {
+ private UnremarkCommandParser parser = new UnremarkCommandParser();
+
+ @Test
+ public void parse_indexSpecified_success() {
+ // have remark
+ Index targetIndex = INDEX_FIRST_COMPANY;
+ String userInput = targetIndex.getOneBased() + " ";
+ RemarkCommand expectedCommand = new RemarkCommand(INDEX_FIRST_COMPANY, new Remark("No remarks"));
+ assertParseSuccess(parser, userInput, expectedCommand);
+ }
+
+ @Test
+ public void parse_invalidIndex_failure() {
+
+ // no index
+ assertParseFailure(parser, " ", MESSAGE_EMPTY_INDEX);
+
+ // non-positive index
+ assertParseFailure(parser, " 0 ", MESSAGE_NON_POSITIVE_INTEGER_INDEX);
+
+ //invalid index
+ assertParseFailure(parser, " 123** ", MESSAGE_NON_INTEGER_INDEX);
+
+
+ }
+}
diff --git a/src/test/java/seedu/address/logic/parser/ViewCommandParserTest.java b/src/test/java/seedu/address/logic/parser/ViewCommandParserTest.java
new file mode 100644
index 00000000000..11c4dce129d
--- /dev/null
+++ b/src/test/java/seedu/address/logic/parser/ViewCommandParserTest.java
@@ -0,0 +1,25 @@
+package seedu.address.logic.parser;
+
+import static seedu.address.logic.Messages.MESSAGE_NON_INTEGER_INDEX;
+import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure;
+import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess;
+import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_COMPANY;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.address.logic.commands.ViewCommand;
+
+public class ViewCommandParserTest {
+
+ private ViewCommandParser parser = new ViewCommandParser();
+
+ @Test
+ public void parse_validArgs_returnsDeleteCommand() {
+ assertParseSuccess(parser, "1", new ViewCommand(INDEX_FIRST_COMPANY));
+ }
+
+ @Test
+ public void parse_invalidArgs_throwsParseException() {
+ assertParseFailure(parser, "a", MESSAGE_NON_INTEGER_INDEX);
+ }
+}
diff --git a/src/test/java/seedu/address/model/AddressBookTest.java b/src/test/java/seedu/address/model/AddressBookTest.java
index 68c8c5ba4d5..d345bf53048 100644
--- a/src/test/java/seedu/address/model/AddressBookTest.java
+++ b/src/test/java/seedu/address/model/AddressBookTest.java
@@ -3,11 +3,9 @@
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 static seedu.address.testutil.TypicalCompanies.META;
+import static seedu.address.testutil.TypicalCompanies.getTypicalAddressBook;
import java.util.Arrays;
import java.util.Collection;
@@ -18,9 +16,9 @@
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;
+import seedu.address.model.company.Company;
+import seedu.address.model.company.exceptions.DuplicateCompanyException;
+import seedu.address.testutil.CompanyBuilder;
public class AddressBookTest {
@@ -28,7 +26,7 @@ public class AddressBookTest {
@Test
public void constructor() {
- assertEquals(Collections.emptyList(), addressBook.getPersonList());
+ assertEquals(Collections.emptyList(), addressBook.getCompanyList());
}
@Test
@@ -44,64 +42,69 @@ public void resetData_withValidReadOnlyAddressBook_replacesData() {
}
@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)
+ public void resetData_withDuplicateCompanies_throwsDuplicateCompanyException() {
+ // Two companies with the same identity fields
+ Company editedMeta = new CompanyBuilder(META)
.build();
- List newPersons = Arrays.asList(ALICE, editedAlice);
- AddressBookStub newData = new AddressBookStub(newPersons);
+ List newCompanies = Arrays.asList(META, editedMeta);
+ AddressBookStub newData = new AddressBookStub(newCompanies);
- assertThrows(DuplicatePersonException.class, () -> addressBook.resetData(newData));
+ assertThrows(DuplicateCompanyException.class, () -> addressBook.resetData(newData));
}
@Test
- public void hasPerson_nullPerson_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> addressBook.hasPerson(null));
+ public void hasCompany_nullCompany_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> addressBook.hasCompany(null));
}
@Test
- public void hasPerson_personNotInAddressBook_returnsFalse() {
- assertFalse(addressBook.hasPerson(ALICE));
+ public void hasCompany_companyNotInAddressBook_returnsFalse() {
+ assertFalse(addressBook.hasCompany(META));
}
@Test
- public void hasPerson_personInAddressBook_returnsTrue() {
- addressBook.addPerson(ALICE);
- assertTrue(addressBook.hasPerson(ALICE));
+ public void hasCompany_companyInAddressBook_returnsTrue() {
+ addressBook.addCompany(META);
+ assertTrue(addressBook.hasCompany(META));
}
@Test
- public void hasPerson_personWithSameIdentityFieldsInAddressBook_returnsTrue() {
- addressBook.addPerson(ALICE);
- Person editedAlice = new PersonBuilder(ALICE).withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND)
+ public void hasCompany_companyWithSameIdentityFieldsInAddressBook_returnsTrue() {
+ addressBook.addCompany(META);
+ Company editedMeta = new CompanyBuilder(META)
.build();
- assertTrue(addressBook.hasPerson(editedAlice));
+ assertTrue(addressBook.hasCompany(editedMeta));
}
@Test
- public void getPersonList_modifyList_throwsUnsupportedOperationException() {
- assertThrows(UnsupportedOperationException.class, () -> addressBook.getPersonList().remove(0));
+ public void getCompanyList_modifyList_throwsUnsupportedOperationException() {
+ assertThrows(UnsupportedOperationException.class, () -> addressBook.getCompanyList().remove(0));
}
@Test
public void toStringMethod() {
- String expected = AddressBook.class.getCanonicalName() + "{persons=" + addressBook.getPersonList() + "}";
+ String expected = AddressBook.class.getCanonicalName() + "{companies=" + addressBook.getCompanyList() + "}";
assertEquals(expected, addressBook.toString());
}
/**
- * A stub ReadOnlyAddressBook whose persons list can violate interface constraints.
+ * A stub ReadOnlyAddressBook whose companies list can violate interface constraints.
*/
private static class AddressBookStub implements ReadOnlyAddressBook {
- private final ObservableList persons = FXCollections.observableArrayList();
+ private final ObservableList companies = FXCollections.observableArrayList();
- AddressBookStub(Collection persons) {
- this.persons.setAll(persons);
+ AddressBookStub(Collection companies) {
+ this.companies.setAll(companies);
}
@Override
- public ObservableList getPersonList() {
- return persons;
+ public ObservableList getCompanyList() {
+ return companies;
+ }
+
+ @Override
+ public ObservableList getCurrentViewedCompany() {
+ return companies;
}
}
diff --git a/src/test/java/seedu/address/model/ModelManagerTest.java b/src/test/java/seedu/address/model/ModelManagerTest.java
index 2cf1418d116..6186fb9197a 100644
--- a/src/test/java/seedu/address/model/ModelManagerTest.java
+++ b/src/test/java/seedu/address/model/ModelManagerTest.java
@@ -3,10 +3,10 @@
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.model.Model.PREDICATE_SHOW_ALL_COMPANIES;
import static seedu.address.testutil.Assert.assertThrows;
-import static seedu.address.testutil.TypicalPersons.ALICE;
-import static seedu.address.testutil.TypicalPersons.BENSON;
+import static seedu.address.testutil.TypicalCompanies.AMAZON;
+import static seedu.address.testutil.TypicalCompanies.META;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -15,7 +15,7 @@
import org.junit.jupiter.api.Test;
import seedu.address.commons.core.GuiSettings;
-import seedu.address.model.person.NameContainsKeywordsPredicate;
+import seedu.address.model.company.predicates.NameContainsKeywordsPredicate;
import seedu.address.testutil.AddressBookBuilder;
public class ModelManagerTest {
@@ -73,29 +73,29 @@ public void setAddressBookFilePath_validPath_setsAddressBookFilePath() {
}
@Test
- public void hasPerson_nullPerson_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> modelManager.hasPerson(null));
+ public void hasCompany_nullCompany_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> modelManager.hasCompany(null));
}
@Test
- public void hasPerson_personNotInAddressBook_returnsFalse() {
- assertFalse(modelManager.hasPerson(ALICE));
+ public void hasCompany_companyNotInAddressBook_returnsFalse() {
+ assertFalse(modelManager.hasCompany(META));
}
@Test
- public void hasPerson_personInAddressBook_returnsTrue() {
- modelManager.addPerson(ALICE);
- assertTrue(modelManager.hasPerson(ALICE));
+ public void hasCompany_companyInAddressBook_returnsTrue() {
+ modelManager.addCompany(META);
+ assertTrue(modelManager.hasCompany(META));
}
@Test
- public void getFilteredPersonList_modifyList_throwsUnsupportedOperationException() {
- assertThrows(UnsupportedOperationException.class, () -> modelManager.getFilteredPersonList().remove(0));
+ public void getFilteredCompanyList_modifyList_throwsUnsupportedOperationException() {
+ assertThrows(UnsupportedOperationException.class, () -> modelManager.getFilteredCompanyList().remove(0));
}
@Test
public void equals() {
- AddressBook addressBook = new AddressBookBuilder().withPerson(ALICE).withPerson(BENSON).build();
+ AddressBook addressBook = new AddressBookBuilder().withCompany(META).withCompany(AMAZON).build();
AddressBook differentAddressBook = new AddressBook();
UserPrefs userPrefs = new UserPrefs();
@@ -117,12 +117,12 @@ public void equals() {
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)));
+ String[] keywords = META.getName().fullName.split("\\s+");
+ modelManager.updateFilteredCompanyList(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);
+ modelManager.updateFilteredCompanyList(PREDICATE_SHOW_ALL_COMPANIES);
// different userPrefs -> returns false
UserPrefs differentUserPrefs = new UserPrefs();
diff --git a/src/test/java/seedu/address/model/company/CompanyTest.java b/src/test/java/seedu/address/model/company/CompanyTest.java
new file mode 100644
index 00000000000..812213919e1
--- /dev/null
+++ b/src/test/java/seedu/address/model/company/CompanyTest.java
@@ -0,0 +1,106 @@
+package seedu.address.model.company;
+
+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_DEADLINE_TIKTOK;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_TIKTOK;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_TIKTOK;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_TIKTOK;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_ROLE_TIKTOK;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_STATUS_TIKTOK;
+import static seedu.address.testutil.TypicalCompanies.META;
+import static seedu.address.testutil.TypicalCompanies.TIKTOK;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.address.testutil.CompanyBuilder;
+
+public class CompanyTest {
+ @Test
+ public void isSameCompany() {
+ // same object -> returns true
+ assertTrue(META.isSameCompany(META));
+
+ // null -> returns false
+ assertFalse(META.isSameCompany(null));
+
+ // same name, same role and deadline all other attributes different -> returns true
+ Company editedMeta = new CompanyBuilder(META).withPhone(VALID_PHONE_TIKTOK).withEmail(VALID_EMAIL_TIKTOK)
+ .withStatus(VALID_STATUS_TIKTOK)
+ .build();
+ assertTrue(META.isSameCompany(editedMeta));
+
+ // different name, all other attributes same -> returns false
+ editedMeta = new CompanyBuilder(META).withName(VALID_NAME_TIKTOK).withRole(VALID_ROLE_TIKTOK)
+ .withDeadline(VALID_DEADLINE_TIKTOK).withStatus(VALID_STATUS_TIKTOK).build();
+ assertFalse(META.isSameCompany(editedMeta));
+
+ // name differs in case, all other attributes same -> returns true (case-insensitive)
+ Company editedTikTok = new CompanyBuilder(TIKTOK).withName(VALID_NAME_TIKTOK.toLowerCase())
+ .withRole(VALID_ROLE_TIKTOK).withDeadline(VALID_DEADLINE_TIKTOK)
+ .withStatus(VALID_STATUS_TIKTOK).build();
+ assertTrue(TIKTOK.isSameCompany(editedTikTok));
+
+ // name has trailing spaces, all other attributes same -> returns true (trailing spaces ignored)
+ String nameWithTrailingSpaces = VALID_NAME_TIKTOK + " ";
+ editedTikTok = new CompanyBuilder(TIKTOK).withName(nameWithTrailingSpaces).withRole(VALID_ROLE_TIKTOK)
+ .withDeadline(VALID_DEADLINE_TIKTOK).withStatus(VALID_STATUS_TIKTOK).build();
+ assertTrue(TIKTOK.isSameCompany(editedTikTok));
+ }
+
+ @Test
+ public void equals() {
+ // same values -> returns true
+ Company metaCopy = new CompanyBuilder(META).build();
+ assertTrue(META.equals(metaCopy));
+
+ // same object -> returns true
+ assertTrue(META.equals(META));
+
+ // null -> returns false
+ assertFalse(META.equals(null));
+
+ // different type -> returns false
+ assertFalse(META.equals(5));
+
+ // different company -> returns false
+ assertFalse(META.equals(TIKTOK));
+
+ // different name -> returns false
+ Company editedMeta = new CompanyBuilder(META).withName(VALID_NAME_TIKTOK).build();
+ assertFalse(META.equals(editedMeta));
+
+ // different phone -> returns false
+ editedMeta = new CompanyBuilder(META).withPhone(VALID_PHONE_TIKTOK).build();
+ assertFalse(META.equals(editedMeta));
+
+ // different role -> returns false
+ editedMeta = new CompanyBuilder(META).withRole(VALID_ROLE_TIKTOK).build();
+ assertFalse(META.equals(editedMeta));
+
+ //different deadline -> returns false
+ editedMeta = new CompanyBuilder(META).withDeadline(VALID_DEADLINE_TIKTOK).build();
+ assertFalse(META.equals(editedMeta));
+
+ //different status -> returns false
+ editedMeta = new CompanyBuilder(META).withStatus(VALID_STATUS_TIKTOK).build();
+ assertFalse(META.equals(editedMeta));
+
+ // different email -> returns false
+ editedMeta = new CompanyBuilder(META).withEmail(VALID_EMAIL_TIKTOK).build();
+ assertFalse(META.equals(editedMeta));
+ }
+
+ @Test
+ public void toStringMethod() {
+ String expected = Company.class.getCanonicalName() + "{name=" + META.getName() + ", role=" + META.getRole()
+ + ", status=" + META.getStatus() + ", deadline=" + META.getDeadline()
+ + ", recruiterName=" + META.getRecruiterName() + ", phone=" + META.getPhone()
+ + ", email=" + META.getEmail()
+ + ", priority=" + META.getPriority()
+ + ", remark=" + META.getRemark()
+ + "}";
+ assertEquals(expected, META.toString());
+ }
+}
diff --git a/src/test/java/seedu/address/model/person/EmailTest.java b/src/test/java/seedu/address/model/company/EmailTest.java
similarity index 99%
rename from src/test/java/seedu/address/model/person/EmailTest.java
rename to src/test/java/seedu/address/model/company/EmailTest.java
index f08cdff0a64..77143e7fa74 100644
--- a/src/test/java/seedu/address/model/person/EmailTest.java
+++ b/src/test/java/seedu/address/model/company/EmailTest.java
@@ -1,4 +1,4 @@
-package seedu.address.model.person;
+package seedu.address.model.company;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
diff --git a/src/test/java/seedu/address/model/person/NameTest.java b/src/test/java/seedu/address/model/company/NameTest.java
similarity index 61%
rename from src/test/java/seedu/address/model/person/NameTest.java
rename to src/test/java/seedu/address/model/company/NameTest.java
index 94e3dd726bd..6a635389b86 100644
--- a/src/test/java/seedu/address/model/person/NameTest.java
+++ b/src/test/java/seedu/address/model/company/NameTest.java
@@ -1,4 +1,4 @@
-package seedu.address.model.person;
+package seedu.address.model.company;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -28,14 +28,14 @@ public void isValidName() {
assertFalse(Name.isValidName("")); // empty string
assertFalse(Name.isValidName(" ")); // spaces only
assertFalse(Name.isValidName("^")); // only non-alphanumeric characters
- assertFalse(Name.isValidName("peter*")); // contains non-alphanumeric characters
+ assertFalse(Name.isValidName("google*")); // contains non-alphanumeric characters
// valid name
- assertTrue(Name.isValidName("peter jack")); // alphabets only
+ assertTrue(Name.isValidName("google")); // alphabets only
assertTrue(Name.isValidName("12345")); // numbers only
- assertTrue(Name.isValidName("peter the 2nd")); // alphanumeric characters
- assertTrue(Name.isValidName("Capital Tan")); // with capital letters
- assertTrue(Name.isValidName("David Roger Jackson Ray Jr 2nd")); // long names
+ assertTrue(Name.isValidName("3M")); // alphanumeric characters
+ assertTrue(Name.isValidName("Lenevo Group")); // with capital letters
+ assertTrue(Name.isValidName("Source Code Software Company")); // long names
}
@Test
@@ -56,5 +56,24 @@ public void equals() {
// different values -> returns false
assertFalse(name.equals(new Name("Other Valid Name")));
+
+ // different case -> returns true
+ assertTrue(name.equals(new Name("VALID NAME")));
+
+ // different case -> returns true
+ assertTrue(name.equals(new Name("valid name")));
+
+ name = new Name("Valid Name 123");
+
+ // Alphanumerics preserved -> returns true
+ assertTrue(name.equals(new Name("Valid Name 123")));
+
+ name = new Name("Valid Name 2");
+
+ //Does not strip numbers
+ assertFalse(name.equals(new Name("Valid Name ")));
+
+ assertFalse(name.equals(new Name("Valid Name")));
+
}
}
diff --git a/src/test/java/seedu/address/model/person/PhoneTest.java b/src/test/java/seedu/address/model/company/PhoneTest.java
similarity index 57%
rename from src/test/java/seedu/address/model/person/PhoneTest.java
rename to src/test/java/seedu/address/model/company/PhoneTest.java
index deaaa5ba190..455758f3b2c 100644
--- a/src/test/java/seedu/address/model/person/PhoneTest.java
+++ b/src/test/java/seedu/address/model/company/PhoneTest.java
@@ -1,4 +1,4 @@
-package seedu.address.model.person;
+package seedu.address.model.company;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -24,18 +24,29 @@ public void isValidPhone() {
// null phone number
assertThrows(NullPointerException.class, () -> Phone.isValidPhone(null));
- // invalid phone numbers
+ // invalid phone numbers without spaces
assertFalse(Phone.isValidPhone("")); // empty string
- assertFalse(Phone.isValidPhone(" ")); // spaces only
- assertFalse(Phone.isValidPhone("91")); // less than 3 numbers
+ assertFalse(Phone.isValidPhone("91")); // less than 3 digits
+ assertFalse(Phone.isValidPhone("-91")); // contains non-numeric characters
assertFalse(Phone.isValidPhone("phone")); // non-numeric
assertFalse(Phone.isValidPhone("9011p041")); // alphabets within digits
- assertFalse(Phone.isValidPhone("9312 1534")); // spaces within digits
+ assertFalse(Phone.isValidPhone("123456789012345678901")); // more than 20 characters (21 characters)
- // valid phone numbers
+ // invalid phone numbers with spaces
+ assertFalse(Phone.isValidPhone(" ")); // spaces only
+ assertFalse(Phone.isValidPhone("1 1")); // less than 3 digits
+ assertFalse(Phone.isValidPhone(" 1 1 ")); // less than 3 digits
+ assertFalse(Phone.isValidPhone("1234 567890 1234567 8901")); // 21 characters excluding spaces
+
+ // valid phone numbers without spaces
assertTrue(Phone.isValidPhone("911")); // exactly 3 numbers
assertTrue(Phone.isValidPhone("93121534"));
- assertTrue(Phone.isValidPhone("124293842033123")); // long phone numbers
+ assertTrue(Phone.isValidPhone("12345678901234567890")); // exactly 20 characters
+
+ // valid phone numbers with spaces
+ assertTrue(Phone.isValidPhone("1 1 1 ")); // exactly 3 digits
+ assertTrue(Phone.isValidPhone("1 1 1 1 1 1 1 1 1 1 1 1 1 1 1")); // 15 characters excluding spaces
+ assertTrue(Phone.isValidPhone("1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0")); // 20 characters excluding spaces
}
@Test
diff --git a/src/test/java/seedu/address/model/company/RecruiterNameTest.java b/src/test/java/seedu/address/model/company/RecruiterNameTest.java
new file mode 100644
index 00000000000..4ebb0d64a6f
--- /dev/null
+++ b/src/test/java/seedu/address/model/company/RecruiterNameTest.java
@@ -0,0 +1,77 @@
+package seedu.address.model.company;
+
+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 RecruiterNameTest {
+ @Test
+ public void constructor_null_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> new RecruiterName(null));
+ }
+
+ @Test
+ public void constructor_invalidRecruiterName_throwsIllegalArgumentException() {
+ String invalidRecruiterName = "";
+ assertThrows(IllegalArgumentException.class, () -> new RecruiterName(invalidRecruiterName));
+ }
+
+ @Test
+ public void isValidName() {
+ // null name
+ assertThrows(NullPointerException.class, () -> RecruiterName.isValidName(null));
+
+ // invalid name
+ assertFalse(RecruiterName.isValidName("")); // empty string
+ assertFalse(RecruiterName.isValidName(" ")); // spaces only
+ assertFalse(RecruiterName.isValidName("^")); // only non-alphanumeric characters
+ assertFalse(RecruiterName.isValidName("Timmy*")); // contains non-alphanumeric characters
+
+ // valid name
+ assertTrue(RecruiterName.isValidName("timmy")); // alphabets only
+ assertTrue(RecruiterName.isValidName("12345")); // numbers only
+ assertTrue(RecruiterName.isValidName("Tricia1")); // alphanumeric characters
+ assertTrue(RecruiterName.isValidName("Timmy Tan")); // with capital letters
+ assertTrue(RecruiterName.isValidName("Timmy Tan Wei Ming")); // long names
+ }
+
+ @Test
+ public void equals() {
+ RecruiterName recruiterName = new RecruiterName("Valid Recruiter Name");
+
+ // same values -> returns true
+ assertTrue(recruiterName.equals(new RecruiterName("Valid Recruiter Name")));
+
+ // same object -> returns true
+ assertTrue(recruiterName.equals(recruiterName));
+
+ // null -> returns false
+ assertFalse(recruiterName.equals(null));
+
+ // different types -> returns false
+ assertFalse(recruiterName.equals(5.0f));
+
+ // different values -> returns false
+ assertFalse(recruiterName.equals(new RecruiterName("Other Valid Recruiter Name")));
+
+ // different case -> returns true
+ assertTrue(recruiterName.equals(new RecruiterName("Valid RECRUITER Name")));
+
+ // different case -> returns true
+ assertTrue(recruiterName.equals(new RecruiterName("valid recruiter name")));
+
+ recruiterName = new RecruiterName("Valid Name 123");
+
+ // Alphanumerics preserved -> returns true
+ assertTrue(recruiterName.equals(new RecruiterName("Valid Name 123")));
+
+ recruiterName = new RecruiterName("Valid Name 2");
+
+ //Does not strip numbers
+ assertFalse(recruiterName.equals(new RecruiterName("Valid Name ")));
+
+ assertFalse(recruiterName.equals(new RecruiterName("Valid Name")));
+ }
+}
diff --git a/src/test/java/seedu/address/model/company/RemarkTest.java b/src/test/java/seedu/address/model/company/RemarkTest.java
new file mode 100644
index 00000000000..13cc985b8d5
--- /dev/null
+++ b/src/test/java/seedu/address/model/company/RemarkTest.java
@@ -0,0 +1,55 @@
+package seedu.address.model.company;
+
+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 RemarkTest {
+
+ @Test
+ public void constructor_null_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> new Remark(null));
+ }
+
+ @Test
+ public void isValidRemark() {
+ // null remark
+ assertThrows(NullPointerException.class, () -> Remark.isValidRemark(null));
+
+ // invalid remark
+ assertFalse(Remark.isValidRemark("")); // empty string
+ assertFalse(Remark.isValidRemark(" ")); // spaces only
+
+
+ // valid remark
+ assertTrue(Remark.isValidRemark("Google")); // alphabets only
+ assertTrue(Remark.isValidRemark("12345")); // numbers only
+ assertTrue(Remark.isValidRemark("3M@#$%^&{}")); // other characters
+ assertTrue(Remark.isValidRemark("Interview@idk-where(11/12/23 1500), Java & python")); // long remark
+ }
+
+ @Test
+ public void equals() {
+ Remark remark = new Remark("Hello");
+
+ // same object -> returns true
+ assertTrue(remark.equals(remark));
+
+ // same values -> returns true
+ Remark remarkCopy = new Remark(remark.value);
+ assertTrue(remark.equals(remarkCopy));
+
+ // different types -> returns false
+ assertFalse(remark.equals(1));
+
+ // null -> returns false
+ assertFalse(remark.equals(null));
+
+ // different remark -> returns false
+ Remark differentRemark = new Remark("Bye");
+ assertFalse(remark.equals(differentRemark));
+ }
+}
+
diff --git a/src/test/java/seedu/address/model/company/RoleTest.java b/src/test/java/seedu/address/model/company/RoleTest.java
new file mode 100644
index 00000000000..b28acd6e9eb
--- /dev/null
+++ b/src/test/java/seedu/address/model/company/RoleTest.java
@@ -0,0 +1,77 @@
+package seedu.address.model.company;
+
+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 RoleTest {
+ @Test
+ public void constructor_null_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> new Role(null));
+ }
+
+ @Test
+ public void constructor_invalidRole_throwsIllegalArgumentException() {
+ String invalidRole = "";
+ assertThrows(IllegalArgumentException.class, () -> new Role(invalidRole));
+ }
+
+ @Test
+ public void isValidRole() {
+ // null role
+ assertThrows(NullPointerException.class, () -> Role.isValidRole(null));
+
+ // invalid role
+ assertFalse(Role.isValidRole("")); // empty string
+ assertFalse(Role.isValidRole(" ")); // spaces only
+ assertFalse(Role.isValidRole("^")); // only non-alphanumeric characters
+ assertFalse(Role.isValidRole("software*engineer")); // contains non-alphanumeric characters
+
+ // valid role
+ assertTrue(Role.isValidRole("software engineer")); // alphabets only
+ assertTrue(Role.isValidRole("12345")); // numbers only
+ assertTrue(Role.isValidRole("web3 developer")); // alphanumeric characters
+ assertTrue(Role.isValidRole("Software Engineer")); // with capital letters
+ assertTrue(Role.isValidRole("Machine Learning and Artificial Intelligence Engineer")); // long roles
+ }
+
+ @Test
+ public void equals() {
+ Role role = new Role("Valid Role");
+
+ // same values -> returns true
+ assertTrue(role.equals(new Role("Valid Role")));
+
+ // same object -> returns true
+ assertTrue(role.equals(role));
+
+ // null -> returns false
+ assertFalse(role.equals(null));
+
+ // different types -> returns false
+ assertFalse(role.equals(5.0f));
+
+ // different values -> returns false
+ assertFalse(role.equals(new Role("Other Valid Role")));
+
+ // different case -> returns true
+ assertTrue(role.equals(new Role("Valid ROLE")));
+
+ // different case -> returns true
+ assertTrue(role.equals(new Role("valid role")));
+
+ role = new Role("Valid Name 123");
+
+ // Alphanumerics preserved -> returns true
+ assertTrue(role.equals(new Role("Valid Name 123")));
+
+ role = new Role("Valid Name 2");
+
+ //Does not strip numbers
+ assertFalse(role.equals(new Role("Valid Name ")));
+
+ assertFalse(role.equals(new Role("Valid Name")));
+ }
+}
diff --git a/src/test/java/seedu/address/model/company/UniqueCompanyListTest.java b/src/test/java/seedu/address/model/company/UniqueCompanyListTest.java
new file mode 100644
index 00000000000..d3b2c57e123
--- /dev/null
+++ b/src/test/java/seedu/address/model/company/UniqueCompanyListTest.java
@@ -0,0 +1,173 @@
+package seedu.address.model.company;
+
+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.address.testutil.TypicalCompanies.META;
+import static seedu.address.testutil.TypicalCompanies.TIKTOK;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.address.model.company.exceptions.CompanyNotFoundException;
+import seedu.address.model.company.exceptions.DuplicateCompanyException;
+import seedu.address.testutil.CompanyBuilder;
+
+public class UniqueCompanyListTest {
+
+ private final UniqueCompanyList uniqueCompanyList = new UniqueCompanyList();
+
+ @Test
+ public void contains_nullCompany_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> uniqueCompanyList.contains(null));
+ }
+
+ @Test
+ public void contains_companyNotInList_returnsFalse() {
+ assertFalse(uniqueCompanyList.contains(META));
+ }
+
+ @Test
+ public void contains_companyInList_returnsTrue() {
+ uniqueCompanyList.add(META);
+ assertTrue(uniqueCompanyList.contains(META));
+ }
+
+ @Test
+ public void contains_companyWithSameIdentityFieldsInList_returnsTrue() {
+ uniqueCompanyList.add(META);
+ Company editedMeta = new CompanyBuilder(META)
+ .build();
+ assertTrue(uniqueCompanyList.contains(editedMeta));
+ }
+
+ @Test
+ public void add_nullCompany_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> uniqueCompanyList.add(null));
+ }
+
+ @Test
+ public void add_duplicateCompany_throwsDuplicateCompanyException() {
+ uniqueCompanyList.add(META);
+ assertThrows(DuplicateCompanyException.class, () -> uniqueCompanyList.add(META));
+ }
+
+ @Test
+ public void setCompany_nullTargetCompany_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> uniqueCompanyList.setCompany(null, META));
+ }
+
+ @Test
+ public void setCompany_nullEditedCompany_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> uniqueCompanyList.setCompany(META, null));
+ }
+
+ @Test
+ public void setCompany_targetCompanyNotInList_throwsCompanyNotFoundException() {
+ assertThrows(CompanyNotFoundException.class, () -> uniqueCompanyList.setCompany(META, META));
+ }
+
+ @Test
+ public void setCompany_editedCompanyIsSameCompany_success() {
+ uniqueCompanyList.add(META);
+ uniqueCompanyList.setCompany(META, META);
+ UniqueCompanyList expectedUniqueCompanyList = new UniqueCompanyList();
+ expectedUniqueCompanyList.add(META);
+ assertEquals(expectedUniqueCompanyList, uniqueCompanyList);
+ }
+
+ @Test
+ public void setCompany_editedCompanyHasSameIdentity_success() {
+ uniqueCompanyList.add(META);
+ Company editedMeta = new CompanyBuilder(META)
+ .build();
+ uniqueCompanyList.setCompany(META, editedMeta);
+ UniqueCompanyList expectedUniqueCompanyList = new UniqueCompanyList();
+ expectedUniqueCompanyList.add(editedMeta);
+ assertEquals(expectedUniqueCompanyList, uniqueCompanyList);
+ }
+
+ @Test
+ public void setCompany_editedCompanyHasDifferentIdentity_success() {
+ uniqueCompanyList.add(META);
+ uniqueCompanyList.setCompany(META, TIKTOK);
+ UniqueCompanyList expectedUniqueCompanyList = new UniqueCompanyList();
+ expectedUniqueCompanyList.add(TIKTOK);
+ assertEquals(expectedUniqueCompanyList, uniqueCompanyList);
+ }
+
+ @Test
+ public void setCompany_editedCompanyHasNonUniqueIdentity_throwsDuplicateCompanyException() {
+ uniqueCompanyList.add(META);
+ uniqueCompanyList.add(TIKTOK);
+ assertThrows(DuplicateCompanyException.class, () -> uniqueCompanyList.setCompany(META, TIKTOK));
+ }
+
+ @Test
+ public void remove_nullCompany_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> uniqueCompanyList.remove(null));
+ }
+
+ @Test
+ public void remove_companyDoesNotExist_throwsCompanyNotFoundException() {
+ assertThrows(CompanyNotFoundException.class, () -> uniqueCompanyList.remove(META));
+ }
+
+ @Test
+ public void remove_existingCompany_removesCompany() {
+ uniqueCompanyList.add(META);
+ uniqueCompanyList.remove(META);
+ UniqueCompanyList expectedUniqueCompanyList = new UniqueCompanyList();
+ assertEquals(expectedUniqueCompanyList, uniqueCompanyList);
+ }
+
+ @Test
+ public void setCompanies_nullUniqueCompanyList_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> uniqueCompanyList.setCompanies((UniqueCompanyList) null));
+ }
+
+ @Test
+ public void setCompanies_uniqueCompanyList_replacesOwnListWithProvidedUniqueCompanyList() {
+ uniqueCompanyList.add(META);
+ UniqueCompanyList expectedUniqueCompanyList = new UniqueCompanyList();
+ expectedUniqueCompanyList.add(TIKTOK);
+ uniqueCompanyList.setCompanies(expectedUniqueCompanyList);
+ assertEquals(expectedUniqueCompanyList, uniqueCompanyList);
+ }
+
+ @Test
+ public void setCompanies_nullList_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> uniqueCompanyList.setCompanies((List) null));
+ }
+
+ @Test
+ public void setCompanies_list_replacesOwnListWithProvidedList() {
+ uniqueCompanyList.add(META);
+ List companyList = Collections.singletonList(TIKTOK);
+ uniqueCompanyList.setCompanies(companyList);
+ UniqueCompanyList expectedUniqueCompanyList = new UniqueCompanyList();
+ expectedUniqueCompanyList.add(TIKTOK);
+ assertEquals(expectedUniqueCompanyList, uniqueCompanyList);
+ }
+
+ @Test
+ public void setCompanies_listWithDuplicateCompanies_throwsDuplicateCompanyException() {
+ List listWithDuplicateCompanies = Arrays.asList(META, META);
+ assertThrows(DuplicateCompanyException.class, () -> uniqueCompanyList.setCompanies(listWithDuplicateCompanies));
+ }
+
+ @Test
+ public void asUnmodifiableObservableList_modifyList_throwsUnsupportedOperationException() {
+ assertThrows(UnsupportedOperationException.class, ()
+ -> uniqueCompanyList.asUnmodifiableObservableList().remove(0));
+ }
+
+ @Test
+ public void toStringMethod() {
+ assertEquals(uniqueCompanyList.asUnmodifiableObservableList().toString(), uniqueCompanyList.toString());
+ }
+}
diff --git a/src/test/java/seedu/address/model/company/predicates/ApplicationStatusPredicateTest.java b/src/test/java/seedu/address/model/company/predicates/ApplicationStatusPredicateTest.java
new file mode 100644
index 00000000000..08d09eeb16a
--- /dev/null
+++ b/src/test/java/seedu/address/model/company/predicates/ApplicationStatusPredicateTest.java
@@ -0,0 +1,55 @@
+package seedu.address.model.company.predicates;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.address.model.company.ApplicationStatus;
+import seedu.address.testutil.CompanyBuilder;
+
+public class ApplicationStatusPredicateTest {
+
+ @Test
+ public void equals() {
+ ApplicationStatus firstPredicateStatus = new ApplicationStatus("pa");
+ ApplicationStatus secondPredicateStatus = new ApplicationStatus("pi");
+
+ ApplicationStatusPredicate firstPredicate = new ApplicationStatusPredicate(firstPredicateStatus);
+ ApplicationStatusPredicate secondPredicate = new ApplicationStatusPredicate(secondPredicateStatus);
+
+ // same object -> returns true
+ assertTrue(firstPredicate.equals(firstPredicate));
+
+ // same values -> returns true
+ ApplicationStatusPredicate firstPredicateCopy = new ApplicationStatusPredicate(firstPredicateStatus);
+ assertTrue(firstPredicate.equals(firstPredicateCopy));
+
+ // different types -> returns false
+ assertFalse(firstPredicate.equals(1));
+
+ // null -> returns false
+ assertFalse(firstPredicate.equals(null));
+
+ // different predicate -> returns false
+ assertFalse(firstPredicate.equals(secondPredicate));
+ }
+
+ @Test
+ public void test_companyContainsStatus_returnsTrue() {
+ ApplicationStatusPredicate predicate = new ApplicationStatusPredicate(new ApplicationStatus("pa"));
+ assertTrue(predicate.test(new CompanyBuilder().withStatus("pa").build()));
+
+ predicate = new ApplicationStatusPredicate(new ApplicationStatus("pi"));
+ assertTrue(predicate.test(new CompanyBuilder().withStatus("pi").build()));
+ }
+
+ @Test
+ public void test_companyDoesNotContainStatus_returnsFalse() {
+ ApplicationStatusPredicate predicate = new ApplicationStatusPredicate(new ApplicationStatus("pa"));
+ assertFalse(predicate.test(new CompanyBuilder().withStatus("pi").build()));
+
+ predicate = new ApplicationStatusPredicate(new ApplicationStatus("pi"));
+ assertFalse(predicate.test(new CompanyBuilder().withStatus("pa").build()));
+ }
+}
diff --git a/src/test/java/seedu/address/model/person/NameContainsKeywordsPredicateTest.java b/src/test/java/seedu/address/model/company/predicates/NameContainsKeywordsPredicateTest.java
similarity index 72%
rename from src/test/java/seedu/address/model/person/NameContainsKeywordsPredicateTest.java
rename to src/test/java/seedu/address/model/company/predicates/NameContainsKeywordsPredicateTest.java
index 6b3fd90ade7..b53d089ec47 100644
--- a/src/test/java/seedu/address/model/person/NameContainsKeywordsPredicateTest.java
+++ b/src/test/java/seedu/address/model/company/predicates/NameContainsKeywordsPredicateTest.java
@@ -1,4 +1,4 @@
-package seedu.address.model.person;
+package seedu.address.model.company.predicates;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
@@ -10,7 +10,7 @@
import org.junit.jupiter.api.Test;
-import seedu.address.testutil.PersonBuilder;
+import seedu.address.testutil.CompanyBuilder;
public class NameContainsKeywordsPredicateTest {
@@ -35,43 +35,43 @@ public void equals() {
// null -> returns false
assertFalse(firstPredicate.equals(null));
- // different person -> returns false
+ // different company -> returns false
assertFalse(firstPredicate.equals(secondPredicate));
}
@Test
public void test_nameContainsKeywords_returnsTrue() {
// One keyword
- NameContainsKeywordsPredicate predicate = new NameContainsKeywordsPredicate(Collections.singletonList("Alice"));
- assertTrue(predicate.test(new PersonBuilder().withName("Alice Bob").build()));
+ NameContainsKeywordsPredicate predicate = new NameContainsKeywordsPredicate(Collections.singletonList("Meta"));
+ assertTrue(predicate.test(new CompanyBuilder().withName("Meta Tiktok").build()));
// Multiple keywords
- predicate = new NameContainsKeywordsPredicate(Arrays.asList("Alice", "Bob"));
- assertTrue(predicate.test(new PersonBuilder().withName("Alice Bob").build()));
+ predicate = new NameContainsKeywordsPredicate(Arrays.asList("Meta", "Tiktok"));
+ assertTrue(predicate.test(new CompanyBuilder().withName("Meta Tiktok").build()));
// Only one matching keyword
- predicate = new NameContainsKeywordsPredicate(Arrays.asList("Bob", "Carol"));
- assertTrue(predicate.test(new PersonBuilder().withName("Alice Carol").build()));
+ predicate = new NameContainsKeywordsPredicate(Arrays.asList("Tiktok", "Google"));
+ assertTrue(predicate.test(new CompanyBuilder().withName("Meta Google").build()));
// Mixed-case keywords
- predicate = new NameContainsKeywordsPredicate(Arrays.asList("aLIce", "bOB"));
- assertTrue(predicate.test(new PersonBuilder().withName("Alice Bob").build()));
+ predicate = new NameContainsKeywordsPredicate(Arrays.asList("mEtA", "tIkToK"));
+ assertTrue(predicate.test(new CompanyBuilder().withName("Meta Tiktok").build()));
}
@Test
public void test_nameDoesNotContainKeywords_returnsFalse() {
// Zero keywords
NameContainsKeywordsPredicate predicate = new NameContainsKeywordsPredicate(Collections.emptyList());
- assertFalse(predicate.test(new PersonBuilder().withName("Alice").build()));
+ assertFalse(predicate.test(new CompanyBuilder().withName("Meta").build()));
// Non-matching keyword
- predicate = new NameContainsKeywordsPredicate(Arrays.asList("Carol"));
- assertFalse(predicate.test(new PersonBuilder().withName("Alice Bob").build()));
+ predicate = new NameContainsKeywordsPredicate(Arrays.asList("Google"));
+ assertFalse(predicate.test(new CompanyBuilder().withName("Meta Tiktok").build()));
// Keywords match phone, email and address, but does not match name
- predicate = new NameContainsKeywordsPredicate(Arrays.asList("12345", "alice@email.com", "Main", "Street"));
- assertFalse(predicate.test(new PersonBuilder().withName("Alice").withPhone("12345")
- .withEmail("alice@email.com").withAddress("Main Street").build()));
+ predicate = new NameContainsKeywordsPredicate(Arrays.asList("12345", "alice@email.com"));
+ assertFalse(predicate.test(new CompanyBuilder().withName("Meta").withPhone("12345")
+ .withEmail("alice@email.com").build()));
}
@Test
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 314885eca26..00000000000
--- a/src/test/java/seedu/address/model/person/AddressTest.java
+++ /dev/null
@@ -1,56 +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
- }
-
- @Test
- public void equals() {
- Address address = new Address("Valid Address");
-
- // same values -> returns true
- assertTrue(address.equals(new Address("Valid Address")));
-
- // same object -> returns true
- assertTrue(address.equals(address));
-
- // null -> returns false
- assertFalse(address.equals(null));
-
- // different types -> returns false
- assertFalse(address.equals(5.0f));
-
- // different values -> returns false
- assertFalse(address.equals(new Address("Other Valid Address")));
- }
-}
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 31a10d156c9..00000000000
--- a/src/test/java/seedu/address/model/person/PersonTest.java
+++ /dev/null
@@ -1,99 +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_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));
- }
-
- @Test
- public void toStringMethod() {
- String expected = Person.class.getCanonicalName() + "{name=" + ALICE.getName() + ", phone=" + ALICE.getPhone()
- + ", email=" + ALICE.getEmail() + ", address=" + ALICE.getAddress() + ", tags=" + ALICE.getTags() + "}";
- assertEquals(expected, ALICE.toString());
- }
-}
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 17ae501df08..00000000000
--- a/src/test/java/seedu/address/model/person/UniquePersonListTest.java
+++ /dev/null
@@ -1,175 +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));
- }
-
- @Test
- public void toStringMethod() {
- assertEquals(uniquePersonList.asUnmodifiableObservableList().toString(), uniquePersonList.toString());
- }
-}
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/JsonAdaptedCompanyTest.java b/src/test/java/seedu/address/storage/JsonAdaptedCompanyTest.java
new file mode 100644
index 00000000000..876e8628d45
--- /dev/null
+++ b/src/test/java/seedu/address/storage/JsonAdaptedCompanyTest.java
@@ -0,0 +1,153 @@
+package seedu.address.storage;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static seedu.address.storage.JsonAdaptedCompany.MISSING_FIELD_MESSAGE_FORMAT;
+import static seedu.address.testutil.Assert.assertThrows;
+import static seedu.address.testutil.TypicalCompanies.AMAZON;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.address.commons.exceptions.IllegalValueException;
+import seedu.address.model.company.ApplicationStatus;
+import seedu.address.model.company.Deadline;
+import seedu.address.model.company.Email;
+import seedu.address.model.company.Name;
+import seedu.address.model.company.Phone;
+import seedu.address.model.company.Priority;
+import seedu.address.model.company.RecruiterName;
+import seedu.address.model.company.Remark;
+import seedu.address.model.company.Role;
+
+public class JsonAdaptedCompanyTest {
+ private static final String INVALID_COMPANY_NAME = "G@ogle";
+ private static final String INVALID_PHONE = "+6512&34";
+ private static final String INVALID_EMAIL = "example.com";
+ private static final String INVALID_PRIORITY = "HIGHH";
+ private static final String INVALID_REMARK = " ";
+
+ private static final String VALID_COMPANY_NAME = AMAZON.getName().toString();
+ private static final String VALID_PHONE = AMAZON.getPhone().toString();
+ private static final String VALID_EMAIL = AMAZON.getEmail().toString();
+ private static final String VALID_ROLE = AMAZON.getRole().toString();
+ private static final String VALID_DEADLINE = AMAZON.getDeadline().toString();
+ private static final String VALID_STATUS = AMAZON.getStatus().toString();
+ private static final String VALID_RECRUITER_NAME = AMAZON.getRecruiterName().toString();
+ private static final String VALID_PRIORITY = AMAZON.getPriority().toString();
+ private static final String VALID_REMARK = AMAZON.getRemark().toString();
+
+ @Test
+ public void toModelType_validCompanyDetails_returnsCompany() throws Exception {
+ JsonAdaptedCompany company = new JsonAdaptedCompany(AMAZON);
+ assertEquals(AMAZON, company.toModelType());
+ }
+
+ @Test
+ public void toModelType_invalidName_throwsIllegalValueException() {
+ JsonAdaptedCompany company =
+ new JsonAdaptedCompany(INVALID_COMPANY_NAME, VALID_PHONE, VALID_EMAIL, VALID_ROLE, VALID_DEADLINE,
+ VALID_STATUS, VALID_RECRUITER_NAME, VALID_PRIORITY, VALID_REMARK);
+ String expectedMessage = Name.MESSAGE_CONSTRAINTS_INVALID_REGEX;
+ assertThrows(IllegalValueException.class, expectedMessage, company::toModelType);
+ }
+
+ @Test
+ public void toModelType_nullName_throwsIllegalValueException() {
+ JsonAdaptedCompany company = new JsonAdaptedCompany(null, VALID_PHONE, VALID_EMAIL, VALID_ROLE,
+ VALID_DEADLINE, VALID_STATUS, VALID_RECRUITER_NAME, VALID_PRIORITY, VALID_REMARK);
+ String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, Name.class.getSimpleName());
+ assertThrows(IllegalValueException.class, expectedMessage, company::toModelType);
+ }
+
+ @Test
+ public void toModelType_invalidPhone_throwsIllegalValueException() {
+ JsonAdaptedCompany company =
+ new JsonAdaptedCompany(VALID_COMPANY_NAME, INVALID_PHONE, VALID_EMAIL, VALID_ROLE,
+ VALID_DEADLINE, VALID_STATUS, VALID_RECRUITER_NAME, VALID_PRIORITY, VALID_REMARK);
+ String expectedMessage = Phone.MESSAGE_CONSTRAINTS_VALID_REGEX;
+ assertThrows(IllegalValueException.class, expectedMessage, company::toModelType);
+ }
+
+ @Test
+ public void toModelType_invalidPriority_throwsIllegalValueException() {
+ JsonAdaptedCompany company =
+ new JsonAdaptedCompany(VALID_COMPANY_NAME, VALID_PHONE, VALID_EMAIL, VALID_ROLE,
+ VALID_DEADLINE, VALID_STATUS, VALID_RECRUITER_NAME, INVALID_PRIORITY, VALID_REMARK);
+ String expectedMessage = Priority.MESSAGE_CONSTRAINTS_VALID_REGEX;
+ assertThrows(IllegalValueException.class, expectedMessage, company::toModelType);
+ }
+
+ @Test
+ public void toModelType_nullPhone_throwsIllegalValueException() {
+ JsonAdaptedCompany company = new JsonAdaptedCompany(VALID_COMPANY_NAME, null, VALID_EMAIL, VALID_ROLE,
+ VALID_DEADLINE, VALID_STATUS, VALID_RECRUITER_NAME, VALID_PRIORITY, VALID_REMARK);
+ String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, Phone.class.getSimpleName());
+ assertThrows(IllegalValueException.class, expectedMessage, company::toModelType);
+ }
+
+ @Test
+ public void toModelType_invalidEmail_throwsIllegalValueException() {
+ JsonAdaptedCompany company =
+ new JsonAdaptedCompany(VALID_COMPANY_NAME, VALID_PHONE, INVALID_EMAIL, VALID_ROLE,
+ VALID_DEADLINE, VALID_STATUS, VALID_RECRUITER_NAME, VALID_PRIORITY, VALID_REMARK);
+ String expectedMessage = Email.MESSAGE_CONSTRAINTS_VALID_REGEX;
+ assertThrows(IllegalValueException.class, expectedMessage, company::toModelType);
+ }
+
+ @Test
+ public void toModelType_nullEmail_throwsIllegalValueException() {
+ JsonAdaptedCompany company = new JsonAdaptedCompany(VALID_COMPANY_NAME, VALID_PHONE, null,
+ VALID_ROLE, VALID_DEADLINE, VALID_STATUS, VALID_RECRUITER_NAME, VALID_PRIORITY, VALID_REMARK);
+ String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, Email.class.getSimpleName());
+ assertThrows(IllegalValueException.class, expectedMessage, company::toModelType);
+ }
+
+ @Test
+ public void toModelType_nullRole_throwsIllegalValueException() {
+ JsonAdaptedCompany company = new JsonAdaptedCompany(VALID_COMPANY_NAME, VALID_PHONE, VALID_EMAIL,
+ null, VALID_DEADLINE, VALID_STATUS, VALID_RECRUITER_NAME, VALID_PRIORITY, VALID_REMARK);
+ String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, Role.class.getSimpleName());
+ assertThrows(IllegalValueException.class, expectedMessage, company::toModelType);
+ }
+
+ @Test
+ public void toModelType_nullDeadline_throwsIllegalValueException() {
+ JsonAdaptedCompany company = new JsonAdaptedCompany(VALID_COMPANY_NAME, VALID_PHONE, VALID_EMAIL, VALID_ROLE,
+ null, VALID_STATUS, VALID_RECRUITER_NAME, VALID_PRIORITY, VALID_REMARK);
+ String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, Deadline.class.getSimpleName());
+ assertThrows(IllegalValueException.class, expectedMessage, company::toModelType);
+ }
+
+ @Test
+ public void toModelType_nullStatus_throwsIllegalValueException() {
+ JsonAdaptedCompany company = new JsonAdaptedCompany(VALID_COMPANY_NAME, VALID_PHONE, VALID_EMAIL, VALID_ROLE,
+ VALID_DEADLINE, null, VALID_RECRUITER_NAME, VALID_PRIORITY, VALID_REMARK);
+ String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, ApplicationStatus.class.getSimpleName());
+ assertThrows(IllegalValueException.class, expectedMessage, company::toModelType);
+ }
+
+
+ @Test
+ public void toModelType_nullRecruiterName_throwsIllegalValueException() {
+ JsonAdaptedCompany company = new JsonAdaptedCompany(VALID_COMPANY_NAME, VALID_PHONE, VALID_EMAIL, VALID_ROLE,
+ VALID_DEADLINE, VALID_STATUS, null, VALID_PRIORITY, VALID_REMARK);
+ String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, RecruiterName.class.getSimpleName());
+ assertThrows(IllegalValueException.class, expectedMessage, company::toModelType);
+ }
+
+ @Test
+ public void toModelType_nullPriority_throwsIllegalValueException() {
+ JsonAdaptedCompany company = new JsonAdaptedCompany(VALID_COMPANY_NAME, VALID_PHONE, VALID_EMAIL, VALID_ROLE,
+ VALID_DEADLINE, VALID_STATUS, VALID_RECRUITER_NAME, null, VALID_REMARK);
+ String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, Priority.class.getSimpleName());
+ assertThrows(IllegalValueException.class, expectedMessage, company::toModelType);
+ }
+
+ @Test
+ public void toModelType_nullRemark_throwsIllegalValueException() {
+ JsonAdaptedCompany company = new JsonAdaptedCompany(VALID_COMPANY_NAME, VALID_PHONE, VALID_EMAIL, VALID_ROLE,
+ VALID_DEADLINE, VALID_STATUS, VALID_RECRUITER_NAME, VALID_PRIORITY, null);
+ String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, Remark.class.getSimpleName());
+ assertThrows(IllegalValueException.class, expectedMessage, company::toModelType);
+ }
+
+}
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
index 4e5ce9200c8..de70ee1a0b3 100644
--- a/src/test/java/seedu/address/storage/JsonAddressBookStorageTest.java
+++ b/src/test/java/seedu/address/storage/JsonAddressBookStorageTest.java
@@ -3,10 +3,10 @@
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 static seedu.address.testutil.TypicalCompanies.META;
+import static seedu.address.testutil.TypicalCompanies.NVIDIA;
+import static seedu.address.testutil.TypicalCompanies.TESLA;
+import static seedu.address.testutil.TypicalCompanies.getTypicalAddressBook;
import java.io.IOException;
import java.nio.file.Path;
@@ -51,13 +51,13 @@ public void read_notJsonFormat_exceptionThrown() {
}
@Test
- public void readAddressBook_invalidPersonAddressBook_throwDataLoadingException() {
- assertThrows(DataLoadingException.class, () -> readAddressBook("invalidPersonAddressBook.json"));
+ public void readAddressBook_invalidCompanyAddressBook_throwDataLoadingException() {
+ assertThrows(DataLoadingException.class, () -> readAddressBook("invalidCompanyAddressBook.json"));
}
@Test
- public void readAddressBook_invalidAndValidPersonAddressBook_throwDataLoadingException() {
- assertThrows(DataLoadingException.class, () -> readAddressBook("invalidAndValidPersonAddressBook.json"));
+ public void readAddressBook_invalidAndValidCompanyAddressBook_throwDataLoadingException() {
+ assertThrows(DataLoadingException.class, () -> readAddressBook("invalidAndValidCompanyAddressBook.json"));
}
@Test
@@ -72,14 +72,14 @@ public void readAndSaveAddressBook_allInOrder_success() throws Exception {
assertEquals(original, new AddressBook(readBack));
// Modify data, overwrite exiting file, and read back
- original.addPerson(HOON);
- original.removePerson(ALICE);
+ original.addCompany(TESLA);
+ original.removeCompany(META);
jsonAddressBookStorage.saveAddressBook(original, filePath);
readBack = jsonAddressBookStorage.readAddressBook(filePath).get();
assertEquals(original, new AddressBook(readBack));
// Save and read without specifying file path
- original.addPerson(IDA);
+ original.addCompany(NVIDIA);
jsonAddressBookStorage.saveAddressBook(original); // file path not specified
readBack = jsonAddressBookStorage.readAddressBook().get(); // file path not specified
assertEquals(original, new AddressBook(readBack));
diff --git a/src/test/java/seedu/address/storage/JsonSerializableAddressBookTest.java b/src/test/java/seedu/address/storage/JsonSerializableAddressBookTest.java
index 188c9058d20..1c356059449 100644
--- a/src/test/java/seedu/address/storage/JsonSerializableAddressBookTest.java
+++ b/src/test/java/seedu/address/storage/JsonSerializableAddressBookTest.java
@@ -11,36 +11,36 @@
import seedu.address.commons.exceptions.IllegalValueException;
import seedu.address.commons.util.JsonUtil;
import seedu.address.model.AddressBook;
-import seedu.address.testutil.TypicalPersons;
+import seedu.address.testutil.TypicalCompanies;
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");
+ private static final Path TYPICAL_COMPANIES_FILE = TEST_DATA_FOLDER.resolve("typicalCompaniesAddressBook.json");
+ private static final Path INVALID_COMPANY_FILE = TEST_DATA_FOLDER.resolve("invalidCompanyAddressBook.json");
+ private static final Path DUPLICATE_COMPANY_FILE = TEST_DATA_FOLDER.resolve("duplicateCompanyAddressBook.json");
@Test
- public void toModelType_typicalPersonsFile_success() throws Exception {
- JsonSerializableAddressBook dataFromFile = JsonUtil.readJsonFile(TYPICAL_PERSONS_FILE,
+ public void toModelType_typicalCompaniesFile_success() throws Exception {
+ JsonSerializableAddressBook dataFromFile = JsonUtil.readJsonFile(TYPICAL_COMPANIES_FILE,
JsonSerializableAddressBook.class).get();
AddressBook addressBookFromFile = dataFromFile.toModelType();
- AddressBook typicalPersonsAddressBook = TypicalPersons.getTypicalAddressBook();
- assertEquals(addressBookFromFile, typicalPersonsAddressBook);
+ AddressBook typicalCompaniesAddressBook = TypicalCompanies.getTypicalAddressBook();
+ assertEquals(addressBookFromFile, typicalCompaniesAddressBook);
}
@Test
- public void toModelType_invalidPersonFile_throwsIllegalValueException() throws Exception {
- JsonSerializableAddressBook dataFromFile = JsonUtil.readJsonFile(INVALID_PERSON_FILE,
+ public void toModelType_invalidCompanyFile_throwsIllegalValueException() throws Exception {
+ JsonSerializableAddressBook dataFromFile = JsonUtil.readJsonFile(INVALID_COMPANY_FILE,
JsonSerializableAddressBook.class).get();
assertThrows(IllegalValueException.class, dataFromFile::toModelType);
}
@Test
- public void toModelType_duplicatePersons_throwsIllegalValueException() throws Exception {
- JsonSerializableAddressBook dataFromFile = JsonUtil.readJsonFile(DUPLICATE_PERSON_FILE,
+ public void toModelType_duplicateCompanies_throwsIllegalValueException() throws Exception {
+ JsonSerializableAddressBook dataFromFile = JsonUtil.readJsonFile(DUPLICATE_COMPANY_FILE,
JsonSerializableAddressBook.class).get();
- assertThrows(IllegalValueException.class, JsonSerializableAddressBook.MESSAGE_DUPLICATE_PERSON,
+ assertThrows(IllegalValueException.class, JsonSerializableAddressBook.MESSAGE_DUPLICATE_COMPANY,
dataFromFile::toModelType);
}
diff --git a/src/test/java/seedu/address/storage/JsonUserPrefsStorageTest.java b/src/test/java/seedu/address/storage/JsonUserPrefsStorageTest.java
index ed0a413526a..f234a5fcb8f 100644
--- a/src/test/java/seedu/address/storage/JsonUserPrefsStorageTest.java
+++ b/src/test/java/seedu/address/storage/JsonUserPrefsStorageTest.java
@@ -73,7 +73,7 @@ public void readUserPrefs_extraValuesInFile_extraValuesIgnored() throws DataLoad
private UserPrefs getTypicalUserPrefs() {
UserPrefs userPrefs = new UserPrefs();
userPrefs.setGuiSettings(new GuiSettings(1000, 500, 300, 100));
- userPrefs.setAddressBookFilePath(Paths.get("addressbook.json"));
+ userPrefs.setAddressBookFilePath(Paths.get("companydata.json"));
return userPrefs;
}
diff --git a/src/test/java/seedu/address/storage/StorageManagerTest.java b/src/test/java/seedu/address/storage/StorageManagerTest.java
index 99a16548970..52925545a7e 100644
--- a/src/test/java/seedu/address/storage/StorageManagerTest.java
+++ b/src/test/java/seedu/address/storage/StorageManagerTest.java
@@ -2,7 +2,7 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;
+import static seedu.address.testutil.TypicalCompanies.getTypicalAddressBook;
import java.nio.file.Path;
diff --git a/src/test/java/seedu/address/testutil/AddressBookBuilder.java b/src/test/java/seedu/address/testutil/AddressBookBuilder.java
index d53799fd110..2e5df11d422 100644
--- a/src/test/java/seedu/address/testutil/AddressBookBuilder.java
+++ b/src/test/java/seedu/address/testutil/AddressBookBuilder.java
@@ -1,12 +1,12 @@
package seedu.address.testutil;
import seedu.address.model.AddressBook;
-import seedu.address.model.person.Person;
+import seedu.address.model.company.Company;
/**
* A utility class to help with building Addressbook objects.
* Example usage:
- * {@code AddressBook ab = new AddressBookBuilder().withPerson("John", "Doe").build();}
+ * {@code AddressBook ab = new AddressBookBuilder().withCompany("John", "Doe").build();}
*/
public class AddressBookBuilder {
@@ -21,10 +21,10 @@ public AddressBookBuilder(AddressBook addressBook) {
}
/**
- * Adds a new {@code Person} to the {@code AddressBook} that we are building.
+ * Adds a new {@code Company} to the {@code AddressBook} that we are building.
*/
- public AddressBookBuilder withPerson(Person person) {
- addressBook.addPerson(person);
+ public AddressBookBuilder withCompany(Company company) {
+ addressBook.addCompany(company);
return this;
}
diff --git a/src/test/java/seedu/address/testutil/Assert.java b/src/test/java/seedu/address/testutil/Assert.java
index 9863093bd6e..1111fd4c477 100644
--- a/src/test/java/seedu/address/testutil/Assert.java
+++ b/src/test/java/seedu/address/testutil/Assert.java
@@ -31,4 +31,14 @@ public static void assertThrows(Class extends Throwable> expectedType, String
Throwable thrownException = Assertions.assertThrows(expectedType, executable);
Assertions.assertEquals(expectedMessage, thrownException.getMessage());
}
+
+ /**
+ * Asserts that the message of the {@code actual} equals to the {@code expected} message.
+ * @param expected the expected message
+ * @param actual the object whose message is to be verified
+ */
+ public static void assertEquals(Object expected, Object actual) {
+ Assertions.assertEquals(expected, actual);
+ }
+
}
diff --git a/src/test/java/seedu/address/testutil/CompanyBuilder.java b/src/test/java/seedu/address/testutil/CompanyBuilder.java
new file mode 100644
index 00000000000..a0bf8e3e4f5
--- /dev/null
+++ b/src/test/java/seedu/address/testutil/CompanyBuilder.java
@@ -0,0 +1,147 @@
+package seedu.address.testutil;
+
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+
+import seedu.address.model.company.ApplicationStatus;
+import seedu.address.model.company.Company;
+import seedu.address.model.company.Deadline;
+import seedu.address.model.company.Email;
+import seedu.address.model.company.Name;
+import seedu.address.model.company.Phone;
+import seedu.address.model.company.Priority;
+import seedu.address.model.company.RecruiterName;
+import seedu.address.model.company.Remark;
+import seedu.address.model.company.Role;
+
+/**
+ * A utility class to help with building Company objects.
+ */
+public class CompanyBuilder {
+
+ public static final String DEFAULT_NAME = "Twitter";
+ public static final String DEFAULT_PHONE = "98782423";
+ public static final String DEFAULT_EMAIL = "john@gmail.com";
+ public static final String DEFAULT_ROLE = "Software Engineer";
+ public static final LocalDate DEFAULT_DEADLINE = LocalDate.of(2023, 10, 10);
+ public static final String DEFAULT_STATUS = "PA";
+ public static final String DEFAULT_RECRUITER_NAME = "John Doe";
+ public static final String DEFAULT_PRIORITY = "LOW";
+ public static final String DEFAULT_REMARK = "No remarks";
+
+ private Name name;
+ private Phone phone;
+ private Email email;
+ private Role role;
+ private Deadline deadline;
+ private ApplicationStatus status;
+ private RecruiterName recruiterName;
+ private Priority priority;
+ private Remark remark;
+
+ /**
+ * Creates a {@code CompanyBuilder} with the default details.
+ */
+ public CompanyBuilder() {
+ name = new Name(DEFAULT_NAME);
+ phone = new Phone(DEFAULT_PHONE);
+ email = new Email(DEFAULT_EMAIL);
+ role = new Role(DEFAULT_ROLE);
+ deadline = new Deadline(DEFAULT_DEADLINE.format(DateTimeFormatter.ofPattern("dd-MM-yyyy")));
+ status = new ApplicationStatus(DEFAULT_STATUS);
+ recruiterName = new RecruiterName(DEFAULT_RECRUITER_NAME);
+ priority = new Priority(DEFAULT_PRIORITY);
+ remark = new Remark(DEFAULT_REMARK);
+ }
+
+ /**
+ * Initializes the CompanyBuilder with the data of {@code companyToCopy}.
+ */
+ public CompanyBuilder(Company companyToCopy) {
+ name = companyToCopy.getName();
+ phone = companyToCopy.getPhone();
+ email = companyToCopy.getEmail();
+ role = companyToCopy.getRole();
+ deadline = companyToCopy.getDeadline();
+ status = companyToCopy.getStatus();
+ recruiterName = companyToCopy.getRecruiterName();
+ priority = companyToCopy.getPriority();
+ remark = companyToCopy.getRemark();
+ }
+
+ /**
+ * Sets the {@code Name} of the {@code Company} that we are building.
+ */
+ public CompanyBuilder withName(String name) {
+ this.name = new Name(name);
+ return this;
+ }
+
+ /**
+ * Sets the {@code Phone} of the {@code Company} that we are building.
+ */
+ public CompanyBuilder withPhone(String phone) {
+ this.phone = new Phone(phone);
+ return this;
+ }
+
+ /**
+ * Sets the {@code Email} of the {@code Company} that we are building.
+ */
+ public CompanyBuilder withEmail(String email) {
+ this.email = new Email(email);
+ return this;
+ }
+
+ /**
+ * Sets the {@code Role} of the {@code Company} that we are building.
+ */
+ public CompanyBuilder withRole(String role) {
+ this.role = new Role(role);
+ return this;
+ }
+
+ /**
+ * Sets the {@code Deadline} of the {@code Company} that we are building.
+ */
+ public CompanyBuilder withDeadline(String deadline) {
+ this.deadline = new Deadline(deadline);
+ return this;
+ }
+
+ /**
+ * Sets the {@code ApplicationStatus} of the {@code Company} that we are building.
+ */
+ public CompanyBuilder withStatus(String status) {
+ this.status = new ApplicationStatus(status);
+ return this;
+ }
+
+ /**
+ * Sets the {@code RecruiterName} of the {@code Company} that we are building.
+ */
+ public CompanyBuilder withRecruiterName(String recruiterName) {
+ this.recruiterName = new RecruiterName(recruiterName);
+ return this;
+ }
+
+ /**
+ * Sets the {@code Priority} of the {@code Company} that we are building.
+ */
+ public CompanyBuilder withPriority(String priority) {
+ this.priority = new Priority(priority);
+ return this;
+ }
+
+ /**
+ * Sets the {@code Remark} of the {@code Company} that we are building.
+ */
+ public CompanyBuilder withRemark(String remark) {
+ this.remark = new Remark(remark);
+ return this;
+ }
+ public Company build() {
+ return new Company(name, phone, email, role, deadline, status, recruiterName, priority, remark);
+ }
+
+}
diff --git a/src/test/java/seedu/address/testutil/CompanyUtil.java b/src/test/java/seedu/address/testutil/CompanyUtil.java
new file mode 100644
index 00000000000..07088c200ea
--- /dev/null
+++ b/src/test/java/seedu/address/testutil/CompanyUtil.java
@@ -0,0 +1,63 @@
+package seedu.address.testutil;
+
+import static seedu.address.logic.parser.CliSyntax.PREFIX_COMPANY_NAME;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_DEADLINE;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_PRIORITY;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_RECRUITER_NAME;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_ROLE;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_STATUS;
+
+import seedu.address.logic.commands.AddCommand;
+import seedu.address.logic.commands.EditCommand.EditCompanyDescriptor;
+import seedu.address.model.company.Company;
+
+/**
+ * A utility class for Company.
+ */
+public class CompanyUtil {
+
+ /**
+ * Returns an add command string for adding the {@code company}.
+ */
+ public static String getAddCommand(Company company) {
+ return AddCommand.COMMAND_WORD + " " + getCompanyDetails(company);
+ }
+
+ /**
+ * Returns the part of command string for the given {@code company}'s details.
+ */
+ public static String getCompanyDetails(Company company) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(PREFIX_COMPANY_NAME + company.getName().fullName + " ");
+ sb.append(PREFIX_PHONE + company.getPhone().value + " ");
+ sb.append(PREFIX_EMAIL + company.getEmail().value + " ");
+ sb.append(PREFIX_ROLE + company.getRole().jobRole + " ");
+ sb.append(PREFIX_DEADLINE + company.getDeadline().toString() + " ");
+ sb.append(PREFIX_STATUS + company.getStatus().toString() + " ");
+ sb.append(PREFIX_RECRUITER_NAME + company.getRecruiterName().fullName + " ");
+ sb.append(PREFIX_PRIORITY + company.getPriority().priority + " ");
+ return sb.toString();
+ }
+
+ /**
+ * Returns the part of command string for the given {@code EditCompanyDescriptor}'s details.
+ */
+ public static String getEditCompanyDescriptorDetails(EditCompanyDescriptor descriptor) {
+ StringBuilder sb = new StringBuilder();
+ descriptor.getName().ifPresent(name -> sb.append(PREFIX_COMPANY_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.getRole().ifPresent(role -> sb.append(PREFIX_ROLE).append(role.jobRole).append(" "));
+ descriptor.getDeadline().ifPresent(deadline -> sb.append(PREFIX_DEADLINE).append(deadline.toString())
+ .append(" "));
+ descriptor.getStatus().ifPresent(status -> sb.append(PREFIX_STATUS).append(status.toString()).append(" "));
+ descriptor.getRecruiterName().ifPresent(recruiterName -> sb.append(PREFIX_RECRUITER_NAME)
+ .append(recruiterName.fullName).append(" "));
+ descriptor.getPriority().ifPresent(priority -> sb.append(PREFIX_PRIORITY).append(priority.priority)
+ .append(" "));
+
+ return sb.toString();
+ }
+}
diff --git a/src/test/java/seedu/address/testutil/EditCompanyDescriptorBuilder.java b/src/test/java/seedu/address/testutil/EditCompanyDescriptorBuilder.java
new file mode 100644
index 00000000000..3569dbf37cc
--- /dev/null
+++ b/src/test/java/seedu/address/testutil/EditCompanyDescriptorBuilder.java
@@ -0,0 +1,120 @@
+package seedu.address.testutil;
+
+
+import seedu.address.logic.commands.EditCommand;
+import seedu.address.logic.commands.EditCommand.EditCompanyDescriptor;
+import seedu.address.model.company.ApplicationStatus;
+import seedu.address.model.company.Company;
+import seedu.address.model.company.Deadline;
+import seedu.address.model.company.Email;
+import seedu.address.model.company.Name;
+import seedu.address.model.company.Phone;
+import seedu.address.model.company.Priority;
+import seedu.address.model.company.RecruiterName;
+import seedu.address.model.company.Role;
+
+/**
+ * A utility class to help with building EditCompanyDescriptor objects.
+ */
+public class EditCompanyDescriptorBuilder {
+
+ private EditCompanyDescriptor descriptor;
+
+ public EditCompanyDescriptorBuilder() {
+ descriptor = new EditCompanyDescriptor();
+ }
+
+ public EditCompanyDescriptorBuilder(EditCompanyDescriptor descriptor) {
+ this.descriptor = new EditCompanyDescriptor(descriptor);
+ }
+
+ /**
+ * Returns an {@code EditCompanyDescriptor} with fields containing {@code company}'s details
+ */
+ public EditCompanyDescriptorBuilder(Company company) {
+ descriptor = new EditCommand.EditCompanyDescriptor();
+ descriptor.setName(company.getName());
+ descriptor.setPhone(company.getPhone());
+ descriptor.setEmail(company.getEmail());
+ descriptor.setPriority(company.getPriority());
+ descriptor.setDeadline(company.getDeadline());
+ descriptor.setRole(company.getRole());
+ descriptor.setRecruiterName(company.getRecruiterName());
+ descriptor.setStatus(company.getStatus());
+ }
+
+ /**
+ * Sets the {@code Name} of the {@code EditCompanyDescriptor} that we are building.
+ */
+ public EditCompanyDescriptorBuilder withName(String name) {
+ descriptor.setName(new Name(name));
+ return this;
+ }
+
+ /**
+ * Sets the {@code Phone} of the {@code EditCompanyDescriptor} that we are building.
+ */
+ public EditCompanyDescriptorBuilder withPhone(String phone) {
+ descriptor.setPhone(new Phone(phone));
+ return this;
+ }
+
+ /**
+ * Sets the {@code Email} of the {@code EditCompanyDescriptor} that we are building.
+ */
+ public EditCompanyDescriptorBuilder withEmail(String email) {
+ descriptor.setEmail(new Email(email));
+ return this;
+ }
+
+ /**
+ * Sets the {@code Role} of the {@code EditCompanyDescriptor} that we are building.
+ */
+
+ public EditCompanyDescriptorBuilder withRole(String role) {
+ descriptor.setRole(new Role(role));
+ return this;
+ }
+
+ /**
+ * Sets the {@code Deadline} of the {@code EditCompanyDescriptor} that we are building.
+ */
+
+ public EditCompanyDescriptorBuilder withDeadline(String deadline) {
+ descriptor.setDeadline(new Deadline(deadline));
+ return this;
+ }
+
+ /**
+ * Sets the {@code ApplicationStatus} of the {@code EditCompanyDescriptor} that we are building.
+ * @param status
+ * @return
+ */
+
+ public EditCompanyDescriptorBuilder withStatus(String status) {
+ descriptor.setStatus(new ApplicationStatus(status));
+ return this;
+ }
+
+ /**
+ * Sets the {@code RecruiterName} of the {@code EditCompanyDescriptor} that we are building.
+ * @param recruiterName
+ * @return
+ */
+ public EditCompanyDescriptorBuilder withRecruiterName(String recruiterName) {
+ descriptor.setRecruiterName(new RecruiterName(recruiterName));
+ return this;
+ }
+
+ /**
+ * Sets the {@code Priority} of the {@code EditCompanyDescriptor} that we are building.
+ */
+ public EditCompanyDescriptorBuilder withPriority(String priority) {
+ descriptor.setPriority(new Priority(priority));
+ return this;
+ }
+
+ public EditCompanyDescriptor build() {
+ return descriptor;
+ }
+}
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/TestUtil.java b/src/test/java/seedu/address/testutil/TestUtil.java
index 896d103eb0b..9fb2e961f10 100644
--- a/src/test/java/seedu/address/testutil/TestUtil.java
+++ b/src/test/java/seedu/address/testutil/TestUtil.java
@@ -7,7 +7,7 @@
import seedu.address.commons.core.index.Index;
import seedu.address.model.Model;
-import seedu.address.model.person.Person;
+import seedu.address.model.company.Company;
/**
* A utility class for test cases.
@@ -33,23 +33,23 @@ public static Path getFilePathInSandboxFolder(String fileName) {
}
/**
- * Returns the middle index of the person in the {@code model}'s person list.
+ * Returns the middle index of the company in the {@code model}'s company list.
*/
public static Index getMidIndex(Model model) {
- return Index.fromOneBased(model.getFilteredPersonList().size() / 2);
+ return Index.fromOneBased(model.getFilteredCompanyList().size() / 2);
}
/**
- * Returns the last index of the person in the {@code model}'s person list.
+ * Returns the last index of the company in the {@code model}'s company list.
*/
public static Index getLastIndex(Model model) {
- return Index.fromOneBased(model.getFilteredPersonList().size());
+ return Index.fromOneBased(model.getFilteredCompanyList().size());
}
/**
- * Returns the person in the {@code model}'s person list at {@code index}.
+ * Returns the company in the {@code model}'s company list at {@code index}.
*/
- public static Person getPerson(Model model, Index index) {
- return model.getFilteredPersonList().get(index.getZeroBased());
+ public static Company getCompany(Model model, Index index) {
+ return model.getFilteredCompanyList().get(index.getZeroBased());
}
}
diff --git a/src/test/java/seedu/address/testutil/TypicalCompanies.java b/src/test/java/seedu/address/testutil/TypicalCompanies.java
new file mode 100644
index 00000000000..eba7106aaf0
--- /dev/null
+++ b/src/test/java/seedu/address/testutil/TypicalCompanies.java
@@ -0,0 +1,94 @@
+package seedu.address.testutil;
+
+import static seedu.address.logic.commands.CommandTestUtil.VALID_DEADLINE_GOOGLE;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_DEADLINE_TIKTOK;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_GOOGLE;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_TIKTOK;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_GOOGLE;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_TIKTOK;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_GOOGLE;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_TIKTOK;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_PRIORITY_GOOGLE;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_PRIORITY_TIKTOK;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_RECRUITER_NAME_GOOGLE;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_RECRUITER_NAME_TIKTOK;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_REMARK_GOOGLE;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_REMARK_TIKTOK;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_ROLE_GOOGLE;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_ROLE_TIKTOK;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_STATUS_GOOGLE;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_STATUS_TIKTOK;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import seedu.address.model.AddressBook;
+import seedu.address.model.company.Company;
+
+/**
+ * A utility class containing a list of {@code Company} objects to be used in tests.
+ */
+public class TypicalCompanies {
+
+ public static final Company META = new CompanyBuilder().withName("Meta")
+ .withEmail("alice@example.com").withPhone("94351253")
+ .withRole("Software Engineer").withDeadline("10-10-2023").withStatus("PA")
+ .withRecruiterName("John Doe").withPriority("LOW").withRemark("No remarks").build();
+ public static final Company AMAZON = new CompanyBuilder().withName("Amazon")
+ .withEmail("janed@example.com").withPhone("98765432")
+ .withRole("Software Engineer").withDeadline("11-11-2023").withStatus("PA")
+ .withRecruiterName("Jane Doe").withPriority("MEDIUM").withRemark("JavaScript&CSS").build();
+ public static final Company MICROSOFT = new CompanyBuilder().withName("Microsoft").withEmail("heinz@example.com")
+ .withPhone("95352563").withRole("Data Engineer").withDeadline("11-12-2023").withStatus("PA")
+ .withRecruiterName("Jim Doe").withPriority("HIGH").withRemark("www.bing.com").build();
+ public static final Company DSTA = new CompanyBuilder().withName("DSTA").withEmail("cornelia@example.com")
+ .withPhone("87652533").withRole("Data Engineer").withDeadline("03-12-2023").withStatus("PA")
+ .withRecruiterName("Tim Doe").withPriority("LOW").withRemark("Java").build();
+ public static final Company APPLE = new CompanyBuilder().withName("Apple").withEmail("werner@example.com")
+ .withPhone("9482224").withRole("UX Designer").withDeadline("09-11-2023").withStatus("PA")
+ .withRecruiterName("Tom Doe").withPriority("MEDIUM").withRemark("Python").build();
+ public static final Company ACCENTURE = new CompanyBuilder().withName("Accenture").withEmail("lydia@example.com")
+ .withPhone("9482427").withRole("UI Designer").withDeadline("08-11-2023").withStatus("PA")
+ .withRecruiterName("Mary Doe").withPriority("HIGH").withRemark("No remarks").build();
+ public static final Company NETFLIX = new CompanyBuilder().withName("Netflix").withEmail("anna@example.com")
+ .withPhone("9482442").withRole("Web Developer").withDeadline("05-12-2023").withStatus("PA")
+ .withRecruiterName("Timmy Doe").withPriority("HIGH").withRemark("No remarks").build();
+
+ // Manually added
+ public static final Company TESLA = new CompanyBuilder().withName("Tesla").withEmail("stefan@example.com")
+ .withPhone("8482424").withRole("Mobile App Developer").withDeadline("11-11-2023").withStatus("PA")
+ .withRecruiterName("Harry Styles").withPriority("HIGH").withRemark("No remarks").build();
+ public static final Company NVIDIA = new CompanyBuilder().withName("Nvidia").withEmail("hans@example.com")
+ .withPhone("8482131").withRole("Software Engineer").withDeadline("12-12-2023").withStatus("PA")
+ .withRecruiterName("Inez Lim").withPriority("HIGH").withRemark("No remarks").build();
+
+ // Manually added - Company's details found in {@code CommandTestUtil}
+ public static final Company GOOGLE = new CompanyBuilder().withName(VALID_NAME_GOOGLE).withPhone(VALID_PHONE_GOOGLE)
+ .withEmail(VALID_EMAIL_GOOGLE).withRole(VALID_ROLE_GOOGLE).withDeadline(VALID_DEADLINE_GOOGLE)
+ .withStatus(VALID_STATUS_GOOGLE).withRecruiterName(VALID_RECRUITER_NAME_GOOGLE)
+ .withPriority(VALID_PRIORITY_GOOGLE).withRemark(VALID_REMARK_GOOGLE)
+ .build();
+ public static final Company TIKTOK = new CompanyBuilder().withName(VALID_NAME_TIKTOK).withPhone(VALID_PHONE_TIKTOK)
+ .withEmail(VALID_EMAIL_TIKTOK).withRole(VALID_ROLE_TIKTOK).withDeadline(VALID_DEADLINE_TIKTOK)
+ .withStatus(VALID_STATUS_TIKTOK).withRecruiterName(VALID_RECRUITER_NAME_TIKTOK)
+ .withPriority(VALID_PRIORITY_TIKTOK).withRemark(VALID_REMARK_TIKTOK)
+ .build();
+
+ private TypicalCompanies() {} // prevents instantiation
+
+ /**
+ * Returns an {@code AddressBook} with all the typical companies.
+ */
+ public static AddressBook getTypicalAddressBook() {
+ AddressBook ab = new AddressBook();
+ for (Company company : getTypicalCompanies()) {
+ ab.addCompany(company);
+ }
+ return ab;
+ }
+
+ public static List getTypicalCompanies() {
+ return new ArrayList<>(Arrays.asList(META, AMAZON, MICROSOFT, DSTA, APPLE, ACCENTURE, NETFLIX));
+ }
+}
diff --git a/src/test/java/seedu/address/testutil/TypicalIndexes.java b/src/test/java/seedu/address/testutil/TypicalIndexes.java
index 1e613937657..3b5150c2d2a 100644
--- a/src/test/java/seedu/address/testutil/TypicalIndexes.java
+++ b/src/test/java/seedu/address/testutil/TypicalIndexes.java
@@ -6,7 +6,7 @@
* A utility class containing a list of {@code Index} objects to be used in tests.
*/
public class TypicalIndexes {
- public static final Index INDEX_FIRST_PERSON = Index.fromOneBased(1);
- public static final Index INDEX_SECOND_PERSON = Index.fromOneBased(2);
- public static final Index INDEX_THIRD_PERSON = Index.fromOneBased(3);
+ public static final Index INDEX_FIRST_COMPANY = Index.fromOneBased(1);
+ public static final Index INDEX_SECOND_COMPANY = Index.fromOneBased(2);
+ public static final Index INDEX_THIRD_COMPANY = Index.fromOneBased(3);
}
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));
- }
-}